Longhorn 是一个 Kubernetes 原生分布式块存储系统

你可以把它理解成:

把每个节点上的本地磁盘组合成一个分布式存储池
PVC 创建出来后,Longhorn 会给这个卷做多个副本
某个节点挂了,只要还有副本,卷还能在其他节点重新挂载

它比 NFS 更适合你现在的目标,因为你想要高可用。

不过先说明:Longhorn 做的是 存储层高可用,不是数据库自动主从。
比如 PostgreSQL 用一个 Longhorn PVC,Longhorn 可以保证磁盘卷有多个副本;但同一时刻这个卷还是通常只挂到一个 PostgreSQL Pod。PostgreSQL 自身高可用以后可以再用 CloudNativePG。


Longhorn 前提要求

Longhorn 官方要求每个节点满足:

Kubernetes >= 1.25
containerd 可用
每个节点安装 open-iscsi,并运行 iscsid
RWX 支持需要 NFSv4 client
节点文件系统支持 ext4 或 XFS
Longhorn 组件需要 privileged/root 权限

你的环境是 Ubuntu 22.04 + kubeadm,适合安装。


一、三台节点都安装依赖

在三台节点都执行:

sudo apt update
sudo apt install -y open-iscsi nfs-common jq curl util-linux

启用 iSCSI:

sudo systemctl enable --now iscsid
sudo systemctl start iscsid

加载模块:

sudo modprobe iscsi_tcp

设置开机加载:

echo iscsi_tcp | sudo tee /etc/modules-load.d/iscsi_tcp.conf

检查:

systemctl status iscsid --no-pager
which iscsiadm

二、建议准备 Longhorn 数据目录

Longhorn 默认数据目录是: 默认不存在

/var/lib/longhorn

如果你的系统盘空间够,可以先用默认目录。

三台都执行:

sudo mkdir -p /var/lib/longhorn

如果你后面有单独数据盘,更推荐挂载到:

/var/lib/longhorn

并写入 /etc/fstab,保证重启后自动挂载。


三、安装 Longhorn

添加 Helm 仓库:

helm repo add longhorn https://charts.longhorn.io
helm repo update

安装:

helm upgrade --install longhorn longhorn/longhorn \
  --namespace longhorn-system \
  --create-namespace \
  --set persistence.defaultClass=true \
  --set persistence.defaultClassReplicaCount=3 \
  --set defaultSettings.defaultReplicaCount=3 \
  --set defaultSettings.defaultDataPath=/var/lib/longhorn

解释:

persistence.defaultClass=true
把 longhorn 设置为默认 StorageClass。

persistence.defaultClassReplicaCount=3
新建 PVC 默认 3 副本。

defaultSettings.defaultReplicaCount=3
Longhorn 默认卷副本数 3。

defaultSettings.defaultDataPath=/var/lib/longhorn
Longhorn 数据存放目录。

四、等待 Longhorn 启动

kubectl get pods -n longhorn-system -o wide

等待全部 Running:

kubectl wait --for=condition=ready pod \
  --all \
  -n longhorn-system \
  --timeout=600s

如果某些 Pod 一直没好,查看:

kubectl get pods -n longhorn-system -o wide
kubectl describe pod -n longhorn-system Pod名
kubectl logs -n longhorn-system Pod名

五、检查 StorageClass

kubectl get storageclass

应该看到:

longhorn (default)

如果以后还有别的默认 StorageClass,要保证只有一个 default。

如果你之前装过 local-path,要取消它默认:

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

六、暴露 Longhorn UI

Longhorn 自带 Web UI。建议通过你已经装好的 ingress-nginx 暴露。

先看 Service:

kubectl get svc -n longhorn-system

应该有:

longhorn-frontend

创建 Ingress:

cat <<'EOF' | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: longhorn-ui
  namespace: longhorn-system
spec:
  ingressClassName: nginx
  rules:
    - host: longhorn.k8s.local
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: longhorn-frontend
                port:
                  number: 80
EOF

查 ingress-nginx 的 EXTERNAL-IP:

kubectl get svc -n ingress-nginx ingress-nginx-controller

假设是:

192.168.3.230

在 Windows hosts 加:

192.168.3.230 longhorn.k8s.local

然后浏览器访问:

http://longhorn.k8s.local

注意:Longhorn UI 默认没有认证。家庭内网可以先用,后面要加 Basic Auth 或只内网访问。


七、创建 PVC 测试

kubectl create namespace storage-test

创建 PVC:

cat <<'EOF' | kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: longhorn-test-pvc
  namespace: storage-test
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: longhorn
  resources:
    requests:
      storage: 1Gi
EOF

创建测试 Pod:

cat <<'EOF' | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: longhorn-test-pod
  namespace: storage-test
spec:
  containers:
    - name: busybox
      image: busybox:latest
      command: ["sh", "-c", "echo hello-longhorn > /data/test.txt && sleep 3600"]
      volumeMounts:
        - name: data
          mountPath: /data
  volumes:
    - name: data
      persistentVolumeClaim:
        claimName: longhorn-test-pvc
EOF

检查:

kubectl get pod,pvc -n storage-test -o wide
kubectl get pv

读取文件:

kubectl exec -n storage-test longhorn-test-pod -- cat /data/test.txt

应输出:

hello-longhorn

八、测试存储高可用

查看 Pod 在哪个节点:

kubectl get pod longhorn-test-pod -n storage-test -o wide

然后可以删除 Pod,让它重建测试卷是否能重新挂载。因为这是普通 Pod,不会自动重建,所以更推荐用 Deployment 测试。

简单先做删除重建:

kubectl delete pod longhorn-test-pod -n storage-test

重新创建刚才的 Pod YAML,再读取:

kubectl exec -n storage-test longhorn-test-pod -- cat /data/test.txt

如果还能读到:

hello-longhorn

说明数据持久化正常。

节点级故障测试可以后面再做,别一开始就直接断电数据库节点。


九、清理测试资源

kubectl delete namespace storage-test

十、Longhorn 对 new-api 的意义

安装 Longhorn 后,后续 PostgreSQL/Redis 的 Helm Chart 可以直接用:

storageClass: longhorn

这样数据库 PVC 会由 Longhorn 管理,并默认 3 副本。

后续我们会这样装:

PostgreSQL PVC -> Longhorn 3 replicas
Redis PVC -> Longhorn 3 replicas
new-api Deployment -> 无状态多副本

不过再提醒一次:

Longhorn 保证卷副本高可用
PostgreSQL 真正的数据库主备高可用以后要用 CloudNativePG

当前阶段先用 Longhorn 作为高可用存储,把 Helm PostgreSQL/Redis 跑起来是合理的。


官方参考: