使用AWS CDK部署MWAA

364 阅读14分钟

简介

在这个快速指南中,我将向你展示如何使用Python AWS CDK应用程序来自动部署和配置你的Apache Airflow环境,在AWS上使用Apache Airflow的管理工作流程(MWAA)。

你将需要什么:

  • 一个具有正确权限的AWS账户
  • 一个配置并运行AWS CDK的开发环境(在撰写本文时,你应该使用AWS CDK v2)。
  • 访问支持Apache Airflow的托管工作流的AWS区域
  • 本指南中使用的所有代码都在这个GitHub仓库中提供。

一些需要注意的事情:

  • 如果你在一个已经有VPC的环境中部署,如果你超过了你的AWS账户中的VPC数量,你可能会产生一个错误(默认情况下,这被设置为5,但这是个软限制,你可以申请增加)。
  • 在运行CDK应用程序之前,请确保你为MWAA环境定义的Amazon S3桶不存在。

入门

确保我们正在运行正确版本的AWS CDKv2工具(至少是v2.2),然后查看git repo。

Shell

cdk --version

> 2.28.1 (build d035432)

git clone https://github.com/094459/blogpost-cdk-mwaa.git

在检查完资源库后,你将在你的本地开发环境中拥有以下文件。

纯文本

├── app.py
├── cdk.json
├── dags
│   ├── sample-cdk-dag-od.py
│   └── sample-cdk-dag.py
├── mwaa_cdk
│   ├── mwaa_cdk_backend.py
│   └── mwaa_cdk_env.py
└── requirements.txt

我们需要做的第一件事是更新我们的Python依赖项,这些依赖项在requirements.txt文件中被记录下来。

注意!如果你目前正在使用在AWS CDKv1和v2之间的移动过程中,那么你应该看看这篇博文,帮助你做好准备,因为后面的步骤可能会失败。

Shell

pip install -r requirements.txt

探索CDK栈

我们的AWS CDK应用程序由一些文件组成。我们应用程序的入口是app.py文件,在这里我们定义了我们要建立的结构和资源。然后我们有两个CDK堆栈来部署和配置AWS资源。最后,我们有资源,我们将其部署到我们的目标Apache Airflow环境

如果我们看一下app.py 文件,我们可以看到更详细地探索我们的CDK应用。我们正在创建两个堆栈,一个叫mwaa_cdk_backend ,另一个叫mwaa_cdk_env

mwaa_cdk_backend 将被用来设置MWAA环境要使用的VPC网络。mwaa_cdk_env 是将配置你的MWAA环境的堆栈。

为了做到这一点,首先,我们要设置一些配置参数,以便我们能够最大限度地重复使用这个CDK应用程序

Shell

import aws_cdk as cdk 

from mwaa_cdk.mwaa_cdk_backend import MwaaCdkStackBackend
from mwaa_cdk.mwaa_cdk_env import MwaaCdkStackEnv

env_EU=cdk.Environment(region="{your-aws-region}", account="{your-aws-ac}")
mwaa_props = {'dagss3location': '{your-unqiue-s3-bucket}','mwaa_env' : '{name-of-your-mwaa-env}'}

app = cdk.App()

mwaa_hybrid_backend = MwaaCdkStackBackend(
    scope=app,
    id="mwaa-hybrid-backend",
    env=env_EU,
    mwaa_props=mwaa_props
)

mwaa_hybrid_env = MwaaCdkStackEnv(
    scope=app,
    id="mwaa-hybrid-environment",
    vpc=mwaa_hybrid_backend.vpc,
    env=env_EU,
    mwaa_props=mwaa_props
)

app.synth()

我们在env_EUmwaa_props 行中定义配置参数。这将使你能够重新使用这个堆栈来创建多个不同的环境。如果你想让其他配置选项可以通过配置属性来改变,你也可以在mwaa_props中添加/改变这些变量(例如,日志口令或可能是Apache Airflow的版本)。

在改变 app.py 文件中的值并保存后,我们就可以部署了。

淘宝网

除了创建MWAA所需的底层网络基础设施外,这并没有什么特别有趣的地方。你不需要做什么,但如果你确实想做实验,那么我要说的是:a)确保你阅读并遵循MWAA文档网站上的网络指导,因为他们为你提供了需要设置的细节;b)如果你试图锁定网络,试着只部署后端堆栈,然后手动创建一个MWAA环境,看看它是否工作/失败了。

Shell

