k8s中的存储
目录
一 configmap
1.1 configmap的功能
1.2 configmap的使用场景
1.3 configmap创建方式
1.3.1 字面值创建
1.3.2 通过文件创建
1.3.3 通过目录创建
1.3.4 通过yaml文件创建
1.3.5 configmap的使用方式
1.3.5.1 使用configmap填充环境变量
1.3.5.2 通过数据卷使用configmap
1.3.5.3 利用configMap填充pod的配置文件
1.3.5.4 通过热更新cm修改配置
二 secrets配置管理
2.1 secrets的功能介绍
2.2 secrets的创建
2.2.1从文件创建
2.2.2 编写yaml文件
2.3 Secret的使用方法
2.3.1 将Secret挂载到Volume中
2.3.2 向指定路径映射 secret 密钥
2.3.3 将Secret设置为环境变量
2.3.4 存储docker registry的认证信息
三 volumes配置管理
3.1 kubernets支持的卷的类型
3.2 emptyDir卷
3.3 hostpath卷
3.4 nfs卷
3.4.1 部署一台nfs共享主机并在所有k8s节点中安装nfs-utils
3.4.2 部署nfs卷
3.5 PersistentVolume持久卷
3.5.1 静态持久卷pv与静态持久卷声明pvc
PersistentVolume(持久卷,简称PV)
PersistentVolumeClaim(持久卷声明,简称PVC)
volumes访问模式
volumes回收策略
volumes状态说明
静态pv实例:
在pod中使用pvc
四 存储类storageclass
4.1 StorageClass说明
4.2 StorageClass的属性
4.3 存储分配器NFS Client Provisioner
4.4 部署NFS Client Provisioner
4.4.1 创建sa并授权
4.4.2 部署应用
4.4.3 创建存储类
4.4.4 创建pvc
4.4.5 创建测试pod
4.4.6 设置默认存储类
五 statefulset控制器
5.1 功能特性
5.2 StatefulSet的组成部分
5.3 构建方法
5.4 测试:
5.5 statefulset的弹缩
一 configmap
1.1 configmap的功能
-
configMap用于保存配置数据,以键值对形式存储。
-
configMap 资源提供了向 Pod 注入配置数据的方法。
-
镜像和配置文件解耦,以便实现镜像的可移植性和可复用性。
-
etcd限制了文件大小不能超过1M
1.2 configmap的使用场景
-
填充环境变量的值
-
设置容器内的命令行参数
-
填充卷的配置文件
1.3 configmap创建方式
1.3.1 字面值创建
#创建一个名为 “superhowe-config” 的 ConfigMap,其中包含两个键值对:“fname=super” 和 “lname=howe”[root@k8s-master ~]# kubectl create cm superhowe-config --from-literal fname=super --from-literal lname=howe
configmap/superhowe-config created[root@k8s-master ~]# kubectl describe cm superhowe-config
Name: superhowe-config
Namespace: default
Labels: <none>
Annotations: <none>Data #键值信息显示
====
fname:
----
super
lname:
----
howeBinaryData
====Events: <none>
1.3.2 通过文件创建
[root@k8s-master ~]# cat /etc/resolv.conf
# Generated by NetworkManager
search exam.com
nameserver 172.25.250.2[root@k8s-master ~]# kubectl create cm howe-config --from-file /etc/resolv.conf
configmap/howe-config created[root@k8s-master ~]# kubectl describe cm howe-config
Name: howe-config
Namespace: default
Labels: <none>
Annotations: <none>Data
====
resolv.conf:
----
# Generated by NetworkManager
search exam.com
nameserver 172.25.250.2BinaryData
====Events: <none>
1.3.3 通过目录创建
[root@k8s-master ~]# mkdir config
[root@k8s-master ~]# cp /etc/fstab /etc/rc.d/rc.local config/
[root@k8s-master ~]# kubectl create cm howe2-config --from-file config/
configmap/howe2-config created
[root@k8s-master ~]# kubectl describe cm howe2-config
Name: howe2-config
Namespace: default
Labels: <none>
Annotations: <none>Data
====
rc.local:
----
#!/bin/bash
# THIS FILE IS ADDED FOR COMPATIBILITY PURPOSES
#
# It is highly advisable to create own systemd services or udev rules
# to run scripts during boot instead of using this file.
#
# In contrast to previous versions due to parallel execution during boot
# this script will NOT be run after all other services.
#
# Please note that you must run 'chmod +x /etc/rc.d/rc.local' to ensure
# that this script will be executed during boot.touch /var/lock/subsys/local
mount /dev/sr0 /rhel9fstab:
----#
# /etc/fstab
# Created by anaconda on Wed Jul 31 03:08:58 2024
#
# Accessible filesystems, by reference, are maintained under '/dev/disk/'.
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info.
#
# After editing this file, run 'systemctl daemon-reload' to update systemd
# units generated from this file.
#
/dev/mapper/rhel-root / xfs defaults 0 0
UUID=15f86ce4-5a55-499e-8510-36a08ab8db17 /boot xfs defaults 0 0
#/dev/mapper/rhel-swap none swap defaults 0 0BinaryData
====Events: <none>
1.3.4 通过yaml文件创建
[root@k8s-master ~]# kubectl create cm howe3-config --from-literal db_host=172.25.250.100 --from-literal db_port=3306 --dry-run=client -o yaml > howe-config.yaml[root@k8s-master ~]# vim howe-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:name: howe3-config
data:db_host: 172.25.250.100db_port: "3306"[root@k8s-master ~]# kubectl apply -f howe-config.yaml
configmap/howe3-config created
[root@k8s-master ~]# kubectl describe cm howe3-config
Name: howe3-config
Namespace: default
Labels: <none>
Annotations: <none>Data
====
db_host:
----
172.25.250.100
db_port:
----
3306BinaryData
====Events: <none>
1.3.5 configmap的使用方式
-
通过环境变量的方式直接传递给pod
-
通过pod的 命令行运行方式
-
作为volume的方式挂载到pod内
1.3.5.1 使用configmap填充环境变量
#讲cm中的内容映射为指定变量
[root@k8s-master ~]# vim testpod1.yml
apiVersion: v1
kind: Pod
metadata:labels:run: testpodname: testpod
spec:containers:- image: busyboxplus:latestname: testpodcommand:- /bin/sh- -c- envenv:- name: key1valueFrom:configMapKeyRef:name: howe-configkey: db_host- name: key2valueFrom:configMapKeyRef:name: howe-configkey: db_portrestartPolicy: Never[root@k8s-master ~]# kubectl apply -f testpod1.yml
pod/testpod created#查看日志
[root@k8s-master ~]# kubectl logs pods/testpod
KUBERNETES_SERVICE_PORT=443
KUBERNETES_PORT=tcp://10.96.0.1:443
MYAPP_V1_SERVICE_HOST=10.102.186.55
HOSTNAME=testpod
SHLVL=1
MYAPP_V2_SERVICE_HOST=10.96.232.137
HOME=/
MYAPP_V1_SERVICE_PORT=80
MYAPP_V1_PORT=tcp://10.102.186.55:80
MYAPP_V2_PORT=tcp://10.96.232.137:80
MYAPP_V2_SERVICE_PORT=80
MYAPP_V1_PORT_80_TCP_ADDR=10.102.186.55
MYAPP_V2_PORT_80_TCP_ADDR=10.96.232.137
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
MYAPP_V1_PORT_80_TCP_PORT=80
MYAPP_V1_PORT_80_TCP_PROTO=tcp
MYAPP_V2_PORT_80_TCP_PORT=80
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MYAPP_V2_PORT_80_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
key1=172.25.250.100
key2=3306
MYAPP_V1_PORT_80_TCP=tcp://10.102.186.55:80
MYAPP_V2_PORT_80_TCP=tcp://10.96.232.137:80
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
PWD=/
KUBERNETES_SERVICE_HOST=10.96.0.1#把cm中的值直接映射为变量
[root@k8s-master ~]# vim testpod2.yml
apiVersion: v1
kind: Pod
metadata:labels:run: testpodname: testpod
spec:containers:- image: busyboxplus:latestname: testpodcommand:- /bin/sh- -c- envenvFrom:- configMapKeyRef:name: howe3-configrestartPolicy: Never#查看日志
[root@k8s-master ~]# kubectl logs pods/testpod
KUBERNETES_SERVICE_PORT=443
KUBERNETES_PORT=tcp://10.96.0.1:443
MYAPP_V1_SERVICE_HOST=10.102.186.55
HOSTNAME=testpod
SHLVL=1
MYAPP_V2_SERVICE_HOST=10.96.232.137
HOME=/
MYAPP_V1_SERVICE_PORT=80
MYAPP_V1_PORT=tcp://10.102.186.55:80
MYAPP_V2_PORT=tcp://10.96.232.137:80
MYAPP_V2_SERVICE_PORT=80
MYAPP_V1_PORT_80_TCP_ADDR=10.102.186.55
MYAPP_V2_PORT_80_TCP_ADDR=10.96.232.137
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
MYAPP_V1_PORT_80_TCP_PORT=80
MYAPP_V1_PORT_80_TCP_PROTO=tcp
MYAPP_V2_PORT_80_TCP_PORT=80
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MYAPP_V2_PORT_80_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
key1=172.25.250.100
key2=3306
MYAPP_V1_PORT_80_TCP=tcp://10.102.186.55:80
MYAPP_V2_PORT_80_TCP=tcp://10.96.232.137:80
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
PWD=/
KUBERNETES_SERVICE_HOST=10.96.0.1#在pod命令行中使用变量
[root@k8s-master ~]# vim testpod3.yml
apiVersion: v1
kind: Pod
metadata:labels:run: testpodname: testpod
spec:containers:- image: busyboxplus:latestname: testpodcommand:- /bin/sh- -c- echo ${db_host} ${db_port}envFrom:- configMapKeyRef:name: howe3-configrestartPolicy: Never#查看日志
[root@k8s-master ~]# kubectl logs pods/testpod
1.3.5.2 通过数据卷使用configmap
[root@k8s-master ~]# vim testpod4.yml
apiVersion: v1
kind: Pod
metadata:labels:run: testpodname: testpod
spec:containers:- image: busyboxplus:latestname: testpodcommand:- /bin/sh- -c- cat /config/db_hostvolumeMounts: #调用卷策略- name: config-volume #卷名称mountPath: /configvolumes: #声明卷的配置- name: config-volume #卷名称configMap:name: howe3-configrestartPolicy: Never#查看日志
[root@k8s-master ~]# kubectl logs testpod
key1=172.25.250.100
key2=3306
1.3.5.3 利用configMap填充pod的配置文件
#建立配置文件模板
[root@k8s-master ~]# vim nginx.conf
server {listen 8000;server_name _;root /usr/share/nginx/html;index index.html;
}#利用模板生成cm
[root@k8s-master ~]# kubectl create cm nginx-conf --from-file nginx.conf
configmap/nginx.conf created[root@k8s-master ~]# kubectl get cm nginx-conf
NAME DATA AGE
nginx-conf 1 32s[root@k8s-master ~]# kubectl describe cm nginx-conf
Name: nginx-conf
Namespace: default
Labels: <none>
Annotations: <none>Data
====
nginx.conf:
----
server {listen 8000;server_name _;root /usr/share/nginx/html;index index.html;
}BinaryData
====Events: <none>#建立nginx控制器文件
[root@k8s-master ~]# kubectl create deployment nginx --image nginx:latest --replicas 1 --dry-run=client -o yaml > nginx.yml#设定nginx.yml中的卷
[root@k8s-master ~]# vim nginx.yml
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: nginxname: nginx
spec:replicas: 1selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:containers:- image: nginx:latestname: nginxvolumeMounts:- name: config-volumemountPath: /etc/nginx/conf.dvolumes:- name: config-volumeconfigMap:name: nginx-conf[root@k8s-master ~]# kubectl apply -f nginx.yml
deployment.apps/nginx created#测试
[root@k8s-master ~]# kubectl get deployments.apps
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 1/1 1 1 16m[root@k8s-master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-8487c65cfc-v8q2g 1/1 Running 0 17m 10.244.1.9 k8s-node1.exam.com <none> <none>[root@k8s-master ~]# curl 10.244.1.9:8000
1.3.5.4 通过热更新cm修改配置
#如需更改端口
[root@k8s-master ~]# kubectl edit cm nginx-conf
9 listen 8080;[root@k8s-master ~]# kubectl exec pods/nginx-8487c65cfc-v8q2g -- cat /etc/nginx/conf.d/nginx.conf
server {listen 8080;server_name _;root /usr/share/nginx/html;index index.html;
}[root@k8s-master ~]# kubectl delete pods nginx-8487c65cfc-v8q2g
pod "nginx-8487c65cfc-v8q2g" deleted[root@k8s-master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-8487c65cfc-7s4lh 1/1 Running 0 92s 10.244.2.6 k8s-node2.exam.com <none> <none>[root@k8s-master ~]# curl 10.244.2.6:8080
二 secrets配置管理
2.1 secrets的功能介绍
-
Secret 对象类型用来保存敏感信息,例如密码、OAuth 令牌和 ssh key。
-
敏感信息放在 secret 中比放在 Pod 的定义或者容器镜像中来说更加安全和灵活
-
Pod 可以用两种方式使用 secret:
-
作为 volume 中的文件被挂载到 pod 中的一个或者多个容器里。
-
当 kubelet 为 pod 拉取镜像时使用。
-
-
Secret的类型:
-
Service Account:Kubernetes 自动创建包含访问 API 凭据的 secret,并自动修改 pod 以使用此类型的 secret。
-
Opaque:使用base64编码存储信息,可以通过base64 --decode解码获得原始数据,因此安全性弱。
-
kubernetes.io/dockerconfigjson:用于存储docker registry的认证信息
-
2.2 secrets的创建
在创建secrets时我们可以用命令的方法或者yaml文件的方法
2.2.1从文件创建
[root@k8s-master ~]# echo -n howe > username.txt
[root@k8s-master ~]# echo -n www > password.txt
[root@k8s-master ~]# kubectl create secret generic userlist --from-file username.txt --from-file password.txt
secret/userlist created
[root@k8s-master ~]# kubectl get secrets userlist -o yaml
apiVersion: v1
data:password.txt: d3d3username.txt: aG93ZQ==
kind: Secret
metadata:creationTimestamp: "2024-09-08T13:02:06Z"name: userlistnamespace: defaultresourceVersion: "222543"uid: 30dfc207-da48-47d4-98db-fe4aa1dca592
type: Opaque
2.2.2 编写yaml文件
#howe的Base64编码表示
[root@k8s-master ~]# echo -n howe | base64 #用户名
aG93ZQ==
[root@k8s-master ~]# echo -n www | base64 #密码
d3d3[root@k8s-master ~]# kubectl create secret generic userlist --dry-run=client -o yaml > userlist.yml[root@k8s-master ~]# vim userlist.yml
apiVersion: v1
kind: Secret
metadata:name: userlist
type: Opaque
data:username: aG93ZQ==password: d3d3[root@k8s-master ~]# kubectl delete secrets userlist
secret "userlist" deleted[root@k8s-master ~]# kubectl get secrets userlist -o yaml
apiVersion: v1
data:password: d3d3username: aG93ZQ==
2.3 Secret的使用方法
2.3.1 将Secret挂载到Volume中
[root@k8s-master ~]# kubectl run nginx --image nginx --dry-run=client -o yaml > pod1.yaml#向固定路径映射
[root@k8s-master ~]# vim pod1.yaml
apiVersion: v1
kind: Pod
metadata:labels:run: nginxname: nginx
spec:containers:- image: nginxname: nginxvolumeMounts:- name: secretsmountPath: /secretreadOnly: truevolumes:- name: secretssecret:secretName: userlist[root@k8s-master ~]# kubectl apply -f pod1.yaml
pod/nginx created[root@k8s-master ~]# kubectl exec pods/nginx -it -- /bin/bash
root@nginx:/# cd /secret/
root@nginx:/secret# ls
password username
root@nginx:/secret# cat password
wwwroot@nginx:/secret# cat username
howeroot@nginx:/secret#
2.3.2 向指定路径映射 secret 密钥
#向指定路径映射
[root@k8s-master ~]# vim pod2.yaml
apiVersion: v1
kind: Pod
metadata:labels:run: nginx1name: nginx1
spec:containers:- image: nginxname: nginx1volumeMounts:- name: secretsmountPath: /secretreadOnly: truevolumes:- name: secretssecret:secretName: userlistitems:- key: usernamepath: my-users/username[root@k8s-master ~]# kubectl apply -f pod2.yaml
pod/nginx1 created[root@k8s-master ~]# kubectl exec pods/nginx1 -it -- /bin/bash
root@nginx1:/# cd secret/
root@nginx1:/secret# ls
my-users
root@nginx1:/secret# cd my-users
root@nginx1:/secret/my-users# ls
username
root@nginx1:/secret/my-users# cat username
howeroot@nginx1:/secret/my-users#
2.3.3 将Secret设置为环境变量
[root@k8s-master ~]# vim pod3.yaml
apiVersion: v1
kind: Pod
metadata:labels:run: busyboxname: busybox
spec:containers:- image: busyboxname: busyboxcommand:- /bin/sh- -c- envenv:- name: USERNAMEvalueFrom:secretKeyRef:name: userlistkey: username- name: PASSvalueFrom:secretKeyRef:name: userlistkey: passwordrestartPolicy: Never[root@k8s-master ~]# kubectl apply -f pod3.yaml
pod/busybox created
[root@k8s-master ~]# kubectl logs pods/busybox
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT=443
HOSTNAME=busybox
MYAPP_V1_SERVICE_HOST=10.102.186.55
MYAPP_V2_SERVICE_HOST=10.96.232.137
SHLVL=1
HOME=/root
MYAPP_V1_SERVICE_PORT=80
MYAPP_V1_PORT=tcp://10.102.186.55:80
MYAPP_V2_SERVICE_PORT=80
MYAPP_V2_PORT=tcp://10.96.232.137:80
MYAPP_V1_PORT_80_TCP_ADDR=10.102.186.55
USERNAME=howe
MYAPP_V2_PORT_80_TCP_ADDR=10.96.232.137
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
MYAPP_V1_PORT_80_TCP_PORT=80
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MYAPP_V2_PORT_80_TCP_PORT=80
MYAPP_V1_PORT_80_TCP_PROTO=tcp
MYAPP_V2_PORT_80_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
MYAPP_V1_PORT_80_TCP=tcp://10.102.186.55:80
MYAPP_V2_PORT_80_TCP=tcp://10.96.232.137:80
PASS=www
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_SERVICE_HOST=10.96.0.1
PWD=/
2.3.4 存储docker registry的认证信息
建立私有仓库并上传镜像
#建立私有仓库并上传镜像
[root@k8s-master ~]# docker login reg.exam.com#上传镜像
[root@k8s-master ~]# docker load -i game2048.tar
[root@k8s-master ~]# docker tag timinglee/game2048:latest reg.exam.com/howe/game2048:latest
[root@k8s-master ~]# docker push reg.exam.com/howe/game2048
Using default tag: latest
The push refers to repository [reg.exam.com/howe/game2048]
88fca8ae768a: Pushed
6d7504772167: Pushed
192e9fad2abc: Pushed
36e9226e74f8: Pushed
011b303988d2: Pushed
latest: digest: sha256:8a34fb9cb168c420604b6e5d32ca6d412cb0d533a826b313b190535c03fe9390 size: 1364#建立用于docker认证的secret
[root@k8s-master ~]# kubectl create secret docker-registry docker-auth --docker-server reg.exam.com --docker-username admin --docker-password redhat --docker-email howe@howe.com#编写yml文件
[root@k8s-master ~]# vim pod4.yml
apiVersion: v1
kind: Pod
metadata:labels:run: game2048name: game2048
spec:containers:- image: reg.exam.com/howe/game2048:latestname: game2048imagePullSecrets: #不设定docker认证时无法下载镜像- name: docker-auth[root@k8s-master ~]# kubectl apply -f pod4.yml
pod/game2048 created[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
game2048 1/1 Running 0 11s
三 volumes配置管理
-
容器中文件在磁盘上是临时存放的,这给容器中运行的特殊应用程序带来一些问题
-
当容器崩溃时,kubelet将重新启动容器,容器中的文件将会丢失,因为容器会以干净的状态重建。
-
当在一个 Pod 中同时运行多个容器时,常常需要在这些容器之间共享文件。
-
Kubernetes 卷具有明确的生命周期与使用它的 Pod 相同
-
卷比 Pod 中运行的任何容器的存活期都长,在容器重新启动时数据也会得到保留
-
当一个 Pod 不再存在时,卷也将不再存在。
-
Kubernetes 可以支持许多类型的卷,Pod 也能同时使用任意数量的卷。
-
卷不能挂载到其他卷,也不能与其他卷有硬链接。 Pod 中的每个容器必须独立地指定每个卷的挂载位置。
3.1 kubernets支持的卷的类型
官网:卷 | Kubernetes
k8s支持的卷的类型如下:
-
awsElasticBlockStore 、azureDisk、azureFile、cephfs、cinder、configMap、csi
-
downwardAPI、emptyDir、fc (fibre channel)、flexVolume、flocker
-
gcePersistentDisk、gitRepo (deprecated)、glusterfs、hostPath、iscsi、local、
-
nfs、persistentVolumeClaim、projected、portworxVolume、quobyte、rbd
-
scaleIO、secret、storageos、vsphereVolume
3.2 emptyDir卷
功能:
当Pod指定到某个节点上时,首先创建的是一个emptyDir卷,并且只要 Pod 在该节点上运行,卷就一直存在。卷最初是空的。 尽管 Pod 中的容器挂载 emptyDir 卷的路径可能相同也可能不同,但是这些容器都可以读写 emptyDir 卷中相同的文件。 当 Pod 因为某些原因被从节点上删除时,emptyDir 卷中的数据也会永久删除
emptyDir 的使用场景:
-
缓存空间,例如基于磁盘的归并排序。
-
耗时较长的计算任务提供检查点,以便任务能方便地从崩溃前状态恢复执行。
-
在 Web 服务器容器服务数据时,保存内容管理器容器获取的文件。
示例:
[root@k8s-master volumes]# vim pod1.yml
apiVersion: v1
kind: Pod
metadata:name: vol1
spec:containers:- image: busyboxplus:latestname: vm1command:- /bin/sh- -c- sleep 30000000volumeMounts:- mountPath: /cachename: cache-vol- image: nginx:latestname: vm2volumeMounts:- mountPath: /usr/share/nginx/htmlname: cache-volvolumes:- name: cache-volemptyDir:medium: MemorysizeLimit: 100Mi[root@k8s-master volumes]# kubectl apply -f pod1.yml
pod/vol1 created#查看pod中卷的使用情况
[root@k8s-master volumes]# kubectl describe pods vol1 #测试效果
[root@k8s-master volumes]# kubectl exec -it pods/vol1 -c vm1 -- /bin/sh
/ # cd cache/
/cache # ls
/cache # echo haha > index.html
/cache # curl localhost
haha
/cache #
/cache # dd if=/dev/zero of=bigfile bs=1M count=101
dd: writing 'bigfile': No space left on device
101+0 records in
99+1 records out
3.3 hostpath卷
功能:
hostPath 卷能将主机节点文件系统上的文件或目录挂载到您的 Pod 中,不会因为pod关闭而被删除
hostPath 的一些用法
-
运行一个需要访问 Docker 引擎内部机制的容器,挂载 /var/lib/docker 路径。
-
在容器中运行 cAdvisor(监控) 时,以 hostPath 方式挂载 /sys。
-
允许 Pod 指定给定的 hostPath 在运行 Pod 之前是否应该存在,是否应该创建以及应该以什么方式存在
hostPath的安全隐患
-
具有相同配置(例如从 podTemplate 创建)的多个 Pod 会由于节点上文件的不同而在不同节点上有不同的行为。
-
当 Kubernetes 按照计划添加资源感知的调度时,这类调度机制将无法考虑由 hostPath 使用的资源。
-
基础主机上创建的文件或目录只能由 root 用户写入。您需要在 特权容器 中以 root 身份运行进程,或者修改主机上的文件权限以便容器能够写入 hostPath 卷。
示例:
[root@k8s-master volumes]# vim pod2.yml
apiVersion: v1
kind: Pod
metadata:name: vol1
spec:containers:- image: nginx:latestname: vm1volumeMounts:- mountPath: /usr/share/nginx/htmlname: cache-volvolumes:- name: cache-volhostPath:path: /data type: DirectoryOrCreate #当/data目录不存在时自动建立#测试:
[root@k8s-master volumes]# kubectl apply -f pod2.yml
pod/vol1 created[root@k8s-master volumes]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
vol1 1/1 Running 0 24s 10.244.2.8 k8s-node2.exam.com <none> <none>[root@k8s-master volumes]# curl 10.244.2.8
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.27.1</center>
</body>
</html>#通过kubectl get pods -o wide查看挂载到了哪个主机 比如这里为node2
[root@k8s-node2 ~]# echo xixi > /data/index.html#回到master
[root@k8s-master volumes]# curl 10.244.2.8
xixi#当pod被删除后hostPath不会被清理
[root@k8s-master volumes]# kubectl delete -f pod2.yml
pod "vol1" deleted
[root@k8s-node2 ~]# ls /data/
index.html
3.4 nfs卷
NFS 卷允许将一个现有的 NFS 服务器上的目录挂载到 Kubernetes 中的 Pod 中。这对于在多个 Pod 之间共享数据或持久化存储数据非常有用
例如,如果有多个容器需要访问相同的数据集,或者需要将容器中的数据持久保存到外部存储,NFS 卷可以提供一种方便的解决方案。
3.4.1 部署一台nfs共享主机并在所有k8s节点中安装nfs-utils
#部署nfs主机
[root@harbor ~]# mkdir /nfsdata
[root@harbor ~]# dnf install nfs-utils -y
[root@harbor ~]# systemctl enable --now nfs-server.service [root@harbor ~]# vim /etc/exports
/nfsdata *(rw,sync,no_root_squash) #no_root_squash因为管理用户为root
[root@harbor ~]# ls -ld /nfsdata/
drwxr-xr-x 2 root root 6 Sep 9 05:58 /nfsdata/
[root@harbor ~]# exportfs -rv #重启
exporting *:/nfsdata[root@k8s-master ~]# showmount -e 172.25.250.250 #每台主机都要能看到
Export list for 172.25.250.250:
/nfsdata *#在k8s所有节点中安装nfs-utils
[root@k8s-master ~]# dnf install nfs-utils -y
[root@k8s-master ~]# systemctl enable --now nfs-server.service
[root@k8s-node1 ~]# dnf install nfs-utils -y
[root@k8s-node1 ~]# systemctl enable --now nfs-server.service
[root@k8s-node2 ~]# dnf install nfs-utils -y
[root@k8s-node2 ~]# systemctl enable --now nfs-server.service
3.4.2 部署nfs卷
[root@k8s-master volumes]# vim pod3.yml
apiVersion: v1
kind: Pod
metadata:name: vol1
spec:containers:- image: nginx:latestname: vm1 volumeMounts:- mountPath: /usr/share/nginx/htmlname: cache-volvolumes:- name: cache-volnfs:server: 172.25.250.250 #nfs服务器IPpath: /nfsdata #nfs服务器共享目录[root@k8s-master volumes]# kubectl apply -f pod3.yml
pod/vol1 created#测试
[root@k8s-master volumes]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
vol1 1/1 Running 0 50s 10.244.2.9 k8s-node2.exam.com <none> <none>[root@k8s-master volumes]# curl 10.244.2.9
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.27.1</center>
</body>
</html>#在nfs主机中
[root@harbor ~]# echo welcome back! > /nfsdata/index.html
[root@k8s-master volumes]# curl 10.244.2.9
welcome back!
3.5 PersistentVolume持久卷
3.5.1 静态持久卷pv与静态持久卷声明pvc
PersistentVolume(持久卷,简称PV)
-
pv是集群内由管理员提供的网络存储的一部分。
-
PV也是集群中的一种资源。是一种volume插件,
-
但是它的生命周期却是和使用它的Pod相互独立的。
-
PV这个API对象,捕获了诸如NFS、ISCSI、或其他云存储系统的实现细节
-
pv有两种提供方式:静态和动态
-
静态PV:集群管理员创建多个PV,它们携带着真实存储的详细信息,它们存在于Kubernetes API中,并可用于存储使用
-
动态PV:当管理员创建的静态PV都不匹配用户的PVC时,集群可能会尝试专门地供给volume给PVC。这种供给基于StorageClass
-
PersistentVolumeClaim(持久卷声明,简称PVC)
-
是用户的一种存储请求
-
它和Pod类似,Pod消耗Node资源,而PVC消耗PV资源
-
Pod能够请求特定的资源(如CPU和内存)。PVC能够请求指定的大小和访问的模式持久卷配置
-
PVC与PV的绑定是一对一的映射。没找到匹配的PV,那么PVC会无限期得处于unbound未绑定状态
volumes访问模式
-
ReadWriteOnce -- 该volume只能被单个节点以读写的方式映射
-
ReadOnlyMany -- 该volume可以被多个节点以只读方式映射
-
ReadWriteMany -- 该volume可以被多个节点以读写的方式映射
-
在命令行中,访问模式可以简写为:
-
RWO - ReadWriteOnce
-
-
ROX - ReadOnlyMany
-
RWX – ReadWriteMany
volumes回收策略
-
Retain:保留,需要手动回收
-
Recycle:回收,自动删除卷中数据(在当前版本中已经废弃)
-
Delete:删除,相关联的存储资产,如AWS EBS,GCE PD,Azure Disk,or OpenStack Cinder卷都会被删除
注意:只有NFS和HostPath支持回收利用
AWS EBS,GCE PD,Azure Disk,or OpenStack Cinder卷支持删除操作
volumes状态说明
-
Available 卷是一个空闲资源,尚未绑定到任何申领
-
Bound 该卷已经绑定到某申领
-
Released 所绑定的申领已被删除,但是关联存储资源尚未被集群回收
-
Failed 卷的自动回收操作失败
静态pv实例:
#在nfs主机中建立实验目录
[root@harbor ~]# mkdir /nfsdata/pv{1..3}#编写创建pv的yml文件,pv是集群资源,不在任何namespace中
[root@k8s-master pvc]# vim pv.yml
apiVersion: v1
kind: PersistentVolume
metadata:name: pv1
spec:capacity:storage: 1GivolumeMode: Filesystem #注意缩进accessModes:- ReadWriteOncepersistentVolumeReclaimPolicy: RetainstorageClassName: nfsnfs:path: /nfsdata/pv1server: 172.25.250.250---
apiVersion: v1
kind: PersistentVolume
metadata:name: pv2
spec:capacity:storage: 3GivolumeMode: FilesystemaccessModes:- ReadWriteManypersistentVolumeReclaimPolicy: RetainstorageClassName: nfsnfs:path: /nfsdata/pv2server: 172.25.250.250
---
apiVersion: v1
kind: PersistentVolume
metadata:name: pv3
spec:capacity:storage: 5GivolumeMode: FilesystemaccessModes:- ReadOnlyManypersistentVolumeReclaimPolicy: RetainstorageClassName: nfsnfs:path: /nfsdata/pv3server: 172.25.250.250[root@k8s-master pvc]# kubectl apply -f pv.yml
persistentvolume/pv1 unchanged
persistentvolume/pv2 unchanged
persistentvolume/pv3 created[root@k8s-master pvc]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE
pv1 1Gi RWO Retain Bound default/pvc1 nfs <unset> 3m26s
pv2 3Gi RWX Retain Available nfs <unset> 3m26s
pv3 5Gi ROX Retain Available nfs <unset> 3m8s#建立pvc,pvc是pv使用的申请,需要保证和pod在一个namesapce中
[root@k8s-master pvc]# vim pvc.ym
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: pvc1
spec:storageClassName: nfsaccessModes:- ReadWriteOnceresources:requests:storage: 1Gi---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: pvc2
spec:storageClassName: nfsaccessModes:- ReadWriteManyresources:requests:storage: 3Gi---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: pvc3
spec:storageClassName: nfsaccessModes:- ReadOnlyManyresources:requests:storage: 5Gi[root@k8s-master pvc]# kubectl apply -f pvc.ym
persistentvolumeclaim/pvc1 created
persistentvolumeclaim/pvc2 created
persistentvolumeclaim/pvc3 created[root@k8s-master pvc]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE
pv1 1Gi RWO Retain Bound default/pvc1 nfs <unset> 3m20s
pv2 3Gi RWX Retain Bound default/pvc2 nfs <unset> 3m20s
pv3 5Gi ROX Retain Bound default/pvc3 nfs <unset> 3m20s[root@k8s-master pvc]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
pvc1 Bound pv1 1Gi RWO nfs <unset> 18s
pvc2 Bound pv2 3Gi RWX nfs <unset> 18s
pvc3 Bound pv3 5Gi ROX nfs <unset> 18s
test-claim Pending nfs-client <unset> 2m35s
www-web-0 Pending nfs-client <unset> 3h29m#在其他namespace中无法应用
[root@k8s-master pvc]# kubectl -n kube-system get pvc
No resources found in kube-system namespace.
在pod中使用pvc
[root@k8s-master pvc]# vim pod.yml
apiVersion: v1
kind: Pod
metadata:name: howe
spec:containers:- image: nginxname: nginxvolumeMounts:- mountPath: /usr/share/nginx/htmlname: vol1volumes:- name: vol1persistentVolumeClaim:claimName: pvc1[root@k8s-master pvc]# kubectl apply -f pod.yml
pod/howe created[root@k8s-master pvc]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
howe 1/1 Running 0 46s 10.244.1.8 k8s-node1.exam.com <none> <none>[root@k8s-master pvc]# kubectl exec -it pods/howe -- /bin/bash
root@howe:~# cd /usr/share/nginx/html/
root@howe:/usr/share/nginx/html# ls#nfs主机写入共享目录
[root@harbor nfsdata]# echo hehehe > /nfsdata/pv1/index.htmlroot@howe:/usr/share/nginx/html# ls
index.html
root@howe:/usr/share/nginx/html# curl localhost
hehehe
四 存储类storageclass
官网: GitHub - kubernetes-sigs/nfs-subdir-external-provisioner: Dynamic sub-dir volume provisioner on a remote NFS server.
4.1 StorageClass说明
-
StorageClass提供了一种描述存储类(class)的方法,不同的class可能会映射到不同的服务质量等级和备份策略或其他策略等。
-
每个 StorageClass 都包含 provisioner、parameters 和 reclaimPolicy 字段, 这些字段会在StorageClass需要动态分配 PersistentVolume 时会使用到
4.2 StorageClass的属性
属性说明:存储类 | Kubernetes
Provisioner(存储分配器):用来决定使用哪个卷插件分配 PV,该字段必须指定。可以指定内部分配器,也可以指定外部分配器。外部分配器的代码地址为: kubernetes-incubator/external-storage,其中包括NFS和Ceph等。
Reclaim Policy(回收策略):通过reclaimPolicy字段指定创建的Persistent Volume的回收策略,回收策略包括:Delete 或者 Retain,没有指定默认为Delete。
4.3 存储分配器NFS Client Provisioner
源码地址:GitHub - kubernetes-sigs/nfs-subdir-external-provisioner: Dynamic sub-dir volume provisioner on a remote NFS server.
-
NFS Client Provisioner是一个automatic provisioner,使用NFS作为存储,自动创建PV和对应的PVC,本身不提供NFS存储,需要外部先有一套NFS存储服务。
-
PV以 ${namespace}-${pvcName}-${pvName}的命名格式提供(在NFS服务器上)
-
PV回收的时候以 archieved-${namespace}-${pvcName}-${pvName} 的命名格式(在NFS服务器上)
4.4 部署NFS Client Provisioner
#上传镜像仓库
[root@k8s-master ~]# docker load -i nfs-subdir-external-provisioner-4.0.2.tar
Loaded image: registry.k8s.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2[root@k8s-master ~]# docker tag registry.k8s.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2 reg.exam.com/sig-storage/nfs-subdir-external-provisioner:v4.0.2[root@k8s-master ~]# docker push reg.exam.com/sig-storage/nfs-subdir-external-provisioner:v4.0.2
The push refers to repository [reg.exam.com/sig-storage/nfs-subdir-external-provisioner]
ad321585b8f5: Pushed
1a5ede0c966b: Pushed
v4.0.2: digest: sha256:f741e403b3ca161e784163de3ebde9190905fdbf7dfaa463620ab8f16c0f6423 size: 739
4.4.1 创建sa并授权
[root@k8s-master nfs]# vim rbac.yml
apiVersion: v1
kind: Namespace
metadata:name: nfs-client-provisioner
---
apiVersion: v1
kind: ServiceAccount
metadata:name: nfs-client-provisionernamespace: 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"]verbs: ["get", "list", "watch", "create", "delete"]- apiGroups: [""]resources: ["persistentvolumeclaims"]verbs: ["get", "list", "watch", "update"]- apiGroups: ["storage.k8s.io"]resources: ["storageclasses"]verbs: ["get", "list", "watch"]- apiGroups: [""]resources: ["events"]verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:name: run-nfs-client-provisioner
subjects:- kind: ServiceAccountname: nfs-client-provisionernamespace: nfs-client-provisioner
roleRef:kind: ClusterRolename: nfs-client-provisioner-runnerapiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:name: leader-locking-nfs-client-provisionernamespace: nfs-client-provisioner
rules:- apiGroups: [""]resources: ["endpoints"]verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:name: leader-locking-nfs-client-provisionernamespace: nfs-client-provisioner
subjects:- kind: ServiceAccountname: nfs-client-provisionernamespace: nfs-client-provisioner
roleRef:kind: Rolename: leader-locking-nfs-client-provisionerapiGroup: rbac.authorization.k8s.io#查看rbac信息
[root@k8s-master nfs]# kubectl apply -f rbac.yml
namespace/nfs-client-provisioner created
serviceaccount/nfs-client-provisioner created
clusterrole.rbac.authorization.k8s.io/nfs-client-provisioner-runner created
clusterrolebinding.rbac.authorization.k8s.io/run-nfs-client-provisioner created
role.rbac.authorization.k8s.io/leader-locking-nfs-client-provisioner created
rolebinding.rbac.authorization.k8s.io/leader-locking-nfs-client-provisioner created[root@k8s-master nfs]# kubectl -n nfs-client-provisioner get sa
NAME SECRETS AGE
default 0 26s
nfs-client-provisioner 0 27s
4.4.2 部署应用
[root@k8s-master nfs]# vim deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:name: nfs-client-provisionerlabels:app: nfs-client-provisionernamespace: nfs-client-provisioner
spec:replicas: 1strategy:type: Recreateselector:matchLabels:app: nfs-client-provisionertemplate:metadata:labels:app: nfs-client-provisionerspec:serviceAccountName: nfs-client-provisionercontainers:- name: nfs-client-provisionerimage: sig-storage/nfs-subdir-external-provisioner:v4.0.2volumeMounts:- name: nfs-client-rootmountPath: /persistentvolumesenv:- name: PROVISIONER_NAMEvalue: k8s-sigs.io/nfs-subdir-external-provisioner- name: NFS_SERVERvalue: 172.25.250.250- name: NFS_PATHvalue: /nfsdatavolumes:- name: nfs-client-rootnfs:server: 172.25.250.250path: /nfsdata[root@k8s-master nfs]# kubectl apply -f deployment.yml
deployment.apps/nfs-client-provisioner created[root@k8s-master nfs]# kubectl -n nfs-client-provisioner get deployments.apps nfs-client-provisioner
NAME READY UP-TO-DATE AVAILABLE AGE
nfs-client-provisioner 1/1 1 1 4s
4.4.3 创建存储类
[root@k8s-master nfs]# vim class.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:name: nfs-client
provisioner: /nfs-subdir-external-provisioner
parameters:archiveOnDelete: "false"[root@k8s-master nfs]# kubectl apply -f class.yaml
storageclass.storage.k8s.io/nfs-client created[root@k8s-master nfs]# kubectl get storageclasses.storage.k8s.io
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
nfs-client k8s-sigs.io/nfs-subdir-external-provisioner Delete Immediate false 26s
4.4.4 创建pvc
[root@k8s-master nfs]# vim pvc.yml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:name: test-claim
spec:storageClassName: nfs-clientaccessModes:- ReadWriteManyresources:requests:storage: 1G[root@k8s-master nfs]# kubectl apply -f pvc.yml
persistentvolumeclaim/test-claim created#pending问题 可能由于没有pv资源
[root@k8s-master nfs]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
test-claim Pending nfs-client <unset> 10s#检查nfs插件是否上传到镜像仓库
[root@k8s-master nfs]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
test-claim Bound pvc-7f3fd08b-186e-42fa-9e0d-02ef7f0c9b36 1G RWX nfs-client <unset> 27s
4.4.5 创建测试pod
[root@k8s-master nfs]# vim pod.yml
apiVersion: v1
kind: Pod
metadata:name: test-pod
spec:containers:- name: test-podimage: busyboxcommand:- "/bin/sh"args:- "-c"- "touch /mnt/SUCCESS && exit 0 || exit 1"volumeMounts:- name: nfs-pvcmountPath: "/mnt"restartPolicy: "Never"volumes:- name: nfs-pvcpersistentVolumeClaim:claimName: test-claim[root@k8s-master nfs]# kubectl apply -f pod.yml
pod/test-pod created[root@k8s-master nfs]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
test-claim Bound pvc-7f3fd08b-186e-42fa-9e0d-02ef7f0c9b36 1G RWX nfs-client <unset> 27s#nfs主机上查看
[root@harbor ~]# ls /nfsdata/default-test-claim-pvc-7f3fd08b-186e-42fa-9e0d-02ef7f0c9b36/
SUCCESS[root@k8s-master nfs]# kubectl delete -f pod.yml
pod "test-pod" deleted
4.4.6 设置默认存储类
-
在未设定默认存储类时pvc必须指定使用类的名称
-
在设定存储类后创建pvc时可以不用指定storageClassName
#一次性指定多个pvc
[root@k8s-master pvc]# vim pvc.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: pvc1
spec:storageClassName: nfs-clientaccessModes:- ReadWriteOnceresources:requests:storage: 1Gi---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: pvc2
spec:storageClassName: nfs-clientaccessModes:- ReadWriteManyresources:requests:storage: 10Gi---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: pvc3
spec:storageClassName: nfs-clientaccessModes:- ReadOnlyManyresources:requests:storage: 15Gi[root@k8s-master pvc]# kubectl apply -f pvc.yml
persistentvolumeclaim/pvc1 created
persistentvolumeclaim/pvc2 created
persistentvolumeclaim/pvc3 created[root@k8s-master pvc]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
pvc1 Bound pvc-1d48c4c3-a6ef-487d-8d88-43297ca804a2 1Gi RWO nfs-client <unset> 12s
pvc2 Bound pvc-27223a35-32c4-4768-8267-ad1866230b0d 10Gi RWX nfs-client <unset> 12s
pvc3 Bound pvc-8ef40d48-991a-4b9d-afd8-3be6b4f45b89 15Gi ROX nfs-client <unset> 12s
设定默认存储类

[root@k8s-master nfs]# kubectl edit sc nfs-client #测试,未指定storageClassName参数
[root@k8s-master nfs]# vim pvc.yml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:name: test-claim
spec:storageClassName: nfs-clientaccessModes:- ReadWriteManyresources:requests:storage: 1Gi[root@k8s-master nfs]# kubectl apply -f pvc.yml
persistentvolumeclaim/test-claim created[root@k8s-master nfs]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
test-claim Bound pvc-7900365a-ca7a-4de9-bcc4-0984b4149f58 1Gi RWX nfs-client <unset> 15s
五 statefulset控制器
5.1 功能特性
-
Statefulset是为了管理有状态服务的问提设计的
-
StatefulSet将应用状态抽象成了两种情况:
-
拓扑状态:应用实例必须按照某种顺序启动。新创建的Pod必须和原来Pod的网络标识一样
-
存储状态:应用的多个实例分别绑定了不同存储数据。
-
StatefulSet给所有的Pod进行了编号,编号规则是:$(statefulset名称)-$(序号),从0开始。
-
Pod被删除后重建,重建Pod的网络标识也不会改变,Pod的拓扑状态按照Pod的“名字+编号”的方式固定下来,并且为每个Pod提供了一个固定且唯一的访问入口,Pod对应的DNS记录。
5.2 StatefulSet的组成部分
-
Headless Service:用来定义pod网络标识,生成可解析的DNS记录
-
volumeClaimTemplates:创建pvc,指定pvc名称大小,自动创建pvc且pvc由存储类供应。
-
StatefulSet:管理pod的
5.3 构建方法
#建立无头服务
[root@k8s-master statefulset]# vim headless.yml
apiVersion: v1
kind: Service
metadata:name: nginx-svclabels:app: nginx
spec:ports:- port: 80name: webclusterIP: Noneselector:app: nginx[root@k8s-master statefulset]# kubectl apply -f headless.yml
service/nginx-svc created#建立statefulset
[root@k8s-master statefulset]# vim statefulset.yml
apiVersion: apps/v1
kind: StatefulSet
metadata:name: web
spec:serviceName: "nginx-svc"replicas: 3selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:containers:- name: nginximage: nginxvolumeMounts:- name: wwwmountPath: /usr/share/nginx/htmlvolumeClaimTemplates:- metadata:name: wwwspec:storageClassName: nfs-clientaccessModes:- ReadWriteOnceresources:requests:storage: 1Gi[root@k8s-master statefulset]# kubectl apply -f statefulset.yml
statefulset.apps/web created[root@k8s-master statefulset]# kubectl get pods
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 6s
web-1 1/1 Running 0 4s
web-2 1/1 Running 0 2s[root@harbor ~]# ls /nfsdata/
default-www-web-0-pvc-a3ceae44-d7f2-4514-8591-02ab8e8bed4c
default-www-web-1-pvc-5f5756d6-5d16-4a69-89ce-beef5321ba41
default-www-web-2-pvc-31726893-6723-42ef-ab56-32a35e263fba
5.4 测试:
#在nfs主机为每个pod建立index.html文件
[root@harbor ~]# cd /nfsdata/
[root@harbor nfsdata]# echo web-0 > default-www-web-0-pvc-a3ceae44-d7f2-4514-8591-02ab8e8bed4c/index.html
[root@harbor nfsdata]# echo web-1 > default-www-web-1-pvc-5f5756d6-5d16-4a69-89ce-beef5321ba41/index.html
[root@harbor nfsdata]# echo web-2 > default-www-web-2-pvc-31726893-6723-42ef-ab56-32a35e263fba/index.html#在master建立测试pod访问web-0~2
[root@k8s-master statefulset]# kubectl run -it testpod --image busyboxplus
/ # curl web-0.nginx-svc
web-0
/ # curl web-1.nginx-svc
web-1
/ # curl web-2.nginx-svc
web-2
/ # #删掉重新建立statefulset
[root@k8s-master statefulset]# kubectl delete -f statefulset.yml
statefulset.apps "web" deleted
[root@k8s-master statefulset]# kubectl apply -f statefulset.yml
statefulset.apps/web created#访问依然不变
[root@k8s-master statefulset]# kubectl attach testpod -c testpod -i -t
If you don't see a command prompt, try pressing enter.
/ # curl web-0.nginx-svc
web-0
/ # curl web-1.nginx-svc
web-1
/ # curl web-2.nginx-svc
web-2
/ #
5.5 statefulset的弹缩
首先,想要弹缩的StatefulSet. 需先清楚是否能弹缩该应用
用命令改变副本数
$ kubectl scale statefulsets <stateful-set-name> --replicas=<new-replicas>
通过编辑配置改变副本数
$ kubectl edit statefulsets.apps <stateful-set-name>
statefulset有序回收
[root@k8s-master statefulset]# kubectl scale statefulset web --replicas 0
statefulset.apps/web scaled
[root@k8s-master statefulset]# kubectl delete -f statefulset.yml
statefulset.apps "web" deleted
[root@k8s-master statefulset]# kubectl delete pvc --all
persistentvolumeclaim "www-web-0" deleted
persistentvolumeclaim "www-web-1" deleted
persistentvolumeclaim "www-web-2" deleted[root@k8s-master statefulset]# kubectl scale statefulsets web --replicas=0[root@k8s-master statefulset]# kubectl delete -f statefulset.yaml[root@k8s-master statefulset]# kubectl delete pvc --all
相关文章:
k8s中的存储
目录 一 configmap 1.1 configmap的功能 1.2 configmap的使用场景 1.3 configmap创建方式 1.3.1 字面值创建 1.3.2 通过文件创建 1.3.3 通过目录创建 1.3.4 通过yaml文件创建 1.3.5 configmap的使用方式 1.3.5.1 使用configmap填充环境变量 1.3.5.2 通过数据卷使用c…...
【Linux进程控制】进程程序替换
目录 进程程序替换 替换函数 看现象 替换原理 多进程替换 exec*函数使用(部分),并且认识函数参数的含义 1.execl 2.execv 3.execvp 4.execvpe execlp 和execlpe 替换函数总结 进程程序替换 替换函数 有六种以exec开头的函数&am…...
02 ETH
以太坊与比特币有什么不同? 以太坊立足比特币创新之上,于 2015 年启动,两者之间有一些显著不同。 比特币就仅仅是比特币;以太坊包括以太币,以太币才是和比特币对等的存在。以太坊是可编程的,所以你可以在…...
web渗透—RCE
一:代码执行 相关函数 1、eval()函数 assert()函数 (1)原理:将用户提交或者传递的字符串当作php代码执行 (2)passby:单引号绕过:闭合注释;开启GPC的话就无法绕过(GPC就是将单引号转换为"反斜杠单引号"&a…...
HomeAssistant显示节假日
先看效果 步骤: 新建卡片时选择“Markdown 卡片”代码在文章最下方,当然你也可以自己修改 点击保存/完成 ### {% if now().hour > 6 and now().hour < 9 -%} 早上好, {%- elif now().hour > 9 and now().hour < 12 -%} 上午好…...
AI问答-HTTP:理解 Content-Disposition
本文背景 在下载arraybuffer文件时,想要获取文件名,这时引入本文内容Content-Disposition,我们在Content-Disposition获取到文件名就可以在下载后的文件以该文件名命名了。 一、简介 Content-Disposition是HTTP协议中的一个响应头字段&…...
kubernetes架构
kubernetes cluster由master和node组成,节点上运行着若干kubernetes服务Master节点: master是kubernetes cluster的大脑,运行着的Daemon服务包括kube-apiserver,kube-scheduler,kube-controller-manager,etcd和Pod网络…...
【隐私计算篇】中国剩余定理解释以及Paillier解密加速应用
1. 背景介绍 本篇主要关注中国剩余定理的原理以及在paillier同态加密系统中的应用。在很多工作中,都可以看到中国剩余定理的影子,特别是同态加密提升计算效率的优化工作中,将paillier与中国剩余定理进行结合,能够实现在加密状态下…...
保护您的隐私:隐藏 IP 地址的重要性
在当今的数字时代,我们的在线隐私和安全变得比以往任何时候都更加重要。浏览互联网时保护自己的一种方法是隐藏您的 IP 地址。 但是为什么要隐藏您的 IP 地址以及如何有效地做到这一点? 隐藏您的 IP 地址有助于保护您的在线匿名性。您的 IP 地址就像您的…...
nodejs 007:错误npm error Error: EPERM: operation not permitted, symlink
完整错误信息 npm error Error: EPERM: operation not permitted, symlink npm warn cleanup Failed to remove some directories [ npm warn cleanup [ npm warn cleanup C:\\Users\\kingchuxing\\Documents\\IPFS\\orbit-db-set-master\\node_modules\\ipfs-cli, npm…...
Rsync未授权访问漏洞复现及彻底修复
一、什么是 Rsync? Rsync 是一种广泛使用的文件传输工具,它允许系统管理员和用户通过局域网(LAN)或广域网(WAN)在计算机之间同步文件和目录。Rsync 支持通过本地或远程 shell 访问,也可以作为守…...
影刀RPA实战:网页爬虫之携程酒店数据
1.实战目标 大家对于携程并不陌生,我们出行定机票,住酒店,去旅游胜地游玩,都离不开这样一个综合性的网站为我们提供信息,同时,如果你也是做旅游的公司,那携程就是一个业界竞争对手,…...
【UCB CS61C】Lecture 5 - Floating Point
目录 引入浮点数(Floating Point)定点表示法(Fixed-Point Model)科学记数法(Scientific Notation)记数法间的转换 IEEE 754 二进制浮点数算术标准实现目标单精度浮点编码阶码字段(The Exponent …...
【Binlog实战】:基于Spring监听Binlog日志
【Binlog实战】:基于Spring监听Binlog日志 binlog的三种模式 MySQL 的二进制日志(binlog)有三种不同的格式,通常被称为 binlog 模式。这三种模式分别是 Statement 模式、Row 模式和Mixed 模式。 Statement 模式: 在 …...
鸿蒙OpenHarmony【轻量系统芯片移植】轻量系统STM32F407芯片移植案例
轻量系统STM32F407芯片移植案例 介绍基于STM32F407IGT6芯片在拓维信息[Niobe407]开发板上移植OpenHarmony LiteOS-M轻量系统,提供交通、工业领域开发板解决方案。移植架构采用Board与SoC分离方案,使用arm gcc工具链Newlib C库,实现了lwip、l…...
基于SpringBoot+定时任务实现地图上绘制车辆实时运动轨迹图
目录 1. 项目结构 2. Maven依赖配置 (pom.xml) 3. 实现后端服务 4. 配置文件 (application.properties) 5. 启动项目 6. 访问页面 实现基于北斗卫星的车辆定位和轨迹图的Maven工程(使用模拟数据),我们将使用以下技术: Spri…...
Rasa对话模型——做一个语言助手
1、Rasa模型 1.1 模型介绍 Rasa是一个用于构建对话 AI 的开源框架,主要用于开发聊天机器人和语音助手。Rasa 提供了自然语言理解(NLU)和对话管理(DM)功能,使开发者能够创建智能、交互式的对话系统。 1.2…...
golang学习笔记19——golang做服务发现与注册的深度剖析
推荐学习文档 golang应用级os框架,欢迎stargolang应用级os框架使用案例,欢迎star案例:基于golang开发的一款超有个性的旅游计划app经历golang实战大纲golang优秀开发常用开源库汇总想学习更多golang知识,这里有免费的golang学习笔…...
ROS和ROS2借助智能大模型的学习和研究方法
机器人相关知识的本身和价值-CSDN博客 知识本身在智能时代毫无价值,需要基于知识应用和创新才有价值。 学历报废并非来自扩招,而是智能模型的快速发展。-CSDN blink-领先的开发者技术社区 2024年中秋,智能模型实力已经如此,但还…...
弹性负载均衡ELB 详解和设置方法
一、弹性负载均衡ELB 详解 1. 定义与概念 弹性负载均衡(Elastic Load Balancing,简称ELB)是一种将访问流量自动分发到多台云服务器的流量分发控制服务。它通过在多个后端服务器之间均衡分配请求,提高应用程序的可用性、可扩展性…...
从零搭建PointRCNN:Linux环境配置与3D检测可视化实战
1. 环境准备:从零搭建Linux深度学习工作站 第一次在Linux系统上配置深度学习环境时,我盯着命令行界面手足无措的样子还历历在目。现在回想起来,其实只要掌握几个关键步骤,就能快速搭建好PointRCNN所需的运行环境。我们以配备NVIDI…...
GPU算力高效利用:Pixel Language Portal在单卡多实例部署中的资源隔离与负载均衡教程
GPU算力高效利用:Pixel Language Portal在单卡多实例部署中的资源隔离与负载均衡教程 1. 引言:为什么需要单卡多实例部署 在AI应用开发中,GPU资源往往是稀缺且昂贵的。Pixel Language Portal作为一款基于Tencent Hunyuan-MT-7B的高端翻译工…...
Qwen3-14B企业知识沉淀:会议录音转写+关键结论自动提炼
Qwen3-14B企业知识沉淀:会议录音转写关键结论自动提炼 1. 企业知识管理的痛点与解决方案 在日常工作中,会议是信息交流的重要场景,但会议录音的整理工作往往耗时费力。传统的人工转写方式存在几个明显问题: 效率低下࿱…...
VRCT终极指南:3步实现VRChat跨语言实时翻译,打破虚拟社交障碍
VRCT终极指南:3步实现VRChat跨语言实时翻译,打破虚拟社交障碍 【免费下载链接】VRCT VRCT(VRChat Chatbox Translator & Transcription) 项目地址: https://gitcode.com/gh_mirrors/vr/VRCT 您是否曾在VRChat的国际房间中,面对来自…...
深入torch.cuda.Event:解锁GPU代码性能瓶颈的精准计时器
1. 为什么你需要torch.cuda.Event? 在GPU编程的世界里,时间就是金钱。你可能遇到过这样的情况:明明优化了算法,但训练速度就是上不去;或者发现某个操作耗时异常,却找不到具体原因。这时候,传统的…...
Pi0一键部署教程:nohup后台运行+log实时监控+进程安全终止
Pi0一键部署教程:nohup后台运行log实时监控进程安全终止 本文介绍如何快速部署和运行Pi0机器人控制模型,重点讲解后台运行、日志监控和进程管理的实用技巧,让AI应用稳定运行在服务器环境中。 1. 项目简介:什么是Pi0? …...
深入浅出Livepatch:从kprobe到ftrace的Linux热补丁实现原理
深入浅出Livepatch:从kprobe到ftrace的Linux热补丁实现原理 当你的生产环境服务器正在处理每秒数万次请求时,突然发现一个关键内核漏洞需要立即修复,传统方式要求重启系统——这无异于在高速公路上急刹车。Livepatch技术应运而生,…...
Wan2.2-I2V-A14B私有部署镜像优势:零依赖冲突、开箱即用、免编译安装
Wan2.2-I2V-A14B私有部署镜像优势:零依赖冲突、开箱即用、免编译安装 1. 镜像核心价值与定位 Wan2.2-I2V-A14B私有部署镜像是专为文生视频场景打造的一站式解决方案。这个镜像最大的特点就是解决了AI模型部署中最让人头疼的环境配置问题,真正做到下载即…...
Tomato Novel Downloader:智能搜索功能的技术突破
Tomato Novel Downloader:智能搜索功能的技术突破 【免费下载链接】Tomato-Novel-Downloader 番茄小说下载器不精简版 项目地址: https://gitcode.com/gh_mirrors/to/Tomato-Novel-Downloader 在数字阅读工具领域,用户体验的每一个细节都可能决定…...
【卷积神经网络作业实现人脸的关键点定位功能】
下面是完成这道题目的代码:import os import cv2 import numpy as np import pandas as pd import torch import torch.nn as nn from torch.utils.data import Dataset,DataLoader from torchvision import transforms import matplotlib.pyplot as plt1. 数据集定…...
