目录
[5.3.2 创建静态持久卷PVC](#5.3.2 创建静态持久卷PVC)
[5.4.3创建provisioner Pod](#5.4.3创建provisioner Pod)
一.简单介绍
产生原因 :容器内部存储的生命周期是短暂的,会随着容器环境的销毁而销毁,具有不稳定性。如果多个容器希望共享同一份存储,则仅仅依赖容器本身是很难实现的。
说明 :在Kubernetes系统中,将对容器应用所需的存储资源抽象为存储卷(Volume)概念来解决这些问题 。 **Volume是与Pod绑定的(独立于容器)与Pod具有相同生命周期的资源对象。**可以将Volume的内容理解为目录或文件,容器如需使用某个Volume,则仅需设置volumeMounts将一个或多个Volume挂载为容器中的目录或文件,即可访问Volume中的数据。Volume具体是什么类型,以及由哪个系统提供,对容器应用来说是透明的。
类型分为 :emptyDir卷,hostPath卷和nfs卷等等。

二.临时存储卷------emptyDir卷
2.1简单介绍
说明 :该类型的Volume将在Pod被调度到Node时进行创建,在初始状态下目录中是空的,所以命名为"空目录"(Empty Directory),它与Pod具有相同的生命周期,当Pod被销毁时,Node上相应的目录也会被删除 。 同一个Pod中的多个容器都可以挂载这种Volume。Pod启动时为空,存储空间来自本地的kubelet 根目录(通常是根磁盘)或内存中。
2.2创建emptyDir卷
说明 :同一个 Pod 内多个容器通过 emptyDir 共享数据,并用"触发文件"做简单同步 。两个容器并行启动,第一个容器生产文件,第二个容器等待信号后消费(列出)文件。
1.编写yaml文件
bash
vim job-emptydir.yml
添加以下内容:
bash
apiVersion: batch/v1
kind: Job
metadata:
name: convert
spec:
backoffLimit: 3 #Pod最多重试 3 次
ttlSecondsAfterFinished: 100 # 100秒后自动回收job和pod
template:
spec:
restartPolicy: OnFailure
containers:
- image: reg.westos.org/library/centos:7
name: create-files
volumeMounts:
- mountPath: /cache
name: cache-volume
command:
- sh
- -c
- touch /cache/{1..30};touch /cache/trigger #创建文件
- image: reg.westos.org/library/centos:7
name: generate-logs
volumeMounts:
- mountPath: /logs
name: cache-volume
command:
- sh
- -c
- until test -f /logs/trigger;do sleep 1;done;find /logs/ #先轮询等待信号文件出现,再列出目录内容。
volumes:
- name: cache-volume
emptyDir: {} #挂载临时卷

2.运行yaml文件
bash
kubectl apply -f job-emptydir.yml
kubectl get jobs.batch
kubectl get pod
kubectl logs convert-2s5kw

2.3内存临时存储卷
1. 说明 :将 emptyDir.medium 字段设置为 "Memory" ,以告诉 Kubernetes 为您安装 tmpfs(基于内存的文件系统)。 虽然 tmpfs 速度非常快,但是要注意它与磁盘不同。 tmpfs 在节点重启时会被清除,并且您所写入的所有文件都会计入容器的内存消耗,受容器内存限制约束。
2.编写yaml文件
bash
vim job-emptydir_nginx.yml #使用内存临时存储
添加以下内容:
bash
apiVersion: v1
kind: Pod
metadata:
name: emptydir-tmpfs
spec:
containers:
- name: webapp
image: reg.westos.org/library/nginx
volumeMounts:
- mountPath: /usr/share/nginx/html
name: cache-volume
volumes:
- name: cache-volume
emptyDir:
medium: Memory #使用内存进行临时存储
sizeLimit: 100Mi #限制内存容量

3.运行yaml文件
说明:存储只有100MB,生成200MB的文件无法做到
bash
kubectl apply -f job-emptydir_nginx.yml #运行yaml文件
kubectl get pod emptydir-tmpfs -o wide #查看Pod
kubectl exec -it emptydir-tmpfs -- bash
dd if=/dev/zero of=/usr/share/nginx/html/bigfile bs=1M count=200 #生成200MB的文件

bash
du /usr/share/nginx/html/bigfile -h #查看文件

三.本地存储卷------hostPath卷
3.1简单介绍
说明 :HostPath类型的存储卷用于将Node文件系统的目录或文件挂载到容器内部使用 。对于大多数容器应用来说,都不需要使用宿主机的文件系统。容器应用的关键数据需要被持久化到宿主机上。 只要节点存在且路径未被删除,数据就会保留。
3.2创建hostPath卷
说明 :以 apiserver-etcd-client 证书通过 TLS 认证 ,连接本机 127.0.0.1:2379,把etcd 数据保存为带时间戳的 .bak 文件到 /backup/etcd/。
1.编写yaml文件
bash
vim etcd-backup.yml
添加以下内容:
bash
apiVersion: batch/v1
kind: CronJob
metadata:
name: etcd-backup
spec:
schedule: "*/5 * * * *" #每5分钟执行一次
concurrencyPolicy: Forbid #确保同一时间只有一个 Job 实例在运行。
jobTemplate:
spec:
ttlSecondsAfterFinished: 100 #Job执行100秒后删除
template:
spec:
nodeSelector:
kubernetes.io/hostname: "k8s1" #在k8s1上执行
tolerations: #容忍度
- key: node-role.kubernetes.io/control-plane
effect: NoSchedule
hostNetwork: true
restartPolicy: Never
volumes:
- name: etcd-certs
hostPath: #使用hostPath本地卷
path: /etc/kubernetes/pki
- name: etcd-data
hostPath: #使用hostPath本地卷
path: /backup/etcd
type: DirectoryOrCreate #挂载宿主机上的一个目录;如果这个目录不存在,就自动创建它。
containers:
- name: etcd-client
image: reg.westos.org/library/etcd:3.6.6-0
args:
- /bin/sh
- -ec
- ETCDCTL_API=3 etcdctl --cacert=/etc/kubernetes/pki/etcd/ca.crt
--cert=/etc/kubernetes/pki/apiserver-etcd-client.crt
--key=/etc/kubernetes/pki/apiserver-etcd-client.key
--endpoints https://127.0.0.1:2379
snapshot save /backup/etcd/etcd-$(date +%s).bak #以 apiserver-etcd-client 证书通过 TLS 认证,连接本机 127.0.0.1:2379,把 etcd 数据保存为带时间戳的 .bak 文件到 /backup/etcd/。
#- sleep 100000
volumeMounts:
- name: etcd-data
mountPath: /backup/etcd
- name: etcd-certs
mountPath: /etc/kubernetes/pki
readOnly: true

2.运行yaml文件
bash
kubectl apply -f etcd-backup.yml
kubectl get pod
kubectl logs emptydir-tmpfs #查看Pod日志
ll /backup/etcd/ #查看 etcd 备份文件


四.远程挂载卷------nfs卷
4.1简单介绍
1.说明 :nfs 卷能将 NFS (网络文件系统) 挂载到你的 Pod 中。 不像 emptyDir 那样会在删除 Pod 的同时也会被删除,nfs 卷的内容在删除 Pod 时会被保存,卷只是被卸载。 这意味着 nfs 卷可以被预先填充数据,并且这些数据可以在 Pod 之间共享。
4.2配置nfs服务
4.2.1配置nfs服务端
说明:真正存放数据的挂载点
1.安装server端
bash
yum install -y nfs-utils

2.编写exports文件
bash
mkdir -p /mnt/nfs/k8s #创建挂载目录
vim /etc/exports #编写exports文件

添加以下内容:
bash
/mnt/nfs *(rw,sync,no_root_squash)
参数介绍:
*:所有外机均可挂载
rw:拥有读写权限
sync:同步写入,数据落盘后,再传入
no_root_squash:客户端 root 用户保留 root 权限,不降权

3.启动服务
bash
systemctl enable --now nfs-server nfs-utils
showmount -e #查看本机的可挂载列表

4.2.2配置nfs客户端
说明:用于kubernetes集群的挂载点,所有节点均安装
bash
yum install -y nfs-utils #安装 nfs 服务
systemctl enable --now nfs-utils
systemctl status nfs-utils
4.3配置nfs卷
1.编写yaml文件
bash
vim sts-db-cm-secret-pvc.yml
添加以下内容:
bash
apiVersion: "apps/v1"
kind: "Deployment"
metadata:
name: "webserver"
spec:
replicas: 3
selector:
matchLabels:
app: "web"
template:
metadata:
labels:
app: "web"
spec:
containers:
- name: "apache-frontend"
image: "reg.westos.org/library/httpd:secure"
ports:
- containerPort: 80
env:
- name: DB_ROOT_PWD
valueFrom:
secretKeyRef: #引入secret
name: db-root-pwd
key: dbpwd
volumeMounts:
- name: webenvvol
mountPath: /etc/httpd/conf.d/env.conf
subPath: env.conf
- name: webdata
mountPath: /var/www/html/ #容器内部文件
volumes:
- name: webenvvol
configMap: #引入configmap
name: webenv
- name: webdata
nfs: #nfs远程挂载
server: 192.168.7.161 #挂载主机
path: /mnt/nfs/k8s #挂载目录

2.运行yaml文件
bash
kubectl apply -f deploy-web-secret-nfs.yml #执行yaml文件
kubectl get deployment
kubectl get pod -o wide

3.服务端添加内容,并完成测试:
bash
echo nfs > /mnt/nfs/k8s/index.html #index.html文件会自动挂载到容器内部

五.持久化存储
5.1简单介绍
说明 :Kubernetes 对于有状态的容器应用或者对数据需要持久化的应用,不仅需要将容器内的目录挂载到宿主机的目录或者emptyDir临时存储卷,而且需要更加可靠的存储来保存应用产生的重要数据,以便容器应用在重建之后仍然可以使用之前的数据。
不过,存储资源和计算资源(CPU/内存)的管理方式完全不同。为了能够屏蔽底层存储实现的细节,让用户方便使用,同时让管理员方便管理,Kubernetes 引入 PersistentVolume(PV)和PersistentVolumeClaim(PVC)两个资源对象来实现对存储的管理子系统。
5.2持久卷------PV
5.2.1简单介绍
1.说明 :是集群中的一块存储,可以由管理员事先制备,或者使用存储类(Storage Class**)来动态制备**。 持久卷是集群资源,就像节点也是集群资源一样。PV持久卷和普通的Volume一样, 也是使用卷插件来实现的,只是它们拥有独立于任何使用 PV 的 Pod 的生命周期。
2.工作流程:

3.PV回收策略
1. Retain:保留,该策略允许手动回收资源, 当删除PVC时,PV仍然存在 ,PV被视为已释放,管理员可以手动回收卷。
2. Recycle:回收,如果Volume插件支持,Recycle策略会对卷执行 rm -rf清理该PV,并使其可用于下一个新的PVC,目前回收策略Recycle已被废弃。3. Delete:删除,如果Volume插件支持,删除PVC时会同时删除PV,动态卷默认为Delete。
4.PV的访问策略
1. ReadWriteOnce :可以被单节点以读写模式挂载 ,命令行中可以被缩写为RWO。(块存储)适用于单Pod独占存储的场景(如数据库)。PV只能被调度到同一节点上的Pod挂载;同一节点上只能有一个Pod挂载该PV并写入数据。
2. ReadOnlyMany :可以被多个节点以只读模式挂载 ,命令行中可以被缩写为ROX。适用于需要多节点共享静态数据的场景(如配置文件)。
3.ReadWriteMany :可以被多个节点以读写模式挂载, 命令行中可以被缩写为RWX。(文件共享存储)
4.ReadWriteOncePod :可以被单个Pod以读写方式挂载。 如果你想确保整个集群中只有一个 Pod 可以读取或写入该 PVC, 请使用 ReadWriteOncePod 访问模式。
5.PV 生命周期的各个阶段状态
1. Available :可用,没有被PVC绑定的空闲资源。
2. Bound :已绑定,已经被PVC绑定。3. Released :已释放,PVC被删除,但是资源还未被重新使用。
4. Failed :失败,自动回收失败
5.3静态持久卷
5.3.1创建静态持久卷PV
说明:这里我使用nfs卷来创建pv,因为nfs卷能够确保不论pod在哪个节点上都可以连接到存储资源。
域名配置如下:
|---------------|------------------------|
| 主机IP | 域名解析 |
| 192.168.7.161 | docker1 reg.westos.org |
| 192.168.7.163 | k8s1 |
| 192.168.7.164 | k8s2 |
| 192.168.7.165 | k8s3 |
2.1配置nfs输出目录
说明:进入docker1,配置nfs挂载目录。由于前面已经讲过如何配置nfs服务,这里就不再赘述。
bash
mkdir -p /mnt/nfs/k8s1
cd /mnt/nfs/k8s1
mkdir pv1 pv2 pv3 #创建3个目录

2.2编写yaml文件
bash
vim pv-nfs.yml
添加以下内容:
bash
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv1 # PV名称
spec:
capacity:
storage: 5Gi # 容量配置,nfs不支持容量配置,配置时需要后端存储设备支持
volumeMode: Filesystem # 卷的模式,目前支持Filesystem(文件系统)和Block(块)
accessModes:
- ReadWriteOnce # PV的访问模式
persistentVolumeReclaimPolicy: Retain # PV的回收策略
storageClassName: nfs # PV的类
nfs:
path: /nfsdata/pv1 # NFS上的共享目录
server: 192.168.7.161 # NFS的IP地址
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv2
spec:
capacity:
storage: 10Gi
volumeMode: Filesystem
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
storageClassName: nfs
nfs:
path: /nfsdata/pv2
server: 192.168.7.161
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv3
spec:
capacity:
storage: 15Gi
volumeMode: Filesystem
accessModes:
- ReadOnlyMany
persistentVolumeReclaimPolicy: Retain
storageClassName: nfs
nfs:
path: /nfsdata/pv3
server: 192.168.7.161

2.3运行yaml文件,创建PV
bash
kubectl apply -f pv-nfs.yml
kubectl get pv

5.3.2 创建静态持久卷PVC
1.编写yaml文件
bash
vim pvc-nfs.yml
添加以下内容:
bash
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc1
spec:
storageClassName: nfs #存储卷类型
accessModes:
- ReadWriteOnce #读写模式
resources:
requests:
storage: 1Gi #请求1G的空间
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc2
spec:
storageClassName: nfs
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc3
spec:
storageClassName: nfs
accessModes:
- ReadOnlyMany
resources:
requests:
storage: 15Gi

2.运行yaml文件
说明:当你创建pvc后,如果pvc所提的资源需求刚好有对应活跃的pv存在吗,K8s 后台的控制器会自动寻找属性匹配的空闲 PV 并瞬间完成绑定。
bash
kubectl apply -f pvc-nfs.yml
kubectl get pvc

5.3.3绑定PVC
说明:如果你想指定绑定的pv,需要我们手动帮他们绑定
1.编写yaml文件
bash
vim deploy-web-secret-pvc.yml
添加以下内容:
bash
apiVersion: "apps/v1"
kind: "Deployment"
metadata:
name: "webserver"
spec:
replicas: 3
selector:
matchLabels:
app: "web"
template:
metadata:
labels:
app: "web"
spec:
containers:
- name: "apache-frontend"
image: "reg.westos.org/library/httpd:secure"
ports:
- containerPort: 80
env:
- name: DB_ROOT_PWD
valueFrom:
secretKeyRef:
name: db-root-pwd
key: dbpwd
volumeMounts:
- name: webenvvol
mountPath: /etc/httpd/conf.d/env.conf
subPath: env.conf
- name: webdata
mountPath: /var/www/html/
volumes:
- name: webenvvol
configMap:
name: webenv
- name: webdata
persistentVolumeClaim: #挂载PVC
claimName: pvc1 #3个pod挂载pvc1

2.运行yaml文件
bash
kubectl apply -f deploy-web-secret-pvc.yml
kubectl describe deployment webserver | grep volume -A5 #查看是否挂载成功

3.测试挂载卷
bash
echo pv1 > /mnt/nfs/k8s1/pv1/index.html #输入内容
kubectl get svc -o wide
curl 192.168.7.100

使用pod测试
bash
kubectl get pod -o wide
curl 10.244.219.60
curl 10.244.109.113
curl 10.244.109.114

5.3.4回收Pv
说明 :清理pvc后,需要手动清理PV,不然无法再次绑定
回收顺序 :先删pvc,后删pv
1.删除pvc
bash
kubectl delete pvc pvc3
kubectl get pvc
kubectl get pv

2.删除pv
bash
kubectl delete pv pv3
kubectl get pv

5.4动态持久卷
5.4.1简单介绍
1.说明 :动态存储就是"存储卷随用随建" :用户写一个 PVC 说"我要多大、什么类型",StorageClass 提供配方,Provisioner 当场在底层存储系统里创建出这块卷并生成 PV,自动完成绑定。它取代了"管理员提前手动创建 PV"的静态模式,实现了存储的按需供给、自助服务、弹性伸缩------这也是云原生存储体系的核心能力。
2.工作流程:
1.管理员创建
StorageClass,声明"我能提供什么"。2.用户创建
PersistentVolumeClaim(PVC) ,声明"我需要什么",并通过storageClassName字段指定想要的类别。3.Kubernetes 根据匹配的
StorageClass定义,自动调用底层存储驱动,创建出对应的 PV 并完成绑定。
5.4.2创建RBAC
1.RBAC :Role-Based Access Control(基于角色的访问控制) ,是 Kubernetes 的授权(Authorization)机制 ,回答的问题是:"这个身份,能对哪些资源,执行哪些操作?"
2.yaml文件说明 :创建一个专用的 ServiceAccount ,并赋予它足够的权限,使其能够监听 PVC 的创建请求,自动在 NFS 服务器上创建目录 ,并生成对应的 PersistentVolume(PV),从而实现基于 NFS 的动态存储供给。
3.编辑yaml文件
bash
vim rbac.yml #编辑yaml文件
添加以下内容:
bash
apiVersion: v1
kind: Namespace
metadata:
name: nfs-client-provisioner #创建一个namespace
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-client-provisioner #创建SA访问角色
namespace: nfs-client-provisioner
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: nfs-client-provisioner-runner
rules:
- apiGroups: [""]
resources: ["nodes"] #节点权限
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["persistentvolumes"] #PV权限
verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"] #PVC权限
verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"] #存储类权限
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["events"] #events权限
verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding #集群权限绑定
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: run-nfs-client-provisioner
subjects:
- kind: ServiceAccount #SA账户
name: nfs-client-provisioner
namespace: nfs-client-provisioner
roleRef:
kind: ClusterRole #集群权限
name: nfs-client-provisioner-runner
apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
namespace: nfs-client-provisioner
rules:
- apiGroups: [""]
resources: ["endpoints"] #后端节点权限,多个后端Pod会竞争成为"Leader",只有 Leader 才执行实际的 PV 创建操作,避免重复供给
verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
namespace: nfs-client-provisioner
subjects:
- kind: ServiceAccount #SA账户
name: nfs-client-provisioner
namespace: nfs-client-provisioner
roleRef:
kind: Role #绑定Role权限
name: leader-locking-nfs-client-provisioner
apiGroup: rbac.authorization.k8s.io
4.运行yaml文件
bash
kubectl apply -f rbac.yml

5.4.3创建provisioner Pod
1.编写deployment控制器
说明:在集群里运行一个 Provisioner Pod,让它监听 PVC 事件,在 NFS 共享目录下创建子目录并生成 PV,实现 NFS 的动态存储供给。
bash
vim deployment.yml
添加以下内容:
bash
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-client-provisioner
labels:
app: nfs-client-provisioner
namespace: nfs-client-provisioner
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: nfs-client-provisioner
template:
metadata:
labels:
app: nfs-client-provisioner
spec:
serviceAccountName: nfs-client-provisioner
containers:
- name: nfs-client-provisioner
image: reg.westos.org/sig-storage/nfs-subdir-external-provisioner:v4.0.2 #镜像需要科学上网下载
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: k8s-sigs.io/nfs-subdir-external-provisioner
- name: NFS_SERVER
value: 192.168.7.161
- name: NFS_PATH
value: /mnt/nfs/k8s
volumes:
- name: nfs-client-root
nfs:
server: 192.168.7.161
path: /mnt/nfs/k8s

运行yaml文件
bash
kubectl apply -f deployment.yml
kubectl get deployments.apps -n nfs-client-provisioner
kubectl get pod -n nfs-client-provisioner -o wide


5.4.4创建StroageClass
1.说明 :StorageClass (存储类)是 Kubernetes 中用于描述和抽象存储"服务等级"的集群级资源 。你可以把它理解为集群管理员提供给用户的一份"存储菜单",用户通过它来声明自己需要"哪种类型、什么性能"的存储,而不必关心底层究竟用的是 AWS EBS、GCE PD 还是 Ceph。
2.编写yaml文件
说明:声明一个名为 nfs-client 的存储类,指定由 k8s-sigs.io/nfs-subdir-external-provisioner 来动态创建 PV,并把它设为集群默认存储类。
bash
vim class.yml #编写yaml文件
添加以下内容:
bash
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs-client
annotations:
storageclass.kubernetes.io/is-default-class: "true"
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner
parameters:
archiveOnDelete: "false" #删除 PVC 时目录直接删

3.运行yaml文件
bash
kubectl apply -f class.yml
kubectl get sc

5.4.5创建PVC
1.说明 :根据nfs-client的存储类创建PVC,PVC创建完成后,会使用Provisioner Pod自动创建对应PV
2.编写yaml文件
bash
vim test-claim.yaml
添加以下内容:
bash
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: test-claim
spec:
storageClassName: nfs-client #定义存储类
accessModes:
- ReadWriteMany
resources: #资源
requests: #需求
storage: 1Gi

3.运行yaml文件
bash
kubectl apply -f test-claim.yaml
kubectl get pv pvc-ca9cdbfc-8ddc-4677-8a62-e1eb9b467d7c #pvc-ca这个是自动创建的
ll /mnt/nfs/k8s | grep default-test-claim-pvc-ca9cdbfc-8ddc-4677-8a62-e1eb9b467d7c



5.4.6回收PVC
说明 :动态创建的PVC,删除PVC后,会自动删除对应的PV
bash
kubectl delete pvc test-claim #删除PVC
kubectl get pv

5.4.7测试前端
1.创建前端PVC
1.1编写yaml文件
bash
vim pvc-webclaim.yml
添加以下内容:
bash
kubectl apply -f pvc-webclaim.yml
kubectl get pvc webclaim

2.创建前端Web
bash
vim deploy-web-secret-pvc-update.yml
添加以下内容:
bash
apiVersion: "apps/v1"
kind: "Deployment"
metadata:
name: "webserver"
spec:
replicas: 3
selector:
matchLabels:
app: "web"
template:
metadata:
labels:
app: "web"
spec:
containers:
- name: "apache-frontend"
image: "reg.westos.org/library/httpd:secure"
ports:
- containerPort: 80
env:
- name: DB_ROOT_PWD
valueFrom:
secretKeyRef:
name: db-root-pwd
key: dbpwd
volumeMounts:
- name: webenvvol
mountPath: /etc/httpd/conf.d/env.conf
subPath: env.conf
- name: webdata
mountPath: /var/www/html/
volumes:
- name: webenvvol
configMap:
name: webenv
- name: webdata
persistentVolumeClaim:
claimName: webclaim #配置webclaim

3.运行yaml文件
bash
kubectl apply -f deploy-web-secret-pvc-update.yml
kubectl get pod -o wide

4.配置访问页面
1.配置访问页
bash
kubectl get pvc webclaim
cd /mnt/nfs/k8s/default-webclaim-pvc-db0cf668-43e5-4fc3-864e-9a93f5aee7f6/
echo webclaim > index.html #配置访问页面

2.访问web页面
bash
kubectl get pod -o wide
curl 10.244.219.15
curl 10.244.109.94
curl 10.244.109.124

5.4.8测试后端
1.编写yaml文件
bash
vim sts-db-cm-secret-pvc.yml
添加以下内容:
bash
apiVersion: "apps/v1"
kind: "StatefulSet"
metadata:
name: "dbserver"
spec:
replicas: 3
selector:
matchLabels:
app: "db"
serviceName: "database"
template:
metadata:
labels:
app: "db"
spec:
containers:
- name: "db-backend"
image: "reg.westos.org/library/mysql:v2"
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: db-root-pwd
key: dbpwd
ports:
- containerPort: 3306
volumeMounts:
- name: configvol
mountPath: /docker-entrypoint-initdb.d/
- name: database
mountPath: /var/lib/mysql #挂载数据目录
resources:
limits:
cpu: 500m
memory: 512Mi
volumes:
- name: configvol
configMap:
name: dbinit
volumeClaimTemplates:
- metadata:
name: database
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1G
2.运行yaml文件
bash
kubectl apply -f sts-db-cm-secret-pvc.yml
kubectl get pod -l app=db -o wide
kubectl get pvc


3.更新后端数据库
3.1创建新用户
bash
kubectl port-forward dbserver-2 33060:3306 & #完成端口映射
mysql -h 127.0.0.1 -P 33060 -u root -pmysql -e 'create user philip;' #只修改dbserver-2的数据库
curl 192.168.7.100/cgi-bin/action #由于存在三个后端,多个后端轮询访问,有一个能够看到


3.2删除后重建Pod
bash
kubectl delete pod dbserver-2
kubectl get pod dbserver-2
curl 192.168.7.100/cgi-bin/action


5.5部署mysql分布式集群
5.5.1部署mysql主数据库
1.创建Service
适用场景: 该配置通常用于 需要提前发现节点 / Pod,或依赖未就绪状态下的网络通信的场景,
1.分布式集群初始化:某些分布式系统(如 ZooKeeper、Kafka)在启动过程中,即使节点未完全就绪(Ready),也需要互相发现并通信以完成集群初始化。
2.健康检查与故障恢复:允许监控系统或管理工具在 Pod 未就绪时仍能访问,以便诊断问题
**3.滚动更新过渡:**在滚动更新过程中,新 Pod 可能需要与旧 Pod 通信以同步数据,即使新 Pod 尚未完全就绪。
bash
vim service-galera.yml
添加以下内容:
bash
apiVersion: "v1"
kind: "Service"
metadata:
name: "galera"
spec:
publishNotReadyAddresses: true #当设置 publishNotReadyAddresses: true 时,Service 会将 所有 Pod(无论是否就绪)的地址都发布到 DNS,客户端可以通过 DNS 解析到未就绪的 Pod IP。
clusterIP: None
ports:
- protocol: "TCP"
port: 3306
selector:
app: "mysql"

2.运行yaml文件
bash
kubectl apply -f service-galera.yml
kubectl get svc galera

2.创建statefulset
2.1编写yaml文件
bash
vim statefulset-galera.yml
添加以下内容:
bash
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
serviceName: "galera"
replicas: 3
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
initContainers:
- name: install
image: reg.westos.org/library/galera-install:0.1
args:
- "--work-dir=/work-dir"
volumeMounts:
- name: workdir
mountPath: "/work-dir"
- name: config
mountPath: "/etc/mysql"
- name: bootstrap
image: reg.westos.org/library/debian:jessie
command:
- "/work-dir/peer-finder"
args:
- -on-start="/work-dir/on-start.sh"
- "-service=galera"
env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
volumeMounts:
- name: workdir
mountPath: "/work-dir"
- name: config
mountPath: "/etc/mysql"
containers:
- name: mysql
image: reg.westos.org/library/mysql-galera:e2e
ports:
- containerPort: 3306
name: mysql
- containerPort: 4444
name: sst
- containerPort: 4567
name: replication
- containerPort: 4568
name: ist
args:
- --defaults-file=/etc/mysql/my-galera.cnf
- --user=root
readinessProbe:
# TODO: If docker exec is buggy just use k8s.gcr.io/mysql-healthz:1.0
exec:
command:
- sh
- -c
- "mysql -u root -e 'show databases;'"
initialDelaySeconds: 15
timeoutSeconds: 5
successThreshold: 2
volumeMounts:
- name: datadir
mountPath: /var/lib/
- name: config
mountPath: /etc/mysql
volumes:
- name: config
emptyDir: {}
- name: workdir
emptyDir: {}
volumeClaimTemplates:
- metadata:
name: datadir
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi
2.2运行yaml文件
bash
kubectl apply -f statefulset-galera.yml
kubectl get pod -l app=mysql -o wide

2.3运行镜像
bash
kubectl run -it dbtest --rm --image=reg.westos.org/library/mysql -- bash
mysql -h galera -e "show status like 'wsrep_incoming_addresses'"
mysql -h galera -e "create database hadb;"
mysql -h mysql-0.galera -e "show databases;"
mysql -h mysql-1.galera -e "show databases;"
mysql -h mysql-2.galera -e "show databases;"


5.5.2回收数据库集群
bash
kubectl scale --replicas=0 statefulset mysql
kubectl delete -f statefulset-galera.yml
