ljzsdut
GitHubToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage
Edit page

0715 跨集群etcd主备数据同步实施方案

一、方案背景

为了提高集团云上协同业务和数据的可靠性和容灾能力,需要针对现有生产环境进行设计异地主备容灾方案。

云上协同生产环境公共组件(etcd 等)数据目前使用本地存储方式存放于集群节点上,为提高数据可用性,规划基于 drbd 技术进行跨集群数据实时同步, 将生产环境(主集群)公共组件业务数据实时同步到备集群(浪潮公有云),并在主集群故障时能够快速将负载切换到备集群,同时确保数据无丢失。

本方案以 etcd 公共组件为例,提供 etcd 生产数据切换 drbd 的具体实施步骤,以及主备切换的演练方案,为其他中间件提供统一参考。

二、实施目标

将生产环境上基于 hostpath-provisioner 本地存储的 etcd 数据切换至 drbd 管理的同步盘上,并确保切换前后数据一致无丢失, 切换过程尽可能简单、易操作、便捷快速,降低实施风险。

三、风险评估

3.1 实施风险

生产环境首次切换中间件本地存储到 DRBD 数据盘,需要重新调度现有中间件 Pod 负载,使其落到规划有 DRBD 资源的节点上,此过程必然影响业务,导致不可用, 整个切换过程至少需要保留总计 2 个小时的操作、数据验证以及排障预留时间窗口。

3.2 数据风险

生产数据切换过程中,需要拷贝已有数据到 DRBD 同步盘中,此过程要求运维操作人员严格安装方案手册执行,操作前进行数据备份,操作过程中确保数据、文件以及递归子目录权限等保持完整一致,杜绝产生任何生产数据的人为变更。

3.3 故障容灾

  • 主备集群运行期间 DRBD 资源数据实时同步,在网络可靠条件下,DRBD 数据主备保持实时一致性;
  • 主集群故障时,当需要进行备集群切换提升为临时主集群,需要人工操作介入,正常可控制到分钟级(<10min)完成切换以及中间件服务可用;

四、实施规划

以下内容均以 10.110.21.51(主集群) 和 10.110.21.45(备集群) 上两套测试环境为例进行演示说明。

总体规划图参考此前 DRBD 数据同步验证方案。

4.1 环境基本信息

4.1.1 主集群

  1. etcd 在主集群 common 命名空间下,以 statefulset 方式运行三副本 etcd 高可用服务;
  2. etcd 使用 hostpath-provisioner 本地存储插件将数据持久化在 pv 中,pv 数据落在所调度节点的 /data/vmdata/hpvolumes/pvc-xxxx 目录下;
  3. /data/vmdata/hpvolumes/ 即 etcd 使用的 sc 中配置的本地数据目录,该目录在集群节点上挂载了一块独立数据盘 /dev/sdb1
  4. 创建集群时,为 etcd 中间件规划的三块 20G 独占磁盘,分别位于 worker01、worker02、worker03 上的 /dev/sdc, 并且未经格式化;
  5. etcd 三个节点落在三个 worker 节点上,但是仅通过 control-plane 标签选择所有 worker 节点,未落在规划了 etcd 磁盘的节点;
  6. 规划 etcd 磁盘的三个节点未打 etcd 相关标签;
  7. 未部署 drbd 组件;

4.1.2 备集群

  1. etcd 磁盘规划与主集群一致(worker01、02、03 个 20G, 盘符 /dev/sdc);
  2. hostpath-provisioner sc 配置一致;
  3. hostpath-provisoner 数据盘挂载点一致;
  4. 节点未添加 etcd 相关标签;
  5. 未部署 etcd 中间件;
  6. 未部署 drbd 组件;

4.2 DRBD 资源规划

根据环境信息,需要为 etcd 三个副本规划三对 drbd 主备同步资源(盘),每一对 DRBD 资源同步其中一个 etcd 副本 Pod 的数据。

主集群 DRBD 资源规划表格如下:

DRBD 资源名称端口号节点IPDRBD 设备盘符底层数据盘符对端地址
etcd07790worker01172.16.1.1/dev/drbd0/dev/sdc172.16.2.1
etcd17790worker02172.16.1.2/dev/drbd0/dev/sdc172.16.2.2
etcd27790worker03172.16.1.3/dev/drbd0/dev/sdc172.16.2.3

