深入掌握K8S Pod - Yabea - 博客园

标签: | 发表时间:2020-07-26 21:02 | 作者:
出处:https://www.cnblogs.com

k8s系列文章:

Pod是k8s中最小的调度单元,包含了一个“根容器”和其它用户业务容器。

如果你使用过k8s的话,当然会了解pod的基本使用,但是为了更好的应用,你需要深入了解pod的配置、调度、升级和扩缩容等。本文将会更进一步的介绍pod。

基础

为什么需要pod?

pod包含一个或多个相对紧密耦合的容器,处于同一个pod中的容器共享同样的存储空间、IP地址和Port端口。

为什么k8s要设计出Pod这个概念并作为最小调度单元呢?

直接部署一个容器可能会更加容易,每个容器都有不同的配置和功能,k8s需要对这些容器进行管理(重启、检测等),那么为了避免在容器这个实体上增加更多的属性,就产生了pod这个概念。

并且,Pod中的多个业务容器共享Pause容器的IP,共享Pause容器挂接的Volume,这样既简化了密切关联的业务容器的通信问题,也很好的解决了它们之间的文件共享问题。

容器配置

pod可以由一个或多个容器组合而成,也就是说, 在创建pod时可以给一个pod配置多个container,一般情况下,建议将应用紧耦合的容器打包为一个pod,原则上一个容器一个进程。

共享Volume

同一个pod中的多个容器能够共享pod级别的存储卷Volume,多个容器各自挂载,将一个volume挂载为容器内部需要的目录。

Pod通信

k8s为每个pod都分配了唯一的IP地址,称之为pod IP,一个pod中的多个容器共享Pod IP地址,属于同一个pod的多个应用之间相互访问时仅通过localhost就可以通信。

k8s底层支持集群内任意两个pod之间的TCP/IP直接通信,因此,在k8s中,一个pod中的容器可以与另外主机上的pod里的容器直接通信。

容器限制

需要注意的是:pod中长时间运行的容器需保证其主程序一直在前台运行。比如创建docker镜像时启动命令是通过nohup在后台运行的:

nohup ./start.sh &

那么kubelet创建了包含这个容器的pod之后运行完这个命令,则会根据配置发生两种情况:

  1. 如果pod未配置RC,则认为该pod执行结束,将立刻销毁该pod。
  2. 如果pod配置了RC,该pod终止以后,k8s会根据RC的数量生成新的pod,会陷入一个 销毁-> 创建的无限循环中。

如果无法前台执行,只能后端运行的话,该怎么办呢?

可以借助supervisor。

配置管理

应用部署的一个最佳实践就是将配置信息和程序进行分离,在k8s中可以使用configmap实现。

详细使用可参考: K8S configmap使用

生命周期和重启策略

在创建pod出错了,通常会看到pending状态,而你使用 kubectl get pods 时,也偶尔会看到重启这个字段,那么pod的生命周期和重启策略具体是怎么实现的呢?

一个pod的状态信息是保存在PodStatus对象中的,phase字段用来描述pod在其生命周期中的不同状态,包括:

状态 说明
Pending 挂起。有一个或多个容器未被创建,可以通过kubectl get po ** 查看原因。
running 运行中。所有容器已被创建,至少有一个是运行状态,可通过kubectl logs -f ** 查看日志
succeeded 成功。所有容器执行成功并终止,不会再次重启。
failed 失败。所有容器都已终止,至少有一个容器以失败的方式终止。
unknown 未知。一般是因为通信问题无法获取pod的状态

Pod通常使用探针来检测容器内的应用是否正常,有两类探针:

  1. LivenessProbe探针:判断容器是否存活(Running状态)
  2. ReadinessProbe探针:判断容器是否可用(Ready状态)

在Pod发生故障时对Pod进行重启(仅在Pod所处的Node上操作),具体的方式包括:

操作方式 说明
Always 容器失效时,自动重启
OnFailure 容器以不为0的状态码终止,自动重启
Never 无论何种状态,都不会重启

