Kubernetes入门与实战:01

1、Kubernetes基本概览

  由于Kubernetes每年三四个版本发布,官网永远是最权威的;话不多说,先提供官网地址:https://kubernetes.io/zh/docs/tutorials/kubernetes-basics/

1.1、集群与节点

  • 查看master主键角色:
1 [root@master1 ~]# kubectl get componentstatuses         #  也可以使用简写: kubectl get cs
2 Warning: v1 ComponentStatus is deprecated in v1.19+
3 NAME                 STATUS      MESSAGE                                                                                       ERROR
4 scheduler            Unhealthy   Get "http://127.0.0.1:10251/healthz": dial tcp 127.0.0.1:10251: connect: connection refused   
5 controller-manager   Healthy     ok                                                                                            
6 etcd-0               Healthy     {"health":"true","reason":""}                                                                 
7 [root@master1 ~]#
  • 查看node节点列表:
1 [root@master1 ~]# kubectl get nodes -o wide          #  也可以使用简写: kubectl get no
2 NAME      STATUS   ROLES                  AGE   VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE         KERNEL-VERSION          CONTAINER-RUNTIME
3 master1   Ready    control-plane,master   44h   v1.22.2   192.168.1.66   <none>        CentOS Linux 8   4.18.0-240.el8.x86_64   docker://20.10.8
4 node1     Ready    <none>                 44h   v1.22.2   192.168.1.77   <none>        CentOS Linux 8   4.18.0-240.el8.x86_64   docker://20.10.8
5 node2     Ready    <none>                 44h   v1.22.2   192.168.1.88   <none>        CentOS Linux 8   4.18.0-240.el8.x86_64   docker://20.10.8
6 [root@master1 ~]# 
  • 查看node节点详情:
 1 [root@master1 ~]# kubectl describe nodes node2
 2 Name:               node2
 3 Roles:              <none>
 4 Labels:             beta.kubernetes.io/arch=amd64
 5                     beta.kubernetes.io/os=linux
 6                     kubernetes.io/arch=amd64
 7                     kubernetes.io/hostname=node2
 8                     kubernetes.io/os=linux
 9 Annotations:        flannel.alpha.coreos.com/backend-data: {"VNI":1,"VtepMAC":"be:68:4a:f9:ac:de"}
10                     flannel.alpha.coreos.com/backend-type: vxlan
11                     flannel.alpha.coreos.com/kube-subnet-manager: true
12                     flannel.alpha.coreos.com/public-ip: 192.168.1.88
13                     kubeadm.alpha.kubernetes.io/cri-socket: /var/run/dockershim.sock
14                     node.alpha.kubernetes.io/ttl: 0
15                     volumes.kubernetes.io/controller-managed-attach-detach: true
16 CreationTimestamp:  Fri, 01 Oct 2021 06:59:33 -0400
17 Taints:             <none>
18 Unschedulable:      false
19 Lease:
20   HolderIdentity:  node2
21   AcquireTime:     <unset>
22   RenewTime:       Sun, 03 Oct 2021 03:45:59 -0400
23 Conditions:
24   Type                 Status  LastHeartbeatTime                 LastTransitionTime                Reason                       Message
25   ----                 ------  -----------------                 ------------------                ------                       -------
26   NetworkUnavailable   False   Sun, 03 Oct 2021 02:47:43 -0400   Sun, 03 Oct 2021 02:47:43 -0400   FlannelIsUp                  Flannel is running on this node
27   MemoryPressure       False   Sun, 03 Oct 2021 03:42:49 -0400   Fri, 01 Oct 2021 06:59:33 -0400   KubeletHasSufficientMemory   kubelet has sufficient memory available
28   DiskPressure         False   Sun, 03 Oct 2021 03:42:49 -0400   Fri, 01 Oct 2021 06:59:33 -0400   KubeletHasNoDiskPressure     kubelet has no disk pressure
29   PIDPressure          False   Sun, 03 Oct 2021 03:42:49 -0400   Fri, 01 Oct 2021 06:59:33 -0400   KubeletHasSufficientPID      kubelet has sufficient PID available
30   Ready                True    Sun, 03 Oct 2021 03:42:49 -0400   Fri, 01 Oct 2021 07:03:54 -0400   KubeletReady                 kubelet is posting ready status
31 Addresses:        # 节点的IP地址和主机名
32   InternalIP:  192.168.1.88
33   Hostname:    node2
34 Capacity:        # 节点总资源
35   cpu:                2
36   ephemeral-storage:  17398Mi
37   hugepages-1Gi:      0
38   hugepages-2Mi:      0
39   memory:             1996236Ki
40   pods:               110
41 Allocatable:      # 节点可以分配的资源
42   cpu:                2
43   ephemeral-storage:  16418812697
44   hugepages-1Gi:      0
45   hugepages-2Mi:      0
46   memory:             1893836Ki
47   pods:               110
48 System Info:      # 系统的相关信息
49   Machine ID:                 fd49b99f63534bc9a6544ff2f1d68ef5
50   System UUID:                2a454d56-033c-c61e-c4f8-37b171f12218
51   Boot ID:                    c66bb70c-b358-4d60-b6f2-9f2cb49dad2e
52   Kernel Version:             4.18.0-240.el8.x86_64
53   OS Image:                   CentOS Linux 8
54   Operating System:           linux
55   Architecture:               amd64
56   Container Runtime Version:  docker://20.10.8
57   Kubelet Version:            v1.22.2          # kubelet版本
58   Kube-Proxy Version:         v1.22.2          # kube-proxy版本
59 PodCIDR:                      172.16.2.0/24      # pod网络
60 PodCIDRs:                     172.16.2.0/24
61 Non-terminated Pods:          (2 in total)       # 当前节点已经运行pod情况,及每个pod占用的资源情况 
62   Namespace                   Name                     CPU Requests  CPU Limits  Memory Requests  Memory Limits  Age
63   ---------                   ----                     ------------  ----------  ---------------  -------------  ---
64   kube-system                 kube-flannel-ds-zp785    100m (5%)     100m (5%)   50Mi (2%)        50Mi (2%)      44h
65   kube-system                 kube-proxy-s6ndp         0 (0%)        0 (0%)      0 (0%)           0 (0%)         53m
66 Allocated resources:    # 已分配资源情况
67   (Total limits may be over 100 percent, i.e., overcommitted.)
68   Resource           Requests   Limits
69   --------           --------   ------
70   cpu                100m (5%)  100m (5%)
71   memory             50Mi (2%)  50Mi (2%)
72   ephemeral-storage  0 (0%)     0 (0%)
73   hugepages-1Gi      0 (0%)     0 (0%)
74   hugepages-2Mi      0 (0%)     0 (0%)
75 Events:
76   Type    Reason                   Age                From     Message
77   ----    ------                   ----               ----     -------
78   Normal  Starting                 44h                kubelet  Starting kubelet.
79   Normal  NodeHasSufficientMemory  44h (x2 over 44h)  kubelet  Node node2 status is now: NodeHasSufficientMemory
80   Normal  NodeHasNoDiskPressure    44h (x2 over 44h)  kubelet  Node node2 status is now: NodeHasNoDiskPressure
81   Normal  NodeHasSufficientPID     44h (x2 over 44h)  kubelet  Node node2 status is now: NodeHasSufficientPID
82   Normal  NodeAllocatableEnforced  44h                kubelet  Updated Node Allocatable limit across pods
83   Normal  NodeReady                44h                kubelet  Node node2 status is now: NodeReady
84 [root@master1 ~]# 

 1.2、容器与应用

  kubernetes是容器编排引擎,其负责容器的调度,管理和容器的运行,但kubernetes调度最小单位并非是container,而是pod,pod中可包含多个container,通常集群中不会直接运行pod,而是通过各种工作负载的控制器如Deployments,ReplicaSets,DaemonSets的方式运行,为啥?因为控制器能够保证pod状态的一致性,正如官方所描述的一样“make sure the current state match to the desire state”,确保当前状态和预期的一致,简单来说就是pod异常了,控制器会在其他节点重建,确保集群当前运行的pod和预期设定的一致。

  • pod是kubernetes中运行的最小单元
  • pod中包含一个容器或者多个容器
  • pod不会单独使用,需要有工作负载来控制,如Deployments,StatefulSets,DaemonSets,CronJobs等

