五、Kubernetes中的存储

news2024/9/20 6:26:35

目录

一 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状态说明

3.5.2 静态pv实例:

3.5.3 在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 字面值创建

[root@k8s-master ~]# kubectl create cm test-config --from-literal  fname=luo --from-literal lname=test
configmap/test-config created
[root@k8s-master ~]# kubectl describe cm test-config 
Name:         test-config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
fname:
----
luo
lname:
----
test

BinaryData
====

Events:  <none>

1.3.2 通过文件创建

[root@k8s-master ~]# cat /etc/resolv.conf
# Generated by NetworkManager
search exam.com
nameserver 114.114.114.114
[root@k8s-master ~]# kubectl create cm test2-config --from-file /etc/resolv.conf
configmap/test2-config created

[root@k8s-master ~]# kubectl describe cm test2-config
Name:         test2-config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
resolv.conf:
----
# Generated by NetworkManager
search exam.com
nameserver 114.114.114.114


BinaryData
====

Events:  <none>

1.3.3 通过目录创建

[root@k8s-master ~]# mkdir testconfig
[root@k8s-master ~]# cp /etc/fstab /etc/rc.d/rc.local testconfig/
[root@k8s-master ~]# kubectl create cm test3-config --from-file testconfig/
configmap/test3-config created
[root@k8s-master ~]# kubectl describe cm test3-config
Name:         test3-config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
fstab:
----

#
# /etc/fstab
# Created by anaconda on Mon Jul 29 15:14:50 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=ba6539ab-774f-4b67-8f3c-5ac2a4573b45 /boot                   xfs     defaults        0 0
#/dev/mapper/rhel-swap   none                    swap    defaults        0 0

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/cdrom /rhel9/


BinaryData
====

Events:  <none>

1.3.4 通过yaml文件创建

[root@k8s-master ~]# vim db.yml
apiVersion: v1
kind: ConfigMap
metadata:
  name: db-conf
data:
  db_host: 172.25.254.100
  db_port: "3306"

[root@k8s-master ingress]# kubectl apply -f db.yml 
configmap/db-conf created
[root@k8s-master ingress]# kubectl describe cm db-conf
Name:         db-conf
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
db_host:
----
172.25.254.100
db_port:
----
3306

BinaryData
====

Events:  <none>
 describe cm test-config 
Name:         test-config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
db_port:
----
3306
db_host:
----
172.25.254.100

BinaryData
====

Events:  <none>

1.3.5 configmap的使用方式

  • 通过环境变量的方式直接传递给pod

  • 通过pod的 命令行运行方式

  • 作为volume的方式挂载到pod内

1.3.5.1 使用configmap填充环境变量
#讲cm中的内容映射为指定变量
[root@k8s-master ingress]# vim testpod1.yml 
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: testpod
  name: testpod
spec:
  containers:
  - image: luohailin/busyboxplus:latest
    name: testpod
    command:
    - /bin/sh
    - -c
    - env
    env:
    - name: key1
      valueFrom:
        configMapKeyRef:
          name: db-conf
          key: db_host
    - name: key2
      valueFrom:
        configMapKeyRef:
          name: db-conf
          key: db_port
  restartPolicy: Never


[root@k8s-master ingress]# kubectl get pods testpod 
NAME      READY   STATUS      RESTARTS   AGE
testpod   0/1     Completed   0          105s
[root@k8s-master ingress]# kubectl logs pods/testpod
MYAPPV1_PORT_80_TCP_ADDR=10.105.230.221
KUBERNETES_SERVICE_PORT=443
MYAPPV2_PORT_80_TCP_ADDR=10.101.114.214
KUBERNETES_PORT=tcp://10.96.0.1:443
MYAPPV1_PORT_80_TCP_PORT=80
MYAPPV1_PORT_80_TCP_PROTO=tcp
MYAPPV2_PORT_80_TCP_PORT=80
HOSTNAME=testpod
SHLVL=1
MYAPPV2_PORT_80_TCP_PROTO=tcp
HOME=/
MYAPPV1_PORT_80_TCP=tcp://10.105.230.221:80
MYAPPV2_PORT_80_TCP=tcp://10.101.114.214:80
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
key1=172.25.254.100
key2=3306
MYAPPV1_SERVICE_HOST=10.105.230.221
MYAPPV2_SERVICE_HOST=10.101.114.214
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT_HTTPS=443
PWD=/
KUBERNETES_SERVICE_HOST=10.96.0.1
MYAPPV1_PORT=tcp://10.105.230.221:80
MYAPPV1_SERVICE_PORT=80
MYAPPV2_PORT=tcp://10.101.114.214:80
MYAPPV2_SERVICE_PORT=80

