Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Uruchamianie klastra Galera na Kubernetes

W ostatnich kilku blogach opisaliśmy, jak uruchomić klaster Galera w Dockerze, niezależnie od tego, czy jest to samodzielny Docker, czy też w wielohostowym Docker Swarm z siecią nakładkową. W tym poście na blogu przyjrzymy się uruchamianiu Galera Cluster na Kubernetes, narzędziu do orkiestracji do uruchamiania kontenerów na dużą skalę. Niektóre elementy są różne, na przykład sposób, w jaki aplikacja powinna łączyć się z klastrem, jak Kubernetes obsługuje przełączanie awaryjne i jak działa równoważenie obciążenia w Kubernetes.

Kubernetes kontra rój Dockerów

Naszym nadrzędnym celem jest zapewnienie niezawodnego działania Galera Cluster w środowisku kontenerowym. Wcześniej omawialiśmy Docker Swarm i okazało się, że uruchamianie na nim Galera Cluster ma szereg blokad, które uniemożliwiają gotowość do produkcji. Nasza podróż jest teraz kontynuowana dzięki Kubernetes, narzędziu do orkiestracji kontenerów klasy produkcyjnej. Zobaczmy, jaki poziom „gotowości produkcyjnej” może obsługiwać podczas uruchamiania usługi stanowej, takiej jak Galera Cluster.

Zanim przejdziemy dalej, podkreślmy kilka kluczowych różnic między Kubernetes (1.6) a Docker Swarm (17.03) podczas uruchamiania Galera Cluster na kontenerach:

  • Kubernetes obsługuje dwie sondy sprawdzające kondycję — żywotność i gotowość. Jest to ważne podczas uruchamiania Galera Cluster na kontenerach, ponieważ aktywny kontener Galera nie oznacza, że ​​jest gotowy do obsługi i powinien być uwzględniony w zestawie równoważenia obciążenia (pomyśl o stanie dołączającym/dawcy). Docker Swarm obsługuje tylko jedną sondę kontroli kondycji podobną do żywotności Kubernetes, kontener jest albo w dobrej kondycji i nadal działa, albo w złej kondycji i zostaje przełożony. Przeczytaj tutaj, aby uzyskać szczegółowe informacje.
  • Kubernetes ma panel UI dostępny przez „proxy Kubectl”.
  • Docker Swarm obsługuje tylko równoważenie obciążenia typu round-robin (przychodzące), podczas gdy Kubernetes używa najmniejszego połączenia.
  • Docker Swarm obsługuje siatkę routingu w celu publikowania usługi w sieci zewnętrznej, podczas gdy Kubernetes obsługuje coś podobnego o nazwie NodePort, a także zewnętrzne systemy równoważenia obciążenia (GCE GLB/AWS ELB) i zewnętrzne nazwy DNS (jak w wersji 1.7)

Instalowanie Kubernetes za pomocą Kubeadm

Zamierzamy użyć kubeadm do zainstalowania 3-węzłowego klastra Kubernetes na CentOS 7. Składa się on z 1 węzła głównego i 2 węzłów (minionów). Nasza fizyczna architektura wygląda tak:

1. Zainstaluj kubelet i Docker na wszystkich węzłach:

$ 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 masterze zainicjalizuj go, skopiuj plik konfiguracyjny, skonfiguruj sieć Pod za pomocą Weave i zainstaluj 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. Następnie w pozostałych pozostałych węzłach:

$ kubeadm join --token 091d2a.e4862a6224454fd6 192.168.55.140:6443

4. Sprawdź, czy węzły są gotowe:

$ 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

Mamy teraz klaster Kubernetes do wdrożenia klastra Galera.

Klaster Galera na Kubernetes

W tym przykładzie zamierzamy wdrożyć MariaDB Galera Cluster 10.1 przy użyciu obrazu Docker pobranego z naszego repozytorium DockerHub. Pliki definicji YAML używane w tym wdrożeniu można znaleźć w katalogu example-kubernetes w repozytorium Github.

