Mysql
 sql >> Base de données >  >> RDS >> Mysql

Présentation de l'opérateur Kubernetes du cluster Percona XtraDB

Si vous avez été dans le monde des conteneurs, vous sauriez qu'il est assez difficile d'adopter une automatisation complète de Kubernetes pour un système de base de données en cluster, ce qui ajoute généralement un niveau de complexité au conteneur. architecture pour ces applications avec état. C'est là qu'un opérateur Kubernetes peut nous aider à résoudre ce problème. Un opérateur Kubernetes est un type spécial de contrôleur introduit pour simplifier les déploiements complexes qui étend essentiellement l'API Kubernetes avec des ressources personnalisées. Il s'appuie sur les concepts de base des ressources et des contrôleurs Kubernetes, mais inclut des connaissances spécifiques au domaine ou à l'application pour automatiser l'ensemble du cycle de vie du logiciel qu'il gère.

Percona XtraDB Cluster Operator est un moyen astucieux d'automatiser les tâches spécifiques de Percona XtraDB Cluster telles que le déploiement, la mise à l'échelle, les sauvegardes et les mises à niveau au sein de Kubernetes, construit et maintenu par Percona. Il déploie le cluster dans un StatefulSet avec un volume persistant, ce qui nous permet de maintenir une identité cohérente pour chaque pod du cluster et nos données à conserver.

Dans cet article de blog, nous allons tester le déploiement de Percona XtraDB Cluster 8.0 dans un environnement conteneurisé, orchestré par Percona XtraDB Cluster Kubernetes Operator sur Google Cloud Platform.

Créer un cluster Kubernetes sur Google Cloud

Dans cette procédure pas à pas, nous allons utiliser le cluster Kubernetes sur Google Cloud, car il est relativement simple et facile de faire fonctionner Kubernetes. Connectez-vous à votre tableau de bord Google Cloud Platform -> Calcul -> Kubernetes Engine -> Créer un cluster, et la boîte de dialogue suivante s'affichera :

Entrez simplement le nom du cluster Kubernetes, choisissez votre zone préférée et cliquez sur "CRÉER " (au bas de la page). Dans 5 minutes, un cluster Kubernetes à 3 nœuds sera prêt. Maintenant, sur votre poste de travail, installez le SDK gcloud comme indiqué dans ce guide, puis importez la configuration Kubernetes sur votre poste de travail :

$ gcloud container clusters get-credentials my-k8s-cluster --zone asia-northeast1-a --project s9s-qa
Fetching cluster endpoint and auth data.
kubeconfig entry generated for my-k8s-cluster.

Vous devriez pouvoir vous connecter au cluster Kubernetes à ce stade. Exécutez la commande suivante pour vérifier :

$ kubectl get nodes
NAME                                            STATUS   ROLES    AGE    VERSION
gke-my-k8s-cluster-default-pool-b80902cd-gp09   Ready    <none>   139m   v1.16.13-gke.401
gke-my-k8s-cluster-default-pool-b80902cd-jdc3   Ready    <none>   139m   v1.16.13-gke.401
gke-my-k8s-cluster-default-pool-b80902cd-rdv8   Ready    <none>   139m   v1.16.13-gke.401

La sortie ci-dessus signifie que nous pouvons nous connecter au maître Kubernetes et récupérer les nœuds du cluster Kubernetes. Nous sommes maintenant prêts à exécuter les charges de travail Kubernetes.

Déployer un cluster Percona XtraDB sur Kubernetes

Pour le déploiement de la charge de travail, nous allons suivre les instructions indiquées dans la documentation Percona XtraDB Cluster Operator. Fondamentalement, nous exécutons la commande suivante sur notre poste de travail pour créer les ressources personnalisées, l'espace de noms, le contrôle d'accès basé sur les rôles et également l'opérateur Kubernetes lui-même :

$ git clone -b v1.6.0 https://github.com/percona/percona-xtradb-cluster-operator
$ cd percona-xtradb-cluster-operator/
$ kubectl apply -f deploy/crd.yaml
$ kubectl create namespace pxc
$ kubectl config set-context $(kubectl config current-context) --namespace=pxc
$ kubectl create clusterrolebinding cluster-admin-binding --clusterrole=cluster-admin --user=$(gcloud config get-value core/account)
$ kubectl apply -f deploy/rbac.yaml
$ kubectl apply -f deploy/operator.yaml

