一文讲透Cluster API的前世、今生与未来
Cluster API是一个Kubernetes项目,它将声明式Kubernetes风格的API用于集群的创建、配置和管理。它通过使用时CustomResourceDefinitions(CRDs)来扩展被Kubernetes API Server暴露的API来实现这些功能,从而允许用户创建新资源,例如集群(指Kubernetes集群)和Machine(指组成集群的节点的Machine)。然后每个资源的控制器负责对这些资源的更改做出反应,以启动集群。API的设计可以让不同的基础架构提供程序可以与其集成,进而提供针对其环境的特定逻辑。
Cluster API项目仍处于早期阶段,但是当前的情况已经证明了它能带来强大的功能。这篇文章的目的是总结迄今为止该项目的功能,并展望后续版本的功能。
过去、现在和未来
撰写这篇文章的时候,Cluster API最新发布的版本实现了v1alpha2。在这里,我们将讨论该API的转换以及提供程序如何与之集成。
过去:v1alpha1
最初,Cluster API的v1alpha1实现要求提供程序需要在其项目中包含Cluster API控制器代码,并实现actuator(接口)以处理其环境的特定逻辑(例如,对云提供程序API的调用)。该代码作为特定于某个提供程序的管理器二进制文件运行,该二进制文件可以为管理集群所需的每个资源管理一个控制器。
现在:v1alpha2
使用Cluster API 的v1alpha1方法存在一个痛点,即它要求每个提供程序都实现一定数量的bootstrap boilerplate code,即代码不灵活并且冗长。为了解决这个问题,v1alpha2引入了bootstrap provider,它们负责生成将Machine转变为Kubernetes节点所需的数据。Kubeadm bootstrap provider则通过使用kubedam在所有环境中处理此任务。它的默认行为是为每台Machine生成一个可用于bootstrap节点的cloud-config脚本。
v1alpha2引入的另一个更改是,提供程序不再需要将Cluster API控制器代码包含在其项目中。而且Cluster API提供了对核心类型负责的独立控制器。有关这些更改的更多信息,请参阅Github上的信息。
对于此版本,现在需要部署3个管理器(而不是此前的1个):
-
Cluster API manager:用于管理核心v1alpha2资源
-
Bootstrap provider manager:用于管理资源以生成将Machine转变为Kubernetes节点的数据
-
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也是十分开放的,你可以通过各种渠道提出建议或是做出自己的贡献。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Apache RocketMQ 的 Service Mesh 开源之旅
作者 |凌楚阿里巴巴开发工程师 导读:自 19 年底开始,支持 Apache RocketMQ 的 Network Filter 历时 4 个月的 Code Review(Pull Request),于本月正式合入 CNCF Envoy 官方社区(RocketMQ Proxy Filter 官方文档),这使得 RocketMQ 成为继 Dubbo 之后,国内第二个成功进入 Service Mesh 官方社区的中间件产品。 Service Mesh 下的消息收发 主要流程如下图: 图 1 简述一下 Service Mesh 下 RocketMQ 消息的发送与消费过程: Pilot 获取到 Topic 的路由信息并通过 xDS 的形式下发给数据平面/Envoy ,Envoy 会代理 SDK 向 Broker/Nameserver 发送的所有的网络请求; 发送时,Envoy 通过 request code 判断出请求为发送,并根据 topic 和 request code 选出对应的 CDS,然后通过 Envoy 提供的负载均衡策略选出对应的 Broker 并发送,这里会使用数据平面的 su...
- 下一篇
做 Java 开发的你,有编译过自己的 JDK 玩玩儿吗
我是风筝,公众号「古时的风筝」,一个不只有技术的技术公众号,一个在程序圈混迹多年,主业 Java,另外 Python、React 也玩儿的 6 的斜杠开发者。 Spring Cloud 系列文章已经完成,可以到 我的github 上查看系列完整内容。也可以在公众号内回复「pdf」获取我精心制作的 pdf 版完整教程。 你每天写的 Java 代码都需要 JDK 的支持,都要跑在 JVM 上,难道你就不好奇 JDK 长什么样子吗。好奇,就来编译并实现一个自己的 JDK 吧。 本次编译环境 macOS 10.12,编译的是 JDK 11 版本。 安装 OpenJDK 11 编译 OpenJDK 需要先在机器上安装 OpenJDK 10 或者 OpenJDK 11,作为 Boot JDK。 先安装 openJDK 11 编译需要,可以到 adoptopenjdk 网站去下载。 pkg 格式安装 进入页面 https://adoptopenjdk.net/index.html?variant=openjdk11&jvmVariant=hotspot 直接下载下载,然后双击就可以完成安装了...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7,8上快速安装Gitea,搭建Git服务器
- SpringBoot2全家桶,快速入门学习开发网站教程
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- 设置Eclipse缩进为4个空格,增强代码规范
- Red5直播服务器,属于Java语言的直播服务器
- 2048小游戏-低调大师作品
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- Windows10,CentOS7,CentOS8安装Nodejs环境
- SpringBoot2整合Redis,开启缓存,提高访问速度
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装