Kubernetes基础

发布时间:2024年01月23日

环境

  • RHEL 9.3
  • Docker Community 24.0.7
  • minikube v1.32.0

基础

在这里插入图片描述

创建集群

(注:关于如何使用minikube创建集群,请参考 https://kubernetes.io/docs/tutorials/hello-minikube 。)

Kubernetes协调一个高可用(High Available, HA)计算机集群,每个计算机作为独立单元互相连接工作。Kubernetes中的“抽象”允许你将容器化的应用部署到集群,而无需将它们绑定到某个特定的计算机。为了使用这种新的部署模型,应用需要以“与特定主机解耦”的方式打包:它们需要被容器化。与过去的那种“直接以包的方式安装在特定主机,与主机深度集成”的部署模型相比,容器化应用更加灵活可用。Kubernetes以更高效的方式在集群里自动分发和调度应用容器。Kubernetes是一个开源平台,并且是“生产就绪”(production-ready)的。

Kubernetes集群由两种资源组成:

  • 控制面(Control Plane):管理、协调集群。
  • 节点(Node):运行应用。通过kubelet管理node并与control plane通信。Node里有操作容器的工具,比如Docker、Containerd、CRI-O。Kubernetes集群应该至少有3个node,因为如果一个node宕机了,etcd成员和control plane实例都会丢失,冗余性就会受影响。可通过添加更多的control plane node来降低该风险。

在这里插入图片描述

在Kubernetes部署应用时,你告知control plane启动应用容器,Control plane调度容器,将其运行在集群的node上。Node级别的组件,比如kubelet,通过Kubernetes API与control plane通信。用户也可以直接使用Kubernetes API与集群交互。

部署应用

deployment

可通过deployment来部署容器化的应用。Deployment告知Kubernetes如何创建和升级应用实例。创建deployment后,control plane调度deployment里的应用实例,运行在集群的各个node上。

创建应用实例后,deployment控制器会持续监视那些实例。如果对应的node宕机或被删除,则deployment控制器会将该实例替换为另一个node上的实例。这就在机器故障或维修时,提供了一种“自愈”机制。

在编排机制出现前,经常使用安装脚本来启动应用,但它们无法做到从机器故障恢复。通过跨node的创建应用实例和保持实例运行,Kubernetes deployment提供了一种完全不同的应用管理方式。

在这里插入图片描述

创建deployment时,需要指定应用的image和副本数量。可以在之后通过更新deployment来改变这些信息。

kubectl

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

该命令做了如下事情:

  • 查找适合应用实例运行的node(minikube只有一个可用node)
  • 将应用调度到该node上运行
  • 配置集群,以便必要时在新的node上重新调度该实例

查看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

Pod是Kubernetes的一种资源抽象,代表单个或多个应用容器(比如Docker)的一个分组,以及这些容器的共享资源。这些资源包括:

  • 共享存储,作为volume
  • 网络,作为唯一的集群IP地址
  • 如何运行容器的信息,比如容器image版本或使用的特定端口

Pod是针对应用的“逻辑主机”模型。一个Pod可以包含不同的应用容器,这些容器之间是相对紧耦合的。Pod里的容器共享地址和端口空间,始终共同定位,共同调度,运行在同一个node上。

Pod是Kubernetes平台上的原子单位。在创建deployment时,该deployment会创建包含容器的pod(而不是直接创建容器)。每个pod被绑定在其被调度的node上,直到被终结(基于重启策略)或删除。若出现node故障,相同的pod会被调度在其它可用的node上。

在这里插入图片描述

Node

Node是Kubernetes里的工作机器。一个node可以有多个pod,control plane会自动处理跨node的pod调度。自动调度会考虑到每个node上的可用资源。

一个node至少包含:

  • kubelet:与control plane通信,管理pod和容器。
  • 容器runtime(比如Docker):负责pull image,解包容器,运行应用。

在这里插入图片描述

Troubleshooting

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是对象上的键/值对,可用于:

  • 指定对象是用于开发、测试、还是生产
  • 嵌入版本tag
  • 通过tag把对象分类

在这里插入图片描述

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

注: rsReplicaSet 的缩写。

现在,我们把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允许以下行为:

  • 将应用从一个环境升级到另一个环境(通过容器image更新)
  • 回滚到以前的版本
  • 持续集成和持续交付(Continuous Integration and Continuous Delivery,CICD),零宕机时间

为了更好的演示滚动更新,把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
文章来源:https://blog.csdn.net/duke_ding2/article/details/135711704
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。