Kubernetes:Pod

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
日志服务 SLS,月写入数据量 50GB 1个月
简介: 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、参考

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
1月前
|
Kubernetes API 调度
k8s中节点无法启动Pod
【10月更文挑战第3天】
74 6
|
1天前
|
弹性计算 Kubernetes Perl
k8s 设置pod 的cpu 和内存
在 Kubernetes (k8s) 中,设置 Pod 的 CPU 和内存资源限制和请求是非常重要的,因为这有助于确保集群资源的合理分配和有效利用。你可以通过定义 Pod 的 `resources` 字段来设置这些限制。 以下是一个示例 YAML 文件,展示了如何为一个 Pod 设置 CPU 和内存资源请求(requests)和限制(limits): ```yaml apiVersion: v1 kind: Pod metadata: name: example-pod spec: containers: - name: example-container image:
|
3天前
|
Kubernetes Nacos 微服务
探讨了在Kubernetes中使用Nacos v2.2.3时,强制删除Pod后Pod仍存在的常见问题
本文深入探讨了在Kubernetes中使用Nacos v2.2.3时,强制删除Pod后Pod仍存在的常见问题。通过检查Pod状态、事件、配置,调整Nacos和Kubernetes设置,以及手动干预等步骤,帮助开发者快速定位并解决问题,确保服务稳定运行。
16 2
|
1月前
|
存储 Kubernetes Perl
K8S中Pod启动异常
【10月更文挑战第3天】
64 2
|
1月前
|
应用服务中间件 调度 nginx
Kubernetes的Pod调度:让你的应用像乘坐头等舱!
Kubernetes的Pod调度:让你的应用像乘坐头等舱!
|
1月前
|
Kubernetes API 调度
k8s学习--pod的所有状态详解(图例展示)
k8s学习--pod的所有状态详解(图例展示)
121 1
|
1月前
|
Kubernetes 应用服务中间件 nginx
k8s学习--kubernetes服务自动伸缩之水平收缩(pod副本收缩)VPA策略应用案例
k8s学习--kubernetes服务自动伸缩之水平收缩(pod副本收缩)VPA策略应用案例
|
1月前
|
JSON Kubernetes API
在K8S中,什么是静态Pod?
在K8S中,什么是静态Pod?
|
1月前
|
Kubernetes 应用服务中间件 调度
k8s的Pod常见的几种调度形式
k8s的Pod常见的几种调度形式
23 0
|
1月前
|
Kubernetes 固态存储 调度
k8s学习--如何控制pod调度的位置
k8s学习--如何控制pod调度的位置