为什么需要Pod?

Pod是K8S的调度单位。

回顾容器和K8S的关系

  • 容器的本质?
    • 一个视图被隔离,资源受限的进程
    • 容器里PID=1的进程就是应用本身
      • 管理虚拟机=管理基础设施
      • 管理容器=直接管理应用
  • K8S?
    • K8s是云时代的操作系统
    • 容器镜像是K8S这个操作系统的软件安装包

真实操作系统的例子

  • 一个Helloworld程序由多个进程组成
  • 四个进程共享helloworld的资源,相互协作,完成helloworld的工作

两者对比

  • k8s=操作系统
  • 容器=进程
  • pod=进程组

进程组

  • 对于上面拥有4个进程的helloworld程序,怎么用容器跑起来?
  • 方法一:在一个docker里面启动4个进程
    • 问题:容器是单进程模型,PID=1的进程比如说是main进程,其他三个进程怎么管理?
    • 解决方法:
      • 应用程序本身具有进程管理的能力,helloworld程序具备systemd的能力。
      • 或者,PID=1的进程改为systemd
        • 这样,管理容器=管理systemd!=直接管理应用本身。

Pod=进程组

来自Borg的思考

Borg部署的应用,往往存在着类似进程与进程组的关系,必须部署在同一台机器上,共享一些信息。

为什么Pod是原子调度单位?

  • 举例:两个容器紧密合作
    • App,业务容器,写日志
    • Log,转发日志到ES
  • 内存要求
    • APP:1G
    • Log:0.5G
  • 可用内存
    • Node_A : 1.25G
    • Node_B : 2G
  • 如果App被调度到了Node_A上,Log资源不足就调度不过来了
  • Task co-scheduling问题的解决方案
    • Mesos:资源囤积(reource hoarding)
      • 所有设置了Afinity约束的任务都达到了,才开始统一调度
      • 问题:调度效率损失、死锁
    • Google Omega:乐观调度处理冲突
      • 先不管冲突,在冲突发生时会有机制进行回滚来处理问题
      • 问题:负载
    • K8S:Pod打包部署

再次理解Pod

  • 亲密关系-调度解决
    • 两个应用需要部署在同一个宿主机上
  • 超亲密关系-pod解决
    • 会直接发生文件交换
    • 会使用localhost或socket文件进行本地通信
    • 会频繁的RPC调用
    • 会共享某些Linux namespace(一个容器加入另一个容器的network namespace,这样就可以看到对方的网络设备)

Pod的实现机制

Pod要解决的问题

  • 如何让一个Pod里的容器之间最高效地共享某些资源和数据?
    • 容器之间是被Linux Namespace和cgroups隔离开的

1 共享网络

  • 容器A和B
    • 通过Infra Container的方式共享同一个Network Namespace
      • 镜像:k8s.gcr.io/pause;汇编语言编写的,永远处于暂停状态,大小100-200KB
    • 直接使用localhost通信
    • 看到的网络设备和Infra容器看到的完全一样
    • 一个Pod只有一个IP地址,也就是这个pod的Network Namespace对应的IP地址
      • 所有网络资源,都是一个Pod一份,被该Pod中的所有容器共享
    • 整个Pod的生命周期和Infra容器一致,而与容器A和B无关

2 共享存储

  • 设置一个Pod级别的Volumn
  • 各个容器去挂载这个Volumn,然后就可以看到(/opt/tiger/...)

详解容器设计模式

举例:WAR包+Tomcat的容器化

  • 方法一:把WAR包和Tomcat打包进一个镜像
    • 无论是WAR更新和Tomcat更新都需要重新制作镜像
  • 方法二:镜像里只打包Tomcat,用数据卷容宿主机上将WAR包挂载进Tomcat容器
    • 需要分布式存储系统
  • 更通用的做法?

InitContainer

  • InitContainer会比spec.containers定义的用户容器先执行,并且严格按照定义的顺序依次执行
  • /app是个Volumn
  • Tomcat容器同样挂载了该Volumn到自己的webapps目录下
  • 当Tomcat容器启动是,它的webapp目录下就一定会有sample.war

容器设计模式:Sidecar

  • 通过在Pod里定义专门容器,来执行主业务容器需要的辅助功能
  • 比如:
    • Init Container把war包复制到Volumn里面
    • 需要SSH进去执行的脚本
    • 日志收集
    • Debug应用
    • 应用监控
  • 优势:
    • 将辅助功能和祝业务容器解耦,实现独立发布和能力重用

Sidecar:应用与日志收集

  • 业务容器将日志写在Volumn里
  • 日志容器共享该Volumn从而将日志转发到远程存储当中
    • Fluentd等

Sidecar:代理容器

  • 代理容器对业务容器屏蔽被代理的服务集群(consul、服务发现?),简化业务代码的实现逻辑
  • 提示:
    • 容器之间通过localhost直接通信
    • 代理容器的代码可以被全公司重用

Sidecar:适配器模式

  • 适配器模式将业务暴露出来的接口转化为另一种格式
  • 举例:
    • 业务暴露出来的监控接口是/metrics
    • 监控系统需要的接口是/healthz
    • monitoring adapter将/metrics转化为/healthz以适配新的监控系统
  • 提示:
    • 容器之间通过localhost通信
    • 代理容器的代码可以被全公司重用

总结

  • Pod是K8s项目里实现容器设计模式的核心机制
  • 容器设计模式是K8s进行复杂应用编排的基础依赖
  • 所有设计模式的本质都是:解耦和重用
Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