青冥 青冥
首页
  • Java 基础
  • Java 进阶
  • Java Java 版本新特性
  • JVM
  • MySQL
  • Tomcat
  • Nginx
  • Spring 系列

    • Spring
    • Spring IOC
    • Spring AOP
    • Spring MVC
  • ORM

    • Mybatis
  • 设计模式

    • 23 种设计模式
  • 操作系统内核
  • JVM 内存模型
  • 并发同步处理
  • Atomic 原子操作
  • 队列(Queue)
  • 线程池(Thread Pool)
  • 分布式 - 消息中间件

    • 消息中间件
  • 分布式 - 存储中间件

    • 存储中间件
  • 分布式 - RPC 框架

    • RPC 框架
  • Spring Boot
  • Spring Cloud Alibaba
  • Spring Cloud Netflix
  • Git
  • Maven
  • Jenkins
  • Linux
  • 容器化

    • Docker
    • Kubernetes
  • 面试合集

    • 缓存
  • 实战项目
  • 数据结构与算法
  • 计算机原理
  • 大数据
  • 人工智能(AI)
  • 前端
  • 留言区
  • 本站

    • 分类
    • 标签
    • 归档
  • 我的

    • 关于
  • 友情链接
🍊Gitlab (opens new window)

iByte Horizon

好记性不如烂笔头
首页
  • Java 基础
  • Java 进阶
  • Java Java 版本新特性
  • JVM
  • MySQL
  • Tomcat
  • Nginx
  • Spring 系列

    • Spring
    • Spring IOC
    • Spring AOP
    • Spring MVC
  • ORM

    • Mybatis
  • 设计模式

    • 23 种设计模式
  • 操作系统内核
  • JVM 内存模型
  • 并发同步处理
  • Atomic 原子操作
  • 队列(Queue)
  • 线程池(Thread Pool)
  • 分布式 - 消息中间件

    • 消息中间件
  • 分布式 - 存储中间件

    • 存储中间件
  • 分布式 - RPC 框架

    • RPC 框架
  • Spring Boot
  • Spring Cloud Alibaba
  • Spring Cloud Netflix
  • Git
  • Maven
  • Jenkins
  • Linux
  • 容器化

    • Docker
    • Kubernetes
  • 面试合集

    • 缓存
  • 实战项目
  • 数据结构与算法
  • 计算机原理
  • 大数据
  • 人工智能(AI)
  • 前端
  • 留言区
  • 本站

    • 分类
    • 标签
    • 归档
  • 我的

    • 关于
  • 友情链接
🍊Gitlab (opens new window)
  • Git

  • Maven

  • Jenkins

  • Linux

  • 虚拟容器

    • Docker

    • Kubernetes

      • 初识 Kubernetes
      • Kubernetes 组件&架构
      • Kubernetes Pod & Container
        • 1. Pod 简介
          • 1.1 简介
          • 1.2 Pod 多个容器管理
          • 1.3 Pod 的使用
        • 2. Pod 基本操作
          • 2.1 查看 pod
          • 2.2 创建 pod
          • 2.3 删除 pod
          • 2.4 进入 pod 中的容器
          • 2.5 查看 pod 日志
          • 2.6 查看 pod 描述信息
        • 3. Pod 运行多个容器
          • 3.1 创建 pod
          • 3.2 查看指定容器日志
          • 3.3 进入指定容器
        • 4. Pod 的 Labels(标签)
          • 4.1 语法
          • 4.2 示例
        • 5. Pod 的 生命周期
          • 5.1 生命周期
          • 5.2 pod 阶段
        • 6. Container 特性
          • 6.1 容器生命周期
          • 6.2 Pod 容器生命周期回调
          • 6.3 容器重启策略
          • 6.4 自定义容器启动命令
          • 6.5 容器探针
        • 7. Pod 的资源限制
          • 7.1 metrics-server
          • 7.2 指定内存请求和限制
          • 7.3 指定 CPU 请求和限制
        • 8. Pod 中 Init 容器
          • 8.1 init 容器特点
          • 8.2 使用 init 容器
        • 9. 节点亲和性分配 Pod
          • 9.1 给节点添加标签
          • 9.2 根据选择节点标签指派 pod 到指定节点[nodeSelector]
          • 9.3 根据节点名称指派 pod 到指定节点[nodeName]
          • 9.4 根据亲和性和反亲和性指派 pod 到指定节点
          • 9.5 节点亲和性权重
          • 9.6 pod 间亲和性和反亲和性及权重
          • 9.7 污点和容忍度
          • 9.8 Pod 拓扑分布约束
      • Kubernetes Controller 控制器
      • Kubernetes Service
      • Kubernetes Volumes
      • ConfigMap & Secret
      • Kubernetes Ingress
      • Kubernetets Namespace
      • Kubernetes Helm
  • 互联网工具 - 专题
  • 虚拟容器
  • Kubernetes
沉梦昂志
2025-04-07
目录

Kubernetes Pod & Container

内容概述

官方文档:https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/#working-with-pods (opens new window)

  • 1. Pod 简介
    • 1.1 简介
    • 1.2 Pod 多个容器管理
    • 1.3 Pod 的使用
  • 2. Pod 基本操作
    • 2.1 查看 pod
    • 2.2 创建 pod
    • 2.3 删除 pod
    • 2.4 进入 pod 中的容器
    • 2.5 查看 pod 日志
    • 2.6 查看 pod 描述信息
  • 3. Pod 运行多个容器
    • 3.1 创建 pod
    • 3.2 查看指定容器日志
    • 3.3 进入指定容器
  • 4. Pod 的 Labels(标签)
    • 4.1 语法
    • 4.2 示例
  • 5. Pod 的 生命周期
    • 5.1 生命周期
    • 5.2 pod 阶段
  • 6. Container 特性
    • 6.1 容器生命周期
    • 6.2 Pod 容器生命周期回调
    • 6.3 容器重启策略
    • 6.4 自定义容器启动命令
    • 6.5 容器探针
  • 7. Pod 的资源限制
    • 7.1 metrics-server
    • 7.2 指定内存请求和限制
    • 7.3 指定 CPU 请求和限制
  • 8. Pod 中 Init 容器
    • 8.1 init 容器特点
    • 8.2 使用 init 容器
  • 9. 节点亲和性分配 Pod
    • 9.1 给节点添加标签
    • 9.2 根据选择节点标签指派 pod 到指定节点[nodeSelector]
    • 9.3 根据节点名称指派 pod 到指定节点[nodeName]
    • 9.4 根据亲和性和反亲和性指派 pod 到指定节点
    • 9.5 节点亲和性权重
    • 9.6 pod 间亲和性和反亲和性及权重
    • 9.7 污点和容忍度
    • 9.8 Pod 拓扑分布约束

# 1. Pod 简介

# 1.1 简介

Pod 是可以在 Kubernetes 中创建和管理的、最小的可部署的计算单元。

Pod(就像在鲸鱼荚或者豌豆荚中)是一组(一个或多个)容器; 这些容器共享存储、网络、以及怎样运行这些容器的声明。 Pod 中的内容总是并置(colocated)的并且一同调度,在共享的上下文中运行。简言之如果用 Docker 的术语来描述, Pod 类似于共享名字空间并共享文件系统卷的一组容器。

定义: Pod 就是用来管理一组(一个|多个)容器的集合;特点: 共享网络 共享存储 共享上下文环境

# 1.2 Pod 多个容器管理

