Kubernetes:Pod

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: Kubernetes:Pod

pod 是 Kubernetes 中创建和管理的最小可部署单元。pod 就像一台逻辑主机,是一组共享上下文的容器集合,共享存储、网络,一同调度。

pod 遵循预定义的生命周期,起始于 Pending 阶段, 如果至少其中有一个主要容器正常启动,则进入 Running,之后取决于 Pod 中是否有容器以失败状态结束而进入 Succeeded 或者 Failed 阶段。pod 在其生命周期中只会被调度一次。 一旦 pod 被调度到某个节点,pod 会一直在该节点运行,直到 pod 停止或者被终止。


1、Pod 定义

pod 使用 yaml 文件定义,使用下面命令查看 pod 资源文档的说明。

kubectl explain pods

pod 有两种用法:

  • 运行单个容器的 pod
  • 运行多个容器的 pod

例如定义 myhello-pod.yaml 配置文件,运行多个容器的 pod

# api 版本
 apiVersion: v1
 # 类型
 kind: Pod
 # 元数据
 metadata: 
   # 名字
   name: myhello-pod
   # 命名空间
   namespace: default 
   # 标签,svc,deployment 通过 labels 管理 pod 
   labels:
     name: myhello-pod
     env: dev
 # 规则
 spec:
   # 容器重启策略:Always、Never、OnFailure
   restartPolicy: Always
   # 定义容器
   containers:
   # 容器1: myhello
   - name: myhello
     image: xlhmzch/hello:1.0.0
     # 镜像拉取策略:Always、Never、IfNotPresent
     # Always:总是拉取最新镜像,测试环境使用
     # Never:不拉取镜像,使用本地镜像
     # IfNotPresent:本地没有镜像,则拉取镜像
     imagePullPolicy: IfNotPresent
     # 容器端口
     ports:
     - containerPort: 80
     # 容器启动命令,二进制文件名 app
     command: ["./app"]
     # 容器启动命令参数
     args: ["--param1=k8s-p1", "--param2=k8s-p2"]
     # 容器使用资源设置
     resources:
       # 容器可分配的最低资源配额
       requests:
         cpu: 100m     # cpu 资源单位:1CPU=1000m,通常容器使用的 cpu 配额 100m~300m
         memory: 200Mi # 内存资源:单位 Ei、Pi、Ti、Gi、Mi、Ki
       # 容器可分配的最高资源配额
       limits:
         cpu: 200m
         memory: 500Mi
     # 注入到容器的环境变量
     env: 
     - name: env1
       value: "k8s-env1"
     - name: env2
       value: "k8s-env2"
   # 容器2: redis
   - name: myredis
     image: redis
     imagePullPolicy: IfNotPresent
     port:
     - containerPort: 6379
     resources:
       requests:
         cpu: 100m
         memory: 200Mi
       limits:
         cpu: 200m
         memory: 500Mi

测试

# 将新的配置应用到资源上
 kubectl apply -f myhello-pod.yaml
 # 获取资源信息
 kubectl get pod/myhello-pod 
 kubectl get -f myhello-pod.yaml
 # 显示资源详细信息
 kubectl describe pod/myhello-pod
 kubectl describe -f myhello-pod.yaml

2、Pod 使用

完整测试代码见 2.4 部分。

2.1、init 容器

作用:业务容器启动前,通常用于数据卷初始化

init 容器与普通容器的区别

  • init 容器总是运行到完成。init 容器不是通过守护进程提供服务,而是通过启动容器来执行处理任务。任务完成,则容器完成。
  • 每个 init 容器都必须在下一个启动之前成功完成。多个 init 容器按定义顺序逐个执行一次, 每个 init 容器必须运行成功,这样下一个 init 容器才能够运行。只有当所有 init 容器完成时,k8s 才会启动 pod 应用容器。

例:在上述例子基础上,定义 init 容器:init-myservice,init-mydb

