方案背景
客户主要生产业务在阿里云,运行在阿里云侧业务应用, MySQL, Redis, MongoDB,现在需要将阿里云侧资源与部署在Ucloud云平台的资源组建多活容灾系统
客户资源现状
| 资源 | 部署形式 | 实例数量 | 数据量 | 容灾策略 | 
|---|---|---|---|---|
| 应用 | 大部分为普通应用,小部分容器 | 150台 | DNS负载均衡 | |
| RDS | MySQL 5.7 binlog默认开启 | 8主5从 | 2T | PXC集群同步 | 
| Redis | 主从版 4.0 | 5 | 4G | 不做容灾处理 | 
| MongoDB | MongoDB 4.0 副本集 | 1 | 50G | 单向同步容灾 | 
| ES | 版本:6.8.6 数据节点4 | 1 | 300G左右 | 应用双写 | 
| Oracle | 机器部署 Oracle 11G | 1 | 1T左右 | Rac方式同步 | 
容灾方式
阿里云/ucloud 主从热备,默认阿里云主,ucloud从,故障后切换后,切换角色
容灾级别
基础设施容灾, Ucloud 支持多云组网能力,可以实现基础设施容灾,和提供数据库级容灾方案能力,对其他各个云厂商限制的应用可以实现定时备份的能力,
数据级容灾, 仅将生产中心的数据复制到容灾中心,在生产中心出现故障时,仅能实现存储系统的接管或是数据的恢复。容灾中心的数据可以是本地生产数据的完全复制(在同城实现),也可以比生产数据略微落后,差异的数据可以通过一些工具(如操作记录、日志等)可以手工补回。
应用级容灾, 是在数据级容灾的基础上,在Ucloud侧创建和阿里云侧生产中心系统的核心资源复制,包括主机、数据库、应用、当生产系统发生灾难时,依赖GTM实现故障切换,切换到备用可用区,实现应用级容灾.
方案概述
- 多云 不同 Region 内网互通,使用ucloud罗马打通
 - 使用GTM 做业务流量调度 -> SLB/ULB(两地中心入口地址) https://developer.aliyun.com/article/754825
 - 业务架构面向多活架构改造
 - 业务应用弹性扩缩容
- 容器化应用采用k8s集群的原生特性自动扩容(CA/HPA/VPA)
 - 虚拟机扩容采用监控结合API方式扩容
 
 - 数据集群分布式化
- mysql采用强一致性的集群方案Percona XtraDB Cluster
 - MongoDB容灾采用 MongoShake 单向实时同步
 - Oracle 可以寻求商业支持,例如采用Oracle Rac高可用方案
 
 
GTM流量调度
GTM 本质上是通过 DNS,结合监控,实现流量调度,为客户输出不同网络或地区用户访问实现就近接入、应用服务运行状态的健康检查、故障自动切换,等能力。
GTM和LB对比表
| 对比项 | 网络层 | 后端地址 | 加权轮询 | 跨Region难度 | 故障间隔时间 | 会话保持 | 
|---|---|---|---|---|---|---|
| GTM | 3 层 | 域名、IP | 支持 | 简单 | 分钟级 | 不支持 | 
| LB | 4层、7层 | IP | 支持 | 困难 | 秒级 | 支持 | 
GTM和GSLB 对比表
无法复制加载中的内容
GTM故障切换时间
GTM能在 5分钟内 将应用服务的90%左右的流量切换成功。GTM的故障切换生效时间 = 故障发现时间 + DNS切换同步时间 。
- 故障发现时间:目前默认的健康检查配置可以在故障的3分钟左右准确发现故障;
 - DNS切换同步时间:目前 GTM 的cname接入域名TTL设置为60秒,理论上域名切换后60秒内可以生效,但实际情况取决于全国各地运营商的缓存设置时间。
 
GTM主要应用场景
- 应用主备容灾:建立两个地址池 Pool A 和 Pool B,设置默认地址池为 Pool A、备用地址池为 Pool B ,结合健康检查,即可以实现应用服务主备IP容灾切换
 - 应用多活:建立一个地址池Pool A, 然后把 1.1.1.1、2.2.2.2、3.3.3.3 三个地址添加进地址池,并配置上健康检查,即可实现多个IP多活。
 - 也适用于,高并发应用服务负载分摊,不同区域访问加速
 
