K8s<五>

七、Kubernetes Pod 资源

1、Pod 服务状态

1、无状态服务
  • 是指该服务运行的实例不会在本地存储需要持久化的数据,并且多个实例对于同一个请求响应的结果是完全一致的。

  • 多个实例可以共享相同的持久化数据。例如:nginx 实例,tomcat 实例等

  • 相关的 k8s 资源有:ReplicaSet、ReplicationController、Deployment等,由于是无状态服务,所以这些控制器创建的 pod 序号都是随机值。并且在缩容的时候并不会明确缩容某一个pod,而是随机的,因为所有实例得到的返回值都是一样,所以缩容任何一个pod都可以。

2、有状态服务
  • 宠物和牛的类比,农场主的牛如果病了可以丢掉再重新买一头,如果宠物主的宠物病死了是没法找到一头一模一样的宠物的。有状态服务可以说是需要数据存储功能的服务、或者指多线程类型的服务,队列等。(mysql数据库、kafka、zookeeper等)

  • 每个实例都需要有自己独立的持久化存储,并且在 k8s 中是通过申明模板来进行定义。持久卷申明模板在创建 pod 之前创建,绑定到 pod 中,模板可以定义多个。

 volumeClaimTemplates:
   - metadata:
      name: zookeeper
    spec:
      selector:
        matchLabels:
          app: zookeeper
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 3Gi
  • 有状态的 pod 是用来运行有状态应用的,所以其在数据卷上存储的数据非常重要,在 Statefulset 缩容时删除这个声明将是灾难性的,特别是对于 Statefulset 来说,缩容就像减少其 replicas 数值一样简单。基于这个原因,当你需要释放特定的持久卷时,需要手动删除对应的持久卷声明。

  • 相关的 k8s 资源为:statefulSet,由于是有状态的服务,所以每个 pod 都有特定的名称和网络标识。比如 pod 名是由 statefulSet名+有序的数字组成(0、1、2…)

  • 在进行缩容操作的时候,可以明确知道会缩容哪一个 pod,从数字最大的开始。并且 Statefulset 在有实例不健康的情况下是不允许做缩容操作的。

  • StatefulSet 缩容,任何时候只会操作 一个 pod 实例,所以有状态应用的缩容不会很迅速。举例来说, 一个分布式存储应用若同时下线多个节点 ,则可能导致其数据丢失 。 比如说一个数据项副本数设置为 2 的数据存储应用, 若同时有两个节点下线,一份数据记录就会丢失,如果它正好保存在这两个节点上 。 若缩容是线性的 ,则分布式存储应用就有时间把丢失的副本复制到其他节点 ,保证数据不会丢失。

2、Pod 基本介绍

  • kubernetes 中的一切都可以理解为是一种资源对象,pod,rc,service,都可以理解是 一种资源对象。

  • pod 由一个叫 ”pause“ 的根容器,加上一个或多个用户自定义的容器构造。pause 的状态带便了这一组容器的状态,pod里多个业务容器共享pod的Ip和数据卷。

  • kubernetes 环境下,pod 是容器的载体,所有的容器都是在 pod 中被管理,一个或多个容器放在 pod 里作为一个单元方便管理。docker 和 kubernetes 也不是一家公司的,如果做一个编排部署的工具,为了更好的管理别人公司开发的产品,然后就把 docker 容器放在了 pod 里,在 kubernetes 的集群环境下,直接管理 pod,然后对于docker 容器的操作,封装在 pod 里,不直接操作。

1、Pod 的创建过程
  • Pod 是 Kubernetes 的基础单元,了解其创建的过程,更有助于理解系统的运作。

    • ①用户通过 kubectl 或其他 API 客户端提交 Pod Spec 给 API Server。
    • ②API Server 尝试将 Pod 对象的相关信息存储到 etcd 中,等待写入操作完成,API Server 返回确认信息到客户端。
    • ③API Server 开始通告 etcd 中的状态变化。
    • ④所有的 Kubernetes 组件通过 “watch” (动态监控) etcd 机制跟踪检查 API Server 上的相关信息变动。
    • ⑤kube-scheduler(调度器)通过其 “watch”(动态监控)etcd 检测到 API Server 创建了新的 Pod 对象但是没有绑定到任何工作节点。
    • ⑥kube-scheduler 为 Pod 对象挑选一个工作节点并将结果信息更新到 API Server。
    • ⑦调度结果新消息由 API Server 更新到 etcd,并且 API Server 也开始反馈该 Pod 对象的调度结果。
    • ⑧Pod 被调度到目标工作节点上的 kubelet 尝试在当前节点上调用 docker engine 进行启动容器,并将容器的状态结果返回到 API Server。
    • ⑨API Server 将 Pod 信息存储到 etcd 系统中。
    • ⑩在 etcd 确认写入操作完成,API Server 将确认信息发送到相关的 kubelet。
2、Pod 类型
  • 静态Pod不存放在etcd存储里,而是存放在某个具体的 Node 上的一个具体文件中,并且只在此 Node 上启动运行。静态 Pod 是由 kubelet 进行管理的仅存在于特定 Node 上的 pod.它们不能通过 API Server 进行管理,无法与 ReplicationController,Deployment 或者 DaemonSet 进行关联,也无法进行健康检查。不常用,所以了解就好

  • 普通的 Pod 一旦被创建,就会被存储到 etcd 中,随后会被 Kubernetes Master 调度到某个具体的 Node 上并进行绑定(Binding),该 Node 上的 kubelet 进程会将其实例化成一组相关的 Docker 容器并启动起来。当 Pod 里的某个容器停止时,Kubernetes 会自动检测到这个问题并且重新启动这个 Pod(重启Pod里的所有容器);如果 Pod 所在的 Node 宕机,则会将这个 Node 上的所有 Pod 重新调度到其他节点上运行。

3、Pod、容器与Node的关系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ow3rpxoG-1610418200971)(assets/8198f5ace2255bd4f515e3db6362cd5d.png)]

  • 定义一个简单的Pod资源文件:
apiVersion: v1
kind: Pod
metadata:
  name: myweb
  labels:
    name: myweb