Pod概览:

   1.3、服务访问

  kubernetes中pod是实际运行的载体,pod依附于node中,node可能会出现故障,kubernetes的控制器如replicasets会在其他node上重新拉起一个pod,新的pod会分配一个新的IP;再者,应用部署时会包含多个副本replicas,如同个应用deployments部署了3个pod副本,pod相当于后端的Real Server,如何实现这三个应用访问呢?对于这种情况,我们一般会在Real Server前面加一个负载均衡Load Balancer,service就是pod的负载均衡调度器,service将动态的pod抽象为一个服务,应用程序直接访问service即可,service会自动将请求转发到后端的pod。负责service转发规则有两种机制:iptables和ipvs,iptables通过设置DNAT等规则实现负载均衡,ipvs通过ipvsadm设置转发规。

 Service 和 Label:

  根据服务不同的访问方式,service分为如下几种类型:ClusterIP,NodePort,LoadBalancer和_ExternalName,可通过type设置:

  • ClusterIP,集群内部互访,与DNS结合实现集群内部的服务发现;
  • NodePort,通过NAT将每个node节点暴露一个端口实现外部访问;
  • LoadBalancer,实现云厂商外部接入方式的接口,需要依赖云服务提供商实现具体技术细节,如腾讯云实现与CLB集成;
  • ExternalName,通过服务名字暴露服务名,当前可由ingress实现,将外部的请求以域名转发的形式转发到集群,需要依附具体的外部实现,如nginx,traefik,各大云计算厂商实现接入细节;

  pod是动态变化的,ip地址可能会变化(如node故障),副本数可能会变化,如应用扩展scale up,应用锁容scale down等,service如何识别到pod的动态变化呢?答案是labels,通过labels自动会过滤出某个应用的Endpoints,当pod变化时会自动更新Endpoints,不同的应用会有由不同的label组成。labels相关可以参考下 https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/

2、创建应用

  下面开始部署一个应用即deployments,kubernetes中包含各种workload如无状态话的Deployments,有状态化的StatefulSets,守护进程的DaemonSets,每种workload对应不同的应用场景,我们先以Deployments为例入门,其他workload均以此类似,一般而言,在kubernetes中部署应用均以yaml文件方式部署,对于初学者而言,编写yaml文件太冗长,不适合初学,我们先kubectl命令行方式实现API的接入。

2.1、创建两个副本的nginx的应用并查看是否处于:AVAILABLE状态:

1 [root@master1 ~]# kubectl create deployment demo-nginx --image=nginx:1.8.1 --replicas=2
2 deployment.apps/demo-nginx created
3 [root@master1 ~]# 
4 [root@master1 ~]# kubectl get deployments.apps 
5 NAME         READY   UP-TO-DATE   AVAILABLE   AGE
6 demo-nginx   2/2     2            2           59s
7 [root@master1 ~]# 

2.2、查看应用的详细信息,我们可以知道Deployments是通过ReplicaSets控制副本数的,由Replicaset控制pod数:

 1 [root@master1 ~]# kubectl describe deployments.apps demo-nginx 
 2 Name:                   demo-nginx
 3 Namespace:              default
 4 CreationTimestamp:      Sun, 03 Oct 2021 04:13:57 -0400
 5 Labels:                 app=demo-nginx  # 标签,后面的service选择的依据
 6 Annotations:            deployment.kubernetes.io/revision: 1
 7 Selector:               app=demo-nginx
 8 Replicas:               2 desired | 2 updated | 2 total | 2 available | 0 unavailable
 9 StrategyType:           RollingUpdate  # 滚动升级的策略
10 MinReadySeconds:        0
11 RollingUpdateStrategy:  25% max unavailable, 25% max surge
12 Pod Template:     # 容器应用模版,包含镜像,port,存储等     
13   Labels:  app=demo-nginx
14   Containers:
15    nginx:
16     Image:        nginx:1.8.1
17     Port:         <none>
18     Host Port:    <none>
19     Environment:  <none>
20     Mounts:       <none>
21   Volumes:        <none>
22 Conditions:
23   Type           Status  Reason
24   ----           ------  ------
25   Available      True    MinimumReplicasAvailable
26   Progressing    True    NewReplicaSetAvailable
27 OldReplicaSets:  <none>
28 NewReplicaSet:   demo-nginx-55ccc46db6 (2/2 replicas created)  # 控制器的名称
29 Events:
30   Type    Reason             Age   From                   Message
31   ----    ------             ----  ----                   -------
32   Normal  ScalingReplicaSet  78s   deployment-controller  Scaled up replica set demo-nginx-55ccc46db6 to 2
33 [root@master1 ~]# 

