往期回顾: 云端技术驾驭DAY01——云计算底层技术奥秘、云服务器磁盘技术、虚拟化管理、公有云概述 云端技术驾驭DAY02——华为云管理、云主机管理、跳板机配置、制作私有镜像模板 云端技术驾驭DAY03——云主机网站部署、web集群部署、Elasticsearch安装 云端技术驾驭DAY04——Logstash安装部署及插件模块 云端技术驾驭DAY06——容器技术概述、镜像与容器管理、定制简单镜像、容器内安装部署服务 云端技术驾驭DAY07——Dockerfile详解、容器镜像制作、私有仓库 云端技术驾驭DAY08——部署容器服务、Compose微服务管理、harbor仓库部署及管理 云端技术驾驭DAY09——k8s集群安装部署、calico插件部署、计算节点配置管理 云端技术驾驭DAY10——kubectl命令详解、Pod创建过程、Pod的生命周期、定制Pod、资源对象文件 云端技术驾驭DAY11——资源对象文件、Pod自定义命令、多容器Pod、资源监控工具 云端技术驾驭DAY12——Pod调度策略、Pod标签管理、Pod资源配额与限额、全局资源配额与限额策略 云端技术驾驭DAY13——Pod污点、容忍策略、Pod优先级与抢占、容器安全
存储卷
持久卷
卷概述
容器化带来的问题
容器中的文件在磁盘上是临时存放的,这给容器中运行的重要的应用程序带来一些问题
问题1:当容器崩溃或重启的时候,kubelet会以干净的状态重启容器,容器内的历史数据会丢失 问题2:当容器被删除时,容器内的数据也会被一起清理 问题3:多个容器中有共享文件或目录的需求 卷是什么?
为什么要使用卷?
卷可以解决容器崩溃或重启后历史数据丢失的问题 卷可以解决容器或Pod被删除后数据持久保存的问题 卷可以解决在多个容器内共享数据的问题 Pod可以同时使用任意数目的卷 k8s支持的卷类型
持久卷:持久卷是集群中的存储资源,在里面存储的数据不会随着Pod的删除而丢失 临时卷:有些应用程序需要额外的存储。卷会遵从Pod的生命周期,与Pod一起创建和删除 投射卷:它允许将多个现有卷映射到同一个目录。通过将这些不同类型的卷源组合成一个统一的卷,可以更方便地管理和使用这些资源 如何使用卷?
首先编写一个Pod资源对象文件 在Pod.spec
下添加volumes
字段,配置外部存储为卷 在Pod.spec.containers[*]
中添加volumeMounts
字段,声明卷在容器中的挂载位置
hostPath存储卷
hostPath是持久卷
hostPath卷的本质是使用本地设备,例如磁盘、分区、目录、Socket、CharDevice和BlockDevice等。hostPath卷的可用性取决于底层节点的可用性,如果节点不健康,那么hostPath卷也将不可用 hostPath卷里的数据不会随着Pod的结束而消失 使用hostPath卷保存日志
[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 # 容器内路径
[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"
type类型 解释 DirectoryOrCreate 卷映射对象是一个目录,不存在就创建它 Directory 卷映射对象是一个目录,且必须存在 FileOrCreate 卷映射对象是一个文件,不存在就创建它 File 卷映射对象是一个文件,且必须存在 Socket 卷映射对象是一个Socket套接字,且必须存在 CharDevice 卷映射对象是一个字符设备,且必须存在 BlockDevice 卷映射对象是一个块设备,且必须存在
NFS存储卷
NFS存储
k8s中允许将nfs存储以卷的方式挂载到你的Pod中 在删除Pod时,nfs存储卷会被卸载,而不是被删除 nfs卷可以在不同节点的Pod之间共享数据 NFS卷的用途
NFS最大的功能就是在不同节点的不同Pod中共享读写数据。本地NFS的客户端可以透明地读写位于远端NFS服务器上的文件,就像访问本地文件一样 实验准备
主机名 P地址 配置 nfs 192.168.1.10 1CPU,1G内存
[root@nfs ~]# mkdir /var/webroot
[root@nfs ~]# echo "nfs server" > /var/webroot/index.html
[root@nfs ~]# dnf -y install nfs-utils
[root@nfs ~]# vim /etc/exports
/var/webroot 192.168.1.0/24(rw,no_root_squash)
[root@nfs ~]# systemctl enable nfs-server.service --now
Created symlink /etc/systemd/system/multi-user.target.wants/nfs-server.service → /usr/lib/systemd/system/nfs-server.service.
[root@ecs-proxy ~]# mkdir nfs
[root@ecs-proxy ~]# cd nfs
[root@ecs-proxy nfs]# vim ansible.cfg
[defaults]
inventory = inventory
host_key_checking = False
[root@ecs-proxy nfs]# vim inventory
[nfs]
192.168.1.[51:55]
[root@ecs-proxy nfs]# vim install_nfs.yml
---
- hosts: all
tasks:
- yum:
name: nfs-utils
- service:
name: nfs-server
state: started
enabled: yes
[root@ecs-proxy nfs]# ansible-playbook install_nfs.yml
[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 NOMINATED NODE READINESS GATES
web1 1/1 Running 0 8s 10.244.147.11 node-0002 <none> <none>
[root@master ~]# curl 10.244.147.11
nfs server
PV/PVC
PV/PVC管理
PV/PVC概述
PV/PVC是什么?
PV的全称是Persistent Volume,是持久卷 PVC的全称是PersistentVolumeClaim,是持久卷声明 PV/PVC有什么用途?
存储的管理是一个与计算实例的管理完全不同的问题。管理员希望能提供一种通用的API来完成Pod对卷的部署管理与使用。PV/PVC就是为了满足这种需求而诞生的,PV/PVC的引入使集群具备了存储的逻辑抽象能力 k8s支持的存储卷
CephFS volume:cephfs
容器存储接口:csi
Fibre Channel存储:fc
HostPath卷:hostPath
iSCSI存储iscsi
网络文件系统存储nfs
Rados块设备卷rbd
如何使用PV/PVC
PV是资源的提供者,根据集群的基础设施变化而变化 PVC是资源的使用者,根据业务服务的需求变化来配置 PVC会根据用户声明的需求,自动找到PV完成绑定
PV资源对象
---
kind: PersistentVolume
apiVersion: v1
metadata:
name: pv-local
spec:
volumeMode: Filesystem # 提供资源的类型[Filesystem,Block]
accessModes: # 存储卷能提供的访问模式
- ReadWriteOnce # 卷支持的模式[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
accessModes:
- ReadWriteOnce
- ReadOnlyMany
- ReadWriteMany
capacity:
storage: 20Gi
persistentVolumeReclaimPolicy: Retain
mountOptions: # mount的参数
- nolock
nfs: # NFS配置
server: 192.168.1.10 # NFS服务器IP地址
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 CLAIM STORAGECLASS REASON AGE
pv-local 30Gi RWO Retain Available 9s
pv-nfs 20Gi RWO,ROX,RWX Retain Available 9s
PVC资源对象
[root@master ~]# vim pvc.yaml
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: pvc1
spec: # 定义需求
volumeMode: Filesystem # 需要使用Filesystem的存储卷
accessModes:
- ReadWriteOnce
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 pv.yaml
persistentvolume/pv-local created
persistentvolume/pv-nfs created
[root@master ~]# kubectl get persistentvolume
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-local 30Gi RWO Retain Available 9s
pv-nfs 20Gi RWO,ROX,RWX Retain Available 9s
Pod调用PVC
映射PVC为卷
使用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:
claimName: pvc2
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 NOMINATED NODE READINESS GATES
web1 1/1 Running 0 12s 10.244.240.138 node-0004 <none> <none>
[root@master ~]# curl 10.244.240.138
nfs server
存储卷管理
临时卷
configMap卷
configMap是一种临时卷
configMap卷提供了向Pod注入配置数据的方法,允许你将配置文件与镜像分离,使容器化的应用具有可移植性 configMap在使用之前需要先创建它,configMap不是用来保存大量数据的,在其中保存的数据不可超过1MiB configMap的用途
创建configMap语法格式:kubectl create configmap 名称 [选项/参数]
修改系统时区(命令行创建)
[root@master ~]# kubectl create configmap tz --from-literal 'TZ=Asia/Shanghai'
configmap/tz created
[root@master ~]# kubectl get configmaps
NAME DATA AGE
kube-root-ca.crt 1 7d2h
tz 1 8s
[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
Nginx解析php
# 在 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是一种临时卷
Secret类似于ConfigMap但专门用语保存机密数据 在设置Secret.data
字段时,所有键值对必须是经过base64编码的字符串 Secret的用途
配置一些需要加密的环境变量或文件(例如:https证书) 访问需要认证登陆的私有镜像仓库(例如:harbor私有仓库) 创建secret语法格式:kubectl create secret 子类型 名称 [选项/参数]
子类型
通用类型:kubectl create secret generic 名称 [选项/参数]
用于认证登陆私有仓库的子类型:kubectl create secret docker-registry 名称 [选项/参数]
用语创建TLS证书的子类型:kubectl create secret tls 名称 [选项/参数]
创建TZ资源对象
[root@master ~]# kubectl create secret generic tz --from-literal 'TZ=Asia/Shanghai'
secret/tz created
[root@master ~]# kubectl get secrets tz -o yaml
apiVersion: v1
data:
TZ: QXNpYS9TaGFuZ2hhaQ== # 经加密过的数据
kind: Secret
metadata:
creationTimestamp: "2024-02-28T11:16:50Z"
name: tz
namespace: default
resourceVersion: "648195"
uid: 21097fce-1632-4b00-b45e-0d257ec599d5
type: Opaque
[root@master ~]# kubectl create secret docker-registry harbor-auth --docker-server=harbor:443 --docker-username="用户名" --docker-password="密码"
secret/harbor-auth created
[root@master ~]# vim web2.yaml
---
kind: Pod
apiVersion: v1
metadata:
name: web2
spec:
containers:
- name: apache
image: myos:httpd
imagePullSecrets:
- name: harbor-auth
[root@master ~]# kubectl apply -f web2.yaml
emptyDir卷
emptyDir临时卷
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)