

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# Amazon Managed Workflows for Apache Airflow용 빠른 시작 튜토리얼
<a name="quick-start"></a>

이 빠른 시작 튜토리얼에서는 AWS CloudFormation 템플릿을 사용하여 Amazon VPC 인프라, `dags` 폴더가 있는 Amazon S3 버킷, Amazon Managed Workflows for Apache Airflow를 함께 생성합니다.

**Topics**
+ [이 튜토리얼에서는](#quick-start-overview)
+ [사전 조건](#quick-start-before)
+ [1단계: CloudFormation 템플릿을 로컬에 저장](#quick-start-template)
+ [2단계: AWS CLI을(를) 사용하여 스택 생성](#quick-start-createstack)
+ [3단계: Amazon S3에 DAG를 업로드하고 Apache Airflow UI에서 실행](#quick-start-upload-dag)
+ [4단계: CloudWatch Logs의 로그 액세스](#quick-start-logs)
+ [다음 단계](#quick-start-next-up)

## 이 튜토리얼에서는
<a name="quick-start-overview"></a>

이 튜토리얼을 사용하여 세 가지 AWS Command Line Interface(AWS CLI) 명령으로 Amazon S3에 DAG를 업로드하고, Apache Airflow에서 DAG를 실행하고, CloudWatch에서 로그에 액세스합니다. 마지막으로 Apache Airflow 개발 팀을 위한 IAM 정책을 생성하는 방법을 알아봅니다.

**참고**  
이 페이지의 CloudFormation 템플릿은 CloudFormation에서 사용할 수 있는 최신 버전의 Apache Airflow를 위한 Amazon Managed Workflows for Apache Airflow 환경을 생성합니다. 사용 가능한 최신 버전은 Apache Airflow v3.0.6입니다.

CloudFormation 템플릿은 다음을 생성합니다.
+ **VPC 인프라**. 이 템플릿은 [인터넷을 통한 퍼블릭 라우팅](networking-about.md#networking-about-overview-public)을(를) 사용합니다. `WebserverAccessMode: PUBLIC_ONLY`의 Apache Airflow 웹 서버에 [퍼블릭 네트워크 액세스 모드](configuring-networking.md#access-overview-public)을(를) 사용합니다.
+ **Amazon S3 버킷**. 템플릿은 `dags` 폴더가 있는 Amazon S3 버킷을 생성합니다. [Amazon MWAA용 Amazon S3 버킷 생성](mwaa-s3-bucket.md)에 정의된 대로 **버킷 버저닝**을 활성화하여 **모든 퍼블릭 액세스를 차단**하도록 구성되어 있습니다.
+ **Amazon MWAA 환경**. 이 템플릿은 Amazon S3 버킷의 `dags` 폴더와 연결된 Amazon MWAA 환경, Amazon MWAA에서 사용하는 AWS 서비스에 대한 권한을 가진 실행 역할, 그리고 [Amazon MWAA 환경 생성](create-environment.md)에서 정의한 대로 [AWS 소유 키](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#aws-owned-cmk)를 사용한 암호화의 기본 환경을 생성합니다.
+ **CloudWatch 로그** 템플릿은 [Amazon CloudWatch에서 Airflow 로그 액세스](monitoring-airflow.md)에 정의된 대로 CloudWatch에서 **INFO** 이상 수준으로 *Airflow 스케줄러 로그 그룹*, *Airflow 웹 서버 로그 그룹*, *Airflow 작업자 로그 그룹*, *Airflow DAG 프로세싱 로그 그룹* 및 *Airflow 작업 로그 그룹*에 대해 Apache Airflow 로그를 켭니다.

이 튜토리얼에서는 다음 작업을 수행할 수 있습니다.
+ **DAG를 업로드하고 실행**. Amazon MWAA가 지원하는 최신 Apache Airflow 버전에 대한 Apache Airflow 튜토리얼 DAG를 Amazon S3에 업로드한 다음 [DAG 추가 또는 업데이트](configuring-dag-folder.md)에 정의된 대로 Apache Airflow UI에서 실행할 수 있습니다.
+ **액세스 로그**: [Amazon CloudWatch에서 Airflow 로그 액세스](monitoring-airflow.md)에 정의된 대로 CloudWatch 로그에서 *Airflow 웹 서버 로그 그룹*에 엑세스합니다.
+ **액세스 제어 정책 생성**. [Amazon MWAA 환경 액세스](access-policies.md)에 정의된 대로 Apache Airflow 개발 팀을 위한 액세스 제어 정책을 IAM에서 생성합니다.

**참고**  
Amazon MWAA 환경을 호스팅하는 VPC에서, 연결된 모든 서브넷에 대해 `assignIpv6AddressOnCreation`을 `true`로 설정합니다. 이 설정은 이러한 서브넷 내의 리소스에 인터넷 프로토콜 버전 6(IPv6) 주소가 자동 할당되도록 합니다.

## 사전 조건
<a name="quick-start-before"></a>

AWS Command Line Interface(AWS CLI)는 명령줄 쉘의 명령을 사용하여 AWS 서비스와 상호 작용할 수 있는 오픈 소스 도구입니다. 이 페이지에서 단계를 완료하려면 다음이 필요합니다.
+ [AWS CLI - 버전 2 설치](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html)
+ [AWS CLI - `aws configure`을(를) 통한 빠른 구성](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html).

## 1단계: CloudFormation 템플릿을 로컬에 저장
<a name="quick-start-template"></a>
+ 다음 템플릿의 내용을 복사하고 로컬에 `mwaa-public-network.yml`로 저장합니다. [템플릿을 다운로드](./samples/mwaa-public-network.zip)할 수도 있습니다.

  ```
  AWSTemplateFormatVersion: "2010-09-09"
  
  Parameters:
  
    EnvironmentName:
      Description: An environment name that is prefixed to resource names
      Type: String
      Default: MWAAEnvironment
  
    VpcCIDR:
      Description: The IP range (CIDR notation) for this VPC
      Type: String
      Default: 10.192.0.0/16
  
    PublicSubnet1CIDR:
      Description: The IP range (CIDR notation) for the public subnet in the first Availability Zone
      Type: String
      Default: 10.192.10.0/24
  
    PublicSubnet2CIDR:
      Description: The IP range (CIDR notation) for the public subnet in the second Availability Zone
      Type: String
      Default: 10.192.11.0/24
  
    PrivateSubnet1CIDR:
      Description: The IP range (CIDR notation) for the private subnet in the first Availability Zone
      Type: String
      Default: 10.192.20.0/24
    PrivateSubnet2CIDR:
      Description: The IP range (CIDR notation) for the private subnet in the second Availability Zone
      Type: String
      Default: 10.192.21.0/24
    MaxWorkerNodes:
      Description: The maximum number of workers that can run in the environment
      Type: Number
      Default: 2
    DagProcessingLogs:
      Description: Log level for DagProcessing
      Type: String
      Default: INFO
    SchedulerLogsLevel:
      Description: Log level for SchedulerLogs
      Type: String
      Default: INFO
    TaskLogsLevel:
      Description: Log level for TaskLogs
      Type: String
      Default: INFO
    WorkerLogsLevel:
      Description: Log level for WorkerLogs
      Type: String
      Default: INFO
    WebserverLogsLevel:
      Description: Log level for WebserverLogs
      Type: String
      Default: INFO
  
  Resources:
    #####################################################################################################################
    # CREATE VPC
    #####################################################################################################################
  
    VPC:
      Type: AWS::EC2::VPC
      Properties:
        CidrBlock: !Ref VpcCIDR
        EnableDnsSupport: true
        EnableDnsHostnames: true
        Tags:
          - Key: Name
            Value: MWAAEnvironment
  
    InternetGateway:
      Type: AWS::EC2::InternetGateway
      Properties:
        Tags:
          - Key: Name
            Value: MWAAEnvironment
  
    InternetGatewayAttachment:
      Type: AWS::EC2::VPCGatewayAttachment
      Properties:
        InternetGatewayId: !Ref InternetGateway
        VpcId: !Ref VPC
  
    PublicSubnet1:
      Type: AWS::EC2::Subnet
      Properties:
        VpcId: !Ref VPC
        AvailabilityZone: !Select [ 0, !GetAZs '' ]
        CidrBlock: !Ref PublicSubnet1CIDR
        MapPublicIpOnLaunch: true
        Tags:
          - Key: Name
            Value: !Sub ${EnvironmentName} Public Subnet (AZ1)
  
    PublicSubnet2:
      Type: AWS::EC2::Subnet
      Properties:
        VpcId: !Ref VPC
        AvailabilityZone: !Select [ 1, !GetAZs  '' ]
        CidrBlock: !Ref PublicSubnet2CIDR
        MapPublicIpOnLaunch: true
        Tags:
          - Key: Name
            Value: !Sub ${EnvironmentName} Public Subnet (AZ2)
  
    PrivateSubnet1:
      Type: AWS::EC2::Subnet
      Properties:
        VpcId: !Ref VPC
        AvailabilityZone: !Select [ 0, !GetAZs  '' ]
        CidrBlock: !Ref PrivateSubnet1CIDR
        MapPublicIpOnLaunch: false
        Tags:
          - Key: Name
            Value: !Sub ${EnvironmentName} Private Subnet (AZ1)
  
    PrivateSubnet2:
      Type: AWS::EC2::Subnet
      Properties:
        VpcId: !Ref VPC
        AvailabilityZone: !Select [ 1, !GetAZs  '' ]
        CidrBlock: !Ref PrivateSubnet2CIDR
        MapPublicIpOnLaunch: false
        Tags:
          - Key: Name
            Value: !Sub ${EnvironmentName} Private Subnet (AZ2)
  
    NatGateway1EIP:
      Type: AWS::EC2::EIP
      DependsOn: InternetGatewayAttachment
      Properties:
        Domain: vpc
  
    NatGateway2EIP:
      Type: AWS::EC2::EIP
      DependsOn: InternetGatewayAttachment
      Properties:
        Domain: vpc
  
    NatGateway1:
      Type: AWS::EC2::NatGateway
      Properties:
        AllocationId: !GetAtt NatGateway1EIP.AllocationId
        SubnetId: !Ref PublicSubnet1
  
    NatGateway2:
      Type: AWS::EC2::NatGateway
      Properties:
        AllocationId: !GetAtt NatGateway2EIP.AllocationId
        SubnetId: !Ref PublicSubnet2
  
    PublicRouteTable:
      Type: AWS::EC2::RouteTable
      Properties:
        VpcId: !Ref VPC
        Tags:
          - Key: Name
            Value: !Sub ${EnvironmentName} Public Routes
  
    DefaultPublicRoute:
      Type: AWS::EC2::Route
      DependsOn: InternetGatewayAttachment
      Properties:
        RouteTableId: !Ref PublicRouteTable
        DestinationCidrBlock: 0.0.0.0/0
        GatewayId: !Ref InternetGateway
  
    PublicSubnet1RouteTableAssociation:
      Type: AWS::EC2::SubnetRouteTableAssociation
      Properties:
        RouteTableId: !Ref PublicRouteTable
        SubnetId: !Ref PublicSubnet1
  
    PublicSubnet2RouteTableAssociation:
      Type: AWS::EC2::SubnetRouteTableAssociation
      Properties:
        RouteTableId: !Ref PublicRouteTable
        SubnetId: !Ref PublicSubnet2
  
  
    PrivateRouteTable1:
      Type: AWS::EC2::RouteTable
      Properties:
        VpcId: !Ref VPC
        Tags:
          - Key: Name
            Value: !Sub ${EnvironmentName} Private Routes (AZ1)
  
    DefaultPrivateRoute1:
      Type: AWS::EC2::Route
      Properties:
        RouteTableId: !Ref PrivateRouteTable1
        DestinationCidrBlock: 0.0.0.0/0
        NatGatewayId: !Ref NatGateway1
  
    PrivateSubnet1RouteTableAssociation:
      Type: AWS::EC2::SubnetRouteTableAssociation
      Properties:
        RouteTableId: !Ref PrivateRouteTable1
        SubnetId: !Ref PrivateSubnet1
  
    PrivateRouteTable2:
      Type: AWS::EC2::RouteTable
      Properties:
        VpcId: !Ref VPC
        Tags:
          - Key: Name
            Value: !Sub ${EnvironmentName} Private Routes (AZ2)
  
    DefaultPrivateRoute2:
      Type: AWS::EC2::Route
      Properties:
        RouteTableId: !Ref PrivateRouteTable2
        DestinationCidrBlock: 0.0.0.0/0
        NatGatewayId: !Ref NatGateway2
  
    PrivateSubnet2RouteTableAssociation:
      Type: AWS::EC2::SubnetRouteTableAssociation
      Properties:
        RouteTableId: !Ref PrivateRouteTable2
        SubnetId: !Ref PrivateSubnet2
  
    SecurityGroup:
      Type: AWS::EC2::SecurityGroup
      Properties:
        GroupName: "mwaa-security-group"
        GroupDescription: "Security group with a self-referencing inbound rule."
        VpcId: !Ref VPC
  
    SecurityGroupIngress:
      Type: AWS::EC2::SecurityGroupIngress
      Properties:
        GroupId: !Ref SecurityGroup
        IpProtocol: "-1"
        SourceSecurityGroupId: !Ref SecurityGroup
  
    EnvironmentBucket:
      Type: AWS::S3::Bucket
      Properties:
        VersioningConfiguration:
          Status: Enabled
        PublicAccessBlockConfiguration: 
          BlockPublicAcls: true
          BlockPublicPolicy: true
          IgnorePublicAcls: true
          RestrictPublicBuckets: true
  
    #####################################################################################################################
    # CREATE MWAA
    #####################################################################################################################
  
    MwaaEnvironment:
      Type: AWS::MWAA::Environment
      DependsOn: MwaaExecutionPolicy
      Properties:
        Name: !Sub "${AWS::StackName}-MwaaEnvironment"
        SourceBucketArn: !GetAtt EnvironmentBucket.Arn
        ExecutionRoleArn: !GetAtt MwaaExecutionRole.Arn
        DagS3Path: dags/  
        NetworkConfiguration:
          SecurityGroupIds:
            - !GetAtt SecurityGroup.GroupId
          SubnetIds:
            - !Ref PrivateSubnet1
            - !Ref PrivateSubnet2
        WebserverAccessMode: PUBLIC_ONLY
        MaxWorkers: !Ref MaxWorkerNodes
        LoggingConfiguration:
          DagProcessingLogs:
            LogLevel: !Ref DagProcessingLogs
            Enabled: true
          SchedulerLogs:
            LogLevel: !Ref SchedulerLogsLevel
            Enabled: true
          TaskLogs:
            LogLevel: !Ref TaskLogsLevel
            Enabled: true
          WorkerLogs:
            LogLevel: !Ref WorkerLogsLevel
            Enabled: true
          WebserverLogs:
            LogLevel: !Ref WebserverLogsLevel
            Enabled: true
  
    MwaaExecutionRole:
      Type: AWS::IAM::Role
      Properties:
        AssumeRolePolicyDocument:
          Version: 2012-10-17&TCX5-2025-waiver;
          Statement:
            - Effect: Allow
              Principal:
                Service:
                  - airflow-env.amazonaws.com
                  - airflow.amazonaws.com
              Action:
               - "sts:AssumeRole"
        Path: "/service-role/"
  
    MwaaExecutionPolicy:
      DependsOn: EnvironmentBucket
      Type: AWS::IAM::ManagedPolicy
      Properties:
        Roles:
          - !Ref MwaaExecutionRole
        PolicyDocument:
          Version: 2012-10-17&TCX5-2025-waiver;
          Statement:
            - Effect: Allow
              Action: airflow:PublishMetrics
              Resource:
                - !Sub "arn:aws:airflow:${AWS::Region}:${AWS::AccountId}:environment/${EnvironmentName}"
            - Effect: Deny
              Action: s3:ListAllMyBuckets
              Resource:
                - !Sub "${EnvironmentBucket.Arn}"
                - !Sub "${EnvironmentBucket.Arn}/*"
  
            - Effect: Allow
              Action:
                - "s3:GetObject*"
                - "s3:GetBucket*"
                - "s3:List*"
              Resource:
                - !Sub "${EnvironmentBucket.Arn}"
                - !Sub "${EnvironmentBucket.Arn}/*"
            - Effect: Allow
              Action:
                - logs:DescribeLogGroups
              Resource: "*"
  
            - Effect: Allow
              Action:
                - logs:CreateLogStream
                - logs:CreateLogGroup
                - logs:PutLogEvents
                - logs:GetLogEvents
                - logs:GetLogRecord
                - logs:GetLogGroupFields
                - logs:GetQueryResults
                - logs:DescribeLogGroups
              Resource:
                - !Sub "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:airflow-${AWS::StackName}*"
            - Effect: Allow
              Action: cloudwatch:PutMetricData
              Resource: "*"
            - Effect: Allow
              Action:
                - sqs:ChangeMessageVisibility
                - sqs:DeleteMessage
                - sqs:GetQueueAttributes
                - sqs:GetQueueUrl
                - sqs:ReceiveMessage
                - sqs:SendMessage
              Resource:
                - !Sub "arn:aws:sqs:${AWS::Region}:*:airflow-celery-*"
            - Effect: Allow
              Action:
                - kms:Decrypt
                - kms:DescribeKey
                - "kms:GenerateDataKey*"
                - kms:Encrypt
              NotResource: !Sub "arn:aws:kms:*:${AWS::AccountId}:key/*"
              Condition:
                StringLike:
                  "kms:ViaService":
                    - !Sub "sqs.${AWS::Region}.amazonaws.com"
  Outputs:
    VPC:
      Description: A reference to the created VPC
      Value: !Ref VPC
  
    PublicSubnets:
      Description: A list of the public subnets
      Value: !Join [ ",", [ !Ref PublicSubnet1, !Ref PublicSubnet2 ]]
  
    PrivateSubnets:
      Description: A list of the private subnets
      Value: !Join [ ",", [ !Ref PrivateSubnet1, !Ref PrivateSubnet2 ]]
  
    PublicSubnet1:
      Description: A reference to the public subnet in the 1st Availability Zone
      Value: !Ref PublicSubnet1
  
    PublicSubnet2:
      Description: A reference to the public subnet in the 2nd Availability Zone
      Value: !Ref PublicSubnet2
  
    PrivateSubnet1:
      Description: A reference to the private subnet in the 1st Availability Zone
      Value: !Ref PrivateSubnet1
  
    PrivateSubnet2:
      Description: A reference to the private subnet in the 2nd Availability Zone
      Value: !Ref PrivateSubnet2
  
    SecurityGroupIngress:
      Description: Security group with self-referencing inbound rule
      Value: !Ref SecurityGroupIngress
  
    MwaaApacheAirflowUI:
      Description: MWAA Environment
      Value: !Sub  "https://${MwaaEnvironment.WebserverUrl}"
  ```

## 2단계: AWS CLI을(를) 사용하여 스택 생성
<a name="quick-start-createstack"></a>

1. 명령 프롬프트에서 `mwaa-public-network.yml`이 저장된 디렉터리로 이동합니다. 예:

   ```
   cd mwaaproject
   ```

1. AWS CLI을(를) 사용하여 스택을 생성하려면 [https://docs.aws.amazon.com/cli/latest/reference/cloudformation/create-stack.html](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/create-stack.html) 명령을 사용합니다.

   ```
   aws cloudformation create-stack --stack-name mwaa-environment-public-network --template-body file://mwaa-public-network.yml --capabilities CAPABILITY_IAM
   ```
**참고**  
Amazon VPC 인프라, Amazon S3 버킷, Amazon MWAA 환경을 생성하는 데 30분 이상이 소요됩니다.

## 3단계: Amazon S3에 DAG를 업로드하고 Apache Airflow UI에서 실행
<a name="quick-start-upload-dag"></a>

1. [지원되는 최신 Apache Airflow 버전](https://airflow.apache.org/docs/apache-airflow/2.2.2/tutorial.html)의 `tutorial.py` 파일 내용을 복사하고 로컬에 `tutorial.py`(으)로 저장합니다.

1. 명령 프롬프트에서 `tutorial.py`이 저장된 디렉터리로 이동합니다. 예:

   ```
   cd mwaaproject
   ```

1. 다음 명령을 사용하여 Amazon S3 버킷을 모두 나열합니다.

   ```
   aws s3 ls
   ```

1. 다음 명령을 사용하여 사용자 환경의 Amazon S3 버킷에 있는 파일과 폴더를 나열합니다.

   ```
   aws s3 ls s3://YOUR_S3_BUCKET_NAME
   ```

1. 다음 스크립트를 사용하면 `tutorial.py` 파일을 `dags` 폴더에 업로드할 수 있습니다. *amzn-s3-demo-bucket*의 샘플 값을 대체합니다.

   ```
   aws s3 cp tutorial.py s3://amzn-s3-demo-bucket/dags/
   ```

1. Amazon MWAA 콘솔에서 [환경 페이지](https://console.aws.amazon.com/mwaa/home#/environments)를 엽니다.

1. 환경을 선택합니다.

1. **Airflow UI 열기**를 선택합니다.

1. Apache Airflow UI의 사용 가능한 DAG 목록에서 **튜토리얼** DAG를 선택합니다.

1. DAG 세부 정보 페이지에서 DAG 이름 옆에 있는 **DAG 일시 중지/일시 중지 해제** 토글을 선택하여 DAG 일시 중지를 해제합니다.

1. **트리거 DAG**를 선택합니다.

## 4단계: CloudWatch Logs의 로그 액세스
<a name="quick-start-logs"></a>

CloudWatch 콘솔에서 CloudFormation 스택에 의해 켜진 모든 Apache Airflow 로그의 Apache Airflow 로그에 액세스할 수 있습니다. 다음 섹션에서는 *Airflow 웹 서버 로그 그룹*의 로그에 액세스하는 방법을 설명합니다.

1. Amazon MWAA 콘솔에서 [환경 페이지](https://console.aws.amazon.com/mwaa/home#/environments)를 엽니다.

1. 환경을 선택합니다.

1. **모니터링** 창에서 **Airflow 웹 서버 로그 그룹**을 선택합니다.

1. **로그 스트림**에서 `webserver_console_ip` 로그를 선택합니다.

## 다음 단계
<a name="quick-start-next-up"></a>
+ DAG를 업로드하고, `requirements.txt`에서 Python 종속성을 지정하고, [Amazon MWAA에서 DAG 작업](working-dags.md)의 `plugins.zip`에서 사용자 지정 플러그인을 지정하는 방법에 대해 자세히 알아봅니다.
+ [Amazon MWAA의 Apache Airflow 성능 튜닝](best-practices-tuning.md)에서 환경 성능 조정을 위해 권장하는 모범 사례에 대해 자세히 알아봅니다.
+ [Amazon MWAA의 대시보드 및 알람 모니터링](monitoring-dashboard.md)에서 사용자 환경을 위한 모니터링 대시보드를 생성합니다.
+ [Amazon Managed Workflows for Apache Airflow용 코드 예제](sample-code.md)에서 일부 DAG 코드 샘플을 실행합니다.