作者:Luke Addison

原文链接:https://blog.jetstack.io/blog/cluster-api-past-present-and-future/

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基础架构提供程序代码库

  1. gcloud container clusters create management-cluster --cluster-version=1.14 --image-type=UBUNTU
  2. CLUSTER_CIDR=$(gcloud container clusters describe management-cluster --format="value(clusterIpv4Cidr)")
  3. gcloud compute firewall-rules create allow-management-cluster-pods-ipip --source-ranges=$CLUSTER_CIDR --allow=ipip
  4. kubectl apply -f <(cat <<EOF
  5. apiVersion: apps/v1
  6. kind: DaemonSet
  7. metadata:
  8. name: forward-ipencap
  9. namespace: kube-system
  10. labels:
  11. app: forward-ipencap
  12. spec:
  13. selector:
  14. matchLabels:
  15. name: forward-ipencap
  16. template:
  17. metadata:
  18. labels:
  19. name: forward-ipencap
  20. spec:
  21. hostNetwork: true
  22. initContainers:
  23. - name: forward-ipencap
  24. command:
  25. - sh
  26. - -c
  27. - |
  28. apk add iptables
  29. iptables -C FORWARD -p ipencap -j ACCEPT || iptables -A FORWARD -p ipencap -j ACCEPT
  30. image: alpine:3.11
  31. securityContext:
  32. capabilities:
  33. add: ["NET_ADMIN"]
  34. containers:
  35. - name: sleep-forever
  36. image: alpine:3.11
  37. command: ["tail"]
  38. args: ["-f", "/dev/null"]
  39. EOF
  40. )

配置了GKE集群后,我们现在可以开始部署必要的管理器(manager)。

  1. # Install cluster api manager
  2. kubectl apply -f https://github.com/kubernetes-sigs/cluster-api/releases/download/v0.2.8/cluster-api-components.yaml
  3. # Install kubeadm bootstrap provider
  4. kubectl apply -f https://github.com/kubernetes-sigs/cluster-api-bootstrap-provider-kubeadm/releases/download/v0.1.5/bootstrap-components.yaml
  5. # Install kubernetes infrastructure provider
  6. kubectl apply -f https://github.com/dippynark/cluster-api-provider-kubernetes/releases/download/v0.2.1/provider-components.yaml
  7. # Allow cluster api controller to interact with kubernetes infrastructure resources
  8. # If the kubernetes provider were SIG-sponsored this would not be necesarry ;)
  9. # https://cluster-api.sigs.k8s.io/providers/v1alpha1-to-v1alpha2.html#the-new-api-groups
  10. kubectl apply -f https://github.com/dippynark/cluster-api-provider-kubernetes/releases/download/v0.2.1/capi-kubernetes-rbac.yaml

现在,我们可以部署我们的集群。

  1. kubectl apply -f <(cat <<EOF
  2. apiVersion: infrastructure.lukeaddison.co.uk/v1alpha2
  3. kind: KubernetesCluster
  4. metadata:
  5. name: example
  6. spec:
  7. controlPlaneServiceType: LoadBalancer
  8. ---
  9. apiVersion: cluster.x-k8s.io/v1alpha2
  10. kind: Cluster
  11. metadata:
  12. name: example
  13. spec:
  14. clusterNetwork:
  15. services:
  16. cidrBlocks: ["172.16.0.0/12"]
  17. pods:
  18. cidrBlocks: ["192.168.0.0/16"]
  19. serviceDomain: "cluster.local"
  20. infrastructureRef:
  21. apiVersion: infrastructure.lukeaddison.co.uk/v1alpha2
  22. kind: KubernetesCluster
  23. name: example
  24. EOF
  25. )

在这里,我们定义了特定于环境的KubernetesCluster资源。这将为运行Kubernetes集群提供必要的基础架构组件。例如,GCPCluster可能会提供VPC、防火墙规则和负载均衡器以访问API Server。而我们的KubernetesCluster只为API Server设置了LoadBalancer类型的Kubernetes服务。我们可以查询KubernetesCluster来查看其状态。

  1. $ kubectl get kubernetescluster
  2. NAME PHASE HOST PORT AGE
  3. example Provisioned 35.205.255.206 443 51s

