k8s概述

云原生

  • 容器化:所有的服务都必须部署在容器中。
  • 微服务:web 服务架构是微服务架构
  • CI/CD:可持续交互和可持续部署
  • DevOps:开发和运维密不可分

what k8s

Kubernetes 为你提供了一个可弹性运行分布式系统的框架。 Kubernetes 会满足你的扩展要求、故障转移、部署模式等。

Kubernetes 为你提供:

  • 服务发现和负载均衡

    Kubernetes 可以使用 DNS 名称或自己的 IP 地址公开容器,如果进入容器的流量很大, Kubernetes 可以负载均衡并分配网络流量,从而使部署稳定。

  • 存储编排

    Kubernetes 允许你自动挂载你选择的存储系统,例如本地存储、公共云提供商等。

  • 自动部署和回滚

    你可以使用 Kubernetes 描述已部署容器的所需状态,它可以以受控的速率将实际状态 更改为期望状态。例如,你可以自动化 Kubernetes 来为你的部署创建新容器, 删除现有容器并将它们的所有资源用于新容器。

  • 自动完成装箱计算

    Kubernetes 允许你指定每个容器所需 CPU 和内存(RAM)。 当容器指定了资源请求时,Kubernetes 可以做出更好的决策来管理容器的资源。

  • 自我修复

    Kubernetes 重新启动失败的容器、替换容器、杀死不响应用户定义的 运行状况检查的容器,并且在准备好服务之前不将其通告给客户端。

  • 密钥与配置管理

    Kubernetes 允许你存储和管理敏感信息,例如密码、OAuth 令牌和 ssh 密钥。 你可以在不重建容器镜像的情况下部署和更新密钥和应用程序配置,也无需在堆栈配置中暴露密钥。

Kubernetes组件工作架构图

引用自《Programming Kubernetes》

k8s组件

Master 负责管理整个集群。 Master 协调集群中的所有活动,例如调度应用、维护应用的所需状态、应用扩容以及推出新的更新。

Node 是一个虚拟机或者物理机,它在 Kubernetes 集群中充当工作机器的角色 每个Node都有 Kubelet , 它管理 Node 而且是 Node 与 Master 通信的代理。 Node 还应该具有用于处理容器操作的工具,例如 Docker 或 rkt 。处理生产级流量的 Kubernetes 集群至少应具有三个 Node 。

Node 使用 Master 暴露的 Kubernetes API 与 Master 通信。终端用户也可以使用 Kubernetes API 与集群交互。

Master组件

Master组件是集群的控制平台(control plane):

  • master 组件负责集群中的全局决策(例如,调度)
  • master 组件探测并响应集群事件(例如,当 Deployment 的实际 Pod 副本数未达到 replicas 字段的规定时,启动一个新的 Pod)

kube-apiserver

此 master 组件提供 Kubernetes API。这是Kubernetes控制平台的前端(front-end),可以水平扩展(通过部署更多的实例以达到性能要求)。kubectl / kubernetes dashboard / kuboard 等Kubernetes管理工具就是通过 kubernetes API 实现对 Kubernetes 集群的管理。

Kubernetes 中所有的组件都会和 API Server 进行连接,组件与组件之间一般不进行独立的连接,都依赖于 API Server 进行消息的传送

提供 HTTP RESTful API 接口的主要服务, 是 Kubernetes 里对所有资源进行增、删 、改 、查等操作的唯一入口,也是集群控制的入口进程 。

kube-scheduler

此 master 组件监控所有新创建尚未分配到节点上的 Pod,并且自动选择为 Pod 选择一个合适的节点去运行。

影响调度的因素有:

  • 单个或多个 Pod 的资源需求
  • 硬件、软件、策略的限制
  • 亲和与反亲和(affinity and anti-affinity)的约定
  • 数据本地化要求
  • 工作负载间的相互作用

kube-controller-manager

此 master 组件运行了所有的控制器

逻辑上来说,每一个控制器是一个独立的进程,但是为了降低复杂度,这些控制器都被合并运行在一个进程里。

