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?

TerraformでのMulti-AZ構成を考えた ― RDSとRegional NAT Gatewayの冗長化

0
Posted at

はじめに

前回、TerraformでEC2を2AZ・2台構成に変更し、ALBを利用して複数のEC2へアクセスを振り分ける構成を作成しました。

構成としては以下のような形です。

                Internet
                    |
                   ALB
               /         \
        EC2 (1a)        EC2 (1c)
               \         /
                   RDS

EC2を1台だけ配置していた構成と比べると、片方のEC2に障害が発生しても、もう片方でサービスを継続できるため可用性は高くなります。

しかし構成全体を見直してみると、

「EC2を2AZに配置しただけで、システム全体をMulti-AZ化したと言えるのか?」

という疑問が出てきました。

EC2以外にも、RDSやNAT Gatewayが特定のAZに依存していれば、そこが障害点として残ります。

そこで今回は、前回のEC2 Multi-AZ化からさらに範囲を広げ、

  • RDSのMulti-AZ化
  • NAT GatewayのAZ依存の見直し
  • Regional NAT Gatewayへの変更

を行いました。


EC2だけMulti-AZにしても十分ではなかった

前回までの構成では、EC2を以下のように配置しました。

AZ 1a                     AZ 1c

EC2-A                     EC2-B
   \                       /
            ALB

これにより、EC2単体の障害だけでなく、一方のAZに障害が発生した場合にも、もう一方のAZでアプリケーションを継続できる構成にしました。

しかし、システムはEC2だけで構成されているわけではありません。

例えばEC2が正常でも、

EC2 ○
 ↓
RDS ×

となれば、Webアプリケーションは正常に動作できません。

同様に、Private SubnetのEC2が外部通信に利用しているNAT Gatewayが特定AZに依存している場合、そのAZの障害によって通信経路に影響する可能性があります。

そのため今回は、

「EC2が何台あるか」ではなく、「AZ障害が発生した場合にシステム全体がどうなるか」

という視点で構成を見直しました。


RDSをMulti-AZ化する

まず見直したのがRDSです。

Single-AZ構成の場合、RDSに障害が発生するとデータベースが利用できなくなり、EC2が2台とも正常でもアプリケーションに影響します。

そこでRDSをMulti-AZ構成に変更しました。

イメージとしては以下です。

AZ 1a                     AZ 1c

Primary RDS  ---------->  Standby RDS

通常はプライマリDBを利用し、障害が発生した場合には別AZのスタンバイへフェイルオーバーできる構成です。

Terraformでは、RDSでMulti-AZを有効化しました。

resource "aws_db_instance" "this" {
  # 省略

  multi_az = true
}

これによって、

EC2
├─ 1a
└─ 1c

RDS
├─ Primary
└─ Standby

という形になり、アプリケーション層だけでなくデータベース層についてもAZ障害を意識した構成になりました。

ここで、

「Multi-AZはEC2を複数AZに置くだけではなく、依存しているリソースも含めて考える必要がある」

と気付きました。


NAT GatewayにもAZ依存が残っていた

次に見直したのがNAT Gatewayです。

Private Subnetに配置したEC2からインターネットへ通信するため、NAT Gatewayを利用しています。

以前は1つのAZにZonal NAT Gatewayを配置していました。

イメージとしては以下のような構成です。

AZ 1a                         AZ 1c

Private EC2                   Private EC2
     \                           /
      \                         /
        NAT Gateway (1a)
               |
              IGW

EC2自体は1aと1cに分散していますが、外向き通信については1aのNAT Gatewayに依存していました。

そのため、

「EC2をMulti-AZ化した一方で、通信経路は特定AZに依存している」

という状態でした。


Zonal NAT Gatewayを複数配置する方法

Zonal NAT Gatewayを使ったまま冗長化する場合は、各AZにNAT Gatewayを配置する方法があります。

AZ 1a                         AZ 1c

EC2                           EC2
 |                             |
NAT GW                        NAT GW
 |                             |
IGW                           IGW

この場合、それぞれのPrivate Subnetから同じAZのNAT Gatewayへ通信させます。

これによって、一方のAZに障害が発生しても、もう一方のAZではNAT Gatewayを利用できます。

ただし構成としては、

  • AZごとのNAT Gateway
  • NAT Gateway用のSubnet
  • AZごとのRoute Table設定

など、管理対象が増えます。

今回の構成では、冗長性を確保しながら構成を簡素化する方法としてRegional NAT Gatewayを採用しました。