from aws_cdk import (
    aws_iam as iam,
    aws_ec2 as ec2,
    Stack,
    CfnOutput
)
from constructs import Construct

class MwaaCdkStackBackend(Stack):

    def __init__(self, scope: Construct, id: str, mwaa_props, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)
   
        # Create VPC network

        self.vpc = ec2.Vpc(
            self,
            id="MWAA-Hybrid-ApacheAirflow-VPC",
            cidr="10.192.0.0/16",
            max_azs=2,
            nat_gateways=1,
            subnet_configuration=[
                ec2.SubnetConfiguration(
                    name="public", cidr_mask=24,
                    reserved=False, subnet_type=ec2.SubnetType.PUBLIC),
                ec2.SubnetConfiguration(
                    name="private", cidr_mask=24,
                    reserved=False, subnet_type=ec2.SubnetType.PRIVATE_WITH_NAT)
            ],
            enable_dns_hostnames=True,
            enable_dns_support=True
        )


        CfnOutput(
            self,
            id="VPCId",
            value=self.vpc.vpc_id,
            description="VPC ID",
            export_name=f"{self.region}:{self.account}:{self.stack_name}:vpc-id"
        )

我们可以看到,一旦这个堆栈部署完毕,它将通过控制台以及AWS CloudFormation输出选项卡来输出VPC的详细信息。

淘宝网

MWAA的环境堆栈更有趣一些,我将对其进行分解。堆栈的第一部分是配置MWAA将使用的Amazon S3桶。

Shell

from aws_cdk import (
    aws_iam as iam,
    aws_ec2 as ec2,
    aws_s3 as s3,
    aws_s3_deployment as s3deploy,
    aws_mwaa as mwaa,
    aws_kms as kms,
    Stack,
    CfnOutput,
    Tags
)
from constructs import Construct