2.3、查看replicasets情况,通过查看可知replicasets副本控制器生成了两个pod:

 1 [root@master1 ~]# kubectl get replicasets.apps 
 2 NAME                    DESIRED   CURRENT   READY   AGE
 3 demo-nginx-55ccc46db6   2         2         2       112s
 4 [root@master1 ~]# 
 5 [root@master1 ~]# kubectl describe replicasets.apps demo-nginx-55ccc46db6 
 6 Name:           demo-nginx-55ccc46db6
 7 Namespace:      default
 8 Selector:       app=demo-nginx,pod-template-hash=55ccc46db6
 9 Labels:         app=demo-nginx
10                 pod-template-hash=55ccc46db6
11 Annotations:    deployment.kubernetes.io/desired-replicas: 2  # 滚动升级的信息,副本树,最大数,应用版本
12                 deployment.kubernetes.io/max-replicas: 3
13                 deployment.kubernetes.io/revision: 1
14 Controlled By:  Deployment/demo-nginx    # 控制器类型
15 Replicas:       2 current / 2 desired    # 当前和期望的pod数量
16 Pods Status:    2 Running / 0 Waiting / 0 Succeeded / 0 Failed
17 Pod Template:
18   Labels:  app=demo-nginx
19            pod-template-hash=55ccc46db6
20   Containers:
21    nginx:
22     Image:        nginx:1.8.1
23     Port:         <none>
24     Host Port:    <none>
25     Environment:  <none>
26     Mounts:       <none>
27   Volumes:        <none>
28 Events:      # 日志事件:生成了三个不同的pod
29   Type    Reason            Age   From                   Message
30   ----    ------            ----  ----                   -------
31   Normal  SuccessfulCreate  2m7s  replicaset-controller  Created pod: demo-nginx-55ccc46db6-lg4nz
32   Normal  SuccessfulCreate  2m7s  replicaset-controller  Created pod: demo-nginx-55ccc46db6-jmjkx
33 [root@master1 ~]# 

2.4、查看pod的情况,实际应用部署的载体,pod中部署了一个nginx的容器并分配了一个ip,可通过该ip直接访问应用:

 1 [root@master1 ~]# kubectl get pods -o wide       # 每个pod的名称前缀和上面的replicasets一样
 2 NAME                          READY   STATUS    RESTARTS   AGE   IP           NODE    NOMINATED NODE   READINESS GATES
 3 demo-nginx-55ccc46db6-jmjkx   1/1     Running   0          20m   172.16.2.4   node2   <none>           <none>
 4 demo-nginx-55ccc46db6-lg4nz   1/1     Running   0          20m   172.16.1.5   node1   <none>           <none>
 5 [root@master1 ~]# 
 6 [root@master1 ~]# kubectl describe pods demo-nginx-55ccc46db6-jmjkx 
 7 Name:         demo-nginx-55ccc46db6-jmjkx
 8 Namespace:    default
 9 Priority:     0
10 Node:         node2/192.168.1.88
11 Start Time:   Sun, 03 Oct 2021 04:13:57 -0400
12 Labels:       app=demo-nginx
13               pod-template-hash=55ccc46db6
14 Annotations:  <none>
15 Status:       Running
16 IP:           172.16.2.4  # pod的IP地址
17 IPs:
18   IP:           172.16.2.4
19 Controlled By:  ReplicaSet/demo-nginx-55ccc46db6
20 Containers:
21   nginx:
22     Container ID:   docker://430d6e35fb2bb8e4cce6d498591da05748592ad254182c19dc87e41fca951dfd
23     Image:          nginx:1.8.1
24     Image ID:       docker-pullable://nginx@sha256:9b3e9f189890ef9d6713c3384da3809731bdb0bff84e7b68da330ebadf533085
25     Port:           <none>
26     Host Port:      <none>
27     State:          Running
28       Started:      Sun, 03 Oct 2021 04:14:28 -0400
29     Ready:          True
30     Restart Count:  0
31     Environment:    <none>
32     Mounts:
33       /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-n2r59 (ro)
34 Conditions:
35   Type              Status
36   Initialized       True 
37   Ready             True 
38   ContainersReady   True 
39   PodScheduled      True 
40 Volumes:
41   kube-api-access-n2r59:
42     Type:                    Projected (a volume that contains injected data from multiple sources)
43     TokenExpirationSeconds:  3607
44     ConfigMapName:           kube-root-ca.crt
45     ConfigMapOptional:       <nil>
46     DownwardAPI:             true
47 QoS Class:                   BestEffort
48 Node-Selectors:              <none>
49 Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
50                              node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
51 Events:
52   Type    Reason     Age   From               Message
53   ----    ------     ----  ----               -------
54   Normal  Scheduled  21m   default-scheduler  Successfully assigned default/demo-nginx-55ccc46db6-jmjkx to node2
55   Normal  Pulling    21m   kubelet            Pulling image "nginx:1.8.1"
56   Normal  Pulled     21m   kubelet            Successfully pulled image "nginx:1.8.1" in 30.161859239s
57   Normal  Created    21m   kubelet            Created container nginx
58   Normal  Started    21m   kubelet            Started container nginx
59 [root@master1 ~]# 
60 [root@master1 ~]# curl 172.16.2.4  # 通过pod的IP地址直接访问
61 <!DOCTYPE html>
62 <html>
63 <head>
64 <title>Welcome to nginx!</title>
65 <style>
66     body {
67          35em;
68         margin: 0 auto;
69         font-family: Tahoma, Verdana, Arial, sans-serif;
70     }
71 </style>
72 </head>
73 <body>
74 <h1>Welcome to nginx!</h1>
75 <p>If you see this page, the nginx web server is successfully installed and
76 working. Further configuration is required.</p>
77 
78 <p>For online documentation and support please refer to
79 <a href="http://nginx.org/">nginx.org</a>.<br/>
80 Commercial support is available at
81 <a href="http://nginx.com/">nginx.com</a>.</p>
82 
83 <p><em>Thank you for using nginx.</em></p>
84 </body>
85 </html>
86 [root@master1 ~]# 

 3、访问应用

  kubernetes为每个pod都分配了一个ip地址,可通过该地址直接访问应用,相当于访问RS,但一个应用是一个整体,由多个副本数组成,需要依赖于service来实现应用的负载均衡,service我们探讨ClusterIP和NodePort的访问方式。

