我們一起聊聊K8s定時(shí)備份MySQL并發(fā)送到指定郵箱
一、背景:
一開(kāi)始的初衷是,想寫(xiě)一個(gè)腳本來(lái)監(jiān)控服務(wù)器的高占用率進(jìn)程并通過(guò)郵件發(fā)送給我,然后突發(fā)奇想,可以使用這種方式來(lái)備份我的數(shù)據(jù)庫(kù),開(kāi)始動(dòng)手!
二、設(shè)計(jì)思路:
通過(guò)編寫(xiě)Shell腳本,調(diào)用Linux的mail工具,MySQLDump的方式來(lái)保存數(shù)據(jù)庫(kù)的sql文件,通過(guò)Mail工具添加到附件,最后發(fā)送到我的郵箱。
三、編寫(xiě)啟動(dòng)腳本
首先我們來(lái)編寫(xiě)一個(gè)啟動(dòng)腳本 為了方便以后的個(gè)性化配置,我們將腳本中的變量都提取到一個(gè)application.yml文件中,文件如下:
RUNTIME: 084900
HOST: 172.16.1.2
USER: root
PORT: 3306
PASSWORD: 123456
DATABASE: dean
TARGETMAIL: deanmr@qq.com
接下來(lái)我們來(lái)寫(xiě)一下shell腳本,邏輯也很簡(jiǎn)單,當(dāng)前時(shí)間與啟動(dòng)時(shí)間相同時(shí),則調(diào)用sendmail函數(shù)發(fā)送郵件
#!/bin/bash
RUNTIME=$(cat ./application.yml | grep RUNTIME| awk '{print $2}')
HOST=$(cat ./application.yml | grep HOST| awk '{print $2}')
USER=$(cat ./application.yml | grep USER| awk '{print $2}')
PORT=$(cat ./application.yml | grep PORT| awk '{print $2}')
PASSWORD=$(cat ./application.yml | grep PASSWORD| awk '{print $2}')
DATABASE=$(cat ./application.yml | grep DATABASE| awk '{print $2}')
TARGETMAIL=$(cat ./application.yml | grep TARGETMAIL| awk '{print $2}')
function sendmail(){
echo -e "mysqlbak_$CURRENT_TIME" |mail -s "mysqlbak_$CURRENT_TIME" -a $DATABASE.sql $TARGETMAIL
sleep 1
}
while true
do
CURRENT_TIME=$(date +%H%M%S)
if [ $CURRENT_TIME = $RUNTIME ];then
echo "starting bak mysql database"
sendmail
continue
else
echo $CURRENT_TIME
sleep 1
fi
done
四、構(gòu)建鏡像
因?yàn)槲覀冏詈笠诺絢8s平臺(tái)上的,所以我們要構(gòu)建一個(gè)鏡像,在構(gòu)建鏡像之前,請(qǐng)先把a(bǔ)pplication.yml demo.sh Dockerfile放在同一目錄下 Dockerfile如下:PS:添加了mysql的客戶(hù)端,郵件mail客戶(hù)端
FROM centos
RUN mkdir /app && yum install -y mysql.x86_64 sendmail mailx libreport-plugin-mailx
WORKDIR /app
COPY demo.sh .
COPY application.yml .
CMD ["/bin/sh","demo.sh"]
使用docker build命令構(gòu)建鏡像,要記得加一下最后的點(diǎn)
docker build -t mysqlmail-bak:1.0.1 .
五、添加邊車(chē)容器
邊車(chē)容器(sidecar):邊車(chē)容器就是與主容器一起在一個(gè)pod中運(yùn)行的容器,為業(yè)務(wù)容器賦能,共享一個(gè)網(wǎng)絡(luò)空間,所以可以用127.0.0.1:3306連接主容器的數(shù)據(jù)庫(kù)。
5.1 創(chuàng)建配置文件
為了方便調(diào)試,我把里面的shell腳本也掛載出來(lái)。創(chuàng)建兩個(gè)configmap,分別對(duì)應(yīng)容器內(nèi)的配置文件與shell腳本,后面如果不需要調(diào)試可以取消mysqlshell的掛載。
apiVersion: v1
kind: ConfigMap
metadata:
name: mysqlmail-conf
namespace: dean
data:
application.yml: |
RUNTIME: 105800
HOST: 127.0.0.1
USER: root
PASSWORD: 123456
DATABASE: dean
TARGETMAIL: deanmr@qq.com
---
apiVersion: v1
kind: ConfigMap
metadata:
name: mysqlmail-shell
namespace: dean
data:
demo.sh: |
#!/bin/bash
RUNTIME=$(cat ./application.yml | grep RUNTIME| awk '{print $2}')
HOST=$(cat ./application.yml | grep HOST| awk '{print $2}')
USER=$(cat ./application.yml | grep USER| awk '{print $2}')
PASSWORD=$(cat ./application.yml | grep PASSWORD| awk '{print $2}')
DATABASE=$(cat ./application.yml | grep DATABASE| awk '{print $2}')
TARGETMAIL=$(cat ./application.yml | grep TARGETMAIL| awk '{print $2}')
function sendmail(){
mysqldump -h$HOST -u$USER -p$PASSWORD --complete-insert --skip-add-drop-table --column-statistics=0 --hex-blob $DATABASE > $DATABASE.sql
echo -e "mysqlbak_$CURRENT_TIME" |mail -s "mysqlbak_$CURRENT_TIME" -a $DATABASE.sql $TARGETMAIL
sleep 1
}
while true
do
CURRENT_TIME=$(date +%H%M%S)
if [ $CURRENT_TIME = $RUNTIME ];then
echo "starting bak mysql database"
sendmail
continue
else
echo $CURRENT_TIME
sleep 1
fi
done
5.2 創(chuàng)建有狀態(tài)服務(wù)部署文件
我們的deploy文件使用的是上篇文章中創(chuàng)建的mysql有狀態(tài)服務(wù)的yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
namespace: dean
spec:
serviceName: mysql-service
selector:
matchLabels:
app: mysql
replicas: 1
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysqlmail-bak
imagePullPolicy: IfNotPresent
image: mysqlmail-bak:1.0.1
volumeMounts:
- name: mysqlmail-conf
mountPath: /app/application.yml
subPath: application.yml
- name: mysqlmail-shell
mountPath: /app/demo.sh
subPath: demo.sh
- name: mysql-pod
imagePullPolicy: IfNotPresent
image: mysql:5.7
env:
- name: MYSQL_ROOT_PASSWORD
value: "123456"
ports:
- containerPort: 3306
name: msyql-listin
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
subPath: mysql-data
- name: mysql-conf
mountPath: /etc/mysql/conf.d/my.cnf
subPath: my.cnf
volumes:
- name: mysql-data
hostPath:
path: /data/mysql
- name: mysql-conf
configMap:
name: mysql-conf
- name: mysqlmail-conf
configMap:
name: mysqlmail-conf
- name: mysqlmail-shell
configMap:
name: mysqlmail-shell
---
apiVersion: v1
kind: Service
metadata:
name: mysql-service
namespace: dean
labels:
app: mysql
spec:
ports:
- targetPort: 3306
port: 3306
clusterIP: None
selector:
app: mysql
六、測(cè)試
我們上面給他定的時(shí)間是RUNTIME: 105800,上海時(shí)區(qū)也就是18點(diǎn)58分,我們來(lái)看一下效果 查看日志, 注意:當(dāng)一個(gè)pod包含多個(gè)容器時(shí),要使用 -c 參數(shù)指定查看哪個(gè)容器
[root@VM-24-15-centos solo]# kubectl logs -n solo mysql-0 -c mysqlmail-bak | grep mysql -C 5
105755
105756
105757
105758
105759
starting bak mysql database
mysqldump: [Warning] Using a password on the command line interface can be insecure.
105801
105802
從日志可以看到,郵件已經(jīng)發(fā)送成功了!我們來(lái)去郵箱看一下,發(fā)現(xiàn)也已經(jīng)成功了,至此我們的實(shí)驗(yàn)完美完成!