spec:
  containers:
  - name: myweb
    image: kubeguide/tomcat-app: v1
    ports:
    - containerPort: 8080
    env:
    - name: MYSQL_SERVICE_HOST
      value: 'mysql'
    - name: MYSQL_SERVICE_PORT
      value: '3306'
  • kind 为 pod 表明这是一个Pod的定义,

  • metadata 里的 name 属性为 Pod 的名字,metadata 里还能定义资源对象的标签(Label),这里声明myweb拥有一个name=myweb的标签(Label)。

  • Pod里包含的容器组的定义则在spec一节中声明,这里定义了一个名字为myweb,对应镜像为kubeguide/tomcat-app: v1的容器,该容器注入了名为MYSQL_SERVICE_HOST=‘mysql’ 和 MYSQL_SERVICE_PORT='3306’的环境变量(env关键字),并且在8080端口(containerPort)上启动容器进程。

  • Pod的IP加上这里的容器端口,就组成了一个新的概念——Endpoint(端点),它代表着此Pod里的一个服务进程的对外通信地址。一个Pod也存在着具有多个Endpoint的情况,比如我们把 Tomcat 定义为一个 Pod 时,可以对外暴露管理端口与服务端口这两个 Endpoint。

  • Docker 里的 Volume 在 Kubernetes 里也有对应的概念—— Pod Volume,Pod Volume 有一些扩展,比如可以用分布式文件系统 GlusterFS 等实现后端存储功能;Pod Volume 是定义在 Pod 之上,然后被各个容器挂载到自己的文件系统中的。对于Pod Volume的定义我们后面会讲到。

  • 这里顺便提一下Event 概念,Event是一个事件的记录,记录了事件的最早产生时间、最后重现时间、重复次数、发起者、类型,以及导致此事件的原因等众多信息。Event 通常会关联到某个具体的资源对象上,是排查故障的重要参考信息,当我们发现某个Pod迟迟无法创建时,可以用 kubectl describe pod xxx来查看它的描述信息,用来定位问题的原因。

  • 每个Pod都可以对其能使用的服务器上的计算资源设置限额,当前可以设置限额的计算资源有CPU和Memory两种,其中CPU的资源单位为CPU(Core)的数量,是一个绝对值。对于容器来说一个CPU的配额已经是相当大的资源配额了,所以在Kubernetes里,通常以千分之一的CPU配额为最小单位,用m来表示。通常一个容器的CPU配额被定义为100-300m,即占用0.1-0.3个CPU。与CPU配额类似,Memory配额也是一个绝对值,它的单位是内存字节数
    对计算资源进行配额限定需要设定以下两个参数:

    • Requests:该资源的最小申请量,系统必须满足要求。
    • Limits:该资源最大允许使用的量,不能超过这个使用限制,当容器试图使用超过这个量的资源时,可能会被Kubernetes Kill并重启。
  • 通常应该把Requests设置为一个比较小的数值,满足容器平时的工作负载情况下的资源需求,而把Limits设置为峰值负载情况下资源占用的最大量。下面是一个资源配额的简单定义:

spec:
  containers:
  - name: db
    image: mysql
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"
  • 最小0.25个CPU及64MB内存,最大0.5个CPU及128MB内存。
4、pod 定义相关资源说明及示例
  • 下面是一个完整的 yaml 格式定义的文件,注意格式,子集包含关系,不要有tab,要用空格。不是所有的元素都要写,按照实际应用场景配置即可。
apiVersion: v1            # 版本
kind: pod                 # 类型,pod
metadata:                 # 元数据
  name: String            # 元数据,pod的名字
  namespace: String       # 元数据,pod的命名空间
  labels:                 # 元数据,标签列表
    - name: String        # 元数据,标签的名字
  annotations:            # 元数据,自定义注解列表
    - name: String        # 元数据,自定义注解名字