class MwaaCdkStackEnv(Stack):

    def __init__(self, scope: Construct, id: str, vpc, mwaa_props,  **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        key_suffix = 'Key'

        # Create MWAA S3 Bucket and upload local dags

        s3_tags = {
            'env': f"{mwaa_props['mwaa_env']}",
            'service': 'MWAA Apache AirFlow'
        }

        dags_bucket = s3.Bucket(
            self,
            "mwaa-dags",
            bucket_name=f"{mwaa_props['dagss3location'].lower()}",
            versioned=True,
            block_public_access=s3.BlockPublicAccess.BLOCK_ALL
        )

        for tag in s3_tags:
            Tags.of(dags_bucket).add(tag, s3_tags[tag])

        s3deploy.BucketDeployment(self, "DeployDAG",
        sources=[s3deploy.Source.asset("./dags")],
        destination_bucket=dags_bucket,
        destination_key_prefix="dags",
        prune=False,
        retain_on_delete=False
        )

        dags_bucket_arn = dags_bucket.bucket_arn

然而,这也是它在本地dags文件夹中发现的所有文件(在这个特定的例子中,以及GitHub repo中的内容,这将是两个DAG,sample-cdk-day-od.py和sample-cdk-day.py),并将这些文件作为部署过程的一部分上传。如果你愿意,你可以根据自己的要求进行调整,如果你不需要这样做,甚至可以根据需要注释它/删除它。

接下来,我们有创建MWAA执行策略和相关角色的代码,这些角色将被MWAA工作节点使用。这是从MWAA文档中摘录的,但你可以根据自己的环境需要来调整。如果你要与其他AWS服务集成,你可能需要这样做 - 这已经设置了默认的无访问权限,所以你需要做的任何事情都需要添加。

Shell

        mwaa_policy_document = iam.PolicyDocument(
            statements=[
                iam.PolicyStatement(
                    actions=["airflow:PublishMetrics"],
                    effect=iam.Effect.ALLOW,
                    resources=[f"arn:aws:airflow:{self.region}:{self.account}:environment/{mwaa_props['mwaa_env']}"],
                ),
                iam.PolicyStatement(
                    actions=[
                        "s3:ListAllMyBuckets"
                    ],
                    effect=iam.Effect.DENY,
                    resources=[
                        f"{dags_bucket_arn}/*",
                        f"{dags_bucket_arn}"
                        ],
                ),
                iam.PolicyStatement(
                    actions=[
                        "s3:*"
                    ],
                    effect=iam.Effect.ALLOW,
                    resources=[
                        f"{dags_bucket_arn}/*",
                        f"{dags_bucket_arn}"
                        ],
                ),
                iam.PolicyStatement(
                    actions=[
                        "logs:CreateLogStream",
                        "logs:CreateLogGroup",
                        "logs:PutLogEvents",
                        "logs:GetLogEvents",
                        "logs:GetLogRecord",
                        "logs:GetLogGroupFields",
                        "logs:GetQueryResults",
                        "logs:DescribeLogGroups"
                    ],
                    effect=iam.Effect.ALLOW,
                    resources=[f"arn:aws:logs:{self.region}:{self.account}:log-group:airflow-{mwaa_props['mwaa_env']}-*"],
                ),
                iam.PolicyStatement(
                    actions=[
                        "logs:DescribeLogGroups"
                    ],
                    effect=iam.Effect.ALLOW,
                    resources=["*"],
                ),
                iam.PolicyStatement(
                    actions=[
                        "sqs:ChangeMessageVisibility",
                        "sqs:DeleteMessage",
                        "sqs:GetQueueAttributes",
                        "sqs:GetQueueUrl",
                        "sqs:ReceiveMessage",
                        "sqs:SendMessage"
                    ],
                    effect=iam.Effect.ALLOW,
                    resources=[f"arn:aws:sqs:{self.region}:*:airflow-celery-*"],
                ),
                iam.PolicyStatement(
                    actions=[
                        "ecs:RunTask",
                        "ecs:DescribeTasks",
                        "ecs:RegisterTaskDefinition",
                        "ecs:DescribeTaskDefinition",
                        "ecs:ListTasks"
                    ],
                    effect=iam.Effect.ALLOW,
                    resources=[
                        "*"
                        ],
                    ),
                iam.PolicyStatement(
                    actions=[
                        "iam:PassRole"
                    ],
                    effect=iam.Effect.ALLOW,
                    resources=[ "*" ],
                    conditions= { "StringLike": { "iam:PassedToService": "ecs-tasks.amazonaws.com" } },
                    ),
                iam.PolicyStatement(
                    actions=[
                        "kms:Decrypt",
                        "kms:DescribeKey",
                        "kms:GenerateDataKey*",
                        "kms:Encrypt",
                        "kms:PutKeyPolicy"
                    ],
                    effect=iam.Effect.ALLOW,
                    resources=["*"],
                    conditions={
                        "StringEquals": {
                            "kms:ViaService": [
                                f"sqs.{self.region}.amazonaws.com",
                                f"s3.{self.region}.amazonaws.com",
                            ]
                        }
                    },
                ),
            ]
        )

        mwaa_service_role = iam.Role(
            self,
            "mwaa-service-role",
            assumed_by=iam.CompositePrincipal(
                iam.ServicePrincipal("airflow.amazonaws.com"),
                iam.ServicePrincipal("airflow-env.amazonaws.com"),
                iam.ServicePrincipal("ecs-tasks.amazonaws.com"),
            ),
            inline_policies={"CDKmwaaPolicyDocument": mwaa_policy_document},
            path="/service-role/"
        )

下一部分是配置MWAA所需的安全组和子网。

Shell

        security_group = ec2.SecurityGroup(
            self,
            id = "mwaa-sg",
            vpc = vpc,
            security_group_name = "mwaa-sg"
        )

        security_group_id = security_group.security_group_id

        security_group.connections.allow_internally(ec2.Port.all_traffic(),"MWAA")

        subnets = [subnet.subnet_id for subnet in vpc.private_subnets]
        network_configuration = mwaa.CfnEnvironment.NetworkConfigurationProperty(
            security_group_ids=[security_group_id],
            subnet_ids=subnets,
        )

从MWAA的角度来看,最后一个部分是最有趣的,那就是设置然后配置环境。我已经注释了一些环境设置,所以可以根据自己的需要自由调整。

我们要做的第一件事是为MWAA日志创建一个配置。在这个特定的配置中,我启用了所有INFO级别的日志,所以请随意启用/禁用或根据你的需要改变日志级别。

Shell

        logging_configuration = mwaa.CfnEnvironment.LoggingConfigurationProperty(
            dag_processing_logs=mwaa.CfnEnvironment.ModuleLoggingConfigurationProperty(
                enabled=True,
                log_level="INFO"
            ),
            task_logs=mwaa.CfnEnvironment.ModuleLoggingConfigurationProperty(
                enabled=True,
                log_level="INFO"
            ),
            worker_logs=mwaa.CfnEnvironment.ModuleLoggingConfigurationProperty(
                enabled=True,
                log_level="INFO"
            ),
            scheduler_logs=mwaa.CfnEnvironment.ModuleLoggingConfigurationProperty(
                enabled=True,
                log_level="INFO"
            ),
            webserver_logs=mwaa.CfnEnvironment.ModuleLoggingConfigurationProperty(
                enabled=True,
                log_level="INFO"
            )
        )

接下来我们定义一些MWAA Apache Airflow配置参数。如果你使用自定义属性,那么这就是你要添加它们的地方。另外,如果你想为你的MWAA环境使用TAG,你可以进行相应的调整。

Shell

        options = {
            'core.load_default_connections': False,
            'core.load_examples': False,
            'webserver.dag_default_view': 'tree',
            'webserver.dag_orientation': 'TB'
        }

        tags = {
            'env': f"{mwaa_props['mwaa_env']}",
            'service': 'MWAA Apache AirFlow'
        }

接下来,我们需要创建一些额外的IAM策略和权限,以及AWS KMS加密密钥,以保持所有内容的加密。如果你在配置MWAA环境时决定不配置KMS加密,那么这部分是可选的,但我在这里包括了信息。

Shell

        kms_mwaa_policy_document = iam.PolicyDocument(
            statements=[
                iam.PolicyStatement(
                    actions=[
                        "kms:Create*",
                        "kms:Describe*",
                        "kms:Enable*",
                        "kms:List*",
                        "kms:Put*",
                        "kms:Decrypt*",
                        "kms:Update*",
                        "kms:Revoke*",
                        "kms:Disable*",
                        "kms:Get*",
                        "kms:Delete*",
                        "kms:ScheduleKeyDeletion",
                        "kms:GenerateDataKey*",
                        "kms:CancelKeyDeletion"
                    ],
                    principals=[
                        iam.AccountRootPrincipal(),
                        # Optional:
                        # iam.ArnPrincipal(f"arn:aws:sts::{self.account}:assumed-role/AWSReservedSSO_rest_of_SSO_account"),
                    ],
                    resources=["*"]),
                iam.PolicyStatement(
                    actions=[
                        "kms:Decrypt*",
                        "kms:Describe*",
                        "kms:GenerateDataKey*",
                        "kms:Encrypt*",
                        "kms:ReEncrypt*",
                        "kms:PutKeyPolicy"
                    ],
                    effect=iam.Effect.ALLOW,
                    resources=["*"],
                    principals=[iam.ServicePrincipal("logs.amazonaws.com", region=f"{self.region}")],
                    conditions={"ArnLike": {"kms:EncryptionContext:aws:logs:arn": f"arn:aws:logs:{self.region}:{self.account}:*"}},
                ),
            ]
        )



        key = kms.Key(
            self,
            f"{mwaa_props['mwaa_env']}{key_suffix}",
            enable_key_rotation=True,
            policy=kms_mwaa_policy_document
        )

        key.add_alias(f"alias/{mwaa_props['mwaa_env']}{key_suffix}")

现在我们来实际创建环境,使用我们在上面创建或设置的东西。以下是MWAA中Apache Airflow核心选项的所有典型配置选项。你可以改变它们以适应你自己的环境,或如上所述对它们进行参数化。

Shell

        managed_airflow = mwaa.CfnEnvironment(
            scope=self,
            id='airflow-test-environment',
            name=f"{mwaa_props['mwaa_env']}",
            airflow_configuration_options={'core.default_timezone': 'utc'},
            airflow_version='2.0.2',
            dag_s3_path="dags",
            environment_class='mw1.small',
            execution_role_arn=mwaa_service_role.role_arn,
            kms_key=key.key_arn,
            logging_configuration=logging_configuration,
            max_workers=5,
            network_configuration=network_configuration,
            #plugins_s3_object_version=None,
            #plugins_s3_path=None,
            #requirements_s3_object_version=None,
            #requirements_s3_path=None,
            source_bucket_arn=dags_bucket_arn,
            webserver_access_mode='PUBLIC_ONLY',
            #weekly_maintenance_window_start=None
        )

        managed_airflow.add_override('Properties.AirflowConfigurationOptions', options)
        managed_airflow.add_override('Properties.Tags', tags)

        CfnOutput(
            self,
            id="MWAASecurityGroup",
            value=security_group_id,
            description="Security Group name used by MWAA"
        )

这个堆栈还输出MWAA安全组,但你也可以输出其他信息。

部署你的CDK应用程序

现在我们已经审查了该应用程序,并修改了它,使其包含你的详细信息(你的AWS帐户/独特的S3桶/等等),你现在可以运行该应用程序并部署CDK栈。要做到这一点,我们使用 "cdk deploy" 命令。

首先,从目录中,确保一切工作正常。要做到这一点,我们可以使用 "cdk ls" 命令。如果工作正常,它应该返回以下信息(这些信息是这个CDK应用程序使用的堆栈中分配的ID)。

Shell

cdk ls

>MWAA-Backend
>MWAA-Environment

我们现在可以部署它们,可以全部部署,也可以一次部署一个。这个CDK应用程序需要先部署MWAA-Backend应用程序,因为它包含了将在MWAA-Environment堆栈中使用的VPC网络,所以我们可以通过部署它。

Shell

cdk deploy MWAA-Backend

如果工作正常,它应该类似于下面的情况。

纯文本

Synthesis time: 7.09s

mwaa-hybrid-backend: deploying...
[0%] start: Publishing 2695cb7a9f601cf94a4151c65c9069787d9ec312084346f2f4359e3f55ff2310:704533066374-eu-central-1
[100%] success: Published 2695cb7a9f601cf94a4151c65c9069787d9ec312084346f2f4359e3f55ff2310:704533066374-eu-central-1
mwaa-hybrid-backend: creating CloudFormation changeset...

 ✅  mwaa-hybrid-backend

✨  Deployment time: 172.13s

Outputs:
mwaa-hybrid-backend.ExportsOutputRefMWAAHybridApacheAirflowVPC677B092EF6F2F587 = vpc-0bbdeee3652ef21ff
mwaa-hybrid-backend.ExportsOutputRefMWAAHybridApacheAirflowVPCprivateSubnet1Subnet2A6995DF7F8D3134 = subnet-01e48db64381efc7f
mwaa-hybrid-backend.ExportsOutputRefMWAAHybridApacheAirflowVPCprivateSubnet2SubnetA28659530C36370A = subnet-0321530b8154f9bd2
mwaa-hybrid-backend.VPCId = vpc-0bbdeee3652ef21ff
Stack ARN:
arn:aws:cloudformation:eu-central-1:704533066374:stack/mwaa-hybrid-backend/b05897d0-f087-11ec-b5f3-02db3f47a5ca

✨  Total time: 179.22s

然后,你可以通过AWS控制台检查CloudFormation栈来跟踪/查看已经部署的内容。

我们现在可以部署MWAA环境了,我们可以简单地通过键入来完成。

Shell

cdk deploy MWAA-Environment

这一次,它将弹出一些与安全有关的信息的细节,在这种情况下,就是我前面提到的IAM策略和安全组。回答 "Y "以部署这些变化。这将启动部署,你可以通过进入CloudFormation控制台跟踪。

这将需要大约20-25分钟,所以是一个很好的时间,拿起一杯茶,也许可以阅读一些我的其他博客文章:-)如果成功了,你会看到以下输出(同样,你的细节会改变,但它应该与此相似)。

