Skip to content

资源调度

Label & Selector

在Kubernetes中,Label是键值对形式的元数据,可以附加到各种资源对象上,比如Pod、Service、Deployment等。这些Label可以用来对资源对象进行分类、组织和标记,从而方便管理和操作。

Label Selector则是一种查询语法,用于根据Label的键值对来选择匹配的资源对象。它可以在各种场景下使用,比如查找特定类型的Pod、服务发现、负载均衡等。通过Label Selector,可以方便地根据需要选择和操作资源对象,实现灵活的资源管理和控制。

命令

shell
# 创建临时label,永久修改可以通过edit
kubectl label po <po> app=hello -n <ns>

# 获取label
kubectl label po--show-labels

# 根据标签去匹配pod
kubectl get po -l type=app
kubectl get po -l 'version in (1.1.0, 1.0.0)'
kubectl get po -l version!=1.1.0,type=app
# 使用逻辑运算符 OR:
kubectl get pods -l 'key1=value1' -o 'key2=value2'

基本操作

Label Selector 通常由以下几种表达式组成:

  1. 等式(Equality): 使用等式操作符(=)来匹配指定键值对的标签。例如,app=nginx 表示选择具有标签 app,其值为 nginx 的资源对象。
  2. 集合匹配(Set-based Matching): 使用集合操作符(in、notin、exists、does not exist)来匹配指定标签的值。例如,environment in (production, staging) 表示选择具有标签 environment,其值为 production 或 staging 的资源对象。
  3. 按键过滤(Key Filtering): 使用键过滤操作符(!=、!)来匹配指定键的资源对象。例如,app!=nginx 表示选择具有标签 app,但其值不为 nginx 的资源对象。
  4. 逻辑运算(Logical Operators): 使用逻辑操作符(AND、OR、NOT)来组合多个标签选择器。例如,app=nginx, environment=production 表示选择具有标签 app 值为 nginx 且具有标签 environment 值为 production 的资源对象。

以下是一些使用 Label Selector 的示例:

  • 选择具有标签 app=nginx 的 Pod:
yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx
  • 选择具有标签 environment 值为 production 或 staging 的 Service:
yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
    environment: 
      in: [production, staging]
  • 选择具有标签 tier 值为 backend 但没有标签 app 的 Deployment:
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend-deployment
spec:
  selector:
    matchLabels:
      tier: backend
  matchExpressions:
  - {key: app, operator: DoesNotExist}

Deployment

在 Kubernetes 中,Deployment、ReplicaSet(简称 RS)和 Pod 之间存在一种关系,它们通常是这样关联的:

  1. Deployment:Deployment 是一个高级别的资源对象,用于管理应用程序的部署和更新。它负责定义所需的 Pod 模板和副本数目,并控制 RS 的创建、更新和删除过程。
  2. ReplicaSet:ReplicaSet 是一个控制器对象,用于确保指定数量的 Pod 副本在集群中运行。Deployment 通常会创建一个或多个 ReplicaSet,并使用 ReplicaSet 来管理 Pod 的生命周期。当 Deployment 进行滚动更新或扩缩容时,它会通过创建新的 ReplicaSet、逐步删除旧的 ReplicaSet 来实现更新和调整副本数目。
  3. Pod:Pod 是 Kubernetes 中最小的部署单元,它可以包含一个或多个容器,并共享相同的网络命名空间、存储卷和 IP 地址。ReplicaSet 负责创建和管理一组相同配置的 Pod 副本,确保它们按照预期的副本数目运行在集群中。

简单来说,Deployment 使用 ReplicaSet 来管理 Pod 的副本数目和生命周期。当需要更新应用程序时,Deployment 会创建一个新的 ReplicaSet,并逐步替换旧的 ReplicaSet 中的 Pod。这种方式可以实现应用程序的滚动更新,并保证在更新过程中不会中断服务。

