はじめに
Terraformを使ってローカル環境でVMをデプロイしてみたのでその記録を残します。利用したバージョンは下記になります。Ubuntu 20.04LTSでの記録になります。
$ terraform version
Terraform v0.14.5
+ provider registry.terraform.io/dmacvicar/libvirt v0.6.3
Terraform?
公式ページ https://www.terraform.io/
Infrastructure as Code (IaC) のツールという紹介がよくされていると思います。Codeつまりテキストファイルに書かれたロジックに基づいてインフラを構築するCLIツールです。インフラと言っても当然物理をどうこうできるわけがありませんので、基本的にはクラウド上でのインフラ構築と考えればいいと思います。ローカル環境でKVMやdockerを使った構成を構築することもできます。
Terraformのインストール
ダウンロードページから、下記のプラットフォーム向けのTerraformを入手できます。
- macOS
- FreeBSD
- Linux
- OpenBSD
- Solaris
- Windows
クラウド環境から実行できる環境Terraform Cloudもあるようです。
Ubuntuであればsudo apt-get install terraform
でインストールすることもできます。他もおそらくパッケージシステムでインストールできると思います。
どんなふうに記述して何を構築するのか
https://learn.hashicorp.com/terraform
ここを読んでおいてください、だと投げやりすぎるのですが、読んでいただけるのならそのほうが以下のしょぼくれた説明よりしっかりしているので、安心できるかと思います。
というわけで雰囲気を味わいたい人向けに、どんなふうに書いたら何が構築できるのか、その一例を紹介します。
ディレクトリを用意する
Terraformの構築対象はディレクトリで管理されます。ここでは試しにtf-test
というディレクトリを用意してみます。Codeをこのディレクトリに置くことになります。
mkdir tf-test
cd tf-test
*.tf ファイルを用意する
Terraformが読んで実行するコードはsuffixを.tfとします。.tfの中身つまり記述言語は、Hashicorp Configuration Language (HCL) というそうです。
下記はオフィシャルのチュートリアルムービーから拝借しました。AWSのEC2インスタンスを構築する例になります。ここではmain.tf
としておきます。suffixをみてファイルを見つけるので、main
である必要は特にありません。
provider "aws" {
access_key = "ACCESS_KEY"
secret_key = "SECRET_KEY"
region = "us-east-1"
}
resource "aws_instance" "example" {
ami = "ami-2757f631"
instance-type = "t2.micro"
}
見て解ると思いますが、これはこのままでは実際に動かすことはできませんので、眺めるだけにとどめておいてください。
Terraformを動かしてみる
まず最初に一回だけ、初期化が必要です。
terraform init
tfファイルの内容が正しいかをチェックできます。(してもしなくても、間違っていれば実行時にエラーが出ます)
terraform validate
なにをどんなふうに変更することになるのかの確認もできます。
terraform plan
実行すると、上記例であればAWS EC2インスタンスが作成されます。
terraform apply
インスタンスを削除することもできます。
terraform destroy
さまざまなprovider
例示したtfファイルにも書きましたが、Terraformではprovider
を指定して、そのprovider
のリソースとしてどういうものを用意するのかを記述していきます。例で提示した"aws"
の他にも様々なprovider
が用意されています。
"aws"
"azurerm"
"google"
"kubernetes"
- ...
数が多くて紹介しきれませんので、https://registry.terraform.io/browse/providers こちらで検索してみてください。
providerは、下記に分類されます。
- HashiCorpのTerraform registryから提供されていて自動的にダウンロードして利用できるもの
- official, verified, communityの3種に分かれます
- Terraform registryにないもの
Terraform registryで提供されているものは、provider "それ"
と書けば利用できます。ローカルになければ自動でダウンロードされます。提供されていないものは手動でダウンロードするなどの作業が必要になります。
terraform-provider-libvirt
terraform-provider-libvirtは、名前から想像できますが、libvirt
を使ってVM環境を構築するTerraform providerです。Terraform registryでは提供されていませんので、自動ダウンロードや自動インストールは失敗します。そのため、インストールと利用には少し手間がかかります。
terraform-provider-libvirtのインストール
さまざまなインストール方法がありますので、公式ページのREADME.mdを読んで、好きな方法でインストールしてください。
たとえばstable packageをUbuntuにインストールする場合は、README.mdからリンクを手繰ってこの手順に従います。
インストール後、もうひと手間必要です。
https://github.com/dmacvicar/terraform-provider-libvirt/blob/master/docs/migration-13.md
こちらのドキュメントのとおりに、ファイルを移動させてください。Terraform 0.13以降のバージョンでは、これをやっておかないとprovider "libvirt"
が使えません。
provider "libvirt" でVMを構築する
用意しておくもの
ディスクイメージ
構築するVM用のディスクイメージが必要です。構築時に(virt-install
によって)複製されます。なんでもいいのですが、ここではたまたま手元にあったdebian10-gns3.qcow2
を使うことにします。(ここから拾えます)
$ ls -lh
total 2.6G
-rw-rw-r-- 1 masaru masaru 2.6G Nov 11 16:07 debian10-gns3.qcow2
libvirt, qemu
当然ですがlibvirt
やqemu
をインストールしておく必要があります。操作しているアカウントをlibvirt
グループに追加するのもお忘れなく。
/etc/libvirt/qemu.conf
の編集
security_driver = "none"
にしておかないと、VMの起動に失敗します。編集しておいてください。編集後は sudo systemd restart libvirt-bin
を実行してください。グループ周りの反映もあるので一度リブートするのでもいいかと思います。
tfファイルの編集
ディレクトリを作って、.tfファイルを編集します。(viである必要はもちろんありません)
mkdir libvirt-test
cd libvirt-test
vi main.cf
いきなりprovider
と書き始めたいところですが、.tfファイルの先頭におまじないが必要です。
terraform {
required_version = ">= 0.13"
required_providers {
libvirt = {
version = ">= 0.6.2"
source = "dmacvicar/libvirt"
}
}
}
この記述によって、先ほど場所を移動したterraform-provider-libvirt
を見つけることができます。これがない場合、Terraform registryに探しに行ってしまい、hashicorp/libvirt
がないんじゃが? と言われエラーになってしまいます。
では続けていよいよprovider
以降をつらつら書きます。
provider "libvirt" {
uri = "qemu:///system"
}
resource "libvirt_volume" "os-image" {
name = "testvm-disk.qcow2"
source = "debian10-gns3.qcow2"
format = "qcow2"
}
resource "libvirt_domain" "domain-testvm" {
name = "debian"
memory = 2048
vcpu = 1
disk { volume_id = libvirt_volume.os-image.id }
network_interface {
network_name = "default"
}
console {
type = "pty"
target_port = "0"
}
graphics {
type = "spice"
listen_type = "address"
autoport = "true"
}
}
ざっくり解説すると
-
pervider "libvirt"
でlibvirt providerの利用を宣言 (以降でlibvirt_
ごにょごにょというリソースが使えるようになる) -
resource "libvirt_volume" "os-image"
でボリューム(ストレージ)を定義。 -
resource "libvirt_domain" "domain-testvm"
でドメイン(VMインスタンス)を定義。
最後に、このディレクトリにdebian10-gns3.qcow2
を置けば準備完了です。
いよいよ実行
terraform init
terraform validate
terraform apply
terraform apply
を実行すると、実行するか問い合わせがありますので yes
と答えます。
実行ログ (たまたまですが裏で別の重いタスクを動かしてる関係で時間がかかっています)
$ terraform init
Initializing the backend...
Initializing provider plugins...
- Reusing previous version of dmacvicar/libvirt from the dependency lock file
- Installing dmacvicar/libvirt v0.6.3...
- Installed dmacvicar/libvirt v0.6.3 (unauthenticated)
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
$ terraform validate
Success! The configuration is valid.
$ terraform apply
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# libvirt_domain.domain-testvm will be created
+ resource "libvirt_domain" "domain-testvm" {
+ arch = (known after apply)
+ disk = [
+ {
+ block_device = null
+ file = null
+ scsi = null
+ url = null
+ volume_id = (known after apply)
+ wwn = null
},
]
+ emulator = (known after apply)
+ fw_cfg_name = "opt/com.coreos/config"
+ id = (known after apply)
+ machine = (known after apply)
+ memory = 2048
+ name = "debian"
+ qemu_agent = false
+ running = true
+ vcpu = 1
+ console {
+ source_host = "127.0.0.1"
+ source_service = "0"
+ target_port = "0"
+ type = "pty"
}
+ graphics {
+ autoport = true
+ listen_address = "127.0.0.1"
+ listen_type = "address"
+ type = "spice"
}
+ network_interface {
+ addresses = (known after apply)
+ hostname = (known after apply)
+ mac = (known after apply)
+ network_id = (known after apply)
+ network_name = "default"
}
}
# libvirt_volume.os-image will be created
+ resource "libvirt_volume" "os-image" {
+ format = "qcow2"
+ id = (known after apply)
+ name = "testvm-disk.qcow2"
+ pool = "default"
+ size = (known after apply)
+ source = "debian10-gns3.qcow2"
}
Plan: 2 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
libvirt_volume.os-image: Creating...
libvirt_volume.os-image: Still creating... [10s elapsed]
libvirt_volume.os-image: Still creating... [20s elapsed]
libvirt_volume.os-image: Still creating... [30s elapsed]
libvirt_volume.os-image: Still creating... [40s elapsed]
libvirt_volume.os-image: Still creating... [50s elapsed]
libvirt_volume.os-image: Still creating... [1m0s elapsed]
libvirt_volume.os-image: Still creating... [1m10s elapsed]
libvirt_volume.os-image: Still creating... [1m20s elapsed]
libvirt_volume.os-image: Still creating... [1m30s elapsed]
libvirt_volume.os-image: Still creating... [1m40s elapsed]
libvirt_volume.os-image: Still creating... [1m50s elapsed]
libvirt_volume.os-image: Still creating... [2m0s elapsed]
libvirt_volume.os-image: Still creating... [2m10s elapsed]
libvirt_volume.os-image: Creation complete after 2m18s [id=/var/lib/libvirt/images/testvm-disk.qcow2]
libvirt_domain.domain-testvm: Creating...
libvirt_domain.domain-testvm: Still creating... [10s elapsed]
libvirt_domain.domain-testvm: Creation complete after 15s [id=33e01c13-97a9-4ec0-ae7a-51853096ad94]
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
masaru@tama:~/src/libvirt-test$
terraform apply
を実行した後、実際にVMが起動しているか確認してみます。
$ virsh list
Id Name State
------------------------
37 debian running
$
virt-viewer
でコンソール画面と接続することができます。今回使ったイメージではbannerに表示がありますがroot/debian
あるいはdebian/debian
でログインできます。
削除
terraform destroy
で構築した環境がまるっと削除されます。ディスクイメージも削除されますので、VMにログインしていろいろファイルを変更などしていてもすべてが無に帰します。ご注意ください。
エラーで困ったら
/var/lib/libvirt/qemu.conf
の編集を忘れていると、terraform apply
の実行で最後の最後にPermission denied
と言われてコケます。/var/lib/libvirt/images
にアクセスできないのでこれかな? と思う方もいらっしゃるかわかりませんが、そこはそのままでOKです。virsh pool-edit default
とかやればオーナーグループパーミッションどれも変更できますが、それでは解決しません。上で書いたとおり、qemu.conf
を編集してください。
この状態でterraform destroy
を実行しても半端にlibvirt domainが残っているので、次のterraform apply
が失敗します。terraform destroy
の後にdomainを削除することでこの問題を回避できます。
virsh undefine debian
さいごに
Terraformにはmodule
という概念があって便利なのですが、これについては別途解説したいと思います。terraform-provider-libvirt
のネットワーク周りについても解説できればと思います。