用实际例子讲透 Kubernetes Pod

Kubernetes Pod

在本指南中,我使用实际示例详细介绍 Kubernetes Pod 概念。如果你想了解如下内容,本指南特别适合你:

  • Pod 核心概念
  • 如何创建 Pod
  • 访问 Pod
  • Pod 关联对象

本指南的目的是让您了解如何构建 Pod,并部署 Pod 和访问在其上运行的应用程序。此外,还有许多与 Pod 对象相关的概念。因此,我提供了与 Pod 相关的所有信息和概念,以进一步构建您所学的基础知识。

注意:在开始探索 Kubernetes Pod 之前,请确保您对 Linux 容器概念有充分的了解。

什么是 Kubernetes Pod?

在了解 Kubernetes Pod 概念之前,让我们先了解一下容器。

众所周知,容器是一个独立的环境,我们在其中打包应用程序及其依赖项。通常,容器运行单个进程(尽管有多种方法可以运行多个进程)。每个容器都有一个 IP 地址,可以附加卷并控制 CPU 和内存资源等。所有这些都是通过命名空间和控制组(cgroups)的概念发生的。

Kubernetes 是一个用于部署、扩展和管理容器化应用程序的容器编排系统,它有自己的容器运行方式。我们称之为 Pod。 Pod 是 Kubernetes 中最小的可部署单元,代表应用程序的单个实例。

例如,如果您想运行 Nginx 应用程序,则可以在 Pod 中运行它。

那么它与容器有什么不同呢?容器是一个单一的单元。但是,一个 Pod 可以包含多个容器。您可以将 Pod 视为一个可以将一个或多个容器容纳在一起的盒子。

Pod 提供了更高级别的抽象,允许您将多个容器作为一个单元进行管理。这里,不再是每个容器分别一个 IP,而是 Pod 整体获取一个 IP,然后,Pod 内的多个不同的容器相互之间,使用 localhost 通信。

multi-container-pod

这意味着 Kubernetes pod 内的容器共享以下内容:

  • Network namespace:网络命名空间 – Pod 内的所有容器都通过 localhost 进行通信。
  • IPC namespace:IPC 命名空间:所有容器都使用共享的进程间通信命名空间。
  • UTS namespace:UTS 命名空间:所有容器共享相同的主机名。

Pod 内的容器之间不共享什么?

  • 默认情况下,PID 命名空间不共享,但是 kubernetes 提供了使用 shareProcessNamespace 选项在 pod 内的容器之间启用进程共享的选项。
  • 挂载命名空间不在容器之间共享。每个容器都有自己的私有文件系统和目录。但是,Pod 挂载卷在容器之间共享。

简而言之,以下是您应该了解 pod 的知识:

  • Pod 是 Kubernetes 中最小的可部署单元。
  • Pod 本质上是短暂的;它们可以被创建、删除和更新。
  • 一个 Pod 可以有多个容器;一个 Pod 内可以运行的容器数量没有限制。
  • 每个 Pod 都有一个唯一的 IP 地址。
  • Pod 使用 IP 地址相互通信。
  • Pod 内的容器使用不同端口,通过 localhost 进行连接。
  • Pod 内运行的容器应具有不同的端口号,以避免端口冲突。
  • 您可以为 Pod 内运行的每个容器设置 CPU 和内存资源。
  • Pod 内的容器共享相同的卷挂载。
  • pod内的所有容器都调度在同一个节点上;它不能跨越多个节点。
  • 如果有多个容器,则在 Pod 启动期间,所有主容器都会并行启动。而 Pod 内的 init 容器按顺序运行。

Pod YAML(对象定义)

现在我们对 Pod 有了基本的了解,让我们看看如何定义 Pod。 Pod 是原生 Kubernetes 对象,如果要创建 pod,则需要以 YAML 格式声明 pod 要求。您还可以使用 kubectl 命令创建 pod。我们将在后面的主题中看到这一点。

以下是创建 Nginx Web 服务器 Pod 的 Pod YAML 示例。此 YAML 只是 pod 的声明性所需状态。

apiVersion: v1
kind: Pod
metadata:
  name: web-server-pod
  labels:
    app: web-server
    environment: production
  annotations:
    description: This pod runs the web server
