Kubernetes Pod 挂载windows共享目录

一、适用场景

本文档适用于以下场景:

应用运行在 Kubernetes 集群中,需要让 Pod 访问某个外部共享目录,例如 Windows SMB/CIFS 共享目录。
操作方式为:

  1. 先在指定 Kubernetes 节点上挂载外部共享目录;
  2. 再通过 hostPath 将节点本地目录挂载到 Pod 内;
  3. 使用 nodeSelector 限制 Pod 只能调度到已完成挂载的节点上。

二、整体架构说明

外部共享目录:

//<共享服务器IP>/<共享目录路径>

挂载到 Kubernetes 节点本地目录:

/<本地挂载目录>

再通过 Kubernetes hostPath 挂载到 Pod 内:

/<Pod内访问目录>

整体关系如下:

Windows / SMB 共享目录
        ↓
Kubernetes 节点本地挂载目录
        ↓
Pod 内目录

示例:

//<共享服务器IP>/<共享目录路径>
        ↓
<Node节点>:/<本地挂载目录>
        ↓
Pod:/<Pod内访问目录>

三、前置准备

1. 确认共享目录信息

需要提前确认以下信息:

项目示例
共享服务器地址<共享服务器IP>
共享目录路径//<共享服务器IP>/<共享目录路径>
共享账号<共享账号>
共享密码<共享密码>
Kubernetes 节点 IP<节点IP1><节点IP2>
节点本地挂载目录/<本地挂载目录>
Pod 内挂载目录/<Pod内访问目录>

2. 确认需要绑定的 Kubernetes 节点

查看节点列表:

kubectl get nodes -o wide

根据内网 IP 找到对应节点:

kubectl get nodes -o wide | grep <节点IP>

如果节点名就是 IP,后续可以直接使用该 IP 作为节点名。


四、在 Kubernetes 节点上挂载 SMB/CIFS 共享目录

以下操作需要在所有目标节点上执行。

例如目标节点为:

<节点IP1>
<节点IP2>

需要分别登录每台节点执行。


1. 安装 CIFS 工具

CentOS / TencentOS / RedHat 系统:

yum install -y cifs-utils

Ubuntu / Debian 系统:

apt-get update
apt-get install -y cifs-utils

2. 创建本地挂载目录

mkdir -p /<本地挂载目录>

示例:

mkdir -p /share-data

检查目录:

ls -ld /<本地挂载目录>

3. 创建 SMB 认证文件

建议不要直接把账号密码写到 /etc/fstab 中,而是放到独立认证文件。

cat > /root/.smbcred <<'EOF'
username=<共享账号>
password=<共享密码>
domain=<域名或工作组>
EOF

chmod 600 /root/.smbcred

如果没有域名,可以写成:

cat > /root/.smbcred <<'EOF'
username=<共享账号>
password=<共享密码>
EOF

chmod 600 /root/.smbcred

4. 手动测试挂载

mount -t cifs "//<共享服务器IP>/<共享目录路径>" /<本地挂载目录> \
-o credentials=/root/.smbcred,iocharset=utf8,vers=3.0,uid=0,gid=0,file_mode=0777,dir_mode=0777,noperm

示例格式:

mount -t cifs "//<共享服务器IP>/<共享目录路径>" /share-data \
-o credentials=/root/.smbcred,iocharset=utf8,vers=3.0,uid=0,gid=0,file_mode=0777,dir_mode=0777,noperm

5. 验证挂载结果

df -hT | grep <共享服务器IP>
mount | grep <共享服务器IP>
ls -l /<本地挂载目录>

正常情况下,df -hT 中应该能看到文件系统类型为:

cifs

如果可以看到共享目录里的文件,说明挂载成功。


6. SMB 版本兼容处理

如果 vers=3.0 挂载失败,可以尝试:

umount /<本地挂载目录>

然后改用:

vers=2.1

或:

vers=2.0

例如:

