Mysql
 sql >> база данни >  >> RDS >> Mysql

Стартиране на Galera Cluster на Kubernetes

В последните няколко блога разгледахме как да стартирате Galera Cluster на Docker, независимо дали на самостоятелен Docker или на Docker Swarm с множество хостове с мрежа за наслагване. В тази публикация в блога ще разгледаме стартирането на Galera Cluster на Kubernetes, инструмент за оркестрация за стартиране на контейнери в мащаб. Някои части са различни, като например как приложението трябва да се свърже с клъстера, как Kubernetes обработва отказ и как работи балансирането на натоварването в Kubernetes.

Kubernetes срещу Docker Swarm

Нашата крайна цел е да гарантираме, че Galera Cluster работи надеждно в контейнерна среда. По-рано покрихме Docker Swarm и се оказа, че стартирането на Galera Cluster върху него има редица блокери, които пречат да бъде готов за производство. Нашето пътуване сега продължава с Kubernetes, инструмент за оркестриране на контейнери от производствен клас. Нека да видим кое ниво на „готовност за производство“ може да поддържа, когато изпълнява услуга за състояние, като Galera Cluster.

Преди да продължим по-нататък, нека подчертаем някои от ключовите разлики между Kubernetes (1.6) и Docker Swarm (17.03) при стартиране на Galera Cluster на контейнери:

  • Kubernetes поддържа две сонди за проверка на здравето – жизненост и готовност. Това е важно при стартиране на Galera Cluster върху контейнери, тъй като живият контейнер Galera не означава, че е готов за обслужване и трябва да бъде включен в комплекта за балансиране на натоварването (помислете за състояние на свързване/донор). Docker Swarm поддържа само една сонда за проверка на здравето, подобна на жизнеността на Kubernetes, контейнерът е или здрав и продължава да работи, или нездравословен и се пренасрочва. Прочетете тук за подробности.
  • Kubernetes има табло за управление на потребителския интерфейс, достъпно чрез „kubectl proxy“.
  • Docker Swarm поддържа само кръгово балансиране на натоварването (влизане), докато Kubernetes използва най-малко връзка.
  • Docker Swarm поддържа мрежа за маршрутизиране за публикуване на услуга във външната мрежа, докато Kubernetes поддържа нещо подобно, наречено NodePort, както и външни балансатори на натоварване (GCE GLB/AWS ELB) и външни DNS имена (както за v1.7)

Инсталиране на Kubernetes с помощта на Kubeadm

Ще използваме kubeadm за инсталиране на Kubernetes клъстер с 3 възли на CentOS 7. Състои се от 1 главен и 2 възела (миньони). Нашата физическа архитектура изглежда така:

1. Инсталирайте kubelet и Docker на всички възли:

$ 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. На главния, инициализирайте главния, копирайте конфигурационния файл, настройте Pod мрежата с помощта на Weave и инсталирайте 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. След това на останалите останали възли:

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

4. Проверете дали възлите са готови:

$ 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

Вече имаме клъстер Kubernetes за внедряване на клъстер Galera.

Galera Cluster на Kubernetes

В този пример ще разположим MariaDB Galera Cluster 10.1, използвайки Docker изображение, изтеглено от нашето хранилище на DockerHub. Файловете с дефиниции на YAML, използвани в това разгръщане, могат да бъдат намерени в директорията example-kubernetes в хранилището на Github.

Kubernetes поддържа редица контролери за внедряване. За да разгърнете клъстер Galera, можете да използвате:

  • Набор реплики
  • StatefulSet

Всеки от тях има своите плюсове и минуси. Ще разгледаме всеки един от тях и ще видим каква е разликата.

Предварителни условия

Изображението, което изградихме, изисква etcd (самостоятелен или клъстер) за откриване на услуга. За да стартирате etcd клъстер, изисква всеки etcd екземпляр да се изпълнява с различни команди, така че ще използваме Pods контролер вместо Deployment и ще създадем услуга, наречена „etcd-client“ като крайна точка за etcd Pods. Файлът с дефиниция etcd-cluster.yaml разказва всичко.

За да разположите 3-pod etcd клъстер, просто изпълнете:

$ kubectl create -f etcd-cluster.yaml

Проверете дали etcd клъстерът е готов:

$ 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

Нашата архитектура сега изглежда така:

Няколко MySQL в Docker:Как да контейнеризирате вашата база данни Открийте всичко, което трябва да разберете, когато обмисляте да стартирате услуга на MySQL горната част на виртуализацията на контейнера Docker Изтеглете Бялата книга

