「小さく始める」Ansible

自分は社内ではインフラ関連の取りまとめなどを行っているチームに所属しているのですが、去年の終わりぐらいから少しずつInfrastructure as a Codeを実践して行っています。

個人的嗜好が主な理由なのですが、構成管理ツールとして主にAnsibleを使用しており、

* 小規模案件のインフラ構築
* 相乗りwebアプリ環境のアプリ追加セットアップ
* エンジニア学習用環境のユーザー管理

という小さめな範囲からコントールの幅を広げていこうと進めている段階です。
ここでは、上のケースのから「エンジニア学習用環境のユーザー管理」について簡単に紹介していきたいと思います。


## 簡単に説明

社内にはミッションという制度があって、場合によってはミッションのためにAWSのインスタンスを1個用意したりしています。
基本的に自社で構築していくインフラ環境は

```
「インフラ踏台」→「機能サーバー」
```
のような形式になっていることが多く、ミッション系環境として**機能サーバー**の部分を**ミッション用サーバー**として構築しています。
ミッションは個人での技術向上やチームでの開発など複数パターンがあるのですが、

* 個人でミッション
    * 依頼者個人のみがアクセスできるインスタンスを提供して、sudoでのフルアクセス権限を付与する
* チームでミッション
    * チームメンバーのみがアクセスできるインスタンスを提供して、sudoでのフル権限持ちをチームで決めてもらう

と言うパターンを自分で用意する箇所は最小限にしつつ、なるべく実際にサーバーを扱う人達に追加設定の提示をしてもらえるようにできないかを進めています。

### Ansibleで解決する

この管理をAnsibleを絡めながら楽な方向に進めようとすると、

* インスタンスの新規追加
* 踏み台側からインスタンスへアクセスする経路を用意
* インスタンスへアクセスするユーザーを設定
* (必要なら)完了したら通知

あたりができていけば、Playbookと設定系ファイルの更新だけで話を進められそうです。

で今の状況がこちら

#### Playbookのほう

```yaml:mission_server.yml
- hosts: all
  vars_prompt:
    - name: 'target'
      prompt: 'Please enter target'
      private: no
  pre_tasks:
    - include_vars: vars/users.yml
  tasks:
    - name: Add groups
      sudo: yes
      group:　name='{{ item }}' state=present
      with_items: ['users', 'managers']
    - name: manager is granted sudo.
      sudo: yes
      lineinfile: dest=/etc/sudoers state=present regexp='^%managers ALL\=' line='%managers ALL=(ALL) NOPASSWD:ALL' validate='visudo -cf %s'
    - name: Add users
      sudo: yes
      user: name='{{ item }}' groups=users
      with_items: '{{ mission_members[target].members }}'
    - name: Add public key for to users
      sudo: yes
      authorized_key: user='{{ item }}' key='{{ ssh_users[item].authorized_keys }}'
      with_items: '{{ mission_members[target].members }}'
    - name: Add users for managers
      sudo: yes
      user: name='{{ item }}' groups=users,managers
      with_items: '{{ mission_members[target].managers }}'
    - name: Add public key for to users
      sudo: yes
      authorized_key: user='{{ item }}' key='{{ ssh_users[item].authorized_keys }}'
      with_items: '{{ mission_members[target].managers }}'
```

基本的には、`var/users.yml`にユーザーのSSHユーザー名と公開鍵、そしてどのサーバーに接続していきたいかを登録してそれをそのままansibleで反映させるスタイルをとってます。
無駄な処理してそうなので、もうちょっと表記を簡略化できるならさせたいですね。

#### ユーザー情報

```yaml:vars/users.yml
ssh_users:
  attakei:
    login_name: attakei
    authorized_keys: |
      (ここに秘密鍵)

  (ユーザー名):
    login_name: (ユーザー名)
    authorized_keys: |
      (ここに秘密鍵)
  (以下略)

mission_members:
  attakei-pyramid:
    managers:
      - attakei
    members:
      - other_team_members

  (以下略)
```

他のエンジニアの方には、「変更設定時にはこちらを編集してマージリクエスト出して」とお願いしています。
このファイル名の割にはサーバー側の構成情報もちょこっと載っているのはどうかなと思案中。

#### インスタンスは？

今はAWSのConsoleで直接作ってます。最終的にはAnsibleで片付けたいのですけどね

## Ansibleで何が変わるか

一般論と概ね変わらないのですが、

* `ansible-playbook`コマンドで冪等な反映が気楽にできるようになった
    * 「SSHでログインしてそこからコマンドラインで…」がいらなくなった
* どういう設定にしているかを視覚化できるようになった
    * おかげで、インフラ以外のエンジニアにも「ここを編集さえすればいい」を示しやすくなった

のような変化をもたらすことができてます。
そこから派生して、「まずツールで設定を書けないか」を軸に考えるようになっていくのが裏で芽生えていくメリットかなと思います。

## 「小さく始める」から「より広く適用する」へ

社内的には「既存の設定をAnsibleに置き換える」アプローチではなく「新規発生する環境を環境が小さいうちにAnsible主体で扱う」アプローチで、広げていっています。
いつか、既存の設定もAnsible(もしくはより使いやすい構成管理ツール)でマネージできるようになり、事業インフラ丸ごとコードベースのインフラ管理が支配できる日を信じで、コツコツPlaybookやRoleを書いていく日々を過ごしています