Kubernetes obsługuje wiele kontrolerów wdrażania. Aby wdrożyć klaster Galera, można użyć:

  • Zestaw replik
  • StatefulSet

Każdy z nich ma swoje zalety i wady. Przyjrzymy się każdemu z nich i zobaczymy, jaka jest różnica.

Wymagania wstępne

Zbudowany przez nas obraz wymaga etcd (samodzielnego lub klastra) do wykrywania usług. Uruchomienie klastra etcd wymaga, aby każda instancja etcd działała z różnymi poleceniami, więc zamiast Deploymentu użyjemy kontrolera Pods i stworzymy usługę o nazwie „etcd-client” jako punkt końcowy do podów etcd. Plik definicji etcd-cluster.yaml mówi wszystko.

Aby wdrożyć 3-podowy klaster etcd, po prostu uruchom:

$ kubectl create -f etcd-cluster.yaml

Sprawdź, czy klaster etcd jest gotowy:

$ 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

Nasza architektura wygląda teraz mniej więcej tak:

Korzystanie z zestawu replik

ReplicaSet zapewnia, że ​​określona liczba „replik” pod jest uruchomiona w danym momencie. Jednak wdrożenie to koncepcja wyższego poziomu, która zarządza zestawami replik i zapewnia deklaratywne aktualizacje zasobników wraz z wieloma innymi przydatnymi funkcjami. Dlatego zaleca się używanie wdrożeń zamiast bezpośredniego korzystania z zestawów ReplicaSets, chyba że potrzebujesz niestandardowej aranżacji aktualizacji lub w ogóle nie potrzebujesz aktualizacji. Korzystając z wdrożeń, nie musisz martwić się o zarządzanie tworzonymi przez nich zestawami replik. Wdrożenia posiadają własne zestawy replik i zarządzają nimi.

W naszym przypadku zamierzamy użyć Deploymentu jako kontrolera obciążenia, jak pokazano w tej definicji YAML. Możemy bezpośrednio utworzyć zestaw replik klastra Galera i usługę, uruchamiając następujące polecenie:

$ kubectl create -f mariadb-rs.yml

Sprawdź, czy klaster jest gotowy, patrząc na ReplicaSet (rs), pody (po) i usługi (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 powyższego wyniku możemy zilustrować nasze pody i usługę jak poniżej:

Uruchamianie Galera Cluster na ReplicaSet jest podobne do traktowania go jako aplikacji bezstanowej. Organizuje tworzenie, usuwanie i aktualizowanie podów i może być ukierunkowany na poziome autoskalowanie podów (HPA), tj. ReplicaSet może być automatycznie skalowany, jeśli spełnia określone progi lub cele (zużycie procesora, pakiety na sekundę, żądania na sekundę itp).

Jeśli jeden z węzłów Kubernetes ulegnie awarii, nowe pody zostaną zaplanowane na dostępnym węźle, aby spełnić żądane repliki. Woluminy powiązane z podem zostaną usunięte, jeśli pod zostanie usunięty lub przełożony. Nazwa hosta poda będzie generowana losowo, co utrudni śledzenie, gdzie należy kontener, po prostu patrząc na nazwę hosta.

Wszystko to działa całkiem dobrze w środowiskach testowych i testowych, w których można wykonać pełny cykl życia kontenera, taki jak wdrażanie, skalowanie, aktualizowanie i niszczenie bez żadnych zależności. Skalowanie w górę i w dół jest proste, dzięki zaktualizowaniu pliku YAML i wysłaniu go do klastra Kubernetes lub za pomocą polecenia scale:

$ kubectl scale replicaset galera-rs --replicas=5

Korzystanie z zestawu stanowego

Znany jako PetSet w wersji przed 1.6, StatefulSet to najlepszy sposób na wdrożenie Galera Cluster w środowisku produkcyjnym, ponieważ:

  • Usunięcie i/lub skalowanie w dół StatefulSet nie spowoduje usunięcia woluminów skojarzonych z StatefulSet. Ma to na celu zapewnienie bezpieczeństwa danych, które jest ogólnie bardziej wartościowe niż automatyczne czyszczenie wszystkich powiązanych zasobów StatefulSet.
  • W przypadku StatefulSet z N replikami, podczas wdrażania podów są one tworzone sekwencyjnie, w kolejności od {0 .. N-1 }.
  • Kiedy pody są usuwane, są kończone w odwrotnej kolejności, od {N-1 .. 0}.
  • Zanim operacja skalowania zostanie zastosowana do poda, wszyscy jego poprzednicy muszą być uruchomieni i gotowi.
  • Zanim pod zostanie zamknięty, wszystkie jego następcy muszą zostać całkowicie zamknięte.

StatefulSet zapewnia pierwszorzędną obsługę kontenerów stanowych. Zapewnia gwarancję wdrożenia i skalowania. Po utworzeniu trzywęzłowego klastra Galera zostaną wdrożone trzy pody w kolejności db-0, db-1, db-2. db-1 nie zostanie wdrożony, dopóki db-0 nie będzie „uruchomiony i gotowy”, a db-2 nie zostanie wdrożony, dopóki db-1 nie będzie „uruchomiony i gotowy”. Jeśli db-0 ulegnie awarii, po tym, jak db-1 jest „Uruchomiony i gotowy”, ale przed uruchomieniem db-2, db-2 nie zostanie uruchomiony, dopóki db-0 nie zostanie pomyślnie uruchomiony ponownie i stanie się „Uruchomiony i gotowy”.

Zamierzamy użyć implementacji Kubernetes pamięci trwałej o nazwie PersistentVolume i PersistentVolumeClaim. Ma to zapewnić trwałość danych, jeśli pod został przeniesiony do innego węzła. Mimo że Galera Cluster zapewnia dokładną kopię danych w każdej replice, trwałe dane w każdym zasobniku są dobre do rozwiązywania problemów i odzyskiwania.

Aby utworzyć trwały magazyn, najpierw musimy utworzyć PersistentVolume dla każdego poda. PV to wtyczki głośności, takie jak Volumes w Dockerze, ale mają cykl życia niezależny od poszczególnych podów, które korzystają z PV. Ponieważ zamierzamy wdrożyć 3-węzłowy klaster Galera, musimy utworzyć 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

Powyższa definicja pokazuje, że zamierzamy stworzyć 3 PV, zmapowane do fizycznej ścieżki węzłów Kubernetes z 10 GB przestrzeni dyskowej. Zdefiniowaliśmy ReadWriteOnce, co oznacza, że ​​wolumin może być montowany w trybie odczytu-zapisu tylko przez jeden węzeł. Zapisz powyższe wiersze w mariadb-pv.yml i prześlij je do Kubernetes:

$ kubectl create -f mariadb-pv.yml
persistentvolume "datadir-galera-0" created
persistentvolume "datadir-galera-1" created
persistentvolume "datadir-galera-2" created

Następnie zdefiniuj zasoby 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"

Powyższa definicja pokazuje, że chcielibyśmy przejąć zasoby PV i użyć spec.selector.matchLabels szukać naszego PV (metadata.labels.app:galera-ss ) na podstawie odpowiedniego indeksu pod (metadata.labels.podindex ) przypisane przez Kubernetes. nazwa.metadanych zasób musi mieć format „{volumeMounts.name}-{pod}-{indeks porządkowy}” zdefiniowany w spec.templates.containers więc Kubernetes wie, który punkt montowania zmapować roszczenie do pod.

Zapisz powyższe wiersze w mariadb-pvc.yml i prześlij 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

Nasza pamięć trwała jest już gotowa. Następnie możemy rozpocząć wdrażanie klastra Galera, tworząc zasób StatefulSet wraz z zasobem usługi Headless, jak pokazano w mariadb-ss.yml:

$ kubectl create -f mariadb-ss.yml
service "galera-ss" created
statefulset "galera-ss" created

Teraz pobierz podsumowanie naszego wdrożenia 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

W tym momencie nasz klaster Galera działający na StatefulSet można zilustrować na poniższym diagramie:

Działanie na StatefulSet gwarantuje spójne identyfikatory, takie jak nazwa hosta, adres IP, identyfikator sieci, domena klastra, Pod DNS i pamięć masowa. Dzięki temu Pod może łatwo odróżnić się od innych w grupie Podów. Wolumin zostanie zachowany na hoście i nie zostanie usunięty, jeśli pod zostanie usunięty lub przeniesiony na inny węzeł. Pozwala to na odzyskanie danych i zmniejsza ryzyko całkowitej utraty danych.

Z drugiej strony czas wdrożenia wyniesie N-1 razy (N =replik) dłużej, ponieważ Kubernetes będzie przestrzegać kolejności porządkowej podczas wdrażania, zmiany harmonogramu lub usuwania zasobów. Przygotowanie PV i roszczeń przed myśleniem o skalowaniu klastra byłoby trochę kłopotliwe. Pamiętaj, że aktualizowanie istniejącego zestawu StatefulSet jest obecnie procesem ręcznym, w którym można tylko aktualizować spec.replicas w tej chwili.

Łączenie z usługą Galera Cluster Service i podami

Istnieje kilka sposobów łączenia się z klastrem bazy danych. Możesz podłączyć się bezpośrednio do portu. W przykładzie usługi „galera-rs” używamy NodePort, eksponując usługę na IP każdego węzła na statycznym porcie (NodePort). Usługa ClusterIP, do której będzie kierować usługa NodePort, jest tworzona automatycznie. Będziesz mógł skontaktować się z usługą NodePort spoza klastra, żądając {NodeIP}:{NodePort} .

Przykład zewnętrznego połączenia z 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

W przestrzeni sieciowej Kubernetes Pody mogą łączyć się wewnętrznie przez adres IP klastra lub nazwę usługi, którą można pobrać za pomocą następującego polecenia:

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

Z listy usług widać, że Galera Cluster ReplicaSet Cluster-IP to 10.107.89.109. Wewnętrznie inny pod może uzyskać dostęp do bazy danych za pośrednictwem tego adresu IP lub nazwy usługi przy użyciu ujawnionego portu 3306:

(etcd0 pod)$ mysql -udb_user -ppassword -hgalera-rs -P3306 -e 'select @@hostname'
+------------------------+
| @@hostname             |
+------------------------+
| galera-251551564-z4sgx |
+------------------------+

Możesz także połączyć się z zewnętrznym NodePort z wnętrza dowolnego kapsuły na porcie 30000:

(etcd0 pod)$ mysql -udb_user -ppassword -h192.168.55.143 -P30000 -e 'select @@hostname'
+------------------------+
| @@hostname             |
+------------------------+
| galera-251551564-z4sgx |
+------------------------+

Połączenie z podami backendu będzie odpowiednio równoważone w oparciu o algorytm najmniejszego połączenia.

Podsumowanie

W tym momencie uruchomienie Galera Cluster na Kubernetes w środowisku produkcyjnym wydaje się znacznie bardziej obiecujące w porównaniu z Docker Swarm. Jak omówiono w ostatnim poście na blogu, zgłaszane problemy są rozwiązywane w inny sposób w sposobie, w jaki Kubernetes organizuje kontenery w StatefulSet (chociaż nadal jest to funkcja beta w wersji 1.6). Mamy nadzieję, że sugerowane podejście pomoże uruchomić Galera Cluster na kontenerach na dużą skalę w produkcji.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL:Powtórz wiersz wyniku wiele razy i ponumeruj wiersze

  2. Pierwsze kroki z GearHost do tworzenia baz danych MySQL

  3. Stosowanie PDO na zajęciach

  4. Jak mogę manipulować trafnością wyszukiwania pełnotekstowego MySQL, aby jedno pole było bardziej „wartościowe” niż inne?

  5. DAYNAME() Przykłady – MySQL