kube-controller-manager 中包含的控制器有:

  • 节点控制器(Node Controller): 负责在节点出现故障时进行通知和响应,水平扩展等
  • 任务控制器(Job controller): 监测代表一次性任务的 Job 对象,然后创建 Pods 来运行这些任务直至完成
  • 端点控制器(Endpoints Controller): 填充端点(Endpoints)对象(即加入 Service 与 Pod)
  • 服务帐户和令牌控制器(Service Account & Token Controllers): 为新的命名空间创建默认帐户和 API 访问令牌

etcd

支持一致性和高可用的名值对存储组件,Kubernetes集群的所有配置信息都存储在 etcd 中。请确保您 备份 (opens new window)了 etcd 的数据。关于 etcd 的更多信息,可参考 etcd 官方文档

是一个分布式的一个存储系统,API Server 中所需要的这些原信息都被放置在 etcd 中,etcd 本身是一个高可用系统,通过 etcd 保证整个 Kubernetes 的 Master 组件的高可用性。

Node 组件

节点组件在每个节点上运行,维护运行的 Pod 并提供 Kubernetes 运行环境。

image-20210711223411424

img

  • kubelet: 负责 Pod 对应容器的创建 、启停等任务,同时与 Master 密切协作,实现 集群管理的基本功能 。定期从kube-apiserver组件接收新的或修改的Pod规范,并确保Pod及其容器在期望规范下运行。同时该组件作为工作节点的监控组件,向kube-apiserver汇报主机的运行状况。
  • kube-proxy: 实现 Kubemetes Service 的通信与负载均衡机制的服务 。
  • 容器运行时(如 Docker ):负责本机的容器创建和管理 。

pod 概述

Pod 容器组 是一个k8s中一个抽象的概念,用于存放一组 container(可包含一个或多个 container 容器,即图上正方体),以及这些 container (容器)的一些共享资源。这些资源包括:

  • 共享存储,称为卷(Volumes),即图上紫色圆柱
  • 网络,每个 Pod(容器组)在集群中有个唯一的 IP,pod(容器组)中的 container(容器)共享该IP地址。Pod 内部的容器可以使用 localhost 互相通信。Pod 中的容器与外界通信时,必须分配共享网络资源。
  • container(容器)的基本信息,例如容器的镜像版本,对外暴露的端口等

Pod(容器组)是 k8s 集群上的最基本的单元。当我们在 k8s 上创建 Deployment 时,会在集群上创建包含容器的 Pod (而不是直接创建容器)。每个Pod都与运行它的 worker 节点(Node)绑定,并保持在那里直到终止或被删除。如果节点(Node)发生故障,则会在群集中的其他可用节点(Node)上运行相同的 Pod(从同样的镜像创建 Container,使用同样的配置,IP 地址不同,Pod 名字不同)。

Pod(容器组)总是在 Node(节点) 上运行。Node(节点)是 kubernetes 集群中的计算机,可以是虚拟机或物理机。每个 Node(节点)都由 master 管理。一个 Node(节点)可以有多个Pod(容器组),kubernetes master 会根据每个 Node(节点)上可用资源的情况,自动调度 Pod(容器组)到最佳的 Node(节点)上。

每个 Kubernetes Node(节点)至少运行:

  • Kubelet,负责 master 节点和 worker 节点之间通信的进程;管理 Pod(容器组)和 Pod(容器组)内运行的 Container(容器)。
  • 容器运行环境(如Docker)负责下载镜像、创建和运行容器等。

总结

  • pod 相当于一个容器,pod 有独立的 ip 地址,也有自己的 hostname,利用 namespace 进行资源隔离,相当于一个独立沙箱环境。
  • pod 内部封装的是容器,可以封装一个,或者多个容器(通常是一组相关的容器)
  • pod 有自己独立的 IP 地址
  • pod 内部的容器之间是通过 localhost 进行访问
  • Pod在设计支持就不是作为持久化实体的。在调度失败、节点故障、缺少资源或者节点维护的状态下都会死掉会被驱逐。

pod 如何对外提供访问

如果 pod 想对外提供服务,必须绑定物理机端口 (即在物理机上开启端口,让这个端口和 pod 的端口进行映射),这样就可以通过物理机进行数据包的转发。

pod 的负载均衡

