无法在本地种类集群中挂载本地主机路径
Cant mount local host path in local kind cluster
下面是我的kubernetes文件,我需要做两件事
- 需要挂载一个包含文件的文件夹
- 需要用启动脚本挂载文件
我的本地 /tmp/zoo 文件夹中的文件和我的 zoo 文件夹文件从未出现在 pod 内的 /bitnami/zookeeper 中。
下面是更新后的Service、Deployment、PVC和PV
kubernetes.yaml
apiVersion: v1
items:
- apiVersion: v1
kind: Service
metadata:
annotations:
kompose.service.type: nodeport
creationTimestamp: null
labels:
io.kompose.service: zookeeper
name: zookeeper
spec:
ports:
- name: "2181"
port: 2181
targetPort: 2181
selector:
io.kompose.service: zookeeper
type: NodePort
status:
loadBalancer: {}
- apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kompose.service.type: nodeport
creationTimestamp: null
name: zookeeper
spec:
replicas: 1
selector:
matchLabels:
io.kompose.service: zookeeper
strategy:
type: Recreate
template:
metadata:
creationTimestamp: null
labels:
io.kompose.service: zookeeper
spec:
containers:
- image: bitnami/zookeeper:3
name: zookeeper
ports:
- containerPort: 2181
env:
- name: ALLOW_ANONYMOUS_LOGIN
value: "yes"
resources: {}
volumeMounts:
- mountPath: /bitnami/zoo
name: bitnamidockerzookeeper-zookeeper-data
restartPolicy: Always
volumes:
- name: bitnamidockerzookeeper-zookeeper-data
#hostPath:
#path: /tmp/tmp1
persistentVolumeClaim:
claimName: bitnamidockerzookeeper-zookeeper-data
status: {}
- apiVersion: v1
kind: PersistentVolumeClaim
metadata:
creationTimestamp: null
labels:
io.kompose.service: bitnamidockerzookeeper-zookeeper-data
type: local
name: bitnamidockerzookeeper-zookeeper-data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Mi
status: {}
- apiVersion: v1
kind: PersistentVolume
metadata:
name: foo
spec:
storageClassName: manual
claimRef:
name: bitnamidockerzookeeper-zookeeper-data
capacity:
storage: 100Mi
accessModes:
- ReadWriteMany
hostPath:
path: /tmp/tmp1
status: {}
kind: List
metadata: {}
有点困惑,如果你想使用节点上的文件路径作为 pod
的卷,你应该这样做:
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /test-pd
name: test-volume
volumes:
- name: test-volume
hostPath:
# directory location on host
path: /data
# this field is optional
type: Directory
但您需要确保 pod
将成为具有文件路径的同一节点的调度程序。
无法为服务分配卷。在 YAML 的第 4 行中,当它应该是“Pod”时指定“Service”,并且 Kubernetes 中使用的每个资源都必须有一个名称,您可以在元数据中添加它。那应该可以解决这个简单的问题。
apiVersion: v1
items:
- apiVersion: v1
kind: Pod #POD
metadata:
name: my-pod #A RESOURCE NEEDS A NAME
creationTimestamp: null
labels:
io.kompose.service: zookeeper
spec:
containers:
- image: bitnami/zookeeper:3
name: zookeeper
ports:
- containerPort: 2181
env:
- name: ALLOW_ANONYMOUS_LOGIN
value: "yes"
resources: {}
volumeMounts:
- mountPath: /bitnami/zookeeper
name: bitnamidockerzookeeper-zookeeper-data
restartPolicy: Always
volumes:
- name: bitnamidockerzookeeper-zookeeper-data
persistentVolumeClaim:
claimName: bitnamidockerzookeeper-zookeeper-data
status: {}
现在,我不知道您使用的是什么,但 hostPath 仅适用于 Minikube 等本地集群。在生产中,情况发生了翻天覆地的变化。如果一切都是本地的,你需要在节点中有目录“/tmp/zoo”,注意不是在你的本地电脑上,而是在节点内。例如,如果你使用 minikube,那么你 运行 minikube ssh
进入节点并在那里复制“/tmp/zoo”。 kubernetes 官方文档中提供了一个很好的指南:https://kubernetes.io/docs/tasks/configure-pod-container/configure-persistent-volume-storage/
您的 YAML 中存在一些潜在问题。
首先,PersistentVolume 的 accessModes
与 PersistentVolumeClaim 不匹配。解决该问题的一种方法是在 PersistentVolume 的 accessModes
中同时列出 ReadWriteMany
和 ReadWriteOnce
。
那么,PersistentVolume 没有指定 storageClassName
。因此,如果您将 StorageClass 配置为集群上的默认 StorageClass(您可以使用 kubectl get sc
看到这一点),它将自动动态配置 PersistentVolume,而不是使用您声明的 PersistentVolume。所以你需要指定一个storageClassName
。 StorageClass 不必真实存在(因为我们使用的是静态配置而不是动态配置)。
接下来PersistentVolume中的claimRef
需要提到PersistentVolumeClaim的Namespace。提醒一下:PersistentVolumes 是集群资源,因此它们没有命名空间;但是 PersistentVolumeClaims 与装载它们的 Pod 属于同一个命名空间。
还有一点就是bitnami图片中Zookeeper数据使用的路径是/bitnami/zookeeper
,不是/bitnami/zoo
.
您还需要在该卷中初始化权限,因为默认情况下,只有 root
具有写入权限,并且 Zookeeper 在这里以非根用户身份运行,并且不会对 data
子目录.
这是一个更新的 YAML,解决了所有这些问题。我还重写了 YAML 以使用 YAML 多文档语法(资源由 ---
分隔)而不是 kind: List
语法,并且我删除了很多未使用的字段(如空 status:
字段和并非绝对必要的标签)。它适用于我的 KinD 集群,我希望它也适用于您的情况。
如果你的集群只有一个节点,这会工作正常,但如果你有多个节点,你可能需要稍微调整一下以确保卷绑定到特定节点(我添加了一个注释掉 YAML 中的 nodeAffinity
部分,但您可能还必须更改绑定模式——我现在只有一个单节点集群来测试它;但是 Kubernetes 文档和博客对此有丰富的详细信息; 也有关于此绑定模式的详细信息。
最后一件事:在这种情况下,我认为使用 StatefulSet 可能更有意义。它不会产生巨大差异,但会更清楚地表明意图(Zookeeper 是有状态服务)并且在一般情况下(超出本地 hostPath
卷)它会避免让两个 Zookeeper Pods 同时访问该卷.
apiVersion: v1
kind: Service
metadata:
name: zookeeper
spec:
ports:
- name: "2181"
port: 2181
targetPort: 2181
selector:
io.kompose.service: zookeeper
type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: zookeeper
spec:
replicas: 1
selector:
matchLabels:
io.kompose.service: zookeeper
template:
metadata:
labels:
io.kompose.service: zookeeper
spec:
initContainers:
- image: alpine
name: chmod
volumeMounts:
- mountPath: /bitnami/zookeeper
name: bitnamidockerzookeeper-zookeeper-data
command: [ sh, -c, "chmod 777 /bitnami/zookeeper" ]
containers:
- image: bitnami/zookeeper:3
name: zookeeper
ports:
- containerPort: 2181
env:
- name: ALLOW_ANONYMOUS_LOGIN
value: "yes"
volumeMounts:
- mountPath: /bitnami/zookeeper
name: bitnamidockerzookeeper-zookeeper-data
volumes:
- name: bitnamidockerzookeeper-zookeeper-data
persistentVolumeClaim:
claimName: bitnamidockerzookeeper-zookeeper-data
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: bitnamidockerzookeeper-zookeeper-data
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Mi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: tmp-tmp1
spec:
storageClassName: manual
claimRef:
name: bitnamidockerzookeeper-zookeeper-data
namespace: default
capacity:
storage: 100Mi
accessModes:
- ReadWriteMany
- ReadWriteOnce
hostPath:
path: /tmp/tmp1
#nodeAffinity:
# required:
# nodeSelectorTerms:
# - matchExpressions:
# - key: kubernetes.io/hostname
# operator: In
# values:
# - kind-control-plane
下面是我的kubernetes文件,我需要做两件事
- 需要挂载一个包含文件的文件夹
- 需要用启动脚本挂载文件
我的本地 /tmp/zoo 文件夹中的文件和我的 zoo 文件夹文件从未出现在 pod 内的 /bitnami/zookeeper 中。
下面是更新后的Service、Deployment、PVC和PV
kubernetes.yaml
apiVersion: v1
items:
- apiVersion: v1
kind: Service
metadata:
annotations:
kompose.service.type: nodeport
creationTimestamp: null
labels:
io.kompose.service: zookeeper
name: zookeeper
spec:
ports:
- name: "2181"
port: 2181
targetPort: 2181
selector:
io.kompose.service: zookeeper
type: NodePort
status:
loadBalancer: {}
- apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kompose.service.type: nodeport
creationTimestamp: null
name: zookeeper
spec:
replicas: 1
selector:
matchLabels:
io.kompose.service: zookeeper
strategy:
type: Recreate
template:
metadata:
creationTimestamp: null
labels:
io.kompose.service: zookeeper
spec:
containers:
- image: bitnami/zookeeper:3
name: zookeeper
ports:
- containerPort: 2181
env:
- name: ALLOW_ANONYMOUS_LOGIN
value: "yes"
resources: {}
volumeMounts:
- mountPath: /bitnami/zoo
name: bitnamidockerzookeeper-zookeeper-data
restartPolicy: Always
volumes:
- name: bitnamidockerzookeeper-zookeeper-data
#hostPath:
#path: /tmp/tmp1
persistentVolumeClaim:
claimName: bitnamidockerzookeeper-zookeeper-data
status: {}
- apiVersion: v1
kind: PersistentVolumeClaim
metadata:
creationTimestamp: null
labels:
io.kompose.service: bitnamidockerzookeeper-zookeeper-data
type: local
name: bitnamidockerzookeeper-zookeeper-data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Mi
status: {}
- apiVersion: v1
kind: PersistentVolume
metadata:
name: foo
spec:
storageClassName: manual
claimRef:
name: bitnamidockerzookeeper-zookeeper-data
capacity:
storage: 100Mi
accessModes:
- ReadWriteMany
hostPath:
path: /tmp/tmp1
status: {}
kind: List
metadata: {}
有点困惑,如果你想使用节点上的文件路径作为 pod
的卷,你应该这样做:
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /test-pd
name: test-volume
volumes:
- name: test-volume
hostPath:
# directory location on host
path: /data
# this field is optional
type: Directory
但您需要确保 pod
将成为具有文件路径的同一节点的调度程序。
无法为服务分配卷。在 YAML 的第 4 行中,当它应该是“Pod”时指定“Service”,并且 Kubernetes 中使用的每个资源都必须有一个名称,您可以在元数据中添加它。那应该可以解决这个简单的问题。
apiVersion: v1
items:
- apiVersion: v1
kind: Pod #POD
metadata:
name: my-pod #A RESOURCE NEEDS A NAME
creationTimestamp: null
labels:
io.kompose.service: zookeeper
spec:
containers:
- image: bitnami/zookeeper:3
name: zookeeper
ports:
- containerPort: 2181
env:
- name: ALLOW_ANONYMOUS_LOGIN
value: "yes"
resources: {}
volumeMounts:
- mountPath: /bitnami/zookeeper
name: bitnamidockerzookeeper-zookeeper-data
restartPolicy: Always
volumes:
- name: bitnamidockerzookeeper-zookeeper-data
persistentVolumeClaim:
claimName: bitnamidockerzookeeper-zookeeper-data
status: {}
现在,我不知道您使用的是什么,但 hostPath 仅适用于 Minikube 等本地集群。在生产中,情况发生了翻天覆地的变化。如果一切都是本地的,你需要在节点中有目录“/tmp/zoo”,注意不是在你的本地电脑上,而是在节点内。例如,如果你使用 minikube,那么你 运行 minikube ssh
进入节点并在那里复制“/tmp/zoo”。 kubernetes 官方文档中提供了一个很好的指南:https://kubernetes.io/docs/tasks/configure-pod-container/configure-persistent-volume-storage/
您的 YAML 中存在一些潜在问题。
首先,PersistentVolume 的 accessModes
与 PersistentVolumeClaim 不匹配。解决该问题的一种方法是在 PersistentVolume 的 accessModes
中同时列出 ReadWriteMany
和 ReadWriteOnce
。
那么,PersistentVolume 没有指定 storageClassName
。因此,如果您将 StorageClass 配置为集群上的默认 StorageClass(您可以使用 kubectl get sc
看到这一点),它将自动动态配置 PersistentVolume,而不是使用您声明的 PersistentVolume。所以你需要指定一个storageClassName
。 StorageClass 不必真实存在(因为我们使用的是静态配置而不是动态配置)。
接下来PersistentVolume中的claimRef
需要提到PersistentVolumeClaim的Namespace。提醒一下:PersistentVolumes 是集群资源,因此它们没有命名空间;但是 PersistentVolumeClaims 与装载它们的 Pod 属于同一个命名空间。
还有一点就是bitnami图片中Zookeeper数据使用的路径是/bitnami/zookeeper
,不是/bitnami/zoo
.
您还需要在该卷中初始化权限,因为默认情况下,只有 root
具有写入权限,并且 Zookeeper 在这里以非根用户身份运行,并且不会对 data
子目录.
这是一个更新的 YAML,解决了所有这些问题。我还重写了 YAML 以使用 YAML 多文档语法(资源由 ---
分隔)而不是 kind: List
语法,并且我删除了很多未使用的字段(如空 status:
字段和并非绝对必要的标签)。它适用于我的 KinD 集群,我希望它也适用于您的情况。
如果你的集群只有一个节点,这会工作正常,但如果你有多个节点,你可能需要稍微调整一下以确保卷绑定到特定节点(我添加了一个注释掉 YAML 中的 nodeAffinity
部分,但您可能还必须更改绑定模式——我现在只有一个单节点集群来测试它;但是 Kubernetes 文档和博客对此有丰富的详细信息;
最后一件事:在这种情况下,我认为使用 StatefulSet 可能更有意义。它不会产生巨大差异,但会更清楚地表明意图(Zookeeper 是有状态服务)并且在一般情况下(超出本地 hostPath
卷)它会避免让两个 Zookeeper Pods 同时访问该卷.
apiVersion: v1
kind: Service
metadata:
name: zookeeper
spec:
ports:
- name: "2181"
port: 2181
targetPort: 2181
selector:
io.kompose.service: zookeeper
type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: zookeeper
spec:
replicas: 1
selector:
matchLabels:
io.kompose.service: zookeeper
template:
metadata:
labels:
io.kompose.service: zookeeper
spec:
initContainers:
- image: alpine
name: chmod
volumeMounts:
- mountPath: /bitnami/zookeeper
name: bitnamidockerzookeeper-zookeeper-data
command: [ sh, -c, "chmod 777 /bitnami/zookeeper" ]
containers:
- image: bitnami/zookeeper:3
name: zookeeper
ports:
- containerPort: 2181
env:
- name: ALLOW_ANONYMOUS_LOGIN
value: "yes"
volumeMounts:
- mountPath: /bitnami/zookeeper
name: bitnamidockerzookeeper-zookeeper-data
volumes:
- name: bitnamidockerzookeeper-zookeeper-data
persistentVolumeClaim:
claimName: bitnamidockerzookeeper-zookeeper-data
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: bitnamidockerzookeeper-zookeeper-data
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Mi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: tmp-tmp1
spec:
storageClassName: manual
claimRef:
name: bitnamidockerzookeeper-zookeeper-data
namespace: default
capacity:
storage: 100Mi
accessModes:
- ReadWriteMany
- ReadWriteOnce
hostPath:
path: /tmp/tmp1
#nodeAffinity:
# required:
# nodeSelectorTerms:
# - matchExpressions:
# - key: kubernetes.io/hostname
# operator: In
# values:
# - kind-control-plane