3.1、设置pod的内容,为了方便区分,我们将两个pod的nginx站点内容设置为不同,以观察通过各自的IP的访问效果:

 1 [root@master1 ~]# kubectl get pods -o wide
 2 NAME                          READY   STATUS    RESTARTS   AGE   IP           NODE    NOMINATED NODE   READINESS GATES
 3 demo-nginx-55ccc46db6-jmjkx   1/1     Running   0          35m   172.16.2.4   node2   <none>           <none>
 4 demo-nginx-55ccc46db6-lg4nz   1/1     Running   0          35m   172.16.1.5   node1   <none>           <none>
 5 [root@master1 ~]# 
 6 [root@master1 ~]# kubectl exec -it demo-nginx-55ccc46db6-jmjkx /bin/bash    # 修改网页内容为:nginx-web1
 7 kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
 8 root@demo-nginx-55ccc46db6-jmjkx:/# echo 'nginx-web1' > /usr/share/nginx/html/index.html 
 9 root@demo-nginx-55ccc46db6-jmjkx:/# exit
10 exit
11 [root@master1 ~]# kubectl exec -it demo-nginx-55ccc46db6-lg4nz /bin/bash    # 修改网页内容为:nginx-web2
12 kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
13 root@demo-nginx-55ccc46db6-lg4nz:/# echo 'nginx-web2' > /usr/share/nginx/html/index.html
14 root@demo-nginx-55ccc46db6-lg4nz:/# exit
15 exit
16 [root@master1 ~]# # 验证访问结果
17 [root@master1 ~]# curl http://172.16.2.4
18 nginx-web1
19 [root@master1 ~]# curl http://172.16.1.5
20 nginx-web2
21 [root@master1 ~]# 

3.2、通过ClusterIP访问

  通过pod的ip直接访问应用,对于单个pod的应用可以实现,对于多个副本replicas的应用则不符合要求,需要通过service来实现负载均衡,service需要设置不同的type,默认为ClusterIP即集群内部访问,如下通过expose子命令将服务暴露到service:

  • 暴露service,其中port表示代理监听端口,target-port代表是容器的端口,type设置的是service的类型,查看service的详情,可以看到service通过labels选择器selector自动将pod的ip生成endpoints
 1 [root@master1 ~]# kubectl expose deployment demo-nginx --port=80 --protocol=TCP --type ClusterIP
 2 service/demo-nginx exposed
 3 [root@master1 ~]# 
 4 [root@master1 ~]# kubectl get svc        # 查看service列表,显示有两个,kubernetes为默认集群创建的service
 5 NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
 6 demo-nginx   ClusterIP   10.96.199.219   <none>        80/TCP    15s
 7 kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP   46h
 8 [root@master1 ~]# 
 9 [root@master1 ~]# kubectl describe service demo-nginx     # 查看service详情,可以看到Labels的Seletor和前面Deployments设置一致,Endpoints将pod组成一个列表
10 Name:              demo-nginx
11 Namespace:         default
12 Labels:            app=demo-nginx
13 Annotations:       <none>
14 Selector:          app=demo-nginx
15 Type:              ClusterIP        # service类型为ClusterIP
16 IP Family Policy:  SingleStack
17 IP Families:       IPv4
18 IP:                10.96.199.219
19 IPs:               10.96.199.219
20 Port:              <unset>  80/TCP    # 服务端口,即ClusterIP对外访问的端口
21 TargetPort:        80/TCP
22 Endpoints:         172.16.1.5:80,172.16.2.4:80    # 访问后端地址列表
23 Session Affinity:  None        # 默认调度算法为:rr
24 Events:            <none>
25 [root@master1 ~]# 
26 [root@master1 ~]# kubectl get endpoints
27 NAME         ENDPOINTS                     AGE
28 demo-nginx   172.16.1.5:80,172.16.2.4:80   71s
29 kubernetes   192.168.1.66:6443             46h
30 [root@master1 ~]# 
31 [root@master1 ~]# kubectl describe endpoints demo-nginx 
32 Name:         demo-nginx
33 Namespace:    default
34 Labels:       app=demo-nginx
35 Annotations:  endpoints.kubernetes.io/last-change-trigger-time: 2021-10-03T08:59:17Z
36 Subsets:
37   Addresses:          172.16.1.5,172.16.2.4
38   NotReadyAddresses:  <none>
39   Ports:
40     Name     Port  Protocol
41     ----     ----  --------
42     <unset>  80    TCP
43 
44 Events:  <none>
45 [root@master1 ~]# 
  • 通过service访问服务,默认的调度算法是:rr;同时可以通过ipvsadm命令检查相关调度的详情:
 1 [root@master1 ~]# kubectl get service
 2 NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
 3 demo-nginx   ClusterIP   10.96.199.219   <none>        80/TCP    6m52s
 4 kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP   46h
 5 [root@master1 ~]# 
 6 [root@master1 ~]# curl http://10.96.199.219
 7 nginx-web1
 8 [root@master1 ~]# curl http://10.96.199.219
 9 nginx-web2