Ensuite, nous devons préparer nos mots de passe (cela s'appelle Secrets dans le terme Kubernetes) en mettant à jour les valeurs dans deploy/secrets.yaml dans un format encodé en base64. Vous pouvez utiliser des outils en ligne comme https://www.base64encode.org/ pour en créer un ou utiliser un outil de ligne de commande comme celui-ci :

$ echo -n 'mypassword' | base64
bXlwYXNzd29yZA==

Ensuite, mettez à jour le fichier deploy/secrets.yaml, comme indiqué ci-dessous :

apiVersion: v1
kind: Secret
metadata:
  name: my-cluster-secrets
type: Opaque
data:
  root: bXlwYXNzd29yZA==
  xtrabackup: bXlwYXNzd29yZA==
  monitor: bXlwYXNzd29yZA==
  clustercheck: bXlwYXNzd29yZA==
  proxyadmin: bXlwYXNzd29yZA==
  pmmserver: bXlwYXNzd29yZA==
  operator: bXlwYXNzd29yZA==

Ce qui précède est une super simplification de la gestion des secrets, où nous définissons tous les mots de passe pour qu'ils soient identiques pour tous les utilisateurs. En production, veuillez utiliser un mot de passe plus complexe et spécifier un mot de passe différent pour chaque utilisateur.

Maintenant, nous pouvons envoyer la configuration secrète à Kubernetes :

$ kubectl apply -f deploy/secrets.yaml

Avant de poursuivre le déploiement d'un cluster Percona XtraDB, nous devons revoir la définition de déploiement par défaut dans deploy/cr.yaml pour le cluster. De nombreux objets Kubernetes sont définis ici, mais la plupart d'entre eux sont commentés. Pour notre charge de travail, nous ferions la modification comme ci-dessous :

$ cat deploy/cr.yaml
apiVersion: pxc.percona.com/v1-6-0
kind: PerconaXtraDBCluster
metadata:
  name: cluster1
  finalizers:
    - delete-pxc-pods-in-order
spec:
  crVersion: 1.6.0
  secretsName: my-cluster-secrets
  vaultSecretName: keyring-secret-vault
  sslSecretName: my-cluster-ssl
  sslInternalSecretName: my-cluster-ssl-internal
  allowUnsafeConfigurations: false
  updateStrategy: SmartUpdate
  upgradeOptions:
    versionServiceEndpoint: https://check.percona.com
    apply: recommended
    schedule: "0 4 * * *"
  pxc:
    size: 3
    image: percona/percona-xtradb-cluster:8.0.20-11.1
    configuration: |
      [client]
      default-character-set=utf8

      [mysql]
      default-character-set=utf8

      [mysqld]
      collation-server = utf8_unicode_ci
      character-set-server = utf8
      default_authentication_plugin = mysql_native_password
    resources:
      requests:
        memory: 1G
    affinity:
      antiAffinityTopologyKey: "kubernetes.io/hostname"
    podDisruptionBudget:
      maxUnavailable: 1
    volumeSpec:
      persistentVolumeClaim:
        resources:
          requests:
            storage: 6Gi
    gracePeriod: 600
  haproxy:
    enabled: true
    size: 3
    image: percona/percona-xtradb-cluster-operator:1.6.0-haproxy
    resources:
      requests:
        memory: 1G
    affinity:
      antiAffinityTopologyKey: "kubernetes.io/hostname"
    podDisruptionBudget:
      maxUnavailable: 1
    gracePeriod: 30
  backup:
    image: percona/percona-xtradb-cluster-operator:1.6.0-pxc8.0-backup
    storages:
      fs-pvc:
        type: filesystem
        volume:
          persistentVolumeClaim:
            accessModes: [ "ReadWriteOnce" ]
            resources:
              requests:
                storage: 6Gi
    schedule:
      - name: "daily-backup"
        schedule: "0 0 * * *"
        keep: 5
        storageName: fs-pvc

Nous avons apporté quelques modifications au cr.yaml fourni pour le faire fonctionner avec notre application, comme indiqué ci-dessus. Tout d'abord, nous devons commenter (ou supprimer) toutes les lignes liées au CPU, par exemple [*].resources.requests.cpu:600m, pour nous assurer que Kubernetes est en mesure de planifier correctement la création du pod sur les nœuds avec un CPU limité. Ensuite, nous devons ajouter des options de compatibilité pour Percona XtraDB Cluster 8.0 qui est basé sur MySQL 8.0, pour fonctionner en douceur avec notre application WordPress que nous allons déployer plus tard, comme le montre l'extrait suivant :

Configuration
   configuration: |
      [client]
      default-character-set=utf8

      [mysql]
      default-character-set=utf8

      [mysqld]
      collation-server = utf8_unicode_ci
      character-set-server = utf8
      default_authentication_plugin = mysql_native_password

Ce qui précède correspondra au jeu de caractères par défaut du serveur MySQL avec le pilote PHP MySQLi dans notre conteneur WordPress. La section suivante est le déploiement HAProxy où il est défini sur "enabled:true". Il existe également une section ProxySQL avec "enabled:false" - généralement, on choisirait l'un des proxys inverses pour chaque cluster. La dernière section est la configuration de la sauvegarde, où nous aimerions avoir une sauvegarde quotidienne planifiée à 12h00 tous les jours et conserver les 5 dernières sauvegardes.

Nous pouvons maintenant commencer à déployer notre cluster Percona XtraDB à 3 nœuds :

$ kubectl apply -f deploy/cr.yaml

Le processus de création prendra un certain temps. L'opérateur déploiera les pods du cluster Percona XtraDB en tant qu'ensemble avec état, ce qui signifie qu'une création de pod à la fois et chaque pod dans le StatefulSet se verra attribuer un ordinal entier, de 0 à N-1, qui est unique sur l'ensemble. Le processus est terminé lorsque l'opérateur et les pods ont atteint leur état d'exécution :

$ kubectl get pods
NAME                                               READY   STATUS    RESTARTS   AGE
cluster1-haproxy-0                                 2/2     Running   0          71m
cluster1-haproxy-1                                 2/2     Running   0          70m
cluster1-haproxy-2                                 2/2     Running   0          70m
cluster1-pxc-0                                     1/1     Running   0          71m
cluster1-pxc-1                                     1/1     Running   0          70m
cluster1-pxc-2                                     1/1     Running   0          69m
percona-xtradb-cluster-operator-79d786dcfb-6clld   1/1     Running   0          121m

Étant donné que cet opérateur est une ressource personnalisée, nous pouvons manipuler la ressource perconaxtradbcluster pour qu'elle ressemble à la ressource Kubernetes standard :

$ kubectl get perconaxtradbcluster
NAME       ENDPOINT               STATUS   PXC   PROXYSQL   HAPROXY   AGE
cluster1   cluster1-haproxy.pxc   ready    3                3         27h

Vous pouvez également utiliser le nom de ressource plus court, "pxc", et essayer avec les commandes suivantes :

$ kubectl describe pxc
$ kubectl edit pxc

En regardant l'ensemble de charge de travail, nous pouvons dire que l'opérateur a créé deux StatefulSets :

$ kubectl get statefulsets -o wide
NAME               READY   AGE   CONTAINERS          IMAGES
cluster1-haproxy   3/3     26h   haproxy,pxc-monit   percona/percona-xtradb-cluster-operator:1.6.0-haproxy,percona/percona-xtradb-cluster-operator:1.6.0-haproxy
cluster1-pxc       3/3     26h   pxc                 percona/percona-xtradb-cluster:8.0.20-11.2

L'opérateur créera également les services correspondants qui équilibreront la charge des connexions aux pods respectifs :

$ kubectl get service
NAME                        TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)                       AGE
cluster1-haproxy            ClusterIP      10.40.9.177    <none>          3306/TCP,3309/TCP,33062/TCP   3h27m
cluster1-haproxy-replicas   ClusterIP      10.40.0.236    <none>          3306/TCP                      3h27m
cluster1-pxc                ClusterIP      None           <none>          3306/TCP,33062/TCP            3h27m
cluster1-pxc-unready        ClusterIP      None           <none>          3306/TCP,33062/TCP            3h27m

