Kubernetes 系统的基础单元,是资源对象模型中可由用户创建或部署的最小组件,也是Kubernetes 系统上运行容器化应用的资源对象。
在K8S中,容器设计准则:
- 现代的容器技术设计用来设计运行单个进程,该进程在容器中的PID名称空间中的进程号为1,可以直接接受并处理信号,在此进程终止时,容器即终止退出。
- 如果需要运行多进程,则需要一个Init 进程维护,以树状结构完成多进程的声明周期管理。
管理Pod 的容器
设置容器
一个POD 是由一个或者多个容器组成的,选择镜像以及镜像版本(tag)
spec:
containers:
# 镜像内容
- image: nginx:1.9
# 镜像名称
name: nginx
镜像获取策略
Always 镜像总是从仓库获取最新,Never 仅使用本地镜像,没有镜像报错,IfNotPresent 优先使用本地镜像。在实际环境中除特殊情况外一般都会选 Always 总是获取最新
spec:
containers:
# 镜像内容
- image: nginx:1.9
# 镜像名称
name: nginx
# 镜像拉取策略
imagePullPolicy: Always
设置镜像秘钥
在访问受限或者私有仓库时候需要配置镜像拉取的秘钥,秘钥存在在
Secret
spec:
containers:
# 镜像内容
- image: nginx:1.9
# 镜像名称
name: nginx
# 镜像拉取策略
imagePullPolicy: Always
# 设置镜像秘钥
imagePullSecrets:
# 秘钥Secret 配置名称
- name: aliyun-shanghai
资源限制
在实际环境中服务器一般都不够用,都会取消资源下限,除特定核心程序。
Kubernetes 给容器分成三个服务质量:
- Guaranteed 每个容器都为CPU资源设置了具有相同值的
request
和limit
属性, 这类Pod 资源优先级最高- Burstable 至少一个容器设置了CPU资源设置了
request
,但不满足Guaranteed
这类Pod 资源优先级中等- BestEffort 没有设置任何的
request
以及limit
属性的Pod 资源优先级最低当资源紧张时候,
BestEffort
首当其冲地被终止,因为系统不为其提供任何级别的资源保证,但换来的好处是可以尽可能多地占用资源在Kubernetes中一个虚拟CPU(vCPU) 相当于1000个微核心(millicores)500m 等于 0.5个核心 内存与物理内存单位一样,默认单位是
字节
E、P、T、G、M、K
spec:
containers:
# 镜像内容
- image: nginx:1.9
# 镜像名称
name: nginx
# 镜像拉取策略
imagePullPolicy: Always
# 请求时想调度器请求的资源
resources:
requests:
memory: "128Mi"
cpu: "200m"
limit:
memory: "512Mi"
cpu: "400m"
容器的重启策略
容器在发生崩溃或者容器申请超出限制的资源等原因都可能会导致Pod 对象的终止,此时容器是否应该重建该Pod对象取决于其重启策略
restartPolicy
属性的定义:Always
但凡Pod对象退出就将其重启、OnFailure
仅在Pod对象出错错误才将其重启,Never
从不重启容器重启后延迟恢复时长会逐渐增加,依次为20秒、40秒、80秒、160秒、300秒,随后的延迟将固定在5分钟而不会在增加。
spec:
containers:
# 镜像内容
- image: nginx:1.9
# 镜像名称
name: nginx
# 镜像拉取策略
imagePullPolicy: Always
# 容器重启策略
restartPolicy: Always
暴露端口
由
containerPort
容器端口 (0~65536),name
端口名称,protocol
(TCP/UDP) 端口协议组成
spec:
containers:
# 镜像内容
- image: nginx:1.9
# 镜像名称
name: nginx
# 镜像拉取策略
imagePullPolicy: Always
# 暴露端口
ports:
# 端口
- containerPort: 8080
# 名称
name: http
# 协议
protocol: TCP
环境变量
复杂应用程序的配置信息多数由配置文件进行指定,环境变量支持:自定义、配置项(ConfigMap)以及保密字典(Secret),环境列表通常是由
name
和value
字段构成。
spec:
containers:
# 镜像内容
- image: nginx:1.9
# 镜像名称
name: nginx
# 镜像拉取策略
imagePullPolicy: Always
# 暴露端口
- env:
# 通过Secret导入秘钥
- name: JAVA_OPS
valueFrom:
# Secret 配置
secretKeyRef:
key: JAVA_OPS_DEFAULT
name: billbear
# 自定义环境变量
- name: AGENT
value: -javaagent:/app/opentelemetry-javaagent.jar
运行的容器命令
自定义容器运行命令
spec:
containers:
# 镜像内容
- image: nginx:1.9
# 镜像名称
name: nginx
# 镜像拉取策略
imagePullPolicy: Always
# 启动执行
args: ["sh -c", "java -jar xx.jar"]
lifecycle:
# 启动后
postStart:
# 除了exec 还有 httpGet tcpSocket
exec:
command: ["/bin/sh","-c","xxx"]
# 停止前
preStop:
# 除了exec 还有 httpGet tcpSocket
exec:
command: ["/bin/sh","-c","xxx"]
存活性探测
存活性探测;可选的配置,没有设置探针POD 会根据进程状态决定容器健康
exec 探针
在容器内执行一个sh脚本,根据脚本执行返回的状态码进行诊断操作
spec:
containers:
- livenessProbe:
# exec 探针
exec:
command: ["test", "-e", "/tmp/healthy"]
http 探针
通过想容器IP地址指定的端口指定的
path
发起GET
请求进行诊断,响应码为2xx
或3xx
即为成功
spec:
containers:
- livenessProbe:
httpGet:
# 发送请求路径
path: /healthz
# 发送请求端口
prot: 8080
# 发送请求协议
scheme: HTTP
tcp 探针
通过特定端口发起TCP请求并尝试建立连接进行结果判定
spec:
containers:
- livenessProbe:
tcpSocket:
# 发送请求端口
path: 8080
就绪性探测
就绪探测;探测容器是否已经初始化完成并可服务于客户端请求,探测服务返回
success
状态,即为容器已准备就绪,就绪探测失败容器不会重启,而是通知尚未准备就绪
exec 探针
在容器内执行一个sh脚本,根据脚本执行返回的状态码进行诊断操作
spec:
containers:
- readiness-exec:
# exec 探针
exec:
command: ["test", "-e", "/tmp/healthy"]
http 探针
通过想容器IP地址指定的端口指定的
path
发起GET
请求进行诊断
spec:
containers:
- readiness-exec:
httpGet:
# 发送请求路径
path: /healthz
# 发送请求端口
prot: 8080
# 发送请求协议
scheme: HTTP
tcp 探针
通过特定端口发起TCP请求并尝试建立连接进行结果判定
spec:
containers:
- readiness-exec:
tcSocket:
# 发送请求端口
path: 8080
数据卷
容器在重启之后数据是不会保留的,当部分数据需要持久的化的时候就需要挂载外部的卷
- 挂载宿主机的磁盘(POD调度会放在随机的宿主机很尴尬)
- 挂载配置项,这个是一个只读的资源
- 挂载保密字典,这是一个只读的资源
- 挂载集群磁盘
PVC
spec:
containers:
# 容器内目标磁盘
- volumeMounts:
- mountPath: /etc/localtime
name: volume-localtime
- mountPath: /app/logs/
name: volumn-sls-16468903025242
# 宿主机或者PVC
volumes:
- hostPath:
path: /etc/localtime
type: ''
name: volume-localtime
- emptyDir: {}
name: volumn-sls-16468903025242
Pod的生命周期
容器相位 (Phase)
Pod 对象总是应该处于其生命进程中以下几个相位(Phase)之一。
**Pending**
:API Server 创建了Pod 资源对象并已存入etcd中,但他尚未被调度完成,或者任然处于仓库下载镜像的过程中**Running**
:Pod 已经被调度至某个节点,并且所有容器都已经被kubelet 创建完成**Succeeded**
:Pod 中的所有容器都已经成功终止并且不会重启**Failed**
:所有容器都已经被禁止,但至少有一个容器终止失败,即容器返回了非0值的退出状态或已经被系统终止**Unknown**
:API Server 无法正常获取到Pod对象的状态信息,通常是由于其无法与所在工作节点的kubelet通讯所导致
容器初始化
容器初始化如下:
- 用户提交
资源清单
到 APIService- APIService 尝试着将Pod对象的相关信息存入
etcd
中,等待写入执行完成,APIService即会返回确认信息至客户端- APIService 反应etcd状态的情况
- 所有kubernetes 自建均使用
watch
机制来跟踪检查APIService上的相关变动- scheduler 调度器通过其
watcher
察觉到APIService创建了新的Pod对象但尚未绑定至任何工作节点- scheduler为Pod对象挑选一个工作节点并将信息更新至APIService
- 调度结果信息由APIService更新至etcd存储系统,而且APIService也开始反应此Pod对象的调度结果
- Pod被调度到的目标工作节点上kubelet的尝试在当前节点上调用
容器运行时
启动并将容器的结果状态返回送至APIService- APIService将Pod状态信息存入etcd系统中
- 在etcd确认写入操作成功完成后,APIService将确认信息发送至相关的kubelet,时间将通过他接受。
容器终止过程
当提交容器终止命令的时候,系统就会进行强制删除操作的宽限期倒计时,并将TERM信息发送给Pod对象的每个容器中主程。宽限期结束后,进程将收到强制KILL信号,Pod对象随即也将由Api Server 删除。
- 用户发送删除Pod对象命令
- API 服务器中的Pod对象会随着时间推移而更新,在宽限期内(默认30秒),Pod 视为
dead
- 将Pod标记为Terminating 状态
- 监控到Pod 对象转成Terminating 状态的同时启动Pod关闭的过程
- 端点控制器监控到Pod对象的关闭行为时将其从所有匹配到此端点的Service 资源的端点列表中移除
- 如果当前Pod对象定义了preStop 钩子处理器,则在其标记为Terminating状态后即会同步的方式启动执行,如宽限期结束后,preStop 任未执行结束,则会额外获取一个时长2秒的小宽限期。
- Pod 对象中的容器进程收到TERM信号
- 宽限期结束后,若任然存在任何一个运行的进程,那么Pod对象即会收到SIGKILL信号
- Kubelet 请求的API Server 将此Pod资源的宽限设置为0从而完成删除操作,它变得对用户不可见
资源对象模型中由用户创建或部署的最小组件,也是在Kubernetes系统上运行容器化应用的资源对象。
标签
随着同类型资源对象的数量越来越多,分类管理也变得越来越有必要:
- 基于简单且直接的标准将资源对象划分为多个较小的分组
- 无论是对开发人员和系统工程师提升管理效率
- 对于附带标签的资源对象,可以使用标签选择器(Lable Select)挑选出符合条件的资源以及完成所需要的操作
标签
标签就是 “键值” 类型的数据,他们可于资源创建时直接指定,也可随时按需添加于活动对象中,而后即由标签选择器进行匹配度检查从而完成资源挑选。
- 版本标签:
release``stable``release
- 环境标签:
environment``dev``qa
- 应用标签:
app``ui
- 架构层级标签:
tier``cache
- 分区标签:
customer
- 品控级别标签:
daily
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: '11'
creationTimestamp: '2022-03-24T05:22:47Z'
generation: 11
# 标签选择器
labels:
# K-V 形式
app: billbear-api-gateway
...
选择器
标签选择器用于表达标签的查询条件或者标准,Kubernetes API 目前进支持二个选择器
- 基于等值关系:== 判断是否相等,!= 判断不相等
- 基于集合关系:in() 搜索是否包含,notin() 不存在
主要场景:
- Service 服务
- Ingress 路由
- NodeSelect 节点选择器
spec:
ports:
- name: http
port: 8080
protocol: TCP
targetPort: 8080
# 选择器 (等值选择器)
selector:
# K-V 形式
app: billbear-api-gateway
节点选择器
Pod 节点选择器是标签及标签选择器的一种应用,它能够让Pod对象基于集群中工作节点的标签来挑选倾向运行的目标节点,后面推荐使用Pod 的亲和度替代这里仅做了解
spec:
containers:
- name: app
# 节点选择器,选择具有disktype标签的节点
nodeSelect:
disktype: ssd
资源注解
Pod 与其他各种资源还能使用
注解(Annotation)
。与标签类似,注解也是 “键值” 类型的数据,不过他不能用于标签及挑选Kubernetes对象,仅可用于为资源提供“元数据”信息。
- 注解中的元数据不受字符数量的限制,它可大可小。
- 可以为结构化或非结构化形式,也支持使用在标签中禁止使用的其他字符。
主要场景:
- 申明式配置层(apply)命令的管理的字段。
- 构建、发行或镜像相关的信息,例如,时间戳、发行ID、Git分支、PR号码、镜像哈希以及仓库地址
- 指向日志、监控、分析或者审计仓库的指针
apiVersion: apps/v1
kind: Deployment
metadata:
# 资源注解
annotations:
# K-V 形式
deployment.kubernetes.io/revision: '11'
creationTimestamp: '2022-03-24T05:22:47Z'
generation: 11
labels:
app: billbear-api-gateway
...
完整的例子
apiVersion: apps/v1
kind: Deployment
metadata:
# 注解
annotations:
deployment.kubernetes.io/revision: '4'
# 标签
labels:
app: billbear-newmall-client
# POD 名称
name: billbear-newmall-client
# 项目名称
namespace: interests
spec:
# POD 数量
replicas: 1
template:
metadata:
# 注解
annotations:
# 标签
labels:
app: billbear-newmall-client
spec:
# 容器集
containers:
# 环境变量
- env:
- name: JAVA_OPS
valueFrom:
secretKeyRef:
key: JAVA_OPS_DEFAULT
name: billbear
- name: AGENT
value: >-
-javaagent:/app/opentelemetry-javaagent.jar
-Dotel.resource.attributes=service.name=billbear-newmall-client,service.version=1.0.0,host.name=billbear-newmall-client.api.local
- name: JAR_OPS
value: '--spring.cloud.nacos.discovery.port=32018'
# 镜像版本
image: xxx:test
# 拉取策略
imagePullPolicy: Always
# 镜像名称
name: billbear-newmall-client
# 暴露端口
ports:
- containerPort: 8080
name: http
protocol: TCP
resources:
requests:
memory: 512Mi
# 容器对应的目录
volumeMounts:
- mountPath: /etc/localtime
name: volume-localtime
- mountPath: /app/logs/
name: volumn-sls-16468903025242
# 镜像拉取秘钥
imagePullSecrets:
- name: aliyun-shanghai
# 申明挂载的磁盘
volumes:
- hostPath:
path: /etc/localtime
type: ''
name: volume-localtime
- emptyDir: {}
name: volumn-sls-16468903025242