Използване на ReplicaSet

ReplicaSet гарантира, че определен брой „реплика“ на модула се изпълняват по всяко време. Въпреки това, внедряването е концепция от по-високо ниво, която управлява ReplicaSets и предоставя декларативни актуализации на pods заедно с много други полезни функции. Ето защо се препоръчва да използвате разгръщания, вместо директно да използвате ReplicaSets, освен ако не се нуждаете от персонализирана оркестрация на актуализации или изобщо не изисквате актуализации. Когато използвате Deployments, не е нужно да се притеснявате за управлението на ReplicaSets, които те създават. Разгръщанията притежават и управляват своите ReplicaSets.

В нашия случай ще използваме Deployment като контролер на натоварването, както е показано в тази дефиниция на YAML. Можем директно да създадем Galera Cluster ReplicaSet и Service, като изпълним следната команда:

$ kubectl create -f mariadb-rs.yml

Проверете дали клъстерът е готов, като погледнете ReplicaSet (rs), pods (po) и услуги (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

От изхода по-горе можем да илюстрираме нашите модули и услуги, както следва:

Изпълнението на Galera Cluster на ReplicaSet е подобно на третирането му като приложение без състояние. Той организира създаването, изтриването и актуализациите на капсули и може да бъде насочен към хоризонтални модули за автоматично мащабиране (HPA), т.е. ReplicaSet може да бъде автоматично мащабиран, ако отговаря на определени прагове или цели (използване на процесора, пакети в секунда, заявка за секунда и др.).

Ако един от възлите на Kubernetes се повреди, новите Pods ще бъдат насрочени на наличен възел, за да отговарят на желаните реплики. Томовете, свързани с Pod, ще бъдат изтрити, ако Pod бъде изтрит или пренасрочен. Името на хост на Pod ще бъде генерирано на случаен принцип, което затруднява проследяването на мястото на контейнера, като просто погледнете името на хоста.

Всичко това работи доста добре в тестови и сценични среди, където можете да изпълнявате пълен жизнен цикъл на контейнера като разгръщане, мащабиране, актуализиране и унищожаване без никакви зависимости. Мащабирането нагоре и надолу е лесно, като актуализирате YAML файла и го публикувате в клъстер Kubernetes или с помощта на командата scale:

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

Използване на StatefulSet

Известен като PetSet във версия преди 1.6, StatefulSet е най-добрият начин за внедряване на Galera Cluster в производството, защото:

  • Изтриването и/или намаляването на StatefulSet няма да изтрие томовете, свързани с StatefulSet. Това се прави, за да се гарантира безопасността на данните, която обикновено е по-ценна от автоматичното изчистване на всички свързани ресурси на StatefulSet.
  • За StatefulSet с N реплики, когато Pods се разгръщат, те се създават последователно, в ред от {0 .. N-1 }.
  • Когато модулите се изтриват, те се прекратяват в обратен ред, от {N-1 .. 0}.
  • Преди операция за мащабиране да бъде приложена към Pod, всичките му предшественици трябва да са Running и Ready.
  • Преди да бъде прекратен Pod, всички негови наследници трябва да бъдат напълно изключени.

StatefulSet осигурява първокласна поддръжка за контейнери с поддържане на състоянието. Той осигурява гаранция за разгръщане и мащабиране. Когато се създаде клъстер Galera с три възли, три модула ще бъдат разгърнати в реда db-0, db-1, db-2. db-1 няма да бъде разгърнат, преди db-0 да е „Работащ и готов“, а db-2 няма да бъде разгърнат, докато db-1 не е „Работащ и готов“. Ако db-0 се провали, след като db-1 е „Работащ и готов“, но преди db-2 да бъде стартиран, db-2 няма да бъде стартиран, докато db-0 не се стартира успешно и не стане „Работащ и готов“.

Ще използваме Kubernetes реализация на постоянно хранилище, наречено PersistentVolume и PersistentVolumeClaim. Това, за да се гарантира устойчивост на данните, ако модулът е пренасрочен към другия възел. Въпреки че Galera Cluster предоставя точното копие на данните за всяка реплика, запазването на данните във всяка капсула е добро за отстраняване на неизправности и цели за възстановяване.

За да създадем постоянно хранилище, първо трябва да създадем PersistentVolume за всяка капсула. PV са обемни плъгини като Volumes в Docker, но имат жизнен цикъл, независим от всеки отделен модул, който използва PV. Тъй като ще внедрим клъстер Galera с 3 възела, трябва да създадем 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

Горната дефиниция показва, че ще създадем 3 PV, съпоставени с физическия път на възлите на Kubernetes с 10 GB пространство за съхранение. Ние дефинирахме ReadWriteOnce, което означава, че томът може да бъде монтиран като четене-запис само от един възел. Запазете горните редове в mariadb-pv.yml и го публикувайте в Kubernetes:

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

След това дефинирайте ресурсите 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"

Горната дефиниция показва, че бихме искали да поискаме PV ресурсите и да използваме spec.selector.matchLabels за да потърсите нашата PV (metadata.labels.app:galera-ss ) въз основа на съответния индекс на капсула (metadata.labels.podindex ) присвоен от Kubernetes. име на метаданни ресурсът трябва да използва формата „{volumeMounts.name}-{pod}-{ordinal index}“, дефиниран под spec.templates.containers така че Kubernetes знае коя точка на монтиране да преобразува искането в модула.

Запазете горните редове в mariadb-pvc.yml и го публикувайте в 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

Нашето постоянно хранилище вече е готово. След това можем да започнем внедряването на Galera Cluster, като създадем ресурс StatefulSet заедно с ресурс за услуга без глава, както е показано в mariadb-ss.yml:

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

Сега извлечете обобщението на нашето внедряване на 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

В този момент нашият Galera Cluster, работещ на StatefulSet, може да бъде илюстриран както на следната диаграма:

Изпълнението на StatefulSet гарантира последователни идентификатори като име на хост, IP адрес, мрежов идентификатор, клъстерен домейн, Pod DNS и съхранение. Това позволява на шушулката лесно да се отличава от другите в група шушулки. Томът ще бъде запазен на хоста и няма да бъде изтрит, ако Pod бъде изтрит или пренасрочен на друг възел. Това позволява възстановяване на данни и намалява риска от пълна загуба на данни.

От отрицателна страна, времето за внедряване ще бъде N-1 пъти (N =реплики) по-дълго, защото Kubernetes ще се подчинява на порядковата последователност при разполагане, разсрочване или изтриване на ресурсите. Би било малко главоболие да подготвите PV и претенциите, преди да помислите за мащабиране на вашия клъстер. Обърнете внимание, че актуализирането на съществуващ StatefulSet понастоящем е ръчен процес, при който можете само актуализирате spec.replicas в момента.

Свързване с Galera Cluster Service и Pods

Има няколко начина, по които можете да се свържете с клъстера на базата данни. Можете да се свържете директно към порта. В примера за услуга „galera-rs“, ние използваме NodePort, излагайки услугата на IP на всеки възел на статичен порт (NodePort). Автоматично се създава ClusterIP услуга, към която услугата NodePort ще маршрутизира. Ще можете да се свържете с услугата NodePort извън клъстера, като поискате {NodeIP}:{NodePort} .

Пример за външно свързване към клъстера Galera:

(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

В мрежовото пространство на Kubernetes Pods могат да се свързват чрез клъстер IP или име на услуга вътрешно, което може да бъде извлечено чрез следната команда:

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

От списъка с услуги можем да видим, че Galera Cluster ReplicaSet Cluster-IP е 10.107.89.109. Вътрешно друг модул може да осъществява достъп до базата данни чрез този IP адрес или име на услугата, използвайки открития порт 3306:

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

Можете също така да се свържете с външния NodePort от вътрешността на всеки модул на порт 30000:

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

Връзката към задните модули ще бъде съответно балансирана на натоварване въз основа на алгоритъм за най-малка връзка.

Резюме

В този момент стартирането на Galera Cluster на Kubernetes в производство изглежда много по-обещаващо в сравнение с Docker Swarm. Както беше обсъдено в последната публикация в блога, повдигнатите опасения се решават по различен начин с начина, по който Kubernetes организира контейнерите в StatefulSet (въпреки че все още е бета функция във v1.6). Надяваме се, че предложеният подход ще помогне за стартирането на Galera Cluster на контейнери в мащабно производство.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да получите числови типове от MySQL с помощта на PDO?

  2. Как да намерите името на ограничение в MySQL

  3. Как работи функцията RTRIM() в MySQL

  4. Как да промените форматите за дата и час в MySQL

  5. Nodejs изразяват и обещават, че не правят това, което очаквам