创建

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment  # 部署的名称
spec:
  replicas: 3  # 副本数
  hostNetwork: true # 是否使用主机网络
  selector:
    matchLabels:
      app: nginx  # 选择器,用于选择部署的 Pod
  strategy:
    type: RollingUpdate  # 滚动更新策略类型
    rollingUpdate:
      maxSurge: 1  # 最大超出副本数
      maxUnavailable: 1  # 最大不可用副本数
  template:  # Pod 模板
    metadata:
      labels:
        app: nginx  # Pod 的标签
    spec:
      containers:
      - name: nginx
        image: nginx:latest  # 使用的镜像
        ports:
        - containerPort: 80  # 容器监听端口
        resources:
          limits:
            cpu: "1"
            memory: "1Gi"
            storage: "1Gi"
            network: "1Mbps"
            gpu: "1"
          requests:
            cpu: "0.5"
            memory: "512Mi"
            storage: "512Mi"
            network: "512Kbps"
            gpu: "0.5"
  revisionHistoryLimit: 5  # 保留的历史版本数量

滚动更新

滚动更新是 Kubernetes 中一种更新 Deployment 的策略,它允许你在不中断服务的情况下逐步更新应用程序的实例。滚动更新的步骤如下:

  1. Kubernetes 更新 Deployment 的 Pod 模板:通过修改 Deployment 中的 Pod 模板,例如更改容器的镜像版本或配置。
  2. Kubernetes 创建新的 ReplicaSet:一旦 Deployment 的 Pod 模板被更新,Kubernetes 将创建一个新的 ReplicaSet,该 ReplicaSet 包含根据新 Pod 模板创建的 Pod。
  3. Kubernetes 逐步调整实例数:Kubernetes 会逐步增加新 ReplicaSet 中 Pod 的数量,同时减少旧 ReplicaSet 中 Pod 的数量,以确保整个应用程序的实例数保持稳定。这确保了在更新期间服务的稳定性。
  4. Kubernetes 删除旧的 ReplicaSet:一旦新 ReplicaSet 中的 Pod 数量达到预期数量,并且旧 ReplicaSet 中的 Pod 数量减少到零,Kubernetes 将删除旧 ReplicaSet。

查看滚动更新信息

shell
kubectl rollout status deploy nginx-deployment

回滚

要回滚 Kubernetes 中的 Deployment,你可以使用以下命令:

shell
kubectl rollout undo deployment <deployment-name>

这会将指定 Deployment 的当前版本回滚到之前的版本。Kubernetes 会自动处理回滚,并且在回滚完成后,新的 Pod 会逐步替换掉旧的 Pod,直到回滚完成。

你也可以使用 --to-revision 标志来指定要回滚到的特定版本,例如:

shell
kubectl rollout undo deployment <deployment-name> --to-revision=<revision>

这将指定 Deployment 回滚到指定的修订版本号。

回滚完成后,你可以使用以下命令查看回滚历史:

shell
kubectl rollout history deployment <deployment-name>

扩容和缩容

  1. 扩容: 使用以下命令将 Deployment 扩容到指定的副本数量:
shell
kubectl scale deployment <deployment-name> --replicas=<desired-replicas>

其中,<deployment-name> 是要扩容的 Deployment 的名称,<desired-replicas> 是要设置的目标副本数量。

  1. 缩容: 使用以下命令将 Deployment 缩容到指定的副本数量:
shell
kubectl scale deployment <deployment-name> --replicas=<desired-replicas>

同样地,<deployment-name> 是要缩容的 Deployment 的名称,<desired-replicas> 是要设置的目标副本数量。

暂停与恢复

shell
kubectl rollout pause deployment <deployment-name>
shell
kubectl rollout resume deployment <deployment-name>

StatefulSet

StatefulSet 是 Kubernetes 中用于管理有状态应用程序的控制器。与 Deployment 不同,StatefulSet 给每个 Pod 分配一个稳定的标识符(通常是序号),并确保每个 Pod 的网络标识符、存储和其他属性在 Pod 重启和迁移时保持不变。