10 [root@master1 ~]# curl http://10.96.199.219
11 nginx-web1
12 [root@master1 ~]# curl http://10.96.199.219
13 nginx-web2
14 [root@master1 ~]# 
15 [root@master1 ~]# kubectl get pods -o wide
16 NAME                          READY   STATUS    RESTARTS   AGE   IP           NODE    NOMINATED NODE   READINESS GATES
17 demo-nginx-55ccc46db6-jmjkx   1/1     Running   0          52m   172.16.2.4   node2   <none>           <none>
18 demo-nginx-55ccc46db6-lg4nz   1/1     Running   0          52m   172.16.1.5   node1   <none>           <none>
19 [root@master1 ~]# 
20 [root@master1 ~]# ipvsadm -ln
21 IP Virtual Server version 1.2.1 (size=4096)
22 Prot LocalAddress:Port Scheduler Flags
23   -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
24 TCP  10.96.0.1:443 rr
25   -> 192.168.1.66:6443            Masq    1      0          0         
26 TCP  10.96.0.10:53 rr
27   -> 172.16.0.4:53                Masq    1      0          0         
28   -> 172.16.0.5:53                Masq    1      0          0         
29 TCP  10.96.0.10:9153 rr
30   -> 172.16.0.4:9153              Masq    1      0          0         
31   -> 172.16.0.5:9153              Masq    1      0          0         
32 TCP  10.96.199.219:80 rr      # 通过ipvsadm命令可以很清晰的看到想情况,包括上面访问了四次,两台服务器上各有两次访问
33   -> 172.16.1.5:80                Masq    1      0          2         
34   -> 172.16.2.4:80                Masq    1      0          2         
35 UDP  10.96.0.10:53 rr
36   -> 172.16.0.4:53                Masq    1      0          0         
37   -> 172.16.0.5:53                Masq    1      0          0         
38 [root@master1 ~]# 

 3.3、通过NodePort访问

  Service通过ClusterIP只能提供集群内部的应用访问,外部无法直接访问应用,如果需要外部访问有如下几种方式:NodePort,LoadBalancer和Ingress,其中LoadBalancer需要由云服务提供商实现,Ingress需要安装单独的Ingress Controller,日常测试可以通过NodePort的方式实现,NodePort可以将node的某个端口暴露给外部网络访问。

  • 修改type的类型由ClusterIP修改为NodePort类型(或者重新创建,指定type的类型为NodePort),并验证访问结果(包括原来的service的地址是否可以访问)
 1 [root@master1 ~]# kubectl get service demo-nginx -o yaml
 2 apiVersion: v1
 3 kind: Service
 4 metadata:
 5   creationTimestamp: "2021-10-03T08:59:17Z"
 6   labels:
 7     app: demo-nginx
 8   name: demo-nginx
 9   namespace: default
10   resourceVersion: "13905"
11   uid: 148f6bc4-963c-4751-a733-02fd8a88c0bc
12 spec:
13   clusterIP: 10.96.199.219
14   clusterIPs:
15   - 10.96.199.219
16   internalTrafficPolicy: Cluster
17   ipFamilies:
18   - IPv4
19   ipFamilyPolicy: SingleStack
20   ports:
21   - port: 80
22     protocol: TCP
23     targetPort: 80
24   selector:
25     app: demo-nginx
26   sessionAffinity: None
27   type: ClusterIP    # 修改前
28 status:
29   loadBalancer: {}
30 [root@master1 ~]# 
31 [root@master1 ~]# kubectl patch service demo-nginx -p '{"spec":{"type":"NodePort"}}'        # 你也可以直接使用:kubectl edit service demo-nginx 直接修改
32 service/demo-nginx patched
33 [root@master1 ~]# 
34 [root@master1 ~]# kubectl get service demo-nginx -o yaml
35 apiVersion: v1
36 kind: Service
37 metadata:
38   creationTimestamp: "2021-10-03T08:59:17Z"
39   labels:
40     app: demo-nginx
41   name: demo-nginx
42   namespace: default
43   resourceVersion: "15278"
44   uid: 148f6bc4-963c-4751-a733-02fd8a88c0bc
45 spec:
46   clusterIP: 10.96.199.219
47   clusterIPs:
48   - 10.96.199.219
49   externalTrafficPolicy: Cluster
50   internalTrafficPolicy: Cluster
51   ipFamilies:
52   - IPv4
53   ipFamilyPolicy: SingleStack
54   ports:
55   - nodePort: 32638
56     port: 80
57     protocol: TCP
58     targetPort: 80
59   selector:
60     app: demo-nginx
61   sessionAffinity: None
62   type: NodePort    # 修改后
63 status:
64   loadBalancer: {}
65 [root@master1 ~]# 
66 [root@master1 ~]# kubectl get service
67 NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
68 demo-nginx   NodePort    10.96.199.219   <none>        80:32638/TCP   16m
69 kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP        46h
70 [root@master1 ~]# 
71 [root@master1 ~]# cat /etc/hosts
72 127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
73 ::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
74 192.168.1.66    master1
75 192.168.1.77    node1
76 192.168.1.88    node2
77 [root@master1 ~]# # 验证访问结果:通过NodePort访问应用程序,每个node的地址相当于vip,可以实现相同的负载均衡效果,同时CluserIP功能依可用
78 [root@master1 ~]# curl http://master1:32638
79 nginx-web1
80 [root@master1 ~]# curl http://node1:32638
81 nginx-web1
82 [root@master1 ~]# curl http://node2:32638
83 nginx-web1
84 [root@master1 ~]# curl http://node2:32638
85 nginx-web2
86 [root@master1 ~]# # 验证访问结果:通过NodePort访问应用程序,同时CluserIP功能依可用 
87 [root@master1 ~]# curl http://10.96.199.219
88 nginx-web1
89 [root@master1 ~]# curl http://10.96.199.219
90 nginx-web2
91 [root@master1 ~]# 

 4、扩展应用

当应用程序的负载比较高无法满足应用请求时,一般我们会通过扩展RS的数量来实现,在kubernetes中,扩展RS实际上通过扩展副本数replicas来实现,扩展RS非常便利,快速实现弹性伸缩。kubernets能提供两种方式的伸缩能力:

  • 手动伸缩能力scale up和scale down;
  • 动态的弹性伸缩horizontalpodautoscalers,基于CPU的利用率实现自动的弹性伸缩,需要依赖与监控组件如metrics server,当前未实现,后续再做深入探讨,本文以手动的scale的方式扩展应用的副本数。

 

  • 手动扩展副本数到四副本并查看:
 1 [root@master1 ~]# kubectl get deployments.apps  -o wide
 2 NAME         READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES        SELECTOR
 3 demo-nginx   2/2     2            2           92m   nginx        nginx:1.8.1   app=demo-nginx
 4 [root@master1 ~]# 
 5 [root@master1 ~]# kubectl get deployments.apps  -o wide
 6 NAME         READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES        SELECTOR
 7 demo-nginx   2/2     2            2           92m   nginx        nginx:1.8.1   app=demo-nginx
 8 [root@master1 ~]# 
 9 [root@master1 ~]# kubectl scale deployment demo-nginx --replicas=4    #  扩容到4副本