Regional NAT Gatewayへ変更

Regional NAT Gatewayでは、特定の1AZにNAT Gatewayを固定するのではなく、VPC単位で利用します。

Terraformでは、Regional NAT Gatewayとして作成するよう変更しました。

resource "aws_nat_gateway" "this" {
  vpc_id            = var.vpc_id
  availability_mode = "regional"

  tags = {
    Name = "${var.name_prefix}-RegionalNAT"
  }
}

これまでのZonal NAT Gatewayでは、NAT Gatewayを配置するSubnetなどを意識する必要がありました。

Regional NAT Gatewayでは、AWS側でAZへの展開が管理されるため、

AZごとにNAT Gatewayを用意して管理する構成を簡素化できる

点をメリットとして感じました。

今回Regional NAT Gatewayを採用した理由は、

「Multi-AZ構成に合わせて外向き通信も特定AZへの依存を減らしたかったこと」

と、

「Zonal NAT GatewayをAZごとに管理するより構成を簡素化できること」

の2点です。


Regional NAT Gateway作成時にIAMエラー

Regional NAT GatewayをTerraformで作成しようとした際、GitHub Actionsの terraform apply でエラーが発生しました。

原因は、

iam:CreateServiceLinkedRole

の権限不足でした。

Regional NAT GatewayではService Linked Roleが利用されます。

Service Linked Roleは、特定のAWSサービスがユーザーに代わって必要なAWSリソースを操作するために利用するIAMロールです。

通常のIAMロールでは、利用者側で用途や権限を設計します。

一方、Service Linked Roleは特定のAWSサービスに紐づいており、そのサービスが必要とする権限や信頼関係をAWS側が定義します。

今回、Regional NAT Gatewayを初めて作成する際に必要となるService Linked Roleを作成する権限が、GitHub Actionsで利用しているIAMロールにありませんでした。

そのため必要なIAM権限を追加し、再度 terraform apply を実行することで作成できました。

このエラーから、

「Terraform上ではNAT Gatewayを作成しているだけに見えても、AWS内部では別のIAMリソースが必要になる場合がある」

ということを学びました。


構成を見直してどう変わったか

最初は、EC2を1台から2台にすることをMulti-AZ化として考えていました。

変更前

ALB
 |
EC2
 |
RDS

そこからEC2を2AZへ配置しました。

ALB
 |
├─ EC2 (1a)
└─ EC2 (1c)
     |
    RDS

さらに今回、RDSとNAT GatewayについてもAZ障害を意識して見直しました。

                 ALB
              /       \
        EC2 (1a)     EC2 (1c)
              \       /
             RDS Multi-AZ

        Regional NAT Gateway

今回の変更によって、

  • アプリケーション層:EC2を2AZへ分散
  • データベース層:RDSをMulti-AZ化
  • 外向き通信:Regional NAT Gatewayへ変更

という形で、EC2だけではなくシステム全体を見ながらMulti-AZ構成を考えられるようになりました。


今回学んだこと

今回一番大きかった学びは、

「Multi-AZ = EC2を2つのAZに配置することではない」

ということです。

最初はEC2を1aと1cに配置した時点で、冗長化構成としてかなり完成したと考えていました。

しかし、システム全体を見ると、

ALB
 ↓
EC2
 ↓
RDS

だけでなく、EC2が利用するネットワーク経路なども含めて複数の要素があります。

その中のどこかが特定のAZに依存していれば、AZ障害時の影響が残ります。

そのため、単純に

「リソースを2台にする」

のではなく、

「このAZが利用できなくなった場合、どのリソースに影響が出るのか」

という視点で構成を見ることが重要だと学びました。


今後

現在、EC2は1aと1cに1台ずつ配置しているため、一方のEC2に障害が発生しても、もう一方でサービスを継続できます。

ただし、障害が発生したEC2を自動的に新しいEC2へ置き換える仕組みはありません。

通常

1a : EC2-A
1c : EC2-B

↓

EC2-A障害

1a : ×
1c : EC2-B

そのため次は、Launch TemplateとAuto Scaling Groupを利用して、

EC2障害
   ↓
ASGが検知
   ↓
新しいEC2を起動
   ↓
必要台数へ自動復旧

という構成を検討しています。

今回のMulti-AZ化では、

「障害時にも別AZでサービスを継続できる構成」

を考えました。

次はそこからさらに一歩進めて、

「障害後に自動的に正常な台数へ戻る構成」

について学習していきます。

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?