新一代的Kubernetes多集群生命周期管理机制
Kubernetes 1.0版本发布已经过去了4年,繁荣的社区和广泛用户群体使得Kubernetes的成熟度超出了预期,大部分用户常用的功能性需求都得到了满足。但是,根据CNCF的调查,很多非功能性的需求尚待完善,比如,用户所面临的最困难的挑战之一仍然是管理多个Kubernetes集群的生命周期,包括集群部署、升级和变更等。Kubernetes社区未来的一个阶段的重点就是帮助用户更好的部署和维护Kubernetes,使其无缝的融入和对接现有的企业环境。
为什么集群的生命周期管理变得越来越重要?
Kubernetes现在已经可以支持超大规模的集群,单集群可以支撑5000个节点,15万个POD。但是由于大规模集群的维护和调度过于复杂,比如,有些企业应用需要分级,不同级别的应用需要使用不同的资源池,有些业务应用需要带有GPU支持的集群,有些应用需要Windows container的支持,甚至不同应用依赖不同版本的Kubernetes,所以在企业环境中通过多集群的方式实现多租户和资源调度已经成为了最佳实践。
当你需要管理多个集群,每个集群都有不同的规模、版本、升级计划、硬件资源池,自动化的管理工具和理念就必不可少了。
我们知道,Kubernetes的很多原则和理念改变了传统资源管理和交付的模式,其中声明式API和自愈机制的引入提升了用户部署和管理应用的效率。它允许用户通过yaml文件描述对象部署的期望状态(比如部署3个POD实例),并持续观测当前状态,如果和预期不一致(只剩2个POD实例),就通过控制器使其达到期望状态(添加1个POD实例,使总数为预期的3个)。
既然这种模式如此的成功,能不能把它适用到更多的场景中呢?比如,能不能用Kubernetes的思想来管理Kubernetes的集群呢?
实际上社区中已经有人这么做了,Cluster API 就是在这个背景下,由google,vmware等公司共同发起的项目。https://github.com/kubernetes-sigs/cluster-api
什么是Cluster API?
Cluster API是一个Kubernetes项目,它将声明式的、Kubernetes风格的API用于集群创建、配置和管理。通过利用Kubernetes API的结构化和可扩展的特性,构建更高级别的云环境无关的工具,声明式的、自动化的改善用户体验。
当前,Cluster API已经可以支持AWS, Azure, GCP, Openstack, VMware, Bare metal等绝大多数基础设施环境。在目前的版本中,该API包含五个customresourcedefinition(CRD):Cluster、Machine、MachineSet、MachineDeployment和MachineClass。
将这几个CRD和大家熟悉的Kubernetes的对象类比一下,
说明:以下的几个CRD yaml文件都可以自动生成模板,在创建cluster的时候,并不都是必须的。
Cluster这个CRD是全新的Kubernetes集群的抽象。它可以定义Kubernetes集群配置,例如POD网络CIDR和service网络CIDR,以及集群是运行在何种云平台之上。
kind: Cluster
metadata:
name: workload-cluster-1
spec:
clusterNetwork:
services:
cidrBlocks: ["100.64.0.0/13"]
pods:
cidrBlocks: ["100.96.0.0/11"]
serviceDomain: "cluster.local"
providerSpec:
value:
apiVersion: vsphere.cluster.k8s.io/v1alpha1
kind: VsphereClusterProviderSpec
server: "vcsa-01a.corp.local"
username: "administrator@vsphere.local"
sshAuthorizedKeys:
- "ssh-rsa AAAAB3N..."
Machine类似于POD,它负责描述单个Kubernetes节点(虚拟机)。只需很少的配置(主要是Kubernetes版本信息),其他配置通过嵌入云环境相关的ProviderSpec。
apiVersion: cluster.k8s.io/v1alpha1
kind: MachineList
items:
- apiVersion: cluster.k8s.io/v1alpha1
kind: Machine
metadata:
name: "workload-cluster-1-controlplane-1"
labels:
cluster.k8s.io/cluster-name: "workload-cluster-1"
spec:
providerSpec:
value:
apiVersion: vsphere.cluster.k8s.io/v1alpha1
kind: VsphereMachineProviderSpec
datacenter: "RegionA01"
datastore: "RegionA01-ISCSI01-COMP01"
resourcePool: "pks-comp-1"
folder: "vm"
network:
devices:
- networkName: "VM-RegionA01-vDS-COMP"
dhcp4: true
dhcp6: false
numCPUs: 2
memoryMiB: 2048
diskGiB: 50
template: "ubuntu-1804-kube-v1.13.6"
versions:
kubelet: "1.13.6"
controlPlane: "1.13.6"
MachineDeloyment 类似于Deployment。它允许对节点配置进行更新,定义工作节点的升级方式(rolling,recreate),它还允许回滚到以前的某个版本的配置。用户可以修改yaml文件来动态调整集群节点的数量。
apiVersion: "cluster.k8s.io/v1alpha1"
kind: MachineDeployment
metadata:
name: sample-machinedeployment
spec:
replicas: 3
template:
spec:
providerSpec:
value:
apiVersion: vsphere.cluster.k8s.io/v1alpha1
kind: VsphereMachineProviderSpec
datacenter: "RegionA01"
datastore: "RegionA01-ISCSI01-COMP01"
resourcePool: "pks-comp-1"
network:
devices:
- networkName: "VM-RegionA01-vDS-COMP"
dhcp4: true
dhcp6: false
numCPUs: 2
memoryMiB: 2048
diskGiB: 50
template: "ubuntu-1804-kube-v1.13.6"
versions:
kubelet: "1.13.6"
MachineSet类似于ReplicaSet,管理一组Machine的扩缩容。与ReplicaSet类似,实践中尽量使用MachineDeloyment来管理一组资源的部署而不应该直接操作ReplicaSet。
apiVersion: cluster.k8s.io/v1alpha1
kind: MachineSet
metadata:
name: "workload-cluster-1-machineset-1"
spec:
replicas: 2
selector:
matchLabels:
machineset-name: "workload-cluster-1-machineset-1"
cluster.k8s.io/cluster-name: "workload-cluster-1"
template:
spec:
providerSpec:
value:
apiVersion: vsphere.cluster.k8s.io/v1alpha1
kind: VsphereMachineProviderSpec
datacenter: "RegionA01"
datastore: "RegionA01-ISCSI01-COMP01"
resourcePool: "pks-comp-1"
network:
devices:
- networkName: "VM-RegionA01-vDS-COMP"
dhcp4: true
dhcp6: false
numCPUs: 2
memoryMiB: 2048
diskGiB: 50
template: "ubuntu-1804-kube-v1.13.6"
versions:
kubelet: "1.13.6"
MachineClass和StorageClass很像,定义Machine的规格。所有节点都会从指定规格的虚拟机模板中clone出来。
apiVersion: "cluster.k8s.io/v1alpha1"
kind: MachineClass
metadata:
name: vsphere-small
providerSpec:
apiVersion: vsphere.cluster.k8s.io/v1alpha1
kind: VsphereMachineProviderSpec
numCPUs: 2
memoryMiB: 2048
diskGiB: 50
template: "ubuntu-1804-kube-v1.13.6"
Cluster API是如何工作的?
Cluster API的工作原理非常简单,用户通过以上的几个CRD定义需要的Kubernetes集群的规格。通过熟悉的kubectl apply命令把yaml传递给management cluster,managerment cluster会根据需要驱动不同的云平台创建虚拟机安装部署Kubernetes binary,并交付集群给用户。
那么management cluster是怎么来的?是否后续的运维工作也需要依赖它呢?实际上,初始的management cluster一般是一个单机版的Kubernetes,比如minikube或者Kind。当置备出第一个workload cluster以后,可以将management cluster的功能转移到任何一个workload cluster,这样后续的工作就不在依赖单机版的Kubernetes。一个有意思的地方是,你会发现,某一个workload cluster同时也是management cluster,在管理和监控着它自己。
下面是一个在vsphere环境使用Cluster API的例子。
首先,使用Cluster API项目提供的工具生成一组部署的yaml模板。
$ docker run --rm \
-v "$(pwd)":/out \
-v "$(pwd)/envvars.txt":/envvars.txt:ro \
gcr.io/cluster-api-provider-vsphere/release/manifests:latest \
-c workload-cluster-1
根据需求调整yaml文件中的内容,比如虚拟机模板的名称、集群节点的数量等。
然后依次创建这些资源对象,
$ kubectl apply -f ./out/workload-cluster-1/cluster.yaml
cluster.cluster.k8s.io/workload-cluster-1 created
$ kubectl apply -f ./out/workload-cluster-1/machines.yaml
machine.cluster.k8s.io/workload-cluster-1-controlplane-1 created
$ kubectl apply -f ./out/workload-cluster-1/machineset.yaml
machineset.cluster.k8s.io/workload-cluster-1-machineset-1 created
这时可以在vcenter中看到Kubernetes集群的虚拟机陆续被创建出来。
大约几分钟后,workload cluster就可以交付给用户使用了。
我们可以关闭或者删除一个workload cluster的节点的虚拟机来模拟故障场景。Cluster API会自动检测所有节点的状态,并且驱动vsphere重新生成一个虚拟机进行替代,使得Kubernetes集群的状态与预期描述的一致。像不像Kubernetes管理POD的功能?
以上实验的具体的细节可参考官方文档,https://github.com/kubernetes-sigs/cluster-api-provider-vsphere/blob/master/docs/getting_started.md
解决多集群生命周期的管理只是企业环境使用Kubernetes的第一步,后续还有什么问题是需要考虑的?
-
权限和资源管理。如何将企业内部不同业务部门和基础设施的资源池匹配起来,并配置合理的权限。
-
日常运维相关。集群的备份恢复、合规状态检查、策略变更和监控等功能。