10 deployment.apps/demo-nginx scaled
11 [root@master1 ~]# 
12 [root@master1 ~]# kubectl get deployments.apps  -o wide
13 NAME         READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES        SELECTOR
14 demo-nginx   4/4     4            4           93m   nginx        nginx:1.8.1   app=demo-nginx
15 [root@master1 ~]# 
  • 此时再次查看service的情况会怎样呢?查看service详情,新扩展的pod会自动更新到service的endpoints中,自动服务发现:
 1 [root@master1 ~]# kubectl get service
 2 NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
 3 demo-nginx   NodePort    10.96.199.219   <none>        80:32638/TCP   51m
 4 kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP        46h
 5 [root@master1 ~]# 
 6 [root@master1 ~]# kubectl describe service demo-nginx 
 7 Name:                     demo-nginx
 8 Namespace:                default
 9 Labels:                   app=demo-nginx
10 Annotations:              <none>
11 Selector:                 app=demo-nginx
12 Type:                     NodePort
13 IP Family Policy:         SingleStack
14 IP Families:              IPv4
15 IP:                       10.96.199.219
16 IPs:                      10.96.199.219
17 Port:                     <unset>  80/TCP
18 TargetPort:               80/TCP
19 NodePort:                 <unset>  32638/TCP
20 Endpoints:                172.16.1.5:80,172.16.1.6:80,172.16.2.4:80 + 1 more...    # 新生成的两个pod地址已经加进来了
21 Session Affinity:         None
22 External Traffic Policy:  Cluster
23 Events:                   <none>
24 [root@master1 ~]# 
25 [root@master1 ~]# kubectl describe endpoints demo-nginx 
26 Name:         demo-nginx
27 Namespace:    default
28 Labels:       app=demo-nginx
29 Annotations:  endpoints.kubernetes.io/last-change-trigger-time: 2021-10-03T09:47:26Z
30 Subsets:
31   Addresses:          172.16.1.5,172.16.1.6,172.16.2.4,172.16.2.5            # 新生成的两个pod地址已经加进来了
32   NotReadyAddresses:  <none>
33   Ports:
34     Name     Port  Protocol
35     ----     ----  --------
36     <unset>  80    TCP
37 
38 Events:  <none>
39 [root@master1 ~]# 
  • 测试验证,将新加入的两个pod站点内容设置为:web3,web4,参考前面的设置方法,测试service的ip,查看负载均衡效果:
 1 [root@master1 ~]# kubectl get pods -o wide
 2 NAME                          READY   STATUS    RESTARTS   AGE   IP           NODE    NOMINATED NODE   READINESS GATES
 3 demo-nginx-55ccc46db6-jmjkx   1/1     Running   0          93m   172.16.2.4   node2   <none>           <none>
 4 demo-nginx-55ccc46db6-l2vj5   1/1     Running   0          26s   172.16.2.5   node2   <none>           <none>
 5 demo-nginx-55ccc46db6-lg4nz   1/1     Running   0          93m   172.16.1.5   node1   <none>           <none>
 6 demo-nginx-55ccc46db6-vrlhw   1/1     Running   0          26s   172.16.1.6   node1   <none>           <none>
 7 [root@master1 ~]# # 修改新加入的两个pod的网页内容:
 8 [root@master1 ~]# kubectl exec -it demo-nginx-55ccc46db6-l2vj5 /bin/bash
 9 kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
10 root@demo-nginx-55ccc46db6-l2vj5:/# echo 'nginx-web3' > /usr/share/nginx/html/index.html
11 root@demo-nginx-55ccc46db6-l2vj5:/# exit
12 exit
13 [root@master1 ~]# kubectl exec -it demo-nginx-55ccc46db6-vrlhw /bin/bash
14 kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
15 root@demo-nginx-55ccc46db6-vrlhw:/# echo 'nginx-web4' > /usr/share/nginx/html/index.html
16 root@demo-nginx-55ccc46db6-vrlhw:/# exit
17 exit
18 [root@master1 ~]# 
19 [root@master1 ~]# kubectl get service
20 NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
21 demo-nginx   NodePort    10.96.199.219   <none>        80:32638/TCP   51m
22 kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP        46h
23 [root@master1 ~]# # 验证情况如下:
24 [root@master1 ~]# curl http://10.96.199.219
25 nginx-web3
26 [root@master1 ~]# curl http://10.96.199.219
27 nginx-web4
28 [root@master1 ~]# curl http://10.96.199.219
29 nginx-web1
30 [root@master1 ~]# curl http://10.96.199.219
31 nginx-web2
32 [root@master1 ~]# 

   由此可知,弹性伸缩会自动自动加入到service中实现服务自动发现和负载均衡,应用的扩展相比于传统应用快速非常多。此外,kubernetes还支持自动弹性扩展的能力,即Horizontal Pod AutoScaler,自动横向伸缩能力,配合监控系统根据CPU的利用率弹性扩展Pod个数。

 5、滚动升级

  • 使用最新版本的nginx替换当前nginx:1.8.1的版本并检查验证相关结果:
 1 [root@master1 ~]# kubectl get deployments.apps demo-nginx -o wide
 2 NAME         READY   UP-TO-DATE   AVAILABLE   AGE    CONTAINERS   IMAGES        SELECTOR
 3 demo-nginx   4/4     4            4           106m   nginx        nginx:1.8.1   app=demo-nginx
 4 [root@master1 ~]# curl -I http://10.96.199.219
 5 HTTP/1.1 200 OK
 6 Server: nginx/1.8.1            # 升级前的nginx版本
 7 Date: Sun, 03 Oct 2021 10:01:58 GMT
 8 Content-Type: text/html
 9 Content-Length: 11
