Cloud Penguins

Flying penguins in the cloud.

vSphere環境が崩壊したのでTerraform活用して一から構築した

今日はTUNA-JP Advent Calendarの24日目

9月からHashiCorpに転職したわたくし。仕事でTanzuプロダクトを触ることはあまりなくなってしまったが、HashiCorpプロダクトを活用してTanzu環境を便利にしていく連携も可能なので、TerraformやVault、Consulを組み合わせて色々やる記事を書くつもりだったのだが・・・

vSphere環境が崩壊した!

我が家のラボ環境は3台のESXiでvSAN+その他用途に独立した1台のESXiという構成で構築しているのだが、そのうちvSANを組んでいる2台が起動しなくなった。2週間ほど前に1台が起動しなくなり、つい数日前にまた1台が起動しなくなってしまった。3台のうち2台が死んでしまったので、vSAN環境は見事に崩壊してしまった。

理由はおおよそ分かっている。この環境は、ESXiをUSBメモリからブートしていたのだ。

ESXi 7.0からUSBメモリやSDカードからESXiをブートするのはサポートされない。

Removal of SD card/USB as a standalone boot device option (85685)

日本語情報だと yuki_kawamitsuさんがまとめてくれている。

kwmtlog.blogspot.com

ESXi 7.0以降、ブート領域へのアクセス頻度が跳ね上がっているためUSBメモリのような耐久性の低いデバイスだと壊れてしまう可能性があるという。

このあたりの情報は、以前からkawamitsuさんの上記ブログやツイート、VMware DevOps Meetupでの発表を聞いて知っていた。

なので乗り換えるために先日のAmazonブラックフライデーで、ブート用SATA SSDを買ったりもしていたのだ。準備は完璧にできいたのだ。準備だけは。

しかし乗り換えもそれなりに手間がかかるものだし、「動きが怪しくなってきたら移行作業しようかな・・・」程度に考え、ついつい作業を後回しにしていたのだ。

その結果がこれだ。しかもAdvent Calendar予定日の数日前に壊れるという・・・。1台だけならまだどうにかなったんだが・・・。同じモデルのUSBメモリに、同じタイミングでセットアップを行っていたため、故障するのも同じタイミングになってしまったと考えられる。

もし自分と同様にUSBメモリにESXiをインストールしている人がいたら、とにかく早めに乗り換えよう。

f:id:jaco-m:20211224194618j:plain:w300

ということで、生き残った1台も壊れるのは時間の問題と考えられたので、この際vSAN環境含めて一から構築し直すことにした。

Terraformで設定していくぞ

ここからが本題。これまでの自宅ラボでは、vCenterやESXi自体の設定は手動で行っており、VMの作成をTerraformで行っていた。

しかし、Terraformのvsphere providerは、VMの作成だけでなくさまざまな設定を行うことが可能だ。そこで、vCenter周りもTerraformで宣言的に設定出来るようにしてみた。 お察しの通り、Tanzu要素はない・・・ 時間なかったの許して・・・。

ちなみにTanzu x Terraformな要素としては、先日carvel providerがVerified providerとしてリリースされた。そのうち記事にしたい。

https://registry.terraform.io/providers/vmware-tanzu/carvel/latest

TerraformでvCenterを設定する例

今回のコードはこちらのリポジトリにpushしてある。

https://github.com/jacopen/terraform-vsphere-cluster

Datacenter / Clusterの設定

DatacenterとClusterを以下のように定義。ClusterはDRSとHAを有効にしている。ドキュメントだと vsphere_datacenter.datacenter.id を使っているが、 今回は vsphere_datacenter.datacenter.moid を使う。

resource "vsphere_datacenter" "datacenter" {
  name = "Datacenter"
}

resource "vsphere_compute_cluster" "compute_cluster" {
  name          = "Wells"
  datacenter_id = vsphere_datacenter.datacenter.moid
  host_managed  = true

  drs_enabled          = true
  drs_automation_level = "fullyAutomated"

  ha_enabled = true
}

HostをClusterに追加する設定

Hostは vsphere_host リソースで設定可能だ。そのままべた書きしていっても良いが、このリソース以外でも今後ホスト単位に設定したい項目があるので、以下のようなmapを変数として渡せるようにしておき

cluster_hosts = [
  {
    ip           = "10.9.8.152",
    name         = "esxi152",
    user         = "root",
    password     = "<password>",
    thumbprint   = "87:81:f3:24:b7:f1:5d:b5:7c:81:c6:75:af:8e:9c:9d:f4:d2:40:51",
    vsan_nic     = "vmnic2",
    vsan_cidr      = "10.9.13.2/24",
    cplane_nic      = "vmnic1"
  },
  {
    ip           = "10.9.8.153",
    name         = "esxi153",
    user         = "root",
    password     = "<password>",
    thumbprint   = "46:b7:db:60:e6:19:f3:63:00:f8:4c:3b:ae:ed:82:f8:40:56:67:84",
    vsan_nic     = "vmnic0",
    vsan_cidr      = "10.9.13.3/24",
    cplane_nic      = "vmnic1"
  },
  {
    ip           = "10.9.8.155",
    name         = "esxi155",
    user         = "root",
    password     = "<password>",
    thumbprint   = "dd:ae:f0:a1:f7:f6:04:52:d3:9b:16:34:f5:a6:e6:18:0d:d3:5b:8d",
    vsan_nic     = "vmnic1",
    vsan_cidr      = "10.9.13.5/24",
    cplane_nic      = "vmnic2"
  },
]