我们从核心集群资源中引用特定于提供程序的集群资源,该资源提供了集群的网络详细信息。KubernetesCluster将被修改为由集群资源所拥有。

现在,我们准备部署我们的Machine。在这里,我们创建一个controller Machine,它引用infrastructure provider中特定的KubernetesMachine资源以及bootstrap provider中特定的KubeadmConfig资源。

  1. kubectl apply -f <(cat <<EOF
  2. apiVersion: bootstrap.cluster.x-k8s.io/v1alpha2
  3. kind: KubeadmConfig
  4. metadata:
  5. name: controller
  6. spec:
  7. initConfiguration:
  8. nodeRegistration:
  9. kubeletExtraArgs:
  10. eviction-hard: nodefs.available<0%,nodefs.inodesFree<0%,imagefs.available<0%
  11. cgroups-per-qos: "false"
  12. enforce-node-allocatable: ""
  13. clusterConfiguration:
  14. controllerManager:
  15. extraArgs:
  16. enable-hostpath-provisioner: "true"
  17. ---
  18. apiVersion: infrastructure.lukeaddison.co.uk/v1alpha2
  19. kind: KubernetesMachine
  20. metadata:
  21. name: controller
  22. ---
  23. apiVersion: cluster.x-k8s.io/v1alpha2
  24. kind: Machine
  25. metadata:
  26. name: controller
  27. labels:
  28. cluster.x-k8s.io/cluster-name: example
  29. cluster.x-k8s.io/control-plane: "true"
  30. spec:
  31. version: "v1.17.0"
  32. bootstrap:
  33. configRef:
  34. apiVersion: bootstrap.cluster.x-k8s.io/v1alpha2
  35. kind: KubeadmConfig
  36. name: controller
  37. infrastructureRef:
  38. apiVersion: infrastructure.lukeaddison.co.uk/v1alpha2
  39. kind: KubernetesMachine
  40. name: controller
  41. EOF
  42. )

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节点的多个副本。

  1. kubectl apply -f <(cat <<EOF
  2. apiVersion: infrastructure.lukeaddison.co.uk/v1alpha2
  3. kind: KubernetesMachineTemplate
  4. metadata:
  5. name: worker
  6. spec:
  7. template:
  8. spec: {}
  9. ---
  10. apiVersion: bootstrap.cluster.x-k8s.io/v1alpha2
  11. kind: KubeadmConfigTemplate
  12. metadata:
  13. name: worker
  14. spec:
  15. template:
  16. spec:
  17. joinConfiguration:
  18. nodeRegistration:
  19. kubeletExtraArgs:
  20. eviction-hard: nodefs.available<0%,nodefs.inodesFree<0%,imagefs.available<0%
  21. cgroups-per-qos: "false"
  22. enforce-node-allocatable: ""
  23. ---
  24. apiVersion: cluster.x-k8s.io/v1alpha2
  25. kind: MachineDeployment
  26. metadata:
  27. name: worker
  28. labels:
  29. cluster.x-k8s.io/cluster-name: example
  30. nodepool: default
  31. spec:
  32. replicas: 3
  33. selector:
  34. matchLabels:
  35. cluster.x-k8s.io/cluster-name: example
  36. nodepool: default
  37. template:
  38. metadata:
  39. labels:
  40. cluster.x-k8s.io/cluster-name: example
  41. nodepool: default
  42. spec:
  43. version: "v1.17.0"
  44. bootstrap:
  45. configRef:
  46. apiVersion: bootstrap.cluster.x-k8s.io/v1alpha2
  47. kind: KubeadmConfigTemplate
  48. name: worker
  49. infrastructureRef:
  50. apiVersion: infrastructure.lukeaddison.co.uk/v1alpha2
  51. kind: KubernetesMachineTemplate
  52. name: worker
  53. EOF
  54. )

MachineDeployments与Kubernetes Deployment工作方式十分相似,因为它们管理MachineSets,后者还管理所需数量的Machines副本。

