

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 为 Apache Airflow Web 服务器设置自定义域
<a name="configuring-custom-domain"></a>

使用 Amazon Managed Workflows for Apache Airflow (Amazon MWAA) 时，您可以为托管式 Apache Airflow Web 服务器设置自定义域。通过使用自定义域，您可以使用 Apache Airflow 用户界面、Apache Airflow CLI 或 Apache Airflow Web 服务器访问环境的 Amazon MWAA 托管式 Apache Airflow Web 服务器。

**注意**  
您只能在无互联网访问权限的私有 Web 服务器上使用自定义域。

**Amazon MWAA 上的自定义域应用场景**

1. 在 AWS 上的云应用程序中共享 Web 服务器域：通过使用自定义域，您可以定义用于访问 Web 服务器的用户友好型 URL，而不是生成的服务域名。您可以存储此自定义域，并将其作为应用程序中的环境变量共享。

1. 访问私有 Web 服务器：如果您想为无互联网访问权限的 VPC 中的 Web 服务器配置访问权限，使用自定义域可以简化 URL 重定向工作流。

**Topics**
+ [配置自定义域](#create-environment-with-custom-domain)
+ [设置联网基础设施](#set-up-networking-for-custom-domain)

## 配置自定义域
<a name="create-environment-with-custom-domain"></a>

要配置自定义域功能，您需要在创建或更新 Amazon MWAA 环境时通过 `webserver.base_url` Apache Airflow 配置来提供自定义域值。以下约束适用于自定义域名：
+ 该值应是不含任何协议或路径的完全限定域名 (FQDN)。例如 `your-custom-domain.com`。
+ Amazon MWAA 不允许在 URL 中添加路径。例如，`your-custom-domain.com/dags/` 不是有效的自定义域名。
+ URL 长度最多为 255 个 ASCII 字符。
+ 如果您提供空字符串，则默认情况下将使用 Amazon MWAA 生成的 Web 服务器 URL 创建环境。

根据以下示例使用 AWS CLI 创建带有自定义 Web 服务器域名的环境。

```
aws mwaa create-environment \
--name my-mwaa-env \
--source-bucket-arn arn:aws:s3:::amzn-s3-demo-bucket \
--airflow-configuration-options '{"webserver.base_url":"my-custom-domain.com"}' \
--network-configuration '{"SubnetIds":["subnet-0123456789abcdef","subnet-fedcba9876543210"]}' \
--execution-role-arn arn:aws:iam::123456789012:role/my-execution-role
```

创建或更新环境后，您需要在 AWS 账户 中设置联网基础设施，以便通过自定义域访问私有 Web 服务器。

要恢复使用默认由服务生成的 URL，请更新您的私有环境并移除 `webserver.base_url` 配置选项。

## 设置联网基础设施
<a name="set-up-networking-for-custom-domain"></a>

执行以下步骤设置所需的联网基础设施，以便与 AWS 账户 中的自定义域一起使用。

1. 获取 Amazon VPC 端点网络接口（ENI）的 IP 地址。要执行此操作，请首先使用 [https://awscli.amazonaws.com/v2/documentation/api/2.9.6/reference/mwaa/get-environment.html](https://awscli.amazonaws.com/v2/documentation/api/2.9.6/reference/mwaa/get-environment.html) 查找适合环境的 `WebserverVpcEndpointService`。

   ```
   aws mwaa get-environment --name your-environment-name
   ```

   如果成功，您将收到与以下内容类似的输出。

   ```
   {
     "Environment": {
       "AirflowConfigurationOptions": {},
       "AirflowVersion": "latest-version",
       "Arn": "environment-arn",
       "CreatedAt": "2024-06-01T01:00:00-00:00",
       "DagS3Path": "dags",
       .
       .
       .
       "WebserverVpcEndpointService": "web-server-vpc-endpoint-service",
       "WeeklyMaintenanceWindowStart": "TUE:21:30"
     }
   }
   ```

   记下 `WebserverVpcEndpointService` 值并将其用于以下 Amazon EC2 `describe-vpc-endpoints` 命令中的 `web-server-vpc-endpoint-service`。以下命令中的 `--filters Name=service-name,Values=web-server-vpc-endpoint-service-id`。

1. 检索 Amazon VPC 端点详细信息。此命令用于获取与特定服务名称匹配的 Amazon VPC 端点详细信息，并以文本格式返回端点 ID 和关联的网络接口 ID。

   ```
   aws ec2 describe-vpc-endpoints \
    --filters Name=service-name,Values=web-server-vpc-endpoint-service \
    --query 'VpcEndpoints[*].{EndpointId:VpcEndpointId,NetworkInterfaceIds:NetworkInterfaceIds}' \
    --output text
   ```

1. 获取网络接口详细信息。此命令用于检索与上一步中所确定 Amazon VPC 端点关联的每个网络接口的私有 IP 地址。

   ```
   for eni_id in $(
     aws ec2 describe-vpc-endpoints \
      --filters Name=service-name,Values=service-id \
      --query 'VpcEndpoints[*].NetworkInterfaceIds' \
      --output text
    ); do
    aws ec2 describe-network-interfaces \
     --network-interface-ids $eni_id \
     --query 'NetworkInterfaces[*].PrivateIpAddresses[*].PrivateIpAddress' \
     --output text
   						done
   ```

1. 使用 `create-target-group` 创建新的目标组。您将使用此目标组来注册 Web 服务器 Amazon VPC 端点的 IP 地址。

   ```
   aws elbv2 create-target-group \
   --name new-target-group-namne \
   --protocol HTTPS \
   --port 443 \
   --vpc-id web-server-vpc-id \
   --target-type ip \
   --health-check-protocol HTTPS \
   --health-check-port 443 \
   --health-check-path / \
   --health-check-enabled \
   --matcher 'HttpCode="200,302"'
   ```

   使用 `register-targets` 命令注册 IP 地址。

   ```
   aws elbv2 register-targets \
   --target-group-arn target-group-arn \
   --targets Id=ip-address-1 Id=ip-address-2
   ```

1. 请求 ACM 证书。如果您使用的是现有证书，则跳过此步骤。

   ```
   aws acm request-certificate \
   --domain-name my-custom-domain.com \
   --validation-method DNS
   ```

1. 配置 Application Load Balancer。首先创建负载均衡器，然后为该负载均衡器创建侦听器。指定在上一步中创建的 ACM 证书。

   ```
   aws elbv2 create-load-balancer \
   --name my-mwaa-lb \
   --type application \
   --subnets subnet-id-1 subnet-id-2
   ```

   ```
   aws elbv2 create-listener \
   --load-balancer-arn load-balancer-arn \
   --protocol HTTPS \
   --port 443 \
   --ssl-policy ELBSecurityPolicy-2016-08 \
   --certificates CertificateArn=acm-certificate-arn \
   --default-actions Type=forward,TargetGroupArn=target-group-arn
   ```

   如果您在私有子网中使用网络负载均衡器，请设置[堡垒主机](tutorials-private-network-bastion.md)或 [Site-to-Site VPN 隧道](tutorials-private-network-vpn-client.md)来访问 Web 服务器。

1. 使用 Route 53 为该域创建托管区。

   ```
   aws route53 create-hosted-zone --name my-custom-domain.com \
   --caller-reference 1
   ```

   为该域创建一条 A 记录。要使用 AWS CLI 执行此操作，请使用 `list-hosted-zones-by-name` 获取托管区 ID，然后使用 `change-resource-record-sets` 应用记录。

   ```
   HOSTED_ZONE_ID=$(aws route53 list-hosted-zones-by-name \
   --dns-name my-custom-domain.com \
   --query 'HostedZones[0].Id' --output text)
   ```

   ```
   aws route53 change-resource-record-sets \
   --hosted-zone-id $HOSTED_ZONE_ID \
   --change-batch '{
     "Changes": [
       {
         "Action": "CREATE",
         "ResourceRecordSet": {
           "Name": "my-custom-domain.com",
           "Type": "A",
           "AliasTarget": {
             "HostedZoneId": "load-balancer-hosted-zone-id>",
             "DNSName": "load-balancer-dns-name",
             "EvaluateTargetHealth": true
           }
         }
       }
     ]
   }'
   ```

1. 更新 Web 服务器 Amazon VPC 端点的安全组规则，使其遵循最低权限原则，仅允许来自应用程序负载均衡器所在公有子网的 HTTPS 流量。将以下 JSON 保存到本地。例如，`sg-ingress-ip-permissions.json`。

   ```
   [
     {
       "IpProtocol": "tcp",
       "FromPort": 443,
       "ToPort": 443,
       "UserIdGroupPairs": [
         {
           "GroupId": "load-balancer-security-group-id"
         }
       ],
       "IpRanges": [
         {
           "CidrIp": "public-subnet-1-cidr"
         },
         {
           "CidrIp": "public-subnet-2-cidr"
         }
       ]
     }
   ]
   ```

   运行以下 Amazon EC2 命令更新入口安全组规则。指定 `--ip-permissions` 的 JSON 文件。

   ```
   aws ec2 authorize-security-group-ingress \
   --group-id <security-group-id> \
   --ip-permissions file://sg-ingress-ip-permissions.json
   ```

   运行以下 Amazon EC2 命令更新出口规则。

   ```
   aws ec2 authorize-security-group-egress \
   --group-id webserver-vpc-endpoint-security-group-id \
   --protocol tcp \
   --port 443 \
   --source-group load-balancer-security-group-id
   ```

打开 Amazon MWAA 控制台并导航到 Apache Airflow UI。如果是在私有子网中设置网络负载均衡器，而不是此处使用的应用程序负载均衡器，则必须使用以下选项之一访问 Web 服务器。
+ [教程：使用 Linux 堡垒主机配置私有网络访问权限](tutorials-private-network-bastion.md)
+ [教程：使用 AWS Client VPN 配置私有网络访问权限](tutorials-private-network-vpn-client.md)