0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【AWS】ALBのみでメンテナンスページを表示させる by CloudFormation

Last updated at Posted at 2022-02-21

#1. はじめに
Lightsailで個人ブログをホスティングしているのですが、メンテナンス時はWordPressの標準機能でメンテナンスページを表示させていました。
今後、LightsailをALBと連携させたいと考えています。
その際、ALB側でメンテナンスページをコントロールできた方がページコントロールの観点から統一性があって良いかなと思い、ALBのリスナールールでメンテナンスページを表示させるようにしようと思いました。

メンテナンスページを表示させる方法は色々ありますが、(CloudFront+S3, 単純にS3から引っ張るetc..)ALBのリスナールールで表示させる方が一番簡単な気がするので、その方法を採用しました。

本記事では単純にALBのリスナールールでメンテナンスページを表示させる方法を公開したいと思います。

#2. 概要
ALBのリスナールールを利用し、静的なメンテナンスページを作成します。
また、リソース作成にはCloudFormationを使用します。

#3. ALBのみで実装するメンテナンスページに関して
##3.1 メリット

  • 運用が楽

    メンテナンスページを表示させたい時は、単純にリスナールールの順位を変更すればいいだけ
  • 実装が簡単

    ALBに新規リスナールールを追加すればいいだけ

##3.2 デメリット

  • html/cssの最大文字数が1024文字

    1024文字以内だとかなり簡易的なページしか作成できない・・(本番利用には向いていない)

#4. メンテナンスページの作成
基本的なVPC環境やセキュリティグループの設定に関しては、既に構築済である前提とします。

CloudFormationテンプレート

alb.yml
AWSTemplateFormatVersion: '2010-09-09'
Description: "Launch a SorryPage to ALB"


# ------------------------------------------------------------
#  Metadate
# ------------------------------------------------------------
Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Parameters:
          - PJPrefix
          - ALBSubnetIDs
          - ACM
          - VPCID
          
          
# ------------------------------------------------------------
#  Input Parameters
# ------------------------------------------------------------
Parameters:
### Share Param ###
  PJPrefix:
    Type: "String"
  ALBSubnetIDs:
    Type: "List<AWS::EC2::Subnet::Id>"
    Description: "Select a subnet from two or more availability-zones."
  VPCID:
    Type: "AWS::EC2::VPC::Id"
    Description: "Select at your VPC."
  ACM:
    Type: "String"
    Description: "Select at your ACM ARN."


### Resources ###
Resources: 
# ------------------------------------------------------------
#  TargetGroup
# ------------------------------------------------------------
  TargetGroup:
    Type: "AWS::ElasticLoadBalancingV2::TargetGroup"
    Properties: 
      VpcId: !Ref VPCID
      Name: !Sub "${PJPrefix}-tg"
      Protocol: HTTP
      Port: 80
      HealthCheckProtocol: HTTP
      HealthCheckPath: "/"
      HealthCheckPort: "traffic-port"
      HealthyThresholdCount: 2
      UnhealthyThresholdCount: 2
      HealthCheckTimeoutSeconds: 5
      HealthCheckIntervalSeconds: 10
      Matcher: 
        HttpCode: 200
      Tags: 
        - Key: Name
          Value: !Sub "${PJPrefix}-tg"
      TargetGroupAttributes: 
        - Key: "deregistration_delay.timeout_seconds"
          Value: 300
        - Key: "stickiness.enabled"
          Value: false
        - Key: "stickiness.type"
          Value: lb_cookie
        - Key: "stickiness.lb_cookie.duration_seconds"
          Value: 86400
          
          
# ------------------------------------------------------------
#  ALB
# ------------------------------------------------------------
### ALB ###
  ALB:
    Type: "AWS::ElasticLoadBalancingV2::LoadBalancer"
    Properties:
      Name: !Sub "${PJPrefix}-ALB"
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-ALB"
      Scheme: "internet-facing"
      LoadBalancerAttributes:
        - Key: "deletion_protection.enabled"
          Value: false
        - Key: "idle_timeout.timeout_seconds"
          Value: 60
        - Key: "access_logs.s3.enabled"
          Value: false
      SecurityGroups:
        - !Ref "ALBSG"
      Subnets: !Ref "ALBSubnetIDs"
        
        
### HTTP通信のリスナー設定 ### 
  ALBListenerHTTP:
    Type: "AWS::ElasticLoadBalancingV2::Listener"
    Properties:
      # HTTP通信でのアクセスはHTTPSへリダイレクトさせる
      DefaultActions:
        - Type: "redirect"
          RedirectConfig:
            Protocol: "HTTPS"
            Port: "443"
            Host: "#{host}"
            Path: "/#{path}"
            Query: "#{query}"
            StatusCode: "HTTP_301"
      LoadBalancerArn: !Ref "ALB"
      Port: "80"
      Protocol: "HTTP"
      
      
### HTTPS通信のリスナー設定 ###
  ALBListenerHTTPS:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      Port: 443
      Protocol: HTTPS
      DefaultActions: 
         - Type: "forward"
           TargetGroupArn: !Ref TargetGroup
      Certificates:
        - CertificateArn: !Ref ACM
      LoadBalancerArn: !Ref ALB
      
      
### 通常パターンのリスナールール ###
  ALBListenerRule:
    Type: AWS::ElasticLoadBalancingV2::ListenerRule
    Properties:
      Actions:
        - Type: forward
          TargetGroupArn: !Ref TargetGroup
      Conditions:
        - Field: path-pattern
          Values:
            - '*'
      ListenerArn: !Ref ALBListenerHTTPS
      Priority: 1
      
### メンテナンスモードのリスナールール ###
  ALBListenerRule503:
    Type: AWS::ElasticLoadBalancingV2::ListenerRule
    Properties:
      Actions:
        - Type: "fixed-response"
          FixedResponseConfig:
            ContentType: 'text/html'
            MessageBody: |
                <!DOCTYPE html>
                <html lang="ja">
                <head>
                <meta charset="UTF-8">
                <title>メンテナンスのお知らせ</title>
                <style>
                  html {
                    text-align: center;
                  }
                  body {
                    margin: 0;
                    padding: 0;
                    background: #eee;
                  }
                  #conainer {
                    margin: 0 auto;
                    padding: 20px;
                    width: 600px;
                    max-width: 600px;
                  }
                  h1 {
                    font-size: 2em;
                  }
                  .warn {
                    padding: 1em;
                    background: #ff7;
                  }
                  #footer {
                    text-align: center;
                  }
                </style>
                </head>
                
                <body>
                  <div id="container">
                    <h1>ただいまメンテナンス中です</h1>
                    <p>
                      システムアップデートのためサービスを停止しています。<br>
                      ユーザーの皆様にはご不便をおかけしますが、メンテナンス終了まで今しばらくお待ち下さい。<br>
                    </p>
                    <h2>メンテナンス期間</h2>
                    <p class="warn">
                      <strong>202x年x月x日(x) xx:xx 〜 xx月xx日(x) xx:xx</strong><br>
                    </p>
                    <h2>
                     お問い合わせ
                    </h2>
                    <p>
                      メンテナンスに関するお問い合わせは<a href="xxxxxxxx@gmail.com">xxxxxxxx@gmail.com</a>までお願いします。
                    </p>
                    <hr>
                    <div id="footer">
                      &copy; 2021~2022 
                    </div>
                  </div>
                </body>
                </html>
            StatusCode: 503
      Conditions:
        - Field: path-pattern
          Values:
            - '*'
      ListenerArn: !Ref ALBListenerHTTPS
      Priority: 2

#5. 動作確認
とりあえずメンテナンスページを表示させたい。
しかし、作成時のリスナールールの順位だと、443の方にアクセスが流れてしまうため、リスナールールの順位を変更する必要があります。

作成したリスナールールの優先順位を入れ替えましょう。
参照:https://blog.serverworks.co.jp/alb-fixed-response

入れ替え後、ALBのDNS名へアクセスし、無事以下のような画面が表示されれば動作確認完了。
※ 1024文字だとこのレベルが限界(汗)
Sorrypage.png

#6. まとめ
とても簡易的で便利な方法ですが、やはり1024文字制限が痛すぎる・・
個人利用レベルならともかく、現場で本番を想定したような場面には向かないでしょう。。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?