现在,我们应该能够查询已经配置的Machine,以查看其状态。

  1. $ kubectl get machines
  2. NAME PROVIDERID PHASE
  3. controller kubernetes://871cde5a-3159-11ea-a1c6-42010a840084 provisioning
  4. worker-6c498c48db-4grxq pending
  5. worker-6c498c48db-66zk7 pending
  6. worker-6c498c48db-k5kkp pending

我们还可以看到相应的KubernetesMachines。

  1. $ kubectl get kubernetesmachines
  2. NAME PROVIDER-ID PHASE AGE
  3. controller kubernetes://871cde5a-3159-11ea-a1c6-42010a840084 Provisioning 53s
  4. worker-cs95w Pending 35s
  5. worker-kpbhm Pending 35s
  6. worker-pxsph Pending 35s

不久,所有KubernetesMachines都应处于运行状态。

  1. $ kubectl get kubernetesmachines
  2. NAME PROVIDER-ID PHASE AGE
  3. controller kubernetes://871cde5a-3159-11ea-a1c6-42010a840084 Running 2m
  4. worker-cs95w kubernetes://bcd10f28-3159-11ea-a1c6-42010a840084 Running 1m
  5. worker-kpbhm kubernetes://bcd4ef33-3159-11ea-a1c6-42010a840084 Running 1m
  6. worker-pxsph kubernetes://bccd1af4-3159-11ea-a1c6-42010a840084 Running 1m

我们还可以看到与你的KubernetesMachines相对应的Pod。

  1. $ kubectl get pods
  2. NAME READY STATUS RESTARTS AGE
  3. controller 1/1 Running 0 2m11s
  4. worker-cs95w 1/1 Running 0 111s
  5. worker-kpbhm 1/1 Running 0 111s
  6. worker-pxsph 1/1 Running 0 111s

Cluster API manager生成一个kubeconfig并将其保存为一个Kubernetes Secret,名为<clusterName>-kubeconfig。我们可以检索它并访问集群。

  1. $ kubectl get secret example-kubeconfig -o jsonpath='{.data.value}' | base64 --decode > example-kubeconfig
  2. $ export KUBECONFIG=example-kubeconfig
  3. $ kubectl get nodes
  4. NAME STATUS ROLES AGE VERSION
  5. controller NotReady master 3m16s v1.17.0
  6. worker-cs95w NotReady <none> 2m34s v1.17.0
  7. worker-kpbhm NotReady <none> 2m32s v1.17.0
  8. worker-pxsph NotReady <none> 2m34s v1.17.0

最后,可以应用我们的Calico CNI解决方案。节点应该很快就准备就绪。

  1. $ kubectl apply -f https://docs.projectcalico.org/v3.11/manifests/calico.yaml
  2. $ kubectl get nodes
  3. NAME STATUS ROLES AGE VERSION
  4. controller Ready master 5m8s v1.17.0
  5. worker-cs95w Ready <none> 4m26s v1.17.0
  6. worker-kpbhm Ready <none> 4m24s v1.17.0
  7. 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也是十分开放的,你可以通过各种渠道提出建议或是做出自己的贡献。