StatefulSet 主要用于运行需要持久化存储或唯一网络标识符的应用程序,如数据库(例如 MySQL、PostgreSQL)、分布式消息队列(例如 Kafka)或其他需要唯一标识符的应用程序。

StatefulSet 与 Deployment 相似,但有几个关键区别:

  1. Pod 的名称:StatefulSet 控制的 Pod 的名称包含了一个有序的索引,例如 pod-name-0、pod-name-1 等。
  2. 稳定标识符:StatefulSet 为每个 Pod 提供一个唯一的稳定标识符,如 hostname。
  3. 网络标识符:StatefulSet 为每个 Pod 提供一个唯一的网络标识符,可用于服务发现和 DNS 查询。
  4. 持久化标识符:StatefulSet 支持动态卷配置,可以确保每个 Pod 在重启和迁移时都能够保留相同的持久化存储。

StatefulSet 在需要管理有状态应用程序的场景下非常有用,它确保了应用程序的稳定性和可靠性,并提供了对有状态应用程序的良好支持。

定义

yaml
apiVersion: apps/v1  # 使用的 Kubernetes API 版本
kind: StatefulSet  # 定义的 Kubernetes 资源类型
metadata:
  name: example-statefulset  # StatefulSet 的名称
spec:
  replicas: 3  # 副本数量
  serviceName: "example-service"  # 关联的服务名称
  selector:  # 选择器,用于匹配 Pod
    matchLabels:  # 匹配的标签
      app: example  # app 标签的值为 example
  template:  # Pod 模板
    metadata:
      labels:
        app: example  # Pod 的标签
    spec:  # Pod 的规格
      containers:  # 容器列表
      - name: nginx  # 容器名称
        image: nginx:1.7.9  # 容器使用的镜像
        ports:  # 容器暴露的端口
        - containerPort: 80  # 端口号为 80
          name: web  # 端口名称为 web
        volumeMounts:  # 挂载的卷
        - name: www  # 卷的名称
          mountPath: /usr/share/nginx/html/  # 挂载路径
  volumeClaimTemplates:  # 卷声明模板
  - metadata:
      name: www  # 卷声明的名称
      annotations:  # 注释
        volume.alpha.kubernetes.io/storage-class: anything  # 存储类注释
    spec:  # 卷声明的规格
      accessModes: ["ReadWriteOnce"]  # 访问模式
      resources:  # 资源请求
        requests:
          storage: 1Gi  # 存储容量

扩容缩容与滚动更新

会按顺序更新

更新image需要通过patch命令

发布与删除

  1. 灰度发布:

    • 通过逐步更新 StatefulSet 中的 Pod 实例来实现灰度发布。您可以先更新一部分 Pod,然后观察它们的行为,如果没有问题,则继续更新其他 Pod。
    • 您可以使用 StatefulSet 的 updateStrategy 字段来控制 Pod 的更新策略,例如 OnDelete 策略会等待所有 Pod 删除后再更新,而 RollingUpdate 策略会逐步更新 Pod。
  2. 金丝雀发布:

    • 类似于灰度发布,您可以先更新一小部分 Pod 实例,然后观察它们的行为和性能。如果一切正常,可以逐步增加更新的 Pod 实例数量。
    • 使用 StatefulSet 的 updateStrategy 字段,结合适当的标签选择器和选择条件,可以实现金丝雀发布。通过逐步更新匹配特定标签的 Pod 实例,您可以控制新版本的逐步部署。
  3. Partition 属性:Partition 属性是 StatefulSet 对象的一个字段,它确定了更新时受影响的 Pod 子集。当您将 partition 属性设置为一个非零值时,StatefulSet 将只更新具有比该值小的索引的 Pod。这允许您以分批的方式更新 Pod,从而实现灰度发布。

  4. 灰度发布策略:通过逐步增加 partition 的值,您可以控制更新的 Pod 数量。例如,将 partition 设置为 1 将更新索引小于 1 的 Pod,将 partition 设置为 2 将更新索引小于 2 的 Pod,依此类推。逐步增加 partition 可以逐步扩大更新范围,实现灰度发布。

  5. 全部更新:如果您希望更新全部的 Pod,可以将 partition 属性设置为 0,这将影响所有 Pod 并触发它们的滚动更新。

