GitHub Actions と Terraform で Nutanix の管理を楽にしてみた

2023年08月02日 水曜日


【この記事を書いた人】
坂口 和也

システムクラウド本部所属。IaaSサービスの画面を作ったりOSイメージをメンテナンスしたりしています。ゲレンデかサウナにいます。

「GitHub Actions と Terraform で Nutanix の管理を楽にしてみた」のイメージ

概要

私の部署には Nutanix で構築された検証環境が存在しているものの、利用者が少なく長らく宝の持ち腐れ状態が続いていました。
もしかして Nutanix を使って VM を作成するまでのハードルが高いのかな、と感じたので、今回は Nutanix を簡単に利用できる仕組みを作って利用促進にテコ入れをし、手軽に自分用検証 VM などを立ち上げられるようにしてみました。

今回はその手段として Terraform とその backend として Consul を採用し、 GitHub Actions と連携させることにより、新規参入者でも気軽に VM を作成できるような環境を作ったため、それらの技術とシステムの解説をしていきます。

特に今回、IaC ツールとして Terraform を採用した結果非常に便利だったため、これにフォーカスしてお話しします。

関連技術

Terraform

Hashicorp 製 IaC ツールで、構成をコードとして管理することができます。
今回は Nutanix 上に VM を起動する部分を、Terraform に任せることにしました。

基本

Terraform では基本となるファイル( *.tf ファイル)を記述し、terraform コマンドによってこれらのファイルを読み込んでインフラを構築します。

コマンド

terraform の代表的な(かつ、今回利用している)コマンドは、以下のようなものがあります。

  • terraform init
    • 作業フォルダの初期化を行うコマンド
    • 関連するプラグインのダウンロード等を含む処理を実行する
  • terraform fmt
    • lint が走り、関連ファイルを自動的に修正する
    • -check オプションで、修正対象ファイル名のみリストアップされる
  • terraform validate
    • 関連ファイルの構文チェックを行う
  • terraform plan
    • dry-run
    • 実行した結果、どのような変更が行われるかを表示する
  • terraform apply
    • 実際に定義通りの構成になるよう変更を行う

.tf ファイル

terraform の各コマンドは、カレントディレクトリの .tf ファイルを自動で読み込んで解釈します。
ファイル内に記述できる代表的なブロックとして、以下のようなものがあります。

  • provider ブロック
    • 各種プラットフォームの API を抽象化し、Terraform 流の書き方ができるように落とし込んだものを provider と呼ぶ
    • このブロックでは、どの provider を利用するか、また provider に与える credential はどのようなものかなどの設定を記述する
  • terraform ブロック
    • terraform 自体の設定を行う
    • 利用する provider を書いておき、これがインストールされていない場合はストア等からプラグインとしてダウンロードする
    • また、後述の backend に何を利用するかの設定もここで記述する
  • resource ブロック
    • プラットフォーム上に作成するリソースに関する定義を行う
    • provider が提供する resource を記述することで、宣言通りにインフラが構築される
  • varidate ブロック
    • 環境変数や実行時に与える変数、また実行時に入力するような変数など、外部から入力される変数の定義
  • local ブロック
    • 同一モジュール内で利用できる変数の定義
  • output ブロック
    • 指定した値を出力する

.tfstate ファイル

Terraform は現在管理しているインフラの情報を、デフォルトで .tfstate というファイルに保存します。
terraform plan で実行する際に表示される「現在の状態との差分」は、この .tfstate ファイルを参照しています。

しかし、Terraform による構成管理を行う上で、関連ファイルを Git 等で管理し複数人で開発する場合、この挙動は少々厄介です。
何故なら、各々が自由に terraform apply を実行した結果、各自が内容の異なる .tfstate ファイルを手元に所有すると、terraform plan の結果が全く信用できなくなります。

そのような時のための仕組みが Terraform には用意されており、tfstate 自体をリモートで管理することができます。
そしてその tfstate の管理先を backend と呼びます。

backend

Terraform で利用できる backend は、ファイルのほかに S3 や Consul, postgres など様々なものがあります。
また、backend がリモートの場合は排他ロックを行うことで、同時に terraform apply が走らないようにできるものもあります。

今回は backend として、同じ Hashicorp 製 K/V ストアの Consul を採用しました。

Consul

