Pod是最小的部署单元,也是后面经常配置的地方,本章节带你熟悉Pod中常见资源配置及参数。

也就是YAML这部分:

...
template:
metadata:
labels:
app: web
spec:
containers:
- image: lizhenliang/java-demo:latest
imagePullPolicy: Always
name: java

6.1 Pod介绍

  • 最小部署单元

  • 一组容器的集合

  • 一个Pod中的容器共享网络命名空间

  • Pod是短暂的

6.2 Pod存在的意义

Pod为亲密性应用而存在。

亲密性应用场景:

  • 两个应用之间发生文件交互

  • 两个应用需要通过127.0.0.1或者socket通信

  • 两个应用需要发生频繁的调用

6.3 Pod实现机制与设计模式

Pod本身是一个逻辑概念,没有具体存在,那究竟是怎么实现的呢?

众所周知,容器之间是通过Namespace隔离的,Pod要想解决上述应用场景,那么就要让Pod里的容器之间高效共享。

具体分为两个部分:网络和存储

  • 共享网络

kubernetes的解法是这样的:会在每个Pod里先启动一个infra container小容器,然后让其他的容器连接进来这个网络命名空间,然后其他容器看到的网络视图就完全一样了,即网络设备、IP地址、Mac地址等,这就是解决网络共享问题。在Pod的IP地址就是infra container的IP地址(即pause容器)。

  • 共享存储

比如有两个容器,一个是nginx,另一个是普通的容器,普通容器要想访问nginx里的文件,就需要nginx容器将共享目录通过volume挂载出来,然后让普通容器挂载这个volume,最后大家看到这个共享目录的内容一样。

例如:

# pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: write
image: centos
command: ["bash","-c","for i in {1..100};do echo $i >> /data/hello;sleep 1;done"]
volumeMounts:
- name: data
mountPath: /data - name: read
image: centos
command: ["bash","-c","tail -f /data/hello"]
volumeMounts:
- name: data
mountPath: /data volumes:
- name: data
emptyDir: {}

上述示例中有两个容器,write容器负责提供数据,read消费数据,通过数据卷将写入数据的目录和读取数据的目录都放到了该卷中,这样每个容器都能看到该目录。

验证:

kubectl apply -f pod.yaml
kubectl logs my-pod -c read -f

在Pod中容器分为以下几个类型:

  • Infrastructure Container:基础容器,维护整个Pod网络空间,对用户不可见(例如,pause容器)。

  • InitContainers: 初始化容器,先于业务容器开始执行,一般用于业务容器的初始化工作。

  • Containers: 业务容器,具体跑应用程序的镜像。

6.4 镜像拉取策略

apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: java
image: lizhenliang/java-demo
imagePullPolicy: IfNotPresent

imagePullPolicy 字段有三个可选值(镜像仓库中的镜像都打标签):

  • IfNotPresent: 镜像在宿主机上不存在时才拉取

  • Always: 默认值,每次创建 Pod 都会重新拉取一次镜像

  • Never: Pod 永远不会主动拉取这个镜像

如果拉取公开的镜像,直接按照上述示例即可,但要拉取私有的镜像,是必须认证镜像仓库才可以,即docker login,而在K8S集群中会有多个Node,显然这种方式是很不放方便的!为了解决这个问题,K8s 实现了自动拉取镜像的功能。 以secret方式保存到K8S中,然后传给kubelet。

apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
imagePullSecrets:
- name: myregistrykey
containers:
- name: java
image: lizhenliang/java-demo
imagePullPolicy: IfNotPresent

上述中名为 myregistrykey 的secret是由 kubectl create secret docker-registry 命令创建:

# kubectl create secret docker-registry myregistrykey --docker-username=admin --docker-password=Harbor12345 --docker-email=admin@harbor.com --docker-server=192.168.31.70
# kubectl get secret

--docker-username: 指定docker仓库账号
--docker-password: 指定docker仓库密码
--docker-email: 指定邮件地址(选填)
--docker-server: 指定docke仓库地址

6.5 资源限制

如果不限制资源默认共享宿主机的所有资源。

Pod资源配额有两种:

  • 申请配额:调度时使用,参考是否有节点满足该配置(申请配额一般大于限制配额1.5或2倍)

    spec.containers[].resources.limits.cpu

    spec.containers[].resources.limits.memory

  • 限制配额:容器能使用的最大配置

    spec.containers[].resources.requests.cpu

    spec.containers[].resources.requests.memory

示例:

apiVersion: v1
kind: Pod
metadata:
name: web
spec:
containers:
- name: java
image: lizhenliang/java-demo
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"

其中cpu值比较抽象,可以这么理解:

1核=1000m

1.5核=1500m

那上面限制配置就是1核的二分之一(500m),即该容器最大使用半核CPU。

该值也可以写成浮点数,更容易理解:

半核=0.5

1核=1

1.5核=1.5

6.6 重启策略

apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: java
image: lizhenliang/java-demo
restartPolicy: Always