spec:
 ---
   # 定义 init 容器
   initContainers:
   - name: init-myservice
     image: busybox
     # 查找命名空间下 myservice 服务,如果存在则执行成功,如果不存在则一直查找
     command: ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]
   - name: init-mydb
     image: busybox
     # 查找命名空间下 mydb 服务,如果存在则执行成功,如果不存在则一直查找
     command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]
 ---
   containers:

测试过程

创建 pod

kubectl delete -f myhello-pod.yaml
 kubectl apply -f myhello-pod.yaml

查看 pod 状态和容器日志

# 获取 pod
 # 显示 pod 一直处于 init 状态
 kubectl get pod
 # 查看 pod 详细信息
 # 显示 pod 状态为 Pending,容器状态:init-myservice: running,其他容器:Waiting
 kubectl describe -f myhello-pod.yaml
 # 查看容器日志
 # 显示:waiting for myservice
 kubectl logs -f myhello-pod -c init-myservice

这是因为 myservice 服务和 mydb 服务没有定义,init 容器空转。

创建 myservice 服务

apiVersion: v1
 kind: Service
 metadata:
   name: myservice
 spec:
   ports:
   - protocol: TCP
     port: 80

查看 pod 状态和容器日志

# 启动服务
 kubectl apply -f myservice.yaml
 # 查看 pod 状态,容器日志
 # STATUS:Init:1/2
 kubectl get -f myhello-pod.yaml
 # init-myservice 容器:State: Terminated,Reason: Completed,Exit Code: 0
 kubectl describe -f myhello-pod.yaml
 # 查看 init-mydb 容器
 kubectl logs -f myhello-pod -c init-mydb

创建 mydb 服务

apiVersion: v1
 kind: Service
 metadata:
   name: mydb
 spec:
   ports:
   - protocol: TCP
     port: 80

查看 pod 状态和容器日志

kubectl apply -f mydb.yaml
 kubectl get -f myhello-pod.yaml
 kubectl describe -f myhello-pod.yaml

2.2、容器生命周期处理函数

k8s 支持 postStart 和 preStop 事件。

  • postStart 事件:容器启动后,k8s 发送该事件
  • preStop 事件:容器停止前,k8s 发送该事件

例:

containers: 
 ---
     # 容器生命周期处理函数
     lifecycle:
       postStart:
         exec:
           command: ["/bin/sh", "-c","echo post start command exec >> /tmp/data"]
       preStop:
         exec:
           command: ["/bin/sh", "-c","echo pre stop command exec >> /tmp/data"]
 ---

创建 pod

kubectl delete pod myhello-pod 
 kubectl create -f myhello-pod.yaml

测试

# 使用 shell 连接到 pod 中的容器
 kubectl exec -it pod/myhello-pod -c myhello --sh
 # 查看 postStart 处理函数写入的文本
 cat /tmp/data

2.3、容器的探测

probe 是由 kubelet 对容器执行的定期诊断,既可以在容器内执行代码,也可以发出一个网络请求。

2.3.1、探测机制

  • exec:在容器内执行指定命令。若退出码为0, 则诊断成功。
  • httpGet:对容器的 IP 地址上指定端口和路径执行 HTTP GET 请求。如果响应的状态码大于等于 200 且小于 400,则诊断成功。
  • tcpSocket:对容器的 IP 地址上的指定端口执行 TCP 检查。如果端口打开,则诊断被认为是成功的
  • grpc:使用 grpc 执行一个远程过程调用。目标应该实现 grpc 健康检查。 如果响应的状态是 "SERVING",则诊断成功。 gRPC 探针是一个 alpha 特性。

2.3.2、探测结果

  • Success:容器通过了诊断。
  • Failure:容器未通过诊断。
  • Unknown:诊断失败,不会采取任何行动。

2.3.3、探测类型

若容器不提供探针,则默认状态为 Success。

startupProbe

启动探测:检测容器是否已经启动。探测成功后,则停止探测;探测失败,kubelet 将杀死容器,容器根据重启策略决定未来。

