Terraform for さくらのクラウドをAnsibleから動かしてみた

昨日の**[「SpringBoot」に疲れたら「jooby」はいかが？](https://qiita.com/yangiYA/items/ff7a8bf980064eb46f2f)**から、本日は毛色を変えてこんなタイトルです。
ちなみに、自分も1年半くらい前にjoobyを少し触ってみてました。
軽量で動作が軽かったのを覚えています。


それでは本題です。

# Terraform for さくらのクラウドをAnsibleから動かしてみた
折角さくらのクラウドを使うので、説明はさくらのナレッジから引用します。
## Terraformとは
> Terraformとは、インフラの構築、変更、バージョンの管理をコードで行うためのコマンドラインツールです。ここでいうインフラとは、コンピューティングリソースやストレージ、ネットワークといった基本的な部分から、ロードバランサーやDNS、データーベース、CDNといった応用的なものまでを含む、システムを構成する基盤の事を指しています。開発はVagrantやPacker、Consulといった製品を開発しているHashicorp社が主体となって行われており、GitHubにてオープンソース・プロジェクトとして進められています。
https://knowledge.sakura.ad.jp/7230/


## Ansibleとは
> 近年、ChefやPuppetなどの構成管理ツールが人気だが、新たに注目されつつある構成管理ツールとして「Ansible」がある。Ansibleは設定ファイルがシンプルで、管理対象サーバーに特別なソフトウェアをインストールすることなく利用できるなど、最小限の手間で各種設定を自動化できるのが特徴だ。今回はこのAnsibleについてその基本的な使い方を紹介する。
https://knowledge.sakura.ad.jp/3124/

## ついで？にさくらのクラウドとは
> さくらのクラウドは、サーバーやストレージなどの多彩なサービスが1時間単位から使える、高性能で低価格なIaaS型クラウドサービスです。
https://cloud.sakura.ad.jp/

※周りでも結構、お世話になっている人がいる。。。

# 本件でやってみる事
Ansible2.5から、Terraformの管理コマンドも標準で追加されたので、せっかくなのでさくらのクラウドで使ってみたということです。

先に書いておきますが、そもそもサーバの構築までAnsibleで実施すると**「鶏が先か、卵が先か」**みたいな事になりますので、
本番構成で使うべきかどうかは、しっかり検討が必要だと思います。

## 前提
+ さくらのクラウドのアカウント、APIキーが必要
+ CentOS7にて環境構築
+ 若干のサーバ費用発生


## Ansibleのインストール
EPELリポジトリから導入しますので、下記のコマンドが必要です
`sudo yum install epel-release`
`sudo yum install ansible`

## AnsibleのPlaybookの作成
下記のようなディレクトリ構成で準備しました。
terraformのインストールもAnsibleにて実施します。
※下記は[GitHub](https://github.com/kitaji0306/ansible-terraform-sakuracloud.git)で公開してます。

```
.
├── ansible.cfg
├── inventories
│   └── local
│       └── hosts
├── local_private_key
├── roles
│   └── terraform
│       ├── files
│       │   └── sakura.tf
│       └── tasks
│           └── main.yml
└── site.yml
```

タスクは下記のような構成になってます。

```main.yml
  - name: mkdir exec dir
    file:
      path: /var/tmp/test
      state: directory

  - name: download and unzip terraform
    unarchive:
      src: https://releases.hashicorp.com/terraform/0.11.10/terraform_0.11.10_linux_amd64.zip
      dest: /var/tmp/test
      remote_src: yes

  - name: download and unzip terraform-provider-sakuracloud
    unarchive:
      src: https://github.com/sacloud/terraform-provider-sakuracloud/releases/download/v1.8.0/terraform-provider-sakuracloud_1.8.0_linux-amd64.zip
      dest: /var/tmp/test
      remote_src: yes

  - name: copy tf file
    copy:
      src: sakura.tf
      dest: /var/tmp/test
      backup: yes

  - name: terraform apply
    terraform:
      project_path: /var/tmp/test
      state: present
      binary_path: /var/tmp/test/terraform
      force_init: yes
    register: result

  - name: debug
    debug:
      msg: "{{ result.stdout }}"
```
作業ディレクトリ掘って、Terraformのバイナリとさくらのクラウド用プラグインをダウンロード後に配置して、TFファイルも同じディレクトリ放り込んで実行という、かなり大雑把な感じです。
※Ansibleを使う上で、重要なファクター**冪等性**を考えると、一時ディレクトリに、いろいろファイルを作成するなどはありえないのですが、今回はお試しということで。。。

## TerraformのTFファイルの作成

```sakura.tf
# genareate ssh key
resource sakuracloud_ssh_key_gen "key" {
  name = "foobar"

  provisioner "local-exec" {
    command = "echo \"${self.private_key}\" > id_rsa; chmod 0600 id_rsa"
  }

  provisioner "local-exec" {
    when    = "destroy"
    command = "rm -f id_rsa"
  }
}

# target zone
provider sakuracloud {
  token  = "****"
  secret = "****"
  zone   = "is1b" # tk1v=Sandbox
}

# archive data
data sakuracloud_archive "centos" {
  filter = {
    name   = "Tags"
    values = ["current-stable", "arch-64bit", "distro-centos"]
  }
}

# disk config
resource "sakuracloud_disk" "disk" {
  name              = "disk01"
  source_archive_id = "${data.sakuracloud_archive.centos.id}"
  password          = "PUT_YOUR_PASSWORD_HERE"
  ssh_key_ids       = ["${sakuracloud_ssh_key_gen.key.id}"]
  disable_pw_auth   = true
}

# server config
resource "sakuracloud_server" "server" {
  name  = "server01"
  disks = ["${sakuracloud_disk.disk.id}"]
  nic   = "shared"
  tags  = ["@group-b", "@boot-cdrom", "@keyboard-us"]

  # provisioning connection
  connection {
    user        = "root"
    host        = "${self.ipaddress}"
    private_key = "${sakuracloud_ssh_key_gen.key.private_key}"
  }

  provisioner "remote-exec" {
    inline = [
      "hostname",
    ] # provision command
  }
}

# show ip address
output "ip_addr" {
    value = "${sakuracloud_server.server.ipaddress}"
}
```
鍵情報を作成して、APIキーと石狩第2をリージョン指定で
最新のCentOSアーカイブからOSを導入しています。
ローカルで作成した鍵情報を、ディスクの修正機能で取り込んで、プロビジョニングもどきなコマンド発行まで行っています。
最後に作成されたサーバは、今回は直接共有グローバルセグメントに繋がっているので、グローバルIPを出力しています。
これで、さくらのクラウドコンソール無しにサーバの生成からSSH接続環境までは整う感じでしょうか。
※上記はrootでSSH可能な簡易設定なので、本番向けの構成ではありませんので、あしからず。。。

# 実際にやってみた
## プレイブックの実行
`ansible-playbook -i inventories/local site.yml`

```
PLAY [web] ******************************************************************************************************************

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

TASK [terraform : mkdir exec dir] *******************************************************************************************
changed: [localhost]

TASK [terraform : download and unzip terraform] *****************************************************************************
changed: [localhost]

TASK [terraform : download and unzip terraform-provider-sakuracloud] ********************************************************
changed: [localhost]

TASK [terraform : copy tf file] *********************************************************************************************
changed: [localhost]

TASK [terraform : terraform apply] ******************************************************************************************
changed: [localhost]

TASK [terraform : show result] **********************************************************************************************
ok: [localhost] => {
    "result.stdout_lines": [
        "sakuracloud_ssh_key_gen.key: Creating...",
        "  fingerprint: \"\" => \"<computed>\"",
        "  name:        \"\" => \"foobar\"",
        "  private_key: \"\" => \"<computed>\"",
        "  public_key:  \"\" => \"<computed>\"",

～～～～省略～～～～～

        "sakuracloud_server.server (remote-exec): Connected!",
        "sakuracloud_server.server (remote-exec): localhost.localdomain",
        "sakuracloud_server.server: Creation complete after 37s (ID: 113001601565)",
        "",
        "Apply complete! Resources: 3 added, 0 changed, 0 destroyed.",
        "",
        "Outputs:",
        "",
        "ip_addr = 153.127.196.37"
    ]
}
```

最後の方に、ログでリモートでコマンド発行結果（プロビもどき）および、IPアドレスを表示しています。
>         "sakuracloud_server.server (remote-exec): localhost.localdomain",
        "ip_addr = 153.127.196.37"


## さくらのクラウドコンソールで確認
![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/70168/0032fdc0-141a-0e17-bc1e-c72c3341547b.png)
サーバが作成されて起動している事が確認できました。

## サーバの作業ディレクトリ
```
[vagrant@localhost qiita-2018]$ ls -l /var/tmp/test/
total 106736
-rw------- 1 root root     1676 Dec  4 15:58 id_rsa
-rw-r--r-- 1 root root     1469 Dec  4 15:58 sakura.tf
-rwxrwxr-x 1 root root 89397536 Oct 24 00:00 terraform
-rwxr-xr-x 1 root root 19877376 Oct 30 14:00 terraform-provider-sakuracloud_v1.8.0_x4
-rw-r--r-- 1 root root     9449 Dec  4 16:00 terraform.tfstate
```
タスクには無かった**terraform.tfstate**というファイルが作成されています。このファイルが、Terraformの認識しているクラウドの状態を保持している**超重要**なファイルで、これをどのように管理するのかが、Terraformを利用する上で鍵になるようです。
※実運用していないので、今回はあんまり触れませんが、Gitで管理するのはオススメしないって、公式ドキュメントには書かれているようです。
さくらのクラウドならオブジェクトストレージ、AWSならS3とかで管理するのが望ましいと思われる。
-> 本当はオブジェクトストレージでの管理までやってみようと思ったんですが、さくらのクラウドで今新規パケット作れないよって（障害？）書かれてたので、そこは断念。。。


# 所感
Ansibleを利用したことで、そのままTerraformを利用するより難易度があがっているような印象を受けたが
やはり、コード化されることでの管理上のメリットはあると思いました。
ただ、上記にも記載した通り、立ち上げたサーバの設定をさらにAnsibleでやろうとすると、卵が鶏がって事になりそうで落としどころがよくわかっていません。


# 参照元
[Terraform by HashiCorp](https://www.terraform.io/)
[Terraform for さくらのクラウド](https://sacloud.github.io/terraform-provider-sakuracloud/)
[terraform - Manages a Terraform deployment (and plans) — Ansible Documentation](https://docs.ansible.com/ansible/2.5/modules/terraform_module.html)
[サンプルコード](https://github.com/kitaji0306/ansible-terraform-sakuracloud.git)


# 最後に
作成したサーバの消し忘れにはご注意を。。。

それではでは。