11. Kubernetes进阶篇-高级调度

定时任务&任务

简介

什么是CronJob

CronJob是一个用于运行定时任务的API对象。
它允许定义一个或多个作业,这些作业将按照预定的时间间隔(如每分钟、每小时、每天等)在Kubernetes集群中执行。
CronJob可以用来执行批处理任务、备份、日志收集、报告生成等操作。

CronJob关键点

  1. 定时调度:CronJob使用标准的Cron表达式来定义作业的调度规则,这使得您可以轻松地指定作业何时运行。
  2. 可重试和可回滚:CronJob允许您设置作业的重试策略,当作业失败时,它将按照预定的次数尝试重新运行。此外,如果作业失败,您可以回滚到之前成功的版本。
  3. 灵活性:CronJob支持多种工作负载,包括Deployment、Job、DaemonSet等,您可以根据需要选择合适的工作负载类型。
  4. 资源限制:您可以为CronJob设置资源限制,以确保作业不会消耗过多的集群资源。
  5. 持久化存储:CronJob支持持久化存储,可以将作业的结果、中间数据或输出存储在PersistentVolume上。

注意:CronJob被调用的时间,是用的Controller-Manager的时间。如果Controller-Manager是容器部署的,需要注意与宿主机时间一致。

什么是Job

Job是一种API对象,用于执行一次性的工作负载,直到所有的工作单元(Pods)都成功完成。
每个Job都有一个期望的结果,通常是成功运行所有的工作单元。
一旦Job完成,它就不会再次执行,除非手动重新创建它。

Job关键点

  1. 一次性任务:Job旨在执行一次性任务,例如数据迁移、批处理作业或任何需要一次性处理大量数据的操作。
  2. 期望的结果:Job可以指定它期望的结果,例如成功完成所有的工作单元或至少完成一个工作单元。这有助于定义Job的成功条件。
  3. Pod模板:Job使用Pod模板来定义执行任务的工作单元。您可以定义Pod的镜像、资源请求、命令和环境变量等。
  4. 资源限制:您可以为Job设置资源限制,以确保Job不会消耗过多的集群资源。
  5. 持久化存储:Job支持持久化存储,可以将工作单元的结果、中间数据或输出存储在PersistentVolume上。
  6. 支持多种工作负载类型:Job可以与多种工作负载类型一起使用,例如Deployment、DaemonSet等。

CronJob&Job的时间语法

# ┌───────────── 分钟 (0 - 59)
# │ ┌───────────── 小时 (0 - 23)
# │ │ ┌───────────── 月的某天 (1 - 31)
# │ │ │ ┌───────────── 月份 (1 - 12)
# │ │ │ │ ┌───────────── 周的某天 (0 - 6)(周日到周一;在某些系统上,7 也是星期日)
# │ │ │ │ │                          或者是 sun,mon,tue,web,thu,fri,sat
# │ │ │ │ │
# │ │ │ │ │
# * * * * *

创建

创建CronJob

  • 编辑yaml
apiVersion: batch/v1beta1
kind: CronJob                                                                             #定义资源的类型为CronJob。
metadata:
  name: cronjob-hello                                                                     #CronJob的名称。
  namespace: default
  labels:
    app: cronjob-hello                                                                    #一个自定义标签,可用于筛选或关联资源。

spec:                                                                                     #CronJob的规格说明。
  jobTemplate:                                                                            #定义了CronJob的Job模板。
    spec:                                                                                 #定义了Job的规格。
      template:                                                                           #定义了Pod的模板。
        spec:                                                                             #定义了Pod的规格。
          schedulerName: crontab-echo-hello                                               #指定用于调度这个Job的调度器名称。
          terminationGracePeriodSeconds: 30                                               #设置Pod终止前的等待时间。
          containers:                                                                     #定义了Pod中的容器。
            - name: busybox                                                               #容器的名称。
              image: registry.cn-beijing.aliyuncs.com/publicspaces/busybox:1.28.0         #容器的镜像。
              imagePullPolicy: IfNotPresent                                               #容器镜像的拉取策略。
              args:
                - /bin/sh
                - -c
                - echo Hello-$(date +%F-%H-%M-%S) > /tmp/test/echo.txt; echo Hello-$(date +%F-%H-%M-%S)
              volumeMounts:
                - mountPath: /tmp/test/
                  name: volume-hostpath
              terminationMessagePath: /usr/local/                                         #定义了Pod终止时,终止消息写入的路径
              terminationMessagePolicy: File                                              #定义了Pod终止时,终止消息的策略
          volumes:
            - name: volume-hostpath
              hostPath:
                path: /data/dir/data/
          restartPolicy: OnFailure                                                        #定义了Pod失败后的重启策略。
  schedule: 0/1 * * * *                                                                   #定义了CronJob的调度规则,Cron表达式0/1 * * * *,表示每分钟执行一次
  concurrencyPolicy: Allow                                                                #定义了CronJob如何处理并发运行的作业。这里设置为Allow,表示允许并发运行作业。
  failedJobsHistoryLimit: 10                                                              #定义了CronJob失败的最大历史作业数。这里设置为10,意味着CronJob失败后最多保留10个历史作业。
  successfulJobsHistoryLimit: 10                                                          #定义了CronJob成功完成的最大历史作业数。这里设置为10,意味着CronJob成功完成后最多保留10个历史作业。
  suspend: false                                                                          #如果设置为true,CronJob将暂停执行。这里设置为false,表示CronJob将继续执行。
  • 创建CronJob
kubectl create -f cronjob-busybox-hello.yaml
  • 查看CronJob
kubectl get cj
# NAME            SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
# cronjob-hello   0/1 * * * *   False     5        20s             9m16s
  • 验证CronJob
cat /data/dir/data/echo.txt
# hello_2024-07-19-07-26-07

kubectl logs cronjob-hello-1721373960-vddbs 
# hello_2024-07-19-07-26-07
  • 作业策略
    • Allow:允许并发运行作业,这是默认值。
    • Forbid:禁止并发运行作业,如果CronJob正在运行,新创建的作业将被拒绝。
    • Replace:如果CronJob正在运行,新创建的作业将替换现有的作业。
    • AllowUntilTime:允许并发运行作业,直到指定的时间点。

创建Job

  • 编辑yaml
apiVersion: batch/v1
kind: Job                                                                                               #定义资源的类型为Job。
metadata:
  name: job-hello                                                                                       #Job的名称。
  namespace: default
  labels:
    app: job-hello                                                                                      #一个自定义标签,可用于筛选或关联资源。

spec:                                                                                                   #Job的规格说明。
  template:                                                                                             #定义了Job的Pod模板。
    metadata:
      name: job-hello-pod                                                                               #Pod的名称。
      labels:
        app: job-hello-pod
    spec:                                                                                               #定义了Pod的规格。
      containers:
        - name: busybox
          imagePullPolicy: IfNotPresent
          image: registry.cn-beijing.aliyuncs.com/publicspaces/busybox:1.28.0
          command:
            - sh
            - -c
            - echo Hello-$(date +%F-%H-%M-%S) > /tmp/test/echo.txt; echo Hello-$(date +%F-%H-%M-%S)
          volumeMounts:
            - mountPath: /tmp/test/                                                                     #定义了容器挂载的卷。
              name: volume-hostpath                                                                     #关联的卷名称。
      volumes:                                                                                          #定义了Pod使用的卷。
        - name: volume-hostpath                                                                         #卷的名称。
          hostPath:                                                                                     #定义了宿主机的路径。
            path: /data/dir/data/
      restartPolicy: OnFailure                                                                          #定义了Pod失败后的重启策略。这里设置为OnFailure,意味着如果容器失败,Pod将被重启。
  • 创建Job
kubectl create -f job-busybox-hello.yaml
  • 查看Job
kubectl get job
# NAME        COMPLETIONS   DURATION   AGE
# job-hello   1/1           1s         4m45s
  • 验证Job
kubectl logs job-hello-qqgvl 
# Hello-2024-07-19-07-36-04

cat /data/dir/data/echo.txt 
# Hello-2024-07-19-07-36-04

应用

CronJob应用案例–定时备份Nginx日志

Deployment和CronJob基于同一NFS共享目录下实现日志备份。

  • 编辑Nginx的Deployment创建文件
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-nginx
  namespace: default
  labels:
    app: deployment-nginx

spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: registry.cn-beijing.aliyuncs.com/publicspaces/nginx:1.22.1
          imagePullPolicy: IfNotPresent
          volumeMounts:
            - mountPath: /var/log/nginx/
              name: nfs-volume
      volumes:
        - name: nfs-volume
          nfs:
            path: /data/nfs/data
            server: 192.168.23.138
      restartPolicy: Always
  replicas: 3
  • 创建Nginx
kubectl create -f nginx-deployment-nfs.yaml
  • 检查Nginx的运行情况
kubectl get deployments.apps 
# NAME               READY   UP-TO-DATE   AVAILABLE   AGE
# deployment-nginx   3/3     3            3           2m28s

kubectl get pod
# NAME                                READY   STATUS    RESTARTS   AGE
# deployment-nginx-7fb95dccf9-8rmr2   1/1     Running   0          2m15s
# deployment-nginx-7fb95dccf9-fd9rh   1/1     Running   0          2m15s
# deployment-nginx-7fb95dccf9-w5j2r   1/1     Running   0          2m15s
  • 编辑周期性CronJob备份Nginx日志
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: cronjob-nginx-logs
  namespace: default
  labels:
    app: cronjob-nginx-logs

spec:
  jobTemplate:
    spec:
      template:
        spec:
          containers:
            - name: nginx-logs-backup
              imagePullPolicy: IfNotPresent
              image: registry.cn-beijing.aliyuncs.com/publicspaces/busybox:1.28.0
              command:
                - sh
                - -c
                - tar -czf /tmp/nginx/logs/nginx-logs_$(date +%F-%H-%M-%S).tgz /tmp/nginx/logs/*.log; echo "备份完成,备份时间:date +%F-%H-%M-%S"
              volumeMounts:
                - mountPath: /tmp/nginx/logs/
                  name: nfs-volume
          volumes:
            - name: nfs-volume
              nfs:
                path: /data/nfs/data/
                server: 192.168.23.138
          restartPolicy: OnFailure
  schedule: "*/1 * * * *"
  successfulJobsHistoryLimit: 3
  failedJobsHistoryLimit: 3
  startingDeadlineSeconds: 30
  suspend: false
  concurrencyPolicy: Allow
  • 创建CronJob
kubectl create -f nginx-cronjob-nfs.yaml
  • 检查CronJob运行情况
kubectl get cronjobs.batch 
# NAME                 SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
# cronjob-nginx-logs   */1 * * * *   False     1        41s             60s
  • 查看备份效果
ll /data/nfs/data/
# total 12
# -rw-r--r--. 1 root root    0 Jul 19 22:15 access.log
# -rw-r--r--. 1 root root 1530 Jul 19 22:15 error.log
# -rw-r--r--. 1 root root  336 Jul 19 22:48 nginx-logs_2024-07-19-14-48-09.tgz
# -rw-r--r--. 1 root root  336 Jul 19 22:49 nginx-logs_2024-07-19-14-49-09.tgz

Job应用案例–备份一次Nginx日志

  • Nginx的Deployment创建
    • 参考“CronJob应用案例–定时备份Nginx日志”中Deployment创建
  • 编辑一次性Job备份Nginx日志
apiVersion: batch/v1
kind: Job
metadata:
  name: job-nginx
  namespace: default
  labels:
    app: job-nginx

spec:
  template:
    spec:
      containers:
        - name: nginx-backup-logs
          image: registry.cn-beijing.aliyuncs.com/publicspaces/busybox:1.28.0
          imagePullPolicy: IfNotPresent
          command:
            - sh
            - -c
            - tar -czf /tmp/nginx/logs/nginx-logs_$(date +%F-%H-%M-%S).tgz /tmp/nginx/logs/*.log; echo "备份完成,备份时间:`date +%F-%H-%M-%S`"
          volumeMounts:
            - mountPath: /tmp/nginx/logs/
              name: nfs-volume
      restartPolicy: OnFailure
      volumes:
        - name: nfs-volume
          nfs:
            path: /data/nfs/data/
            server: 192.168.23.138
  • 创建Job
kubectl create -f nginx-job-nfs.yaml
  • 查看Job
kubectl get job
# NAME        COMPLETIONS   DURATION   AGE
# job-nginx   1/1           1s         2m25s
  • 查看备份效果
ll /data/nfs/data/
# total 16
# -rw-r--r--. 1 root root    0 Jul 19 22:15 access.log
# -rw-r--r--. 1 root root 3060 Jul 20 09:43 error.log
# -rw-r--r--. 1 root root  336 Jul 19 22:48 nginx-logs_2024-07-19-14-48-09.tgz
# -rw-r--r--. 1 root root  336 Jul 19 22:49 nginx-logs_2024-07-19-14-49-09.tgz
# -rw-r--r--. 1 root root  396 Jul 20 10:51 nginx-logs_2024-07-20-02-51-58.tgz

污点&容忍

简介

什么是Taint

Taints(污点)是一种节点级别的机制,用于标记节点,并控制Pod可以调度到这些节点上的方式。
Taints(污点)可以防止Pod调度到特定的节点上,或者要求Pod必须具有特定的标签才能调度到这些节点上。

Taint关键点

  1. 硬性污点(Hard Taints):硬性污点会完全阻止Pod调度到标记了污点的节点上,除非Pod具有相应的容忍(Tolerations)。
  2. 软性污点(Soft Taints):软性污点会减少Pod调度到标记了污点的节点上的概率,但不会完全阻止。软性污点不会要求Pod具有相应的容忍。
  3. 容忍(Tolerations):容忍是Pod的一种配置,它允许Pod调度到标记了特定污点的节点上。容忍可以配置污点的键(Key)、值(Value)和容忍期(Effect),容忍期可以是NoSchedule、PreferNoSchedule或NoExecute。

Taint应用场景

  • 防止Pod调度到特定节点:可以使用硬性污点来标记那些不希望Pod调度到的节点。
  • 优先级调度:可以使用软性污点来标记具有某些资源的节点,以便优先调度到这些节点上。
  • 管理节点状态:可以使用污点来标记维护或故障的节点,以便Pod不会调度到这些节点上。

什么是Toleration

Toleration(容忍)是一种Pod配置,它允许Pod调度到标记有特定污点的节点上。
Toleration(容忍)是Pod容忍污点的声明,可以配置污点的键(Key)、值(Value)和容忍期(Effect)。

Toleration关键点

  1. 容忍期(Effect):容忍期定义了污点对Pod调度的影响。有以下几种容忍期:
    • NoSchedule:Pod不会调度到标记有污点的节点上,除非Pod有其他的容忍。
    • PreferNoSchedule:Pod不会优先调度到标记有污点的节点上,但可以调度到这些节点上。
    • NoExecute:如果Pod已经调度到标记有污点的节点上,当污点被添加时,Pod将被驱逐(Evicted)。
  2. 键(Key)和值(Value):Toleration必须与污点的键和值匹配。这意味着Toleration将只容忍具有特定键和值的污点。
  3. 容忍时间(TolerationSeconds):容忍时间定义了Pod在节点上容忍污点的持续时间。当容忍时间到期时,Pod将被驱逐。

注意事项

  • 污点没有命名空间概念;
  • 污点主要用于节点的标记;
  • 节点设置污点时,此节点仍可运行被标记容忍的Pod;
  • 节点设置污点后,此节点根据污点的效果对Pod操作;
  • 节点设置多个污点后,此节点如果想运行Pod需要容忍所有污点;

Taint命令

创建Taint

#格式:
kubectl taint node Node名称 污点的Key=污点的Value:污点的效果

#举例:
kubectl taint node k8s-01 test-taint=test:NoExecute

修改Taint

注意:Taint只能修改其效果,如需要修改Key&Value,需要删除后重新创建。

#格式:
kubectl taint node Node名称 污点的Key=污点的Value:污点的效果

#举例:
kubectl taint node k8s-01 test-taint=test:PreferNoSchedule
# node/k8s-01 tainted

查看Taint

#格式:
kubectl describe node Node名称 | grep Taints

#举例:
kubectl describe node k8s-01 | grep Taints
# Taints:             test-taint=test:NoExecute

删除Taint

  • 删除Taint的Key
#格式:
kubectl taint node Node名称 污点的Key-

#举例:
kubectl taint node k8s-01 test-taint-
  • 删除Taint的Effett
#格式:
kubectl taint node Node名称 污点的Key:污点的效果-

#举例:
kubectl taint node k8s-01 test-taint:污点的效果-

Taint的三种效果

  • **NoSchedule: **
    • 完全阻止调度
    • 如果污点设置了NoSchedule效果,则没有容忍(Toleration)的Pod将不会被调度到该节点上。
    • 即使节点上有足够的资源,Pod也不会被调度。
  • **PreferNoSchedule: **
    • 减少调度概率
    • 如果污点设置了PreferNoSchedule效果,则没有容忍的Pod不会被优先调度到该节点上。
    • 如果有其他可用的节点,没有容忍的Pod将不会被调度到带有PreferNoSchedule污点的节点上。
    • 如果没有其他可用的节点,没有容忍的Pod仍然可以被调度到带有PreferNoSchedule污点的节点上。
  • **NoExecute: **
    • 驱逐已调度的Pod
    • 如果污点设置了NoExecute效果,则没有容忍的Pod将被驱逐(Evicted)出该节点。
    • 如果Pod已经调度到带有NoExecute污点的节点上,当污点被添加时,Pod将被驱逐。

Toleration配置

Toleration设置

apiVersion: apps/v1
kind: Deployment                                                                  #定义资源的类型为Deployment。
metadata:
  name: deployment-nginx                                                          #定义Deployment的名称。
  namespace: default
  labels:
    app: deployment-nginx                                                         #一个自定义标签,可用于筛选或关联资源。

spec:
  replicas: 3                                                                     #定义Deployment中Pod的副本数量。这里设置为3。
  selector:                                                                       #定义Deployment如何选择Pod。
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          imagePullPolicy: IfNotPresent                                           #定义了如何处理镜像的拉取。
          image: registry.cn-beijing.aliyuncs.com/publicspaces/nginx:1.22.1
      restartPolicy: Always                                                       #定义了Pod失败后的重启策略。这里设置为Always,意味着如果容器失败,Pod将被重启。
      tolerations:                                                                #定义了Pod容忍的污点。
        - key: nginx-in-master                                                    #污点的键。
          value: nginx                                                            #污点的值。
          effect: NoExecute                                                       #污点的效果,这里设置为NoExecute,意味着没有容忍的Pod将被驱逐出节点。
          operator: Equal                                                         #污点键和值之间如何匹配。这里设置为Equal,意味着只有当污点的键和值完全匹配时,容忍才会生效。
          tolerationSeconds: 60                                                   #定义了Pod在节点上容忍污点的持续时间。当容忍时间到期时,Pod将被驱逐。

Toleration的三种匹配

  • Exists
    • 如果污点的键存在,则容忍生效。
    • 只要污点的键与容忍的键匹配,不管污点的值是什么,容忍都会生效。
  • Equal
    • 如果污点的键和值与容忍的键和值完全匹配,则容忍生效。
  • NoEqual
    • 如果污点的键和值与容忍的键和值不完全匹配,则容忍生效。
  • 三者之间的区别
    • Exists 容忍适用于任何标记了该键的污点;
    • Equal 容忍要求污点的值与容忍的值完全匹配;
    • NotEqual 容忍适用于任何标记了该键但不具有该值的污点;

应用

需求

由于公司Kubernetes集群节点数量有限资源使用将近枯竭,限制新增项目需要临时部署在master节点上;

操作

  • 查看master节点上的Taint
kubectl describe nodes k8s-01
# Name:               k8s-01
# Roles:              control-plane,master
# Labels:             beta.kubernetes.io/arch=amd64
#                     beta.kubernetes.io/os=linux
#                     kubernetes.io/arch=amd64
#                     kubernetes.io/hostname=k8s-01
#                     kubernetes.io/os=linux
#                     node-role.kubernetes.io/control-plane=
#                     node-role.kubernetes.io/master=
# Annotations:        kubeadm.alpha.kubernetes.io/cri-socket: /var/run/dockershim.sock
#                     node.alpha.kubernetes.io/ttl: 0
#                     volumes.kubernetes.io/controller-managed-attach-detach: true
# CreationTimestamp:  Sat, 20 Jul 2024 15:46:52 +0800
# Taints:             node-role.kubernetes.io/master:NoSchedule
# Unschedulable:      false
# Lease:
#   HolderIdentity:  k8s-01
#   AcquireTime:     <unset>
#   RenewTime:       Sat, 20 Jul 2024 15:48:37 +0800
# Conditions:
#   Type             Status  LastHeartbeatTime                 LastTransitionTime                Reason                       Message
#   ----             ------  -----------------                 ------------------                ------                       -------
#   MemoryPressure   False   Sat, 20 Jul 2024 15:47:05 +0800   Sat, 20 Jul 2024 15:46:46 +0800   KubeletHasSufficientMemory   kubelet has sufficient memory available
#   DiskPressure     False   Sat, 20 Jul 2024 15:47:05 +0800   Sat, 20 Jul 2024 15:46:46 +0800   KubeletHasNoDiskPressure     kubelet has no disk pressure
#   PIDPressure      False   Sat, 20 Jul 2024 15:47:05 +0800   Sat, 20 Jul 2024 15:46:46 +0800   KubeletHasSufficientPID      kubelet has sufficient PID available
#   Ready            True    Sat, 20 Jul 2024 15:47:05 +0800   Sat, 20 Jul 2024 15:47:05 +0800   KubeletReady                 kubelet is posting ready status
# Addresses:
#   InternalIP:  192.168.23.138
#   Hostname:    k8s-01
# Capacity:
#   cpu:                2
#   ephemeral-storage:  41921540Ki
#   hugepages-1Gi:      0
#   hugepages-2Mi:      0
#   memory:             4026164Ki
#   pods:               110
# Allocatable:
#   cpu:                2
#   ephemeral-storage:  38634891201
#   hugepages-1Gi:      0
#   hugepages-2Mi:      0
#   memory:             3923764Ki
#   pods:               110
# System Info:
#   Machine ID:                 34d58adc8afc4eb48a6691cd11aa3f2e
#   System UUID:                13504D56-910B-ABF0-AA45-AD2FFB4ED65B
#   Boot ID:                    e6da337d-00d0-406f-87c0-83c9d28578bd
#   Kernel Version:             3.10.0-1160.el7.x86_64
#   OS Image:                   CentOS Linux 7 (Core)
#   Operating System:           linux
#   Architecture:               amd64
#   Container Runtime Version:  docker://26.1.4
#   Kubelet Version:            v1.20.9
#   Kube-Proxy Version:         v1.20.9
# PodCIDR:                      83.12.0.0/24
# PodCIDRs:                     83.12.0.0/24
# Non-terminated Pods:          (7 in total)
#   Namespace                   Name                              CPU Requests  CPU Limits  Memory Requests  Memory Limits  AGE
#   ---------                   ----                              ------------  ----------  ---------------  -------------  ---
#   kube-system                 coredns-7f89b7bc75-pk7tj          100m (5%)     0 (0%)      70Mi (1%)        170Mi (4%)     96s
#   kube-system                 coredns-7f89b7bc75-vbsvh          100m (5%)     0 (0%)      70Mi (1%)        170Mi (4%)     96s
#   kube-system                 etcd-k8s-01                       100m (5%)     0 (0%)      100Mi (2%)       0 (0%)         109s
#   kube-system                 kube-apiserver-k8s-01             250m (12%)    0 (0%)      0 (0%)           0 (0%)         109s
#   kube-system                 kube-controller-manager-k8s-01    200m (10%)    0 (0%)      0 (0%)           0 (0%)         109s
#   kube-system                 kube-proxy-hd9f5                  0 (0%)        0 (0%)      0 (0%)           0 (0%)         96s
#   kube-system                 kube-scheduler-k8s-01             100m (5%)     0 (0%)      0 (0%)           0 (0%)         109s
# Allocated resources:
#   (Total limits may be over 100 percent, i.e., overcommitted.)
#   Resource           Requests    Limits
#   --------           --------    ------
#   cpu                850m (42%)  0 (0%)
#   memory             240Mi (6%)  340Mi (8%)
#   ephemeral-storage  0 (0%)      0 (0%)
#   hugepages-1Gi      0 (0%)      0 (0%)
#   hugepages-2Mi      0 (0%)      0 (0%)
# Events:
#   Type    Reason                   Age   From        Message
#   ----    ------                   ----  ----        -------
#   Normal  Starting                 109s  kubelet     Starting kubelet.
#   Normal  NodeHasSufficientMemory  109s  kubelet     Node k8s-01 status is now: NodeHasSufficientMemory
#   Normal  NodeHasNoDiskPressure    109s  kubelet     Node k8s-01 status is now: NodeHasNoDiskPressure
#   Normal  NodeHasSufficientPID     109s  kubelet     Node k8s-01 status is now: NodeHasSufficientPID
#   Normal  NodeNotReady             109s  kubelet     Node k8s-01 status is now: NodeNotReady
#   Normal  NodeAllocatableEnforced  109s  kubelet     Updated Node Allocatable limit across pods
#   Normal  NodeReady                99s   kubelet     Node k8s-01 status is now: NodeReady
#   Normal  Starting                 93s   kube-proxy  Starting kube-proxy.
  • 添加污点
kubectl taint node k8s-01 taint-nginx-node=nginx-temp-node:NoExecute
  • 编辑Deployment中Pod的Toleration
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-nginx
  namespace: default
  labels:
    app: deployment-nginx

spec:
  replicas: 10
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          imagePullPolicy: IfNotPresent
          image: registry.cn-beijing.aliyuncs.com/publicspaces/nginx:1.22.1
      restartPolicy: Always
      tolerations:
        - key: taint-nginx-node
          value: nginx-temp-node
          effect: NoExecute
          operator: Equal
        - key: node-role.kubernetes.io/master
          effect: NoSchedule
          operator: Exists

亲和力&反亲和力

简介

什么是Affinity

Affinity(亲和力)是一组策略,用于影响Pod的调度过程,以实现特定的调度目标。
亲和力包括多种类型的规则,用于指定Pod应该与哪些其他Pod一起调度,或者应该避免与哪些Pod一起调度。

Affinity的几种类型

  1. 节点亲和力(Node Affinity)
    • 硬性要求(RequiredDuringSchedulingIgnoredDuringExecution):如果节点不满足亲和力要求,Pod将不会被调度到该节点上。
    • 软性要求(PreferredDuringSchedulingIgnoredDuringExecution):调度器将尝试将Pod调度到满足亲和力要求的节点上,但不是强制的。
  2. Pod亲和力(Pod Affinity)
    • 硬性要求(RequiredDuringSchedulingIgnoredDuringExecution):如果Pod不满足亲和力要求,Pod将不会被调度到该节点上。
    • 软性要求(PreferredDuringSchedulingIgnoredDuringExecution):调度器将尝试将Pod调度到满足亲和力要求的节点上,但不是强制的。
  3. Pod反亲和力(Pod Anti-Affinity)
    • 硬性要求(RequiredDuringSchedulingIgnoredDuringExecution):如果Pod不满足反亲和力要求,Pod将不会被调度到该节点上。
    • 软性要求(PreferredDuringSchedulingIgnoredDuringExecution):调度器将尝试避免将Pod调度到满足反亲和力要求的节点上,但不是强制的。

什么是Anti-Affinity

Anti-Affinity(反亲和力)是一种调度策略,用于确保Pod不会被调度到与某些其他Pod或节点一起运行。
反亲和力(Anti-Affinity)与亲和力(Affinity)相反,亲和力旨在促进Pod之间的协作或避免冲突,而反亲和力则旨在防止Pod之间的冲突。

Anti-Affinity关键点

  1. 避免特定Pod或节点:反亲和力允许您指定Pod不应该与哪些其他Pod或节点一起调度。
  2. 硬性要求(RequiredDuringSchedulingIgnoredDuringExecution):如果反亲和力要求不被满足,Pod将不会被调度到该节点上。
  3. 软性要求(PreferredDuringSchedulingIgnoredDuringExecution):调度器将尝试避免将Pod调度到满足反亲和力要求的节点上,但不是强制的。

节点亲和性支持的运算符

  1. In:标签值必须与其中一个指定的值匹配。
  2. NotIn:标签值不得与指定的任何一个值匹配。
  3. Exists:指定的标签必须存在于节点上(不需要指定值)。
  4. DoesNotExist:指定的标签不得存在于节点上。
  5. Gt(大于):标签值必须大于指定的值(只适用于数字)。
  6. Lt(小于):标签值必须小于指定的值(只适用于数字)。

注意事项

  1. 节点反亲和性没有专门的语法,可以通过operator中的NotIn、DoesNotExist和node的污点实现。
  2. 亲和力需要与标签配合使用。
  3. 软亲和力规则中的权重(weight)是一个介于 0 到 100 之间的整数值,用于表示该规则的偏好程度。权重越高,调度器在调度 Pod 时就越倾向于选择符合该规则的节点。
  4. topologyKeytopology 这两个术语有时会被混淆,但它们实际上描述的是不同的概念。**topologyKey,**它是节点亲和性(Node Affinity)或 Pod 亲和性(Pod Affinity)中的一个参数。**topology,**它指的是 Kubernetes 集群中节点之间的关系。
  5. 亲和力的标签选择可以跨namespace(命名空间)。如果写了namespace字段但是留空,表示匹配所有namespace下指定label的Pod;如果指定了namespace字段且写了值,表示仅匹配相关namespace下指定label的Pod。

应用

NodeAffinity

  1. requiredDuringSchedulingIgnoredDuringExecution
  • 案例说明
    • 在Kubernetes集群中,部署的nginx服务需要使用到SSD磁盘;
    • 在Kubernetes集群中,为配备SSD磁盘的Node创建标签标识;
  • 创建标签
#创建标签
kubectl label nodes k8s-02 DISK=SSD

#查看标签
kubectl get nodes --show-labels
NAME     STATUS   ROLES                  AGE    VERSION   LABELS
k8s-01   Ready    control-plane,master   2d2h   v1.20.9   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-01,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=
k8s-02   Ready    <none>                 60m    v1.20.9   DISK=SSD,beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-02,kubernetes.io/os=linux
k8s-03   Ready    <none>                 60m    v1.20.9   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-03,kubernetes.io/os=linux
  • 编辑yaml
apiVersion: apps/v1
kind: Deployment                                                                #定义资源类型为 Deployment。
metadata:
  name: deployment-nginx                                                        #指定 Deployment 的名称。
  namespace: default                                                            #指定 Deployment 应该被创建在 default 命名空间。
  labels:
    app: deployment-nginx

spec:                                                                           #定义 Deployment 的规格。
  selector:                                                                     #定义如何选择要管理的 Pod。
    matchLabels:                                                                #Pod 必须具有的标签,这里要求 Pod 有 app: nginx 标签。
      app: nginx
  template:                                                                     #定义如何选择要管理的 Pod。
    metadata:
      labels:
        app: nginx
    spec:                                                                       #定义 Pod 的规格。
      containers:                                                               #定义 Pod 中的容器列表。
        - name: nginx-web                                                       #容器的名称。
          imagePullPolicy: IfNotPresent
          image: registry.cn-beijing.aliyuncs.com/publicspaces/nginx:1.22.1
      restartPolicy: Always                                                     #定义 Pod 的重启策略,这里设置为总是重启。
      affinity:                                                                 #定义 Pod 的亲和性设置。
        nodeAffinity:                                                           #定义节点亲和性。
          requiredDuringSchedulingIgnoredDuringExecution:                       #置硬亲和性规则,即在调度时必须满足的条件,但在执行后忽略。
            nodeSelectorTerms:                                                  #节点选择器列表。
              - matchExpressions:                                               #匹配表达式列表。
                  - key: DISK                                                   #要匹配的节点标签键。
                    operator: In                                                #运算符 In,表示节点的标签值必须在给定的列表中。
                    values:                                                     #包含 SSD 的列表,表示只有当节点标签 DISK 的值为 SSD 时,Pod 才可以被调度到该节点。
                      - SSD
  replicas: 3                                                                   #指定此 Deployment 应管理的 Pod 副本数量为 3。
  • 创建服务
kubectl create -f affinity-deployment-nginx.yaml
  • 查看服务
kubectl get pod -o wide
# NAME                                READY   STATUS    RESTARTS   AGE     IP            NODE     NOMINATED NODE   READINESS GATES
# deployment-nginx-75b5b8c6c7-97vs5   1/1     Running   0          5m37s   83.12.179.4   k8s-02   <none>           <none>
# deployment-nginx-75b5b8c6c7-jc6ng   1/1     Running   0          5m37s   83.12.179.6   k8s-02   <none>           <none>
# deployment-nginx-75b5b8c6c7-s2zlv   1/1     Running   0          5m37s   83.12.179.5   k8s-02   <none>           <none>
  • 验证亲和性
#删除节点标签
kubectl label nodes k8s-02 DISK-

#删除服务重新部署
kubectl delete -f affinity-deployment-nginx.yaml
kubectl create -f affinity-deployment-nginx.yaml

#检查服务
kubectl get pod -o wide
# NAME                                READY   STATUS    RESTARTS   AGE   IP       NODE     NOMINATED NODE   READINESS GATES
# deployment-nginx-75b5b8c6c7-jjsgh   0/1     Pending   0          69s   <none>   <none>   <none>           <none>
# deployment-nginx-75b5b8c6c7-pkcsh   0/1     Pending   0          69s   <none>   <none>   <none>           <none>
# deployment-nginx-75b5b8c6c7-pqsgn   0/1     Pending   0          69s   <none>   <none>   <none>           <none>
  1. PreferredDuringSchedulingIgnoredDuringExecution
  • 案例说明
    • 在Kubernetes集群中,部署的nginx服务需要优先部署到GPU的节点上;
    • 在Kubernetes集群中,为GPU节点创建标签;
  • 创建标签
kubectl label nodes k8s-02 HOST=GPU
  • 编辑yaml
apiVersion: apps/v1
kind: Deployment                                                                  #定义资源类型为 Deployment。
metadata:
  name: deployment-nginx                                                          #指定 Deployment 的名称。
  namespace: default
  labels:
    app: deployment-nginx                                                         #为 Deployment 本身设置标签,这里标签为 app: deployment-nginx。

spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:                                                                         #定义 Pod 的规格。
      containers:                                                                 #定义 Pod 中的容器列表。
        - name: nginx-web
          imagePullPolicy: IfNotPresent
          image: registry.cn-beijing.aliyuncs.com/publicspaces/nginx:1.22.1
      restartPolicy: Always
      affinity:                                                                   #定义 Pod 的亲和性设置。
        nodeAffinity:                                                             #定义节点亲和性。
          preferredDuringSchedulingIgnoredDuringExecution:                        #设置软亲和性规则,即在调度时优先考虑某些节点,但不是强制性的。
            - preference:                                                         #定义偏好规则的具体内容。
                matchExpressions:                                                 #匹配表达式列表。
                  - key: HOST                                                     #要匹配的节点标签键。
                    operator: In                                                  #运算符 In,表示节点的标签值必须在给定的列表中。
                    values:                                                       #包含 GPU 的列表,表示调度器会优先将 Pod 调度到具有 HOST: GPU 标签的节点上。
                      - GPU
              weight: 1                                                           #指定偏好规则的权重,这里权重为 1。
  replicas: 6
  • 创建服务
kubectl create -f affinity-deployment-nginx.yaml
  • 查看服务
kubectl get pod -o wide
# NAME                                READY   STATUS    RESTARTS   AGE   IP             NODE     NOMINATED NODE   READINESS GATES
# deployment-nginx-5ccc9fbb5c-4rv69   1/1     Running   0          10s   83.12.179.10   k8s-02   <none>           <none>
# deployment-nginx-5ccc9fbb5c-f2kdr   1/1     Running   0          10s   83.12.179.9    k8s-02   <none>           <none>
# deployment-nginx-5ccc9fbb5c-h6sht   1/1     Running   0          10s   83.12.179.12   k8s-02   <none>           <none>
# deployment-nginx-5ccc9fbb5c-j7954   1/1     Running   0          10s   83.12.179.11   k8s-02   <none>           <none>
# deployment-nginx-5ccc9fbb5c-p5dsr   1/1     Running   0          10s   83.12.179.8    k8s-02   <none>           <none>
# deployment-nginx-5ccc9fbb5c-s4bgz   1/1     Running   0          10s   83.12.179.7    k8s-02   <none>           <none>
  • 验证亲和性
#删除节点标签
kubectl label nodes k8s-02 HOST-

#删除服务重新部署
kubectl delete -f affinity-deployment-nginx.yaml
kubectl create -f affinity-deployment-nginx.yaml

#检查服务
kubectl get pod -o wide
# NAME                                READY   STATUS    RESTARTS   AGE   IP              NODE     NOMINATED NODE   READINESS GATES
# deployment-nginx-5ccc9fbb5c-bgxfq   1/1     Running   0          72s   83.12.61.207    k8s-01   <none>           <none>
# deployment-nginx-5ccc9fbb5c-bk2t2   1/1     Running   0          72s   83.12.165.193   k8s-03   <none>           <none>
# deployment-nginx-5ccc9fbb5c-bqjxk   1/1     Running   0          72s   83.12.165.196   k8s-03   <none>           <none>
# deployment-nginx-5ccc9fbb5c-c2hzz   1/1     Running   0          72s   83.12.61.210    k8s-01   <none>           <none>
# deployment-nginx-5ccc9fbb5c-krnmx   1/1     Running   0          72s   83.12.165.195   k8s-03   <none>           <none>
# deployment-nginx-5ccc9fbb5c-sggns   1/1     Running   0          72s   83.12.165.194   k8s-03   <none>           <none>
  1. 混合使用
  • 案例说明
    • 在Kubernetes集群中,部署的nginx服务需要部署到特点的GPU节点,并且希望这些Pod尽可能的运行在SSD磁盘的节点上;
    • 在Kubernetes集群中,为GPU节点、SSD节点创建标签;
  • 创建标签
kubectl label nodes k8s-02 HOST=GPU
kubectl label nodes k8s-01 HOST=GPU
kubectl label nodes k8s-01 DISK=SSD
  • 编辑yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-nginx
  namespace: default
  labels:
    app: deployment-nginx

spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx-web
          imagePullPolicy: IfNotPresent
          image: registry.cn-beijing.aliyuncs.com/publicspaces/nginx:1.22.1
      restartPolicy: Always
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: HOST
                    operator: In
                    values:
                      - GPU
          preferredDuringSchedulingIgnoredDuringExecution:
            - preference:
                matchExpressions:
                  - key: DISK
                    operator: In
                    values:
                      - SSD
              weight: 1
  replicas: 6
  • 创建服务
kubectl create -f affinity-deployment-nginx.yaml
  • 查看服务
kubectl get pod -o wide
# NAME                                READY   STATUS    RESTARTS   AGE   IP             NODE     NOMINATED NODE   READINESS GATES
# deployment-nginx-7987b94b58-2kfrr   1/1     Running   0          5s    83.12.61.209   k8s-01   <none>           <none>
# deployment-nginx-7987b94b58-6zbzl   1/1     Running   0          5s    83.12.61.208   k8s-01   <none>           <none>
# deployment-nginx-7987b94b58-9xqfb   1/1     Running   0          5s    83.12.61.214   k8s-01   <none>           <none>
# deployment-nginx-7987b94b58-dldwh   1/1     Running   0          5s    83.12.61.212   k8s-01   <none>           <none>
# deployment-nginx-7987b94b58-hvqnb   1/1     Running   0          5s    83.12.61.206   k8s-01   <none>           <none>
# deployment-nginx-7987b94b58-t57bz   1/1     Running   0          5s    83.12.61.211   k8s-01   <none>           <none>
  • 验证亲和性
#删除节点DISK=SSD标签
kubectl label nodes k8s-01 DISK-

#删除服务重新部署
kubectl delete -f affinity-deployment-nginx.yaml
kubectl create -f affinity-deployment-nginx.yaml

#检查服务
kubectl get pod -o wide
# NAME                                READY   STATUS    RESTARTS   AGE   IP             NODE     NOMINATED NODE   READINESS GATES
# deployment-nginx-7987b94b58-88qdx   1/1     Running   0          13s   83.12.179.13   k8s-02   <none>           <none>
# deployment-nginx-7987b94b58-bql2j   1/1     Running   0          13s   83.12.179.16   k8s-02   <none>           <none>
# deployment-nginx-7987b94b58-jpb5q   1/1     Running   0          13s   83.12.179.18   k8s-02   <none>           <none>
# deployment-nginx-7987b94b58-n8cb4   1/1     Running   0          13s   83.12.179.15   k8s-02   <none>           <none>
# deployment-nginx-7987b94b58-pw7g8   1/1     Running   0          13s   83.12.179.17   k8s-02   <none>           <none>
# deployment-nginx-7987b94b58-wrr47   1/1     Running   0          13s   83.12.179.14   k8s-02   <none>           <none>

#删除节点HOST=GPU标签
kubectl label nodes k8s-01 HOST-.

#删除服务重新部署
kubectl delete -f affinity-deployment-nginx.yaml
kubectl create -f affinity-deployment-nginx.yaml

#检查服务
kubectl get pod -o wide
# NAME                                READY   STATUS    RESTARTS   AGE   IP             NODE     NOMINATED NODE   READINESS GATES
# deployment-nginx-7987b94b58-2wg88   1/1     Running   0          25s   83.12.179.21   k8s-02   <none>           <none>
# deployment-nginx-7987b94b58-7xqfl   1/1     Running   0          25s   83.12.179.20   k8s-02   <none>           <none>
# deployment-nginx-7987b94b58-hdz49   1/1     Running   0          25s   83.12.179.22   k8s-02   <none>           <none>
# deployment-nginx-7987b94b58-qcmth   1/1     Running   0          25s   83.12.179.19   k8s-02   <none>           <none>
# deployment-nginx-7987b94b58-wkpvs   1/1     Running   0          25s   83.12.179.24   k8s-02   <none>           <none>
# deployment-nginx-7987b94b58-xcr8m   1/1     Running   0          25s   83.12.179.23   k8s-02   <none>           <none>

PodAffinity

  1. requiredDuringSchedulingIgnoredDuringExecution
  • 案例说明
    • 在Kubernetes集群中,已经部署了Redis服务,现在需要将Nginx服务与Redis服务部署在一起;
  • 编辑yaml-redis
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: statefulset-redis
  namespace: default
  labels:
    app: statefulset-redis

spec:
  selector:
    matchLabels:
      app: redis
  serviceName: service-redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
        - name: redis-web
          imagePullPolicy: IfNotPresent
          image: registry.cn-beijing.aliyuncs.com/publicspaces/redis:6.2.6
          ports:
            - containerPort: 6379

---
apiVersion: v1
kind: Service
metadata:
  name: service-redis
  namespace: default
  labels:
    app: service-redis

spec:
  clusterIP: None
  ports:
    - port: 63799
      targetPort: 6379
      protocol: TCP
      name: redis-tcp
    - port: 63799
      targetPort: 6379
      protocol: UDP
      name: redis-udp
  • 部署redis
kubectl create -f podaffinity-statefulset-redis.yaml
  • 查看redis
kubectl get pod -o wide
# NAME                  READY   STATUS    RESTARTS   AGE   IP             NODE     NOMINATED NODE   READINESS GATES
# statefulset-redis-0   1/1     Running   0          88s   83.12.179.25   k8s-02   <none>           <none>
  • 编辑yaml-nginx
apiVersion: apps/v1
kind: Deployment                                                                        #定义资源类型为 Deployment。
metadata:
  name: deployment-nginx                                                                #指定 Deployment 的名称。
  namespace: default
  labels:
    app: deployment-nginx                                                               #为 Deployment 本身设置标签,这里标签为 app: deployment-nginx。

spec:                                                                                   #定义 Deployment 的规格。
  selector:                                                                             #定义如何选择要管理的 Pod。
    matchLabels:
      app: nginx                                                                        #Pod 必须具有的标签,这里要求 Pod 有 app: nginx 标签。
  template:
    metadata:
      labels:
        app: nginx                                                                      #设置 Pod 的标签,这里标签为 app: nginx,与 selector 匹配。
    spec:                                                                               #定义 Pod 的规格。
      containers:
        - name: nginx-web
          imagePullPolicy: IfNotPresent
          image: registry.cn-beijing.aliyuncs.com/publicspaces/nginx:1.22.1
      restartPolicy: Always                                                             #定义 Pod 的重启策略,这里设置为总是重启。
      affinity:                                                                         #定义 Pod 的亲和性设置。
        podAffinity:                                                                    #定义 Pod 亲和性规则。
          requiredDuringSchedulingIgnoredDuringExecution:                               #设置硬亲和性规则,即在调度时必须满足的条件,但在执行后忽略。
            - labelSelector:                                                            #定义了需要与之关联的 Pod 的标签。
                matchExpressions:                                                       #匹配表达式列表。
                  - key: app                                                            #要匹配的Pod标签键。
                    operator: In                                                        #运算符 In,表示节点的标签值必须在给定的列表中。
                    values:
                      - redis                                                           #包含 redis 的列表,表示只有当 Pod 的 app 标签值为 redis 时,Nginx 容器才会被调度到与之关联的 Pod 所在的节点上。
              topologyKey: kubernetes.io/hostname                                       #指定用于比较的键,这里是 hostname。这意味着 Nginx 容器将只与具有相同 hostname 的 Redis 容器一起调度到同一个节点上。
  • 部署nginx
kubectl create -f podaffinity-deployment-nginx.yaml 
  • 查看服务
kubectl get pod -o wide
# NAME                                READY   STATUS    RESTARTS   AGE     IP             NODE     NOMINATED NODE   READINESS GATES
# deployment-nginx-77d8b877c6-gf46p   1/1     Running   0          6m35s   83.12.179.26   k8s-02   <none>           <none>
# statefulset-redis-0                 1/1     Running   0          27m     83.12.179.25   k8s-02   <none>           <none>
  • 验证亲和性
#删除服务
kubectl delete -f podaffinity-statefulset-redis.yaml
kubectl delete -f podaffinity-deployment-nginx.yaml

#单独启动nginx
kubectl create -f podaffinity-deployment-nginx.yaml

#查看nginx服务
kubectl get pod -o wide
# NAME                                READY   STATUS    RESTARTS   AGE   IP       NODE     NOMINATED NODE   READINESS GATES
# deployment-nginx-77d8b877c6-pqsdn   0/1     Pending   0          16s   <none>   <none>   <none>           <none>
  1. PreferredDuringSchedulingIgnoredDuringExecution
  • 案例说明
    • 在Kubernetes集群中,已经部署了Redis服务,现在需要将Nginx服务与Redis服务尽可能的部署在一起;
  • 编辑yaml-redis
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: statefulset-redis
  namespace: default
  labels:
    app: statefulset-redis

spec:
  selector:
    matchLabels:
      app: redis
  serviceName: service-redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
        - name: redis-web
          imagePullPolicy: IfNotPresent
          image: registry.cn-beijing.aliyuncs.com/publicspaces/redis:6.2.6
          ports:
            - containerPort: 6379

---
apiVersion: v1
kind: Service
metadata:
  name: service-redis
  namespace: default
  labels:
    app: service-redis

spec:
  clusterIP: None
  ports:
    - port: 63799
      targetPort: 6379
      protocol: TCP
      name: redis-tcp
    - port: 63799
      targetPort: 6379
      protocol: UDP
      name: redis-udp
  • 部署redis
kubectl create -f podaffinity-statefulset-redis.yaml
  • 查看redis
kubectl get pod -o wide
# NAME                  READY   STATUS    RESTARTS   AGE   IP             NODE     NOMINATED NODE   READINESS GATES
# statefulset-redis-0   1/1     Running   0          88s   83.12.179.25   k8s-02   <none>           <none>
  • 编辑yaml-nginx
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-nginx
  namespace: default
  labels:
    app: deployment-nginx

spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx-web
          imagePullPolicy: IfNotPresent
          image: registry.cn-beijing.aliyuncs.com/publicspaces/nginx:1.22.1
      restartPolicy: Always
      affinity:                                                                   #定义 Pod 的亲和性设置。
        podAffinity:                                                              #定义 Pod 亲和性规则。
          preferredDuringSchedulingIgnoredDuringExecution:                        #设置软亲和性规则,即在调度时优先考虑某些条件,但在执行后忽略。
            - podAffinityTerm:                                                    #Pod 亲和性条件。
                topologyKey: kubernetes.io/hostname                               #指定用于比较的键,这里是 hostname。
                labelSelector:                                                    #定义了需要与之关联的 Pod 的标签。
                  matchExpressions:                                               #匹配表达式列表。
                    - key: app                                                    #要匹配的Pod标签键。
                      operator: In                                                #运算符 In,表示节点的标签值必须在给定的列表中。
                      values:
                        - redis                                                   #包含 redis 的列表,表示只有当 Pod 的 app 标签值为 redis 时,Nginx 容器才会被调度到与之关联的 Pod 所在的节点上。
              weight: 1                                                           #指定偏好规则的权重,这里权重为 1。
  • 部署nginx
kubectl create -f podaffinity-deployment-nginx.yaml
  • 查看服务
kubectl get pod -o wide
# NAME                              READY   STATUS    RESTARTS   AGE   IP             NODE     NOMINATED NODE   READINESS GATES
# deployment-nginx-75fc99b4-jtwwr   1/1     Running   0          9s    83.12.179.28   k8s-02   <none>           <none>
# statefulset-redis-0               1/1     Running   0          20s   83.12.179.27   k8s-02   <none>           <none>
  • 验证亲和性
#删除服务
kubectl delete -f podaffinity-statefulset-redis.yaml
kubectl delete -f podaffinity-deployment-nginx.yaml

#单独启动nginx
kubectl create -f podaffinity-deployment-nginx.yaml

#查看nginx服务
kubectl get pod -o wide
# NAME                              READY   STATUS    RESTARTS   AGE   IP             NODE     NOMINATED NODE   READINESS GATES
# deployment-nginx-75fc99b4-qhc7z   1/1     Running   0          10s   83.12.179.29   k8s-02   <none>           <none>

PodAnitiAffinity

  1. requiredDuringSchedulingIgnoredDuringExecution
  • 案例说明
    • 在Kubernetes集群中,部署的Nginx有4个副本,要求4副本不部署在一起;
  • 编辑yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-nginx
  namespace: default
  labels:
    app: deployment-nginx

spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx-web
          imagePullPolicy: IfNotPresent
          image: registry.cn-beijing.aliyuncs.com/publicspaces/nginx:1.22.1
      restartPolicy: Always
      affinity:                                                                       #定义 Pod 的亲和性设置。
        podAntiAffinity:                                                              #定义 Pod 反亲和性规则。
          requiredDuringSchedulingIgnoredDuringExecution:                             #设置硬反亲和性规则,即在调度时必须满足的条件,但在执行后忽略。
            - topologyKey: kubernetes.io/hostname                                     #指定用于比较的键,这里是 hostname。
              labelSelector:                                                          #定义了需要避免的 Pod 的标签。
                matchExpressions:                                                     #匹配表达式列表。
                  - key: app                                                          #要匹配的Pod标签键。
                    operator: In                                                      #运算符 In,表示节点的标签值必须在给定的列表中。
                    values:
                      - nginx                                                         #包含 nginx 的列表,表示只有当 Pod 的 app 标签值为 nginx 时,Nginx 容器才会被调度到不与具有相同 hostname 的其他 Nginx 容器在同一个节点上。
  replicas: 4
  • 创建服务
kubectl create -f podAnitiAffinity-deployment-nginx.yaml
  • 验证反亲和性
#注意:由于要求4个副本都不部署在一起,这里只有三个节点,所以有一个副本一直处于Pending状态
kubectl get pod -o wide
# NAME                                READY   STATUS    RESTARTS   AGE   IP              NODE     NOMINATED NODE   READINESS GATES
# deployment-nginx-866bd85b89-98w9m   1/1     Running   0          12s   83.12.61.213    k8s-01   <none>           <none>
# deployment-nginx-866bd85b89-c8cp6   1/1     Running   0          12s   83.12.165.197   k8s-03   <none>           <none>
# deployment-nginx-866bd85b89-vdmmj   0/1     Pending   0          12s   <none>          <none>   <none>           <none>
# deployment-nginx-866bd85b89-w9qps   1/1     Running   0          12s   83.12.179.31    k8s-02   <none>           <none>
  1. PreferredDuringSchedulingIgnoredDuringExecution
  • 案例说明
    • 在Kubernetes集群中,部署的Nginx有4个副本,要求4副本尽量不部署在一起;
  • 编辑yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-nginx
  namespace: default
  labels:
    app: deployment-nginx

spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx-web
          imagePullPolicy: IfNotPresent
          image: registry.cn-beijing.aliyuncs.com/publicspaces/nginx:1.22.1
      restartPolicy: Always
      affinity:                                                                   #定义 Pod 的亲和性设置。
        podAntiAffinity:                                                          #定义 Pod 反亲和性规则。
          preferredDuringSchedulingIgnoredDuringExecution:                        #设置软反亲和性规则,即在调度时优先考虑某些条件,但在执行后忽略。
            - podAffinityTerm:                                                    #Pod 反亲和性条件。
                topologyKey: kubernetes.io/hostname                               #指定用于比较的键,这里是 hostname。
                namespaces:                                                       #指定在哪个命名空间中查找关联的 Pod。
                  - default                                                       #表示在默认命名空间中查找关联的 Pod。如果写了namespace字段但是留空,表示匹配所有namespace下指定label的Pod;如果指定了namespace字段且写了值,表示仅匹配相关namespace下指定label的Pod。
                labelSelector:                                                    #定义了需要避免的 Pod 的标签。
                  matchExpressions:                                               #匹配表达式列表。
                    - key: app                                                    #要匹配的Pod标签键。
                      operator: In                                                #运算符 In,表示节点的标签值必须在给定的列表中。
                      values:
                        - nginx                                                   #包含 nginx 的列表,表示只有当 Pod 的 app 标签值为 nginx 时,Nginx 容器才会被调度到不与具有相同 hostname 的其他 Nginx 容器在同一个节点上。
              weight: 1
  replicas: 4
  • 创建服务
kubectl create -f podAnitiAffinity-deployment-nginx.yaml
  • 验证反亲和性
#注意:由于要求4个副本尽量不部署在一起,这里只有三个节点,所以会有两个副本部署在一起
kubectl get pod -o wide
# NAME                                READY   STATUS    RESTARTS   AGE   IP              NODE     NOMINATED NODE   READINESS GATES
# deployment-nginx-64577c5f6c-7bgh4   1/1     Running   0          66s   83.12.179.33    k8s-02   <none>           <none>
# deployment-nginx-64577c5f6c-jlmls   1/1     Running   0          66s   83.12.179.32    k8s-02   <none>           <none>
# deployment-nginx-64577c5f6c-q7t5c   1/1     Running   0          66s   83.12.61.218    k8s-01   <none>           <none>
# deployment-nginx-64577c5f6c-sd6tr   1/1     Running   0          66s   83.12.165.198   k8s-03   <none>           <none>

拓扑域

简介

什么是Topology

拓扑域(Topology Domain)是 Kubernetes 中用来描述集群中节点之间的关系和组织方式的一个概念。
拓扑域反映了节点的物理位置、资源类型、可用性等属性,这些属性可以用于对节点进行分组和调度。
拓扑域的概念有助于 Kubernetes 调度器更好地理解和利用集群的拓扑结构,从而实现更高效的资源调度和负载均衡。

什么是TopologyKey

topologyKey是一个用于指定节点亲和性(Node Affinity)或 Pod 亲和性(Pod Affinity)规则中的键,该键用于确定哪些节点与 Pod 匹配。
topologyKey 通常与节点的标签相关联,用于在调度过程中确定 Pod 的位置。

Topology和TopologyKey的区别

  1. Topology
    • 它指的是 Kubernetes 集群中节点之间的关系和组织方式。
    • 在 Kubernetes 中,节点通常根据其物理位置、资源类型、可用性等属性进行分组。
    • 这些分组被称为拓扑(Topology)。
    • 例如,拓扑可以基于可用区(Zone)、区域(Region)或主机名(Hostname)来组织节点。
  2. TopologyKey
    • 它是用于指定节点亲和性(Node Affinity)或 Pod 亲和性(Pod Affinity)规则中的键,该键用于确定哪些节点与 Pod 匹配。
    • 通常是节点的标签。
    • 用于在调度过程中确定 Pod 的位置。
    • 例如,在节点亲和性或 Pod 亲和性规则中,你可以使用 TopologyKey 值来指定 Pod 应该与具有特定标签的节点关联。

Topology和TopologyKey的关系

TopologyKey 是用于定义 Topology 的键。
TopologyKey 是一个属性,它用于在节点亲和性(Node Affinity)或 Pod 亲和性(Pod Affinity)规则中指定一个键,这个键用于确定哪些节点与 Pod 匹配。
Topology 则是通过这个键定义的节点的属性或状态,如物理位置、资源类型或可用性等。
TopologyKey 是用于定义 Topology 的键,它帮助 Kubernetes 理解节点的属性或状态,并据此调度 Pod。

Topology划分原则

拓扑域的划分原则可以根据集群的特定需求和目标来确定,以下是一些常见的拓扑域划分原则:

  1. 可用性区域(Zone)
    • 基于物理位置:将集群中的节点按照它们所在的物理位置(如数据中心、机房)进行分组。
    • 基于网络隔离:将集群中的节点按照它们所在的网络区域进行分组,以减少网络延迟和提高可用性。
  2. 区域(Region)
    • 基于地理区域:将集群中的节点按照它们所在的地理区域进行分组,以优化跨区域的数据传输和延迟。
    • 基于网络拓扑:将集群中的节点按照它们在网络拓扑中的位置进行分组,以优化网络路径和带宽。
  3. 节点角色
    • 基于功能角色:将集群中的节点按照它们的功能角色(如 master 节点、worker 节点)进行分组,以实现更好的资源管理和负载均衡。
    • 基于硬件特性:将集群中的节点按照它们具有的硬件特性(如 CPU 架构、内存大小、GPU 类型)进行分组,以优化资源利用和提高应用程序性能。
  4. 节点标签
    • 基于自定义属性:将集群中的节点按照它们具有的自定义标签进行分组,以实现更精细的调度策略和资源管理。
    • 基于业务需求:根据业务需求和应用场景,将集群中的节点按照特定的属性进行分组,以满足特定的部署要求。

常见的TopologyKey

常见的 topologyKey 值及其含义:

  1. kubernetes.io/hostname:这是默认的 topologyKey 值,用于匹配具有相同 hostname 的节点。
  2. failure-domain.beta.kubernetes.io/zone:用于匹配具有相同可用区的节点。
  3. failure-domain.beta.kubernetes.io/region:用于匹配具有相同区域的节点。
  4. beta.kubernetes.io/os:用于匹配具有相同操作系统的节点。
  5. beta.kubernetes.io/arch:用于匹配具有相同架构的节点。
  6. beta.kubernetes.io/instance-type:用于匹配具有相同实例类型的节点。
  7. beta.kubernetes.io/disk:用于匹配具有相同磁盘类型的节点。
  8. beta.kubernetes.io/storage-type:用于匹配具有相同存储类型的节点。
  9. beta.kubernetes.io/vm-type:用于匹配具有相同虚拟机类型的节点。
  10. beta.kubernetes.io/vendor:用于匹配具有相同供应商的节点。
  11. beta.kubernetes.io/instance-class:用于匹配具有相同实例类的节点。
  12. beta.kubernetes.io/os-image:用于匹配具有相同操作系统镜像的节点。
  13. beta.kubernetes.io/architecture:用于匹配具有相同架构的节点。
  14. beta.kubernetes.io/cpu:用于匹配具有相同 CPU 类型的节点。
  15. beta.kubernetes.io/memory:用于匹配具有相同内存类型的节点。

个人理解

  1. Topology只是一个概念,可以对地区、机房、主机等进行一个概念上的区域划分;
  2. Topology实际上还是一个Node标签的Key,与标签一样包含Key和Value;
  3. 例如“kubernetes.io/hostname”可以说它是一个Topology,同样它也是TopologyKey的一个值;
  4. TopologyKey是亲和力的一个参数,就类似于一个标签选择器,用于确定哪些节点与 Pod 匹配;
  5. TopologyKey可以使用Topology来确定具有相同Value的节点;
  6. 但是节点上不同的Key、不同的Value都属于不同的Topology;

应用

  • 案例说明
    • 在Kubernetes集群中,部署的Nginx有4个副本,要求4副本不部署在一起;
  • 编辑yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-nginx
  namespace: default
  labels:
    app: deployment-nginx

spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx-web
          imagePullPolicy: IfNotPresent
          image: registry.cn-beijing.aliyuncs.com/publicspaces/nginx:1.22.1
      restartPolicy: Always
      affinity:                                                                       #定义 Pod 的亲和性设置。
        podAntiAffinity:                                                              #定义 Pod 反亲和性规则。
          requiredDuringSchedulingIgnoredDuringExecution:                             #设置硬反亲和性规则,即在调度时必须满足的条件,但在执行后忽略。
            - topologyKey: kubernetes.io/hostname                                     #指定用于比较的键,这里是 hostname。
              labelSelector:                                                          #定义了需要避免的 Pod 的标签。
                matchExpressions:                                                     #匹配表达式列表。
                  - key: app                                                          #要匹配的Pod标签键。
                    operator: In                                                      #运算符 In,表示节点的标签值必须在给定的列表中。
                    values:
                      - nginx                                                         #包含 nginx 的列表,表示只有当 Pod 的 app 标签值为 nginx 时,Nginx 容器才会被调度到不与具有相同 hostname 的其他 Nginx 容器在同一个节点上。
  replicas: 4
  • 创建服务
kubectl create -f podAnitiAffinity-deployment-nginx.yaml
  • 验证反亲和性
#注意:由于要求4个副本都不部署在一起,这里只有三个节点,所以有一个副本一直处于Pending状态
kubectl get pod -o wide
# NAME                                READY   STATUS    RESTARTS   AGE   IP              NODE     NOMINATED NODE   READINESS GATES
# deployment-nginx-866bd85b89-98w9m   1/1     Running   0          12s   83.12.61.213    k8s-01   <none>           <none>
# deployment-nginx-866bd85b89-c8cp6   1/1     Running   0          12s   83.12.165.197   k8s-03   <none>           <none>
# deployment-nginx-866bd85b89-vdmmj   0/1     Pending   0          12s   <none>          <none>   <none>           <none>
# deployment-nginx-866bd85b89-w9qps   1/1     Running   0          12s   83.12.179.31    k8s-02   <none>           <none>

初始化容器

简介

什么是InitContainers

初始化容器(Init Containers)是Pod中的特殊容器,它们在主容器启动之前运行。
初始化容器的目的是执行一些必要但非关键的初始化任务,如数据同步、环境设置或应用程序配置。
初始化容器完成后,主容器才能启动。

常见应用场景

  1. 数据同步:将数据从外部存储同步到Pod的本地存储。
  2. 依赖安装:安装Pod运行所需但主容器不需要的依赖,如语言运行时或工具。
  3. 环境设置:设置环境变量或配置文件,这些环境变量或配置文件在主容器中使用。
  4. 证书获取:从外部源获取证书,并将其复制到Pod中。
  5. 应用程序配置:执行配置脚本,以确保主容器可以正确启动。

初始化容器的特点

  1. 执行顺序:初始化容器按定义的顺序运行,每个容器都必须成功完成才能启动下一个容器。如果任何初始化容器失败,整个Pod将被标记为失败。
  2. 资源限制:您可以为初始化容器设置资源限制,如CPU和内存。
  3. 重启策略:初始化容器可以设置为AlwaysOnFailureNever。默认情况下,如果初始化容器失败,它将不会重启,但Pod会失败。
  4. 生命周期钩子:初始化容器可以与Pod的生命周期钩子(如PostStartPreStop)集成,以执行特定操作。
  5. 网络策略:初始化容器可以有自己的网络策略,例如使用不同的网络命名空间。
  6. 文件系统:初始化容器可以访问Pod的文件系统,但主容器无法访问初始化容器的文件系统。

注意事项

  • PostStart:依赖主应用的环境,而且并不一定先于Command运行
  • InitContainer:不依赖主应用的环境,可以有更高的权限和更多的工具,一定会在主应用启动之前完成。

应用

初始化数据

在主容器启动之前将数据从外部存储同步到Pod的本地存储。
数据存放在NFS下,共享目录为:/data/nfs/data/temp/,服务地址为:192.168.23.138

  • 准备数据
mkdir -p /data/nfs/data/{temp,nginx}
touch /data/nfs/data/temp/{1..9}.txt
  • 编辑yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-nginx
  namespace: default
  labels:
    app: deployment-nginx

spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      initContainers:
        - name: init-nginx
          imagePullPolicy: IfNotPresent
          image: registry.cn-beijing.aliyuncs.com/publicspaces/busybox:1.28.0
          command:
            - sh
            - -c
            - cp -a /tmp/test/data/* /opt/test/data/
          volumeMounts:
            - mountPath: /tmp/test/data/
              name: nfs-volume
            - mountPath: /opt/test/data/
              name: nfs-volume-nginx
      containers:
        - name: nginx-web
          imagePullPolicy: IfNotPresent
          image: registry.cn-beijing.aliyuncs.com/publicspaces/nginx:1.22.1
          command:
            - sh
            - -c
            - ls /opt/test/data/
          volumeMounts:
            - mountPath: /opt/test/data/
              name: nfs-volume-nginx
      volumes:
        - name: nfs-volume
          nfs:
            path: /data/nfs/data/temp/
            server: 192.168.23.138
        - name: nfs-volume-nginx
          nfs:
            path: /data/nfs/data/nginx/
            server: 192.168.23.138
      restartPolicy: Always
  • 创建服务
kubectl create -f initContainers-data.yaml
  • 查看过程
kubectl describe pod deployment-nginx-6b86b8f7dc-k84zf 
# Name:         deployment-nginx-6b86b8f7dc-k84zf
# Namespace:    default
# Priority:     0
# Node:         k8s-01/192.168.23.138
# Start Time:   Sun, 21 Jul 2024 10:36:27 +0800
# Labels:       app=nginx
#               pod-template-hash=6b86b8f7dc
# Annotations:  cni.projectcalico.org/containerID: e0ccc3c0713a58a96de35fca95788462c9223ef853b8f0aece7511f07b2f29d6
#               cni.projectcalico.org/podIP: 83.12.61.253/32
#               cni.projectcalico.org/podIPs: 83.12.61.253/32
# Status:       Running
# IP:           83.12.61.253
# IPs:
#   IP:           83.12.61.253
# Controlled By:  ReplicaSet/deployment-nginx-6b86b8f7dc
# Init Containers:
#   init-nginx:
#     Container ID:  docker://e07eede1a082e7e2a473422cb549cd2f993a550368e94c965b9082238c9c72fa
#     Image:         registry.cn-beijing.aliyuncs.com/publicspaces/busybox:1.28.0
#     Image ID:      docker-pullable://registry.cn-beijing.aliyuncs.com/publicspaces/busybox@sha256:4cee1979ba0bf7db9fc5d28fb7b798ca69ae95a47c5fecf46327720df4ff352d
#     Port:          <none>
#     Host Port:     <none>
#     Command:
#       sh
#       -c
#       cp -a /tmp/test/data/* /opt/test/data/
#     State:          Terminated
#       Reason:       Completed
#       Exit Code:    0
#       Started:      Sun, 21 Jul 2024 10:36:28 +0800
#       Finished:     Sun, 21 Jul 2024 10:36:28 +0800
#     Ready:          True
#     Restart Count:  0
#     Environment:    <none>
#     Mounts:
#       /opt/test/data/ from nfs-volume-nginx (rw)
#       /tmp/test/data/ from nfs-volume (rw)
#       /var/run/secrets/kubernetes.io/serviceaccount from default-token-q9946 (ro)
# Containers:
#   nginx-web:
#     Container ID:   docker://1f151895db86a04b9509dea1197e263b55d8829033b6090104bbfc7575b7f91f
#     Image:          registry.cn-beijing.aliyuncs.com/publicspaces/nginx:1.22.1
#     Image ID:       docker-pullable://registry.cn-beijing.aliyuncs.com/publicspaces/nginx@sha256:9081064712674ffcff7b7bdf874c75bcb8e5fb933b65527026090dacda36ea8b
#     Port:           <none>
#     Host Port:      <none>
#     State:          Running
#       Started:      Sun, 21 Jul 2024 10:36:29 +0800
#     Ready:          True
#     Restart Count:  0
#     Environment:    <none>
#     Mounts:
#       /opt/test/data/ from nfs-volume-nginx (rw)
#       /var/run/secrets/kubernetes.io/serviceaccount from default-token-q9946 (ro)
# Conditions:
#   Type              Status
#   Initialized       True 
#   Ready             True 
#   ContainersReady   True 
#   PodScheduled      True 
# Volumes:
#   nfs-volume:
#     Type:      NFS (an NFS mount that lasts the lifetime of a pod)
#     Server:    192.168.23.138
#     Path:      /data/nfs/data/temp/
#     ReadOnly:  false
#   nfs-volume-nginx:
#     Type:      NFS (an NFS mount that lasts the lifetime of a pod)
#     Server:    192.168.23.138
#     Path:      /data/nfs/data/nginx/
#     ReadOnly:  false
#   default-token-q9946:
#     Type:        Secret (a volume populated by a Secret)
#     SecretName:  default-token-q9946
#     Optional:    false
# QoS Class:       BestEffort
# Node-Selectors:  <none>
# Tolerations:     node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
#                  node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
# Events:
#   Type    Reason     Age   From               Message
#   ----    ------     ----  ----               -------
#   Normal  Scheduled  14s   default-scheduler  Successfully assigned default/deployment-nginx-6b86b8f7dc-k84zf to k8s-01
#   Normal  Pulled     13s   kubelet            Container image "registry.cn-beijing.aliyuncs.com/publicspaces/busybox:1.28.0" already present on machine
#   Normal  Created    13s   kubelet            Created container init-nginx
#   Normal  Started    13s   kubelet            Started container init-nginx
#   Normal  Pulled     12s   kubelet            Container image "registry.cn-beijing.aliyuncs.com/publicspaces/nginx:1.22.1" already present on machine
#   Normal  Created    12s   kubelet            Created container nginx-web
#   Normal  Started    12s   kubelet            Started container nginx-web
  • 查看数据
ll /data/nfs/data/nginx/
# total 0
# -rw-r--r--. 1 root root 0 Jul 21 10:55 1.txt
# -rw-r--r--. 1 root root 0 Jul 21 10:55 2.txt
# -rw-r--r--. 1 root root 0 Jul 21 10:55 3.txt
# -rw-r--r--. 1 root root 0 Jul 21 10:55 4.txt
# -rw-r--r--. 1 root root 0 Jul 21 10:55 5.txt
# -rw-r--r--. 1 root root 0 Jul 21 10:55 6.txt
# -rw-r--r--. 1 root root 0 Jul 21 10:55 7.txt
# -rw-r--r--. 1 root root 0 Jul 21 10:55 8.txt
# -rw-r--r--. 1 root root 0 Jul 21 10:55 9.txt

ll /data/nfs/data/temp/
# total 0
# -rw-r--r--. 1 root root 0 Jul 21 10:55 1.txt
# -rw-r--r--. 1 root root 0 Jul 21 10:55 2.txt
# -rw-r--r--. 1 root root 0 Jul 21 10:55 3.txt
# -rw-r--r--. 1 root root 0 Jul 21 10:55 4.txt
# -rw-r--r--. 1 root root 0 Jul 21 10:55 5.txt
# -rw-r--r--. 1 root root 0 Jul 21 10:55 6.txt
# -rw-r--r--. 1 root root 0 Jul 21 10:55 7.txt
# -rw-r--r--. 1 root root 0 Jul 21 10:55 8.txt
# -rw-r--r--. 1 root root 0 Jul 21 10:55 9.txt

临时容器

简介

什么是临时容器

临时容器(ephemeral container)是一种特殊类型的容器,它在主容器(primary container)启动后由 Kubernetes 动态创建和销毁。
临时容器是在原有的Pod上添加一个临时的Container,这个临时Container中包含了排查问题的工具,可以利用它排查Pod中容器的问题。
临时容器的生命周期完全依赖于主容器,它们不会独立于主容器存在。
临时容器在Kubernetes1.16版本以上自动开启

常见应用场景

  1. 执行特定任务:临时容器可以在主容器启动后立即执行一些特定的任务,例如清理、日志收集、监控等。一旦任务完成,临时容器就会自动销毁。
  2. 测试和调试:在开发和测试环境中,临时容器可以用来执行测试代码或调试工具,而不需要将这些工具永久集成到主容器中。
  3. 清理工作:临时容器可以用来执行清理工作,例如清理临时文件或执行垃圾回收。

开启临时容器

检查临时容器是否开启

kubelet -h | grep EphemeralContainers
# EphemeralContainers=true|false (ALPHA - default=false)
#ALPHA - default=false,表示并未开启临时容器

开启临时容器–kubeadm部署

所有节点都要操作

  • 编辑/etc/kubernetes/manifests/kube-apiserver.yaml

注意:这里为master节点修改

vim /etc/kubernetes/manifests/kube-apiserver.yaml
# spec:
#   containers:
#   - command:
#     - kube-apiserver
#     - --advertise-address=192.168.23.138
#     - --allow-privileged=true
#     - --authorization-mode=Node,RBAC
#     - --client-ca-file=/etc/kubernetes/pki/ca.crt
#     - --enable-admission-plugins=NodeRestriction
#     - --enable-bootstrap-token-auth=true
#     - --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt
#     - --etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt
#     - --etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key
#     - --etcd-servers=https://127.0.0.1:2379
#     - --insecure-port=0
#     - --kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt
#     - --kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key
#     - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
#     - --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.crt
#     - --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client.key
#     - --requestheader-allowed-names=front-proxy-client
#     - --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt
#     - --requestheader-extra-headers-prefix=X-Remote-Extra-
#     - --requestheader-group-headers=X-Remote-Group
#     - --requestheader-username-headers=X-Remote-User
#     - --secure-port=6443
#     - --service-account-issuer=https://kubernetes.default.svc.cluster.local
#     - --service-account-key-file=/etc/kubernetes/pki/sa.pub
#     - --service-account-signing-key-file=/etc/kubernetes/pki/sa.key
#     - --service-cluster-ip-range=10.96.0.0/16
#     - --tls-cert-file=/etc/kubernetes/pki/apiserver.crt
#     - --tls-private-key-file=/etc/kubernetes/pki/apiserver.key
#添加一行
#     - --feature-gates=EphemeralContainers=true
  • 编辑/etc/sysconfig/kubelet
cat /var/lib/kubelet/kubeadm-flags.env

vim /etc/sysconfig/kubelet
#如下配置
# KUBELET_EXTRA_ARGS="--pod-infra-container-image=registry.aliyuncs.com/google_containers/pause:3.2 --feature-gates=EphemeralContainers=true"
  • 编辑/etc/kubernetes/manifests/kube-scheduler.yaml

注意:这里为master节点修改

vim /etc/kubernetes/manifests/kube-scheduler.yaml
# spec:
#   containers:
#   - command:
#     - kube-scheduler
#     - --authentication-kubeconfig=/etc/kubernetes/scheduler.conf
#     - --authorization-kubeconfig=/etc/kubernetes/scheduler.conf
#     - --bind-address=127.0.0.1
#     - --kubeconfig=/etc/kubernetes/scheduler.conf
#     - --leader-elect=true
#     - --port=0
#添加一行
#     - --feature-gates=EphemeralContainers=true
  • 重启kubelet
systemctl daemon-reload
systemctl restart kubelet

开启临时容器–二进制部署

所有节点都要操作

  • 编辑/usr/lib/systemd/system/kube-apiserver.service
--feature-gates=EphemeralContainers=true
  • 编辑/usr/lib/systemd/system/kube-controller-manager.service
--feature-gates=EphemeralContainers=true
  • 编辑/usr/lib/systemd/system/kube-scheduler.service
--feature-gates=EphemeralContainers=true
  • 编辑/usr/lib/systemd/system/kube-proxy.service
--feature-gates=EphemeralContainers=true
  • 编辑/etc/kubernetes/kubelet-conf.yml
featureGates:
  EphemeralContainers: true
  • 重启服务
systemctl daemon-reload
systemctl restart kubelet kube-apiserver kube-scheduler kube-controller-manager kube-proxy

应用

编辑yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-redis-nginx
  namespace: default
  labels:
    app: deployment-redis-nginx

spec:
  selector:
    matchLabels:
      app: nginx-redis
  template:
    metadata:
      labels:
        app: nginx-redis
    spec:
      containers:
        - name: nginx
          imagePullPolicy: IfNotPresent
          image: registry.cn-beijing.aliyuncs.com/publicspaces/nginx:1.22.1
        - name: redis
          imagePullPolicy: IfNotPresent
          image: registry.cn-beijing.aliyuncs.com/publicspaces/redis:6.2.6
      restartPolicy: Always
      shareProcessNamespace: true                                               #选项可能会带来安全风险,因为它允许容器之间进行更直接的通信;当设置为 true 时,Pod 中的所有容器将共享同一个进程命名空间,这意味着它们可以使用 IPC 机制进行直接通信。

创建服务

kubectl create -f deployment-nginx.yaml

查看服务

kubectl get pod
# NAME                              READY   STATUS    RESTARTS   AGE
# deployment-nginx-75fc99b4-fld89   1/1     Running   0          23m

下载镜像

docker pull registry.cn-beijing.aliyuncs.com/publicspaces/debug-tools:latest

管理容器

  • Pod中包含一个容器
#格式:
kubectl debug Pod的名称 -it --image=使用哪个镜像生产临时容器

#举例:
kubectl debug deployment-nginx-75fc99b4-fld89 -ti --image=registry.cn-beijing.aliyuncs.com/dotbalo/debug-tools:latest
# Defaulting debug container name to debugger-ttzfq.
# 如果看不到命令提示符,请尝试按enter键
# If you don't see a command prompt, try pressing enter.
# (01:42 deployment-nginx-75fc99b4-fld89:/) 
  • Pod中包含多个容器

这种方法创建的临时容器不会自动删除

#格式:
kubectl debug Pod的名称 -it --copy-to="临时容器名称" --container="容器名称" --image=使用哪个镜像生产临时容器

#举例:
kubectl debug deployment-redis-nginx-b45d5c555-hcpgw -it --copy-to="debugger" --container="nginx" --image=registry.cn-beijing.aliyuncs.com/dotbalo/debug-tools:latest
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值