👉️URL: https://crossplane.io/

📝Description:

将云基础架构和服务组成自定义平台 API

简介

在 11 月的 KCD 上海现场,听了一场阿里云的工程师关于他们自己的多云基础架构管理工具的介绍,前边的引言部分有介绍到 Terraform,还有另一款竞品就是 Crossplane,而且表示 Crossplane 在通用性 API 等方面做得比 Terraform 更好,阿里云的也参考了其架构和实现。就让我很感兴趣,同时在 2019 年使用 OpenShift 4 的时候也在其 OperatorHub 里有发现 Crossplane,当时觉得其 Logo 很有辨识度便一直有印象。所以这次抽了个周末专门体验了一下,看它是否当得起这个标题。开始~

Crossplane(跨平面,意思是可以跨越多个 公有云平台) 是一个开源的 Kubernetes 插件,它允许平台团队组装来自多个供应商的基础设施,并向应用程序团队公开更高级别的自助服务 api,而不需要编写任何代码。

Crossplane Overview

愿景

为更开放的云提供动力

Crossplane 通用 API 说明

构建 Crossplane 是为了帮助组织构建他们的云,就像云供应商构建他们的云一样——通过一个控制平面。Crossplane 是一个 CNCF 项目,它扩展了 Kubernetes API 来管理和组合基础设施。操作人员可以在 Crossplane 生成的自定义 API 线后封装策略、权限和其他防护措施,而应用程序开发人员无需成为基础设施专家就可以从 API 自助服务。

对标产品

Terraform

价值

以下是它的价值所在:

使用 kubectl 提供和管理云基础设施和服务

Crossplane 基础设施示意

Crossplane 扩展您的 Kubernetes 集群,为您提供任何基础设施或托管服务的 crd。将这些细粒度资源组合成更高级别的抽象,这些抽象可以使用您喜欢的工具,也可以和已经集成到集群中的现有流程进行版本管理、管理、部署和使用。

在 Crossplane 中,每个人都有自己的基础设施

Crossplane 支持公有云供应商

Crossplane 支持来自所有主要云提供商的基础设施,社区也在不断开发新的提供商。目前支持以下主流公有云供应商:

为你的应用程序提供简化的基础架构抽象

Crossplane 对资源的简化抽象

在 CRDs Crossplane 提供的基础上构建您自己的内部基础架构抽象。您的自定义 api 可以包含策略护栏,隐藏基础设施的复杂性,并确保应用程序可以安全地使用它。

通用云 API

Crossplane 制作标准通用 API

Crossplane 在不同的供应商、资源和抽象集合中提供一致的 API。跨平面资源模型(XRM, Crossplane Resource Model)以一种武断的方式扩展了 Kubernetes 资源模型(KRM),不管是哪个供应商或供应商构建了它们都能产生了一种统一的资源管理体验。

Run Crossplane anywhere

标准 API

无论您是在 EKS、AKS、GKE、ACK、PKS 中使用单个 Kubernetes 集群,还是在 Rancher 或 Anthos 等多集群管理器中使用,Crossplane 都能很好地集成它们。Crossplane 可以安装到任何现有的集群中,跨基础设施和服务提供商公开 crd 和标准 API,使供应和管理变得轻而易举。

为什么要使用 Crossplane 来管理应用程序和基础设施?

🔘 声明式基础设施配置

Crossplane 将 kubernetes 风格的声明式和 api 驱动的配置和管理引入到任何基础设施、本地和云中。通过这种方法,通过 Crossplane 管理的基础设施可以通过kubectl 进行访问,可以使用 YAML 进行配置,并且可以立即自修复。

🔗 统一应用程序和基础设施的配置和部署

Crossplane 允许应用程序和基础设施配置在相同的 Kubernetes 集群上共存,降低了工具链和部署管道的复杂性。

⚓️ 基础设施配置和设置的单一真实来源

Crossplane 集成了 CI/CD 管道,因此应用程序基础设施配置存储在单个控制集群中。团队可以使用已经在使用的 GitOps 最佳实践创建、跟踪和批准变更。

