Kubernetes is powerful, but managing stateful applications and complex deployments still requires human intervention. Operators solve this by encoding operational knowledge into software—they’re like having a site reliability engineer watching your cluster 24/7. And Go is the perfect language to build them.
What is a Kubernetes Operator?
An operator is a custom controller that extends Kubernetes’ capabilities by managing the complete lifecycle of an application. Instead of manually performing tasks like:
- Deploying database replicas
- Handling failovers
- Running backups
- Scaling based on custom metrics
An operator automates all of this by watching for changes and reconciling the desired state with the actual state of your cluster.
Why Build Operators with Go?
1. Native Kubernetes Integration
Kubernetes itself is written in Go, and all its client libraries are Go-first. The client-go library provides full access to the Kubernetes API with type safety and code generation.
2. Controller-Runtime Framework
The controller-runtime library, part of the Kubebuilder project, provides high-level abstractions that eliminate boilerplate:
| |
3. Excellent Concurrency Model
Operators need to watch multiple resources and handle events concurrently. Go’s goroutines and channels make this natural and efficient.
4. Static Binaries
Go compiles to a single binary with no dependencies, making container images small and startup fast—perfect for running in Kubernetes.
5. Strong Ecosystem
Prometheus metrics, structured logging, gRPC support—everything you need for production operators is available in Go.
The Operator Pattern
Every operator follows the same reconciliation loop:
Building Your First Operator: A Simple Website Manager
Let’s build a practical operator that manages static websites. When you create a Website custom resource, the operator will:
- Create a Deployment with nginx
- Create a ConfigMap with the website content
- Create a Service to expose it
- Update status with the website URL
Step 1: Set Up the Project
First, install Kubebuilder and create a new project:
| |
Step 2: Define the Custom Resource
Edit api/v1/website_types.go:
| |
Step 3: Implement the Controller
Edit internal/controller/website_controller.go:
| |
Don’t forget to add the import for resource:
| |
Step 4: Deploy and Test
Generate manifests and install CRDs:
| |
Create a sample website:
| |
Apply and verify:
| |
Key Concepts Explained
Owner References and Garbage Collection
When the Website custom resource is deleted, Kubernetes automatically cleans up all owned resources:
| |
Watching Owned Resources
The controller watches not just Website resources, but also Deployments, ConfigMaps, and Services it owns:
| |
If someone manually modifies the Deployment, the controller will reconcile it back to the desired state.
Idempotent Reconciliation
The reconcile function must be idempotent—running it multiple times produces the same result:
| |
Best Practices for Production Operators
1. Add Finalizers for Cleanup
If your operator creates external resources (cloud infrastructure, DNS records), use finalizers:
| |
2. Implement Status Conditions
Use conditions for detailed status reporting:
| |
3. Add Prometheus Metrics
Monitor your operator’s health:
| |
4. Rate Limiting and Backoff
Handle transient failures gracefully:
| |
Conclusion
Building Kubernetes operators with Go unlocks powerful automation capabilities:
- Encode operational knowledge into code that runs 24/7
- Self-healing applications that recover from failures automatically
- Declarative management that integrates with GitOps workflows
- Native Kubernetes integration with proper garbage collection and status reporting
The example in this post is simple, but the same patterns apply to complex operators managing databases, message queues, ML training jobs, or multi-cluster deployments.
At Sajima Solutions, we help organizations build custom operators that automate their infrastructure operations. Contact us to discuss how operators can reduce your operational burden.