Kubernetes 系统的基础单元,是资源对象模型中可由用户创建或部署的最小组件,也是Kubernetes 系统上运行容器化应用的资源对象。

在K8S中,容器设计准则:

  • 现代的容器技术设计用来设计运行单个进程,该进程在容器中的PID名称空间中的进程号为1,可以直接接受并处理信号,在此进程终止时,容器即终止退出。
  • 如果需要运行多进程,则需要一个Init 进程维护,以树状结构完成多进程的声明周期管理。

管理Pod 的容器

设置容器

一个POD 是由一个或者多个容器组成的,选择镜像以及镜像版本(tag)

  1. spec:
  2. containers:
  3. # 镜像内容
  4. - image: nginx:1.9
  5. # 镜像名称
  6. name: nginx

image.png

镜像获取策略

Always 镜像总是从仓库获取最新,Never 仅使用本地镜像,没有镜像报错,IfNotPresent 优先使用本地镜像。在实际环境中除特殊情况外一般都会选 Always 总是获取最新

  1. spec:
  2. containers:
  3. # 镜像内容
  4. - image: nginx:1.9
  5. # 镜像名称
  6. name: nginx
  7. # 镜像拉取策略
  8. imagePullPolicy: Always

image.png

设置镜像秘钥

在访问受限或者私有仓库时候需要配置镜像拉取的秘钥,秘钥存在在 Secret

  1. spec:
  2. containers:
  3. # 镜像内容
  4. - image: nginx:1.9
  5. # 镜像名称
  6. name: nginx
  7. # 镜像拉取策略
  8. imagePullPolicy: Always
  9. # 设置镜像秘钥
  10. imagePullSecrets:
  11. # 秘钥Secret 配置名称
  12. - name: aliyun-shanghai

image.png

资源限制

在实际环境中服务器一般都不够用,都会取消资源下限,除特定核心程序。

Kubernetes 给容器分成三个服务质量:

  • Guaranteed 每个容器都为CPU资源设置了具有相同值的requestlimit属性, 这类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

  1. spec:
  2. containers:
  3. # 镜像内容
  4. - image: nginx:1.9
  5. # 镜像名称
  6. name: nginx
  7. # 镜像拉取策略
  8. imagePullPolicy: Always
  9. # 请求时想调度器请求的资源
  10. resources:
  11. requests:
  12. memory: "128Mi"
  13. cpu: "200m"
  14. limit:
  15. memory: "512Mi"
  16. cpu: "400m"

image.png

容器的重启策略

容器在发生崩溃或者容器申请超出限制的资源等原因都可能会导致Pod 对象的终止,此时容器是否应该重建该Pod对象取决于其重启策略restartPolicy属性的定义:Always 但凡Pod对象退出就将其重启、OnFailure 仅在Pod对象出错错误才将其重启,Never 从不重启

容器重启后延迟恢复时长会逐渐增加,依次为20秒、40秒、80秒、160秒、300秒,随后的延迟将固定在5分钟而不会在增加。

  1. spec:
  2. containers:
  3. # 镜像内容
  4. - image: nginx:1.9
  5. # 镜像名称
  6. name: nginx
  7. # 镜像拉取策略
  8. imagePullPolicy: Always
  9. # 容器重启策略
  10. restartPolicy: Always

暴露端口

containerPort 容器端口 (0~65536),name 端口名称,protocol (TCP/UDP) 端口协议组成 image.png

  1. spec:
  2. containers:
  3. # 镜像内容
  4. - image: nginx:1.9
  5. # 镜像名称
  6. name: nginx
  7. # 镜像拉取策略
  8. imagePullPolicy: Always
  9. # 暴露端口
  10. ports:
  11. # 端口
  12. - containerPort: 8080
  13. # 名称
  14. name: http
  15. # 协议
  16. protocol: TCP

环境变量

复杂应用程序的配置信息多数由配置文件进行指定,环境变量支持:自定义、配置项(ConfigMap)以及保密字典(Secret),环境列表通常是由namevalue字段构成。

  1. spec:
  2. containers:
  3. # 镜像内容
  4. - image: nginx:1.9
  5. # 镜像名称
  6. name: nginx
  7. # 镜像拉取策略
  8. imagePullPolicy: Always
  9. # 暴露端口
  10. - env:
  11. # 通过Secret导入秘钥
  12. - name: JAVA_OPS
  13. valueFrom:
  14. # Secret 配置
  15. secretKeyRef:
  16. key: JAVA_OPS_DEFAULT
  17. name: billbear
  18. # 自定义环境变量
  19. - name: AGENT
  20. value: -javaagent:/app/opentelemetry-javaagent.jar

image.png

运行的容器命令

自定义容器运行命令

  1. spec:
  2. containers:
  3. # 镜像内容
  4. - image: nginx:1.9
  5. # 镜像名称
  6. name: nginx
  7. # 镜像拉取策略
  8. imagePullPolicy: Always
  9. # 启动执行
  10. args: ["sh -c", "java -jar xx.jar"]
  11. lifecycle:
  12. # 启动后
  13. postStart:
  14. # 除了exec 还有 httpGet tcpSocket
  15. exec:
  16. command: ["/bin/sh","-c","xxx"]
  17. # 停止前
  18. preStop:
  19. # 除了exec 还有 httpGet tcpSocket
  20. exec:
  21. command: ["/bin/sh","-c","xxx"]

image.png

存活性探测

存活性探测;可选的配置,没有设置探针POD 会根据进程状态决定容器健康

exec 探针

在容器内执行一个sh脚本,根据脚本执行返回的状态码进行诊断操作

  1. spec:
  2. containers:
  3. - livenessProbe:
  4. # exec 探针
  5. exec:
  6. command: ["test", "-e", "/tmp/healthy"]

http 探针

通过想容器IP地址指定的端口指定的path发起GET请求进行诊断,响应码为2xx3xx即为成功

  1. spec:
  2. containers:
  3. - livenessProbe:
  4. httpGet:
  5. # 发送请求路径
  6. path: /healthz
  7. # 发送请求端口
  8. prot: 8080
  9. # 发送请求协议
  10. scheme: HTTP

tcp 探针

通过特定端口发起TCP请求并尝试建立连接进行结果判定

  1. spec:
  2. containers:
  3. - livenessProbe:
  4. tcpSocket:
  5. # 发送请求端口
  6. path: 8080

就绪性探测

就绪探测;探测容器是否已经初始化完成并可服务于客户端请求,探测服务返回success状态,即为容器已准备就绪,就绪探测失败容器不会重启,而是通知尚未准备就绪

exec 探针

在容器内执行一个sh脚本,根据脚本执行返回的状态码进行诊断操作

  1. spec:
  2. containers:
  3. - readiness-exec:
  4. # exec 探针
  5. exec:
  6. command: ["test", "-e", "/tmp/healthy"]

http 探针

通过想容器IP地址指定的端口指定的path发起GET请求进行诊断

  1. spec:
  2. containers:
  3. - readiness-exec:
  4. httpGet:
  5. # 发送请求路径
  6. path: /healthz
  7. # 发送请求端口
  8. prot: 8080
  9. # 发送请求协议
  10. scheme: HTTP

tcp 探针

通过特定端口发起TCP请求并尝试建立连接进行结果判定

  1. spec:
  2. containers:
  3. - readiness-exec:
  4. tcSocket:
  5. # 发送请求端口
  6. path: 8080

image.png

数据卷

容器在重启之后数据是不会保留的,当部分数据需要持久的化的时候就需要挂载外部的卷

  • 挂载宿主机的磁盘(POD调度会放在随机的宿主机很尴尬)
  • 挂载配置项,这个是一个只读的资源
  • 挂载保密字典,这是一个只读的资源
  • 挂载集群磁盘 PVC
  1. spec:
  2. containers:
  3. # 容器内目标磁盘
  4. - volumeMounts:
  5. - mountPath: /etc/localtime
  6. name: volume-localtime
  7. - mountPath: /app/logs/
  8. name: volumn-sls-16468903025242
  9. # 宿主机或者PVC
  10. volumes:
  11. - hostPath:
  12. path: /etc/localtime
  13. type: ''
  14. name: volume-localtime
  15. - emptyDir: {}
  16. name: volumn-sls-16468903025242

image.png

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,时间将通过他接受。

Pod - 图11

容器终止过程

当提交容器终止命令的时候,系统就会进行强制删除操作的宽限期倒计时,并将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从而完成删除操作,它变得对用户不可见

Pod - 图12

资源对象模型中由用户创建或部署的最小组件,也是在Kubernetes系统上运行容器化应用的资源对象

标签

随着同类型资源对象的数量越来越多,分类管理也变得越来越有必要:

  • 基于简单且直接的标准将资源对象划分为多个较小的分组
  • 无论是对开发人员和系统工程师提升管理效率
  • 对于附带标签的资源对象,可以使用标签选择器(Lable Select)挑选出符合条件的资源以及完成所需要的操作

标签