mount -t cifs "//<共享服务器IP>/<共享目录路径>" /<本地挂载目录> \
-o credentials=/root/.smbcred,iocharset=utf8,vers=2.1,uid=0,gid=0,file_mode=0777,dir_mode=0777,noperm

实际使用哪个版本,以测试成功为准。


五、配置开机自动挂载

确认手动挂载成功后,再配置 /etc/fstab

1. 备份 fstab

cp /etc/fstab /etc/fstab.bak.$(date +%F_%H%M%S)

2. 追加自动挂载配置

cat >> /etc/fstab <<'EOF'
//<共享服务器IP>/<共享目录路径> /<本地挂载目录> cifs credentials=/root/.smbcred,iocharset=utf8,vers=3.0,uid=0,gid=0,file_mode=0777,dir_mode=0777,noperm,_netdev,nofail 0 0
EOF

示例格式:

cat >> /etc/fstab <<'EOF'
//<共享服务器IP>/<共享目录路径> /share-data cifs credentials=/root/.smbcred,iocharset=utf8,vers=3.0,uid=0,gid=0,file_mode=0777,dir_mode=0777,noperm,_netdev,nofail 0 0
EOF

说明:

参数说明
_netdev表示该挂载依赖网络
nofail避免共享目录异常导致系统启动失败
iocharset=utf8支持中文路径和中文文件名
file_mode=0777文件权限
dir_mode=0777目录权限
noperm客户端不做额外权限校验

3. 测试自动挂载配置

mount -a

检查:

df -hT | grep <共享服务器IP>
ls -l /<本地挂载目录>

六、给 Kubernetes 节点打标签

为了保证 Pod 只调度到已经完成共享目录挂载的节点,需要给这些节点打标签。

1. 确认当前集群

执行前先确认当前 kubectl 连接的是正确集群:

kubectl config current-context

2. 查看目标节点

kubectl get nodes -o wide | egrep '<节点IP1>|<节点IP2>'

3. 给节点打标签

kubectl label node <节点名称1> <标签key>=<标签value> --overwrite
kubectl label node <节点名称2> <标签key>=<标签value> --overwrite

示例:

kubectl label node <节点名称1> app-sharedata=true --overwrite
kubectl label node <节点名称2> app-sharedata=true --overwrite

如果节点名就是 IP,可以这样写:

kubectl label node <节点IP1> app-sharedata=true --overwrite
kubectl label node <节点IP2> app-sharedata=true --overwrite

4. 检查节点标签

kubectl get nodes -l <标签key>=<标签value> -o wide

示例:

kubectl get nodes -l app-sharedata=true -o wide

七、修改 Kubernetes Deployment YAML

1. 添加 nodeSelector

在 Deployment 的:

spec:
  template:
    spec:

下面添加:

      nodeSelector:
        <标签key>: "<标签value>"

示例:

      nodeSelector:
        app-sharedata: "true"

作用:
限制该 Pod 只能调度到带有该标签的节点上。


2. 添加 volumeMounts

在容器配置中添加:

          volumeMounts:
            - name: sharedata
              mountPath: /<Pod内访问目录>

示例:

          volumeMounts:
            - name: sharedata
              mountPath: /share-data

3. 添加 volumes

spec.template.spec 下,与 containers 同级添加:

      volumes:
        - name: sharedata
          hostPath:
            path: /<本地挂载目录>
            type: Directory

示例:

      volumes:
        - name: sharedata
          hostPath:
            path: /share-data
            type: Directory

八、Deployment YAML 通用模板

apiVersion: v1
kind: Service
metadata:
  name: <应用名称>
  namespace: <命名空间>
  labels:
    app: <应用名称>
spec:
  selector:
    app: <应用名称>
  ports:
    - name: http
      port: <Service端口>
      targetPort: <容器端口>
      protocol: TCP
  type: NodePort

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: <应用名称>
  namespace: <命名空间>
  labels:
    app: <应用名称>
