Terraformを使ってみる
概要
役割と期待すること
TerrafomとはHashicorpが開発したソフトウェアで、役割はインフラの構築・変更を定義ファイルベースで行うことです。
構築作業を定義ファイルベースで行うことで、次のことが期待できます。
自動化 | 構築作業の自動化と複数回の実行 |
---|---|
可視化 | 構築定義・変更定義の可視化 |
版管理 | 各種定義の版管理 |
定義を作成により実行を自動化するという流れや、それによって受けられる恩恵が単体テストの自動化と似ていますね。また実行に関しても最適化されており依存性のない作業同士は並列で実行されるという非機能面での恩恵もあります。
対応する環境
2016年10月現在では次のサービスに対応しています。色々とあり過ぎておなかが減ってきますね。今回は公式サイトのGetting Startedの流れに倣ってAWS環境を利用してゆきます。
Archive | Atlas | AWS | Bitbucket | Bitbucket |
Chef | CenturyLinkCloud | CloudFlare | CloudStack | Cobbler |
Consul | Datadog | DigitalOcean | DNSMadeEasy | DNSimple |
Docker | Google Cloud | Dyn | GitHub | Fastly |
Grafana | Heroku | InfluxDB | Librato | Logentries |
Mailgun | Microsoft Azure | Microsoft Azure(Legacy ASM) | ||
MySQL | OpenStack | Packet | PostgreSQL | PowerDNS |
RabbitMQ | Random | Rundeck | StatusCake | SoftLayer |
Scaleway | Template | Terraform | TLS | Triton |
UltraDNS | VMware vCloud Director | VMware vSphere |
公式サイト
こちらが公式サイトになります。詳細情報や関連ソフトウェアの情報が掲載されていますので確認してみてください。
Terraform by HashiCorp
インストール
さて実際にインストールから実行してゆきます。公式サイトより適切なパッケージ(下記のOSに対応)をダウンロードしてください。現時点での最新版は0.7.7となります。
- Mac OS X (32-bit, 64-bit)
- FreeBSD (32-bit, 64-bit, Arm)
- Linux (32-bit, 64-bit, Arm
- OpenBSD (32-bit, 64-bit)
- Solaris (64-bit)
- Windows (32-bit, 64-bit)
ダウンロードが完了したら環境に応じた方法でPATHを通してください。(僕は面倒なので /usr/local/sbinに実行ファイルを入れました) 終わったら正常にインストール出来たかterraform -v
で確認してみましょう。
$ terraform -v Terraform v0.7.7
定義ファイルの作成
環境が出来たら定義ファイルを作成してゆきます。正式名称は Terraform Configurationとなります。
定義ファイルの形式
形式は独自の Terraform Format(*.tf)または JSON(*.tf.json) の何れかを任意で選択します。公式では人間の可視性の観点から前者の利用を推奨しています。後者はプログラム等による出力を想定して用意したものの様です。個人的にはJSONでも充分見やすいと思います。
ファイルの定義
では実際に定義ファイルを作成します。定義ファイルの内容は、対応するサービス種別(provider)と、内部資源(resource)の 2部で構成されます。なお今回はサンプルなので providerの認証情報も内部定義していますが、版管理の観点から外部ファイルに切り出すことも可能です。
provider "aws" { access_key = "(自身のAWS環境のアクセスキーを設定)" secret_key = "(自身のAWS環境のシークレットキーを設定)" region = "us-east-1" } resource "aws_instance" "example" { ami = "ami-0d729a60" instance_type = "t2.micro" }
計画
terraform plan
で実行計画を確認することができます。実環境は変更しない点で後述のterraform apply
とは異なります。
$ terraform plan 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. The Terraform execution plan has been generated and is shown below. Resources are shown in alphabetical order for quick scanning. Green resources will be created (or destroyed and then created if an existing resource exists), yellow resources are being changed in-place, and red resources will be destroyed. Cyan entries are data sources to be read. Note: You didn't specify an "-out" parameter to save this plan, so when "apply" is called, Terraform can't guarantee this is what will execute. + aws_instance.example ami: "ami-0d729a60" availability_zone: "<computed>" ebs_block_device.#: "<computed>" ephemeral_block_device.#: "<computed>" instance_state: "<computed>" instance_type: "t2.micro" key_name: "<computed>" network_interface_id: "<computed>" placement_group: "<computed>" private_dns: "<computed>" private_ip: "<computed>" public_dns: "<computed>" public_ip: "<computed>" root_block_device.#: "<computed>" security_groups.#: "<computed>" source_dest_check: "true" subnet_id: "<computed>" tenancy: "<computed>" vpc_security_group_ids.#: "<computed>" Plan: 1 to add, 0 to change, 0 to destroy.
実行
terraform apply
で実行をかけます
$ terraform apply aws_instance.example: Creating... ami: "" => "ami-0d729a60" availability_zone: "" => "<computed>" ebs_block_device.#: "" => "<computed>" ephemeral_block_device.#: "" => "<computed>" instance_state: "" => "<computed>" instance_type: "" => "t2.micro" key_name: "" => "<computed>" network_interface_id: "" => "<computed>" placement_group: "" => "<computed>" private_dns: "" => "<computed>" private_ip: "" => "<computed>" public_dns: "" => "<computed>" public_ip: "" => "<computed>" root_block_device.#: "" => "<computed>" security_groups.#: "" => "<computed>" source_dest_check: "" => "true" subnet_id: "" => "<computed>" tenancy: "" => "<computed>" vpc_security_group_ids.#: "" => "<computed>" aws_instance.example: Still creating... (10s elapsed) aws_instance.example: Still creating... (20s elapsed) aws_instance.example: Still creating... (30s elapsed) aws_instance.example: Creation complete Apply complete! Resources: 1 added, 0 changed, 0 destroyed. The state of your infrastructure has been saved to the path below. This state is required to modify and destroy your infrastructure, so keep it safe. To inspect the complete state use the `terraform show` command. State path: terraform.tfstate
実際に作成されたかをAWSの管理コンソールで確認してみます。リージョンを"バージニア北部"に設定し、サービスからEC2を選択します。
どうやら無事動いている様です。
尚 AccessKey/SecretAccessKey のオーナーとなるAWS上のIAMユーザにEC2へのアクセス権が無いと以下の様にエラーとなります。
Error applying plan: 1 error(s) occurred: * aws_instance.example: Error launching source instance: UnauthorizedOperation: You are not authorized to perform this operation. Encoded authorization failure message: DyxG53T..... status code: 403, request id: 81414ade-9598-403f-af9a-5d264bff26a3 Terraform does not automatically rollback in the face of errors. Instead, your Terraform state file has been partially updated with any resources that successfully completed. Please address the error above and apply again to incrementally change your infrastructure.
この場合、AWSのマネージメントコンソール上で サービスからIAM (Identity and Management Service)を選択し、該当ユーザに適切な権限を与えて下さい。(下の画面では暫定でEC2のフルアクセスを与えています)
結果の確認
先にAWSの管理コンソールから結果を確認しましたが、実は Terraformのコマンドからも結果の確認が可能です。
terraform show
で以下の様な表示が出ます。
aws_instance.example: id = i-xxxxxxxx ami = ami-xxxxxxxx availability_zone = us-east-1b disable_api_termination = false ebs_block_device.# = 0 ebs_optimized = false ephemeral_block_device.# = 0 iam_instance_profile = instance_state = running instance_type = t2.micro key_name = monitoring = false network_interface_id = eni-xxxxxxxx private_dns = ip-xxx-xx-xx-xxx.ec2.internal private_ip = xxx.xxx.xxx.xxx public_dns = ec2-xxx-xxx-xxx-xxx.compute-1.amazonaws.com public_ip = xxx.xxx.xxxx.xxx root_block_device.# = 1 root_block_device.0.delete_on_termination = true root_block_device.0.iops = 0 root_block_device.0.volume_size = 8 root_block_device.0.volume_type = standard security_groups.# = 0 source_dest_check = true subnet_id = subnet-xxxxxxxx tags.% = 0 tenancy = default vpc_security_group_ids.# = 1 vpc_security_group_ids.xxxxxxxxxx = sg-xxxxxxxx
尚、この情報は実行時に作成された terraform.tfstateというファイルが入力元となっています。
$ ls
example.tf terraform.tfstate terraform.tfstate.backup
Vagrantを触ってみる
Vagrantと言えば Mitchell Hashimotoさんが開発した仮想マシン環境構築ソフトです。Mitchell Hashimoto さんと言えば HashiCorpの設立者で、Packer, Serf, Consul等、色々な素晴らしいソフトを作っていますよね。
さて、その第一弾となった Vagrantですが、今まであまり使う機会が無かったので触れておきたいなと思いました。今更感は半端ないですが、それ考えると先進まないので思考停止して行ってみよー!
公式サイト
何を始めるにしても公式サイトを見るのが楽だよね。
というわけで、この記事でも公式サイトの流れを追う感じで書いていこうと思います。
www.vagrantup.com
手順
1. Vagrantのインストール (公式サイト参照)
環境に応じたインストール手順でインストールしてね
僕は homebrewを使った様な気がする (覚えてない)
www.vagrantup.com
2. Vagrantファイルの作成
vagrant init でVagrantファイルのテンプレートを作成してくれます
$ vagrant init hashicorp/precise64 A `Vagrantfile` has been placed in this directory. You are now ready to `vagrant up` your first virtual environment! Please read the comments in the Vagrantfile as well as documentation on `vagrantup.com` for more information on using Vagrant.
終わると Vagrantファイルが作成されているのが分かります
$ ls
Vagrantfile
中身はこんな感じです
$ less Vagrantfile # -*- mode: ruby -*- # vi: set ft=ruby : # All Vagrant configuration is done below. The "2" in Vagrant.configure # configures the configuration version (we support older styles for # backwards compatibility). Please don't change it unless you know what # you're doing. Vagrant.configure("2") do |config| # The most common configuration options are documented and commented below. # For a complete reference, please see the online documentation at # https://docs.vagrantup.com. # Every Vagrant development environment requires a box. You can search for # boxes at https://atlas.hashicorp.com/search. config.vm.box = "hashicorp/precise64" # Disable automatic box update checking. If you disable this, then # boxes will only be checked for updates when the user runs # `vagrant box outdated`. This is not recommended. # config.vm.box_check_update = false # Create a forwarded port mapping which allows access to a specific port # within the machine from a port on the host machine. In the example below, # accessing "localhost:8080" will access port 80 on the guest machine. # config.vm.network "forwarded_port", guest: 80, host: 8080 # Create a private network, which allows host-only access to the machine # using a specific IP. # config.vm.network "private_network", ip: "192.168.33.10" # Create a public network, which generally matched to bridged network. # Bridged networks make the machine appear as another physical device on # your network. # config.vm.network "public_network" # Share an additional folder to the guest VM. The first argument is # the path on the host to the actual folder. The second argument is # the path on the guest to mount the folder. And the optional third # argument is a set of non-required options. # config.vm.synced_folder "../data", "/vagrant_data" # Provider-specific configuration so you can fine-tune various # backing providers for Vagrant. These expose provider-specific options. # Example for VirtualBox: # # config.vm.provider "virtualbox" do |vb| # # Display the VirtualBox GUI when booting the machine # vb.gui = true # # # Customize the amount of memory on the VM: # vb.memory = "1024" # end # # View the documentation for the provider you are using for more # information on available options. # Define a Vagrant Push strategy for pushing to Atlas. Other push strategies # such as FTP and Heroku are also available. See the documentation at # https://docs.vagrantup.com/v2/push/atlas.html for more information. # config.push.define "atlas" do |push| # push.app = "YOUR_ATLAS_USERNAME/YOUR_APPLICATION_NAME" # end # Enable provisioning with a shell script. Additional provisioners such as # Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the # documentation for more information about their specific syntax and use. # config.vm.provision "shell", inline: <<-SHELL # apt-get update # apt-get install -y apache2 # SHELL end
3. 仮想マシンプロバイダ上にマシンの配置
vagrant upにて実施
ログを見ると色々やっているのが分かりますね
$ vagrant up ==> default: Importing base box 'hashicorp/precise64'... ==> default: Matching MAC address for NAT networking... ==> default: Checking if box 'hashicorp/precise64' is up to date... ==> default: Setting the name of the VM: new_default_1476494705030_32930 ==> default: Clearing any previously set network interfaces... ==> default: Preparing network interfaces based on configuration... default: Adapter 1: nat ==> default: Forwarding ports... default: 22 (guest) => 2222 (host) (adapter 1) ==> default: Booting VM... ==> default: Waiting for machine to boot. This may take a few minutes... default: SSH address: 127.0.0.1:2222 default: SSH username: vagrant default: SSH auth method: private key default: Warning: Remote connection disconnect. Retrying... default: default: Vagrant insecure key detected. Vagrant will automatically replace default: this with a newly generated keypair for better security. default: default: Inserting generated public key within guest... default: Removing insecure key from the guest if it's present... default: Key inserted! Disconnecting and reconnecting using new SSH key... ==> default: Machine booted and ready! ==> default: Checking for guest additions in VM... default: The guest additions on this VM do not match the installed version of default: VirtualBox! In most cases this is fine, but in rare cases it can default: prevent things such as shared folders from working properly. If you see default: shared folder errors, please make sure the guest additions within the default: virtual machine match the version of VirtualBox you have installed on default: your host and reload your VM. default: default: Guest Additions Version: 4.2.0 default: VirtualBox Version: 5.0 ==> default: Mounting shared folders... default: /vagrant => /Users/xxxx/work/study/vagrant/new
4. ログイン
vagrant sshで完成した仮想マシンにログインできます
$ vagrant ssh Welcome to Ubuntu 12.04 LTS (GNU/Linux 3.2.0-23-generic x86_64) * Documentation: https://help.ubuntu.com/ New release '14.04.5 LTS' available. Run 'do-release-upgrade' to upgrade to it. Welcome to your Vagrant-built virtual machine. Last login: Fri Sep 14 06:23:18 2012 from 10.0.2.2 vagrant@precise64:~$ ls postinstall.sh vagrant@precise64:~$ pwd /home/vagrant vagrant@precise64:~$ exit logout
5. SSHクライアントからログイン
sshコマンドや putty/Teratermの様なクライアントからのログインも可能です
先ずはvagrant ssh-configで接続設定を確認します
$ vagrant ssh-config
Host default
HostName 127.0.0.1
User vagrant
Port 2222
UserKnownHostsFile /dev/null
StrictHostKeyChecking no
PasswordAuthentication no
IdentityFile
/Users/xxx/work/study/vagrant/new/.vagrant/machines/default/virtualbox/private_key
IdentitiesOnly yes
LogLevel FATAL
続けて確認した設定に基づいて Host, Port, ユーザ, 秘密鍵を指定すればログインできます
ホスト | 127.0.0.1 |
---|---|
ポート | 2222 |
ユーザ | vagrant |
秘密鍵 | ~/work/study/vagrant/new/.vagrant/machines/default/virtualbox/private_key |
$ ssh vagrant@127.0.0.1 -p 2222 \ -i ~/work/study/vagrant/new/.vagrant/machines/default/virtualbox/private_key The authenticity of host '[127.0.0.1]:2222 ([127.0.0.1]:2222)' can't be established. ECDSA key fingerprint is SHA256:+zgKqxyYlTBAs0xtTVGxxxxxS9Zr71wQGvnG/k2igw. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '[127.0.0.1]:2222' (ECDSA) to the list of known hosts. Welcome to Ubuntu 12.04 LTS (GNU/Linux 3.2.0-23-generic x86_64) * Documentation: https://help.ubuntu.com/ New release '14.04.5 LTS' available. Run 'do-release-upgrade' to upgrade to it. Welcome to your Vagrant-built virtual machine. Last login: Sat Oct 15 02:12:55 2016 from 10.0.2.2