pod 是一个进程,是有生命周期的,一旦宕机、版本更新都会创建新的 pod( IP 地址会变化,hostname 会变化)。因为它不知道 pod 发生了改变,那请求就不能被接受了。所以服务发生了变化它根本不知道,Nginx 无法发现服务,不能用 Nginx 做负载均衡。那该如何实现呢?使用 Service 资源对象

  • POD IP:pod 的 IP 地址
  • NODE IP:物理机的 IP 地址
  • cluster IP:虚拟 IP,是由 kubernetes 抽象出的 service 对象,这个 service 对象就是一个 VIP (virtual IP, VIP) 的资源对象

尽管每个 Pod 都有一个唯一的 IP 地址,但是如果没有 Service ,这些 IP 不会暴露在集群外部。Service 允许您的应用程序接收流量。Service 也可以用在 ServiceSpec 标记type的方式暴露

  • ClusterIP (默认) - 在集群的内部 IP 上公开 Service 。这种类型使得 Service 只能从集群内访问。
  • NodePort - 使用 NAT 在集群中每个选定 Node 的相同端口上公开 Service 。使用<NodeIP>:<NodePort> 从集群外部访问 Service。是 ClusterIP 的超集。
  • LoadBalancer - 在当前云中创建一个外部负载均衡器(如果支持的话),并为 Service 分配一个固定的外部IP。是 NodePort 的超集。
  • ExternalName - 通过返回带有该名称的 CNAME 记录,使用任意名称(由 spec 中的externalName指定)公开 Service。不使用代理。这种类型需要kube-dns的v1.7或更高版本。

这时就要去做一个 service,对外表现出是一个进程或资源对象,有虚拟的 IP (VIP) 和端口。请求会访问 service,然后 service 自己会 负载均衡 地发送给相应服务的 POD。

image-20210904231334253

  • service 和 pod 都是一个进程,都是虚拟的,因此实际上 service 也不能对外网提供服务

  • service 和 pod 之间可以直接进行通信,它们的通信属于局域网通信。通过标签选择器 selector关联service 和 pod ,且service 只能对 一组相同的副本 提供服务,不能跨组提供服务。如果有另一组,需要再创建一个 service。因此不同的业务会有不同的 service。

    image-20210904231758474

  • 负载策略:把请求交给 service 后,service 使用 iptables,ipvs 来实现数据包的分发

  • service 是如何发现 pod 已经发生变化

    通过kube-proxy来通知改变

    image-20210904232105570

    service 实现服务的发现

    • kube-proxy 监控 pod,一旦发现 pod 服务变化,将会把新的 ip 地址更新到 service。
    • endpoints 那些都是存储在 etcd 里的,所以 kube-proxy 更新的存储在 etcd 里的映射关系。

stop pod

因为Pod作为在集群的节点上运行的进程,所以在不再需要的时候能够优雅的终止掉是十分必要的(比起使用发送KILL信号这种暴力的方式)。用户需要能够发起一个删除 Pod 的请求,并且知道它们何时会被终止,是否被正确的删除。用户想终止程序时发送删除pod的请求,在pod可以被强制删除前会有一个宽限期,会发送一个TERM请求到每个容器的主进程。一旦超时,将向主进程发送KILL信号并从API server中删除。如果kubelet或者container manager在等待进程终止的过程中重启,在重启后仍然会重试完整的宽限期。

示例流程如下:

  1. 用户发送删除pod的命令,默认宽限期是30秒;
  2. 在Pod超过该宽限期后API server就会更新Pod的状态为“dead”;
  3. 在客户端命令行上显示的Pod状态为“terminating”;
  4. 跟第三步同时,当kubelet发现pod被标记为“terminating”状态时,开始停止pod进程:
    1. 如果在pod中定义了preStop hook,在停止pod前会被调用。如果在宽限期过后,preStop hook依然在运行,第二步会再增加2秒的宽限期;
    2. 向Pod中的进程发送TERM信号;
  5. 跟第三步同时,该Pod将从该service的端点列表中删除,不再是replication controller的一部分。关闭的慢的pod将继续处理load balancer转发的流量;
  6. 过了宽限期后,将向Pod中依然运行的进程发送SIGKILL信号而杀掉进程。
  7. Kubelet会在API server中完成Pod的的删除,通过将优雅周期设置为0(立即删除)。Pod在API中消失,并且在客户端也不可见。

