应公司开发要求业务分离需要用到 ETCD 数据库,因为资源问题,也就不申请机器在虚机部署了,准备直接上容器,开发/测试/预生产都上了单节点的 ETCD
对于 ETCD 的容器化部署,官方目前只有 docker 容器的部署方式 https://etcd.io/docs/v3.6/install/ https://github.com/etcd-io/etcd/releases ,有一个 bitnami 的开源项目,它做了很多不支持 k8s 容器化的项目,其中就有 ETCD,我猛地一头就扎了进去,立马上手就部署,ETCD 起来了把连接方式给到开发就完了,我没有做任何自定义,直到那天 etcd 挂了(-_-||),我想着这上生产可不行啊,赶紧补一下 ETCD 的知识吧,先把自定义的内容先搞一搞,今天我来了
HELM 部署 ETCD
https://www.cnblogs.com/davygeek/p/8951999.html
helm 添加仓库
helm repo add bitnami https://charts.bitnami.com/bitnami
可根据 github 参数解析配置 https://github.com/bitnami/charts/tree/master/bitnami/etcd
部署集群
端口暴露修改(可选),如果没有集群外访问的需求可跳过
指定存储,我本地用了 nfs,公司 PRE 环境用了阿里云oss,默认申请8G,云存储20G起步,需要修改
$ helm install etcd bitnami/etcd --version 8.2.3 \
--set replicaCount=3 \
--set global.storageClass="nfs-client" \
--set service.type=NodePort \
--set service.nodePorts.client=32379 \
--set service.nodePorts.peer=32380 \
--set auth.rbac.rootPassword=abcdef # 密码不能为纯数字
# 释义
--set replicaCount=3 # 副本数量
--set global.storageClass="nfs-client" # 指定可用的storageClass的名字
--set service.type=NodePort # 通过NodePort暴露端口
--set service.nodePorts.client=32379 # 暴露客户端通信端口
--set service.nodePorts.peer=32380 # 暴露集群通信端口
--set auth.rbac.rootPassword=abcdef # etcd用户密码,默认用户为root,密码不能为纯数字
执行成功后输出
NAME: etcd
LAST DEPLOYED: Fri Jun 10 15:06:21 2022
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
CHART NAME: etcd
CHART VERSION: 8.2.3
APP VERSION: 3.5.4
** Please be patient while the chart is being deployed **
etcd can be accessed via port 2379 on the following DNS name from within your cluster:
etcd.default.svc.cluster.local
To create a pod that you can use as a etcd client run the following command:
kubectl run etcd-client --restart='Never' --image docker.io/bitnami/etcd:3.5.4-debian-10-r25 --env ROOT_PASSWORD=$(kubectl get secret --namespace default etcd -o jsonpath="{.data.etcd-root-password}" | base64 -d) --env ETCDCTL_ENDPOINTS="etcd.default.svc.cluster.local:2379" --namespace default --command -- sleep infinity
Then, you can set/get a key using the commands below:
kubectl exec --namespace default -it etcd-client -- bash
etcdctl --user root:$ROOT_PASSWORD put /message Hello
etcdctl --user root:$ROOT_PASSWORD get /message
To connect to your etcd server from outside the cluster execute the following commands:
export NODE_IP=$(kubectl get nodes --namespace default -o jsonpath="{.items[0].status.addresses[0].address}")
export NODE_PORT=$(kubectl get --namespace default -o jsonpath="{.spec.ports[0].nodePort}" services etcd)
echo "etcd URL: http://$NODE_IP:$NODE_PORT/"
* As rbac is enabled you should add the flag `--user root:$ETCD_ROOT_PASSWORD` to the etcdctl commands. Use the command below to export the password:
export ETCD_ROOT_PASSWORD=$(kubectl get secret --namespace default etcd -o jsonpath="{.data.etcd-root-password}" | base64 -d)
输出信息主要看一下几个
# ETCD客户端启动,这里我是使用了 nodeport 来暴露的,所以 ETCDCTL_ENDPOINTS="etcd.default.svc.cluster.local:2379,改为
# ETCDCTL_ENDPOINTS="192.168.1.12:32379" 随便一台节点的加 nodeport 端口
$ kubectl run etcd-client --restart='Never' --image docker.io/bitnami/etcd:3.5.4-debian-10-r25 --env ROOT_PASSWORD=$(kubectl get secret --namespace default etcd -o jsonpath="{.data.etcd-root-password}" | base64 -d) --env ETCDCTL_ENDPOINTS="192.168.1.12:32379" --namespace default --command -- sleep infinity
# 进入容器ETCD客户端
$ kubectl exec --namespace default -it etcd-client -- bash
# 尝试操作ETCD数据库
etcdctl --user root:$ROOT_PASSWORD put /message Hello
etcdctl --user root:$ROOT_PASSWORD get /message
感兴趣的可以拉取 ETCD chart 包来研究研究
指定版本是因为我在部署开发测试的时候拉取的最新的是这个版本,过了几天就成 8.2.5 了,也不知道改动了啥
helm pull bitnami/etcd --version 8.2.3
解压 Chart 包
tar zxf etcd-8.2.2-tgz
使用 CronJob 备份
CronJob 备份后存储在
本地 nfs 存储,已经创建 nfs 的 storageClass,创建 nfs 请参考:Kubernetes–StorageClass(二)
$ kubectl get sc -o name
storageclass.storage.k8s.io/nfs-client
编写 PVC 文件,用来存储 etcd 备份
$ vim etcd-backup-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: etcd-backup-pvc
namespace: default
spec:
accessModes:
- ReadWriteMany
storageClassName: "nfs-client" # 指定storageClass
resources:
requests:
storage: 2Gi
创建 PVC
$ kubectl create -f etcd-backup-pvc.yaml
编写 CronJob 来定时备份,注意命名空间
$ vim etcd-backup-cronjob.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
name: etcd-backup-cronjob
namespace: default
spec:
schedule: "* * * * *" # 为了测试改为每分钟执行备份
jobTemplate:
spec:
template:
metadata:
labels:
app: etcd-backup-cronjob
spec:
containers:
- name: etcd
image: docker.io/bitnami/etcd:3.5.4-debian-10-r25
command:
- sh
- -c
- "etcdctl --endpoints $ENDPOINT --user $USER:$PASSWORD snapshot save /snapshot/$(date +%Y%m%d_%H%M%S)_snapshot.db"
env:
- name: USER # etcd 用户
value: root
- name: PASSWORD # etcd 用户密码
value: qYKH9wUBch
- name: ENDPOINT
value: "192.168.1.12:32379" # ETCD的客户端地址
volumeMounts:
- mountPath: "/snapshot"
name: snapshot
subPath: data/etcd-snapshot
restartPolicy: OnFailure
volumes:
- name: snapshot
persistentVolumeClaim:
claimName: etcd-backup-pvc # 指定创建好的PVC
hostNetwork: true
创建 cronjob
$ kubectl create -f etcd-backup-cronjob.yaml
$ kubectl get cj,po | grep etcd-backup
cronjob.batch/etcd-backup-cronjob * * * * * False 0 42s 55s
pod/etcd-backup-cronjob-27580769-gjxz9 0/1 Completed 0 42s
查看 NFS 路径的备份文件
$ ls /nfsdata/default-etcd-backup-pvc-pvc-1196fd3b-2cf7-4991-9131-03d4c28246bf/data/etcd-snapshot
20220610_014012_snapshot.db
模拟数据增删
$ etcdctl --user root:$ROOT_PASSWORD put /myblogurl https://www.feiyiblog.com
OK
$ etcdctl --user root:$ROOT_PASSWORD put /myname FeiYi
OK
$ etcdctl --user root:$ROOT_PASSWORD get /myblogurl
/myblogurl
https://www.feiyiblog.com
$ etcdctl --user root:$ROOT_PASSWORD get /myname
/myname
FeiYi
启动新集群并根据备份数据添加数据
挑一个最新的备份数据文件
# ll /nfsdata/default-etcd-backup-pvc-pvc-1196fd3b-2cf7-4991-9131-03d4c28246bf/data/etcd-snapshot/
total 192
-rw------- 1 1001 root 20512 Jun 10 15:32 20220610_014012_snapshot.db
-rw------- 1 1001 root 20512 Jun 10 15:34 20220610_014212_snapshot.db
-rw------- 1 1001 root 20512 Jun 10 15:35 20220610_014312_snapshot.db
-rw------- 1 1001 root 20512 Jun 10 15:36 20220610_014412_snapshot.db
-rw------- 1 1001 root 20512 Jun 10 15:37 20220610_014512_snapshot.db
-rw------- 1 1001 root 20512 Jun 10 15:38 20220610_014612_snapshot.db
-rw------- 1 1001 root 20512 Jun 10 15:39 20220610_014712_snapshot.db
启动新的 ETCD 集群,密码最好一致,不一样好像会无法恢复
# 记得改nodeport的端口,否则和旧集群冲突
helm install etcd-new bitnami/etcd --version 8.2.3 \
--set replicaCount=3 \
--set service.type=NodePort \
--set auth.rbac.rootPassword=abcdef \
--set service.nodePorts.client=32479 \
--set service.nodePorts.peer=32480 \
--set startFromSnapshot.enabled=true \
--set global.storageClass=nfs-client \
--set startFromSnapshot.existingClaim=etcd-backup-pvc \
--set startFromSnapshot.snapshotFilename=data/etcd-snapshot/20220610_014712_snapshot.db
# 释义
--set replicaCount=3 # 副本数量
--set service.type=NodePort # 通过NodePort暴露端口
--set auth.rbac.rootPassword=abcdef # etcd用户密码,默认用户为root,密码不能为纯数字,这里的密码要与旧集群密码一致
--set service.nodePorts.client=32479 # 暴露客户端通信端口
--set service.nodePorts.peer=32480 # 暴露集群通信端口
--set startFromSnapshot.enabled=true # 开启从快照启动集群
--set global.storageClass=nfs-client # 指定可用的storageClass的名字
--set startFromSnapshot.existingClaim=etcd-backup-pvc # 指定快照所在的pvc名字
--set startFromSnapshot.snapshotFilename=data/etcd-snapshot/20220610_014712_snapshot.db # 指定快照所在pvc内的路径
登录客户端验证数据
$ kubectl run etcd-new-client --restart='Never' --image docker.io/bitnami/etcd:3.5.4-debian-10-r25 --env ROOT_PASSWORD=$(kubectl get secret --namespace default etcd-new -o jsonpath="{.data.etcd-root-password}" | base64 -d) --env ETCDCTL_ENDPOINTS="192.168.1.12:32479" --namespace default --command -- sleep infinity
$ kubectl exec --namespace default -it etcd-new-client -- bash
$ etcdctl --user root:$ROOT_PASSWORD get /myname
/myname
FeiYi
$ etcdctl --user root:$ROOT_PASSWORD get /myblogurl
/myblogurl
https://www.feiyiblog.com
$ etcdctl --user root:$ROOT_PASSWORD get /message
/message
Hello
最后我真牛逼~