KubeKanvas Logo
FeaturesPricingTemplatesBlogFAQsContactBook a Demo
Book a Demo
FeaturesPricingTemplatesBlogFAQsContactBook a Demo

How to Manage Events with a Dynamic Informer in Kubernetes

Kubernetes operators and controllers rely heavily on informers to watch and react to changes in the cluster. While static informers work well for known resource types, dynamic informers are essential when dealing with Custom Resource Definitions (CRDs) or multiple unknown resources at runtime.

Rafay Siddiquie

July 7, 2025

Kubernetes Development
How to Manage Events with a Dynamic Informer in Kubernetes

In this guide, you’ll learn:

✔ What a dynamic informer is and how it differs from a static informer.

✔ How to set up a dynamic informer to watch Kubernetes events.

✔ Best practices for managing multiple resources efficiently.

✔ Real-world Golang code examples for dynamic informers.

✔ Common pitfalls and how to avoid them.

By the end, you’ll be able to implement a production-ready dynamic informer that scales with your Kubernetes workloads.


1. What is a Dynamic Informer in Kubernetes?

A dynamic informer is a Kubernetes client-go component that watches unstructured resources (like CRDs) without requiring compile-time schema definitions. Unlike static informers (which require predefined types), dynamic informers use unstructured.Unstructured to handle arbitrary Kubernetes objects.

Key Use Cases for Dynamic Informers

✅ Watching Custom Resource Definitions (CRDs) dynamically.

✅ Monitoring multiple resource types with a single informer.

✅ Building generic controllers that adapt to new CRDs at runtime.

Dynamic Informer vs. Static Informer

FeatureStatic InformerDynamic Informer
Resource TypePredefined (e.g., v1.Pod)Any (unstructured.Unstructured)
FlexibilityLimited to known typesWorks with CRDs and unknown resources
PerformanceOptimized for known schemasSlightly slower due to runtime type checks
Use CaseBuilt-in resources (Pods, Deployments)Custom resources, multi-resource watchers

2. Setting Up a Dynamic Informer in Golang

To create a dynamic informer, we’ll use:

  • dynamic.Interface (from k8s.io/client-go/dynamic)
  • informer.GenericInformer (for unstructured data)
  • cache.SharedIndexInformer (to cache and index resources)

Step 1: Initialize the Dynamic Client

package main

import (
 "k8s.io/client-go/dynamic"
 "k8s.io/client-go/tools/clientcmd"
)

func main() {
 // Load kubeconfig
 config, err := clientcmd.BuildConfigFromFlags("", "/path/to/kubeconfig")
 if err != nil {
  panic(err)
 }

 // Create dynamic client
 dynamicClient, err := dynamic.NewForConfig(config)
 if err != nil {
  panic(err)
 }
}

Step 2: Define the Resource to Watch (GVR)

Use schema.GroupVersionResource to specify which resource to watch.

import (
 "k8s.io/apimachinery/pkg/runtime/schema"
)

// Example: Watch for changes in a CRD (e.g., "myresources.example.com")
gvr := schema.GroupVersionResource{
 Group:    "example.com",
 Version:  "v1",
 Resource: "myresources",
}

Step 3: Create the Dynamic Informer

import (
 "k8s.io/client-go/informers"
)

// Create a factory for dynamic informers
factory := informers.NewSharedInformerFactoryWithOptions(
 dynamicClient,
 0, // Resync period (0 = no resync)
 informers.WithNamespace("default"), // Optional: Watch a specific namespace
)

// Get a dynamic informer for the GVR
informer := factory.ForResource(gvr)

Step 4: Add Event Handlers

informer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
 AddFunc: func(obj interface{}) {
  // Handle newly created resource
  log.Println("Resource added:", obj)
 },
 UpdateFunc: func(oldObj, newObj interface{}) {
  // Handle updates
  log.Println("Resource updated:", newObj)
 },
 DeleteFunc: func(obj interface{}) {
  // Handle deletions
  log.Println("Resource deleted:", obj)
 },
})

Step 5: Start the Informer

stopCh := make(chan struct{})
defer close(stopCh)

factory.Start(stopCh)
factory.WaitForCacheSync(stopCh)