备集群 DRBD 资源规划:

DRBD 资源名称端口号节点IPDRBD 设备盘符底层数据盘符对端地址
etcd07790worker01172.16.2.1/dev/drbd0/dev/sdc172.16.1.1
etcd17790worker02172.16.2.2/dev/drbd0/dev/sdc172.16.1.2
etcd27790worker03172.16.2.3/dev/drbd0/dev/sdc172.16.1.3

特别说明

  1. DRBD 两端默认使用节点 IP 以及节点端口号进行互联,要求主备集群两节点可通过网络直连;若无法直连,需要重新设计代理方案(不建议);
  2. 由于 etcd 使用的 hostpath 存储插件生产的数据目录带有 uuid 信息,无法多个节点统一配置挂载点,而现版本 drbd 组件不支持各节点差异化配置,本方案所有 drbd 资源均为手动配置,不使用组件化配置;

五、实施前检查

5.1 确认集群状态

  1. 确认 K8S 集群控制面正常,Pod 健康无异常;

    kubectl get po -A -owide | grep -vE '(.)\/\1|Comp'
    
  2. 确认业务运行正常,数据可正常读写;

5.2 确认跨集群网络状态

  1. 确认主备集群 DRBD 同步节点两端可互相 ping 通;

    ping 172.16.2.1
    
  2. 确认主备节点之间网络带宽满足业务吞吐量要求;

    netperf -H 172.16.2.1 -l 30
    

六、备集群实施步骤

为了尽可能减少因数据切换产生的业务中断时间,在主集群配置之前,首先配置备集群 DRBD 资源。

6.1 DRBD 组件部署

6.1.1 声明式组件定义

DRBD 基于 CKE 组件化部署,直接在 CKE 环境中通过 apply 对应的组件定义 (component/com) 和组件部署定义(comdeploy/cd)即可:

DRBD com yaml:

apiVersion: cie.inspur.com/v1alpha1
kind: Component
metadata:
  name: drbd-9.1.7-1
  namespace: kube-system
spec:
  depends:
    - docker
    - cke-certs
  deployImage: library/cke/components/drbd:9.1.7-1-20220706_145827
  images:
    drbd_kernel: library/cke/piraeusdatastore/drbd9-bionic:v9.1.7
    drbd_utils: library/cke/piraeusdatastore/drbd-utils:v9.21.2
    drbd_top: library/cke/piraeusdatastore/drbdtop:v0.2.3
  version: 9.1.7-1

DRBD cd yaml:

apiVersion: cie.inspur.com/v1alpha1
kind: Comdeploy
metadata:
  name: drbd-deploy
  namespace: kube-system
spec:
  comDependenceName: cke-dependence
  component:
    name: drbd
    version: 9.1.7-1
  nodeSelector:
    - node-role.kubernetes.io/node=true
  parameters:
    # 脑裂处理脚本放置路径,默认执行预装通知脚本 '/usr/lib/drbd/notify-split-brain.sh root' 即向 root 用户发送邮件
    split_brain_handler_path: ""
    # 脑裂处理脚本内容,自定义脚本内容时必须指定路径,若路径为空则使用内置脚本而忽略此配置;
    split_brain_handler_script: ""
    # drbd 资源配置采用 yaml 格式,此例中留空,后续采取手动方式配置资源;
    resources: ""

6.1.2 组件部署

注意 apply 有先后顺序,先创建组件(com)定义,在创建组件部署(cd)定义:

kubectl apply -f drbd-com.yaml

kubectl apply -f drbd-cd.yaml

查看组件部署状态,变为 Running 后即部署完成:

root@master01:~# kubectl get cd -n kube-system drbd-deploy
NAME          COMPONENT   VERSION   STATUS    REASON   AGE     NODES
drbd-deploy   drbd        9.1.7-1   Running            3d15h   ["master01","master02","master03","worker01","worker02","worker03","worker04","worker05","worker06","worker07","worker08","worker09","worker10","worker11","worker12","worker13","worker14","worker15","worker16","worker17","worker18","worker19","worker20","worker21"]

6.3 DRBD 资源配置

每个 drbd 资源对应一个资源配置文件,通常存放于 /etc/drbd.d/ 目录下,以 .res 作为文件后缀。

6.3.1 特别说明

  1. 在 CKE 组件化部署的 drbd 中,会部署开机自启逻辑,实现 drbd 资源开机自动加载,官方原生的 drbd 资源不具备开机自动加载能力。 当手动配置 drbd 资源时,需要将 drbd 资源配置文件命名为 /etc/drbd.d/cke_<资源名>.res 格式即可。
  2. 官方原生的 drbd 也不会记录资源的主备角色,即重启后,并不会自动变为主角色,需要手动介入。CKE 组件同样设计了自动提升主角色的能力,在本方案场景中,主集群在通常情况下需要保持主角色,即使单个节点重启后,应当自动加载资源,并恢复主角色,持续提供服务,只有在确认主集群故障需要切换备集群时,才需要处理原主集群中 drbd 资源主角色的自动提升配置。
  3. 当手动配置 DRBD 资源时,要使用 CKE 重启保持主角色的能力 ,需要创建(touch)一个 /etc/drbd.d/cke_<资源名>.primary 的空文件,以标记当前节点上该资源为持久化的主角色。

6.3.2 资源配置文件说明

以备节点 worker01 上的 drbd 配置文件为例,以 3.2 中规划的资源配置参数填充。

此配置文件仅包含必要的参数,如果需要配置其他参数请参考 《DRBD 9 用户手册》。

# cat /etc/drbd.d/cke_etcd0.res
# resource 后面跟资源名称,即 drbdadm 命令行操作使用的名称
resource etcd0 {
  net {
      # 同步复制协议
      protocol C;
      # 不允许双主
      allow-two-primaries no;
  }
  options {
      # 不允许自动提升为主角色
      auto-promote no;
  }
  # 节点名称,与 hostname 一致
  on worker01 {
    # drbd 生成的设备盘符
    device /dev/drbd0;
    # 底层物理盘符
    disk /dev/sdc;
    # 本地 ip + 端口号
    address 172.16.2.1:7790;
    # 节点 id, 自己分配控制,每个节点唯一,取值范围 1~32,一旦分配生效,不可随意更改
    node-id 2;
  }
  # 对端节点名称,可自定义,无需与实际节点 hostname 一致
  on remote_172.16.1.1 {
    # 对端地址+端口号,必须直通,若走代理则配置代理地址和端口号
    address 172.16.1.1:7790;
    # 对端 drbd 设备盘符
    device /dev/drbd0;
    # 对端底层物理盘符
    disk /dev/sdc;
    # 对端节点 id
    node-id 1;
  }
}

特别说明

  1. drbd 资源配置文件 res 格式文件无严格的缩进验证,与 yaml 不同;
  2. 注释以 # 号开头;
  3. 每一行配置严格以英文分号结尾,不可缺省;
  4. 部分公共基础配置参数存放于 /etc/drbd.d/global_common.conf 全局配置文件中;

6.3.3 创建资源

将 DRBD 资源文件准备就绪,确保路径格式为 /etc/drbd.d/cke_<资源名>.res

  1. 创建元数据(首次纳管底层数据盘时需要执行):

    drbdadm create-md etcd0
    
  2. 挂载数据盘:

    drbdadm attach etcd0
    
  3. 检查状态

    drbdadm status etcd0
    

此时备集群的 drbd 资源由于无法连接对端资源(主集群还未配置),status 返回状态通常会显示 StandAlone 。

备集群 drbd 资源默认保持备角色(secondary)

按照以上步骤分别配置备集群 3 个节点上的 etcd 资源。

6.4 中间件部署

6.4.1 确认节点标签

etcd 的 pod 需要落在指定配置了 drbd 资源的三个节点上,必须为三个节点配置 etcd 专属标签:

kubectl label ckenode -n kube-system worker01 worker02 worker03 cnp.inspurcloud.cn/etcd-tenant=true

特别说明

  1. 在 CKE 集群中,K8S 节点标签统一由 CKE 节点资源 CKENode 管理,尽量避免直接在 k8s node 上修改标签,需要修改 ckenode 标签,会自动同步至对应的 k8s node.

6.4.2 确认 chart 节点选择器

在 etcd chart 的 values.yaml 中,也需要确认 nodeSelector 中,包含上一步我们为 etcd 节点添加的标签:

nodeSelector:
  cnp.inspurcloud.cn/control-plane: "true"
  cnp.inspurcloud.cn/etcd-tenant: "true"

6.4.3 部署中间件 chart

