关于k8s:万字警告-k8s入门理应Pod先行

4次阅读

共计 13691 个字符,预计需要花费 35 分钟才能阅读完成。

大家好,欢送来到小菜集体 solo 学堂。在这里,常识收费,不吝排汇!关注收费,不吝入手!
死鬼~ 看完记得给我来个三连哦!

本文次要介绍 kubernetes 中 pod 的应用

如有须要,能够参考

如有帮忙,不忘 点赞

微信公众号已开启,小菜良记,没关注的同学们记得关注哦!

上篇文章咱们说到如何搭建 k8s 集群,不晓得看完的小伙伴有没有本人去尝试一下呢!

不要让贫困扼杀了你学 k8s 的趣味

这篇咱们本着虎头蛇尾的准则,持续带你搞明确 k8s 中的pod,成为他人家的程序员~

咱们老样子,先回顾下 k8s 中存在的几种组件:

那咱们还得理解一下 k8s 中几种常见的资源:

  • Master: 集群管制节点,每个集群都至多须要一个 master 节点负责集群的管控
  • Node: 工作负载节点,由 master 调配容器到这些 node 节点上,而后 node 节点上的 docker 负责容器的运行
  • Pod: kubernetes 的最小管制单元,容器都是运行在 pod 中的,一个 pod 中能够有 1 个或多个容器
  • Controller: 控制器,通过它来实现对 pod 的治理,比方启动 pod,进行 pod,伸缩 pod 的数量等等
  • Service: pod 对外服务的对立入口,能够保护同一类的多个 pod
  • Label: 标签,用于对 pod 进行分类,同一类的 pod 会领有雷同的标签
  • NameSpace: 命名空间,用来隔离 pod 的运行环境

这几个概念先初步有个理解即可,接下来便是对每个概念开展阐明的时候~ 那么,正片开始!

Kubernetes

一、资源管理

在 kubernetes 中,所有的内容都形象为资源,用户须要通过操作资源来治理 kubernetes

对于对 资源管理 的了解,咱们须要理解以下几个概念:

  • kubernetes 实质上是一个集群零碎,用户能够在集群中部署各种服务
  • kubernetes 最小治理单元是 pod 而不是容器,所以咱们须要将容器放在 pod 中运行,而 pod 个别是由 pod 控制器 进行治理的
  • pod 提供服务后,咱们须要借助 service 这个资源来实现拜访 pod 中的服务
  • pod 也反对数据的长久化

而后咱们通过上面图例梳理一下下面几个概念:

通过下面那张图咱们差不多就能够将 kubernetes 中的重点资源了解一遍了,大略明确每个资源在集群中起到的作用。

咱们有三种形式能够对资源对象进行治理:

  • 命令式对象治理

间接应用命令来操作 kubernetes 资源。例如:

kubectl run nginx --image=nginx:1.19.0 -port=80
  • 命令式对象配置

通过命令配置和配置文件来操作 kubernetes 资源。例如:

kubectl create/patch -f nginx.yml
  • 申明式对象配置

通过 apply 命令和配置文件来操作 kubernetes 资源。例如:

kubectl apply -f nginx.yml

在 k8s 中咱们个别应用 YAML 格局的文件来创立合乎咱们预期冀望的 pod,这样的 YAML 文件称为资源清单。咱们也比拟激励应用清单的形式来创立资源。

如果咱们应用 命令式对象治理,这种形式尽管比较简单,能够间接创立一个 pod 进去,然而只能操作流动对象,无奈进行审计和跟踪。

命令式对象配置 申明式对象配置 在咱们日常中在创立资源服务中是比拟常常用到。

1)命令式对象治理

kubectl 这个是 kubernetes 集群的命令行工具,通过 kubectl 可能对集群自身进行治理,并可能在集群上进行容器化利用的装置部署。能够设想咱们接下来的操作绝大部分都须要借助这个命令工具的帮忙。

咱们之前也曾经应用过一次了:kubectl get nodes。这个命令便是用来获取集群中各个节点状态的,那么不难想象,这个命令的语法:

kubectl [command] [TYPE] [NAME] [flags]
  • command:指定对资源执行的操作、例如:create、get、describe、delete...
  • TYPE: 指定资源类型。资源类型是大小写敏感的,开发者能以复数、复数和缩写的模式,例如:pod、pods、po
  • NAME: 指定资源的名称。名称也是大小写敏感的,如果省略名称,则会显示所有的资源,例如:kubectl get pods
  • flags: 指定可选的参数。例如:-s、-server、-o ...

k8s 反对的 command 有很多,咱们能够跟 docker 一样应用 kubectl --help 来获取帮忙文档:

文档很多,当然有些是罕用的,有些是不罕用的,小菜在这里给你们简略分个类,下次有须要能够间接查看分类中的后果!

命令分类

1、根底命令

名称 形容
create 通过文件名或规范输出创立资源
expose 将一个资源公开为一个新的 Service
run 在集群中运行一个特定的镜像
set 在对象上设置特定的性能
get 显示一个或多个资源
edit 应用默认的编辑器编辑一个资源
delete 通过文件名、规范输出、资源名称或标签
explain 获取文档参考资料

2、部署命令

名称 形容
rollout 治理资源的公布
rolling-update 对给定的控制器进行滚动更新
scale 扩容或缩容 pod 数量,可对 Deployment、ReplicaSet、RC 或 Job 操作
autoscale 创立一个主动抉择扩容或缩容并设置 pod 数量

3、集群治理命令

名称 形容
certificate 批改证书资源
cluster-info 显示集群信息
top 显示资源应用状况,须要运行 Heapster
cordon 标记节点不可调度
uncordon 标记节点可调度
drain 驱赶节点上的利用,筹备下线保护
taint 批改节点的 taint 标记

4、故障 \ 调试命令

名称 形容
describe 显示特定资源或资源组的详细信息
logs 在一个 pod 中打印容器日志,如果 pod 中只有多个容器,容器名称是可选的
attach 附加到一个运行的容器
exec 执行一个命令到容器中
port-forward 转发一个或多个本地端口到一个 pod
proxy 运行一个 proxy 到 kubernetes ApiServer
cp 拷贝文件或目录到容器中
auth 查看受权

6、高级命令

名称 形容
apply 通过文件名或规范输出对资源利用配置
patch 应用补丁批改、更新资源的字段
replace 通过文件名或规范输出替换一个资源
convert 不同的 API 版本之间转换配置文件

7、设置命令

名称 形容
label 更新资源上的标签
annotate 更新资源上的标签
completion 用于实现 kubectl 工具主动补全

8、其余命令

名称 形容
api-versions 打印受反对的 API 版本
config 批改 kubeconfig 文件(用于拜访 API,比方配置认证信息)
help 获取所有命令帮忙
plugin 运行一个命令行插件
version 打印客户端和服务版本信息

咱们通过一些简略的例子来简略的认识一下这个命令工具:

2)资源清单

不论是 命令式对象配置 还是 申明式对象配置 咱们都须要借助 yaml 资源清单创立。

咱们先来看看一个 pod controller(控制器) 的yaml 文件中有哪些内容:

下面便是一个残缺的 deployment 资源配置清单。内容很多,老样子咱们先混个眼生,不是每个 deployment 都须要这么多的配置,以下便是必须存在的字段属性介绍:

名称 类型 形容
version String 属于 k8s 哪一个 API 版本或组
kind String 资源类型,如pod、deployment、service
metadata Object 元数据对象,嵌套字段
metadata.name String 元数据对象的名字
spec Object 定义容器的标准,创立的容器应该有哪些个性
spec.container[] List 定义容器的列表
spec.container[].name String 容器的名称
spec.container[].image String 定义要用到镜像的名称

3)命令式对象配置

咱们联合以上必存的字段,能够简略写出一个 yaml(test.yaml)文件:

而后咱们能够通过 命令式对象配置 的形式创立出一个 pod:

kubectl create -f test.yaml

4)申明式对象配置

申明式对象配置 命令式对象配置 很类似,然而这种形式都是基于 apply 这一个命令来进行操作的。

咱们这边复用一下下面创立的 test.yaml 文件

kubectl apply -f test.yaml

这种形式不能说是鸡肋,它有它的特点,比如说咱们执行完上述命令后再执行一遍:

kubectl apply -f tset.yaml

能够发现是没什么改变的,然而如果咱们应用的是 create 来反复执行两遍呢?后果是 报错