spec:
  replicas: <副本数>
  selector:
    matchLabels:
      app: <应用名称>
  template:
    metadata:
      labels:
        app: <应用名称>
      annotations:
        cloud.tencent.com/inject-java: 'true'
        cloud.tencent.com/otel-service-name: <应用名称>
    spec:
      nodeSelector:
        <标签key>: "<标签value>"

      containers:
        - name: <应用名称>
          image: <镜像地址>:<镜像版本>
          imagePullPolicy: IfNotPresent
          env:
            - name: profile
              value: "<环境名称>"
            - name: JAVA_OPTION
              value: "-Dfile.encoding=UTF-8 -XX:+UseG1GC"
            - name: XMX
              value: "<最大堆内存>"
            - name: XMS
              value: "<初始堆内存>"
          ports:
            - containerPort: <容器端口>
              protocol: TCP
          resources:
            requests:
              cpu: <请求CPU>
              memory: <请求内存>
            limits:
              cpu: <限制CPU>
              memory: <限制内存>
          volumeMounts:
            - name: sharedata
              mountPath: /<Pod内访问目录>

      volumes:
        - name: sharedata
          hostPath:
            path: /<本地挂载目录>
            type: Directory

      imagePullSecrets:
        - name: <镜像仓库Secret名称>

九、发布前检查

发布前需要确认所有目标节点都已经成功挂载共享目录。

在每台目标节点执行:

df -hT /<本地挂载目录>

正常应该显示文件系统类型为:

cifs

继续检查:

mount | grep <共享服务器IP>
ls -l /<本地挂载目录>

如果 df -hT /<本地挂载目录> 显示的是:

xfs
ext4

而不是:

cifs

说明当前目录只是节点本地目录,并没有真正挂载到共享目录。


十、发布应用

kubectl apply -f <应用YAML文件名>.yaml

查看 Pod:

kubectl get pod -n <命名空间> -o wide

确认 Pod 所在节点必须是已打标签的节点。


十一、验证 Pod 内挂载

进入 Pod:

kubectl exec -it -n <命名空间> deploy/<Deployment名称> -- sh

查看挂载目录:

ls -l /<Pod内访问目录>

查看文件系统类型:

df -hT /<Pod内访问目录>

可以测试写入:

echo "k8s mount test $(date)" > /<Pod内访问目录>/k8s-mount-test.txt
cat /<Pod内访问目录>/k8s-mount-test.txt

测试完成后删除:

rm -f /<Pod内访问目录>/k8s-mount-test.txt

十二、注意事项

1. 容器内目录不需要提前存在

即使镜像中没有:

/<Pod内访问目录>

Kubernetes 在挂载时也会自动处理。

真正必须提前存在的是节点上的:

/<本地挂载目录>

并且该目录需要已经成功挂载外部共享目录。


2. 不建议使用 DirectoryOrCreate

建议使用:

type: Directory

不建议使用:

type: DirectoryOrCreate

原因是:

如果共享目录没有挂载成功,DirectoryOrCreate 可能会在节点上自动创建一个空目录。
这样 Pod 虽然能启动,但实际读写的是节点本地目录,不是共享目录,容易造成生产文件写错位置。


3. 多节点时每台节点都必须挂载

如果同一个标签打在多台节点上,例如:

app-sharedata=true

那么 Pod 可能会调度到任意一台带该标签的节点。

因此,每一台带该标签的节点都必须提前完成共享目录挂载。


4. hostPath 不是共享存储

hostPath 只是把节点上的本地路径挂进 Pod。
如果 Pod 被调度到不同节点,看到的是对应节点上的本地路径。

所以必须配合:

nodeSelector

或:

nodeAffinity

来限制 Pod 调度范围。


十三、回滚操作

1. 回滚 Deployment

kubectl rollout undo deployment/<Deployment名称> -n <命名空间>

查看回滚状态:

kubectl rollout status deployment/<Deployment名称> -n <命名空间>