🔄 使用协调控制器自动化操作任务

资源控制器负责资源的整个生命周期。此资源负责供应、运行状况、扩展、故障转移,并积极响应与所需配置不一致的外部更改。

➕ 具有高水平的可扩展性

Crossplane 利用了广泛接受的 Kubernetes 模式,通过添加自己的 api 和控制器可以轻松地扩展它。通过将策略、配额和权限打包到自定义基础设施定义中来提高灵活性和安全性。

⇅ 强烈的关注点分离

开发人员可以定义工作负载,而不必担心实现细节、环境约束或策略。管理员可以定义环境细节和策略。支持更高程度的可重用性并降低复杂性。

Crossplane vs Terraform

Crossplane 经常被比作 HashiCorp 的 Terraform。这两个项目有相似之处:

  • 两者都允许工程师将其基础设施建模为声明性配置

  • 两者都支持使用提供商插件管理大量不同的基础设施

  • 两者都是拥有强大社区的开源工具

关键的区别是 Crossplane 是一个控制平面,而 Terraform 是一个命令行工具 —— 一个控制平面的界面。下面触及了企业在扩展 Terraform 时经常面临的几个痛点,并强调了 Crossplane 如何解决这些问题。

协作

企业通常通过运维团队采用 Terraform。将基础设施表示为声明性配置,可以让运维团队从软件工程的最佳实践中获益 —— 将配置保存在修订控制中,以便在必要时对更改进行同行评审和恢复。

当更多的工程师需要合作管理他们组织的基础设施时,Terraform 就会崩溃。Terraform 依赖于一个单一的状态文件将所需的配置映射到实际运行的基础设施。在应用配置时,这个状态文件上必须有一个锁,而应用 Terraform 配置是一个阻塞过程,可能需要几分钟才能完成。在此期间,没有其他实体 —— 没有其他工程师—— 可以对配置进行更改。类似地,Terraform 使用一个单一的 apply 进程 —— 在一个配置中,没有推荐的方法只修改一个基础设施。如果您使用相同的配置来管理缓存和数据库,您必须始终同时更新它们 — 您不能只更新缓存。

Terraform 建议将单个配置分解为越来越细粒度的配置。因此,虽然运维团队可能从代表「产品(production)」的 Terraform 配置开始,但他们被鼓励将其纳入「产品账单(production billing)」和「产品认证(production auth)」等范围配置中。这是很难做到的,所以它可能需要大量的重构时间,并经常导致一个复杂的网格状的 Terraform 配置耦合其输入和输出。

跨平面资源模型(Crossplane Resource Model, XRM)促进了松散耦合和最终的一致性。在 Crossplane 中,基础设施的每个部分都是支持创建、读取、更新和删除操作的 API 端点。Crossplane 不需要计算依赖关系图来进行更改,因此即使使用 Crossplane 管理整个生产环境,也可以轻松地对单个数据库进行操作。

自服务

现代组织正从基础设施的集中管理发展到自助服务模型,在这种模型中,运维团队(通常称为平台团队)定义了他们支持的开发团队可以按需使用的基础设施抽象。Terraform 已经通过使用模块(modules)来支持这个模型。模块与软件库没有什么不同。与 Crossplane 一样,Terraform 资源也是外部 API 资源的高保真表示。模块在这些资源的更广泛的配置之上提供了一个简化的抽象 —— 例如,RDS 模块将 8 个不同的 Terraform 资源抽象为一个单一的「RDS实例」概念。

将应用团队视为 Terraform 配置「库」的消费者,意味着他们要受制于 Terraform 的协作约束。应用程序开发人员被邀请在他们组织的基础设施上进行协作,就好像他们是一个关注范围较窄的运维团队。平台团队邀请应用程序开发团队共享他们的工作流,而不是向他们提供服务。这意味着应用团队必须学习一种新的、特殊用途的工具集和语言——Terraform 和 HashiCorp 配置语言(HCL)。它还提高了应用程序开发人员的配置抽象级别,而不提高访问控制抽象级别。虽然平台团队可以发布一个模块,允许应用程序团队管理「RDS实例」,但访问控制仍然在云提供商 API 级别,因此围绕着「数据库子网组」和「数据库参数组」展开。

