Terraformで複数のAWSリージョンを使う

複数のAWSリージョンを使うケース

ほとんどのクラウドプロバイダは世界中のデータセンタ(リージョン)に対してデプロイができます。 Terraformプロバイダを設定する際には、通常はどれか一つのリージョンを選択します。 例えば、通常は日本のAWSを利用するプロジェクトでは、ap-northeast-1 という一つのAWSリージョンにデプロイするよう設定します。

ですが、複数のリージョンにまたがってプロバイダをデプロイしなければならないケースもあります。 例えば、AWSのCloudfrontサービスを使用する際、Cloudfrontをどこのリージョンで使うかに関わらず、証明書を us-eas-1でリージョンで作る必要があります。

複数のリージョンを使用するのは比較的稀なケースで、通常は各環境は完全に分離し、各リージョンを別々のモジュールで管理する状態にするべきです。

複数のAWSリージョンで、複数のリソースを作成する

複数のリージョンでデプロイするためには、providerブロックでエイリアスを設定します。

provider "aws" {
    region  = "us-east-2" #デプロイ先のリージョン
    alias   = "region_1"  #Terraformで使う際の別名
}
provider "aws" {
    region  = "us-east-1" #デプロイ先のリージョン
    alias   = "region_2"  #Terraformで使う際の別名
}

resource "aws_instance" "region_1" {
    provider    = aws.region_1
    ami         = "ami-0822295a729d2a28e"
    instance_type   = "t2.micro"
}

resource "aws_instance" "region_2" {
    provider    = aws.region_2
    ami         = "ami-0dd97ebb907cf9366"
    instance_type   = "t2.micro"
}

それぞれのリソースが provider パラメータをどのように設定しているかに注意してください。 providerパラメーターを設定することによって、 特定のリージョンにサービスをデプロイすることができます。

このコードを保存した後、 terraform initでプロバイダーをインストールし、 terraform applyで実際に二つのリージョンにEC2を設置できます。

Note:それぞれリージョンが異なることについて

また、それぞのれリージョンで AMIが異なることも注意が必要です。 例えば、 ap-northeast-1のUbuntuと ap-northeast-2のUbuntuは同じバージョンでも amiは異なります。

参考 : https://cloud-images.ubuntu.com/locator/ec2/

補足 : 特定リージョンのAMI ID を自動取得する方法

複数のリージョンを使用する方法から話がそれますが、 AMIをベタ張するのではなく、データソースを使用してAMIIDを検索する方法もあります。

provider "aws" {
    region  = "us-east-2"
    alias   = "region_1"
}
provider "aws" {
    region  = "us-east-1"
    alias   = "region_2"
}

data "aws_ami" "ubuntu_region_1" {
    provider = aws.region_1

    most_recent = true
    owners      = ["099720109477"] 
    filter {
        name    = "name"
        values  = "ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"
    }
}

data "aws_ami" "ubuntu_region_2" {
    provider = aws.region_2

    most_recent = true
    owners      = ["099720109477"] 
    filter {
        name    = "name"
        values  = "ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"
    }
}

resource "aws_instance" "region_1" {
    provider    = aws.region_1
    ami         = data.aws_ami.ubuntu_region_1.id #変更点
    instance_type   = "t2.micro"
}

resource "aws_instance" "region_2" {
    provider    = aws.region_2
    ami         = data.aws_ami.ubuntu_region_2.id #変更点
    instance_type   = "t2.micro"
}
  • owners

oweners の値は 各リージョンで共通である上に、OSごとにほとんど固定です。

OS, Distribution 所有者 ID
RockyLinux 792107900819
RedHat 309956199498
Fedora 125523088429
CentOS Stream 125523088429
CentOS 125523088429
AlmaLinux 764336703387
OracleLinux 131827586825
Ubuntu 099720109477
Debian 136693071363
openSUSE 679593333241
WindowsServer 801119661308

参考 : https://qiita.com/NaoyaOgura/items/4d8aeeb64963d0eb4831

