SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

小規模な受託開発におけるAWS活用の勘所

Ansible、Vagrant、Packerを用いたAWSの開発/本番/ステージング環境の構築

小規模な受託開発におけるAWS活用の勘所 第2回

Vagrantの設定(2)

3. Roleの作成

 ようやく、実際に実行するRole及びTaskの作成に移ります。

 ここでは以下のRoleを作成します。

  • common:共通的にインストールするツールなどを定義
  • user_setup:Linux上でのユーザーに関する設定
  • web:Webサーバ(Nginx)のインストールと設定

 他にもPHPのインストールなどが必要な場合は同様にRoleを作成します。

 vagrant_playbook.ymlのrolesに指定したRole名と同じディレクトリをvagrant/provisioning/roles以下に作成し、tasks/main.ymlを生成することでRoleのタスクが実行されます。

 まず、commonを作成します。

vagrant/provisioning/roles/common/tasks/main.yml
--- # 共通なタスク
# インストールするツール
- import_tasks: install_common_tools.yml

 ここでは、install_common_tools.ymlに記載されたタスクをインポートしているだけです。同じRoleでも複数のタスクがある場合があるため、main.ymlではそれらをまとめるだけにしておきます。

vagrant/provisioning/roles/common/tasks/install_common_tools.yml
---
- name: Install tools
  yum:
    state: installed
    name:
      - vim
      - wget
      - lsof
      - git
      - ruby
      - tcpdump
      - jq

 ここで実際にyumを用いていくつかのパッケージをインストールしています。以降でも同様ですが、基本的にはAnsibleで用意されているモジュール(ここではyum)を使用します。Ansibleのモジュールは冪等性を確保するように作られており、state等の状態(ここではinstalled:インストールされた状態にする)を確認しており、インストール済みだとこのタスクは実行されません(一部例外があります。commandやshellモジュールは実装者が冪等性の考慮をする必要があります。ですのでやむを得ない限り、使用しないようにします)。

 続いて、user_setupを作成します。

vagrant/provisioning/roles/user_setup/tasks/main.yml
--- # Linux上のユーザ関連の設定
- import_tasks: add_user.yml
vagrant/provisioning/roles/user_setup/tasks/add_user.yml
--- # user setup
# デフォルトユーザ用グループの追加
- name: Add group for default user
  group:
    name: "{{ default_user.group }}"
    state: present

# デフォルトユーザを追加
- name: Add user default user
  user:
    name: "{{ default_user.name }}"
    uid: "{{ default_user.uid }}"
    group: "{{ default_user.group }}"
    password: "{{ default_user.password}}"
    state: present

# デフォルトユーザをsudo可能に
- name: Add default user to sudoers
  template:
    src: default_user_sudoers.j2
    dest: /etc/sudoers.d/{{ default_user.name }}
    owner: root
    group: root
    mode: '0644'

# 以下、packerの場合
- block:
  # デフォルトユーザの.sshディレクトリを作成
  - name: create .ssh directory for default user
    file:
      path: "/home/{{ default_user.name }}/.ssh"
      state: directory
      owner: "{{ default_user.name }}"
      group: "{{ default_user.group }}"
      mode: 0700

  # ec2-userの公開鍵をデフォルトユーザに追加
  - name: check authorized_keys for default user
    stat: path="/home/{{ default_user.name }}/.ssh/authorized_keys"
    register: default_user_authorized_keys

  # EC2ではEC2インスタンス生成時にキーペアを指定します。指定したキーはec2-userに配置されるため、作成したユーザにもコピー
  - name: copy authorized_keys for default user from ec2-user
    shell: "cp -p /home/ec2-user/.ssh/authorized_keys /home/{{ default_user.name }}/.ssh/authorized_keys"
    when: not default_user_authorized_keys.stat.exists

  # キーを使用可能に
  - name: chown/chmod authorized_keys for default user
    file:
      path: "/home/{{ default_user.name }}/.ssh/authorized_keys"
      owner: "{{ default_user.name }}"
      group: "{{ default_user.group}}"
      mode: '0600'

  # セキュリティ上、ec2-userの接続禁止
  - name: deny ec2-user on ssh connection
    lineinfile:
      path: /etc/ssh/sshd_config
      state: present
      line: 'DenyUsers ec2-user'

  when: not is_vagrant

 ここでは、vagrant/provisioning/group_vars/all.ymlの定義に従い、ユーザーを作成しています。

 また、Packerでの利用を鑑み、PackerとVagrantでの分岐をis_vagrantを用いて実施しています。

 ここで新たにtemplateモジュールを使用しており、タスク内のtemplateフォルダにあるファイルをjinja2テンプレートエンジンを用いて変数を展開し、ファイルを配置しています。