onDelete

onDelete 策略类型:onDelete 策略有两种类型:

  • Delete:表示在删除 StatefulSet 对象时,Pod 将被删除,并且 StatefulSet 控制器不会自动创建替代的 Pod。这意味着一旦删除了 StatefulSet,相关的 Pod 将被永久删除。
  • Orphan:表示在删除 StatefulSet 对象时,Pod 将被“放逐”而不是立即删除。被放逐的 Pod 不再受 StatefulSet 控制,但它们仍然存在于集群中。这允许您手动处理这些 Pod,例如将它们重新分配到其他控制器。

级联删除与非级联删除

StatefulSet 的级联删除与非级联删除与一般资源的概念类似,但是有一些特定的注意事项:

  1. 级联删除:
    • 在删除 StatefulSet 时,默认情况下会执行级联删除,这意味着与 StatefulSet 相关的所有 Pod 和持久卷声明 (PVC) 也会被删除。
    • 该操作将删除 StatefulSet 的所有实例,以及它们对应的网络标识符、持久化存储和其他相关资源。
    • 级联删除适用于在删除 StatefulSet 时希望清理所有相关资源的场景。
  2. 非级联删除:
    • 非级联删除将仅删除 StatefulSet 本身,而不会影响与其相关的 Pod 和 PVC。
    • 这意味着 StatefulSet 的 Pod 将继续运行,并且与它们的网络标识符和持久化存储保持连接,即使 StatefulSet 自身已被删除。
    • 非级联删除通常用于确保 StatefulSet 的实例持续运行,即使 StatefulSet 资源本身不再存在。

在 Kubernetes 中,您可以通过在删除资源时设置 --cascade=false 选项来执行非级联删除,例如:

bash
kubectl delete statefulset <statefulset-name> --cascade=false

主要命令

  1. 创建 StatefulSet:
bash
kubectl create -f <statefulset-definition.yaml>
  1. 查看 StatefulSet:
bash
kubectl get sts
  1. 查看详细信息:
bash
kubectl describe sts <statefulset-name>
  1. 更新 StatefulSet:
bash
kubectl apply -f <updated-statefulset-definition.yaml>
  1. 删除 StatefulSet:
bash
kubectl delete sts <statefulset-name>
  1. 扩容或缩容:
bash
kubectl scale sts <statefulset-name> --replicas=<new-replica-count>
  1. 滚动更新:
bash
kubectl rollout status sts <statefulset-name>
  1. 回滚到先前的版本:
bash
kubectl rollout undo sts <statefulset-name>

DaemonSet

  1. 每个节点一个 Pod:
    • DaemonSet 会在集群中的每个节点上创建一个 Pod 的副本,确保每个节点都运行指定的应用程序或服务。
    • 当有新的节点加入集群时,DaemonSet 会自动在新节点上创建 Pod,以确保集群中每个节点的运行环境都是一致的。
  2. 滚动更新:
    • 类似于其他控制器,DaemonSet 支持滚动更新功能,可以在更新 DaemonSet 时逐步替换现有的 Pod 实例,以避免影响集群的稳定性。
  3. 节点调度:
    • DaemonSet 可以根据节点的标签选择器来确定在哪些节点上运行 Pod 实例。
    • 通过节点选择器,可以灵活地控制 DaemonSet 在哪些节点上运行 Pod,从而满足不同节点的资源需求或特定的部署策略。
  4. 应用场景:
    • DaemonSet 适用于需要在每个节点上运行的服务或应用程序,例如日志收集代理、监控代理、网络代理等。
    • 它还常用于在整个集群中部署辅助工具,如存储卷插件、容器网络插件等。
  5. 自动调整:
    • 通过 Kubernetes 的自动调度和自愈机制,DaemonSet 可以确保在节点故障或不可用时自动重新调度 Pod 实例,以保证系统的高可用性和稳定性。