複数のAWSリージョンで、複数のモジュールを使用する

一つのリージョンに、Aurora RDSのMySQLデータベースを立てるときは、以下のようなterraformリソースを使えます。

provider "aws" {
    region = "us-east-2"
}

variable "db_username" {
    type = string
    default = null
}

variable "db_password" {
    type = string
    default = null
}

resource "aws_db_instance" "example" {
    identifier_prefix = "minegishi-test"
    engine = "mysql"
    allocated_storage = 10
    instance_classes = "db.t2.micro"
    skip_final_snapshot = true

    username = var.db_username
    password = var.db_password
}

これを一つのリージョン("us-east-2")だけでなく、別のリージョンにDBの内容をレプリケーションすることで、より強固になります。 では、ステージング環境用のMySQLコードをマルチリージョンにレプリケーションをサポートしたコードに変えてみます。

## variables.tf
variable "backup_retenion_period" {
    type = number
    default = null
}

variable "replicate_source_db" {
    type = string
    default = null
}

variable "db_username" {
    type = string
    default = null
}

variable "db_password" {
    type = string
    default = null
}

main.tf

//provider "aws" {
//    region = "us-east-2"
//}

terraform {
    required_providers {
        aws = {
            source = "hashicorp/aws"
            version = "~> 4.0"
        }
    }
}

resource "aws_db_instance" "example" {
    identifier_prefix = "minegishi-test"
    allocated_storage = 10
    instance_classes = "db.t2.micro"
    skip_final_snapshot = true

    # バックアップを有効化
    backup_retention_period = var.backup_retention_period

    # 設定されているときはこのデータベースはレプリカ
    replicate_source_db = var.replicate_source_db

    # replicate_source_dbが設定されていない時だけ、これらのパラメーターを設定
    engine = var.replicate_source_db == null ? "mysql" : null
    username =  var.replicate_source_db == null ? var.db_username : null
    password =  var.replicate_source_db == null ? var.db_password : null
}

outputs.tf

output "arn" {
    value = aws_db_instance.example.arn
}

このモジュールを呼び出す側(environment/dev/main.tf)は以下のように設定します。 (ただし、この指定だと同じリージョンにデプロイされてしまいます)

module "mysql_primary" {
    source = "../../../../modules/data-stores/mysql"

    db_name = "prod_db"
    db_username = var.db_username
    db_password = var.db_password

    backup_retention_period = 1
}

module "mysql_replica" {
    source = "../../../../modules/data-stores/mysql"

    replicate_source_db = module.mysql_primary.arn
}

上記の構成では、同一リージョンにRDSがレプリケートされてしまいますが、ここでproviderブロックを複数追加し、 それぞれのproviders引数に当てはめることで、 それぞれのリージョンにデプロイすることができます。

provider "aws" {
    region = "us-east-2"
    alias = "primary"
}

provider "aws" {
    region = "us-west-1"
    alias = "replica"
}

module "mysql_primary" {
    source = "../../../../modules/data-stores/mysql"

    providers = {
        aws = aws.primary
    }

    db_name = "prod_db"
    db_username = var.db_username
    db_password = var.db_password

    backup_retention_period = 1
}

module "mysql_replica" {
    source = "../../../../modules/data-stores/mysql"

    providers = {
        aws = aws.replica
    }

    replicate_source_db = module.mysql_primary.arn
}

これらのモジュールを呼ぶ引数の providersはマップであり、 providerパラメータは一つの値であることに注意してください。 これは、各リソースとデータソースは一つのプロバイダのみにデプロイされる一方、 モジュールは複数のデータソースやリソースを含んで複数のプロバイダを使う必要があるためです。

モジュールに渡すprovidersのキーは、モジュール内のrequired_providersで明示的に定義する必要があります。

terraform {
    required_providers {
        aws = {
            source = "hashicorp/aws"
            version = "~> 4.0"
        }
    }
}

page:https://minegishirei.hatenablog.com/entry/2025/01/12/151623