#把cm中的值直接映射为变量

1.3.5.2 通过数据卷使用configmap
[root@k8s-master ingress]# vim testpod3.yml
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: testpod
  name: testpod
spec:
  containers:
  - image: luohailin/busyboxplus:latest
    name: testpod
    command:
    - /bin/sh
    - -c
    - cat /config/db_host
    volumeMounts:					#调用卷策略
    - name: config-volume			#卷名称
      mountPath: /config
  volumes:							#声明卷的配置
  - name: config-volume				#卷名称
    configMap:
      name: db-conf
  restartPolicy: Never

[root@k8s-master ingress]# kubectl apply -f testpod3.yml 
pod/testpod created

#查看日志
[root@k8s-master ingress]#  kubectl logs testpod
172.25.254.100

1.3.5.3 利用configMap填充pod的配置文件
#建立配置文件模板

[root@k8s-master ~]# kubectl edit cm nginx-conf
9       listen 80;

[root@k8s-master ingress]# kubectl delete pods nginx-b84cc489f-8m429 
pod "nginx-b84cc489f-8m429" deleted

[root@k8s-master ingress]# kubectl get pods -o wide
NAME                    READY   STATUS    RESTARTS   AGE   IP           NODE                 NOMINATED NODE   READINESS GATES
nginx-b84cc489f-dd5dd   1/1     Running   0          30s   10.244.7.5   k8s-node2.exam.com   <none>           <none>
[root@k8s-master ingress]# curl 10.244.7.5:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
1.3.5.4 通过热更新cm修改配置
[root@k8s-master ~]# kubectl edit cm nginx-conf
apiVersion: v1
data:
  nginx.conf: |
    server {
      listen 8080;						#端口改为8080
      server_name _;
      root /usr/share/nginx/html;
      index index.html;
    }
kind: ConfigMap
metadata:
  creationTimestamp: "2024-09-07T02:49:20Z"
  name: nginx-conf
  namespace: default
  resourceVersion: "153055"
  uid: 20bee584-2dab-4bd5-9bcb-78318404fa7a

#查看配置文件
[root@k8s-master ~]# kubectl exec pods/nginx-8487c65cfc-cz5hd -- cat /etc/nginx/conf.d/nginx.conf
server {
  listen 8080;
  server_name _;
  root /usr/share/nginx/html;
  index index.html;
}

配置文件修改后不会生效,需要删除pod后控制器会重建pod,这时就生效了

[root@k8s-master ~]# kubectl delete pods nginx-8487c65cfc-cz5hd
pod "nginx-8487c65cfc-cz5hd" deleted

[root@k8s-master ~]# curl  10.244.2.41: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 secrets]# echo -n test > username.txt
[root@k8s-master secrets]# echo -n redhat > password.txt
[root@k8s-master secrets]# kubectl create secret generic userlist --from-file username.txt --from-file password.txt
secret/userlist created
[root@k8s-master secrets]# kubectl get secrets userlist -o yaml
apiVersion: v1
data:
  password.txt: cmVkaGF0
  username.txt: dGVzdA==
kind: Secret
metadata:
  creationTimestamp: "2024-09-08T14:27:38Z"
  name: userlist
  namespace: default
  resourceVersion: "122185"
  uid: 83acad78-46c0-430f-b9c2-002911fb24ae
type: Opaque

2.2.2 编写yaml文件

[root@k8s-master secrets]# echo -n test | base64
dGVzdA==
[root@k8s-master secrets]# echo -n redhat | base64
cmVkaGF0
[root@k8s-master secrets]# kubectl create secret generic userlist --dry-run=client -o yaml > userlist.yml

[root@k8s-master secrets]# vim userlist.yml 
apiVersion: v1
kind: Secret
metadata:
  name: userlist
type: Opaque
data:
  username: dGVzdA==
  password: cmVkaGF0

[root@k8s-master secrets]# kubectl apply -f userlist.yml
Warning: resource secrets/userlist is missing the kubectl.kubernetes.io/last-applied-configuration annotation which is required by kubectl apply. kubectl apply should only be used on resources created declaratively by either kubectl create --save-config or kubectl apply. The missing annotation will be patched automatically.
secret/userlist configured
[root@k8s-master secrets]# kubectl describe secrets userlist
Name:         userlist
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
password:      6 bytes
password.txt:  6 bytes
username:      4 bytes
username.txt:  4 bytes

