❝本文转自方石剑的博客,原文:https://juejin.cn/post/7130839991999004680,版权归原作者所有。
在这篇文章中,我将介绍Cluster API[1]的一个很棒的功能:对你的 Kubernetes 集群进行滚动升级的能力。Cluster API 让它变得简单,而且可重复。
说实话,我曾经手动升级过一个 Kubernetes 集群,这并不是世界末日,但我是个懒惰的黑客,既然可以自动升级,又有安全的可重复性,为什么还要手动?
什么是群集 API?
如果你不熟悉 Cluster API,它是 Kubernetes 的一个子项目,专注于提供声明式 API 和工具,以简化多个 Kubernetes 集群的配置、升级和操作[2]。作为一个类比,把 Cluster API 看作是你的 Java 接口,它使用 Kubernetes 风格的接口来管理 Kubernetes 集群所需的基础设施。
回到我们的 Java 类比;为了使用上述 Java 接口,你需要在一个类中实现它。Cluster API 使用一个基础设施提供者模型来扩展对多个基础设施提供者的支持。几乎每个基础设施提供商都实现了一个。Oracle 的在这里[3],它可以用来在 Oracle 云中建立集群。关于如何开始使用我们的提供商的简要介绍,请查看 blogs.oracle.com/cloud-infra…[4],或阅读我们的文档,以了解更多关于开始使用的信息[5]。你也应该看看 Cluster API 那本很棒的书。
创建一个新的 Kubernetes 镜像
为了升级我们的工作节点,我们需要使用 Kubernetes Image Builder[6]来构建镜像。按照 "构建镜像[7]" 部分的更详细步骤进行前提条件和其他设置。
然后,我们需要将 kubernetes
信息设置为比我们当前集群版本更新的版本。现在,正在使用的集群是 1.22.9
,我们想升级到 1.23.6
(当前的发布版本可以在这里找到 kubernetes.io/releases/[8])。我们将编辑 images/capi/packer/config/kubernetes.json
,并改变以下内容。
"kubernetes_deb_version": "1.23.6-00",
"kubernetes_rpm_version": "1.23.6-0",
"kubernetes_semver": "v1.23.6",
"kubernetes_series": "v1.23"
配置更新后,我们将使用 Ubuntu 20.04 build,用 packer 创建新的镜像。
$ cd <root_of_image_builder_repo>/images/capi
$ PACKER_VAR_FILES=oci.json make build-oci-ubuntu-2004
这将在 OCI 中启动一个实例来构建镜像。一旦完成,你应该得到镜像 OCID 的输出。你也可以通过访问 https://console.us-phoenix-1.oraclecloud.com/compute/images
来检查镜像是否已经建立。你将想保存这个 OCID,因为我们以后会用到它。
使用 Cluster API 升级我的集群
Cluster API 的主要目标[9]之一是
❝使用声明式 API 来管理符合 Kubernetes 的集群的生命周期(创建、扩展、升级、销毁)。
将升级过程自动化是一个很大的成就[10]。我不希望必须封锁 / 抽干节点来进行滚动更新。这些工具应该为我做到这一点。
我假设你已经有了一个管理和工作负载集群并正在运行。如果没有,请按照入门[11]指南来创建工作负载集群。下面是我如何创建工作负载集群的例子。
$ clusterctl generate cluster oci-cluster-phx --kubernetes-version v1.22.9 \
--target-namespace default \
--control-plane-machine-count=3 \
--from https://github.com/oracle/cluster-api-provider-oci/releases/download/v.3.0/cluster-template.yaml | kubectl apply -f -
现在我们已经有了一个工作负载集群和一个新的镜像,现在是时候升级了。升级过程的步骤如下 :
升级 控制平面[12] 升级 工作母机[13]
在我们开始之前,让我们继续检查我们正在运行的工作负载集群的版本。为了访问我们的工作负载集群,我们需要从我们的管理集群导出 Kubernetes 配置
$ clusterctl get kubeconfig oci-cluster-phx -n default > oci-cluster-phx.kubeconfig
一旦我们有了 kubeconfig
文件,我们就可以检查我们工作负载集群的版本了。
$ kubectl --kubeconfig=oci-cluster-phx.kubeconfig version
Client Version: version.Info{Major:"1", Minor:"23", GitVersion:"v1.23.4", GitCommit:"e6c093d87ea4cbb530a7b2ae91e54c0842d8308a", GitTreeState:"clean", BuildDate:"2022-02-16T12:38:05Z", GoVersion:"go1.17.7", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.9", GitCommit:"6df4433e288edc9c40c2e344eb336f63fad45cd2", GitTreeState:"clean", BuildDate:"2022-04-13T19:52:02Z", GoVersion:"go1.16.15", Compiler:"gc", Platform:"linux/amd64"}
注意服务器版本是 v1.22.9
。让我们来改变它。
升级控制平面
首先,让我们为控制平面制作一个机器模板的副本。
$ kubectl get ocimachinetemplate oci-cluster-phx-control-plane -o yaml > control-plane-machine-template.yaml
我们需要修改以下内容 :
spec.template.spec.imageId
- 使用之前创建的自定义镜像 OCIDmetadata.name
- 用一个新的名字。例如。oci-cluster-phx-control-plane-v1-23-6
一旦字段被修改,我们就可以把它们应用到集群上。注意,这只会创建新的机器模板。下一步将触发实际的更新。
$ kubectl apply -f control-plane-machine-template.yaml
ocimachinetemplate.infrastructure.cluster.x-k8s.io/oci-cluster-phx-control-plane configured
我们现在要告诉 KubeadmControlPlane
资源关于新的机器模板并升级版本号。
把这个补丁文件保存为 kubeadm-control-plan-update.yaml
spec:
machineTemplate:
infrastructureRef:
name: oci-cluster-phx-control-plane-v1-23-6
version: v1.23.6
然后应用该补丁 :
$ kubectl patch --type=merge KubeadmControlPlane oci-cluster-phx-control-plane --patch-file kubeadm-control-plan-update.yaml
这将触发控制平面的滚动更新。
我们可以通过以下方式观察集群的进展 clusterctl
$ clusterctl describe cluster oci-cluster-phx
NAME READY SEVERITY REASON SINCE MESSAGE
Cluster/oci-cluster-phx False Warning RollingUpdateInProgress 98s Rolling 3 replicas with outdated spec (1 replicas up to date)
├─ClusterInfrastructure - OCICluster/oci-cluster-phx True 4h50m
├─ControlPlane - KubeadmControlPlane/oci-cluster-phx-control-plane False Warning RollingUpdateInProgress 98s Rolling 3 replicas with outdated spec (1 replicas up to date)
│ └─4 Machines... True 9m17s See oci-cluster-phx-control-plane-ptg4m, oci-cluster-phx-control-plane-sg67j, ...
└─Workers
└─MachineDeployment/oci-cluster-phx-md-0 True 10m
└─3 Machines... True 4h44m See oci-cluster-phx-md-0-8667c8d69-47nh9, oci-cluster-phx-md-0-8667c8d69-5r4zc, ...
我们也可以看到随着新实例的创建,滚动更新开始发生。
$ kubectl --kubeconfig=oci-cluster-phx.kubeconfig get nodes -A
NAME STATUS ROLES AGE VERSION
oci-cluster-phx-control-plane-464zs Ready control-plane,master 4h40m v1.22.5
oci-cluster-phx-control-plane-7vdxp NotReady control-plane,master 27s v1.23.6
oci-cluster-phx-control-plane-dhxml Ready control-plane,master 4h48m v1.22.5
oci-cluster-phx-control-plane-dmk8j Ready control-plane,master 4h44m v1.22.5
oci-cluster-phx-md--cnrbf Ready <none> 4h44m v1.22.5
oci-cluster-phx-md--hc6fj Ready <none> 4h45m v1.22.5
oci-cluster-phx-md--nc2g9 Ready <none> 4h44m v1.22.5
在终止一个控制平面实例之前,它将按照预期进行封锁和排水。
oci-cluster-phx-control-plane-dmk8j NotReady,SchedulingDisabled control-plane,master 4h52m v1.22.5
这个过程应该需要 15 分钟左右。一旦所有的控制平面节点都升级了,你应该使用 kubectl version
,看到新的版本。
$ kubectl --kubeconfig=oci-cluster-phx.kubeconfig version
Client Version: version.Info{Major:"1", Minor:"23", GitVersion:"v1.23.4", GitCommit:"e6c093d87ea4cbb530a7b2ae91e54c0842d8308a", GitTreeState:"clean", BuildDate:"2022-02-16T12:38:05Z", GoVersion:"go1.17.7", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"23", GitVersion:"v1.23.6", GitCommit:"ad3338546da947756e8a88aa6822e9c11e7eac22", GitTreeState:"clean", BuildDate:"2022-04-14T08:43:11Z", GoVersion:"go1.17.9", Compiler:"gc", Platform:"linux/amd64"}
升级工作节点
在升级了控制平面节点之后,我们现在可以升级工作节点了cluster-api.sigs.k8s.io/tasks/updat…[14]
首先,我们需要做的是复制工作节点的机器模板。
$ kubectl get ocimachinetemplate oci-cluster-phx-md-0 -o yaml > worker-machine-template.yaml
你将需要修改以下内容
spec.template.spec.imageId
- 使用之前创建的自定义图像 OCIDmetadata.name
- 用一个新的名字。例如。oci-cluster-phx-md-0-v1-23-6
一旦字段被修改,我们需要将它们应用于集群。和以前一样,这只是创建新的机器模板。下一步将开始实际的更新。
$ kubectl apply -f worker-machine-template.yaml
ocimachinetemplate.infrastructure.cluster.x-k8s.io/oci-cluster-phx-md-0-v1-23-6 created
我们现在要用我们刚刚创建的新资源来修改工人节点的 MachineDeployment
。
将此补丁文件保存为 worker-machine-deployment-update.yaml
spec:
template:
spec:
infrastructureRef:
name: oci-cluster-phx-md--v1-23-6
version: v1.23.6
然后应用该补丁,这将触发机器部署的滚动更新。
$ kubectl patch --type=merge MachineDeployment oci-cluster-phx-md- --patch-file worker-machine-deployment-update.yaml
同样,我们可以通过 clusterctl
命令观察集群的进展。但与控制平面不同,机器部署处理更新工人机器。clusterctl describe cluster
,只显示机器部署正在更新。如果你想观察滚动更新的发生和新实例的创建,你可以做以下事情。
$ kubectl --kubeconfig=oci-cluster-phx.kubeconfig get nodes -A
...
oci-cluster-phx-md--z59t8 Ready,SchedulingDisabled <none> 55m v1.22.5
oci-cluster-phx-md--z59t8 NotReady,SchedulingDisabled <none> 56m v1.22.5
如果你在工作母机上有 pod,你会看到它们被迁移到新机器上。
$ kubectl --kubeconfig=oci-cluster-phx.kubeconfig get pods
NAME READY STATUS AGE NODE
echoserver-55587b4c46-2q5hz 1/1 Terminating 89m oci-cluster-phx-md-0-z59t8
echoserver-55587b4c46-4x72p 1/1 Running 5m24s oci-cluster-phx-md-0-v1-23-6-bqs8l
echoserver-55587b4c46-tmj4b 1/1 Running 29s oci-cluster-phx-md-0-v1-23-6-btjzs
echoserver-55587b4c46-vz7gm 1/1 Running 89m oci-cluster-phx-md-0-z79bd
大约 10 或 15 分钟后,在我们的例子中,工人机应该被更新。很明显,你的节点越多,这个滚动更新就越长。你可以检查所有节点的版本来确认。
$ kubectl --kubeconfig=oci-cluster-phx.kubeconfig get nodes -A
NAME STATUS ROLES AGE VERSION
oci-cluster-phx-control-plane-v1-23-6-926gx Ready control-plane,master 18m v1.23.6
oci-cluster-phx-control-plane-v1-23-6-vfp5g Ready control-plane,master 24m v1.23.6
oci-cluster-phx-control-plane-v1-23-6-vprqc Ready control-plane,master 30m v1.23.6
oci-cluster-phx-md--v1-23-6-bqs8l Ready <none> 9m58s v1.23.6
oci-cluster-phx-md--v1-23-6-btjzs Ready <none> 5m37s v1.23.6
oci-cluster-phx-md--v1-23-6-z79bd Ready <none> 71s v1.23.6
机器部署的策略
Cluster API 提供了两种 MachineDeployment 策略 RollingUpdate
和 OnDelete
。
我们遵循的例子使用 RollingUpdate
。通过这个策略,你可以修改 maxSurge
和 maxUnavailable
。
maxSurge
和 maxUnavailable
的值都可以是一个数字(例如,5)或所需机器的百分比(例如,10%)。
另一个策略选项是 OnDelete
。这需要用户完全删除一台旧机器来驱动更新。当机器被完全删除后,新的机器就会出现。
结论
我们创建了一个新的镜像,并向集群的控制平面和工作节点推送了一个滚动升级,所有这些都是通过对我们的配置进行一些修改。无论集群是小是大,升级过程都是一样的。如果这还不是集群 API 的一个卖点,我不知道什么才是。
Cluster API 项目正在迅速发展,许多新功能即将推出。OCI Cluster[15] API 供应商团队正在努力工作,为 Cluster API 提供所有新的伟大功能,如 ClusterClass[16], MachinePools[17]和 ManagedClusters[18]。
引用链接
Cluster API: https://cluster-api.sigs.k8s.io/
[2]如果你不熟悉 Cluster API,它是 Kubernetes 的一个子项目,专注于提供声明式 API 和工具,以简化多个 Kubernetes 集群的配置、升级和操作: https://dzone.com/articles/introducing-the-kubernetes-cluster-api-project-2
[3]这里: https://github.com/oracle/cluster-api-provider-oci
[4]blogs.oracle.com/cloud-infra…: https://blogs.oracle.com/cloud-infrastructure/post/create-and-manage-kubernetes-clusters-on-oracle-cloud-infrastructure-with-cluster-api
[5]我们的文档,以了解更多关于开始使用的信息: https://oracle.github.io/cluster-api-provider-oci/gs/overview.html
[6]Kubernetes Image Builder: https://image-builder.sigs.k8s.io/capi/providers/oci.html
[7]构建镜像: https://image-builder.sigs.k8s.io/capi/providers/oci.html%23building-images
[8]kubernetes.io/releases/: https://kubernetes.io/releases/
[9]主要目标: https://cluster-api.sigs.k8s.io/%23goals
[10]将升级过程自动化是一个很大的成就: https://dzone.com/articles/kubernetes-upgrade-the-definitive-guide-to-do-it-yourself
[11]入门: https://oracle.github.io/cluster-api-provider-oci/gs/gs.html
[12]控制平面: https://dzone.com/refcardz/advanced-kubernetes
[13]工作母机: https://dzone.com/refcardz/getting-started-kubernetes
[14]cluster-api.sigs.k8s.io/tasks/updat…: https://cluster-api.sigs.k8s.io/tasks/updating-machine-templates.html
[15]OCI Cluster: https://dzone.com/articles/5-best-security-practices-for-kubernetes-and-oracle-kubernetes-engine
[16]ClusterClass: https://cluster-api.sigs.k8s.io/tasks/experimental-features/cluster-class/index.html
[17]MachinePools: https://cluster-api.sigs.k8s.io/tasks/experimental-features/machine-pools.html
[18]ManagedClusters: https://cluster-api.sigs.k8s.io/tasks/experimental-features/cluster-class/operate-cluster.html