Mysql
 sql >> Database >  >> RDS >> Mysql

Una panoramica dell'operatore Percona XtraDB Cluster Kubernetes

Se sei stato in giro nel mondo dei container, sapresti che è piuttosto difficile adottare un'automazione Kubernetes completa per un sistema di database in cluster, che comunemente aggiunge un livello di complessità al sistema basato su container architettura per queste applicazioni stateful. È qui che un operatore Kubernetes può aiutarci ad affrontare questo problema. Un operatore Kubernetes è un tipo speciale di controller introdotto per semplificare implementazioni complesse che sostanzialmente estende l'API Kubernetes con risorse personalizzate. Si basa sui concetti di base delle risorse e dei controller Kubernetes, ma include conoscenze specifiche del dominio o dell'applicazione per automatizzare l'intero ciclo di vita del software che gestisce.

Percona XtraDB Cluster Operator è un modo efficace per automatizzare le attività specifiche di Percona XtraDB Cluster come distribuzione, ridimensionamento, backup e aggiornamenti all'interno di Kubernetes, creato e gestito da Percona. Distribuisce il cluster in uno StatefulSet con un volume persistente, che ci consente di mantenere un'identità coerente per ogni Pod nel cluster e mantenere i nostri dati.

In questo post del blog testeremo l'implementazione di Percona XtraDB Cluster 8.0 in un ambiente containerizzato, orchestrato dall'operatore Percona XtraDB Cluster Kubernetes su Google Cloud Platform.

Creazione di un cluster Kubernetes su Google Cloud

In questa procedura dettagliata, utilizzeremo il cluster Kubernetes su Google Cloud perché è relativamente semplice e facile far funzionare Kubernetes. Accedi alla dashboard di Google Cloud Platform -> Compute -> Kubernetes Engine -> Crea cluster e ti verrà presentata la seguente finestra di dialogo:

Inserisci il nome del cluster Kubernetes, scegli la tua zona preferita e fai clic su "CREA " (Nella parte inferiore della pagina). In 5 minuti sarà pronto un cluster Kubernetes a 3 nodi. Ora, sulla tua workstation, installa l'SDK di gcloud come mostrato in questa guida, quindi estrai la configurazione di Kubernetes nella tua workstation:

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

Dovresti essere in grado di connetterti al cluster Kubernetes a questo punto. Esegui il comando seguente per verificare:

$ 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

L'output sopra indica che siamo in grado di connetterci al master Kubernetes e recuperare i nodi del cluster Kubernetes. Ora siamo pronti per eseguire i carichi di lavoro Kubernetes.

Distribuzione di un cluster Percona XtraDB su Kubernetes

Per l'implementazione del carico di lavoro, seguiremo le istruzioni indicate nella documentazione dell'operatore del cluster Percona XtraDB. Fondamentalmente, eseguiamo il seguente comando sulla nostra workstation per creare le risorse personalizzate, lo spazio dei nomi, il controllo degli accessi basato sui ruoli e anche l'operatore Kubernetes stesso:

$ 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

Successivamente, dobbiamo preparare le nostre password (si chiamano Secrets nel termine di Kubernetes) aggiornando i valori all'interno di deploy/secrets.yaml in un formato con codifica base64. Puoi utilizzare strumenti online come https://www.base64encode.org/ per crearne uno o utilizzare uno strumento da riga di comando come il seguente:

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

Quindi, aggiorna deploy/secrets.yaml, come mostrato di seguito:

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==

Quella sopra è una super semplificazione della gestione dei segreti, in cui impostiamo tutte le password in modo che siano le stesse per tutti gli utenti. In produzione, utilizzare una password più complessa e specificare una password diversa per ogni utente.

Ora possiamo inviare la configurazione segreta a Kubernetes:

$ kubectl apply -f deploy/secrets.yaml

Prima di procedere con la distribuzione di un cluster Percona XtraDB, è necessario rivedere la definizione di distribuzione predefinita all'interno di deploy/cr.yaml per il cluster. Ci sono molti oggetti Kubernetes che sono definiti qui, ma la maggior parte di essi è commentata. Per il nostro carico di lavoro, apporteremmo la modifica come di seguito:

$ 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

Abbiamo apportato alcune modifiche al cr.yaml fornito per farlo funzionare con la nostra applicazione, come mostrato sopra. Prima di tutto, dobbiamo commentare (o rimuovere) tutte le righe relative alla CPU, ad esempio [*].resources.requests.cpu:600m, per assicurarci che Kubernetes sia in grado di pianificare correttamente la creazione del pod su nodi con CPU limitata. Quindi dobbiamo aggiungere alcune opzioni di compatibilità per Percona XtraDB Cluster 8.0 basato su MySQL 8.0, per funzionare senza problemi con la nostra applicazione WordPress che implementeremo in seguito, come mostrato nel seguente estratto:

   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

Quanto sopra corrisponderà al set di caratteri predefinito del server MySQL con il driver PHP MySQLi nel nostro contenitore WordPress. La sezione successiva è la distribuzione HAProxy in cui è impostato su "enabled:true". C'è anche una sezione ProxySQL con "enabled:false" - comunemente si sceglierebbe uno dei proxy inversi per ogni cluster. L'ultima sezione è la configurazione del backup, in cui vorremmo avere un backup giornaliero programmato alle 00:00 ogni giorno e conservare gli ultimi 5 backup.

Ora possiamo iniziare a distribuire il nostro cluster Percona XtraDB a 3 nodi:

$ kubectl apply -f deploy/cr.yaml

Il processo di creazione richiederà del tempo. L'operatore distribuirà i pod del cluster Percona XtraDB come un insieme con stato, il che significa la creazione di un pod alla volta e a ciascun pod nello StatefulSet verrà assegnato un ordinale intero, da 0 fino a N-1, che è univoco sul set. Il processo termina quando sia l'operatore che i Pod hanno raggiunto lo stato In esecuzione:

$ 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

Dato che questo operatore è una risorsa personalizzata, possiamo manipolare la risorsa perconaxtradbcluster in modo che apprezzi la risorsa Kubernetes standard:

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

Puoi anche usare il nome della risorsa più breve, "pxc", e provare con i seguenti comandi:

$ kubectl describe pxc
$ kubectl edit pxc

Guardando il set di carichi di lavoro, possiamo dire che l'operatore ha creato due StatefulSet:

$ 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'operatore creerà anche i servizi corrispondenti che effettueranno il bilanciamento del carico delle connessioni ai rispettivi pod:

$ 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

L'output sopra mostra che l'operatore ha creato 4 servizi:

  • cluster1-haproxy - Il servizio per MySQL single-master (3306), protocollo Proxy (3309) e MySQL Admin (33062) con bilanciamento del carico - Una nuova porta amministrativa introdotta in MySQL 8.0.14 e versioni successive. Questo è il nome del servizio o l'indirizzo IP del cluster che le applicazioni devono connettersi per avere una connessione single-master al cluster Galera.
  • cluster1-haproxy-replica - Il servizio per un multimaster MySQL con bilanciamento del carico (3306). Questo è il nome del servizio o l'indirizzo IP del cluster che le applicazioni devono connettersi per avere una connessione multi-master al cluster Galera con algoritmo di bilanciamento round-robin.
  • cluster1-pxc - Il servizio per pod PXC con bilanciamento del carico, bypassando HAProxy. Connettendosi direttamente a questo servizio, Kubernetes instraderà la connessione in modalità round robin a tutti i pod PXC, in modo simile a ciò che fornisce cluster-haproxy-replicase. Il servizio non ha un indirizzo IP pubblico assegnato e non è disponibile all'esterno del cluster.
  • cluster1-pxc-unready - Il servizio "non pronto" è necessario per il rilevamento dell'indirizzo del pod durante l'avvio dell'applicazione indipendentemente dallo stato del pod. I pod Proxysql e pxc dovrebbero conoscersi prima che il database diventi completamente operativo. Il servizio non pronto non ha un indirizzo IP pubblico assegnato e non è disponibile all'esterno del cluster.

Per connetterti tramite un client MySQL, esegui semplicemente il seguente comando:

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

Questo creerà un Pod transitorio e entrerà immediatamente nell'ambiente del contenitore. Quindi, esegui il comando client mysql standard con una credenziale adeguata:

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 |
+----------------+

Quando esaminiamo il posizionamento dei pod, tutti i pod Cluster Percona XtraDB si trovano su un host Kubernetes diverso:

$ 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>

Ciò migliorerà sicuramente la disponibilità del servizio, nel caso in cui uno degli host Kubernetes si interrompa.

Per scalare fino a 5 pod, è necessario preparare in anticipo altri 2 nuovi nodi Kubernetes per rispettare la configurazione dell'affinità del pod (impostazione predefinita per affinity.antiAffinityTopologyKey.topologyKey="kubernetes.io/hostname"). Quindi, eseguire il seguente comando patch per ridimensionare il cluster Percona XtraDB a 5 nodi:

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

Monitora la creazione del pod utilizzando il comando 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>

Altri 2 nuovi Pod (cluster1-pxc-3 e cluster1-pxc-4) sono stati creati su altri 2 nuovi nodi Kubernetes (gke-my-k8s-cluster-pool-1-ab14a45e-h1pf e gke-my-k8s-cluster-pool-1-ab14a45e-01qn). Per ridimensionare, riportare semplicemente il valore a 3 nel comando patch sopra. Tieni presente che Percona XtraDB Cluster dovrebbe essere in esecuzione con un numero dispari di nodi per prevenire lo split brain.

Distribuzione di un'applicazione (WordPress)

In questo esempio, implementeremo un'applicazione WordPress sopra il nostro Percona XtraDB Cluster e HAProxy. Per prima cosa prepariamo il file di definizione YAML come il seguente:

$ 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

Prestare attenzione alle variabili di ambiente WORDPRESS_DB_HOST e WORDPRESS_DB_PASSWORD. La prima variabile in cui abbiamo definito "cluster1-haproxy" come host del database, invece di un singolo nodo del database e per il secondo abbiamo specificato la password di root indicando a Kubernetes di leggerla dall'oggetto my-cluster-secrets sotto la chiave "root", che equivale a "mypassword" (dopo che il valore base64 è stato decodificato). Saltiamo la definizione della variabile d'ambiente WORDPRESS_DB_USER poiché il valore predefinito è "root".

Ora possiamo creare la nostra applicazione:

$ kubectl apply -f wordpress-deployment.yaml

Controlla il servizio:

$ 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

A questo punto, possiamo connetterci alla nostra applicazione WordPress all'indirizzo http://35.200.78.195/ (l'indirizzo IP esterno) e iniziare a configurare l'applicazione WordPress. A questo punto, la nostra applicazione WordPress è connessa a uno dei Cluster Percona XtraDB (connessione single-master) tramite uno dei pod HAProxy.

Per ora è tutto. Per ulteriori informazioni, consultare la documentazione di Percona Kubernetes Operator per Percona XtraDB Cluster. Buona containerizzazione!