spec:
  containers:
  - name: web-server
    image: nginx:latest
    ports:
    - containerPort: 80

让我们来理解一下这个 pod YAML。一旦您了解了基本的 YAML,您就会更轻松地使用 Pod 和相关对象,例如部署(Deployment)、守护进程集(Daemonset)、状态集(Statefulset)等。每个 Kubernetes 对象都有一些通用的参数集。这些值会根据我们正在创建的对象类型而变化。

让我们看一下 Kubernetes pod 对象。

参数描述
apiVersionpod 的 API 版本。在我们的例子中,它是 v1
kind对象的种类,这里是 Pod
metadata元数据用于唯一标识和描述容器

– 标签(表示 Pod 的键值对集)。这类似于云环境中的标记。每个对象都必须使用标准标签进行标记。它有助于对对象进行分组。
– name(Pod 的名称)
– namespace (pod 的命名空间)
– 注解(键值格式的附加数据)
spec在“spec”部分下,我们声明了 pod 的所需状态。这些是我们希望在 pod 中运行的容器的规格。
containers在容器下,我们声明 pod 内容器的所需状态。容器镜像、公开端口等。

现在,我们已经查看了一个基本的 Pod YAML 清单。请务必注意,此清单支持许多参数。我们将通过动手实践的方法逐步探索这些附加参数。

现在我们已经对 Pod 有了基本的了解,让我们创建一个 Pod。

创建 Pod(实例)

您可以通过两种方式创建容器:

  • 使用 kubectl 命令:主要用于学习和测试目的。命令有其自身的局限性。
  • 声明性方法:使用 YAML 清单。正儿八经做项目时,使用 YAML 部署 Pod。

让我们看一下这两个选项。我们将创建一个具有以下内容的 NGINX pod:

  • Pod 的名称是 web-server-pod
  • 它应该有标签 app: web-server 和 environment: production
  • 添加注释来描述容器。
  • 使用 nginx:1.14.2 容器镜像。
  • 公开容器端口 80。

使用 kubectl 命令创建 Pod

对于所讨论的 pod 要求,这里是 kubectl 命令。

kubectl run web-server-pod \
  --image=nginx:1.14.2 \
  --restart=Never \
  --port=80 \
  --labels=app=web-server,environment=production \
  --annotations description="This pod runs the web server"

在这里,Pod 部署在默认命名空间中。您可以获取已部署的 pod kubectl 的状态。

kubectl get pods

部署容器后,您将看到容器正在运行状态,如下所示。在我们的示例中,pod 内只有一个容器。因此,它显示 1/1 准备就绪并正在运行。

kubectl-get-pods

查看一个 Pod 的描述

如果你想知道正在运行的 pod 的所有细节,你可以使用 kubectl 来查看这个 pod 的描述。

kubectl describe pod web-server-pod

在以下输出中,您可以看到有关容器的所有详细信息。它的 IP 地址、命名空间、容器详细信息、QoS 类等。

kubectl-describe-pod

以下是 describe 命令显示的所有重要 Pod 信息的图形视图。

pod-info

现在,让我们使用以下命令删除 pod。

kubectl delete pod web-server-pod

使用声明式 YAML 创建 Pod

在正儿八经做项目时,您主要是通过声明式方法创建 pod。让我们看看如何使用 YAML 清单创建一个 pod。创建一个包含以下内容的文件 nginx.yaml。

apiVersion: v1
kind: Pod
metadata:
  name: web-server-pod
  labels:
    app: web-server
    environment: production
  annotations:
    description: This pod runs the web server
spec:
  containers:
  - name: web-server
    image: nginx:1.14.2
    ports:
    - containerPort: 80

现在,要部署清单,您需要使用文件名执行以下 kubectl 命令。

kubectl create -f nginx.yaml

我们是否应该记住每个参数来创建 YAML?不。您可以使用 –dry-run 标志创建 YAML 文件。下面是一个示例。

kubectl run nginx-pod --image=nginx:1.14.2 --dry-run=client -o yaml

您也可以通过重定向输出把它写入文件。

kubectl run nginx-pod --image=nginx:1.14.2 --dry-run=client -o yaml > nginx-pod.yaml

访问在 Pod 中运行的应用程序

