云原生系列技术(八):Kubernetes 工作负载详解

上一节我们介绍了《Kubernetes Service详解》,Service是我们应用的访问入口,真正的应用是跑在后端的容器里面的,而这些容器都是以容器组(Pod)为单位进行管理和调度的,本节主要给大家介绍容器组(Pod)以及容器组控制器(Controllers).

Pod 介绍

Pod 概述

如何理解Pod? 我们可以把它想象成一个虚拟机(VM), 一个Pod里面通常只跑一个应用容器,有时候我们的应用容器之间耦合度比较紧密,我们也可以让它们跑在一个Pod里面。同一Pod里面的容器共享存储和网络。Pod是Kubernetes管理与调度的最小单位。

Pod定义

那么如何使用Pod呢,下面通过一段最简单的编排代码定义一个Pod:

apiVersion: v1
kind: Pod
metadata:
  labels:
    app: nginx
  name: nginx
  namespace: default
spec:
  containers:
   - image: nginx
     name: nginx-name
     ports:
      - containerPort: 80

上面的编排创建一个名为nginx的Pod,Pod里面只运行一个容器(name=nginx-name),容器里面跑真正的nginx应用服务。

容器探针

容器探针主要用于诊断容器里面应用是否正常,为修复容器或服务负载提供依据。

容器探针有两种:存活探针(liveness)和就绪探针(readiness)。

存活探针(liveness)

主要用于判断容器是否处于运行状态,比如当服务crash或者死锁等情况发生时,kubelet会kill掉容器, 然后根据其设置的restartPolicy进行相应操作(可能会在本机重新启动容器,或者因为设置Kubernetes QoS,本机没有资源情况下会被分发到其他机器上重新创建)。

就绪探针(readiness)

主要用于判断服务是否已经正常工作,如果服务没有加载完成或工作异常,服务所在的Pod的IP地址会从服务的endpoints中被移除,也就是说,当服务没有ready时,会将其从服务的load balancer中移除,不会再接受或响应任何请求。

以上两种探针都支持以下三种类型的实现:

探针类型说明通过健康检查标准
ExecAction容器内部执行shell命令shell命令返回0
HTTPGetAction通过容器的IP、port、path用HTTP Get请求进行检查200<=返回值<400
TCPSocketAction通过容器的IP、port执行tcp进行检查port是否打开

下面使用一个简单的例子说明:

apiVersion: v1
kind: Pod
metadata:
  labels:
    app: nginx
  name: nginx
  namespace: default
spec:
  containers:
   - image: nginx
     name: nginx-name
     ports:
      - containerPort: 80
     livenessProbe:
       tcpSocket:
         port: 80
       initialDelaySeconds: 8
       periodSeconds: 2
       timeoutSeconds: 3
       successThreshold: 1
       failureThreshold: 3
     readinessProbe:
       httpGet:
         path: /
         port: 80
       initialDelaySeconds: 8
       periodSeconds: 2
       timeoutSeconds: 3 
       successThreshold: 1
       failureThreshold: 3

上面的例子中添加了两个探针:存活探针(livenessProbe)和就绪探针(readinessProbe)。

存活探针使用TCPSocketAction实现,就绪探针使用HTTPGetAction实现。

解释下以上几个参数:

  • initialDelaySeconds:指定第一次执行探针前等待的时间,单位秒。默认不等待。
  • periodSeconds:指定kubelet每隔多少秒执行一次探针操作,默认10。
  • timeoutSeconds: 设置每次探针执行的超时时间,默认1。
  • successThreshold: 设置执行成功多少次才算最终成功,默认1。
  • failureThreshold: 设置执行失败多少次才算最终失败,用于防止偶然失败导致不必要的容器重启,默认3。
容器钩子

容器钩子主要是让容器可以优雅的终止,或者启动后做一些初始化操作。

主要有两个:PostStart 和 PreStop

PostStart
  • 这个钩子在容器被创建后立刻触发,通知容器已经被创建。
  • 容器ENTRYPOINT和钩子执行是异步的,并不能保证钩子将在容器ENTRYPOINT之前运行。
  • 如果该钩子对应的Action执行失败,则该容器会被杀死,并根据该容器的重启策略决定是否要重启该容器。
  • 如果该钩子花费太长时间以至于不能运行或者挂起, 容器将不能达到running状态.
PreStop
  • 这个钩子在容器被删除前触发。
  • 它是阻塞的,意味着它是同步的, 所以它必须在删除容器的调用发出之前完成.。
  • 该钩子对应的Action完成后不论执行的结果如何,都会删除该容器。
  • 如果钩子在执行期间挂起, 容器将停留在running状态并且永远不会达到failed状态.

以上两种钩子都支持以下两种类型的实现:

Action类型说明成功标志
ExecAction容器内部执行shell命令shell命令返回0
HTTPGetAction通过容器的IP、port、path用HTTP Get请求进行检查200<=返回值<400

下面使用一个简单的例子说明:

apiVersion: v1
kind: Pod
metadata:
  labels:
    app: nginx
  name: nginx
  namespace: default
spec:
  containers:
   - image: nginx
     name: nginx-name
     ports:
      - containerPort: 80
     lifecycle:
       postStart:
         exec:
            command: ["/bin/sh", "-c", "echo postStart handler > /tmp/started.txt"]
       preStop:
         exec:
            command: ["/bin/sh", "-c", "echo preStop handler > /tmp/stopping.txt"]

以上例子实现的是:

  • 容器每次启动后打印“postStart handler”到/tmp/started.txt。
  • 容器每次停止前打印“preStop handler”到/tmp/stopping.txt。
容器资源

Kubernetes支持给容器设置资源,可以设置最小请求的资源和最大使用的资源。

通过resources.requests 设置容器最小需要的资源,也用于调度时决策。

通过resources.limits 设置容器运行占用的最大资源。

通过一个简单的例子说明下:

apiVersion: v1
kind: Pod
metadata:
  labels:
    app: nginx
  name: nginx
  namespace: default
spec:
  containers:
   - image: nginx
     name: nginx-name
     ports:
      - containerPort: 80
     resources:
        requests:
          memory: "60Mi"
          cpu: "0.1"
        limits:
          memory: "128Mi"
          cpu: "0.2"

以上例子中:

设置容器最小需要的资源:内存:60Mi,cpu:0.1

设置容器最大占用的资源:内存:128Mi,cpu:0.2

针对内存和CPU的单位进行说明:

内存单位:

内存资源是以字节为单位的,可以表示为纯整数或者固定的十进制数字,后缀可以是E, P, T, G, M, K, Ei, Pi, Ti, Gi, Mi, Ki.比如,下面几种写法表示相同的数值:

128974848, 129e6, 129M , 123Mi

CPU单位:

整数或者小数均可,整数比较好理解。

如果是小数,那么一个容器申请0.5个CPU,就相当于申请1个CPU的一半,你也可以加个后缀m 表示千分之一的概念。比如说100m的CPU,100豪的CPU和0.1个CPU都是一样的。

Controller介绍

平常使用的过程中,我们很少会直接创建Pod,因为Pod的生命周期是短暂的,且没有自愈能力。因此我们都会通过Controller来管理Pod.

Controller可以创建和管理多个Pod,提供副本管理,滚动升级和集群级别的自愈能力。

下面介绍Kubernetes中几种常用的Controller.

Deployment

介绍Deployment之前,先简单说下副本控制器,主要是用于确保Pod的实际副本数跟用户定义的副本数保持一致,少增多减。平时我们不需要手动创建副本控制器,而是用更高层次的Deployment,它能管理副本控制器,并提供对Pod的更新等功能。

Deployment的定义:为Pod和副本控制器提供声明式更新。

它主要有以下几个功能:

  • 管理副本控制器:根据定义的模板创建副本控制器。
    • 使用Deployment来创建ReplicaSet(副本控制器),ReplicaSet在后台创建Pod,然后检测启动/运行状态,维持Pod的副本数为我们预定义的数目。
    • 通过更新Deployment的 template字段来声明Pod的新状态。
    • 通过命令set image 可以升级或更新应用的镜像。
      • 例如:kubectl set image deploy nginx nginx-name=nginx:v2
    • 通过命令scale 可以伸缩应用的副本数。
      • 例如:kubectl scale deploy nginx --replicas=3
  • 版本记录:每一次对Deployment的修改,通过指定参数 --record,都会保存下来。
    • 例如创建Deployment时:kubectl create -f deployment.yaml --record
  • 事件和状态查看:可以查看Deployment的升级详细进度和状态。
    • 通过命令 rollout status 可以查看指定Deployment的状态.
      • 例如:kubectl rollout status deploy nginx
    • 通过命令 rollout history 可以查看历史版本信息。
      • 例如:kubectl rollout history deploy nginx
  • 版本回滚:支持回滚到指定版本。
    • 通过命令 rollout undo 可以回滚到上一个版本
      • 例如:kubectl rollout undo deploy nginx
    • 通过命令 rollout undo --to-revision=‘指定版本’ 可以回滚到指定版本。
      • 例如:kubectl rollout undo deploy nginx --to-revision=2
  • 暂停和启动:对于每一次升级,都能随时暂停和启动。
    • 通过命令 rollout pause 暂停更新
      • 例如:kubectl rollout pause deploy nginx
    • 通过命令 rollout resume 恢复已暂停资源
      • 例如:kubectl rollout resume deploy nginx
StatefulSet

StatefulSet是为了解决有状态服务的问题(Deployment是为无状态服务而设计的)。

在具有以下特点时使用StatefulSet:

  • 稳定性:唯一的网络标识符;持久化存储。
  • 有序性:有序部署、扩展、删除、滚动更新。

StatefulSet的稳定性主要通过以下几点体现:

  • 在创建StatefulSet的时候,通过volumeClaimTemplates字段设置PVC的模板,这样它的每一个副本就会拥有各自的数据卷。

  • 为StatefulSet部署的应用创建无头服务(Headless Service),这样集群内部每个成员都会有一个唯一的DNS域名来作为其网络标识,成员之间通过这个域名进行通信。

    • StatefulSet创建出来的每个Pod,会得到以下域名:

      $(podname).$(servicename).$(namespace).svc.cluster.local

StatefulSet的有序性主要通过podManagementPolicy字段来设置:

  • OrderedReady:默认值,副本的扩展和删除都是有序进行的,第一个副本没有准备好之前,后面的副本不会被创建,删除顺序则相反。
  • Parallel:副本的扩展和删除可以并行进行,不需要按照顺序启动或终止。
DaemonSet

DaemonSet能够让指定Pod部署到所有Node节点。

当有新的节点加入到Kubernetes集群中时,DaemonSet Controller会自动在该节点上部署指定Pod;

被DaemonSet Controller创建的Pod会默认指定.spec.nodeName,所以pod会被k8s的调度器忽略.

当k8s的调度器没有启动的时候,DaemonSet Controller也能工作.

DaemonSet通常用来部署一些集群的日志、监控或者其他系统管理应用。

总结

本文介绍了Kubernetes 工作负载(Workloads)的使用。我们知道Pod是对容器的封装,Controller是对Pod的封装,通常我们写编排文件都是通过Controller来定义我们的应用,避免直接使用Pod,因为Pod的生命周期比较短,且没有自愈能力。下节分享《Kubernetes 存储管理》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值