restartPolicy字段有三个可选值:

  • Always: 默认策略,当容器终止退出后,总是重启容器。

  • OnFailure: 当容器异常退出(退出状态码非0)时,才重启容器。适于job

  • Never: 当容器终止退出,从不重启容器。适于job

6.7 健康检查

默认情况下,kubelet 根据容器状态作为健康依据,但不能检查容器应用程序状态,例如程序假死。这就会导致无法提供服务,丢失流量。因此引入健康检查机制确保容器健康存活。

健康检查有两种类型:

  • livenessProbe

    如果检查失败,将杀死容器,根据Pod的restartPolicy来操作。

  • readinessProbe

    如果检查失败,Kubernetes会把Pod从service endpoints中剔除。

这两种类型支持三种检查方法:

Probe支持以下三种检查方法:

  • httpGet

    发送HTTP请求,返回200-400范围状态码为成功。

  • exec

    执行Shell命令返回状态码是0为成功。

  • tcpSocket

    发起TCP Socket建立成功。

示例:

apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-exec
spec:
containers:
- name: liveness
image: busybox
args:
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 60
livenessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5

上述示例:启动容器第一件事创建文件,停止30s,删除该文件,再停止60s,确保容器还在运行中。

验证现象:容器启动正常,30s后异常,会restartPolicy策略自动重建,容器继续正常,反复现象。

6.8 调度策略

先看下创建一个Pod的工作流程:
create pod -> apiserver -> write etcd -> scheduler -> bind pod to node -> write etcd -> kubelet( apiserver get pod) -> dcoekr api,create container -> apiserver -> update pod status to etcd -> kubectl get pods

Pod根据调度器默认算法将Pod分配到合适的节点上,一般是比较空闲的节点。但有些情况我们希望将Pod分配到指定节点,该怎么做呢?

这里给你介绍调度策略:nodeName、nodeSelector和污点(kubectl edit 或 kubectl apply -f 方式改变已经存在 pod 的调度机器,保存后,配置不生效)

1、nodeName

nodeName用于将Pod调度到指定的Node名称上。

例如:下面示例会绕过调度系统,直接分配到k8s-node1节点。

apiVersion: v1
kind: Pod
metadata:
labels:
run: busybox
name: busybox
namespace: default
spec:
nodeName: k8s-node1
containers:
- image: busybox
name: bs
command:
- "ping"
- "baidu.com"

2、nodeSelector

nodeSelector用于将Pod调度到匹配Label的Node上。

先给规划node用途,然后打标签,例如将两台node划分给不同团队使用:

# 创建标签
kubectl label node <node-name> <label-key>=<label-value>
# 查看标签
kubectl get node --show-labels
# 删除标签
kubectl label node <node-name> <label-key>-
# 修改标签值
kubectl label node <node-name> <label-key>=<label-value> --overwrite

kubectl label nodes k8s-node1 team=a
kubectl label nodes k8s-node2 team=b

然后在创建Pod只会被调度到含有team=a标签的节点上。

apiVersion: v1
kind: Pod
metadata:
name: busybox
namespace: default
spec:
nodeSelector:
team: a
containers:
- image: busybox
name: bs
command:
- "ping"
- "baidu.com"

3、taint(污点)与tolerations(容忍)

污点应用场景:节点独占,例如具有特殊硬件设备的节点,如GPU

设置污点命令:

kubectl taint node [node] key=value[effect] 

其中[effect] 可取值:

  • NoSchedule :一定不能被调度。

  • PreferNoSchedule:尽量不要调度。

  • NoExecute:不仅不会调度,还会驱逐Node上已有的Pod。

示例:

先给节点设置污点,说明这个节点不是谁都可以调度过来的:

kubectl taint node k8s-node1  abc=123:NoSchedule

查看污点:

kubectl describe node k8s-node1 |grep Taints

然后在创建Pod只有声明了容忍污点(tolerations),才允许被调度到abc=123污点节点上。

apiVersion: v1
kind: Pod
metadata:
labels:
run: busybox
name: busybox3
namespace: default
spec:
tolerations:
- key: "abc"
operator: "Equal"
value: "123"
effect: "NoSchedule"
containers:
- image: busybox
name: bs
command:
- "ping"
- "baidu.com"

如果不配置容忍污点,则永远不会调度到k8s-node1。

去掉污点:

kubectl taint node [node] key:[effect]-
kubectl taint node k8s-node1 abc:NoSchedule-

6.9 故障排查

# 查看事件,可用于大部分资源
kubectl describe TYPE/NAME   
# 如果pod启动失败,先查看日志
kubectl logs TYPE/NAME [-c CONTAINER] 
# 进入到容器中debug
kubectl exec POD [-c CONTAINER] -- COMMAND [args...]

