Skip to main content

Events

Events in Kubernetes are objects that provide insight into what's happening inside a cluster. They are represented by the Corev1Event resource and are used to track important state changes, errors, and other information about resources.

Understanding Kubernetes Events

Events in Kubernetes are:

  • Namespaced resources
  • Automatically cleaned up after a certain time
  • Used to track state changes and errors
  • Visible through kubectl describe and kubectl get events

Event Structure

A Kubernetes event contains:

  • Type: Either Normal or Warning
  • Reason: A short, machine-readable string
  • Message: A human-readable description
  • Count: Number of times this event has occurred
  • FirstTimestamp: When the event first occurred
  • LastTimestamp: When the event last occurred
  • InvolvedObject: The object the event is about

Common Event Examples

Here are some typical events you might see for a Deployment:

# Successful pod creation
Type: Normal
Reason: Scheduled
Message: Successfully assigned default/my-deployment-5d89d9d6b8-abc12 to node-1

# Image pull success
Type: Normal
Reason: Pulled
Message: Successfully pulled image "myapp:1.0.0"

# Image pull failure
Type: Warning
Reason: Failed
Message: Failed to pull image "myapp:1.0.0": rpc error: code = Unknown desc = Error response from daemon: pull access denied for myapp, repository does not exist or may require 'docker login'

# Pod startup
Type: Normal
Reason: Started
Message: Started container myapp

Publishing Events in KubeOps

KubeOps provides an EventPublisher to create and update events for your custom resources. The publisher is available through dependency injection in your controllers and finalizers.

note

Publishing events requires write permissions on the events resource — these are part of the default RBAC rules KubeOps generates. To change how the event objects themselves are constructed (naming, labels, additional metadata), see Customizing Resource Generation.

Basic Usage

public class DemoController(EventPublisher eventPublisher) : IEntityController<V1DemoEntity>
{
public async Task<ReconciliationResult<V1DemoEntity>> ReconcileAsync(
V1DemoEntity entity,
CancellationToken cancellationToken)
{
try
{
// Your reconciliation logic here
await eventPublisher(
entity,
"Reconciled",
"Entity was successfully reconciled",
EventType.Normal,
cancellationToken);

return ReconciliationResult<V1DemoEntity>.Success(entity);
}
catch (Exception ex)
{
await eventPublisher(
entity,
"ReconcileFailed",
$"Failed to reconcile entity: {ex.Message}",
EventType.Warning,
cancellationToken);

return ReconciliationResult<V1DemoEntity>.Failure(
entity,
"Reconciliation failed",
ex);
}
}

public Task<ReconciliationResult<V1DemoEntity>> DeletedAsync(
V1DemoEntity entity,
CancellationToken cancellationToken)
{
return Task.FromResult(ReconciliationResult<V1DemoEntity>.Success(entity));
}
}

Event Types

KubeOps provides two event types:

  • EventType.Normal: For informational events
  • EventType.Warning: For error conditions or issues

Best Practices

  1. Event Naming:

    • Use consistent, machine-readable reason codes
    • Write human-readable, descriptive messages
    • Include relevant details in the message
  2. Event Frequency:

    • Don't create too many events
    • Use the count field to track repeated events
    • Focus on important state changes
  3. Event Content:

    • Include relevant error messages
    • Add context about the operation
    • Reference related resources

Example Scenarios

  1. Resource Creation:
await eventPublisher(
entity,
"Created",
$"Created new {entity.Kind} {entity.Metadata.Name}",
EventType.Normal,
token);
  1. Validation Failure:
await eventPublisher(
entity,
"ValidationFailed",
$"Invalid configuration: {validationError}",
EventType.Warning,
token);
  1. External Service Error:
await eventPublisher(
entity,
"ExternalServiceError",
$"Failed to connect to external service: {error.Message}",
EventType.Warning,
token);

Viewing Events

You can view events in several ways:

  1. Using kubectl:
# List all events in a namespace
kubectl get events

# Describe a specific resource to see its events
kubectl describe demo-entity my-entity
  1. Using the Kubernetes Dashboard:
    • Navigate to the Events section
    • Filter by namespace and resource type

Common Pitfalls

  1. Event spam from the reconcile loop: Publishing an event on every ReconcileAsync call floods etcd — reconciliations run on every spec change, requeue, and retry. Publish events for state transitions (created, became ready, failed), not for no-op reconciliations. KubeOps deduplicates identical events for you: the same entity + reason + message + type maps to the same event name, so the publisher increments Count instead of creating a new object (see how the default factory works).

  2. Dynamic values defeat deduplication: Putting timestamps, counters, or exception .ToString() output into the message makes every event unique — the Count aggregation stops working and each occurrence becomes a separate object. Keep reason and message stable and put variable details into logs instead.

  3. Wrong event type: EventType.Warning should mean "a human may need to act" — using it for routine conditions trains users to ignore warnings, while reporting real failures as Normal hides them from kubectl get events --field-selector type=Warning.