一、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重点看这几个:
| 字段 | 含义 |
|---|---|
| NAME | Pod 名称 |
| READY | 容器是否准备好,1/1 表示 1 个容器全部正常 |
| STATUS | Pod 当前状态 |
| RESTARTS | 容器重启次数 |
| AGE | Pod 存活时间 |
| IP | Pod IP |
| NODE | Pod 被调度到哪台节点 |
所以:
lee 1/1 Running 0 9s 10.244.1.3 k8s-node1意思就是:
lee这个 Pod 有一个容器,容器已经正常运行,Pod IP 是10.244.1.3,运行在k8s-node1
2.创建pod
[root@k8s-master ~]# docker load -i nginx-1.26.tar
Loaded image: nginx:1.26
先拉镜像,你是什么版本就用什么版本
[root@k8s-master ~]# docker images | grep nginx
nginx:1.26 41b194461e4b 279MB 75.2MB
[root@k8s-master ~]# docker tag nginx:1.26 reg.timinglee.org/nginx/nginx:1.26
[root@k8s-master ~]# docker images | grep nginx
nginx:1.26 41b194461e4b 279MB 75.2MB
reg.timinglee.org/nginx/nginx:1.26 41b194461e4b 279MB 75.2MB
[root@k8s-master ~]# docker login reg.timinglee.org -u admin
Password:
Login Succeeded
[root@k8s-master ~]# docker push reg.timinglee.org/nginx/nginx:1.26
The push refers to repository [reg.timinglee.org/nginx/nginx]
6923759e66ab: Pushed
8a628cdd7ccc: Pushed
7a0654aeb922: Pushed
5e98d206134b: Pushed
d44088bb6ae8: Pushed
9ebfb40fb06b: Pushed
4fd410795c0f: Pushed
1.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创建 Pod
kubectl run lee --image=reg.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这个镜像。
但是最关键的是最后的 Events:
Failed 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. 为什么删除 Pod?
kubectl delete pods error删除指定 Pod:
error或者:
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 \ --image=reg.timinglee.org/library/myapp:v1 \ --replicas=2 \ --dry-run=client \ -o yaml > webcluster.yml这个命令可以拆成:
kubectl create deployment webcluster创建一个 Deployment,名字叫:
webcluster--image=reg.timinglee.org/library/myapp:v1指定 Pod 使用的镜像。
--replicas=2意思:
我要 2 个 Pod。
所以最终:
Deployment ↓ ReplicaSet ↓ ┌───────┴───────┐ ↓ ↓ Pod Pod v1 v1这个特别重要。
--dry-run=client意思:
只生成配置,不真正创建资源。
所以:
kubectl create deployment ...本来会直接创建 Deployment。
但是加上:
--dry-run=client以后:
不创建,只把 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: 2
replicas: 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 通过
app=webcluster这个标签寻找、管理自己的 Pod。
所以 Pod 模板里面必须有:
labels: app: webcluster这两个要对应:
Deployment selector ↓ app=webcluster ↑ Pod labels app=webcluster否则 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 -f
kubectl 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实际上中间还有一个 ReplicaSet:
Deployment ↓ ReplicaSet ↓ Pod Pod这个层级一定要记住。
8.rollout history
kubectl 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 \ --port=80 \ --target-port=80 \ --type=NodePortDeployment 本身主要负责:
管理 Pod。
但是客户端要访问 Pod,还需要:
Service。
所以:
客户端 ↓ Service ↓ Pod Pod10.--port=80和--target-port=80
这里很容易混。
--port=80表示:
Service 对外提供的端口。
--target-port=80表示:
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 \ myapp=reg.timinglee.org/library/myapp:v2意思:
修改 Deployment
webcluster中,名字叫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 status
kubectl rollout status deployment/webcluster查看滚动更新是否完成。
如果:
deployment "webcluster" successfully rolled out就是:
滚动更新已经完成。
16. 再次查看 history
kubectl 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 myapp=myapp:v2 # 查看更新进度 kubectl rollout status deployment/webcluster # 回滚 kubectl rollout undo deployment/webcluster --to-revision 1