vagrant/provisioning/roles/user_setup/templates/default_user_sudoers.j2
{{ default_user.name }} ALL=(ALL) ALL

 最後に、webを作成します。

vagrant/provisioning/roles/web/tasks/main.yml
--- # Webサーバのインストール
- import_tasks: install_nginx.yml
vagrant/provisioning/roles/web/tasks/install_nginx.yml
--- # nginxのインストール
# Extra Libraryのnginxが有効かどうか確認
- name: Check amazon-linux-extras for nginx
  shell: amazon-linux-extras | grep nginx{{nginx_version}} | grep enabled
  register: nginx
  failed_when: nginx.rc not in [0, 1]
  changed_when: False

# Extra Libraryが有効でない場合、有効化
- name: Enable nginx in amazon-linux-extra
  shell: amazon-linux-extras enable nginx{{nginx_version}}
  changed_when: False
  when: nginx.rc==1

# nginxのインストール
- name: Install nginx
  yum:
    name: "nginx"
    state: installed

# nginxの設定ファイルを配置
- name: Put nginx.conf template
  template:
    dest: /etc/nginx/nginx.conf
    src: nginx.conf.j2
    owner: root
    group: root
    mode: 0644

# nginxのvirtualhost用設定ファイルを配置
- name: Put virtual.conf template
  template:
    dest: /etc/nginx/conf.d/virtual.conf
    src: virtual.conf.j2
    owner: root
    group: root
    mode: 0644

# 一度nginxを起動(ログファイル生成のため)
- name: Start nginx
  systemd: name=nginx state=started enabled=yes
  changed_when: False

# 一度nginxを停止
- name: Stop nginx
  systemd: name=nginx state=stopped
  changed_when: False

# ログ出力ディレクトリ、ログ・ファイル等のパーミッションを変更
- name: chown /var/log/nginx for default user
  file:
    path: "/var/log/nginx"
    owner: "{{ default_user.name }}"
    group: "{{ default_user.group}}"
    mode: '0700'
- name: chown /var/log/nginx/access.log for default user
  file:
    path: "/var/log/nginx/access.log"
    owner: "{{ default_user.name }}"
    group: "{{ default_user.group}}"
    mode: '0600'
- name: chown /var/log/nginx/error.log for default user
  file:
    path: "/var/log/nginx/error.log"
    owner: "{{ default_user.name }}"
    group: "{{ default_user.group}}"
    mode: '0600'
- name: chown /var/lib/nginx for default user
  file:
    path: "/var/lib/nginx"
    owner: "{{ default_user.name }}"
    group: "{{ default_user.group}}"
    mode: '0700'
- name: chown /var/lib/nginx/tmp for default user
  file:
    path: "/var/lib/nginx/tmp"
    owner: "{{ default_user.name }}"
    group: "{{ default_user.group}}"
    mode: '0700'

# 再度nginxを起動
- name: Start nginx
  systemd: name=nginx state=started
  changed_when: False

 ここで、changed_when: Falseをいくつか使用しています。理由は最後に詳しく解説しますが、再実行されたときに、タスクがchangedになってほしくない(状態が変更されてもされていないように表示してほしい)場合に使用しています。

 また、テンプレートファイルは以下の2つを使用しています。

