第五章 Kubernetes进阶之Pod
Pod
- 最小部署单元
- 一组容器的组合
- 一个Pod中容器共享网络命名空间
- Pod是短暂的
Pod容器分类
Infrastructure Container 基础容器
维护整个Pod网络空间
InitContainers 初始化容器
先于业务容器运行
Container 业务容器
并行启动
镜像拉取策略
- IfNotPresent:默认值,镜像在宿主机上不存在时才拉取
- Alway:每次创建Pod都会拉取一次镜像
- Never:Pod永远不会拉取这个镜像
查看默认镜像拉取参数是否是IfNotPresent
1 | kubectl get deploy / nginx - deployment - o yaml |
没有认证的公共镜像仓库可以直接拉取,搭建私有镜像仓库Habor
本次搭建的主机为192.168.1.61,之前使用改主机搭建了nginx+keepalived为了不冲突需要关闭该主机的nginx即使用192.168.1.62来产生VIP192.168.1.60
搭建参考
https://www.cnblogs.com/minseo/p/8905736.html
登录Harbor创建一个私有项目project
默认用户名:admin 密码:Harbor12345
私有仓库需要登录才能下载,Harbor不是http提供访问,需要在node 192.168.1.65 192.168.1.66配置可信任
1 2 3 4 5 | # cat /etc/docker/daemon.json { "registry-mirrors" : [ "https://7sl94zzz.mirror.aliyuncs.com" ], "insecure-registries" : [ "192.168.1.61" ] } |
设置可信任之后需要重启docker否则下面操作无法登录
1 | systemctl restart docker |
node上面登录,输入用户名和密码
1 | docker login 192.168 . 1.61 |
查看该node已有的镜像
1 | docker images |
下载一个tomcat镜像用于推送测试
1 | docker pull tomcat |
下载完毕打tag
1 | docker tag tomcat 192.168 . 1.61 / project / tomcat |
查看
推送至harbor私有仓库
1 | docker push 192.168 . 1.61 / project / tomcat |
推送成功在harbor上可以看到
排错,推送是出现提示,查看haabor该项目是否创建
1 | requested access to the resource is denied |
在另外一台node上拉取该镜像
1 | docker pull 192.168 . 1.61 / project / tomcat |
PS:需要在该node节点至少登录过一次才能下载,否则会出现如下提示
1 2 3 | docker pull 192.168 . 1.61 / project / tomcat Using default tag: latest Error response from daemon: pull access denied for 192.168 . 1.61 / project / tomcat, repository does not exist or may require 'docker login' : denied: requested access to the resource is denied |
推送至harbor的镜像是私有的,如果是通过k8s部署则是拉取公网的镜像无法拉取到私有的镜像,需要通过配置imagePullSecrets参数才能从私有仓库拉取镜像
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | # cat tomcat-deployment.yaml apiVersion: apps / v1 kind: Deployment metadata: labels: run: tomcat name: tomcat spec: replicas: 3 selector: matchLabels: run: tomcat template: metadata: labels: run: tomcat spec: containers: - image: tomcat name: tomcat ports: - containerPort: 8080 - - - apiVersion: v1 kind: Service metadata: labels: run: tomcat name: tomcat - service spec: ports: - port: 8080 protocol: TCP targetPort: 8080 selector: run: tomcat type : NodePort |
该yaml配置文件可以通过以下命令生成
1 2 3 4 5 6 7 8 | #生成deployment配置文件 kubectl run tomcat - - replicas = 3 - - image = tomcat - - port = 8080 - - dry - run - o yaml>>tomcat - deployment2.yaml #间隔符 多个配置需要间隔,否则创建时候部分不生效 echo "---" >>tomcat - deployment2.yaml #生成service配置文件 #生成该配置文件需要指定的deployment已经在运行中即要已经运行了命令启动了delpoyment<br>kubectl run tomcat --replicas=3 --image=tomcat --port=8080 #可以先运行再删除该deployment kubectl expose deployment tomcat - - port = 8080 - - type = NodePort - - target - port = 8080 - - name = nginx - service - - dry - run - o yaml >> tomcat - deployment.yaml |
使用配置文件创建deployment和service
1 2 3 | # kubectl create -f tomcat-deployment.yaml deployment.apps / tomcat created service / tomcat - service created |
查看
1 2 3 4 5 6 7 8 9 | # kubectl get pod,svc NAME READY STATUS RESTARTS AGE pod / tomcat - 5d6455cc4 - lpwht 1 / 1 Running 0 36s pod / tomcat - 5d6455cc4 - wnfsh 1 / 1 Running 0 36s pod / tomcat - 5d6455cc4 - zgvbp 1 / 1 Running 0 36s NAME TYPE CLUSTER - IP EXTERNAL - IP PORT(S) AGE service / kubernetes ClusterIP 10.10 . 10.1 <none> 443 / TCP 6d2h service / tomcat - service NodePort 10.10 . 10.105 <none> 8080 : 37426 / TCP 36s |
通过node ip加NodePort端口即可访问tomcat默认页面
配置文件指定镜像是从docker hub拉取的,现在改成私有镜像的地址,因为默认的策略是优先拉取本机已有镜像所以拉取镜像策略改成Always
修改yaml配置文件,修改以下两处
应用更新
1 2 3 | # kubectl apply -f tomcat-deployment.yaml deployment.apps / tomcat configured service / tomcat - service unchanged |
查看pod事件
1 | kubectl describe pod tomcat - 78876547c6 - jn7c4 |
需要配置凭据才能拉取
在已经docker login过的node上面获取
1 | cat / root / .docker / config.json | base64 - w0 |
复制这串字符编辑配置文件
1 2 3 4 5 6 7 8 | #cat registry-pull-secret.yaml apiVersion: v1 kind: Secret metadata: name: registry - pull - secret data: .dockerconfigjson: ewoJImF1dGhzIjogewoJCSIxOTIuMTY4LjEuNjEiOiB7CgkJCSJhdXRoIjogIllXUnRhVzQ2U0dGeVltOXlNVEl6TkRVPSIKCQl9Cgl9LAoJIkh0dHBIZWFkZXJzIjogewoJCSJVc2VyLUFnZW50IjogIkRvY2tlci1DbGllbnQvMTkuMDMuNiAobGludXgpIgoJfQp9 type : kubernetes.io / dockerconfigjson |
应用
1 2 | # kubectl create -f registry-pull-secret.yaml secret / registry - pull - secret created |
查看已经生成secret
1 2 3 4 | # kubectl get secret NAME TYPE DATA AGE default - token - pw8st kubernetes.io / service - account - token 3 6d2h registry - pull - secret kubernetes.io / dockerconfigjson 1 22s |
修改tomcat-deployment.yaml增加认证
修改后完整的yaml文件如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | # cat tomcat-deployment.yaml apiVersion: apps / v1 kind: Deployment metadata: labels: run: tomcat name: tomcat spec: replicas: 3 selector: matchLabels: run: tomcat template: metadata: labels: run: tomcat spec: imagePullSecrets: - name: registry - pull - secret containers: - image: 192.168 . 1.61 / project / tomcat imagePullPolicy: Always name: tomcat ports: - containerPort: 8080 - - - apiVersion: v1 kind: Service metadata: labels: run: tomcat name: tomcat - service spec: ports: - port: 8080 protocol: TCP targetPort: 8080 selector: run: tomcat type : NodePort |
应用更改
1 | kubectl apply - f tomcat - deployment.yaml |
查看
1 2 3 4 5 6 7 8 9 | # kubectl get pod,svc NAME READY STATUS RESTARTS AGE pod / tomcat - 68c76b858d - 5lq22 1 / 1 Running 0 4m41s pod / tomcat - 68c76b858d - ckrqr 1 / 1 Running 0 4m45s pod / tomcat - 68c76b858d - dctgt 1 / 1 Running 0 4m43s NAME TYPE CLUSTER - IP EXTERNAL - IP PORT(S) AGE service / kubernetes ClusterIP 10.10 . 10.1 <none> 443 / TCP 6d3h service / tomcat - service NodePort 10.10 . 10.105 <none> 8080 : 37426 / TCP 29m |
因为镜像拉取策略是Always所以从pod的运行时间即可看出是否拉取了私有仓库的镜像
登录Harbor查看也可以看到本次拉取镜像是从私有仓库拉取
拍错:访问tomcat出现404错误提示,原因是tomcat镜像根目录没有文件,解决办法
1 2 3 4 5 6 7 8 | #分别进入容器 kubectl exec - it tomcat - 68c76b858d - 5lq22 - c tomcat bash kubectl exec - it tomcat - 68c76b858d - ckrqr - c tomcat bash kubectl exec - it tomcat - 68c76b858d - dctgt - c tomcat bash #复制根目录文件,默认webapps为空 cd / usr / local / tomcat rm - rf webapps mv webapps.dist / webapps |
资源限制
为了防止某个Pod占用资源过多影响宿主机需要对Pod进行资源限制
Pod中的每个容器都可以指定一下一个或者多个值
1 2 3 4 | spec.containers[].resources.limits.cpu spec.containers[].resources.limits.memory spec.containers[].resources.requests.cpu spec.containers[].resources.requests.memory |
示例,该示例可以在官方复制https://kubernetes.io/zh/docs/concepts/configuration/manage-compute-resources-container/
以下 Pod 有两个容器。每个容器的请求为 0.25 cpu 和 64MiB(226 字节)内存,每个容器的限制为 0.5 cpu 和 128MiB 内存。您可以说该 Pod 请求 0.5 cpu 和 128 MiB 的内存,限制为 1 cpu 和 256MiB 的内存。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | # cat pod2.yaml apiVersion: v1 kind: Pod metadata: name: frontend spec: containers: - name: db image: mysql env: - name: MYSQL_ROOT_PASSWORD value: "password" resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m" - name: wp image: wordpress resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m" |
查看该pod分配到那一台node
1 | kubectl describe pod frontend |
查看资源限制是否生效
1 | kubectl describe nodes 192.168 . 1.66 |
Pod重启策略
restartPolicy
- Always:当容器终止退出后,总是重启容器,默认策略
- OnFailure:当容器异常退出(退出状态码非0)时,才重启容器
- Never:当容器终止退出,从不重启容器
查看
1 | kubectl edit pods nginx - 7cdbd8cdc9 - ngpgr |
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 | # cat pod3.yaml apiVersion: v1 kind: Pod metadata: name: foo spec: containers: - name: busybox image: busybox args: - / bin / sh - - c - sleep 30 ; exit 3 |
该yaml执行进入容器后等待30秒退出
应用
1 | kubectl apply - f pod3.yaml |
查看pod会从running状态,到退出会提示错误状态,因为策略是Always所以又重启一次
修改
1 2 3 4 5 6 7 8 9 10 11 12 13 | apiVersion: v1 kind: Pod metadata: name: foo spec: containers: - name: busybox image: busybox args: - / bin / sh - - c - sleep 10 restartPolicy: Never |
删除再应用
1 2 | kubectl delete - f pod3.yaml kubectl apply - f pod3.yaml |
查看状态,容器运行10秒以后正常退出了,策略为Never所以不再新启动一个pod 状态显示完成状态
健康检查
Probe有以下两种类型
livenessProbe
如果检查失败,将杀死容器,根据Pod的restartPolicy来操作
readinessProbe
如果检查失败,Kubernetes会把Pod从service endpoint中剔除
查看endpoint使用命令
1 2 3 4 | # kubectl get ep NAME ENDPOINTS AGE kubernetes 192.168 . 1.63 : 6443 , 192.168 . 1.64 : 6443 6d4h tomcat - service 172.17 . 41.4 : 8080 , 172.17 . 55.2 : 8080 , 172.17 . 55.5 : 8080 131m |
Probe支持以下三种检查方法
HttpGet
发送HTTP请求,返回200-400范围状态码为成功
exec
执行shell命令返回状态码是0为成功
tcpSocket
发起TCP Socket建立成功
官方示例 下载地址https://kubernetes.io/zh/docs/concepts/configuration/manage-compute-resources-container/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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 livenessProbe: exec : command: - cat - / tmp / healthy #启动延时5秒以后开始健康检查 initialDelaySeconds: 5 #健康检查周期是5秒 periodSeconds: 5 |
应用
1 | kubectl apply - f pod4.yaml |
启动后创建了健康检查文件,等待30秒以后,删除了健康检查文件,健康检查没有发现该文件就重启容器了
查看pod的描述日志
企业生产环境中需要配置健康检查
Pod调度约束
可以让Pod放在指定节点上,例如A部门创建的Pod放在一台node,B部门创建的Pod放在另一台node
用户创建Pod过程
nodeName用于将Pod调度到指定的Node名称上
nodeSelector用于将Pod调度到匹配Label的Node上
1 2 3 4 5 6 7 8 9 10 11 12 | #cat pod5.yaml apiVersion: v1 kind: Pod metadata: name: pod - example labels: app: nginx spec: nodeName: 192.168 . 1.65 containers: - name: nginx image: nginx |
设置标签
1 2 3 4 5 | #设置标签 kubectl label nodes 192.168 . 1.65 team = a kubectl label nodes 192.168 . 1.66 team = b #查看标签 kubectl get nodes - - show - labels |
删除标签
1 2 3 | #在标签后加-号即可删除标签 kubectl label nodes 192.168 . 1.65 team - kubectl label nodes 192.168 . 1.66 team - |
在yaml文件里面设置标签
1 2 3 4 5 6 7 8 9 10 11 12 13 | # cat pod6.yaml apiVersion: v1 kind: Pod metadata: name: pod - example labels: app: nginx spec: nodeSelector: team: b containers: - name: nginx image: nginx |
应用
1 | kubectl apply - f pod6.yaml |
查看
PS:如果调度约束配置不正确Pod会出现Pending状态查看描述会出现以下错误提示
1 | Warning FailedScheduling 27s (x2 over 27s) default-scheduler 0 /2 nodes are available: 2 node(s) didn't match node selector. |
故障排查
值 | 描述 |
Pending | Pod创建已经提交k8s,但是因为,某种原因不能顺利创建。例如下载镜像慢,调度不成功 |
Running | Pod已经绑定到一个节点,并且已经创建了所有容器。至少有一个容器在运行,或正在启动或重启 |
Suceeded | Pod中所有容器都已成功终止,不会重新启动 |
Failed | Pod中所有容器已终止,且至少有一个容器已在故障中终止,也就是说,容器要么已非零状态退出,要么被系统终止 |
Unknown | 由于某种原因apiserver无法获取Pod的状态,通常是由于master与pod所在主机kubelet通信时出错 |
故障排查命令
1 2 3 4 5 6 | #查看pod事件 kubectl describe TYPE / NAME #查看pod日志 kubectl logs TYPE / NAME #登录容器查看 kubectl exec POD [ - c CONTAINER] - - COMMAND [args...] |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
2018-03-04 Openstack使用NFS作为后端存储
2018-03-04 Openstack块存储cinder安装配置