现在我们有一个带有 Nginx Web Server 的运行 pod。整个想法是部署和访问在 pod 中运行的应用程序。

Kubectl 提供了一个端口转发命令,用于从本地工作站访问 Kubernetes 集群中正在运行的 Pod。

我们有一个正在运行的 pod,名为 web-server-pod。让我们通过 port-forward 命令访问它。

kubectl port-forward pod/web-server-pod 8080:80

您应该会看到如下所示的输出。

kubectl-pod-forward

现在,如果您进入浏览器并访问 http://localhost:8080,您应该会看到 Nginx 主页,如下所示。该网页由我们的 Nginx Web Server 的 pod 提供服务。

Nginx-Web-Home-Page

现在,您可以通过按 CTRL+C 断开端口转发。

运行 kubectl port-forward 时,发生了什么:

  • Kubectl 绑定本地系统中的指定端口。在我们的例子中,它是 8080。
  • 然后,它与 Kubernetes 集群 API 通信,以建立到所需节点的隧道(单个 HTTP 连接),然后连接到指定的 Pod 和容器端口,即 80。

注意:kubectl 端口转发更像是一个调试实用程序。您需要使用 Kubernetes Service 对象来公开在 Pod 中运行的应用程序。我们将在另一篇博客中实际了解 Kubernetes 服务概念

访问 Pod Shell

我们已经学习了如何访问在 pod 中运行的应用程序。现在,如果您想访问 pod shell,该怎么办?在许多用例中,您需要终端访问容器。一个主要场景是调试和故障排除。这就是 kubectl exec 命令派上用场的地方。您可以使用以下命令访问 web-server-pod 的 shell。

kubectl exec -it web-server-pod -- /bin/sh

在以下输出中,我正在 pod 内执行 whoami 命令。

kubectl-exec-shell

注意:容器镜像通常被设计为非常小,因此您可能会发现无法执行在普通 Linux 系统上执行的所有命令。此限制取决于镜像的生成方式以及容器镜像中包含的工具程序。

Pod 生命周期

关于 Pod 你应该知道的另一个重要概念是它的生命周期。

Pod 通常由 ReplicaSet Controller、Deployment Controller 等控制器管理。使用 YAML 创建单个 Pod 时,它不受任何控制器的管理。在这两种情况下,Pod 都会经历不同的生命周期阶段。

以下是 Pod 生命周期阶段。

  • Pending:表示 Pod 创建请求成功,但调度正在进行中。例如,它正在下载容器映像。
  • Running:容器已成功运行并按预期运行。例如,Pod 是服务客户端请求。
  • Succeeded:容器内的所有容器都已成功终止。例如,成功完成 CronJob 对象。
  • Failed:所有 Pod 都已终止,但至少有一个容器因失败而终止。例如,由于配置问题,在 Pod 内运行的应用程序无法启动,并且容器以非零退出代码退出。
  • Unknown:容器状态未知。例如,集群无法监控 Pod 的状态。

如果描述容器,则可以查看容器的阶段。下面是一个示例。

kubectl-describe-pod

如果您想了解更多信息,请查看有关 Pod 生命周期 的详细博客。

Pod 功能特性

我们部署了一个简单的 Nginx pod,配置非常少。但是,Pod 在资源管理、配置、机密、可用性、安全性等方面具有许多功能。

如果你是初学者,一口气学会所有这些概念就太过分了。在实际用例中使用与 Pod 相关的对象(如部署)时,学习所有这些概念更有意义。

此外,您需要通过实际用例详细了解每个功能。以下是与容器相关的主要功能。

  • Resource Requests and Limits: 资源请求和限制:Pod CPU/内存分配
  • Labels: 标签:附加到 Pod 的键值对,用于对资源进行分类。
  • Selectors: 选择器:根据标签对资源进行分组。
  • Liveness, Readiness, and Startup Probes: 存活、就绪和启动探测:容器运行状况检查
  • ConfigMaps: 用于配置管理
  • Secrets: 用于密钥管理
  • Volumes: 卷:持久性数据存储
  • Init Containers: 初始化容器:在主容器之前运行的容器。
  • Ephemeral Containers: 临时容器:添加到容器中的临时容器,用于调试或故障排除目的。
  • Service Account: 服务帐户:限制对 Kubernetes 对象和资源的访问。
  • SecurityContext: 主机权限和特权。
  • Affinity and Anti-Affinity Rules: 亲和和反亲和规则:跨节点的 Pod 放置控制
  • Pod Preemption & Priority: Pod 抢占和优先级:设置 Pod 调度和逐出的优先级。
  • Pod Disruption Budget: 容器中断预算:在自愿中断期间需要运行的容器副本的最小数量。
  • Container Life Cycle Hooks: 容器生命周期钩子:根据 Pod 的生命周期阶段变化执行自定义脚本。

