
一、Pod 管理1. 查看 Pod的运行情况kubectl get pods -o wide这里kubectl操作 Kubernetesget pods查看 Pod-o wide显示更多信息例如NAME READY STATUS RESTARTS AGE IP NODE lee 1/1 Running 0 9s 10.244.1.3 k8s-node1重点看这几个字段含义NAMEPod 名称READY容器是否准备好1/1 表示 1 个容器全部正常STATUSPod 当前状态RESTARTS容器重启次数AGEPod 存活时间IPPod IPNODEPod 被调度到哪台节点所以lee 1/1 Running 0 9s 10.244.1.3 k8s-node1意思就是lee这个 Pod 有一个容器容器已经正常运行Pod IP 是10.244.1.3运行在k8s-node12.创建pod[rootk8s-master ~]# docker load -i nginx-1.26.tarLoaded image: nginx:1.26先拉镜像你是什么版本就用什么版本[rootk8s-master ~]# docker images | grep nginxnginx:1.26 41b194461e4b 279MB 75.2MB[rootk8s-master ~]# docker tag nginx:1.26 reg.timinglee.org/nginx/nginx:1.26[rootk8s-master ~]# docker images | grep nginxnginx:1.26 41b194461e4b 279MB 75.2MBreg.timinglee.org/nginx/nginx:1.26 41b194461e4b 279MB 75.2MB[rootk8s-master ~]# docker login reg.timinglee.org -u adminPassword:Login Succeeded[rootk8s-master ~]# docker push reg.timinglee.org/nginx/nginx:1.26The push refers to repository [reg.timinglee.org/nginx/nginx]6923759e66ab: Pushed8a628cdd7ccc: Pushed7a0654aeb922: Pushed5e98d206134b: Pushedd44088bb6ae8: Pushed9ebfb40fb06b: Pushed4fd410795c0f: Pushed1.26: digest: sha256:c8042489f41ddaf05b7dfbe1e32d5227f94f1b002aca8e3b7b9c9d0cee6b0fed size: 2293把镜像上传到 Harbor。最终 Harbor 中有reg.timinglee.org └── nginx └── nginx └── 1.26这样 Kubernetes 节点才能通过reg.timinglee.org/nginx/nginx:1.26去拉镜像并不意味着 node1、node2 也有这个镜像。所以把镜像放进 Harbor 后Pod 被调度到哪个节点那个节点就可以从 Harbor 拉Harbor ↑ ┌───────┴───────┐ │ │ node1 node2 ↑ ↑ Pod Pod3.kubectl run创建 Podkubectl run lee --imagereg.timinglee.org/nginx/nginx:1.26意思创建一个名字叫lee的 Pod使用 nginx 1.26 镜像。注意kubectl run创建的是最基本的 Pod。它没有 Deployment、ReplicaSet 这些控制器管理。所以kubectl delete pod lee删掉以后它就真的没了4.kubectl describe pod你这里kubectl describe pod error这个命令非常重要。可以把它理解成把这个 Pod 的详细档案全部打印出来。尤其是排错的时候。你这里最关键的是Node: k8s-node2/172.25.254.20说明error这个 Pod 被调度到了k8s-node2。然后Image: lee:v1说明它需要lee:v1这个镜像。但是最关键的是最后的 EventsFailed to pull image lee:v1: Error response from daemon: failed to resolve reference docker.io/library/lee:v1: docker.io/library/lee:v1: not found这句话就非常关键。5. 为什么lee:v1会去 Docker Hub执行kubectl run error --image lee:v1Kubernetes 看到lee:v1没有写仓库地址。所以它会把它理解成docker.io/library/lee:v1也就是Docker Hub ↓ library ↓ lee ↓ v1但是 Docker Hub 上没有这个镜像。所以ErrImagePull ↓ ImagePullBackOff6.ImagePullBackOff是什么意思ImagePullBackOff不是说 Kubernetes 本身挂了。意思是Kubernetes 拉取镜像失败并且正在进行退避重试。过程大概Pod 创建 ↓ 拉取镜像 ↓ 失败 ↓ ErrImagePull ↓ 等待一段时间 ↓ 重新拉取 ↓ 又失败 ↓ ImagePullBackOffBackOff就是失败以后不要疯狂重试等一会儿再试。7. Pod 为什么有 IP但还是 Pending这里Status: Pending IP: 10.244.2.3都有 IP 了为什么还是 Pending因为 Pod 的生命周期不是有 IP RunningPod 还要创建 Pod ↓ 分配 IP ↓ 拉镜像 ↓ 创建容器 ↓ 启动容器 ↓ Running情况是Pod 创建成功 ↓ 调度到 node2 ↓ 分配 10.244.2.3 ↓ 拉 lee:v1 ↓ 失败 ↓ Pending所以有 Pod IP 不代表容器已经成功运行。8. 为什么删除 Podkubectl delete pods error删除指定 Poderror或者kubectl delete pods --all删除当前 namespace 下的所有 Pod。因为前面都是直接创建的 Pod所以可以直接删。但是要特别注意如果 Pod 被 Deployment 管理例如Deployment ↓ ReplicaSet ↓ Pod你执行kubectl delete pod xxxPod 虽然被删除了但是 Deployment 会发现我明明需要 2 个 Pod 现在只剩 1 个于是马上再创建一个。所以直接创建的 Pod删除就是删除。Deployment 管理的 Pod删除 Pod控制器会重新创建二、利用控制器实现版本更替这里使用的是Deployment它主要解决Pod 数量控制Pod 自动创建Pod 故障自动恢复版本更新滚动更新版本回滚实验实际上是在做myapp:v1 ↓ Deployment ↓ 两个 Pod ↓ 访问业务 ↓ 升级 ↓ myapp:v2 ↓ 滚动更新 ↓ 回退 ↓ myapp:v11. 创建 Deployment 配置文件执行kubectl create deployment webcluster \ --imagereg.timinglee.org/library/myapp:v1 \ --replicas2 \ --dry-runclient \ -o yaml webcluster.yml这个命令可以拆成kubectl create deployment webcluster创建一个 Deployment名字叫webcluster--imagereg.timinglee.org/library/myapp:v1指定 Pod 使用的镜像。--replicas2意思我要 2 个 Pod。所以最终Deployment ↓ ReplicaSet ↓ ┌───────┴───────┐ ↓ ↓ Pod Pod v1 v1这个特别重要。--dry-runclient意思只生成配置不真正创建资源。所以kubectl create deployment ...本来会直接创建 Deployment。但是加上--dry-runclient以后不创建只把 YAML 生成出来。-o yaml让 Kubernetes 把结果按照 YAML 格式输出。然后 webcluster.yml把输出保存到webcluster.yml所以这一整条命令本质就是让 kubectl 帮我生成一个 Deployment YAML 文件2. 看 YAML核心内容apiVersion: apps/v1 kind: Deployment metadata: name: webcluster spec: replicas: 2 selector: matchLabels: app: webcluster template: metadata: labels: app: webcluster spec: containers: - image: myapp:v1 name: myapp这里最重要的是理解Deployment ↓ Pod模板 ↓ Pod3.replicas: 2replicas: 2表示始终保持 2 个符合条件的 Pod。比如Pod 1 Pod 2如果 Pod 1 挂了Pod 1 ❌ Pod 2 ✅Deployment 会发现实际 1 期望 2于是自动再创建一个Pod 1 ❌ Pod 2 ✅ Pod 3 ✅这就是控制器的核心作用。4.selector是干什么的selector: matchLabels: app: webcluster意思Deployment 通过appwebcluster这个标签寻找、管理自己的 Pod。所以 Pod 模板里面必须有labels: app: webcluster这两个要对应Deployment selector ↓ appwebcluster ↑ Pod labels appwebcluster否则 Deployment 就不知道哪些 Pod 是自己的。5.template是什么template:可以理解成Pod 模板。Deployment 并不是直接写pod1 pod2而是告诉 Kubernetes按照这个模板创建 Pod。例如template: spec: containers: - image: myapp:v1 name: myapp意思创建 Pod 的时候里面运行一个叫myapp的容器使用myapp:v1。所以最终Deployment webcluster ↓ Pod模板 ↓ ┌─────┴─────┐ ↓ ↓ Pod-1 Pod-2 myapp:v1 myapp:v16.kubectl apply -fkubectl apply -f webcluster.yml意思根据 YAML 文件创建/更新 Kubernetes 资源。于是webcluster.yml ↓ kubectl apply ↓ Deployment ↓ ReplicaSet ↓ 2个Pod输出deployment.apps/webcluster created说明 Deployment 创建成功。7. 为什么会出现两个 Pod因为replicas: 2所以kubectl get pods看到webcluster-xxxx Running webcluster-yyyy Running这两个 Pod 都属于Deployment webcluster实际上中间还有一个 ReplicaSetDeployment ↓ ReplicaSet ↓ Pod Pod这个层级一定要记住。8.rollout historykubectl rollout history deployment webcluster查看 Deployment 的版本历史。第一次REVISION 1表示当前 Deployment 的第一个版本。之后你把myapp:v1更新成myapp:v2就产生REVISION 1 REVISION 2所以你可以理解成Revision 1 myapp:v1 ↓ 更新 Revision 2 myapp:v29. 为什么要创建 Service执行kubectl expose deployment webcluster \ --port80 \ --target-port80 \ --typeNodePortDeployment 本身主要负责管理 Pod。但是客户端要访问 Pod还需要Service。所以客户端 ↓ Service ↓ Pod Pod10.--port80和--target-port80这里很容易混。--port80表示Service 对外提供的端口。--target-port80表示Service 把流量转发到 Pod 的 80 端口。所以客户端 ↓ Service:80 ↓ Pod:8011.NodePort是什么得到80:30976/TCP这里80是 Service Port。30976是 NodePort。所以你可以访问curl http://172.25.254.100:30976/流量大概是172.25.254.100:30976 ↓ NodePort ↓ Service :80 ↓ ┌─────┴─────┐ ↓ ↓ Pod1 Pod2 :80 :80所以你访问的是NodeIP:NodePort12、版本更新现在是整个实验的核心。执行kubectl set image deployment/webcluster \ myappreg.timinglee.org/library/myapp:v2意思修改 Deploymentwebcluster中名字叫myapp的容器把镜像从 v1 改成 v2。原来Deployment ↓ myapp:v1 ↓ Pod v1 Pod v1执行更新以后Deployment ↓ myapp:v2然后 Deployment 会启动滚动更新。13. 什么叫滚动更新不是两个 v1 全部删除 ↓ 再创建两个 v2而是逐步替换。大概开始 Pod1 v1 Pod2 v1 更新 Pod1 v1 Pod2 v1 Pod3 v2 继续 Pod1 v1 Pod3 v2 Pod4 v2 最终 Pod3 v2 Pod4 v2这样业务不会因为一次性删除所有旧 Pod 而直接中断。这就是Rolling Update滚动更新。14. 为什么更新之后 Pod 名字变了之前webcluster-74f44fdcd7-25s4w webcluster-74f44fdcd7-f2jvc更新以后webcluster-6c8b4bb9d7-hpxf7 webcluster-6c8b4bb9d7-kz46j因为 Deployment 的 Pod 模板发生了变化myapp:v1 ↓ myapp:v2因此 Deployment 创建了新的 ReplicaSet。可以理解成Deployment │ ├── ReplicaSet A │ ├── Pod v1 │ └── Pod v1 │ └── ReplicaSet B ├── Pod v2 └── Pod v2更新完成后ReplicaSet A Pod v1 Pod v1被缩减到 0。而ReplicaSet B Pod v2 Pod v2变成 2 个。15.rollout statuskubectl rollout status deployment/webcluster查看滚动更新是否完成。如果deployment webcluster successfully rolled out就是滚动更新已经完成。16. 再次查看 historykubectl rollout history deployment webcluster得到REVISION 1 2意思Revision 1 → v1 Revision 2 → v217、版本回退现在已经从v1 → v2升级成功。如果发现v2 有问题怎么办不需要重新写 YAML。直接kubectl rollout undo deployment webcluster --to-revision 1意思把 Deployment 回退到 Revision 1。也就是v2 ↓ 回退 ↓ v118. 为什么回退以后又出现新的 Pod回退并不是把原来的 Pod 原封不动拿回来。Deployment 会重新调整 ReplicaSet。可以理解为Revision 1 ↓ myapp:v1 Revision 2 ↓ myapp:v2执行rollout undo --to-revision 1以后Revision 1 的配置重新成为当前配置然后 Kubernetes 再通过 ReplicaSet 创建新的 v1 Pod。所以 Pod 名字仍然会变化。19. 为什么回退之后 history 是 2 和 3你这里REVISION 2 3第一次看到可能特别懵我明明回到 1 了为什么没有 1这是 Deployment Revision 的一个很重要的特点。你的过程实际上是第一次创建 Revision 1 v1 ↓ 更新 Revision 2 v2 ↓ 回滚 Revision 3 v1所以Revision 3实际上记录的是这次回滚操作产生的新 Deployment 状态。它不是说3 v3而是Revision 3 → 当前内容又变成 v1所以Revision 编号 ≠ 镜像版本号。这一点考试和面试都很容易问。20.总结Deployment │ ↓ ReplicaSet │ ┌──────┴──────┐ ↓ ↓ Pod Pod │ │ └──────┬──────┘ ↓ Service │ ↓ NodePort │ ↓ 客户端访问然后版本变化Deployment │ myapp:v1 ↓ ┌────────┴────────┐ ↓ ↓ Pod v1 Pod v1 ↓ set image v2 ↓ Deployment │ myapp:v2 ↓ ┌────────┴────────┐ ↓ ↓ Pod v2 Pod v2如果 v2 出问题myapp:v2 ↓ 出问题 ↓ rollout undo ↓ myapp:v1Pod 基本操作# 查看 Pod kubectl get pods -o wide # 查看 Pod 详细信息 kubectl describe pod Pod名称 # 删除指定 Pod kubectl delete pod Pod名称 # 删除所有 Pod kubectl delete pods --allDeployment# 创建 Deployment kubectl create deployment # 创建/更新 YAML kubectl apply -f webcluster.yml # 查看 Deployment kubectl get deployment # 查看版本历史 kubectl rollout history deployment webcluster # 更新镜像 kubectl set image deployment/webcluster myappmyapp:v2 # 查看更新进度 kubectl rollout status deployment/webcluster # 回滚 kubectl rollout undo deployment/webcluster --to-revision 1