删除宽限期默认是30秒。 kubectl delete命令支持 —grace-period=<seconds> 选项,允许用户设置自己的宽限期。如果设置为0将强制删除pod。在kubectl>=1.5版本的命令中,你必须同时使用 --force--grace-period=0 来强制删除pod。 在 yaml 文件中可以通过 `` 来修改此值。

Pod的生命周期示意图

Pod的生命周期示意图(图片来自网络)

kubelet

一个在集群中每个节点(node)上运行的代理。 它保证容器(containers)都 运行在 Pod(集群中运行的容器) 中。

kubelet 接收一组通过各类机制提供给它的 PodSpecs,确保这些 PodSpecs 中描述的容器处于运行状态且健康。 kubelet 不会管理不是由 Kubernetes 创建的容器。

每个 node 节点都有一份kubelet,在 node 节点上的资源操作指令由 kuberlet 来执行,scheduler 把请求交给api ,然后 api sever 再把信息指令数据存储在 etcd 里,于是 kuberlet 会扫描 etcd 并获取指令请求,然后去执行

kube-proxy

kube-proxy 是集群中每个节点上运行的网络代理, 实现 Kubernetes 服务(Service) 概念的一部分。

kube-proxy 维护节点上的网络规则。这些网络规则允许从集群内部或外部的网络会话与 Pod 进行网络通信。

如果操作系统提供了数据包过滤层并可用的话,kube-proxy 会通过它来实现网络规则。否则, kube-proxy 仅转发流量本身。

workload

ReplicaSet

管理控制 pod 副本(服务集群)的数量,以使其永远与预期设定的数量保持一致

当副本设置为 3 时,副本控制器将会永远保证副本数量为 3。因此当有 pod 服务宕机时(如上面第 3 个 pod),那副本控制器会立马重新创建一个新的 pod,就能够保证副本数量一直为预先设定好的 3 个。

ReplicaSet 可以使用标签选择器进行 单选 和 复合选择

假设下面有下面两个不同机器上的 Node 结点,如何知道它们的 pod 其实都是相同的呢?答案是通过标签。

给每个 pod 打上标签 ( key=value 格式,如下图中的 app=web, release=stable,这有两个选项,相同的pod副本的标签是一样的),于是副本控制器可以通过标签选择器 seletor 去选择一组相关的服务。

一旦 selector 和 pod 的标签匹配上了,就表明这个 pod 是当前这个副本控制器控制的,表明了副本控制器和 pod 的所属关系。如下图中 seletor 指定了 app = web 和 release=stable 是复合选择,要用 ReplicaSet 才能实现若用 ReplicationController 的话只能选择一个,如只选择匹配app=web标签。这样下面的 3 个 pod 就归这个副本控制器管。 image-20210904214602960

Deployment

一旦运行了 Kubernetes 集群,就可以在其上部署容器化应用程序。 为此,您需要创建 Kubernetes Deployment 配置。Deployment 指挥 Kubernetes 如何创建和更新应用程序的实例。创建 Deployment 后,Kubernetes master 将应用程序实例调度到集群中的各个节点上。

创建应用程序实例后,Kubernetes Deployment 控制器会持续监视这些实例。 如果托管实例的节点关闭或被删除,则 Deployment 控制器会将该实例替换为群集中另一个节点上的实例。 这提供了一种自我修复机制来解决机器故障维护问题。

滚动更新

重新创建一个 pod (v2版本) 来代替 之前的 pod (v1版本),不是把服务停掉再把新版本部署上去

单独的 ReplicaSet 是不支持滚动更新的,Deployment 对象支持滚动更新

滚动更新时的步骤:

  • Deployment 建立新的 Replicaset

  • Replicaset 重新建立新的 pod

Deployment 管 Replicaset,Replicaset 维护 pod。在更新时删除的是旧的 pod,老版本的 ReplicaSet 是不会删除的,所以在需要时还可以回退以前的状态。

image-20210904220320766