一文讲透Cluster API的前世、今生与未来的更多相关文章

  1. 一文讲透Dubbo负载均衡之最小活跃数算法

    本文是对于Dubbo负载均衡策略之一的最小活跃数算法的详细分析.文中所示源码,没有特别标注的地方均为2.6.0版本. 为什么没有用截止目前的最新的版本号2.7.4.1呢?因为2.6.0这个版本里面有两 ...

  2. 从零入门 Serverless | 一文讲透 Serverless Kubernetes 容器服务

    作者 | 张维(贤维) 阿里云函数计算开发工程师 导读:Serverless Kubernetes 是以容器和 kubernetes 为基础的 Serverless 服务,它提供了一种简单易用.极致弹 ...

  3. 一文讲透静电放电(ESD)保护(转发)

    一直想给大家讲讲ESD的理论,很经典.但是由于理论性太强,任何理论都是一环套一环的,如果你不会画鸡蛋,注定了你就不会画大卫. 先来谈静电放电(ESD: Electrostatic Discharge) ...

  4. 一文讲透Java序列化

    本文目录 一.序列化是什么 二.为什么需要序列化 三.序列化怎么用 四.序列化深度探秘 4.1 为什么必须实现Serializable接口 4.2 被序列化对象的字段是引用时该怎么办 4.3 同一个对 ...

  5. 一文讲透APaaS平台是什么

    关注「开源Linux」,选择"设为星标" 回复「学习」,有我为您特别筛选的学习资料~ 互联网行业就喜欢搞一些单词的缩写,在云计算行业,前者有SaaS.PaaS.IaaS,最近两三年 ...

  6. 一文讲透为Power Automate for Desktop (PAD) 实现自定义模块 - 附完整代码

    概述 Power Automate for Desktop (以下简称PAD)是微软推出的一款针对Windows桌面端的免费RPA(机器人流程自动化)工具,它目前默认会随着Windows 11安装,但 ...

  7. 一文讲透Modbus协议

    前言 Modbus是一种串行通讯协议,是Modicon公司(现在的施耐德电气 Schneider Electric) 于1979年为使用可编程逻辑控制器(PLC)通信而发表.Modbus已经成为工业领 ...

  8. 终于有人把Elasticsearch原理讲透了!

    终于有人把Elasticsearch原理讲透了! http://developer.51cto.com/art/201904/594615.htm 小史是一个非科班的程序员,虽然学的是电子专业,但是通 ...

  9. (转)终于有人把Elasticsearch原理讲透了!

    终于有人把Elasticsearch原理讲透了! 小史是一个非科班的程序员,虽然学的是电子专业,但是通过自己的努力成功通过了面试,现在要开始迎接新生活了. 来源:互联网侦察 | 2019-04-08 ...

随机推荐

  1. 设计模式 - 模板方法模式详解及其在Spring中的应用

    基本介绍 模板方法模式(Template Method Pattern)也叫模板模式,它在一个抽象类中公开定义了执行它的方法的模板,它的字类可以按需重写方法实现,但调用将以抽象类中定义的方式进行. 简 ...

  2. Mybatis Generator通用Join的实现

    通常,我们使用Mybatis实现join表关联的时候,一般都是通过在xml或注解里写自定义sql实现. 本文通过Mybatis Generator的插件功能新增一个JoinPlugin插件,只要在配置 ...

  3. STM32 i2c通讯失败复位方法

    最近在调研STM32 F10X,准备把公司AVR的MCU项目迁移到STM32上.在调研STM32 i2c这一部分时,在与i2c slave硬件连接断开后,这时再去读/写 i2c slave需要STM3 ...

  4. tp5 -- 控制器的参数

    方法的参数是可以直接获取的到get和post这集中提交格式的数据的. 但是呢. 前置操作时不能这样操作的, 只能老老实实的使用input()这个方法来获取!!!

  5. thinkphp 5 一些常见问题

    ##  请求缓存 request_cache        

  6. 一,连接Oracle 一

    连接Oracle数据库方法: 一,使用sqlplus连接 二,使用第三方软件连接 sqlplus sqlplus 工具简介 (1).概述:sqlplus是在Linux下操作oracle的工具 (2). ...

  7. 2019-2020-1 20199329《Linux内核原理与分析》第十二周作业

    <Linux内核原理与分析>第十二周作业 一.本周内容概述: 通过编程理解 Set-UID 的运行机制与安全问题 完成实验楼上的<SET-UID程序漏洞实验> 二.本周学习内容 ...

  8. 【Linux常见命令】cd命令

    BASH_BUILTINS(1) cd命令用于切换当前工作目录至 dirName(目录参数). 其中 dirName 表示法可为绝对路径或相对路径.若目录名称省略,则变换至使用者的 home 目录 ( ...

  9. 老男孩教育每日一题-2017年3月29日-使用ifconfig取出网卡eth0的ip地址-看看你有多少方法...

    方法1:sed命令 [root@oldboyedu ~]# ifconfig eth0 |sed -n '2p' |sed's#^.*addr:##g'|sed 's#  B.*$##g' 10.0. ...

  10. Linked List-2

    三.编码技巧 1.遍历链表 先将head指针赋值给一个局部变量current: //return the number of nodes in a list (while-loop version) ...