• Kubernetes Pod 生命周期


    一、 Pod Hook

    Kubernetes 为我们提供了生命周期钩子,就是我们所说的Pod Hook,Pod Hook是由kubelet发起的,当容器中的进程启动前或者容器中的进程终止之前运行。这是包含在容器的生命周期之中。我们可以同时为Pod中的所有容器都配置hook。

    Kubernetes为我们提供了两种钩子函数:

    • PostStart:这个钩子在容器创建后立即执行。但是并不能保证钩子将在ENTRYPOINT之前运行,因为没有参数传递给处理程序。主要用于资源部署、环境准备等。不过需要注意的是如果钩子花费太长时间以至于运行或者挂起,容器将不能达到runnig状态。
    • PreStop:这个钩子在容器终止之前立即被调用。它是阻塞的,意味着它是同步的,所以它必须在删除容器的调用发出之前完成。主要用于优雅关闭应用程序、通知其他系统等。如果钩子在执行期间挂起,Pod阶段将停留在running状态并且永不会达到failed状态。

    如果PostStart或者PreStop钩子失败, 它会杀死容器。所以我们应该让钩子函数尽可能的轻量。当然有些情况下,长时间运行命令是合理的, 比如在停止容器之前预先保存状态。

    另外我们有两种方式来实现上面的钩子函数:

    • Exec - 用于执行一段特定的命令,不过要注意的是该命令消耗的资源会被计入容器。
    • HTTP - 对容器上的特定的端点执行HTTP请求

    以下示例中,定义了一个Nginx Pod,其中设置了PostStart钩子函数,即在容器创建成功后,写入一句话到/usr/share/message文件中:

    apiVersion: v1
    kind: Pod
    metadata:
      name: hook-demo1
    spec:
      containers:
      - name: hook-demo1
        image: nginx
        lifecycle:
          postStart:
            exec:
              command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"]

     优雅删除资源对象

    当用户请求删除含有 pod 的资源对象时(如Deployment等),K8S 为了让应用程序优雅关闭(即让应用程序完成正在处理的请求后,再关闭软件),K8S提供两种信息通知:

    • 默认:K8S 通知 node 执行docker stop命令,docker 会先向容器中PID为1的进程发送系统信号SIGTERM,然后等待容器中的应用程序终止执行,如果等待时间达到设定的超时时间,或者默认超时时间(30s),会继续发送SIGKILL的系统信号强行 kill 掉进程
    • 使用 pod 生命周期(利用PreStop回调函数),它执行在发送终止信号之前

    默认所有的优雅退出时间都在30秒内。kubectl delete 命令支持 --grace-period=<seconds>选项,这个选项允许用户用他们自己指定的值覆盖默认值。值'0'代表 强制删除 pod. 在 kubectl 1.5 及以上的版本里,执行强制删除时必须同时指定 --force --grace-period=0

    强制删除一个 pod 是从集群状态还有 etcd 里立刻删除这个 pod。 当 Pod 被强制删除时, api 服务器不会等待来自 Pod 所在节点上的 kubelet 的确认信息:pod 已经被终止。在 API 里 pod 会被立刻删除,在节点上, pods 被设置成立刻终止后,在强行杀掉前还会有一个很小的宽限期。

    以下示例中,定义了一个Nginx Pod,其中设置了PreStop钩子函数,即在容器退出之前,优雅的关闭 Nginx:

    apiVersion: v1
    kind: Pod
    metadata:
      name: hook-demo2
    spec:
      containers:
      - name: hook-demo2
        image: nginx
        lifecycle:
          preStop:
            exec:
              command: ["/usr/sbin/nginx","-s","quit"]
    
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: hook-demo2
      labels:
        app: hook
    spec:
      containers:
      - name: hook-demo2
        image: nginx
        ports:
        - name: webport
          containerPort: 80
        volumeMounts:
        - name: message
          mountPath: /usr/share/
        lifecycle:
          preStop:
            exec:
              command: ['/bin/sh', '-c', 'echo Hello from the preStop Handler > /usr/share/message']
      volumes:
      - name: message
        hostPath:
          path: /tmp

    另外Hook调用的日志没有暴露个给 Pod 的 event,所以只能通过describe命令来获取,如果有错误将可以看到FailedPostStartHookFailedPreStopHook这样的 event。

    二、Pod健康检查

    Kubernetes集群当中,我们可以通过配置liveness probe(存活探针)和readiness probe(可读性探针)来影响容器的生存周期。

    1. kubelet 通过使用 liveness probe 来确定你的应用程序是否正在运行,通俗点将就是是否还活着。一般来说,如果你的程序一旦崩溃了, Kubernetes 就会立刻知道这个程序已经终止了,然后就会重启这个程序。而我们的 liveness probe 的目的就是来捕获到当前应用程序还没有终止,还没有崩溃,如果出现了这些情况,那么就重启处于该状态下的容器,使应用程序在存在 bug 的情况下依然能够继续运行下去。

    2. kubelet 使用 readiness probe 来确定容器是否已经就绪可以接收流量过来了。这个探针通俗点讲就是说是否准备好了,现在可以开始工作了。只有当 Pod 中的容器都处于就绪状态的时候 kubelet 才会认定该 Pod 处于就绪状态,因为一个 Pod 下面可能会有多个容器。当然 Pod 如果处于非就绪状态,那么我们就会将他从我们的工作队列(实际上就是我们后面需要重点学习的 Service)中移除出来,这样我们的流量就不会被路由到这个 Pod 里面来了。

    Kubelet使用liveness probe(存活探针)来确定何时重启容器。例如,当应用程序处于运行状态但无法做进一步操作,liveness探针将捕获到deadlock,重启处于该状态下的容器,使应用程序在存在bug的情况下依然能够继续运行下去(谁的程序还没几个bug呢)。

    Kubelet使用readiness probe(就绪探针)来确定容器是否已经就绪可以接受流量。只有当Pod中的容器都处于就绪状态时kubelet才会认定该Pod处于就绪状态。该信号的作用是控制哪些Pod应该作为service的后端。如果Pod处于非就绪状态,那么它们将会被从service的load balancer中移除。

    Probe中有很多精确和详细的配置,通过它们你能准确的控制liveness和readiness检查:

    • initialDelaySeconds:容器启动后第一次执行探测是需要等待多少秒
    • periodSeconds:执行探测的频率。默认是10秒,最小1秒。
    • timeoutSeconds:探测超时时间。默认1秒,最小1秒。
    • successThreshold:探测失败后,最少连续探测成功多少次才被认定为成功。默认是1。对于liveness必须是1。最小值是1。
    • failureThreshold:探测成功后,最少连续探测失败多少次才被认定为失败。默认是3。最小值是1。

    HTTP probe中可以给 httpGet设置其他配置项:

    • host:连接的主机名,默认连接到pod的IP。你可能想在http header中设置”Host”而不是使用IP。
    • scheme:连接使用的schema,默认HTTP。
    • path: 访问的HTTP server的path。
    • httpHeaders:自定义请求的header。HTTP运行重复的header。
    • port:访问的容器的端口名字或者端口号。端口号必须介于1和65525之间。

    对于HTTP探测器,kubelet向指定的路径和端口发送HTTP请求以执行检查。 Kubelet将probe发送到容器的IP地址,除非地址被httpGet中的可选host字段覆盖。 在大多数情况下,你不想设置主机字段。 有一种情况下你可以设置它。 假设容器在127.0.0.1上侦听,并且Pod的hostNetwork字段为true。 然后,在httpGet下的host应该设置为127.0.0.1。 如果你的pod依赖于虚拟主机,这可能是更常见的情况,你不应该是用host,而是应该在httpHeaders中设置Host头。

  • 相关阅读:
    linux:安装php7.x
    linux:搭建 WordPress 个人站点
    linux:lnmp环境
    knn初了解
    Pycharm:鼠标滚动控制字体大小
    数据集的获取
    弄懂Java的自增变量
    面试中的volatile关键字
    Java的类锁、对象锁和方法锁
    Error creating bean with name 'entityManagerFactory' defined in class path resource解决方案
  • 原文地址:https://www.cnblogs.com/skymyyang/p/12010843.html
Copyright © 2020-2023  润新知