配置 Pod 使用 PersistentVolume 进行存储
本页展示如何配置 Pod 以使用 PersistentVolumeClaim 进行存储。以下是该过程的摘要
您作为集群管理员,创建由物理存储支持的 PersistentVolume。您不会将该卷与任何 Pod 关联。
您现在扮演开发人员/集群用户的角色,创建一个 PersistentVolumeClaim,该声明会自动绑定到合适的 PersistentVolume。
您创建一个 Pod,该 Pod 使用上述 PersistentVolumeClaim 进行存储。
开始之前
您需要一个 Kubernetes 集群,该集群只有一个节点,并且 kubectl 命令行工具必须配置为与您的集群通信。如果您还没有单节点集群,可以使用 Minikube 创建一个。
熟悉 持久卷 中的材料。
在您的节点上创建一个 index.html 文件
打开到集群中单个节点的 shell。打开 shell 的方式取决于您如何设置集群。例如,如果您使用的是 Minikube,则可以通过输入 minikube ssh 打开到节点的 shell。
在节点的 shell 中,创建一个 /mnt/data 目录
# This assumes that your Node uses "sudo" to run commands
# as the superuser
sudo mkdir /mnt/data
在 /mnt/data 目录中,创建一个 index.html 文件
# This again assumes that your Node uses "sudo" to run commands
# as the superuser
sudo sh -c "echo 'Hello from Kubernetes storage' > /mnt/data/index.html"
说明
如果您的节点使用除sudo 之外的其他工具进行超级用户访问,通常可以通过将 sudo 替换为其他工具的名称来使其工作。测试 index.html 文件是否存在
cat /mnt/data/index.html
输出应为
Hello from Kubernetes storage
现在您可以关闭到节点的 shell 了。
创建一个 PersistentVolume
在本练习中,您将创建一个 hostPath PersistentVolume。Kubernetes 支持 hostPath 用于在单节点集群上进行开发和测试。hostPath PersistentVolume 使用节点上的文件或目录来模拟网络附加存储。
在生产集群中,您将不会使用 hostPath。相反,集群管理员将配置网络资源,例如 Google Compute Engine 持久磁盘、NFS 共享或 Amazon Elastic Block Store 卷。集群管理员还可以使用 StorageClasses 设置 动态配置。
以下是 hostPath PersistentVolume 的配置文件
apiVersion: v1
kind: PersistentVolume
metadata:
name: task-pv-volume
labels:
type: local
spec:
storageClassName: manual
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/mnt/data"
配置文件指定该卷位于集群节点的 /mnt/data 上。该配置还指定大小为 10 GiB,访问模式为 ReadWriteOnce,这意味着该卷可以由单个节点以读写方式挂载。它定义了 PersistentVolume 的 StorageClass 名称 manual,该名称将用于将 PersistentVolumeClaim 请求绑定到此 PersistentVolume。
说明
此示例使用ReadWriteOnce 访问模式,为了简单起见。对于生产使用,Kubernetes 项目建议使用 ReadWriteOncePod 访问模式。创建 PersistentVolume
kubectl apply -f https://k8s.io/examples/pods/storage/pv-volume.yaml
查看 PersistentVolume 的信息
kubectl get pv task-pv-volume
输出显示 PersistentVolume 的 STATUS 为 Available。这意味着它尚未绑定到 PersistentVolumeClaim。
NAME CAPACITY ACCESSMODES RECLAIMPOLICY STATUS CLAIM STORAGECLASS REASON AGE
task-pv-volume 10Gi RWO Retain Available manual 4s
创建一个 PersistentVolumeClaim
下一步是创建一个 PersistentVolumeClaim。Pod 使用 PersistentVolumeClaim 请求物理存储。在本练习中,您将创建一个 PersistentVolumeClaim,该声明请求至少 3 GiB 的卷,该卷可以为最多一个节点提供读写访问权限。
以下是 PersistentVolumeClaim 的配置文件
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: task-pv-claim
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi
创建 PersistentVolumeClaim
kubectl apply -f https://k8s.io/examples/pods/storage/pv-claim.yaml
创建 PersistentVolumeClaim 后,Kubernetes 控制平面会查找满足声明要求的 PersistentVolume。如果控制平面找到具有相同 StorageClass 的合适的 PersistentVolume,它会将声明绑定到该卷。
再次查看 PersistentVolume
kubectl get pv task-pv-volume
现在输出显示 STATUS 为 Bound。
NAME CAPACITY ACCESSMODES RECLAIMPOLICY STATUS CLAIM STORAGECLASS REASON AGE
task-pv-volume 10Gi RWO Retain Bound default/task-pv-claim manual 2m
查看 PersistentVolumeClaim
kubectl get pvc task-pv-claim
输出显示 PersistentVolumeClaim 已绑定到您的 PersistentVolume task-pv-volume。
NAME STATUS VOLUME CAPACITY ACCESSMODES STORAGECLASS AGE
task-pv-claim Bound task-pv-volume 10Gi RWO manual 30s
创建 Pod
下一步是创建一个使用您的 PersistentVolumeClaim 作为卷的 Pod。
这是 Pod 的配置文件
apiVersion: v1
kind: Pod
metadata:
name: task-pv-pod
spec:
volumes:
- name: task-pv-storage
persistentVolumeClaim:
claimName: task-pv-claim
containers:
- name: task-pv-container
image: nginx
ports:
- containerPort: 80
name: "http-server"
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: task-pv-storage
请注意,Pod 的配置文件指定了一个 PersistentVolumeClaim,但没有指定 PersistentVolume。从 Pod 的角度来看,该声明是一个卷。
创建 Pod
kubectl apply -f https://k8s.io/examples/pods/storage/pv-pod.yaml
验证 Pod 中的容器是否正在运行
kubectl get pod task-pv-pod
获取正在 Pod 中运行的容器的 shell
kubectl exec -it task-pv-pod -- /bin/bash
在您的 shell 中,验证 nginx 是否正在从 hostPath 卷提供 index.html 文件
# Be sure to run these 3 commands inside the root shell that comes from
# running "kubectl exec" in the previous step
apt update
apt install curl
curl https:///
输出显示您写入 hostPath 卷上的 index.html 文件中的文本
Hello from Kubernetes storage
如果您看到该消息,则已成功配置 Pod 以使用来自 PersistentVolumeClaim 的存储。
清理
删除 Pod
kubectl delete pod task-pv-pod
在两个位置挂载相同的 PersistentVolume
您已经了解了如何创建 PersistentVolume 和 PersistentVolumeClaim,以及如何将卷挂载到容器中的单个位置。让我们探讨如何在容器中的两个不同位置挂载相同的 PersistentVolume。以下是一个示例
apiVersion: v1
kind: Pod
metadata:
name: test
spec:
containers:
- name: test
image: nginx
volumeMounts:
# a mount for site-data
- name: config
mountPath: /usr/share/nginx/html
subPath: html
# another mount for nginx config
- name: config
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
volumes:
- name: config
persistentVolumeClaim:
claimName: task-pv-claim
这里
subPath:此字段允许将挂载的 PersistentVolume 中的特定文件或目录在容器内的不同位置公开。在本例中subPath: html挂载 html 目录。subPath: nginx.conf挂载一个特定文件,nginx.conf。
由于第一个 subPath 是 html,因此必须在节点上的 /mnt/data/ 中创建一个 html 目录。
第二个 subPath nginx.conf 意味着 /mnt/data/ 目录中的一个文件将被使用。不需要创建其他目录。
将在您的 nginx 容器上创建两个卷挂载
/usr/share/nginx/html用于静态网站/etc/nginx/nginx.conf用于默认配置
将 index.html 文件移动到您的节点上的新文件夹
这里提到的 index.html 文件指的是在 "在您的节点上创建一个 index.html 文件" 部分中创建的文件。
打开到集群中单个节点的 shell。打开 shell 的方式取决于您如何设置集群。例如,如果您使用的是 Minikube,则可以通过输入 minikube ssh 打开到节点的 shell。
创建一个 /mnt/data/html 目录
# This assumes that your Node uses "sudo" to run commands
# as the superuser
sudo mkdir /mnt/data/html
将 index.html 移动到该目录
# Move index.html from its current location to the html sub-directory
sudo mv /mnt/data/index.html html
创建一个新的 nginx.conf 文件
user nginx; worker_processes auto;error_log /var/log/nginx/error.log notice; pid /var/run/nginx.pid;
events { worker_connections 1024; }
http { include /etc/nginx/mime.types; default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; keepalive_timeout 60; #gzip on; include /etc/nginx/conf.d/*.conf;
}
这是 nginx.conf 默认文件的修改版本。这里,默认的 keepalive_timeout 已被修改为 60
创建 nginx.conf 文件
cat <<EOF > /mnt/data/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '\$remote_addr - \$remote_user [\$time_local] "\$request" '
'\$status \$body_bytes_sent "\$http_referer" '
'"\$http_user_agent" "\$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 60;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
EOF
创建 Pod
在这里,我们将创建一个使用现有的 persistentVolume 和 persistentVolumeClaim 的 Pod。但是,该 Pod 只挂载特定的文件 nginx.conf 和目录 html 到容器中。
创建 Pod
kubectl apply -f https://k8s.io/examples/pods/storage/pv-duplicate.yaml
验证 Pod 中的容器是否正在运行
kubectl get pod test
获取正在 Pod 中运行的容器的 shell
kubectl exec -it test -- /bin/bash
在您的 shell 中,验证 nginx 是否正在从 hostPath 卷提供 index.html 文件
# Be sure to run these 3 commands inside the root shell that comes from
# running "kubectl exec" in the previous step
apt update
apt install curl
curl https:///
输出显示您写入 hostPath 卷上的 index.html 文件中的文本
Hello from Kubernetes storage
在你的 shell 中,也要验证 nginx 是否正在从 hostPath volume 提供 nginx.conf 文件
# Be sure to run these commands inside the root shell that comes from
# running "kubectl exec" in the previous step
cat /etc/nginx/nginx.conf | grep keepalive_timeout
输出显示你写入 hostPath volume 上 nginx.conf 文件的修改后的文本
keepalive_timeout 60;
如果你看到这些消息,你已经成功配置了一个 Pod 来使用来自 PersistentVolumeClaim 的存储中的特定文件和目录。
清理
删除 Pod
kubectl delete pod test
kubectl delete pvc task-pv-claim
kubectl delete pv task-pv-volume
如果你还没有打开到集群中 Node 的 shell,请以与之前相同的方式打开一个新的 shell。
在 Node 上的 shell 中,删除你创建的文件和目录
# This assumes that your Node uses "sudo" to run commands
# as the superuser
sudo rm /mnt/data/html/index.html
sudo rm /mnt/data/nginx.conf
sudo rmdir /mnt/data
现在您可以关闭到节点的 shell 了。
访问控制
使用组 ID (GID) 配置的存储只允许使用相同 GID 的 Pod 进行写入。不匹配或缺失的 GID 会导致权限被拒绝的错误。为了减少与用户的协调需求,管理员可以将 PersistentVolume 注解为 GID。然后,该 GID 将自动添加到使用 PersistentVolume 的任何 Pod 中。
使用 pv.beta.kubernetes.io/gid 注解如下
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv1
annotations:
pv.beta.kubernetes.io/gid: "1234"
当 Pod 使用带有 GID 注解的 PersistentVolume 时,注释的 GID 将以与 Pod 的安全上下文中指定的 GID 相同的方式应用于 Pod 中的所有容器。每个 GID,无论其来源是 PersistentVolume 注解还是 Pod 的规范,都将应用于每个容器中运行的第一个进程。
说明
当 Pod 使用 PersistentVolume 时,与 PersistentVolume 关联的 GID 不存在于 Pod 资源本身上。接下来
- 了解有关 持久卷 的更多信息。
- 阅读 Persistent Storage 设计文档。