K3S存储Longhorn

针对K3S集群来说,存储肯定不能直接使用本地磁盘,因为一旦这台机器故障,pod漂移走了,那么数据就没了,还有很多分布式存储,比如Cept(功能强,但是维护复杂),NFS(性能差),如果公司已有 SAN、分布式存储,直接用其 CSI 驱动,最稳,K3S推荐的官方存储是Longhorn

Longhorn也是Rancher开发的存储,跟K3S是同一家公司开发,完美适配K3S和K8S,优点如下:

  • 分布式块存储
  • 多副本(1/2/3 副本)
  • 节点挂了,Pod 飘到别的节点,数据自动挂载
  • 自带备份、快照、恢复
  • 有 Web UI
  • 资源占用低,适合内网

Longhorn原理:

Longhorn 本质就是用各个节点的本地磁盘,拼成一个分布式高可用存储

  • 它会把 K3s 集群里每台机器的空闲磁盘 / 分区拿出来
  • 统一管理,变成一个虚拟的分布式块存储池
  • 创建 PVC 时,它就在这些本地盘里划空间给 Pod

部署

1、先给所有的k3s-master01节点打上污点,禁止调度,如下:

kubectl taint nodes k3s-master01 node-role.kubernetes.io/control-plane=:NoSchedule
kubectl taint nodes k3s-master02 node-role.kubernetes.io/control-plane=:NoSchedule
kubectl taint nodes k3s-master03 node-role.kubernetes.io/control-plane=:NoSchedule

2、在worker节点安装依赖,如下:

apt update
apt install -y open-iscsi nfs-common xfsprogs
systemctl enable --now iscsid

3、给worker节点打上标签,如下:

kubectl label node k3s-node01 k3s-node02 node-role.kubernetes.io/worker=storage

4、使用官方yaml一键安装Longhorn,如下:

kubectl apply -f https://raw.githubusercontent.com/longhorn/longhorn/v1.7.2/deploy/longhorn.yaml

执行后验证是否启动正常,如下:

kubectl get pods -n longhorn-system

注:很多镜像需要单独下载回来的

查看自动创建的StorageClass,如图:

  • (default) 代表:集群默认存储类,没指定 sc 时自动用 longhorn

开启Longhorn web

K3s 默认集成了 Traefik 作为 Ingress Controller,通过 Ingress 暴露 Longhorn UI 是最标准的做法。因此不需要修改 Longhorn 的任何服务配置,直接创建一条路由规则即可

1、在创建 Ingress 前,先确认 longhorn-frontend服务状态正常:

kubectl get svc -n longhorn-system longhorn-frontend

预期输出(Type 应为 ClusterIP,Port 为 80):

NAME                TYPE        CLUSTER-IP      PORT(S)
longhorn-frontend   ClusterIP   10.43.xxx.xxx   80/TCP

2、编辑ingress文件longhorn-ingress.yaml,配置域名规则,如下:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: longhorn-ingress
  namespace: longhorn-system
  annotations:
    # 可选:如果你希望访问时带基本认证(用户名/密码),取消注释以下两行
    # ingress.kubernetes.io/auth-type: "basic"
    # ingress.kubernetes.io/auth-secret: longhorn-auth
spec:
  ingressClassName: traefik  # K3s 默认的 Ingress Class
  rules:
  - host: longhorn.oa.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: longhorn-frontend
            port:
              number: 80

执行:

kubectl apply -f longhorn-ingress.yaml

配置域名解析到192.168.51.72(Metallb分配的IP),最后通过域名访问,如下:

3、修改Longhorn的数据目录,默认情况下使用的是系统跑的/var/lib/longhorn,现在修改为数据盘,首先创建目录:

mkdir -p /data/longhorn && chmod 755 /data/longhorn  #两个worker节点都要执行

4、登录web ui界面,点击Node,先构建一个节点,然后点击右侧的Edit node and disks,如图:

将之前调度到系统盘的修改为Disable,然后点击Add Disk,如图:

新增磁盘设置预留空间,并开启调度:

  • Storage Reserved:存储预留的,Longhorn不会动,给其他系统用的
  • Scheduling:开启调度

最后查看节点信息,总量199.9G,可使用149.9,已使用0,如图:

注:Longhorn 是集群级别的应用,它实际上运行的是 DaemonSet(一种每个节点跑一个实例的控制器)。只要新节点加入集群,Longhorn 的 Agent(longhorn-manager)就会自动调度到新节点上运行,前提是要规划好资源,比如,创建好磁盘目录,安装好依赖iSCSI

取消默认存储类local-path

Kubernetes 有一个“兜底”机制:当你创建 PVC(申请存储)时,如果没有写 storageClassName字段,系统会自动找一个带有 (default)标记的 StorageClass 来用,查看当前存储类,如图:

查看local-path是否是默认类,也是true,如图:

从上图看出,两个都是default,因此如果在申请PVC的时候没有指定stroageClassName字段,那就可能会走默认的local-path,这个是本地路径,如果pod漂移了,数据就没有了,因此需要将这个默认存储类取消,只保留一个longhorn,执行如下命令:

kubectl patch storageclass local-path -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"false"}}}'

附加:如果longhorn不是默认存储类,可以通过命令设置让它默认,如下:

kubectl patch storageclass longhorn -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'

标签