纯文本

Including dependency stacks: mwaa-hybrid-backend
[Warning at /mwaa-hybrid-environment/mwaa-sg] Ignoring Egress rule since 'allowAllOutbound' is set to true; To add customize rules, set allowAllOutbound=false on the SecurityGroupSynthesis time: 12.37s

mwaa-hybrid-backend
mwaa-hybrid-backend: deploying...
[0%] start: Publishing 2695cb7a9f601cf94a4151c65c9069787d9ec312084346f2f4359e3f55ff2310:704533066374-eu-central-1
[100%] success: Published 2695cb7a9f601cf94a4151c65c9069787d9ec312084346f2f4359e3f55ff2310:704533066374-eu-central-1

 ✅  mwaa-hybrid-backend (no changes)

✨  Deployment time: 1.97s

Outputs:
mwaa-hybrid-backend.ExportsOutputRefMWAAHybridApacheAirflowVPC677B092EF6F2F587 = vpc-0bbdeee3652ef21ff
mwaa-hybrid-backend.ExportsOutputRefMWAAHybridApacheAirflowVPCprivateSubnet1Subnet2A6995DF7F8D3134 = subnet-01e48db64381efc7f
mwaa-hybrid-backend.ExportsOutputRefMWAAHybridApacheAirflowVPCprivateSubnet2SubnetA28659530C36370A = subnet-0321530b8154f9bd2
mwaa-hybrid-backend.VPCId = vpc-0bbdeee3652ef21ff
Stack ARN:
arn:aws:cloudformation:eu-central-1:704533066374:stack/mwaa-hybrid-backend/b05897d0-f087-11ec-b5f3-02db3f47a5ca

