亚马逊AWS官方博客

推出适用于 AWS CloudFormation 的公有注册表

AWS CloudFormationAWS Cloud Development KitCDK)提供了可扩展且预置过程一致的 AWS 资源(例如计算基础设施、监控工具、数据库等)。我们从许多客户那里得知,他们希望在预置来自于 AWS 合作伙伴网络 (APN) 成员、第三方供应商和开源技术的资源时,无论他们正在使用 CloudFormation 模板或者已经通过 CDK 定义了他们的云基础设施,都能享受到同样的一致性和可扩展性。

我很高兴地宣布,我们为 CloudFormation 新推出了公有注册表。该注册表提供了一系列由 AWS、APN 合作伙伴、第三方和开发人员社群发布的,可供搜索的拓展程序(资源类型或模块)集。注册表允许您像使用 AWS 提供的资源一样,在 CloudFormation 模板和 CDK 应用程序中轻松地探索和预置这些扩展程序。通过这些拓展程序,您无需再为来自第三方供应商的资源类型创建和维护自定义预置逻辑。此外,您可以通过单一的“基础设施即代码”工具 CloudFormation 来预置和管理 AWS 和第三方资源,从而进一步简化基础设施预置过程(CDK 的内核使用的也是 CloudFormation)。

启动合作伙伴
令人激动的是,有十几位 AWS 合作伙伴参与了我们此次的注册表发布,今天起有超过 35 个扩展程序可供您使用。您在下面可以找到共同参与此次发布的 AWS 合作伙伴的博客文章、公告以及相关的 AWS Quick Start(其中一些内容将在未来几天内添加)。

注册表和资源类型
2019 年,CloudFormation 启动了对私有注册表的支持。私有注册表允许在您的账户中注册和使用来自 AWS 和第三方供应商的资源提供程序(Lambda 函数)。在您注册提供程序之后,就可以在 CloudFormation 模板中使用提供程序的资源类型(包括自定义预置逻辑)。资源类型由提供程序上载到 Amazon Simple Storage Service (Amazon S3) 存储桶,您可以通过引用相关的 S3 URL 来使用这些类型。公有注册表提供了资源类型和模块来源的一致性,您无需再使用 Amazon Simple Storage Service (Amazon S3) 存储桶中的资源类型/模块集。

公有注册表中的第三方资源类型也集成了漂移检测。从第三方资源类型创建资源后,CloudFormation 将从其模板配置中检测对资源的更改(即配置偏移),就像使用 AWS 资源一样。您还可以通过 AWS Config 管理从注册表使用的第三方资源的合规性。当您配置 AWS Config 记录这些资源类型,以及使用 CloudFormation 创建、更新和删除它们时,这些资源类型会被视作配置项目自动受到跟踪。无论您使用的资源类型是第三方资源还是 AWS 资源,您都可以查看它们的配置历史记录,还可以编写 AWS Config 规则来验证配置的最佳实践。

公有注册表还支持类型配置,使您能够用 API 密钥和 OAuth 令牌为每个账户和区域配置第三方资源类型。设置完成后,配置将被安全地存储,并且可以进行更新。这也提供了一种集中化配置第三方资源类型的方式。

将扩展程序发布到公有注册表
扩展程序的发布者必须是经过验证的 AWS Marketplace 卖家,或者是GitHub 或 BitBucket 的用户。同时,扩展程序必须通过最佳实践验证。要将扩展程序(资源类型或模块)发布到注册表,您必须首先使用符合上述类型之一的账户在一个 AWS 区域中进行注册。

注册后,接下来您需要将扩展程序发布到同一区域的私有注册表。然后,您需要测试扩展程序是否符合发布要求。资源类型扩展程序必须通过为该类型设定的所有合约测试。针对模块拓展程序的要求不同,您可以在文档中找到更多详细信息。测试完成后,您可以将扩展程序发布到您所在区域的公有注册表。有关发布扩展程序的详细信息,请参阅用户指南

在公有注册表中使用扩展程序
我决定尝试使用几个由 AWS Quick Start 贡献的 Kubernetes 扩展程序,对集群进行配置更改。我个人对于 Kubernetes 及其 API 没有太多经验,所以这是一个很好的机会来展示扩展程序如何为我节省大量时间和精力。在写这篇文章时,我从别人那里了解到,想要实现我预想中的改动通常需要使用 Kubernetes API,这需要花费不少精力,即使对于那些经验丰富的人也是如此。

在这个例子中,我需要一个 Kubernetes 集群,因此我按照这篇教程使用托管式节点 – Linux 节点类型在 Amazon Elastic Kubernetes Services (EKS) 中设置了一个集群。在我的集群准备就绪之后,我想修改两处配置。

