LoginSignup
3
2

More than 5 years have passed since last update.

[JAWS-UG CLI] ACM入門 #8 ALBでACM証明書を用いたHTTP/2配信環境の構築

Posted at

これはAWS Certificate Manager (ACM)入門ハンズオン資料の一部です。
最初から続けて行っている場合「0.準備」の各項は作業不要です。第1項へ進んでください

前提条件

us-east-1 リージョンにACMによるSSL証明書を発行済みであること。
(ALBは他リージョンでも利用可能ですが、今回はCloudFrontとSSL証明書を共有する事を想定しているため us-east-1 リージョンとしています)
us-east-1 リージョンにWebサーバが稼働しているEC2インスタンスが起動していること。

デフォルトVPCとサブネットが存在すること

us-east-1 リージョンにデフォルトVPCと、デフォルトVPCの各AZにサブネットが1つずつ存在すること。
アカウントを作成後、VPCに変更削除をしていなければ問題ありません。

必要な権限

トラブル防止の為、全ての操作が可能なクレデンシャル(アカウント)を原則として使用してください。

AWS CLI

以下のバージョンで動作確認済

  • AWS CLI 1.10.63
コマンド
aws --version
結果(例)
      aws-cli/1.10.63 Python/2.7.11 Darwin/15.6.0 botocore/1.4.53

注意:elbv2は2016年8月実装の新機能です。バージョン 1.10.57 より古い場合は動作しません。
次のコマンドを実行して最新版に更新しましょう。

コマンド
sudo -H pip install -U awscli

0. 準備

0.1. リージョンの決定

今回はバージニアリージョン(us-east-1)で作業してください。

変数の設定
export AWS_DEFAULT_REGION='us-east-1'

0.2. 変数の確認

プロファイルが想定のものになっていることを確認します。

変数の確認
aws configure list
結果(例)
            Name                    Value             Type    Location
            ----                    -----             ----    --------
         profile                <not set>             None    None
      access_key     ****************2LMA shared-credentials-file
      secret_key     ****************VXyK shared-credentials-file
          region                us-east-1      config-file    ~/.aws/config

0.3. VPC IDの取得

コマンド
VPC_ID=` aws ec2 describe-vpcs \
          --filters Name=isDefault,Values=true \
          --query 'Vpcs[].VpcId' \
          --output text ` && echo ${VPC_ID}
結果(例)
      vpc-xxxxxxxx

0.4. Subnet IDの取得

コマンド
aws ec2 describe-subnets \
 --query "Subnets[?VpcId==\`${VPC_ID}\`].[SubnetId,CidrBlock]" --output text
結果(例)
      subnet-77777777 172.31.48.0/20
      subnet-55555555 172.31.32.0/20
      subnet-11111111 172.31.0.0/20
      subnet-33333333 172.31.16.0/20

出力結果は左がsubnet id、右がそのサブネットのCIDRブロックです。
172.31.0.0/20のSubnet idを変数 SUBNET_ID1 へ、172.31.16.0/20のものをSUBNET_ID2 へ、コピーペーストして変数へ格納します。

コマンド
SUBNET_ID1="subnet-11111111"
SUBNET_ID2="subnet-33333333"

0.5. ACM証明書arnの変数への格納

(本作業は最初から続けて行っている場合は不要です)
証明書のarnを変数 CERT_ARN へ格納します。

コマンド(例)
CERT_ARN=`aws acm list-certificates --region us-east-1 \
 --query CertificateSummaryList[].CertificateArn \
 --output text` && echo ${CERT_ARN}
結果
      arn:aws:acm:us-east-1:777777777777:certificate/9eb6865a-63a3-48df-92c2-ae113c877b33

0.6. EC2インスタンスIDの変数への格納

コマンド(例)
EC2_INSTANCE_ID=`aws ec2 describe-instances \
 --query Reservations[].Instances[].InstanceId \
 --output text` && echo ${EC2_INSTANCE_ID}
結果
      i-88888888888888888

1. セキュリティグループの作成

1.1. ALB用セキュリティグループの作成

セキュリティグループ elbv2-handson-sg を作成します。

コマンド
SG_NAME="elbv2-handson-sg"
SG_ID=`aws ec2 create-security-group --group-name ${SG_NAME} \
 --description ${SG_NAME} --output text` && echo ${SG_ID}
結果(例)
      sg-59c3e63d

外部からのHTTPS接続をセキュリティグループに追加。

コマンド
aws ec2 authorize-security-group-ingress --group-id ${SG_ID} --protocol 'tcp' --port 443 --cidr 0.0.0.0/0
結果
      返り値なし

2. アプリケーションロードバランサの作成

2.1. ロードバランサの作成

コマンド
ELB_NAME="elbv2-handson-lb"
ELB_ARN=`aws elbv2 create-load-balancer --name ${ELB_NAME} \
 --subnets ${SUBNET_ID1} ${SUBNET_ID2} --security-groups ${SG_ID} \
 --query LoadBalancers[].LoadBalancerArn --output text `
aws elbv2 describe-load-balancers --load-balancer-arns ${ELB_ARN}
結果(例)
      {
          "LoadBalancers": [
              {
                  "VpcId": "vpc-15b0ec70",
                  "LoadBalancerArn": "arn:aws:elasticloadbalancing:ap-northeast-1:571972591141:loadbalancer/app/elbv2-handson-lb/666a7169294ec5bc",
                  "State": {
                      "Code": "provisioning"
                  },
                  "DNSName": "elbv2-handson-lb-1654351783.ap-northeast-1.elb.amazonaws.com",
                  "SecurityGroups": [
                      "sg-c2a4b2a6"
                  ],
                  "LoadBalancerName": "elbv2-handson-lb",
                  "CreatedTime": "2016-09-13T13:05:11.480Z",
                  "Scheme": "internet-facing",
                  "Type": "application",
                  "CanonicalHostedZoneId": "Z14GRHDCWA56QT",
                  "AvailabilityZones": [
                      {
                          "SubnetId": "subnet-67919410",
                          "ZoneName": "ap-northeast-1a"
                      },
                      {
                          "SubnetId": "subnet-692a7730",
                          "ZoneName": "ap-northeast-1c"
                      }
                  ]
              }
          ]
      }

2.2. ターゲットグループの作成 (デフォルトアクション用)

デフォルトアクション(リスナへ届いた通常のアクセスの転送先)用のターゲットグループを作成します。

コマンド
ELB_TG_NAME="elbv2-handson-tg"
ELB_TG_ARN=`aws elbv2 create-target-group --name ${ELB_TG_NAME} \
 --protocol HTTP --port 80 --vpc-id ${VPC_ID} \
 --query TargetGroups[].TargetGroupArn --output text `
aws elbv2 describe-target-groups --target-group-arns ${ELB_TG_ARN}
結果(例)
      {
          "TargetGroups": [
              {
                  "HealthCheckPath": "/",
                  "HealthCheckIntervalSeconds": 30,
                  "VpcId": "vpc-15b0ec70",
                  "Protocol": "HTTP",
                  "HealthCheckTimeoutSeconds": 5,
                  "HealthCheckProtocol": "HTTP",
                  "LoadBalancerArns": [],
                  "UnhealthyThresholdCount": 2,
                  "HealthyThresholdCount": 5,
                  "TargetGroupArn": "arn:aws:elasticloadbalancing:ap-northeast-1:571972591141:targetgroup/elbv2-handson-tg/0dc3bae28b0c8b99",
                  "Matcher": {
                      "HttpCode": "200"
                  },
                  "HealthCheckPort": "traffic-port",
                  "Port": 80,
                  "TargetGroupName": "elbv2-handson-tg"
              }
          ]
      }

2.3. ターゲットグループへターゲットを登録

ターゲット(Webサービスのインスタンス)をターゲットグループへ登録します。
インスタンスIDとポート番号の組み合わせで登録するので、コンテナインスタンスで複数のWebサービスコンテナが稼働していてもそれらを登録することができます。
ポート番号はターゲットグループのデフォルト値である場合、省略可能です。

コマンド
aws elbv2 register-targets --target-group-arn ${ELB_TG_ARN} \
 --targets Id=${EC2_INSTANCE_ID}
結果
      返り値なし

2.4. HTTPSリスナの作成

最後に外部からHTTPS(TCP/443)でアクセスを受け、ACMによるSSL証明書による処理を行い、ターゲットグループのWebサーバへHTTP(TCP/80)で接続するリスナを作成し、Webサーバへアクセスできるようにします。

コマンド
ELB_LISTENER_ARN=`aws elbv2 create-listener --load-balancer-arn ${ELB_ARN} \
 --protocol HTTPS --port 443 --certificates CertificateArn=${CERT_ARN} \
 --default-actions Type=forward,TargetGroupArn=${ELB_TG_ARN} \
 --query Listeners[].ListenerArn --output text `