那么咱们不难猜出 apply 这个命令就是对 createpatch 这两个命令的联合:

  • 如果资源不存在,则执行创立 等同于 create
  • 如果资源存在,则执行更新 等同于 patch

二、实战入门

接下来的阶段便是咱们针对 k8sNameSpace 和 Pod 资源开展阐明了,小伙伴们打起精神了哦!

1)Namespace

Namespace(命名空间) 的作用便是用来实现多用户之间的资源那个李的,通过将集群外部的资源对象调配到不同的 Namespace 中,造成逻辑上的分组,便于不同分组在共享应用整个集群资源的同时被别离治理。默认状况下,kubernetes 集群中的所有 pod 都是能够相互拜访的,然而有些时候咱们不想呈现这种状况,那就能够借助于 namespace

在集群外部有个默认的Namespace – default,咱们创立资源的时候如果不指定 namespace,那么就会将该资源分配到该 default 的命名空间之下。

[root@master test]# kubectl get namespace

创立 Namespace 的形式也很简略,通过以下指令便可创立:

[root@master test]# kubectl create namespace aaa-test

这样子,咱们就取得了一个名称为 aaa-test 的命名空间。或者咱们也能够通过 命令式对象配置 的形式创立,先筹备一个 yaml 文件:

apiVersion: v1
kind: Namespace # yaml 文件中大小写敏感
metadata:name:aaa-test  #命名空间的名称

而后执行kubectl create -f namespace.yml,这样子咱们同样也能够取得一个名称为 aaa-test 的命名空间。

而后咱们就能够在资源创立的时候应用了:

而后执行 kubectl create -f nginx.yml,这样子咱们就能够获取到一个 pod 资源,只有通过指定命名空间能力查看到咱们的 pod 资源,这阐明对其余用户是隔离的:

如果咱们想删除命名空间的话,能够应用指令:kubectl delete -f namespace.ymlkubectl delete ns ns 名称

注: 如果将命名空间删除,那么存在于该命名空间下的资源会全副被删除

2)Pod

Pod 是 k8s 中能够创立和治理的最小单元,是资源对象模型中由用户穿件或部署的最小资源对象模型,也是在 k8s 上运行容器化利用的资源对象。

在应用 docker 的时候,咱们分明程序要运行就必须部署在容器中,而在 k8s 中,咱们容器必须存在与 pod 中,pod 就能够认为是容器的封装,一个 pod 能够存在一个或多个容器。

㈠ Pod 概念
① pod 个性

1. 资源共享

在一个pod 中,多个容器之间能够共享存储和网络,相当于一个逻辑意义上的主机。

2. 生命周期短暂

pod 是一个具备生命周期的组件,如果 pod 所在的节点产生故障,那么该节点上的 pod 都会被调度到其余节点上,而调度后的pod 是一个全新的 pod,与之前没有任何关系。

3. 平坦的网络

k8s 集群中的所有 pod 都在同一个网络地址空间中,也就是说每个 pod 都能够通过其余 pod 的 IP 地址来实现拜访

② pod 分类
  • 一般 pod

这种就是咱们 日常中常常用到 的。一旦被创立就会放入 etcd 中存储,接着就会被调度到任一节点上运行,当 Pod 里某个容器进行时,Kubernetes 会自动检测到这个问题并且重新启动这个 Pod 里某所有容器,如果 Pod 所在的 Node 宕机,则会将这个 Node 上的所有 Pod 从新调度到其它节点上。

  • 动态 pod

动态 pod 是由 kubelet 激进型治理的仅存在于特定 node 节点上的,它们不能通过 API server 进行治理,无奈与 controller 控制器 进行治理,并且 kubelet 也无奈对其进行衰弱检测。

③ pod 申明周期

pod 中有 5 中生命周期,咱们都须要理解一下~

状态名称 形容
Pending API Server 曾经创立了 pod,但 pod 中的一个或多个容器的镜像还没有创立,包含镜像下载过程
Running Pod 内所有容器都已创立,且至多一个容器处于运行状态,正在启动状态或正在重启状态
Completed Pod 内所有容器均胜利执行退出,且不会再重启
Failed Pod 内所有容器都已退出,但至多一个容器退出失败
Unknown 因为某种原因无奈获取 Pod 状态,例如网络不通
④ pod 重启策略
策略名称 形容
Always 当容器生效时,有 kubelet 主动重启该容器
OnFailure 当容器进行运行且退出码不为 0 时,由 kubelet 主动重启该容器
Never 不管容器运行状态如何,kubelet 都不会重启该容器
⑤ pod 资源配置

