Kubernetes(五)Pod设计原理和生命周期

一    为什么KUbernetes调度的最小单位是Pod

为什么'需要' Pod

pod demo

问题引入假设 Kubernetes 中调度的基本单元就是容器,对于一个非常简单的应用可以直接被调度直接使用,没有什么问题,但是往往还有很多应用程序是由多个进程组成的

尝试1:我们可以这些进程都打包到一个容器中去不就可以了吗?理论上是可以实现的,但是不要忘记了 Docker 管理的进程是 pid=1 的主进程,其他进程死掉了就会成为僵尸进程,没办法进行管理了,这种方式本身也不是容器推荐的运行方式,一个容器最好只干一件事情,所以在真实的环境中不会使用这种方式。

尝试2:那么我们就把这个应用的进程进行拆分,拆分成一个一个的容器总可以了吧(容器与微服务关系)?但是不要忘记一个问题,拆分成一个一个的容器后,是不是就有可能出现一个应用下面的某个进程容器被调度到了不同的节点上?往往我们应用内部的进程与进程间通信(通过 IPC 或者共享本地文件之类)都是要求在本地进行的,也就是需要在同一个节点上运行。

所以我们需要一个更高级别的结构来将这些容器绑定在一起,并将他们作为一个基本的调度单元进行管理,这样就可以保证这些容器始终在同一个节点上面,这也就是 Pod 设计的初衷

'一个Pod里面多个容器间的关系'

在一个 Pod 下面运行几个关系'非常密切'的容器进程,这样一来这些'进程本身'又可以收到'容器的管控',又具有几乎'一致的运行环境'

二    Pod原理

 Pod 也只是一个逻辑概念,真正起作用的还是 Linux 容器的 Namespace 和 Cgroup 这两个最基本的概念,Pod 被创建出来其实是一组共享了一些资源的容器而已,一组容器的集合

 Pod 里面容器特点

   1)网络方面:默认都是共享的同一个 Network Namespace

   2)文件系统方面:涉及到文件系统的时候,默认情况下 Pod 里面的容器之间的文件系统完全隔离的,但是我们可以通过声明来共享同一个 Volume

(1)Pod内容器网络共享

历史回顾:Docker 网络模式中网络的 Container 模式特点,可以指定新创建的容器和一个已经存在的容器共享一个 Network Namespace,在运行容器的时候只需要指定 --net=container:目标容器名 这个参数

kuberntes中容器之间通过container的网络模式,使同一个Pod里面的容器共享一个NS,但是这种模式有一个明显的问题:那就是容器的启动先后顺序问题

引出:那么 Pod 是怎么来处理这个问题的呢?

那就是加入一个中间容器(相当于加一个中间件),这个容器叫做 Infra(infrastucture) 容器,也叫做sandbox容器,或者沙盒容器、pause容器

这个容器在 Pod 中永远都是第一个被创建的容器,后续启动的容器加入到这个 Infra 容器就可以了,这样就完全实现了 Pod 中的所有容器都和 Infra 容器共享同一个 Network Namespace 

pod infra container

eg:由于'端口冲突,'默认一个pod里面'不能同时有'nginx和apache容器

kubernetes中的Pause容器如何理解

kubernetes pod为什么需要pause容器

问题:'每个Pod都有一个pause容器',是不是'很臃肿'  --> pause容器很轻量,'只有几KB',保证'业务容器'共享Pause容器的'网络栈'和Volume'挂载卷'

systemctl 'status' kubelet  -->  cat /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf

--> cat '/var/lib/kubelet/kubeadm-flags.env' --> kubelet启动传入的'环境变量'

(2)Pod内容器存储共享

问题引入:对于文件系统 Kubernetes 是怎么实现让一个 Pod 中的容器共享的呢?

'默认情况'下容器的文件系统是'互相隔离的'

1)要实现共享只需要在 'Pod(级别)的顶层声明'一个 Volume

2)然后在需要'共享'这个 Volume 的'容器中声明挂载'即可

说明:下面声明了三种卷类型-->'hostPath、empty、vpc' --> '后续讲解存储的时候细讲'

pod containers share volumes

特殊yaml语法

yaml语法: 使用 ">" 和文本内容缩进表示的块:将块中'回车替换为空格',最终'连接成一行'

一个案例

args的'两种表现形式',一种是json格式'[]',一种是yaml格式'-'

 

pod所在主机查询

示例传达

1)我们在 Pod 的'顶层声明了'一个名为 log 的 Volume,而这个 Volume 的类型是 hostPath

 意味这个宿主机的 /var/log/counter 目录将'被这个 Pod 共享'

 '共享给谁呢?' -->  在需要'用到这个数据目录的容器上'声明挂载即可,也就是通过 'volumeMounts 声明挂载'接口

 最终:我们'这个 Pod 就实现了'共享容器的 /var/log 目录,而且数据被'持久化到了'宿主机目录上

牢记:'volume'是Pod级别、'volumeMounts'是container级别、hostPath是'卷类型'的一种