aws elbv2 describe-listeners --listener-arns ${ELB_LISTENER_ARN}
結果(例)
      {
          "Listeners": [
              {
                  "Protocol": "HTTPS",
                  "DefaultActions": [
                      {
                          "TargetGroupArn": "arn:aws:elasticloadbalancing:ap-northeast-1:571972591141:targetgroup/hoge/e155d347d35f05f0",
                          "Type": "forward"
                      }
                  ],
                  "SslPolicy": "ELBSecurityPolicy-2015-05",
                  "Certificates": [
                      {
                          "CertificateArn": "arn:aws:acm:ap-northeast-1:571972591141:certificate/07150260-d46a-4a5f-8f20-900a9573d0a6"
                      }
                  ],
                  "LoadBalancerArn": "arn:aws:elasticloadbalancing:ap-northeast-1:571972591141:loadbalancer/app/hoge/b6183b688ccfbdce",
                  "Port": 443,
                  "ListenerArn": "arn:aws:elasticloadbalancing:ap-northeast-1:571972591141:listener/app/hoge/b6183b688ccfbdce/c9dc5e52bde4de8e"
              }
          ]
      }

ここで3分ほど待ちます。
ロードバランサとターゲットが接続完了するのに時間がかかるからです。

2.5. ターゲットのヘルスチェック状況確認

コマンド
aws elbv2 describe-target-health --target-group-arn ${ELB_TG_ARN}
結果(例)
      {
          "TargetHealthDescriptions": [
              {
                  "HealthCheckPort": "80",
                  "Target": {
                      "Id": "i-5d3f2bc2",
                      "Port": 80
                  },
                  "TargetHealth": {
                      "State": "healthy"
                  }
              }
          ]
      }

State が healthy になっていることを確認します。
initial である場合はヘルスチェックが規定回数まで達していないので少し待って再実行します。
unhealthy など他の内容が表示された場合は、チューターか講師へ声を掛けてください。

2.6. DNSNameの取得

ALBはIPアドレスは動的で、DNS名をCNAMEまたはエイリアスレコードによって登録するためこの値を取得します。

コマンド
DNSNAME=`aws elbv2 describe-load-balancers --load-balancer-arns ${ELB_ARN} \
 --query LoadBalancers[].DNSName --output text `
echo ${DNSNAME}
結果(例)
      elbv2-handson-lb-1654351783.ap-northeast-1.elb.amazonaws.com

3. Route53の設定

www.example.tk でアクセスできるようにするため、Route53の設定を行います。
今回はexample.tkでCloudFrontのS3コンテンツが、example.tkでALBによるEC2インスタンスのWebコンテンツが表示されるようにします。

3.1. Route53レコードセットの作成

まずRoute53へレコードを登録するためのJSONファイルを作成します。

コマンド
cat << EOF > route53c.json
{
  "Comment": "ALB-AliasRecord",
  "Changes": [
    {
      "Action": "CREATE",
      "ResourceRecordSet": {
        "AliasTarget": {
          "HostedZoneId": "Z35SXDOTRQ7X7K",
          "EvaluateTargetHealth": false,
          "DNSName": "${DNSNAME}."
        },
        "Type": "A",
        "Name": "www.${DOMAINNAME}."
      }
    }
  ]
}
EOF
cat route53c.json
結果
      {
        "Comment": "ALB-AliasRecord",
        "Changes": [
          {
            "Action": "CREATE",
            "ResourceRecordSet": {
              "AliasTarget": {
                "HostedZoneId": "Z35SXDOTRQ7X7K",
                "EvaluateTargetHealth": false,
                "DNSName": "elbv2-handson-lb-254473736.us-east-1.elb.amazonaws.com."
              },
              "Type": "A",
              "Name": "www.example.tk."
            }
          }
        ]
      }

HostedZoneIdに書かれている文字列は全ユーザ共通の固定値です。
ALBをエイリアスレコードに登録する場合は常にこの値を使用します。

JSONファイルを作成したら、フォーマットが壊れてないか必ず確認します。

コマンド
jsonlint -q route53.json
結果
      返り値なし

3.2. Route53への登録

コマンド
aws route53 change-resource-record-sets \
 --hosted-zone-id ${HOSTED_ZONE_ID} --change-batch file://route53c.json
結果(例)
      {
          "ChangeInfo": {
              "Status": "PENDING",
              "Comment": "ALB-AliasRecord",
              "SubmittedAt": "2016-10-13T08:34:57.794Z",
              "Id": "/change/C3SSDTIES1RAMM"
          }
      }

4. 動作確認

4.1. Webブラウザでアクセス

コマンド
echo https://www.${DOMAINNAME}/
結果(例)
      https://www.example.tk/

WebブラウザでURLへアクセスしてみます。問題無く表示されたでしょうか。
Route53の機能であるエイリアスレコード機能によって、Zone APEXでも別名が利用できることがわかります。

4.2. HTTP/2対応の確認

これは外部のサイトで確認することができます。
https://tools.keycdn.com/http2-test
へアクセスして、URL欄に自分のサイトを入力してみましょう。

結果(例)
      Yeah! www.example.tk supports HTTP/2.0.

緑色でこのような表示がされればHTTP/2対応です。

おめでとうございます。
ハンズオンの最終目標までこれで達成です。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2