13. Pod 从入门到深入理解(二)

本章讲解知识点

  • Pod 容器共享 Volume
  • ConfigMap
  • Secret
  • Downward API
  • EmptyDir Volume
  • HostPath Volume

<br>

1. Pod 容器共享 Volume

1.1. Volume 的背景及需要解决的问题

存储是必不可少的,对于服务运行产生的日志、数据,必须有一个地方进行保存,但是我们的容器每一次重启都是“恢复到出厂设置”,这样容器产生的所有数据都会丢失。因此 Kubernetes 必须要解决 Pod 持久化存储问题。

同时一个 Pod 里的容器 A 和容器 B,相互之间存在数据共享的情况,那么 Kubernetes 还得解决存储共享的问题。

在 Kubernetes 中,Pod 是最小的可部署单元。Pod 可以包含一个或多个容器,它们在同一个节点上运行,并共享相同的网络命名空间、PID 命名空间、IPC 命名空间和主机名。Pod 中的容器可以使用 Volume 共享数据,这个 Volume 是由 Kubernetes 提供的一个抽象概念,它可以映射到宿主机上的文件系统目录、网络存储设备或其他存储设备上

Docker 中也有 Volume,但是存在局限性。docker 从 1.7 开始,每个容器只允许有一个卷驱动程序,并且无法将参数传递给卷。

Kubernetes 中的 Volume 与 Docker 中的 Volume 不同,Kubernetes 中的 Volume 是针对 Pod 而言的,而不是针对容器而言的,我们在上一章讲过这个重要结论。因此,在 Kubernetes 中,Volume 可以被多个容器共享,不同容器之间可以通过 Volume 共享数据。

另一方面,Kubernetes Volume 具有明确的生命周期,与使用它的 Pod 相同。因此,在 Kubernetes 中的卷可以比 Pod 中运行的任何 Container 都长,并且可以在 Container 重启或者销毁之后保留数据。Kubernetes 支持多种类型的卷,Pod 可以同时使用任意数量的卷。将 Pod 看作是一个虚拟机,那么 Volume 就是虚拟机的磁盘,Container 则是虚拟机上运行的进程,使用 Volume 存储数据。

1.2. Volume 是什么

从本质上讲,Volume 是一个抽象概念,它可以映射到宿主机上的文件系统目录、网络存储设备或其他存储设备上。但是在使用的过程中,给我们的感受是:Volume 就是一个目录,虽然不准确,但也可以这么理解。

要使用 Volume,需要通过 .spec.volumes 字段指定为 Pod 提供的卷,以及使用 .spec.containers.volumeMounts 字段指定卷挂载的目录。

1.3. Volume 的类型

Kubernetes 目前支持的 Volume 类型包括 Kubernetes 的内部资源对象类型、开源共享存储类型、存储厂商提供的硬件存储设备和公有云提供的存储设备等。

1.Kubernetes 的内部资源对象类型

将 Kubernetes 的内部资源对象类型映射为目录或文件,包括以下类型:

  • ConfigMap:这种方式允许将配置文件或其他非 Secret 以 Volume 形式共享到 Pod 中的一个或多个容器。
  • Secret:这种方式允许将 Secret 以 Volume 形式共享到 Pod 中的一个或多个容器。
  • DownwardAPI:Pod 或 container 的元数据信息。

2.Kubernetes 管理的宿主机本地存储类型

  • EmptyDir Volume:这是最简单的方式,它创建一个空目录,并将它挂载到每个容器中。容器可以读写此目录中的文件。但是,当 Pod 重新启动或在另一个节点上重新创建时,该目录将被清空。
  • HostPath Volume:这种方式将 Pod 的本地文件系统目录直接挂载到容器中。这允许多个容器共享同一文件系统,但它不适用于多个节点之间的容器共享。

3.持久化存储(PV)和网络共享存储类型

  • NFS存储:NFS(Network File System) 是一种分布式文件系统,可以实现多台计算机之间的文件共享,是 Kubernetes 中常用的一种网络共享存储类型。
  • iSCSI存储:iSCSI(Internet Small Computer System Interface) 是一种基于 IP 网络的存储协议,可以将远程的存储设备挂载到本地计算机上,实现数据的访问和共享。Kubernetes 支持 iSCSI 存储的挂载。
  • Ceph存储:Ceph 是一种分布式的存储系统,可以实现多个节点之间的数据存储和访问。Kubernetes 支持 Ceph 存储的挂载。
  • GlusterFS存储:GlusterFS 是一种开源的分布式文件系统,可以将多个存储节点组成一个统一的存储池,实现数据的共享和访问。Kubernetes 支持 GlusterFS 存储的挂载。
  • Cinder存储:Cinder 是 OpenStack 提供的一种块存储服务,可以将存储设备挂载到虚拟机上,实现数据的持久化存储。Kubernetes 支持 Cinder 存储的挂载。