而 Crossplane 相当于一个 Terraform 模块的是一个复合资源 —— 一个 XR。每个 XR 都作为 API 端点公开。平台团队可以定义和记录每个 XR (每个 API)的OpenAPI 模式,并在 API 级别实施基于角色的访问控制(RBAC)。这意味着,如果一个平台团队决定框架抽象它们并提供给他们的开发团队「AcmeCo PostgreSQL数据库」,他们可以授予 RBAC 访问创建、读取、更新或删除一个 AcmeCo PostgreSQL 数据库,而不必管理对各种潜在的云概念,比如 RDS 实例的访问或子网组。因为 Crossplane 建立在经过实战历练的 Kubernetes RBAC 系统上,平台团队可以轻松地在一个控制平面内支持多个应用程序开发团队。每个团队只能被授予访问他们需要的抽象的权限 —— 一些团队可能只能管理存储桶,而另一些团队可能被允许管理缓存和数据库。

在 Crossplane 中,自助服务的规模甚至更大,因为任何一个 XR 都可以提供多种服务。Crossplane 将 XR 的输入和输出(Kubernetes的说法是它的 spec 和 status )与它的实现解耦,后者由 Composition 来描述。如果应用程序开发人员被授予创建 AcmeCo PostgreSQL 数据库的权限,他们可以很容易地从任何服务类中选择——任何组合——他们的平台团队已经声明与上述数据库兼容。这些服务类可以代表生产、staging 和开发; AWS、Azure和GCP; 快和慢; 或两者的任何组合。

集成和自动化

Terraform 有很多 api,但它不提供自己的 api。这使得许多团队将他们的 Terraform 配置提交到版本控制(git)中,并将 Terraform 作为 CI/CD 管道的一部分执行。相对于一个团队在他们的笔记本电脑上运行 Terraform 来说,这是一个进步,但它暴露了组织在试图扩大 Terraform 的使用时面临的一个关键问题。Terraform 是一个命令行工具 —— 不是一个控制平面。因为它是一个短暂的、一次性的过程,所以在调用它时,它只会尝试将所需的配置与实际的基础设施协调起来。无论是从 CI/CD 管道运行还是从笔记本电脑运行,Terraform 通常只在工程师希望基础设施需要更新时才会被调用。

Terraform 的保守的、「按需」的方法与实际的基础设施状态相协调,可能会导致新的死锁。回想一下,应用 Terraform 配置的过程是「要么全部成功,要么全部失败」的——如果你在相同的配置中描述你的缓存和数据库,你必须总是同时更新它们。这意味着,如果你的组织中有人绕过 Terraform,下一个触发 Terraform 运行的人将面临一个令人惊讶的计划,因为他试图撤销改变。例如,考虑这样一个场景: 工程师在半夜被呼叫来处理一个事件,通过 AWS 控制台对生产缓存配置进行了一些快速编辑,却忘记在 Terraform 中反映这些更改。基础设施漂移如此之大,以至于应用 Terraform 配置成为一个有风险的、令人生畏的命题,这并非前所未闻。

而另一方面,Crossplane 是由一系列长期运行的控制循环所组成。它不断地观察和纠正组织的基础设施,以匹配其期望的配置,无论是否期望更改。这阻碍了团队绕过 Crossplane。当 Crossplane 被要求管理一段基础设施时,在该基础设施之外所做的任何更改都将自动且持久地恢复。

Terraform 简化技术栈

组织在使用 Terraform 时面临的一个持续的问题是它没有提供 API。与 Terraform 集成是一个挑战,因为它是使用领域特定语言(DSL,Domain Specific Language) ——(HCL) 配置的,并通过调用命令行工具来调用。Crossplane 公开了 REST API —— 自动化的通用语言。无论团队主要编写 shell 脚本、主要编写 Python,还是主要编写 Erlang common pattern 都可以调用 REST API。

Crossplane 简化技术栈

