Déployer un opérateur Kubernetes basé sur Helm sur OVHcloud Managed Kubernetes
Découvrez comment déployer un opérateur Kubernetes sur OVHcloud Managed Kubernetes avec Helm et l'Operator SDK
Objectif
Les opérateurs sont un moyen d'étendre Kubernetes pour automatiser certaines actions dans le cluster.

En quelques mots, un opérateur propose des actions OPS de manière programmatique et évite les activités humaines répétitives dénuées de valeur ajoutée.
Les tâches qu'un opérateur peut effectuer sont variées et peuvent concerner des ressources déployées dans Kubernetes (comme un Pod) ou en dehors (comme une base de données par exemple).
Dans ce guide, nous nous concentrons sur les ressources internes à un cluster Kubernetes.
Un opérateur repose sur des Custom Resources qui permettent d'étendre l'API Kubernetes.
Grâce à la boucle de contrôle de Kubernetes, l'opérateur maintient les ressources dans l'état souhaité.
Le rôle de l'opérateur est ensuite de surveiller l'état des objets internes ou externes qu'il gère.
Un opérateur peut avoir différentes capacités :
- configuration et installation basique de l'application
- mise à jour de l'application (avec rollback si nécessaire)
- sauvegarde et restauration si l'opérateur gère un état
- auto-remédiation de l'application en cas de problème
- supervision et observabilité de ses propres métriques
- autoscaling, auto-tuning...
Un bon résumé des capacités d'un opérateur est disponible sur le site de l'operator framework.
Un opérateur étant une API personnalisée dans Kubernetes, vous devez le développer. Heureusement, des frameworks existent pour vous aider à développer votre propre opérateur.
Le framework le plus important vous permet de développer un opérateur avec Ansible, Helm et Go.
D'autres types de frameworks existent pour utiliser d'autres langages, comme Java par exemple avec le Java operator SDK.
Comme nous allons le voir dans le tutoriel ci-dessous, les capacités de l'opérateur développé dépendent du langage utilisé. Par exemple, développer un opérateur avec Helm offre moins de possibilités (mais c'est plus simple).
Prérequis
Ce tutoriel suppose que vous disposez déjà d'un cluster Kubernetes managé par OVHcloud, ainsi que de connaissances de base sur son utilisation. Pour en savoir plus sur ces sujets, consultez la documentation déployer une application Hello World.
En pratique
Dans ce tutoriel, vous allez créer un opérateur simple qui gère l'installation d'un serveur Nginx et le supervise.
L'opérateur vous permet de :
- installer un serveur Nginx avec le nombre de Pods requis
- mettre à jour le nombre de Pods
- changer le port HTTP
- recréer le service s'il est supprimé
Vous allez développer cet opérateur avec l'operator SDK.
L'operator SDK fournit plusieurs outils :
- une CLI pour développer et exécuter localement l'opérateur développé
- plusieurs helpers dans différents langages (Helm, Ansible et Go) pour développer facilement un opérateur
Dans cet article, vous allez utiliser le helper Helm.
Installer la CLI
Le SDK inclut une CLI (Command Line Interface).
Pour installer la CLI, suivez les instructions applicables à votre système d'exploitation.
Vous pouvez, par exemple, l'installer via Homebrew :
brew install operator-sdk
Vérifiez ensuite que la CLI est correctement installée sur votre ordinateur :
Le résultat devrait être le suivant :
$ brew install operator-sdk
...
==> Installing dependencies for operator-sdk: go
==> Installing operator-sdk dependency: go
==> Pouring go--1.17.6.x86_64_linux.bottle.tar.gz
🍺 /home/linuxbrew/.linuxbrew/Cellar/go/1.17.6: 10,822 files, 532.9MB
==> Installing operator-sdk
==> Pouring operator-sdk--1.17.0.x86_64_linux.bottle.tar.gz
==> Caveats
Bash completion has been installed to:
/home/linuxbrew/.linuxbrew/etc/bash_completion.d
==> Summary
🍺 /home/linuxbrew/.linuxbrew/Cellar/operator-sdk/1.17.0: 10 files, 196.3MB
==> Running `brew cleanup operator-sdk`...
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
==> Caveats
==> operator-sdk
...
$ operator-sdk version
operator-sdk version: "v1.17.0", commit: "704b02a9ba86e85f43edb1b20457859e9eedc6e6", kubernetes version: "v1.21", go version: "go1.17.6", GOOS: "darwin", GOARCH: "arm64"
Développer un opérateur avec Helm
Dans ce guide, vous allez utiliser Helm pour créer votre premier opérateur.
Helm est un gestionnaire de packages qui fournit des templates pour déployer des applications dans Kubernetes.
La CLI propose de générer le squelette d'un projet complet, mais cela génère de nombreux fichiers qui ne sont pas nécessaires pour une application non destinée à la production.
Plus d'informations sur la structure de projet générée par la CLI sont disponibles dans la documentation officielle.
Le chart Helm
Un opérateur basé sur Helm ressemble à un chart Helm classique : il suit la même structure et la même organisation.
Votre premier opérateur Helm suivra l'organisation de code suivante :
├── helm-charts
│ └── ovh-nginx
│ ├── Chart.yaml
│ ├── templates
│ │ ├── _helpers.tpl
│ │ ├── deployment.yaml
│ │ └── service.yaml
│ └── values.yaml
Créez d'abord un dossier helm-charts, puis un dossier ovh-nginx à l'intérieur.
Placez-vous dans le dossier helm-charts/ovh-nginx.
Créez ensuite un dossier templates.
Dans ce dossier templates, créez un fichier nommé deployment.yaml avec le contenu suivant :
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "ovh-nginx.fullname" . }}
labels:
{{- include "ovh-nginx.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }} # Thanks to Helm the replicas field will be dynamic
selector:
matchLabels:
{{- include "ovh-nginx.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "ovh-nginx.selectorLabels" . | nindent 8 }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
resources:
requests:
memory: "2Mi"
cpu: "0"
limits:
memory: "32Mi"
cpu: "500m"
ports:
- name: http
containerPort: 80
protocol: TCP
livenessProbe:
httpGet:
path: /
port: http
readinessProbe:
httpGet:
path: /
port: http
Ensuite, dans le dossier templates, vous pouvez créer le Service dans un fichier service.yaml avec le contenu suivant :
apiVersion: v1
kind: Service
metadata:
name: {{ include "ovh-nginx.fullname" . }}
labels:
{{- include "ovh-nginx.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }} # Thanks to Helm the HTTP port field will be dynamic
targetPort: http
protocol: TCP
name: http
selector:
{{- include "ovh-nginx.selectorLabels" . | nindent 4 }}
Ensuite, toujours dans le dossier templates, créez un helper pour simplifier les templates. Pour cela, créez un fichier _helper.tpl avec le contenu suivant :
{{/*
Expand the name of the chart.
*/}}
{{- define "ovh-nginx.name" -}}
{{- default .Chart.Name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "ovh-nginx.fullname" -}}
{{- printf "%s-%s" .Release.Name .Chart.Name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "ovh-nginx.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "ovh-nginx.labels" -}}
helm.sh/chart: {{ include "ovh-nginx.chart" . }}
{{ include "ovh-nginx.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "ovh-nginx.selectorLabels" -}}
app.kubernetes.io/name: {{ include "ovh-nginx.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
Vos valeurs doivent être définies dans un fichier values.yaml dans le dossier ovh-nginx, avec le contenu suivant :
# To allow your operator to change the number of replicas
replicaCount: 1
image:
repository: ovhplatform/hello
pullPolicy: IfNotPresent
tag: "1.0"
service:
type: LoadBalancer
# To allow your operator to change the port
port: 80
Info
L'opérateur ne peut gérer que les champs déclarés dans le fichier values.yaml et dans la custom resource (voir le chapitre custom resource definition ci-dessous).
Enfin, dans le dossier ovh-nginx, créez le fichier Chart.yaml avec le contenu suivant :
apiVersion: v2
appVersion: 1.0
description: A Helm chart to deploy the OVHcloud hello world Nginx server
name: ovh-nginx
type: application
version: 0.1.0
À ce stade, vous disposez d'un chart Helm standard.
Il peut être utilisé avec le client Helm (helm upgrade par exemple) pour déployer le serveur Nginx.
Dans les sections suivantes, vous allez voir comment déléguer cela à un opérateur.
Custom resources definition
La custom resources definition (CRD) est l'élément central de l'opérateur.
Elle vous permet d'étendre l'API par défaut de Kubernetes. Vous pouvez ainsi les utiliser de la même manière que ses ressources natives.
En d'autres termes, une fois qu'une CRD est créée, vous pouvez créer de nouvelles ressources, appelées Custom Resources (CR), pour les distinguer des ressources natives de Kubernetes.
La CRD constitue une sorte de schéma pour la CR qui s'appuie sur elle.
Il est important de noter que les CRD, en elles-mêmes, ne sont que des données. Elles ne contiennent aucune logique ni comportement particulier.
Pour ajouter de la logique, vous avez besoin d'un controller ou d'un opérateur.
Vous devez mettre à jour votre organisation de code et ajouter les dossiers suivants :
.
├── helm-charts
│ └── ovh-nginx
│ ├── Chart.yaml
│ ├── templates
│ │ ├── _helpers.tpl
│ │ ├── deployment.yaml
│ │ └── service.yaml
│ └── values.yaml
├── manifests
│ ├── crd
│ │ └── tutorials.ovhcloud.com_ovhnginxoperators.yaml
└── watches.yaml
Créez d'abord un dossier manifests. Placez-vous dedans et créez un dossier crd.
Dans le dossier crd, créez un fichier tutorials.ovhcloud.com_ovhnginxoperators.yaml avec le contenu suivant :
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition # The API to declare new API (CRD)
metadata:
# name must match the spec fields below, and be in the form: <plural>.<group>
name: ovhnginxs.tutorials.ovhcloud.com
spec:
group: tutorials.ovhcloud.com
names:
kind: OvhNginx # The name of your CRD
listKind: OvhNginxList
# plural name to be used in the URL: /apis/<group>/<version>/<plural>
plural: ovhnginxs
# singular name to be used as an alias on the CLI and for display
singular: ovhnginx
scope: Namespaced
versions:
- name: v1
schema:
openAPIV3Schema:
type: object
properties:
spec: # List of the properties in the CR, must match the values.yaml structure
type: object
properties:
service:
type: object
properties:
port: # To change the port of the Nginx server
type: integer
replicaCount: # To change the number of Pod
type: integer
served: true
storage: true
subresources:
status: {}
Créez ensuite le fichier watches.yaml avec le contenu suivant :
- group: tutorials.ovhcloud.com
version: v1
kind: OvhNginx
chart: helm-charts/ovh-nginx
Le tester localement (presque)
Avant de packager et de déployer votre opérateur dans un cluster Kubernetes réel, vous pouvez le tester localement.
Vous avez toujours besoin de votre cluster Managed Kubernetes pour déployer votre CRD et le serveur Nginx géré par l'opérateur.
Créez d'abord la CRD dans votre cluster Kubernetes :
kubectl apply -f manifests/crd/tutorials.ovhcloud.com_ovhnginxoperators.yaml
Le résultat devrait être le suivant :
$ kubectl apply -f manifests/crd/tutorials.ovhcloud.com_ovhnginxoperators.yaml
customresourcedefinition.apiextensions.k8s.io/ovhnginxs.tutorials.ovhcloud.com created
$ kubectl get crds/ovhnginxs.tutorials.ovhcloud.com
NAME CREATED AT
ovhnginxs.tutorials.ovhcloud.com 2022-02-18T13:51:14Z
À ce stade, il n'est pas nécessaire de déployer l'opérateur dans le cluster Kubernetes ; vous pouvez l'exécuter localement sur votre ordinateur :
Le résultat devrait être le suivant :
$ helm-operator run
{"level":"info","ts":1645197230.698494,"logger":"cmd","msg":"Version","Go Version":"go1.17.6","GOOS":"darwin","GOARCH":"arm64","helm-operator":"v1.17.0","commit":"704b02a9ba86e85f43edb1b20457859e9eedc6e6"}
{"level":"info","ts":1645197230.699863,"logger":"cmd","msg":"Watch namespaces not configured by environment variable WATCH_NAMESPACE or file. Watching all namespaces.","Namespace":""}
{"level":"info","ts":1645197231.877758,"logger":"controller-runtime.metrics","msg":"Metrics server is starting to listen","addr":":8080"}
{"level":"info","ts":1645197231.888722,"logger":"helm.controller","msg":"Watching resource","apiVersion":"tutorials.ovhcloud.com/v1","kind":"OvhNginx","namespace":"","reconcilePeriod":"1m0s"}
{"level":"info","ts":1645197231.890322,"msg":"Starting server","kind":"health probe","addr":"[::]:8081"}
{"level":"info","ts":1645197231.8903291,"msg":"Starting server","path":"/metrics","kind":"metrics","addr":"[::]:8080"}
{"level":"info","ts":1645197231.8913422,"logger":"controller.ovhnginx-controller","msg":"Starting EventSource","source":"kind source: *unstructured.Unstructured"}
{"level":"info","ts":1645197231.891497,"logger":"controller.ovhnginx-controller","msg":"Starting Controller"}
{"level":"info","ts":1645197231.993102,"logger":"controller.ovhnginx-controller","msg":"Starting workers","worker count":8}
Info
N'arrêtez pas l'exécution de l'opérateur. Il est indispensable qu'il continue de fonctionner pour les étapes suivantes.
Vous pourrez l'arrêter plus tard dans ce tutoriel, lorsque vous le déploierez dans le cluster Kubernetes.
Il est maintenant temps de créer votre première CR.
Vous devez mettre à jour votre organisation de code et ajouter le dossier samples dans le dossier manifests :
.
├── helm-charts
│ └── ovh-nginx
│ ├── Chart.yaml
│ ├── templates
│ │ ├── _helpers.tpl
│ │ ├── deployment.yaml
│ │ └── service.yaml
│ └── values.yaml
├── manifests
│ ├── crd
│ │ └── tutorials.ovhcloud.com_ovhnginxoperators.yaml
│ └── samples
│ └── tutorials_v1_ovhnginxoperator.yaml
└── watches.yaml
Dans le dossier samples, créez le fichier tutorials_v1_ovhnginxoperator.yaml avec le contenu suivant :
apiVersion: tutorials.ovhcloud.com/v1
kind: OvhNginx
metadata:
name: mynginx-sample
spec:
replicaCount: 1
service:
port: 80
Avant de créer la CR, n'oubliez pas de créer un namespace. Ce sera le namespace dans lequel la CR sera créée et où le serveur Nginx sera déployé :
kubectl create ns test-ovh-nginx-operator
Le résultat devrait être le suivant :
$ kubectl create ns test-ovh-nginx-operator
namespace/test-ovh-nginx-operator created
$ kubectl get ns
NAME STATUS AGE
default Active 11d
kube-node-lease Active 11d
kube-public Active 11d
kube-system Active 11d
test-ovh-nginx-operator Active 8s
Créez ensuite la CR :
kubectl apply -f manifests/samples/tutorials_v1_ovhnginxoperator.yaml
Le résultat devrait être le suivant :
$ kubectl apply -f manifests/samples/tutorials_v1_ovhnginxoperator.yaml
ovhnginx.tutorials.ovhcloud.com/mynginx-sample created
$ kubectl get ovhnginx
NAME AGE
mynginx-sample 79s
À ce moment-là, l'opérateur en cours d'exécution détecte la nouvelle CR et effectue plusieurs actions :
{"level":"info","ts":1645197784.822017,"logger":"controller.ovhnginx-controller","msg":"Starting EventSource","source":"kind source: *unstructured.Unstructured"}
{"level":"info","ts":1645197784.822165,"logger":"helm.controller","msg":"Watching dependent resource","ownerApiVersion":"tutorials.ovhcloud.com/v1","ownerKind":"OvhNginx","apiVersion":"apps/v1","kind":"Deployment"}
{"level":"info","ts":1645197784.82237,"logger":"controller.ovhnginx-controller","msg":"Starting EventSource","source":"kind source: *unstructured.Unstructured"}
{"level":"info","ts":1645197784.822401,"logger":"helm.controller","msg":"Watching dependent resource","ownerApiVersion":"tutorials.ovhcloud.com/v1","ownerKind":"OvhNginx","apiVersion":"v1","kind":"Service"}
{"level":"info","ts":1645197784.822422,"logger":"helm.controller","msg":"Installed release","namespace":"test-ovh-nginx-operator","name":"mynginx-sample","apiVersion":"tutorials.ovhcloud.com/v1","kind":"OvhNginx","release":"mynginx-sample"}
Examinons les ressources de votre cluster Kubernetes :
kubectl get pod -n test-ovh-nginx-operator
kubectl get svc -n test-ovh-nginx-operator
Le résultat devrait être le suivant :
$ kubectl get pod -n test-ovh-nginx-operator
NAME READY STATUS RESTARTS AGE
mynginx-sample-ovh-nginx-65b64c6585-wtc5g 1/1 Running 0 72s
$ kubectl get svc -n test-ovh-nginx-operator
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
mynginx-sample-ovh-nginx LoadBalancer 10.3.175.10 152.XXX.XXX.255 80:30356/TCP 105s
Récupérez l'IP externe du service :
kubectl get svc mynginx-sample-ovh-nginx -o jsonpath='{.status.loadBalancer.ingress[0].ip}' -n test-ovh-nginx-operator
Le résultat devrait être le suivant :
$ kubectl get svc mynginx-sample-ovh-nginx -o jsonpath='{.status.loadBalancer.ingress[0].ip}' -n test-ovh-nginx-operator
152.XXX.XXX.255
Vous pouvez maintenant visiter l'URL http://152.XXX.XXX.255/ :

À cette étape, l'opérateur devrait être déclenché et supprimer les pods et services créés.
kubectl delete ovhnginxs.tutorials.ovhcloud.com/mynginx-sample -n test-ovh-nginx-operator
Le résultat devrait être le suivant :
$ kubectl delete ovhnginxs.tutorials.ovhcloud.com/mynginx-sample -n test-ovh-nginx-operator
ovhnginx.tutorials.ovhcloud.com "mynginx-sample" deleted
$ kubectl get pod -n test-ovh-nginx-operator
No resources found in test-ovh-nginx-operator namespace.
$ kubectl get svc -n test-ovh-nginx-operator
No resources found in test-ovh-nginx-operator namespace.
Déployer l'opérateur sur le cluster OVHcloud Managed Kubernetes
Nous allons maintenant vous montrer comment déployer votre opérateur sur un cluster Kubernetes.
Vous pouvez maintenant arrêter en toute sécurité l'opérateur local qui s'exécute dans votre terminal.
Info
Pour plus de clarté, les ressources suivantes sont plus simples que celles que vous devrez créer en conditions réelles, en particulier la configuration de sécurité.
Le packaging d'un opérateur ressemble à celui d'une application classique.
Créez d'abord un fichier Dockerfile dans le dossier racine avec le contenu suivant :
FROM quay.io/operator-framework/helm-operator:v1.17.0
ENV HOME=/opt/helm
COPY watches.yaml ${HOME}/watches.yaml
COPY helm-charts ${HOME}/helm-charts
WORKDIR ${HOME}
Ensuite, construisez l'image et poussez-la vers votre registre préféré.
Pour créer un registre privé, vous pouvez suivre le tutoriel comment créer un Managed Private Registry OVHcloud.
docker login [YOUR_PRIVATE_REGISTRY_URL]
docker build -t [YOUR_PRIVATE_REGISTRY_URL]/example/ovh-nginx-operator:1.0.0 .
docker push [YOUR_PRIVATE_REGISTRY_URL]/example/ovh-nginx-operator:1.0.0
Le résultat devrait être le suivant :
$ docker build -t myregistryid.xxx1.container-registry.ovh.net/example/ovh-nginx-operator:1.0.0 .
[+] Building 0.4s (9/9) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 32B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for quay.io/operator-framework/helm-operator:v1.17.0 0.4s
=> [internal] load build context 0.0s
=> => transferring context: 659B 0.0s
=> [1/4] FROM quay.io/operator-framework/helm-operator:v1.17.0@sha256:516e69e6c0c78cca64fd3fe2a43703cf709f399bcfc36dabbc238f8d90954e59 0.0s
=> CACHED [2/4] COPY watches.yaml /opt/helm/watches.yaml 0.0s
=> CACHED [3/4] COPY helm-charts /opt/helm/helm-charts 0.0s
=> CACHED [4/4] WORKDIR /opt/helm 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:0f71fd44ff901ed21977e5079a68d3aade40f0cca4550a72365241b5cf450f98 0.0s
=> => naming to myregistryid.xxx1.container-registry.ovh.net/example/ovh-nginx-operator:1.0.0
$ docker login https://myregistryid.xxx1.container-registry.ovh.net
Username: harbor-user1
Password:
Login Succeeded
$ docker push myregistryid.xxx1.container-registry.ovh.net/example/ovh-nginx-operator:1.0.0
The push refers to repository [myregistryid.xxx1.container-registry.ovh.net/example/ovh-nginx-operator]
5f70bf18a086: Pushed
4edd44e1433c: Pushed
35217553513b: Pushed
7766e4bae829: Pushed
895f2ebb55fa: Pushed
ede2e4397fdc: Pushed
87cd41b1f9f8: Pushed
44f62afd0479: Pushed
1.0.0: digest: sha256:509549a6bac0a2e52a19b4bbac80b5411a2c0fe581c5fbd2cc6b4a456e339eb3 size: 1984
La dernière étape consiste à déployer votre opérateur dans le cluster Kubernetes.
Créez d'abord le namespace pour l'opérateur :
kubectl create ns ovh-nginx-operator
Le résultat devrait être le suivant :
$ kubectl create ns ovh-nginx-operator
namespace/ovh-nginx-operator created
Vous devez maintenant créer un secret Kubernetes afin d'indiquer à Kubernetes les identifiants permettant de se connecter et de récupérer les images depuis votre registre Docker privé :
kubectl create secret generic regcred \
--from-file=.dockerconfigjson=<path/to/.docker/config.json>/config.json \
--type=kubernetes.io/dockerconfigjson \
--namespace=ovh-nginx-operator
Le résultat devrait être le suivant :
$ kubectl create secret generic regcred \
--from-file=.dockerconfigjson=/Users/sphilipp/.docker/config.json \
--type=kubernetes.io/dockerconfigjson \
--namespace=ovh-nginx-operator
secret/regcred created
$ kubectl get secret regcred -n ovh-nginx-operator
NAME TYPE DATA AGE
regcred kubernetes.io/dockerconfigjson 1 49s
Créez ensuite le fichier ovh-nginx-operator.yaml dans le dossier manifests avec le contenu suivant :
# Authorisations for the operator
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: ovhnginxoperator-admin-role
rules:
- apiGroups:
- tutorials.ovhcloud.com
resources:
- ovhnginxs
- ovhnginxs/status
- ovhnginxs/finalizers
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- ""
resources:
- secrets
- "serviceaccounts"
- "services"
verbs:
- "*"
- apiGroups:
- "apps"
verbs:
- "*"
resources:
- "deployments"
---
# The service account used for the Pod where the operator is
apiVersion: v1
kind: ServiceAccount
metadata:
name: ovh-nginx-operator-sa
namespace: ovh-nginx-operator
---
# The affected authorisation to the service account
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: ovh-nginx-operator-admin
subjects:
- kind: ServiceAccount
name: ovh-nginx-operator-sa
namespace: ovh-nginx-operator
roleRef:
kind: ClusterRole
name: ovhnginxoperator-admin-role
apiGroup: ""
---
# The deployment for the operator
apiVersion: apps/v1
kind: Deployment
metadata:
name: ovh-nginx-operator
namespace: ovh-nginx-operator
spec:
selector:
matchLabels:
app: ovh-nginx-operator
replicas: 1
strategy:
type: Recreate
template:
metadata:
labels:
app: ovh-nginx-operator
spec:
serviceAccountName: ovh-nginx-operator-sa
containers:
- name: operator
# Set the pah to your own image registry
image: myregistryid.xxx1.container-registry.ovh.net/example/ovh-nginx-operator:1.0.0
imagePullPolicy: Always
imagePullSecrets:
- name: regcred
Info
Le chemin vers l'image de l'opérateur doit être la même valeur que le champ [YOUR_PRIVATE_REGISTRY_URL] des exemples précédents.
Appliquez le fichier au cluster Kubernetes :
kubectl apply -f manifests/ovh-nginx-operator.yaml -n ovh-nginx-operator
Le résultat devrait être le suivant :
$ kubectl apply -f manifests/ovh-nginx-operator.yaml -n ovh-nginx-operator
clusterrole.rbac.authorization.k8s.io/ovhnginxoperator-admin-role created
serviceaccount/ovh-nginx-operator-sa created
clusterrolebinding.rbac.authorization.k8s.io/ovh-nginx-operator-admin configured
deployment.apps/ovh-nginx-operator created
$ kubectl get pods -n ovh-nginx-operator
NAME READY STATUS RESTARTS AGE
ovh-nginx-operator-5487958499-v9q46 1/1 Running 0 70s
Il est temps de tester l'opérateur.
Une fois encore, vous pouvez appliquer la CR du dossier samples :
kubectl apply -f manifests/samples/tutorials_v1_ovhnginxoperator.yaml -n test-ovh-nginx-operator
Le résultat devrait être le suivant :
$ kubectl apply -f manifests/samples/tutorials_v1_ovhnginxoperator.yaml -n test-ovh-nginx-operator
ovhnginx.tutorials.ovhcloud.com/mynginx-sample created
$ kubectl get pods -n test-ovh-nginx-operator
NAME READY STATUS RESTARTS AGE
mynginx-sample-ovh-nginx-65b64c6585-5ddpm 1/1 Running 0 44s
$ kubectl get svc -n test-ovh-nginx-operator
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
mynginx-sample-ovh-nginx LoadBalancer 10.3.175.10 152.XXX.XXX.255 80:30403/TCP 2m36s
Vous pouvez maintenant modifier le comportement de l'opérateur et lui indiquer de créer deux répliques au lieu d'une seule.
Pour cela, dans le dossier samples, modifiez le fichier tutorials_v1_ovhnginxoperator.yaml avec le contenu suivant :
apiVersion: tutorials.ovhcloud.com/v1
kind: OvhNginx
metadata:
name: mynginx-sample
spec:
replicaCount: 2
service:
port: 8080
kubectl apply -f manifests/samples/tutorials_v1_ovhnginxoperator.yaml -n test-ovh-nginx-operator
Affichez ensuite les pods et le service :
kubectl get pods -n test-ovh-nginx-operator
kubectl get svc -n test-ovh-nginx-operator
Le résultat devrait être le suivant :
$ kubectl apply -f manifests/samples/tutorials_v1_ovhnginxoperator.yaml -n test-ovh-nginx-operator
ovhnginx.tutorials.ovhcloud.com/mynginx-sample updated
$ kubectl get pods -n test-ovh-nginx-operator
NAME READY STATUS RESTARTS AGE
mynginx-sample-ovh-nginx-65b64c6585-4nc88 1/1 Running 0 4m29s
mynginx-sample-ovh-nginx-65b64c6585-5ddpm 1/1 Running 0 28m
$ kubectl get svc -n test-ovh-nginx-operator
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
mynginx-sample-ovh-nginx LoadBalancer 10.3.175.10 152.XXX.XXX.255 8080:30403/TCP 30m
Suppression (nettoyage)
Si vous le souhaitez, vous pouvez désinstaller le serveur Nginx et l'opérateur.
Supprimez d'abord votre CR pour supprimer le serveur Nginx déployé :
kubectl delete ovhnginxs.tutorials.ovhcloud.com/mynginx-sample -n test-ovh-nginx-operator
Supprimez ensuite le namespace :
kubectl delete ns test-ovh-nginx-operator
Supprimez ensuite toutes les ressources ainsi que l'opérateur lui-même :
kubectl delete ns ovh-nginx-operator
Enfin, supprimez la CRD :
kubectl delete crds/ovhnginxs.tutorials.ovhcloud.com
Aller plus loin
Pour aller plus loin sur le sujet des opérateurs Kubernetes, suivez les autres tutoriels Kubernetes de la section Operators.
Le pattern des opérateurs dans Kubernetes.
Le SDK de l'opérateur.
-
Si vous avez besoin d'une formation ou d'une assistance technique pour la mise en oeuvre de nos solutions, contactez votre commercial ou cliquez sur ce lien pour obtenir un devis et demander une analyse personnalisée de votre projet à nos experts de l’équipe Professional Services.
-
Échangez avec notre communauté d'utilisateurs.