La sortie ci-dessus montre que l'opérateur a créé 4 services :

  • cluster1-haproxy - Le service pour un maître unique MySQL à charge équilibrée (3306), le protocole Proxy (3309) et MySQL Admin (33062) - Un nouveau port administratif introduit dans MySQL 8.0.14 et versions ultérieures. Il s'agit du nom de service ou de l'adresse IP du cluster auquel les applications doivent se connecter pour avoir une connexion maître unique au cluster Galera.
  • cluster1-haproxy-replicas - Le service pour un multi-maître MySQL à charge équilibrée (3306). Il s'agit du nom de service ou de l'adresse IP du cluster auquel les applications doivent se connecter pour avoir une connexion multimaître au cluster Galera avec un algorithme d'équilibrage à tour de rôle.
  • cluster1-pxc - Le service pour les pods PXC à charge équilibrée, en contournant HAProxy. En se connectant directement à ce service, Kubernetes acheminera la connexion de manière circulaire vers tous les pods PXC, comme ce que fournit cluster-haproxy-replicase. Le service n'a pas d'adresse IP publique attribuée et n'est pas disponible en dehors du cluster.
  • cluster1-pxc-unready - Le service "non prêt" est nécessaire pour la découverte d'adresse de pod lors du démarrage de l'application, quel que soit l'état du pod. Les pods proxysql et pxc doivent se connaître avant que la base de données ne devienne pleinement opérationnelle. Le service non prêt n'a pas d'adresse IP publique attribuée et n'est pas disponible en dehors du cluster.