标签就是 “键值” 类型的数据,他们可于资源创建时直接指定,也可随时按需添加于活动对象中,而后即由标签选择器进行匹配度检查从而完成资源挑选。

  • 版本标签:release``stable``release
  • 环境标签:environment``dev``qa
  • 应用标签:app``ui
  • 架构层级标签:tier``cache
  • 分区标签:customer
  • 品控级别标签:daily
  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4. annotations:
  5. deployment.kubernetes.io/revision: '11'
  6. creationTimestamp: '2022-03-24T05:22:47Z'
  7. generation: 11
  8. # 标签选择器
  9. labels:
  10. # K-V 形式
  11. app: billbear-api-gateway
  12. ...

选择器

标签选择器用于表达标签的查询条件或者标准,Kubernetes API 目前进支持二个选择器

  • 基于等值关系:== 判断是否相等,!= 判断不相等
  • 基于集合关系:in() 搜索是否包含,notin() 不存在

主要场景:

  • Service 服务
  • Ingress 路由
  • NodeSelect 节点选择器
  1. spec:
  2. ports:
  3. - name: http
  4. port: 8080
  5. protocol: TCP
  6. targetPort: 8080
  7. # 选择器 (等值选择器)
  8. selector:
  9. # K-V 形式
  10. app: billbear-api-gateway

节点选择器

Pod 节点选择器是标签及标签选择器的一种应用,它能够让Pod对象基于集群中工作节点的标签来挑选倾向运行的目标节点,后面推荐使用Pod 的亲和度替代这里仅做了解

  1. spec:
  2. containers:
  3. - name: app
  4. # 节点选择器,选择具有disktype标签的节点
  5. nodeSelect:
  6. disktype: ssd

资源注解

Pod 与其他各种资源还能使用注解(Annotation)。与标签类似,注解也是 “键值” 类型的数据,不过他不能用于标签及挑选Kubernetes对象,仅可用于为资源提供“元数据”信息。

  • 注解中的元数据不受字符数量的限制,它可大可小。
  • 可以为结构化或非结构化形式,也支持使用在标签中禁止使用的其他字符。

主要场景:

  • 申明式配置层(apply)命令的管理的字段。
  • 构建、发行或镜像相关的信息,例如,时间戳、发行ID、Git分支、PR号码、镜像哈希以及仓库地址
  • 指向日志、监控、分析或者审计仓库的指针
  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4. # 资源注解
  5. annotations:
  6. # K-V 形式
  7. deployment.kubernetes.io/revision: '11'
  8. creationTimestamp: '2022-03-24T05:22:47Z'
  9. generation: 11
  10. labels:
  11. app: billbear-api-gateway
  12. ...

完整的例子

  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4. # 注解
  5. annotations:
  6. deployment.kubernetes.io/revision: '4'
  7. # 标签
  8. labels:
  9. app: billbear-newmall-client
  10. # POD 名称
  11. name: billbear-newmall-client
  12. # 项目名称
  13. namespace: interests
  14. spec:
  15. # POD 数量
  16. replicas: 1
  17. template:
  18. metadata:
  19. # 注解
  20. annotations:
  21. # 标签
  22. labels:
  23. app: billbear-newmall-client
  24. spec:
  25. # 容器集
  26. containers:
  27. # 环境变量
  28. - env:
  29. - name: JAVA_OPS
  30. valueFrom:
  31. secretKeyRef:
  32. key: JAVA_OPS_DEFAULT
  33. name: billbear
  34. - name: AGENT
  35. value: >-
  36. -javaagent:/app/opentelemetry-javaagent.jar
  37. -Dotel.resource.attributes=service.name=billbear-newmall-client,service.version=1.0.0,host.name=billbear-newmall-client.api.local
  38. - name: JAR_OPS
  39. value: '--spring.cloud.nacos.discovery.port=32018'
  40. # 镜像版本
  41. image: xxx:test
  42. # 拉取策略
  43. imagePullPolicy: Always
  44. # 镜像名称
  45. name: billbear-newmall-client
  46. # 暴露端口
  47. ports:
  48. - containerPort: 8080
  49. name: http
  50. protocol: TCP
  51. resources:
  52. requests:
  53. memory: 512Mi
  54. # 容器对应的目录
  55. volumeMounts:
  56. - mountPath: /etc/localtime
  57. name: volume-localtime
  58. - mountPath: /app/logs/
  59. name: volumn-sls-16468903025242
  60. # 镜像拉取秘钥
  61. imagePullSecrets:
  62. - name: aliyun-shanghai
  63. # 申明挂载的磁盘
  64. volumes:
  65. - hostPath:
  66. path: /etc/localtime
  67. type: ''
  68. name: volume-localtime
  69. - emptyDir: {}
  70. name: volumn-sls-16468903025242