k8S中的MySQL如何扩容_Kubernetes的etcd多节点扩容实战技巧
在《Kubernetes探秘-多master节点容错部署》中介绍了通过部署多个主节点来提高Kubernetes的容错能力。其中,最为关键是存储集群控制数据的etcd服务必须在多个副节点间实时同步,而kube-apiserver通过keepalived进行IP主地址的切换。在《Kubernetes探秘-etcd节点和实例扩容》中已经详细介绍了etcd多节点扩容的步骤,但在实际操作中发现,必需要遵循一
在《Kubernetes探秘-多master节点容错部署》中介绍了通过部署多个主节点来提高Kubernetes的容错能力。其中,最为关键是存储集群控制数据的etcd服务必须在多个副节点间实时同步,而kube-apiserver通过keepalived进行IP主地址的切换。在《Kubernetes探秘-etcd节点和实例扩容》中已经详细介绍了etcd多节点扩容的步骤,但在实际操作中发现,必需要遵循一定的操作顺序、注意细节,否则会导致扩容失败,而且很容易造成整个etcd集群无法访问。这里将etcd集群扩容的实际操作经验整理出来分享。
注意:
因为扩容过程中,需要将原来的etcd库删除,会导致kubernetes集群的master节点信息丢失。
因此在扩容之前,建议使用etcdctl snapshot命令进行备份。或者,另建etcd节点,将原来的数据传送过去。
如果出现“ID mismatch”等错误,整个etcd集群将无法连接,后续的member remove等操作都无法进行,只能全部废弃。
可以将/var/lib/etcd目录和etcd容器实例全部删除。重启动kubelet服务后可以恢复,但是里面存储的数据将会全部丢失。
提示:
在宿主机安装etcd-client,就可以直接在宿主机操作容器中的etcd服务,需要提供证书参数(参见下面的命令实例)。
1、生成证书文件
全部使用https进行etcd集群的连接,需要生成和配置证书,可以参考《Kubernetes探秘-etcd节点和实例扩容》里的方法,这些证书文件需要复制到每一个节点的/etc/kubernetes/pki目录下。需要全部使用固定IP地址,在Ubuntu 18.06中使用 Netplan进行配置(参考《Ubuntu 18.04设置静态IP》),使用 sudo netplan apply让其立即生效(需要稍等会儿配置完毕)。
上传目录,示例:
sudo scp -r root@10.1.1.201:/etc/kubernetes/pki /etc/kubernetes
2、安装Kubernetes主节点
2.1 安装主节点
我们首先安装一个Kubernetes主节点,其它节点配置参数将从其衍生出来。参考:
准备工作完成后,使用下面的命令安装Kubernetes的单实例Master节点。
sudo kubeadm init --kubernetes-version=v1.13.1 --apiserver-advertise-address=10.1.1.199
因为我的机器上有多块网卡,使用 --apiserver-advertise-address=10.1.1.199 指定apiserver的服务地址,这个地址也是keepalived的虚拟IP地址(需要提前安装,参考《Keepalived快速使用》),将会在遇故障时在多个节点间自动漂移该主地址,使其它节点可以访问到。
输入 kubectl get pod --all-namespaces检查该单实例集群是否运行正常。
2.2 备份etcd数据库
主节点已经安装了一个etcd的实例,并且存放了集群运行的最基础参数。为了防止etcd集群扩容过程数据丢失,我们将其备份。具体操作参见《Kubernetes的etcd数据查看和迁移》。需要注意的是,etcd api2和api3的备份和恢复方法不同,因为从Kubernetes 1.13.0开始已经使用API3,下面介绍的都是API3的方法。
创建snapshot
ETCDCTL_API=3 etcdctl --endpoints=https://[10.1.1.202]:2379 \
--cacert=/etc/kubernetes/pki/etcd-certs/ca.pem \
--cert=/etc/kubernetes/pki/etcd-certs/client.pem \
--key=/etc/kubernetes/pki/etcd-certs/client-key.pem \
snapshot save /home/supermap/openthings/etcd$(date +%Y%m%d_%H%M%S)_snapshot.db
恢复snapshot restore:
ETCDCTL_API=3 etcdctl --endpoints=https://[10.1.1.199]:2379 \
--cacert=/etc/kubernetes/pki/etcd-certs/ca.pem \
--cert=/etc/kubernetes/pki/etcd-certs/client.pem \
--key=/etc/kubernetes/pki/etcd-certs/client-key.pem \
--data-dir=/var/lib/etcd \
--initial-advertise-peer-urls=https://10.1.1.199:2380 \
--initial-cluster=podc01=https://10.1.1.199:2380 \
--initial-cluster-token=etcd-cluster \
--name=podc01 \
snapshot restore /home/supermap/etcd_snapshot.db
上面的备份文件名可以自己起,恢复时能对上就行。
2.3 更新主节点的etcd配置参数
为什么需要更新?
集群apiserver使用地址为10.1.1.199需要在多节点漂移,本地的etcd实例使用10.1.1.201固定地址。
主节点etcd实例初始使用199地址,与最终的201不一致,这将自动生成两个不同的etcd peerID,出现“peerID mismatch”错误,引起整个etcd集群无法访问。
10.1.1.199的PeerID已写入/var/lib/etcd数据库中,只能在etcd服务可用时通过服务接口member update修改。
包括:
/var/lib/etcd目录下的数据,使用etcdctl member update命令来进行。
以及修改/etc/kubernetes/manifests/etcd.yaml配置参数,由kubelet来加载运行etcd的实例。
首先,检查etcd集群的运行状态:
ETCDCTL_API=3 etcdctl --endpoints=https://[10.1.1.199]:2379 \
--cacert=/etc/kubernetes/pki/etcd-certs/ca.pem \
--cert=/etc/kubernetes/pki/etcd-certs/client.pem \
--key=/etc/kubernetes/pki/etcd-certs/client-key.pem \
endpoint status -w table
然后,更新etcd实例的peer-urls:
ETCDCTL_API=3 etcdctl --cacert=/etc/kubernetes/pki/etcd-certs/ca.pem \
--cert=/etc/kubernetes/pki/etcd-certs/client.pem \
--key=/etc/kubernetes/pki/etcd-certs/client-key.pem \
--endpoints=https://[10.1.1.199]:2379 \
member update podc01 --peer-urls=https://10.1.1.201:2380
第三,修改etcd实例的client-urls。
此时,停止kubelet服务。
sudo systemctl stop kubelet
编辑/etc/kubernetes/manifests/etcd.yaml文件.
apiVersion: v1
kind: Pod
metadata:
annotations:
scheduler.alpha.kubernetes.io/critical-pod: ""
creationTimestamp: null
labels:
component: etcd
tier: control-plane
name: etcd
namespace: kube-system
spec:
containers:
- command:
- etcd
- --advertise-client-urls=https://10.1.1.201:2379
- --cert-file=/etc/kubernetes/pki/etcd/server.pem
- --client-cert-auth=true
- --data-dir=/var/lib/etcd
- --initial-advertise-peer-urls=https://10.1.1.201:2380
- --initial-cluster=podc01=https://10.1.1.201:2380
- --key-file=/etc/kubernetes/pki/etcd/server-key.pem
- --listen-client-urls=https://127.0.0.1:2379,https://10.1.1.201:2379
- --listen-peer-urls=https://10.1.1.201:2380
- --name=podc01
- --peer-cert-file=/etc/kubernetes/pki/etcd/peer1.pem
- --peer-client-cert-auth=true
- --peer-key-file=/etc/kubernetes/pki/etcd/peer1-key.pem
- --peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.pem
- --snapshot-count=10000
- --trusted-ca-file=/etc/kubernetes/pki/etcd/ca.pem
image: k8s.gcr.io/etcd:3.2.24
imagePullPolicy: IfNotPresent
livenessProbe:
exec:
command:
- /bin/sh
- -ec
- ETCDCTL_API=3 etcdctl --endpoints=https://[127.0.0.1]:2379 --cacert=/etc/kubernetes/pki/etcd/ca.pem
--cert=/etc/kubernetes/pki/etcd/client.pem --key=/etc/kubernetes/pki/etcd/client-key.pem
get foo
failureThreshold: 8
initialDelaySeconds: 15
timeoutSeconds: 15
name: etcd
resources: {}
volumeMounts:
- mountPath: /var/lib/etcd
name: etcd-data
- mountPath: /etc/kubernetes/pki/etcd
name: etcd-certs
hostNetwork: true
priorityClassName: system-cluster-critical
volumes:
- hostPath:
path: /etc/kubernetes/pki/etcd-certs
type: DirectoryOrCreate
name: etcd-certs
- hostPath:
path: /var/lib/etcd
type: DirectoryOrCreate
name: etcd-data
status: {}
此时,重启kubelet服务。
sudo systemctl start kubelet
检查一下etcd的服务状态:
ETCDCTL_API=3 etcdctl --endpoints=https://[10.1.1.201]:2379 --cacert=/etc/kubernetes/pki/etcd-certs/ca.pem --cert=/etc/kubernetes/pki/etcd-certs/client.pem --key=/etc/kubernetes/pki/etcd-certs/client-key.pem endpoint status -w table
注意这里的变化:--endpoints=https://[10.1.1.201]:2379,已经完成了地址切换。
2.4 修改 api-server.yaml
修改/etc/kubernetes/manifests/api-server.yaml文件,如下:
# - --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt
# - --etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt
# - --etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key
# - --etcd-servers=https://127.0.0.1:2379
- --etcd-cafile=/etc/kubernetes/pki/etcd-certs/ca.pem
- --etcd-certfile=/etc/kubernetes/pki/etcd-certs/client.pem
- --etcd-keyfile=/etc/kubernetes/pki/etcd-certs/client-key.pem
- --etcd-servers=https://10.1.1.201:2379
将上面的新的etcd服务地址配置给kube-apiserver。
重启 kubelet,如下:
#重新启动kubelet服务。
sudo systemctl restart kubelet
#查看运行的容器实例。
docker ps
#查看所有运行的容器实例。
#包含已停止的,如果etcd启动失败退出,可通过该命令查看。
docker ps -a
#查看特定容器实例的日志。
docker logs idxxxx
再次检查etcd状态:
ETCDCTL_API=3 etcdctl --endpoints=https://[10.1.1.201]:2379 \
--cacert=/etc/kubernetes/pki/etcd-certs/ca.pem \
--cert=/etc/kubernetes/pki/etcd-certs/client.pem \
--key=/etc/kubernetes/pki/etcd-certs/client-key.pem \
endpoint status -w table
检查kubernetes集群状态(kubectl get pod --all-namespaces)。
2.5 注意事项
Kubernetes的kubeadm工具安装的单节点etcd实例无法直接扩展到集群,需要修改配置参数。
任何时候(以下同)修改etcd文件时,都应该停止kubelet集群,手工终止运行的etcd实例。
否则,如果“脏”信息被写入etcd数据库,将导致etcd服务全部无法访问。
在出现“ID mismatch”错误时:
如果直接删除/var/lib/etcd的内容,将丢失Kubernetes集群的配置信息。
即便etcd集群运行成功,后续也无法访问K8s服务。
可以通过备份snapshot store来重置原始数据库。
3、扩展etcd实例到多个节点
下面将节点逐个加入(etcd节点的IP地址必须在前面的证书生成时加入)。
我使用Kubernetes的kubelet来托管etcd的运行(也可以部署为独立的系统服务,如使用systemd)。
3.1 添加为k8s工作节点
使用kubeadm join加入新的节点(将会创建kubelet基础服务,而且etcd节点和kubernetes节点同时可用)。在主节点获取添加命令,如下:
#在主节点上执行
kubeadm token create --print-join-command
3.2 复制pki证书
直接将master节点的/etc/kubernetes/pki目录复制到子节点。如下:
#在子节点上执行
sudo scp -r root@10.1.1.201:/etc/kubernetes/pki /etc/kubernetes/
其中,etcd的证书放在/etc/kubernetes/pki/etc-certs中,在下面的etcd.yaml文件将按照此设置。
3.3 停止kubelet服务
命令为:
sudo systemctl stop kubelet
如果不是第一次启动,使用docker ps查看etcd实例是否已经运行。
如果已经有etcd实例运行,使用docker rm -f idxxx将该实例彻底删除。
3.4 添加节点到etcd集群
使用etcdctl的member add命令添加节点:
#在子节点上执行,将子节点peer-urls添加到etcd集群中。
ETCDCTL_API=3 etcdctl \
--cacert=/etc/kubernetes/pki/etcd-certs/ca.pem \
--cert=/etc/kubernetes/pki/etcd-certs/client.pem \
--key=/etc/kubernetes/pki/etcd-certs/client-key.pem \
--endpoints=https://[10.1.1.201]:2379 \
member add podc02 --peer-urls=https://10.1.1.202:2380
此时,etcdctl member list查看成员为unstarted状态。命令如下:
ETCDCTL_API=3 etcdctl --endpoints=https://[10.1.1.201]:2379 \
--cacert=/etc/kubernetes/pki/etcd-certs/ca.pem \
--cert=/etc/kubernetes/pki/etcd-certs/client.pem \
--key=/etc/kubernetes/pki/etcd-certs/client-key.pem \
member list -w table
在编辑etcd.yaml过程中,保持kubelet不要启动(否则触发etcd实例启动,如果写入错误数据到etcd集群,将可能导致集群无法访问)。
3.5 复制etcd.yaml
将etcd.yaml文件放入各个子节点的/etc/kubernetes/manifests目录下,跟master节点一样,然后sudo systemctl restart kubelet重启kubelet服务,kubelet启动时将会自动启动/etc/kubernetes/manifests下的所有*.yaml实例为静态pod(静态pod在Dashboard删除时会删除当前的运行实例,然后被kubelet自动重启,不会永久删除)。
复制etcd.yaml文件,如下:
#在子节点上执行
sudo scp -r root@10.1.1.201:/etc/kubernetes/manifests/etcd.yaml /etc/kubernetes/manifests/
编辑 etcd.conf 文件,如下:
sudo nano /etc/kubernetes/manifest/etcd.yaml
内容如下:
#子节点podc02上的/etc/kubernetes/manifests/etcd.yaml
apiVersion: v1
kind: Pod
metadata:
annotations:
scheduler.alpha.kubernetes.io/critical-pod: ""
creationTimestamp: null
labels:
component: etcd
tier: control-plane
name: etcd
namespace: kube-system
spec:
containers:
- command:
- etcd
- --advertise-client-urls=https://10.1.1.202:2379
- --cert-file=/etc/kubernetes/pki/etcd/server.pem
- --client-cert-auth=true
- --data-dir=/var/lib/etcd
- --initial-advertise-peer-urls=https://10.1.1.202:2380
- --initial-cluster=podc01=https://10.1.1.201:2380,podc02=https://10.1.1.202:2380
- --initial-cluster-token=etcd-cluster
- --initial-cluster-state=existing
- --key-file=/etc/kubernetes/pki/etcd/server-key.pem
- --listen-client-urls=https://127.0.0.1:2379,https://10.1.1.202:2379
- --listen-peer-urls=https://10.1.1.202:2380
- --name=podc02
- --peer-cert-file=/etc/kubernetes/pki/etcd/peer2.pem
- --peer-client-cert-auth=true
- --peer-key-file=/etc/kubernetes/pki/etcd/peer2-key.pem
- --peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.pem
- --snapshot-count=10000
- --trusted-ca-file=/etc/kubernetes/pki/etcd/ca.pem
image: k8s.gcr.io/etcd:3.2.24
imagePullPolicy: IfNotPresent
livenessProbe:
exec:
command:
- /bin/sh
- -ec
- ETCDCTL_API=3 etcdctl --endpoints=https://[127.0.0.1]:2379 --cacert=/etc/kubernetes/pki/etcd/ca.pem
--cert=/etc/kubernetes/pki/etcd/client.pem --key=/etc/kubernetes/pki/etcd/client-key.pem
get foo
failureThreshold: 8
initialDelaySeconds: 15
timeoutSeconds: 15
name: etcd
resources: {}
volumeMounts:
- mountPath: /var/lib/etcd
name: etcd-data
- mountPath: /etc/kubernetes/pki/etcd
name: etcd-certs
hostNetwork: true
priorityClassName: system-cluster-critical
volumes:
- hostPath:
path: /etc/kubernetes/pki/etcd-certs
type: DirectoryOrCreate
name: etcd-certs
- hostPath:
path: /var/lib/etcd
type: DirectoryOrCreate
name: etcd-data
status: {}
提示:
修改的地方:
修改:本地IP地址全部设为10.1.1.202。
修改:--name=podc02
修改:--initial-cluster=podc01=https://10.1.1.201:2380,podc02=https://10.1.1.202:2380
添加:initial-cluster-token=etcd-cluster、- --initial-cluster-state=existing两个参数。
修改:证书格式为*.pem,cfssl生成的格式与kubernetes原始的有些不同,用法一样。
修改:host-path的证书目录指向到/etc/kubernetes/pki/etcd-certs。
仔细检查设置参数是否有错。
3.6 重启kubelet服务
确认etcd参数正确,现在可以启动kubelet服务了。命令为:
sudo systemctl start kubelet
使用docker ps查看etcd实例是否已经运行。
如果etcd实例未运行,使用docker ps -a查看未运行的etcd实例ID。
使用命令 docker logs idxxx 查看etcd实例的日志信息,根据信息修改etcd.yaml重新启动kubelet。
命令为:sudo systemctl restart kubelet
⚠️注意:该节点必须已有etcd的容器镜像。
参考《Kubernetes镜像的离线保存和载入》将与主节点版本一致的镜像传送到该节点。
! 参照上面的3.1-3.6方法将所有etcd集群子节点加入到集群中(注意严格按照顺序操作)。
3.7 查看etcd集群信息
可以在主机安装etcd-client,然后etcdctl可以直接连接到容器中的etcd服务。
查看etcd集群成员列表:
# etcd cluster member list
echo ""
echo "============================="
echo "+ etcd cluster member list..."
ETCDCTL_API=3 etcdctl \
--cacert=/etc/kubernetes/pki/etcd-certs/ca.pem \
--cert=/etc/kubernetes/pki/etcd-certs/client.pem \
--key=/etc/kubernetes/pki/etcd-certs/client-key.pem \
member list -w table --endpoints=https://[10.1.1.201]:2379
输出如下:
=============================
+ etcd cluster member list...
+------------------+---------+--------+-------------------------+-------------------------+
| ID | STATUS | NAME | PEER ADDRS | CLIENT ADDRS |
+------------------+---------+--------+-------------------------+-------------------------+
| 741ead392743e35 | started | podc02 | https://10.1.1.202:2380 | https://10.1.1.202:2379 |
| 72077d56570df47f | started | podc01 | https://10.1.1.201:2380 | https://10.1.1.201:2379 |
| dfc70cacefa4fbbb | started | podc04 | https://10.1.1.204:2380 | https://10.1.1.204:2379 |
| e3ecb8f6d5866785 | started | podc03 | https://10.1.1.203:2380 | https://10.1.1.203:2379 |
+------------------+---------+--------+-------------------------+-------------------------+
查看etcd集群成员状态:
# member list, local
echo ""
echo "========================="
echo "+ etcd cluster status... "
ETCDCTL_API=3 etcdctl \
--cacert=/etc/kubernetes/pki/etcd-certs/ca.pem \
--cert=/etc/kubernetes/pki/etcd-certs/client.pem \
--key=/etc/kubernetes/pki/etcd-certs/client-key.pem \
--endpoints=https://[10.1.1.201]:2379,https://[10.1.1.202]:2379,https://[10.1.1.203]:2379,https://[10.1.1.204]:2379 \
endpoint status -w table
输出如下:
=========================
+ etcd cluster status...
+---------------------------+------------------+---------+---------+-----------+-----------+------------+
| ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | RAFT TERM | RAFT INDEX |
+---------------------------+------------------+---------+---------+-----------+-----------+------------+
| https://[10.1.1.201]:2379 | 72077d56570df47f | 3.2.24 | 4.2 MB | true | 1875 | 253980 |
| https://[10.1.1.202]:2379 | 741ead392743e35 | 3.2.24 | 4.2 MB | false | 1875 | 253980 |
| https://[10.1.1.203]:2379 | e3ecb8f6d5866785 | 3.2.24 | 4.2 MB | false | 1875 | 253980 |
| https://[10.1.1.204]:2379 | dfc70cacefa4fbbb | 3.2.24 | 4.2 MB | false | 1875 | 253980 |
+---------------------------+------------------+---------+---------+-----------+-----------+------------+
3.8 修改etcd节点的api-server.yaml
修改/etc/kubernetes/manifests/api-server.yaml文件,如下:
# - --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt
# - --etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt
# - --etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key
# - --etcd-servers=https://127.0.0.1:2379
- --etcd-cafile=/etc/kubernetes/pki/etcd-certs/ca.pem
- --etcd-certfile=/etc/kubernetes/pki/etcd-certs/client.pem
- --etcd-keyfile=/etc/kubernetes/pki/etcd-certs/client-key.pem
- --etcd-servers=https://10.1.1.201:2379
将上面的新的etcd服务地址配置给kube-apiserver。
⚠️提示:
etcd集群要么一个节点,要么至少三个节点,可以对一个节点失败提供容错。
etcd集群如果只有两个节点,一个节点失败时,整个集群将无法访问,即使还有一个节点可用。
下一步:
再配合keepalived的虚拟IP漂移功能,节点故障时主IP转移到子节点上的apiserver服务,并使用本地的etcd实例访问存储。
此时,主节点的状态控制和调度功能在子节点上还没有,因此无法使用。
还需要对kube-control-manager和kube-scheduler进行多节点部署,实现状态控制和调度功能的多节点迁移,即可完整实现容错机制。
参考:
更多推荐
所有评论(0)