Kubernetes + iSCSI 静态存储实施全指南

作者:Administrator 发布时间: 2025-11-22 阅读量:9 评论数:0

1. iSCSI 核心概念(必读)

在配置 Kubernetes 存储之前,理解 iSCSI 的层级关系至关重要。这有助于理解 YAML 文件中 iqnlun 参数的含义。

1.1 核心组件

  • Initiator (发起端):即你的 Kubernetes 节点。它是客户端,负责去“连接”存储。
  • Target (目标):即你的 Fons 存储服务端的一个访问点
    • 通俗理解:你可以把 Target 想象成一个 “用户账户”“USB 集线器”
    • 它是连接的入口,拥有全球唯一的名称(IQN)。
    • Kubernetes 必须先登录这个 Target,才能看到里面的磁盘。
  • LUN (逻辑单元号):即 实际的存储空间/磁盘卷
    • 通俗理解:LUN 就是插在“USB 集线器”上的 U盘
    • Target 只是门,LUN 才是真正存数据的房间。

1.2 Target 与 LUN 的绑定关系

一个 Target 可以绑定多个 LUN。这就是为什么在 YAML 中 iqnlun 是分开配置的。

  • 一对一 (One-to-One):这是最简单、最推荐给 K8s 使用的模式。一个 Target 只挂载一个 LUN。
    • 此时,该 LUN 的编号永远是 0
  • 一对多 (One-to-Many):一个 Target 挂载了多个磁盘卷。
    • 编号逻辑:LUN 的 ID 通常取决于绑定顺序(在 Fons/Linux LIO 等系统中常见)。
    • 第 1 个绑定的卷 -> LUN 0
    • 第 2 个绑定的卷 -> LUN 1
    • 第 3 个绑定的卷 -> LUN 2

⚠️ 之前的故障复盘:

你之前在 Fons 上创建了一个名为 target-2 的目标,但它是你创建的第 3 个 Target。

你在 K8s YAML 中填了 lun: 2,以为名字带 "2" 就是 LUN 2。

这是错误的。 因为在这个 target-2 内部,你只挂载了一块盘。根据顺序逻辑,这块唯一的盘就是 LUN 0。

所以,绝大多数情况下,除非你在同一个 Target 下挂了多块盘,否则 YAML 里的 lun 永远填 0。


2. 节点准备工作(所有节点)

必须在所有 K8s Worker 节点执行以下操作,否则 Pod 无法挂载磁盘。

2.1 安装 iSCSI 客户端工具

# Ubuntu / Debian
sudo apt-get update
sudo apt-get install -y open-iscsi
sudo systemctl enable --now iscsid

# CentOS / RHEL
sudo yum install -y iscsi-initiator-utils
sudo systemctl enable --now iscsid

3. 磁盘初始化(关键步骤)

为了规避 Kubernetes 在自动挂载时可能发生的 mkfs.ext4: Input/Output error 或超时错误,我们需要在 Linux 层面手动提前格式化磁盘。

请找任意一台安装了上述工具的节点执行:

3.1 格式化 PostgreSQL 磁盘 (8Gi)

假设这是你分配给 Target-2 的盘。

# 1. 发现 Target
sudo iscsiadm -m discovery -t sendtargets -p 192.168.6.157:3260

# 2. 登录 Target-2
# 登录也就是“插上 USB 集线器”
sudo iscsiadm -m node -T iqn.2025-11.com.fnnas:target-2.um5v1y55fuww -p 192.168.6.157:3260 -l

# 3. 确认磁盘设备
# 既然是 Target 下的第一块盘,它就是 LUN 0。系统会识别为一个 sdX 设备。
lsblk 
# (找到 8Gi 的那个盘,假设是 /dev/sdb)

# 4. 格式化为 ext4 (警告:数据会清空)
sudo mkfs.ext4 /dev/sdb