spec:                     # pod中容器的详细定义
  containers:             # pod中的容器列表,可以有多个容器
  - name: String
    image: String         # 容器中的镜像
    imagesPullPolicy: [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: Srting
        memory: String
      requeste:
        cpu: String
        memory: String
    livenessProbe:         # pod内容器健康检查的设置
      exec:
        command: [String]
      httpGet:             # 通过httpget检查健康
        path: String
        port: number
        host: String
        scheme: Srtring
        httpHeaders:
        - name: Stirng
          value: String 
      tcpSocket:             # 通过tcpSocket检查健康
        port: number
      initialDelaySeconds: 0 # 首次检查时间
      timeoutSeconds: 0      # 检查超时时间
      periodSeconds: 0       # 检查间隔时间
      successThreshold: 0
      failureThreshold: 0
      securityContext:       # 安全配置
        privileged: falae
    restartPolicy: [Always|Never|OnFailure] # 重启策略
    nodeSelector: object     # 节点选择
    imagePullSecrets:
    - name: String
    hostNetwork: false       # 是否使用主机网络模式,默认否
  volumes:                   # 在该pod上定义共享存储卷
  - name: String
    meptyDir: {}
    hostPath:
      path: string
    secret:                  #  类型为 secret 的存储卷
      secretName: String
      item:
      - key: String
        path: String
    configMap:               # 类型为configMap的存储卷
      name: String
      items:
      - key: String
        path: String  
5、Pod 中 command 和 args
    command: ['sh']        # 启动容器的运行命令,将覆盖容器中的Entrypoint,对应Dockefile中的ENTRYPOINT  
    args: ["$(str)"]       # 启动容器的命令参数,对应 Dockerfile 中 CMD 参数  
    env:                   # 指定容器中的环境变量  
    - name: str            # 变量的名字  
      value: "/etc/run.sh" # 变量的值   sh /etc/run.sh
Image EntrypointImage CmdContainer commandContainer argsCommand run
[/ep-1][foo bar][ep-1 foo bar]
[/ep-1][foo bar][/ep-2][ep-2]
[/ep-1][foo bar][zoo boo][ep-1 zoo boo]
[/ep-1][foo bar][/ep-2][zoo boo][ep-2 zoo boo]
6、 Pod 定义 apiVsersion
1、查看当前可用的API版本
[root@k8s-master ~]# kubectl api-versions
  • 1.6版本之前 apiVsersion:extensions/v1beta1

  • 1.6版本到1.9版本之间:apps/v1beta1

  • 1.9版本之后: apps/v1

2、各种 apiVersion 的含义
1、alpha 内测版
  • 该软件可能包含错误。启用一个功能可能会导致bug
  • 随时可能会丢弃对该功能的支持,恕不另行通知
2、beta 公测版
  • 软件经过很好的测试。启用功能被认为是安全的。
  • 默认情况下功能是开启的
  • 细节可能会改变,但功能在后续版本不会被删除
3、stable 稳定版
  • 该版本名称命名方式:vX 这里X是一个整数

  • 稳定版本、放心使用

  • 将出现在后续发布的软件版本中

4、v1

  • Kubernetes API 的稳定版本,包含很多核心对象:pod、service等
5、apps/v1beta2
  • 在kubernetes1.8版本中,新增加了 apps/v1beta2 的概念,apps/v1beta1 同理

  • DaemonSet,Deployment,ReplicaSet 和 StatefulSet 的当时版本迁入 apps/v1beta2,兼容原有的 extensions/v1beta1

6、apps/v1
  • 在 kubernetes1.9 版本中,引入 apps/v1,deployment 等资源从 extensions/v1beta1, apps/v1beta1 和 apps/v1beta2 迁入 apps/v1,原来的 v1beta1 等被废弃。

  • apps/v1 代表:包含一些通用的应用层的api组合,如:Deployment, RollingUpdate, and ReplicaSet

7、batch/v1
  • 代表 job 相关的 api 组合

  • 在 kubernetes1.8 版本中,新增了 batch/v1beta1,后 CronJob 已经迁移到了 batch/v1beta1,然后再迁入 batch/v1

8、autoscaling/v1
  • 代表自动扩缩容的 api 组合,kubernetes1.8 版本中引入。

  • 这个组合中后续的 alpha 和 beta 版本将支持基于memory 使用量、其他监控指标进行扩缩

9、extensions/v1beta1
  • deployment 等资源在1.6版本时放在这个版本中,后迁入到 apps/v1beta2,再到 apps/v1 中统一管理
10、certificates.k8s.io/v1beta1
  • 安全认证相关的api组合
11、authentication.k8s.io/v1
  • 资源鉴权相关的api组合

3、Pod 生命周期

1、pod 的四种状态
状态值描述
PendingAPIserver已经创建该server,但pod内有一个或多个容器的镜像还未创建,可能在下载中。
RunningPod内所有的容器已创建,所有容器都是运行状态
FailedPod内所有容器都已退出,其中至少有一个容器退出失败
Unknown由于某种原因无法获取Pod的状态,比如 网络不通。
2、Kubernetes 排错之 Pod 异常
  • 一般来说,无论 Pod 处于什么异常状态,都可以执行以下命令来查看 Pod 的状态
1、查看 Pod 的配置是否正确
[root@k8s-master ~]# kubectl get pod <pod-name> -o yaml 
2、查看 Pod 的事件
[root@k8s-master ~]# kubectl describe pod <pod-name> 
3、查看容器日志
[root@k8s-master ~]# kubectl logs <pod-name> [-c <container-name>]
kubectl logs test-pod -c c1-name/  -- /bin/bash    /-c c1-name -- /bin/bash  / -c c2-name --  /bin/bash 
  • 这些事件和日志通常都会有助于排查 Pod 发生的问题。
2、Pod 一直处于 Pending 状态
  • Pending 说明 Pod 还没有调度到某个 Node 上面。查看到当前 Pod 的事件,进而判断为什么没有调度。可能的原因包括
    • 资源不足,集群内所有的 Node 都不满足该 Pod 请求的 CPU、内存、GPU 等资源
    • HostPort 已被占用,通常推荐使用 Service 对外开放服务端口
3、Pod 一直处于 Waiting 或 ContainerCreating 状态
  • 查看到当前 Pod 的事件。可能的原因包括

    • 镜像拉取失败
    • 配置了错误的镜像
    • Kubelet 无法访问镜像(国内环境访问 gcr.io 需要特殊处理)
    • 私有镜像的密钥配置错误
    • 镜像太大,拉取超时(可以适当调整 kubelet 的 --image-pull-progress-deadline 和 --runtime-request-timeout 选项)
  • CNI 网络错误,一般需要检查 CNI 网络插件的配置,比如

    • 无法配置 Pod 网络

    • 无法分配 IP 地址

  • 容器无法启动,需要检查是否打包了正确的镜像或者是否配置了正确的容器参数

4、Pod 处于 ImagePullBackOff 状态
  • 这通常是镜像名称配置错误或者私有镜像的密钥配置错误导致。这种情况可以使用 docker pull 来验证镜像是否可以正常拉取。

  • 如果是私有镜像,需要首先创建一个 docker-registry 类型的 Secret

[root@k8s-master ~]# kubectl create secret docker-registry my-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
  • 然后在容器中引用这个 Secret
spec:
  containers:
  - name: private-reg-container
    image: <your-private-image>
  imagePullSecrets:
  - name: my-secret
5、Pod 一直处于 CrashLoopBackOff 状态
  • CrashLoopBackOff 状态说明容器曾经启动了,但又异常退出了。此时可以先查看一下容器的日志
[root@k8s-master ~]# kubectl logs <pod-name>
[root@k8s-master ~]# kubectl logs --previous <pod-name>
  • 这里可以发现一些容器退出的原因,比如

    • 容器进程退出
    • 健康检查失败退出
  • 此时如果还未发现线索,还可以到容器内执行命令来进一步查看退出原因

[root@k8s-master ~]# kubectl exec cassandra -- cat /var/log/cassandra/system.log
  • 如果还是没有线索,那就需要 SSH 登录该 Pod 所在的 Node 上,查看 Kubelet 或者 Docker 的日志进一步排查了
# 查询 Node
[root@k8s-master ~]# kubectl get pod <pod-name> -o wide
5、Pod 处于 Error 状态
  • 依赖的 ConfigMap、Secret 或者 PV 等不存在
  • 请求的资源超过了管理员设置的限制,比如超过了 LimitRange 等
  • 违反集群的安全策略,比如违反了 PodSecurityPolicy 等
  • 容器无权操作集群内的资源,比如开启 RBAC 后,需要为 ServiceAccount 配置角色绑定
6、Pod 处于 Terminating 或 Unknown 状态
  • 从 v1.5 开始,Kubernetes 不会因为 Node 失联而删除其上正在运行的 Pod,而是将其标记为 Terminating 或 Unknown 状态。想要删除这些状态的 Pod 有三种方法:
    • 从集群中删除该 Node。使用公有云时,kube-controller-manager 会在 VM 删除后自动删除对应的 Node。而在物理机部署的集群中,需要管理员手动删除 Node(如 kubectl delete node 。
    • Node 恢复正常。Kubelet 会重新跟 kube-apiserver 通信确认这些 Pod 的期待状态,进而再决定删除或者继续运行这些 Pod。
    • 用户强制删除。用户可以执行 kubectl delete pods --grace-period=0 --force 强制删除 Pod。除非明确知道 Pod 的确处于停止状态(比如 Node 所在 VM 或物理机已经关机),否则不建议使用该方法。特别是 StatefulSet 管理的 Pod,强制删除容易导致脑裂或者数据丢失等问题。
7、Pod 行为异常
  • 这里所说的行为异常是指 Pod 没有按预期的行为执行,比如没有运行 podSpec 里面设置的命令行参数。这一般是 podSpec yaml 文件内容有误,可以尝试使用 --validate 参数重建容器,比如
[root@k8s-master ~]# kubectl delete pod mypod
[root@k8s-master ~]# kubectl create --validate -f mypod.yaml
  • 也可以查看创建后的 podSpec 是否是对的,比如
[root@k8s-master ~]# kubectl get pod mypod -o yaml
8、修改静态 Pod 的 Manifest 后未自动重建
  • Kubelet 使用 inotify (监控文件系统) 机制检测 /etc/kubernetes/manifests 目录(可通过 Kubelet 的 --pod-manifest-path 选项指定)中静态 Pod 的变化,并在文件发生变化后重新创建相应的 Pod。但有时也会发生修改静态 Pod 的 Manifest 后未自动创建新 Pod 的情景,此时一个简单的修复方法是重启 Kubelet。

  • Inotify 可用于检测单个文件,也可以检测整个目录。当检测的对象是一个目录的时候,目录本身和目录里的内容都会成为检测的对象。此种机制的出现的目的是当内核空间发生某种事件之后,可以立即通知到用户空间。方便用户做出具体的操作

4、Pod 重启策略

  • Pod的重启策略应用于Pod内的所有容器,由Pod所在Node节点上的Kubelet进行判断和重启操作。重启策略有以下三种:
重启策略描述
Always容器失效时,即重启 (不能正常提供服务)
OnFailure容器终止运行,且退出码不为0 时重启 退出码是0(不重启)
Never不重启

5、Pod 健康检查

1、健康检测介绍
  • Kubernetes内部通过2种探针,实现了对Pod健康的检查
    • LivenessProbe探针:判断容器是否存活(running)
      • 表示container是否处于live状态。如果 LivenessProbe失败,LivenessProbe将会通知kubelet对应的container不健康了。随后kubelet将kill掉 container,并根据RestarPolicy进行进一步的操作。默认情况下LivenessProbe在第一次检测之前初始化值为 Success,如果container没有提供LivenessProbe,则也认为是Success;
    • ReadinessProbe探针: 用于判断容器是否启动完成(ready)
      • 表示container是否以及处于可接受service请求的状态了。如 果ReadinessProbe失败,endpoints controller将会从service所匹配到的endpoint列表中移除关于这个container的IP地址。因此对于Service匹配到的 endpoint的维护其核心是ReadinessProbe。默认Readiness的初始值是Failure,如果一个container没有提供 Readiness则被认为是Success。
  • Kubernetes 内部2种探针结果也有三个固定的可选值:
    • Success:表示通过检测
    • Failure:表示没有通过检测
    • Unknown:表示检测没有正常进行
  • Kubernetes 内部2种探针的三种健康的检查方法
    • ExecAction:在container中执行指定的命令。当其执行成功时,将其退出码设置为0;
    • TCPSocketAction:执行一个TCP检查使用container的IP地址和指定的端口作为socket。如果端口处于打开状态视为成功
    • HTTPGetAcction:执行一个HTTP默认请求使用container的IP地址和指定的端口以及请求的路径作为url,用户可以通过host参数设置请求的地址,通过scheme参数设置协议类型(HTTP、HTTPS)如果其响应代码在200~400之间,设为成功。
  • Kubernetes 内部2种探针用法都一样,拥有相同的参数和相同的监测方式。
    • initialDelaySeconds:用来表示初始化延迟的时间,也就是告诉监测从多久之后开始运行,单位是秒
    • timeoutSeconds: 用来表示监测的超时时间,如果超过这个时长后,则认为监测失败
2、健康检测测试
  • 针对LivenessProbe如何使用,请看下面的几种方式,如果要使用ReadinessProbe只需要将livenessProbe修改为readinessProbe即可

  • LivenessProbe探针通过三种方式来检查容器是否健康

1、容器内部执行命令
  • ExecAction:在容器内部执行一个命令,如果返回码为0,则表示健康
apiVersion: v1
kind: Pod
metadata:
  name: liveness
spec:
  containers:
  - name: liveness
    image: busybox
    args: 
    - "/bin/sh"
    - "-c"
    - "echo ok > /tmp/healthy; sleep 10; rm - rf /tmp/healthy; sleep 3600"
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      initialDelaySeconds: 15   # 用来表示初始化延迟的时间,也就是告诉监测从容器启动之后延迟多久进行liveness探测,单位是秒
      timeoutSeconds: 1     # 用来表示监测的超时时间,如果超过这个时长后,则认为监测失败
      periodSeconds: 20     # 检测间隔时间
# 查看pod重启情况
kubectl get pods -w
2、通过IP 和port
  • TcpAction:通过IP 和port ,如果能够和容器建立连接则表示容器健康
apiVersion: v1
kind: Pod
metadata:
  name: pod-with-healthcheck
spec:
  containers:
  - name: nginx
    image: nginx
    ports:
    - containerPort: 80
    livenessProbe:
      tcpSocket:
        port: 80
      initialDelaySeconds: 15
      timeoutSeconds: 1   
# 查看pod重启情况
kubectl get pods -w
==============================================================================================

apiVersion: v1
kind: Pod
metadata:
 name: pod-with-healthcheck
spec:
  containers:
  - name: nginx
    image: nginx
    ports:
    - containerPort: 80
    livenessProbe:
      tcpSocket:
        port: 8080
      initialDelaySeconds: 15
      timeoutSeconds: 1   

# 查看pod重启情况
kubectl get pods -w
3、获取状态码
  • HttpGetAction:发送一个http Get请求(ip+port+请求路径)如果返回状态吗在200-400之间则表示健康
apiVersion: v1
kind: Pod
metadata:
 name: pod-with-healthcheck
spec:
  containers:
  - name: nginx
    image: nginx
    ports:
    - containerPort: 80
    livenessProbe:
      httpGet:
        path: /_status/healthz  # 请求路径
        port: 80
      initialDelaySeconds: 15
      timeoutSeconds: 1   

6、Pod 调度策略

1、默认的scheduler的调度过程是通过自己的预设来影响预选、优选过程,从而实现符合我们期望的调度结果

  • 预选策略:从所有节点当中选择基本符合选择条件的节点。
  • 优选函数:在众多符合基本条件的节点中使用优选函数,计算节点各自的得分,通过比较进行排序。从最高得分的节点中随机选择出一个作为Pod运行的节点。

2、影响调度方式

  • 节点选择器:NodeSelector,甚至可以设置nodename来选择节点本身。

  • 亲和性调度:NodeAffinity(节点亲和性)、podAffinity(Pod亲和性)、PodAntiAffinity(Pod的反亲和性)

  • 污点和容忍度:Taint、toleration

1、Pod 调动到某些节点上
1、首先通过 kubectl 给 node 打上标签
格式:
kubectl label nodes <node-name> <label-key>=<label-value>
[root@k8s-master ~]# kubectl label nodes k8s-node01 zone=sh
[root@k8s-master ~]# kubectl get nodes --show-labels
2、通过 nodeSelector 调度 pod 到 node
  • Pod的定义中通过nodeSelector指定label标签,pod将会只调度到具有该标签的node之上
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    env: test
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  nodeSelector:
    disktype: ssd
  • 这个例子中pod只会调度到具有 disktype=ssd 的 node 上面.
  • 验证 节点调度
[root@k8s-master ~]# vim pod-demo.yaml
# 内容为
apiVersion: v1
kind: Pod
metadata:
  name: pod-demo
  labels:
    app: myapp
    tier: frontend
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
  nodeSelector:
    disktype: harddisk


[root@k8s-master ~]# kubectl apply -f pod-demo.yaml 
[root@k8s-master ~]# kubectl get pods

[root@k8s-master ~]# kubectl describe pod  pod-demo
# 运行结果:
Warning  FailedScheduling  2m3s (x25 over 3m15s)  default-scheduler  0/3 nodes are available: 3 node(s) didn't match node selector.

# 打上标签
[root@k8s-master ~]# kubectl label node k8s-node02 disktype=harddisk

# 正常启动
[root@k8s-master ~]# kubectl get pods
2、Node 间亲和性(Affinity)调度
1、Node 亲和性介绍
  • Affinity/anti-affinity node 相对于nodeSelector机制更加的灵活和丰富
    • 表达的语法:支持In,NotIn,Exists,DoesNotExist,Gt,Lt.
    • 支持soft(preference)和hard(requirement),
      • hard表示pod sheduler到某个node上时必须满足的亲和性设置.
      • soft表示scheduler的时候,当无法满足节点的时候,会选择非 nodeSelector 匹配的节点.
      • requiredDuringSchedulingIgnoredDuringExecution 硬亲和性 必须满足亲和性
      • preferredDuringSchedulingIgnoredDuringExecution 软亲和性 能满足最好,不满足也没关系。
    • nodeAffinity 的基础上添加多个 nodeSelectorTerms 字段,调度的时候 Node 只需要 nodeSelectorTerms 中的某一个符合条件就符合 nodeAffinity 的规则.在nodeSelectorTerms 中添加 matchExpressions,需要可以调度的Node是满足 matchExpressions 中表示的所有规则.
2、硬亲和性
  • matchExpressions : 匹配表达式,这个标签可以指定一段,例如pod中定义的key为zone,operator为In(包含那些),values为 foo和bar。就是在node节点中包含foo和bar的标签中调度

  • matchFields : 匹配字段,不过可以不定义标签值,可以定义匹配在 node 有 zone 标签值为 foo 或 bar 值的节点上运行 pod

[root@k8s-master ~]# vim pod-nodeaffinity-demo.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-node-affinity-demo
  labels:
    app: myapp
    tier: frontend
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: zone
            operator: In
            values:
            - foo
            - bar

[root@k8s-master ~]# kubectl apply -f pod-nodeaffinity-demo.yaml

[root@k8s-master ~]# kubectl describe pod pod-node-affinity-demo
# 运行结果:
Warning  FailedScheduling  2s (x8 over 20s)  default-scheduler  0/3 nodes are available: 3 node(s) didn't match node selector.

# 给其中一个node打上foo的标签
[root@k8s-master ~]# kubectl label node k8s-node01 zone=foo

# 正常启动
[root@k8s-master ~]# kubectl get pods
3、软亲和性
[root@k8s-master ~]# vim pod-nodeaffinity-demo-2.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-node-affinity-demo-2
  labels:
    app: myapp
    tier: frontend
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
  affinity:
    nodeAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - preference:
          matchExpressions:
          - key: zone
            operator: In
            values:
            - foo
            - bar
        weight: 60
      - preference:
          matchExpressions:
          - key: zone1
            operator: In
            values:
            - foo1
            - bar1
        weight: 10 

[root@k8s-master ~]# kubectl apply -f pod-nodeaffinity-demo-2.yaml
4、软硬亲和性同时存在
apiVersion: v1
kind: Pod
metadata:
  name: with-node-affinity
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: zone
            operator: In
            values:
            - dev
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: disktype
            operator: In
            values:
            - ssd
  containers:
  - name: with-node-affinity
    image: nginx
  • 此节点亲和性规则表示,只能将Pod放在带有标签的键为 zone 值为 dev 的node上,在满足该条件的节点中,应该首选带有键值为 disktype 值为 ssd 的节点.

  • 如果同时指定nodeSelector和nodeAffinity,则必须满足两个条件,才能将Pod调度到候选节点上。

  • 如果指定了多个nodeSelectorTerms关联nodeAffinity类型,那么pod 可以安排到满足nodeSelectorTerms之一的节点。

  • 如果指定matchExpressions与关联的多个nodeSelectorTerms,则只有matchExpressions在满足所有nodeSelectorTerms条件的情况下,才能将Pod调度到节点上。

  • 如果删除或更改计划了pod的节点的标签,则该pod不会被删除。亲和性选择仅在安排pod时有效。

  • weight 在场 preferredDuringSchedulingIgnoredDuringExecution 的范围是从1-100,值越大优先级越高,计算节点权重值之和,和 matchExpressions 的匹配度结合,实现调度 pod 节点的选择。

3、Pod 间的亲和性和反亲和性(Affinity/AntiAffinity)调度
  • 基于已经运行在 Node 上 pod 的 labels 来决定需要新创建的Pods是否可以调度到node节点上,配置的时候可以指定那个namespace中的pod需要满足pod的亲和性.可以通过 topologyKey 来指定 topology domain, 可以指定为 node/cloud provider zone 的范围.
    • 表达的语法:支持In, NotIn, Exists, DoesNotExist
    • Pod的亲和性和反亲和性可以分成
      • requiredDuringSchedulingIgnoredDuringExecution  # 硬要求
      • preferredDuringSchedulingIgnoredDuringExecution #软要求
    • labelSelector : 选择跟那组Pod亲和
    • namespaces : 选择哪个命名空间
    • topologyKey : 指定节点上的哪个键,可以设置成如下几种类型(节点标签)
      • kubernetes.io/hostname  #Node
      • failure-domain.beta.kubernetes.io/zone #Zone
      • 可以设置node上的label的值来表示node的name,zone,region等信息,pod的规则中指定topologykey的值表示指定topology 范围内的 node 上运行的 pod 满足指定规则
1、pod 亲和性
  • Pod亲和性场景,k8s集群的节点分布在不同的区域或者不同的机房,当服务A和服务B要求部署在同一个区域或者同一机房的时候,我们就需要亲和性调度了
[root@k8s-master ~]# kubectl get pods
[root@k8s-master ~]# kubectl delete pod pod-node-affinity-demo pod-node-affinity-demo-2 pod-demo

[root@k8s-master ~]# cd schedule/

[root@k8s-master ~]# vim pod-required-affinity-demo.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-first
  labels:
    app: myapp
    tier: frontend
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
---
apiVersion: v1
kind: Pod
metadata:
  name: pod-second
  labels:
    app: db
    tier: db
spec:
  containers:
  - name: busybox
    image: busybox
    imagePullPolicy: IfNotPresent
    command: ["sh","-c","sleep 3600"]
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - {key: app, operator: In, values: ["myapp"]}
        topologyKey: kubernetes.io/hostname


[root@k8s-master ~]# kubectl apply -f pod-required-affinity-demo.yaml 

[root@k8s-master ~]# kubectl get pods -o wide
# 运行结果,两个 pod 在同一 node 节点上
NAME         READY   STATUS    RESTARTS   AGE   IP           NODE
pod-first    1/1     Running   0          11s   10.244.1.6   k8s-node01
pod-second   1/1     Running   0          11s   10.244.1.5   k8s-node01
2、pod 反亲和性
  • Pod反亲和性场景,当应用服务A和数据库服务B要求尽量不要在同一台节点上的时候。
[root@k8s-master ~]# kubectl delete -f pod-required-affinity-demo.yaml 

[root@k8s-master ~]# cp pod-required-affinity-demo.yaml pod-required-anti-affinity-demo.yaml 

[root@k8s-master ~]# vim pod-required-anti-affinity-demo.yaml 
# 内容为
apiVersion: v1
kind: Pod
metadata:
  name: pod-first
  labels:
    app: myapp
    tier: frontend
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
---
apiVersion: v1
kind: Pod
metadata:
  name: pod-second
  labels:
    app: backend
    tier: db
spec:
  containers:
  - name: busybox
    image: busybox:latest
    imagePullPolicy: IfNotPresent
    command: ["sh","-c","sleep 3600"]
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - {key: app, operator: In, values: ["myapp"]}
        topologyKey: kubernetes.io/hostname

[root@k8s-master ~]# kubectl apply -f pod-required-anti-affinity-demo.yaml 

[root@k8s-master ~]# kubectl get pods -o wide
# 运行结果,两个 pod 不在同一个 node
NAME         READY   STATUS    RESTARTS   AGE   IP           NODE
pod-first    1/1     Running   0          5s    10.244.2.4   k8s-node02
pod-second   1/1     Running   0          5s    10.244.1.7   k8s-node01

[root@k8s-master ~]# kubectl delete -f pod-required-anti-affinity-demo.yaml 
3、pod 亲和性和反亲和性
  • node01 打标签 zone=test1 node02 打标签 zone=test
apiVersion: v1
kind: Pod
metadata:
  name: pod-test1
  labels:
    security: S1
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
  nodeSelector:
    zone: test1
---
apiVersion: v1
kind: Pod
metadata:
  name: pod-test2
  labels:
    security: S1
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
  nodeSelector:
    zone: test
---
apiVersion: v1
kind: Pod
metadata:
  name: pod-test3
  labels:
    security: S2
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
  nodeSelector:
    zone: test    
---
apiVersion: v1
kind: Pod
metadata:
  name: pod-first
  labels:
    security: S2
    tier: frontend2
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1    
nodeSelector:
  zone: test1
---
apiVersion: v1
kind: Pod
metadata:
  name: with-pod-affinity
spec:
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: security
            operator: In
            values:
            - S1
        topologyKey: kubernetes.io/hostname
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: security
              operator: In
              values:
              - S2
          topologyKey: kubernetes.io/hostname
  containers:
  - name: with-pod-affinity
    image: nginx
  • 例子中指定了pod的亲和性和反亲和性,指定的规则是pod将会调度到的node尽量会满足如下条件:
1、podAffinity 亲和性要求满足
  • node上具有 kubernetes.io/hostname区域,并且 node 上运行有一个pod 包含标签 label为securtity=S1.
2、podAntiAffinity 反亲和性要求满足
  • 不会调度 pod 到运行包含有 security=S2 的 pod 的 node上.

  • 如果这里将topologyKey= kubernetes.io/hostname,那么 pod 将不会调度到 node

  • 满足的条件是:node上具有 kubernetes.io/hostname 相同的 value,并且这些相同 zone下的 node 上运行有 security=S2 的 pod

3、对于topologyKey字段具有如下约束
  • topologyKey 定义pod亲和性调度和反亲和性调度中需要各个相关的pod对象是否运行于"同一位置",指定“同一位置” 是通过 topologyKey 来定义的,topologyKey 对应的值是 node 上的一个标签名称

  • 如果topologyKey指定区域已经在运行一个或多个满足LabelSelector规则的Pod,则该Pod应该(或者在非亲和性的情况下不应该)在 topologyKey 中运行

  • 对于亲和性和 requiredDuringSchedulingIgnoredDuringExecution 的 Pod 反亲和性,topologyKey 不能为空。

  • 对于 requiredDuringSchedulingIgnoredDuringExecution 的 Pod 反亲和性,引入 LimitPodHardAntiAffinityTopology 准入控制器来限制 topologyKey 只能是 kubernetes.io/hostname。如果要使用自定义拓扑域,则需要修改准入控制器,或者直接禁用它。

  • 对于 preferredDuringSchedulingIgnoredDuringExecution 的 Pod 反亲和性,空的 topologyKey 表示所有拓扑域。截止 v1.12 版本,所有拓扑域还只能是 kubernetes.io/hostname、failure-domain.beta.kubernetes.io/zone 和 failure-domain.beta.kubernetes.io/region 的组合。

  • topologyKey 除上述情况外,可以是任何合法的标签 key。规则中可以指定匹配pod所在namespace,如果定义了但是为空,它表示所有namespace范围内的pod.

  • 所有关联requiredDuringSchedulingIgnoredDuringExecution的matchExpressions全都满足之后,系统才能将pod调度到某个node上。

4、topologyKey 调度示例
  • 需求:当前有两个机房( beijing,shanghai),需要部署一个nginx产品,副本为两个,为了保证机房容灾高可用场景,需要在两个机房分别部署一个副
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-affinity-test
spec:
  replicas: 2
  selector:
    matchLabels:
      service: nginx z
  template:
    metadata:
      name: nginx
      labels:
        service: nginx
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: service
                operator: In
                values:
                - nginx
            topologyKey: zone
      containers:
      - name: nginx
        image: busybox:latest
        command: ["sh","-c","sleep 3600"]

img

  • 解释:两个node上分别有zone标签,来标注自己属于哪个机房,topologyKey定义为zone,pod所以在调度的时候,会根据node上zone标签来区分拓扑域,当前用的上 反亲和性调度 根据拓扑纬度调度,beijing机房调度完一个pod后,然后控制器判断beijing 拓扑域已经有server=nginx标签的pod,就在下一个拓扑域的node上调度了
4、Pod 亲和性调度常用的场景
1、pod 反亲和性调度
  • 创建了一个Deployment,副本数为3,指定了反亲和规则如上所示,pod的label为app:store,那么pod调度的时候将不会调度到node上已经运行了label为app:store的pod了,这样就会使得Deployment的三副本分别部署在不同的host的node上
apiVersion: apps/v1 
kind: Deployment
metadata:
  name: redis-cache
spec:
  replicas: 3    # 必须有对应的节点数(master不能创建pod)
  template:
    metadata:
      labels:
        app: store
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - store
            topologyKey: "kubernetes.io/hostname"
      containers:
      - name: redis-server
        image: redis:3.2-alpine
# 每个节点保证有一个pod 必须满足这个 pod 有 app = store 这样的标签,如果存在这样的 pod 就不满足要求
2、pod 亲和性调度
  • 在一个例子中基础之上,要求pod的亲和性满足 requiredDuringSchedulingIgnoredDuringExecution 中topologyKey=”kubernetes.io/hostname”,并且 node上需要运行有 app=store 的label.
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-server
spec:
  replicas: 4   #必须有对应的节点数(master不能创建pod)
  template:
    metadata:
      labels:
        app: web-store
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - web-store
            topologyKey: "kubernetes.io/hostname"
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - store
            topologyKey: "kubernetes.io/hostname"
      containers:
      - name: web-app
        image: nginx:1.12-alpine
  • 运行完例子一,例子二,那么pod的分布如下所示
kubectl get pods -o wide
NAME                           READY STATUS    RESTARTS   AGE     IP           NODE
redis-cache-1450370735-6dzlj   1/1   Running   0          8m      10.192.4.2   kube-node-3
redis-cache-1450370735-j2j96   1/1   Running   0          8m      10.192.2.2   kube-node-1
redis-cache-1450370735-z73mh   1/1   Running   0          8m      10.192.3.1   kube-node-2
web-server-1287567482-5d4dz    1/1   Running   0          7m      10.192.2.3   kube-node-1
web-server-1287567482-6f7v5    1/1   Running   0          7m      10.192.4.3   kube-node-3
web-server-1287567482-s330j    1/1   Running   0          7m      10.192.3.2   kube-node-2
3、pod 亲和性调度
  • 在一些应用中,pod副本之间需要共享cache,需要将pod运行在一个节点之上
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-server
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: web-store
    spec:
      affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - web-store
            topologyKey: "kubernetes.io/hostname"
      containers:
      - name: web-app
        image: nginx
  • pod 的分布如下所示
web-server-77bfb4575f-bhxvg            1/1       Running   0          11s       10.233.66.79     hzc-slave2   app=web-store,pod-template-hash=3369601319
web-server-77bfb4575f-mkfd9            1/1       Running   0          11s       10.233.66.80     hzc-slave2   app=web-store,pod-template-hash=3369601319
web-server-77bfb4575f-wgjq6            1/1       Running   0          11s       10.233.66.78     hzc-slave2   app=web-store,pod-template-hash=3369601319123
4、污点容忍调度(Taint和Toleration)
  • taints and tolerations 允许将某个节点做标记,以使得所有的pod都不会被调度到该节点上。但是如果某个pod明确指定了 tolerates 则可以正常调度到被标记的节点上。
  • 使用命令行为 Node 节点添加 Taints
[root@k8s-master ~]# kubectl taint nodes k8s-node01 key=value:NoSchedule

      - key: "node-type"
        operator: "Equal"
        value: "production"
        effect: "NoSchedule"
  • operator 可以定义为

    • Equal:表示key是否等于value,默认
    • Exists:表示key是否存在,此时无需定义value
  • tain 的 effect 定义对 Pod 排斥效果

    • NoSchedule:仅影响调度过程,对现存的Pod对象不产生影响;
    • NoExecute:既影响调度过程,也影响现有的Pod对象;不容忍的Pod对象将被驱逐
    • PreferNoSchedule: 表示尽量不调度
  • 查看节点的 taint

[root@k8s-master ~]# kubectl describe node k8s-node01 | grep Taints
  • 为 k8s-node01 打上污点
[root@k8s-master ~]# kubectl taint node k8s-node01 node-type=production:NoSchedule
  • 创建 pod 验证
[root@k8s-master ~]# vim deploy-demo.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deploy
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: myapp
      release: canary
  template:
    metadata:
      labels:
        app: myapp
        release: canary
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
        ports:
        - name: http
          containerPort: 80

[root@k8s-master ~]# kubectl apply -f deploy-demo.yaml 

[root@k8s-master ~]# kubectl get pods -o wide
# 运行结果:
NAME                            READY   STATUS    RESTARTS   AGE   IP           NODE
myapp-deploy-69b47bc96d-cwt79   1/1     Running   0          5s    10.244.2.6   k8s-node02
myapp-deploy-69b47bc96d-qqrwq   1/1     Running   0          5s    10.244.2.5   k8s-node02
  • 为 k8s-node02 打上污点
[root@k8s-master ~]# kubectl taint node k8s-node02 node-type=dev:NoExecute
  • NoExecute 将会驱逐没有容忍该污点的 pod,因两个node节点都有污点,pod没有定义容忍,导致没有节点可以启动pod

  • 查看pod 运行结果

[root@k8s-master ~]# kubectl get pods -o wide
# 运行结果:
NAME                            READY   STATUS    RESTARTS   AGE   IP       NODE
myapp-deploy-69b47bc96d-psl8f   0/1     Pending   0          14s   <none>   <none>
myapp-deploy-69b47bc96d-q296k   0/1     Pending   0          14s   <none>   <none>
  • 定义Toleration(容忍)
[root@k8s-master ~]# vim deploy-demo.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deploy
  namespace: defaultm
spec:
  replicas: 2
  selector:
    matchLabels:
      app: myapp
      release: canary
  template:
    metadata:
      labels:
        app: myapp
        release: canary
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v2
        ports:
        - name: http
          containerPort: 80
      tolerations:
      - key: "node-type"
        operator: "Equal"
        value: "production"
        effect: "NoSchedule"


[root@k8s-master ~]# kubectl apply -f deploy-demo.yaml
  • pod 容忍 k8s-node01 的 tain ,可以在 k8s-node01 上运行
[root@k8s-master ~]# kubectl get pods -o wide
NAME                            READY   STATUS    RESTARTS   AGE   IP            NODE
myapp-deploy-65cc47f858-tmpnz   1/1     Running   0          10s   10.244.1.10   k8s-node01
myapp-deploy-65cc47f858-xnklh   1/1     Running   0          13s   10.244.1.9    k8s-node01
  • 定义Toleration,是否存在 node-type 这个key 且 effect 值为 NoSchedule
[root@k8s-master ~]# vim deploy-demo.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deploy
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: myapp
      release: canary
  template:
    metadata:
      labels:
        app: myapp
        release: canary
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v2
        ports:
        - name: http
          containerPort: 80
      tolerations:
      - key: "node-type"
        operator: "Exists"
        value: ""
        effect: "NoSchedule"

[root@k8s-master ~]# kubectl apply -f deploy-demo.yaml

[root@k8s-master ~]# kubectl get pods -o wide
NAME                            READY   STATUS    RESTARTS   AGE   IP            NODE
myapp-deploy-559f559bcc-6jfqq   1/1     Running   0          10s   10.244.1.11   k8s-node01
myapp-deploy-559f559bcc-rlwp2   1/1     Running   0          9s    10.244.1.12   k8s-node01
  • 定义Toleration,是否存在 node-type 这个key 且 effect 值为空,则包含所有的值
[root@k8s-master ~]# vim deploy-demo.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deploy
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: myapp
      release: canary
  template:
    metadata:
      labels:
        app: myapp
        release: canary
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v2
        ports:
        - name: http
          containerPort: 80
      tolerations:
      - key: "node-type"
        operator: "Exists"
        value: ""
        effect: ""

[root@k8s-master ~]# kubectl apply -f deploy-demo.yaml

# 两个 pod 均衡调度到两个节点
kubectl get pods -o wide
NAME                            READY   STATUS    RESTARTS   AGE   IP            NODE
myapp-deploy-5d9c6985f5-hn4k2   1/1     Running   0          2m    10.244.1.13   k8s-node01
myapp-deploy-5d9c6985f5-lkf9q   1/1     Running   0          2m    10.244.2.7    k8s-node02

7、Pod 扩容和缩容

1、kubectl scale
  • 扩容或缩容 Deployment、ReplicaSet、Replication Controller或 Job 中Pod数量。

  • scale 也可以指定多个前提条件,如:当前副本数量或 --resource-version ,进行伸缩比例设置前,系统会先验证前提条件是否成立。

2、scale 语法
[root@k8s-master ~]# kubectl scale [--resource-version=version] [--current-replicas=count] --replicas=COUNT (-f FILENAME | TYPE NAME)
3、scale 示例
  • 将名为 foo 的 rs资源中的 pod 副本数设置为 3。
[root@k8s-master ~]# kubectl scale --replicas=3 deployment foo
  • 将配置文件中指定的资源对象和名称标识的Pod资源副本设为3。
[root@k8s-master ~]# kubectl scale --replicas=3 -f foo.yaml
  • 配置deployment 资源, 如果当前副本数为2,则将其扩展至3。
[root@k8s-master ~]# kubectl scale --current-replicas=2 --replicas=3 deployment  mysql
  • 设置多个RC资源中Pod副本数量。
[root@k8s-master ~]# kubectl scale --replicas=5 rc foo bar baz
  • 假设 redis-slave 这个 rc 资源中原来定义了5个副本(reolics:5)

  • 扩容到10个,执行命令:

[root@k8s-master ~]# kubectl scale rc redis-slave --replicas=10
  • 缩容到2个,执行命令:
[root@k8s-master ~]# kubectl scale rc redis-slave --replicas=2
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值