// Keep the informer running
select {}

3. Advanced Dynamic Informer Techniques

A. Watching Multiple Resources with One Informer

Use dynamicinformer.NewDynamicSharedInformerFactory to watch multiple CRDs:

import (
 "k8s.io/client-go/dynamic/dynamicinformer"
)

factory := dynamicinformer.NewDynamicSharedInformerFactory(dynamicClient, 0)

// Watch multiple GVRs
informer1 := factory.ForResource(gvr1).Informer()
informer2 := factory.ForResource(gvr2).Informer()

// Add event handlers to each
informer1.AddEventHandler(...)
informer2.AddEventHandler(...)

B. Mocking a Dynamic Informer for Testing

Use fake.NewSimpleDynamicClient for unit tests:

import (
 "k8s.io/client-go/dynamic/fake"
)

// Create a fake dynamic client
fakeClient := fake.NewSimpleDynamicClient(runtime.NewScheme())

// Use in tests
factory := dynamicinformer.NewDynamicSharedInformerFactory(fakeClient, 0)

C. Handling Timeouts in Dynamic Informers

To prevent hanging, use a context with timeout:

ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

// Start informer with context
go informer.Run(ctx.Done())

4. Best Practices for Dynamic Informers

🔹 Optimize Performance: Use WithNamespace() to limit scope.

🔹 Error Handling: Always check cache.WaitForCacheSync().

🔹 Logging: Use structured logging (zap, logrus) for debugging.

🔹 Rate Limiting: Avoid API throttling with RateLimitingQueue.


5. Common Pitfalls & Solutions

IssueSolution
Informer not detecting changesEnsure AddEventHandler is registered before starting.
Memory leaksAlways close(stopCh) to clean up informers.
API throttlingUse client-go's built-in rate limiter.
Unstructured parsing errorsValidate with unstructured.Unstructured.GetXXX().

Conclusion

Dynamic informers are essential for Kubernetes operators that need to watch CRDs or multiple resource types. By following this guide, you can:

✔ Set up a dynamic informer in Golang.

✔ Watch multiple resources efficiently.

✔ Handle edge cases like timeouts and testing.

Now you’re ready to build scalable, event-driven Kubernetes controllers with dynamic informers! 🚀

Kubernetes

Related Articles

Strapi and NextJS on Kubernetes - Part 2
Building and Deploying a Modern Blog Platform with Next.js, Strapi, and Kubernetes – Part 2: Adding the Frontend

Deploy Next.js + Strapi blog on Kubernetes with Docker, Ingress routing, and service discovery. Comp...

Shamaila Mahmood

Shamaila Mahmood

July 29, 2025

Cloud-Native Web Applications
Kubernetes Architecture Series – Part 2: Designing Scalable and Resilient Applications
Kubernetes Architecture Series – Part 2: Designing Scalable and Resilient Applications

This is the second part of our three-part Kubernetes architecture series.

Khurram Mahmood

Khurram Mahmood

July 27, 2025

Kubernetes Architecture
Building a Modern Blog with Strapi & Kubernetes: Your First CMS in the Cloud
Building a Modern Blog with Strapi & Kubernetes: Your First CMS in the Cloud

Learn how to build and run a modern blog CMS using Strapi in Kubernetes. This first part walks you t...

Shamaila Mahmood

Shamaila Mahmood

July 23, 2025

Cloud-Native Web Applications
Kubernetes Architecture Series - Part 1: From Containers to Cloud-Native Orchestration
Kubernetes Architecture Series - Part 1: From Containers to Cloud-Native Orchestration

Part 1 of the three-part blog series on Kubernetes architecture

Khurram Mahmood

Khurram Mahmood

July 23, 2025

Kubernetes Architecture
KubeKanvas Logo

Visual Kubernetes cluster design tool that helps you create, manage, and deploy your applications with ease.

Product

  • Features
  • Pricing
  • Templates

Resources

  • Blog
  • Tutorials

Company

  • About Us
  • Contact
  • Terms of Service
  • Privacy Policy
  • Impressum
XGitHubLinkedIn
© 2025 KubeKanvas. All rights reserved.