Studyplus Engineering Blog

スタディプラスの開発者が発信するブログ

便利に使えるAnsibleのAWSモジュール11選

こんにちは、インフラエンジニアの菅原です。

皆さんはAWSをどのように管理されてますか?
Ansibleでしょうか?ChefやTerraform、CloudFormationでしょうか?  

弊社ではAnsibleのAWSモジュールを使って、構成をコード化し、管理しております。
そのため最近関わったプロジェクトでも一人で手早く対応することができました。

今回は便利に使い回せるAWSモジュールを厳選して紹介したいと思います。  

AnsibleでAWSを管理する理由

弊社では以下の理由でAnsibleをメインに構成管理を行っています。

  • 構成変更の影響範囲をできるだけ小さくしたい(破壊的変更を避けたい)
  • エージェントレスで導入コストが少なく、手元で設定を完結したい
  • 使うツールは最小限にしたい(新規メンバー参画時の学習コストを減らしたい)
  • 前任者の好み

Infrastructure as Codeを挫折してしまう理由が「ちょっと変更したいけどコード化に時間がかかる」や「ここだけ変更したいけど影響範囲が大きい」という要望に簡単に答えられないときだと個人的に思ってます。「手でやった方が早い」という気持ちになってしまうと再現性のない環境が次々とできてしまいかねません。
その点Ansibleであれば、変更箇所を変えて実行するだけですし、変更したい箇所以外はskipされるため影響範囲も最小限に抑えられます。

この記事の前提

この記事の前提は以下となります。

  • Ansible2.7系で利用することを前提に記載してます。
  • モジュールは順不同になります。
  • 以下の図のような構成を目的としたAWSモジュールの紹介になります。

f:id:ksugahara08:20190416080142p:plain
AWSモジュールでのsample構成

便利AWSモジュール

iam_role

- name: Create IAM roles
  iam_role:
    state: present
    name: "sample-iamrole"
    assume_role_policy_document: "{{ lookup('file', 'sample-role.json') }}"

iam_roleはIAMロールを作成、変更することができます。
初回実行時にAWS環境にJSONファイルで用意した内容でIAMロールを作成してくれます。
JSONファイルは以下のようにfilesディレクトリ配下に配置します。

├── files
│   ├── sample-policy.json
│   └── sample-role.json
└── tasks
    └── main.yml

IAMロールの設定内容を変更したい場合はJSONファイルを書き換えて実行すれば上書き変更できます。
一つ作ってしまえば使い回しが効くのですごく便利です。

iam_policy

- name: Set policy
  iam_policy:
    iam_type: role
    iam_name: "sample-iamrole"
    policy_name: "sample-policy"
    policy_json: "{{ lookup('file', 'sample-policy.json') }}"
    state: present

iam_policyはIAMのポリシーを作成、変更することができます。
弊社ではtrusted entitiesをiam_roleで設定し、policyをiam_policyで付与しています。

route53

- name: Set Route53
  route53:
    command: create
    zone: "sample.com"
    record: "new.sample.com"
    type: "A"
    ttl: "7200"
    value: "dualstack.sample-1111111111.ap-northeast-1.elb.amazonaws.com."
    overwrite: "{{ DNS_OVERWRITE | default(false) }}"
    alias: "True"
    alias_hosted_zone_id: "ZXXXXXXXXXXXXX"

route53はRoute53にDNS設定を追加、変更することができます。
上記はロードバランサー(ELB)に設定する例です。ホスト名の変更を簡単に行うことができるため重宝してます。
既存のレコードを変更する場合はoverwritetrueにします。その際は変数を実行時に渡してあげるとroles配下のファイルを書き直さなくても良くなります。

ansible-playbook main.yml -e DNS_OVERWRITE=true

ec2_vpc_net

ec2_vpc_net, ec2_vpc_igw, ec2_vpc_subnetは基本的に新規プロジェクトや環境追加するときにしか実行しませんが、手間が省けたり、環境設定をコードで管理することができるため利用しています。

- name: Create vpc
  ec2_vpc_net:
    state: present
    name: "sample-vpc"
    cidr_block: "10.10.0.0/16"
    dns_hostnames: yes
    dns_support: yes
  register: vpc_net

ec2_vpc_netはCIDRブロックを指定してVPCを作成、変更することができます。
変更する対象はcidr_blocknameで一意に決まります。

ec2_vpc_igw

- name: Create igw
  ec2_vpc_igw:
    state: present
    vpc_id: "{{ vpc_net.vpc.id }}"

ec2_vpc_igwはInternet Gatewayを設定できるモジュールです。
vpc_idec2_vpc_netで作成したidを渡すことで設定することができます。
例のようにregistervpc_idを渡してあげるとスムーズです。

ec2_vpc_subnet