2.3 Secret的使用方法

2.3.1 将Secret挂载到Volume中

#向固定路径映射
[root@k8s-master secrets]# vim pod1.yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: nginx
  name: nginx
spec:
  containers:
  - image: luohailin/nginx
    name: nginx
    volumeMounts:
    - name: secrets
      mountPath: /secret
      readOnly: true

  volumes:
  - name: secrets
    secret:
      secretName: userlist

[root@k8s-master secrets]# kubectl apply -f pod1.yaml
pod/nginx created


[root@k8s-master secrets]# kubectl exec  pods/nginx -it -- /bin/bash
root@nginx:/# cat /secret/
cat: /secret/: Is a directory
root@nginx:/# cd /secret/
root@nginx:/secret# ls
password  password.txt	username  username.txt
root@nginx:/secret# cat password
redhatroot@nginx:/secret# cat username
testroot@nginx:/secret# 

2.3.2 向指定路径映射 secret 密钥

[root@k8s-master secrets]# vim pod2.yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: nginx1
  name: nginx1
spec:
  containers:
  - image: luohailin/nginx
    name: nginx1
    volumeMounts:
    - name: secrets
      mountPath: /secret
      readOnly: true

  volumes:
  - name: secrets
    secret:
      secretName: userlist
      items:
      - key: username
        path: my-users/username


[root@k8s-master secrets]# kubectl apply -f pod2.yaml
pod/nginx1 created
[root@k8s-master secrets]# 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
testroot@nginx1:/secret/my-users# 

2.3.3 将Secret设置为环境变量

[root@k8s-master secrets]# vim pod3.yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: busybox
  name: busybox
spec:
  containers:
  - image: luohailin/busybox
    name: busybox
    command:
    - /bin/sh
    - -c
    - env
    env:
    - name: USERNAME
      valueFrom:
        secretKeyRef:
          name: userlist
          key: username
    - name: PASS
      valueFrom:
        secretKeyRef:
          name: userlist
          key: password
  restartPolicy: Never

[root@k8s-master secrets]# kubectl apply -f pod3.yaml
pod/busybox created
[root@k8s-master secrets]# kubectl logs pods/busybox
KUBERNETES_SERVICE_PORT=443
KUBERNETES_PORT=tcp://10.96.0.1:443
HOSTNAME=busybox
SHLVL=1
HOME=/root
USERNAME=test
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
PASS=redhat
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 secrets]# docker login www.test.com
Authenticating with existing credentials...
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credential-stores

Login Succeeded

#上传镜像
[root@k8s-master secrets]# docker tag busyboxplus:latest www.test.com/test/busyboxplus:latest

[root@k8s-master secrets]# docker push www.test.com/test/busyboxplus:latest
The push refers to repository [www.test.com/test/busyboxplus]
5f70bf18a086: Layer already exists 
774600fa57ae: Layer already exists 
075a34aac01b: Layer already exists 
latest: digest: sha256:9d1c242c1fd588a1b8ec4461d33a9ba08071f0cc5bb2d50d4ca49e430014ab06 size: 1353


#建立用于docker认证的secret
[root@k8s-master secrets]# kubectl create secret docker-registry docker-auth --docker-server www.test.com --docker-username admin --docker-password redhat --docker-email admin@test.com
secret/docker-auth created
[root@k8s-master secrets]# vim pod3.yml
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: game2048
  name: game2048
spec:
  containers:
  - image: www.test.com/test/game2048:latest
    name: game2048
  imagePullSecrets:					#不设定docker认证时无法下载镜像
  - name: docker-auth
[root@k8s-master secrets]# kubectl get pods
NAME       READY   STATUS    RESTARTS   AGE
game2048   1/1     Running   0          4s

三 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: luohailin/busyboxplus:latest
    name: vm1
    command:
    - /bin/sh
    - -c
    - sleep 30000000
    volumeMounts:
    - mountPath: /cache
      name: cache-vol
  - image: luohailin/nginx:latest
    name: vm2
    volumeMounts:
    - mountPath: /usr/share/nginx/html
      name: cache-vol
  volumes:
  - name: cache-vol
    emptyDir:
      medium: Memory
      sizeLimit: 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 # curl localhost
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.27.1</center>
</body>
</html>
/cache # echo test!!!! > index.html
/cache # curl localhost
test!!!!
/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
/cache # exit
command terminated with exit code 1

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: luohailin/nginx:latest
    name: vm1
    volumeMounts:
    - mountPath: /usr/share/nginx/html
      name: cache-vol
  volumes:
  - name: cache-vol
    hostPath:
      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          10s   10.244.2.48   k8s-node2   <none>           <none>

