2
2

More than 3 years have passed since last update.

AnsibleでAmazonLinuxにRubyとNginxをインストール

Posted at

はじめに

先日TerraformでEC2やALBを作成したのですが、
各サーバにRuby(rbenv)のインストールとnginxのインストールと簡単な設定を行います。

環境情報

pythonのvenvで環境は作成しています。
AWSのリソースを扱うので、boto,boto3,botocoreあたりは必須になります。
事前にpip installしておきましょう。

% python -V
Python 3.8.3

% ansible --version
ansible 2.9.9

% pip list
Package         Version
--------------- -------
ansible         2.9.9
boto            2.49.0
boto3           1.14.12
botocore        1.17.12
cffi            1.14.0
cryptography    2.9.2
docutils        0.15.2
Jinja2          2.11.2
jmespath        0.10.0
MarkupSafe      1.1.1
pip             19.2.3
pycparser       2.20
python-dateutil 2.8.1
PyYAML          5.3.1
s3transfer      0.3.3
setuptools      41.2.0
six             1.15.0
urllib3         1.25.9

ディレクトリ構成

最終的なディレクトリ構成は以下です。
かなり多いですが大半は使わないディレクトリです。

% tree
.
├── README.md
├── ansible.cfg
├── inventory
│   ├── ec2.ini
│   └── ec2.py
├── playbook.yml
└── roles
    ├── common
    │   ├── README.md
    │   ├── defaults
    │   │   └── main.yml
    │   ├── files
    │   ├── handlers
    │   │   └── main.yml
    │   ├── meta
    │   │   └── main.yml
    │   ├── tasks
    │   │   └── main.yml
    │   ├── templates
    │   ├── tests
    │   │   ├── inventory
    │   │   └── test.yml
    │   └── vars
    │       └── main.yml
    ├── nginx
    │   ├── README.md
    │   ├── defaults
    │   │   └── main.yml
    │   ├── files
    │   ├── handlers
    │   │   └── main.yml
    │   ├── meta
    │   │   └── main.yml
    │   ├── tasks
    │   │   ├── main.yml
    │   │   └── nginx.yml
    │   ├── templates
    │   │   └── nginx.conf.j2
    │   ├── tests
    │   │   ├── inventory
    │   │   └── test.yml
    │   └── vars
    │       └── main.yml
    └── ruby
        ├── README.md
        ├── defaults
        │   └── main.yml
        ├── files
        ├── handlers
        │   └── main.yml
        ├── meta
        │   └── main.yml
        ├── tasks
        │   ├── main.yml
        │   ├── rbenv_settings.yml
        │   └── ruby_packages.yml
        ├── templates
        │   └── rbenv_system.sh.j2
        ├── tests
        │   ├── inventory
        │   └── test.yml
        └── vars
            └── main.yml

インベントリ、ansible.cfgの設定

ダイナミックインベントリの設定

EIPを使っている場合は固定IPなので問題無いのですが、動的パブリックIPのときはダイナミックインベントリを使うことになります。
ダイナミックインベントリ用のpythonスクリプトは何故か最新の物は動かなかったので少し古いものをダウンロードしました。

% ls -l inventory
total 160
-rw-r--r--  1 user  staff   4890  6 28 18:29 ec2.ini
-rwxr-xr-x  1 user  staff  73056  6 13 01:22 ec2.py

ec2.iniで以下パラメータに変更します。regionは環境に合わせます。
cache_max_age = 0
regions = ap-northeast-1

ansible.cfgの設定

次にanisble.cfgの設定変更します。
まずansible.cfgをダウンロードします。

% wget https://raw.githubusercontent.com/ansible/ansible/devel/examples/ansible.cfg

ダウンロードしたasnible.cfgの[default]セクションを書き換えます。
private_key_fileは適宜修正します。

% vim ansible.cfg

以下書き換え
[defaults]
inventory        = inventory/ec2.py
remote_user      = ec2-user
private_key_file = ~/.ssh/test-key.pem
host_key_checking = False

すでにAWS CLIでログイン濟みであれば以下でsuccessとなるはずです。

% ansible -i inventory/ec2.py -m ping

コードの作成

roleの作成

role を作成します。小分けでcommonrubynginxとしました。(名前は、わかり易ければなんでもOKです。)
ディレクトリはansible-galaxy initコマンドで一発で作成出来ます。

% ansible-galaxy init roles/common
% ansible-galaxy init roles/ruby
% ansible-galaxy init roles/nginx

サーバ基本設定

role=役割なのでそれぞれのtasksを書いていきます。
commonはユーザの作成などサーバの基本設定ですが、今回は簡単にパッケージのアップデートのみにしています。

./roles/common/tasks/main.yml
---
- name: update packages
  yum:
    name: '*'
    state: latest
  become: true

rubyの設定

次にrubyの設定をします。
rubyに必要なパッケージのインストールとrbenvの設定でファイルを分けました。
include_tasks:で同一ディレクトリのファイルも読み取ってくれます。