之前在 docker 咱们有进行测试没有对 docker 资源进行限额的时候,运行一个 elasticSearch 镜像的时候服务器间接卡死。那么在 docker 能做到资源限额,k8s 中天然也能够。

Kubernetes 中能够设置限额的计算资源有 CPUMemory 两种。Kubernetes 咱们想要进行配额限定须要设定两个参数:RequestLimits

  • Request:示意该资源最小的申请量,零碎必须满足要求
  • Limits:示意该资源最大容许使用量,不能超出这个量,当容器试图应用超过这个量的资源时,就会被 Kubernetes kill 掉并重启

下面示意一个 nginx 容器起码须要 0.25 个 CPU 和 64 MB 内存,最多只能应用 0.5 个 CPU 和 128 MB 内存。

㈡ pod 基操

以下是一份 pod 的残缺资源清单:

这份清单大部分看起来会比拟生疏,然而有局部要害属性咱们在下面曾经讲过了,当咱们理论要用的时候如果记不起那么多咱们能够应用指令 kubectl explain pod.xxx 的形式来查看每个属性的含意,例如

① 简略创立

咱们如果想要创立一个 pod,只须要简略筹备一份 test.yml 文件即可:

而后通过 命令式对象配置 的指令 kubectl create -f test.yml 就能够获取到一个含有 nginx 和 centos 容器的 pod。而后咱们通过指令kubectl get pod -n cbuc-test 查看以后 pod 的状态。

docker 能够用 docker exec -it 进入容器,k8s 也是相似此命令:

kubectl exec -it pod 名称 -c 容器名称 -n 命名空间 bash

通过以上命令就能够进入到咱们的 pod 中

如果 pod 中只有一个容器,-c 能够不必指定容器名称

② 属性阐明

下面咱们曾经胜利的创立了一个 pod,然而这只是一个简略的 pod 配置,咱们能够针对该 yaml 文件进行扩大~

1. imagePullPolicy

这个属性用来设置镜像拉取策略,在 k8s 中反对三种镜像拉取策略:

  • Always: 总是从近程仓库拉取镜像
  • IfNotPresent: 本地有则应用本地镜像,本地没有则从近程仓库拉取镜像
  • Never: 只应用本地镜像,从不去近程仓库拉取,本地如果不存在就会报错

留神:

如果镜像号为指定版本号,则默认策略为:IfNotPresent

如果镜像号为 latest,则默认策略为:Always

2. command

command 是用于在 pod 中的容器初始化结束之后运行一个命令。

咱们在下面创立了一个 centos 的 pod,而后在 pod 初始化实现后,便会执行 command 中的命令,咱们能够通过 kubectl exec -it pod 名称 -n 命名空间 bash 而后进入 pod 中查看 /mnt/test.txt

或者咱们能够在 pod 内部执行命令:

kubectl exec pod 名称 -n 命名空间 -c 容器名称 -- shell 命令

3. args

咱们下面说到的 command 曾经能够实现启动命令和传递参数的性能,然而咱们 k8s 中还提供了一个 args 选项,用于传递参数。k8s 中应用 command 和 args 两个参数能够实现笼罩 Dockerfile 中的 ENTRYPOINE 的性能。

留神:

  1. 如果 command 和 args 均没有写,那么是应用 Dockerfile 的配置
  2. 如果 command 写了,args 没有写,那么 Dockerfile 默认的配置会被疏忽,执行输出的 command
  3. 如果 command 没写,args 写了,那么 Dockerfile 中配置的 ENTRYPOINT 的命令会被执行,应用以后 args 的参数
  4. 如果 command 和 arg 都写了,那么 Dockerfile 的配置就会被疏忽,执行 command 命令加上 args 参数

4. env

用于在 pod 中的容器设置环境变量

进入 pod 查看:

5. ports

ports 在 k8s 的属性类型是 Object,咱们能够通过 kubectl explain pod.spec.containers.ports 查看该对象下的属性:

咱们从图中能够发现该对象由 5 个属性:

  • containerPort: 容器要监听的端口(0~65536)
  • hostIP: 要将内部端口绑定到主机 IP(个别省略)
  • hostPort: 容器要在主机上公开的端口,如果设置,主机上只能运行容器的一个正本(个别省略)
  • name: 端口名称,如果指定,必须保障 name 在 pod 中是惟一的
  • protocol: 端口协定,必须是 UDP、TCP 或 SCTP,默认为 TCP

咱们简略看个 nginx 的例子:

创立形式能够抉择 3 中创立形式任意一种,而后创立实现后咱们能够通过 podIp+containerPort 来拜访到 nginx 资源

6. resources

容器中运行的程序须要占用肯定的资源(CPU 和内存),在运行的时候如果不对某个容器的资源进行限度,那么它可能会耗尽服务器的大量资源,避免这种状况的产生,k8s 中提供了 resource 属性,对资源进行限度。这个属性下有两个子选项:

  • limits: 用于限度运行容器的最大占用资源,当容器占用资源超过 limit 时会被终止,并进行重启
  • requests: 用于设置容器须要的最小资源,如果环境资源不够,容器将会无奈启动

看个应用例子:

  • cpu: core 数,能够为整数或小数
  • memory: 内存大小,能够应用 Gi,Mi,G,M 等模式
㈢ pod 扩大
① 生命周期

任何事物的创立过程都有属于它本人的生命周期,而 pod 对象从创立到销毁,这段的工夫范畴便称为 pod 的生命周期。生命周期个别蕴含上面几个过程:

运行初始化容器(init container)过程

运行主容器(main container)

2.1 容器启动后钩子(post start),容器终止前钩子(pre stop)

2.2 容器存活性检测(liveness probe),就绪性检测(readiness probe)

pod 终止过程

在整个生命周期中,pod 也会相应的呈现 5 中状态,如下:

  • 挂起(Pending): apiServer 曾经创立 pod 资源对象,但它尚未被调度实现或者仍处于下载镜像的过程中
  • 运行中(Running): pod 曾经被调度至某节点,并且所用容器都曾经被 kubelet 创立实现
  • 胜利(Succeeded): pod 中的所有容器都曾经胜利终止并且不会被重启
  • 失败(Failed): 所有容器都曾经终止,但至多有一个容器终止失败,即容器返回了非 0 值的退出状态
  • 未知(UnKnown): apiServer 无奈获取到 pod 对象的状态信息,通常是因为网络通信失败导致的

    ⑴ pod 的创立过程

kubernetes 启动后,无论是 master 节点 亦或者 node 节点,都会将本身的信息存储到 etcd 数据库中

  1. 用户通过 kubectl 或其余 api 客户端提交须要创立的 pod 信息给 apiServer
  2. apiServer 接管到信息后会生成 pod 对象信息,并存入 etcd 数据库中,返回确认音讯给客户端
  3. apiServer 开始反映 etcd 中 pod 对象的变动,其余组件会应用 watch 机制来跟踪查看 apiServer 上的变动
  4. scheduler 发现如果有新的 pod 对象须要创立,便会为 pod 调配主机并将后果回送至 apiServer
  5. node 节点上的 kubectl 发现有 pod 调度过去,会尝试调用 docker 启动容器,并将后果返回给 apiServer
  6. apiServer 将接管到的 pod 状态信息存入 etcd

⑵ pod 的终止过程

  1. 用户首先向 apiServer 发送删除 pod 对象的命令
  2. apiServer 中的 pod 对象信息会随着工夫的推移而更新,在宽限期内(默认 30s),pod 会被视为 dead 状态,并将 pod 标记为 terminating 状态
  3. kubelet 在监控到 pod 对象转为 terminating 状态的同时启动 pod 敞开过程
  4. 端点控制器监控到 pod 对象的敞开行为时将其从所有匹配到此端点的 service 资源的端点列表中移除
  5. 如果以后 pod 对象定义了 preStop 钩子处理器,则在其标记为 terminating 后即会以同步的形式启动执行
  6. pod 对象中的容器过程接管到进行信号,并进行容器
  7. 宽限期完结后,如果 pod 中还存在仍在运行的过程,那么 pod 对象就会收到立刻终止的信号
  8. kubelet 申请 apiServer 将此 pod 资源的宽限期设置为 0 从而实现删除操作。