[root@k8s-master volumes]# curl  10.244.2.48
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.27.1</center>
</body>
</html>

[root@k8s-node2 ~]# echo timinglee > /data/index.html
[root@k8s-master volumes]# curl  10.244.2.48
timinglee

#当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@reg ~]# dnf install nfs-utils -y
[root@reg ~]# systemctl enable --now nfs-server.service

[root@reg ~]# vim /etc/exports
/nfsdata   *(rw,sync,no_root_squash)

[root@reg ~]# exportfs -rv
exporting *:/nfsdata

[root@reg ~]# showmount  -e
Export list for reg.timinglee.org:
/nfsdata *

#在k8s所有节点中安装nfs-utils
[root@k8s-master & node1 & node2  ~]# dnf install nfs-utils -y

3.4.2 部署nfs卷

[root@k8s-master volumes]# vim pod3.yml
apiVersion: v1
kind: Pod
metadata:
  name: vol1
spec:
  containers:
  - image: luohailin/nginx:latest
    name: vm1
    volumeMounts:
    - mountPath: /usr/share/nginx/html
      name: cache-vol
  volumes:
  - name: cache-vol
    nfs:
      server: 172.25.254.200
      path: /nfsdata

[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          100s   10.244.2.50   k8s-node2.exam.com   <none>           <none>
[root@k8s-master volumes]# curl  10.244.2.50
<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@reg ~]# echo test > /nfsdata/index.html
[root@k8s-master volumes]# curl  10.244.2.50
test

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卷都会被删除

注意:

[!NOTE]

只有NFS和HostPath支持回收利用

AWS EBS,GCE PD,Azure Disk,or OpenStack Cinder卷支持删除操作。

volumes状态说明
  • Available 卷是一个空闲资源,尚未绑定到任何申领

  • Bound 该卷已经绑定到某申领

  • Released 所绑定的申领已被删除,但是关联存储资源尚未被集群回收

  • Failed 卷的自动回收操作失败

3.5.2 静态pv实例:

#编写创建pv的yml文件,pv是集群资源,不在任何namespace中
[root@k8s-master pv]# vim pv.yml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv1
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: nfs
  nfs:
    path: /nfsdata/pv1
    server: 172.25.254.200

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv2
spec:
  capacity:
    storage: 15Gi
  volumeMode: Filesystem
  accessModes:
  - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  storageClassName: nfs
  nfs:
    path: /nfsdata/pv2
    server: 172.25.254.200
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv3
spec:
  capacity:
    storage: 25Gi
  volumeMode: Filesystem
  accessModes:
  - ReadOnlyMany
  persistentVolumeReclaimPolicy: Retain
  storageClassName: nfs
  nfs:
    path: /nfsdata/pv3
    server: 172.25.254.200
    
[root@k8s-master pv]# kubectl apply -f pv.yml 
persistentvolume/pv1 created
persistentvolume/pv2 created
persistentvolume/pv3 created
[root@k8s-master pv]# kubectl get  pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   VOLUMEATTRIBUTESCLASS   REASON   AGE
pv1    5Gi        RWO            Retain           Available           nfs            <unset>                          10s
pv2    15Gi       RWX            Retain           Available           nfs            <unset>                          10s
pv3    25Gi       ROX            Retain           Available           nfs            <unset>                          10s

#建立pvc,pvc是pv使用的申请,需要保证和pod在一个namesapce中
[root@k8s-master pv]# vim pvc.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc1
spec:
  storageClassName: nfs
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

---
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

[root@k8s-master pv]# kubectl apply -f pvc.yml 
persistentvolumeclaim/pvc1 created
persistentvolumeclaim/pvc2 created
persistentvolumeclaim/pvc3 created
[root@k8s-master pv]# kubectl get pvc
NAME   STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
pvc1   Bound    pv1      5Gi        RWO            nfs            <unset>                 6s
pvc2   Bound    pv2      15Gi       RWX            nfs            <unset>                 6s
pvc3   Bound    pv3      25Gi       ROX            nfs            <unset>                 6s

#在其他namespace中无法应用
[root@k8s-master pv]# kubectl -n kube-system  get pvc
No resources found in kube-system namespace.