第6章:深入理解Pod对象的更多相关文章

  1. 第4 章 : 理解 Pod 和容器设计模式

    理解Pod和容器设计模式 本文整理自 CNCF 和阿里巴巴联合举办的云原生技术公开课的课时 4:理解 Pod 和容器设计模式.本次课程中,阿阿里巴巴高级技术专家.CNCF 官方大使张磊为大家介绍了为什 ...

  2. kubernetes-深入理解pod对象(七)

    Pod中如何管理多个容器 Pod中可以同时运行多个进程(作为容器运行)协同工作.同一个Pod中的容器会自动的分配到同一个 node 上.同一个Pod中的容器共享资源.网络环境和依赖,它们总是被同时调度 ...

  3. kubernetes实践之三:深入理解Pod对象

    一.Pod定义 最小部署单元 一组容器集合 一个pod中的容器共享网络命名空间 Pod是短暂的 二.Pod容器分类 基础容器 维护整个Pod的网络命名空间 初始化容器 先于业务容器开始执行,在应用启动 ...

  4. Kubernetes — 深入解析Pod对象:基本概念(二)

    作为 Kubernetes 项目里最核心的编排对象,Pod 携带的信息非常丰富.其中,资源定义(比如 CPU.内存等),以及调度相关的字段.在本篇,我们就先从一种特殊的 Volume 开始,来帮助你更 ...

  5. [Kubernetes]深入解析Pod对象

    k8s集群搭建是比较容易的,但是我们为什么要搭建,里面涉及到的内容,我们为什么需要? 这篇文章就尝试来讲讲,我们为什么需要一个Pod,对Pod对象来一个深入解析. 我们为什么需要Pod 我们先来谈一个 ...

  6. Kubernetes — 深入解析Pod对象:基本概念(一)

    在上一篇文章中,我详细介绍了 Pod 这个 Kubernetes 项目中最重要的概念. 现在,你已经非常清楚:Pod,而不是容器,才是 Kubernetes 项目中的最小编排单位.将这个设计落实到 A ...

  7. 14. 深入解析Pod对象(一)

    14. 深入解析Pod对象(一) """ 通过前面的讲解,大家应该都知道: Pod,而不是容器,它是 Kubernetes 项目中的最小编排单位.将这个设计落实到 API ...

  8. js对象详解(JavaScript对象深度剖析,深度理解js对象)

    js对象详解(JavaScript对象深度剖析,深度理解js对象) 这算是酝酿很久的一篇文章了. JavaScript作为一个基于对象(没有类的概念)的语言,从入门到精通到放弃一直会被对象这个问题围绕 ...

  9. Java基础之深入理解Class对象与反射机制

    深入理解Class对象 RRIT及Class对象的概念 RRIT(Run-Time Type Identification)运行时类型识别.在<Thinking in Java>一书第十四 ...

随机推荐

  1. 深入源码,深度解析Java 线程池的实现原理

    java 系统的运行归根到底是程序的运行,程序的运行归根到底是代码的执行,代码的执行归根到底是虚拟机的执行,虚拟机的执行其实就是操作系统的线程在执行,并且会占用一定的系统资源,如CPU.内存.磁盘.网 ...

  2. 基于混合云模式的calico部署

    开始前准备 确定calico数据存储 Calico同时支持kubernetes api和etcd数据存储.官方给出的建议是在本地部署中使用K8S API,仅支持Kubernetes模式.而官方给出的e ...

  3. prometheus管理api

    健康检查:GET /-/healthy 准备检查:GET /-/ready 停止服务:PUT|POST /-/quit 重载配置文件 PUT|POST /-/reload reference mana ...

  4. nginx 的常用模块

    nginx的常用模块 ngx_http_index_module Syntax: index file ...; Default: index index.html; Context: http, s ...

  5. 020.Python生成器和生成器函数

    一 生成器 1.1 基本概念 元组推导式是是生成器(generator) 生成器定义 生成器可以实现自定义,迭代器是系统内置的,不能够更改 生成器的本质就是迭代器,只不过可以自定义. 生成器有两种定义 ...

  6. rsync 服务配置_rsync命令使用方法

    rsync介绍 rsync用来定时备份服务器中的文件或者目录,有三种工作模式,本地复制,使用系统用户认证,守护进程方式,开源高效.同步工具,把一台机器上的文件同步都另一台机器 .默认使用873端口 选 ...

  7. centos7 的Linux下ip命令替换ifconfig命令的用法

    linux的ip命令和ifconfig类似,但前者功能更强大,并旨在取代后者.使用ip命令,只需一个命令,你就能很轻松地执行一些网络管理任务.ifconfig是net-tools中已被废弃使用的一个命 ...

  8. Redux 原理和简单实现

    前端开发中React + Redux 是大部分项目的标配,Redux也是我喜欢的库之一,他的源码也拜读过几遍,每次都有很多收获,尤其他的中间件设计模式,对自己封装一些库提供了思想上的指导. Redux ...

  9. Scrum Master 生存指南

    近年来,出现了一批新兴且广受关注的岗位,以 Scrum Master 为典型代表.2018年,Scrum Master 的平均工资为98239美元.领英更是将其列为2019年最有前途的工作之一.但对于 ...

  10. Sparse R-CNN: End-to-End Object Detection with Learnable Proposals 论文解读

    前言 事实上,Sparse R-CNN 很多地方是借鉴了去年 Facebook 发布的 DETR,当时应该也算是惊艳众人.其有两点: 无需 nms 进行端到端的目标检测 将 NLP 中的 Transf ...