Expect
Ansible
Anaconda
ansible2

Ansible2.xのexpectを使ってAnacondaをインストールする

More than 1 year has passed since last update.

背景

Anacondaの本家で提供されているLinux向けのインストーラーはBashで実行し対話式でインストール先を指定したり、パスの設定をしたりという動きになっています。

このAnacondaをAnsibleを使って複数サーバにインストールする時に、対話式であることがネックになります。以前はexpectを使って自力でなんとかしていたのですが、2.x系ではexpectのmoduleが追加されたそうなので、その動作確認も兼ねてAnsible2.x系を使ってAnacondaのインストールをしてみることにしました。

やりたいこと

  • SSHで接続できる対象サーバにAnacondaをインストールする
  • 全部Ansibleで完結させる

動作確認環境

  • ansibleを実行するサーバ
    • hostname:ansible-server
    • OS:Ubuntu14.04
  • 対象サーバ
    • hostname:test-server
    • OS:Ubuntu14.04

この2つのサーバをVagrantで用意して動作確認しました。

大雑把な流れ

  1. Ansibleの実行環境構築
  2. AnacondaのInstall時の挙動を確認
  3. 2の内容を踏まえてansible-playbookを作成
  4. ansible実行後の動作確認

1. Ansibleの実行環境構築

Ansibleはapt-getでインストールできますが、OSやバージョンによって2.x系をインストールする手順が少し異なります。
Ubuntu14.04の場合は以下のコマンドでインストールできます。

Ansibleインストールコマンド
$ sudo apt-get install software-properties-common
$ sudo apt-add-repository ppa:ansible/ansible
$ sudo apt-get update
$ sudo apt-get install ansible

Ubuntu意外のOSでの導入方法はAnsibleのInstallationページを参照してください。

インストールが完了したら、以下のコマンドでバージョンを確認します。バージョンが返ってきたらインストール成功です。

Ansibleバージョン確認コマンド
$ ansible --version
ansible 2.1.1.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = Default w/o overrides

2. AnacondaのInstall時の挙動を確認

Anacondaのインストーラーを実際に実行して、どのようにそれぞれの質問に対応すべきか確認します。今回の動作確認では「Anaconda3-4.1.1-Linux-x86_64.sh」を利用しています。

Anacondaインストールコマンド
bash Anaconda3-4.1.1-Linux-x86_64.sh

実行すると、以下の部分で入力を求められます。

Anacondaインストール時の標準出力1
Welcome to Anaconda3 4.1.1 (by Continuum Analytics, Inc.)

In order to continue the installation process, please review the license
agreement.
Please, press ENTER to continue
>>>

expectのmoduleで挙動を定義するために、途中で入力を求められる部分が重要になります。
1つめの「>>>」は単にENTERすれば良いのでそれを覚えておきます。
処理をすすめるにENTERします。次に以下のところで入力を求められます。

Anacondaインストール時の標準出力2
(略)
Anaconda contains open source software packages from third parties. These
--More--

この部分はスペースでページ送りすれば良い部分です。
ただ、この部分もちゃんとexpectのmoduleに書いてあげる必要があります。
標準出力には「--More--」と表示されていますが、実はこれは「:」を置き換えられている(※)ので
「:」ときはスペースとして覚えておきます。
※:Macで試すと「:」が表示されるんです。Ubuntuだと気を利かせて置き換えてくれてる?

更にすすめると、以下のように同意するか求められます。

Anacondaインストール時の標準出力3
(略)
Do you approve the license terms? [yes|no]
>>>

ここではもちろん「yes」なので、 2つめの「>>>」はyesとおぼえておきます。
次にインストールパスの確認が来ます。

Anacondaインストール時の標準出力4
(略)
Anaconda3 will now be installed into this location:
/home/vagrant/anaconda3

  - Press ENTER to confirm the location
  - Press CTRL-C to abort the installation
  - Or specify a different location below

[/home/vagrant/anaconda3] >>>

デフォルトでよければENTERで良いので 3つめの「>>>」はENTERと覚えておきます。
ENTERするとパッケージのインストールがスタートします。
パッケージのインストールが終わると、最後にパスを.bashrcに追加するか確認されます。

Anacondaインストール時の標準出力5
(略)
installation finished.
Do you wish the installer to prepend the Anaconda3 install location
to PATH in your /home/vagrant/.bashrc ? [yes|no]
[no] >>>

個人的には.bashrcに追加してほしいので 4つめの「>>>」はyesと覚えておきます。
これでインストールまでの挙動の確認は完了です。

3. 2の内容を踏まえてansible-playbookを作成

2で確認した挙動をもとにAnsibleのexpectのmoduleを記述します。
ansible-playbook全体はgithubにアップしているので、他の部分も確認したい場合はそちらを参照してください。

先程挙動を確認した結果をresponsesの下に書きます。

roles/anaconda/tasks/main.ymlの抜粋
- name: install anaconda3
  expect:
    chdir: "/home/{{ target_user }}"
    command: "bash {{ anaconda_script }}"
    timeout: 360
    responses:
      '>>>': '\n'
      ':': ' '
      '>>>': 'yes'
      '>>>': '\n'
      '>>>': 'yes'
  become: true
  become_method: su
  become_user: "{{ target_user }}"

Anacondaはgroup_vars/allで指定したtarget_userの権限でインストールしたいので以下のように記述しています。

roles/anaconda/tasks/main.ymlの抜粋
  become: true
  become_method: su
  become_user: "{{ target_user }}"

expectのmoduleを使うためにpexpectをpipでインストールしないといけないので
expectのmoduleよりも前に以下のような記述も必要です。

roles/anaconda/tasks/main.ymlの抜粋
- name: install pexpect by anaconda pip
  pip: name=pexpect

4. ansible実行後の動作確認

無事すべてのansible-playbookが流れると以下のように出力されます。

Ansibleの実行結果
(略)
PLAY RECAP *********************************************************************
test-server                : ok=5    changed=4    unreachable=0    failed=0

最後に動作確認として、test-serverにログインしてAnacondaがインストールされたかを確認します。

pythonコマンドの実行結果
vagrant@test-server:~$ python
Python 3.5.2 |Anaconda 4.1.1 (64-bit)| (default, Jul  2 2016, 17:53:06)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

パスがしっかり通っていれば対象のユーザでpythonコマンドを打つと↑のような形になり、先程インストールしたAnaconda4.1.1のPythonが利用されていることが確認できます。

まとめ

今回はAnacondaのインストールのやり方をベースに説明しましたが、他にもAnacondaと同じようにBashで対話式にインストールするタイプのものは、同様の方法で対応することが可能だと思います。
もし、そういうものをAnsibleで入れる必要が出てきたら参考にしてみてください。

質問やコメントがあれば気軽にお願いします。