10 Last-Modified: Sun, 03 Oct 2021 09:49:12 GMT
11 Connection: keep-alive
12 ETag: "61597c98-b"
13 Accept-Ranges: bytes
14 
15 [root@master1 ~]# 
16 [root@master1 ~]# kubectl set image deployments.apps demo-nginx nginx=nginx:latest        # 具体的升级命令
17 deployment.apps/demo-nginx image updated
18 [root@master1 ~]# 
19 [root@master1 ~]# kubectl get deployments.apps demo-nginx -o wide
20 NAME         READY   UP-TO-DATE   AVAILABLE   AGE    CONTAINERS   IMAGES         SELECTOR
21 demo-nginx   4/4     4            4           110m   nginx        nginx:latest   app=demo-nginx
22 [root@master1 ~]# curl -I http://10.96.199.219
23 HTTP/1.1 200 OK
24 Server: nginx/1.21.3        # 升级后的nginx版本
25 Date: Sun, 03 Oct 2021 10:04:44 GMT
26 Content-Type: text/html
27 Content-Length: 615
28 Last-Modified: Tue, 07 Sep 2021 15:21:03 GMT
29 Connection: keep-alive
30 ETag: "6137835f-267"
31 Accept-Ranges: bytes
32 
33 [root@master1 ~]# 
  • 观察升级过程,通过查看可知,升级过程中是通过新建+删除的方式逐个替换pod的方式:
 1 [root@master1 ~]# kubectl get pods -w
 2 NAME                          READY   STATUS    RESTARTS   AGE
 3 demo-nginx-55ccc46db6-jmjkx   1/1     Running   0          107m
 4 demo-nginx-55ccc46db6-l2vj5   1/1     Running   0          13m
 5 demo-nginx-55ccc46db6-lg4nz   1/1     Running   0          107m
 6 demo-nginx-55ccc46db6-vrlhw   1/1     Running   0          13m
 7 # 这里是升级前后的分界……
 8 demo-nginx-6b99c5bdf5-qxdkh   0/1     Pending   0          0s
 9 demo-nginx-6b99c5bdf5-qxdkh   0/1     Pending   0          0s
10 demo-nginx-55ccc46db6-vrlhw   1/1     Terminating   0          16m
11 demo-nginx-6b99c5bdf5-qxdkh   0/1     ContainerCreating   0          0s
12 demo-nginx-6b99c5bdf5-vsrc8   0/1     Pending             0          0s
13 demo-nginx-6b99c5bdf5-vsrc8   0/1     Pending             0          0s
14 demo-nginx-6b99c5bdf5-vsrc8   0/1     ContainerCreating   0          0s
15 demo-nginx-55ccc46db6-vrlhw   0/1     Terminating         0          16m
16 demo-nginx-55ccc46db6-vrlhw   0/1     Terminating         0          16m
17 demo-nginx-55ccc46db6-vrlhw   0/1     Terminating         0          16m
18 demo-nginx-6b99c5bdf5-qxdkh   1/1     Running             0          2s
19 demo-nginx-55ccc46db6-l2vj5   1/1     Terminating         0          16m
20 demo-nginx-6b99c5bdf5-kwkzs   0/1     Pending             0          0s
21 demo-nginx-6b99c5bdf5-kwkzs   0/1     Pending             0          0s
22 demo-nginx-6b99c5bdf5-kwkzs   0/1     ContainerCreating   0          0s
23 demo-nginx-6b99c5bdf5-vsrc8   1/1     Running             0          2s
24 demo-nginx-55ccc46db6-lg4nz   1/1     Terminating         0          110m
25 demo-nginx-6b99c5bdf5-cpb2t   0/1     Pending             0          0s
26 demo-nginx-6b99c5bdf5-cpb2t   0/1     Pending             0          0s
27 demo-nginx-6b99c5bdf5-cpb2t   0/1     ContainerCreating   0          1s
28 demo-nginx-55ccc46db6-lg4nz   0/1     Terminating         0          110m
29 demo-nginx-55ccc46db6-lg4nz   0/1     Terminating         0          110m
30 demo-nginx-55ccc46db6-lg4nz   0/1     Terminating         0          110m
31 demo-nginx-55ccc46db6-l2vj5   0/1     Terminating         0          16m
32 demo-nginx-55ccc46db6-l2vj5   0/1     Terminating         0          16m
33 demo-nginx-55ccc46db6-l2vj5   0/1     Terminating         0          16m
34 demo-nginx-6b99c5bdf5-cpb2t   1/1     Running             0          3s
35 demo-nginx-55ccc46db6-jmjkx   1/1     Terminating         0          110m
36 demo-nginx-6b99c5bdf5-kwkzs   1/1     Running             0          3s
37 demo-nginx-55ccc46db6-jmjkx   0/1     Terminating         0          110m
38 demo-nginx-55ccc46db6-jmjkx   0/1     Terminating         0          110m
39 demo-nginx-55ccc46db6-jmjkx   0/1     Terminating         0          110m
  •  再次查看deployments的详情可知道,deployments已经更换了新的replicasets,原来的replicasets的版本为1,可用于回滚;查看滚动升级的版本,可以看到有两个版本,分别对应的两个不同的replicasets:
 1 [root@master1 ~]# kubectl describe deployments.apps demo-nginx 
 2 Name:                   demo-nginx
 3 Namespace:              default
 4 CreationTimestamp:      Sun, 03 Oct 2021 04:13:57 -0400
 5 Labels:                 app=demo-nginx
 6 Annotations:            deployment.kubernetes.io/revision: 2    # 新的版本号,用于回滚
 7 Selector:               app=demo-nginx
 8 Replicas:               4 desired | 4 updated | 4 total | 4 available | 0 unavailable
 9 StrategyType:           RollingUpdate
