はじめに
先日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 を作成します。小分けでcommon
、ruby
、nginx
としました。(名前は、わかり易ければなんでもOKです。)
ディレクトリはansible-galaxy init
コマンドで一発で作成出来ます。
% ansible-galaxy init roles/common
% ansible-galaxy init roles/ruby
% ansible-galaxy init roles/nginx
サーバ基本設定
role=役割なのでそれぞれのtasksを書いていきます。
commonはユーザの作成などサーバの基本設定ですが、今回は簡単にパッケージのアップデートのみにしています。
---
- name: update packages
yum:
name: '*'
state: latest
become: true
rubyの設定
次にrubyの設定をします。
rubyに必要なパッケージのインストールとrbenvの設定でファイルを分けました。
include_tasks:
で同一ディレクトリのファイルも読み取ってくれます。
---
- include_tasks: ruby_packages.yml
- include_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に書いておきます。このくらいなら直書きでも大丈夫ですが、、
---
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が起動しないので変えてます
---
- 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
---
nginx_version: 1.12
nginxのコンフィグ
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のハンドラー
---
- name: restart_nginx
systemd:
name: nginx
state: restarted
become: true
playbook
最後に全部まとめたplaybookの中身
hosts
はAWSのEC2についてるタグを指定します。(stageのところに実際についてるタグ名をつける)
---
- 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