StatefulSet 部署有状态服务

通常情况下,Deployment 被用来部署无状态服务。然后 StatefulSet 就是为了解决有状态服务使用容器化部署的一个问题。

  • 有状态服务 有实时的数据需要存储 在有状态服务集群中,如果把某一个服务抽离出来,一段时间后再加入回集群网络,此后集群网络会无法使用
  • 无状态服务 没有实时的数据需要存储 在无状态服务集群中,如果把某一个服务抽离出去,一段时间后再加入回集群网络,对集群服务无任何影响,因为它们不需要做交互,不需要数据同步等等。

借助 PVC(与存储有关) 文件系统来存储的实时数据,因此下图就是一个有状态服务的部署。 在 pod 宕机之后重新建立 pod 时,StatefulSet 通过保证 hostname 不发生变化来保证数据不丢失。因此 pod 就可以通过 hostname 来关联(找到) 之前存储的数据。 image-20210904221819260

许多群集环境都安装了默认的 StorageClass。如果在 PersistentVolumeClaim 中未指定 StorageClass,则使用群集的默认 StorageClass。

创建 PersistentVolumeClaim 时,将根据 StorageClass 配置动态设置 PersistentVolume。

警告:

在本地群集中,默认的 StorageClass 使用hostPath供应器。 hostPath卷仅适用于开发和测试。使用 hostPath 卷,您的数据位于 Pod 调度到的节点上的/tmp中,并且不会在节点之间移动。如果 Pod 死亡并被调度到群集中的另一个节点,或者该节点重新启动,则数据将丢失。

如果要建立需要使用hostPath设置程序的集群,则必须在 controller-manager 组件中设置--enable-hostpath-provisioner标志。

A Secret 是存储诸如密码或密钥之类的敏感数据的对象。从 1.14 开始,kubectl支持使用 kustomization 文件管理 Kubernetes 对象。您可以通过kustomization.yaml中的生成器创建一个 Secret。

通过以下命令在kustomization.yaml中添加一个 Secret 生成器。您需要用您要使用的密码替换YOUR_PASSWORD

1
2
3
4
5
6
cat <<EOF >./kustomization.yaml
secretGenerator:
- name: mysql-pass
  literals:
  - password=YOUR_PASSWORD
EOF

MySQL 容器将 PersistentVolume 挂载在/var/lib/mysqlMYSQL_ROOT_PASSWORD环境变量设置来自 Secret 的数据库密码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
apiVersion: v1
kind: Service
metadata:
  name: wordpress-mysql
  labels:
    app: wordpress
spec:
  ports:
    - port: 3306
  selector:
    app: wordpress
    tier: mysql
  clusterIP: None
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pv-claim
  labels:
    app: wordpress
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: wordpress-mysql
  labels:
    app: wordpress
spec:
  selector:
    matchLabels:
      app: wordpress
      tier: mysql
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: wordpress
        tier: mysql
    spec:
      containers:
      - image: mysql:5.6
        name: mysql
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-pass
              key: password
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
      volumes:
      - name: mysql-persistent-storage
        persistentVolumeClaim:
          claimName: mysql-pv-claim

example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
apiVersion: apps/v1beta1 # 创建该对象所使用的 Kubernetes API 的版本
kind: Deployment # 想要创建的对象的类型
metadata:  # 识别对象唯一性的数据,包括一个 name 字符串、UID 和可选的 namespace
  name: nginx-deployment
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

1
kubectl create -f docs/user-guide/nginx-deployment.yaml --record	

spec 必须提供,它描述了对象的 期望状态希望对象所具有的特征。

status 描述了对象的 实际状态

在任何时刻,Kubernetes 控制平面一直处于活跃状态,管理着对象的实际状态以与我们所期望的状态相匹配。

命令行

1
pod(po),service(svc),replication controller(rc),deployment(deploy),replica set(rs)、pvc(PersistentVolume)

下表列出的是 kubernetes 中所有支持的类型和缩写的别名。

