Stage 3 · Build
Kubernetes Controllers in Go
Operator SDK & Ansible/Helm
Scaffolding, bundle, and OLM integration for production operators.
The Operator Pattern
An operator is a controller that manages complex stateful applications. It encodes operational knowledge — how to deploy, scale, backup, and upgrade — into software. The operator SDK provides tools for building operators in Go, Ansible, or Helm.
# Install operator-sdk
brew install operator-sdk
# Or download from GitHub
curl -sL https://github.com/operator-framework/operator-sdk/releases/download/v1.34.0/operator-sdk_$(go env GOOS)_$(go env GOARCH) -o operator-sdk
chmod +x operator-sdk && mv operator-sdk /usr/local/bin/operator-sdk provides scaffolding, build tooling, and bundle generation. It supports three operator types: Go, Ansible, and Helm. Choose based on your use case and team expertise.
Scaffolding with operator-sdk
operator-sdk scaffolds a complete operator project with Makefile, Dockerfile, RBAC, and sample resources. The scaffolding follows best practices and is ready for customization.
# Initialize a new Go operator
operator-sdk init --domain myorg.io --repo github.com/myorg/my-operator
# Create an API (CRD + controller)
operator-sdk create api --group app --version v1 --kind MyApp --resource --controller
# Create a webhook
operator-sdk create webhook --group app --version v1 --kind MyApp --defaulting --programmatic-validation
# Build and push the operator image
make docker-build docker-push IMG=myregistry/my-operator:v1.0.0
# Generate the bundle
make bundle IMG=myregistry/my-operator:v1.0.0init creates the project structure. create api generates the CRD types and controller. create webhook generates admission webhook scaffolding. make targets handle building, testing, and packaging.
Go Operator
Go operators use controller-runtime directly. They provide full control over the reconcile logic, status management, and event handling. This is the most flexible option.
Ansible Operator
Ansible operators use Ansible playbooks to manage resources. They are ideal for teams with existing Ansible expertise and for managing infrastructure that Ansible already handles well.
# roles/myapp/tasks/main.yml
---
- name: Create namespace
kubernetes.core.k8s:
state: present
definition:
apiVersion: v1
kind: Namespace
metadata:
name: "{{ ansible_operator_meta.namespace }}"
- name: Deploy application
kubernetes.core.k8s:
state: present
definition:
apiVersion: apps/v1
kind: Deployment
metadata:
name: "{{ ansible_operator_meta.name }}"
namespace: "{{ ansible_operator_meta.namespace }}"
spec:
replicas: "{{ spec.replicas }}"
selector:
matchLabels:
app: "{{ ansible_operator_meta.name }}"
template:
metadata:
labels:
app: "{{ ansible_operator_meta.name }}"
spec:
containers:
- name: app
image: "{{ spec.image }}"
ports:
- containerPort: "{{ spec.port | default(8080) }}"Ansible roles manage the Kubernetes resources. ansible_operator_meta contains the CR metadata (name, namespace). spec contains the CR spec fields. The operator translates CR changes into Ansible playbook runs.
Helm Operator
Helm operators wrap existing Helm charts. They are the fastest way to turn a Helm chart into an operator with status reporting, drift detection, and Kubernetes-native lifecycle management.
# watches.yaml
---
- group: app.myorg.io
version: v1
kind: MyApp
chart: helm-charts/myapp
overrideValues:
# Fixed values that users cannot override
monitoring.enabled: true
valuesFrom:
- name: myapp-defaults
key: values.yaml
optional: falsewatches.yaml maps CRD kinds to Helm charts. overrideValues sets values that cannot be overridden by users. valuesFrom loads default values from a ConfigMap. The operator renders the chart and applies the manifests.
OLM Integration
The Operator Lifecycle Manager (OLM) manages operator installation, upgrades, and dependency resolution. Bundles package your operator for distribution through OLM.
# Generate bundle metadata
make bundle IMG=myregistry/my-operator:v1.0.0
# Test the bundle
operator-sdk bundle validate ./bundle
# Build and push the bundle image
operator-sdk bundle create myregistry/my-operator-bundle:v1.0.0
operator-sdk bundle push myregistry/my-operator-bundle:v1.0.0
# Create a catalog
operator-sdk catalog render myregistry/my-operator-bundle:v1.0.0 > catalog.yamlBundles contain your operator CSV, CRDs, and metadata. OLM uses bundles to install and upgrade operators. The catalog is an index of available bundles. Publish your catalog to make your operator available through OLM.
Unless you have a specific reason to use Ansible or Helm, start with Go operators. They provide the most control, the best testing story, and the strongest community support. You can always wrap Ansible or Helm playbooks inside a Go operator later.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.