😊

ALBに関して初歩の初歩からセットアップする記事(EC2-1台構成)

2025/02/19に公開

対象

EC2にapache/nginxなどのhttpdを起動して運用できる方でALBみたいなのを導入経験があんまり無い方

まず、ALBとは

これは http/https専用 のトラフィック分散装置であり、以下のようなアスキーアートで表現できる

        Clients (Users)
                │
                ▼
    ┌───────────────────────────┐
    │        ALB (L7)           │
    │  Application Load Balancer│
    └────────────┬──────────────┘
                 │
      ┌──────────┴─────────┐
      │                    │
┌──────────────┐    ┌──────────────┐
│   EC2 #1     │    │   EC2 #2     │
│  Web Server  │    │  Web Server  │
│(Apache/Nginx)│    │(Apache/Nginx)│
└──────────────┘    └──────────────┘

この図だと、EC2#1EC2#2の2台構成であるが、1台で運用する事も可能だ。ただし、1台と2台以上の構成ではアプリケーションの設定で差分が出てくるので、構築においては結構違うというのがあるため、ここではALBからEC2を1台組んだ構成でチュートリアルしていく事にする。

チュートリアル: EC2を1つ起動してALBを設定してみる

EC2の起動

ここではシンプルにEC2を1台起動しよう。これに関しては何も考えず起動するとネットワークはデフォルトvpcになると思う(消してなければ)


パブリックIPを確認しつつポートを開放

パブリックIPが有効になっている事を確認しつつhttpを開放する

sudo apt update && sudo apt install -y apache2


apache2のdefaultページ


どのサブネットに所属したのか確実にメモする

なお、起動したEC2がどのサブネットに所属しているか非常に重要だ。
ここではap-northeast-1cに所属した。これを記録しておく事。

ターゲットグループの作成

ALBを作成する前に、ターゲットグループを作成する必要がある。これはEC2のメニューより作成する


グループ詳細の設定


ここではインスタンスとし、test-target-groupと命名した


ここではデフォルト


これもデフォルト


このページで現在稼働中のEC2インスタンスを選択できる

このようにしてターゲットグループをさくっと作成する

ALBを設定していく

これはEC2のロードバランサーという項目に存在している


ここの場所から Application Load Balancerの作成をするのが一番確実だ。

Application Load Balancer を作成

ここに関しては通常defaultの設定で事足りるはずだ

AZを選ぶ

AZとは、まあ簡単にいって物理ゾーンのことで、どこにサーバーがあるとかいう話なのだが、今は前回確認したようにap-northeast-1cに所属しているのでこれは選択する。さらに1つどれでもいいから付ける。まあここではap-northeast-1aとした。


aとcを選択


セキュリティーグループ

これは後で設定するのでとりあえず何も考えていない


リスナーとルーティング

ここでとりえずリスナーとは何かというと、要するにALBがlistenするポートである。ここではALBは80番をリッスンする。デフォルトアクションはとりあえず設定しない。つまりこのdefaultの状態で選択を終える

さらにデフォルトアクションとして先に作成しておいたtest-targat-groupを指定


その他設定

この辺は上級オプションであり使うと便利なこともあるのだが、不要なトラブルを排除するためにここでは何もしない。熟練したらこの辺も研究してみよう。


以上の設定にてロードバランサーが作成された


画面の表示の通り少し時間がかかるがうまいこと行くとステータスがアクティブになる

疎通確認

このDNS名にアクセスする。http://test-alb-44988526.ap-northeast-1.elb.amazonaws.com

現状この通り到達できない。これはALBのセキュリティーグループ設定で正しくポートを開放していないからだ



このような形でhttpを開放して保存する


これで到達できた

到達できない場合

ターゲットグループを確認しUnhealtyになっている場合、大抵インスタンス側のポート80に到達できていない。セキュリティーグループでのポート設定やらhttpサーバーの設定を見直してみよう。この時サーバー側のグローバルIPにアクセスして確認するのが初手としては確実ではある


Healtyにならないと接続できない

ここまでのまとめと確認

  • EC2を1つ起動した
  • ターゲットグループ: test-target-groupを作成し、起動したEC2を割り当てた
  • ALB: test-alb を起動し、test-target-groupにルーティングした
    • ALBのセキュリティーグループ設定でポート80を開放した
             Internet
                │
         ┌──────┴──────────┐
         │  ALB (test-alb) │
         │    Port: 80     │
         └──────┬──────────┘
                │
         ┌──────┴───────────────────────────┐
         │ Target Group (test-target-group) │
         └──────┬───────────────────────────┘
                │
         ┌──────┴───────────┐
         │   EC2 Instance   │
         │  (Running App)   │
         └──────────────────┘

さらに図解すると

               Internet
                  │
        ┌─────────┴────────┐
        │                  │
 ┌──────┴──────────┐    ┌──────────────────┐
 │  ALB (test-alb) │    │   EC2 Instance   │
 │  http://test-   │    │  35.78.201.175   │
 │ alb-xxxx.elb.   │    │  (Direct Access) │
 │ amazonaws.com   │    └──────────────────┘
 └──────┬──────────┘
        │
 ┌──────┴───────────────────────────┐
 │ Target Group (test-target-group) │
 └──────┬───────────────────────────┘
        │
 ┌──────┴───────────┐
 │   EC2 Instance   │
 │  35.78.201.175   │
 │ (Behind ALB)     │
 └──────────────────┘

このようになっている。すなわち

の両方でアクセス可能になっている。なお、ここでアクセスログをみると、ALBからのアクセスは

172.31.41.104 - - [17/Feb/2025:20:34:35 +0000] "GET / HTTP/1.1" 200 3324 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:134.0) Gecko/20100101 Firefox/134.0"

