(注:关于如何使用minikube创建集群,请参考 https://kubernetes.io/docs/tutorials/hello-minikube
。)
Kubernetes协调一个高可用(High Available, HA)计算机集群,每个计算机作为独立单元互相连接工作。Kubernetes中的“抽象”允许你将容器化的应用部署到集群,而无需将它们绑定到某个特定的计算机。为了使用这种新的部署模型,应用需要以“与特定主机解耦”的方式打包:它们需要被容器化。与过去的那种“直接以包的方式安装在特定主机,与主机深度集成”的部署模型相比,容器化应用更加灵活可用。Kubernetes以更高效的方式在集群里自动分发和调度应用容器。Kubernetes是一个开源平台,并且是“生产就绪”(production-ready)的。
Kubernetes集群由两种资源组成:
在Kubernetes部署应用时,你告知control plane启动应用容器,Control plane调度容器,将其运行在集群的node上。Node级别的组件,比如kubelet,通过Kubernetes API与control plane通信。用户也可以直接使用Kubernetes API与集群交互。
可通过deployment来部署容器化的应用。Deployment告知Kubernetes如何创建和升级应用实例。创建deployment后,control plane调度deployment里的应用实例,运行在集群的各个node上。
创建应用实例后,deployment控制器会持续监视那些实例。如果对应的node宕机或被删除,则deployment控制器会将该实例替换为另一个node上的实例。这就在机器故障或维修时,提供了一种“自愈”机制。
在编排机制出现前,经常使用安装脚本来启动应用,但它们无法做到从机器故障恢复。通过跨node的创建应用实例和保持实例运行,Kubernetes deployment提供了一种完全不同的应用管理方式。
创建deployment时,需要指定应用的image和副本数量。可以在之后通过更新deployment来改变这些信息。
kubectl
是Kubernetes的命令行工具,它通过Kubernetes API与集群交互。
用法:
kubectl <action> <resource>
比如:
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
minikube Ready control-plane 29h v1.28.3
查看帮助:
kubectl help <action>
kubectl <action> <resource> --help
创建deployment的命令是: kubectl create deployment
,比如:
kubectl create deployment kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1
注:如果访问不了 gcr.io
,可以事先把image push到docker.io里,然后指定docker.io的image,比如:
kubectl create deployment kubernetes-bootcamp --image=kaiding1/kubernetes-bootcamp:v1
该命令做了如下事情:
查看deployment:
$ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
kubernetes-bootcamp 1/1 1 1 4m38s
pod运行在一个私有的隔离网络里。默认情况下,它们只能被同一个集群里的其它pod和service可见,而不能在网络外可见。当我们使用 kubectl
时,是通过API endpoint交互来与应用通信的。
可用 kubectl proxy
命令创建一个代理,把通信转发到集群的私有网络里。
$ kubectl proxy
Starting to serve on 127.0.0.1:8001
现在,就可以通过 curl
命令来访问Kubernetes API,比如:
$ curl http://localhost:8001/version
{
"major": "1",
"minor": "28",
"gitVersion": "v1.28.3",
"gitCommit": "a8a1abc25cad87333840cd7d54be2efaf31a3177",
"gitTreeState": "clean",
"buildDate": "2023-10-18T11:33:18Z",
"goVersion": "go1.20.10",
"compiler": "gc",
"platform": "linux/amd64"
}
API server会基于pod名字,自动为每个pod创建一个endpoint。
首先获取pod名字:
$ kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}'
kubernetes-bootcamp-5d5df887b5-zjcdl
注意:如果有多个pod,会返回多行。
$ curl http://localhost:8001/api/v1/namespaces/default/pods/kubernetes-bootcamp-5d5df887b5-zjcdl
......
......
注:这里的输出结果是应用的元数据,并不包含应用本身的逻辑。
Pod是Kubernetes的一种资源抽象,代表单个或多个应用容器(比如Docker)的一个分组,以及这些容器的共享资源。这些资源包括:
Pod是针对应用的“逻辑主机”模型。一个Pod可以包含不同的应用容器,这些容器之间是相对紧耦合的。Pod里的容器共享地址和端口空间,始终共同定位,共同调度,运行在同一个node上。
Pod是Kubernetes平台上的原子单位。在创建deployment时,该deployment会创建包含容器的pod(而不是直接创建容器)。每个pod被绑定在其被调度的node上,直到被终结(基于重启策略)或删除。若出现node故障,相同的pod会被调度在其它可用的node上。
Node是Kubernetes里的工作机器。一个node可以有多个pod,control plane会自动处理跨node的pod调度。自动调度会考虑到每个node上的可用资源。
一个node至少包含:
kubectl
常见用法:
kubectl get
:列出资源kubectl describe
:描述某个资源的详细信息kubectl logs
:打印pod里容器的日志kubectl exec
:在pod容器里执行命令例如:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
kubernetes-bootcamp-5d5df887b5-zjcdl 1/1 Running 0 48m
$ kubectl describe pod kubernetes-bootcamp-5d5df887b5-zjcdl
Name: kubernetes-bootcamp-5d5df887b5-zjcdl
Namespace: default
Priority: 0
Service Account: default
Node: minikube/192.168.49.2
Start Time: Sat, 20 Jan 2024 11:25:46 +0800
Labels: app=kubernetes-bootcamp
pod-template-hash=5d5df887b5
Annotations: <none>
Status: Running
IP: 10.244.0.43
......
通过 kubectl proxy
创建代理后,可以访问应用:
$ curl http://localhost:8001/api/v1/namespaces/default/pods/kubernetes-bootcamp-5d5df887b5-zjcdl:8080/proxy/
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5d5df887b5-zjcdl | v=1
注意URL里最后的 /
不能省略。
这里的输出结果是应用本身的逻辑,注意前面 curl http://localhost:8001/api/v1/namespaces/default/pods/kubernetes-bootcamp-5d5df887b5-zjcdl
的结果不包含应用本身逻辑。
$ kubectl logs kubernetes-bootcamp-5d5df887b5-zjcdl
Kubernetes Bootcamp App Started At: 2024-01-20T03:26:09.823Z | Running On: kubernetes-bootcamp-5d5df887b5-zjcdl
Running On: kubernetes-bootcamp-5d5df887b5-zjcdl | Total Requests: 1 | App Uptime: 3210.267 seconds | Log Time: 2024-01-20T04:19:40.090Z
Running On: kubernetes-bootcamp-5d5df887b5-zjcdl | Total Requests: 2 | App Uptime: 3229.445 seconds | Log Time: 2024-01-20T04:19:59.268Z
Running On: kubernetes-bootcamp-5d5df887b5-zjcdl | Total Requests: 3 | App Uptime: 3394.623 seconds | Log Time: 2024-01-20T04:22:44.446Z
应用的标准输出(stdout)被包含在Pod的容器log里。
注:此处只指定了pod,没有指定容器,是因为该pod里只有一个容器。
打印容器的环境变量:
$ kubectl exec kubernetes-bootcamp-5d5df887b5-zjcdl -- env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=kubernetes-bootcamp-5d5df887b5-zjcdl
......
同样,此处只指定了pod,没有指定容器,是因为该pod里只有一个容器。
进入容器:
$ kubectl exec -ti kubernetes-bootcamp-5d5df887b5-zjcdl -- bash
root@kubernetes-bootcamp-5d5df887b5-zjcdl:/#
在容器里,访问本机的8080端口:
root@kubernetes-bootcamp-5d5df887b5-zjcdl:/# curl http://localhost:8080
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5d5df887b5-zjcdl | v=1
操作完成后,输入 exit
退出容器。
Pod是有生命周期的。当node宕机时,node上运行的pod也会丢失。然后ReplicaSet会创建新的pod,把集群带回期望的状态,以保持应用的运行。另一个例子是,一个图像处理的后端有3个副本。前端不应关心后端的副本,甚至也不关心pod是否丢失被重建。每个pod都有唯一的IP地址,即便是同一node上的pod,IP地址也各不相同,所以,集群需要能够自动调和(reconcile)pod的变化,以便应用保持运行。
Service是Kubernetes的一种抽象资源,定义了pod的逻辑集合以及访问策略。Service带来了相关pod之间的松耦合。像其它Kubernetes对象manifest一样,可用YAML或JSON来定义service。通常,由label selector来决定pod集合。
虽然每个pod都有唯一的IP地址,但这些IP并没有暴露在集群外部。通过service spec
里的 type
值,service可使用不同的方式来暴露:
ClusterIP
(默认):在集群的内部IP上暴露service,只能从集群内访问。NodePort
:顾名思义,就是node端口。在集群里使用NAT,在node的相同端口上暴露service。在集群外部可通过 <NodeIP>:<NodePort>
访问service。是ClusterIP的超集。LoadBalancer
:在当前云中创建一个外部的负载均衡器(如果支持的话),并为service分配一个固定的外部IP。是NodePort的超集。ExternalName
:通过返回带有该名称的 CNAME
记录和其值来,把service映射到 externalName
字段的内容(例如 foo.bar.example.com
)。无需建立任何代理。这种类型需要 kube-dns
v1.7或更高版本,或者CoreDNS 0.8或更高版本。此外,注意在有些用例里,service没有在其 spec
下定义 selector
,也就不会创建相应的endpoint对象。用户需要手工映射service到特定的endpoint。另一种没有selector的可能性是严格使用 type: ExternalName
。
Service使用label和selector来匹配pod集合,它们是允许对Kubernetes对象进行逻辑操作的分组原语(primitive)。Label是对象上的键/值对,可用于:
Label可以在创建对象时添加,或者以后再添加,也可以随时修改。
创建service:
$ kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080
service/kubernetes-bootcamp exposed
查看service:
$ kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 24h
kubernetes-bootcamp NodePort 10.102.243.158 <none> 8080:31507/TCP 27s
查看service kubernetes-bootcamp
:
$ kubectl describe services/kubernetes-bootcamp
Name: kubernetes-bootcamp
Namespace: default
Labels: app=kubernetes-bootcamp
Annotations: <none>
Selector: app=kubernetes-bootcamp
Type: NodePort
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.102.243.158
IPs: 10.102.243.158
Port: <unset> 8080/TCP
TargetPort: 8080/TCP
NodePort: <unset> 31507/TCP
Endpoints: 10.244.0.48:8080
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>
可见,对外开放的端口是31507(对于 NodePort
service)。
也可以通过下面的方法查看端口:
$ kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort}}'
31507
现在我们就可以通过node的IP地址和暴露的端口访问应用:
$ curl http://"$(minikube ip):31507"
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5d5df887b5-zjcdl | v=1
注: minikube ip
可查看minikube的IP地址,在本例中是 192.168.49.2
。
注:minikube只有一个node,所以minikube的IP地址就是node的IP地址。
kubectl describe deployment kubernetes-bootcamp
Name: kubernetes-bootcamp
Namespace: default
CreationTimestamp: Sat, 20 Jan 2024 11:25:46 +0800
Labels: app=kubernetes-bootcamp
......
通过label过滤pod:
$ kubectl get pods -l app=kubernetes-bootcamp
NAME READY STATUS RESTARTS AGE
kubernetes-bootcamp-5d5df887b5-zjcdl 1/1 Running 1 (11m ago) 4h36m
同理,可通过label过滤service:
$ kubectl get services -l app=kubernetes-bootcamp
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes-bootcamp NodePort 10.102.243.158 <none> 8080:31507/TCP 8m6s
给pod加上 version=v1
的label:
$ kubectl label pod kubernetes-bootcamp-5d5df887b5-zjcdl version=v1
pod/kubernetes-bootcamp-5d5df887b5-zjcdl labeled
查看该pod:
$ kubectl describe pod kubernetes-bootcamp-5d5df887b5-zjcdl
Name: kubernetes-bootcamp-5d5df887b5-zjcdl
Namespace: default
Priority: 0
Service Account: default
Node: minikube/192.168.49.2
Start Time: Sat, 20 Jan 2024 11:25:46 +0800
Labels: app=kubernetes-bootcamp
pod-template-hash=5d5df887b5
version=v1
......
可以看到新添加的label version=v1
。
用新label来过滤pod:
$ kubectl get pods -l version=v1
NAME READY STATUS RESTARTS AGE
kubernetes-bootcamp-5d5df887b5-zjcdl 1/1 Running 1 (16m ago) 4h41m
删除service:
$ kubectl delete service -l app=kubernetes-bootcamp
service "kubernetes-bootcamp" deleted
确认删除:
$ kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 24h
此时,再次访问31507端口就会失败:
$ curl http://"$(minikube ip):31507"
curl: (7) Failed to connect to 192.168.49.2 port 31507: Connection refused
Service被删了,而实际上容器里的应用还在运行:
$ kubectl exec -ti kubernetes-bootcamp-5d5df887b5-zjcdl -- curl http://localhost:8080
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5d5df887b5-zjcdl | v=1
前面的deployment,只创建了一个pod来运行应用。当流量增长/减少时,可能就需要伸缩(scale)应用。
Scale是通过改变deployment的副本数量来实现的。
横向扩容(scale out)将会创建新的pod,并将其调度到node上。Kubernetes也支持自动伸缩(autoscaling)。可以伸缩到“0”,这将终结deployment里所有的pod。
要运行一个多实例的应用,就需要分发流量。Service有一个集成的负载均衡器,会把网络流量分发到所有pod。Service会通过endpoint持续监视pod运行,以确保流量只会被发送到可用的pod上。
在scale之前,先查看一下deployment:
$ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
kubernetes-bootcamp 1/1 1 1 5h17m
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
kubernetes-bootcamp-5d5df887b5 1 1 1 5h18m
注: rs
是 ReplicaSet
的缩写。
现在,我们把deployment扩容到4个副本:
$ kubectl scale deployments/kubernetes-bootcamp --replicas=4
deployment.apps/kubernetes-bootcamp scaled
再次查看deployment:
$ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
kubernetes-bootcamp 4/4 4 4 5h21m
查看pod:
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kubernetes-bootcamp-5d5df887b5-9xlhf 1/1 Running 0 72s 10.244.0.52 minikube <none> <none>
kubernetes-bootcamp-5d5df887b5-cg8qh 1/1 Running 0 72s 10.244.0.50 minikube <none> <none>
kubernetes-bootcamp-5d5df887b5-ghw56 1/1 Running 0 72s 10.244.0.51 minikube <none> <none>
kubernetes-bootcamp-5d5df887b5-zjcdl 1/1 Running 1 (56m ago) 5h21m 10.244.0.48 minikube <none> <none>
可见,4个pod有各自不同的IP地址。
查看deployment kubernetes-bootcamp
:
$ kubectl describe deployments/kubernetes-bootcamp
......
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 2m23s deployment-controller Scaled up replica set kubernetes-bootcamp-5d5df887b5 to 4 from 1
如果刚才把service删了,现在重新创建service:
kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080
查看service kubernetes-bootcamp
:
$ kubectl describe services/kubernetes-bootcamp
Name: kubernetes-bootcamp
Namespace: default
Labels: app=kubernetes-bootcamp
Annotations: <none>
Selector: app=kubernetes-bootcamp
Type: NodePort
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.107.156.4
IPs: 10.107.156.4
Port: <unset> 8080/TCP
TargetPort: 8080/TCP
NodePort: <unset> 31290/TCP
Endpoints: 10.244.0.53:8080,10.244.0.54:8080,10.244.0.56:8080 + 1 more...
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>
获取service端口:
$ kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort}}'
31290
多次通过该端口访问应用:
[ding@192 ~]$ curl http://"$(minikube ip):31290"
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5d5df887b5-9xlhf | v=1
[ding@192 ~]$ curl http://"$(minikube ip):31290"
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5d5df887b5-zjcdl | v=1
[ding@192 ~]$ curl http://"$(minikube ip):31290"
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5d5df887b5-ghw56 | v=1
[ding@192 ~]$ curl http://"$(minikube ip):31290"
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5d5df887b5-zjcdl | v=1
可见,每次处理请求的pod可能都不同。
缩容(scale down):
$ kubectl scale deployments/kubernetes-bootcamp --replicas=2
deployment.apps/kubernetes-bootcamp scaled
查看deployment:
$ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
kubernetes-bootcamp 2/2 2 2 5h33m
查看pod:
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kubernetes-bootcamp-5d5df887b5-cg8qh 1/1 Running 1 (7m49s ago) 13m 10.244.0.58 minikube <none> <none>
kubernetes-bootcamp-5d5df887b5-ghw56 1/1 Running 1 (7m49s ago) 13m 10.244.0.53 minikube <none> <none>
滚动更新(rolling update) 实现了以零宕机时间(zero down-time)来更新deployment。它渐进式的把现有pod替换为新pod。
默认情况下,在升级过程中,不可用pod的最大数量是1,能创建新pod的最大数量也是1。这两项都可以通过数值或者百分比来配置。更新是有版本控制的,可以回退到之前的稳定版本。
Rolling update允许以下行为:
为了更好的演示滚动更新,把deployment scale out为4个副本:
$ kubectl scale deployments/kubernetes-bootcamp --replicas=4
deployment.apps/kubernetes-bootcamp scaled
查看deployment和pod:
$ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
kubernetes-bootcamp 4/4 4 4 3m22s
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
kubernetes-bootcamp-5d5df887b5-22n8b 1/1 Running 0 89s
kubernetes-bootcamp-5d5df887b5-5gc2k 1/1 Running 0 89s
kubernetes-bootcamp-5d5df887b5-84vj2 1/1 Running 0 89s
kubernetes-bootcamp-5d5df887b5-wvrqf 1/1 Running 0 3m41s
$ kubectl describe pod kubernetes-bootcamp-5d5df887b5-22n8b
......
Image: kaiding1/kubernetes-bootcamp:v1
......
可见,现在使用的image是 kaiding1/kubernetes-bootcamp:v1
。
使用 kubectl set image
命令升级应用:
$ kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=jocatalin/kubernetes-bootcamp:v2
deployment.apps/kubernetes-bootcamp image updated
查看pod:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
kubernetes-bootcamp-5d5df887b5-22n8b 1/1 Terminating 0 3m41s
kubernetes-bootcamp-5d5df887b5-5gc2k 1/1 Terminating 0 3m41s
kubernetes-bootcamp-5d5df887b5-84vj2 1/1 Terminating 0 3m41s
kubernetes-bootcamp-5d5df887b5-wvrqf 1/1 Terminating 0 5m53s
kubernetes-bootcamp-65df967b7f-8fs97 1/1 Running 0 6s
kubernetes-bootcamp-65df967b7f-9sv8b 1/1 Running 0 7s
kubernetes-bootcamp-65df967b7f-b7jfr 1/1 Running 0 7s
kubernetes-bootcamp-65df967b7f-mbcvj 1/1 Running 0 6s
过一会儿,再次查看pod:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
kubernetes-bootcamp-65df967b7f-8fs97 1/1 Running 0 69s
kubernetes-bootcamp-65df967b7f-9sv8b 1/1 Running 0 70s
kubernetes-bootcamp-65df967b7f-b7jfr 1/1 Running 0 70s
kubernetes-bootcamp-65df967b7f-mbcvj 1/1 Running 0 69s
可见,已经完成升级。
查看service:
$ kubectl describe services/kubernetes-bootcamp
Name: kubernetes-bootcamp
Namespace: default
Labels: app=kubernetes-bootcamp
Annotations: <none>
Selector: app=kubernetes-bootcamp
Type: NodePort
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.109.170.65
IPs: 10.109.170.65
Port: <unset> 8080/TCP
TargetPort: 8080/TCP
NodePort: <unset> 32265/TCP
Endpoints: 10.244.0.72:8080,10.244.0.73:8080,10.244.0.74:8080 + 1 more...
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>
$ kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort}}'
32265
注:端口跟之前相比有变化,是因为重新创建过。
访问应用:
$ curl http://"$(minikube ip):32265"
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-65df967b7f-mbcvj | v=2
可见,版本升级了。
再运行一次,可能就是不同的pod:
$ curl http://"$(minikube ip):32265"
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-65df967b7f-8fs97 | v=2
查看更新状态:
$ kubectl rollout status deployments/kubernetes-bootcamp
deployment "kubernetes-bootcamp" successfully rolled out
查看pod kubernetes-bootcamp-65df967b7f-8fs97
:
$ kubectl describe pod kubernetes-bootcamp-65df967b7f-8fs97
......
Image: jocatalin/kubernetes-bootcamp:v2
......
可见,现在的image是 jocatalin/kubernetes-bootcamp:v2
。
接下来,我们来尝试升级到一个不存在的版本。
$ kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=kaiding1/kubernetes-bootcamp:v10
deployment.apps/kubernetes-bootcamp image updated
查看deployment:
$ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
kubernetes-bootcamp 3/4 2 3 13m
查看pod:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
kubernetes-bootcamp-65df967b7f-9sv8b 1/1 Running 0 7m52s
kubernetes-bootcamp-65df967b7f-b7jfr 1/1 Running 0 7m52s
kubernetes-bootcamp-65df967b7f-mbcvj 1/1 Running 0 7m51s
kubernetes-bootcamp-7645d7c7fc-d5gfg 0/1 ImagePullBackOff 0 59s
kubernetes-bootcamp-7645d7c7fc-fgcr8 0/1 ImagePullBackOff 0 59s
查看pod kubernetes-bootcamp-7645d7c7fc-d5gfg
:
$ kubectl describe pod kubernetes-bootcamp-7645d7c7fc-d5gfg
......
Status: Pending
......
Image: kaiding1/kubernetes-bootcamp:v10
......
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 3m3s default-scheduler Successfully assigned default/kubernetes-bootcamp-7645d7c7fc-d5gfg to minikube
Normal Pulling 72s (x4 over 3m3s) kubelet Pulling image "kaiding1/kubernetes-bootcamp:v10"
Warning Failed 69s (x4 over 2m56s) kubelet Failed to pull image "kaiding1/kubernetes-bootcamp:v10": Error response from daemon: manifest for kaiding1/kubernetes-bootcamp:v10 not found: manifest unknown: manifest unknown
Warning Failed 69s (x4 over 2m56s) kubelet Error: ErrImagePull
Warning Failed 56s (x6 over 2m56s) kubelet Error: ImagePullBackOff
Normal BackOff 44s (x7 over 2m56s) kubelet Back-off pulling image "kaiding1/kubernetes-bootcamp:v10"
升级失败,回滚:
$ kubectl rollout undo deployments/kubernetes-bootcamp
deployment.apps/kubernetes-bootcamp rolled back
kubectl rollout undo
命令把deployment回退到先前的已知状态。
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
kubernetes-bootcamp-65df967b7f-9sv8b 1/1 Running 0 11m
kubernetes-bootcamp-65df967b7f-b7jfr 1/1 Running 0 11m
kubernetes-bootcamp-65df967b7f-cm5v4 1/1 Running 0 6s
kubernetes-bootcamp-65df967b7f-mbcvj 1/1 Running 0 11m
注意 kubernetes-bootcamp-65df967b7f-cm5v4
是刚刚重新创建的。
$ kubectl describe pod kubernetes-bootcamp-65df967b7f-cm5v4
......
Image: jocatalin/kubernetes-bootcamp:v2
......
测试完毕,最后,删除deployment和service:
$ kubectl delete deployments/kubernetes-bootcamp services/kubernetes-bootcamp
deployment.apps "kubernetes-bootcamp" deleted
service "kubernetes-bootcamp" deleted
Pod会随deployment一起删除。
https://kubernetes.io/docs/tutorials/kubernetes-basics