sql >> Database >  >> RDS >> Mysql

Een overzicht van de Percona XtraDB Cluster Kubernetes-operator

Als je in de containerwereld bent geweest, zou je weten dat het een behoorlijke uitdaging is om een ​​volledige Kubernetes-automatisering te implementeren voor een geclusterd databasesysteem, wat gewoonlijk een niveau van complexiteit toevoegt aan de containergebaseerde architectuur voor deze stateful applicaties. Dat is waar een Kubernetes-operator ons kan helpen dit probleem aan te pakken. Een Kubernetes-operator is een speciaal type controller dat is geïntroduceerd om complexe implementaties te vereenvoudigen, waardoor de Kubernetes-API in feite wordt uitgebreid met aangepaste bronnen. Het bouwt voort op de basisconcepten van Kubernetes-bronnen en -controllers, maar omvat domein- of applicatiespecifieke kennis om de volledige levenscyclus van de software die het beheert te automatiseren.

Percona XtraDB Cluster Operator is een handige manier om de specifieke taken van Percona XtraDB Cluster te automatiseren, zoals implementatie, schaling, back-ups en upgrades binnen Kubernetes, gebouwd en onderhouden door Percona. Het implementeert het cluster in een StatefulSet met een persistent volume, waardoor we een consistente identiteit kunnen behouden voor elke pod in het cluster en onze gegevens kunnen worden onderhouden.

In deze blogpost gaan we de implementatie van Percona XtraDB Cluster 8.0 testen in een containeromgeving, georkestreerd door Percona XtraDB Cluster Kubernetes Operator op Google Cloud Platform.

Een Kubernetes-cluster maken op Google Cloud

In deze walkthrough gaan we het Kubernetes-cluster op Google Cloud gebruiken omdat het relatief eenvoudig en gemakkelijk is om Kubernetes aan de gang te krijgen. Log in op uw Google Cloud Platform-dashboard -> Compute -> Kubernetes Engine -> Cluster maken en u krijgt het volgende dialoogvenster te zien:

Voer gewoon de naam van het Kubernetes-cluster in, kies de zone van uw voorkeur en klik op "MAKEN " (onderaan de pagina). Over 5 minuten is een Kubernetes-cluster met 3 knooppunten gereed. Installeer nu op uw werkstation de gcloud SDK zoals weergegeven in deze handleiding en trek vervolgens de Kubernetes-configuratie naar uw werkstation:

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

Je zou nu verbinding moeten kunnen maken met het Kubernetes-cluster. Voer de volgende opdracht uit om te verifiëren:

$ 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

De bovenstaande uitvoer betekent dat we verbinding kunnen maken met de Kubernetes-master en de Kubernetes-clusterknooppunten kunnen ophalen. Nu zijn we klaar om de Kubernetes-workloads uit te voeren.

Een Percona XtraDB-cluster implementeren op Kubernetes

Voor de implementatie van workloads gaan we de instructies volgen zoals vermeld in de Percona XtraDB Cluster Operator-documentatie. Kortom, we voeren de volgende opdracht uit op ons werkstation om de aangepaste bronnen, naamruimte, op rollen gebaseerd toegangsbeheer en ook de Kubernetes-operator zelf te maken:

$ 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

Vervolgens moeten we onze wachtwoorden voorbereiden (het heet Secrets in Kubernetes-term) door de waarden in deploy/secrets.yaml bij te werken in een base64-gecodeerd formaat. U kunt online tools zoals https://www.base64encode.org/ gebruiken om er een te maken of een opdrachtregelprogramma zoals het volgende gebruiken:

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

Update vervolgens de deploy/secrets.yaml, zoals hieronder weergegeven:

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

Het bovenstaande is een supervereenvoudiging van geheimbeheer, waarbij we alle wachtwoorden zo instellen dat ze voor alle gebruikers hetzelfde zijn. Gebruik in de productie een complexer wachtwoord en geef voor elke gebruiker een ander wachtwoord op.

Nu kunnen we de geheime configuratie naar Kubernetes pushen:

$ kubectl apply -f deploy/secrets.yaml

Voordat we verder gaan met het implementeren van een Percona XtraDB-cluster, moeten we de standaardimplementatiedefinitie in deploy/cr.yaml voor het cluster opnieuw bekijken. Er zijn veel Kubernetes-objecten die hier zijn gedefinieerd, maar de meeste zijn becommentarieerd. Voor onze werklast zouden we de onderstaande wijziging aanbrengen:

$ 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

We hebben enkele wijzigingen aangebracht in de geleverde cr.yaml om het te laten werken met onze applicatie, zoals hierboven getoond. Allereerst moeten we alle CPU-gerelateerde regels uit commentaar geven (of verwijderen), bijvoorbeeld [*].resources.requests.cpu:600m, om ervoor te zorgen dat Kubernetes het maken van de pod correct kan plannen op knooppunten met een beperkte CPU. Vervolgens moeten we enkele compatibiliteitsopties toevoegen voor Percona XtraDB Cluster 8.0, dat is gebaseerd op MySQL 8.0, om soepel te werken met onze WordPress-toepassing die we later gaan implementeren, zoals weergegeven in het volgende fragment:

   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

Het bovenstaande komt overeen met de standaardtekenset van de MySQL-server met het MySQLi PHP-stuurprogramma in onze WordPress-container. De volgende sectie is de HAProxy-implementatie waar deze is ingesteld op "enabled:true". Er is ook een ProxySQL-sectie met "enabled:false" - gewoonlijk zou men een van de omgekeerde proxy's voor elk cluster kiezen. De laatste sectie is de back-upconfiguratie, waarbij we graag een dagelijkse back-up willen hebben die elke dag om 12.00 uur wordt gepland en die laatste 5 back-ups willen behouden.

We kunnen nu beginnen met de implementatie van ons Percona XtraDB-cluster met 3 knooppunten:

$ kubectl apply -f deploy/cr.yaml

Het creatieproces zal enige tijd duren. De operator zal de Percona XtraDB Cluster-pods inzetten als een Stateful Set, wat betekent dat er één pod tegelijk wordt gemaakt en aan elke Pod in de StatefulSet wordt een geheel getal toegewezen, van 0 tot en met N-1, dat uniek is voor de set. Het proces is afgelopen wanneer zowel de operator als de pods hun status Actief hebben bereikt:

$ 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

Aangezien deze operator een aangepaste bron is, kunnen we de perconaxtradbcluster-bron manipuleren om de standaard Kubernetes-bron leuk te vinden:

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

U kunt ook de kortere resourcenaam "pxc" gebruiken en de volgende opdrachten proberen:

$ kubectl describe pxc
$ kubectl edit pxc

Als we naar de werklastset kijken, kunnen we zien dat de operator twee StatefulSets heeft gemaakt:

$ 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

De operator maakt ook de bijbehorende services die load-balanced verbindingen met de respectievelijke pods zullen maken:

$ 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

De bovenstaande uitvoer laat zien dat de operator 4 services heeft gemaakt:

  • cluster1-haproxy - De service voor een load-balanced MySQL single-master (3306), Proxy-protocol (3309) en MySQL Admin (33062) - Een nieuwe administratieve poort geïntroduceerd in MySQL 8.0.14 en later. Dit is de servicenaam of het cluster-IP-adres waarmee de applicaties verbinding moeten maken om een ​​single-masterverbinding met het Galera-cluster te hebben.
  • cluster1-haproxy-replica's - De service voor een load-balanced MySQL multi-master (3306). Dit is de servicenaam of het cluster-IP-adres waarmee de applicaties verbinding moeten maken om een ​​multi-masterverbinding te hebben met het Galera-cluster met round-robin balanceringsalgoritme.
  • cluster1-pxc - De service voor load-balanced PXC-pods, waarbij HAProxy wordt omzeild. Door rechtstreeks verbinding te maken met deze service, leidt Kubernetes de verbinding in round-robin-mode naar alle PXC-pods, vergelijkbaar met wat cluster-haproxy-replicase biedt. De service heeft geen openbaar IP-adres toegewezen gekregen en is niet beschikbaar buiten het cluster.
  • cluster1-pxc-unready - De 'unready'-service is nodig voor detectie van pod-adressen tijdens het opstarten van de toepassing, ongeacht de status van de pod. Proxysql- en pxc-pods moeten van elkaar weten voordat de database volledig operationeel wordt. De onklaar-service heeft geen openbaar IP-adres toegewezen en is niet beschikbaar buiten het cluster.

Om verbinding te maken via een MySQL-client, voert u gewoon de volgende opdracht uit:

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

Hiermee wordt een tijdelijke pod gemaakt en gaat deze onmiddellijk naar de containeromgeving. Voer vervolgens het standaard mysql-clientcommando uit met de juiste referentie:

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

Als we kijken naar de plaatsing van de pod, bevinden alle Percona XtraDB Cluster-pods zich op een andere Kubernetes-host:

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

Dit zal de beschikbaarheid van de service zeker verbeteren, voor het geval een van de Kubernetes-hosts uitvalt.

Om tot 5 pods te schalen, moeten we vooraf nog 2 nieuwe Kubernetes-knooppunten voorbereiden om de pod-affiniteitsconfiguratie te respecteren (standaard affinity.antiAffinityTopologyKey.topologyKey="kubernetes.io/hostname"). Voer vervolgens de volgende patchopdracht uit om de Percona XtraDB-cluster te schalen naar 5 nodes:

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

Houd de creatie van de pod in de gaten met de opdracht 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>

Er zijn nog 2 nieuwe pods (cluster1-pxc-3 en cluster1-pxc-4) gemaakt op nog eens 2 nieuwe Kubernetes-knooppunten (gke-my-k8s-cluster-pool-1-ab14a45e-h1pf en gke-my-k8s-cluster-pool-1-ab14a45e-01qn). Om te verkleinen, verander je de waarde gewoon terug naar 3 in de bovenstaande patchopdracht. Houd er rekening mee dat Percona XtraDB Cluster met een oneven aantal knooppunten moet werken om split-brain te voorkomen.

Een toepassing implementeren (WordPress)

In dit voorbeeld gaan we een WordPress-applicatie implementeren bovenop onze Percona XtraDB Cluster en HAProxy. Laten we eerst het YAML-definitiebestand als volgt voorbereiden:

$ 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

Let op de omgevingsvariabelen WORDPRESS_DB_HOST en WORDPRESS_DB_PASSWORD. De eerste variabele waar we "cluster1-haproxy" als de databasehost definieerden, in plaats van een individueel databaseknooppunt en voor de laatste hebben we het root-wachtwoord gespecificeerd door Kubernetes opdracht te geven het te lezen uit het my-cluster-secrets-object onder de sleutel "root", wat gelijk is aan "mypassword" (nadat de base64-waarde was gedecodeerd). We slaan het definiëren van de omgevingsvariabele WORDPRESS_DB_USER over, aangezien de standaardwaarde "root" is.

Nu kunnen we onze applicatie maken:

$ kubectl apply -f wordpress-deployment.yaml

Controleer de dienst:

$ 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

Op dit punt kunnen we verbinding maken met onze WordPress-applicatie op http://35.200.78.195/ (het externe IP-adres) en beginnen met het configureren van de WordPress-applicatie. Op dit moment is onze WordPress-applicatie via een van de HAProxy-pods verbonden met een van de Percona XtraDB-clusters (single-masterverbinding).

Dat was het voor nu. Raadpleeg voor meer informatie de Percona Kubernetes Operator voor Percona XtraDB Cluster-documentatie. Veel plezier met containervervoer!


  1. Kan een externe sleutel NULL en/of duplicaat zijn?

  2. Bereken kantooruren tussen twee datums

  3. Scans van toewijzingsorders

  4. Monitor SQL Database via SP_WhoIsActive of FogLight | Problemen met SQL Server-prestaties oplossen -1