日志收集

Fluentd

yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd
  namespace: kube-system
spec:
  selector:
    matchLabels:
      app: fluentd
  template:
    metadata:
      labels:
        app: fluentd
    spec:
      serviceAccount: fluentd
      containers:
      - name: fluentd
        image: agilestacks/fluentd-elasticsearch:v1.3.0
        volumeMounts:
        - name: containers
          mountPath: /var/lib/docker/containers
        - name: varlog
          mountPath: /varlog
      volumes:
      - hostPath:
          path: /var/lib/docker/containers
        name: containers
      - hostPath: 
          path: /var/log
        name: varlog

指定部署节点

在 DaemonSet 中指定节点部署有几种方法:

  1. nodeSelector: 使用 nodeSelector 字段可以指定一个或多个节点标签,以确保 DaemonSet 的 Pod 仅部署到具有匹配标签的节点上。
yaml
spec:
  template:
    spec:
      nodeSelector:
        disk: ssd
  1. affinity/anti-affinity: 使用 affinity 字段可以根据节点的亲和性或反亲和性进行部署。亲和性可确保一组 Pod 在同一节点上部署,而反亲和性则确保一组 Pod 在不同的节点上部署。
yaml
spec:
  template:
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: disk
                operator: In
                values:
                - ssd
  1. nodeSelectorTerms: 在 nodeAffinity 字段中,nodeSelectorTerms 允许您指定多个节点选择器条件。这样可以更灵活地控制 DaemonSet 的 Pod 部署。
yaml
spec:
  template:
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: disk
                operator: In
                values:
                - ssd
            - matchExpressions:
              - key: gpu
                operator: Exists

更新策略

推荐使用OnDelete

HPA

metrics

top本身不可用,需要安装这个命令才可以使用

在使用 Horizontal Pod Autoscaler (HPA) 之前,您需要确保您的 Kubernetes 集群中已经配置了支持 HPA 所需的度量指标(metrics)。常见的度量指标包括 CPU 利用率和内存利用率。

HPA 支持以下两种类型的度量指标:

  1. Resource Metrics:资源度量指标是关于 Pod 的资源使用情况,例如 CPU 利用率和内存利用率。这些度量指标由 Kubernetes 监控系统(如 metrics-server)提供。
  2. Custom Metrics:自定义度量指标是您可以根据自己的需求定义的度量指标,例如队列长度、请求速率等。这些度量指标由您自己的监控系统提供,并且需要安装和配置相应的监控适配器,例如 Prometheus 适配器。
shell
wget https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml -O metrics-server-components.yaml

sed -i "s/k8s.gcr.ioVmetrics-server/registry.cn-hangzhou.aliyuncs.comVgoogle_containers/g' metrics-server-components.yaml

# 去除HTTPS 配置
在containers里面添加
# - --kubelet-insecure-tls

使用

Horizontal Pod Autoscaler(HPA)是 Kubernetes 中的一种资源,用于根据 CPU 使用率或自定义指标自动调整 Pod 的副本数量,以适应应用程序的负载变化。以下是一个简单的 HPA 的 YAML 示例:

yaml
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: my-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-deployment
  minReplicas: 1
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      targetAverageUtilization: 50

这个 HPA 的 YAML 文件描述了一个 HorizontalPodAutoscaler 资源,它会自动调整名为 my-deployment 的 Deployment 中 Pod 的副本数量。

  • scaleTargetRef: 指定了要自动扩展的 Deployment 的引用。
  • minReplicas 和 maxReplicas: 指定了 Pod 副本数量的最小值和最大值。
  • metrics: 指定了用于自动扩展的指标。
    • type: Resource: 表示使用资源指标(例如 CPU 使用率)进行自动扩展。
    • resource.name: cpu: 指定了使用 CPU 使用率作为自动扩展的指标。
    • resource.targetAverageUtilization: 50: 指定了目标平均 CPU 利用率为 50%,当 CPU 利用率超过此阈值时,HPA 将增加 Pod 的副本数量。