Pod 中的容器被自动安排到集群中的同一物理机或虚拟机上,并可以一起进行调度。容器之间可以共享资源和依赖、彼此通信、协调何时以及何种方式终止自身。 例如,你可能有一个容器,为共享卷中的文件提供 Web 服务器支持,以及一个单独的 "边车 (sidercar)" 容器负责从远端更新这些文件,如下图所示: Pod 多个容器管理

# 1.3 Pod 的使用

通常你不需要直接创建 Pod,甚至单实例 Pod。 相反,你会使用诸如 Deployment 或 Job 这类工作负载资源来创建 Pod。 、 如果 Pod 需要跟踪状态,可以考虑 StatefulSet 资源。

Kubernetes 集群中的 Pod 主要有两种用法:

  • 运行单个容器的 Pod。"每个 Pod 一个容器" 模型是最常见的 Kubernetes 用例; 在这种情况下,可以将 Pod 看作单个容器的包装器, 并且Kubernetes 直接管理 Pod,而不是容器。
  • 运行多个协同工作的容器 的 Pod。 Pod 可能封装由多个紧密耦合且需要共享资源的共处容器组成的应用程序。 这些位于同一位置的容器可能形成单个内聚的服务单元 —— 一个容器将文件从共享卷提供给公众, 而另一个单独的“边车”(sidecar)容器则刷新或更新这些文件。 Pod 将这些容器和存储资源打包为一个可管理的实体。

说明:

  • 将多个并置、同管的容器组织到一个 Pod 中是一种相对高级的使用场景。 只有在一些场景中,容器之间紧密关联时你才应该使用这种模式。
  • 每个 Pod 都旨在运行给定应用程序的单个实例。如果希望横向扩展应用程序 (例如,运行多个实例以提供更多的资源), 则应该使用多个 Pod,每个实例使用一个 Pod。 在 Kubernetes 中,这通常被称为副本(Replication)。 通常使用一种工作负载资源及其控制器来创建和管理一组 Pod 副本。

# 2. Pod 基本操作

Pod 的所有操作都和命名空间(namespace)相关,在不指定命名空间的情况下操作 pod,都使用的是默认的命名空间:default。

# 2.1 查看 pod

# 查看默认命名空间的 pod
$ kubectl get pods|pod|po

# 查看所有命名空间的 pod
$ kubectl get pods|pod -A

# 查看指定命名空间的 pod
$ kubectl get pods|pod|po -n <命名空间名称>

# 查看默认命名空间下 pod 的详细信息
$ kubectl get pods -o wide

# 查看所有命名空间下 pod 的详细信息
$ kubectl get pods -o wide -A

# 实时监控 pod 的状态
$ kubectl get pod -w
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 2.2 创建 pod

官网参考地址: https://kubernetes.io/zh-cn/docs/reference/kubernetes-api/workload-resources/pod-v1/ (opens new window)

Pod YAML 文件

# pod.yml
apiVersion: v1
kind: Pod
metadata:
  name: string
  namespace: string
  labels:
    - name: string
  annotations:
    - name: string
spec:
  containers:
    - name: string
      image: string
      imagePullPolicy: [ Always | Never | IfNotPresent ]
      command: [ string ]
      args: [ string ]
      workingDir: string
      volumeMounts:
        - name: string
          mountPath: string
          readOnly: boolean
      ports:
        - name: string
          containerPort: int
          hostPort: int
          protocol: string
      env:
        - name: string
          value: string
      resources:
        limits:
          cpu: string
          memory: string
        requests:
          cpu: string
          memory: string
      livenessProbe:
        exec:
          command: [ string ]
        httpGet:
          path: string
          port: number
          host: string
          schema: string
          httpHeaders:
            - name: string
              value: string
        tcpSocket:
          prot: number
        initialDelaySeconds: 0
        timeoutSeconds: 0
        periodSeconds: 0
        successThreshold: 0
        failureThreshold: 0
      securityContext:
        privileged: false
      restartPolicy: [ Always | Never | OnFailure ]
      nodeSelector: object
      imagePullSecrets:
        - name: string
      hostNetwork: false
      volumes:
        - name: string
          empthDir: { }
          hostPath:
            path: string
          secret:
            secretName: string
            items:
              - key: string
                path: string
          configMap:
            name: string
            items:
              - key: string
                path: string
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77

Pod 基础属性详解:

  • apiVersion: 指定 Kubernetes API 的版本,对于 Pod 来说,通常是 v1,表示使用的是核心 API 版本。
  • kind: 指定 Kubernetes 对象的类型,对于 Pod 来说,这个值是 Pod。
  • metadata: 包含关于 Pod 的元数据信息,如名称、命名空间、标签和注解等。
    • name: Pod 的名称。
    • namespace: Pod 所属的命名空间,默认是 default。
    • labels: 键值对,用于标识 Pod,常用于选择器(selectors),用于组织和选择资源。
    • annotations: 键值对,用于存储元数据,不会被 Kubernetes 核心组件直接使用。
  • spec: 定义了 Pod 的规格(specifications),包括容器定义、重启策略、资源限制、卷挂载等。
    • containers: 定义 Pod 中的容器列表。每个容器可以有自己的名称、镜像、端口、环境变量和卷挂载设置。
      • name: 容器的名称。
      • image: 容器使用的 Docker 镜像。
      • imagePullPolicy:镜像拉取策略,有 Always、IfNotPresent、Never 等。
      • command: 容器启动时执行的命令。
      • args: 传递给容器的参数。
      • workingDir: 容器的工作目录
      • volumeMounts: 挂载到容器内部的存储卷列表。
        • name: 卷的名称,必须与 volumes 中定义的名称匹配。
        • mountPath: 在容器内的挂载的绝对路径。
        • readOnly: 布尔类型,是否为只读模式,默认值为读写模式。
      • ports: 容器需要暴漏的端口号列表。
        • name: 端口的名称。
        • containerPort: 容器需要监听的端口号。
        • hostPort: 容器所在主机需要监听的端口号,默认与 containerPort 相同。设置 hostPort 时,同一台宿主机无法启动该容器的第2份副本。
        • protocol: 端口协议,支持TCP和UDP,默认值为 TCP。
      • env: 环境变量列表。
        • name: 环境变量名称。
        • value: 环境变量值。
      • resources: 资源限制和资源请求设置。
        • limits: 资源限制设置。
          • cpu: CPU 限制,单位为 core 数,将用于 docker run --cpu-shares参数。
          • memory: 内存限制,单位可以为 MiB/GiB 等,将用于 docker run --cpu-shares 参数。
        • requests: 资源限制设置。
          • cpu: CPU 请求,单位为 core 数,容器启动的初始可用数量。
          • memory: 内存请求,单位可以为 MiB/GiB 等,容器启动的初始可用数量。
      • livenessProbe: 对 Pod 内各容器健康检查的设置,当探测无响应几次之后,系统将自动重启该容器。可以设置的方法包括: exec、httpGet、tcpSoccket。对一个容器需设置一种健康检查方法
        • exec: 对 Pod 内各容器健康检查的设置,exec 方式,适用场景:无网络服务或需要复杂状态判断的场景。
          • command: exec 方式需要指定的命令或者脚本。
        • httpGet: 对 Pod 内各容器健康检查的设置,httpGet 方式,需要指定 Path、port, 适用场景:Web服务或暴露HTTP接口的应用。
          • path: 应用用来返回健康状态信息的HTTP路径。
          • port: 应用监听的端口号。
          • host: 指定要访问的主机名。默认情况下,如果未设置,host 将是 Pod 的 IP 地址。如果你想通过特定的域名(例如example.com)来访问服务,可以在这里指定。
          • schema: 默认HTTP,也可以设置为HTTPS
          • httpHeaders: 应用请求头列表信息
            • name: 请求头名称
            • value: 请求头值
        • tcpSocket: 对 Pod 内各容器健康检查的设置,tcpSocket 方式,数据库、Redis等非HTTP协议的TCP服务。
          • prot: 应用监听的端口号。
        • initialDelaySeconds: 容器启动到开始探测的等待时间,默认 0。
        • timeoutSeconds: 单次探测超时时间 ,单位为s,默认值为1s。超过该超时时间设置,将认为该容器不健康,将重启该容器。
        • periodSeconds: 探测间隔时间,单位为s,默认为10s探测一次。
        • successThreshold: 标记健康的最小连续成功次数,默认1次。
        • failureThreshold: 标记不健康的最小连续失败次数,默认3次。
      • securityContext: Pod 权限设置。
      • restartPolicy: 重启策略,可以是 Always、OnFailure 或 Never。
      • nodeSelector: 节点选择器,用于指定 Pod 应该被调度到哪些节点上,表示该 Pod 调度到包含这些 label 的 Node 上,以 key:value 格式指定。
      • volumes: 定义 Pod 可以使用的卷列表。
        • name: 共享存储卷的名称。容器定义部分的containers[].volumeMounts[].name 将引用该存储卷的名称。
        • empthDir: 类型为 emptyDir 的存储卷,表示与 Pod 同生命周期的一个临时目录,其默认值为一个空对象: emptyDir:{}。
        • hostPath: 将主机节点上的文件或目录挂载到 Pod 中。
          • path: 挂载主机路径
          • type: Directory、FileOrCreate、File、Socket、CharDevice、BlockDevice等类型之一。
        • secret: 从 Secret 挂载数据。
          • secretName:
          • items:
            • key:
            • path:
        • configMap: 从 ConfigMap 挂载数据
          • name:
          • items:
            • key:
            • path:

创建 pod

$ kubectl create -f <pod文件名>
$ kubectl apply -f <pod文件名>
1
2

注意:

  • create 仅仅是不存在时创,如果已经存在则报错!
  • apply 不存在创建,存在更新配置。推荐使用 apply!

# 2.3 删除 pod

$ kubectl delete pod <pod名称>
$ kubectl delete -f <pod文件名>
1
2

# 2.4 进入 pod 中的容器

# 注意: 这种方式进入容器默认只会进入 pod 中第一个容器
$ kubectl exec -it <pod名称> -- <执行命令>
# 注意: 进入指定 pod 中指定容器
$ kubectl exec -it <pod名称> -c <容器名称> -- <执行命令>
1
2
3
4

# 2.5 查看 pod 日志

# 注意: 查看 pod 中第一个容器日志
$ kubectl logs [-f] <pod名称>
# 注意: 查看 pod 中指定容器的日志
$ kubect logs [-f] <pod名称> -c <容器名称>
1
2
3
4

# 2.6 查看 pod 描述信息

$ kubectl describe pod <pod名称>
1

# 3. Pod 运行多个容器

# 3.1 创建 pod

# step 1:创建 myapp-pod.yml 文件
apiVersion: v1
kind: Pod
metadata:
  name: myapp
spec:
  containers:
    - name: nginx
      image: nginx:1.19
      ports:
    		- containerPort: 80
      imagePullPolicy: IfNotPresent

    - name: redis
      image: redis:5.0.10
      ports:
    		- containerPort: 6379
      imagePullPolicy: IfNotPresent

# step 2:创建 pod
$ kubectl apply -f myapp-pod.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 3.2 查看指定容器日志

# 查看日志 (默认只查看第一个容器日志,这里是展示 nginx 日志)
$ kubectl logs -f myapp

# 查看 pod 中指定容器的日志
$ kubectl logs -f myapp -c <容器名称>
$ kubectl logs -f myapp -c nginx
$ kubectl logs -f myapp -c redis
1
2
3
4
5
6
7

# 3.3 进入指定容器

# 进入 pod 的容器 (默认进入第一个容器内部,这里会进入 nginx 容器内部)
$ kubectl exec -it myapp -- sh

# 进入 pod 中指定容器内部
$ kubectl exec -it <pod名称> -c <容器名称> -- <执行命令>
$ kubectl exec -it myapp -c nginx -- sh
$ kubectl exec -it myapp -c redis -- sh
1
2
3
4
5
6
7

# 4. Pod 的 Labels(标签)

标签(Labels) 是附加到 Kubernetes 对象(比如 Pod)上的键值对。 标签旨在用于指定对用户有意义且相关的对象的标识属性。标签可以在创建时附加到对象,随后可以随时添加和修改。 每个对象都可以定义一组键(key)/值(value)标签,但是每个键(key)对于给定对象必须是唯一的。

标签作用: 就是用来给 k8s 中对象起别名, 有了别名可以过滤和筛选

# 4.1 语法

标签由键值对组成,其有效标签规则:

  • 必须为 63 个字符或更少(可以为空)
  • 除非标签值为空,必须以字母数字字符([a-z0-9A-Z])开头和结尾
  • 包含破折号(-)、下划线(_)、点(.)和字母或数字

# 4.2 示例

apiVersion: v1
kind: Pod
metadata:
  name: myapp
  labels:
    name: myapp #创建时添加
spec:
  containers:
    - name: nginx
      image: nginx:1.21
      imagePullPolicy: IfNotPresent

    - name: redis
      image: redis:5.0.10
      imagePullPolicy: IfNotPresent
  restartPolicy: Always
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 4.3 标签基本操作

# 查看标签
$ kubectl get pods --show-labels

# 新增标签
$ kubectl label pod <pod名称> <标签key=标签value>
$ kubectl label pod myapp env=prod

# 覆盖标签 --overwrite
$ kubectl label --overwrite pod myapp env=test

# 删除标签 -号代表删除标签
$ kubectl label pod <pod名称> <标签key>-
$ kubectl label pod myapp env-

# 根据标签筛选 >、<、=、!、in、not in
$ kubectl get po -l env=test                # 查询 env=test 的 pod
$ kubectl get po -l env                     # 包含的 pod
$ kubectl get po -l '!env'                  # 不包含的 pod
$ kubectl get po -l 'env in (test,prod)'    # 选择含有指定值的 pod
$ kubectl get po -l 'env notin (test,prod)' # 选择含有指定值的 pod
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 5. Pod 的 生命周期

摘自官网: https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/pod-lifecycle/ (opens new window)

Pod 遵循预定义的生命周期,起始于 Pending 阶段, 如果至少其中有一个主要容器正常启动,则进入 Running, 之后取决于 Pod 中是否有容器以失败状态结束而进入 Succeeded 或者 Failed 阶段。与此同时Pod 在其生命周期中只会被调度一次。 一旦 Pod 被调度(分派)到某个节点,Pod 会一直在该节点运行,直到 Pod 停止或者被终止。

# 5.1 生命周期

和一个个独立的应用容器一样,Pod 也被认为是相对临时性(而不是长期存在)的实体。 Pod 会被创建、赋予一个唯一的 ID(UID), 并被调度到节点,并在终止(根据重启策略)或删除之前一直运行在该节点。如果一个节点死掉了,调度到该节点的 Pod 也被计划在给定超时期限结束后删除。