3.5.3 在pod中使用pvc

[root@k8s-master pvc]# vim pod.yml
apiVersion: v1
kind: Pod
metadata:
  name: test
spec:
  containers:
  - image: luohailin/nginx
    name: nginx
    volumeMounts:
    - mountPath: /usr/share/nginx/html
      name: vol1
  volumes:
  - name: vol1
    persistentVolumeClaim:
      claimName: pvc1

[root@k8s-master pvc]# kubectl get pods  -o wide
NAME        READY   STATUS    RESTARTS   AGE   IP            NODE               NOMINATED NODE   READINESS GATES
test        1/1     Running   0          83s   10.244.2.54   k8s-node2.exam.com   <none>           <none>
[root@k8s-master pvc]# kubectl exec -it pods/timinglee -- /bin/bash
root@timinglee:/# curl  localhost
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.27.1</center>
</body>
</html>
root@timinglee:/# cd /usr/share/nginx/
root@timinglee:/usr/share/nginx# ls
html
root@timinglee:/usr/share/nginx# cd html/
root@timinglee:/usr/share/nginx/html# ls

[root@reg ~]# echo test > /data/pv1/index.html

[root@k8s-master pvc]# kubectl exec -it pods/test -- /bin/bash
root@test:/# cd /usr/share/nginx/html/
root@test:/usr/share/nginx/html# ls
index.html

四 存储类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

4.4.1 创建sa并授权

[root@k8s-master storageclass]# vim rbac.yml
apiVersion: v1
kind: Namespace
metadata:
  name: nfs-client-provisioner
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-client-provisioner
  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"]
    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: ServiceAccount
    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"]
    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
    name: nfs-client-provisioner
    namespace: nfs-client-provisioner
roleRef:
  kind: Role
  name: leader-locking-nfs-client-provisioner
  apiGroup: rbac.authorization.k8s.io


#查看rbac信息
[root@k8s-master storageclass]# 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 storageclass]# kubectl -n nfs-client-provisioner get sa
NAME                     SECRETS   AGE
default                  0         6s
nfs-client-provisioner   0         6s

4.4.2 部署应用

[root@k8s-master storageclass]# kubectl apply -f deployment.yml
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: 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: 172.25.254.200
            - name: NFS_PATH
              value: /nfsdata
      volumes:
        - name: nfs-client-root
          nfs:
            server: 172.25.254.200
            path: /nfsdata

deployment.apps/nfs-client-provisioner created
[root@k8s-master storageclass]#  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           6s

4.4.3 创建存储类

[root@k8s-master storageclass]# vim class.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-client
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner
parameters:
  archiveOnDelete: "false"
  
[root@k8s-master storageclass]# kubectl apply -f class.yaml
storageclass.storage.k8s.io/nfs-client created
[root@k8s-master storageclass]# kubectl get storageclasses.storage.k8s.io
NAME         PROVISIONER                                   RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
nfs-client   k8s-sigs.io/nfs-subdir-external-provisioner   Delete          Immediate           false                  4s

4.4.4 创建pvc

[root@k8s-master storageclass]# vim pvc.yml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: test-claim
spec:
  storageClassName: nfs-client
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1G
      
[root@k8s-master storageclass]# kubectl apply -f pvc.yml
persistentvolumeclaim/test-claim created
[root@k8s-master storageclass]# kubectl get pvc
NAME         STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
test-claim   Bound    pvc-fc1b1403-1008-495b-a0d8-9e9476bf8957   1G         RWX            nfs-client     <unset>                 4s

4.4.5 创建测试pod

[root@k8s-master storageclass]# vim pod.yml
kind: Pod
apiVersion: v1
metadata:
  name: test-pod
spec:
  containers:
  - name: test-pod
    image: busybox
    command:
      - "/bin/sh"
    args:
      - "-c"
      - "touch /mnt/SUCCESS && exit 0 || exit 1"
    volumeMounts:
      - name: nfs-pvc
        mountPath: "/mnt"
  restartPolicy: "Never"
  volumes:
    - name: nfs-pvc
      persistentVolumeClaim:
        claimName: test-claim
        
[root@k8s-master storageclass]# kubectl apply -f pod.yml
pod/test-pod created
[root@k8s-master storageclass]# vim pod.yml 
[root@k8s-master storageclass]# kubectl get pods
NAME                    READY   STATUS      RESTARTS   AGE
nginx-b84cc489f-p74d5   1/1     Running     0          6m11s
test-pod                0/1     Completed   0          82s