首先,我想在集群中添加一个新的命名空间。命名空间是一种分区结构。由于命名空间提供的隔离,我可以将同一组资源部署到同一集群中的不同命名空间而不发生冲突。其次,我想设置和使用 Kubernetes 的软件包管理器 Helm。我将使用 Helm 来安装 Prometheus helm-charts 仓库中的 kube-state-metrics 软件包,以收集集群指标。虽然以前我可以使用 CloudFormation 来预置集群和计算资源,但为了执行这两项配置任务,我只能通过 API 或各种定制的工具链。有了注册表和这两个扩展程序,现在我可以使用 CloudFormation 完成所有的事情(当然正如我之前提到的,我也可以将扩展程序与 CDK 一起使用,我将在后面展示)。

扩展程序需要在我的账户中激活后才能使用。虽然通过控制台对单独的账户进行激活很容易。但是稍后我们会看到,如果我使用了 AWS Organizations 并且希望在我的整个组织中(或者为特定的 OU)激活各种第三方扩展程序,我可以使用 CloudFormation 中的服务托管 StackSets 来实现这一点。使用提交给服务托管 StackSet 模板中的 AWS::CloudFormation::TypeActivation 资源类型,我可以将整个组织或特定的 OU 作为目标,经由 Amazon Resource Name (ARN) 识别要激活的第三方扩展。只需几行代码即可使用 CDK 轻松激活扩展程序(无论是否使用 AWS Organizations),再次利用上述 TypeActivation 资源类型。

要激活扩展程序,我转到 CloudFormation 控制台,然后单击导航栏中的 Public extensions (公有扩展程序)。然后会进入 Registry:Public extensions (注册表:公有扩展程序) 主页,在这里我切换到查看第三方资源类型扩展程序。

在注册表中查看第三方类型

我需要的扩展程序是 AWSQS::Kubernetes::ResourceAWSQS::Kubernetes::HelmResource 扩展程序用于对集群应用描述配置更改的清单。在本例中,清单请求创建命名空间。单击 AWSQS::Kubernetes::Resource 扩展程序的名称可以进入一个页面,我可以在其中查看扩展程序的架构、配置详细信息和版本。

查看 Resource 扩展程序的详细信息

如果您停用正在使用的扩展程序,或者发布者撤回了扩展程序,会发生什么情况? 如果停用堆栈所依赖的扩展程序,则通过该扩展程序创建的任何资源均不会受到影响,但是您将无法执行进一步的堆栈操作,例如读取、更新、删除和列出(在重新激活该扩展程序之前,这些操作都无法执行)。发布者必须请求从注册表中撤回其扩展程序(没有“删除”API)。如果请求获得批准,在撤回前激活扩展程序的客户仍然可以使用其账户中扩展程序的快照来执行创建/读取/更新/删除/列出操作。

单击 Activate (激活) 将转到一个页面,我需要在其中指定 CloudFormation 在扩展程序后台运行代码时将承担的执行角色的 ARN。我按照本用户指南主题创建了一个角色,但基本信任关系如下所示,仅供参考。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "resources.cloudformation.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

我还将正在使用的资源类型的权限添加到我的执行角色中。有关我选择的类型所需权限的详细信息可以在针对 Helm针对 Kubernetes 的 GitHub 上找到(请注意 GitHub 示例也包括信任关系)。

激活扩展程序时,我可以选择使用默认名称,这就是我在模板或 CDK 应用程序中引用该类型的方式,我也可以输入新名称。选择的名称在我的账户中必须是唯一的,因此,如果我启用了默认名称的扩展程序版本,并且想要启用其他版本,我必须更改名称。我填写详细信息并选择我的版本控制策略(扩展程序使用语义版本控制,我可以选择接受次要版本更改的自动更新,或者“锁定”到特定版本)后,单击 Activate extension (激活扩展程序) 即可完成该过程。

从注册表激活扩展程序

这样就完成了第一个扩展程序的过程,对于 AWSQS::Kubernetes::Helm 扩展程序我执行相同的步骤。导航到 Activated extensions (已激活扩展程序),我可以查看所有已启用的扩展程序的列表。

查看已启用扩展程序的列表

我还有一组权限要更新。资源类型代表我调用 Kubernetes API,因此我需要为我的集群更新 aws-auth ConfigMap 以引用我刚使用的执行角色,否则我使用的资源类型进行的调用将失败。为此,我在命令提示符下运行 kubectl edit cm aws-auth -n kube-system 命令。在打开的文本编辑器中,我用一个引用我的 CfnRegistryExtensionExecRole 的新组更新 ConfigMap,如下所示(如果您也采用这种方法,请务必更改账户 ID 和角色名称以匹配您的账户 ID 和角色名称)。

apiVersion: v1
data:
  mapRoles: |
    - groups:
      - system:bootstrappers
      - system:nodes
      rolearn: arn:aws:iam::111122223333:role/myAmazonEKSNodeRole
      username: system:node:{{EC2PrivateDNSName}}
    - groups:
      - system:masters
      rolearn: arn:aws:iam::111122223333:role/CfnRegistryExtensionExecRole
      username: cfnresourcetypes
