Om du har funnits i containervärlden skulle du veta att det är ganska utmanande att införa en fullständig Kubernetes-automatisering för ett klustrade databassystem, vilket vanligtvis lägger till en nivå av komplexitet till det containerbaserade arkitektur för dessa statistiska tillämpningar. Det är där en Kubernetes-operatör kan hjälpa oss att lösa det här problemet. En Kubernetes Operator är en speciell typ av kontroller som introduceras för att förenkla komplexa distributioner som i princip utökar Kubernetes API med anpassade resurser. Den bygger på Kubernetes grundläggande resurs- och kontrollerkoncept men inkluderar domän- eller applikationsspecifik kunskap för att automatisera hela livscykeln för programvaran som den hanterar.
Percona XtraDB Cluster Operator är ett snyggt sätt att automatisera de specifika uppgifterna för Percona XtraDB Cluster som distribution, skalning, säkerhetskopiering och uppgraderingar inom Kubernetes, byggda och underhållna av Percona. Den distribuerar klustret i ett StatefulSet med en persistent volym, vilket gör att vi kan upprätthålla en konsekvent identitet för varje Pod i klustret och vår data som ska underhållas.
I det här blogginlägget kommer vi att testa implementeringen av Percona XtraDB Cluster 8.0 i en containermiljö, orkestrerad av Percona XtraDB Cluster Kubernetes Operator på Google Cloud Platform.
Skapa ett Kubernetes-kluster i Google Cloud
I den här genomgången kommer vi att använda Kubernetes-klustret på Google Cloud eftersom det är relativt enkelt och lätt att få igång Kubernetes. Logga in på din Google Cloud Platform-instrumentpanel -> Compute -> Kubernetes Engine -> Skapa kluster, så kommer du att presenteras med följande dialogruta:
Ange bara Kubernetes-klusternamnet, välj önskad zon och klicka på "SKAPA " (på botten av sidan). Om 5 minuter kommer ett Kubernetes-kluster med 3 noder att vara klart. Nu, på din arbetsstation, installera gcloud SDK som visas i den här guiden och dra sedan Kubernetes-konfigurationen till din arbetsstation:
$ 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.
Du bör kunna ansluta till Kubernetes-klustret vid det här laget. Kör följande kommando för att verifiera:
$ 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
Ovanstående utdata betyder att vi kan ansluta till Kubernetes-mastern och hämta Kubernetes-klusternoderna. Nu är vi redo att köra Kubernetes-arbetsbelastningarna.
Distribuera ett Percona XtraDB-kluster på Kubernetes
För arbetsbelastningsdistribution kommer vi att följa instruktionerna som anges i Percona XtraDB Cluster Operator-dokumentationen. I grund och botten kör vi följande kommando på vår arbetsstation för att skapa de anpassade resurserna, namnutrymmet, rollbaserad åtkomstkontroll och även Kubernetes-operatören själv:
$ 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
Närnäst måste vi förbereda våra lösenord (det kallas Secrets in Kubernetes term) genom att uppdatera värdena inuti deploy/secrets.yaml i ett base64-kodat format. Du kan använda onlineverktyg som https://www.base64encode.org/ för att skapa ett eller använda ett kommandoradsverktyg som följande:
$ echo -n 'mypassword' | base64
bXlwYXNzd29yZA==
Uppdatera sedan deploy/secrets.yaml, som visas nedan:
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==
Ovanstående är en super förenkling av hemlig hantering, där vi ställer in alla lösenord för att vara lika för alla användare. I produktionen, använd ett mer komplext lösenord och ange ett annat lösenord för varje användare.
Nu kan vi skicka den hemliga konfigurationen till Kubernetes:
$ kubectl apply -f deploy/secrets.yaml
Innan vi går vidare för att distribuera ett Percona XtraDB-kluster måste vi se över standarddefinitionen för distribution i deploy/cr.yaml för klustret. Det finns många Kubernetes-objekt som är definierade här, men de flesta av dem kommenteras bort. För vår arbetsbörda skulle vi göra ändringen enligt nedan:
$ 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
Vi har gjort några ändringar av den medföljande cr.yaml för att få den att fungera med vår applikation, som visas ovan. Först och främst måste vi kommentera (eller ta bort) alla CPU-relaterade rader, till exempel [*].resources.requests.cpu:600m, för att se till att Kubernetes kan schemalägga podden korrekt på noder med begränsad CPU. Sedan måste vi lägga till några kompatibilitetsalternativ för Percona XtraDB Cluster 8.0 som är baserad på MySQL 8.0, för att fungera smidigt med vår WordPress-applikation som vi kommer att distribuera senare, som visas i följande utdrag:
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
Ovanstående kommer att matcha MySQL-serverns standardteckenuppsättning med MySQLi PHP-drivrutinen i vår WordPress-behållare. Nästa avsnitt är HAProxy-distributionen där den är inställd på "enabled:true". Det finns också en ProxySQL-sektion med "enabled:false" - vanligtvis skulle man välja någon av de omvända proxyerna för varje kluster. Det sista avsnittet är säkerhetskopieringskonfigurationen, där vi skulle vilja ha en daglig säkerhetskopiering schemalagd klockan 12:00 varje dag och behålla de sista 5 säkerhetskopiorna.
Vi kan nu börja distribuera vårt Percona XtraDB-kluster med 3 noder:
$ kubectl apply -f deploy/cr.yaml
Skapandet kommer att ta lite tid. Operatören kommer att distribuera Percona XtraDB Cluster-poddarna som en Stateful Set, vilket innebär att skapa en pod åt gången och varje Pod i StatefulSet kommer att tilldelas en heltalsordning, från 0 upp till N-1, som är unik över setet. Processen är över när både operatören och poddarna har nått sin körstatus:
$ 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
Eftersom den här operatören är en anpassad resurs kan vi manipulera perconaxtradbcluster-resursen så att den liknar standard Kubernetes-resursen:
$ kubectl get perconaxtradbcluster
NAME ENDPOINT STATUS PXC PROXYSQL HAPROXY AGE
cluster1 cluster1-haproxy.pxc ready 3 3 27h
Du kan också använda det kortare resursnamnet, "pxc", och prova med följande kommandon:
$ kubectl describe pxc
$ kubectl edit pxc
När vi tittar på arbetsbelastningsuppsättningen kan vi se att operatören har skapat två 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
Operatören kommer också att skapa motsvarande tjänster som kommer att lastbalanserade anslutningar till respektive poddar:
$ 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
Ovanstående utdata visar att operatören har skapat fyra tjänster:
- kluster1-haproxy - Tjänsten för en lastbalanserad MySQL single-master (3306), Proxy-protokoll (3309) och MySQL Admin (33062) - En ny administrativ port introducerad i MySQL 8.0.14 och senare. Detta är tjänstens namn eller kluster-IP-adress som applikationerna behöver ansluta för att ha en enkelmasteranslutning till Galera-klustret.
- kluster1-haproxy-repliker - Tjänsten för en lastbalanserad MySQL multi-master (3306). Detta är tjänstens namn eller kluster-IP-adress som applikationerna behöver ansluta för att ha en multimasteranslutning till Galera-klustret med round-robin-balanseringsalgoritm.
- cluster1-pxc - Tjänsten för belastningsbalanserade PXC-poddar, som går förbi HAProxy. Genom att ansluta direkt till den här tjänsten kommer Kubernetes att dirigera anslutningen i round-robin-form till alla PXC-poddar, liknande vad kluster-haproxy-replikas tillhandahåller. Tjänsten har ingen offentlig IP-adress tilldelad och är inte tillgänglig utanför klustret.
- cluster1-pxc-unready - Tjänsten "oklar" behövs för att hitta podadress under applikationsstarten oavsett Pod-tillstånd. Proxysql- och pxc-pods bör känna till varandra innan databasen blir fullt funktionsduglig. Den oklara tjänsten har ingen offentlig IP-adress tilldelad och är inte tillgänglig utanför klustret.
För att ansluta via en MySQL-klient, kör helt enkelt följande kommando:
$ kubectl run -i --rm --tty percona-client --image=percona:8.0 --restart=Never -- bash -il
Detta skapar en övergående Pod och går omedelbart in i containermiljön. Kör sedan standardkommandot mysql-klient med en korrekt referens:
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 |
+----------------+
När vi tittar på Pod-placeringen är alla Percona XtraDB Cluster-poddar placerade på en annan Kubernetes-värd:
$ 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>
Detta kommer definitivt att förbättra tillgängligheten för tjänsten, om någon av Kubernetes-värdarna går ner.
För att skala upp till 5 poddar måste vi förbereda ytterligare två nya Kubernetes-noder i förväg för att respektera podaffinitetskonfigurationen (standard till affinity.antiAffinityTopologyKey.topologyKey="kubernetes.io/hostname"). Kör sedan följande patchkommando för att skala Percona XtraDB-klustret till 5 noder:
$ kubectl patch pxc cluster1 \
--type='json' -p='[{"op": "replace", "path": "/spec/pxc/size", "value": 5 }]'
Övervaka skapandet av podden genom att använda kommandot 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>
Ytterligare 2 nya Pods (cluster1-pxc-3 och cluster1-pxc-4) har skapats på ytterligare 2 nya Kubernetes-noder (gke-my-k8s-cluster-pool-1-ab14a45e-h1pf och gke-my-k8s-cluster-pool-1-ab14a45e-01qn). För att skala ner, ändra helt enkelt tillbaka värdet till 3 i patchkommandot ovan. Observera att Percona XtraDB Cluster bör köras med ett udda antal noder för att förhindra split-brain.
Distribuera ett program (WordPress)
I det här exemplet kommer vi att distribuera en WordPress-applikation ovanpå vårt Percona XtraDB-kluster och HAProxy. Låt oss först förbereda YAML-definitionsfilen enligt följande:
$ 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
Var uppmärksam på miljövariablerna WORDPRESS_DB_HOST och WORDPRESS_DB_PASSWORD. Den förra variabeln där vi definierade "cluster1-haproxy" som databasvärd, istället för en individuell databasnod och för den senare angav vi root-lösenordet genom att instruera Kubernetes att läsa det från my-cluster-secrets-objektet under nyckeln "root", vilket motsvarar "mypassword" (efter att base64-värdet avkodats). Vi hoppar över att definiera miljövariabeln WORDPRESS_DB_USER eftersom standardvärdet är "root".
Nu kan vi skapa vår applikation:
$ kubectl apply -f wordpress-deployment.yaml
Kontrollera tjänsten:
$ 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
Vid denna tidpunkt kan vi ansluta till vår WordPress-applikation på http://35.200.78.195/ (den externa IP-adressen) och börja konfigurera WordPress-applikationen. Vid det här laget är vår WordPress-applikation ansluten till ett av Percona XtraDB-klustret (single-master-anslutning) via en av HAProxy-podarna.
Det var allt för nu. För mer information, kolla in dokumentationen för Percona Kubernetes Operator for Percona XtraDB Cluster. Lycka till med containersändningen!