Longhorn跨AZ实现存储高可用

Longhorn跨AZ实现存储高可用

longhorn基础组件功能及其作用这里就不做介绍了

方案一

  • Longhorn跨AZ的高可用的就是一个PVC的replicas 均匀打散的不同的AZ区域之间,这样当某个AZ挂掉后,engine会立即使用另外一个数据副本,并重建这个副本,但是目前的关键点是如何将replica均匀打散到不同的AZ区域
  • 为保证最大程度上的跨AZ数据高可用,这里列出关于longhorn关键参数(仅供参考)
shell 复制代码
	# replica-soft-anti-affinity
	是否允许replica跑在使用pv的节点上

# default-replica-count	
	设置pv数据副本个数

# default-data-locality
	是否允许replica跑在使用pv的节点上

# auto-salvage
	当所有副本挂掉,时候允许longhorn找出可用的副本

# auto-delete-pod-when-volume-detached-unexpectedly
	如果启用,当Longhorn卷意外分离(例如Kubernetes升级、Docker重启或网络断开)时,Longhorn将自动删除由控制器管理的工作负载pod。通过删除pod,其控制器将重新启动pod, Kubernetes将处理卷的重新连接和重新挂载

# disable-scheduling-on-cordoned-node
	禁止在cordon节点安排replica

# `replica-zone-soft-anti-affinity`    实现跨AZ高可用关键参数
	允许将卷的新副本调度到与现有健康副本相同区域中的节点。不属于任何Zone的节点将被视为属于同一个Zone。注意Longhorn依赖于标签拓扑。topology.kubernetes.io/zone=<Zone name of the node>

方案二

  • 使用longhorn的backup/restore功能,但是随着数据量的增加,RTO时间具体需要多久待测试,且由于backup是定时或某个时刻手动触发的,RPO大小取决于备份完成后到发生故障这段时间具体产生了多少数据。且用户是否能容忍丢失这个数据量?

  • 验证略

方案一验证

  • 验证跨区域高可用(这里我们用topology.kubernetes.io/zone来模拟不同的zone)
  • Longhorn需要开启:replica-zone-soft-anti-affinity参数,实现replica跨AZ数据同步
  • 这里仅验证replica在某个AZ down是否可用,某个AZ内replica down了,实测是会重构replica,这里不做验证了
shell 复制代码
# 查看k8s节点
╰─ kubectl get nodes -o custom-columns=NAME:.metadata.name,LABELS:.metadata.labels
NAME           LABELS
k8s-master-1   map[beta.kubernetes.io/arch:arm64 beta.kubernetes.io/os:linux kubernetes.io/arch:arm64 kubernetes.io/hostname:k8s-master-1 kubernetes.io/os:linux]
k8s-node-1     map[beta.kubernetes.io/arch:arm64 beta.kubernetes.io/os:linux kubernetes.io/arch:arm64 kubernetes.io/hostname:k8s-node-1 kubernetes.io/os:linux]
k8s-node-2     map[beta.kubernetes.io/arch:arm64 beta.kubernetes.io/os:linux kubernetes.io/arch:arm64 kubernetes.io/hostname:k8s-node-2 kubernetes.io/os:linux]
k8s-node-3     map[beta.kubernetes.io/arch:arm64 beta.kubernetes.io/os:linux kubernetes.io/arch:arm64 kubernetes.io/hostname:k8s-node-3 kubernetes.io/os:linux]

# 设置节点zone
	kubectl label nodes k8s-master-1 k8s-node-1 topology.kubernetes.io/zone=one --overwrite
	kubectl label nodes k8s-node-2 k8s-node-3 topology.kubernetes.io/zone=two --overwrite

# 测试YAML
╰─ cat mysql.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pvc
  namespace: devops
spec:
  storageClassName: longhorn
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
  namespace: devops
spec:
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - image: docker.io/library/mysql:8.2
        name: mysql
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: password
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: data
          mountPath: /var/lib/mysql
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: mysql-pvc
---


通过上图我们可以发现:

  1. 我们事先打的zone标签,longhorn识别了
  2. 我们在创建mysql后,查看pv信息可以发现,replica分布在二个不同的ZONE区域