以下のようにfor_eachで回す

resource "vsphere_host" "cluster_hosts" {
  for_each = { for i in var.cluster_hosts : i.name => i }
  hostname = each.value.ip
  username = each.value.user
  password = each.value.password
  license  = var.licenses.esxi
  cluster    = vsphere_compute_cluster.compute_cluster.id
  thumbprint = each.value.thumbprint
}

thumbprintはESXiにブラウザ等でアクセスして証明書の情報を見る方法や、opensslコマンドを利用する方法が考えられる。 f:id:jaco-m:20211224201131p:plain:w300

openssl s_client -connect <ESXiのIP>:443 < /dev/null 2>/dev/null | openssl x509 -fingerprint -noout -in /dev/stdin

Resource poolやFolderの作成

これは簡単

# Resource Pools
resource "vsphere_resource_pool" "tkg" {
  name                    = "tkg"
  parent_resource_pool_id = vsphere_compute_cluster.compute_cluster.resource_pool_id
}

# Folders
resource "vsphere_folder" "tkg_folder" {
  path          = "tkg"
  type          = "vm"
  datacenter_id = vsphere_datacenter.datacenter.moid
}

vDSやPortGroupの作成

以下のようにvDSを作成。dynamic blockを活用してホストとUplinkに使う物理インターフェースを設定している。ホストによって使いたい物理インターフェースの名前が異なる可能性があるため、Cluster設定時に作った cluster_hosts から値を渡せるようにしてある。

resource "vsphere_distributed_virtual_switch" "vsan_vmotion" {
  name          = "dPlane"
  datacenter_id = vsphere_datacenter.datacenter.moid
  version       = "7.0.2"

  dynamic "host" {
    for_each = { for i in var.cluster_hosts : i.name => i }
    content {
      host_system_id = vsphere_host.cluster_hosts[host.key].id
      devices        = [host.value.vsan_nic]
    }
  }
}

PortGroupを作成。デフォルトではstatic bindingで作られるが、 type = "ephemeral"とすればEpehemralで作成も出来る。また、この例にはないが、 vlan_idでVLANの設定も可能だ。

resource "vsphere_distributed_port_group" "vsan_vmotion" {
  name                            = "vsan-pg"
  distributed_virtual_switch_uuid = vsphere_distributed_virtual_switch.vsan_vmotion.id
  number_of_ports                 = 32
}

ライセンスの設定

以下のようにvariableからvCenter, vSAN, ESXi, Tanzuのライセンスを渡せるようにした

resource "vsphere_license" "vcenter" {
  license_key = var.licenses.vcenter
}

resource "vsphere_license" "vsan" {
  license_key = var.licenses.vsan
}

resource "vsphere_license" "esxi" {
  license_key = var.licenses.esxi
}

resource "vsphere_license" "tanzu" {
  license_key = var.licenses.tanzu
}

Storage周りの設定

vSAN周りの設定も自動化できそうだがまだ行っていない。もしかすると数カ所手動設定が必要な雰囲気もある・・・

以下のようにDatastore Clusterだけ作成しておいた。

resource "vsphere_datastore_cluster" "datastore_cluster" {
  name          = "das_datastore_cluster"
  datacenter_id = vsphere_datacenter.datacenter.moid
  sdrs_enabled  = true
}

設定出来なかったこと

iSCSIのSoftware Adapterの設定は今のところやる方法が見つかっていない。

あとESXiの細かな設定も今のところやる方法がないように見える。

vCenterの設定をTerraformで管理するメリット

変更や追加が多い物、数が多くなるものについてはTerraformの恩恵を受けやすい。例えばVMの作成やディスクの作成などはメリットを感じやすい

一方でvCenterの設定はそれほど頻繁に変更するものではないため、もしかすると「手で設定した方が早い」と感じることもあるかもしれない。

今回設定してみて感じたTerraform化の理由やメリットとしては

  • あまり頻繁に変更しないものだからこそ、コード化する
    • 手で変更を行う場合、きちんと記録を残しておかないと、どういう設定を行ったのか忘れてしまう。今回一から組み直したが、かつて何を設定したか思い出すのが大変だった。Terraformにしておけば、コードを見れば入っている設定が一目瞭然
  • 万が一環境を設定し直しとなってもすぐに戻せる
    • 今回ちゃんとTerraform化したので、次また環境が壊れて修復することになったとしても設定がすぐに戻せる(壊れて欲しくはないけど)
  • いつ誰がどういう設定を変更したのが記録に残る

といったところだろうか。

今回はここまで。Tanzu組み合わせた話はまた後日書けたら書く!