見出し画像

Ansibleを使って複数のサーバーにDockerをインストールする

こんにちは。SHIFTからRGA(リアルグローブ・オートメーティッド)に出向中の前田です。

ここ最近、コンテナ関連の業務にかかわることもあり、複数台の新規サーバーにDockerをインストールする作業を自動化したい(ついでに個人的によく使うEmacsもインストールしておきたい)と思い立ちました。せっかくなので、Ansibleを使ってやってみたところ上手くできたので、その様子を書いてみたいと思います。

構成

  • コントロールノード (Ansibleを動作させるマシン)1台

    • Ubuntu 20.04 (on VirtualBox)

    • Ansible 2.12.1

  • ターゲットノード (Ansibleによって操作されるマシン)3台

    • Ubuntu 20.04 (on AWS EC2)

自動化の手順

まずは(ターゲットノードとなる)サーバー1台を対象として、正しく動作するPlaybookを作成していきます。

これがうまく動作することを確認してから、対象となるサーバーを3台に増やします。

Ansibleの疎通確認

Ansibleのインストール方法はネット上に多数見つかるので、ここでは省略させていただき、Ansibleがターゲットホストと通信できることを確認します。そのために、まず下のようなhostsファイルを作成します。ユーザー名やSSH鍵はあらかじめ取得しておいてください。

hosts

[maeda_no_saba]
targetnode ansible_host=18.176.54.90

[maeda_no_saba:vars]
ansible_user=ubuntu
ansible_ssh_private_key_file="~/.ssh/maeda6-rga.pem"

この状態で "ansible all -i hosts -m ping" を実行して、以下のような結果が返ってこれば成功です。

$ ansible all -i hosts -m ping
targetnode | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}

Playbookの作成

さてここからPlaybookを作成していきます。今回作成する内容は以下の2点です。

  • Dockerのインストール

  • Emacsのインストール

これをRoleを使って実装しますので、最終的なディレクトリ構成は以下のような感じになります。site.ymlが実行ポイントで、ここから2つのRoleを呼び出す形ですね。

maeda@maeda-VirtualBox:~/WorkingDir/Ansible$ tree
.
├── ansible.cfg
├── hosts
├── roles
│   ├── docker
│   │   ├── handlers
│   │   │   └── main.yml
│   │   └── tasks
│   │       ├── install.yml
│   │       └── main.yml
│   └── emacs
│       └── tasks
│           ├── install.yml
│           └── main.yml
└── site.yml

Emacsタスクの作成

簡単なのでEmacsから行きましょう。aptモジュールを使ってEmacsをインストールするタスクを作成します。

roles/emacs/tasks/install.yml

- name: apt updateを実行します
  become: yes
  apt:
    update_cache: yes

- name: Emacsのインストールを行います
  become: yes
  apt:
    name: emacs
    state: present

roles/emacs/tasks/main.yml

- import_tasks: install.yml

Roleの実行はtasks/main.ymlがスタートポイントになるので、main.ymlは必須です。ここから、install.ymlをimport_taskでインポートする形になります。

install.ymlの内容は見ての通りですが、aptのキャッシュのアップデートして、emacsをインストールするだけのシンプルなものです。

Dockerタスクの作成

続いてDockerをインストールするタスクを作成します。

Ubuntu 20.04へのDockerのインストールおよび使用方法を参考にして、ここに記載されている手順をPlaybookに落とし込んでいきます。

roles/docker/tasks/install.yml

- name: apt updateを実行します
  become: yes
  apt:
    update_cache: yes

- name: Dockerのインストールに必要なパッケージをインストールします
  become: yes
  apt:
    name:
      - apt-transport-https
      - ca-certificates
      - curl
      - software-properties-common
    state: present

- name: DockerリポジトリのGPGキーをシステムに追加します
  become: yes
  ansible.builtin.apt_key:
    url: https://download.docker.com/linux/ubuntu/gpg
    state: present

- name: DockerリポジトリをAPTソースに追加します
  become: yes
  ansible.builtin.apt_repository:
    repo: deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable
    state: present

- name: apt updateを実行します
  become: yes
  apt:
    update_cache: yes

- name: Dockerをインストールします
  become: yes
  apt:
    name: docker-ce
  notify: 
    - add_user_to_docker_group
    - restart_docker_daemon
  changed_when: yes

- meta: flush_handlers

roles/docker/tasks/main.yml

- import_tasks: install.yml