10 MinReadySeconds:        0
11 RollingUpdateStrategy:  25% max unavailable, 25% max surge
12 Pod Template:
13   Labels:  app=demo-nginx
14   Containers:
15    nginx:
16     Image:        nginx:latest
17     Port:         <none>
18     Host Port:    <none>
19     Environment:  <none>
20     Mounts:       <none>
21   Volumes:        <none>
22 Conditions:
23   Type           Status  Reason
24   ----           ------  ------
25   Available      True    MinimumReplicasAvailable
26   Progressing    True    NewReplicaSetAvailable
27 OldReplicaSets:  <none>
28 NewReplicaSet:   demo-nginx-6b99c5bdf5 (4/4 replicas created)    # 和下面的命令:kubectl get replicasets.apps查看结果对应上
29 Events:                                                            # replicasets 之间替换的过程
30   Type    Reason             Age    From                   Message
31   ----    ------             ----   ----                   -------
32   Normal  ScalingReplicaSet  23m    deployment-controller  Scaled up replica set demo-nginx-55ccc46db6 to 4
33   Normal  ScalingReplicaSet  6m45s  deployment-controller  Scaled up replica set demo-nginx-6b99c5bdf5 to 1
34   Normal  ScalingReplicaSet  6m45s  deployment-controller  Scaled down replica set demo-nginx-55ccc46db6 to 3
35   Normal  ScalingReplicaSet  6m45s  deployment-controller  Scaled up replica set demo-nginx-6b99c5bdf5 to 2
36   Normal  ScalingReplicaSet  6m43s  deployment-controller  Scaled down replica set demo-nginx-55ccc46db6 to 2
37   Normal  ScalingReplicaSet  6m43s  deployment-controller  Scaled up replica set demo-nginx-6b99c5bdf5 to 3
38   Normal  ScalingReplicaSet  6m43s  deployment-controller  Scaled down replica set demo-nginx-55ccc46db6 to 1
39   Normal  ScalingReplicaSet  6m43s  deployment-controller  Scaled up replica set demo-nginx-6b99c5bdf5 to 4
40   Normal  ScalingReplicaSet  6m40s  deployment-controller  Scaled down replica set demo-nginx-55ccc46db6 to 0
41 [root@master1 ~]# 
42 [root@master1 ~]# 
43 [root@master1 ~]# kubectl rollout history deployment demo-nginx 
44 deployment.apps/demo-nginx 
45 REVISION  CHANGE-CAUSE
46 1         <none>
47 2         <none>
48 
49 [root@master1 ~]# :             # 查看replicasets列表,旧的包含pod为0
50 NAME                    DESIRED   CURRENT   READY   AGE
51 demo-nginx-55ccc46db6   0         0         0       127m
52 demo-nginx-6b99c5bdf5   4         4         4       17m
53 [root@master1 ~]# 
  • 回滚到旧的版本:
 1 [root@master1 ~]# kubectl rollout undo deployment demo-nginx --to-revision=1    # 回退到指定的版本
 2 deployment.apps/demo-nginx rolled back
 3 [root@master1 ~]# # 相关查看验证
 4 [root@master1 ~]# curl -I http://10.96.199.219
 5 HTTP/1.1 200 OK
 6 Server: nginx/1.8.1
 7 Date: Sun, 03 Oct 2021 10:27:31 GMT
 8 Content-Type: text/html
 9 Content-Length: 612
10 Last-Modified: Tue, 26 Jan 2016 15:24:47 GMT
11 Connection: keep-alive
12 ETag: "56a78fbf-264"
13 Accept-Ranges: bytes
14 
15 [root@master1 ~]# 
16 [root@master1 ~]# kubectl get replicasets.apps 
17 NAME                    DESIRED   CURRENT   READY   AGE
18 demo-nginx-55ccc46db6   4         4         4       133m
19 demo-nginx-6b99c5bdf5   0         0         0       23m
20 [root@master1 ~]# 
21 [root@master1 ~]# kubectl describe deployments.apps demo-nginx 
22 Name:                   demo-nginx
23 Namespace:              default
24 CreationTimestamp:      Sun, 03 Oct 2021 04:13:57 -0400
25 Labels:                 app=demo-nginx
26 Annotations:            deployment.kubernetes.io/revision: 3
27 Selector:               app=demo-nginx
28 Replicas:               4 desired | 4 updated | 4 total | 4 available | 0 unavailable
29 StrategyType:           RollingUpdate
30 MinReadySeconds:        0
31 RollingUpdateStrategy:  25% max unavailable, 25% max surge
32 Pod Template:
33   Labels:  app=demo-nginx
34   Containers:
35    nginx:
36     Image:        nginx:1.8.1
37     Port:         <none>
38     Host Port:    <none>
39     Environment:  <none>
40     Mounts:       <none>
41   Volumes:        <none>
42 Conditions:
43   Type           Status  Reason
44   ----           ------  ------
45   Available      True    MinimumReplicasAvailable
46   Progressing    True    NewReplicaSetAvailable
47 OldReplicaSets:  <none>
48 NewReplicaSet:   demo-nginx-55ccc46db6 (4/4 replicas created)
49 Events:
50   Type    Reason             Age                 From                   Message
51   ----    ------             ----                ----                   -------
52   Normal  ScalingReplicaSet  24m                 deployment-controller  Scaled up replica set demo-nginx-6b99c5bdf5 to 1
53   Normal  ScalingReplicaSet  24m                 deployment-controller  Scaled down replica set demo-nginx-55ccc46db6 to 3
54   Normal  ScalingReplicaSet  24m                 deployment-controller  Scaled up replica set demo-nginx-6b99c5bdf5 to 2
55   Normal  ScalingReplicaSet  23m                 deployment-controller  Scaled up replica set demo-nginx-6b99c5bdf5 to 3
56   Normal  ScalingReplicaSet  23m                 deployment-controller  Scaled down replica set demo-nginx-55ccc46db6 to 1
57   Normal  ScalingReplicaSet  23m                 deployment-controller  Scaled down replica set demo-nginx-55ccc46db6 to 2
58   Normal  ScalingReplicaSet  23m                 deployment-controller  Scaled up replica set demo-nginx-6b99c5bdf5 to 4
59   Normal  ScalingReplicaSet  23m                 deployment-controller  Scaled down replica set demo-nginx-55ccc46db6 to 0
60   Normal  ScalingReplicaSet  46s                 deployment-controller  Scaled up replica set demo-nginx-55ccc46db6 to 1
61   Normal  ScalingReplicaSet  46s                 deployment-controller  Scaled down replica set demo-nginx-6b99c5bdf5 to 3
62   Normal  ScalingReplicaSet  46s (x2 over 133m)  deployment-controller  Scaled up replica set demo-nginx-55ccc46db6 to 2
63   Normal  ScalingReplicaSet  43s (x2 over 40m)   deployment-controller  Scaled up replica set demo-nginx-55ccc46db6 to 4
64   Normal  ScalingReplicaSet  43s                 deployment-controller  Scaled down replica set demo-nginx-6b99c5bdf5 to 2
65   Normal  ScalingReplicaSet  43s                 deployment-controller  Scaled up replica set demo-nginx-55ccc46db6 to 3
66   Normal  ScalingReplicaSet  43s                 deployment-controller  Scaled down replica set demo-nginx-6b99c5bdf5 to 1
67   Normal  ScalingReplicaSet  41s                 deployment-controller  Scaled down replica set demo-nginx-6b99c5bdf5 to 0
68 [root@master1 ~]# kubectl rollout history deployment demo-nginx 
69 deployment.apps/demo-nginx 
70 REVISION  CHANGE-CAUSE
71 2         <none>
72 3         <none>
73 
74 [root@master1 ~]# 
原文地址:https://www.cnblogs.com/zheng-weimin/p/15364320.html