Ansible

aws上に作成したansibleサーバーでテストサイトを構築する(2) AWSネットワーク構成

More than 1 year has passed since last update.

はじめに

前回はAnsibleサーバーの構築を実施しました。
今回は構築したAndibleを使ってAWS上にVPCなどのネットワークリソースやキーペアの作成を行います。

Playbookの作成

まずはPlaybookを格納するディレクトリを作成します。今後はすべてここを基準に作成、実行していきます。
大まかなレイアウトはここに記載されているものと合わせるようにしています。

command
> mkdir aws_testsite
> cd aws_testsite

次にansible-playbookコマンドから呼び出すおおもとのPlaybookファイルsite.ymlを作成します。
AWSのリソースを作成する部分と、作成したEC2インスタンス上の設定(OSやミドルウェア等)を行う部分とに分けて別々に実行できるようにしようと思いますので、このファイルからは子ファイルを呼び出すのみとします。

site.yml
- import_playbook: aws_infra.yml

呼び出される子のPlaybookは以下のように、aws_networkロールを呼び出すものとします。ここには今後、EC2インスタンスやRDSインスタンスの作成ロールを追加していきます。

aws_infta.yml
- hosts: localhost
  roles:
  - { role: aws_network, tags: [aws_network] }

Playbookで指定した通り、aws_networkロールをrolesフォルダ配下に作ります。

command
> mkdir -p roles/aws_network/tasks

ネットワークリソースの内容の定義

どのようなネットワーク構成にするかをgroup_varsフォルダのall.ymlファイルに定義します。
ここでは、アジアパシフィック(東京)リージョンap-northeast-1にVPCを作成して、中のAZそれぞれにwebapp用のサブネットを一つづつ作ることにします。

command
> mkdir -p group_vars
group_vars/all.yml
---
vpc:
  name: "testsite"
  region: "ap-northeast-1"
  cidr: "172.22.0.0/16"
  subnets:
  - name: "webapp1"
    cidr: "172.22.1.0/24"
    az: "ap-northeast-1a"
  - name: "webapp2"
    cidr: "172.22.2.0/24"
    az: "ap-northeast-1c"

各リソースを作成するタスクの作成

group_vars/all.ymlで定義した内容に従って、各リソースを作成するタスクを作ります。
VPC等のネットワークリソースを作成するタスクは相互のかかわりが大きいのでcreate_vpc.ymlとして1つのファイルにまとめます。

roles/aws_network/tasks/main.yml
---
- import_tasks: create_vpc.yml

VPCの作成

まずVPCを作成します。テストサイトを構成するPlaybookなので、複数のVPCを作成することは考慮しません。

roles/aws/tasks/create_vpc.yml
---
- name: create vpc
  ec2_vpc_net:
    state: present
    region: "{{ vpc.region }}"
    cidr_block: "{{ vpc.cidr }}"
    name: "{{ vpc.name }}"
  register: aws_network_vpc

- debug: var=aws_network_vpc

ここまでのPlaybookを実行すると以下のようになります。

command
$ ansible-playbook site.yml 

PLAY [localhost] *************************************************************************************************************************************************************************************

TASK [Gathering Facts] *******************************************************************************************************************************************************************************
ok: [localhost]

TASK [aws_network : create vpc] **********************************************************************************************************************************************************************
changed: [localhost]

TASK [aws_network : debug] ***************************************************************************************************************************************************************************
ok: [localhost] => {
    "aws_vpc": {
        "changed": false, 
        "failed": false, 
        "vpc": {
            "cidr_block": "172.22.0.0/16", 
            "classic_link_enabled": null, 
            "dhcp_options_id": "dopt-f6c50e92", 
            "id": "vpc-603e2404", 
            "instance_tenancy": "default", 
            "is_default": false, 
            "state": "available", 
            "tags": {
                "Name": "testsite"
            }
        }
    }
}

サブネットの作成

続いてVPC内にサブネットを作成します。こちらは複数のサブネットを構成するのでwith_itemsで複数のサブネットを作成します。
引数として前タスクで作成したVPCのIDが必要となりますので、registerディレクティブで確保したaws_network_vpcから取得します。

roles/aws/tasks/create_vpc.yml(追記)
- name: create vpc subnets
  ec2_vpc_subnet:
    state: present
    vpc_id: "{{ aws_network_vpc.vpc.id }}"
    region: "{{ vpc.region }}"
    cidr: "{{ item.cidr }}"
    az: "{{ item.az }}"
    tags:
      Name: "{{ item.name }}"
  with_items: "{{ vpc.subnets }}"

インターネットゲートウェイの作成

このVPC内とインターネット間での通信ができるようにインターネットゲートウェイを作成します。
インターネットからのWebアクセスやSSH接続、また内部からインターネットの参照に使用します。
ここでもVPC IDが必要となります。

roles/aws/tasks/create_vpc.yml(追記)
- name: create internet gateway
  ec2_vpc_igw:
    state: present
    region: "{{ vpc.region }}"
    vpc_id: "{{ aws_network_vpc.vpc.id }}"
  register: aws_igw

ルートテーブルの作成

各サブネットにインターネット参照を可能とするルートテーブルを定義します。
今回の構成では、すべてのサーバーをAnsibleで管理するためにインターネットからのSSH接続が必要となるため、作成したサブネットすべてにインターネット向けのルートを設定します。

ルートテーブルに登録するサブネット名のリストが必要となるため、group_vars/all.ymlの定義から、サブネット名のリストを作成しています。

roles/aws_network/tasks/create_vpc.yml(追記)
- name: make subnet list
  set_fact:
    list_subnets: "{{ vpc.subnets | map(attribute='name') | list }}"

- name: Set up public subnet route table
  ec2_vpc_route_table:
    state: present
    region: "{{ vpc.region }}"
    vpc_id: "{{ aws_network_vpc.vpc.id }}"
    tags:
      Name: "Public subnet"
    subnets: "{{ list_subnets }}"
    routes:
      - dest: 0.0.0.0/0
        gateway_id: "{{ aws_igw.gateway_id }}"

セキュリティグループの作成

続いて作成するWEBサーバーへのアクセスを制御するためのセキュリティグループを定義します。
まずはAnsibleサーバーからのSSH接続を可能にするために、「0.0.0.0/0」からのSSH(TCP/22)接続を許可します。
EC2は停止するたびにグローバルIPアドレスが変わるため、全アドレスからのSSHを許可しています。
EC2のSSHは既定で公開鍵認証のみが有効となるので、テストサイトであれば問題ないでしょう…
(SSHに脆弱性が発見される可能性もあるので本番サイトの場合はまた別に考える必要があります)

Webアプリへの接続を許可するルールも定義しておきます。
こちらは接続元のIPを限定して許可する設定としています。これは、AWS上でWebサーバーを公開すると、すぐにWordPressやphpMyAdminへのアタックと思われるアクセスがあるためです。
複数の接続元がある場合には、それぞれルールを定義します。(Ansible 2.4になればcidr_ipや、portをリスト構成にできるようになるようです)

group_vars/all.yml(追記)
security_groups:
  - name: "SG_webapps"
    description: "for WebApplication Servers"
    rules:
    - proto: tcp
      from_port: 22
      to_port: 22
      cidr_ip: 0.0.0.0/0
    - proto: tcp
      from_port: 80
      to_port: 80
      cidr_ip: x.x.x.x/32
    - proto: tcp
      from_port: 80
      to_port: 80
      cidr_ip: y.y.y.y/32
roles/aws_network/tasks/create_vpc.yml(追記)
- name: create security group
  ec2_group:
    name: "{{ item.name }}"
    description: "{{ item.description }}"
    vpc_id: "{{ aws_network_vpc.vpc.id }}"
    region: "{{ vpc.region }}"
    rules: "{{ item.rules }}"
  with_items: "{{ security_groups }}"

キーペアの作成

EC2インスタンスにアクセスするキーペアを作成するタスクを作成します。
秘密鍵は、実行ユーザー(ec2-user)の~/.sshに保存するようにしています。

roles/aws_network/tasks/main.yml
---
- import_tasks: create_vpc.yml
- import_tasks: create_keypair.yml
group_vars/all.yml(追加分)
keypair:
  name: "testsite_key"

ssh_keyfile_path: '~/.ssh'
ansible_ssh_private_key_file: '{{ ssh_keyfile_path }}/{{ keypair.name }}.pem'
roles/aws_network/tasks/create_keypair.yml
---
- name: create keypair
  ec2_key:
    name: "{{ keypair.name }}"
    region: "{{ vpc.region }}"
  register: aws_keypair
roles/aws_network/tasks/create_keypair.yml(追記)
- name: create keypair file
  file:
    path: '{{ ansible_ssh_private_key_file }}'
    state: touch
    mode: 0600
  when: aws_keypair.key.private_key is defined

- name: keypair write
  shell: echo "{{ aws_keypair.key.private_key }}" > {{ ansible_ssh_private_key_file }}
  delegate_to: 127.0.0.1
  when: aws_keypair.key.private_key is defined

次回

次回は EC2インスタンスを作成します。