⑶ 初始化容器

初始化容器,看名字也大抵可能猜到初始化容器是在 pod 主容器启动之前要运行的容器,次要是做一些主容器的前置工作。

特色:

  • 初始化容器必须运行实现直至完结,如果运行失败便会进行重启直至胜利
  • 初始化容器必须依照程序执行,只有前一个胜利后,后一个能力执行

这里简略看一个应用例子:

咱们在初始化容器中定义了一个 centos 容器,只有 ping 通对应的地址才会启动胜利,已知以后网络能通 192.168.108.101

能够看到,在初始化容器胜利启动的状况下,咱们的 nginx 容器也能运行胜利,然而如果咱们把 ping 的地址改一下,就会导致初始化容器启动失败,那么失常容器也是会启动失败的:

⑷ 钩子函数

不晓得你对钩子函数这个词是否有一些理解~ 钩子函数可能感知本身生命周期中的事件,在相应的时刻到来时就会运行用户指定的程序代码。

k8s 提供了两个钩子函数,别离是 启动之后 进行之前

  • post start:容器创立之后执行。如果失败了会重启容器
  • pre stop: 容器终止之前执行。执行实现之后容器将胜利终止,在其实现之前会阻塞删除容器的操作

那么钩子函数有了,咱们该如何定义这个函数呢?在 k8s 中钩子函数反对应用三种形式定义动作:

  • exec 命令

在容器中执行一次命令,如果命令执行的退出码为 0,则认为程序失常,否则反之。

  • tcpSocket

将会尝试拜访一个用户容器的端口,如果可能建设这条连贯,则认为程序失常,否则不失常

  • httpGet

调用容器内 Web 利用的 URL,如果返回的状态码在 200 和 399 之间,则认为程序失常,否则不失常

② 容器探测

容器探测是用来检测容器中的利用实例是否失常工作,是保障业务可用性的一种传统机制。如果通过探测,实例的状态不合乎预期后果,那么 k8s 就会把这个实例删除。在 k8s 中也反对了两种探针来实现容器探测:

  • liveness probes: 存活性探针,用于检测利用实例以后是否处于失常运行状态,如果不是,k8s 会重启容器
  • readiness probe: 就绪性探针,用于检测利用实例以后是否能够承受申请,如果不能,k8s 不会转发流量

留神:

livenessProbe 决定了容器是否须要重启

readinessProbe 决定了是否将申请转发给容器

这两种探针反对的检测形式与下面生命周期检测的形式一样:

  • exec 命令

  • TCPSocket

  • httpGet

③ 重启策略

容器探测 检测出容器有问题后,k8s 就会对容器所在的 pod 进行重启,而这些重启的定义便是由 pod 本身的重启策略决定的,pod 的重启策略有如下 3 种:

  • Always: 容器生效时,主动重启该容器(默认值)
  • OnFailure: 容器终止运行且退出码不为 0 时重启
  • Never: 不管状态为何,都不重启该容器

首次须要重启的容器会立刻进行重启,如果随后还须要重启,那么kubectl 便会提早一段时间后才进行,重复重启的操作提早时长为 10s,20s,30s,40s,80s,160s 和 300s,其中 300s 是最大的提早时长

㈣ pod 调度

下面说到过默认状况下,pod 在哪个 Node 节点上运行是由 Scheduler组件采纳相应的算法计算出来的,这个过程是不受人工控制的。然而在理论的应用场景中咱们有时候想要管制某些 pod 达到某些节点上,而针对于这种需要,k8s 当然也是能够满足的~ 在 k8s 中它提供了 4 中调度形式:

  • 主动调度:scheduler 组件计算运行在哪个 node 节点上
  • 定向调度: 由用户自定义,须要用到 NodeNameNodeSelector 属性
  • 亲和性调度: 由用户自定义,须要用到 NodeAffinity、PodAffinity、PodAntiAffinity 属性
  • 污点容忍调度: 由用户自定义,须要用到 Taints、Toleration属性
① 定向调度