4.4.6 设置默认存储类

  • 在未设定默认存储类时pvc必须指定使用类的名称

  • 在设定存储类后创建pvc时可以不用指定storageClassName

#一次性指定多个pvc
[root@k8s-master storageclass]# vim pvc.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc1
spec:
  storageClassName: nfs-client
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc2
spec:
  storageClassName: nfs-client
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Gi

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc3
spec:
  storageClassName: nfs-client
  accessModes:
    - ReadOnlyMany
  resources:
    requests:
      storage: 15Gi


[root@k8s-master storageclass]# kubectl apply -f pvc.yml
persistentvolumeclaim/pvc1 created
persistentvolumeclaim/pvc2 created
persistentvolumeclaim/pvc3 created
[root@k8s-master storageclass]# kubectl get pvc
NAME         STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
pvc1         Bound    pvc-2d651822-2b2e-42d4-a16d-342fb409efff   1Gi        RWO            nfs-client     <unset>                 3s
pvc2         Bound    pvc-88c5bd04-8812-4fda-ab5a-a203a264734f   10Gi       RWX            nfs-client     <unset>                 3s
pvc3         Bound    pvc-f02e11ad-87f0-4b9b-896c-d388a924379d   15Gi       ROX            nfs-client     <unset>                 3s
test-claim   Bound    pvc-fc1b1403-1008-495b-a0d8-9e9476bf8957   1G         RWX            nfs-client     <unset>                 20m


设定默认存储类

[root@k8s-master storageclass]# kubectl edit sc nfs-client
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"storage.k8s.io/v1","kind":"StorageClass","metadata":{"annotations":{},"name":"nfs-client"},"parameters":{"archiveOnDelete":"false"},"provisioner":"k8s-sigs.io/nfs-subdir-external-provisioner"}
    storageclass.kubernetes.io/is-default-class: "true"		#设定默认存储类
  creationTimestamp: "2024-09-07T13:49:10Z"
  name: nfs-client
  resourceVersion: "218198"
  uid: 9eb1e144-3051-4f16-bdec-30c472358028
parameters:
  archiveOnDelete: "false"
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner
reclaimPolicy: Delete
volumeBindingMode: Immediate

#测试,未指定storageClassName参数
[root@k8s-master storageclass]# vim pvc.yml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: test-claim
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Gi

[root@k8s-master storageclass]# kubectl apply -f pvc.yml
persistentvolumeclaim/test-claim created
[root@k8s-master storageclass]# kubectl get pvc
NAME         STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
test-claim   Bound    pvc-b96c6983-5a4f-440d-99ec-45c99637f9b5   1Gi        RWX            nfs-client     <unset>                 7s