kind: ConfigMap
metadata:
  creationTimestamp: "2021-06-04T20:44:24Z"
  name: aws-auth
  namespace: kube-system
  resourceVersion: "6355"
  selfLink: /api/v1/namespaces/kube-system/configmaps/aws-auth
  uid: dc91bfa8-1663-45d0-8954-1e841913b324

现在我已经准备好使用这些扩展程序来配置我的集群,采用新的命名空间 Helm 和 kube-state-metrics 软件包。我创建了一个使用扩展程序的 CloudFormation 模板,为创建堆栈时要指定的元素添加参数:要更新的集群的名称和命名空间名称。KubeStateMetrics 资源的属性引用了我希望 Helm 安装的软件包。

AWSTemplateFormatVersion: "2010-09-09"
Parameters:
  ClusterName:
    Type: String
  Namespace:
    Type: String
Resources:
  KubeStateMetrics:
    Type: AWSQS::Kubernetes::Helm
    Properties:
      ClusterID: !Ref ClusterName
      Name: kube-state-metrics
      Namespace: !GetAtt KubeNamespace.Name
      Repository: https://prometheus-community.github.io/helm-charts
      Chart: prometheus-community/kube-state-metrics
  KubeNamespace:
    Type: AWSQS::Kubernetes::Resource
    Properties:
      ClusterName: !Ref ClusterName
      Namespace: default
      Manifest: !Sub |
        apiVersion: v1
        kind: Namespace
        metadata:
          name: ${Namespace}
          labels:
            name: ${Namespace}

CloudFormation 控制台的 Stacks (堆栈) 页面上,我单击 Create stack (创建堆栈),上传我的模板,然后为我的堆栈指定一个名称并为声明的参数赋值。

使用我激活的扩展程序启动堆栈

我单击 Next (下一步) 继续执行向导的其余部分,将其他设置保留默认值,然后单击 Create stack (创建堆栈) 以完成该过程。

堆栈创建完成后,我使用 kubectl 命令行工具验证我的更改。我首先检查新的命名空间 newsblog-sample-namespace 是否有 kubectl get namespaces 命令。然后我运行 kubectl get all --namespace newsblog-sample-namespace 命令来验证 kube-state-metrics 软件包是否已安装。

验证更改应用的扩展程序

扩展程序也可以与 AWS Cloud Development Kit 一起使用。为了总结这次关于使用新注册表的探索,我在 TypeScript 中包含了一个如下所示的 CDK 应用程序代码段的例子,该示例使用与我之前展示的 YAML 模板相同的扩展程序实现了相同的效果(我也可以使用 CDK 支持的任何语言 – C#、Java 或 Python 编写这段代码)。

import {Stack, Construct, CfnResource} from '@aws-cdk/core';
export class UnoStack extends Stack {
  constructor(scope: Construct, id: string) {
    super(scope, id);
    const clusterName = 'newsblog-cluster';
    const namespace = 'newsblog-sample-namespace';

    const kubeNamespace = new CfnResource(this, 'KubeNamespace', {
      type: 'AWSQS::Kubernetes::Resource',
      properties: {
        ClusterName: clusterName,
        Namespace: 'default',
        Manifest: this.toJsonString({
          apiVersion: 'v1',
          kind: 'Namespace',
          metadata: {
            name: namespace,
            labels: {
              name: namespace,
            }
          },
        }),
      },
    });
    
    new CfnResource(this, 'KubeStateMetrics', {
      type: 'AWSQS::Kubernetes::Helm',
      properties: {
        ClusterID: clusterName,
        Name: 'kube-state-metrics',
        Namespace: kubeNamespace.getAtt('Name').toString(),
        Repository: 'https://prometheus-community.github.io/helm-charts',
        Chart: 'prometheus-community/kube-state-metrics',
      },
    });
  }
};

正如本文前面提到的那样,总体来说,我对 Kubernetes API 和 Kubernetes 没有太多经验。但是,通过将公有注册表中的资源类型与 CloudFormation 结合使用,我能够使用熟悉的环境轻松配置我的集群,而无需求助于 API 或定制工具链。

开始使用 CloudFormation 公有注册表
公有注册表的定价与现有注册表和私有资源类型的定价相同。使用本机 AWS 资源类型不会收取额外费用;对于第三方资源类型,将根据每月运行的处理程序操作(添加、删除、列出等)的数量向您收费。有关详细信息,请参阅 AWS CloudFormation 定价页面。 新的公有注册表现已在美国东部(弗吉尼亚北部、俄亥俄)、美国西部(俄勒冈、加利福尼亚北部)、加拿大(中部)、欧洲(爱尔兰、法兰克福、伦敦、斯德哥尔摩、巴黎、米兰)、亚太地区(香港、孟买、大阪、新加坡、悉尼、首尔、东京)、南美洲(圣保罗)、中东(巴林)和非洲(开普敦)的 AWS 区域推出。

有关更多信息,请参阅 AWS CloudFormation 用户指南扩展程序开发用户指南,然后立即开始发布或使用扩展程序!

– Steve