其中,Pod的重启策略与控制方式息息相关,不同的控制器对pod的重启策略要求不一样:

  1. RC和DaemonSet:必须设置为Always,需要保证容器持续运行
  2. Job:onfailure或者Never,保证容器执行完成后不再重启。

Pod调度

在使用K8S时,我们很少直接创建Pod,大多数情况都是会通过RC、Deployment、DaemonSet、Job等控制器来实现对一组Pod副本的创建、调度和全生命周期的自动控制。

官方建议:不应该使用底层的ReplicaSet来控制Pod副本,推荐直接使用管理ReplicaSet的Deployment对象来控制Pod副本。

全自动调度

Deployment或RC的主要功能之一就是自动部署一个容器应用的多份副本,持续监控副本的数量,保证集群内始终维持指定的副本数量。创建的pod完全由系统自动完成调度,pod各自运行在哪个节点上,完全由master scheduler计算出一个最佳的目标节点进行分配,用户无法干预。

举个例子:

      apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx 
spec:
  replicas: 3
  template:
    metadata:
      labels:
      app: nginx
    spec:
       containers:
         - name: nginx
           image: nginx:1.0
           ports:
             - containerPort: 80

使用kubectl create -f **.yaml创建该Deployment。

使用kubectl get deployments,就会发现刚才创建的deployment有三个副本。

使用kubectl get rs和kubectl get pods可查看已创建的RS和pod,使用kubectl get pod -o wide可以查看pod的分配情况。

定向调度

在实际应用中,经常会需要将Pod调度到指定的一些Node节点上,这时候可配置NodeSelector或者NodeAffinity来进行定向调度。

NodeSelector

具体的使用:

  1. 通过kubectl label命令给目标Node打上标签,可通过kubectl label nodes命令查看所有节点的标签;
  2. 在Pod的定义中加上NodeSelector的设置
  3. 运行kubectl create -f 命令创建Pod时,scheduler就会将pod自动调度指定标签的Node上。

NodeAffinity(节点亲和力调度)

NodeSelector通过标签机制,简单的限制了Pod所在节点的方法,亲和力调度机制则更好扩展了Pod的调度能力,可以使用软限制,支持In、NotIn、Exists、DoesNotExist、Gt、LT等操作符。

  1. 可依据节点上正在运行的其它Pod的标签来进行限制,而非节点本身的标签。

需要注意以下几点:

  1. 如果同时定义了nodeSelector和nodeAffinity,则必须两个条件都满足
  2. 如果nodeAffinity指定了多个nodeSelectorTerms,则其中一个匹配成功即可。
  3. 如果nodeSelectorTerms中有多个matchExpressions。则一个节点必须满足所有matchExpressions才能运行该Pod

PodAffinity(Pod亲和与互斥调度)

根据节点上正在运行的Pod标签而非节点的标签进行判断和调度,对节点和Pod两个条件进行匹配。

具体的使用:

  1. 创建一个名为pod-flag的pod,设置标签
  2. 亲和性调度:创建pod-flag在同一个Node节点的pod
  3. 互斥性调度:可创建与pod-flag不在同一个Node节点的pod

DaemonSet

用于管理在集群的每个Node上仅运行一份pod的副本实例。适用场景:日志采集、性能监控等。

优先调度

为了提高资源利用率,我们通常会采用优先级方案,即不同类型的负载对应不同的优先级,并且当发生资源不足时,系统可以选择释放一些不重要的负载,保障最重要的负载以获取足够的资源稳定运行。

优先级抢占调度策略的有两个核心点:

  1. 驱逐(Eviction):kubelet的行为,当一个Node发生资源不足时,该结点上的kubelet进程会综合考虑优先级、资源申请量和实际资源使用等进行驱逐
  2. 抢占(Preemption):scheduler的行为,当一个新的pod因资源无法满足而不能调度时,scheduler可能会选择(跨节点或本节点)驱逐部分低优先级的pod实例来满足调度

