5.6. Opérateurs basés sur Java


5.6.1. Premiers pas avec Operator SDK pour les opérateurs basés sur Java

Important

Le SDK de l'opérateur basé sur Java est une fonctionnalité d'aperçu technologique uniquement. Les fonctionnalités de l'aperçu technologique ne sont pas prises en charge par les accords de niveau de service (SLA) de production de Red Hat et peuvent ne pas être complètes sur le plan fonctionnel. Red Hat ne recommande pas de les utiliser en production. Ces fonctionnalités offrent un accès anticipé aux fonctionnalités des produits à venir, ce qui permet aux clients de tester les fonctionnalités et de fournir un retour d'information pendant le processus de développement.

Pour plus d'informations sur la portée de l'assistance des fonctionnalités de l'aperçu technologique de Red Hat, voir Portée de l'assistance des fonctionnalités de l'aperçu technologique.

Pour démontrer les bases de la configuration et de l'exécution d'un opérateur Java à l'aide des outils et des bibliothèques fournis par le SDK Operator, les développeurs d'opérateurs peuvent créer un exemple d'opérateur Java pour Memcached, un magasin de valeurs clés distribué, et le déployer dans une grappe.

5.6.1.1. Conditions préalables

  • Operator SDK CLI installé
  • OpenShift CLI (oc) v4.12 installé
  • Java v11
  • Maven v3.6.3
  • Connexion à un cluster OpenShift Container Platform 4.12 avec oc avec un compte qui a les permissions cluster-admin
  • Pour permettre au cluster d'extraire l'image, le dépôt où vous avez poussé votre image doit être défini comme public, ou vous devez configurer un secret d'extraction d'image

5.6.1.2. Création et déploiement d'opérateurs basés sur Java

Vous pouvez construire et déployer un simple opérateur basé sur Java pour Memcached en utilisant le SDK de l'opérateur.

Procédure

  1. Create a project.

    1. Créez votre répertoire de projet :

      $ mkdir memcached-operator
    2. Allez dans le répertoire du projet :

      $ cd memcached-operator
    3. Exécutez la commande operator-sdk init avec le plugin quarkus pour initialiser le projet :

      $ operator-sdk init \
          --plugins=quarkus \
          --domain=example.com \
          --project-name=memcached-operator
  2. Create an API.

    Créer une API Memcached simple :

    $ operator-sdk create api \
        --plugins quarkus \
        --group cache \
        --version v1 \
        --kind Memcached
  3. Build and push the Operator image.

    Utilisez les cibles par défaut de Makefile pour construire et pousser votre opérateur. Définissez IMG avec une spécification d'extraction pour votre image qui utilise un registre vers lequel vous pouvez pousser :

    $ make docker-build docker-push IMG=<registry>/<user>/<image_name>:<tag>
  4. Run the Operator.

    1. Installer le CRD :

      $ make install
    2. Déployez le projet sur le cluster. Définissez IMG sur l'image que vous avez poussée :

      $ make deploy IMG=<registry>/<user>/<image_name>:<tag>
  5. Create a sample custom resource (CR).

    1. Créer un échantillon de CR :

      $ oc apply -f config/samples/cache_v1_memcached.yaml \
          -n memcached-operator-system
    2. Il faut s'attendre à ce que le CR réconcilie l'opérateur :

      $ oc logs deployment.apps/memcached-operator-controller-manager \
          -c manager \
          -n memcached-operator-system
  6. Delete a CR

    Supprimez un CR en exécutant la commande suivante :

    $ oc delete -f config/samples/cache_v1_memcached.yaml -n memcached-operator-system
  7. Clean up.

    Exécutez la commande suivante pour nettoyer les ressources qui ont été créées dans le cadre de cette procédure :

    $ make undeploy

5.6.1.3. Prochaines étapes

5.6.2. Didacticiel sur le SDK pour les opérateurs basés sur Java

Important

Le SDK de l'opérateur basé sur Java est une fonctionnalité d'aperçu technologique uniquement. Les fonctionnalités de l'aperçu technologique ne sont pas prises en charge par les accords de niveau de service (SLA) de production de Red Hat et peuvent ne pas être complètes sur le plan fonctionnel. Red Hat ne recommande pas de les utiliser en production. Ces fonctionnalités offrent un accès anticipé aux fonctionnalités des produits à venir, ce qui permet aux clients de tester les fonctionnalités et de fournir un retour d'information pendant le processus de développement.

Pour plus d'informations sur la portée de l'assistance des fonctionnalités de l'aperçu technologique de Red Hat, voir Portée de l'assistance des fonctionnalités de l'aperçu technologique.

Les développeurs d'opérateurs peuvent tirer parti de la prise en charge du langage de programmation Java dans l'Operator SDK pour créer un exemple d'opérateur basé sur Java pour Memcached, un magasin de valeurs clés distribué, et gérer son cycle de vie.

Ce processus est réalisé à l'aide de deux pièces maîtresses du cadre de l'opérateur :

SDK de l'opérateur
L'outil CLI operator-sdk et la bibliothèque API java-operator-sdk
Gestionnaire du cycle de vie des opérateurs (OLM)
Installation, mise à niveau et contrôle d'accès basé sur les rôles (RBAC) des opérateurs sur un cluster
Note

5.6.2.1. Conditions préalables

  • Operator SDK CLI installé
  • OpenShift CLI (oc) v4.12 installé
  • Java v11
  • Maven v3.6.3
  • Connexion à un cluster OpenShift Container Platform 4.12 avec oc avec un compte qui a les permissions cluster-admin
  • Pour permettre au cluster d'extraire l'image, le dépôt où vous avez poussé votre image doit être défini comme public, ou vous devez configurer un secret d'extraction d'image

5.6.2.2. Création d'un projet

Utilisez l'interface de programmation Operator SDK pour créer un projet appelé memcached-operator.

Procédure

  1. Créer un répertoire pour le projet :

    $ mkdir -p $HOME/projects/memcached-operator
  2. Accédez au répertoire :

    $ cd $HOME/projects/memcached-operator
  3. Exécutez la commande operator-sdk init avec le plugin quarkus pour initialiser le projet :

    $ operator-sdk init \
        --plugins=quarkus \
        --domain=example.com \
        --project-name=memcached-operator
5.6.2.2.1. Dossier PROJET

Parmi les fichiers générés par la commande operator-sdk init figure un fichier Kubebuilder PROJECT. Les commandes operator-sdk suivantes, ainsi que la sortie help, qui sont exécutées à partir de la racine du projet, lisent ce fichier et savent que le type de projet est Java. Par exemple :

domain: example.com
layout:
- quarkus.javaoperatorsdk.io/v1-alpha
projectName: memcached-operator
version: "3"

5.6.2.3. Création d'une API et d'un contrôleur

Utilisez le SDK CLI de l'opérateur pour créer une API et un contrôleur de définition de ressources personnalisées (CRD).

Procédure

  1. Exécutez la commande suivante pour créer une API :

    $ operator-sdk create api \
        --plugins=quarkus \ 1
        --group=cache \ 2
        --version=v1 \ 3
        --kind=Memcached 4
    1
    Définir le drapeau du plugin à quarkus.
    2
    Fixer l'indicateur de groupe à cache.
    3
    Attribuer la valeur v1 à l'indicateur de version.
    4
    Fixer le drapeau de type à Memcached.

Vérification

  1. Exécutez la commande tree pour visualiser la structure du fichier :

    $ tree

    Exemple de sortie

    .
    ├── Makefile
    ├── PROJECT
    ├── pom.xml
    └── src
        └── main
            ├── java
            │   └── com
            │       └── example
            │           ├── Memcached.java
            │           ├── MemcachedReconciler.java
            │           ├── MemcachedSpec.java
            │           └── MemcachedStatus.java
            └── resources
                └── application.properties
    
    6 directories, 8 files

5.6.2.3.1. Définition de l'API

Définir l'API pour la ressource personnalisée (CR) Memcached.

Procédure

  • Modifiez les fichiers suivants qui ont été générés dans le cadre du processus create api:

    1. Mettez à jour les attributs suivants dans le fichier MemcachedSpec.java pour définir l'état souhaité du CR Memcached:

      public class MemcachedSpec {
      
          private Integer size;
      
          public Integer getSize() {
              return size;
          }
      
          public void setSize(Integer size) {
              this.size = size;
          }
      }
    2. Mettez à jour les attributs suivants dans le fichier MemcachedStatus.java pour définir l'état observé de la CR Memcached:

      Note

      L'exemple ci-dessous illustre un champ d'état de nœud. Il est recommandé d'utiliser des propriétés d'état typiques dans la pratique.

      import java.util.ArrayList;
      import java.util.List;
      
      public class MemcachedStatus {
      
          // Add Status information here
          // Nodes are the names of the memcached pods
          private List<String> nodes;
      
          public List<String> getNodes() {
              if (nodes == null) {
                  nodes = new ArrayList<>();
              }
              return nodes;
          }
      
          public void setNodes(List<String> nodes) {
              this.nodes = nodes;
          }
      }
    3. Mettre à jour le fichier Memcached.java pour définir le Schema for Memcached APIs qui s'étend aux fichiers MemcachedSpec.java et MemcachedStatus.java.

      @Version("v1")
      @Group("cache.example.com")
      public class Memcached extends CustomResource<MemcachedSpec, MemcachedStatus> implements Namespaced {}
5.6.2.3.2. Générer des manifestes CRD

Une fois l'API définie à l'aide des fichiers MemcachedSpec et MemcachedStatus, vous pouvez générer des manifestes CRD.

Procédure

  • Exécutez la commande suivante à partir du répertoire memcached-operator pour générer le CRD :

    $ mvn clean install

Vérification

  • Vérifiez le contenu du CRD dans le fichier target/kubernetes/memcacheds.cache.example.com-v1.yml comme indiqué dans l'exemple suivant :

    $ cat target/kubernetes/memcacheds.cache.example.com-v1.yaml

    Exemple de sortie

    # Generated by Fabric8 CRDGenerator, manual edits might get overwritten!
    apiVersion: apiextensions.k8s.io/v1
    kind: CustomResourceDefinition
    metadata:
      name: memcacheds.cache.example.com
    spec:
      group: cache.example.com
      names:
        kind: Memcached
        plural: memcacheds
        singular: memcached
      scope: Namespaced
      versions:
      - name: v1
        schema:
          openAPIV3Schema:
            properties:
              spec:
                properties:
                  size:
                    type: integer
                type: object
              status:
                properties:
                  nodes:
                    items:
                      type: string
                    type: array
                type: object
            type: object
        served: true
        storage: true
        subresources:
          status: {}

5.6.2.3.3. Création d'une ressource personnalisée

Après avoir généré les manifestes CRD, vous pouvez créer la ressource personnalisée (CR).

Procédure

  • Créer un CR Memcached appelé memcached-sample.yaml:

    apiVersion: cache.example.com/v1
    kind: Memcached
    metadata:
      name: memcached-sample
    spec:
      # Add spec fields here
      size: 1

5.6.2.4. Mise en œuvre du contrôleur

Après avoir créé une nouvelle API et un nouveau contrôleur, vous pouvez mettre en œuvre la logique du contrôleur.

Procédure

  1. Ajoutez la dépendance suivante au fichier pom.xml:

        <dependency>
          <groupId>commons-collections</groupId>
          <artifactId>commons-collections</artifactId>
          <version>3.2.2</version>
        </dependency>
  2. Pour cet exemple, remplacez le fichier de contrôleur généré MemcachedReconciler.java par l'exemple de mise en œuvre suivant :

    Exemple 5.9. Exemple MemcachedReconciler.java

    package com.example;
    
    import io.fabric8.kubernetes.client.KubernetesClient;
    import io.javaoperatorsdk.operator.api.reconciler.Context;
    import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
    import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
    import io.fabric8.kubernetes.api.model.ContainerBuilder;
    import io.fabric8.kubernetes.api.model.ContainerPortBuilder;
    import io.fabric8.kubernetes.api.model.LabelSelectorBuilder;
    import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
    import io.fabric8.kubernetes.api.model.OwnerReferenceBuilder;
    import io.fabric8.kubernetes.api.model.Pod;
    import io.fabric8.kubernetes.api.model.PodSpecBuilder;
    import io.fabric8.kubernetes.api.model.PodTemplateSpecBuilder;
    import io.fabric8.kubernetes.api.model.apps.Deployment;
    import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder;
    import io.fabric8.kubernetes.api.model.apps.DeploymentSpecBuilder;
    import org.apache.commons.collections.CollectionUtils;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.stream.Collectors;
    
    public class MemcachedReconciler implements Reconciler<Memcached> {
      private final KubernetesClient client;
    
      public MemcachedReconciler(KubernetesClient client) {
        this.client = client;
      }
    
      // TODO Fill in the rest of the reconciler
    
      @Override
      public UpdateControl<Memcached> reconcile(
          Memcached resource, Context context) {
          // TODO: fill in logic
          Deployment deployment = client.apps()
                  .deployments()
                  .inNamespace(resource.getMetadata().getNamespace())
                  .withName(resource.getMetadata().getName())
                  .get();
    
          if (deployment == null) {
              Deployment newDeployment = createMemcachedDeployment(resource);
              client.apps().deployments().create(newDeployment);
              return UpdateControl.noUpdate();
          }
    
          int currentReplicas = deployment.getSpec().getReplicas();
          int requiredReplicas = resource.getSpec().getSize();
    
          if (currentReplicas != requiredReplicas) {
              deployment.getSpec().setReplicas(requiredReplicas);
              client.apps().deployments().createOrReplace(deployment);
              return UpdateControl.noUpdate();
          }
    
          List<Pod> pods = client.pods()
              .inNamespace(resource.getMetadata().getNamespace())
              .withLabels(labelsForMemcached(resource))
              .list()
              .getItems();
    
          List<String> podNames =
              pods.stream().map(p -> p.getMetadata().getName()).collect(Collectors.toList());
    
    
          if (resource.getStatus() == null
                   || !CollectionUtils.isEqualCollection(podNames, resource.getStatus().getNodes())) {
               if (resource.getStatus() == null) resource.setStatus(new MemcachedStatus());
               resource.getStatus().setNodes(podNames);
               return UpdateControl.updateResource(resource);
          }
    
          return UpdateControl.noUpdate();
      }
    
      private Map<String, String> labelsForMemcached(Memcached m) {
        Map<String, String> labels = new HashMap<>();
        labels.put("app", "memcached");
        labels.put("memcached_cr", m.getMetadata().getName());
        return labels;
      }
    
      private Deployment createMemcachedDeployment(Memcached m) {
          Deployment deployment = new DeploymentBuilder()
              .withMetadata(
                  new ObjectMetaBuilder()
                      .withName(m.getMetadata().getName())
                      .withNamespace(m.getMetadata().getNamespace())
                      .build())
              .withSpec(
                  new DeploymentSpecBuilder()
                      .withReplicas(m.getSpec().getSize())
                      .withSelector(
                          new LabelSelectorBuilder().withMatchLabels(labelsForMemcached(m)).build())
                      .withTemplate(
                          new PodTemplateSpecBuilder()
                              .withMetadata(
                                  new ObjectMetaBuilder().withLabels(labelsForMemcached(m)).build())
                              .withSpec(
                                  new PodSpecBuilder()
                                      .withContainers(
                                          new ContainerBuilder()
                                              .withImage("memcached:1.4.36-alpine")
                                              .withName("memcached")
                                              .withCommand("memcached", "-m=64", "-o", "modern", "-v")
                                              .withPorts(
                                                  new ContainerPortBuilder()
                                                      .withContainerPort(11211)
                                                      .withName("memcached")
                                                      .build())
                                              .build())
                                      .build())
                              .build())
                      .build())
              .build();
        deployment.addOwnerReference(m);
        return deployment;
      }
    }

    Le contrôleur de l'exemple exécute la logique de rapprochement suivante pour chaque ressource personnalisée (CR) Memcached:

    • Crée un déploiement Memcached s'il n'existe pas.
    • Veille à ce que la taille du déploiement corresponde à la taille spécifiée par la spécification Memcached CR.
    • Met à jour l'état de Memcached CR avec les noms des pods memcached.