少しタスク数が多いですが、emacsのRoleと同じ構成です。

emacsのRoleとの一番の違いは、Dockerをインストールした後にadd_user_to_docker_groupとrestart_docker_daemonという二つのハンドラーが実行されるようにしている点です。

add_user_to_docker_groupはサーバーにログインしているユーザーをdockerグループに追加し、restart_docker_daemonはDockerを再起動します。

これにより、dockerグループに所属しているユーザーであれば、管理者権限なしでdockerコマンドを実行できるようになります。

ユーザーをdockerグループに追加した後にその変更を反映させるため、Dockerを再起動します。再起動しなくても変更が反映されるかもしれませんが、そのあたりはよくわかりません(今ちょっとテストしてみたら、Dockerの再起動は必要なくて、一度ログアウトしてから再ログインする必要がありました)。

Dockerがすでにインストールされていて変更点がなかった場合にも上記二つのハンドラーは実行されてほしいので、changed_when: yesを追加しています。

ハンドラーは以下のとおりです。

rokes/docker/handlers/main.yml

- name: add_user_to_docker_group
  become: yes
  user:
    name: "{{ansible_user_id}}"
    groups: docker
    append: yes

- name: restart_docker_daemon
  become: yes
  service:
    name: docker
    state: restarted

ansible_user_id変数にはタスクを実行しているユーザーの名前が入っています(自分の環境では、ubuntu)。

site.ymlの作成

site.ymlはansible-playbookコマンドを実行するときに指定するPlaybookです。内容としては、上記2つのRoleを呼び出すだけの簡単なものになります。

site.yml

- hosts: all
  roles:
    - emacs
    - docker

以上でPlaybookの作成は終了です。念のため最初に示したディレクトリ構成になっていることを確認します。

maeda@maeda-VirtualBox:~/WorkingDir/Ansible$ tree
.
├── ansible.cfg
├── hosts
├── roles
│   ├── docker
│   │   ├── handlers
│   │   │   └── main.yml
│   │   └── tasks
│   │       ├── install.yml
│   │       └── main.yml
│   └── emacs
│       └── tasks
│           ├── install.yml
│           └── main.yml
└── site.yml

Playbookの実行

さて、いよいよ作成したPlaybookを実際に実行してみます。

ターミナル上で、"ansible-playbook site.yml -i hosts" を実行してください。
自分はテストのためにこのPlaybookを複数回実行しているので、okやchangedといったステータスは皆さんの環境とは異なるかもしれません。

$ ansible-playbook site.yml -i hosts

PLAY [all] *************************************************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************************************
ok: [targetnode]

TASK [emacs : apt updateを実行します] **********************************************************************************************************
changed: [targetnode]

TASK [emacs : Emacsのインストールを行います] ***************************************************************************************************
changed: [targetnode]

TASK [docker : apt updateを実行します] *********************************************************************************************************
changed: [targetnode]

TASK [docker : Dockerのインストールに必要なパッケージをインストールします] *********************************************************************
ok: [targetnode]

TASK [docker : DockerリポジトリのGPGキーをシステムに追加します] ********************************************************************************
ok: [targetnode]

TASK [docker : DockerリポジトリをAPTソースに追加します] ****************************************************************************************
ok: [targetnode]

TASK [docker : apt updateを実行します] *********************************************************************************************************
changed: [targetnode]

TASK [docker : Dockerをインストールします] *****************************************************************************************************
changed: [targetnode]

TASK [docker : meta] ***************************************************************************************************************************

RUNNING HANDLER [docker : add_user_to_docker_group] ********************************************************************************************
changed: [targetnode]

RUNNING HANDLER [docker : restart_docker_daemon] ***********************************************************************************************
changed: [targetnode]

PLAY RECAP *************************************************************************************************************************************
targetnode                 : ok=11   changed=7    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

最後の行に"failed=0"と表示され、すべてのタスクが実行できたことを確認したら、ターゲットホストにEmacsとDockerがインストールされていることを確認しましょう。

ターゲットノードを3台に増やす

作成したPlaybookが正しく実行されることが確認できたので、次はターゲットノードを1台から3台に増やしたいと思います。

変更が必要なのは、hostsファイルだけです。下のように、1つだけ登録していたターゲットホストを3つに増やしました。

hosts

[maeda_no_sabas]
maeda_no_saba ansible_host=18.176.54.90
maeda_no_saba_2 ansible_host=13.230.197.65
maeda_no_saba_3 ansible_host=52.199.123.115

