Kubernetes is great for stateless workloads. It’s painful for stateful systems (databases, caches, message queues).
A Kubernetes Operator is a custom controller that embeds domain knowledge. Instead of manually managing a database cluster (“create replica sets, handle failover, manage keys”), you declare: “I want a MySQL cluster with 3 replicas,” and the Operator handles the rest.
| Related: Terraform IaC | Observability at scale | High-throughput systems | Latency optimization | Zero-trust security |
Operators are how enterprise platforms scale without hiring a DBA per customer.
# Create database manually
gcloud sql instances create prod-db --tier=db-custom-16-65536
# SSH into VM, configure replication
ssh prod-db
mysql> CHANGE MASTER TO MASTER_HOST='...', MASTER_LOG_FILE='...';
# Oops, replica crashed
gcloud compute instances reset replica-2
# Manually reconfigure replication again
# Just declare what you want
apiVersion: database.example.com/v1
kind: MySQL
metadata:
name: prod-db
spec:
replicas: 3
version: "8.0"
backup:
enabled: true
schedule: "0 2 * * *"
---
# Operator automatically handles:
# - Creating 3 replicas
# - Configuring replication
# - Monitoring health
# - Auto-healing on failure
# Using kopf (Kubernetes Operator Framework Python)
import kopf
import kubernetes
@kopf.on.event('database.example.com', 'v1', 'MySQL')
def sync_mysql(event, **kwargs):
"""When a MySQL resource changes, make reality match the spec."""
mysql = event['object']
namespace = mysql['metadata']['namespace']
name = mysql['metadata']['name']
# Create StatefulSet for replicas
statefulset = {
'apiVersion': 'apps/v1',
'kind': 'StatefulSet',
'metadata': {'name': name, 'namespace': namespace},
'spec': {
'serviceName': f'{name}-headless',
'replicas': mysql['spec']['replicas'],
'selector': {'matchLabels': {'app': name}},
'template': {
'metadata': {'labels': {'app': name}},
'spec': {
'containers': [{
'name': 'mysql',
'image': f"mysql:{mysql['spec']['version']}",
'ports': [{'containerPort': 3306}],
'env': [
{'name': 'MYSQL_ROOT_PASSWORD', 'valueFrom': {
'secretKeyRef': {
'name': f'{name}-secret',
'key': 'root-password'
}
}}
],
'volumeMounts': [{'name': 'data', 'mountPath': '/var/lib/mysql'}],
}],
'volumes': [{'name': 'data', 'emptyDir': {}}],
}
}
}
}
# Create the StatefulSet
api = kubernetes.client.AppsV1Api()
try:
api.create_namespaced_stateful_set(namespace, statefulset)
except kubernetes.client.exceptions.ApiException as e:
if e.status != 409: # 409 = already exists
raise
# Configure replication
master_host = f'{name}-0.{name}-headless.{namespace}.svc.cluster.local'
for i in range(1, mysql['spec']['replicas']):
replica_host = f'{name}-{i}.{name}-headless.{namespace}.svc.cluster.local'
_configure_replication(replica_host, master_host)
# Set up backups if enabled
if mysql['spec'].get('backup', {}).get('enabled'):
_setup_backup_cron(name, mysql['spec']['backup'])
def _configure_replication(replica_host: str, master_host: str):
"""SSH into replica and configure replication."""
# In production, use mysql-connector-python or mysql-operator SDK
pass
def _setup_backup_cron(name: str, backup_spec: dict):
"""Create a CronJob for backups."""
pass
We built this for Ericsson + AT&T: dynamically provision Azure resources from Kubernetes.
apiVersion: serviceoperator.azure.com/v1beta1
kind: AzureSQLServer
metadata:
name: customer-123-db
namespace: customer-123
spec:
location: eastus
administratorLogin: admin
version: "12.0"
---
# Operator automatically:
# - Creates Azure SQL Server in eastus
# - Sets up firewall rules
# - Creates credentials in Kubernetes Secret
# - Integrates with Azure Key Vault
Result: 30% reduction in manual operations.
Tags: #Kubernetes #Operators #Automation #CloudNative
Published: June 2026
Author: Pratik Dhanave
Related Projects: Azure Service Operator (Ericsson, AT&T)