Pod 自身不具有自愈能力。如果 Pod 被调度到某节点而该节点之后失效, Pod 会被删除;类似地,Pod 无法在因节点资源耗尽或者节点维护而被驱逐期间继续存活。 Kubernetes 使用一种高级抽象来管理这些相对而言可随时丢弃的 Pod 实例,称作控制器。

任何给定的 Pod(由 UID 定义)从不会被“重新调度(rescheduled)”到不同的节点; 相反,这一 Pod 可以被一个新的、几乎完全相同的 Pod 替换掉。 如果需要,新 Pod 的名字可以不变,但是其 UID 会不同。 且 Kubernetes 不保证现有 Pod 的替换 Pod 会被调度到与被替换的旧 Pod 相同的节点。

如果某物声称其生命期与某 Pod 相同,例如存储卷, 这就意味着该对象在此 Pod (UID 亦相同)存在期间也一直存在。 如果 Pod 因为任何原因被删除,甚至完全相同的替代 Pod 被创建时, 这个相关的对象(例如这里的卷)也会被删除并重建。

# 5.2 pod 阶段

Pod 阶段的数量和含义是严格定义的。 除了本文档中列举的内容外,不应该再假定 Pod 有其他的 phase 值。

取值 描述
Pending(悬决) Pod 已被 Kubernetes 系统接受,但有一个或者多个容器尚未创建亦未运行。此阶段包括等待 Pod 被调度的时间和通过网络下载镜像的时间。
Running(运行中) Pod 已经绑定到了某个节点,Pod 中所有的容器都已被创建。至少有一个容器仍在运行,或者正处于启动或重启状态。
Succeeded(成功) Pod 中的所有容器都已成功终止,并且不会再重启。
Failed(失败) Pod 中的所有容器都已终止,并且至少有一个容器是因为失败终止。也就是说,容器以非 0 状态退出或者被系统终止。
Unknown(未知) 因为某些原因无法取得 Pod 的状态。这种情况通常是因为与 Pod 所在主机通信失败。

说明:

  1. 当一个 Pod 被删除时,执行一些 kubectl 命令会展示这个 Pod 的状态为 Terminating(终止)。 这个 Terminating 状态并不是 Pod 阶段之一。 Pod 被赋予一个可以体面终止的期限,默认为 30 秒。 你可以使用 --force 参数来强制终止 Pod。
  2. 如果某节点死掉或者与集群中其他节点失联,Kubernetes 会实施一种策略,将失去的节点上运行的所有 Pod 的 phase 设置为 Failed。

# 6. Container 特性

# 6.1 容器生命周期

Kubernetes 会跟踪 Pod 中每个容器的状态,就像它跟踪 Pod 总体上的阶段一样。 你可以使用容器生命周期回调来在容器生命周期中的特定时间点触发事件。

一旦调度器将 Pod 分派给某个节点,kubelet 就通过容器运行时开始为 Pod 创建容器。容器的状态有三种:Waiting(等待)、Running (运行中)和 Terminated(已终止)。

要检查 Pod 中容器的状态,你可以使用 kubectl describe pod <pod名称>。 其输出中包含 Pod 中每个容器的状态。

$ kubectl describe pod <pod名称>
1

每种状态都有特定的含义:

  • Waiting (等待)

如果容器并不处在 Running 或 Terminated 状态之一,它就处在 Waiting 状态。 处于 Waiting 状态的容器仍在运行它完成启动所需要的操作:例如, 从某个容器镜像仓库拉取容器镜像,或者向容器应用 Secret 数据等等。 当你使用 kubectl 来查询包含 Waiting 状态的容器的 Pod 时, 你也会看到一个 Reason 字段,其中给出了容器处于等待状态的原因。

  • Running(运行中)

Running 状态表明容器正在执行状态并且没有问题发生。 如果配置了 postStart 回调,那么该回调已经执行且已完成。 如果你使用 kubectl 来查询包含 Running 状态的容器的 Pod 时,你也会看到关于容器进入 Running 状态的信息。

  • Terminated(已终止)

处于 Terminated 状态的容器已经开始执行并且或者正常结束或者因为某些原因失败。 如果你使用 kubectl 来查询包含 Terminated 状态的容器的 Pod 时, 你会看到容器进入此状态的原因、退出代码以及容器执行期间的起止时间。

如果容器配置了 preStop 回调,则该回调会在容器进入 Terminated 状态之前执行。

# 6.2 Pod 容器生命周期回调

容器生命周期回调/事件/钩子

类似于许多具有生命周期回调组件的编程语言框架,例如 Angular、Vue、Kubernetes 为容器提供了生命周期回调。 回调使容器能够了解其管理生命周期中的事件,并在执行相应的生命周期回调时运行在处理程序中实现的代码。

有两个回调暴露给容器:

  • PostStart:这个回调在容器被创建之后立即被执行。 但是,不能保证回调会在容器入口点(ENTRYPOINT)之前执行。 没有参数传递给处理程序。

  • PreStop:在容器因 API 请求或者管理事件(诸如存活态探针、启动探针失败、资源抢占、资源竞争等) 而被终止之前,此回调会被调用。 如果容器已经处于已终止或者已完成状态,则对 preStop 回调的调用将失败。 在用来停止容器的 TERM 信号被发出之前,回调必须执行结束。 Pod 的终止宽限周期在 PreStop 回调被执行之前即开始计数, 所以无论回调函数的执行结果如何,容器最终都会在 Pod 的终止宽限期内被终止。 没有参数会被传递给处理程序。

使用容器生命周期回调

# nginx-pod.yml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
    - name: nginx
      image: nginx:1.19
      lifecycle:
        postStart: # 容器创建过程中执行
          exec:
            command: [ "/bin/sh","-c","echo postStart >> /start.txt" ]
        preStop: # 容器终止之前执行
          exec:
            command: [ "/bin/sh","-c","echo postStop >> /stop.txt && sleep 5" ]
      ports:
        - containerPort: 80
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 6.3 容器重启策略

Pod 的 spec 中包含一个 restartPolicy 字段,其可能取值包括 Always(总是重启)、OnFailure(容器异常退出状态码非 0,重启) 和 Never 。默认值是 Always。

restartPolicy 适用于 Pod 中的所有容器。restartPolicy 仅针对同一节点上 kubelet 的容器重启动作。当 Pod 中的容器退出时, kubelet 会按指数回退方式计算重启的延迟(10s、20s、40s、...),其最长延迟为 5 分钟。 一旦某容器执行了 10 分钟并且没有出现问题, kubelet 对该容器的重启回退计时器执行重置操作。

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  containers:
    - name: nginx
      image: nginx:1.19
      imagePullPolicy: IfNotPresent
  restartPolicy: Always # OnFailure Never
1
2
3
4
5
6
7
8
9
10
11
12

# 6.4 自定义容器启动命令

和 Docker 容器一样,k8s 中容器也可以通过command、args 用来修改容器启动默认执行命令以及传递相关参数。 但一般推荐使用 command 修改启动命令,使用 args 为启动命令传递参数。

apiVersion: v1
kind: Pod
metadata:
  name: redis
  labels:
    app: redis
spec:
  containers:
    - name: redis
      image: redis:5.0.10
      command: [ "redis-server" ]                 # 用来指定启动命令
      args: [ "--appendonly yes" ]                # 用来为启动命令传递参数
      # args: ["redis-server","--appendonly yes"] # 单独使用修改启动命令并传递参数
      # args:                                     # 另一种语法格式
      #  - redis-server
      #  - "--appendonly yes"
      imagePullPolicy: IfNotPresent
  restartPolicy: Always
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 6.5 容器探针