批处理调度 Job

可以通过Job来定义并启动一个批处理任务(并行启动多个进程去处理一些工作项),处理完成后,整个批处理任务结束。

定时任务 Cronjob

类似Linux Cron的定时任务Cron Job。

除此以外,你还可以自定义调度器。

升级和回滚

为了保证服务的高可用,k8s提供了滚动升级功能。主要介绍下deployment。

Deployment

升级

更新镜像名的话,有以下方法进行更新:

  1. 通过 kubectl set image命令设置新的镜像名
  2. 使用 kubectl edit命令修改Deployment的配置,根据yaml的结构更新(比如:将spec.template.spec.containers[0].image从nginx:1.0改为nginx:1.1)。

对于RC的滚动升级,可以使用 kubectl rolling-update命令,该命令会创建一个新的RC,自动控制旧的RC中pod副本数量逐渐减少到0,新的RC中的Pod副本数量从0逐步增加到目标值。

一旦pod的定义发生了修改,则将触发系统完成Deployment中所有pod的滚动操作,可使用 kubectl rollout status查看滚动更新过程。

在升级过程中,deployment能够保证服务不中断,并且副本数量始终维持在用户指定数量。可在Deployment定义中,通过spec.strategy指定pod的更新策略,包括:

  1. Recreate 重建
  2. RollingUpdate 滚动更新

回滚

服务稳定性或者配置错误等原因会使得我们需要进行回滚,Deployment的所有发布历史记录都被保留在系统中,所以回滚是很方便的。具体操作:

  1. 用kubectl rollout history查看deployment的部署历史记录,确定要回退的版本,可以加上--revision=参数查看特定版本详情
  2. 回退到上一个版本或者指定版本
  3. kubectl describe deployment查看操作过程

对于相对复杂的配置修改,为了避免频繁大量触发更新操作,可使用 kubectl rollout pause命令暂停更新操作,然后进行配置修改,最后恢复deployment,一次性触发完整的更新操作。

扩缩容

伴随着资源的使用情况,常需要对pod进行扩缩容,可以利用Deployment/RC的Scale机制来实现,分为手动和自动两种模式。

手动

通过 kubectl scale deployment *** --replicas 3命令更新Pod副本数量,将--replicas设置比当前pod副本数量更小的数字的话,系统会kill一些正在运行的pod。

自动

用户指定pod副本的数量范围,设定依据的性能指标或者自定义业务指标,系统将自动的在这个范围内根据性能指标变化调整pod副本数量。

k8s 1.1版本开始新增了HPA控制器,基于Master的kube-controller-manager服务启动参数--horizontal-pod-autoscal-sync-period定义的探测周期,周期性检测目标pod的资源性能指标。并与设定的扩容条件进行对比,进行pod副本数量的自动调整。

以上。

相关 [k8s pod yabea] 推荐:

深入掌握K8S Pod - Yabea - 博客园

- -
K8S configmap介绍. Pod是k8s中最小的调度单元,包含了一个“根容器”和其它用户业务容器. 如果你使用过k8s的话,当然会了解pod的基本使用,但是为了更好的应用,你需要深入了解pod的配置、调度、升级和扩缩容等. pod包含一个或多个相对紧密耦合的容器,处于同一个pod中的容器共享同样的存储空间、IP地址和Port端口.

k8s外网如何访问业务应用之Service 池化pod

- - IT瘾-geek
一、废话:先讲述一个k8s重要概念,我觉得这个概念是整个k8s集群实现微服务的最核心的概念. Service定义了Pod的逻辑集合和访问该集合的策略,是真实服务的抽象. Service提供了一个统一的服务访问入口以及服务代理和发现机制,用户不需要了解后台Pod是如何运行. 只需要将一组跑同一服务的pod池化成一个service,k8s集群会自动给这个service分配整个集群唯一ip和端口号(这个端口号自己在yaml文件中定义),一个service定义了访问pod的方式,就像单个固定的IP地址和与其相对应的DNS名之间的关系.