全面的 Pod YAML 配置

注意:我给出以下示例仅供参考。不要被所有参数所淹没。它并不像看起来那么复杂。一旦你了解了基础知识,就会很容易。

如果您添加我上面列出的 pod 功能,您将获得一个全面的 pod YAML 配置,如下所示。此外,这些选项将与 Deployment、Statefulset 等对象一起使用。

apiVersion: v1
kind: Pod
metadata:
  name: web-server-pod
spec:
  initContainers:
  - name: init-myservice
    image: busybox:1.28
    command: ['sh', '-c', 'echo "Init container started!"']
  containers:
  - name: web-server
    image: nginx:latest
    ports:
    - containerPort: 80
    volumeMounts:
    - name: shared-data
      mountPath: /usr/share/nginx/html
    - name: secret-volume
      mountPath: /etc/my-secret
    - name: configmap-volume
      mountPath: /etc/config
    securityContext:
      capabilities:
        add: ["NET_ADMIN", "SYS_TIME"]
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"
    readinessProbe:
      httpGet:
        path: /index.html
        port: 80
      initialDelaySeconds: 5
      periodSeconds: 5
    livenessProbe:
      httpGet:
        path: /index.html
        port: 80
      initialDelaySeconds: 15
      periodSeconds: 20
    startupProbe:
      httpGet:
        path: /index.html
        port: 80
      failureThreshold: 30
      periodSeconds: 10
    lifecycle:
      postStart:
        exec:
          command: ["/bin/sh", "-c", "echo 'PostStart'"]
      preStop:
        exec:
          command: ["/bin/sh", "-c", "echo 'PreStop'"]
  serviceAccountName: nginx-service-account   
  securityContext:                        
    runAsUser: 1000
    runAsGroup: 3000
    fsGroup: 2000
  shareProcessNamespace: true
  volumes:
  - name: shared-data
    emptyDir: {}
  - name: secret-volume
    secret:
      secretName: nginx-secret
  - name: configmap-volume
    configMap:
      name: nginx-configmap

Pod 关联对象

在 Kubernetes 上运行应用程序时,我们不会运行单个 pod。因为 Kubernetes 是关于扩展和维护 Pod 的可用性的。因此,如果您运行单个 Pod,它将是单点故障。因为 Pod 本身无法直接缩放。正如我们在 Kubernetes 架构中所讨论的,我们需要像 Replicaset 这样的控制器来确保始终运行所需数量的 Pod。

Kubernetes 具有与不同用例相关的 Pod 的不同类型的对象。

pod-objects

以下是与 Pod 相关的重要对象。

  • Replicaset:保持一组稳定的 Pod 副本在任何给定时间运行。
  • Deployment: 部署:运行无状态应用程序,如 Web 服务器、API 等
  • StatefulSets: 运行有状态应用程序,如分布式数据库。
  • Daemonsets: 守护程序集:在所有 Kubernetes 节点上运行代理。
  • Jobs: 作业:用于批处理
  • CronJobs: 计划作业

总结

在本指南中,我们了解了 Kubernetes Pod 的所有核心概念。正如我在介绍中提到的,在 kubernetes 生产级实现方面,pod 有很多功能。

相关阅读:

本文翻译自:https://devopscube.com/kubernetes-pod/

译者:秦晓辉,开源项目 Open-Falcon、Nightingale 创始人,极客时间专栏《运维监控实战笔记》作者,目前在创业,为客户提供可观测性产品和解决方案,欢迎联系做产品技术交流:联系我们交流可观测性产品和方案

  • 17
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夜莺开源监控

您的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值