这个示例中的 HPA 会监视名为 my-deployment 的 Deployment 中 Pod 的 CPU 使用率,并在 CPU 使用率超过 50% 时增加 Pod 的副本数量,最多不超过 10 个,最少不少于 1 个。

shell
kubectl autoscale deployment <deployment-name> --cpu-percent=80 --min=1 --max=10

Job

Job 负责确保 Pod 成功运行完成(成功退出代码 0),适合一次性任务,比如数据库初始化、日志分析等。 与Deployment 不同的是,Job 不会自动重启 Pod,当 Pod 退出时,Job 会自动删除 Pod。 Deployment 维护长期运行的服务(不断重启),而 Job 只负责运行一次并成功退出的任务。

  • 一次性任务:数据库迁移、批处理脚本
  • 异步任务:用户上传处理、模型训练
  • 定期运行:结合 CronJob 使用
  • 大规模并发任务(MapReduce 类似)

使用

yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: example-job
spec:
  template:
    spec:
      containers:
      - name: pi
        image: perl
        command: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(2000)"]
      restartPolicy: Never

控制 Job 行为的参数

参数说明
completions完成任务所需的 Pod 次数(默认 1)
parallelism同时运行的 Pod 数量(默认 1)
backoffLimit失败重试次数(默认 6)
activeDeadlineSeconds最长运行时间
ttlSecondsAfterFinishedJob 完成后保留多久再清理资源(支持自动清理)

Job 类型

类型场景特点
普通 Job一次性执行任务最常见
Parallel Job多任务并行执行使用 completionsparallelism 控制
Indexed Job有编号的任务使用 completionMode: Indexed,用于任务分片
CronJob定时任务类似 Linux 的 cron,生成 Job

Job 的状态和排错

状态字段含义
status.succeeded成功完成的 Pod 数量
status.failed失败的 Pod 次数
kubectl describe job查看 Job 控制器行为
kubectl logs pod-name查看 Pod 输出

最佳实践

  • 设置 ttlSecondsAfterFinished,自动清理资源
  • 合理设置 backoffLimit 和 activeDeadlineSeconds
  • 使用 Resource Limit,避免批处理任务消耗过多资源
  • 对大规模并发任务使用 Indexed Job 做任务分片处理
  • Job 中不要使用 restartPolicy: Always

CronJob

CronJob 会在指定时间创建一个或多个 Job。 每次调度都会生成一个新的 Job 实例(Job controller 来管理)。 适合做定时清理、定时备份、周期性同步、定时上报等任务。

  • 日志归档:定时清理旧日志文件
  • 数据备份:每天/每周备份数据库、对象存储
  • 数据同步:定时从外部源拉取/推送数据
  • 模型训练调度:每晚训练模型、更新指标
  • 健康检测:定时调用内外部服务健康检查并上报

使用

yaml
apiVersion: batch/v1
kind: CronJob
metadata:
  name: hello-cron
spec:
  schedule: "*/5 * * * *"    # 每5分钟执行一次
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: hello
            image: busybox
            args:
            - /bin/sh
            - -c
            - date; echo Hello from the Kubernetes CronJob!
          restartPolicy: OnFailure
字段说明
schedule定时规则(Cron 表达式)
jobTemplateJob 模板,与普通 Job 一样
startingDeadlineSeconds最大延迟时间,超出则不执行
concurrencyPolicyAllow 允许多个并发执行(默认);
Forbid 禁止并发,前一个未完成则跳过当前调度;
Replace 杀掉上一个未完成的 Job,执行新的 ;
successfulJobsHistoryLimit成功 Job 保留数量(默认 3)
failedJobsHistoryLimit失败 Job 保留数量(默认 1)
suspend设置为 true 可暂停调度

