For AI agents: the complete documentation index is available at https://docs.ovhcloud.com/fr/llms.txt, the full documentation bundle is available at https://docs.ovhcloud.com/fr/llms-full.txt, and this page is available as Markdown at https://docs.ovhcloud.com/fr/guides/public-cloud/containers-orchestration/managed-kubernetes/deploy-helm-operator.md.

Déployer un opérateur Kubernetes basé sur Helm sur OVHcloud Managed Kubernetes

Voir en Markdown

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.

Schéma d'un opérateur

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 :

operator-sdk version

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 :

helm-operator run

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/ :

Hello world depuis Nginx

À 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.

Cette page vous a-t-elle aidé ?