AnsibleでEC2にRuby環境(rbenv, ruby, bundler)をインストール

以前まとめたAnsibleでのAWS環境構築のPlaybookに続いて、Ruby環境(rbenv, ruby, bundler)もインストールできるようにしてみましたので、Playbookの書き方をまとめておこうと思います。

構成

ローカル環境とEC2環境におけるRubyインストール後のファイル構成は以下の図の通りです。 f:id:moritamorie:20190727223730p:plain

環境

  • ローカル環境(ansibleを実行する環境): Ubuntu 18.04.2 LTS
  • EC2環境(Rubyをインストールする環境): Ubuntu 18.04.2 LTS
  • ansible: 2.5.1
  • ruby: 2.6.3

Ansibleのインストール

まだ、Ansibleをインストールされていないようでしたら、以下の記事を元にインストールしてみてください。 simple-minds-think-alike.hatenablog.com

Ansible定義ファイルのディレクトリ/ファイル構成

ローカル環境に作るAnsible定義ファイルのディレクトリ/ファイル構成の最終形は以下のようになります。

├── install_ruby.yml
├── hosts
│   └── all_host
└─ roles
    ├── bundler
    │   ├── meta
    │   │   └── main.yml
    │   └── tasks
    │       └── main.yml
   ├── rbenv
   │   └── tasks
   │       └── main.yml
   └── ruby
       ├── meta
       │   └── main.yml
       └── tasks
           └── main.yml 

Ansibleのplaybook実行時に指定する定義ファイル install_ruby.yml には、以下のように記載しました。

- name: ruby/rbenv/bundlerインストール
  hosts: web
  become_user: ubuntu
  become: true
  vars:
    home_path: "/home/ubuntu"
    rbenv_path: "{{ home_path }}/.rbenv"
    ruby_version: 2.6.3
    ruby_dir: "{{ rbenv_path }}/versions/{{ ruby_version }}"
  roles:
    - rbenv
    - ruby

ubuntuユーザでログインし、/home/ubuntu/.rbenvディレクトリにrbenv / ruby 2.6.3のインストールを行う想定です。

インベントリファイル

インベントリファイル ( hosts/all_hostのファイル ) には、以下のようにrubyインストール対象のマシンホスト名を指定しています。

[web]
ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com
ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com

rbenvインストール

roles/rbenv/tasks/main.yml に、rbenvのインストールのためのタスクを記載します。

- name: rbenvがインストール済か確認
  shell: "{{ rbenv_path }}/bin/rbenv --version"
  register: rbenv_exists
  changed_when: False
  ignore_errors: yes

- name: rbenvが未インストールならrbenvをインストール
  git:
    repo: https://github.com/sstephenson/rbenv.git
    dest: "{{ rbenv_path }}"
  when: rbenv_exists is failed

- name: ruby-buildをインストール
  git:
    repo: https://github.com/sstephenson/ruby-build.git
    dest: "{{ rbenv_path }}/plugins/ruby-build"
  when: rbenv_exists is failed

- name: rbenv installを実行できるようにする
  # root権限で実行
  become_user: root
  command: "{{ rbenv_path }}/plugins/ruby-build/install.sh"
  when:  rbenv_exists is failed

- name: 環境変数PATHにrbenvのパスを設定
  blockinfile:
    dest: "{{ home_path }}/.bash_profile"
    create: yes
    insertafter: '^PATH=\$PATH:\$HOME/bin$'
    content: |
      export RBENV_ROOT={{ rbenv_path }}
      export PATH="$RBENV_ROOT/bin:$PATH"
      eval "$(rbenv init -)"
  when: rbenv_exists is failed

最初の「rbenvがインストール済か確認」以外は、rbenvが未インストールのみ実行するようにしています。

rubyインストール

roles/ruby/tasks/main.yml には、Rubyインストールするためのタスクを記載します。

- name: Rubyインストールに必要なパッケージをインストール
  # root権限で各パッケージをインストール
  become_user: root
  apt: pkg={{ item }}
  with_items:
    - build-essential
    - libssl-dev
    - libcurl4-openssl-dev
    - libreadline-dev
    - ruby-dev
    - zlib1g-dev

- name: インストール対象のバージョンのrubyがインストール済か確認
  shell: bash -lc "rbenv versions | grep {{ ruby_version }}"
  register: rbenv_check_install
  changed_when: False
  ignore_errors: yes

- name: 未インストールの場合rubyをインストール
  shell: bash -lc "RUBY_CONFIGURE_OPTS=--disable-install-doc rbenv install {{ ruby_version }}"
  when: rbenv_check_install is failed
  args:
    creates: "{{ ruby_dir }}"

- name: 既にインストール対象のバージョンのrubyがrbenv globalとして設定してあるか確認
  shell: bash -lc "rbenv version | grep {{ ruby_version }}"
  register: rbenv_check_default
  changed_when: False
  ignore_errors: yes

- name: もし、rbenv globalに設定されていなければ設定する
  shell: bash -lc "rbenv global {{ ruby_version }}"
  when: rbenv_check_default is failed

Rubyのインストールの仕方は色々試行錯誤しました。 というのも、Rubyインストールに必要なパッケージが足りないなどインストールエラーが発生している場合、エラーが返ってこなかったためです。 もし、20,30分インストールが終わらない場合は、EC2環境にSSHで接続し、実行される想定のコマンドを実行して、インストールできることを確認すると良いです。

また、roles/ruby/meta/main.yml には、rbenvの依存関係を記載し、rubyインストールよりも先にrbenvをインストールされるようにしました。

dependencies:
  - { role: rbenv }

bundlerインストール

roles/bundler/tasks/main.yml には、Bundlerインストールするためのタスクを記載します。

- name: bundleインストールで必要なライブラリをインストール
  become_user: root
  apt: pkg={{ item }}
  with_items:
    - libpq-dev

- name: bundlerインストール
  gem:
    name: bundler
    executable: "{{ rbenv_path }}/shims/gem"
    user_install: False
    version: 2.0.1

roles/bundler/meta/main.yml には、rbenv、rubyが先にインストールされるように依存関係を記載しました。

dependencies:
  - { role: rbenv }
  - { role: ruby }

実行

以下のように実行します。-iオプションでインベントリファイルを指定し、-uでSHH接続するユーザを、--private-keyで使用するキーを指定できます。

$ ansible-playbook ./install_ruby.yml -i ./hosts/all_host -u ubuntu  --private-key="~/.ssh/performance_test.pem"

確認

rbenv / rubyをインストールしたEC2環境にSSH接続し、でRuby環境をインストールした環境に入って想定通りインストールできたか確認します。

$ rbenv versions
  system
* 2.6.3 (set by /home/ubuntu/.rbenv/version)