probe 是由 kubelet 对容器执行的定期诊断。要执行诊断,kubelet 既可以在容器内执行代码,也可以发出一个网络请求。

定义: 容器探针 就是用来定期对容器进行健康检查的。

# 探测类型

针对运行中的容器,kubelet 可以选择是否执行以下三种探针,以及如何针对探测结果作出反应:

  • livenessProbe:指示容器是否正在运行。如果存活态探测失败,则 kubelet 会杀死容器, 并且容器将根据其重启策略决定未来。 如果容器不提供存活探针,则默认状态为 Success。
  • readinessProbe:指示容器是否准备好为请求提供服。如果就绪态探测失败, 端点控制器将从与 Pod 匹配的所有服务的端点列表中删除该 Pod 的 IP 地址。 初始延迟之前的就绪态的状态值默认为 Failure。 如果容器不提供就绪态探针,则默认状态为 Success。
  • startupProbe 1.7+:指示容器中的应用是否已经启动。如果提供了启动探针,则所有其他探针都会被 禁用,直到此探针成功为止。如果启动探测失败, kubelet 将杀死容器, 而容器依其重启策略进行重启。 如果容器没有提供启动探测,则默认状态为 Success。

# 探针机制

使用探针来检查容器有四种不同的方法。 每个探针都必须准确定义为这四种机制中的一种:

  • exec

    在容器内执行指定命令。如果命令退出时返回码为 0 则认为诊断成功。

  • grpc

    使用 gRPC 执行一个远程过程调用。 目标应该实现 gRPC健康检查。 如果响应的状态是 "SERVING",则认为诊断成功。 gRPC 探针是一个 Alpha 特性,只有在你启用了 "GRPCContainerProbe" 特性门控时才能使用。

  • httpGet

    对容器的 IP 地址上指定端口和路径执行 HTTP GET 请求。如果响应的状态码大于等于 200 且小于 400,则诊断被认为是成功的。

  • tcpSocket

    对容器的 IP 地址上的指定端口执行 TCP 检查。如果端口打开,则诊断被认为是成功的。 如果远程系统(容器)在打开连接后立即将其关闭,这算作是健康的。

# 探针结果

每次探测都将获得以下三种结果之一:

  • Success(成功)容器通过了诊断。
  • Failure(失败)容器未通过诊断。
  • Unknown(未知)诊断失败,因此不会采取任何行动。

# 探针参数

initialDelaySeconds: 5       # 初始化时间 5s
periodSeconds: 4             # 检测间隔时间 4s
timeoutSeconds: 1             # 默认检测超时时间为 1s
failureThreshold: 3         # 默认失败次数为 3 次,达到3次后重启pod
successThreshold: 1         # 默认成功次数为 1 次,1次监测成功代表成功
1
2
3
4
5

# 使用探针

  • exec
apiVersion: v1
kind: Pod
metadata:
  name: liveness-exec
  labels:
    exec: exec
spec:
  containers:
    - name: nginx
      image: nginx:1.19
      ports:
        - containerPort: 80
      args:
        - /bin/sh
        - -c
        - sleep 7;nginx -g "daemon off;" # 这一步会和初始化同时开始运行,也就是在初始化5s后和7秒之间,会检测出一次失败,7秒后启动后检测正常,所以pod不会重启
      imagePullPolicy: IfNotPresent
      livenessProbe:
        exec: # 这里使用 exec 执行 shell 命令检测容器状态
          command:
            - ls
            - /var/run/nginx.pid  # 查看是否有pid文件
        initialDelaySeconds: 5    # 初始化时间5s
        periodSeconds: 4          # 检测间隔时间4s
        timeoutSeconds: 1         # 默认检测超时时间为1s
        failureThreshold: 3       # 默认失败次数为3次,达到3次后重启pod
        successThreshold: 1       # 默认成功次数为1次,1 次代表成功
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

说明:

  1. 如果 sleep 7s,第一次检测发现失败,但是第二次检测发现成功后容器就一直处于健康状态不会重启。
  2. 如果 sleep 30s,第一次检测失败,超过 3 次检测同样失败,k8s 就回杀死容器进行重启,反复循环这个过程。
  • tcpSocket
apiVersion: v1
kind: Pod
metadata:
  name: liveness-tcpsocket
  labels:
    tcpsocket: tcpsocket
spec:
  containers:
    - name: nginx
      image: nginx:1.19
      ports:
        - containerPort: 80
      args:
        - /bin/sh
        - -c
        - sleep 7;nginx -g "daemon off;"
      imagePullPolicy: IfNotPresent
      livenessProbe:
        tcpSocket: # tcpSocket
          port: 80
        initialDelaySeconds: 5   # 初始化时间5s
        periodSeconds: 4         # 检测间隔时间4s
        timeoutSeconds: 1        # 默认检测超时时间为1s
        failureThreshold: 3      # 默认失败次数为3次,达到3次后重启pod
        successThreshold: 1      # 默认成功次数为1次,1 次代表成功
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
  • httpGet
# probe-liveness-httget.yml
apiVersion: v1
kind: Pod
metadata:
  name: liveness-httpget
  labels:
    httpget: httpget
spec:
  containers:
    - name: nginx
      image: nginx:1.19
      ports:
        - containerPort: 80
      args:
        - /bin/sh
        - -c
        - sleep 7;nginx -g "daemon off;"
      imagePullPolicy: IfNotPresent
      livenessProbe:
        httpGet: # httpGet
          port: 80               # 访问的端口
          path: /index.html      # 访问的路径
        initialDelaySeconds: 5   # 初始化时间5s
        periodSeconds: 4         # 检测间隔时间4s
        timeoutSeconds: 1        # 默认检测超时时间为1s
        failureThreshold: 3      # 默认失败次数为3次,达到3次后重启pod
        successThreshold: 1      # 默认成功次数为1次,1 次代表成功
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  • GRPC 探针

官方参考地址: https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/ (opens new window)

# 7. Pod 的资源限制

在k8s中对于容器资源限制主要分为以下两类:

  • 内存资源限制: 内存请求(request)和内存限制(limit)分配给一个容器。 我们保障容器拥有它请求数量的内存,但不允许使用超过限制数量的内存。

官网参考地址: https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/assign-memory-resource/ (opens new window)

  • CPU 资源限制: 为容器设置 CPU request(请求) 和 CPU limit(限制)。 容器使用的 CPU 不能超过所配置的限制。 如果系统有空闲的 CPU 时间,则可以保证给容器分配其所请求数量的 CPU 资源。

官网参考地址: https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/assign-cpu-resource/ (opens new window)

请求 request memory cpu :可以使用的基础资源 100M 限制 limit memory cpu :可以使用的最大资源 200M,超过最大资源之后容器会被 kill ,抛出 OOM 错误。

# 7.1 metrics-server

官网地址: https://github.com/kubernetes-sigs/metrics-server (opens new window)

Kubernetes Metrics Server (Kubernetes指标服务器),它是一个可扩展的、高效的容器资源度量源。 Metrics Server 用于监控每个 Node 和 Pod 的负载(用于Kubernetes内置自动扩缩管道)。Metrics Server 从Kubelets 收集资源指标, 并通过 Metrics API 在Kubernetes apiserver中公开,供 Horizontal Pod Autoscaler 和 Vertical Pod Autoscaler 使用。 Metrics API 也可以通过 kubectl top 访问,使其更容易调试自动扩缩管道。

  • 查看 metrics-server(或者其他资源指标 API metrics.k8s.io 服务提供者)是否正在运行, 请键入以下命令:
$ kubectl get apiservices
1
  • 如果资源指标 API 可用,则会输出将包含一个对 metrics.k8s.io 的引用:
NAME
v1beta1.metrics.k8s.io
1
2
  • 安装 metrics-server
# components.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    k8s-app: metrics-server
  name: metrics-server
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  labels:
    k8s-app: metrics-server
    rbac.authorization.k8s.io/aggregate-to-admin: "true"
    rbac.authorization.k8s.io/aggregate-to-edit: "true"
    rbac.authorization.k8s.io/aggregate-to-view: "true"
  name: system:aggregated-metrics-reader
rules:
  - apiGroups:
      - metrics.k8s.io
    resources:
      - pods
      - nodes
    verbs:
      - get
      - list
      - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  labels:
    k8s-app: metrics-server
  name: system:metrics-server
rules:
  - apiGroups:
      - ""
    resources:
      - nodes/metrics
    verbs:
      - get
  - apiGroups:
      - ""
    resources:
      - pods
      - nodes
    verbs:
      - get
      - list
      - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  labels:
    k8s-app: metrics-server
  name: metrics-server-auth-reader
  namespace: kube-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: extension-apiserver-authentication-reader
subjects:
  - kind: ServiceAccount
    name: metrics-server
    namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  labels:
    k8s-app: metrics-server
  name: metrics-server:system:auth-delegator
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:auth-delegator
subjects:
  - kind: ServiceAccount
    name: metrics-server
    namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  labels:
    k8s-app: metrics-server
  name: system:metrics-server
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:metrics-server
subjects:
  - kind: ServiceAccount
    name: metrics-server
    namespace: kube-system
---
apiVersion: v1
kind: Service
metadata:
  labels:
    k8s-app: metrics-server
  name: metrics-server
  namespace: kube-system
spec:
  ports:
    - name: https
      port: 443
      protocol: TCP
      targetPort: https
  selector:
    k8s-app: metrics-server
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    k8s-app: metrics-server
  name: metrics-server
  namespace: kube-system
spec:
  selector:
    matchLabels:
      k8s-app: metrics-server
  strategy:
    rollingUpdate:
      maxUnavailable: 0
  template:
    metadata:
      labels:
        k8s-app: metrics-server
    spec:
      containers:
        - args:
            - --cert-dir=/tmp
            - --secure-port=4443
            - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
            - --kubelet-use-node-status-port
            - --metric-resolution=15s
            - --kubelet-insecure-tls #修改去掉证书验证
          image: dyrnq/metrics-server:v0.6.2 #修改官方无法下载
          imagePullPolicy: IfNotPresent
          livenessProbe:
            failureThreshold: 3
            httpGet:
              path: /livez
              port: https
              scheme: HTTPS
            periodSeconds: 10
          name: metrics-server
          ports:
            - containerPort: 4443
              name: https
              protocol: TCP
          readinessProbe:
            failureThreshold: 3
            httpGet:
              path: /readyz
              port: https
              scheme: HTTPS
            initialDelaySeconds: 20
            periodSeconds: 10
          resources:
            requests:
              cpu: 100m
              memory: 200Mi
          securityContext:
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            runAsNonRoot: true
            runAsUser: 1000
          volumeMounts:
            - mountPath: /tmp
              name: tmp-dir
      hostNetwork: true  #必须指定这个才行
      nodeSelector:
        kubernetes.io/os: linux
      priorityClassName: system-cluster-critical
      serviceAccountName: metrics-server
      volumes:
        - emptyDir: { }
          name: tmp-dir
---
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
  labels:
    k8s-app: metrics-server
  name: v1beta1.metrics.k8s.io
spec:
  group: metrics.k8s.io
  groupPriorityMinimum: 100
  insecureSkipTLSVerify: true
  service:
    name: metrics-server
    namespace: kube-system
  version: v1beta1
  versionPriority: 100
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
$ kubectl appply -f components.yaml
1

# 7.2 指定内存请求和限制

官网参考: https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/assign-memory-resource/ (opens new window)

为容器指定内存请求,请在容器资源清单中包含 resources:requests 字段。 同理,要指定内存限制,请包含 resources:limits。

# nginx-memory-demo.yaml
# 内存资源的基本单位是字节(byte)。你可以使用这些后缀之一,将内存表示为 纯整数或定点整数:E、P、T、G、M、K、Ei、Pi、Ti、Gi、Mi、Ki。 
# 例如,下面是一些近似相同的值:128974848, 129e6, 129M, 123Mi
apiVersion: v1
kind: Pod
metadata:
  name: nginx-memory-demo
spec:
  containers:
    - name: nginx-memory-demo
      image: nginx:1.19
      resources:
        requests:
          memory: "100Mi"
        limits:
          memory: "200Mi"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ kubectl appply -f nginx-memory-demo.yaml
1
  • 查看容器内存使用情况
$ kubectl get pod nginx-memory-demo --output=yaml
1
  • 查看容器正在使用内存情况
$ kubectl top pod nginx-memory-demo 
1

内存请求和限制的目的

通过为集群中运行的容器配置内存请求和限制,你可以有效利用集群节点上可用的内存资源。 通过将 Pod 的内存请求保持在较低水平, 你可以更好地安排 Pod 调度。 通过让内存限制大于内存请求,你可以完成两件事:

  • Pod 可以进行一些突发活动,从而更好的利用可用内存。
  • Pod 在突发活动期间,可使用的内存被限制为合理的数量。

没有指定内存限制

如果你没有为一个容器指定内存限制,则自动遵循以下情况之一:

  • 容器可无限制地使用内存。容器可以使用其所在节点所有的可用内存, 进而可能导致该节点调用 OOM Killer。 此外,如果发生 OOM Kill,没有资源限制的容器将被杀掉的可行性更大。
  • 运行的容器所在命名空间有默认的内存限制,那么该容器会被自动分配默认限制。

# 7.3 指定 CPU 请求和限制

官网参考: https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/assign-cpu-resource/ (opens new window)

为容器指定 CPU 请求,请在容器资源清单中包含 resources: requests 字段。 要指定 CPU 限制,请包含 resources:limits。

  • CPU 资源以 CPU 单位度量,小数值是可以使用的。例如:一个请求 0.5 CPU 的容器保证会获得请求 1 个 CPU 的容器的 CPU 的一半。
  • 可以使用后缀 m 表示毫。例如 100m CPU、100 milliCPU 和 0.1 CPU 都相同。
  • CPU 请求只能使用绝对数量,而不是相对数量。0.1 在单核、双核或 48 核计算机上的 CPU 数量值是一样的。
# nginx-cpu-demo.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-cpu-demo
spec:
  containers:
    - name: nginx-cpu-demo
      image: nginx:1.19
      resources:
        limits:
          cpu: "1"
        requests:
          cpu: "0.5"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ kubectl appply -f nginx-cpu-demo.yaml
1
  • 显示 pod 详细信息
$ kubectl get pod nginx-cpu-demo --output=yaml 
1
  • 显示 pod 运行指标
$ kubectl top pod nginx-cpu-demo
1

CPU 请求和限制的初衷

