深入掌握K8S Pod
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之后运行完这个命令,则会根据配置发生两种情况:
- 如果pod未配置RC,则认为该pod执行结束,将立刻销毁该pod。
- 如果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通常使用探针来检测容器内的应用是否正常,有两类探针:
- LivenessProbe探针:判断容器是否存活(Running状态)
- ReadinessProbe探针:判断容器是否可用(Ready状态)
在Pod发生故障时对Pod进行重启(仅在Pod所处的Node上操作),具体的方式包括:
操作方式 | 说明 |
---|---|
Always | 容器失效时,自动重启 |
OnFailure | 容器以不为0的状态码终止,自动重启 |
Never | 无论何种状态,都不会重启 |
其中,Pod的重启策略与控制方式息息相关,不同的控制器对pod的重启策略要求不一样:
- RC和DaemonSet:必须设置为Always,需要保证容器持续运行
- 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
具体的使用:
- 通过kubectl label命令给目标Node打上标签,可通过kubectl label nodes命令查看所有节点的标签;
- 在Pod的定义中加上NodeSelector的设置
- 运行kubectl create -f 命令创建Pod时,scheduler就会将pod自动调度指定标签的Node上。
NodeAffinity(节点亲和力调度)
NodeSelector通过标签机制,简单的限制了Pod所在节点的方法,亲和力调度机制则更好扩展了Pod的调度能力,可以使用软限制,支持In、NotIn、Exists、DoesNotExist、Gt、LT等操作符。
- 可依据节点上正在运行的其它Pod的标签来进行限制,而非节点本身的标签。
需要注意以下几点:
- 如果同时定义了nodeSelector和nodeAffinity,则必须两个条件都满足
- 如果nodeAffinity指定了多个nodeSelectorTerms,则其中一个匹配成功即可。
- 如果nodeSelectorTerms中有多个matchExpressions。则一个节点必须满足所有matchExpressions才能运行该Pod
PodAffinity(Pod亲和与互斥调度)
根据节点上正在运行的Pod标签而非节点的标签进行判断和调度,对节点和Pod两个条件进行匹配。
具体的使用:
- 创建一个名为pod-flag的pod,设置标签
- 亲和性调度:创建pod-flag在同一个Node节点的pod
- 互斥性调度:可创建与pod-flag不在同一个Node节点的pod
DaemonSet
用于管理在集群的每个Node上仅运行一份pod的副本实例。适用场景:日志采集、性能监控等。
优先调度
为了提高资源利用率,我们通常会采用优先级方案,即不同类型的负载对应不同的优先级,并且当发生资源不足时,系统可以选择释放一些不重要的负载,保障最重要的负载以获取足够的资源稳定运行。
优先级抢占调度策略的有两个核心点:
- 驱逐(Eviction):kubelet的行为,当一个Node发生资源不足时,该结点上的kubelet进程会综合考虑优先级、资源申请量和实际资源使用等进行驱逐
- 抢占(Preemption):scheduler的行为,当一个新的pod因资源无法满足而不能调度时,scheduler可能会选择(跨节点或本节点)驱逐部分低优先级的pod实例来满足调度
批处理调度 Job
可以通过Job来定义并启动一个批处理任务(并行启动多个进程去处理一些工作项),处理完成后,整个批处理任务结束。
定时任务 Cronjob
类似Linux Cron的定时任务Cron Job。
除此以外,你还可以自定义调度器。
升级和回滚
为了保证服务的高可用,k8s提供了滚动升级功能。主要介绍下deployment。
Deployment
升级
更新镜像名的话,有以下方法进行更新:
- 通过
kubectl set image
命令设置新的镜像名 - 使用
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的更新策略,包括:
- Recreate 重建
- RollingUpdate 滚动更新
回滚
服务稳定性或者配置错误等原因会使得我们需要进行回滚,Deployment的所有发布历史记录都被保留在系统中,所以回滚是很方便的。具体操作:
- 用kubectl rollout history查看deployment的部署历史记录,确定要回退的版本,可以加上--revision=参数查看特定版本详情
- 回退到上一个版本或者指定版本
- 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的更多相关文章
- k8s pod的4种网络模式最佳实战(externalIPs )
[k8s]k8s pod的4种网络模式最佳实战(externalIPs ) hostPort相当于docker run -p 8081:8080,不用创建svc,因此端口只在容器运行的vm ...
- k8s pod节点调度及k8s资源优化
一.k8s pod 在节点间调度控制 k8s起pod时,会通过调度器scheduler选择某个节点完成调度,选择在某个节点上完成pod创建.当需要在指定pod运行在某个节点上时,可以通过以下几种方式: ...
- kubectl cp 从k8s pod 中 拷贝 文件到本地
请查看官方的说明 kubectl cp --help 官方说使用cp , pod里需要有tar命令 从k8s pod 中 拷贝 文件到本地 这是我使用的命令 kubectl exec redis-6c ...
- k8s Pod的自动水平伸缩(HPA)
我们知道,当访问量或资源需求过高时,使用:kubectl scale命令可以实现对pod的快速伸缩功能 但是我们平时工作中我们并不能提前预知访问量有多少,资源需求多少. 这就很麻烦了,总不能为了需求总 ...
- k8s pod访问不通外网问题排查
环境概况 自建k8s集群,主机操作系统ubuntu16.04,k8s版本v1.14, 集群网络方案calico-3.3.6. worker节点数50+,均为GPU物理服务器,服务器类型异构,如Nvid ...
- 2.k8s.Pod生命周期,健康检查
#Pod生命周期,健康检查 pod创建过程 Init容器 就绪探测 存活探测 生命周期钩子 #Pod创建过程 master节点:kubectl -> kube-api -> kubenle ...
- k8s pod,pvc,pv无法删除问题
注意步骤: 一般删除步骤为:先删pod再删pvc最后删pv 但是遇到pv始终处于“Terminating”状态,而且delete不掉 pod一直删不掉 [root@hadoop01 nacos-k8s ...
- k8s pod时区更改
一.问题所在 在K8S里启动一个容器,该容器的设置的时区是UTC0,但是对于很多客户而言,其主机环境并不在UTC0.例如中国客户在UTC8.如果不把容器的时区和主机主机设置为一致,则在查找日志等时候将 ...
- 混沌工程之ChaosToolkit使用之一删除K8s POD
今天我们来玩一下混沌工程的开源工具chaostoolkit . 它的目标是提供一个免费,开放,社区驱动的工具集以及api. 官方源码链接:https://github.com/chaostoolkit ...
随机推荐
- 北京开发票/v电13543443967
关于事项:Iㄋ5一★4З44一★ㄋ9.б7开发票的准备资料必须要公司名称个人的话就用个人名字和身份证去税务柜台申请办理!公司的话要提供公司全称就是营业执照上的名称,纳税人税号,如果是开普通增值税发票的 ...
- Asp.Net 五大对象及作用
Connection(连接对象):与数据源建立连接. DataAdapter(适配器对象):对数据源执行操作并返回结果,在DataSet与数据源之间建立通信,将数据源中的数据写入DataSet中,或根 ...
- MongoDB副本集replica set (二)--副本集环境搭建
(一)主机信息 操作系统版本:centos7 64-bit 数据库版本 :MongoDB 4.2 社区版 ip hostname 192.168.10.41 mongoserver1 192.16 ...
- python3 闭包函数 装饰器
闭包函数 1.闭:定义在函数内部的函数 2.包:内部函数引用了外部函数作用域的名字 在函数编程中经常用到闭包.闭包是什么,它是怎么产生的及用来解决什么问题呢.给出字面的定义先:闭包是由函数及其相关的引 ...
- Lens —— 最炫酷的 Kubernetes 桌面客户端
原文链接:https://fuckcloudnative.io/posts/lens/ Kubernetes 的桌面客户端有那么几个,曾经 Kubernetic 应该是最好用的,但最近有个叫 Lens ...
- java基础-java与c#的可变参数
正文 可变参数,必须最为参数的最后一个参数:可变参数只能有一个: c#可变参数例子: class Program { static void Main(string[] args) { T ...
- 理解C#中的ValueTask
原文:https://devblogs.microsoft.com/dotnet/understanding-the-whys-whats-and-whens-of-valuetask/ 作者:Ste ...
- Js数据类型、Json格式、Json对象、Json字符串
数据类型,从结构上看,所有的数据最终都可以分成三种类型: 第一种类型是scalar(标量),也就是一个单独的string(字符串)或数字(numbers),比如“北京”这个单独的词. 第二种类型是se ...
- C#由转换二进制所引起的思考,了解下?
前言 最近遇到很有意思转换二进制的问题,有部分童鞋俨然已了解,可能也有一部分童鞋没碰到过也就不知情,这里我们来深入学习下转换二进制所带来的问题. 二进制转换问题 假设现在我们有一个int类型的数据,它 ...
- 小程序拾色器(颜色选择器)组件mini-color-picker
特性: 现有方案分析 we-color-picker 需注意组件定位,操作不跟手不流畅,配置复杂.其定位会撑开原有页面,体验不佳.滑动距离按像素区分(固定),需考虑设备分辨率,不利于多端. Papae ...