容器中的文件在磁盘上是临时存放的,这给容器中运行的重要的应用程序带来一些问题
问题1:当容器崩溃或重启的时候,kubelet 会以干净的状态(镜像的状态)重启容器,容器内的历史数据会丢失
问题2:当容器被删除时 (k8s 没有停止容器的概念,只有创建、删除),容器内的数据也会被一起清理
问题3:多个容器中有共享文件或目录的需求
卷是一个抽象化的存储设备
卷可以解决容器崩溃或重启后历史数据丢失的问题
卷可以解决容器或 Pod 被删除后数据持久保存的问题
卷可以解决在多个容器内共享数据的问题
Pod 可以同时使用任意数目的卷
持久卷:持久卷是集群中的存储资源,就像他的名字一样在里面存储的数据不会随着 Pod 的删除而丢失
临时卷:有些应用程序需要额外的存储,但并不关心数据在重启后是否仍然可用。卷会遵从 Pod 的生命周期,与 Pod一起创建和删除
投射卷:它允许您将多个现有卷源映射到同一个目录。通过将这些不同类型的卷源组合成一个统一的卷,可以更方便地管理和使用这些资源
- [root@master ~]# vim web1.yaml
- ---
- kind: Pod
- apiVersion: v1
- metadata:
- name: web1
- spec:
- containers:
- - name: nginx
- image: myos:nginx
- [root@master ~]# vim web1.yaml
- ---
- kind: Pod
- apiVersion: v1
- metadata:
- name: web1
- spec:
- volumes: # 卷定义
- - name: logdata # 卷名称
- hostPath: # 资源类型
- path: /var/weblog # 宿主机路径
- type: DirectoryOrCreate # 目录不存在就创建
- containers:
- - name: nginx
- image: myos:nginx
- volumeMounts: # mount 卷
- - name: logdata # 卷名称
- mountPath: /usr/local/nginx/logs # 容器内路径
type对应的类型

