1. POD的基本概念

  • Pod 是K8s 系统中可以创建(部署)和管理的最小单元。

  • Pod 里面可以包含多个容器(多实例),是一组容器的集合。

    也就是讲K8S 不会直接管理容器

  • 1个POD中的容器共享网络命名空间(共享ip)

  • POD 是短暂的(可以被创建 迁移)

来自google的解析, POD的存在是为了覆盖container的细节

2. POD 存在的意义

  • 创建容器使用docker, 1个docker 对应1个container, 一个container对应1个进程, 一个container运行1个程序, 是1个单进程的设计。
  • Pod 是1个多进程的设计, 可以运行多个应用程序。 1 个POD可以有多个容器, 1个容器运行1个应用程序
  • Pod 存在为了亲密性应用,
    ** 两个应用之间进行交互 (直接调用)
    ** 网络之间调用 (API), 如果不在同1个POD, 通常应用之间只能用ip调用, 如果在同1个POD, 可以用过127.0.0.1 和 socket直接调用
    ** 两个应用需要频繁调用(例如普通App 和 数据库)

上图的Pause 表示POD里面必须存在的根容器

3 POD 的实现机制

通常POD的实现基于两种机制
分别是

  • 共享网络
  • 共享存储

3.1 共享网络机制

我们知道, 在docker中各个容器之间是相互隔离的。
在K8S 中, 容器也可以用namespace 和 group进行隔离。
但是如果两个容器在同1个POD 或namespace 中, 它们是可以做到网络共享的。(在同1个Namespace中是网络共享的大前提)

下面介绍的是在POD中网络共享机制的实现:

3.1.1 POD中多个容器的网络共享

如下图, 在POD的初始化中, 会首先建立1个根容器, 这个根容器通常被称为 Pause, 也可以叫做info容器。
在这个根容器中, 会被分配1个ip地址, mac地址和 ports端口。

然后POD会继续根据用户要求创造若干个业务容器, 每个业务容器都会作为子容器加入到根容器中, 那么这些子容器就可以共享根容器的网络(ip mac port等)资源。


yaml 例子:
下面的yaml, 在同1个POD testPod1 中创建了两个容器, write-cont 和 read-cont, 至于根容器会被默认创建, 不用写在yaml中。
这两个容器都被加入到根容器的网络资源使用者列表中, 所以 这两个容器是可以共享网络的。

apiVersion: v1
kind: Pod
metadata:name: testPod1
spec:containers:- name: write-contimage: centoscommand: ["bash", "-c", "for i in {1..100}; do echo $i >> /data/hello; sleep 1; done"]volumeMounts:- name: datamountPath: /data- name: read-contimage: centoscommand: ["bash","-c", "tail -f /data/hello"]volumeMounts:- name: datamountPath: /datavolumns:- name: dataemptyDir: {}

3.2 共享存储机制

Pod的容器在运行中 , 通常会不断产生数据, 为了持续使用, 必须对数据进行持久化。

  • 共享存储: 跟docker机制类似, K8S 引入数据卷概念, 使用数据卷进行持久化存储
    参考上面的yaml例子, 1个 write 容器会对1个公共的卷 data写数据, 而另1个容器 read可以从数据卷去读取数据。 因为他们都把数据卷挂在到容器中.

  • 共享存储不只在POD的容器level, 实际上可以在Node之间, 让多个Node里面的POD 共享数据

4 POD 的镜像拉取

4.1 镜像拉取策略

我们看下面的yaml例子

apiVersion: v1
kind: Pod
metadata:name: pod1
spec:container:- name: nginximage: nginx: 1.14imagePullPolicy: Always   # 镜像拉取策略

上面的 imagePullPolicy 就是 镜像拉取策略
有3个选项

  • IfNotPresent: 默认值, 镜像在宿主机不存在才拉取
  • Alway: 每次创建Pod时都会拉取
  • Never: Pod 永不会主动拉取镜像

5 POD 的资源需求 和 资源限制

我们看1个例子
假如我们要构建运行1个POD1, 在k8s 集群中, 系统会把这个POD 分配到其中1个 k8s node上运行。

如果当前k8s 有如下面3个节点