Crossplane 不公开任何旧的 REST API。在 Kubernetes API 上构建意味着团队可以使用 kubectl 这样的工具来编排他们所有的基础设施 —— 云或者其他。他们使用相同的工具来编排他们的容器化应用程序。Crossplane 甚至可以将应用程序需要连接到基础设施的细节作为 Kubernetes Secret 公开,以简化集成。它可以与ArgoCD、Gatekeeper 或 Velero 等项目搭配使用,以启用 GitOps、高级策略和备份。需要定制的自动化? 构建自己的 Kubernetes Operator,来与 Crossplane 集成。

两者一起?

Crossplane 和 Terraform 都可以协调一个组织的基础设施。两者之间有相似之处,但每个项目的编排方法不同。Terraform 提供了一个命令行接口来控制平面 api,而 Crossplane 本身就是一个控制平面,可以用来在其他控制平面上构建抽象。因为 Crossplane 让平台团队能够提供自己的控制平面,所以它避免了平台团队在缩放 Terraform 时所面临的许多挑战。

包含 Terraform 的 Crossplane 技术栈

精明的读者可能会注意到,这两个项目可以相互补充——Terraform 是一个控制平面的接口,它的 Kubernetes 提供商允许编排 Kubernetes 控制平面! 这意味着可以将 Terraform 与 Crossplane 配对,例如,如果您的组织更喜欢 HCL 而不是 YAML,那么您的平台团队就可以使用 Terraform 来定义 xr 和 composition,对于您的应用团队来说,可以使用 Terraform 来规划并应用 Crossplane 所需状态的更改!

我们认为,对于平台团队来说,Crossplane 是一种很好的方式,可以帮助他们支持的开发人员自助服务他们的基础设施需求。

安装配置

希望获得更多灵活性的用户可以将 Crossplane 安装到自己的 Kubernetes 集群中。

Crossplane 将使用定期发布的 Helm Chart 安装。Helm 图表包含部署和配置 Crossplane 所需的所有自定义资源和控制器。

将 Crossplane 安装到现有的 Kubernetes 集群中需要更多的设置,但是可以为需要它的用户提供更多的灵活性。

前提

  • Kubernetes 集群
  • Helm 3

安装 Crossplane

kubectl create namespace crossplane-system

helm repo add crossplane-master https://charts.crossplane.io/master/
helm repo update
helm search repo crossplane-master --devel

helm install crossplane --namespace crossplane-system crossplane-master/crossplane \
  --devel --version <version>

检查 Crossplane 状态

helm list -n crossplane-system

kubectl get all -n crossplane-system

安装 Crossplane CLI

Crossplane CLI 扩展了 kubectl 的功能,可以构建、推送和安装 Crossplane 包:

curl -sL https://raw.githubusercontent.com/crossplane/crossplane/release-1.5/install.sh | CHANNEL=master sh

选择一个入门配置

Crossplane 超越了简单地将基础设施原语建模为自定义资源 —— 它使您能够使用您选择的模式定义新的自定义资源。我们称之为“复合资源”(XRs, composite resources)。复合资源组合托管资源 —— Kubernetes 自定义资源,提供基础设施原语的高保真表示,如 SQL 实例或防火墙规则.

我们使用两个特殊的 Crossplane 资源来定义和配置这些新的自定义资源:

  • 一个是 CompositeResourceDefinition (XRD) 它定义了一种新的复合资源,包括它的 schema 。XRD 可以选择性地提供一项声明(XRC)。
  • Composition 指定复合资源将由哪些资源组成,以及应该如何配置它们。您可以为每个复合资源创建多个 Composition 选项。

XRD 和 Composition 可以打包并作为 configuration 安装。Configuration是一个组合配置 package,可以通过创建声明性配置资源或使用 kubectl crossplane install configuration 轻松地安装到 Crossplane。

在下面的示例中,我们将安装一个配置,该配置定义一个新的 XPostgreSQLInstance XR 和一个接受单个 storageGB 参数的 PostgreSQLInstance XRC,并创建一个连接 Secret,其中包含用户名、密码和端点的密钥。每个提供程序都有一个 Configuration,它可以满足 PostgreSQLInstance。让我们开始吧!

