云原生公开课笔记——Pod和容器设计模式

解决问题:

  • 为什么需要Pod
  • Pod的实现机制
  • 详解容器设计模式

为什么需要Pod

容器本质是一个进程,是一个资源视图被隔离,资源受限的进程

其中使用Namespace来进行视图隔离,Cgroup进行资源的限制。

容器中PID=1的进程等于应用本身
管理容器即管理应用本身
管理虚拟机等于管理基础设施

容器实际上是一个单进程的模型,单进程指"容器的生命周期等同于PID=1的进程的生命周期"

问题引入:跑一个由4个进程组成的程序,进程之间共享某些文件。
容器怎么跑这个4个进程?

PID=1的进程就是应用本身,例如main进程。那么谁来管理剩下的3个进程?

除非应用进程本身具备进程管理能力或者把PID=1的进程改为管理进程的进程(systemd)

这会导致: 管理容器 = 管理systemd!=直接管理容器本身

违背了容器的设计模式。

所以我们引入了"Pod"这个概念,相当于进程组。

Pod不是一个物理概念,没有一个真实存在的概念。而是一个抽象的概念。

所以当要执行一个由4个进程组成的程序的时候,其实是跑在"Pod"里面的。由Pod来进行进程的管理

在这里插入图片描述

Pod——K8s的原子调度单位

  • Pod里容器之间的关系:”亲密关系“
    指两个应用运行在同一台宿主机上
  • ”超亲密关系“
    1.直接发生文件交换
    2.使用localhost或者socket文件进行本地通信
    3.发生非常频繁的RPC调用
    4.共享某些linux namespace

所以我们引入Pod,是为了解决两个问题:

1.怎么去描述超亲密关系
2.怎么去对超亲密关系的容器或者是业务去做统一调度。

Pod的实现

关键在于:如何让一个Pod里的多个容器之间高效地共享某些数据或者资源

容器之间本来是被Linux Namespace和cgroups隔开的。所以现在解决的问题在于如何打破这个隔离。使得Pod里面多个容器之间能够实现高效的共享资源和数据

具体措施:从网络与存储两个方面:

共享网络:

如何Pod里面多个容器怎么去共享网络?

比如现在有一个Pod,其中包含了容器A和容器B,两个共享Network Namespace.
K8s会在每个Pod起一个infra Container小容器来共享整个Pod的Network Namespace.

什么是Infra container呢? 这是一个很小的镜像,永远处于”Pending“状态。

有了这么一个Infra container,其他所有容器都会通过Join Namespace的方式加入到Infra container的Network Namespace.

所以一个Pod里面所有的容器所看到的网络视图是完全一样的,ip,mac地址等都是来自于Pod第一次创建的这个Infra container.

在Pod里面,一定有一个IP地址,是Pod的网络Namespace对应的地址,即Infra Container的IP地址。

在这里插入图片描述
整个Pod的生命周期等同于Infra container的生命周期。在整个Pod里面,Infra container必然是第一个启动的。

共享存储

利用Volume挂载在Pod的主机。Pod里面多个容器都可以共享Volume挂载的文件目录。

容器设计模式

在这里插入图片描述
方法二的问题在于,容器可能第一次运行在宿主机A上,第二次运行在宿主机B上,所以容器是一个可迁移的东西,状态是不保持的。

所以必须维护一套分布式存储系统。使得容器不管是在A还是在B上,都可以找到这个war包。

下面使用initContainer来解决这个问题

  • InitContainer
    在这里插入图片描述
    init container会比用户定义的spec.containers先启动。用途是把war包从镜像复制到"/app"这个Volume里面。

然后启动的container声明/app作为volume,然后把容器内的webapps挂载到/app,那么就可以找到init container复制的那个sample.war了

这就是Sidecar容器设计模式

什么是Sidecar? Sidecar指的是Pod可以定义一些专门的容器,来执行主业务容器所需要的一些辅助工作。上面的init container就是一个sidecar

原本需要在容器里面执行SSH需要干的事情,可以写脚本,一些前置条件等,都可以用Sidecar来解决。

日志收集也可以使用这种方法,另外起一个小的容器专门用于收集日志。业务容器把日志写在Volume里面,日志容器共享这个Volume从而把日志转发到远程存储中。

可以用来debug

可以把监控组件额外装在小容器里面,作为sidecar启动起来,与主业务容器进行协作。

Sidecar最明显的优势就是把辅助功能从业务容器解耦开来,所以就能独立发布Sidecar容器。
而且这些Sidecar容器是可以重用的。

Sidecar as Proxy

假设现在有个Pod需要访问一个外部系统或者外部服务,但是这些外部系统是一个集群,我们需要提供一种简单统一的方式,把集群的访问地址或者是外界对Pod的访问方式用一个IP地址抽象起来。

可以单独写一个小的Proxy用来处理对接外部的服务集群。

业务容器主要访问Proxy,然后由Proxy去连接这些服务集群。关键在于Pod里面多个容器是通过localhost直接通信的,所以他们同属于一个network Namespce.容器间通过localhost通信,没有性能损耗。

Sidecar as adapter
  • 适配器容器将业务容器暴露出来的接口转换为另一种格式
    例如业务容器暴露出来的监控接口是A,现在监控系统更新,需要访问的URL是B,那么可以不用修改代码,额外写一个Adapter容器,把所有对B的请求转发到A,那么Adapter对外暴露的就是B这么一个接口.

设计模式本质

  • 解耦和重用
  • 容器设计模式是K8s进行复杂应用编排的依赖基础之一

docker创建一个pod的全流程

  • 配置namesapce,创建一个namesapce隔离的容器进程
  • 初始进程调用自己
  • 调用exec系统调用,把用户自己指定的程序为容器的初始进程,然后初始化容器内容
  • 创建完成,开始运行容器

K8s运行一个pod的全流程

1.客户端提交请求,可以通过API Server的Restful API/Kubectl

2.API Server处理用户请求,存储Pod数据到etcd

3.调度器(Scheduler会监听API Server)通过API Server查看未绑定的Pod,尝试为Pod分配主机

4.过滤主机(调度预选):调度器可以使用特定规则过滤掉不符合要求的主机,然后进行(调度优选),首先对第一步筛选出来的符合要求的主机进行打分,本质上就是根据调度策略选举最优的Pod

5.选择的结果会告知API-Server,然后结果存储到etcd

6.Kubelet会根据调度结果执行Pod创建操作, 绑定成功后,scheduler会调用APIServer的API在etcd中创建一个boundpod对象,描述在一个工作节点上绑定运行的所有pod信息。运行在每个工作节点上的kubelet也会定期与etcd同步boundpod信息,一旦发现应该在该工作节点上运行的boundpod对象没有更新,则调用Docker API创建并启动pod内的容器。

ref

https://gitbook.cn/gitchat/column/5d68b823de93ed72d6eca1bc/topic/5d6dcee2de93ed72d6ed64ae

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值