helm install common-etcd -n common ./etcd

等待并确认部署完成,etcd pod 运行正常,节点调度符合预期:

kubectl get pod -n common -owide | grep etcd

6.4.4 后续操作

备集群作为备用节点,使用的数据来自于 drbd 从主集群同步来的数据,因此备集群无需保留数据,在备集群角色状态下,也无需运行工作负载, 同时为了便于后续数据切换,需要直接将 etcd 副本数缩容为 0。

kubectl scale sts -n common common-etcd-etcd --replicas=0

七、主集群实施步骤

如本方案第三章节所属,进行主集群实施时,必须在合适的时间窗口进行,并保持敏捷稳健原则,确保快速平稳迁移。

主集群迁移实施计划内耗时预估为 10~30min (不含 drbd 部署配置操作)

特别说明

  1. 在主集群(生产环境)进行 drbd 组件部署和资源配置,对业务无影响,可在常规运维窗口提前进行部署配置,减少迁移时间。

7.1 实施前检查

主集群进行变更操作前,同样需要首先确认集群和网络状态,参考本方案第五章节。

7.2 DRBD 组件部署和资源配置

主集群 drbd 部署配置参考本方案第六章节,按照第四章节规划的节点和参数进行配置。

特别说明

  1. 在组件部署这一步,同样需要提前完成同 6.4.1 步骤中一样的节点 label 配置,为中间件重新规划好对应的标签。

7.3 DRBD 主备连接以及初始化同步

配置完主集群三个节点 drbd 资源后,将主节点 drbd 资源提升为主角色,并进行主备资源连接:

drbdadm primary etcd0

drbdadm connect etcd0

首次建立连接时,将进行数据初始化同步,可以通过 drbdadm status 或者 drbdtop 查看同步进度。

同步速率受磁盘大小以及网络带宽决定。

当同步完成后,status 应显示两端均为 UpToDate 状态:

# drbdadm status
etcd0 role:Primary
  disk:UpToDate
  remote_172.16.2.1 role:Secondary
    peer-disk:UpToDate

将主集群三个 etcd 节点均设置为主角色并完成数据同步。

完成同步后,如果数据盘为裸盘,需要在迁移数据之前,首先进行格式化:

mkfs.ext4 /dev/drbd0

7.3 ETCD 数据迁移

进行 etcd 迁移之前,确保访问 etcd 的相关业务暂停或者具备离线条件。

7.3.0 *预埋测试数据

在测试验证环境中(非生产),为了验证迁移数据可靠性,建议写入测试数据,在迁移后对比验证,确保无数据损失。

向 etcd 中测试数据 key 中写入当前时间戳数据:

kubectl exec -n common -it common-etcd-etcd-0 -- etcdctl put test-ts  "$(date +%s.%N | cut -b 1-14)"

7.3.1 缩容 ETCD 实例

此步骤预计耗时 1min

将 etcd 副本数缩容为 0,确保业务数据在迁移期间无变更。

kubectl scale sts -n common common-etcd-etcd --replicas=0

7.3.2 备份 ETCD 数据

此步骤预计耗时 6min

待 etcd 缩容完成后,进行数据备份。

  1. 首先查询获取 etcd 使用的本地卷 pv 的名称,后面需要根据 pv 名称查找对应的数据目录:

    kubectl get pv | grep etcd
    
  2. 登陆到 etcd 所在节点上,以 保留文件原始信息 的形式,将 etcd pv 数据目录拷贝到本地节点的备份目录:

    cp -a /data/vmdata/hpvolumes/pvc-16e9053a-27e7-4479-80a5-0ea2381974e6/ /data/vmdata/backup/
    
  3. 拷贝完成后再次确认备份数据与原始数据文件大小、hash、权限一致。

三个节点均以此方式进行数据备份。

7.4 重建 ETCD 实例

此步骤预计耗时 5min