通过配置你的集群中运行的容器的 CPU 请求和限制,你可以有效利用集群上可用的 CPU 资源。 通过将 Pod CPU 请求保持在较低水平, 可以使 Pod 更有机会被调度。 通过使 CPU 限制大于 CPU 请求,你可以完成两件事:

  • Pod 可能会有突发性的活动,它可以利用碰巧可用的 CPU 资源。
  • Pod 在突发负载期间可以使用的 CPU 资源数量仍被限制为合理的数量。

如果不指定 CPU 限制

如果你没有为容器指定 CPU 限制,则会发生以下情况之一:

  • 容器在可以使用的 CPU 资源上没有上限。因而可以使用所在节点上所有的可用 CPU 资源。
  • 容器在具有默认 CPU 限制的名字空间中运行,系统会自动为容器设置默认限制。

如果你设置了 CPU 限制但未设置 CPU 请求

  • 如果你为容器指定了 CPU 限制值但未为其设置 CPU 请求,Kubernetes 会自动为其 设置与 CPU 限制相同的 CPU 请求值。
  • 类似的,如果容器设置了内存限制值但未设置 内存请求值,Kubernetes 也会为其设置与内存限制值相同的内存请求。

# 8. Pod 中 Init 容器

Init 容器是一种特殊容器,在 Pod 内的应用容器启动之前运行。Init 容器可以包括一些应用镜像中不存在的实用工具和安装脚本。

# 8.1 init 容器特点

Init 容器与普通的容器非常像,除了如下几点:

  • 它们总是运行到完成。如果 Pod 的 Init 容器失败,kubelet 会不断地重启该 Init 容器直到该容器成功为止。 然而,如果 Pod 对应的 restartPolicy 值为 "Never",并且 Pod 的 Init 容器失败, 则 Kubernetes 会将整个 Pod 状态设置为失败。
  • 每个都必须在下一个启动之前成功完成。
  • 同时 Init 容器不支持 lifecycle、livenessProbe、readinessProbe 和 startupProbe, 因为它们必须在 Pod 就绪之前运行完成。
  • 如果为一个 Pod 指定了多个 Init 容器,这些容器会按顺序逐个运行。 每个 Init 容器必须运行成功,下一个才能够运行。 当所有的Init 容器运行完成时, Kubernetes 才会为 Pod 初始化应用容器并像平常一样运行。
  • Init 容器支持应用容器的全部字段和特性,包括资源限制、数据卷和安全设置。 然而,Init 容器对资源请求和限制的处理稍有不同。

# 8.2 使用 init 容器

官网地址: https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/init-containers/ (opens new window)

在 Pod 的规约中与用来描述应用容器的 containers 数组平行的位置指定 Init 容器。

apiVersion: v1
kind: Pod
metadata:
  name: init-demo
spec:
  containers:
    - name: myapp-container
      image: busybox:1.28
      command: [ 'sh', '-c', 'echo The app is running! && sleep 3600' ]
  initContainers:
    - name: init-myservice
      image: busybox:1.28
      command: [ 'sh', '-c', 'echo init-myservice is running! && sleep 5' ]
    - name: init-mydb
      image: busybox:1.28
      command: [ 'sh', '-c', 'echo init-mydb is running! && sleep 10' ]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  • 查看启动详细
$ kubectl describe pod init-demo

# 部分结果
Events:
  Type    Reason     Age    From               Message
  ----    ------     ----   ----               -------
  Normal  Scheduled  2m16s  default-scheduler  Successfully assigned default/init-demo to k8s-node2
  Normal  Pulling    2m16s  kubelet            Pulling image "busybox:1.28"
  Normal  Pulled     118s   kubelet            Successfully pulled image "busybox:1.28" in 17.370617268s (17.370620685s including waiting)
  Normal  Created    118s   kubelet            Created container init-myservice
  Normal  Started    118s   kubelet            Started container init-myservice
  Normal  Pulled     112s   kubelet            Container image "busybox:1.28" already present on machine
  Normal  Created    112s   kubelet            Created container init-mydb
  Normal  Started    112s   kubelet            Started container init-mydb
  Normal  Pulled     101s   kubelet            Container image "busybox:1.28" already present on machine
  Normal  Created    101s   kubelet            Created container myapp-container
  Normal  Started    101s   kubelet            Started container myapp-container
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 9. 节点亲和性分配 Pod

官方地址: http://kubernetes.p2hp.com/docs/concepts/scheduling-eviction/assign-pod-node.html (opens new window)

你可以约束一个 Pod 以便 限制 其只能在特定的节点上运行, 或优先在特定的节点上运行。 有几种方法可以实现这点,推荐的方法都是用 标签选择算符来进行选择。 通常这样的约束不是必须的,因为调度器将自动进行合理的放置(比如,将 Pod 分散到节点上, 而不是将 Pod 放置在可用资源不足的节点上等等)。 但在某些情况下,你可能需要进一步控制 Pod 被部署到哪个节点。例如,确保 Pod 最终落在连接了 SSD 的机器上, 或者将来自两个不同的服务且有大量通信的 Pods 被放置在同一个可用区。

你可以使用下列方法中的任何一种来选择 Kubernetes 对特定 Pod 的调度:

  • 与节点标签匹配的 nodeSelector 推荐
  • 亲和性与反亲和性 推荐
  • nodeName
  • Pod 拓扑分布约束 推荐

定义: 使用节点亲和性可以把 Kubernetes Pod 分配到特定节点。

# 9.1 给节点添加标签

  • 列出集群中的节点及其标签:
$ kubectl get nodes --show-labels
# 输出类似于此:
NAME        STATUS   ROLES           AGE   VERSION   LABELS
k8s-node1   Ready    control-plane   10d   v1.26.0   beta.kubernetes.io/arch=arm64,beta.kubernetes.io/os=linux...
k8s-node2   Ready    <none>          10d   v1.26.0   beta.kubernetes.io/arch=arm64,beta.kubernetes.io/os=linux...
1
2
3
4
5
  • 选择一个节点,给它添加一个标签:
$ kubectl label nodes <node名称> disktype=ssd
1
$ kubectl label nodes k8s-node1 disktype=ssd
1
  • 验证你所选节点具有 disktype=ssd 标签:
$ kubectl get nodes --show-labels
# 输出类似于此:
NAME        STATUS   ROLES           AGE   VERSION   LABELS
k8s-node1   Ready    control-plane   10d   v1.26.0   beta.kubernetes.io/arch=arm64,beta.kubernetes.io/os=linux,disktype=ssd...
k8s-node2   Ready    <none>          10d   v1.26.0   beta.kubernetes.io/arch=arm64,beta.kubernetes.io/os=linux...
k8s-node3   Ready    <none>          10d   v1.26.0   beta.kubernetes.io/arch=arm64,beta.kubernetes.io/os=linux...
1
2
3
4
5
6

# 9.2 根据选择节点标签指派 pod 到指定节点[nodeSelector]

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    env: nginx
spec:
  containers:
    - name: nginx
      image: nginx:1.19
      imagePullPolicy: IfNotPresent
  nodeSelector:
    disktype: ssd                     # 选择节点为标签为 ssd 的节点
1
2
3
4
5
6
7
8
9
10
11
12
13

# 9.3 根据节点名称指派 pod 到指定节点[nodeName]

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  nodeName: worker1                   # 调度 Pod 到特定的节点
  containers:
    - name: nginx
      image: nginx
      imagePullPolicy: IfNotPresent
1
2
3
4
5
6
7
8
9
10