其中node1 的规格是4 core 8G
node2 的规格是1 core 2G
node3 的规格是2 core 4G

而我们会觉得我们所建立的POD1正常运行至少需要2 core 4G, 如果被分配到POD2 运行则很有可能出问题

这时我们可以设置POD1 的最少资源需求 为 2 core 4G.
则k8s 就不会把这个POD 放到node2 去执行了。

至于把POD1 放到node3 可行吗?, 则要看node3有没有其他POD在运行, 空闲资源怎么样。

所以引申出另1个东西: 资源限制
当POD1 在node1运行时, 如果我们不想它占用过多的node资源, 则可以作出限制。

资源限制在yaml的关键字是

spec.containers[x].resources.requests.cpu   # 最低需求cpu数  1 代表 1 core, 1000m 代表 1 core,  500m 和 0.5 都代表 0.5 core
spec.containers[x].resources.requests.memory # 最低需要内存 单位是Mi, 1 Mi = 1 MB
spec.containers[x].resources.limits.cpu   # 最高能用到的cpu 数
spec.containers[x].resources.limits.memory # 能用到的最大内存限制

1个 yaml例子:

apiVersion: v1
kind: Pod
metadata:name: Pod1
spec:containers:- name: dbimage: mysqlenv:- name: MYSQL_ROOT_PASSWORDvalue: "password"resources:  # 资源需求requests:memory: "120Mi"cpu: "500m"limits:  # 资源限制memory: "500Mi"cpu: "1000m"

6 POD 的重启机制

当POD里面的容器非正常退出, POD会对容器作一些处理,这就是POD对容器的重启机制

如下面的yaml例子:

apiVersion: v1
kind: Pod
metadata:name: Pod1
spec:containers:- name: busyboximage: busybox:1.28.4args:- /bin/sh- -c- sleep 36000restartPolicy: Never # 重启机制

restartPolicy 的选项有3种:

  • Always: 当容器终止退出时, 总是会重启容器, 这个是默认策略
  • OnFailture: 当容器异常退出 (退出码非0)时才会重启
  • Never: 容器退出时不会重启, 多用于执行批量任务(批处理)

7 POD 的健康检查

如果我们想查看 POD的运行状态, 可以用下面的命令

gateman@k8smaster:~$ kubectl get pods
NAME                     READY   STATUS    RESTARTS   AGE
nginx-6799fc88d8-scjht   1/1     Running   0          7d

但是这个Running status 并不能保证这个pod是健康的, 它并不能检查pod里面是否有oom or 程序已经崩溃的问题.
通常靠谱的方法是调用POD里面程序的health checking 接口

例如:

gateman@k8smaster:~$ curl -I 127.0.0.1:31407
HTTP/1.1 200 OK
Server: nginx/1.21.5
Date: Sun, 27 Nov 2022 11:59:18 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Tue, 28 Dec 2021 15:28:38 GMT
Connection: keep-alive
ETag: "61cb2d26-267"
Accept-Ranges: bytes

但是K8S 允许我们在POD 的yaml文件中自定义 health checking 的规则

其中

1. livenessProbe (存活检查)

这个规则 如果health checking不通过, 则K8s 会kill掉 POD, 然后根据Pod 的restartPolily(上面的章节6) 的规则来操作

2. readnessProbe (就绪检查)

这个规则下, 如果health checking 不通过, K8s 会直接将这个pod 从service endpoint 中移除。

而上面两个Probe 支持一下三种检查方法:

1. httpGet

发送http 请求, 返回200 - 399 认为成功

2. exec

执行shell 命令,如果返回的退出码是0, 则认为成功

3. tcpSocket

发起TCP socket 连接, 如果连接建立, 则认为成功

例子:

apiVersion: 1
kind: Pod
metadata:labels:test: livenessname: test-pod-liveness
spec:containers:- name: livenessimage: busyboxargs:- /bin/sh- c- mkdir -p /tmp/healthy;- sleep 30;- rm -rf /tmp/healthylivenessProbe:exec:command:- ls /tmp/healthyinitialDelaySeconds: 5perodSeconds: 5