# 5. 【重要】注销连接 (防止设备占用)
# 格式化完必须“拔掉”,否则 K8s 稍后会认为设备正忙。
sudo iscsiadm -m node -T iqn.2025-11.com.fnnas:target-2.um5v1y55fuww -p 192.168.6.157:3260 -u

3.2 格式化 Halo 磁盘 (10Gi)

假设这是你分配给 Target-3 的盘。

# 1. 登录 Target-3
sudo iscsiadm -m node -T iqn.2025-11.com.fnnas:target-3.ta85oymzy6vq -p 192.168.6.157:3260 -l

# 2. 确认磁盘设备 (找 10Gi 的盘)
lsblk

# 3. 格式化
sudo mkfs.ext4 /dev/sdb

# 4. 【重要】注销连接
sudo iscsiadm -m node -T iqn.2025-11.com.fnnas:target-3.ta85oymzy6vq -p 192.168.6.157:3260 -u

4. Kubernetes 资源部署

4.1 PV 与 PVC 的使用逻辑

  • PV (PersistentVolume):是对底层存储(Fons iSCSI)的描述。我们需要在这里告诉 K8s:去连哪个 Target (IQN),找第几个 LUN (通常是 0)。
  • PVC (PersistentVolumeClaim):是 Pod 对存储的申请书。
  • 绑定:我们通过 claimRef 字段,强行把这两个东西绑在一起,防止 K8s 乱点鸳鸯谱。

4.2 创建 PersistentVolume (PV)

将以下内容保存为 pv.yaml 并应用。

apiVersion: v1
kind: PersistentVolume
metadata:
  name: halo-postgresql-iscsi-pv
spec:
  capacity:
    storage: 8Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: ""  # 必须留空,因为我们手动管理
  claimRef:             # 【关键】强制绑定到指定的 PVC
    name: data-halo-postgresql-0
    namespace: halo
  iscsi:
    targetPortal: 192.168.6.157:3260
    iqn: iqn.2025-11.com.fnnas:target-2.um5v1y55fuww
    # 【重点】这里填 0,因为这块 8G 盘是你在这个 Target 下绑定的第一块盘
    lun: 0              
    fsType: ext4
    readOnly: false

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: halo-iscsi-pv
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: ""
  claimRef:
    name: halo
    namespace: halo
  iscsi:
    targetPortal: 192.168.6.157:3260
    iqn: iqn.2025-11.com.fnnas:target-3.ta85oymzy6vq
    lun: 0
    fsType: ext4
    readOnly: false

4.3 创建 PersistentVolumeClaim (PVC)

将以下内容保存为 pvc.yaml 并应用。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: data-halo-postgresql-0  # 名字必须与 StatefulSet 要求的一致
  namespace: halo
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 8Gi
  storageClassName: ""          # 必须为空
  volumeName: halo-postgresql-iscsi-pv # 反向指定 PV,确保双向绑定

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: halo
  namespace: halo
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  storageClassName: ""
  volumeName: halo-iscsi-pv

5. 常见问题排查 (Troubleshooting)

现象原因解决方案
Pending, executable file not found节点未安装 iSCSI 工具在所有 Node 执行 apt/yum install open-iscsi
Timed out waiting for deviceLUN ID 错误检查 YAML 中的 lun。如果你每个 Target 只给了一块盘,lun 必须填 0,无论 Target 叫什么名字。
mkfs.ext4: Input/Output error网络波动或自动格式化失败按照本文第 3 节,手动在节点上 mkfs,然后重启 Pod。
iscsiadm: No records found未执行发现操作执行 sudo iscsiadm -m discovery -t sendtargets -p <IP>
session already present之前的连接未断开执行 sudo iscsiadm -m node -u 强制注销。
删除 PVC 后 PV 显示 ReleasedRetain 策略的保护机制kubectl edit pv xxx,删除 claimRef 字段下的所有内容,保存后 PV 会变为 Available。

评论