Les sous-sections suivantes expliquent comment le contrôleur de l'exemple de mise en œuvre surveille les ressources et comment la boucle de rapprochement est déclenchée. Vous pouvez sauter ces sous-sections pour passer directement à l'exécution de l'opérateur.

5.6.2.4.1. Boucle de réconciliation
  1. Chaque contrôleur possède un objet de rapprochement avec une méthode Reconcile() qui met en œuvre la boucle de rapprochement. L'argument Deployment est transmis à la boucle de rapprochement, comme le montre l'exemple suivant :

            Deployment deployment = client.apps()
                    .deployments()
                    .inNamespace(resource.getMetadata().getNamespace())
                    .withName(resource.getMetadata().getName())
                    .get();
  2. Comme le montre l'exemple suivant, si le site Deployment est null, le déploiement doit être créé. Après avoir créé Deployment, vous pouvez déterminer si un rapprochement est nécessaire. Si la réconciliation n'est pas nécessaire, renvoyez la valeur de UpdateControl.noUpdate(), sinon renvoyez la valeur de `UpdateControl.updateStatus(resource) :

            if (deployment == null) {
                Deployment newDeployment = createMemcachedDeployment(resource);
                client.apps().deployments().create(newDeployment);
                return UpdateControl.noUpdate();
            }
  3. Après avoir obtenu le site Deployment, obtenez les répliques actuelles et requises, comme le montre l'exemple suivant :

            int currentReplicas = deployment.getSpec().getReplicas();
            int requiredReplicas = resource.getSpec().getSize();
  4. Si currentReplicas ne correspond pas à requiredReplicas, vous devez mettre à jour Deployment, comme le montre l'exemple suivant :

            if (currentReplicas != requiredReplicas) {
                deployment.getSpec().setReplicas(requiredReplicas);
                client.apps().deployments().createOrReplace(deployment);
                return UpdateControl.noUpdate();
            }
  5. L'exemple suivant montre comment obtenir la liste des pods et leurs noms :

            List<Pod> pods = client.pods()
                .inNamespace(resource.getMetadata().getNamespace())
                .withLabels(labelsForMemcached(resource))
                .list()
                .getItems();
    
            List<String> podNames =
                pods.stream().map(p -> p.getMetadata().getName()).collect(Collectors.toList());
  6. Vérifiez si des ressources ont été créées et vérifiez les podnames avec les ressources Memcached. En cas de non-concordance dans l'une ou l'autre de ces conditions, procédez à une réconciliation comme indiqué dans l'exemple suivant :

            if (resource.getStatus() == null
                    || !CollectionUtils.isEqualCollection(podNames, resource.getStatus().getNodes())) {
                if (resource.getStatus() == null) resource.setStatus(new MemcachedStatus());
                resource.getStatus().setNodes(podNames);
                return UpdateControl.updateResource(resource);
            }
5.6.2.4.2. Définir labelsForMemcached

labelsForMemcached est un utilitaire qui renvoie une carte des étiquettes à attacher aux ressources :

    private Map<String, String> labelsForMemcached(Memcached m) {
        Map<String, String> labels = new HashMap<>();
        labels.put("app", "memcached");
        labels.put("memcached_cr", m.getMetadata().getName());
        return labels;
    }
5.6.2.4.3. Définir le createMemcachedDeployment

La méthode createMemcachedDeployment utilise la classe DeploymentBuilder de fabric8:

    private Deployment createMemcachedDeployment(Memcached m) {
        Deployment deployment = new DeploymentBuilder()
            .withMetadata(
                new ObjectMetaBuilder()
                    .withName(m.getMetadata().getName())
                    .withNamespace(m.getMetadata().getNamespace())
                    .build())
            .withSpec(
                new DeploymentSpecBuilder()
                    .withReplicas(m.getSpec().getSize())
                    .withSelector(
                        new LabelSelectorBuilder().withMatchLabels(labelsForMemcached(m)).build())
                    .withTemplate(
                        new PodTemplateSpecBuilder()
                            .withMetadata(
                                new ObjectMetaBuilder().withLabels(labelsForMemcached(m)).build())
                            .withSpec(
                                new PodSpecBuilder()
                                    .withContainers(
                                        new ContainerBuilder()
                                            .withImage("memcached:1.4.36-alpine")
                                            .withName("memcached")
                                            .withCommand("memcached", "-m=64", "-o", "modern", "-v")
                                            .withPorts(
                                                new ContainerPortBuilder()
                                                    .withContainerPort(11211)
                                                    .withName("memcached")
                                                    .build())
                                            .build())
                                    .build())
                            .build())
                    .build())
            .build();
      deployment.addOwnerReference(m);
      return deployment;
    }

5.6.2.5. Fonctionnement de l'opérateur

Vous pouvez utiliser l'interface de programmation de l'opérateur SDK de trois manières différentes pour créer et exécuter votre opérateur :

  • Exécuter localement en dehors du cluster comme un programme Go.
  • Exécuter en tant que déploiement sur le cluster.
  • Regroupez votre opérateur et utilisez Operator Lifecycle Manager (OLM) pour le déployer sur le cluster.
5.6.2.5.1. Exécution locale en dehors du cluster

Vous pouvez exécuter votre projet Operator en tant que programme Go en dehors du cluster. Ceci est utile pour le développement afin d'accélérer le déploiement et les tests.

Procédure

  1. Exécutez la commande suivante pour compiler l'Opérateur :

    $ mvn clean install

    Exemple de sortie

    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time:  11.193 s
    [INFO] Finished at: 2021-05-26T12:16:54-04:00
    [INFO] ------------------------------------------------------------------------

  2. Exécutez la commande suivante pour installer le CRD dans l'espace de noms par défaut :

    $ oc apply -f target/kubernetes/memcacheds.cache.example.com-v1.yml

    Exemple de sortie

    customresourcedefinition.apiextensions.k8s.io/memcacheds.cache.example.com created

  3. Créez un fichier appelé rbac.yaml comme indiqué dans l'exemple suivant :

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: memcached-operator-admin
    subjects:
    - kind: ServiceAccount
      name: memcached-quarkus-operator-operator
      namespace: default
    roleRef:
      kind: ClusterRole
      name: cluster-admin
      apiGroup: ""
  4. Exécutez la commande suivante pour accorder les privilèges de cluster-admin à memcached-quarkus-operator-operator en appliquant le fichier rbac.yaml:

    $ oc apply -f rbac.yaml
  5. Saisissez la commande suivante pour lancer l'opérateur :

    $ java -jar target/quarkus-app/quarkus-run.jar
    Note

    La commande java lancera l'opérateur et restera active jusqu'à ce que vous mettiez fin au processus. Vous aurez besoin d'un autre terminal pour exécuter le reste de ces commandes.

  6. Appliquez le fichier memcached-sample.yaml à l'aide de la commande suivante :

    $ kubectl apply -f memcached-sample.yaml

    Exemple de sortie

    memcached.cache.example.com/memcached-sample created

Vérification

  • Exécutez la commande suivante pour confirmer que le module a démarré :

    $ oc get all

    Exemple de sortie

    NAME                                                       READY   STATUS    RESTARTS   AGE
    pod/memcached-sample-6c765df685-mfqnz                      1/1     Running   0          18s

5.6.2.5.2. Exécution en tant que déploiement sur le cluster

Vous pouvez exécuter votre projet Operator en tant que déploiement sur votre cluster.

Procédure

  1. Exécutez les commandes make suivantes pour construire et pousser l'image de l'opérateur. Modifiez l'argument IMG dans les étapes suivantes pour référencer un référentiel auquel vous avez accès. Vous pouvez obtenir un compte pour stocker des conteneurs sur des sites de dépôt tels que Quay.io.

    1. Construire l'image :

      $ make docker-build IMG=<registry>/<user>/<image_name>:<tag>
      Note

      Le fichier Docker généré par le SDK pour l'Operator fait explicitement référence à GOARCH=amd64 pour go build. Cette référence peut être modifiée en GOARCH=$TARGETARCH pour les architectures non-AMD64. Docker définira automatiquement la variable d'environnement à la valeur spécifiée par –platform. Avec Buildah, il faudra utiliser –build-arg à cette fin. Pour plus d'informations, voir Architectures multiples.

    2. Transférer l'image dans un référentiel :

      $ make docker-push IMG=<registry>/<user>/<image_name>:<tag>
      Note

      Le nom et la balise de l'image, par exemple IMG=<registry>/<user>/<image_name>:<tag>, dans les deux commandes peuvent également être définis dans votre Makefile. Modifiez la valeur de IMG ?= controller:latest pour définir votre nom d'image par défaut.

  2. Exécutez la commande suivante pour installer le CRD dans l'espace de noms par défaut :

    $ oc apply -f target/kubernetes/memcacheds.cache.example.com-v1.yml

    Exemple de sortie

    customresourcedefinition.apiextensions.k8s.io/memcacheds.cache.example.com created

  3. Créez un fichier appelé rbac.yaml comme indiqué dans l'exemple suivant :

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: memcached-operator-admin
    subjects:
    - kind: ServiceAccount
      name: memcached-quarkus-operator-operator
      namespace: default
    roleRef:
      kind: ClusterRole
      name: cluster-admin
      apiGroup: ""
    Important

    Le fichier rbac.yaml sera appliqué à une étape ultérieure.

  4. Exécutez la commande suivante pour déployer l'opérateur :

    $ make deploy IMG=<registry>/<user>/<image_name>:<tag>
  5. Exécutez la commande suivante pour accorder les privilèges de cluster-admin à memcached-quarkus-operator-operator en appliquant le fichier rbac.yaml créé à l'étape précédente :

    $ oc apply -f rbac.yaml
  6. Exécutez la commande suivante pour vérifier que l'opérateur fonctionne :

    $ oc get all -n default

    Exemple de sortie

    NAME                                                      READY   UP-TO-DATE   AVAILABLE   AGE
    pod/memcached-quarkus-operator-operator-7db86ccf58-k4mlm   0/1       Running   0           18s

  7. Exécutez la commande suivante pour appliquer le memcached-sample.yaml et créer le pod memcached-sample:

    $ oc apply -f memcached-sample.yaml

    Exemple de sortie

    memcached.cache.example.com/memcached-sample created

Vérification

  • Exécutez la commande suivante pour confirmer le démarrage des pods :

    $ oc get all

    Exemple de sortie

    NAME                                                       READY   STATUS    RESTARTS   AGE
    pod/memcached-quarkus-operator-operator-7b766f4896-kxnzt   1/1     Running   1          79s
    pod/memcached-sample-6c765df685-mfqnz                      1/1     Running   0          18s

5.6.2.5.3. Regroupement d'un opérateur et déploiement avec Operator Lifecycle Manager
5.6.2.5.3.1. Regroupement d'un opérateur

Le format Operator bundle est la méthode d'emballage par défaut pour Operator SDK et Operator Lifecycle Manager (OLM). Vous pouvez préparer votre Operator pour une utilisation sur OLM en utilisant Operator SDK pour construire et pousser votre projet Operator en tant qu'image groupée.

Conditions préalables

  • Operator SDK CLI installé sur un poste de développement
  • OpenShift CLI (oc) v4.12 installé
  • Projet d'opérateur initialisé à l'aide de l'Operator SDK

Procédure

  1. Exécutez les commandes make suivantes dans le répertoire de votre projet Operator pour construire et pousser votre image Operator. Modifiez l'argument IMG dans les étapes suivantes pour référencer un référentiel auquel vous avez accès. Vous pouvez obtenir un compte pour stocker des conteneurs sur des sites de dépôt tels que Quay.io.

    1. Construire l'image :

      $ make docker-build IMG=<registry>/<user>/<operator_image_name>:<tag>
      Note

      Le fichier Docker généré par le SDK pour l'Operator fait explicitement référence à GOARCH=amd64 pour go build. Cette référence peut être modifiée en GOARCH=$TARGETARCH pour les architectures non-AMD64. Docker définira automatiquement la variable d'environnement à la valeur spécifiée par –platform. Avec Buildah, il faudra utiliser –build-arg à cette fin. Pour plus d'informations, voir Architectures multiples.

    2. Transférer l'image dans un référentiel :

      $ make docker-push IMG=<registry>/<user>/<operator_image_name>:<tag>
  2. Créez votre manifeste Operator bundle en exécutant la commande make bundle, qui invoque plusieurs commandes, dont les sous-commandes Operator SDK generate bundle et bundle validate:

    $ make bundle IMG=<registry>/<user>/<operator_image_name>:<tag>

    Les manifestes de l'offre groupée d'un opérateur décrivent la manière d'afficher, de créer et de gérer une application. La commande make bundle crée les fichiers et répertoires suivants dans votre projet Operator :

    • Un répertoire bundle manifests nommé bundle/manifests qui contient un objet ClusterServiceVersion
    • Un répertoire de métadonnées de la liasse nommé bundle/metadata
    • Toutes les définitions de ressources personnalisées (CRD) dans un répertoire config/crd
    • Un fichier Docker bundle.Dockerfile

    Ces fichiers sont ensuite automatiquement validés à l'aide de operator-sdk bundle validate afin de s'assurer que la représentation du paquet sur le disque est correcte.

  3. Construisez et poussez votre image de bundle en exécutant les commandes suivantes. OLM consomme les liasses d'opérateurs à l'aide d'une image d'index, qui fait référence à une ou plusieurs images de liasses.

    1. Créez l'image de l'ensemble. Définissez BUNDLE_IMG avec les détails du registre, de l'espace de noms de l'utilisateur et de la balise d'image où vous avez l'intention de pousser l'image :

      $ make bundle-build BUNDLE_IMG=<registry>/<user>/<bundle_image_name>:<tag>
    2. Pousser l'image de la liasse :

      $ docker push <registry>/<user>/<bundle_image_name>:<tag>
5.6.2.5.3.2. Déploiement d'un opérateur avec Operator Lifecycle Manager

Operator Lifecycle Manager (OLM) vous aide à installer, mettre à jour et gérer le cycle de vie des opérateurs et de leurs services associés sur un cluster Kubernetes. OLM est installé par défaut sur OpenShift Container Platform et s'exécute en tant qu'extension Kubernetes afin que vous puissiez utiliser la console web et l'OpenShift CLI (oc) pour toutes les fonctions de gestion du cycle de vie des opérateurs sans outils supplémentaires.

Le format Operator bundle est la méthode d'emballage par défaut pour Operator SDK et OLM. Vous pouvez utiliser Operator SDK pour exécuter rapidement une image de bundle sur OLM afin de vous assurer qu'elle fonctionne correctement.

Conditions préalables

  • Operator SDK CLI installé sur un poste de développement
  • L'image de l'ensemble de l'opérateur est construite et poussée vers un registre
  • OLM installé sur un cluster basé sur Kubernetes (v1.16.0 ou version ultérieure si vous utilisez apiextensions.k8s.io/v1 CRD, par exemple OpenShift Container Platform 4.12)
  • Connexion au cluster avec oc en utilisant un compte avec les permissions de cluster-admin

Procédure

  1. Saisissez la commande suivante pour exécuter l'opérateur sur le cluster :

    $ operator-sdk run bundle \1
        -n <namespace> \2
        <registry>/<user>/<bundle_image_name>:<tag> 3
    1
    La commande run bundle crée un catalogue de fichiers valide et installe le paquet Operator sur votre cluster à l'aide d'OLM.
    2
    Facultatif : Par défaut, la commande installe l'opérateur dans le projet actif dans votre fichier ~/.kube/config. Vous pouvez ajouter l'option -n pour définir un espace de noms différent pour l'installation.
    3
    Si vous ne spécifiez pas d'image, la commande utilise quay.io/operator-framework/opm:latest comme image d'index par défaut. Si vous spécifiez une image, la commande utilise l'image du paquet elle-même comme image d'index.
    Important

    Depuis OpenShift Container Platform 4.11, la commande run bundle prend en charge par défaut le format de catalogue basé sur des fichiers pour les catalogues Operator. Le format de base de données SQLite déprécié pour les catalogues Operator continue d'être pris en charge ; cependant, il sera supprimé dans une prochaine version. Il est recommandé aux auteurs d'Operator de migrer leurs flux de travail vers le format de catalogue basé sur des fichiers.

    Cette commande permet d'effectuer les actions suivantes :

    • Créez une image d'index faisant référence à votre image de liasse. L'image d'index est opaque et éphémère, mais elle reflète fidèlement la manière dont un paquet serait ajouté à un catalogue en production.
    • Créez une source de catalogue qui pointe vers votre nouvelle image d'index, ce qui permet à OperatorHub de découvrir votre opérateur.
    • Déployez votre opérateur sur votre cluster en créant un site OperatorGroup, Subscription, InstallPlan, et toutes les autres ressources nécessaires, y compris RBAC.

5.6.2.6. Ressources supplémentaires

5.6.3. Présentation du projet pour les opérateurs basés sur Java

Important

Le SDK de l'opérateur basé sur Java est une fonctionnalité d'aperçu technologique uniquement. Les fonctionnalités de l'aperçu technologique ne sont pas prises en charge par les accords de niveau de service (SLA) de production de Red Hat et peuvent ne pas être complètes sur le plan fonctionnel. Red Hat ne recommande pas de les utiliser en production. Ces fonctionnalités offrent un accès anticipé aux fonctionnalités des produits à venir, ce qui permet aux clients de tester les fonctionnalités et de fournir un retour d'information pendant le processus de développement.

Pour plus d'informations sur la portée de l'assistance des fonctionnalités de l'aperçu technologique de Red Hat, voir Portée de l'assistance des fonctionnalités de l'aperçu technologique.

Le CLI operator-sdk peut générer, ou scaffold, un certain nombre de paquets et de fichiers pour chaque projet Operator.

5.6.3.1. Mise en page de projet basée sur Java

Les projets Operator basés sur Java générés par la commande operator-sdk init contiennent les fichiers et répertoires suivants :

Fichier ou répertoireObjectif

pom.xml

Fichier contenant les dépendances nécessaires à l'exécution de l'opérateur.

<domain>/

Répertoire qui contient les fichiers représentant l'API. Si le domaine est example.com, ce dossier s'appelle example/.

MemcachedReconciler.java

Fichier Java qui définit les implémentations du contrôleur.

MemcachedSpec.java

Fichier Java qui définit l'état souhaité du CR Memcached.

MemcachedStatus.java

Fichier Java qui définit l'état observé du CR Memcached.

Memcached.java

Fichier Java qui définit le schéma des API de Memcached.

target/kubernetes/

Répertoire contenant les fichiers yaml du CRD.

5.6.4. Mise à jour des projets pour les nouvelles versions du SDK de l'opérateur

OpenShift Container Platform 4.12 supporte Operator SDK 1.25.4. Si vous avez déjà le CLI 1.22.0 installé sur votre station de travail, vous pouvez mettre à jour le CLI vers 1.25.4 en installant la dernière version.

Cependant, pour que vos projets Operator existants restent compatibles avec Operator SDK 1.25.4, des étapes de mise à jour sont nécessaires pour les ruptures associées introduites depuis la version 1.22.0. Vous devez effectuer les étapes de mise à jour manuellement dans tous vos projets Operator qui ont été précédemment créés ou maintenus avec la version 1.22.0.

5.6.4.1. Mise à jour des projets Operator basés sur Java pour Operator SDK 1.25.4

La procédure suivante permet de mettre à jour un projet d'opérateur Java existant pour le rendre compatible avec la version 1.25.4.

Conditions préalables

  • Operator SDK 1.25.4 installé
  • Un projet Operator créé ou maintenu avec Operator SDK 1.22.0

Procédure

  1. Apportez les modifications suivantes au fichier config/default/manager_auth_proxy_patch.yaml:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: controller-manager
      namespace: system
    spec:
      template:
        spec:
          containers:
          - name: kube-rbac-proxy
            image: registry.redhat.io/openshift4/ose-kube-rbac-proxy:v4.12 1
            args:
            - "--secure-listen-address=0.0.0.0:8443"
            - "--upstream=http://127.0.0.1:8080/"
            - "--logtostderr=true"
            - "--v=0"
    ...
    1
    Mettre à jour la version de la balise de v4.11 à v4.12.
  2. Apportez les modifications suivantes à votre site Makefile:

    1. Pour activer la prise en charge des architectures multiples, ajoutez la cible docker-buildx à votre projet Makefile:

      Exemple Makefile

      # PLATFORMS defines the target platforms for  the manager image be build to provide support to multiple
      # architectures. (i.e. make docker-buildx IMG=myregistry/mypoperator:0.0.1). To use this option you need to:
      # - able to use docker buildx . More info: https://docs.docker.com/build/buildx/
      # - have enable BuildKit, More info: https://docs.docker.com/develop/develop-images/build_enhancements/
      # - be able to push the image for your registry (i.e. if you do not inform a valid value via IMG=<myregistry/image:<tag>> than the export will fail)
      # To properly provided solutions that supports more than one platform you should use this option.
      PLATFORMS ?= linux/arm64,linux/amd64,linux/s390x,linux/ppc64le
      .PHONY: docker-buildx
      docker-buildx: test ## Build and push docker image for the manager for cross-platform support
      	# copy existing Dockerfile and insert --platform=${BUILDPLATFORM} into Dockerfile.cross, and preserve the original Dockerfile
      	sed -e '1 s/\(^FROM\)/FROM --platform=\$$\{BUILDPLATFORM\}/; t' -e ' 1,// s//FROM --platform=\$$\{BUILDPLATFORM\}/' Dockerfile > Dockerfile.cross
      	- docker buildx create --name project-v3-builder
      	docker buildx use project-v3-builder
      	- docker buildx build --push --platform=$(PLATFORMS) --tag ${IMG} -f Dockerfile.cross
      	- docker buildx rm project-v3-builder
      	rm Dockerfile.cross

    2. Pour appliquer les changements à votre Makefile et reconstruire votre Opérateur, entrez la commande suivante :

      $ make

5.6.4.2. Ressources supplémentaires

Red Hat logoGithubRedditYoutubeTwitter

Apprendre

Essayez, achetez et vendez

Communautés

À propos de la documentation Red Hat

Nous aidons les utilisateurs de Red Hat à innover et à atteindre leurs objectifs grâce à nos produits et services avec un contenu auquel ils peuvent faire confiance.

Rendre l’open source plus inclusif

Red Hat s'engage à remplacer le langage problématique dans notre code, notre documentation et nos propriétés Web. Pour plus de détails, consultez leBlog Red Hat.

À propos de Red Hat

Nous proposons des solutions renforcées qui facilitent le travail des entreprises sur plusieurs plates-formes et environnements, du centre de données central à la périphérie du réseau.

© 2024 Red Hat, Inc.