在 k8s 中对指定 Pod 进行抓包

- -
Distributed Tracing时,遇到了一些问题,需要深入到底层去进行网络抓包分析报文. 但是应用时运行在 k8s 集群中的,与传统的在一台机器上跑一个进程直接通过 tcpdump 抓包方式略有不同. 最初对容器的理解不深刻认为一定要进入到这个容器抓包,而进入容器内并没有 tcpdump 等基础工具,相当于自己还是把容器当作虚拟机在看待.

影响K8S Pod分配和调度策略的两大关键特性

- - DockOne.io
在Kubernetes中有一个最复杂的调度器可以处理pod的分配策略. 基于在pod规范中所提及的资源需求,Kubernetes调度器会自动选择最合适的节点来运行pod. 但在许多实际场景下,我们必须干预调度过程才能在pod和一个节点或两个特定pod之间进行匹配. 因此,Kubernetes中有一种十分强大的机制来管理及控制pod的分配逻辑.

CentOS7 安装 K8S

- - 企业架构 - ITeye博客
前提:VirtualBox CentOS7. 物理机IP   192.168.18.8. 虚拟机1IP:192.168.18.100(VMaster master). 虚拟机2IP:192.168.18.101(VServer1 node1). 虚拟机3IP:192.168.18.102(VServer2 node2).

解决Kubernetes Pod故障的5个简单的技巧

- - DockOne.io
——轻松地解决Kubernetes应用程序的故障并理解其机制. 在很多情况下,你可能会发现Kubernetes中的应用程序没有正确地部署,或者没有正常地工作. 今天这篇文章就提供了如何去快速解决这类故障以及一些技巧. 在阅读了这篇文章之后,你还将深入了解Kubernetes的内部机制,另外,我还将与大家分享一些关于自己操作K8S的一些非常有用的技巧.

监控 Pod 时,我们在监控什么

- - DockOne.io
应用 Kubernetes 化已经开始推进了一段时间,监控系统也提供了 Kubernetes Pod 相关的监控指标和警报规则. 由于 Kubernetes 和传统的物理机/虚拟机是完全不同的运行环境,因此监控系统提供的监控指标也存在一定的区别. 虽然我们已经尽量统一不同平台的差异,但是日常工作中仍会收到用户对 Kubernetes 监控指标的反馈.

k8s docker集群搭建 - CSDN博客

- -
一、Kubernetes系列之介绍篇.     - 一次构建,到处运行. 2.什么是kubernetes.   首先,他是一个全新的基于容器技术的分布式架构领先方案. Kubernetes(k8s)是Google开源的容器集群管理系统(谷歌内部:Borg). 在Docker技术的基础上,为容器化的应用提供部署运行、资源调度、服务发现和动态伸缩等一系列完整功能,提高了大规模容器集群管理的便捷性.

当Gorilla Pod“踩”上轮滑 小玩意助你完成大制作

- EG - 爱活网最新资讯
还记得当年Gorilla Pod的出现,让多少摄影师大大们一把鼻涕一把泪地欢呼再也不用抬着三脚架那“千斤之躯”满世界跑吗. 但是到了现在,当高清视频拍摄成了数码单反普遍具备的功能时,Gorilla Pod已经满足不了一个简单如摇镜头的要求了. 仿佛一夜回到解放前,各种视频拍摄适用的三脚架又回到了各位惨淡的摄影师肩膀上.

使用kube-proxy让外部网络访问K8S service的ClusterIP

- - zzm
kubernetes版本大于或者等于1.2时,外部网络(即非K8S集群内的网络)访问cluster IP的办法是:. 修改master的/etc/kubernetes/proxy,把KUBE_PROXY_ARGS=”“改为KUBE_PROXY_ARGS=”–proxy-mode=userspace”.