WordPress ist die Mainstream-Plattform zum Bearbeiten und Ver?ffentlichen von Webinhalten. In diesem Tutorial erl?utere ich, wie Sie mit Kubernetes eine WordPress-Bereitstellung mit hoher Verfügbarkeit (HA) erstellen.
WordPress besteht aus zwei Hauptkomponenten: dem WordPress-PHP-Server und der Datenbank, in der Benutzerinformationen, Beitr?ge und Website-Daten gespeichert werden. Wir müssen beide Komponenten der gesamten Anwendung gleichzeitig hochverfügbar und fehlertolerant machen.
Der Betrieb eines hochverfügbaren Dienstes kann schwierig sein, wenn sich Hardware und Adressen ?ndern: sehr schwierig zu warten. Mit Kubernetes und seinen leistungsstarken Netzwerkkomponenten k?nnen wir hochverfügbare WordPress-Sites und MySQL-Datenbanken bereitstellen, ohne (fast) eine einzige IP-Adresse eingeben zu müssen.
In diesem Tutorial zeige ich Ihnen, wie Sie Speicherklassen, Dienste, Konfigurationskarten und Sammlungen in Kubernetes erstellen, wie Sie hochverfügbares MySQL ausführen und wie Sie einen hochverfügbaren WordPress-Cluster in einen Datenbankdienst einbinden. Wenn Sie noch keinen Kubernetes-Cluster haben, k?nnen Sie diesen ganz einfach auf Amazon, Google oder Azure finden und starten oder Rancher Kubernetes Engine (RKE)
auf einem beliebigen Server verwenden Rancher Kubernetes Engine (RKE)
架構(gòu)概述
現(xiàn)在我來簡要介紹一下我們將要使用的技術(shù)及其功能:
WordPress應用程序文件的存儲:具有GCE持久性磁盤備份的NFS存儲
數(shù)據(jù)庫集群:帶有用于奇偶校驗的xtrabackup的MySQL
應用程序級別:掛載到NFS存儲的WordPress DockerHub映像
負載均衡和網(wǎng)絡:基于Kubernetes的負載均衡器和服務網(wǎng)絡
該體系架構(gòu)如下所示:
在K8s中創(chuàng)建存儲類、服務和配置映射
在Kubernetes中,狀態(tài)集提供了一種定義pod初始化順序的方法。我們將使用一個有狀態(tài)的MySQL集合,因為它能確保我們的數(shù)據(jù)節(jié)點有足夠的時間在啟動時復制先前pods中的記錄。我們配置這個狀態(tài)集的方式可以讓MySQL主機在其他附屬機器之前先啟動,因此當我們擴展時,可以直接從主機將克隆發(fā)送到附屬機器上。
首先,我們需要創(chuàng)建一個持久卷存儲類和配置映射,以根據(jù)需要應用主從配置。我們使用持久卷,避免數(shù)據(jù)庫中的數(shù)據(jù)受限于集群中任何特定的pods。這種方式可以避免數(shù)據(jù)庫在MySQL主機pod丟失的情況下丟失數(shù)據(jù),當主機pod丟失時,它可以重新連接到帶xtrabackup的附屬機器,并將數(shù)據(jù)從附屬機器拷貝到主機中。MySQL的復制負責主機-附屬的復制,而xtrabackup負責附屬-主機的復制。
要動態(tài)分配持久卷,我們使用GCE持久磁盤創(chuàng)建存儲類。不過,Kubernetes提供了各種持久性卷的存儲方案:
#?storage-class.yamlkind:?StorageClassapiVersion:?storage.k8s.io/v1metadata: ?name:?slowprovisioner:?kubernetes.io/gce-pdparameters: ?type:?pd-standard??zone:?us-central1-a
創(chuàng)建類,并且使用指令:$ kubectl create -f storage-class.yaml
部署它。
接下來,我們將創(chuàng)建configmap,它指定了一些在MySQL配置文件中設(shè)置的變量。這些不同的配置由pod本身選擇有關(guān),但它們也為我們提供了一種便捷的方式來管理潛在的配置變量。
創(chuàng)建名為mysql-configmap.yaml
的YAML文件來處理配置,如下:
#?mysql-configmap.yamlapiVersion:?v1kind:?ConfigMapmetadata: ?name:?mysql??labels: ???app:?mysqldata: ?master.cnf:?|????#?Apply?this?config?only?on?the?master. ???[mysqld] ???log-bin ???skip-host-cache ???skip-name-resolve??slave.cnf:?|????#?Apply?this?config?only?on?slaves. ???[mysqld] ???skip-host-cache ???skip-name-resolve
創(chuàng)建configmap
并使用指令:$ kubectl create -f mysql-configmap.yaml
來部署它。
接下來我們要設(shè)置服務以便MySQL pods可以互相通信,并且我們的WordPress pod可以使用mysql-services.yaml
與MySQL通信。這也為MySQL服務啟動了服務負載均衡器。
#?mysql-services.yaml#?Headless?service?for?stable?DNS?entries?of?StatefulSet?members.apiVersion:?v1kind:?Servicemetadata: ?name:?mysql??labels: ???app:?mysqlspec: ?ports: ?-?name:?mysql????port:?3306??clusterIP:?None??selector: ???app:?mysql
通過此服務聲明,我們就為實現(xiàn)一個多寫入、多讀取的MySQL實例集群奠定了基礎(chǔ)。這種配置是必要的,每個WordPress實例都可能寫入數(shù)據(jù)庫,所以每個節(jié)點都必須準備好讀寫。
執(zhí)行命令 $ kubectl create -f mysql-services.yaml
來創(chuàng)建上述的服務。
到這為止,我們創(chuàng)建了卷聲明存儲類,它將持久磁盤交給所有請求它們的容器,我們配置了configmap
ArchitekturübersichtLassen Sie mich nun kurz die von uns verwendete Technologie und ihre F?higkeiten vorstellen:
Speicherung von WordPress-Anwendungsdateien: NFS-Speicher mit GCE-Persistent-Disk-Backup
Datenbankcluster: mit für Parit?t bew?hrtem xtrabackup für MySQL Anwendungsebene: WordPress DockerHub-Image im NFS-Speicher bereitgestellt
Lastenausgleich und Netzwerk: Kubernetes-basierter Lastenausgleich und Servicenetzwerk ????Die Architektur sieht folgenderma?en aus: ?? ??
?? ??In Kubernetes bieten Zustandss?tze eine M?glichkeit, die Reihenfolge der Pod-Initialisierung zu definieren. Wir werden eine zustandsbehaftete MySQL-Sammlung verwenden, da diese sicherstellt, dass unsere Datenknoten beim Start genügend Zeit haben, Datens?tze aus vorherigen Pods zu replizieren. Wir konfigurieren diesen Statussatz so, dass der MySQL-Master vor den anderen Slave-Maschinen gestartet wird, sodass bei der Skalierung Klone direkt vom Master an die Slave-Maschinen gesendet werden k?nnen. ????Zuerst müssen wir eine persistente Volume-Speicherklasse und eine Konfigurationszuordnung erstellen, um die Master-Slave-Konfiguration nach Bedarf anzuwenden. Wir verwenden persistente Volumes, um zu verhindern, dass die Daten in der Datenbank an bestimmte Pods im Cluster gebunden werden. Dieser Ansatz verhindert, dass die Datenbank Daten verliert, wenn der MySQL-Host-Pod verloren geht. Wenn der Host-Pod verloren geht, kann er sich mit xtrabackup erneut mit dem Slave-Computer verbinden und die Daten vom Slave-Computer auf den Host kopieren. Die MySQL-Replikation ist für die Host-Slave-Replikation verantwortlich, und xtrabackup ist für die Slave-Host-Replikation verantwortlich. ????Um persistente Volumes dynamisch zuzuweisen, erstellen wir eine Speicherklasse mit GCE Persistent Disk. Kubernetes bietet jedoch verschiedene Speicherl?sungen für persistente Volumes: ??apiVersion:?apps/v1beta1kind:?StatefulSetmetadata:
?name:?mysqlspec:
?selector:
???matchLabels:
?????app:?mysql??serviceName:?mysql??replicas:?3??template:
???metadata:
?????labels:
???????app:?mysql????spec:
?????initContainers:
?????-?name:?init-mysql????????image:?mysql:5.7????????command:
???????-?bash????????-?"-c"
???????-?|
?????????set?-ex??????????#?Generate?mysql?server-id?from?pod?ordinal?index.
?????????[[?`hostname`?=~?-([0-9]+)$?]]?||?exit?1
?????????ordinal=${BASH_REMATCH[1]}
?????????echo?[mysqld]?>?/mnt/conf.d/server-id.cnf??????????#?Add?an?offset?to?avoid?reserved?server-id=0?value.
?????????echo?server-id=$((100?+?$ordinal))?>>?/mnt/conf.d/server-id.cnf??????????#?Copy?appropriate?conf.d?files?from?config-map?to?emptyDir.
?????????if?[[?$ordinal?-eq?0?]];?then
???????????cp?/mnt/config-map/master.cnf?/mnt/conf.d/
?????????else
???????????cp?/mnt/config-map/slave.cnf?/mnt/conf.d/
?????????fi????????volumeMounts:
???????-?name:?conf??????????mountPath:?/mnt/conf.d????????-?name:?config-map??????????mountPath:?/mnt/config-map??????-?name:?clone-mysql????????image:?gcr.io/google-samples/xtrabackup:1.0????????command:
???????-?bash????????-?"-c"
???????-?|
?????????set?-ex??????????#?Skip?the?clone?if?data?already?exists.
?????????[[?-d?/var/lib/mysql/mysql?]]?&&?exit?0??????????#?Skip?the?clone?on?master?(ordinal?index?0).
?????????[[?`hostname`?=~?-([0-9]+)$?]]?||?exit?1
?????????ordinal=${BASH_REMATCH[1]}
?????????[[?$ordinal?-eq?0?]]?&&?exit?0??????????#?Clone?data?from?previous?peer.
?????????ncat?--recv-only?mysql-$(($ordinal-1)).mysql?3307?|?xbstream?-x?-C?/var/lib/mysql??????????#?Prepare?the?backup.
?????????xtrabackup?--prepare?--target-dir=/var/lib/mysql????????volumeMounts:
???????-?name:?data??????????mountPath:?/var/lib/mysql??????????subPath:?mysql????????-?name:?conf??????????mountPath:?/etc/mysql/conf.d??????containers:
?????-?name:?mysql????????image:?mysql:5.7????????env:
???????-?name:?MYSQL_ALLOW_EMPTY_PASSWORD??????????value:?"1"
???????ports:
???????-?name:?mysql??????????containerPort:?3306????????volumeMounts:
???????-?name:?data??????????mountPath:?/var/lib/mysql??????????subPath:?mysql????????-?name:?conf??????????mountPath:?/etc/mysql/conf.d????????resources:
?????????requests:
???????????cpu:?500m????????????memory:?1Gi????????livenessProbe:
?????????exec:
???????????command:?["mysqladmin",?"ping"]
?????????initialDelaySeconds:?30??????????periodSeconds:?10??????????timeoutSeconds:?5????????readinessProbe:
?????????exec:
???????????#?Check?we?can?execute?queries?over?TCP?(skip-networking?is?off).
???????????command:?["mysql",?"-h",?"127.0.0.1",?"-e",?"SELECT?1"]
?????????initialDelaySeconds:?5??????????periodSeconds:?2??????????timeoutSeconds:?1??????-?name:?xtrabackup????????image:?gcr.io/google-samples/xtrabackup:1.0????????ports:
???????-?name:?xtrabackup??????????containerPort:?3307????????command:
???????-?bash????????-?"-c"
???????-?|
?????????set?-ex
?????????cd?/var/lib/mysql??????????#?Determine?binlog?position?of?cloned?data,?if?any.
?????????if?[[?-f?xtrabackup_slave_info?]];?then????????????#?XtraBackup?already?generated?a?partial?"CHANGE?MASTER?TO"?query
???????????#?because?we're?cloning?from?an?existing?slave.
???????????mv?xtrabackup_slave_info?change_master_to.sql.in????????????#?Ignore?xtrabackup_binlog_info?in?this?case?(it's?useless).
???????????rm?-f?xtrabackup_binlog_info
?????????elif?[[?-f?xtrabackup_binlog_info?]];?then????????????#?We're?cloning?directly?from?master.?Parse?binlog?position.
???????????[[?`cat?xtrabackup_binlog_info`?=~?^(.*?)[[:space:]]+(.*?)$?]]?||?exit?1
???????????rm?xtrabackup_binlog_info
???????????echo?"CHANGE?MASTER?TO?MASTER_LOG_FILE='${BASH_REMATCH[1]}',\??????????????????MASTER_LOG_POS=${BASH_REMATCH[2]}"?>?change_master_to.sql.in
?????????fi??????????#?Check?if?we?need?to?complete?a?clone?by?starting?replication.
?????????if?[[?-f?change_master_to.sql.in?]];?then
???????????echo?"Waiting?for?mysqld?to?be?ready?(accepting?connections)"
???????????until?mysql?-h?127.0.0.1?-e?"SELECT?1";?do?sleep?1;?done
???????????echo?"Initializing?replication?from?clone?position"
???????????#?In?case?of?container?restart,?attempt?this?at-most-once.
???????????mv?change_master_to.sql.in?change_master_to.sql.orig
???????????mysql?-h?127.0.0.1??? Erstellen Sie eine Klasse und stellen Sie sie mit dem Befehl bereit: <code>$ kubectl create -f storage-class.yaml</code>. ????Als n?chstes erstellen wir eine Konfigurationszuordnung, die einige Variablen angibt, die in der MySQL-Konfigurationsdatei festgelegt sind. Diese unterschiedlichen Konfigurationen werden vom Pod selbst ausgew?hlt, bieten uns aber auch eine bequeme M?glichkeit, potenzielle Konfigurationsvariablen zu verwalten. ????Erstellen Sie eine YAML-Datei mit dem Namen <code>mysql-configmap.yaml</code>, um die Konfiguration wie folgt zu verwalten: ??<pre class="brush:php;toolbar:false">#?wordpress.yamlapiVersion:?v1kind:?Servicemetadata:
?name:?wordpress??labels:
???app:?wordpressspec:
?ports:
???-?port:?80??selector:
???app:?wordpress????tier:?frontend??type:?LoadBalancer---apiVersion:?v1kind:?PersistentVolumemetadata:
?name:?nfsspec:
?capacity:
???storage:?20G??accessModes:
???-?ReadWriteMany??nfs:
???#?FIXME:?use?the?right?IP
???server:?<ip>????path:?"/"---apiVersion:?v1kind:?PersistentVolumeClaimmetadata:
?name:?nfsspec:
?accessModes:
???-?ReadWriteMany??storageClassName:?""
?resources:
???requests:
?????storage:?20G---apiVersion:?apps/v1beta1?#?for?versions?before?1.8.0?use?apps/v1beta1kind:?Deploymentmetadata:
?name:?wordpress??labels:
???app:?wordpressspec:
?selector:
???matchLabels:
?????app:?wordpress??????tier:?frontend??strategy:
???type:?Recreate??template:
???metadata:
?????labels:
???????app:?wordpress????????tier:?frontend????spec:
?????containers:
?????-?image:?wordpress:4.9-apache????????name:?wordpress????????env:
???????-?name:?WORDPRESS_DB_HOST??????????value:?mysql????????-?name:?WORDPRESS_DB_PASSWORD??????????value:?""
???????ports:
???????-?containerPort:?80??????????name:?wordpress????????volumeMounts:
???????-?name:?wordpress-persistent-storage??????????mountPath:?/var/www/html??????volumes:
?????-?name:?wordpress-persistent-storage????????persistentVolumeClaim:
???????????claimName:?nfs</ip>
??Erstellen Sie configmap
und verwenden Sie den Befehl: $ kubectl create - f mysql-configmap.yaml
, um es bereitzustellen. ????Als n?chstes m?chten wir Dienste einrichten, damit MySQL-Pods miteinander kommunizieren k?nnen und unsere WordPress-Pods über mysql-services.yaml
mit MySQL kommunizieren k?nnen. Dadurch wird auch der Dienst-Load-Balancer für den MySQL-Dienst gestartet. ??rrreee??Mit dieser Service-Deklaration haben wir den Grundstein für die Implementierung eines Multi-Write- und Multi-Read-MySQL-Instanzclusters gelegt. Diese Konfiguration ist notwendig, da jede WordPress-Instanz in die Datenbank schreiben darf und daher jeder Knoten zum Lesen und Schreiben bereit sein muss. ????Führen Sie den Befehl $ kubectl create -f mysql-services.yaml
aus, um den oben genannten Dienst zu erstellen. ????Bis zu diesem Punkt haben wir die Volume-Deklarationsspeicherklasse erstellt, die persistente Festplatten an alle Container weitergibt, die sie anfordern, wir haben die configmap
konfiguriert, einige Variablen in der MySQL-Konfigurationsdatei festgelegt und ein Netzwerk erstellt Der Layer-Dienst ist für den Lastenausgleich von Anforderungen an den MySQL-Server konfiguriert. Das Obige ist nur ein Framework zum Vorbereiten von Stateful-Sets. Wo der MySQL-Server tats?chlich l?uft, werden wir als n?chstes weiter diskutieren. ??配置有狀態(tài)集的MySQL
本節(jié)中,我們將編寫一個YAML配置文件應用于使用了狀態(tài)集的MySQL實例。
我們先定義我們的狀態(tài)集:
1, 創(chuàng)建三個pods并將它們注冊到MySQL服務上。
2, 按照下列模版定義每個pod:
? 為主機MySQL服務器創(chuàng)建初始化容器,命名為init-mysql
.
? ?給這個容器使用mysql:5.7鏡像
? ?運行一個bash腳本來啟動xtrabackup
? ?為配置文件和configmap
掛載兩個新卷
3, 為主機MySQL服務器創(chuàng)建初始化容器,命名為clone-mysql
.
? ?為該容器使用Google Cloud Registry的xtrabackup:1.0
鏡像
? 運行bash腳本來克隆上一個同級的現(xiàn)有xtrabackups
? ?為數(shù)據(jù)和配置文件掛在兩個新卷
? ?該容器有效地托管克隆的數(shù)據(jù),便于新的附屬容器可以獲取它
4, 為附屬MySQL服務器創(chuàng)建基本容器
? ?創(chuàng)建一個MySQL附屬容器,配置它連接到MySQL主機
? ?創(chuàng)建附屬xtrabackup
容器,配置它連接到xtrabackup主機
5, 創(chuàng)建一個卷聲明模板來描述每個卷,每個卷是一個10GB的持久磁盤
下面的配置文件定義了MySQL集群的主節(jié)點和附屬節(jié)點的行為,提供了運行附屬客戶端的bash配置,并確保在克隆之前主節(jié)點能夠正常運行。附屬節(jié)點和主節(jié)點分別獲得他們自己的10GB卷,這是他們在我們之前定義的持久卷存儲類中請求的。
apiVersion:?apps/v1beta1kind:?StatefulSetmetadata: ?name:?mysqlspec: ?selector: ???matchLabels: ?????app:?mysql??serviceName:?mysql??replicas:?3??template: ???metadata: ?????labels: ???????app:?mysql????spec: ?????initContainers: ?????-?name:?init-mysql????????image:?mysql:5.7????????command: ???????-?bash????????-?"-c" ???????-?| ?????????set?-ex??????????#?Generate?mysql?server-id?from?pod?ordinal?index. ?????????[[?`hostname`?=~?-([0-9]+)$?]]?||?exit?1 ?????????ordinal=${BASH_REMATCH[1]} ?????????echo?[mysqld]?>?/mnt/conf.d/server-id.cnf??????????#?Add?an?offset?to?avoid?reserved?server-id=0?value. ?????????echo?server-id=$((100?+?$ordinal))?>>?/mnt/conf.d/server-id.cnf??????????#?Copy?appropriate?conf.d?files?from?config-map?to?emptyDir. ?????????if?[[?$ordinal?-eq?0?]];?then ???????????cp?/mnt/config-map/master.cnf?/mnt/conf.d/ ?????????else ???????????cp?/mnt/config-map/slave.cnf?/mnt/conf.d/ ?????????fi????????volumeMounts: ???????-?name:?conf??????????mountPath:?/mnt/conf.d????????-?name:?config-map??????????mountPath:?/mnt/config-map??????-?name:?clone-mysql????????image:?gcr.io/google-samples/xtrabackup:1.0????????command: ???????-?bash????????-?"-c" ???????-?| ?????????set?-ex??????????#?Skip?the?clone?if?data?already?exists. ?????????[[?-d?/var/lib/mysql/mysql?]]?&&?exit?0??????????#?Skip?the?clone?on?master?(ordinal?index?0). ?????????[[?`hostname`?=~?-([0-9]+)$?]]?||?exit?1 ?????????ordinal=${BASH_REMATCH[1]} ?????????[[?$ordinal?-eq?0?]]?&&?exit?0??????????#?Clone?data?from?previous?peer. ?????????ncat?--recv-only?mysql-$(($ordinal-1)).mysql?3307?|?xbstream?-x?-C?/var/lib/mysql??????????#?Prepare?the?backup. ?????????xtrabackup?--prepare?--target-dir=/var/lib/mysql????????volumeMounts: ???????-?name:?data??????????mountPath:?/var/lib/mysql??????????subPath:?mysql????????-?name:?conf??????????mountPath:?/etc/mysql/conf.d??????containers: ?????-?name:?mysql????????image:?mysql:5.7????????env: ???????-?name:?MYSQL_ALLOW_EMPTY_PASSWORD??????????value:?"1" ???????ports: ???????-?name:?mysql??????????containerPort:?3306????????volumeMounts: ???????-?name:?data??????????mountPath:?/var/lib/mysql??????????subPath:?mysql????????-?name:?conf??????????mountPath:?/etc/mysql/conf.d????????resources: ?????????requests: ???????????cpu:?500m????????????memory:?1Gi????????livenessProbe: ?????????exec: ???????????command:?["mysqladmin",?"ping"] ?????????initialDelaySeconds:?30??????????periodSeconds:?10??????????timeoutSeconds:?5????????readinessProbe: ?????????exec: ???????????#?Check?we?can?execute?queries?over?TCP?(skip-networking?is?off). ???????????command:?["mysql",?"-h",?"127.0.0.1",?"-e",?"SELECT?1"] ?????????initialDelaySeconds:?5??????????periodSeconds:?2??????????timeoutSeconds:?1??????-?name:?xtrabackup????????image:?gcr.io/google-samples/xtrabackup:1.0????????ports: ???????-?name:?xtrabackup??????????containerPort:?3307????????command: ???????-?bash????????-?"-c" ???????-?| ?????????set?-ex ?????????cd?/var/lib/mysql??????????#?Determine?binlog?position?of?cloned?data,?if?any. ?????????if?[[?-f?xtrabackup_slave_info?]];?then????????????#?XtraBackup?already?generated?a?partial?"CHANGE?MASTER?TO"?query ???????????#?because?we're?cloning?from?an?existing?slave. ???????????mv?xtrabackup_slave_info?change_master_to.sql.in????????????#?Ignore?xtrabackup_binlog_info?in?this?case?(it's?useless). ???????????rm?-f?xtrabackup_binlog_info ?????????elif?[[?-f?xtrabackup_binlog_info?]];?then????????????#?We're?cloning?directly?from?master.?Parse?binlog?position. ???????????[[?`cat?xtrabackup_binlog_info`?=~?^(.*?)[[:space:]]+(.*?)$?]]?||?exit?1 ???????????rm?xtrabackup_binlog_info ???????????echo?"CHANGE?MASTER?TO?MASTER_LOG_FILE='${BASH_REMATCH[1]}',\??????????????????MASTER_LOG_POS=${BASH_REMATCH[2]}"?>?change_master_to.sql.in ?????????fi??????????#?Check?if?we?need?to?complete?a?clone?by?starting?replication. ?????????if?[[?-f?change_master_to.sql.in?]];?then ???????????echo?"Waiting?for?mysqld?to?be?ready?(accepting?connections)" ???????????until?mysql?-h?127.0.0.1?-e?"SELECT?1";?do?sleep?1;?done ???????????echo?"Initializing?replication?from?clone?position" ???????????#?In?case?of?container?restart,?attempt?this?at-most-once. ???????????mv?change_master_to.sql.in?change_master_to.sql.orig ???????????mysql?-h?127.0.0.1?<p>將該文件存為<code>mysql-statefulset.yaml</code>,輸入<code>kubectl="" create="" -f="" mysql-statefulset.yaml</code>并讓kubernetes部署你的數(shù)據(jù)庫。<br>現(xiàn)在當你調(diào)用<code>$="" kubectl="" get="" pods</code>,你應該看到3個pods啟動或者準備好,其中每個pod上都有兩個容器。主節(jié)點pod表示為mysql-0,而附屬的pods為<code>mysql-1</code>和<code>mysql-2</code>.讓pods執(zhí)行幾分鐘來確保<code>xtrabackup</code>服務在pod之間正確同步,然后進行wordpress的部署。<br>您可以檢查單個容器的日志來確認沒有錯誤消息拋出。 查看日志的命令為<code>$="" logs="" <container_name></container_name></code></p><p>主節(jié)點<code>xtrabackup</code>容器應顯示來自附屬的兩個連接,并且日志中不應該出現(xiàn)任何錯誤。</p><h2>部署高可用的WordPress</h2><p>整個過程的最后一步是將我們的WordPress pods部署到集群上。為此我們希望為WordPress的服務和部署進行定義。</p><p>為了讓WordPress實現(xiàn)高可用,我們希望每個容器運行時都是完全可替換的,這意味著我們可以終止一個,啟動另一個而不需要對數(shù)據(jù)或服務可用性進行修改。我們也希望能夠容忍至少一個容器的失誤,有一個冗余的容器負責處理slack。</p><p>WordPress將重要的站點相關(guān)數(shù)據(jù)存儲在應用程序目錄<code>/var/www/html</code>中。對于要為同一站點提供服務的兩個WordPress實例,該文件夾必須包含相同的數(shù)據(jù)。</p><p>當運行高可用WordPress時,我們需要在實例之間共享<code>/var/www/html</code>文件夾,因此我們定義一個NGS服務作為這些卷的掛載點。<br>下面是設(shè)置NFS服務的配置,我提供了純英文的版本:</p><p><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/image/456/243/673/1623137239811988.png" class="lazy" title="1623137239811988.png" alt="So führen Sie hochverfügbares WordPress und MySQL auf Kubernetes aus"></p><p><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/image/229/961/277/1623137243449231.png" class="lazy" title="1623137243449231.png" alt="So führen Sie hochverfügbares WordPress und MySQL auf Kubernetes aus"></p><p><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/image/737/299/982/1623137248223155.png" class="lazy" title="1623137248223155.png" alt="So führen Sie hochverfügbares WordPress und MySQL auf Kubernetes aus"></p><p><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/image/282/959/213/1623137253150095.png" class="lazy" title="1623137253150095.png" alt="So führen Sie hochverfügbares WordPress und MySQL auf Kubernetes aus"></p><p>使用指令<code>$ kubectl create -f nfs.yaml</code>部署NFS服務?,F(xiàn)在,我們需要運行<code>$ kubectl describe services nfs-server</code>獲得IP地址,這在后面會用到。</p><p>注意:將來,我們可以使用服務名稱講這些綁定在一起,但現(xiàn)在你需要對IP地址進行硬編碼。</p><pre class="brush:php;toolbar:false">#?wordpress.yamlapiVersion:?v1kind:?Servicemetadata: ?name:?wordpress??labels: ???app:?wordpressspec: ?ports: ???-?port:?80??selector: ???app:?wordpress????tier:?frontend??type:?LoadBalancer---apiVersion:?v1kind:?PersistentVolumemetadata: ?name:?nfsspec: ?capacity: ???storage:?20G??accessModes: ???-?ReadWriteMany??nfs: ???#?FIXME:?use?the?right?IP ???server:?<ip>????path:?"/"---apiVersion:?v1kind:?PersistentVolumeClaimmetadata: ?name:?nfsspec: ?accessModes: ???-?ReadWriteMany??storageClassName:?"" ?resources: ???requests: ?????storage:?20G---apiVersion:?apps/v1beta1?#?for?versions?before?1.8.0?use?apps/v1beta1kind:?Deploymentmetadata: ?name:?wordpress??labels: ???app:?wordpressspec: ?selector: ???matchLabels: ?????app:?wordpress??????tier:?frontend??strategy: ???type:?Recreate??template: ???metadata: ?????labels: ???????app:?wordpress????????tier:?frontend????spec: ?????containers: ?????-?image:?wordpress:4.9-apache????????name:?wordpress????????env: ???????-?name:?WORDPRESS_DB_HOST??????????value:?mysql????????-?name:?WORDPRESS_DB_PASSWORD??????????value:?"" ???????ports: ???????-?containerPort:?80??????????name:?wordpress????????volumeMounts: ???????-?name:?wordpress-persistent-storage??????????mountPath:?/var/www/html??????volumes: ?????-?name:?wordpress-persistent-storage????????persistentVolumeClaim: ???????????claimName:?nfs</ip>
我們現(xiàn)在創(chuàng)建了一個持久卷聲明,和我們之前創(chuàng)建的NFS服務建立映射,然后將卷附加到WordPress pod上,即/var/www/html
根目錄,這也是WordPress安裝的地方。這里保留了集群中WordPress pods的所有安裝和環(huán)境。有了這些配置,我們就可以對任何WordPress節(jié)點進行啟動和拆除,而數(shù)據(jù)能夠留下來。因為NFS服務需要不斷使用物理卷,該卷將保留下來,并且不會被回收或錯誤分配。
Verwenden Sie den Befehl $ kubectl create -f wordpress.yaml
, um eine WordPress-Instanz bereitzustellen. Bei der Standardbereitstellung wird nur eine WordPress-Instanz ausgeführt. Sie k?nnen den Befehl $ kubectl scale --replicas=<number of="" replicas=""></number>
$ kubectl create -f wordpress.yaml
部署WordPress實例。默認部署只會運行一個WordPress實例,可以使用指令$ kubectl scale --replicas=<number of="" replicas=""></number>
deployment/wordpress
擴展WordPress實例數(shù)量。
要獲得WordPress服務負載均衡器的地址,你需要輸入$ kubectl get services wordpress
并從結(jié)果中獲取EXTERNAL-IP字段來導航到WordPress。
彈性測試
OK,現(xiàn)在我們已經(jīng)部署好了服務,那我們來拆除一下它們,看看我們的高可用架構(gòu)如何處理這些混亂。在這種部署方式中,唯一剩下的單點故障就是NFS服務(原因總結(jié)在文末結(jié)論中)。你應該能夠測試其他任何的服務來了解應用程序是如何響應的?,F(xiàn)在我已經(jīng)啟動了WordPress服務的三個副本,以及MySQL服務中的一個主兩個附屬節(jié)點。
首先,我們先kill掉其他而只留下一個WordPress節(jié)點,來看看應用如何響應:$ kubectl scale --replicas=1 deployment/wordpress
現(xiàn)在我們應該看到WordPress部署的pod數(shù)量有所下降。$ kubectl get pods
應該能看到WordPress pods的運行變成了1/1。
點擊WordPress服務IP,我們將看到與之前一樣的站點和數(shù)據(jù)庫。如果要擴展復原,可以使用$ kubectl scale --replicas=3 deployment/wordpress
再一次,我們可以看到數(shù)據(jù)包留在了三個實例中。
下面測試MySQL的狀態(tài)集,我們使用指令縮小備份的數(shù)量:$ kubectl scale statefulsets mysql --replicas=1
我們會看到兩個附屬從該實例中丟失,如果主節(jié)點在此時丟失,它所保存的數(shù)據(jù)將保存在GCE持久磁盤上。不過就必須手動從磁盤恢復數(shù)據(jù)。
如果所有三個MySQL節(jié)點都關(guān)閉了,當新節(jié)點出現(xiàn)時就無法復制。但是,如果一個主節(jié)點發(fā)生故障,一個新的主節(jié)點就會自動啟動,并且通過xtrabackup重新配置來自附屬節(jié)點的數(shù)據(jù)。因此,在運行生產(chǎn)數(shù)據(jù)庫時,我不建議以小于3的復制系數(shù)來運行。在結(jié)論段中,我們會談談針對有狀態(tài)數(shù)據(jù)有什么更好的解決方案,因為Kubernetes并非真正是為狀態(tài)設(shè)計的。
結(jié)論和建議
到現(xiàn)在為止,你已經(jīng)完成了在Kubernetes構(gòu)建并部署高可用WordPress和MySQL的安裝!
不過盡管取得了這樣的效果,你的研究之旅可能還遠沒有結(jié)束。可能你還沒注意到,我們的安裝仍然存在著單點故障:NFS服務器在WordPress pods之間共享/var/www/html
deployment/wordpress Skalieren Sie die Anzahl der WordPress-Instanzen.
Um die Adresse des WordPress-Services-Load-Balancers zu erhalten, müssen Sie $ kubectl get services wordpress
Resilienztests
OK, jetzt, da wir die Dienste bereitgestellt haben, lassen Sie uns sie abrei?en und sehen, wie unsere Hochverfügbarkeitsarchitektur mit dem Chaos umgeht. Bei dieser Bereitstellung ist der NFS-Dienst der einzige verbleibende Single Point of Failure (aus Gründen, die in der Schlussfolgerung am Ende des Artikels zusammengefasst sind). Sie sollten jeden anderen Dienst testen k?nnen, um zu sehen, wie die Anwendung reagiert. Jetzt habe ich drei Replikate des WordPress-Dienstes gestartet, sowie einen Master- und zwei Slave-Knoten des MySQL-Dienstes. Lassen Sie uns zun?chst die anderen t?ten und nur einen WordPress-Knoten belassen, um zu sehen, wie die Anwendung reagiert.: $ kubectl Scale --replicas=1 Deployment/Wordpress
Jetzt sollten wir die Anzahl der Pods bei der WordPress-Bereitstellung sehen hat abgenommen. $ kubectl get pods
Sie sollten sehen, dass sich die Ausführung von WordPress-Pods auf 1/1 ge?ndert hat.
Klicken Sie auf die WordPress-Dienst-IP und wir sehen die gleiche Website und Datenbank wie zuvor. Wenn Sie die Wiederherstellung skalieren m?chten, k?nnen Sie $ kubectl scale --replicas=3bereitstellung/wordpress
verwenden. Auch hier k?nnen wir sehen, dass die Pakete in drei Instanzen übrig bleiben.