咱们能够利用 nodeName 或者 nodeSelector 来标记 pod 须要调度到冀望的 node 节点上。这里的标记是强制性,不论 node 节点有没有宕机,都会往这个节点下面调度,因而如果 node 节点宕机的话,就会导致 pod 运行失败。

  • NodeName

这个属性用于强制束缚将 Pod 调度到指定名称的 node 节点上,这种形式,其实就是间接跳过 scheduler 的调度逻辑。

下面曾经筹备了一个 pod 的 yaml 文件,咱们创立看下是否可能调度到咱们想要的节点上

能够看到 pod 节点曾经胜利的调度到名称为 node02 的节点上了

  • NodeSelector

这个属性是用于将 pod 调度到增加了指定标签上的 node 节点上(k8s 中资源能够打标签,咱们一样能够对 node 节点打标签)。它是通过 k8s 的 label-selector 机制实现的,就是说在 pod 创立之前,会由 scheduler 的应用 MatchNodeSelector 的调度策略进行 label 匹配,找出指标 node,而后将 pod 调度到指标节点,该匹配规定也是属于强制束缚。

测试:

首先对 node 节点打上标签:

kubectl label nodes node02 app=node-dev

查看是否打胜利:

而后筹备一份 pod yaml 文件:

而后咱们创立后查看:

② 亲和度调度

下面介绍的定向调度是属于强制性束缚,如果没有满足的 node 节点供运行的话,pod 就是启动失败,这样子就很大地限度了它的应用场景。所以咱们接下来介绍的 亲和度调度 (Affinity) 便是用来解决这种问题的。

它是通过配置的模式,实现优先选择满足条件的 Node 进行调度,如果有就调度到对应节点,如果没有,也能够调度到不满足条件的节点上,这样能够使调度更加灵便

Affinity 分为三大类:

  • nodeAffinity(node 亲和性)

node 为指标,解决 pod 能够调度到哪些 node 的问题

这个属性中又存在 requiredDuringSchedulingIgnoredDuringExecution (硬限度)preferredDuringSchedulingIgnoredDuringExecution (软限度) 两种

Ⅰ、requiredDuringSchedulingIgnoredDuringExecution (硬限度)

这个限度和下面说到的定向调度有点像,只抉择满足条件的 node 节点进行调度,应用例子如下:

下面咱们创立了一个 pod,会在标签 keyapp,且valuenode-pro 或 node-test 的节点上抉择,然而并不存在具备这个标签的节点,因而这个 pod 始终处于挂起的状态~

咱们下面看到了一个新的属性 matchExpressions,这个是用来编写关系表达式的,具体应用办法如下:

- matchExpressions:
  - key: app # 匹配存在标签的 key 为 app 的节点
    operator: Exists
  - key: app # 匹配标签的 key 为 app , 且 value 是 "xxx" 或 "yyy" 的节点
    operator: In
    values: ["xxx","yyy"]
  - key: app # 匹配标签的 key 为 app, 且 value 大于 "xxx" 的节点
    operator: Gt
    values: "xxx"

Ⅱ、preferredDuringSchedulingIgnoredDuringExecution (软限度)

下面曾经理解到了 硬限度 的应用, 软限度 的应用如下,咱们间接来看 yaml 文件:

这边能够看到尽管不存在满足条件的 node,然而也是能够胜利运行 pod 的,只是调度到了不满足条件的 node 上!

咱们来总结一下硬限度和软限度的用法:

  • podAffinity(pod 亲和性)

以 pod 为指标,解决 pod 能够和哪些已存在的 pod 部署在同一个拓扑域中的问题。

podAffinity 同样也存在 硬限度 和 软限度,咱们接下来间接看下如何配置:

下面便是 podAffinity 硬限度的 yaml 文件,除了眼生的属性之外,咱们还看到了一个新的属性 topologyKey,那么这个属性是用来干嘛的呢?

topologyKey 用于指定调度时作用域:

  • 如果值为 kubernetes.io/hostname,阐明是以 node 节点为辨别范畴
  • 如果值为 kubernetes.io/os,则以 node 节点的 操作系统 来辨别

理解完硬限度的编写,软限度也是与下面 node 亲和度的用法类似,这里不再赘诉~

  • podAntiAffinity(pod 反亲和性)