五 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
[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: 3
 selector:
  matchLabels:
   app: nginx
 template:
  metadata:
   labels:
    app: nginx
  spec:
   containers:
   - name: nginx
     image: nginx
     volumeMounts:
       - name: www
         mountPath: /usr/share/nginx/html
 volumeClaimTemplates:
  - metadata:
     name: www
    spec:
     storageClassName: nfs-client
     accessModes:
     - ReadWriteOnce
     resources:
      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
nginx-b84cc489f-p74d5   1/1     Running     0          24m
test-pod                0/1     Completed   0          20m
web-0                   1/1     Running     0          8s
web-1                   1/1     Running     0          6s
web-2                   1/1     Running     0          3s



[root@docker-hub ~]# ls /nfsdata/
default-test-claim-pvc-fc1b1403-1008-495b-a0d8-9e9476bf8957
default-www-web-0-pvc-2b5573b4-3855-401b-90b1-a71a53733079
default-www-web-1-pvc-44776dd1-1d58-41e4-86ea-15b699fcc0d2
default-www-web-2-pvc-958e484e-68fa-47da-9808-8721a1f9dcac

5.4 测试:

#为每个pod建立index.html文件
[root@docker-hub nfsdata]# echo web-0 > default-www-web-0-pvc-2b5573b4-3855-401b-90b1-a71a53733079/index.html
[root@docker-hub nfsdata]# echo web-1 > default-www-web-1-pvc-44776dd1-1d58-41e4-86ea-15b699fcc0d2/index.html
[root@docker-hub nfsdata]# echo web-2 > default-www-web-2-pvc-958e484e-68fa-47da-9808-8721a1f9dcac/index.html

#建立测试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.
/ # cu
curl  cut
/ # 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 "test-claim" deleted
persistentvolumeclaim "www-web-0" deleted
persistentvolumeclaim "www-web-1" deleted
persistentvolumeclaim "www-web-2" deleted
persistentvolumeclaim "www-web-3" deleted
persistentvolumeclaim "www-web-4" deleted
persistentvolumeclaim "www-web-5" deleted
[root@k8s2 statefulset]# kubectl scale statefulsets web --replicas=0

[root@k8s2 statefulset]# kubectl delete -f statefulset.yaml

[root@k8s2 mysql]# kubectl delete pvc --all

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2140566.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深度学习自编码器 - 引言篇

序言 在深度学习的浩瀚星空中&#xff0c;自编码器&#xff08; Autoencoder \text{Autoencoder} Autoencoder&#xff09;以其独特的魅力闪耀着光芒。作为一种无监督学习技术&#xff0c;自编码器通过构建输入数据的压缩表示&#xff08;编码&#xff09;及其重构&#xff08…

鸿蒙开发之ArkTS 基础八 联合类型

联合类型 是一个变量可以存储不同的数据类型 形式灵活 使用场景&#xff0c;比如&#xff0c;考试&#xff0c;结果有两种形式&#xff0c;一种是给出具体的多少分&#xff0c;一种是是给出A、B、C、D、这种等级&#xff0c;在之前的变量中&#xff0c;只能存储要么分数&#…

Docker简介在Centos和Ubuntu环境下安装Docker

文章目录 1.Docker简介2.Docker镜像与容器3.安装Docker3.1 Centos环境3.2 Ubuntu环境 1.Docker简介 Docker 是一个开源的应用容器引擎&#xff0c;它允许开发者将应用程序及其依赖项打包到一个可移植的容器中&#xff0c;然后发布到任何流行的 Linux 或 Windows 操作系统上。D…

强制类型转换有哪几种?

目录 1.static_cast 2.dynamic_cast 3.const_cast 4.reinterpret_cast 每种类型转换操作符都有其特定的应用场景和限制&#xff0c;应根据实际需求选择合适的转换方式。特别是 reinterpret_cast&#xff0c;由于它的类型安全性很低&#xff0c;使用时需格外小心。 1.static…

芜湖小孩自闭症寄宿制学校:释放潜能,开启未来

在探索儿童成长的无限可能中&#xff0c;有一群特别的孩子&#xff0c;他们以自己的节奏和方式感知着这个世界&#xff0c;那就是自闭症儿童。自闭症&#xff0c;一个逐渐为社会所熟知的领域&#xff0c;其背后承载着无数家庭的期望与挑战。在广州这座充满温情与活力的城市中&a…

成立LDAR检测公司的条件和投资额度(扩项)-泄漏检测与修复CMA认证

一、成立检验检测机构 1&#xff09;独立法人&#xff1a;营业执照&#xff08;经营范围包括检验检测机构服务的相关内容&#xff0c;不得有影响其检验检测活动公正性的经营项目&#xff0c;如&#xff1a;生产&#xff0c;销售等&#xff09; 2&#xff09;内设机构&#…

比传统机器学习更先进的深度学习神经网络的二分类建模全流程教程

比传统机器学习更先进的深度学习神经网络的二分类建模全流程分析教程 深度学习介绍和与传统机器学习的区别 深度学习&#xff08;Deep Learning&#xff09;是一种机器学习的分支&#xff0c;基于多层神经网络模型&#xff0c;能够自动从大量数据中学习特征并进行预测。深度学…

MES生产执行管理

技术架构&#xff1a; 基于RuoYi前后端分离版本开发 有需要该项目的小伙伴可以添加我Q&#xff1a;598748873&#xff0c;备注&#xff1a;CSDN 功能描述&#xff1a; 系统管理、主数据、物料产品管理、工作站设置、生产管理、生产排产、质量管理、生产排班、节假日/工作日…

自动驾驶自动泊车场景应用总结

自动泊车技术是当前智能驾驶技术的一个重要分支,其目标是通过车辆自身的感知、决策和控制系统,实现车辆在有限空间内的自主泊车操作。目前自动泊车可分为半自动泊车、全自动泊车、记忆泊车、自主代客泊车四种产品形态,其中, 根据搭载传感器和使用场景的不同,全自动泊车又可…

Redis Universe: 探索无边界的数据处理星系

目录 引言 一、NoSQL的崛起 - 数据处理的新纪元 1.1 关系型数据库与NoSQL数据库概述 1.2 NoSQL数据库的兴起 1.3 RDBMS与NoSQL的比较 二、Redis星系导论 2.1 Redis的定义与历史 2.2 Redis的特性 2.3 Redis的应用场景 2.4 Redis缓存实现流程 三、构建你的第一座数据库…

yolo-word复现

github下载代码&#xff1a;https://github.com/AILab-CVC/YOLO-World 配置环境&#xff1a; 官方的方式 当然也可以按照官方给的配置方式去安装库&#xff0c;我也试了&#xff0c;出现小问题了。 我这边是从我本身的yolov8的环境克隆过来的&#xff0c;然后安装我环境里没有…

java坏境搭建

目录 安装 步骤1 步骤2 步骤3 步骤4 环境变量 1、在桌面“计算机”或“此电脑”图标上右键&#xff0c;选择“属性”&#xff0c;进入控制面板的计算机系统页面后&#xff0c;点击“高级系统设置”&#xff0c;不同操作系统可能界面不同&#xff1a; 2、点击“环境变量”…

C++基础知识7 list

list 1. list的介绍及使用1.1 list的介绍1.2 list的使用1.2.1 list的构造1.2.2 list iterator的使用1.2.3 list capacity1.2.4 list element access1.2.5 list modifiers1.2.6 list的迭代器失效 2.1 模拟实现list 1. list的介绍及使用 1.1 list的介绍 1.2 list的使用 1.2.1 l…

三步设置NAS的内网穿透

现在的NAS很多&#xff0c;NAS中可以提供的dock服务也很多&#xff0c;博主也试了一下&#xff0c;可以把家里的服务提供到公网上&#xff1a; 1、博主有一个“终身免费的花生壳域名”&#xff1a; 2、博主家有一个华为的AX3 PRO路由器&#xff0c;在路由器中设置花生壳域名的…

DBA运维小技巧之存储篇-Oracle服务器根目录满了怎么处理(2)迁移至新存储空间

1 前情提要 话说上次DBA小倩通过删除home lv&#xff0c;把空间扩给了/分区&#xff0c;问题暂时得到了解决。 没过几天&#xff0c;领导找到小倩下达任务&#xff0c;客户说数据库在本地磁盘空间太小了又快要满了&#xff0c;由于之前用的服务器本地磁盘&#xff0c;性能也比…

如何利用Samba跨平台分享Ubuntu文件夹

1.安装Samba 终端输入sudo apt install samba 2.配置Samba 终端输入sudo vim /etc/samba/smb.conf 打开配置文件 滑动文件到最底下 输入以下内容 [Share] # 要共享的文件夹路径 path /home/xxx/sambashare read only no browsable yes编辑完成后按一下Esc按键后输入:wq回…

CRE6255MS (5V2.1A电源芯片方案)

CRE6255MS产品是一款内置高压 MOS 功率开关管12W原边控制的开关电源芯片。CRE6255MS较少的外围元器件、较低的系统成本设计出高性能的交直流转换开关电源。CRE6255MS 提供了极为全面和性能优异的智能化保护功能&#xff0c;包括逐周期过流保护、软启动、芯片过温保护、输出过压…

用SpringBoot进行通义千问接口调用同步方法和异步流式多轮回复方法

同步效果就不展示了,这里展示更常用的异步,多轮异步流式效果展示如下: 第一轮回答,此时没有会话id,需要雪花算法生成插入数据库 第二轮问题以及结果内容组合 1、同步版本环境准备以及代码 需要开通阿里大模型服务,如果没有开通服务,单独的去生成 key 是无效的。 阿里…

春秋云境之CVE-2022-30887

一.靶场环境 1.下载靶场环境 根据题目提示&#xff0c;此靶场存在文件上传漏洞。 2.启动靶场环境 我们可以看到是一个登录页面&#xff0c;我们尝试进行登录 二.登录页面 1.尝试进行登录 我们发现用户名必须是邮箱&#xff0c;那么弱口令肯定不行&#xff0c;我们可以看到…

Redis的缓存穿透、缓存雪崩、缓存击穿怎么解决

Redis在实际使用中是会遇到很多问题的&#xff0c;例如今天说到的缓存穿透、缓存雪崩、缓存击穿。 缓存穿透&#xff1a; 缓存穿透是指客户端请求的数据在redis缓存和数据中都不存在&#xff0c;这样缓存永远都不会生效&#xff0c;这些请求都会打到数据库当中&#xff0c;对…