安装 Configuration Package

如果您想了解这个配置包的内容以及在安装之前如何构造它,请跳到创建 Configuration部分。

kubectl crossplane install configuration registry.upbound.io/xp/getting-started-with-aws:v1.5.1

等到所有的 package 都变得健康:

watch kubectl get pkg

获取AWS帐户密钥文件

使用 AWS 帐号管理 RDS 数据库:

AWS_PROFILE=default && echo -e "[default]\naws_access_key_id = $(aws configure get aws_access_key_id --profile $AWS_PROFILE)\naws_secret_access_key = $(aws configure get aws_secret_access_key --profile $AWS_PROFILE)" > creds.conf

创建一个 云提供商 Secret

kubectl create secret generic aws-creds -n crossplane-system --from-file=creds=./creds.conf

配置云提供商

我们将创建以下 ProviderConfig 对象来为 AWS Provider 配置凭证:

apiVersion: aws.crossplane.io/v1beta1
kind: ProviderConfig
metadata:
  name: default
spec:
  credentials:
    source: Secret
    secretRef:
      namespace: crossplane-system
      name: aws-creds
      key: creds
kubectl apply -f https://raw.githubusercontent.com/crossplane/crossplane/release-1.5/docs/snippets/configure/aws/providerconfig.yaml

现在您已经配置了支持 PostgreSQLInstance 的 Crossplane,现在可以提供基础设施了。

提供基础设施

组合资源(XRs,Composite resources) 总是在集群范围内 — 它们存在于任何名称空间之外。这允许 XR 表示可能来自几个不同 namespace 的基础设施。对于VPC 网络来说,这通常是正确的 —— 基础设施管理员可能希望定义一个 VPC 网络 XR 和一个 SQL 实例 XR,只有后者可能由应用程序操作员管理。应用程序操作员只能使用其团队的 namespace,但是他们的 SQL 实例都应该连接到基础架构操作员管理的 VPC 网络。Crossplane 允许基础设施操作人员向其应用程序操作人员提供复合资源声明(XRC,composite resource claim),从而实现这样的场景。XRC 是 XR 的命名空间代理; XRC 的 schema 与其对应的 XR 的 schema 是相同的。当应用程序操作员创建一个 XRC 时,会自动创建一个相应的后备 XR。这个模型与 Kubernetes 中的持久卷(PV)和持久卷声明(PVC)相似

声明基础设施

我们在上一节中安装的 Configuration包:

  • 定义一个XPostgreSQLInstance XR。

  • 提供一个对应 XR 的 PostgreSQLInstance 声明(XRC)。

  • 创建一个可以满足 XR 的 Composition

这意味着我们可以在 default 的命名空间中创建一个 PostgreSQLInstance XRC来提供一个PostgreSQL 实例和它可能需要的所有支持基础设施(vpc、防火墙规则、资源组等)!

注意,该资源将使用您的默认 VPC 创建一个 RDS 实例,该实例可能允许也可能不允许来自互联网的连接,这取决于它的配置方式。

apiVersion: database.example.org/v1alpha1
kind: PostgreSQLInstance
metadata:
  name: my-db
  namespace: default
spec:
  parameters:
    storageGB: 20
  compositionSelector:
    matchLabels:
      provider: aws
      vpc: default
  writeConnectionSecretToRef:
    name: db-conn
kubectl apply -f https://raw.githubusercontent.com/crossplane/crossplane/release-1.5/docs/snippets/compose/claim-aws.yaml

创建 PostgreSQLInstance Crossplane 后,将开始在您选择的云供应商上提供一个数据库实例。一旦配置完成,当你运行时,你应该在输出中看到READY: True:

kubectl get postgresqlinstance my-db

注意:

在等待 PostgreSQLInstance 就绪时,您可能想查看集群中的其他资源。通过以下命令可以查看 Crossplane 资源组:

  • kubectl get claim: 获取所有声明类型的所有资源,如 PostgreSQLInstance
  • kubectl get composite: 获取所有复合类型的资源,如 XPostgreSQLInstance
  • kubectl get managed:获取代表一个外部基础设施单元的所有资源。
  • kubectl get <name-of-provider>:获取与云供应商相关的所有资源。
  • kubectl get crossplane:获得所有与 Crossplane 相关的资源。

试试下面的命令,以观察您准备好的资源:

kubectl get crossplane -l crossplane.io/claim-name=my-db

一旦准备好 PostgreSQLInstance,您应该在 default 命名空间中看到一个名为 db-conn 的 Secret,它包含我们在 XRD 中定义的 key。如果它们是由 composition 填充的,那么它们应该出现:

$ kubectl describe secrets db-conn
Name:         db-conn
Namespace:    default
...

Type:  connection.crossplane.io/v1alpha1

Data
====
password:  27 bytes
port:      4 bytes
username:  25 bytes
endpoint:  45 bytes

这里我创建好了一个 RDS,endpoint 是:my-db-lfcp2-v792d.cbijsmocclgy.us-east-1.rds.amazonaws.com

消费基础设施

因为连接秘密信息被写成 Kubernetes Secret,它们很容易被 Kubernetes 原语使用。Kubernetes 中最基本的构建块是 Pod。让我们定义一个 Pod,它将显示我们能够连接到新供应的数据库。

apiVersion: v1
kind: Pod
metadata:
  name: see-db
  namespace: default
spec:
  containers:
  - name: see-db
    image: postgres:12
    command: ['psql']
    args: ['-c', 'SELECT current_database();']
    env:
    - name: PGDATABASE
      value: postgres
    - name: PGHOST
      valueFrom:
        secretKeyRef:
          name: db-conn
          key: endpoint
    - name: PGUSER
      valueFrom:
        secretKeyRef:
          name: db-conn
          key: username
    - name: PGPASSWORD
      valueFrom:
        secretKeyRef:
          name: db-conn
          key: password
    - name: PGPORT
      valueFrom:
        secretKeyRef:
          name: db-conn
          key: port
kubectl apply -f https://raw.githubusercontent.com/crossplane/crossplane/release-1.5/docs/snippets/compose/pod.yaml

这个 Pod只是连接到一个 PostgreSQL 数据库并打印它的名字,所以如果你运行 kubectl logs see-db,你应该在创建它之后看到以下输出(或类似的):

 current_database
------------------
 postgres
(1 row)

清理

要清理 Pod,运行:

kubectl delete pod see-db

为了清理准备好的基础设施,你可以删除 PostgreSQLInstance XRC:

kubectl delete postgresqlinstance my-db

当我执行这个的时候,对应的 Crossplane 状态为 deleting

$ kubectl get crossplane -l crossplane.io/claim-name=my-db
NAME                                                       READY   SYNCED   STATE      ENGINE     VERSION   AGE
rdsinstance.database.aws.crossplane.io/my-db-lfcp2-v792d   False   True     deleting   postgres   12.7      14m

查看 AWS 控制台,也正在删除:

AWS 控制台正在删除

删除完毕后,2 边也是状态一致的:

AWS 控制台状态和 Crossplane 状态一致

下一步

现在您已经了解了如何通过组合来供应和使用复杂的基础设施。在下一节中,您将学习如何编写和打包您自己的基础设施api。

卸载

See Uninstall docs for cleaning up resources, packages, and Crossplane itself.

总结

结合前面章节《Crossplane vs Terraform》里提到的,Crossplane 确实在云基础设施管理这块更进一步,仅从上面这个简单的「快速上手」环节,就能感觉到,相比 Terraform,Crossplane 在这些方面更有优势:

  • 🔘 声明式基础设施配置(Kubernetes 一脉相承)
  • 🔗 统一应用程序和基础设施的配置和部署(都用 Kubernetes)
  • 🔄 使用协调控制器自动化操作任务 (这点体验真的不错)
  • ⇅ 强烈的关注点分离

以上。

三人行, 必有我师; 知识共享, 天下为公. 本文由东风微鸣技术博客 EWhisper.cn 编写.