【Ansible入門】EC2環境でAnsibleを実行してみよう

記事タイトルとURLをコピーする

こんにちは、CI部の柿﨑です。
先日、洗濯槽の掃除をしようと専用の洗剤を入れたところ、黒い物体がたくさん浮いてきました。
どうやらn年間の汚れが溜まっていたようです。。。猛省。
つまり、何事も定期的なメンテナンスが必要ということですね!

と、いうことで!
定期的なメンテンスといえば、そう!!
Infrastructure as Code(以下Iac)ですね!
今回はIaCの中でも代表的なツールである、Ansible入門を題材にします。
なるべくシンプルな構成にしていますので、是非、ご一読いただければと思います。

2019/10/24追記:本記事の続きを書きました → こちら

本記事の対象者

  • AWS環境にてサクッとAnsibleに触りたい方
  • 初っ端Ansibleのベストプラクティスを見て、やる気を失った方

本記事のコンセプト

  • なるべくシンプルに
  • 最低限使えるディレクトリ構成でAnsibleの動作を理解する
  • 今回はリモートにログインユーザーを作成し、パスワード認証でSSH接続します

前提条件

  • 下記、構成図の環境を構築
  • SSH接続にはteratermを使用
  • 今回使用したAMIはami-0ff21806645c5e492(Amazon Linux 2)
  • AnsibleサーバーはSSH接続、インターネット接続が可能なこと
  • Client01サーバーはSGにてAnsibleサーバーからのSSH接続許可、秘密鍵名はansible-key.pem、IPアドレスは192.168.20.4/32 

目次

  1. Ansibleとは
  2. インストールからPlaybook実行
  3. さいごに

1.Ansibleとは

インフラ環境をコード化し、インフラ構成を管理するツール。→ 公式ドキュメント
Ansible用にコード化されたファイル群をPlaybookと呼び、Playbookを1度でも何度でも実行しようが、同じ結果が得られる冪等性という特徴がある。
対象ホストが多ければ多いほど、実行したPlaybookの処理が成功したときに気持ち良くなれる。(失敗したときは知りません。)