业务应用系统面向多活架构改造
容灾说明:
- 业务应用需要清晰的解耦分层,web应用(无状态),缓存/消息队列,ES日志,DB 云主机资源
 - 阿里云/Ucloud云 VPC网络使用ipsecVpn 或者罗马打通vpc
 - 业务域名入口采用阿里云GTM做跨Region 流量调度和故障切换
 - 业务阿里云/Ucloud云容灾,其中阿里云BGP入口为主,Ucloud云BGP入口为备用,阿里云杭州可用区和UC上海可用区使用罗马打通VPC网络,延时4-6ms
 - 阿里云资源故障后,GTM将流量切换到Ucloud云BGP入口
 - Ucloud云资源全新部署,建议web应用采用容器集群,充分利用k8s原生的特性实现节点自动扩容,应用实例扩容
- Cluster Autoscaler:集群node节点扩容/缩容
 - HPA: Pod个数自动扩/缩容
 - VPA :Pod配置自动扩/缩容,主要是CPU、内存 addon-resizer组件
 
 - 虚拟机扩容采用监控结合API方式扩容 (节点监控(cpu/mem/connet) -> monitor -> altermanager-webhook-API操作扩容 )
 - MySQL数据层建议采用兼容InnoDB引擎的Percona XtraDB Cluster集群模式来保证强一致性
 - MongoDB容灾采用 MongoShake实现实时从阿里云侧同步到Ucloud云侧
 
问题:
1、网络抖动或短时故障,不建议切业务主备,影响时间将更长
2、都云异构的容灾方式后续维护成本较高,包括物理环境、网络环境、自建系统环境等,需要业务侧投入人力更大
3、Percona XtraDB Cluster保证了强一致性能,但是牺牲了部分性能


不支持在 Docs 外粘贴 block
MongoDB 容灾
MongoShake从源库抓取oplog数据,然后发送到各个不同的tunnel通道。源库支持:ReplicaSet,Sharding,Mongod,目的库支持:Mongos,Mongod。
MongoDB同步方式采用 Direct通道类型,直接写入目的MongoDB
DB容灾方案
Percona XtraDB Cluster(简称PXC),是由percona公司推出的mysql集群解决方案。特点是每个节点都能进行读写,且都保存全量的数据。也就是说在任何一个节点进行写入操作,都会同步给其它所有节点写入到自己的磁盘,选择PXC作为容灾方案的理由是:
- PXC 强一致性特性,在故障转移,恢复等自动化程度高
 - 支持 IST 增量传输,适合在跨地域,网路延迟较高的场景做同步
 - 阿里云侧和Ucloud侧各自配置了一个4层LB来作为DB请求的入口,轮询方式(避免)
 
PXC特性和优点
- 完全兼容 MySQL。
 - 同步复制,事务要么在所有节点提交或不提交。
 - 多主复制,可以在任意节点进行写操作。
 - 在从服务器上并行应用事件,真正意义上的并行复制。
 - 节点自动配置,数据一致性,不再是异步复制。
 - 故障切换:因为支持多点写入,所以在出现数据库故障时可以很容易的进行故障切换。
 - 自动节点克隆:在新增节点或停机维护时,增量数据或基础数据不需要人工手动备份提供,galera cluster会自动拉取在线节点数据,集群最终会变为一致;
 
PXC最大的优势:强一致性、无同步延迟,适合订单,交易系统等场景
PXC的局限和劣势
- 复制只支持InnoDB 引擎,其他存储引擎的更改不复制
 - 短板效应
- 集群写入性能取决于性能最差那台机器,所以建议配置相同
 
 - 锁冲突严重
- 建议单节点写+负载均衡,或者写不同的库
 
 - 全量SST时,donor节点性能影响较为严重,receiver恢复较慢
- 尽量避免SST
 
 - 维护成本高,限制和注意事项较多
 
PXC与Replication的区别
无法复制加载中的内容
PXC 使用注意事项
- PXC各个节点默认是不会记录全量日志的,只会记录当前节点变化数据的binlog:想要节点记录全量binlog日志需要添加该配置:log_slave_updates, 在PXC集群中,官方推荐使用相同的server-id
 - PXC支持两种同步方式:
- SST 全量传输支持 XtraBackup、mysqldump、rsync三种方式,
 - IST 增量传输支持 XtraBackup
 
 - 群集的最小建议大小是3个节点。第三个节点会是仲裁者
 - 复制仅适用于InnoDB存储引擎。其他存储引擎的表的写入都不复制(包括mysql.表)。但是,DDL语句会在statement级别进行复制,对mysql.表的更改将以这种方式进行复制。因此您使用CREATE USER...命令,而不应该使用INSERT INTO mysql.user...。
 - 不支持的查询:
- 在多主设置中,不支持LOCK TABLES和UNLOCK TABLES
 - Lock functions如GET_LOCK(),RELEASE_LOCK()也不支持
 
 - general.log、slow.log不支持输出到TABLE,如果启用general.log、slow.log,则必须将日志输出到文件:
 