4.存储厂商提供的硬件存储设备

  • StorageOS:StorageOS 提供的存储设备
  • Vsphere Volume:VMWare 提供的存储系统

5.公有云提供的存储设备

  • AWS EBS存储:AWS EBS(Elastic Block Store) 是亚马逊提供的一种云存储服务,可以将存储设备挂载到云服务器上,实现数据的持久化存储。Kubernetes 支持 AWS EBS 存储的挂载。
  • Azure Disk存储:Azure Disk 是微软提供的一种云存储服务,可以将存储设备挂载到云服务器上,实现数据的持久化存储。Kubernetes 支持 Azure Disk 存储的挂载。

本章只侧重讲解 Kubernetes 的内部资源对象类型Kubernetes 管理的宿主机本地存储类型两种,其他的在以后章节详解。

<br>

2. ConfigMap

2.1. 基本概念

ConfigMap 是 Kubernetes 中的一种资源对象,用于存储应用程序的配置数据,例如环境变量、命令行参数、配置文件等。它可以将配置数据与应用程序分离,从而使得应用程序更加灵活和可配置化。

在 Kubernetes 中,ConfigMap 是通过键值对的方式存储数据的。可以将多个键值对组合成一个 ConfigMap 对象,然后将其挂载到 Pod 中的容器中,以便容器可以使用其中的配置数据。

ConfigMap 的优点包括:

  • 简化应用程序的部署:将配置数据与应用程序分离,使得应用程序更加灵活和可配置化。
  • 提高应用程序的可移植性:ConfigMap 可以在不同的环境中重用,从而提高了应用程序的可移植性。
  • 支持热更新:ConfigMap 中的数据可以在不重启 Pod 或无需重新构建镜像的情况下进行更新,从而实现了热更新。

ConfigMap 的使用步骤包括:

  • 创建 ConfigMap 对象,并设置其中的键值对。
  • 在 Pod 的配置文件中,使用 env 或 volume 将 ConfigMap 挂载到容器中。
  • 在容器中通过环境变量或配置文件的方式使用 ConfigMap 中的数据。

2.2. 小实验

1.创建 ConfigMap 对象

首先,我们创建一个 ConfigMap 对象,将应用程序的配置数据存储到其中:

apiVersion: v1
kind: ConfigMap
metadata:
  name: myapp-config
data:
  DB_HOST: db.example.com
  DB_PORT: "5432"

上述配置文件定义了一个名为 myapp-config 的 ConfigMap 对象,其中包含了 2 个键值对,分别表示数据库的主机名、端口号。

2.通过环境变量方式使用 ConfigMap

apiVersion: v1
kind: Pod
metadata:
  name: my-first-pod
spec:
  containers:
    - name: my-first-container
      image: nginx:latest
      ports:
        - containerPort: 80
    - name: my-second-container
      image: redis:latest
      ports:
        - containerPort: 90
      env:
        - name: DB_HOST
          valueFrom:
            configMapKeyRef:
              name: myapp-config
              key: DB_HOST
        - name: DB_PORT
          valueFrom:
            configMapKeyRef:
              name: myapp-config
              key: DB_PORT

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: myapp-config
data:
  DB_HOST: db.example.com
  DB_PORT: "5432"

可以注意到,我们在一个文件里就定义了 Pod 和 ConfigMap,中间只需要用 --- 分隔开就行。然后运行命令 kubectl create -f my-first-pod.yaml 进行创建。

我们在 Pod 的配置文件中使用 env 将 ConfigMap 挂载到容器中,并通过环境变量的方式使用其中的数据。启动 Pod 后,容器中的应用程序就可以使用 ConfigMap 中定义的配置数据了。例如,可以使用 DB_HOST 环境变量连接数据库。如果需要更新配置数据,只需要修改 ConfigMap 对象即可,无需重启 Pod

我们通过 docker exec 进入 redis 容器:printenv,可以直观看到环境变量 DB_PORTDB_HOST

[root@node1 mtuser]# docker ps | grep redis
c1ba8c4f11d6   redis                  "docker-entrypoint.s…"   34 seconds ago   Up 33 seconds             k8s_my-second-container_my-first-pod_default_5365ad32-a7d7-4a21-bf64-7702aa343e83_0
[root@node1 mtuser]#
[root@node1 mtuser]# docker exec -it c1ba8c4f11d6 bash
root@my-first-pod:/data# printenv | grep DB_PORT
DB_PORT=5432
root@my-first-pod:/data# printenv | grep DB_HOST
DB_HOST=db.example.com