readinessProbe

就绪探测:检查容器是否准备好为请求提供服务。探测成功,继续探测;探测失败,端点控制器 将从与 Pod 匹配的所有服务的端点列表中删除该 Pod 的 IP 地址,即流量不再分配对应的节点。对 pod 本身不做任何处理。

使用场景:就绪探测检测后端服务是否可用。例如:数据库服务。就绪探测标识容器具备接收请求的能力,可以处理流量。

livenessProbe

存活探测:检测容器是否正在运行。探测成功,继续探测;探测失败,kubelet 将杀死容器,容器根据重启策略决定未来。

2.3.4、案例

containers:
 ---
   # 1、启动探测
   startupProbe:
     exec:
       command: ["/bin/sh", "-c","statuscode=`curl -o /dev/null -s -w %{http_code} http://localhost/healthz`; [ $$statuscode -le 400 ] || exit 1"]
     # 指定初始化时间,即探针在容器启动之后的延迟时长
     initialDelaySeconds: 5
     # 探测周期,即每隔多长时间探测一次
     periodSeconds: 5
     # 最小连续失败次数,即连续失败多少次表示探测失败
     failureThreshold: 3
     # 最小连续成功次数,即连续探测成功多少次表示探测成功,liveness 和 startup 必须为1
     successThreshold: 1
     # 探测超时时间
     timeoutSeconds: 1
   # 2、就绪探测
   readinessProbe:
     httpGet:
       path: /health
       port: 80
     initialDelaySeconds: 5
     periodSeconds: 5
     failureThreshold: 3
     successThreshold: 1
     timeoutSeconds: 1
   # 3、存活检测
   livenessProbe:
     httpGet:
       path: /health
       port: 80
     initialDelaySeconds: 5
     periodSeconds: 5
     failureThreshold: 3
     successThreshold: 1
     timeoutSeconds: 1
 ---       
 - name: myredis
   # 存活检测
   livenessProbe:
     tcpSocket:
       port: 6379
     initialDelaySeconds: 5
     periodSeconds: 5
     failureThreshold: 3
     successThreshold: 1

创建 pod

kubectl delete pod myhello-pod 
 kubectl create -f myhello-pod.yaml

查看启动探测

# 查看启动检测
 kubectl logs -f pod/myhello-pod -c myhello

查看就绪探测和存活探测

kubectl describe pod/myhello-pod
 # 容器 myhello
 Liveness: http-get http://:80/health delay=5s timeout=1s period=5s #success=1 #failure=3
 Readiness:http-get http://:80/health delay=5s timeout=1s period=5s #success=1 #failure=3
 # 容器 redis
 Liveness: tcp-socket :6379 delay=5s timeout=1s period=5s #success=1 #failure=3

2.4、测试代码