- [root@master ~]# kubectl apply -f web1.yaml
- pod/web1 created
- [root@master ~]# kubectl get pods -o wide
- NAME READY STATUS RESTARTS AGE IP NODE
- web1 1/1 Running 0 45m 10.244.2.16 node-0002
-
- [root@master ~]# curl http://10.244.2.16/
- Nginx is running !
-
- # 删除Pod ,日志数据也不会丢失
- [root@master ~]# kubectl delete pod web1
- pod "web1" deleted
-
- # 来到 node 上查看日志
- [root@node-0002 ~]# cat /var/weblog/access.log
- 10.244.0.0 - - [27/Jun/2022:02:00:12 +0000] "GET / HTTP/1.1" 200 19 "-" "curl/7.29.0"
NFS最大的功能就是在不同节点的不同 Pd 中共享读写数据。本地NFS的客户端可以透明地读写位于远端NFS服务器上的文件,就像访问本地文件一样。
| 名称 | IP地址 | 配置 |
|---|---|---|
| nfs | 192.168.1.10 | 1CPU,1G内存 |
- # 创建共享目录,并部署测试页面
- [root@nfs ~]# mkdir -p /var/webroot
- [root@nfs ~]# echo "nfs server" >/var/webroot/index.html
-
- # 部署 NFS 服务
- [root@nfs ~]# dnf install -y nfs-utils
- [root@nfs ~]# vim /etc/exports
- /var/webroot 192.168.1.0/24(rw,no_root_squash)
- [root@nfs ~]# systemctl enable --now nfs-server.service
- #----------------------------------------------------------#
- # 由于 Pod 是随机调度的,为了保证 NFS 存储卷可以正确加载,需要在所有 node 节点都安装 NFS软件工具包
- [root@node ~]# dnf install -y nfs-utils
- [root@master ~]# vim web1.yaml
- ---
- kind: Pod
- apiVersion: v1
- metadata:
- name: web1
- spec:
- volumes:
- - name: logdata
- hostPath:
- path: /var/weblog
- type: DirectoryOrCreate
- - name: website # 卷名称
- nfs: # NFS 资源类型
- server: 192.168.1.10 # NFS 服务器地址
- path: /var/webroot # NFS 共享目录
- containers:
- - name: nginx
- image: myos:nginx
- volumeMounts:
- - name: logdata
- mountPath: /usr/local/nginx/logs
- - name: website # 卷名称
- mountPath: /usr/local/nginx/html # 路径
-
- [root@master ~]# kubectl apply -f web1.yaml
- pod/web1 created
- [root@master ~]# kubectl get pods -o wide
- NAME READY STATUS RESTARTS AGE IP NODE
- web1 1/1 Running 0 12m 10.244.1.19 node-0001
- [root@master ~]# curl http://10.244.1.19
- nfs server
PV 的全称是 Persistent Volume,是持久卷
PVC 的全称是 PersistentVolumeClaim,是持久卷声明
存储的管理是一个与计算实例的管理完全不同的问题。管理员希望能提供一种通用的 API来完成Pod 对卷的部署管理与使用。PV/PVC就是为了满足这和需求而诞生的,PV/PVC的引入使集群具备了存储的逻辑抽象能力。
PV 是资源的提供者,根据集群的基础设施变化而变化,由K8s集群管理员配置
PVC是资源的使用者,根据业务服务的需求变化来配置,用户无需知道PV的技术细节,只需要声明你需求什么样的资源即可
PVC会根据用户声明的需求,自动找到 PV完成绑定
- ---
- kind: PersistentVolume
- apiVersion: v1
- metadata:
- name: pv-local
- spec:
- volumeMode: Filesystem # 提供的资源类型 [Filesystem,Block]
- accessModes: # 存储卷能提供的访问模式
- - ReadWriteOnce # 卷支持的模式,支持多种
- - ReadOnlyMany # RWO,ROX,RWX,RWOP
- capacity: # 存储卷能提供的存储空间
- storage: 30Gi # 空间大小
- persistentVolumeReclaimPolicy: Retain # 数据回收方式
- hostPath: # hostPath配置
- path: /var/weblog
- type: DirectoryOrCreate
- ---
- kind: PersistentVolume
- apiVersion: v1
- metadata:
- name: pv-nfs
- spec:
- volumeMode: Filesystem # 提供 Fileststem 访问方式
- accessModes: # NFS 支持多种访问方式
- - ReadWriteOnce # RWO,ROX,RWX
- - ReadOnlyMany
- - ReadWriteMany
- capacity:
- storage: 20Gi # 提供的磁盘空间大小
- persistentVolumeReclaimPolicy: Retain # 数据手工回收
- mountOptions: # mount 的参数
- - nolock
- nfs: # NFS配置
- server: 192.168.1.10 # <NFS服务器IP地址>
- path: /var/webroot # <共享目录路径>
- # 创建 PV
- [root@master ~]# kubectl apply -f pv.yaml
- persistentvolume/pv-local created
- persistentvolume/pv-nfs created
-
- # 查看PV状态
- [root@master ~]# kubectl get persistentvolume
- NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS AGE
- pv-local 30Gi RWO Retain Available 2s
- pv-nfs 20Gi RWO,ROX,RWX Retain Available 2s
- [root@master ~]# vim pv.yaml
- ---
- kind: PersistentVolume
- apiVersion: v1
- metadata:
- name: pv-local
- spec:
- volumeMode: Filesystem
- accessModes:
- - ReadWriteOnce
- capacity:
- storage: 30Gi
- persistentVolumeReclaimPolicy: Retain
- hostPath:
- path: /var/weblog
- type: DirectoryOrCreate
-
- ---
- kind: PersistentVolume
- apiVersion: v1
- metadata:
- name: pv-nfs
- spec:
- volumeMode: Filesystem
- accessModes:
- - ReadWriteOnce
- - ReadOnlyMany
- - ReadWriteMany
- capacity:
- storage: 20Gi
- persistentVolumeReclaimPolicy: Retain
- mountOptions:
- - nolock
- nfs:
- server: 192.168.1.10
- path: /var/webroot
-
- [root@master ~]# kubectl apply -f pv.yaml
- persistentvolume/pv-local created
- persistentvolume/pv-nfs created
- [root@master ~]# kubectl get persistentvolume
- NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS AGE
- pv-local 30Gi RWO Retain Available 2s
- pv-nfs 20Gi RWO,ROX,RWX Retain Available 2s
- [root@master ~]# vim pvc.yaml
- ---
- kind: PersistentVolumeClaim
- apiVersion: v1
- metadata:
- name: pvc1
- spec: # 定义需求
- volumeMode: Filesystem # 需要使用 Filesystem 的存储卷
- accessModes:
- - ReadWriteOnce # 需要支持 RWO 的存储卷
- resources:
- requests:
- storage: 25Gi # 最小磁盘需求
-
- ---
- kind: PersistentVolumeClaim
- apiVersion: v1
- metadata:
- name: pvc2
- spec:
- volumeMode: Filesystem
- accessModes:
- - ReadWriteMany
- resources:
- requests:
- storage: 15Gi
-
- [root@master ~]# kubectl apply -f pvc.yaml
- persistentvolumeclaim/pvc1 created
- persistentvolumeclaim/pvc2 created
- [root@master ~]# kubectl get persistentvolumeclaims
- NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
- pvc1 Bound pv-local 30Gi RWO 8s
- pvc2 Bound pv-nfs 20Gi RWO,ROX,RWX 8s
映射PVC为卷
Pod 挂载 PVC
- [root@master ~]# vim web1.yaml
- ---
- kind: Pod
- apiVersion: v1
- metadata:
- name: web1
- spec:
- volumes: # 卷定义
- - name: logdata # 卷名称
- persistentVolumeClaim: # 通过PVC引用存储资源
- claimName: pvc1 # PVC名称
- - name: website # 卷名称
- persistentVolumeClaim: # 通过PVC引用存储资源
- claimName: pvc2 # PVC名称
- containers:
- - name: nginx
- image: myos:nginx
- volumeMounts:
- - name: logdata # PVC卷名称
- mountPath: /usr/local/nginx/logs # 挂载路径
- - name: website # PVC卷名称
- mountPath: /usr/local/nginx/html # 挂载路径
服务验证
创建 Pod 后访问查看
- [root@master ~]# kubectl delete pods web1
- pod "web1" deleted
- [root@master ~]# kubectl apply -f web1.yaml
- pod/web1 created
- [root@master ~]# kubectl get pods -o wide
- NAME READY STATUS RESTARTS AGE IP NODE
- web1 1/1 Running 0 45m 10.244.2.16 node-0002
- [root@master ~]# curl http://10.244.2.16
- nfs server
configMap 是一种临时卷
configMap 卷提供了向 Pod 注入配置数据的方法,允许你将配置文件与镜像分离,使容器化的应用具有可移植性。
configMap 在使用之前需要先创建它,configMap 不是用来保存大量数据的,在其中保存的数据不可超过 1 MiB。
配置环境变量
修改配置文件的参数,数据库的地址等
<3> 修改系统时区
创建 configMap 语法格式
kubectI create configmap 名称 [选项/参数]
- # 使用命令创建 configMap
- [root@master ~]# kubectl create configmap tz --from-literal=TZ="Asia/Shanghai"
- configmap/tz created
-
- # 使用资源对象文件创建
- [root@master ~]# vim timezone.yaml
- ---
- kind: ConfigMap
- apiVersion: v1
- metadata:
- name: timezone
- data:
- TZ: Asia/Shanghai
-
- [root@master ~]# kubectl apply -f timezone.yaml
- configmap/timezone created
-
- [root@master ~]# kubectl get configmaps
- NAME DATA AGE
- kube-root-ca.crt 1 9d
- timezone 1 15s
- tz 1 50s
- [root@master ~]# vim web1.yaml
- ---
- kind: Pod
- apiVersion: v1
- metadata:
- name: web1
- spec:
- volumes:
- - name: logdata
- persistentVolumeClaim:
- claimName: pvc1
- - name: website
- persistentVolumeClaim:
- claimName: pvc2
- containers:
- - name: nginx
- image: myos:nginx
- envFrom: # 配置环境变量
- - configMapRef: # 调用资源对象
- name: timezone # 资源对象名称
- volumeMounts:
- - name: logdata
- mountPath: /usr/local/nginx/logs
- - name: website
- mountPath: /usr/local/nginx/html
-
- [root@master ~]# kubectl delete pods web1
- pod "web1" deleted
- [root@master ~]# kubectl apply -f web1.yaml
- pod/web1 created
- [root@master ~]# kubectl exec -it web1 -- date +%T
- 10:41:27
在 Pod 中增加 php 容器,与 nginx 共享同一块网卡
- # 在 Pod 中增加 php 容器,与 nginx 共享同一块网卡
- [root@master ~]# vim web1.yaml
- ---
- kind: Pod
- apiVersion: v1
- metadata:
- name: web1
- spec:
- volumes:
- - name: logdata
- persistentVolumeClaim:
- claimName: pvc1
- - name: website
- persistentVolumeClaim:
- claimName: pvc2
- containers:
- - name: nginx
- image: myos:nginx
- envFrom:
- - configMapRef:
- name: timezone
- volumeMounts:
- - name: logdata
- mountPath: /usr/local/nginx/logs
- - name: website
- mountPath: /usr/local/nginx/html
- - name: php # 以下为新增加内容
- image: myos:php-fpm
- envFrom: # 不同容器需要单独配置时区
- - configMapRef:
- name: timezone
- volumeMounts:
- - name: website # 不同容器需要单独挂载NFS
- mountPath: /usr/local/nginx/html
-
- [root@master ~]# kubectl delete pod web1
- pod "web1" deleted
- [root@master ~]# kubectl apply -f web1.yaml
- pod/web1 created
- [root@master ~]# kubectl get pods
- NAME READY STATUS RESTARTS AGE
- web1 2/2 Running 0 5s
- [root@master ~]# kubectl exec -it web1 -c nginx -- ss -ltun
- Netid State Recv-Q Send-Q Local Address:Port ... ...
- tcp LISTEN 0 128 0.0.0.0:80 ... ...
- tcp LISTEN 0 128 127.0.0.1:9000 ... ...
- # 使用 nginx 配置文件创建 configMap
- [root@master ~]# kubectl cp -c nginx web1:/usr/local/nginx/conf/nginx.conf nginx.conf
- [root@master ~]# vim nginx.conf
- location ~ \.php$ {
- root html;
- fastcgi_pass 127.0.0.1:9000;
- fastcgi_index index.php;
- include fastcgi.conf;
- }
-
- # 使用命令创建 configMap
- [root@master ~]# kubectl create configmap nginx-php --from-file=nginx.conf
- configmap/nginx-php created
- [root@master ~]# vim web1.yaml
- ---
- kind: Pod
- apiVersion: v1
- metadata:
- name: web1
- spec:
- volumes:
- - name: logdata
- persistentVolumeClaim:
- claimName: pvc1
- - name: website
- persistentVolumeClaim:
- claimName: pvc2
- - name: nginx-php # 卷名称
- configMap: # 引用资源对象
- name: nginx-php # 资源对象名称
- containers:
- - name: nginx
- image: myos:nginx
- envFrom:
- - configMapRef:
- name: timezone
- volumeMounts:
- - name: nginx-php # 卷名称
- subPath: nginx.conf # 键值(文件名称)
- mountPath: /usr/local/nginx/conf/nginx.conf # 路径
- - name: logdata
- mountPath: /usr/local/nginx/logs
- - name: website
- mountPath: /usr/local/nginx/html
- - name: php
- image: myos:php-fpm
- envFrom:
- - configMapRef:
- name: timezone
- volumeMounts:
- - name: website
- mountPath: /usr/local/nginx/html
- # 拷贝测试页面 s4/public/info.php
- [root@ecs-proxy s4]# rsync -av public/info.php 192.168.1.10:/var/webroot/info.php
- #---------------------------------------------------------------------------------#
- [root@master ~]# kubectl delete pod web1
- pod "web1" deleted
- [root@master ~]# kubectl apply -f web1.yaml
- pod/web1 created
- [root@master ~]# kubectl get pods -o wide
- NAME READY STATUS RESTARTS AGE IP NODE
- web1 2/2 Running 0 18s 10.244.3.17 node-0003
-
- [root@master ~]# curl http://10.244.3.17/info.php
- <pre>
- Array
- (
- [REMOTE_ADDR] => 10.244.0.0
- [REQUEST_METHOD] => GET
- [HTTP_USER_AGENT] => curl/7.29.0
- [REQUEST_URI] => /info.php
- )
- php_host: web1
- 1229
Secret 是一种临时卷
Secret 类似于 ConfigMap 但专门用于保存机密数据
在设置 Secret.data 字段时,所有键值都必须是经过base64编码的字符串
配置一些需要加密的环境变量或文件(例如:https 证书)
访问需要认证登录的私有镜像仓库(例如: harbor 私有仓库)
kubect creat secret 子类型 名称 [选项/参数]
kubect creat secret generic 名称 [选项/参数]
kubect creat secret docker-registry 名称 [选项/参数]
kubectl create secret tls 名称 [选项/参数]
- # 创建需要登录私有仓库的资源对象
- [root@master ~]# kubectl create secret docker-registry harbor-auth --docker-server=harbor:443 --docker-username="用户名" --docker-password="密码"
- secret/harbor-auth created
-
- [root@master ~]# kubectl get secrets harbor-auth -o yaml
- apiVersion: v1
- data:
- .dockerconfigjson: <经过加密的数据>
- kind: Secret
- metadata:
- name: harbor-auth
- namespace: default
- resourceVersion: "1558265"
- uid: 08f55ee7-2753-41fa-8aec-98a292115fa6
- type: kubernetes.io/dockerconfigjson
- [root@master ~]# vim web2.yaml
- ---
- kind: Pod
- apiVersion: v1
- metadata:
- name: web2
- spec:
- imagePullSecrets: # 引用 secret 数据
- - name: harbor-auth # 资源对象名称
- containers:
- - name: apache
- image: harbor:443/myimg/httpd:latest # 使用私有仓库里的镜像
-
- [root@master ~]# kubectl apply -f web2.yaml
- pod/web2 created
- [root@master ~]# kubectl get pods
- NAME READY STATUS RESTARTS AGE
- web1 2/2 Running 0 33m
- web2 1/1 Running 0 18m
emptyDir 的本质是一个简单的空目录
emptyDir 可以提供临时空间,同一个 Pod 中容器也可以用来共享数据。案例:缓存服务器、数据统计分析、排序等
emptyDir 随 Pod 创建而创建,Pod 在该节点上运行期间一直存在。当 Pod 被从节点上删除时,临时卷中的数据也会被永久删除
重启 Pod中的容器不会造成 emptyDir 数据的丢失
- [root@master ~]# vim web2.yaml
- ---
- kind: Pod
- apiVersion: v1
- metadata:
- name: web2
- spec:
- imagePullSecrets:
- - name: harbor-auth
- volumes: # 卷配置
- - name: cache # 卷名称
- emptyDir: {} # 资源类型
- containers:
- - name: apache
- image: harbor:443/myimg/httpd:latest
- volumeMounts: # 挂载卷
- - name: cache # 卷名称
- mountPath: /var/cache # 路径
-
创建容器,验证配置
- [root@master ~]# kubectl delete pod web2
- pod "web2" deleted
- [root@master ~]# kubectl apply -f web2.yaml
- pod/web2 created
- [root@master ~]# kubectl exec -it web2 -- bash
- [root@web2 html]# mount -l |grep cache
- /dev/vda1 on /var/cache type xfs (rw,relatime,attr2)