之前相關的文章請參考:
Docker集群管理方案Kubernetes之部署
Docker集群管理方案Kubernetes之組件
通過本文的實踐,我們可以了解一下k8s能帶給我們什么。另外,實際生產環境中mysql的主從復制考慮的事情會更多。
mysql主從復制
mysql的主從復制可以通過如下方式實現。
master
在master主機上修改配置文件,比如通常是修改my.cnf。
[mysqld] server-id=1 log-bin
在mysql上創建同步賬號并授權。
如下,創建用戶名為repl,密碼為1234567:
create user 'repl'@'%' identified by '1234567';
如下,給repl用戶授權允許同步:
grant replication slave on *.* to 'repl'@'%' identified by '1234567';
slave
同樣,在slave主機上修改配置文件。
[mysqld] server-id=2 log-bin
接著配置如下,其中x.x.x.x為master主機ip地址。
change master to master_host='x.x.x.x',master_user='repl',master_password='1234567';
注意server-id為主機標識,不能重復。
利用Docker實現主從復制
本節介紹利用Docker官網鏡像文件實現上述的各項配置,這是為了接下來k8s的使用。利用Docker實現mysql的方式有很多種,可以參考其他文章。
mysql官網Docker鏡像文件地址:https://hub.docker.com/_/mysql/
這里用的是8.0 Dockerfile,包括兩個文件Dockerfile, docker-entrypoint.sh。
-
準備master的鏡像
將Dockerfile, docker-entrypoint.sh復制一份作為master的鏡像。
在Dockerfile中添加如下:
RUN sed -i '/\[mysqld\]/a server-id=1\nlog-bin' /etc/mysql/mysql.conf.d/mysqld.cnf
在docker-entrypoint.sh中添加如下:
echo "CREATE USER '$MYSQL_REPLICATION_USER'@'%' IDENTIFIED BY '$MYSQL_REPLICATION_PASSWORD' ;" | "${mysql[@]}" echo "GRANT REPLICATION SLAVE ON *.* TO '$MYSQL_REPLICATION_USER'@'%' IDENTIFIED BY '$MYSQL_REPLICATION_PASSWORD' ;" | "${mysql[@]}" echo 'FLUSH PRIVILEGES ;' | "${mysql[@]}"
可以看到上面添加了兩個環境變量MYSQL_REPLICATION_USER和MYSQL_REPLICATION_PASSWORD,用作主從復制的賬號和密碼。
通過下面的截圖可以看到上面添加內容所在的位置。
Dockerfile.png
docker-entrypoint.sh.png -
準備slave的鏡像
將Dockerfile, docker-entrypoint.sh復制一份作為slave的鏡像。
在Dockerfile中添加如下:
RUN RAND="$(date +%s | rev | cut -c 1-2)$(echo ${RANDOM})" && sed -i '/\[mysqld\]/a server-id='$RAND'\nlog-bin' /etc/mysql/mysql.conf.d/mysqld.cnf
這里server-id用的是隨機數。
在docker-entrypoint.sh中添加如下:
echo "STOP SLAVE;" | "${mysql[@]}" echo "CHANGE MASTER TO master_host='$MYSQL_MASTER_SERVICE_HOST', master_user='$MYSQL_REPLICATION_USER', master_password='$MYSQL_REPLICATION_PASSWORD' ;" | "${mysql[@]}" echo "START SLAVE;" | "${mysql[@]}"
通過下面的截圖可以看到上面添加內容所在的位置。
Dockerfile.png
docker-entrypoint.sh.png
重要的來了,上面slave的配置中,master_host一項用的是$MYSQL_MASTER_SERVICE_HOST,這個環境變量(enviromnent variable)是由k8s生成的。
k8s的service創建后,會自動分配一個cluster ip,這個cluster ip是動態的,我們沒法直接使用或硬編碼,k8s為了service對容器的可見,生成了一組環境變量,這些環境變量用于記錄service name到cluster ip地址的映射關系,這樣容器中就可以使用這些變量來使用service。(類似的,Docker中提供了links。)
舉例:如果service的名稱為foo,則生成的環境變量如下:
FOO_SERVICE_HOST
FOO_SERVICE_PORT
更多介紹請參考k8s官方資料:http://kubernetes.io/docs/user-guide/container-environment/
- 構建鏡像并上傳至docker hub
分別構建用于mysql master和mysql slave的Docker鏡像,并上傳至docker hub,地址為https://hub.docker.com/ (這是因為當我們用k8s去做mysql集群部署的時候,k8s默認會去docker hub下載鏡像。通常在生產環境中服務器是不運行連接internet的,因此通常會搭建自己的docker hub服務器。)。
構建master鏡像
切換到master Dockerfile所在的目錄,執行命令:
docker build -t paulliu/mysql-master:0.1 .
構建slave鏡像
切換到slave Dockerfile所在的目錄,執行命令:
docker build -t paulliu/mysql-slave:0.1 .
鏡像推送
然后將構建好的鏡像文件推送到docker hub,首先使用下面的命令登陸,如果沒有注冊,需要先到官網注冊一下。
docker login
接著執行推送命令:
docke push paulliu/mysql-master:0.1
docke push paulliu/mysql-slave:0.1
如果感覺上面的一堆配置太麻煩,可以直接使用我構建好的鏡像,地址為:
https://hub.docker.com/u/paulliu/
k8s部署
終于進入到正題,接下來開始利用k8s構建mysql集群。
首先聲明,由于yaml格式的問題,沒法直接貼源代碼,只能貼截圖,見諒。
-
mysql master的部署
replication controller和service的yaml文件如下,文件名分別為mysql-master-rc.yaml和mysql-master-service.yaml。
replication controller:
mysql-master-rc.yaml.png
可以看到在env中添加了mysql需要的環境變量。
service:
mysql-master-service.yaml.png
切換到yaml文件所在目錄,執行命令以部署mysql master服務:
kubectl create -f mysql-master-rc.yaml
kubectl create -f mysql-master-service.yaml
-
mysql slave的部署
replication controller和service的yaml文件如下,文件名分別為mysql-slave-rc.yaml和mysql-slave-service.yaml。
replication controller:
mysql-slave-rc.yaml.png
service:
mysql-slave-service.yaml.png
切換到yaml文件所在目錄,執行命令以部署mysql slave服務:
kubectl create -f mysql-slave-rc.yaml
kubectl create -f mysql-slave-service.yaml
-
查看運行狀態
執行命令,查看k8s各資源的運行情況:
kubectl get pods,service,rc
我的環境的運行截圖,各資源運行正常。
k8s.png 測試mysql的主從復制
到目前為止,mysql的一主一從均運行在k8s的pod中。由于上面service創建并沒有使用type: NodePort
方式,所以service只能在kubernetes的pods中引用,外界是無法使用的。
mysql master上的操作
通過如下命令連接到pods中的容器,其中mysql-master-pe18a為pod名稱。
kubectl exec -it mysql-master-pe18a /bin/bash
接著連接本地mysql master服務器:
mysql -uroot -p
至此進入到mysql命令模式。
執行命令show master status;
查看狀態。
執行下面的命令創建數據庫以及表,以測試數據同步:
create database paul_test_sync_db; use paul_test_sync_db; create table test_tb(id int(3),name char(10)); insert into test_tb values(001,'ok');
mysql slave上的操作
按照上面相同的方式進入到mysql slave的命令行,執行以下命令:
show slave status\G;
通過該命令可以查看主從同步的情況,通常利用該命令來檢查主從配置是否有問題。
執行以下命令,可以看到剛才在master上創建的庫表已經同步過來了:
show databases; use paul_test_sync_db; select * from test_tb;
- 集群伸縮
上面僅僅是一主一從,那接下來看看如何利用k8s對從服務器進行擴展。
此處將原先的1臺從服務器擴展為3臺,執行命令:
kubectl scale rc mysql-slave --replicas=3
上面命令的意思是將名稱為mysql-slave的rc控制的pod副本數量變更為3。
執行kubectl get pods
命令可以看到擴展后的結果。
總結
本文假設你已經對kubernetes有一定了解,因此并沒有對一些命令、文件進行解釋。
本文搭建的mysql一主多從集群環境,并沒有考慮外部卷的掛載,因此當集群服務重啟后,在mysql中創建的數據庫、添加的數據會全部丟失。