资源类型 缩写别名
clusters -
componentstatuses cs
configmaps cm
daemonsets ds
deployments deploy
endpoints ep
event ev
horizontalpodautoscalers hpa
ingresses ing
jobs -
limitranges limits
namespaces ns
networkpolicies -
nodes no
statefulsets -
persistentvolumeclaims pvc
persistentvolumes pv
pods po
podsecuritypolicies psp
podtemplates -
replicasets rs
replicationcontrollers rc
resourcequotas quota
cronjob -
secrets -
serviceaccount sa
services svc
storageclasses -
thirdpartyresources -

格式化输出

要以特定的格式向终端窗口输出详细信息,可以在 kubectl 命令中添加 -o 或者 -output 标志。

1
2
3
4
5
6
7
8
-o=custom-columns=<spec>   #使用逗号分隔的自定义列列表打印表格
-o=custom-columns-file=<filename> #使用文件中的自定义列模板打印表格
-o=json    #输出JSON 格式的API对象
-o=jsonpath=< template>       #打印jsonpath表达式中定义的字段
-o=jsonpath-file=<filename>   #打印由文件中的jsonpath表达式定义的字段
-o=name  #仅打印资源名称 
-o=wide  #以纯文本格式输出任何附加信息,对于Pod ,包含节点名称
-o=yaml  #输出 YAML 格式的 API 对象 
1
2
3
4
5
6
7
8
# 获取列出一个或多个资源的信息
kubectl get [pods|deployments|services|nodes|pvc]
# 列出当前命名空间下的全部 Pods,并显示更详细的信息
kubectl get pods -o wide
# 获取一个 pod 的 YAML
kubectl get pod my-pod -o yaml
# 显示所有 Pods 的标签(或任何其他支持标签的 Kubernetes 对象)
kubectl get pods --show-labels
  • NAME lists the names of the Deployments in the cluster.
  • READY shows the ratio of CURRENT/DESIRED replicas
  • UP-TO-DATE displays the number of replicas that have been updated to achieve the desired state.
  • AVAILABLE displays how many replicas of the application are available to your users.
  • AGE displays the amount of time that the application has been running.
1
kubectl get rs
  • DESIRED displays the desired number of replicas of the application, which you define when you create the Deployment. This is the desired state.
  • CURRENT displays how many replicas are currently running.
1
2
# 创建具有指定名称的deployment
kubectl create deployment NAME --image=image [--dry-run]
  • 搜索合适的Node运行应用程序
  • 让应用程序在该节点上运行
  • 在需要时,配置集群在新节点上重新安排实例
1
2
3
4
5
6
7
8
9
10
kubectl describe - 显示有关资源的详细信息
kubectl logs - 打印 pod 和其中容器的日志
kubectl exec -ti $POD_NAME -c $container_name -- bash - 在 pod 中的容器上执行命令

# 获取 Pod 容器的日志(标准输出, 多容器场景)
kubectl logs [-f] my-pod -c my-container
# 获取含 name=myLabel 标签的 Pods 的日志(标准输出)
kubectl logs -l name=myLabel


1
2
3
4
5
6
kubectl expose -f nginx-controller.yaml --port=80 --target-port=8000

# label
kubectl get pods -l app=kubernetes-bootcamp
kubectl label pods $POD_NAME version=v1
kubectl delete service -l app=kubernetes-bootcamp
1
2
3
# 扩容缩容
kubectl scale --current-replicas=2 --replicas=3 deployment/mysql
kubectl scale --replicas=5 rc/foo rc/bar rc/baz
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 更新回滚
kubectl set image deployment/nginx busybox=busybox nginx=nginx:1.9.1
kubectl rollout status deployments/kubernetes-bootcamp
kubectl rollout undo deployments/kubernetes-bootcamp

# 滚动更新 "frontend" Deployment 的 "www" 容器镜像
kubectl set image deployment/frontend www=image:v2
# 检查 Deployment 的历史记录,包括版本
kubectl rollout history deployment/frontend
# 回滚到上次部署版本
kubectl rollout undo deployment/frontend
# 回滚到特定部署版本
kubectl rollout undo deployment/frontend --to-revision=2
# 监视 "frontend" Deployment 的滚动升级状态直到完成
kubectl rollout status -w deployment/frontend
# 轮替重启 "frontend" Deployment
kubectl rollout restart deployment/frontend

实战