最佳实践

  • 避免执行时间太短的任务(调度开销大)
  • Job 的运行时间不应超过 schedule 间隔
  • 设置好 concurrencyPolicy 避免重复执行
  • 使用 ttlSecondsAfterFinished 清理 Job
  • 为任务配置资源限制和失败重试
  • 保留 successfulJobsHistoryLimit 和 failedJobsHistoryLimit 以便追踪日志

InitC

在 Kubernetes 中,Init 容器是在主业务容器(app container)启动之前运行的容器,用于执行一些预处理或准备任务。 它们和普通容器一样定义镜像、命令、挂载等,但只能 顺序运行,所有 Init 容器完成后,主容器才会启动。

作用

  • 依赖检查:等待数据库、缓存服务等就绪
  • 文件准备:拷贝配置文件或初始化数据
  • 权限设定:设置挂载目录的权限
  • 等待条件满足:使用 nslookup、curl 等工具等待某服务可用

使用

yaml
apiVersion: v1
kind: Pod
metadata:
  name: init-demo
spec:
  initContainers:
  - name: init-myservice
    image: busybox
    command: ['sh', '-c', 'until nslookup myservice; do echo waiting; sleep 2; done;']
  containers:
  - name: main-app
    image: busybox
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  1. initContainer 依次执行。
  2. 每个 initContainer 必须 成功(退出码 0),下一个才能运行。
  3. 所有 init 容器执行完成后,Pod 中的主容器(containers)开始启动。

污点和容忍(Taints and Tolerations)

概念

  • 污点(Taint):施加在节点上的标记,用于“驱逐”不满足条件的 Pod,使得这些 Pod 不能调度到该节点上。
  • 容忍(Toleration):Pod 对污点的“容忍”声明,表示该 Pod 可以被调度到带有相应污点的节点上。

作用

  • 通过污点和容忍机制,Kubernetes 实现节点对 Pod 调度的过滤与控制。
  • 防止某些 Pod 被调度到不适合的节点。
  • 实现节点隔离、资源预留、专用节点等场景。

机制说明

  • 节点可以有多个污点,每个污点包含 key=value:effect,其中 effect 有三种类型:

    • NoSchedule:不允许 Pod 调度到此节点,除非 Pod 有对应容忍。
    • PreferNoSchedule:尽量避免调度,但不强制。
    • NoExecute:驱逐节点上不容忍该污点的 Pod,并且后续不允许调度。
  • Pod 通过添加容忍,声明可以容忍特定的污点。

示例

给节点打污点:

bash
kubectl taint nodes node1 key=value:NoSchedule

Pod 添加容忍:

yaml
tolerations:
- key: "key"
  operator: "Equal"
  value: "value"
  effect: "NoSchedule"

亲和力(Affinity)

概念

  • 亲和力用于定义 Pod 在节点上的调度偏好和约束,主要有两种:

    • 节点亲和力(Node Affinity):指定 Pod 需要调度到符合特定标签的节点。
    • Pod 亲和力/反亲和力(Pod Affinity/AntiAffinity):指定 Pod 与其他 Pod 的共存或避让规则。

作用

  • 实现更灵活的调度策略。
  • 优化资源利用、提高可用性。
  • 实现 Pod 之间的协同或隔离。

节点亲和力

  • 类似污点/容忍,但更细粒度。
  • 支持“必须(requiredDuringSchedulingIgnoredDuringExecution)”和“优选(preferredDuringSchedulingIgnoredDuringExecution)”两种规则。

示例:调度到带有 disktype=ssd 标签的节点

yaml
affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
      - matchExpressions:
        - key: disktype
          operator: In
          values:
          - ssd

Pod 亲和力与反亲和力

  • Pod 亲和力:要求新 Pod 与已有 Pod 在同一节点或同一区域。
  • Pod 反亲和力:要求新 Pod 不和某些 Pod 在同一节点或同一区域。

示例:Pod 反亲和力,避免和标签为 app=web 的 Pod 在同一节点

yaml
affinity:
  podAntiAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
    - labelSelector:
        matchExpressions:
        - key: app
          operator: In
          values:
          - web
      topologyKey: "kubernetes.io/hostname"