./roles/ruby/tasks/main.yml
---
- include_tasks: ruby_packages.yml
- include_tasks: rbenv_settings.yml
./roles/ruby/tasks/rbenv_settings.yml
---
- name: Install rbenv & ruby_build
  git:
    repo: "{{item.repo}}"
    dest: "{{item.directory}}"
  loop:
    - { repo: "https://github.com/sstephenson/rbenv.git", directory: "~/.rbenv"}
    - { repo: "https://github.com/sstephenson/ruby-build.git", directory: "~/.rbenv/plugins/ruby-build" }
- name: Edit bashrc
  blockinfile:
    path: ~/.bashrc
    create: yes
    insertafter: EOF
    marker: "###<!-- {mark} ANSIBLE MANAGED BLOCK -->###"
    block: |
      export RBENV_ROOT="${HOME}/.rbenv"
      export PATH="${RBENV_ROOT}/bin:${PATH}"
      eval "$(rbenv init -)"
- name: Check the Ruby Version Installed
  shell: bash -lc "rbenv versions | grep {{ruby_version}} | tr '*' ' ' | sed 's/^[ \t]*//' | cut -f1 -d' '"
  register: installed_ruby
- name: Install Ruby
  shell: bash -lc "RUBY_CONFIGURE_OPTS="--disable-install-rdoc" rbenv install -s {{ ruby_version }}"
  when: installed_ruby.stdout == ""
- name: Check Current Ruby Version
  shell: bash -lc "rbenv version" | grep "{{ ruby_version }}" | cut -f1 -d' '
  register: current_ruby_version
- name: Set default Ruby version
  shell: bash -lc "rbenv global {{ ruby_version }} && rbenv rehash"
  when: ruby_version not in current_ruby_version.stdout
- name: Install bundler and so on
  shell: bash -lc "gem install {{ item }}"
  loop:
    - rbenv-rehash
    - bundler -v {{ bundler_version }}
    - rails

rbenvで指定したrubyのバージョンはvarsに書いておきます。このくらいなら直書きでも大丈夫ですが、、

./roles/ruby/vars/main.yml
---
ruby_version: 2.6.3
bundler_version: 2.1.4

nginxの設定

nginx側のインストール&設定
ポイントはALBからDNS名(デフォルトでついてくる長いやつ)を抜いて、nginxのコンフィグを書き換えています。
AWS側の環境はTerrafromで作成したのでALBの名前がTerraformにしています。
server_names_hash_bucket_sizeはAWSのデフォルトでつくDNS名が長すぎてnginxが起動しないので変えてます

./roles/ruby/vars/main.yml
---
- name: install nginx
  command: amazon-linux-extras install nginx{{ nginx_version }} -y
  args:
    creates: /sbin/nginx
  become: yes
- name: configuration nginx
  template:
    src: nginx.conf.j2
    dest: /etc/nginx/conf.d/sampleapp.conf
  become: yes
  notify: restart_nginx
- name: get alb_dns_name
  delegate_to: 127.0.0.1
  elb_application_lb_info:
    names: "Terraform"
  register: alb
  run_once: true
- name: replace dns name
  replace:
    path: /etc/nginx/conf.d/sampleapp.conf
    regexp: "ALB_DNS_NAME"
    replace: "{{ alb.load_balancers.0.dns_name }}"
  become: yes
  notify: restart_nginx
- name: insert server_name_hash
  lineinfile:
    path: /etc/nginx/nginx.conf
    insertafter: "http {"
    line: "server_names_hash_bucket_size 128;"
    state: present
  become: yes
./roles/nginx/vars/main.yml
---
nginx_version: 1.12

nginxのコンフィグ

./roles/nginx/templates/nginx.conf.j2
upstream unicorn_server {
    server unix:/var/www/projects/sample-app/tmp/unicorn.sock
    fail_timeout=0;
}

server {
    listen 80;
    client_max_body_size 4G;
    server_name ALB_DNS_NAME;
    keepalive_timeout 5;
    access_log  /var/log/nginx/access.log;
    error_log   /var/log/nginx/error.log;

    # Location of our static files
    root /var/www/projects/sample-app/public;

    location ~ ^/assets/ {
        root /var/www/projects/sample-app/public;
    }

    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;

        if (!-f $request_filename) {
            proxy_pass http://unicorn_server;
            break;
        }
    }

    error_page 500 502 503 504 /500.html;
    location = /500.html {
        root /var/www/projects/sample-app/public;
    }
}

nginxのハンドラー

./roles/ruby/vars/main.yml
---
- name: restart_nginx
  systemd:
    name: nginx
    state: restarted
  become: true

playbook

最後に全部まとめたplaybookの中身
hostsはAWSのEC2についてるタグを指定します。(stageのところに実際についてるタグ名をつける)

./roles/ruby/vars/main.yml
---
- name: test
  hosts: tag_env_stage
  gather_facts: no
  roles:
    - role: common
      tags: base_install
    - role: ruby
      tags: ruby_insall
    - role: nginx
      tags: nginx_install
2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2