vagrant/provisioning/roles/web/templates/nginx.conf.j2
user {{ default_user.name }} {{ default_user.group }};

pid /var/run/nginx.pid;

# 動的モジュールのロード
include /usr/share/nginx/modules/*.conf;

events {
	# 最大同時接続数
	worker_connections 1024;
	# 接続をマルチに処理
	multi_accept on;
	# 多重IOをカーネルで処理
	use epoll;
	# mutex処理失敗時の待機時間(デフォルト500mx)
	accept_mutex_delay 100ms;
}

error_log /var/log/nginx/error.log warn;

http {
	include /etc/nginx/mime.types;
	default_type application/octet-stream;

	log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
	                  '$status $body_bytes_sent "$http_referer" '
	                  '"$http_user_agent" "$http_x_forwarded_proto" $request_time $upstream_response_time';

	# 他ファイルのインクルード
	include /etc/nginx/conf.d/*.conf;
vagrant/provisioning/roles/web/templates/virtual.conf.j2
server {
	listen 80;

	# Nameベースのバーチャルホスト
	server_name {{ hostname }};

	# DocumentRoot
	root /var/www/html/app/public;

	# access_log
	access_log  /var/log/nginx/access.log  main;

	index index.html;

}

 さらに、このタスク(web)でのみ有効な変数を作成します。

vagrant/provisioning/roles/web/vars/main.yml
nginx_version: 1.12

 このように、バージョンを切り出しておくと、今後のメンテナンスが容易になります。

4. Vagrantの起動

 ようやくVagrantを起動します。

 ここでは解説しませんが、動作確認のため、PROJECT_ROOT/app/public/index.htmlを作成しておいてください。

Vagrantの起動
cd PROJECT_ROOT/vagrant
vagrant up

 うまくいけば、VagrantでゲストOSが起動し、Ansibleによるプロビジョニングが動作します。

 動作の途中で、vagrant-hostupdaterにより、/etc/hostsを更新するためにパスワードを聞かれますが、その際にはホストOSのユーザーのパスワードを入力してください。

 最終的に、以下のような表示がされ、起動状態になります。

・・・
TASK [web : Start nginx] *******************************************************
ok: [default]

PLAY RECAP *********************************************************************
default                    : ok=18   changed=12   unreachable=0    failed=0

 動作を確認するため、ホストOSで、index.htmlにアクセスすると、以下の表示になるかと思います。

$ curl http://sample.test/index.html
test

 これで環境構築は完了です。

 なお、開発中にplaybookを変更する場合があると思います。その際はvagrant upした状態で、以下を実行すると、プロビジョニングのみ実施されます。

vagrant provision

 冪等性が確保されている場合は、以下のようになります。

PLAY RECAP *********************************************************************
default                    : ok=17   changed=1    unreachable=0    failed=0

 okは変更されなかったタスクの数、changedは変更されたタスクの数となります。

 他にもよく使用するコマンドとして、以下のようなものがあります。

# 仮想マシンの停止
vagrant halt
# ゲストOSにvagrantユーザーでssh接続
vagrant ssh
# 仮想マシンの破棄
vagrant destroy

次のページ
Packer、AnsibleによるAWS上での本番/ステージング環境用AMIの作成

この記事は参考になりましたか?

小規模な受託開発におけるAWS活用の勘所連載記事一覧

もっと読む

この記事の著者

塩飽 展弘(株式会社鈴木商店)(シワク ノブヒロ)

 株式会社鈴木商店 経営企画室室長。 大手通信事業者にて、SE、研究開発、経営企画等に従事後、2016年株式会社鈴木商店に入社。 営業、要件定義、開発(主にAWS関連インフラ)に従事後、現職。 AWS Certified Solutions Architect - Professional 鈴木商店HP Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/11323 2019/01/17 11:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー