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"}}}'