2.インストールからPlaybook実行

  1. Ansibleサーバーにec2-userでSSH接続

  2. Ansibleサーバーにて以下コマンドを実行し、Ansibleをインストール
    sudo yum -y install python-devel openssl-devel gcc git
    sudo easy_install pip
    sudo pip install ansible
    ansible --version
    ※最後にAnsibleのバージョンが表示されたら成功です。
  3. Client01サーバーの秘密鍵をAnsibleサーバーの/home/ec2-user/.ssh/配下に格納

    以下のとおり、ansible-key.pemを確認できれば準備完了。
    [ec2-user@ip-192-168-10-33 ~]$ ls -la .ssh/
    total 8
    drwx------ 2 ec2-user ec2-user 52 Sep 6 08:33 .
    drwx------ 4 ec2-user ec2-user 90 Sep 6 08:23 ..
    -rw-r--r-- 1 ec2-user ec2-user 1696 Sep 6 08:30 ansible-key.pem
    -rw------- 1 ec2-user ec2-user 394 Sep 6 08:02 authorized_keys
    [ec2-user@ip-192-168-10-33 ~]$
  4. 急いでる人用 (急いでいない人は、この手順を飛ばして5.の手順へお進みください。)
    急いでいる人用にPlaybookをgitに上げましたので、そちらをAnsibleサーバーに格納して、Playbookを実行。
    cd
    git clone https://github.com/ikayarou/hands-on-01.git
    cd hands-on-01
    sudo ansible-playbook -i inventory/hosts site.yml
    ※SSHの接続確認をされるので、yesと入力しEnter Playbookの実行に成功すると以下のように結果が出力される。
    このPlaybookでは、Client01にパスワード認証でログインするユーザーを作成しました。
    早速、接続確認を行ってみます。
    ssh hands-on-user01@192.168.20.4
    ※SSHの接続確認をされるので、yesと入力しEnter パスワード:hands-on を入力 SSH接続に成功出来たら完了です。
    急いでいる人向けの内容は、ここで終わりです。
  5. 急いでいない人向け手順
    以下のようなディレクトリ構造を順次作成していきます。まずはインベントリファイルから作成。
    mkdir -p hands-on-01/inventory
    cd hands-on-01
    cat << EOF > inventory/hosts
    [client_node]
    Clinet01 ansible_ssh_host=192.168.20.4
    
    [client_node:vars]
    ansible_ssh_user=ec2-user
    ansible_ssh_private_key_file=/home/ec2-user/.ssh/ansible-key.pem
    EOF
    [client_node]はグループ名です。
    グループ名を使うことで対象ホストをグルーピングすることができます。
    この項目で対象ホストのIPアドレスを記述しています。

    こちらに記載のansible_ssh_host=はホスト変数と呼ばれ、このホストにのみ適用されます。
    [client_node:vars]は、[client_node]グループに適用する変数を指定しています。
    これをグループ変数と呼びます。
    ansible_ssh_user=では対象ホストにSSH接続するユーザー名、ansible_ssh_private_key_file=ではSSH接続に使用する秘密鍵を指定しています。
    このように設定することで、グループごとにSSH接続するユーザーを変えたり、パスワード認証でSSH接続したりすることが可能です。 続いて、site.ymlファイルを作成します。
    cd ~/hands-on-01
    cat << EOF > site.yml
    ---
    - hosts: client_node
      become: True
      roles:
        - hands-on
    EOF
    hosts:では、Playbook実行対象のグループを指定します。
    先ほど、hostsファイルに記述した[client_node]ですね。
    become:を有効化することにより、リモートユーザーでの処理をsudo権限で実行してくれます。
    roles:では、実行するロールを指定します。今回はhands-onロールを実行します。 続いて、hands-onロールのtasksファイルを作成していきます。
    cd ~/hands-on-01
    mkdir -p roles/hands-on/tasks
    cat << EOF > roles/hands-on/tasks/main.yml
    ---
    - name: create user
      user:
        name: hands-on-user01
        createhome: yes
        state: present
        password: "{{ 'hands-on' | password_hash('sha512') }}"
    
    - name: modify sshd_config
      lineinfile:
        dest: /etc/ssh/sshd_config
        state: present
        backrefs: yes
        regexp: '^PasswordAuthentication no'
        line: 'PasswordAuthentication yes'
        backup: yes
      notify:
        - restart sshd
    EOF
    tasksファイルでは、リモートユーザーで実行したい処理を記述します。
    ここで重要になってくるのが、user:およびlineinfile:です。
    これらはモジュールと呼ばれ、各モジュールごとにAnsibleの処理が実装されています。
    今回であれば、userモジュールでユーザーを作成し、lineinfileモジュールでsshd_configファイルの編集を行っています。
    基本的には、各モジュールのドキュメントでパラメーターの内容を参照しつつ、Playbookを書いていきます。
    userモジュールのドキュメントはこちらlineinfileモジュールのドキュメントはこちら
    ※細かいパラメーターの説明は公式ドキュメントにおまかせします。

    といいますのも、今回注目していただきたいパラメーターはnotify:だからです。
    このnotify:が記述されているタスクが実行され、設定が変更された場合、notify:に記述されているrestart sshdが実行されます。
    restart sshdは後述するhandlersにて定義されている処理です。
    つまり、notify:を記述することにより、sshd_configファイルの設定変更を契機として、handlersファイルの処理を呼び出すことが可能となります。

    それでは、最後にhandlersファイルを作成します。
    cd ~/hands-on-01
    mkdir -p roles/hands-on/handlers
    cat << EOF > roles/hands-on/handlers/main.yml
    ---
    - name: restart sshd
      service:
        name: sshd
        state: restarted
        enabled: yes
    EOF
    前述したrestart sshdの正体がこのファイルになります。
    serviceモジュールにより、sshdをリスタートすることで設定を反映させています。serviceモジュールのドキュメントはこちら
    今回はディレクトリを分けましたが、1つのファイル内に記述することも可能です。 さて、これでPlaybookが完成しました。
    早速、実行してみましょう。
    cd ~/hands-on-01
    sudo ansible-playbook -i inventory/hosts site.yml
    ※SSHの接続確認をされるので、yesと入力しEnter ansible-playbookがPlaybookの実行コマンドで、-iでインベントリファイルを指定、そしてPlaybookの起点となるsite.ymlを指定して実行しています。
    エラーがなく正常に実行されたら、SSH接続の確認をして完了となります。
    ssh hands-on-user01@192.168.20.4
    ※SSHの接続確認をされるので、yesと入力しEnter パスワード:hands-on を入力 hands-on-user-01ユーザーで、パスワード:hands-onを入力してSSH接続に成功すればハンズオンは完了です。
    ちなみにですが、リモートユーザーでls -la /etc/sshと叩くと以下のようなファイルが存在するかと思われます。
    -rw------- 1 root root 3957 Sep 9 08:06 sshd_config.3699.2019-09-09@08:11:41~

    これは、lineinfileモジュールのbackup: yesとすることで、ファイル編集時に元ファイルのバックアップを作成してくれたりします。
    便利ですね♪

3.さいごに

AnsibleはモジュールをベースにPlaybookを書いていきますので、コードが標準化されるという利点がございます。
そのため、誰が見てもコードが理解しやすく、IaCやコードに不慣れな方の入口として最適だと思われます。
逆をいえば、複雑に書かないでくださいということですね!
Ansibleの思想として、チームでコードを管理するために分かりやすい記述を心がける必要があります。
もし、複雑な処理を実行したい場合は、AnsibleではなくほかのIaCツールをご検討いただくのが無難です。

Ansibleのベストプラクティスについては、こちらの方が分かりやすく書いてくれています。
今回作成したPlaybookと見比べると、ずいぶん違いますね!
ベストプラクティスの方は、最初から手をつけるにはいろいろと知らなければいけないことが多いです。
そのため、今回のPlaybookを理解しつつ、改善を積み重ねていくことでベストプラクティスへの理解も深まっていくものと思われます。
例えばここで、変数を使っていったり・・・というのを書こうと思っていましたが、どうやら時間切れのようです。
また、機会がありましたら続きを書きます。
最後に簡単な課題としまして、余っているプライベートサブネットにサーバーを作成して、今回作成したサーバーと2台同時にPlaybookを実行してみてください。
これができますと、いくつものサーバーに対してPlaybookを実行するのも容易になるものと思われます。

本記事が、皆様のお役に立てれば幸いでございます。

2019/10/24追記:本記事の続きを書きました → こちら

柿﨑 拓人 (記事一覧)

クラウドインテグレーション部

AWS移行案件の要件定義~構築をメインに担当。
最近はボルダリングとバドミントンをやっています。