Pour vous connecter via un client MySQL, exécutez simplement la commande suivante :

$ kubectl run -i --rm --tty percona-client --image=percona:8.0 --restart=Never -- bash -il

Cela créera un pod transitoire et entrera immédiatement dans l'environnement du conteneur. Ensuite, exécutez la commande client mysql standard avec les informations d'identification appropriées :

bash-4.2$ mysql -uroot -pmypassword -h cluster1-haproxy -P3306 -e 'SELECT @@hostname'
mysql: [Warning] Using a password on the command line interface can be insecure.
+----------------+
| @@hostname     |
+----------------+
| cluster1-pxc-0 |
+----------------+

Lorsque nous examinons le placement des pods, tous les pods du cluster Percona XtraDB sont situés sur un hôte Kubernetes différent :

$ kubectl get pods -o wide --selector=app.kubernetes.io/component=pxc
NAME             READY   STATUS    RESTARTS   AGE   IP           NODE                                            NOMINATED NODE   READINESS GATES
cluster1-pxc-0   1/1     Running   0          67m   10.36.2.5    gke-my-k8s-cluster-default-pool-b80902cd-gp09   <none>           <none>
cluster1-pxc-1   1/1     Running   0          66m   10.36.1.10   gke-my-k8s-cluster-default-pool-b80902cd-rdv8   <none>           <none>
cluster1-pxc-2   1/1     Running   0          65m   10.36.0.11   gke-my-k8s-cluster-default-pool-b80902cd-jdc3   <none>           <none>

Cela améliorera certainement la disponibilité du service, au cas où l'un des hôtes Kubernetes tomberait en panne.

Pour évoluer jusqu'à 5 pods, nous devons au préalable préparer 2 nouveaux nœuds Kubernetes supplémentaires afin de respecter la configuration d'affinité du pod (par défaut, affinity.antiAffinityTopologyKey.topologyKey="kubernetes.io/hostname"). Ensuite, exécutez la commande de correctif suivante pour faire évoluer le cluster Percona XtraDB à 5 nœuds :

$ kubectl patch pxc cluster1 \
--type='json' -p='[{"op": "replace", "path": "/spec/pxc/size", "value": 5 }]'

Surveillez la création du pod à l'aide de la commande kubectl get pods :

