0
点赞
收藏
分享

微信扫一扫

Kubernetes的Pod研究(3)--Pod设计模式和生命周期

一、Pod设计模式

1.1 容器设计模式

基于容器的分布式系统中常用的3类设计模式

  • 单容器模式:单一容器形式运行的应用。现代应用容器技术用来运行单个进程(包括子进程)
  • 单节点多容器模式:即跨容器的设计模式,目的是在单个主机上运行多个具有超亲密关系的容器(进程),因此容器管理系统需要将其作为一个原子单位进行统一调度。Kubernetes编排系统设计的Pod概念就是该设计模式的实现之一。
  • 多节点模式:将分布式应用(eg:Mysql主从、Redis Cluster)的每个实例分布于多个节点,分别以单节点模式运行

1.2 单节点多容器模式的实现方案

1.2.1 Sidecar模式

Sidecar(边车,也称挎斗)模式通常由主应用程序(通常是web程序)和一个辅助容器(Sidecar容器)组成。该辅助容器用于为主容器提供辅助服务以增强主容器的功能,是主应用程序必不可少的一部分,但未必非要运行为应用的一部分。简单理解就是,他俩可以分别用两个进程去运行,将辅助功能与业务容器解耦。

      像主应用程序需要的日志记录服务、代理服务、数据同步服务、配置服务等就可以由SideCar容器完成,主应用程序主要关注业务的实现。Sidecar模式主要是利用在同一个Pod中的容器可以共享存储的能力。

      Eg:对于应用服务(eg:Nginx)来说,主要功能是对外提供web服务,而非日志的持久化存储,但运维人员又需要借助日志排查服务异常问题。此时,可以为应用服务的Pod添加一个用于收集日志的Sidecar容器。应用服务容器作为主容器只需关注业务,日志信息由Sidecar 容器进行收集处理。

Kubernetes的Pod研究(3)--Pod设计模式和生命周期_Kubernetes

1.2.2 Ambassador模式

Ambassador(大使)模式通常由主应用程序和一个辅助容器(Ambassador容器)组成。辅助容器代表主容器发送网络请求到外部环境,其作用可视为主容器(客户端)的”大使”。

云原生应用程序需要诸如路由、计量、监视、断路等功能,但更新已有的应用程序或现有代码库去添加这些功能比较麻烦,进程外代理就成了有效的解决方案。大使模式本质上就是这么一类代理程序。可以利用它去访问数据库,甚至是分布式数据库(eg:Redis Cluster)。

Kubernetes的Pod研究(3)--Pod设计模式和生命周期_Kubernetes_02

1.2.3 Adapter模式

Adapter(适配器)模式主要是以标准化和规范化应用对外暴露服务接口。每个应用程序可能会以各种形式(如JSON、XML等),对外输出监控指标数据。然而,监控系统却希望收到的是统一数据模型的数据。这时就可以通过使用适配器模式,将应用程序容器,同相应的监控指标数据转换的适配器容器创建在同一个Pod内,就可做到将不同应用的监控指标数据转换为单个统一模型数据。

其理想的应用场景就是Prometheus与Kubernetes的结合,获取Kubernetes集群的相关数据。

Kubernetes的Pod研究(3)--Pod设计模式和生命周期_Kubernetes_03

1.2.4 Init Container模式

Init Container(初始化容器)运行于主容器之前,完成必要的初始化任务(eg:设置环境变量,文件系统设置特殊权限)

初始化容器可以有多个,但它们需要以特定顺序串行运行,在启动应用程序容器之前成功终止。而多个应用程序容器一般需要并行启动和运行。

二、容器生命周期钩子函数

当容器内部功能复杂的时候,仅仅依赖常用的信号(SIGTERM、SIGKILL)终止进程可能不足以完成所有的必要操作。因此,容器需要支持postStart和preStop事件,前者常用于为程序启动前进行预热,后者在“干净”的关闭应用(eg:关闭数据库、关闭网络连接)之前释放占用的资源。

Kubernetes也为容器提供了postStart和preStop两种生命周期钩子。

  • postStart

在容器创建完成后立即运行的钩子句柄,该钩子定义的事件完成后容器才能真正完成启动过程。

  • preStop

在容器终止操作执行之前立即运行的钩子句柄,它以同步方式调用,因此在其完成之前会阻塞删除容器的操作。即当该钩子定义的事件成功执行并退出时,容器终止操作才能真正完成。

钩子句柄的实现方式类似于容器健康状态检测探针,同样有exec、httpGet和tcpSocket这些类型。

postStart和preStop句柄定义在容器的lifecycle字段中。下面给出一个示例

vim lifecycle-demo.yaml
apiVersion: v1
kind: Pod
metadata:
  name: lifecycle-demo
  namespace: default
spec:
  containers:
  - name: demo
    image: ikubernetes/demoapp:v1.0
    imagePullPolicy: IfNotPresent
    securityContext:
      capabilities:
        add:
        - NET_ADMIN
    livenessProbe:
      httpGet:
        path: '/livez'
        port: 80
        scheme: HTTP
      initialDelaySeconds: 5
    lifecycle:
      postStart:
        exec:
          command: ['/bin/sh','-c','iptables -t nat -A PREROUTING -p tcp --dport 8080 -j REDIRECT --to-ports 80']
      preStop:
        exec:
          command: ['/bin/sh','-c','while killall python3; do sleep 1; done']
  restartPolicy: Always

在该yaml中,demo容器通过postStart执行iptables命令设置端口重定向规则,将发往该Pod IP的8080端口的所有请求重定向到80端口,这样容器能同时从8080端口接收请求。之后借助preStop执行killall命令,更优雅地终止基于python3运行的容器应用。

Apply成功之后,查看iptables规则,验证postStart钩子事件的执行结果

kubectl exec -it lifecycle-demo -- iptables -t nat -nL PREROUTING

Kubernetes的Pod研究(3)--Pod设计模式和生命周期_Pod生命周期_04

可以人为的将探针检测结果设置为失败状态,以促使kubelet重启demo容器验证preStop钩子事件的执行。由于该事例中给出的操作是终止容器应用,则当容器重启成功则说明对应命令运行完成。

Kubernetes的Pod研究(3)--Pod设计模式和生命周期_Pod设计模式_05

三、Pod的生命周期

Kubernetes的Pod研究(3)--Pod设计模式和生命周期_Pod设计模式_06

1st.    在启动任何容器之前(包括初始化容器)先创建pause基础容器,它初始化Pod环境并为后续加入的容器提供共享的名称空间

2nd.  按顺序以串行方式运行用户定义的各个初始化容器进行Pod环境初始化;任何一个初始化容器运行失败都会导致Pod创建失败,根据重启策略(restartPolicy)进行处理,默认为重启。

3rd.   当所有初始化容器成功完成后,启动应用程序容器。此步骤会并行启动多个应用容器。主容器运行的那一刻会同时运行主容器定义的postStart钩子事件,该步骤失败将导致相关容器被重启。

4th.   运行启动健康状态检测(startupProbe),判断容器是否启动成功。如果失败,也参照重启策略进行处理。未定义时默认为success。

5th.   当主容器正常运行时,定期进行存活状态监测(liveness)和就绪状态监测(readiness)。存活状态监测检测失败将导致容器重启,而就绪状态监测失败会使得该容器从它隶属的Service对象的可用节点列表中移除

6th.   终止Pod对象时,先运行preStop钩子事件,并在宽限期(terminationGrace-PeriodSeconds)结束后终止主容器,宽限期默认30秒。

举报

相关推荐

0 条评论