Une page de maintenance pour ingress k8s avec Caddy v2
-
Besoin : une page de maintenance pour des services hébergés sur un cluster kubernetes.
Contraintes pour cette page de maintenance :- être stateless
- avoir la possibilité de donner une raison à la maintenance en cours
Je voulais tester Caddy v2 depuis un petit moment, ca a été l’occasion pour ce besoin.
L’idée retenue :
- Un serveur caddy en reverse proxy d’un minio qui héberge les données de ma page de maintenance (html, css et un simple js).
- Il a une route
/reason
qui me permettra de changer la raison de la maintenance. - Tous les uris non connus sont renvoyés vers mon index.html pour que la page de maintenance fonctionne pour tous les uris (et ne pas chercher n’importe quoi via le reverse proxy).
- L’ingress controller Nginx utilise cette page de maintenance en default-backend.
Configurer le Minio (ou votre s3)
- Je créé un nouveau bucket pour héberger le contenu de la page de maintenance :
mc mb minio/maintenance
- Je copie le contenu de ma page de maintenance :
mc cp --recursive data/ minio/maintenance
- Je donne un accès publique à ces fichiers :
mc policy set download minio/maintenance
Si vous avez à votre disposition un backend HTTP x ou y, la suite de cet exemple fonctionnera.
Caddy
La configuration Caddy en json est disponible sur ce gist.
Attention : l’api Caddy est exposée sur toutes les interfaces. A adapter selon votre besoin. Il y a peut-être moyen de faire plus simple avec Caddy, je découvre tout justeTester en local avec Docker
Pour tester en local sur votre machine, vous pouvez utiliser tout simplement cette commande :
docker run -p 10080:80 -p 2019:2019 -v $PWD/caddy.json:/caddy.json -it caddy caddy run -config /caddy.json
En pointant votre navigateur sur http://localhost:10080, Caddy devrait servir les pages de votre backend. Pour mon exemple, ca ressemble à ca :
Je peux modifier la raison de la maintenance avec un curl :
curl \ localhost:2019/config/apps/http/servers/maintenance/routes/0/handle/0/body \ -X POST \ -H "Content-Type: application/json" \ -d '"<b>Le cluster Etcd du K8S est HS :(</b>"'
Cette petite magie fonctionne grace au JS trouvé ici. J’ai dans ma page HTML :
<div w3-include-html="/reason" class="reason"></div>
Le JS charge donc la raison de ma maintenance via la route Caddy
/reason
qui sert le contenu envoyé par le POST Json.Pour information, il est aussi possible de changer la configuration et de forcer le rechargement :
curl localhost:2019/load \ -X POST \ -H "Content-Type: application/json" \ -d @caddy.json
Déployer sur un kubernetes
Rien de particulier à rajouter à ce niveau là. A vous d’adapter pour exposer en toute sécurité et selon votre besoin l’api Caddy.
apiVersion: v1 kind: Service metadata: name: maintenance spec: ports: - name: http port: 80 protocol: TCP targetPort: http - name: api port: 2019 protocol: TCP targetPort: api sessionAffinity: None type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: name: maintenance spec: replicas: 1 selector: matchLabels: name: maintenance template: metadata: labels: name: maintenance spec: containers: - image: caddy:v2.2.1 command: - caddy - run - -config - /etc/caddy/caddy.json name: maintenance ports: - containerPort: 80 name: http protocol: TCP - containerPort: 2109 name: api protocol: TCP resources: limits: cpu: 200m memory: 200Mi requests: cpu: 100m memory: 64Mi volumeMounts: - name: maintenance-config mountPath: /etc/caddy/caddy.json subPath: caddy.json securityContext: capabilities: drop: - ALL add: - NET_BIND_SERVICE livenessProbe: httpGet: path: / port: 80 initialDelaySeconds: 10 periodSeconds: 60 volumes: - name: maintenance-config configMap: name: maintenance-config
Changer le default-backend de votre ingress
Sur l’ingress devant votre service, rajoutez l’annotation suivante pour utiliser cette page de maintenance si les endpoints du service défini dans l’ingress sont HS :
nginx.ingress.kubernetes.io/default-backend: maintenance
A savoir qu’il est également possible de renvoyer certaines erreurs http sur cette page de maintenance avec l’annotation
nginx.ingress.kubernetes.io/custom-http-errors
.Plus d’information dans la documentation.
Vous pouvez tester le bon fonctionnement de la page de maintenance avec un scale à 0 des pods du service derrière cet ingress.
Bref
Tout ceci est là pour vous inspirer et sera à adapter en fonction de votre stratégie de mise à jour, déploiement … Bon tests !