AWSで3層ネットワーク構成を構築するansibleのplaybookを作ってみた


こんにちは。
SSチームの讃岐です。
以前にansibleで2層のネットワークを構築する記事を書いたんですが、実際の案件では3層のネットワークで環境を構築することが多いんですよね…
という訳で、ansibleでAWSの3層ネットワークを構築するplaybookを作ってみましたー。
*実際に構築する環境はこちらになります↓

記事のタイトルは先輩の記事のパクリじゃな……げふんげふん

[terraform] AWSで3層ネットワーク構成を構築するmoduleを書いてみた

ディレクトリ構成

playbookのディレクトリ構成は下記のような形となります。
2層のplaybookと変わらないじゃないか……げふんげふん(2回目)

.
├── README.md
├── ansible.cfg
├── hosts
├── roles
│   └── aws_vpc
│       ├── tasks
│       │   └── main.yml
│       └── vars
│           └── main.yml
└── vpc_create.yml

playbook

はい、playbookです。
基本的には2層のplaybookと同じなんですが、新たにNATGATEWAYの作成と、DMZサブネット用のルートテーブルを作成する機能を追加してます。

---
# tasks file for aws_vpc
- name: create_vpc
  ec2_vpc_net:
    name: "{{ vpc_name }}"
    cidr_block: "{{ vpc_cidr }}"
    region: "{{ region }}"
    profile: "{{ profile }}"
    dns_hostnames: yes
    dns_support: yes
  register: vpc_info

# PUBLIC_SUBNETの作成
- name: create_public_subnet
  ec2_vpc_subnet:
    vpc_id: "{{ vpc_info.vpc.id }}"
    cidr: "{{ item.pub_subnet_cidr }}"
    az: "{{ item.subnet_az }}"
    region: "{{ region }}"
    resource_tags: { "Name":"{{ item.pub_subnet_name }}" }
    profile: "{{ profile }}"
  register: pubsub_info
  with_items:
    - "{{ pub_subnet }}"

# DMZ_SUBNETの作成
- name: create_dmz_subnet
  ec2_vpc_subnet:
    vpc_id: "{{ vpc_info.vpc.id }}"
    cidr: "{{ item.dmz_subnet_cidr }}"
    az: "{{ item.subnet_az }}"
    region: "{{ region }}"
    resource_tags: { "Name":"{{ item.dmz_subnet_name }}" }
    profile: "{{ profile }}"
  register: pubsub_info
  with_items:
    - "{{ dmz_subnet }}"

# PRIVATE_SUBNETの作成
- name: create_private_subnet
  ec2_vpc_subnet:
    vpc_id: "{{ vpc_info.vpc.id }}"
    cidr: "{{ item.pri_subnet_cidr }}"
    az: "{{ item.subnet_az }}"
    region: "{{ region }}"
    resource_tags: { "Name":"{{ item.pri_subnet_name }}" }
    profile: "{{ profile }}"
  register: prisub_info
  with_items:
    - "{{ pri_subnet }}"

# IGWの作成
- name: create_igw
  ec2_vpc_igw:
    vpc_id: "{{ vpc_info.vpc.id }}"
    region: "{{ region }}"
    tags: { "Name":"{{ igw_name }}" }
    profile: "{{ profile }}"
  register: igw_info

# ROUTETABLEの作成(IGW)
- name: create_route_table
  ec2_vpc_route_table:
    vpc_id: "{{ vpc_info.vpc.id }}"
    subnets: "{{ atache_igw_subnet }}"
    routes:
      - dest: 0.0.0.0/0
        gateway_id: "{{ igw_info.gateway_id }}"
    region: "{{ region }}"
    profile: "{{ profile }}"
    resource_tags: { "Name":"{{ rttable_pub_name }}" }

# NGWを配置するSUBNETIDを取得
- name: get_subnet_id
  shell: aws ec2 describe-subnets --region {{ region }} --profile {{ profile }} --output text | grep -B 1 {{ ngw_subnet_name }} | awk 'NR==1 {print $12}'
  register: ngw_subnet_id

#- name: show
#  debug:
#    msg: "{{ ngw_subnet_id.stdout }}"

# NGWの作成
- name: create_ngw
  ec2_vpc_nat_gateway:
    subnet_id: "{{ ngw_subnet_id.stdout }}"
    region: "{{ region }}"
    profile: "{{ profile }}"
    wait: yes
  register: ngw_info

#- name: show
#  debug:
#    msg: "{{ ngw_info.nat_gateway_id }}"

# NGW作成まで待つ
#- name: wait_for_ngw
#  pause:
#    minutes: 5

# ROUTETABLEの作成(NGW)
- name: create_route_table2
  ec2_vpc_route_table:
    vpc_id: "{{ vpc_info.vpc.id }}"
    subnets: "{{ atache_ngw_subnet }}"
    routes:
      - dest: 0.0.0.0/0
        gateway_id: "{{ ngw_info.nat_gateway_id }}"
    region: "{{ region }}"
    profile: "{{ profile }}"
    resource_tags: { "Name":"{{ rttable_dmz_name }}" }

awscliコマンドの結果を整形してDMZサブネットのIDを取得しています。
これを利用してNATGATEWAYを作成する感じですね。
あとNATGATEWAYが作成されるまで少し時間がかかるので、「pause」モジュールで一時的に処理を止めてます。
*追記
Twitterにて「ec2_vpc_nat_gateway」に「wait」というオプションがあることご指摘いただきました!
ありがとうございます!

変数の定義

---
# vars file for aws_vpc

# REGION
  region: "ap-northeast-1"

# PROFILE
  profile: "default"

# VPC
  vpc_name: "sanuki-3layer-vpc"
  vpc_cidr: "10.10.0.0/16"

# IGW
  igw_name: "sanuki-3layer-igw"

# NGW
  ngw_name: "sanuki-3layer-ngw"


# NGWを作成するサブネット名
  ngw_subnet_name: "sanuki-3layer-public-subnet-a"

# ROUTETABLE(PUBLIC)
  rttable_pub_name: "sanuki-3layer-pub-rt"

# ROUTETABLE(DMZ)
  rttable_dmz_name: "sanuki-3layer-dmz-rt"

# PUBLIC_SUBNET
  pub_subnet:
    - { pub_subnet_cidr: "10.10.10.0/24" ,subnet_az: "ap-northeast-1a" ,pub_subnet_name: "sanuki-3layer-public-subnet-a" }
    - { pub_subnet_cidr: "10.10.20.0/24" ,subnet_az: "ap-northeast-1c" ,pub_subnet_name: "sanuki-3layer-public-subnet-c" }


# DMZ_SUBNET
  dmz_subnet:
    - { dmz_subnet_cidr: "10.10.30.0/24" ,subnet_az: "ap-northeast-1a" ,dmz_subnet_name: "sanuki-3layer-dmz-subnet-a" }
    - { dmz_subnet_cidr: "10.10.40.0/24" ,subnet_az: "ap-northeast-1c" ,dmz_subnet_name: "sanuki-3layer-dmz-subnet-c" }


# PRIVATE_SUBNET
  pri_subnet:
    - { pri_subnet_cidr: "10.10.50.0/24" ,subnet_az: "ap-northeast-1a" ,pri_subnet_name: "sanuki-3layer-private-subnet-a" }
    - { pri_subnet_cidr: "10.10.60.0/24" ,subnet_az: "ap-northeast-1c" ,pri_subnet_name: "sanuki-3layer-private-subnet-c" }

# IGWに紐付けるサブネット
  atache_igw_subnet:
    - "10.10.10.0/24"
    - "10.10.20.0/24"

# NGWに紐付けるサブネット
  atache_ngw_subnet:
    - "10.10.30.0/24"
    - "10.10.40.0/24"

今回はそれぞれのリソースに「sanuki-3layer」のprefixをつけます。

実行

実際に実行してみましょう。

root@BYD-NPC-023:/opt/playbook/aws-vpc-3layer# ansible-playbook -i hosts vpc_create.yml

PLAY [create vpc subnet igw routetable] *************************************************************************************************************************************************************************

TASK [aws_vpc : create_vpc] *************************************************************************************************************************************************************************************
changed: [127.0.0.1]

TASK [aws_vpc : create_public_subnet] ***************************************************************************************************************************************************************************
changed: [127.0.0.1] => (item={u'pub_subnet_name': u'sanuki-3layer-public-subnet-a', u'subnet_az': u'ap-northeast-1a', u'pub_subnet_cidr': u'10.10.10.0/24'})
changed: [127.0.0.1] => (item={u'pub_subnet_name': u'sanuki-3layer-public-subnet-c', u'subnet_az': u'ap-northeast-1c', u'pub_subnet_cidr': u'10.10.20.0/24'})

TASK [aws_vpc : create_dmz_subnet] ******************************************************************************************************************************************************************************
changed: [127.0.0.1] => (item={u'dmz_subnet_cidr': u'10.10.30.0/24', u'dmz_subnet_name': u'sanuki-3layer-dmz-subnet-a', u'subnet_az': u'ap-northeast-1a'})
changed: [127.0.0.1] => (item={u'dmz_subnet_cidr': u'10.10.40.0/24', u'dmz_subnet_name': u'sanuki-3layer-dmz-subnet-c', u'subnet_az': u'ap-northeast-1c'})

TASK [aws_vpc : create_private_subnet] **************************************************************************************************************************************************************************
changed: [127.0.0.1] => (item={u'pri_subnet_cidr': u'10.10.50.0/24', u'pri_subnet_name': u'sanuki-3layer-private-subnet-a', u'subnet_az': u'ap-northeast-1a'})
changed: [127.0.0.1] => (item={u'pri_subnet_cidr': u'10.10.60.0/24', u'pri_subnet_name': u'sanuki-3layer-private-subnet-c', u'subnet_az': u'ap-northeast-1c'})

TASK [aws_vpc : create_igw] *************************************************************************************************************************************************************************************
changed: [127.0.0.1]

TASK [aws_vpc : create_route_table] *****************************************************************************************************************************************************************************
changed: [127.0.0.1]

TASK [aws_vpc : get_subnet_id] **********************************************************************************************************************************************************************************
changed: [127.0.0.1]

TASK [aws_vpc : create_ngw] *************************************************************************************************************************************************************************************
changed: [127.0.0.1]

TASK [aws_vpc : wait_for_ngw] ***********************************************************************************************************************************************************************************
Pausing for 300 seconds
(ctrl+C then 'C' = continue early, ctrl+C then 'A' = abort)
ok: [127.0.0.1]

TASK [aws_vpc : create_route_table2] ****************************************************************************************************************************************************************************
changed: [127.0.0.1]

PLAY RECAP ******************************************************************************************************************************************************************************************************
127.0.0.1                  : ok=10   changed=9    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

うん、成功です!

終わりに

AWSのネットワークを管理画面からポチポチして構築することもできますが、時間もかかるしヒューマンエラーが発生するかもで、あんまり推奨できないですよね。
その点ansibleを使えば、時短になるし、ミスも減らせます!
うん、やっぱりansibleは便利ですね。

↓因みに2層はこちらですー。

【ansible】AWSのネットワークを構築するplaybookを書いてみた


この記事をかいた人

About the author

讃岐佳介

  CERTIFICATE:
    - TOEIC 835
    - LPIC304
    - AWS Solution Architect Associate
    - GCP Professional Cloud Architect