- name: Create subnets
  ec2_vpc_subnet:
    state: present
    vpc_id: "{{ vpc_net.vpc.id }}"
    cidr: "{{ item.cidr }}"
    az: "{{ item.az }}"
    tags: { "Name": "{{ item.name }}" }
  with_items:
    - { cidr: "10.10.0.0/20", az: "ap-northeast-1a", name: "sample-vpc-subnet1" }

ec2_vpc_subnetはサブネットを設定するモジュールです。
例ではCIDRブロック、Availability Zone、nameタグをwith_itemsに変数として入れて実行しています。
サブネットを複数設定する場合はwith_items構文でループ実行します。

ec2_group

- name: Create security group
  ec2_group:
    name: "sample-sg"
    description: "sample security group"
    vpc_id: "{{ vpc_id }}"
    rules:
      - proto: tcp
        from_port: 22
        to_port: 22
        cidr_ip: "10.10.0.0/20"
      - proto: tcp
        from_port: 80
        to_port: 80
        cidr_ip: "0.0.0.0/20"

ec2_groupはセキュリティグループを作成し、対象のVPCに設定することができます。
2回目以降の実行ではセキュリティグループの変更(上書き)を行うことができます。
ただし、AWSのマネジメントコンソールから直接入れた設定があるとロールバックさせてしまうので、実行する前は--checkを付けて変更箇所を確認した方が良いです。

elb_target_group

- name: Create Target Group
  elb_target_group:
    state: present
    name: "sample-alb-target-group"
    protocol: http
    port: 80
    vpc_id: "{{ vpc_id }}"
    health_check_protocol: http
    health_check_path: /health_check
    health_check_interval: 10
    health_check_timeout: 5
    healthy_threshold_count: 2
    unhealthy_threshold_count: 2
    deregistration_delay_timeout: 0
    successful_response_codes: 200

elb_target_groupはロードバランサーのターゲットグループを作成、変更できます。
例ではリクエストをhttpで80番ポートに受け渡すように設定しています。
ヘルスチェックは要件に合わせて設定値を変えてください。
ターゲットグループにAWSのマネジメントコンソールから追加したインスタンスがあると実行時にターゲットから外れるので注意してください。

elb_application_lb

- name: Create ALB
  elb_application_lb:
    state: present
    name: "sample-alb"
    scheme: internet-facing
    subnets: "sample-vpc-subnet1"
    security_groups:
      - "sample-sg"
    listeners:
      - Protocol: HTTP
        Port: 80
        DefaultActions:
          - Type: forward
            TargetGroupName: "sample-alb-target-group"
      - Protocol: HTTPS
        Port: 443
        DefaultActions:
          - Type: forward
            TargetGroupName: "sample-alb-target-group"
        Certificates:
          - CertificateArn: "arn:aws:acm:ap-northeast-1:123456789:certificate/aaaa-bbbb-cccc-dddd-eeee"
        SslPolicy: ELBSecurityPolicy-2016-08

elb_application_lbはアプリケーションロードバランサーを作成、変更できます。
今まで作成してきたサブネットやセキュリティグループを指定して作成します。
例ではロードバランサーに証明書を設定しています。Certificatesにarnを記述すれば証明書を設定する事ができます。
ALBとして利用するのであればlistenersタグの中にRulesタグを設ければパスで振り分けることができます。(詳しくは公式ドキュメントを確認してください。)

ec2_lc

- name: Create launch configuration
  ec2_lc:
    state: present
    name: "sample-lc"
    image_id: "ami-123456789"
    key_name: galaxy
    security_groups: "sample-sg"
    instance_profile_name: "sample-iamrole"
    instance_type: "t3.small"
    assign_public_ip: yes
    volumes:
      - device_name: /dev/sda1
        volume_size: 32
        volume_type: gp2
        delete_on_termination: true
  register: lc

ec2_lcはAuto Scalingの起動設定を作成、変更をすることができます。
AMIを用意してあればimage_idで指定することで任意のイメージを利用することができます。
弊社ではAMIをAnsibleとPackerで作成しています。
また、EC2のインスタンスサイズやボリームはここで管理する形にしています。

ec2_asg

- name: Set Auto-scaling group
  ec2_asg:
    state: present
    name: "sample-asg"
    launch_config_name: "{{ lc.name }}"
    health_check_period: 500
    health_check_type: EC2
    replace_all_instances: yes
    min_size: "1"
    max_size: "3"
    desired_capacity: "2"
    vpc_zone_identifier: "sample-vpc-subnet1"
    tags:
      - Name: "sample-web"
      - role: "web"
      - env: "cage"

ec2_asgはAuto Scaling グループの作成、変更をすることができます。
ec2_lcregister: lcを指定しておけばlc.nameを受け渡せます。
弊社ではEC2の起動/停止はec2_asgを使って管理しています。

最後に

今回は弊社でもよく使っているAnsibleのAWSモジュールを紹介しました。
AWSモジュールを利用することでインフラの自動化を進めていますが、Ansibleでは対応していない設定項目やAWSの最新の変更に追従できないこともあります。しかし、うまく使うことで運用をかなり楽にできるができます。