# api 版本
 apiVersion: v1
 # 类型
 kind: Pod
 # 元数据
 metadata: 
   # 名字
   name: myhello-pod
   # 命名空间
   namespace: default 
   # 标签,svc,deployment 通过 labels 管理 pod 
   labels:
     name: myhello-pod
     env: dev
 # 规则
 spec:
   # 容器重启策略
   restartPolicy: Always
   # 定义 init 容器
   initContainers:
   - name: init-myservice
     image: busybox
     # 查找命名空间下myservice服务,如果存在则执行成功,如果不存在则一直查找
     command: ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]
   - name: init-mydb
     image: busybox
     # 查找命名空间下mydb服务,如果存在则执行成功,如果不存在则一直查找
     command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]
   # 定义容器
   containers:
   # 容器1:myhello
   - name: myhello
     image: xlhmzch/hello:1.0.0
     # 镜像拉取策略
     imagePullPolicy: IfNotPresent
     # 容器端口
     ports:
     - containerPort: 80
     # 容器启动命令,二进制文件名 app
     command: ["./app"]
     # 容器启动命令参数
     args: ["--param1=k8s-p1", "--param2=k8s-p2"]
     # 容器使用资源设置
     resources:
       # 容器可分配的最低资源配额
       requests:
         cpu: 100m
         memory: 200Mi
       # 容器可分配的最高资源配额
       limits:
         cpu: 200m
         memory: 500Mi
     # 注入到容器的环境变量
     env: 
     - name: env1
       value: "k8s-env1"
     - name: env2
       value: "k8s-env2"
     # 容器生命周期处理函数
     lifecycle:
       postStart: 
         exec: 
           command: ["/bin/sh", "-c","echo post start command exec >> /tmp/data"]
       preStop:
         exec:
           command: ["/bin/sh", "-c","echo pre stop command exec >> /tmp/data"]
     # 启动探测
     startupProbe:
       exec:
         command: ["/bin/sh", "-c","statuscode=`curl -o /dev/null -s -w %{http_code} http://localhost/healthz`; [ $$statuscode -le 400 ] || exit 1"]
       # 指定初始化时间,即探针在容器启动之后的延迟时长
       initialDelaySeconds: 5
       # 探测周期,即每隔多长时间探测一次
       periodSeconds: 5
       # 最小连续失败次数,即连续失败多少次表示探测失败
       failureThreshold: 3
       # 最小连续成功次数,即连续探测成功多少次表示探测成功,liveness 和 startup 必须为1
       successThreshold: 1
       # 探测超时时间
       timeoutSeconds: 1
     # 就绪探测
     readinessProbe:
       httpGet:
         path: /health
         port: 80
       initialDelaySeconds: 5
       periodSeconds: 5
       failureThreshold: 3
       successThreshold: 1
       timeoutSeconds: 1
     # 存活检测
     livenessProbe:
       httpGet:
         path: /health
         port: 80
       initialDelaySeconds: 5
       periodSeconds: 5
       failureThreshold: 3
       successThreshold: 1
       timeoutSeconds: 1
   # 容器2: redis
   - name: myredis
     image: redis
     imagePullPolicy: IfNotPresent
     ports:
     - containerPort: 6379
     resources:
       requests:
         cpu: 100m
         memory: 200Mi
       limits:
         cpu: 200m
         memory: 500Mi
     # 存活检测
     livenessProbe:
       tcpSocket:
         port: 6379
       initialDelaySeconds: 5
       periodSeconds: 5
       failureThreshold: 3
       successThreshold: 1

3、Pod 的部署

在 Kubernetes 中,Pod 工作负载,是集群上处于运行状态的一组容器的集合。为了减轻用户的使用负担,通常不需要用户直接管理每个 Pod。 而是使用负载资源来替用户管理一组 Pod。 这些负载资源通过配置控制器来管理。

负载资源

  • Deployment:管理无状态应用
  • StatefulSet:管理有状态应用
  • DaemonSet:每个节点只运行 1 个 pod 副本
  • JobCronJob:定义任务。

3.1、Deployment

管理无状态应用部署。内部自动创建 RS (ReplicaSet) 用于 pod 副本控制。

相较于 RC | RS 具有以下优势:

  • deployment 资源对象会自动创建 RS 资源对象来完成部署,对 deployment 的修改并发布会产生新的 RS 资源对象,为新的发布版本服务。
  • 支持查看部署进度,以确定部署操作是否完成
  • 更新 deployment,会触发部署从而更新 pod
  • 支持 pause | resume 操作,暂停后修改不会触发发布,恢复后发布新的 deployment
  • 支持回滚操作
  • 支持重新启动操作,触发 pod 更新。
  • 自动清理不需要的 RS

例:定义 deployment 配置文件

