k8s的存储

这样生成的pod名字不固定,IP不固定

此时是访问一个无状态的服务,那没什么影响,访问到访问不到都没啥影响

但是如果有一个有状态的服务,他要指定master,那此时的pod做不了负载均衡

statefulset控制器

  • kind: StatefulSet:StatefulSet 是用于管理有状态应用的控制器(与 Deployment 用于无状态应用不同)
  • serviceName: web:指定关联的 Headless Service 名称,这是 StatefulSet 的核心配置(用于为 Pod 提供稳定的网络标识)
  • StatefulSet 管理的 Pod 会有固定的名称(如 web-0web-1)和稳定的 DNS 记录,适合需要持久化存储、固定网络标识的应用(如数据库)

无头服务

创建一个 Headless Service(无头服务),为 StatefulSet 的 Pod 提供网络访问能力。

  • clusterIP: None:Headless Service 不分配集群 IP,而是通过 DNS 直接解析到后端 Pod 的 IP。
  • 与 StatefulSet 配合时,会为每个 Pod 生成固定的 DNS 记录(格式:{pod-name}.{service-name}.{namespace}.svc.cluster.local),例如 web-0.web.default.svc.cluster.local


configmap

configmap的功能

  • configMap用于保存配置数据,以键值对形式存储。

  • configMap 资源提供了向 Pod 注入配置数据的方法。

  • 镜像和配置文件解耦,以便实现镜像的可移植性和可复用性。

  • etcd限制了文件大小不能超过1M

configmap的使用场景

  • 填充环境变量的值

  • 设置容器内的命令行参数

  • 填充卷的配置文件

configmap创建方式

字面值创建

授权证书会被多个文件里认证,这个认证是绝对不能删除的

通过文件创建

把这个文件的内容换了一种方式来储存,并且保存到了集群中


通过yaml文件创建

指定文件,并加上文件内容

举例:

创建第一个 ConfigMap(test

  • 通过 vim test.yml 编写了一个 YAML 文件,定义了名为 test 的 ConfigMap

  • 查看详情 kubectl describe cm test 发现:

    • 该 ConfigMap 包含一个键 nginxconf,对应的值是一段 Nginx 配置(server { ... }

    • 这是将配置文件内容存储到了 ConfigMap 中

修改 YAML 并创建第二个 ConfigMap(userlist

  • 该 ConfigMap 包含两个键值对:username=lee 和 password=lee123

  • 这是将简单键值对存储到了 ConfigMap 中

(1)ConfigMap 是 “配置的容器”

  • 它本质是键值对的集合

    • 像 userlist 这样的简单键值对(适合存储用户名、密码等参数)

    • 像 test 这样的配置文件内容(适合存储 Nginx、MySQL 等服务的配置文件)

(2)配置与代码解耦

  • 通过将配置放入 ConfigMap,避免了将配置硬编码到容器镜像中。例如:

    • Nginx 配置(nginxconf)无需打包到镜像,而是通过 ConfigMap 动态提供

    • 用户名密码(username/password)可以独立管理,无需重新构建镜像

(3)通过 YAML 声明式管理

  • 使用 kubectl apply -f <yaml文件> 是 Kubernetes 的声明式管理方式:

    • YAML 文件定义了 “期望的状态”(如 ConfigMap 应该包含哪些键值对)

    • Kubernetes 会自动将实际状态调整为期望状态(创建或更新资源)

(4)配置的可复用性

  • 这两个 ConfigMap 可以被多个 Pod 引用:

    • test 中的 Nginx 配置可以被所有需要该配置的 Nginx 容器复用

    • userlist 中的账号信息可以被多个应用共享(如前端、后端同时读取)


使用configmap填充环境变量

#cm中的内容映射为指定变量

通过env字段手动指定需要映射的 CM 中的 key,并自定义环境变量名(如key1对应db_host

apiVersion: v1  # Kubernetes API版本(Pod属于v1核心API)
kind: Pod       # 资源类型为Pod
metadata:
  labels:
    run: testpod  # 给Pod打标签(用于筛选或关联其他资源)
  name: testpod   # Pod的名称(必须唯一)
spec:
  containers:
  - image: busyboxplus:latest  # 容器使用的镜像(轻量Linux工具集)
    name: testpod              # 容器名称(在Pod内唯一)
    command:                   # 容器启动命令(替代镜像默认命令)
    - /bin/sh
    - -c
    - env                      # 启动后执行`env`命令(打印所有环境变量)
    env:                       # 定义环境变量(重点)
    - name: key1               # 自定义环境变量名:key1
      valueFrom:
        configMapKeyRef:       # 从ConfigMap中取值
          name: lee4-config    # 引用的ConfigMap名称
          key: db_host         # 引用ConfigMap中的db_host键
    - name: key2               # 自定义环境变量名:key2
      valueFrom:
        configMapKeyRef:
          name: lee4-config
          key: db_port         # 引用ConfigMap中的db_port键
  restartPolicy: Never  # Pod终止后不重启(测试场景常用)

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

[root@k8s-master ~]# kubectl logs pods/testpod:查看容器日志(因为启动命令是env,会打印所有环境变量)

KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT=443
MYAPP_V1_SERVICE_HOST=10.104.84.65
HOSTNAME=testpod
SHLVL=1
MYAPP_V2_SERVICE_HOST=10.105.246.219
HOME=/
MYAPP_V1_PORT=tcp://10.104.84.65:80
MYAPP_V1_SERVICE_PORT=80
MYAPP_V2_SERVICE_PORT=80
MYAPP_V2_PORT=tcp://10.105.246.219:80
MYAPP_V1_PORT_80_TCP_ADDR=10.104.84.65
MYAPP_V2_PORT_80_TCP_ADDR=10.105.246.219
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
MYAPP_V1_PORT_80_TCP_PORT=80
MYAPP_V2_PORT_80_TCP_PORT=80
MYAPP_V1_PORT_80_TCP_PROTO=tcp
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.254.100
key2=3306

MYAPP_V1_PORT_80_TCP=tcp://10.104.84.65:80
MYAPP_V2_PORT_80_TCP=tcp://10.105.246.219:80
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT_HTTPS=443
PWD=/
KUBERNETES_SERVICE_HOST=10.96.0.1

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

通过envFrom字段批量导入整个 ConfigMap 的所有键值对,环境变量名与 CM 中的 key 完全一致,适合需要使用 CM 中大部分或全部配置的场景

[root@k8s-master ~]# vim testpod2.yml
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: testpod
  name: testpod
spec:
  containers:
  - image: busyboxplus:latest
    name: testpod
    command:
    - /bin/sh
    - -c
    - env
    envFrom:  # 重点:批量导入ConfigMap中的所有键值对
    - configMapRef:
        name: lee4-config  # 引用的ConfigMap名称
  restartPolicy: Never

#查看日志
[root@k8s-master ~]# kubectl logs pods/testpod
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT=443
MYAPP_V1_SERVICE_HOST=10.104.84.65
HOSTNAME=testpod
SHLVL=1
MYAPP_V2_SERVICE_HOST=10.105.246.219
HOME=/
db_port=3306
MYAPP_V1_SERVICE_PORT=80
MYAPP_V1_PORT=tcp://10.104.84.65:80
MYAPP_V2_SERVICE_PORT=80
MYAPP_V2_PORT=tcp://10.105.246.219:80
MYAPP_V1_PORT_80_TCP_ADDR=10.104.84.65
MYAPP_V2_PORT_80_TCP_ADDR=10.105.246.219
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
MYAPP_V1_PORT_80_TCP_PORT=80
age=18
MYAPP_V2_PORT_80_TCP_PORT=80
MYAPP_V1_PORT_80_TCP_PROTO=tcp
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
KUBERNETES_PORT_443_TCP_PORT=443
MYAPP_V2_PORT_80_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_PROTO=tcp
MYAPP_V1_PORT_80_TCP=tcp://10.104.84.65:80
MYAPP_V2_PORT_80_TCP=tcp://10.105.246.219:80
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
name=lee
PWD=/
KUBERNETES_SERVICE_HOST=10.96.0.1
db_host=172.25.254.100

#在pod命令行中使用变量

apiVersion: v1
kind: Pod
metadata:
  labels:
    run: testpod
  name: testpod
spec:
  containers:
  - image: busyboxplus:latest
    name: testpod
    command:
    - /bin/sh
    - -c
    - echo ${db_host} ${db_port}  # 重点:在命令中引用环境变量(需用${变量名})
    envFrom:
    - configMapRef:
        name: lee4-config
  restartPolicy: Never

#查看日志
[root@k8s-master ~]# kubectl logs pods/testpod
172.25.254.100 3306        

在集群中直接暴漏端口很危险,我们可以利用微服务来暴露端口更加安全

测试:

实际上是没有50IP的


通过数据卷使用configmap

此时有两个键,1和2,值为timinglee

之前的实验键都只是信息,现在想把它们变成文件

建立一个卷,并且对他们进行一个说明

把键值的方式映射成文件的形式

这个名字要是真实存在的

通过配置把信息注入给pod


通过热更新cm修改配置

把配置文件修改后

[root@k8s-master ~]# kubectl edit cm nginx-conf

apiVersion: v1  # ConfigMap属于v1核心API
data:           # 存储配置数据的核心字段
  nginx.conf: |  # 定义了一个名为nginx.conf的键,值是Nginx配置内容
    server {
      listen 8080;                # Nginx监听8080端口(这里特意修改为8080)
      server_name _;              # 匹配所有未指定的域名
      root /usr/share/nginx/html; # 网站根目录
      index index.html;           # 默认首页文件
    }
kind: ConfigMap  # 资源类型为ConfigMap
metadata:        # 元数据(名称、创建时间等,自动生成无需手动修改)
  ...

通过编辑 ConfigMap,我们更新了 Nginx 的配置(比如这里将监听端口改为 8080),而无需修改 Nginx 镜像本身,实现了 “配置与镜像分离”

#查看配置文件
[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;
}

  • kubectl exec:在运行的 Pod 容器中执行命令。
  • pods/nginx-8487c65cfc-cz5hd:指定要操作的 Pod 名称(这里是一个 Nginx Deployment 创建的 Pod)。
  • -- cat /etc/nginx/conf.d/nginx.conf:在容器内执行cat命令,查看/etc/nginx/conf.d/nginx.conf文件的内容

执行结果显示:容器内的 Nginx 配置文件内容,与我们在 ConfigMap 中定义的nginx.conf完全一致(包括listen 8080

验证 ConfigMap 中的配置是否成功挂载到了容器内的指定路径,确保 Nginx 使用的是我们通过 ConfigMap 管理的配置


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的认证信息

-n也是字符

怎么对这两个文件来创建secret

被转码

反码

要先转码,才能放到配置文件里


以变量的方式注入

name指的是这个文件里的键值

如果


以文件的方式

以卷的方式来做

卷的名字,所使用的资源的名字

真正的键值挂载到那个目录下mountPath

读取认证文件,加密文件如何注入pod呢,就是以文件的形式

存储docker registry的认证信息

写入之后默认使用集群的屏障

没有指定为什么可以下载镜像,因为在指定时,指定了建立软件仓库时的用户和密码,所以可以直接下载到


volumes配置管理

  • 容器中文件在磁盘上是临时存放的,这给容器中运行的特殊应用程序带来一些问题

  • 当容器崩溃时,kubelet将重新启动容器,容器中的文件将会丢失,因为容器会以干净的状态重建。

  • 当在一个 Pod 中同时运行多个容器时,常常需要在这些容器之间共享文件。

  • Kubernetes 卷具有明确的生命周期与使用它的 Pod 相同

  • 卷比 Pod 中运行的任何容器的存活期都长,在容器重新启动时数据也会得到保留

  • 当一个 Pod 不再存在时,卷也将不再存在。

  • Kubernetes 可以支持许多类型的卷,Pod 也能同时使用任意数量的卷。

  • 卷不能挂载到其他卷,也不能与其他卷有硬链接。 Pod 中的每个容器必须独立地指定每个卷的挂载位置。

删除了容器数据没有消失,因为没有成功挂载在目录上


emptyDir卷

功能:

当Pod指定到某个节点上时,首先创建的是一个emptyDir卷,并且只要 Pod 在该节点上运行,卷就一直存在。卷最初是空的。 尽管 Pod 中的容器挂载 emptyDir 卷的路径可能相同也可能不同,但是这些容器都可以读写 emptyDir 卷中相同的文件。 当 Pod 因为某些原因被从节点上删除时,emptyDir 卷中的数据也会永久删除

emptyDir 的使用场景:

  • 缓存空间,例如基于磁盘的归并排序。

  • 耗时较长的计算任务提供检查点,以便任务能方便地从崩溃前状态恢复执行。

  • 在 Web 服务器容器服务数据时,保存内容管理器容器获取的文件。

临时存放数据,并实现数据互通

这个卷里的容器都是空的,但是数据完全互通,完全一致

容量限制只在了100兆

如果无限制,磁盘会崩溃


hostpath卷

如果不想pod被关掉而被删除,用hostPath 卷能将主机节点文件系统上的文件或目录挂载到您的 Pod 中

hostPath 的一些用法

  • 运行一个需要访问 Docker 引擎内部机制的容器,挂载 /var/lib/docker 路径。

  • 在容器中运行 cAdvisor(监控) 时,以 hostPath 方式挂载 /sys。

  • 允许 Pod 指定给定的 hostPath 在运行 Pod 之前是否应该存在,是否应该创建以及应该以什么方式存在

hostPath的安全隐患

  • 具有相同配置(例如从 podTemplate 创建)的多个 Pod 会由于节点上文件的不同而在不同节点上有不同的行为。

  • 当 Kubernetes 按照计划添加资源感知的调度时,这类调度机制将无法考虑由 hostPath 使用的资源。

  • 基础主机上创建的文件或目录只能由 root 用户写入。您需要在 特权容器 中以 root 身份运行进程,或者修改主机上的文件权限以便容器能够写入 hostPath 卷。

示例:

如果存在就不建立,不存在就建立

在运行前,是没有这个挂载目录的

及时删除了,也是持久化保存


nfs卷

部署一台nfs共享主机并在所有k8s节点中安装nfs-utils

禁用防火墙

关闭防火墙,并打开nfs服务

每个主机都要安装nfs

此时访问都没有

没有激活的情况下,即使有index也不行

进去了里面的容器,里面其实是有这个文件,此时也就激活了

激活了一台主机,其他的都会激活了

数据是持久化的


PersistentVolume持久卷

静态持久卷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 卷的自动回收操作失败

静态pv实例:

这三个目录就是我们要创建的PV

要把他们抽象成集群中的资源

没有创建的命令,直接写

建立PV、查看PV

如何使用,它们是资源,要用要申请资源

创建PVC

申请的内存,一定不要大于pv里申请的

此时pv已经被绑定好了

在pod中使用pvc

创建一个pod

name:lee1  卷的名字

运行配置文件后,开启一个容器测试

此时我们查看在配置文件中设置的挂载目录

在实际上的pod的挂载目录中,新建内容测试

可以看到在挂载的目录中也出现了,说明实验成功了

测试容器的挂载目录此时能不能创建文件

为什么不能建立文件,因为设立的pv是单点读写

只能有一个点能写文件


删除pv的方法

回收命令

想要彻底删除,要在配置文件里删除内容


存储类storageclass

部署NFS Client Provisioner

一定要成功运行

必须要指定你已经存在的存储分配器

之间建立pvc就行,有存储分配器可以直接分配pv

此时存储分配器自动生成的pv

回收自动创建的pv也消失了

用的时候就自动创建,不用就自动回收


设置默认存储类

指定默认存储类

#一次性指定多个pvc

设定默认存储类


statefulset控制器

功能特性

  • Statefulset是为了管理有状态服务的问提设计的

  • StatefulSet将应用状态抽象成了两种情况:

  • 拓扑状态:应用实例必须按照某种顺序启动。新创建的Pod必须和原来Pod的网络标识一样

  • 存储状态:应用的多个实例分别绑定了不同存储数据。

  • StatefulSet给所有的Pod进行了编号,编号规则是:$(statefulset名称)-$(序号),从0开始。

  • Pod被删除后重建,重建Pod的网络标识也不会改变,Pod的拓扑状态按照Pod的“名字+编号”的方式固定下来,并且为每个Pod提供了一个固定且唯一的访问入口,Pod对应的DNS记录。

StatefulSet的组成部分

  • Headless Service:用来定义pod网络标识,生成可解析的DNS记录

  • volumeClaimTemplates:创建pvc,指定pvc名称大小,自动创建pvc且pvc由存储类供应。

  • StatefulSet:管理pod的

构建方法

建立无头服务

建立statefulset模板

在建立pod的同时就会给它建立pv

优点:永远挂载是一对一的

测试:

#为每个pod建立index.html文件

#建立测试pod访问web-0~2

#删掉重新建立statefulset,#访问依然不变


statefulset的弹缩

statefulset有序回收

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值