3.通过 volumeMount 方式使用 ConfigMap

apiVersion: v1
kind: Pod
metadata:
  name: my-first-pod
spec:
  containers:
    - name: my-first-container
      image: nginx:latest
      ports:
        - containerPort: 80
    - name: my-second-container
      image: redis:latest
      ports:
        - containerPort: 90
      volumeMounts:
      - name: config-volume
        mountPath: /etc/example
  volumes:
  - name: config-volume
    configMap:
      name: myapp-config
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: myapp-config
data:
  DB_HOST: db.example.com
  DB_PORT: "5432"

上面定义文件中,采用了 volumeMounts 的方式将 ConfigMap 挂载到 Pod 的 /etc/example 目录下。在容器启动后,ConfigMap 中的配置数据就会被挂载到容器中,容器就可以通过 /etc/example 路径访问配置数据了。如果需要更新配置数据,只需要更新 ConfigMap 中的数据即可,无需重新创建容器。

[root@node1 mtuser]# docker ps | grep redis
da6566d813d0   redis                  "docker-entrypoint.s…"   5 seconds ago    Up 4 seconds              k8s_my-second-container_my-first-pod_default_105e8f26-137e-4944-b5c5-6e99bbe63712_0
[root@node1 mtuser]# docker exec -it da6566d813d0 bash
root@my-first-pod:/data# cd /etc/example
root@my-first-pod:/etc/example# ls
DB_HOST  DB_PORT
root@my-first-pod:/etc/example# cat DB_HOST
db.example.comroot@my-first-pod:/etc/example# cat DB_PORT
5432root@my-first-pod:/etc/example#

我们通过 docker exec 进入 redis 容器后,就可以在/etc/example 目录下找到相应了 ConfigMap 键值对。

总结下两种方式:

一种是通过环境变量引用,一种是直接挂载进容器里。两种方式各有应用场景,如果只用到几个变量,当然是通过环境变量引用最好,反之挂载进容器里。

4.Pod 使用 ConfigMap 的局限性

  • ConfigMap 必须在 Pod 之前创建,Pod 才能引用它。
  • 如果 Pod 使用 envFrom 基于 ConfigMap 定义环境变量,则无效的环境变量名称将被忽略。
  • ConfigMap 受命名空间限制,只有处于相同命名空间中的 Pod 才能引用它
  • ConfigMap 无法用于静态 Pod。
  • ConfigMap 数据得不到加密。

<br>

3. Secret

Kubernetes 中的 Secret 是一种用于存储敏感数据的对象,例如 API 访问令牌、密码、SSH 密钥等,它们可以被安全地传递给容器中的应用程序。Secret 可以在 Pod 中被挂载为文件或环境变量,并且在使用时会被自动解密。

与 Configmap 的用法类似,不再赘述。

<br>

4. Downward API

4.1. 基本概念

Kubernetes Downward API 是一种 Kubernetes API,它允许 Pod 中的容器访问其自身的元数据和环境变量。通过 Downward API,容器可以获取 Pod 名称、命名空间、IP 地址等元数据,还可以获取 Pod 的标签、注释等信息。同时,Downward API 还允许容器将自身的信息暴露给其他容器或者外部系统。

它的作用是:让 Pod 里的容器能够直接获取到这个 Pod API 对象本身的信息

4.2. 小实验

apiVersion: v1
kind: Pod
metadata:
  name: test-downwardapi-volume
  labels:
    zone: us-est-coast
    cluster: test-cluster1
    rack: rack-22
spec:
  containers:
    - name: client-container
      image: k8s.gcr.io/busybox
      command: ["sh", "-c"]
      args:
      - while true; do
          if [[ -e /etc/podinfo/labels ]]; then
            echo -en '\n\n'; cat 

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

云计算面试题全解析 文章被收录于专栏

本专刊适合于立志转行云计算的小白,有一定的编程、操作系统、计算机网络、数据结构、算法基础。 本专刊同时也适合于面向云计算(Docker + Kubernetes)求职的从业者。 本专刊囊括了云计算、VMWare、Docker、Kubernetes、Containerd等一系列知识点的讲解,并且最后总

全部评论

相关推荐

12-05 15:39
门头沟学院 Java
正在努力学习的鼠鼠:这个博主就是主要做校招互联网招聘的,恰的就是这个流量,你问他他肯定给你列出来100条互联网的好。
点赞 评论 收藏
分享
双非坐过牢:非佬,可以啊10.28笔试,11.06评估11.11,11.12两面,11.19oc➕offer
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务