# 9.4 根据亲和性和反亲和性指派 pod 到指定节点

官网地址: http://kubernetes.p2hp.com/docs/concepts/scheduling-eviction/assign-pod-node.html (opens new window)

说明

nodeSelector 提供了一种最简单的方法来将 Pod 约束到具有特定标签的节点上。亲和性和反亲和性扩展了你可以定义的约束类型。使用亲和性与反亲和性的一些好处有:

  • 亲和性、反亲和性语言的表达能力更强。 nodeSelector 只能选择拥有所有指定标签的节点。 亲和性、反亲和性为你提供对选择逻辑的更强控制能力。
  • 你可以标明某规则是“软需求”或者“偏好”,这样调度器在无法找到匹配节点时仍然调度该 Pod。
  • 你可以使用节点上(或其他拓扑域中)运行的其他 Pod 的标签来实施调度约束, 而不是只能使用节点本身的标签。 这个能力让你能够定义规则允许哪些 Pod 可以被放置在一起。

亲和性功能由两种类型的亲和性组成:

  • 节点亲和性功能类似于 nodeSelector 字段,但它的表达能力更强,并且允许你指定软规则。
  • Pod 间亲和性/反亲和性允许你根据其他 Pod 的标签来约束 Pod。

节点亲和性概念上类似于 nodeSelector, 它使你可以根据节点上的标签来约束 Pod 可以调度到哪些节点上。 节点亲和性有两种:

  • requiredDuringSchedulingIgnoredDuringExecution: 调度器只有在规则被满足的时候才能执行调度。 此功能类似于 nodeSelector, 但其语法表达能力更强。
  • preferredDuringSchedulingIgnoredDuringExecution: 调度器会尝试寻找满足对应规则的节点。 如果找不到匹配的节点,调度器仍然会调度该 Pod。

注意:在上述类型中,IgnoredDuringExecution 意味着如果节点标签在 Kubernetes 调度 Pod 后发生了变更,Pod 仍将继续运行。

apiVersion: v1
kind: Pod
metadata:
  name: with-node-affinity
spec:
  affinity:
    nodeAffinity:
      # 节点必须包含一个键名为 ssd 的标签, 并且该标签的取值必须为 fast 或 superfast。
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
          - matchExpressions:
              - key: ssd
                operator: In
                values:
                  - fast
                  - superfast
  containers:
    - name: nginx
      image: nginx:1.19
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

注意:

  • 你可以使用 In、NotIn、Exists、DoesNotExist、Gt 和 Lt 之一作为操作符。
  • NotIn 和 DoesNotExist 可用来实现节点反亲和性行为。

# 9.5 节点亲和性权重

你可以为 preferredDuringSchedulingIgnoredDuringExecution 亲和性类型的每个实例设置 weight 字段,其取值范围是 1 到 100。 权重主要用于调整亲和性规则的优先级。当存在多个亲和性规则时,权重高的规则将比权重低的规则有更高的优先级。 这有助于在有多个亲和性规则冲突时,决定哪个规则应该优先被考虑。且权重值大优先。

apiVersion: v1
kind: Pod
metadata:
  name: with-node-affinity
spec:
  affinity:
    nodeAffinity:
      # 节点最好具有一个键名为 app 且取值为 fast 的标签。
      preferredDuringSchedulingIgnoredDuringExecution:
        - weight: 1     # 取值范围是 1 到 100
          preference:
            matchExpressions:
              - key: ssd
                operator: In
                values:
                  - fast
        - weight: 50
          preference:
            matchExpressions:
              - key: app
                operator: In
                values:
                  - demo
  containers:
    - name: nginx
      image: nginx:1.19
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# 9.6 pod 间亲和性和反亲和性及权重

与节点亲和性类似,Pod 的亲和性与反亲和性也有两种类型:

  • requiredDuringSchedulingIgnoredDuringExecution
  • preferredDuringSchedulingIgnoredDuringExecution

例如,你可以使用 requiredDuringSchedulingIgnoredDuringExecution 亲和性来告诉调度器, 将两个服务的 Pod 放到同一个云提供商可用区内,因为它们彼此之间通信非常频繁。 类似地,你可以使用preferredDuringSchedulingIgnoredDuringExecution 反亲和性来将同一服务的多个 Pod 分布到多个云提供商可用区中。

要使用 Pod 间亲和性,可以使用 Pod 规约中的 spec.affinity.podAffinity 字段。 对于 Pod 间反亲和性, 可以使用 Pod 规约中的spec.affinity.podAntiAffinity 字段。

apiVersion: v1
kind: Pod
metadata:
  name: redis
  labels:
    app: redis
spec:
  containers:
    - name: redis
      image: redis:5.0.10
      imagePullPolicy: IfNotPresent
  restartPolicy: Always
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        # 更确切的说,调度器必须将 Pod 调度到具有 cpu 标签的节点上,并且集群中至少有一个位于该可用区的节点上运行着带有 app=nginx 标签的 Pod。
        - topologyKey: cpu
          labelSelector:
            matchExpressions:
              - key: app
                operator: In
                values:
                  - nginx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  • pod 间亲和性权重
apiVersion: v1
kind: Pod
metadata:
  name: redis
  labels:
    app: redis
spec:
  containers:
    - name: redis
      image: redis:5.0.10
      imagePullPolicy: IfNotPresent
  restartPolicy: Always
  affinity:
    podAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
        # 更确切的说,调度器必须将 Pod 调度到具有 cpu 标签的节点上,并且集群中至少有一个位于该可用区的节点上运行着带有 app=nginx 标签的 Pod。
        - podAffinityTerm:
            topologyKey: cpu
            labelSelector:
              matchExpressions:
                - key: app
                  operator: In
                  values:
                    - nginx
          weight: 1
        - podAffinityTerm:
            topologyKey: cpu
            labelSelector:
              matchExpressions:
                - key: app
                  operator: In
                  values:
                    - web
          weight: 30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

# 9.7 污点和容忍度

官网参考: http://kubernetes.p2hp.com/docs/concepts/scheduling-eviction/taint-and-toleration.html (opens new window)

节点亲和性 是 Pod 的一种属性,它使 Pod 被吸引到一类特定的节点 (这可能出于一种偏好,也可能是硬性要求)。 污点(Taint) 则相反——它使节点能够排斥一类特定的 Pod。

容忍度(Toleration)是应用于 Pod 上的。容忍度允许调度器调度带有对应污点的 Pod。 容忍度允许调度但并不保证调度:作为其功能的一部分,调度器也会评估其他参数。

污点和容忍度(Toleration)相互配合,可以用来避免 Pod 被分配到不合适的节点上。 每个节点上都可以应用一个或多个污点, 这表示对于那些不能容忍这些污点的 Pod, 是不会被该节点接受的。

# 9.8 Pod 拓扑分布约束

官网参考: http://kubernetes.p2hp.com/docs/concepts/scheduling-eviction/topology-spread-constraints/ (opens new window)

#K8s#Pod
最近更新: 2025/04/11, 14:29:15
Kubernetes 组件&架构
Kubernetes Controller 控制器

← Kubernetes 组件&架构 Kubernetes Controller 控制器→

最近更新
01
Kubernetes Helm
04-11
02
Kubernetets Namespace
04-11
03
Kubernetes Ingress
04-11
更多文章>
Theme by Vdoing | Copyright © 2021-2025 光年矩阵科技有限公司 | All Rights Reserved. |
渝ICP备2021888888号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×