となっている。ここで172.31.41.104はALBのIPなので、もしapacheなどでログを採取する場合はこれはまったくアテにならない。これはX-Forwarded-Forヘッダーを見ればわかるのであるが、この辺の設定をまずみていこう。

httpd側のロギング

まずはX-Forwarded-Forを参照するようにする

000-default.conf を変更 (debian系の場合)

元を変更してもいいけど、現状はこうなっている

/etc/apache2/sites-available/000-default.conf
<VirtualHost *:80>
        # The ServerName directive sets the request scheme, hostname and port that
        # the server uses to identify itself. This is used when creating
        # redirection URLs. In the context of virtual hosts, the ServerName
        # specifies what hostname must appear in the request's Host: header to
        # match this virtual host. For the default virtual host (this file) this
        # value is not decisive as it is used as a last resort host regardless.
        # However, you must set it for any further virtual host explicitly.
        #ServerName www.example.com

        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html

        # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
        # error, crit, alert, emerg.
        # It is also possible to configure the loglevel for particular
        # modules, e.g.
        #LogLevel info ssl:warn

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        # For most configuration files from conf-available/, which are
        # enabled or disabled at a global level, it is possible to
        # include a line for only one particular virtual host. For example the
        # following line enables the CGI configuration for this host only
        # after it has been globally disabled with "a2disconf".
        #Include conf-available/serve-cgi-bin.conf
</VirtualHost>

これを以下のようにする

/etc/apache2/sites-available/000-default.conf
<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html

    ErrorLog ${APACHE_LOG_DIR}/error.log

        # X-Forwarded-For を記録するカスタムログフォーマット
        LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" \"%{X-Forwarded-For}i\" %D" custom
        CustomLog ${APACHE_LOG_DIR}/access.log custom
</VirtualHost>

そして

sudo systemctl restart apache2

すると

172.31.8.105 - - [18/Feb/2025:05:45:25 +0000] "GET / HTTP/1.1" 200 3324 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:135.0) Gecko/20100101 Firefox/135.0" xxx.xxx.xxx.xxx 

このように実際のクライアント名も記録されるようになる

Cloudwatch Logsに転送する

https://zenn.dev/catatsumuri/articles/e933567b128875

この辺。ALB + EC2構成だとほぼ必須

ALBの設定変更

これは意外と変なところにあって「属性」とういタブっぽいところからアクセスする


X-Forwarded-Forはこの辺で設定されている。これはそのままにしておいていいとは思うが


ALBのログを取る

これはhttpdがcloudwatchに転送するログより前で取るので、ほとんど保全用のログであり、根本的にリアルタイム解析を目的としていない。従って保存先は基本的にS3になる。しかも保存設定にクセがあるので注意が必要だ。

https://dev.classmethod.jp/articles/alb-access-log-permission-error-s3-bucket/

S3バケット作成

https://ap-northeast-1.console.aws.amazon.com/s3/home?region=ap-northeast-1# よりここではtestbucketforalb-2025-02というバケットをdefaultで作成した


バケットを選択

すると以下のようになる

権限

これは以下のようなjsonをバケットポリシーに適用する必要があるようだ

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::582318560864:root"
            },
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::testbucketforalb-2025-02/*"
        }
    ]
}


jsonを保存した

これで保存できるようになる。


書き込まれたログ

即時に反映しているわけでもないようなので、ある程度運用して溜っていくか確認する。コンプライアンスでログ保全がある場合は検討してもいい項目だろう。アクセスログと接続ログの違いは中身見てください。

https

これは基本的にドメインが無いと厳しい。またドメインがあってもホストゾーンを当該アカウントで管理しているのか管理していないのかで難易度が変わってくる。まあここでは外部を使っているとしよう。

まず 当該ALBのDNSをメモる

ここでは test-alb-34539353.ap-northeast-1.elb.amazonaws.comであった


適当なCNAMEに割り当てる。ここではawsの管理画面であるが別にどの会社の画面でもいい


うまいこと設定が反映されたらSSL証明書を取得する

SSL証明書

ALBが起動しているAWS画面でACMに移動する https://ap-northeast-1.console.aws.amazon.com/acm/home?region=ap-northeast-1#

証明書をリクエストする



取得しようとするドメイン名を入力する。ここではtest.catatsumuri.orgとなった。検証はDNS検証としている


するとCNAMEを追加で設定しろといわれるので設定する。これは同一アカウントで管理していると簡単にできるが外部を使っている場合はCNAMEを頑張ってセットする


暫く放置していると、うまく行った場合発行済みになる


これでSSL証明書の準備は整った

ALB側の設定

これはリスナーを追加する。冒頭でも伸べたようにリスナーはリッスンするポートあるいはサービスのようなもので今HTTPリスナーがセットされているのでHTTPSリスナーもセットする必要があるわけだ


このように追加し


先程ゲットした証明書を割り付ける


最後にセキュリティーグループにてポートを正しく開放する


このような形でSSL保護にて接続可能になった

http → https フォワード

現状 http://test.catatsumuri.org でも https://test.catatsumuri.org でも接続できてしまうので、httpをhttpsにリダイレクトする。これはhttpリスナーを変更する

現状このようにターゲットグループに転送しているので、これを変更する



テストはもちろんブラウザーでもいいのだが、今日日のブラウザーはわかり辛いのでcurlをつかってもいいかもしれないです

まとめ

このようにALBを使うとhttp/httpsのロードバランシングに加えてSSL/TLSの終端装置としても機能するため、EC2自体にSSLのセットアップは不要となる。さらにWAFも加えたり諸々機能があるため、資金に余裕があるのであれば1台構成でもこれをセットアップしておく事は非常に有益

Discussion