✨  Total time: 14.35s

mwaa-hybrid-environment
This deployment will make potentially sensitive changes according to your current security approval level (--require-approval broadening).
Please confirm you intend to make the following modifications:

IAM Statement Changes
┌───┬──────────────────────────────┬────────┬──────────────────────────────┬──────────────────────────────┬─────────────────────────────────┐
│   │ ResourceEffectActionPrincipalCondition                       │
├───┼──────────────────────────────┼────────┼──────────────────────────────┼──────────────────────────────┼─────────────────────────────────┤
│ + │ ${Custom::CDKBucketDeploymenAllowsts:AssumeRoleService:lambda.amazonaws.com │                                 │
│   │ t8693BB64968944B69AAFB0CC9EB │        │                              │                              │                                 │
│   │ 8756C/ServiceRole.Arn}       │        │                              │                              │                                 │
├───┼──────────────────────────────┼────────┼──────────────────────────────┼──────────────────────────────┼─────────────────────────────────┤
│ + │ ${mwaa-dags.Arn}             │ Denys3:ListAllMyBucketsAWS:${mwaa-service-role}     │                                 │
│   │ ${mwaa-dags.Arn}/*           │        │                              │                              │                                 │
│ + │ ${mwaa-dags.Arn}             │ Allows3:*                         │ AWS:${mwaa-service-role}     │                                 │
│   │ ${mwaa-dags.Arn}/*           │        │                              │                              │                                 │
│ + │ ${mwaa-dags.Arn}             │ Allows3:Abort*                    │ AWS:${Custom::CDKBucketDeplo │                                 │
│   │ ${mwaa-dags.Arn}/*           │        │ s3:DeleteObject*             │ yment8693BB64968944B69AAFB0C │                                 │
│   │                              │        │ s3:GetBucket*                │ C9EB8756C/ServiceRole}       │                                 │
│   │                              │        │ s3:GetObject*                │                              │                                 │
│   │                              │        │ s3:List*                     │                              │                                 │
│   │                              │        │ s3:PutObject                 │                              │                                 │
├───┼──────────────────────────────┼────────┼──────────────────────────────┼──────────────────────────────┼─────────────────────────────────┤
│ + │ ${mwaa-hybrid-demoKey.Arn}   │ Allowkms:CancelKeyDeletionAWS:arn:${AWS::Partition}:ia │                                 │
│   │                              │        │ kms:Create*                  │ m::704533066374:root         │                                 │
│   │                              │        │ kms:Decrypt*                 │                              │                                 │
│   │                              │        │ kms:Delete*                  │                              │                                 │
│   │                              │        │ kms:Describe*                │                              │                                 │
│   │                              │        │ kms:Disable*                 │                              │                                 │
│   │                              │        │ kms:Enable*                  │                              │                                 │
│   │                              │        │ kms:GenerateDataKey*         │                              │                                 │
│   │                              │        │ kms:Get*                     │                              │                                 │
│   │                              │        │ kms:List*                    │                              │                                 │
│   │                              │        │ kms:Put*                     │                              │                                 │
│   │                              │        │ kms:Revoke*                  │                              │                                 │
│   │                              │        │ kms:ScheduleKeyDeletion      │                              │                                 │
│   │                              │        │ kms:Update*                  │                              │                                 │
│ + │ ${mwaa-hybrid-demoKey.Arn}   │ Allowkms:Decrypt*                 │ Service:logs.eu-central-1.am │ "ArnLike": {                    │
│   │                              │        │ kms:Describe*                │ azonaws.com                  │   "kms:EncryptionContext:aws:lo │
│   │                              │        │ kms:Encrypt*                 │                              │ gs:arn": "arn:aws:logs:eu-centr │
│   │                              │        │ kms:GenerateDataKey*         │                              │ al-1:704533066374:*"            │
│   │                              │        │ kms:PutKeyPolicy             │                              │ }                               │
│   │                              │        │ kms:ReEncrypt*               │                              │                                 │
├───┼──────────────────────────────┼────────┼──────────────────────────────┼──────────────────────────────┼─────────────────────────────────┤
│ + │ ${mwaa-service-role.Arn}     │ Allowsts:AssumeRoleService:airflow-env.amazonaw │                                 │
│   │                              │        │                              │ s.com                        │                                 │
│   │                              │        │                              │ Service:airflow.amazonaws.co │                                 │
│   │                              │        │                              │ m                            │                                 │
│   │                              │        │                              │ Service:ecs-tasks.amazonaws. │                                 │
│   │                              │        │                              │ com                          │                                 │
├───┼──────────────────────────────┼────────┼──────────────────────────────┼──────────────────────────────┼─────────────────────────────────┤
│ + │ *                            │ Allowlogs:DescribeLogGroupsAWS:${mwaa-service-role}     │                                 │
│ + │ *                            │ Allowecs:DescribeTaskDefinitionAWS:${mwaa-service-role}     │                                 │
│   │                              │        │ ecs:DescribeTasks            │                              │                                 │
│   │                              │        │ ecs:ListTasks                │                              │                                 │
│   │                              │        │ ecs:RegisterTaskDefinition   │                              │                                 │
│   │                              │        │ ecs:RunTask                  │                              │                                 │
│ + │ *                            │ Allowiam:PassRoleAWS:${mwaa-service-role}     │ "StringLike": {                 │
│   │                              │        │                              │                              │   "iam:PassedToService": "ecs-t │
│   │                              │        │                              │                              │ asks.amazonaws.com"             │
│   │                              │        │                              │                              │ }                               │
│ + │ *                            │ Allowkms:DecryptAWS:${mwaa-service-role}     │ "StringEquals": {               │
│   │                              │        │ kms:DescribeKey              │                              │   "kms:ViaService": [           │
│   │                              │        │ kms:Encrypt                  │                              │     "sqs.eu-central-1.amazonaws │
│   │                              │        │ kms:GenerateDataKey*         │                              │ .com",                          │
│   │                              │        │ kms:PutKeyPolicy             │                              │     "s3.eu-central-1.amazonaws. │
│   │                              │        │                              │                              │ com"                            │
│   │                              │        │                              │                              │   ]                             │
│   │                              │        │                              │                              │ }                               │
├───┼──────────────────────────────┼────────┼──────────────────────────────┼──────────────────────────────┼─────────────────────────────────┤
│ + │ arn:${AWS::Partition}:s3:::cAllows3:GetBucket*                │ AWS:${Custom::CDKBucketDeplo │                                 │
│   │ dk-hnb659fds-assets-70453306 │        │ s3:GetObject*                │ yment8693BB64968944B69AAFB0C │                                 │
│   │ 6374-eu-central-1            │        │ s3:List*                     │ C9EB8756C/ServiceRole}       │                                 │
│   │ arn:${AWS::Partition}:s3:::c │        │                              │                              │                                 │
│   │ dk-hnb659fds-assets-70453306 │        │                              │                              │                                 │
│   │ 6374-eu-central-1/*          │        │                              │                              │                                 │
├───┼──────────────────────────────┼────────┼──────────────────────────────┼──────────────────────────────┼─────────────────────────────────┤
│ + │ arn:aws:airflow:eu-central-1Allowairflow:PublishMetricsAWS:${mwaa-service-role}     │                                 │
│   │ :704533066374:environment/mw │        │                              │                              │                                 │
│   │ aa-hybrid-demo               │        │                              │                              │                                 │
├───┼──────────────────────────────┼────────┼──────────────────────────────┼──────────────────────────────┼─────────────────────────────────┤
│ + │ arn:aws:logs:eu-central-1:70Allowlogs:CreateLogGroupAWS:${mwaa-service-role}     │                                 │
│   │ 4533066374:log-group:airflow │        │ logs:CreateLogStream         │                              │                                 │
│   │ -mwaa-hybrid-demo-*          │        │ logs:DescribeLogGroups       │                              │                                 │
│   │                              │        │ logs:GetLogEvents            │                              │                                 │
│   │                              │        │ logs:GetLogGroupFields       │                              │                                 │
│   │                              │        │ logs:GetLogRecord            │                              │                                 │
│   │                              │        │ logs:GetQueryResults         │                              │                                 │
│   │                              │        │ logs:PutLogEvents            │                              │                                 │
├───┼──────────────────────────────┼────────┼──────────────────────────────┼──────────────────────────────┼─────────────────────────────────┤
│ + │ arn:aws:sqs:eu-central-1:*:aAllowsqs:ChangeMessageVisibilityAWS:${mwaa-service-role}     │                                 │
│   │ irflow-celery-*              │        │ sqs:DeleteMessage            │                              │                                 │
│   │                              │        │ sqs:GetQueueAttributes       │                              │                                 │
│   │                              │        │ sqs:GetQueueUrl              │                              │                                 │
│   │                              │        │ sqs:ReceiveMessage           │                              │                                 │
│   │                              │        │ sqs:SendMessage              │                              │                                 │
└───┴──────────────────────────────┴────────┴──────────────────────────────┴──────────────────────────────┴─────────────────────────────────┘
IAM Policy Changes
┌───┬───────────────────────────────────────────────────────────────────┬───────────────────────────────────────────────────────────────────┐
│   │ ResourceManaged Policy ARN                                                │
├───┼───────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────┤
│ + │ ${Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/Serarn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasic │
│   │ viceRole}                                                         │ ExecutionRole                                                     │
└───┴───────────────────────────────────────────────────────────────────┴───────────────────────────────────────────────────────────────────┘
Security Group Changes
┌───┬────────────────────┬─────┬────────────┬────────────────────┐
│   │ GroupDirProtocolPeer               │
├───┼────────────────────┼─────┼────────────┼────────────────────┤
│ + │ ${mwaa-sg.GroupId} │ InEverything${mwaa-sg.GroupId} │
│ + │ ${mwaa-sg.GroupId} │ OutEverythingEveryone (IPv4)    │
└───┴────────────────────┴─────┴────────────┴────────────────────┘
(NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299)

Do you wish to deploy these changes (y/n)? y
mwaa-hybrid-environment: deploying...
[0%] start: Publishing e9882ab123687399f934da0d45effe675ecc8ce13b40cb946f3e1d6141fe8d68:704533066374-eu-central-1
[0%] start: Publishing 983c442a2fe823a8b4ebb18d241a5150ae15103dacbf3f038c7c6343e565aa4c:704533066374-eu-central-1
[0%] start: Publishing 91ab667f7c88c3b87cf958b7ef4158ef85fb9ba8bd198e5e0e901bb7f904d560:704533066374-eu-central-1
[0%] start: Publishing f2a926ee3d8ca4bd02b0cf073eb2bbb682e94c021925bf971a9730045ef4fb02:704533066374-eu-central-1
[25%] success: Published 983c442a2fe823a8b4ebb18d241a5150ae15103dacbf3f038c7c6343e565aa4c:704533066374-eu-central-1
[50%] success: Published 91ab667f7c88c3b87cf958b7ef4158ef85fb9ba8bd198e5e0e901bb7f904d560:704533066374-eu-central-1
[75%] success: Published f2a926ee3d8ca4bd02b0cf073eb2bbb682e94c021925bf971a9730045ef4fb02:704533066374-eu-central-1
[100%] success: Published e9882ab123687399f934da0d45effe675ecc8ce13b40cb946f3e1d6141fe8d68:704533066374-eu-central-1
mwaa-hybrid-environment: creating CloudFormation changeset...

 ✅  mwaa-hybrid-environment

✨  Deployment time: 1412.35s

Outputs:
mwaa-hybrid-environment.MWAASecurityGroup = sg-0ea83e01caded2bb3
Stack ARN:
arn:aws:cloudformation:eu-central-1:704533066374:stack/mwaa-hybrid-environment/450337a0-f088-11ec-a169-06ba63bfdfb2

✨  Total time: 1424.72s

测试环境

如果我们看一下Amazon S3桶,我们可以看到我们已经创建了MWAA桶和dags文件夹,以及上传了我们的本地DAG。

如果我们去MWAA控制台,我们可以看到我们的环境

我们现在可以抓取这个环境的URL,可以从控制台获取,也可以使用AWS CLI。只需替换MWAA环境和AWS区域的名称,然后它应该给你一个可以在浏览器中使用的URL(尽管你必须在它后面加上/home)。

注意,我使用的是jq,如果你的环境中没有这个,你可以不运行这个命令,但只需要在输出中找到 "WebserverUrl "的条目。

Shell

aws mwaa get-environment --name {name of the environment created} --region={region} | jq -r '.Environment | .WebserverUrl'

我们可以看到,我们有两个在本地文件夹中的样本DAGS,现在可以在MWAA环境中使用。

拆除/清理我们的MWAA环境

为了删除我们所部署的一切,我们所要做的就是。

Shell

cdk destroy MWAA-Environment

清理MWAA的环境需要20-30分钟。然而,它不会做的一件事是删除我们设置的亚马逊S3桶,所以你将需要通过控制台手动删除它(或使用AWS CLI - 这将是我的方法)。一旦你删除了S3桶,现在清理后端堆栈

Shell

cdk destroy MWAA-Backend

这样清理起来应该会快得多。一旦完成,你应该就可以了。