以前もご紹介した Hashicorp 製 K/V ストアの Consul ですが、Terraform も Hashicorp 製と言うことで、デフォルトで Consul を backend に指定することができます。

我らの時代のコンテナデプロイ – Nomad, Consul, Vault

また、Consul を backend とした際には、上述の排他ロックもデフォルトで設定されているため非常に便利です。

Consul Server が環境内にすでに存在していたので、今回はこれを backend として採用してみます。

GitHub Actions

別の方が記事にしていますが、IIJ 社内には GitHub Enterprise がオンプレで構築されています。

GitHub Actionsと仲良くなったよ

今回はこの GitHub Enterprise で GitHub Actions という CI/CD サービスを利用し、Terraform を使ってみようと思います。

構成

今回のシステムの構成はこのようになっています。

  • Terraform のファイル群は GitHub Enterprise にて管理する
    • Repository の secrets には、Nutanix の Credential や endpoint を設定してある
  • 検証環境で、このシステムを動かすための管理 VM を起動している
    • GitHub Actions の Self-Hosted Runner が起動、上記 Repository に登録してある
    • 同じ VM 内に Consul Client が起動しており、既に存在する Consul Server に join している
    • この VM で実行する terraform は足元の consul client を backend としている

使い方

  1. GitHub Repository で servers.auto.tfvars を修正し、Pull Request を作成
    • ファイルは以下のような内容であり、servers に記載した内容通りに VM が立ち上がる
      • servers = [
          {
            name = "test1"
          }
        ]
         
        templates = {
          rocky8 = "5cd084dc-402b-4dad-9043-4f1dc0e1405b"
        }
    • servers に指定できる情報は、別途 vars.tf ファイルを参照することで、default 値や optional な項目かどうかがわかる
      • variable "servers" {
          type = list(object({
            name      = string
            mem       = optional(number, 1024)
            disk      = optional(number, 40960)
            addr      = optional(string, null)
            template  = optional(string, null)
            user_data = optional(string, null)
          }))
          description = "Information of virtual machine"
        }
    • 現状、VM 名以外は任意
    • templates はクローン元となる VM を指定する
      • human readable にするためにテンプレート名と VM の UUID をマッピングしているだけのもの
      • 一旦 Rocky Linux8 のテンプレートを作成しておいた
  2. Pull Request で上述の commit のテストが通っていることを確認
    • GitHub Actions において、commit された時点で terraform fmt -check と terraform validate, および terraform plan を実行している
    • 内容に誤りがあればログから確認できるし、誤りが無くても plan の内容でどのような変更が行われるか確認ができる
  3. Pull Request を merge する
    • merge をトリガとして terraform apply が実行され、実際に VM が起動する
    • 後述の GitHub Pages の更新も同時に行われる
  4. GitHub Pages を確認する
    • DHCP でアドレスが付与された場合などのため、一覧ページを用意した
    • Nutanix のコントロールパネル上で参照しても良いが、ここでも確認できる

GitHub Pages

管理している Repository に GitHub Pages の設定をしておきました。
terraform が output する json を読み込んで表示するだけの簡単なサイトを作り、terraform apply が成功した場合に json ファイルを更新するようにしています。

感想

Terraform の利用は初めてでしたが、とても使い勝手が良いと感じました。

特にv1.3.0から、optional  な変数に対して default な値が設定できるようになっている所が素晴らしいです。
これにより、利用者は最低限の指定で VM が起動できるようになりました。何もわからない人はとりあえず触ってみて良いし、わかる人は自分なりの指定ができる、目論見通りのシステムができました。

同じ Hashicorp 製品ということで Consul との連携も非常に簡単、意識せずとも実行の排他ロックができるのが素敵です。

GitHub Actions と連携させることで、各自が手元にツールを持たずとも Pull Request ベースで証跡を残しながら VM を作成/削除/管理できる点も満足しています。

一方で、Terraform を付け焼き刃の知識で利用するのはやはりやや難しく、体系的な学習が必要だなと感じました。
Nutanix 自体を利用する学習コストは大幅に削減されたものの、このシステムを運用していくコストが発生し、卵が先か鶏が先か……という思いです。

皆さんも Terraform を使ってみてはいかがでしょうか。

坂口 和也

2023年08月02日 水曜日

システムクラウド本部所属。IaaSサービスの画面を作ったりOSイメージをメンテナンスしたりしています。ゲレンデかサウナにいます。

Related
関連記事