以 pod 为指标,解决 pod 不能和哪些已存在的 pod 部署在同一个拓扑域中的问题。

这个应用就是和下面基本一致了,就是和 podAffinity 要求反着来就是了,属性名换个就完事了~

这个 yaml 文件代表的含意便是抉择不和标签带有 app=test01app=test02 的 pod “ 共处一室 ”。同样存在硬限度和软限度的配置

亲和性 反亲和性 的应用场景

亲和性: 如果两个利用交互频繁,那就有必要利用亲和性让两个利用尽可能的凑近,能够缩小因为网络通信而带来的性能损耗

反亲和性: 当利用采纳多正本部署的时候,有必要采纳反亲和性让各个利用实例打散散布在各个 node 上,这样能够进步服务的高可用性

③ 污点(Taint)

咱们先来看下目前 pod 存在于每个节点的状况,

是否发现了一个问题,那就是 pod 根本都散布在了 node 节点上,而 master 节点却没有运行任何 pod。而这个起因便是和咱们要讲到的 污点 有关系了!

咱们后面说到的调度都是站在 pod 的角度,让 pod 抉择 node 进行运行,而污点很好的进行了反转。让 node 节点决定让哪些 pod 能够调度过去!

Node 能够设置 污点 ,设置上 污点 之后,就会和 pod 之间造成了一种排挤关系。这种关系存在的意义便是能够回绝 pod 调度进来,也能够将曾经存在的 pod 驱赶进来。

污点格局: key=value:effect

keyvalue 是污点的标签,而 effect 则是用来形容污点的作用,反对三种性能定义:

  • PreferNoSchedule

    k8s将尽量避免把 Pod 调度到具备该污点的 node 节点上,除非没有其余节点能够调度。(尽量不要来,除非没方法)

  • NoScheduler

    k8s 将不会把 Pod 调度到具备该污点的 node 节点上,但不会影响以后 Node 上曾经存在的 pod。(新的不要来,在这的就别动了)

  • NoExecute

    k8s 将不会把 Pod 调度到具备该污点的 node 节点上,同时也会将 Node 上曾经存在的 Pod 驱赶。(新的不要来,在这的连忙走)

设置污点命令如下:

# 设置污点
kubectl taint nodes node01 key=value:effect

# 去除污点
kubectl taint nodes node01 key:effect-

# 去除所有污点
kubectl taint nodes node01 key-

而 k8s 中的 master节点之所以没有运行任何 pod,那便是因为 master 节点上曾经存在了污点:

④ 容忍(Toleration)

下面说到如果 node 节点存在污点,那么 pod 就会无奈调度。那如果 pod 有时候就是想 “ 厚着脸皮 ”,哪怕你存在污点,也不厌弃的想要调度进去有没有方法解决呢?

k8s 也是想到了这种状况的存在,因而便有了一个 容忍 的属性!

污点就是回绝,容忍就是疏忽,Node 通过污点来回绝 pod 调度下来,pod 通过容忍疏忽回绝

咱们先给 node01 打上 NoExecute 的污点,而后咱们再给 pod 增加容忍,看下是否可能胜利调度下来

pod yaml:

通过增加容忍后,咱们能够发现 pod 在 node01 的节点上胜利运行了,阐明容忍胜利~

容忍的配置信息如下:

tolerations:
- key         # 对应着要容忍的污点的键,空意味着匹配所有的键
  value        # 对应着要容忍的污点值
  operator    # key-value 的运算符,反对 Equal 和 Exists(默认)effect    # 对应污点的 effect,空意味着匹配所有的影响
  tolerationSeconds  # 容忍工夫,当 effect 为 NoExecute 时失效,示意 pod 在 Node 上的停留时间

END

对于 k8s 中 pod 的介绍到这里就完结啦~ 集体感觉还是挺具体的,如果可能认真看下来,置信对 pod 曾经有足够理解了。然而你认为 k8s 到这里就完结了吗?那必定不会的,碍于篇幅,所以其余资源组件留到下一节介绍~ 请动动小手,点点关注不迷路。路漫漫,小菜与你一起求索!

明天的你多致力一点,今天的你就能少说一句求人的话!

我是小菜,一个和你一起学习的男人。 💋

微信公众号已开启,小菜良记,没关注的同学们记得关注哦!

正文完
 0