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上报节点状态信息间隔等参数),这段时间实际上是无法访问的

相关推荐
GJCTYU18 分钟前
阿里云多端低代码开发平台魔笔使用测评
低代码·阿里云·云原生·容器·serverless·云计算
铁锤妹妹头发多1 小时前
新手用docker真**难受
运维·docker·容器
超栈1 小时前
HCIP(11)-期中综合实验(BGP、Peer、OSPF、VLAN、IP、Route-Policy)
运维·网络·网络协议·计算机网络·web安全·网络安全·信息与通信
Cachel wood1 小时前
Github配置ssh key原理及操作步骤
运维·开发语言·数据库·windows·postgresql·ssh·github
编程一生1 小时前
回调数据丢了?
运维·服务器·前端
华为云PaaS服务小智1 小时前
华为大咖说 | 浅谈智能运维技术
运维·华为·华为云
zhd15306915625ff3 小时前
化工厂主要涉及的自动化备件有哪些?
运维·自动化·化工厂
Jason-河山3 小时前
利用API返回值实现商品信息自动化更新:技术与实践
运维·自动化
wowocpp4 小时前
查看 linux ubuntu 分区 和 挂载 情况 lsblk
linux·运维·ubuntu
_.Switch8 小时前
高级Python自动化运维:容器安全与网络策略的深度解析
运维·网络·python·安全·自动化·devops