はじめに
仕事でTerafformを使うことになったので、Terraformの基本的な操作方法を習得します。
Terraformのblog投稿、参考訳 - Qiita
http://qiita.com/zembutsu/items/402e02950ce9d59fa0e6
Terraform入門 日本語訳 - Qiita
http://qiita.com/zembutsu/items/84f5478701c5391df537
環境
- Windows7
- VirtualBox V5.1.26
- Terraform v0.10.5
- docker 17.06.2-ce
1. ダウンロードと導入
MacOS版(AMD64)、Linux版(i386, AMD64)、Windows版(i386)等のバイナリが、ダウンロードページから配付されています。Linux版があるということはDockerでも提供されているのかなと思い、DockerHubを確認。ありましたので、こちらを使います。
仮想化層という余計なモジュールは必要なく、WindowsやLinuxにterraformを導入すれば良いのですが、Docker Swarm、Kubernetes等により以下が実現できるのでDocker版を選択します。もう少し平たくお伝えすると、どんなSWであれ、特に理由がなければ、Docker版を個人的に選択しています。
①コスト効率の向上
- 必要な時に、必要な分だけ、自動でサーバーを追加・削除する
- リソースが不要な期間はリソースを利用しないことにより、コスト効率が向上する
②可用性の向上 - 複数のAvailability Zone(=AZ)でAuto Scalingを設定し、1つのAZが利用できなくなっても別AZで新しいインスタンスを起動する
③耐障害性の向上 - サーバー異常時を検出し、サーバーを終了し、新しいサーバーを起動する
デスクトップにあるアイコンをダブルクリックし、Docker Quick Start Terminalを起動します。こちらに従って、docker pullコマンドを実行します。
$ docker pull hashicorp/terraform:light
$ docker pull hashicorp/terraform:full
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hashicorp/terraform full 57305292ab71 3 days ago 647.9 MB
hashicorp/terraform latest e84f3c7e4c2e 3 days ago 96.65 MB
$ docker run -it hashicorp/terraform:latest version
Terraform v0.10.5
$ docker run -it hashicorp/terraform:full version
Terraform v0.10.5
2. エディション選定
lightバージョン(=tagはlatest)とfullバージョンがありますが、コンテナーにログインしたいためfullバージョンを使います。647.9MBと96.65MBで、かなりの差があります。
Dockerfileを確認したところ、ENTRYPOINT ["terraform"]が設定されていました。lightバージョンで、ENTRYPOINTを/bin/bashで上書きしてコンテナーを起動してみたのですが、no such file or directoryになりました。lightバージョンはterraformコマンドの実行だけに特化されているコンテナーのようです。
FROM golang:alpine
MAINTAINER "HashiCorp Terraform Team <terraform@hashicorp.com>"
ENV TERRAFORM_VERSION=0.10.0
RUN apk add --update git bash openssh
ENV TF_DEV=true
ENV TF_RELEASE=true
WORKDIR $GOPATH/src/github.com/hashicorp/terraform
RUN git clone https://github.com/hashicorp/terraform.git ./ && \
git checkout v${TERRAFORM_VERSION} && \
/bin/bash scripts/build.sh
WORKDIR $GOPATH
ENTRYPOINT ["terraform"]
$ docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
default * virtualbox Running tcp://192.168.99.100:2376 v17.06.2-ce
$ docker-machine ssh default
docker@default:~$ sudo -s
root@default:/home/docker# docker run -it --entrypoint /bin/bash hashicorp/terraform:latest
docker: Error response from daemon: oci runtime error: container_linux.go:262: starting container process caused "exec: \"/bin/bash\": stat /bin/bash: no such file or directory".
3. 事前準備
Terraform社のホームページに従って設定ファイル(=test01.tf)を作成し、仮想マシン(=HostOS/名前:default)上の/test01に保管します。
root@default:~# mkdir /test01
root@default:~# cat /test01/test01.tf
provider "docker" {
host = "tcp://192.168.99.100:2376/"
}
resource "docker_container" "hoge" {
image = "${docker_image.centos.latest}"
name = "hoge"
hostname = "hoge"
command = ["/bin/sh", "-c", "while true ; do sleep 1; hostname -s ; done"]
}
resource "docker_image" "centos" {
name = "centos:latest"
}
Unix環境の場合、host = "unix:///var/run/docker.sock"のようにunixドメインソケットを設定できます。今回、Terraformが稼働するコンテナー(=GuestOS)から仮想マシン(=HostOS/名前:default)上にunixドメインソケットを設定するので、下記でも対応できそうなのですが、tcp://xxxにしました。。
docker のコンテナ内から ホストの docker を操作する - Qiita
その他、こちらの注意事項に対応するために、鍵関連のファイル(=C:\Users\shimizu.docker\machine\machines\default)を仮想マシン(=HostOS/名前:default)上の/test01に保管します。ここ、曲者です。
docker-machine environment, the Docker daemon uses an encrypted TCP socket (TLS) and requires cert_path for a successful connection. As an alternative, if using docker-machine, run eval $(docker-machine env ) prior to running Terraform, and the host and certificate path will be extracted from the environment.
考慮しないと、malformed HTTP response "\x15\x03\x01\x00\x02\x02"のメッセージが出力されます。
$ docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
default * virtualbox Running tcp://192.168.99.100:2376 v17.06.2-ce
$ docker-machine env default
export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://192.168.99.100:2376"
export DOCKER_CERT_PATH="C:\Users\shimizu\.docker\machine\machines\default"
export DOCKER_MACHINE_NAME="default"
# Run this command to configure your shell:
# eval $("C:\Program Files\Docker Toolbox\docker-machine.exe" env default)
root@default:/test01# ls -la /test01
total 36
drwxr-xr-x 3 root root 240 Sep 18 15:34 .
drwxr-xr-x 18 tc staff 440 Sep 18 14:32 ..
-rw-r--r-- 1 root root 1039 Sep 18 14:45 ca.pem
-rw-r--r-- 1 root root 1079 Sep 18 14:45 cert.pem
-rw-r--r-- 1 root root 1676 Sep 18 14:45 key.pem
-rw-r--r-- 1 root root 1680 Sep 18 14:46 server-key.pem
-rw-r--r-- 1 root root 1112 Sep 18 14:46 server.pem
-rw-r--r-- 1 root root 330 Sep 18 14:34 test01.tf
これらのファイルを仮想マシン(=HostOS/名前:default)上の/test01に保管するのは、Terraformが稼働するコンテナー(=GuestOS)からデータを読めるようにするためです。もっとスマートなやり方があるかと思いますが、理屈を理解するのが目的ですので、これで良しとしました。
4. 基本操作
docker runコマンドを実行し、Terraformが導入されているコンテナーを起動します。HostOS:/test01を、GuestOS:/mnt/test01にマウントしています。ENTRYPOINTを/bin/bashに上書きし、コンテナーにログインします。
- コンテナーの起動
$ docker run -v /test01:/mnt/test01 -it --entrypoint /bin/bash hashicorp/terraform:full
- 環境変数の設定
bash-4.3# export DOCKER_TLS_VERIFY="1"
bash-4.3# export DOCKER_HOST="tcp://192.168.99.100:2376"
bash-4.3# export DOCKER_CERT_PATH="/mnt/test01"
bash-4.3# export DOCKER_MACHINE_NAME="default"
- 初期化:terraform init
bash-4.3# terraform init /mnt/test01
Initializing provider plugins...
- Checking for available provider plugins on https://releases.hashicorp.com...
- Downloading plugin for provider "docker" (0.1.0)...
(省略)
- 計画:terraform plan
bash-4.3# terraform plan /mnt/test01/
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be persisted to local or remote state storage.
(省略)
- 実行:terraform apply
bash-4.3# terraform apply /mnt/test01
docker_image.centos: Creating...
latest: "" => "<computed>"
name: "" => "centos:latest"
- 確認:terraform state
bash-4.3# terraform state list
docker_image.centos
bash-4.3# terraform state show
id = sha256:196e0ce0c9fbb31da595b893dd39bc9fd4aa78a474bbdc21459a3ebe855b7768centos:latest
latest = sha256:196e0ce0c9fbb31da595b893dd39bc9fd4aa78a474bbdc21459a3ebe855b7768
name = centos:latest
- 確認:docker ps
root@default:/test01# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
58a7abd9022a hashicorp/terraform:full "/bin/bash" 24 minutes ago Up 24 minutes priceless_shaw
8ea9cb51ff36 196e0ce0c9fb "/bin/sh -c 'while..." 2 hours ago Up 2 hours hoge
- 計画(破棄):terraform plan -destroy
bash-4.3# terraform plan -destroy
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.
docker_image.centos: Refreshing state... (ID: sha256:196e0ce0c9fbb31da595b893dd39bc9f...474bbdc21459a3ebe855b7768centos:latest)
- コンテナー停止: docker stop / docker rm
root@default:/test01# docker stop 8ea9cb51ff36
root@default:/test01# docker rm 8ea9cb51ff36
- 破棄:terraform destroy
bash-4.3# terraform destroy
docker_image.centos: Refreshing state... (ID: sha256:196e0ce0c9fbb31da595b893dd39bc9f...474bbdc21459a3ebe855b7768centos:latest)
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
- destroy
Terraform will perform the following actions:
(省略)
5. ログの出力
ログ(詳細)を出力する場合は、export TF_LOG=1を実行します。出力したくない場合は、export TF_LOG=''を実行します。その他、ログファイルに書き込むこともできました。
https://www.terraform.io/docs/configuration/environment-variables.html
bash-4.3# export TF_LOG=1
bash-4.3# export TF_LOG_PATH='./terraform.log'
bash-4.3# terraform version
2017/09/18 17:30:54 [WARN] Invalid log level: "1". Defaulting to level: TRACE. Valid levels are: [TRACE DEBUG INFO WARN ERROR]
Terraform v0.10.5
まとめ
Terraform@Docker版の選択したら、マウント(run -v)、環境変数(DOCKER_CERT_PATH)、ENTRYPOINT(/bin/bash)等を使う必要があり、Dockerを復習できてしまいました。そして、少し苦労しました...
Terraformに関しては、マルチクラウド環境ではないので、今回の検証だけでは価値を享受できなかったです。しかし、一応、理解しているつもりです。サーバーセットアップ部分もコード化でき、GithubやJenkinsと連携することで、インフラCI環境を実現できるのが本当の価値であることを...
またTerraformのResouceとして、docker_container、docker_image、docker_network、docker_volumeが提供されているので、docker_network、docker_volumeを試してみます。昔は、docker_containerとdocker_imageだけだったのかな...
その他、Terraform経由でプロビジョニングした仮想マシンの起動/停止はできないのかな。terraformコマンドにはstart/stopがなく、destroy(=停止ではなく破棄)しかありませんでした。