2. 删除节点标签

kubectl label node <节点名称1> <标签key>-
kubectl label node <节点名称2> <标签key>-

示例:

kubectl label node <节点名称1> app-sharedata-
kubectl label node <节点名称2> app-sharedata-

3. 卸载共享目录

在节点上执行:

umount /<本地挂载目录>

如果提示 busy,查看占用进程:

lsof +f -- /<本地挂载目录>

或者:

fuser -vm /<本地挂载目录>

4. 删除 fstab 自动挂载配置

先备份:

cp /etc/fstab /etc/fstab.bak.$(date +%F_%H%M%S)

编辑:

vi /etc/fstab

删除对应挂载行:

//<共享服务器IP>/<共享目录路径> /<本地挂载目录> cifs credentials=/root/.smbcred,iocharset=utf8,vers=3.0,uid=0,gid=0,file_mode=0777,dir_mode=0777,noperm,_netdev,nofail 0 0

然后执行:

mount -a

确认没有异常。


十四、操作流程汇总

步骤操作执行位置
1确认共享服务器、共享目录、账号密码运维人员
2确认需要绑定的 Kubernetes 节点kubectl 客户端
3安装 cifs-utils目标节点
4创建本地挂载目录目标节点
5创建 SMB 认证文件目标节点
6手动挂载共享目录目标节点
7验证挂载类型是否为 cifs目标节点
8配置 /etc/fstab 自动挂载目标节点
9给目标节点打 Kubernetes 标签kubectl 客户端
10修改 Deployment YAMLGit 仓库 / 本地
11发布 Deploymentkubectl 客户端
12进入 Pod 验证目录kubectl 客户端

十五、关键命令模板

1. 节点挂载命令

mount -t cifs "//<共享服务器IP>/<共享目录路径>" /<本地挂载目录> \
-o credentials=/root/.smbcred,iocharset=utf8,vers=3.0,uid=0,gid=0,file_mode=0777,dir_mode=0777,noperm

2. fstab 配置模板

//<共享服务器IP>/<共享目录路径> /<本地挂载目录> cifs credentials=/root/.smbcred,iocharset=utf8,vers=3.0,uid=0,gid=0,file_mode=0777,dir_mode=0777,noperm,_netdev,nofail 0 0

3. 节点标签命令

kubectl label node <节点名称> <标签key>=<标签value> --overwrite

4. YAML 核心配置

nodeSelector:
  <标签key>: "<标签value>"
volumeMounts:
  - name: sharedata
    mountPath: /<Pod内访问目录>
volumes:
  - name: sharedata
    hostPath:
      path: /<本地挂载目录>
      type: Directory

十六、常见问题

1. Pod 启动失败,提示 hostPath 目录不存在

原因:节点上没有创建本地挂载目录,或者 Pod 被调度到了未挂载共享目录的节点。

处理:

ls -ld /<本地挂载目录>
df -hT /<本地挂载目录>
kubectl get pod -n <命名空间> -o wide

2. Pod 能启动,但目录里没有共享文件

原因:节点目录存在,但没有真正挂载到 SMB 共享目录。

处理:

df -hT /<本地挂载目录>

如果不是 cifs,需要重新挂载共享目录。


3. Pod 被调度到了错误节点

原因:节点标签配置错误,或者 Deployment 没有配置 nodeSelector

处理:

kubectl get nodes --show-labels | grep <标签key>
kubectl get pod -n <命名空间> -o wide
kubectl describe pod <Pod名称> -n <命名空间>

4. 中文路径无法访问

处理方式:

挂载参数中需要包含:

iocharset=utf8

同时确认 Linux 系统环境支持 UTF-8。

可以检查:

locale

5. 共享目录重启后丢失

原因:没有写入 /etc/fstab,或者 /etc/fstab 配置错误。

处理:

mount -a
df -hT /<本地挂载目录>

确认 /etc/fstab 中存在正确配置。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