引出sidecar 模式

这个方式也是 Kubernetes 中一个非常重要的'设计模式':'sidecar 模式'的常用方式

典型的场景:就是'容器日志收集'

1)比如上面我们的这个应用'业务容器',其中'应用的日志'是被输出到容器的 /var/log 目录上的,这个时候我们可以把 Pod 声明的 Volume '挂载到'容器的 /var/log 目录上

2)然后在这个 Pod 里面'同时运行一个 sidecar 容器',它也声明挂载相同的 Volume 到自己容器的 /var/log (或其他)目录上,这样我们这个 sidecar 容器就只需要从 /var/log 目录下面'不断消费'日志发送到 'Elasticsearch 中存储起来'就完成了最基本的应用日志的'基本收集'工作了

更多的还是'利用 Pod 中的所有容器共享同一个 Network Namespace' 这个特性,这样我们就可以把 'Pod 网络相关的配置和管理'也可以'交给一个 sidecar 容器'来完成,完全'不需要去干涉'用户容器,这个特性在现在非常火热的 Service Mesh'服务网格'中应用非常广泛,典型的应用就是' Istio'

(3)如何划分 Pod

上面我们介绍了 'Pod 的实现原理',了解到了应该把'业务紧密的容器'划分到同一个 Pod 中运行,那么怎么来区分"关系紧密"呢?

举例:比如我们的 Wordpress 应用,是一个典型的'前端服务器'和'后端数据服务'的应用,那么你认为应该使用一个 Pod 还是两个 Pod 呢?

思考:如果在同一个 Pod 中同时运行服务器程序和后端的数据库服务这两个容器,'理论上肯定是可行的-->你懂的',但是'不推荐'这样使用-->'Wordpress 和 MySQL 即使不运行在同一个节点上也是可行的,只要能够访问到即可'

备注:如果'单机测试'可以这样用下

原因:我们知道一个 Pod 中的所有容器都是同一个'整体进行调度'的,那么在'扩容的时候'

   wordpress --> db1  --> 'pod1'

   wordpress --> db1  --> 'pod2'

造成:'数据隔离'

总结:'有状态的应用'最好不要和'无状态的应用'放在同一个Pod

pod wordpress demo1

判断准则

三    Pod的生命周期

容器启动顺序: 'infra容器'  --> 'init容器'  --> '业务容器'

(1)Pod 状态

官网文档

想'了解下' Pod 的状态值,我们可以通过 'kubectl explain pod.status' 命令来'了解关于 Pod 状态'的一些信息

重点:'控制器'自动'auto'帮我们更新'Pod Status',不需要'手动修改'

说明:Pod 的状态定义在 'PodStatus 对象中',其中有一个 'phase 字段'

下面是 phase 的'可能取值':
  • 挂起(Pending):Pod 信息已经提交给了集群,但是还没有被调度器调度到合适的节点或者 Pod 里的镜像正在下载
  • 运行中(Running):该 Pod 已经绑定到了一个节点上,Pod 中所有的容器都已被创建。至少有一个容器正在运行,或者正处于启动或重启状态
  • 成功(Succeeded):Pod 中的所有容器都被成功终止,并且不会再重启,一般用在Job任务
  • 失败(Failed):Pod 中的所有容器都已终止了,并且至少有一个容器是因为失败终止。也就是说,容器以非0状态退出或者被系统终止(OOM)
  • 未知(Unknown):因为某些原因无法取得 Pod 的状态,通常是因为与 Pod 所在主机网络通信失败导致的
除此之外,'PodStatus 对象'中还包含一个 'PodCondition 的数组',里面'包含的属性'有:

 pod-conditions

kubectl explain pod.status.conditions.type

type:Condition 类型,包括以下方面 --> '官网有文档,但本地文档没有'

pod的状态分析

kubectl get pods pod-init -w  -->  '看到状态变化'
常见的'状态转换场景'

(2)重启策略

强调:一旦'binding --> 绑定'到一个节点,Pod将永远'不会重新绑定'到另一个节点,除非'Node异常'

查看已下载的'Docker镜像'latest'具体版本'

docker image inspect 'docker images 某一个镜像的名称':latest | grep -i version

(3)初始化容器

初始化容器常与'volume'有关  --> 一个pod里面'声明的卷',可以挂在'任意容器'里'有需要的容器'

  Init 容器与普通的容器差异

1)Init 容器总是'运行到成功完成'为止

2)每个 Init 容器都必须在下一个 Init 容器'启动之前成功'完成

如果 Pod 的 Init 容器失败,Kubernetes 会'不断地重启'该 Pod,直到 Init 容器成功为止。然而如果 Pod 对应的 'restartPolicy 为 Never',它不会重新启动

kubectl explain pods.spec.initContainers

下面一个案例: init容器,生成'配置信息-->这里随意生成一个文件',让另一个pod使用

init容器'不在'READY总容器中

 

报错信息 

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值