$ kubectl get pods -o wide
NAME               READY   STATUS      RESTARTS   AGE   IP           NODE                                            NOMINATED NODE   READINESS GATES
cluster1-pxc-0     1/1     Running     0          27h   10.36.2.5    gke-my-k8s-cluster-default-pool-b80902cd-gp09   <none>           <none>
cluster1-pxc-1     1/1     Running     0          27h   10.36.1.10   gke-my-k8s-cluster-default-pool-b80902cd-rdv8   <none>           <none>
cluster1-pxc-2     1/1     Running     0          27h   10.36.0.11   gke-my-k8s-cluster-default-pool-b80902cd-jdc3   <none>           <none>
cluster1-pxc-3     1/1     Running     0          30m   10.36.7.2    gke-my-k8s-cluster-pool-1-ab14a45e-h1pf         <none>           <none>
cluster1-pxc-4     1/1     Running     0          13m   10.36.5.3    gke-my-k8s-cluster-pool-1-ab14a45e-01qn         <none>           <none>

2 autres nouveaux pods (cluster1-pxc-3 et cluster1-pxc-4) ont été créés sur 2 autres nouveaux nœuds Kubernetes (gke-my-k8s-cluster-pool-1-ab14a45e-h1pf et gke-my-k8s-cluster-pool-1-ab14a45e-01qn). Pour réduire, remettez simplement la valeur à 3 dans la commande patch ci-dessus. Notez que le cluster Percona XtraDB doit fonctionner avec un nombre impair de nœuds pour éviter le split-brain.

Déployer une application (WordPress)

Dans cet exemple, nous allons déployer une application WordPress sur notre cluster Percona XtraDB et HAProxy. Commençons par préparer le fichier de définition YAML comme suit :

$ cat wordpress-deployment.yaml
apiVersion: v1
kind: Service
metadata:
  name: wordpress
  labels:
    app: wordpress
spec:
  ports:
    - port: 80
  selector:
    app: wordpress
    tier: frontend
  type: LoadBalancer
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: wp-pv-claim
  labels:
    app: wordpress
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 2Gi
---
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: wordpress
  labels:
    app: wordpress
spec:
  selector:
    matchLabels:
      app: wordpress
      tier: frontend
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: wordpress
        tier: frontend
    spec:
      containers:
      - image: wordpress:4.8-apache
        name: wordpress
        env:
        - name: WORDPRESS_DB_HOST
          value: cluster1-haproxy
        - name: WORDPRESS_DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: my-cluster-secrets
              key: root
        ports:
        - containerPort: 80
          name: wordpress
        volumeMounts:
        - name: wordpress-persistent-storage
          mountPath: /var/www/html
      volumes:
      - name: wordpress-persistent-storage
        persistentVolumeClaim:
          claimName: wp-pv-claim

Faites attention aux variables d'environnement WORDPRESS_DB_HOST et WORDPRESS_DB_PASSWORD. La première variable où nous avons défini "cluster1-haproxy" comme hôte de base de données, au lieu d'un nœud de base de données individuel et pour ce dernier nous avons spécifié le mot de passe root en demandant à Kubernetes de le lire à partir de l'objet my-cluster-secrets sous la clé "root", qui équivaut à "mypassword" (après le décodage de la valeur base64). Nous ignorons la définition de la variable d'environnement WORDPRESS_DB_USER puisque la valeur par défaut est "root".

Nous pouvons maintenant créer notre application :

$ kubectl apply -f wordpress-deployment.yaml

Vérifier le service :

$ kubectl get service
NAME                        TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)                       AGE
cluster1-haproxy            ClusterIP      10.40.9.177    <none>          3306/TCP,3309/TCP,33062/TCP   4h42m
cluster1-haproxy-replicas   ClusterIP      10.40.0.236    <none>          3306/TCP                      4h42m
cluster1-pxc                ClusterIP      None           <none>          3306/TCP,33062/TCP            4h42m
cluster1-pxc-unready        ClusterIP      None           <none>          3306/TCP,33062/TCP            4h42m
wordpress                   LoadBalancer   10.40.13.205   35.200.78.195   80:32087/TCP                  4h39m

À ce stade, nous pouvons nous connecter à notre application WordPress à l'adresse http://35.200.78.195/ (l'adresse IP externe) et commencer à configurer l'application WordPress. À ce stade, notre application WordPress est connectée à l'un des clusters Percona XtraDB (connexion à maître unique) via l'un des pods HAProxy.

C'est tout pour le moment. Pour plus d'informations, consultez la documentation Percona Kubernetes Operator for Percona XtraDB Cluster. Bonne conteneurisation !