Un Operator Kubernetes encode la connaissance opérationnelle d’une application — comment la déployer, la scaler, la sauvegarder, la restaurer, la mettre à jour. C’est la différence entre gérer PostgreSQL manuellement et utiliser le CloudNativePG Operator.
Le pattern Operator
Un Operator est composé de deux éléments : une Custom Resource Definition (CRD) qui étend l’API Kubernetes, et un contrôleur qui surveille ces ressources et réconcilie l’état réel avec l’état désiré.
# CRD : définir un nouveau type de ressource Kubernetes
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: databases.mycompany.com
spec:
group: mycompany.com
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
engine:
type: string
enum: [postgresql, mysql]
version:
type: string
storage:
type: string
replicas:
type: integer
minimum: 1
maximum: 5
scope: Namespaced
names:
plural: databases
singular: database
kind: Database
# Custom Resource : utiliser la CRD
apiVersion: mycompany.com/v1
kind: Database
metadata:
name: myapp-db
spec:
engine: postgresql
version: "16"
storage: "100Gi"
replicas: 3
Le contrôleur : la boucle de réconciliation
# Avec kopf (Python Operator Framework)
import kopf
import kubernetes
@kopf.on.create('databases')
def create_database(spec, name, namespace, **kwargs):
engine = spec['engine']
replicas = spec.get('replicas', 1)
# Créer les ressources Kubernetes nécessaires
api = kubernetes.client.AppsV1Api()
statefulset = create_statefulset_manifest(name, engine, replicas)
api.create_namespaced_stateful_set(namespace=namespace, body=statefulset)
service = create_service_manifest(name)
kubernetes.client.CoreV1Api().create_namespaced_service(
namespace=namespace, body=service)
return {'status': 'created', 'endpoint': f'{name}.{namespace}.svc.cluster.local'}
@kopf.on.update('databases')
def update_database(spec, old, new, name, namespace, **kwargs):
old_replicas = old['spec'].get('replicas', 1)
new_replicas = new['spec'].get('replicas', 1)
if old_replicas != new_replicas:
api = kubernetes.client.AppsV1Api()
api.patch_namespaced_stateful_set_scale(
name=name, namespace=namespace,
body={'spec': {'replicas': new_replicas}}
)
@kopf.on.delete('databases')
def delete_database(name, namespace, **kwargs):
# Nettoyer toutes les ressources créées par l'operator
kubernetes.client.AppsV1Api().delete_namespaced_stateful_set(
name=name, namespace=namespace)
kopf.info(f"Database {name} supprimée")
Operators prêts à l’emploi
Avant d’écrire un Operator, vérifiez si un Operator open source existe déjà sur OperatorHub.io :
- CloudNativePG — PostgreSQL en HA avec failover automatique
- Strimzi — Apache Kafka sur Kubernetes
- Prometheus Operator — déploiement et gestion de Prometheus
- cert-manager — certificats TLS automatiques
- External Secrets Operator — synchronisation Vault → K8s Secrets
- CNPG — clusters PostgreSQL avec sauvegardes S3
# Installer le Prometheus Operator via Helm
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack
# Utiliser la CRD ServiceMonitor de l'Operator
kubectl apply -f - <<EOF
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: myapp-monitor
spec:
selector:
matchLabels:
app: myapp
endpoints:
- port: metrics
interval: 30s
EOF
Notre formation Kubernetes couvre les Operators et l’extension de l’API Kubernetes.