# Headless Service。类似绑定了mysql-0的IP地址# 通过为 Pod 分配 DNS 记录来固定它的拓扑状态,比如“mysql-0.mysql”和“mysql-1.mysql”这样的 DNS 名字# 其中,编号为 0 的节点就是我们的主节点# 写请求,则必须直接以 DNS 记录的方式访问到 MySQL 的主节点apiVersion: v1
kind: Service
metadata:name: mysql
labels:app: mysql
spec:ports:-name: mysql
port:3306clusterIP: None
selector:app: mysql
---# 常规的 Service。用于负载均衡# 所有用户的读请求,都必须访问第二个 Service 被自动分配的 DNS 记录# 即:“mysql-read”(当然,也可以访问这个 Service 的 VIP)# 读请求就可以被转发到任意一个 MySQL 的主节点或者从节点上apiVersion: v1
kind: Service
metadata:name: mysql-read
labels:app: mysql
spec:ports:-name: mysql
port:3306selector:app: mysql
创建service资源
kubectl apply -f mysql-services.yaml
StatefulSet
mysql-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:name: mysql
spec:selector:# 这个 StatefulSet 要管理的 Pod 必须携带 app=mysql 标签# 它声明要使用的 Headless Service 的名字是:mysqlmatchLabels:app: mysql
app.kubernetes.io/name: mysql
serviceName: mysql
# 这个 StatefulSet 的 replicas 值是 3,表示它定义的 MySQL 集群有三个节点# 一个 Master 节点,两个 Slave 节点replicas:3template:metadata:labels:app: mysql
app.kubernetes.io/name: mysql
spec:# InitContainer 应该是排头兵,做了一系列的准备工作:确定M/S角色、拷贝配置文件、挂载存储卷# 当 InitContainer 复制完配置文件退出后,后面启动的 MySQL 容器只需要直接声明挂载这个名叫 conf 的 Volume# 它所需要的.cnf 配置文件已经出现在里面了initContainers:-name: init-mysql
image: mysql:5.7command:- bash
-"-c"-|
set -ex
# 从Pod的序号, 生成server-id
# 通过这个序号,判断当前 Pod 到底是 Master 节点(即:序号为 0)还是 Slave 节点(即:序号不为 0)
[[ $HOSTNAME =~ -([0-9]+)$ ]] || exit 1
ordinal=${BASH_REMATCH[1]}
echo [mysqld] > /mnt/conf.d/server-id.cnf
# 由于server-id=0有特殊含义, 我们给ID加一个100来避开它
echo server-id=$((100 + $ordinal)) >> /mnt/conf.d/server-id.cnf
# 如果Pod序号是0, 说明它是Master节点, 从ConfigMap里把Master的配置文件拷贝到/mnt/conf.d/目录. 否则,拷贝Slave的配置文件
if [[ $ordinal -eq 0 ]]; then
cp /mnt/config-map/primary.cnf /mnt/conf.d/
else
cp /mnt/config-map/replica.cnf /mnt/conf.d/
fi volumeMounts:# 而文件拷贝的目标目录,即容器里的 /mnt/conf.d/ 目录# 对应的则是一个名叫 conf 的、emptyDir 类型的 Volume-name: conf
mountPath: /mnt/conf.d
# ConfigMap 里保存的内容,就会以文件的方式出现在它的 /mnt/config-map 目录-name: config