log_output  =  FILE
- 允许的最大事务大小由wsrep_max_ws_rows和wsrep_max_ws_size变量定义。LOAD DATA INFILE处理将(按参数设置)每10000行提交一次。因此大事务LOAD DATA时将被拆分为一系列小事务。
 - 由于集群级的乐观并发控制,事务在COMMIT阶段可能仍会中止。可以有两个事务写入相同的行并在单独的Percona XtraDB Cluster节点中提交,并且只有其中一个可以成功提交。失败的将被中止。对于集群级中止,Percona XtraDB Cluster提供了死锁错误代码:
 
(Error: 1213 SQLSTATE: 40001  (ER_LOCK_DEADLOCK)).
- 由于可能在提交时回滚,因此不支持XA事务。
 - 整个集群的写吞吐量受最弱节点的限制。如果一个节点变慢,则整个群集速度变慢。如果您对稳定的高性能有要求,则应该由相应的硬件支持。
 - 不支持InnoDB虚假更改功能。enforce_storage_engine=InnoDB与wsrep_replicate_myisam=OFF(默认)不兼容 。
 - 在群集模式下运行Percona XtraDB群集时,请避免ALTER TABLE ... IMPORT/EXPORT操作。如果未在所有节点上同步执行,则可能导致节点数据不一致。
 - 所有表必须具有主键。这可确保相同的行在不同节点上以相同的顺序出现。DELETE没有主键的表的语句不被支持。
 
无法复制加载中的内容
POC 环境以及测试数据
GTM故障切换
这里采用阿里云的GTM服务做业务流量调度,和
- 首先需要开通阿里云GTM服务,购买GTM实例,完成基本配置域名和配置地址池
 


- 为地址池IP 添加健康检查,支持ping tcp http https
 

- 设置访问策略
 

- 模拟故障,停掉 主地址池IP 业务应用服务,业务域名解析会切换到备用地址池IP
 
阿里云 GTM 标准版本TTL需要10分钟,健康检查最小间隔分钟级,需要更快切换,建议购买阿里云 GTM 旗舰版服务

- 故障恢复后,业务域名会重新恢复到主地址池
 
业务应用扩容
业务应用弹性扩容分两个场景, 容器方式部署的应用和虚拟机部署的应用:
容器应用扩容
首先将应用转变容器应用,然后部署在k8s集群中,可以充分k8s集群的能力,实现自动扩缩容:
- 集群节点的自动扩容
 - 应用资源配额的横向/纵向扩容
 - 通过配置uk8s的集群伸缩,可以实现集群node节点扩容/缩容(Cluster Autoscaler)
 

- Metrics-server 已经内置,Pod个数自动扩/缩容(HPA),只需要对应用配置 HPA 即可,示例如下:
 
创建一个nginx服务,ULB 由 cloudprovider-ucloud 自动创建,和公有云相关配置在名为uk8sconfig的configmap中,创建 test-nginx.yaml
apiVersion: v1
kind: Service
metadata:
  name: ucloud-nginx
  labels:
    app: ucloud-nginx
spec:
  type: LoadBalancer
  ports:
    - protocol: TCP
      port: 80
  selector:
    app: ucloud-nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ucloud-nginx
spec:
  selector:
    matchLabels:
      app: ucloud-nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: ucloud-nginx
    spec:
      containers:
      - name: ucloud-nginx
        image: uhub.service.ucloud.cn/ucloud/nginx:1.9.2
        resources:
          requests:
            memory: "64Mi"
            cpu: "250m"
          limits:
            memory: "128Mi"
            cpu: "500m"
        ports:
        - containerPort: 80
执行命令: kubectl apply -f test-nginx.yaml 创建资源,
执行命令: kubectl get services 可以查询到 EXTERNAL-IP 即创建服务生成ULB外网IP
创建HPA配置,参考如下:
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: ucloud-nginx
  namespace: default
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: ucloud-nginx
  minReplicas: 1
  maxReplicas: 1000
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 2
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 0
      policies:
      - type: Percent
        value: 500
        periodSeconds: 15
      - type: Pods
        value: 10
        periodSeconds: 15
      selectPolicy: Max
    scaleDown:
      stabilizationWindowSeconds: 10
      policies:
      - type: Percent
        value: 100
        periodSeconds: 15
- 缩容策略: 稳定窗口的时间为 300 秒,允许 100% 删除当前运行的副本,
 - 扩缩策略: 立即扩容,每 15 秒添加 4 个 Pod 或 100% 当前运行的副本数,直到 HPA 达到稳定状态。
 - https://kubernetes.io/zh/docs/tasks/run-application/horizontal-pod-autoscale/
 