[maeda_no_sabas:vars]
ansible_user=ubuntu
ansible_ssh_private_key_file="~/.ssh/maeda6-rga.pem"

実行結果

再度ansible-playbookコマンドを実行します。

maeda@maeda-VirtualBox:~/WorkingDir/Ansible$ ansible-playbook site.yml -i hosts

PLAY [all] *************************************************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************************************
ok: [maeda_no_saba]
ok: [maeda_no_saba_2]
ok: [maeda_no_saba_3]

TASK [emacs : apt updateを実行します] **********************************************************************************************************
changed: [maeda_no_saba_3]
changed: [maeda_no_saba_2]
changed: [maeda_no_saba]

TASK [emacs : Emacsのインストールを行います] ***************************************************************************************************
ok: [maeda_no_saba_2]
ok: [maeda_no_saba]
ok: [maeda_no_saba_3]

TASK [docker : apt updateを実行します] *********************************************************************************************************
changed: [maeda_no_saba]
changed: [maeda_no_saba_3]
changed: [maeda_no_saba_2]

TASK [docker : Dockerのインストールに必要なパッケージをインストールします] *********************************************************************
ok: [maeda_no_saba]
changed: [maeda_no_saba_3]
changed: [maeda_no_saba_2]

TASK [docker : DockerリポジトリのGPGキーをシステムに追加します] ********************************************************************************
ok: [maeda_no_saba]
changed: [maeda_no_saba_2]
changed: [maeda_no_saba_3]

TASK [docker : DockerリポジトリをAPTソースに追加します] ****************************************************************************************
ok: [maeda_no_saba]
changed: [maeda_no_saba_2]
changed: [maeda_no_saba_3]

TASK [docker : apt updateを実行します] *********************************************************************************************************
changed: [maeda_no_saba_3]
changed: [maeda_no_saba]
changed: [maeda_no_saba_2]

TASK [docker : Dockerをインストールします] *****************************************************************************************************
changed: [maeda_no_saba]
changed: [maeda_no_saba_3]
changed: [maeda_no_saba_2]

TASK [docker : meta] ***************************************************************************************************************************

RUNNING HANDLER [docker : add_user_to_docker_group] ********************************************************************************************
ok: [maeda_no_saba]
changed: [maeda_no_saba_2]
changed: [maeda_no_saba_3]

RUNNING HANDLER [docker : restart_docker_daemon] ***********************************************************************************************
changed: [maeda_no_saba]
changed: [maeda_no_saba_2]
changed: [maeda_no_saba_3]

PLAY RECAP *************************************************************************************************************************************
maeda_no_saba              : ok=11   changed=5    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
maeda_no_saba_2            : ok=11   changed=9    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
maeda_no_saba_3            : ok=11   changed=9    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

期待通り、3台のターゲットホストに対してインストールが行われました。

まとめ

Roleに分割しているので少しファイル数は多いですが、Ansibleを用いて(しかもRole分割した分かりやすい形で)複数サーバーに対する環境構築を自動化することができました。

今回は対象サーバーが3台だけでしたが、この手法を用いれば対象が100台や1,000台になっても対応できそうです。

マガジン|IT自動化技術ブログ集

SHIFTのグループ会社の1つである、リアルグローブ・オートメーティッド(RGA)のIT自動化に関する技術ブログをまとめています。IT自動化を導入すると「どんな良いことがあるのか」について紹介しつつ、RGAメンバーの技師たちが日々の業務を通じて培った技術情報や参考情報をお届けします!

――――――――――――――――――――――――――――――――――

執筆者プロフィール:前田  勝太郎
大学卒業後、IT関連会社にて約1年間仕様書まわりの業務およびプログラムのテストを行う。
Pythonなどの言語を独学で修得し、趣味として機械学習や3Dグラフィックスといった幅広い技術に触れる。
RGAでは、コンテナやインフラ関連の業務に従事している。

【ご案内】
ITシステム開発やITインフラ運用の効率化、高速化、品質向上、その他、情シス部門の働き方改革など、IT自動化導入がもたらすメリットは様々ございます。

IT業務の自動化にご興味・ご関心ございましたら、まずは一度、IT自動化の専門家リアルグローブ・オートメーティッド(RGA)にご相談ください!

お問合せは以下の窓口までお願いいたします。

【お問い合わせ窓口】
代表窓口:info@rg-automated.jp
URL: https://rg-automated.jp