V několika posledních blozích jsme se zabývali tím, jak spustit Galera Cluster na Dockeru, ať už na samostatném Dockeru nebo na multihostitelském Docker Swarm s překryvnou sítí. V tomto příspěvku na blogu se podíváme na spuštění Galera Cluster na Kubernetes, nástroj pro orchestraci pro spouštění kontejnerů ve velkém. Některé části se liší, například jak se má aplikace připojit ke clusteru, jak Kubernetes zpracovává převzetí služeb při selhání a jak funguje vyrovnávání zátěže v Kubernetes.
Kubernetes vs Docker Swarm
Naším konečným cílem je zajistit, aby Galera Cluster fungoval spolehlivě v prostředí kontejnerů. Dříve jsme se zabývali Docker Swarm a ukázalo se, že spuštění Galera Cluster na něm má řadu blokátorů, které brání tomu, aby byl připraven k produkci. Naše cesta nyní pokračuje s Kubernetes, nástrojem pro orchestraci kontejnerů na produkční úrovni. Podívejme se, jakou úroveň „produkční připravenosti“ může podporovat při spuštění stavové služby, jako je Galera Cluster.
Než se přesuneme dále, pojďme zdůraznit některé klíčové rozdíly mezi Kubernetes (1.6) a Docker Swarm (17.03) při spouštění Galera Cluster na kontejnerech:
- Kubernetes podporuje dvě sondy pro kontrolu stavu – živost a připravenost. To je důležité při spouštění Galera Cluster na kontejnerech, protože živý kontejner Galera neznamená, že je připraven sloužit a měl by být zahrnut do sady pro vyrovnávání zátěže (přemýšlejte o stavu připojení/dárce). Docker Swarm podporuje pouze jednu sondu pro kontrolu stavu podobnou živosti Kubernetes, kontejner je buď zdravý a stále běží, nebo nezdravý a bude přeplánován. Podrobnosti naleznete zde.
- Kubernetes má ovládací panel uživatelského rozhraní přístupný prostřednictvím „kubectl proxy“.
- Docker Swarm podporuje pouze vyvažování zátěže typu round-robin (vstup), zatímco Kubernetes využívá nejméně připojení.
- Docker Swarm podporuje směrovací síť pro publikování služby do externí sítě, zatímco Kubernetes podporuje něco podobného, co se nazývá NodePort, stejně jako externí nástroje pro vyrovnávání zatížení (GCE GLB/AWS ELB) a externí názvy DNS (jako u verze 1.7)
Instalace Kubernetes pomocí Kubeadm
Budeme používat kubeadm k instalaci 3uzlového clusteru Kubernetes na CentOS 7. Skládá se z 1 hlavního a 2 uzlů (minionů). Naše fyzická architektura vypadá takto:
1. Nainstalujte kubelet a Docker na všechny uzly:
$ ARCH=x86_64
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-${ARCH}
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg
https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF
$ setenforce 0
$ yum install -y docker kubelet kubeadm kubectl kubernetes-cni
$ systemctl enable docker && systemctl start docker
$ systemctl enable kubelet && systemctl start kubelet
2. Na masteru inicializujte master, zkopírujte konfigurační soubor, nastavte síť Pod pomocí Weave a nainstalujte Kubernetes Dashboard:
$ kubeadm init
$ cp /etc/kubernetes/admin.conf $HOME/
$ export KUBECONFIG=$HOME/admin.conf
$ kubectl apply -f https://git.io/weave-kube-1.6
$ kubectl create -f https://git.io/kube-dashboard
3. Poté na ostatních zbývajících uzlech:
$ kubeadm join --token 091d2a.e4862a6224454fd6 192.168.55.140:6443
4. Ověřte, zda jsou uzly připraveny:
$ kubectl get nodes
NAME STATUS AGE VERSION
kube1.local Ready 1h v1.6.3
kube2.local Ready 1h v1.6.3
kube3.local Ready 1h v1.6.3
Nyní máme cluster Kubernetes pro nasazení Galera Cluster.
Galera Cluster na Kubernetes
V tomto příkladu se chystáme nasadit MariaDB Galera Cluster 10.1 pomocí obrazu Docker staženého z našeho úložiště DockerHub. Definiční soubory YAML použité v tomto nasazení lze nalézt v adresáři example-kubernetes v úložišti Github.
Kubernetes podporuje řadu řadičů nasazení. K nasazení Galera Cluster lze použít:
- ReplicaSet
- StatefulSet
Každý z nich má své pro a proti. Podíváme se na každý z nich a uvidíme, jaký je rozdíl.
Předpoklady
Obraz, který jsme vytvořili, vyžaduje pro zjišťování služeb etcd (samostatný nebo cluster). Spuštění clusteru etcd vyžaduje, aby každá instance etcd běžela s různými příkazy, takže místo Deployment použijeme ovladač Pods a vytvoříme službu nazvanou „etcd-client“ jako koncový bod pro moduly etcd Pods. Definiční soubor etcd-cluster.yaml říká vše.
Chcete-li nasadit cluster se 3 moduly etcd, jednoduše spusťte:
$ kubectl create -f etcd-cluster.yaml
Ověřte, zda je cluster etcd připraven:
$ kubectl get po,svc
NAME READY STATUS RESTARTS AGE
po/etcd0 1/1 Running 0 1d
po/etcd1 1/1 Running 0 1d
po/etcd2 1/1 Running 0 1d
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
svc/etcd-client 10.104.244.200 <none> 2379/TCP 1d
svc/etcd0 10.100.24.171 <none> 2379/TCP,2380/TCP 1d
svc/etcd1 10.108.207.7 <none> 2379/TCP,2380/TCP 1d
svc/etcd2 10.101.9.115 <none> 2379/TCP,2380/TCP 1d
Naše architektura nyní vypadá asi takto:
Několik řádků MySQL na Docker:Jak kontejnerizovat databáziZjistěte vše, co potřebujete pochopit, když zvažujete spuštění služby MySQL na horní část virtualizace kontejneru DockerStáhněte si bílou knihuPoužití ReplicaSet
Sada ReplicaSet zajišťuje, že v daný čas běží určený počet „replik“ pod. Deployment je však koncept vyšší úrovně, který spravuje sady ReplicaSets a poskytuje deklarativní aktualizace modulů spolu se spoustou dalších užitečných funkcí. Proto se doporučuje používat Deployments namísto přímého používání ReplicaSets, pokud nevyžadujete vlastní orchestraci aktualizací nebo nevyžadujete aktualizace vůbec. Když používáte Deployments, nemusíte se starat o správu ReplicaSets, které vytvoří. Implementace vlastní a spravují své ReplicaSets.
V našem případě budeme používat Deployment jako řadič pracovní zátěže, jak je znázorněno v této definici YAML. Můžeme přímo vytvořit Galera Cluster ReplicaSet and Service spuštěním následujícího příkazu:
$ kubectl create -f mariadb-rs.yml
Ověřte, zda je cluster připraven, pohledem na ReplicaSet (rs), pody (po) a služby (svc):
$ kubectl get rs,po,svc
NAME DESIRED CURRENT READY AGE
rs/galera-251551564 3 3 3 5h
NAME READY STATUS RESTARTS AGE
po/etcd0 1/1 Running 0 1d
po/etcd1 1/1 Running 0 1d
po/etcd2 1/1 Running 0 1d
po/galera-251551564-8c238 1/1 Running 0 5h
po/galera-251551564-swjjl 1/1 Running 1 5h
po/galera-251551564-z4sgx 1/1 Running 1 5h
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
svc/etcd-client 10.104.244.200 <none> 2379/TCP 1d
svc/etcd0 10.100.24.171 <none> 2379/TCP,2380/TCP 1d
svc/etcd1 10.108.207.7 <none> 2379/TCP,2380/TCP 1d
svc/etcd2 10.101.9.115 <none> 2379/TCP,2380/TCP 1d
svc/galera-rs 10.107.89.109 <nodes> 3306:30000/TCP 5h
svc/kubernetes 10.96.0.1 <none> 443/TCP 1d
Z výše uvedeného výstupu můžeme ilustrovat naše moduly a službu takto:
Spuštění Galera Cluster na ReplicaSet je podobné jako s ním zacházet jako s bezstavovou aplikací. Organizuje vytváření, mazání a aktualizace podů a může být zaměřeno na automatické škálování horizontálních podů (HPA), tj. sadu ReplicaSet lze automaticky škálovat, pokud splňuje určité prahové hodnoty nebo cíle (využití CPU, pakety za sekundu, požadavek za sekundu atd).
Pokud dojde k výpadku jednoho z uzlů Kubernetes, budou na dostupném uzlu naplánovány nové moduly, aby splnily požadované repliky. Svazky přidružené k modulu budou odstraněny, pokud je modul smazán nebo přeplánován. Název hostitele pod bude vygenerován náhodně, takže bude obtížnější sledovat, kam kontejner patří, pouhým pohledem na název hostitele.
To vše funguje docela dobře v testovacích a přípravných prostředích, kde můžete provádět celý životní cyklus kontejneru, jako je nasazení, škálování, aktualizace a zničení bez jakýchkoli závislostí. Změna měřítka nahoru a dolů je přímočará aktualizací souboru YAML a jeho odesláním do clusteru Kubernetes nebo pomocí příkazu scale:
$ kubectl scale replicaset galera-rs --replicas=5
Použití StatefulSet
StatefulSet, známý jako PetSet ve verzi starší než 1.6, je nejlepší způsob, jak nasadit Galera Cluster v produkci, protože:
- Odstraněním a/nebo zmenšením StatefulSet nedojde k odstranění svazků přidružených k StatefulSet. To se provádí za účelem zajištění bezpečnosti dat, která je obecně cennější než automatické čištění všech souvisejících zdrojů StatefulSet.
- U StatefulSet s N replikami se moduly při nasazování modulů vytvářejí postupně v pořadí od {0 .. N-1 }.
- Když jsou moduly mazány, jsou ukončeny v opačném pořadí, od {N-1 .. 0}.
- Před použitím operace změny velikosti na podu musí být všechny jeho předchůdce spuštěné a připravené.
- Před ukončením podu musí být všechny jeho nástupce zcela vypnuty.
StatefulSet poskytuje prvotřídní podporu pro stavové kontejnery. Poskytuje záruku nasazení a škálování. Když je vytvořen tříuzlový Galera Cluster, budou nasazeny tři moduly v pořadí db-0, db-1, db-2. db-1 nebude nasazen, dokud nebude db-0 „Spuštěno a připraveno“ a db-2 nebude nasazeno, dokud nebude db-1 „Spuštěno a připraveno“. Pokud by db-0 selhal, poté, co je db-1 „Běžící a připravený“, ale před spuštěním db-2, nebude db-2 spuštěn, dokud nebude db-0 úspěšně znovu spuštěn a nestane se „Spuštěný a připravený“.
Budeme používat Kubernetes implementaci trvalého úložiště s názvem PersistentVolume a PersistentVolumeClaim. Tím se zajistí perzistence dat, pokud bude modul přeplánován na jiný uzel. Přestože Galera Cluster poskytuje přesnou kopii dat na každé replice, trvalé uložení dat v každém modulu je dobré pro účely odstraňování problémů a obnovy.
Abychom vytvořili trvalé úložiště, musíme nejprve vytvořit PersistentVolume pro každý modul. PV jsou moduly pro objemy jako Volumes v Dockeru, ale mají životní cyklus nezávislý na jakémkoli jednotlivém modulu, který používá PV. Protože se chystáme nasadit 3-uzlový Galera Cluster, musíme vytvořit 3 PV:
apiVersion: v1
kind: PersistentVolume
metadata:
name: datadir-galera-0
labels:
app: galera-ss
podindex: "0"
spec:
accessModes:
- ReadWriteOnce
capacity:
storage: 10Gi
hostPath:
path: /data/pods/galera-0/datadir
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: datadir-galera-1
labels:
app: galera-ss
podindex: "1"
spec:
accessModes:
- ReadWriteOnce
capacity:
storage: 10Gi
hostPath:
path: /data/pods/galera-1/datadir
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: datadir-galera-2
labels:
app: galera-ss
podindex: "2"
spec:
accessModes:
- ReadWriteOnce
capacity:
storage: 10Gi
hostPath:
path: /data/pods/galera-2/datadir
Výše uvedená definice ukazuje, že vytvoříme 3 PV, mapované na fyzickou cestu uzlů Kubernetes s 10 GB úložného prostoru. Definovali jsme ReadWriteOnce, což znamená, že svazek může být připojen jako čtení a zápis pouze jedním uzlem. Uložte výše uvedené řádky do mariadb-pv.yml a odešlete je do Kubernetes:
$ kubectl create -f mariadb-pv.yml
persistentvolume "datadir-galera-0" created
persistentvolume "datadir-galera-1" created
persistentvolume "datadir-galera-2" created
Dále definujte prostředky PersistentVolumeClaim:
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: mysql-datadir-galera-ss-0
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
selector:
matchLabels:
app: galera-ss
podindex: "0"
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: mysql-datadir-galera-ss-1
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
selector:
matchLabels:
app: galera-ss
podindex: "1"
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: mysql-datadir-galera-ss-2
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
selector:
matchLabels:
app: galera-ss
podindex: "2"
Výše uvedená definice ukazuje, že bychom chtěli nárokovat PV zdroje a používat spec.selector.matchLabels hledat naše PV (metadata.labels.app:galera-ss ) na základě příslušného indexu pod (metadata.labels.podindex). ) přidělený Kubernetes. metadata.name zdroj musí používat formát „{volumeMounts.name}-{pod}-{ordinální index}“ definovaný v spec.templates.containers takže Kubernetes ví, který přípojný bod má mapovat nárok do podu.
Uložte výše uvedené řádky do mariadb-pvc.yml a odešlete je do Kubernetes:
$ kubectl create -f mariadb-pvc.yml
persistentvolumeclaim "mysql-datadir-galera-ss-0" created
persistentvolumeclaim "mysql-datadir-galera-ss-1" created
persistentvolumeclaim "mysql-datadir-galera-ss-2" created
Naše trvalé úložiště je nyní připraveno. Poté můžeme zahájit nasazení Galera Cluster vytvořením prostředku StatefulSet společně se zdrojem služby Headless, jak je znázorněno v mariadb-ss.yml:
$ kubectl create -f mariadb-ss.yml
service "galera-ss" created
statefulset "galera-ss" created
Nyní si načtěte souhrn našeho nasazení StatefulSet:
$ kubectl get statefulsets,po,pv,pvc -o wide
NAME DESIRED CURRENT AGE
statefulsets/galera-ss 3 3 1d galera severalnines/mariadb:10.1 app=galera-ss
NAME READY STATUS RESTARTS AGE IP NODE
po/etcd0 1/1 Running 0 7d 10.36.0.1 kube3.local
po/etcd1 1/1 Running 0 7d 10.44.0.2 kube2.local
po/etcd2 1/1 Running 0 7d 10.36.0.2 kube3.local
po/galera-ss-0 1/1 Running 0 1d 10.44.0.4 kube2.local
po/galera-ss-1 1/1 Running 1 1d 10.36.0.5 kube3.local
po/galera-ss-2 1/1 Running 0 1d 10.44.0.5 kube2.local
NAME CAPACITY ACCESSMODES RECLAIMPOLICY STATUS CLAIM STORAGECLASS REASON AGE
pv/datadir-galera-0 10Gi RWO Retain Bound default/mysql-datadir-galera-ss-0 4d
pv/datadir-galera-1 10Gi RWO Retain Bound default/mysql-datadir-galera-ss-1 4d
pv/datadir-galera-2 10Gi RWO Retain Bound default/mysql-datadir-galera-ss-2 4d
NAME STATUS VOLUME CAPACITY ACCESSMODES STORAGECLASS AGE
pvc/mysql-datadir-galera-ss-0 Bound datadir-galera-0 10Gi RWO 4d
pvc/mysql-datadir-galera-ss-1 Bound datadir-galera-1 10Gi RWO 4d
pvc/mysql-datadir-galera-ss-2 Bound datadir-galera-2 10Gi RWO 4d
V tomto okamžiku lze náš Galera Cluster běžící na StatefulSet znázornit jako na následujícím diagramu:
Běh na StatefulSet zaručuje konzistentní identifikátory, jako je název hostitele, IP adresa, ID sítě, doména clusteru, pod DNS a úložiště. To umožňuje, aby se modul snadno odlišil od ostatních ve skupině modulů. Svazek bude uchován na hostiteli a nebude odstraněn, pokud je modul smazán nebo přeplánován na jiný uzel. To umožňuje obnovu dat a snižuje riziko úplné ztráty dat.
Na druhou stranu bude doba nasazení N-1 krát (N =repliky) déle, protože Kubernetes se bude při nasazování, přeplánování nebo mazání prostředků řídit pořadovým pořadím. Bylo by trochu obtížné připravit PV a nároky, než začnete přemýšlet o škálování vašeho clusteru. Upozorňujeme, že aktualizace existující sady StatefulSet je v současné době ruční proces, kdy můžete pouze aktualizovat spec.replicas v tuto chvíli.
Připojování ke Galera Cluster Service a modulům
Existuje několik způsobů, jak se připojit k databázovému clusteru. Můžete se připojit přímo k portu. V příkladu služby „galera-rs“ používáme NodePort, vystavujeme službu na IP každého uzlu na statickém portu (NodePort). Automaticky se vytvoří služba ClusterIP, na kterou bude služba NodePort směrovat. Službu NodePort budete moci kontaktovat z místa mimo klastr vyžádáním {NodeIP}:{NodePort} .
Příklad externího připojení ke Galera Cluster:
(external)$ mysql -udb_user -ppassword -h192.168.55.141 -P30000
(external)$ mysql -udb_user -ppassword -h192.168.55.142 -P30000
(external)$ mysql -udb_user -ppassword -h192.168.55.143 -P30000
V rámci síťového prostoru Kubernetes se mohou Pods připojit přes IP clusteru nebo název služby interně, který lze získat pomocí následujícího příkazu:
$ kubectl get services -o wide
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
etcd-client 10.104.244.200 <none> 2379/TCP 1d app=etcd
etcd0 10.100.24.171 <none> 2379/TCP,2380/TCP 1d etcd_node=etcd0
etcd1 10.108.207.7 <none> 2379/TCP,2380/TCP 1d etcd_node=etcd1
etcd2 10.101.9.115 <none> 2379/TCP,2380/TCP 1d etcd_node=etcd2
galera-rs 10.107.89.109 <nodes> 3306:30000/TCP 4h app=galera-rs
galera-ss None <none> 3306/TCP 3m app=galera-ss
kubernetes 10.96.0.1 <none> 443/TCP 1d <none>
Ze seznamu služeb vidíme, že Galera Cluster ReplicaSet Cluster-IP je 10.107.89.109. Interně může další modul přistupovat k databázi prostřednictvím této IP adresy nebo názvu služby pomocí vystaveného portu 3306:
(etcd0 pod)$ mysql -udb_user -ppassword -hgalera-rs -P3306 -e 'select @@hostname'
+------------------------+
| @@hostname |
+------------------------+
| galera-251551564-z4sgx |
+------------------------+
Můžete se také připojit k externímu NodePort z libovolného modulu na portu 30000:
(etcd0 pod)$ mysql -udb_user -ppassword -h192.168.55.143 -P30000 -e 'select @@hostname'
+------------------------+
| @@hostname |
+------------------------+
| galera-251551564-z4sgx |
+------------------------+
Připojení k backendovým modulům bude odpovídajícím způsobem vyváženo na základě algoritmu nejmenšího připojení.
Shrnutí
V tuto chvíli se spuštění Galera Cluster na Kubernetes ve výrobě zdá mnohem slibnější ve srovnání s Docker Swarm. Jak bylo uvedeno v posledním příspěvku na blogu, vznesené obavy se řeší odlišně způsobem, jakým Kubernetes organizuje kontejnery ve StatefulSet (ačkoli je to stále beta funkce ve verzi 1.6). Doufáme, že navrhovaný přístup pomůže spustit Galera Cluster na kontejnerech ve velkém měřítku ve výrobě.