使用AB压测验证:
操作压测集群节点执行命令: ab -n 100000 -c 300 http://nginx_server_ip/
集群初始状态:

压测过程中,随着请求带来对pod带来的压力,会触发Pod快速扩容个数,同时集群node节点的请求值达到扩容阈值的时候,会自动新增node节点

在压测结束后,稳定窗口时间结束后,集群内pod数量,node节点数会恢复到初始状态
- Pod配置自动扩/缩容(VPA) 需要部署vertical-pod-autoscaler控制器 参考https://github.com/kubernetes/autoscaler VPA示例以及VPA使用限制
 
apiVersion: autoscaling.k8s.io/v1beta2
kind: VerticalPodAutoscaler
metadata:
  name: nginx-vpa
  namespace: vpa
spec:
  targetRef:
    apiVersion: "apps/v1"
    kind: Deployment
    name: nginx
  updatePolicy:
    updateMode: "Off"
  resourcePolicy:
    containerPolicies:
    - containerName: "nginx"
      minAllowed:
        cpu: "250m"
        memory: "100Mi"
      maxAllowed:
        cpu: "2000m"
        memory: "2048Mi"
- 不能与HPA(Horizontal Pod Autoscaler )一起使用
 - Pod比如使用副本控制器,例如属于Deployment或者StatefulSet
 
非容器应用扩容
虚拟机节点扩容目前没有标准的服务,可以结合监控,调用API方式扩容,需要结合具体业务监控做ucloud平台接口对接实现。
部署 PXC 集群
部署第一个节点
docker run -d                    \
-p 3306:3306                     \
-e MYSQL_ROOT_PASSWORD=abc123456 \
-e CLUSTER_NAME=PXC              \
-e XTRABACKUP_PASSWORD=abc123456 \
-v /data/:/var/lib/mysql         \
--privileged                     \
--name=pxc-node-1                \
--net=host                       \
percona/percona-xtradb-cluster:5.7
加入其他节点
docker run -d                    \
-p 3306:3306                     \
-e MYSQL_ROOT_PASSWORD=abc123456 \
-e CLUSTER_NAME=PXC              \
-e XTRABACKUP_PASSWORD=abc123456 \
-e CLUSTER_JOIN=pxc-node-1       \
--privileged                     \
--name=pxc-node-4                \
--net=host                       \
percona/percona-xtradb-cluster:5.7
可用性测试
- 停掉任一节点,PXC集群服务不中断,业务应用无感知
 - 如需PXC升级集群配置,逐台离线升级,重建加入集群即可
 
sysbench压力测试
mysql -h 10.10.114.135 -uroot -pabc123456
create database sbtest;
sysbench /usr/share/sysbench/tests/include/oltp_legacy/oltp.lua \
--mysql-host=10.10.114.135  \
--mysql-port=3306           \
--mysql-user=root           \
--mysql-password=abc123456  \
--oltp-test-mode=complex    \
--oltp-tables-count=10      \
--oltp-table-size=10000     \
--threads=10                \
--time=120                  \
--report-interval=10 prepare
sysbench /usr/share/sysbench/tests/include/oltp_legacy/oltp.lua \
--mysql-host=10.10.114.135  \
--mysql-port=3306           \
--mysql-user=root           \
--mysql-password=abc123456  \
--oltp-test-mode=complex    \
--oltp-tables-count=10      \
--oltp-table-size=100000    \
--threads=10                \
--time=120                  \
--report-interval=10 run >> /root/sysbench-mysql.log
POC 应用环境
整个 POC 环境使用,wordpress / redis插件/ PXC DB集群 北京/上海两地 多活部署方式
- 北京/上海两地网络延迟 平均30ms
 - 北京/上海 两地k8s集群规模 3master 5node
 - PXC DB 集群 单节点配置 4核8G sysbench测试结果
 
   SQL statistics:
    queries performed:
        read:                            304850
        write:                           54616
        other:                           76002
        total:                           435468
    transactions:                        21760  (181.25 per sec.)
    queries:                             435468 (3627.15 per sec.)
    ignored errors:                      15     (0.12 per sec.)
    reconnects:                          0      (0.00 per sec.)
General statistics:
    total time:                          120.0560s
    total number of events:              21760
Latency (ms):
         min:                                   52.43
         avg:                                   55.16
         max:                                  110.09
         95th percentile:                       56.84
         sum:                              1200266.64
Threads fairness:
    events (avg/stddev):           2176.0000/14.59
    execution time (avg/stddev):   120.0267/0.02









