1 概述
为避免地域级别的故障,需要将单机房架构变成双地域架构(两个机房物理距离越远,网络延时越大,网延时是业务研发首先关注的)。单边写的多机房架构,是落地性比较大的一个方案,相对于单元化架构。并且,通过域名作为中间层来屏蔽故障切换时的数据库IP变化,业务研发就不需要修改应用配置了,只需要平台组工程师在DNS服务器上进行DNS记录的变更即可,省去故障切换时应用配置的变更。
2 架构
3 环境
3.1 广州地域:
ELB的公网地址是:139.xx.xx.xxx
数据库内网地址是:10.0.29.52
数据库公网地址是:113.xx.xx.xx
数据库域名是:mysql.example.com
数据库的database是:demo
数据库的用户是:demo
3.2 上海地域:
ELB的公网地址是:122.xx.xx.xxx
数据库内网地址是:192.168.14.185
数据库公网地址是:116.xx.xx.xx
数据库域名是:mysql.example.com
数据库的database是:demo
数据库的用户是:demo
3.3 数据库同步
使用华为云DRS服务的实时灾备任务作为数据同步工具:
3.4 应用公网域名:
demo-mall.xxxxx.com
3.5 应用部署
环境变量DATA_CENTER,表示该用于属于哪个地域。
环境变量MYSQL_HOST,表示数据库的地址。
环境变量MYSQL_USER,表示数据库的账号。
环境变量MYSQL_PASSWORD:表示数据库的密码。
应用会自动初始化数据库记录。
应用对外暴露的接口:
curl http://127.0.0.1:8080/products
curl -XPOST http://127.0.0.1:8080/products -d '{"name": "Product-21", "price": 1088.29}'
广州应用的kubernetes yaml,环境变量DATA_CENTER设置为GZ,内容如下:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: gorm-demo
name: gorm-demo
spec:
selector:
matchLabels:
app: gorm-demo
template:
metadata:
labels:
app: gorm-demo
spec:
containers:
- image: swr.cn-south-1.myhuaweicloud.com/migrator/gorm-demo:latest
name: gorm-demo
imagePullPolicy: Always
ports:
- containerPort: 8080
protocol: TCP
env:
- name: DATA_CENTER
value: "GZ"
- name: MYSQL_HOST
value: mysql.example.com
- name: MYSQL_PASSWORD
value: *****************your_password*****************
- name: MYSQL_USER
value: demo
resources:
limits:
cpu: 500m
memory: 500Mi
requests:
cpu: 100m
memory: 128Mi
livenessProbe:
failureThreshold: 30
httpGet:
path: /products
port: 8080
scheme: HTTP
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 3
readinessProbe:
failureThreshold: 3
httpGet:
path: /products
port: 8080
scheme: HTTP
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 3
---
apiVersion: v1
kind: Service
metadata:
name: gorm-demo
spec:
ports:
- name: gorm-demo
port: 80
protocol: TCP
targetPort: 8080
selector:
app: gorm-demo
type: ClusterIP
上海应用的kubernetes yaml,环境变量DATA_CENTER设置为SH,内容如下:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: gorm-demo
name: gorm-demo
spec:
selector:
matchLabels:
app: gorm-demo
template:
metadata:
labels:
app: gorm-demo
spec:
containers:
- image: swr.cn-south-1.myhuaweicloud.com/migrator/gorm-demo:latest
name: gorm-demo
imagePullPolicy: Always
ports:
- containerPort: 8080
protocol: TCP
env:
- name: DATA_CENTER
value: "SH"
- name: MYSQL_HOST
value: mysql.example.com
- name: MYSQL_PASSWORD
value: *****************your_password*****************
- name: MYSQL_USER
value: demo
resources:
limits:
cpu: 500m
memory: 500Mi
requests:
cpu: 100m
memory: 128Mi
livenessProbe:
failureThreshold: 30
httpGet:
path: /products
port: 8080
scheme: HTTP
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 3
readinessProbe:
failureThreshold: 3
httpGet:
path: /products
port: 8080
scheme: HTTP
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 3
---
apiVersion: v1
kind: Service
metadata:
name: gorm-demo
spec:
ports:
- name: gorm-demo
port: 80
protocol: TCP
targetPort: 8080
selector:
app: gorm-demo
type: ClusterIP
3.6 公网访问效果
4 模拟源端数据故障
直接在web控制台,停止广州数据库实例:
会发现,应用的pod的状态变成非就绪,因为探针接口会访问数据库,数据库不可用则探针失败:
很显然,此时如果访问公网域名,ELB会返回如下响应,因为它对后端pod的健康检查失败:
此时,关闭DRS的容灾任务,让上海数据库实例变成正常状态:
接着,不修改广州应用的环境变量配置,只需要将广州地域的数据库域名修改成上海数据库的公网地址:
发现广州的pod又重新就绪了:
接着,不修改上海应用的环境变量配置,只需要将上海地域的数据库域名修改成上海数据库的内网地址:
发现上海的pod又重新就绪了:
此时,重新访问外部域名,服务又正常了:
现在系统的架构变成这样了:
5 小结
单边写的应用双活,是落地性比较大的一种双活架构。加之通过域名来屏蔽数据库IP的变化,进一步减少了故障转移时的应用配置的变化,应用配置变化越少,RTO则越短。