上面的例子中, health checking的探针 在POD创建后5秒后就不断尝试隔5秒去检查 /tmp/healthy 文件夹, 当这个文件夹被删除后, 则会认为检查失败

8 POD 的调度策略

上面提到了, 我们用 kubectl get pods 命令可以查看pod的运行状态。
但是如果想知道pod 是在哪个node去运行的,必须加多1个参数

gateman@k8smaster:~$ kubectl get pods -o wide
NAME                     READY   STATUS    RESTARTS   AGE    IP           NODE       NOMINATED NODE   READINESS GATES
nginx-6799fc88d8-scjht   1/1     Running   0          7d7h   10.244.1.5   k8snode0   <none>           <none>
gateman@k8smaster:~$

可以看出, nigix 这个pod 跑在 k8snode0上。

但是我们创建pod其实并不需要指定pod在哪个node上跑到的, 而是k8s会根据规则去自动分配。 这个规则就是所谓的POD 调度策略

8.1 POD 从建立到被分配(调度)到某个node的流程

8.1.1 用户发起POD create 指令 到API server处理

这一步在master node内完成, 毕竟api server是存在master node的

gateman@k8smaster:~$ docker ps | grep -i api
e2dc342dd4f8   bd16c7ea581a                                        "kube-apiserver --ad…"   5 days ago   Up 5 days             k8s_kube-apiserver_kube-apiserver-k8smaster_kube-system_e12ac92bf1f55f7391d09a0523658312_2
906ba92f4bdf   registry.aliyuncs.com/google_containers/pause:3.5   "/pause"                 5 days ago   Up 5 days             k8s_POD_kube-apiserver-k8smaster_kube-system_e12ac92bf1f55f7391d09a0523658312_2

当API server接收到用户create POD指令后, 会把对应的POD创建信息写入 ectd

其实到第一步, 指令会马上返回给用户, 用户一般需要等待一会才去查询POD状态, 所以后面的动作是异步的

8.1.2 schedule 根据调度策略 分配 POD 到某个node

这一步也在master node内完成
所谓Schedlue 就是会定时与API server沟通, 一旦发现有新的pod create指令, 则会从ectd 获得pod信息, 然后根据调度策略去分配node, 然后将结果写入ectd

8.1.3 Node 的 kubelet 会根据pod信息在自己的docker容器内创建pod 的容器(s)

这一步当然在node内完成啦。

8.2 影响POD调度的一些因素

8.1 资源限制

这个很容易理解, 如本文的第5 章

  resources:  # 资源需求requests:memory: "120Mi"cpu: "500m"

如果1个POD 需要120M 内存, 而某个node 剩余内存不足120M, 则这个node不会被选择

8.2 节点选择器标签

在Pod 的yaml 定义文件中, 我们还可以用标签选择器去选择被部署的node

例子:

apiVersion: v1
kind: Pod
metadata:name: pod-env-test
spec:nodeSeletor:env_role: devcontianers:- name: ngniximages: ngnix: 1.15

上面的nodeSelector 中的env_role 就是所谓的标签选择器, 看名字也知道这个选择器跟不同的运行环境有关

原理如图:

我们可以为每个node分别打上env_role 标签, 去定义这个node是输入 开发 or 测试 or 生产环境.

当我们的某个pod的yaml文件中制定了 标签, 则master 只会把这个pod 部署去对应的nodes, 这个优先级是最高的。

如何为某个node 打标签:
gateman@k8smaster:~$ kubectl label node k8snode0 env_role=dev
node/k8snode0 labeled
如何查看node的labels
gateman@k8smaster:~$ kubectl get nodes --show-labels
NAME         STATUS   ROLES                  AGE     VERSION    LABELS
admeuc-vm1   Ready    <none>                 7d22h   v1.22.15   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,env_role=uat,kubernetes.io/arch=amd64,kubernetes.io/hostname=admeuc-vm1,kubernetes.io/os=linux
amdeuc-vm2   Ready    <none>                 55m     v1.22.15   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,env_role=uat,kubernetes.io/arch=amd64,kubernetes.io/hostname=amdeuc-vm2,kubernetes.io/os=linux
amdeuc-vm3   Ready    <none>                 55m     v1.22.15   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,env_role=dev,kubernetes.io/arch=amd64,kubernetes.io/hostname=amdeuc-vm3,kubernetes.io/os=linux
k8smaster    Ready    control-plane,master   43d     v1.22.15   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8smaster,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=,node.kubernetes.io/exclude-from-external-load-balancers=
k8snode0     Ready    <none>                 43d     v1.22.15   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,env_role=dev,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8snode0,kubernetes.io/os=linux
8.3 节点亲和性 nodeAffinity