由于现有生产环境 etcd 所在节点不在规划的 drbd 同步节点,使用的 pv 已经固定在其他节点,迁移 etcd 节点必须迁移 pv, 最简便快捷的方式就是重建 etcd 。

  1. 首先删除现有 etcd chart:

    helm uninstall -n common common-etcd
    
  2. 删除旧 etcd 的 pvc:

    kubectl delete pvc -n common data-common-etcd-etcd-0 data-common-etcd-etcd-1 data-common-etcd-etcd-2
    
  3. 确认 pvc 和 pv 都删除后,确认节点上组件 label 以及 chart 中节点选择器都已配置好,能够按预期调度到 drbd 同步节点,重建 etcd chart:

    kubectl get node -l cnp.inspurcloud.cn/etcd-tenant=true
    
    helm install common-etcd -n common ./etcd
    
  4. 等待 etcd pod 重建完成并 running, 再次缩容为 0, 准备数据回迁:

    kubectl scale sts -n common common-etcd-etcd --replicas=0
    

7.5 数据回迁

此步骤预计耗时 6min

重建后的 etcd 完成缩容后,进行原生产数据的回迁操作,需要将原所在节点对应的三个副本的备份数据目录,通过 scp 等方式迁移到新节点上 drbd 的同步盘中。

7.5.1 挂载 drbd 同步盘

  1. 首先通过 kubectl 查询新创的的 etcd pv 名称,以确认对应节点上的 pv 数据目录;

  2. 将 drbd 数据盘 /dev/drbd0 挂载到 etcd 新建的 pv 目录下,掩蔽原始目录:

mount /dev/drbd0 /data/vmdata/hpvolumes/pvc-66129604-196d-4d2d-9a6b-d4b2eeca9553
  1. 三个 etcd 同步节点完成同样的挂载操作。

7.5.2 数据回迁

此步骤预计耗时 4min

通过 scp 方式,将原备份节点上对应 etcd 副本的数据目录下的文件内容,拷回新节点上,drbd 同步盘的挂载点即新 pv 目录下:

scp -rp -P 6233 -i /etc/kubernetes/ckemonitor/private_key /data/vmdata/backup/ 172.16.1.1:/data/vmdata/hpvolumes/pvc-66129604-196d-4d2d-9a6b-d4b2eeca9553/

特别说明

  1. 数据拷贝回迁时同样需要注意保留数据文件的原始信息和权限等,使用 scp 时可添加 -rp 参数递归并保留原始信息;
  2. 通过 scp 拷贝目录时需要注意目录层级要与原 pv 目录层级一致(避免出现类似 /data/vmdata/pvc-xxxx-xxx/pvc-xxxx-xxxx 目录嵌套问题);

7.5.3 服务恢复

此步骤预计耗时 5min

  1. 三个 etcd 节点数据迁移完成后,确认 drbd 同步状态正常后,扩容 etcd 服务,恢复至 3 副本:

    kubectl scale sts -n common common-etcd-etcd --replicas=3
    
  2. 待 etcd 运行正常后,查询业务数据,确保与迁移前一致,无数据丢失;*测试环境中可查询迁移前写入的测试数据,是否能查询到且一致:

    kubectl exec -n common -it common-etcd-etcd-0 -- etcdctl get test-ts
    
  3. 恢复业务;

八、后续优化配置

8.1 配置主集群 drbd 资源开机自动加载

  1. 写入 CKE drbd 资源主角色标记:

    touch /etc/drbd.d/cke_etcd0.res.primary
    
  2. 配置 etcd pv 目录开机自动挂载

    TODO 由于各节点目录不一致,无法走 CKE DRBD 组件的逻辑进行自动目录挂载,需重新确认方案

十、主备切换演练

10.1 主集群停止服务

测试环境演练可直接进行节点宕机;

生产环境演练时,可通过停止 etcd 服务来演练;

模拟故障前,参考 7.3.1 步骤向 etcd 写入测试数据。

10.2 备集群提升 drbd 角色

此步骤预计耗时 2min

登陆备集群 etcd 同步节点,将 3 各节点上的 drbd 资源提升为主角色, 并通过 status 查看资源状态,主集群宕机失联不影响备集群 drbd 提升为主角色

drbdadm primary etcd0

drbdadm status etcd0

10.3 备集群挂载 drbd 到 pv 目录

此步骤预计耗时 2min

参考 7.5.1 步骤,挂载 drbd 同步盘到 pv 目录。

10.4 启动备集群 etcd

此步骤预计耗时 1min

直接将 etcd 副本数扩容为 3 副本:

kubectl scale sts -n common common-etcd --replicas=3

10.5 数据验证以及业务恢复

此步骤预计耗时 3min

参考 7.5.3 步骤在备集群查询故障前写入的测试数据,验证是否一致。

十一、常见问题

待补充