shell 复制代码
# 生成1000条数据
cat > 1.sql <<"EOF"
CREATE DATABASE `test_bai`;
USE `test_bai`;
CREATE TABLE `app_user`(
    `id` INT  NOT NULL AUTO_INCREMENT COMMENT '主键',
    `name` VARCHAR(50) DEFAULT '' COMMENT '用户名称',
    `email` VARCHAR(50) NOT NULL COMMENT '邮箱',
    `phone` VARCHAR(20) DEFAULT '' COMMENT '手机号',
    `gender` TINYINT DEFAULT '0' COMMENT '性别(0-男  : 1-女)',
    `password` VARCHAR(100) NOT NULL COMMENT '密码',
    `age` TINYINT DEFAULT '0' COMMENT '年龄',
    `create_time` DATETIME DEFAULT NOW(),
    `update_time` DATETIME DEFAULT NOW(),
    PRIMARY KEY (`id`)
)ENGINE = INNODB DEFAULT CHARSET = utf8 COMMENT='app用户表';
SET GLOBAL log_bin_trust_function_creators=TRUE;
DELIMITER $$
CREATE FUNCTION mock_data()
RETURNS INT
BEGIN
    DECLARE num INT DEFAULT 1000;
    DECLARE i INT DEFAULT 0;

    WHILE i < num DO
         INSERT INTO app_user(`name`,`email`,`phone`,`gender`,`password`,`age`)
         VALUES(CONCAT('用户',i),'2548928007qq.com',CONCAT('18',FLOOR(RAND() * ((999999999 - 100000000) + 1000000000))),FLOOR(RAND()  *  2),UUID(),FLOOR(RAND()  *  100));
        SET i =  i + 1;
    END WHILE;
    RETURN i;
END;
SELECT mock_data();
EOF

# 导入数据
bash-4.4# mysql -uroot -ppassword < 1.sql
mysql: [Warning] Using a password on the command line interface can be insecure.
mock_data()
1000

将k8s-node-3/k8s-node-2节点关机(模拟zone-two down,mysql目前也跑在这个zone)

shell 复制代码
# 等待controller-manager驱逐mysql后,在zone-one启动mysql
╰─ kubectl get pods -n devops -o wide | grep mysql 
mysql-7bc9bc8b55-g7jn8                   1/1     Running   0                   118s    172.16.1.85    k8s-node-1     <none>           <none>

# mysql 调度到k8s-node-1后,查询数据量大小
bash-4.4# mysql -uroot -ppassword -e "use test_bai; select count(*) from app_user;"
mysql: [Warning] Using a password on the command line interface can be insecure.
+----------+
| count(*) |
+----------+
|     1000 |
+----------+

通过上述测试我们可以发现

  • 当zone-two down后,pv的replica被标志为失败,且会在zone-one找一个节点去复制pv的replica来保证replica=2(即使我们配置了replica不能在同一个zone)
  • 数据量大小也一致(未发生数据丢失),这里仅做了小数据验证

注意:节点异常->apiserver感知->controller-manager驱逐mysql是存在一段间隔时间的(取决于controller-manager和kubelet上报节点状态信息间隔等参数),这段时间实际上是无法访问的

相关推荐
JuiceFS15 小时前
从 MLPerf Storage v2.0 看 AI 训练中的存储性能与扩展能力
运维·后端
chen94520 小时前
mysql 3节点mgr集群部署
运维·后端
LH_R21 小时前
OneTerm开源堡垒机实战(三):功能扩展与效率提升
运维·后端·安全
dessler1 天前
Hadoop HDFS-高可用集群部署
linux·运维·hdfs
资源开发与学习2 天前
Kubernetes集群核心概念 Service
kubernetes
少妇的美梦2 天前
logstash教程
运维
容器魔方2 天前
Bloomberg 正式加入 Karmada 用户组!
云原生·容器·云计算
chen9452 天前
k8s集群部署vector日志采集器
运维
chen9452 天前
aws ec2部署harbor,使用s3存储
运维
muyun28002 天前
Docker 下部署 Elasticsearch 8 并集成 Kibana 和 IK 分词器
elasticsearch·docker·容器