Cluster API是一个Kubernetes项目,它将声明式Kubernetes风格的API用于集群的建立、配置和管理。它经过使用时CustomResourceDefinitions(CRDs)来扩展被Kubernetes API Server暴露的API来实现这些功能,从而容许用户建立新资源,例如集群(指Kubernetes集群)和Machine(指组成集群的节点的Machine)。而后每一个资源的控制器负责对这些资源的更改作出反应,以启动集群。API的设计可让不一样的基础架构提供程序能够与其集成,进而提供针对其环境的特定逻辑。html
Cluster API项目仍处于早期阶段,可是当前的状况已经证实了它能带来强大的功能。这篇文章的目的是总结迄今为止该项目的功能,并展望后续版本的功能。node
过去、如今和将来
撰写这篇文章的时候,Cluster API最新发布的版本实现了v1alpha2。在这里,咱们将讨论该API的转换以及提供程序如何与之集成。nginx
过去:v1alpha1
最初,Cluster API的v1alpha1实现要求提供程序须要在其项目中包含Cluster API控制器代码,并实现actuator(接口)以处理其环境的特定逻辑(例如,对云提供程序API的调用)。该代码做为特定于某个提供程序的管理器二进制文件运行,该二进制文件能够为管理集群所需的每一个资源管理一个控制器。git
如今:v1alpha2
使用Cluster API 的v1alpha1方法存在一个痛点,即它要求每一个提供程序都实现必定数量的bootstrap boilerplate code,即代码不灵活而且冗长。为了解决这个问题,v1alpha2引入了bootstrap provider,它们负责生成将Machine转变为Kubernetes节点所需的数据。Kubeadm bootstrap provider则经过使用kubedam在全部环境中处理此任务。它的默认行为是为每台Machine生成一个可用于bootstrap节点的cloud-config脚本。github
v1alpha2引入的另外一个更改是,提供程序再也不须要将Cluster API控制器代码包含在其项目中。并且Cluster API提供了对核心类型负责的独立控制器。有关这些更改的更多信息,请参阅Github上的信息。json
对于此版本,如今须要部署3个管理器(而不是此前的1个):bootstrap
-
Cluster API manager:用于管理核心v1alpha2资源api
-
Bootstrap provider manager:用于管理资源以生成将Machine转变为Kubernetes节点的数据bash
-
Infrastructure provider manager:用于管理提供运行集群所需基础架构的资源网络
例如,若是我想使用kubedam在配置好的GCP上建立一个集群,我应该部署Cluster API manager(用于调和核心资源,例如集群和Machine资源),kubeadm bootstrap provider(例如,用于调和KubeadmConfig资源)以及GCP infrastructure provider(用于调和环境的特定资源,如GCPClusters和GCPMachines)。
为了了解如何应用这些资源,咱们将使用我编写的Kubernetes基础架构提供程序实现来进行集群部署,即由Kubernetes自己提供基础架构的提供程序。Kubernetes节点使用kind镜像做为Kubernetes Pod运行。
首先,咱们须要建立一个基础集群来为咱们的Cluster API集群提供基础架构。咱们将使用GKE。如下命令假定你已安装gcloud和GCP项目并设置了账户。
警告:gcloud命令将产生一些花费,你也能够考虑使用GCP免费套餐。
Calico将做为Cluster API集群的CNI解决方案。在配置GKE集群以路由IPv4封装的数据包时,须要一些特殊的配置。为了避免分散本文关于Cluster API行为的描述,咱们将在此处直接运行它们,不作详细解释。有关详细信息,能够参考Kubernetes基础架构提供程序代码库。
gcloud container clusters create management-cluster --cluster-version=1.14 --image-type=UBUNTU CLUSTER_CIDR=$(gcloud container clusters describe management-cluster --format="value(clusterIpv4Cidr)") gcloud compute firewall-rules create allow-management-cluster-pods-ipip --source-ranges=$CLUSTER_CIDR --allow=ipip kubectl apply -f <(cat <<EOF apiVersion: apps/v1 kind: DaemonSet metadata: name: forward-ipencap namespace: kube-system labels: app: forward-ipencap spec: selector: matchLabels: name: forward-ipencap template: metadata: labels: name: forward-ipencap spec: hostNetwork: true initContainers: - name: forward-ipencap command: - sh - -c - | apk add iptables iptables -C FORWARD -p ipencap -j ACCEPT || iptables -A FORWARD -p ipencap -j ACCEPT image: alpine:3.11 securityContext: capabilities: add: ["NET_ADMIN"] containers: - name: sleep-forever image: alpine:3.11 command: ["tail"] args: ["-f", "/dev/null"] EOF )
配置了GKE集群后,咱们如今能够开始部署必要的管理器(manager)。
# Install cluster api manager kubectl apply -f https://github.com/kubernetes-sigs/cluster-api/releases/download/v0.2.8/cluster-api-components.yaml # Install kubeadm bootstrap provider kubectl apply -f https://github.com/kubernetes-sigs/cluster-api-bootstrap-provider-kubeadm/releases/download/v0.1.5/bootstrap-components.yaml # Install kubernetes infrastructure provider kubectl apply -f https://github.com/dippynark/cluster-api-provider-kubernetes/releases/download/v0.2.1/provider-components.yaml # Allow cluster api controller to interact with kubernetes infrastructure resources # If the kubernetes provider were SIG-sponsored this would not be necesarry ;) # https://cluster-api.sigs.k8s.io/providers/v1alpha1-to-v1alpha2.html#the-new-api-groups kubectl apply -f https://github.com/dippynark/cluster-api-provider-kubernetes/releases/download/v0.2.1/capi-kubernetes-rbac.yaml
如今,咱们能够部署咱们的集群。
kubectl apply -f <(cat <<EOF apiVersion: infrastructure.lukeaddison.co.uk/v1alpha2 kind: KubernetesCluster metadata: name: example spec: controlPlaneServiceType: LoadBalancer --- apiVersion: cluster.x-k8s.io/v1alpha2 kind: Cluster metadata: name: example spec: clusterNetwork: services: cidrBlocks: ["172.16.0.0/12"] pods: cidrBlocks: ["192.168.0.0/16"] serviceDomain: "cluster.local" infrastructureRef: apiVersion: infrastructure.lukeaddison.co.uk/v1alpha2 kind: KubernetesCluster name: example EOF )
在这里,咱们定义了特定于环境的KubernetesCluster资源。这将为运行Kubernetes集群提供必要的基础架构组件。例如,GCPCluster可能会提供VPC、防火墙规则和负载均衡器以访问API Server。而咱们的KubernetesCluster只为API Server设置了LoadBalancer类型的Kubernetes服务。咱们能够查询KubernetesCluster来查看其状态。
$ kubectl get kubernetescluster NAME PHASE HOST PORT AGE example Provisioned 35.205.255.206 443 51s
咱们从核心集群资源中引用特定于提供程序的集群资源,该资源提供了集群的网络详细信息。KubernetesCluster将被修改成由集群资源所拥有。
如今,咱们准备部署咱们的Machine。在这里,咱们建立一个controller Machine,它引用infrastructure provider中特定的KubernetesMachine资源以及bootstrap provider中特定的KubeadmConfig资源。
kubectl apply -f <(cat <<EOF apiVersion: bootstrap.cluster.x-k8s.io/v1alpha2 kind: KubeadmConfig metadata: name: controller spec: initConfiguration: nodeRegistration: kubeletExtraArgs: eviction-hard: nodefs.available<0%,nodefs.inodesFree<0%,imagefs.available<0% cgroups-per-qos: "false" enforce-node-allocatable: "" clusterConfiguration: controllerManager: extraArgs: enable-hostpath-provisioner: "true" --- apiVersion: infrastructure.lukeaddison.co.uk/v1alpha2 kind: KubernetesMachine metadata: name: controller --- apiVersion: cluster.x-k8s.io/v1alpha2 kind: Machine metadata: name: controller labels: cluster.x-k8s.io/cluster-name: example cluster.x-k8s.io/control-plane: "true" spec: version: "v1.17.0" bootstrap: configRef: apiVersion: bootstrap.cluster.x-k8s.io/v1alpha2 kind: KubeadmConfig name: controller infrastructureRef: apiVersion: infrastructure.lukeaddison.co.uk/v1alpha2 kind: KubernetesMachine name: controller EOF )
kubeadm bootstrap provider将KubeadmConfig资源转换为cloud-config
脚本,Kubernetes infrastructure provider使用该脚原本bootstrap Kubernetes Pod以造成新集群的控制平面。
Kubernetes infrastructure provider经过依靠systemd(它做为kind镜像的一部分运行)来实现这一目的。而后从cloud-config脚本生成一个bash脚本,以建立和运行指定的文件和命令。使用Kubernetes Secret将脚本安装到Pod中,当containerd socket可使用以后,就使用systemd路径单元触发该脚本。你能够到controller pod中执行,并运行journalctl -u cloud-init
来查看此脚本的输出。cat /opt/cloud-init/bootstrap.sh
将显示完整脚本。
Kubelet运行以后,它将经过在etcd中建立controller Node对象(也在controller Pod上运行)向集群注册本身。
如今,咱们能够部署咱们的worker Machine了。这看起来与controller Machine 配置很是相似,但咱们还会利用MachineDeployment、KubeadmConfigTemplate和KubernetesMachineTemplate来请求worker节点的多个副本。
kubectl apply -f <(cat <<EOF apiVersion: infrastructure.lukeaddison.co.uk/v1alpha2 kind: KubernetesMachineTemplate metadata: name: worker spec: template: spec: {} --- apiVersion: bootstrap.cluster.x-k8s.io/v1alpha2 kind: KubeadmConfigTemplate metadata: name: worker spec: template: spec: joinConfiguration: nodeRegistration: kubeletExtraArgs: eviction-hard: nodefs.available<0%,nodefs.inodesFree<0%,imagefs.available<0% cgroups-per-qos: "false" enforce-node-allocatable: "" --- apiVersion: cluster.x-k8s.io/v1alpha2 kind: MachineDeployment metadata: name: worker labels: cluster.x-k8s.io/cluster-name: example nodepool: default spec: replicas: 3 selector: matchLabels: cluster.x-k8s.io/cluster-name: example nodepool: default template: metadata: labels: cluster.x-k8s.io/cluster-name: example nodepool: default spec: version: "v1.17.0" bootstrap: configRef: apiVersion: bootstrap.cluster.x-k8s.io/v1alpha2 kind: KubeadmConfigTemplate name: worker infrastructureRef: apiVersion: infrastructure.lukeaddison.co.uk/v1alpha2 kind: KubernetesMachineTemplate name: worker EOF )
MachineDeployments与Kubernetes Deployment工做方式十分类似,由于它们管理MachineSets,后者还管理所需数量的Machines副本。
如今,咱们应该可以查询已经配置的Machine,以查看其状态。
$ kubectl get machines NAME PROVIDERID PHASE controller kubernetes://871cde5a-3159-11ea-a1c6-42010a840084 provisioning worker-6c498c48db-4grxq pending worker-6c498c48db-66zk7 pending worker-6c498c48db-k5kkp pending
咱们还能够看到相应的KubernetesMachines。
$ kubectl get kubernetesmachines NAME PROVIDER-ID PHASE AGE controller kubernetes://871cde5a-3159-11ea-a1c6-42010a840084 Provisioning 53s worker-cs95w Pending 35s worker-kpbhm Pending 35s worker-pxsph Pending 35s
不久,全部KubernetesMachines都应处于运行状态。
$ kubectl get kubernetesmachines NAME PROVIDER-ID PHASE AGE controller kubernetes://871cde5a-3159-11ea-a1c6-42010a840084 Running 2m worker-cs95w kubernetes://bcd10f28-3159-11ea-a1c6-42010a840084 Running 1m worker-kpbhm kubernetes://bcd4ef33-3159-11ea-a1c6-42010a840084 Running 1m worker-pxsph kubernetes://bccd1af4-3159-11ea-a1c6-42010a840084 Running 1m
咱们还能够看到与你的KubernetesMachines相对应的Pod。
$ kubectl get pods NAME READY STATUS RESTARTS AGE controller 1/1 Running 0 2m11s worker-cs95w 1/1 Running 0 111s worker-kpbhm 1/1 Running 0 111s worker-pxsph 1/1 Running 0 111s
Cluster API manager生成一个kubeconfig并将其保存为一个Kubernetes Secret,名为<clusterName>-kubeconfig
。咱们能够检索它并访问集群。
$ kubectl get secret example-kubeconfig -o jsonpath='{.data.value}' | base64 --decode > example-kubeconfig $ export KUBECONFIG=example-kubeconfig $ kubectl get nodes NAME STATUS ROLES AGE VERSION controller NotReady master 3m16s v1.17.0 worker-cs95w NotReady <none> 2m34s v1.17.0 worker-kpbhm NotReady <none> 2m32s v1.17.0 worker-pxsph NotReady <none> 2m34s v1.17.0
最后,能够应用咱们的Calico CNI解决方案。节点应该很快就准备就绪。
$ kubectl apply -f https://docs.projectcalico.org/v3.11/manifests/calico.yaml $ kubectl get nodes NAME STATUS ROLES AGE VERSION controller Ready master 5m8s v1.17.0 worker-cs95w Ready <none> 4m26s v1.17.0 worker-kpbhm Ready <none> 4m24s v1.17.0 worker-pxsph Ready <none> 4m26s v1.17.0
如今,咱们能够在全新的集群上运行工做负载:
kubectl run nginx --image=nginx --replicas=3
对于其余基础设施提供程序,流程相似。你还能够在Cluster API文档中的快速入门部分找到许多其余示例。
将来:v1alpha3以及更高级的版本
咱们仅仅是根据当前的状况进行延展,探讨Cluster API可能提供的功能。此外,咱们还将讨论roadmap上的其余一些有趣的事情。
机器健康检查(MachineHealthCheck)
在v1alpha2中,特定于基础架构的Machine能够将其自身标记为故障,而且状态将上升到owning Machine,可是owning MachineSet不执行任何操做。这样作是由于,除了MachineSet以外的其余资源均可以拥有Machine,所以将Machine修复逻辑与MachineSet分离是有意义的。
MachineHealthCheck是一种建议的资源,用于描述节点的故障状况并在发生故障时删除相应的Machine。这将触发适当的删除行为(例如,驱散)和任何控制资源来启动替换Machine。
Kubeadm控制平面(KubeadmControlPlane)
当前,建立一个高可用控制平面并管理它一般须要使用正确的bootstrap配置(须要以正确的顺序启动)仔细配置独立的controller Machine。v1alpha3则但愿经过初始的kubeadm控制平面实现来支持控制平台提供程序。从infrastructure provider的角度来看,这机会不须要进行任何更改,可是将容许用户管理控制平面的实例化和弹性伸缩,而无需手动建立相应的Machine。关于此功能,你能够查看Github上相关页面获取更多信息。
与MachineHealthChecks一块儿使用,可使用Cluster API进行控制平面自动修复。
集群自动伸缩(Cluster Autoscaler)
Cluster Autoscaler是能够利用Cluster API的项目的一个示例。当前的实现要求每一个受支持的云提供程序都实现扩展其环境中的实例组所需的CloudProvider和NodeGroup接口。随着Cluster API的出现,能够经过与Cluster API资源交互而不是直接与提供程序特定的API交互,来实现自动弹性伸缩逻辑,而且没有厂商锁定。
总 结
咱们已经对Cluster API的当前功能以及不久的未来进行了深刻的研究。该项目看起来十分强大而且完整,这使人激动。做为一个与Kubernetes相关的开源项目,Cluster API也是十分开放的,你能够经过各类渠道提出建议或是作出本身的贡献。