apiVersion: apps/v1
 kind: Deployment
 metadata:
   name: myapp-deploy
   namespace: default
   labels:
     name: myapp-deploy
 spec:
   # pod 副本数
   replicas: 3
   # 标签选择器:查找管理的 pod 
   selector:
     # 匹配 template.metadata.labels
     matchLabels:
       app: myapp
   # pod 模板:定义 pod
   template:
     metadata:
       labels:
         app: myapp
     spec:
       restartPolicy: Always
       containers:
       - name: myhello
         image: xlhmzch/hello:1.0.0
         imagePullPolicy: IfNotPresent
         ports:
         - containerPort: 80
         command: ["./app"]
         args: ["--param1=k8s-p1", "--param2=k8s-p2"]
         resources:
           requests:
             cpu: 100m
             memory: 200Mi
           limits:
             cpu: 200m
             memory: 500Mi
         env: 
         - name: env1
           value: "k8s-env1"
         - name: env2
           value: "k8s-env2"
         startupProbe:
           exec:
             command: ["/bin/sh", "-c","statuscode=`curl -o /dev/null -s -w %{http_code} http://localhost/healthz`; [ $$statuscode -le 400 ] || exit 1"]
           initialDelaySeconds: 5
           periodSeconds: 5
           failureThreshold: 3
           successThreshold: 1
           timeoutSeconds: 1
         readinessProbe:
           httpGet:
             path: /health
             port: 80
           initialDelaySeconds: 5
           periodSeconds: 5
           failureThreshold: 3
           successThreshold: 1
           timeoutSeconds: 1
         livenessProbe:
           httpGet:
             path: /health
             port: 80
           initialDelaySeconds: 5
           periodSeconds: 5
           failureThreshold: 3
           successThreshold: 1
           timeoutSeconds: 1

测试方法:

# 应用部署
 kubectl apply -f myapp-deployment.yaml 
 # 获取部署信息
 kubectl get -f myapp-deployment.yaml
 # 获取副本控制器
 kubectl get rs
 # 修改 deployment
 # 查看线上与线下的区别
 kubectl diff -f myapp-deployment.yaml 
 # 应用新的配置文件,实现 deployment 升级
 kubectl apply -f myapp-deployment.yaml 
 # 获取部署信息
 kubectl get -f myapp-deployment.yaml
 # 获取副本控制器
 kubectl get rs
 # 管理发布版本
 kubectl rollout
 # 查看版本发布的历史
 kubectl rollout history deployment myapp-deploy
 # 查看指定版本
 kubectl rollout history deployment myapp-deploy --revision 1
 # 回滚指定版本,回滚后也算新版本(revision + 1)
 kubectl rollout undo deployment myapp-deploy --to-revision 1
 # 查看发布状态
 kubectl rollout status deployment myapp-deploy
 # 暂停部署
 kubectl rollout pause deployment myapp-deploy 
 # 期间任何修改,不会上线
 kubectl apply -f myapp-deployment.yaml
 # 恢复部署
 kubectl rollout resume deployment myapp-deploy
 # 重启部署
 kubectl rollout restart deployment myapp-deploy 
 # 自动伸缩容
 kubectl autoscale deployment myapp-deploy --min 2 --max 3 --cpu-percent 20
 kubectl get horizontalpodautoscalers.autoscaling

3.2、DaemonSets

每个节点只运行一个 pod 副本。

应用:每个节点上运行集群守护进程、日志收集守护进程和监控守护进程。

例:编写 DaemonSet 配置文件

apiVersion: apps/v1
 kind: DaemonSet
 metadata:
   name: myapp-ds
   namespace: default
   labels:
     app: myapp-ds
 spec:
   selector:
     matchLabels:
       app: myapp-ds
   template:
     metadata:
       labels:
         app: myapp-ds
     spec:
       tolerations: # 设置容忍度,即能否部署到有污点的节点上 master
       - key: node-role.kubernetes.io/control-plane
         operator: Exists
         effect: NoSchedule
       containers:
       - name: myhello 
         image: xlhmzch/hello:1.0.0 
         imagePullPolicy: IfNotPresent
         ports:
         - containerPort: 80
         env: 
         - name: env1
           value: "k8s-env1"
         - name: env2
           value: "k8s-env2"

测试方法同上。

3.3、静态 pod