用法基本上与8.2 标签选择器一样, 但功能更加强大

包括

8.3.1 硬亲和性,requireDuringSchedulingIgnoreDuringExecution

Node必须要满足亲和性的条件才会被选择, 如果没有任何node满足, 则POD的部署会一直等待

apiVersion: v1
kind: Pod
metadata:name: node-affinity-test
spec:affinity:requireDuringSchedulingIgnoreDuringExecution:nodeSelectorTerms:- matchExpressions:- key: env_roleoperator: Invalues:- dev- test
containers:- name: ngnix:image: ngnix: 1.15

8.3.2 软亲和性,preferredDuringSchedulingIgnoreDuringExecution

就是require和prefer的区别
Node调度会尝试满足亲和性的条件, 但不保证一定满足。

apiVersion: v1
kind: Pod
metadata:name: node-affinity-test
spec:affinity:preferredDuringSchedulingIgnoreDuringExecution:- weight: 1 # 权重preference:- matchExpressions:- key: env_roleoperator: Invalues:- dev- test
containers:- name: ngnix:image: ngnix: 1.15

Opertor - 常用的操作符

In
NotIn  # 所谓的反亲和性
Exists
Gt
Lt
DoesNotExists # 所谓的反亲和性
8.4 污点和污点容忍 Taint

其实上面8.1 到 8.3 影响pod调度的属性都是在pod定义本身的。
但是污点 Taint是跟POD定义无关的, 它是Node的属性… 用于作一些特别分配处理

8.4.1 场景

a. 专用节点
例如某些node的有外网网络, 会部署一些专用应用

b. 配置特点硬件节点
例如某写node具有ssd硬盘, 会部署大量IO的应用

c. 基于Taint驱逐
用于排除某些node

8.4.2 查看node 的 污点信息
kubectl describe node xxxxx | grep -i taint

gateman@k8smaster:~$ kubectl describe node | grep -i taint
Taints:             <none>
Taints:             <none>
Taints:             <none>
Taints:             node-role.kubernetes.io/master:NoSchedule
Taints:             <none>

只有master node 有1个污点, 表示 master node 有NoSchedule的污点

8.4.3 3个污点的值

** NoSchedule 表示一定不会被调度
** PreferNoSchedule 尽量不会被调度
** NoExecute: 不会被调度, 并且还会驱逐Node的已有pods 这个 吊

8.4.4 为Node打上污点

kubectl taint node [nodename] key=value #污点的3个值

例如:

Kubectl taint node k8snode0 env_role=dev:NoSchedule

这样就代表, 如果POd选择了dev env_role 标签, pod也不会调度到这个k8snode0上, 会选择另个存在 dev标签的节点。

8.4.4 为Node删除污点
kubectl taint node [nodename] key:[污点值] -

8.4.5 污点容忍
例子:

spec:tolerations:- key: "key"operator: "Equal"value: "value"effect: "NoSchedule"

一旦在pod 配置文件中 写上上面的污点容忍信息

则代表即使打上对应污点的node也可能会被调度到…

K8S - Pod 的概念和简介相关推荐

  1. k8s pod基础概念

    k8s pod基础概念 Pod基础概念: Pod是kubernetes中最小的资源管理组件,Pod也是最小化运行容器化应用的资源对象.一个Pod代表着集群中运行的一个进程.kubernetes中其他大 ...

  2. K8S --- Pod 基础概念

    文章目录 1. 资源限制 2. Pod 的两种使用方式 3. Pod 资源共享 4. 底层容器 Pause 4.1 Pause共享资源 4.1.1 网络 4.1.2 存储 4.1.3 总结 4.2 P ...

  3. k8s pod里访问不到外部ip_K8S中的Service的存在理由

    前言 上篇文章中老顾介绍了相关pod.容器.node之间的通信,通过pod的ip进行通信,存在一定的问题. Kubernetes Pod是有生命周期的,它们可以被创建,也可以被销毁,然而一旦被销毁生命 ...

  4. 混沌工程之ChaosToolkit使用之一删除K8s POD

    混沌工程之ChaosToolkit使用之一删除K8s POD 1.概述 今天我们来玩一下混沌工程的开源工具chaostoolkit . 它的目标是提供一个免费,开放,社区驱动的工具集以及api. 2. ...

  5. 为什么Kubernetes要引入pod的概念,而不直接操作Docker容器

    首先我们要明确一个概念,Kubernetes并不是只支持Docker这一个容器运行时,通过我的另一篇文章什么是Kubernetes的CRI-容器运行时接口介绍的内容,我们知道Kubernetes通过C ...

  6. K8S Pod该如何监控

    背景 由于业务容器化的推进,对K8S上运行的业务,也必须做到向之前物理机/虚拟机上一样,要有完备的监控保障.但是,毕竟K8S不是物理机/虚拟机,由于技术实现方式不同,监控方面也是有一定差别的. Pod ...

  7. k8s每天报告服务器状态信息,[工作随笔] 配置 cron 检查 K8s Pod 存活状态以推送钉钉消息...

    背景 前段时间接手了一份维护老系统的任务.该系统使用了早期的 Spring Cloud 全家桶,其中有一个微服务随着时间运行会出现大量 CLOSE_WAIT 状态的 socket 连接以至于堵塞网关, ...

  8. K8s Pod优雅关闭,没你想象的那么简单!

    更新部署服务时,旧的 Pod 会终止,新 Pod 上位.如果在这个部署过程中老 Pod 有一个很长的操作,我们想在这个操作成功完成后杀死这个 pod(优雅关闭),如果无法做到的话,被杀死的 pod 可 ...

  9. K8S POD无限重启问题

    记录一次K8S POD无限重启 项目在K8S上无限重启 问题排查 发现问题 解决方案 最终成果 项目在K8S上无限重启 项目无限重启,不可用. 问题排查 首先查看k8s描述. kubectl desc ...

最新文章

  1. 第一篇随笔——新的开端
  2. 为了人类的未来,请赋予机器人智慧和情感!
  3. 千亿参数大模型时代,QQ浏览器团队十亿级小模型「摩天」登顶CLUE
  4. EdoGantt甘特图中间件的事件对象
  5. simplexml php,php的simplexml
  6. MySQL 安装包下载教程
  7. 201621123053 张雨阳软工作业2
  8. 计算机科学速成视频35,计算机科学速成课30:万维网【视频】
  9. 2022年中国美妆护肤品行业投资研究报告
  10. javaee 第五周作业
  11. servelt笔记一
  12. (第五章)统计函数分组
  13. python xlrd导入后怎么保存_Python xlrd模块导入过程及常用操作
  14. 答题器——游戏工作室的亲密搭档!
  15. windows不支持scp指令解决方案
  16. 新型能力的分解与组合
  17. 冤家路窄?——软件开源与软件专利保护
  18. 发送短信并存入短信库
  19. krpano资源下载及还原全景图
  20. Fast and Provably Good Seedings for k-Means阅读笔记

热门文章

  1. 什么是301重定向与301重定向怎么做
  2. 【码农学编曲】基础乐理 快速掌握(吐血整理 纯干货 适合小白)
  3. python核心编程第三版(一)学习笔记:正则表达式
  4. DC-DC直流升压高压电源模块HRA5V12V24V转正负50V100V150V180V200V250V300V
  5. 戴尔灵越游匣+Ubuntu16.04的NVIDIA GTX1050显卡驱动安装.md
  6. 孤陋寡闻的我刚知道怎么debug远程服务
  7. RIPNG (RIP下一代)
  8. 【转】利用kali破解wifi密码全过程
  9. 好莱坞著名影星Brooke Shields联合Casper推出全球首款在太空铸造的NFT作品
  10. 初学List和Set集合