静态 pod 直接由指定节点上的 kubelet 守护进程管理。 大多数 Pod 都是通过控制面(例 Deployment)来管理的,对于静态 Pod 而言,kubelet 直接监控每个 Pod。

例:编写静态 pod 配置文件

apiVersion: v1
 kind: Pod
 metadata:
   name: myhello-static-pod
   namespace: default
   labels:
     name: myhello-static-pod
     env: dev
 spec:
   containers:
   - name: myhello
     image: xlhmzch/hello:1.0.0
     imagePullPolicy: IfNotPresent
     ports:
     - containerPort: 80
     command: ["./app"]
     args: ["--param1=k8s-p1", "--param2=k8s-p2"]
     resources:
       requests:
         cpu: 100m     
         memory: 200Mi 
       limits:
         cpu: 200m
         memory: 500Mi
     env: 
     - name: env1
       value: "k8s-env1"
     - name: env2
       value: "k8s-env2"

4、参考

相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
24天前
|
前端开发 编解码 数据格式
浅谈响应式编程在企业级前端应用 UI 开发中的实践
浅谈响应式编程在企业级前端应用 UI 开发中的实践
20 0
浅谈响应式编程在企业级前端应用 UI 开发中的实践
|
1月前
|
Prometheus Kubernetes 监控
容器服务ACK常见问题之pod设置securityContext调整参数失败如何解决
容器服务ACK(阿里云容器服务 Kubernetes 版)是阿里云提供的一种托管式Kubernetes服务,帮助用户轻松使用Kubernetes进行应用部署、管理和扩展。本汇总收集了容器服务ACK使用中的常见问题及答案,包括集群管理、应用部署、服务访问、网络配置、存储使用、安全保障等方面,旨在帮助用户快速解决使用过程中遇到的难题,提升容器管理和运维效率。
|
3月前
|
Kubernetes 监控 调度
Kubernetes Pod调度:从基础到高级实战技巧
Kubernetes Pod调度:从基础到高级实战技巧
191 0
|
4月前
|
Kubernetes 安全 Cloud Native
云原生|kubernetes|pod或容器的安全上下文配置解析
云原生|kubernetes|pod或容器的安全上下文配置解析
112 0
|
15天前
|
存储 Kubernetes 调度
Kubernetes Pod生命周期
Kubernetes Pod生命周期
25 0
Kubernetes Pod生命周期
|
15天前
|
存储 Kubernetes 应用服务中间件
Kubernetes Pod
Kubernetes Pod
48 0
Kubernetes Pod
|
26天前
|
存储 Kubernetes 调度
K8s Pod亲和性、污点、容忍度、生命周期与健康探测详解(下)
本文全面探讨了Kubernetes集群中Pod的四种关键机制——Pod亲和性、污点(Taints)、容忍度(Tolerations)、生命周期以及健康探测,为读者提供了深入理解并有效应用这些特性的指南。
|
26天前
|
Kubernetes 网络协议 Perl
k8s Failed to create pod sandbox: open /run/systemd/resolve/resolv.conf: no such file or directory
k8s Failed to create pod sandbox: open /run/systemd/resolve/resolv.conf: no such file or directory
25 0
|
1月前
|
Kubernetes Nacos 微服务
nacos常见问题之v2.2.3 k8s 微服务注册nacos强制删除 pod不消失如何解决
Nacos是阿里云开源的服务发现和配置管理平台,用于构建动态微服务应用架构;本汇总针对Nacos在实际应用中用户常遇到的问题进行了归纳和解答,旨在帮助开发者和运维人员高效解决使用Nacos时的各类疑难杂症。
24 1
nacos常见问题之v2.2.3 k8s 微服务注册nacos强制删除 pod不消失如何解决
|
1月前
|
域名解析 Kubernetes Linux
Kubernetes 外部 HTTP 请求到达 Pod 容器的全过程
Kubernetes 外部 HTTP 请求到达 Pod 容器的全过程
43 4