4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

OpenShift (OKD4) on KVM

Last updated at Posted at 2023-11-09

TL;DR

RedHat OpenShift のコミュニティ版である OKD4 のクラスタを、1台の物理マシン上に構成する。

install-config.yaml を用意し、 openshift-install コマンドを実行すると Ignition 設定ファイルが生成される。それを Terraform に与え、 KVM 上に OKD4 クラスタをプロビジョニングする。導入フローを図に表すと次の通り:

installation-flow.png

サンプルコード:

概要

本記事で作成するネットワーク構成は下図の通り:

network_architecture.drawio.png

手順は次の公式のガイドに従う:

前提条件

Softwares

  • terraform
  • KVM Packages
    • qemu-kvm
    • libvirt
  • systemd-resolved

ホスト(物理マシン)

Machine Intel NUC13 Pro (NUC13ANHi7)
CPU Core i7-1065G7
Memory 64GB (DDR4-3200MHz)
SSD 1TB (NVMe)
Host OS Rocky Linux 9.2 (Minimal)

RedHat アカウント

RedHat Hybrid Cloud Console にログインできること。

Host の事前準備

簡単のために SE Linux は permisive にしておく。

$ setenforce 0

同様に、簡単のために Firewall を無効化する。

$ systemctl stop firewalld
$ systemctl disable firewalld

Libvirt の事前準備

libvirt の事前設定準備として、こちらの Libvirt HOTOW · openshift/installer に記載の内容を実行する。

次を実行し、net.ipv4.ip_forward 設定値が 1 であるか確認する:

$ sysctl net.ipv4.ip_forward
sysctl net.ipv4.ip_forward=1

もし net.ipv4.ip_forward = 0 であった場合、次を実行して設定値を変更する。

$ sysctl net.ipv4.ip_forward=1

設定を永続化する場合は:

$ echo "net.ipv4.ip_forward = 1" | sudo tee /etc/sysctl.d/99-ipforward.conf
$ sudo sysctl -p /etc/sysctl.d/99-ipforward.conf

libvirtd-tcp.socket を有効化する:

$ sudo systemctl enable libvirtd-tcp.socket
$ sudo systemctl start libvirtd-tcp.socket

NetworkManager DNS overlayを使用する:

$ echo -e "[main]\ndns=dnsmasq" | sudo tee /etc/NetworkManager/conf.d/openshift.conf
$ echo server=/ocp4.example.com/192.168.126.1 | sudo tee /etc/NetworkManager/dnsmasq.d/openshift.conf

設定を適用する:

sudo systemctl restart NetworkManager

libvirtd args の値を設定する。ホストが Fedora 系OS (e.g. Fedora, RHEL, CentOS, etc.) か Debian 系 OS (Debian, Ubuntu, etc.) かで設定値が異なるので注意。

(Fedora系 の場合):/etc/sysconfig/libvirtd に次の設定を加える。

/etc/sysconfig/libvirtd
# For Fedora-based distro
LIBVIRTD_ARGS="--listen"

(Debian 系の場合):/etc/default/libvirtd に次の設定を加える。

/etc/default/libvirtd
# For Debian-based distro
libvirtd_opts="--listen"

/etc/libvirt/libvirtd.conf で次の設定を有効にする:

listen_tls = 0
listen_tcp = 1
auth_tcp = "none"
tcp_port = "16509"

libvirt を再起動する。

sudo systemctl restart libvirtd

OKD4 クラスタ設定ファイルの用意

本節では、 OKD4 クラスタ設定ファイル install-config.yaml を用意し、VM の作成に必要な Ignition ファイルを生成するまでの手順を説明する。

openshift-install の用意

まずはインストーラ openshift-install をインストールする:

$ curl -LO https://github.com/okd-project/okd/releases/download/4.13.0-0.okd-2023-09-30-084937/openshift-client-linux-4.13.0-0.okd-2023-09-30-084937.tar.gz
$ tar -zxvf openshift-client-linux-4.13.0-0.okd-2023-09-30-084937.tar.gz
$ mv openshift-install /usr/local/bin
$ openshift-install version
openshift-install 4.14.0-0.okd-2023-10-28-073550
built from commit 03546e550ae68f6b36d78d78b539450e66b5f6c2
release image quay.io/openshift/okd@sha256:7a6200e347a1b857e47f2ab0735eb1303af7d796a847d79ef9706f217cd12f5c
release architecture amd64

install-config.yaml の設定

公式ドュメンテーションのサンプル をベースに、次の install-config.yaml を作成する:

カスタマイズ可能な項目は Cluster Customization · openshift/installer から確認できる。

install-config.yaml
---
apiVersion: v1
baseDomain: example.com
compute:
- hyperthreading: Enabled
  name: worker
  replicas: 2
controlPlane:
  hyperthreading: Enabled
  name: master
  replicas: 3
metadata:
  name: ocp4
networking:
  clusterNetwork:
  - cidr: 10.128.0.0/14
    hostPrefix: 23
  serviceNetwork:
  - 172.30.0.0/16
  networkType: OVNKubernetes
platform:
  none: {}
pullSecret: '{"auths":{"fake":{"auth":"aWQ6cGFzcwo="}}}'
sshKey: |
  ssh-ed25519 AAAA... user1@example.com
  ssh-ed25519 AAAA... user2@example.com

特に書き換える必要がある項目について説明する:

pullSecret

Install OpenShift 4 | Pull Secret から pullSecret をコピーし、そのまま上記 yaml の pullSecret の値とする。

設定しなかった場合、コンテナレジストリ (quay.io や registry.redhat.io など) へのアクセスや、Operator Hub でインストール可能な Operator の種類が制限される場合がある。

sshKey

各ノードの CoreOS に SSH ログインするために設定する。

Ignition ファイルの生成

Ignition ファイルは、 自動で CoreOS の初期設定を行うための設定ファイルであり、先ほどの openshift-install コマンドから生成できる。

install-config.yaml は次の openshift-install コマンド実行後に自動で削除されるため、バックアップをとっておく。

$ cp install-config.yaml install-config.yaml.backup

次のコマンドで ignition ファイルを作成する:

$ openshift-install create ignition-configs

下記ファイルが生成されていればOK:

./
├── auth/
│   ├── kubeadmin-password
│   └── kubeconfig
├── bootstrap.ign
├── master.ign
├── metadata.json
└── worker.ign

これらの ignition ファイルには有効期限が埋め込まれており、24時間で失効する。失効後はクラスタを作成できないため、 ignition ファイルを作り直す必要がある (参考)。

Terraform によるクラスタのプロビジョニング

Terraform を用いて、要求されるリソースを作成する。
詳細は公式ドキュメンテーション Installing a cluster on any platform - Installing on any platform | Installing | OKD 4 を参照。

ノードの最小要求は次の表の通り:

Machine Operating System vCPU Virtual RAM Storage Input/Output Per Second required number 備考
Bootstrap FCOS 4 16 GB 100 GB 300 1 クラスタ構築後に削除可能
Control plane FCOS 4 16 GB 100 GB 300 3
Compute FCOS 2 8 GB 100 GB 300 >=2

DNS の要求は次の表の通り:

Record Target
api.<cluster_name>.<base_domain>. Load balancer
api-int.<cluster_name>.<base_domain>. Load balancer
*.apps.<cluster_name>.<base_domain>. Load balancer
bootstrap.<cluster_name>.<base_domain>. Bootstrap node
master<n>.<cluster_name>.<base_domain>. Master nodes
worker<n>.<cluster_name>.<base_domain>. Worker nodes

CoreOS イメージの用意

CoreOS の qcow2 イメージを用意する。推奨される CoreOS のバージョンは openshift-install のバージョンに対応して定められており、次のコマンドで確認できる(参考):

$ openshift-install coreos print-stream-json | jq -r '.architectures.x86_64.artifacts.qemu.formats["qcow2.xz"].disk.location'
https://builds.coreos.fedoraproject.org/prod/streams/stable/builds/38.20230609.3.0/x86_64/fedora-coreos-38.20230609.3.0-qemu.x86_64.qcow2.xz

次のコマンドでイメージをダウンロードする。

$ wget $(openshift-install coreos print-stream-json | jq -r '.architectures.x86_64.artifacts.qemu.formats["qcow2.xz"].disk.location')

ダウンロードしたイメージは libvirt のデフォルトプール /var/lib/libvirt/images に配置する:

$ xz -dv ./fedora-coreos-38.20230609.3.0-qemu.x86_64.qcow2.xz
$ sudo mv fedora-coreos-38.20230609.3.0-qemu.x86_64.qcow2  /var/lib/libvirt/images

Terraform ファイルの作成

下記の main.tf を作成する。
(CoreOS の qcow2 イメージの path vm_base_image_uri は、適宜修正してください。)

下記の main.tf は、OKDを作成するための module github.com/sawa2d2/k8s-on-kvm//okd/ をインポートしています。このモジュールの説明は 本記事内の付録 でしています。

main.tf
locals {
  user_home_directory = pathexpand("~")
}

module "okd" {
  source = "github.com/sawa2d2/k8s-on-kvm//okd/"

  ## Localhost:
  # libvirt_uri = "qemu:///system"
  ## Remote:
  # libvirt_uri = "qemu+ssh://<remote-user>@<remote-host>/system?keyfile=${local.user_home_directory}/.ssh/id_rsa&known_hosts_verify=ignore"
  ## Remote via bastion:
  ##   Forward port in advance.
  ##   $ ssh -C -N -f -L 50000:<remote-user>@<remote-host>:22 <bastion-host> -p <bastion-port>
  # libvirt_uri = "qemu+ssh://<remote-user>@localhost:50000/system?keyfile=${local.user_home_directory}/.ssh/id_rsa&known_hosts_verify=ignore"
  libvirt_uri = "qemu:///system"

  domain       = "ocp4.example.com"
  network_name = "okd"
  bridge_name  = "tt0"
  cidr         = "192.168.126.0/24"
  gateway      = "192.168.126.1"
  nameservers  = ["192.168.126.1"]

  load_balancer_ip = "192.168.126.1" # or `null`
  # load_balancer_ip = null とした場合、DNS ラウンドロビンで分散する。
  # HAProxy が不要になる一方、ホスト外部からクラスタにアクセスする入口はなくなる。


  # Download a CoreOS image from:
  #   $ openshift-install version
  #   openshift-install 4.14.0-0.okd-2023-10-28-073550
  #   $ wget $(openshift-install coreos print-stream-json | jq -r '.architectures.x86_64.artifacts.qemu.formats["qcow2.xz"].disk.location')
  #   $ xz -dv *.qcow2.xz
  vm_base_image_uri = "/var/lib/libvirt/images/fedora-coreos-38.20231002.3.1-qemu.x86_64.qcow2"
  pool              = "default"

  bootstrap = {
    name          = "bootstrap"
    vcpu          = 4
    memory        = 12288                    # in MiB
    disk          = 100 * 1024 * 1024 * 1024 # 100 GB
    ip            = "192.168.126.100"
    ignition_file = "bootstrap.ign"
    volumes       = []
  }

  masters = [
    {
      name          = "master0"
      vcpu          = 4
      memory        = 12288                    # in MiB
      disk          = 100 * 1024 * 1024 * 1024 # 100 GB
      ip            = "192.168.126.101"
      ignition_file = "master.ign"
      volumes       = []
    },
    {
      name          = "master1"
      vcpu          = 4
      memory        = 12288                    # in MiB
      disk          = 100 * 1024 * 1024 * 1024 # 100 GB
      ip            = "192.168.126.102"
      ignition_file = "master.ign"
      volumes       = []
    },
    {
      name          = "master2"
      vcpu          = 4
      memory        = 12288                    # in MiB
      disk          = 100 * 1024 * 1024 * 1024 # 100 GB
      ip            = "192.168.126.103"
      ignition_file = "master.ign"
      volumes       = []
    },
  ]

  workers = [
    {
      name          = "worker0"
      vcpu          = 2
      memory        = 8192                     # in MiB
      disk          = 100 * 1024 * 1024 * 1024 # 100 GB
      ip            = "192.168.126.104"
      ignition_file = "worker.ign"
      volumes = [
        {
          name = "additional_disk"
          disk = 200 * 1024 * 1024 * 1024 # 200 GB
        }
      ]
    },
    {
      name          = "worker1"
      vcpu          = 2
      memory        = 8192                     # in MiB
      disk          = 100 * 1024 * 1024 * 1024 # 100 GB
      ip            = "192.168.126.105"
      ignition_file = "worker.ign"
      volumes = [
        {
          name = "additional_disk"
          disk = 200 * 1024 * 1024 * 1024 # 200 GB
        }
      ]
    },
  ]
}

次のコマンドを実行し、VM とネットワークを作成する。

$ terraform init
$ terraform apply -auto-approve

ネットワークの設定は /etc/libvirt/qemu/networks/okd.xml から確かめることができる。DNSレコードが下記のようになっていれば OK。

$ less /etc/libvirt/qemu/networks/okd.xml
...
  <dnsmasq:options>
    <dnsmasq:option value='address=/api.ocp4.example.com/192.168.126.1'/>
    <dnsmasq:option value='address=/api-int.ocp4.example.com/192.168.126.1'/>
    <dnsmasq:option value='address=/apps.ocp4.example.com/192.168.126.1'/>
    <dnsmasq:option value='address=/bootstrap.ocp4.example.com/192.168.126.100'/>
    <dnsmasq:option value='address=/master0.ocp4.example.com/192.168.126.101'/>
    <dnsmasq:option value='address=/master1.ocp4.example.com/192.168.126.102'/>
    <dnsmasq:option value='address=/master2.ocp4.example.com/192.168.126.103'/>
    <dnsmasq:option value='address=/worker0.ocp4.example.com/192.168.126.104'/>
    <dnsmasq:option value='address=/worker1.ocp4.example.com/192.168.126.105'/>
  </dnsmasq:options>

ホスト内において、ドメイン ocp4.example.com に対して libvirt の DNS 192.168.126.1 を利用させる:

$ sudo resolvectl dns tt0 192.168.126.1
$ sudo resolvectl domain tt0 ~ocp4.example.com

上記の操作は永続化されないので、ネットワークを作成するたびに実行する。
永続化する場合は、/etc/systemd/resolved.conf を次のように編集する:

/etc/systemd/resolved.conf
[Resolve]
DNS=192.168.126.1
Domains=~ocp4.example.com

次を実行して設定を反映する:

sudo systemctl restart systemd-resolved

ドメインが解決されることを確認する。

$ nslookup api.ocp4.example.com
Server:         127.0.0.53
Address:        127.0.0.53#53

Non-authoritative answer:
Name:   api.ocp4.example.com
Address: 192.168.126.1

Load Balancer (HAProxy) の起動

まず HAProxy をインストールする。

$ dnf install haproxy

公式ドキュメントのサンプル をもとに、下記 HAProxy の設定ファイルを /etc/haproxy/haproxy.cfg に置く。

/etc/haproxy/haproxy.cfg
global
  log         127.0.0.1 local2
  pidfile     /var/run/haproxy.pid
  maxconn     4000
  daemon
defaults
  mode                    http
  log                     global
  option                  dontlognull
  option http-server-close
  option                  redispatch
  retries                 3
  timeout http-request    10s
  timeout queue           1m
  timeout connect         10s
  timeout client          1m
  timeout server          1m
  timeout http-keep-alive 10s
  timeout check           10s
  maxconn                 3000
listen api-server-6443 
  bind *:6443
  mode tcp
  server bootstrap bootstrap.ocp4.example.com:6443 check inter 1s backup
  server master0 master0.ocp4.example.com:6443 check inter 1s
  server master1 master1.ocp4.example.com:6443 check inter 1s
  server master2 master2.ocp4.example.com:6443 check inter 1s
listen machine-config-server-22623 
  bind *:22623
  mode tcp
  server bootstrap bootstrap.ocp4.example.com:22623 check inter 1s backup
  server master0 master0.ocp4.example.com:22623 check inter 1s
  server master1 master1.ocp4.example.com:22623 check inter 1s
  server master2 master2.ocp4.example.com:22623 check inter 1s
listen ingress-router-443 
  bind *:443
  mode tcp
  balance source
  server worker0 worker0.ocp4.example.com:443 check inter 1s
  server worker1 worker1.ocp4.example.com:443 check inter 1s
listen ingress-router-80 
  bind *:80
  mode tcp
  balance source
  server worker0 worker0.ocp4.example.com:80 check inter 1s
  server worker1 worker1.ocp4.example.com:80 check inter 1s

最後の1行は、空行にしておかないとエラーになるので注意。

HAProxy を起動する。

$ systemctl start haproxy.service

ホームネットワーク上からクラスタにアクセスできるようにする

ホストから直接ではなく、外部のクライアントからクラスタにアクセスしたい場合、ルートドメインとホスト IP の対応をホームネットワーク内の DNS に追加する。例えば、ホームネットワーク192.168.8.0/24 上でホスト 192.168.8.10 を公開する場合、次のようなレコードを DNS に追加すればよい。

address=/ocp4.example.com/192.168.8.10

publish.drawio.png

ホームネットワークの DNS を設定するのが難しい場合、クライアントマシン側の /etc/hosts 次のようにを設定してもよい。

/etc/hosts
192.168.8.10 ocp4.example.com
192.168.8.10 api.ocp4.example.com
192.168.8.10 api-int.ocp4.example.com
192.168.8.10 console-openshift-console.apps.ocp4.example.com
192.168.8.10 oauth-openshift.apps.ocp4.example.com

Bootstrap の完了を待つ

次のコマンドで Bootstrap の進捗を確認できる:

$ openshift-install wait-for bootstrap-complete --log-level=info

さらに別ターミナルで次のコマンドを実行すると、リアルタイムのログを確認できる:

$ tail --follow .openshift_install.log

より詳細なログを確認する場合、bootstrap ノード内で次を実行する:

$ journalctl -f -u bootkube -u openshift

Bootstrap が完了すると、次のようなログが確認できる。

$ openshift-install wait-for bootstrap-complete --log-level=info
INFO Waiting up to 20m0s (until 11:08AM JST) for the Kubernetes API at https://api.ocp4.example.com:6443...
INFO API v1.27.1-3348+f67aeb31c9b95f-dirty up
INFO Waiting up to 30m0s (until 11:18AM JST) for bootstrapping to complete...
INFO It is now safe to remove the bootstrap resources
INFO Time elapsed: 0s

インストールがうまくいかない場合、 Troubleshooting installations - Troubleshooting | Support | OKD 4 を参照しながらトラブルシューティングを行う。

Bootstrap 完了後は、次のコマンドで Bootstrap ノードを削除することができる:

$ terraform destroy -auto-approve -target=module.okd.module.bootstrap
$ terraform apply -auto-approve -target=module.okd.libvirt_network.network -var="exclude_bootstrap=true"

Bootstrap 完了後は、次のコマンドでインストールプロセス完了までのログをモニタリングできる。

$ ./openshift-install agent wait-for install-complete --log-level=debug

OKD4 クラスタへのアクセス

クライアントに OpenShift 用 の CLI oc コマンドをインストールする:

$ curl -LO https://github.com/okd-project/okd/releases/download/4.13.0-0.okd-2023-09-30-084937/openshift-client-linux-4.13.0-0.okd-2023-09-30-084937.tar.gz
$ openshift-client-linux-4.13.0-0.okd-2023-09-30-084937.tar.gz
$ mv oc /usr/local/bin

インストーラが生成した Kubeconfig ファイルを環境変数に通す。

$ export KUBECONFIG=`pwd`/auth/kubeconfig

oc コマンドからクラスタにアクセスできることを確認する。

$ oc whoami
system:admin

CSR の承認

ブートストラップ完了直後は worker node の CSR (CertificateSigningRequest) が承認されていないため、使用できない状態にある。

$ oc get node
NAME      STATUS   ROLES                  AGE   VERSION
master0   Ready    control-plane,master   47m   v1.27.6+f67aeb3
master1   Ready    control-plane,master   47m   v1.27.6+f67aeb3
master2   Ready    control-plane,master   48m   v1.27.6+f67aeb3

次のコマンドで CSR の一覧を確認する。

$ oc get csr
csr-2x4wd                                        26m   kubernetes.io/kube-apiserver-client-kubelet   system:serviceaccount:openshift-machine-config-operator:node-bootstrapper         <none>              Pending
csr-82sgp                                        50m   kubernetes.io/kube-apiserver-client-kubelet   system:serviceaccount:openshift-machine-config-operator:node-bootstrapper         <none>              Approved,Issued
csr-8hb7s                                        31m   kubernetes.io/kube-apiserver-client-kubelet   system:serviceaccount:openshift-machine-config-operator:node-bootstrapper         <none>              Pending
csr-8vlll                                        10m   kubernetes.io/kube-apiserver-client-kubelet   system:serviceaccount:openshift-machine-config-operator:node-bootstrapper         <none>              Pending
csr-9kcj8                                        9s    kubernetes.io/kube-apiserver-client-kubelet   system:serviceaccount:openshift-machine-config-operator:node-bootstrapper         <none>              Pending
csr-9lbqw                                        15m   kubernetes.io/kube-apiserver-client-kubelet   system:serviceaccount:openshift-machine-config-operator:node-bootstrapper         <none>              Pending
csr-bn4w4                                        51m   kubernetes.io/kube-apiserver-client-kubelet   system:serviceaccount:openshift-machine-config-operator:node-bootstrapper         <none>              Approved,Issued
csr-ch4vc                                        31m   kubernetes.io/kube-apiserver-client-kubelet   system:serviceaccount:openshift-machine-config-operator:node-bootstrapper         <none>              Pending
csr-j8jh6                                        29m   kubernetes.io/kube-apiserver-client-kubelet   system:serviceaccount:openshift-machine-config-operator:node-bootstrapper         <none>              Pending
csr-mjk2h                                        29m   kubernetes.io/kube-apiserver-client-kubelet   system:serviceaccount:openshift-machine-config-operator:node-bootstrapper         <none>              Pending
csr-rdv2b                                        30m   kubernetes.io/kube-apiserver-client-kubelet   system:serviceaccount:openshift-machine-config-operator:node-bootstrapper         <none>              Pending
csr-wzcgp                                        50m   kubernetes.io/kube-apiserver-client-kubelet   system:serviceaccount:openshift-machine-config-operator:node-bootstrapper         <none>              Approved,Issued

Pending になっているものを oc amd certificate approve <csr> で承認する。全ての Pending の CSR を承認する場合は、次のコマンドを実行する:

$ oc get csr -o go-template='{{range .items}}{{if not .status}}{{.metadata.name}}{{"\n"}}{{end}}{{end}}' | xargs --no-run-if-empty oc adm certificate approve

少し待つと Worker node がReadyになる

$ oc get node
NAME      STATUS   ROLES                  AGE     VERSION
master0   Ready    control-plane,master   61m     v1.27.6+f67aeb3
master1   Ready    control-plane,master   61m     v1.27.6+f67aeb3
master2   Ready    control-plane,master   61m     v1.27.6+f67aeb3
worker0   Ready    worker                 9m22s   v1.27.6+f67aeb3
worker1   Ready    worker                 9m25s   v1.27.6+f67aeb3

ROLES の control-planemaster は、どちらも同じものである。旧 master がより中立的な control-plane という表現に変えられたが、master も互換性のために残されている、という事情らしい。

Web コンソールへのアクセス

コンソールのURLを調べる

$ oc whoami --show-console
https://console-openshift-console.apps.ocp4.example.com

ブラウザからアクセスする。

Screenshot from 2023-11-09 14-54-57.png

ユーザ名は kubeadmin、パスワードは ./auth/kubeamind-password に書かれたものを使用し、コンソールにログインする。

Screenshot from 2023-11-09 14-55-41.png

その他の初期設定

OKD は OpenShift と異なり、初期設定では Community 提供の Operator しか表示されないように制限されているので、解除する。


$ oc patch operatorhub cluster -p '{"spec": {"disableAllDefaultSources": false}}' --type=merge

付録

Terraform module の詳細

モジュールは次の3ファイルからなる。

  • provider.tf
  • variables.tf
  • main.tf

provider.tf

Terraform Libvirt Provider をインポートする。

provider.tf
terraform {
  required_providers {
    libvirt = {
      source  = "dmacvicar/libvirt"
      version = "0.7.1"
    }
  }
}

provider "libvirt" {
  uri = var.libvirt_uri
}

variables.tf

変数を定義する。

variables.tf
variable "bootstrap" {
  type = object({
    name          = string
    vcpu          = number
    memory        = number
    disk          = number
    ip            = string
    ignition_file = string
    volumes = list(
      object({
        name = string
        disk = number
      })
    )
  })
}

variable "masters" {
  type = list(
    object({
      name          = string
      vcpu          = number
      memory        = number
      disk          = number
      ip            = string
      ignition_file = string
      volumes = list(
        object({
          name = string
          disk = number
        })
      )
    })
  )
}

variable "workers" {
  type = list(
    object({
      name          = string
      vcpu          = number
      memory        = number
      disk          = number
      ip            = string
      ignition_file = string
      volumes = list(
        object({
          name = string
          disk = number
        })
      )
    })
  )
}

variable "domain" {
  type = string
}

variable "exclude_bootstrap" {
  type    = bool
  default = false
}

variable "load_balancer_ip" {
  type    = string
  default = null
}

variable "libvirt_uri" {
  type    = string
  default = "qemu:///system"
}

variable "pool" {
  type    = string
  default = "default"
}

variable "vm_base_image_uri" {
  type = string
}

variable "network_name" {
  type    = string
  default = "okd"
}

variable "cidr" {
  type    = string
  default = "192.168.126.0/24"
}

variable "bridge_name" {
  type    = string
  default = "tt0"
}

variable "gateway" {
  type    = string
  default = "192.168.126.1"
}

variable "nameservers" {
  type    = list(string)
  default = ["192.168.126.1"]
}

main.tf

VM、およびネットワークを作成するロジックを書く。なお、変数 load_balancer_ip は HAProxy が稼働するホストの IP 指定する変数だが、これを null とした場合、DNS ラウンドロビンによる分散を行う。

main.tf
locals {
  dns_hosts = var.load_balancer_ip == null ? concat(
    [
      for vm in var.masters : {
        hostname = "api.${var.domain}"
        ip       = vm.ip
      }
    ],
    [
      for vm in var.masters : {
        "hostname" : "api-int.${var.domain}"
        "ip" : vm.ip
      }
    ],
    var.exclude_bootstrap ? [] : [
      {
        hostname = "api.${var.domain}"
        ip       = var.bootstrap.ip
      },
      {
        hostname = "api-int.${var.domain}"
        ip       = var.bootstrap.ip
      },
    ],
  ) : []

  dnsmasq_options = concat(
    var.load_balancer_ip != null ? [
      {
        option_name  = "address"
        option_value = "/api.${var.domain}/${var.load_balancer_ip}"
      },
      {
        option_name  = "address"
        option_value = "/api-int.${var.domain}/${var.load_balancer_ip}"
      },
      {
        option_name  = "address"
        option_value = "/apps.${var.domain}/${var.load_balancer_ip}"
      },
    ] : [],
    var.exclude_bootstrap ? [] : [
      {
        option_name  = "address"
        option_value = "/bootstrap.${var.domain}/${var.bootstrap.ip}"
      },
    ],
    [
      for vm in var.masters : {
        option_name  = "address",
        option_value = "/${vm.name}.${var.domain}/${vm.ip}"
      }
    ],
    [
      for vm in var.workers : {
        option_name  = "address"
        option_value = "/${vm.name}.${var.domain}/${vm.ip}"
      }
    ],
  )
}

resource "libvirt_network" "network" {
  name      = var.network_name
  mode      = "nat"
  domain    = var.domain
  bridge    = var.bridge_name
  addresses = [var.cidr]
  autostart = true

  dns {
    local_only = true
    dynamic "hosts" {
      for_each = local.dns_hosts
      content {
        hostname = hosts.value.hostname
        ip       = hosts.value.ip
      }
    }
  }

  dnsmasq_options {
    dynamic "options" {
      for_each = local.dnsmasq_options
      content {
        option_name  = options.value["option_name"]
        option_value = options.value["option_value"]
      }
    }
  }
}

module "bootstrap" {
  source = "github.com/sawa2d2/terraform-modules//libvirt-ignition-nat/"

  libvirt_uri       = var.libvirt_uri
  pool              = var.pool
  vm_base_image_uri = var.vm_base_image_uri
  network_name      = var.network_name
  vms               = [var.bootstrap]
}

module "cluster" {
  source = "github.com/sawa2d2/terraform-modules//libvirt-ignition-nat/"

  libvirt_uri       = var.libvirt_uri
  pool              = var.pool
  vm_base_image_uri = var.vm_base_image_uri
  network_name      = var.network_name
  vms               = concat(var.masters, var.workers)
}

中でさらに使用している Terraform モジュールの詳細は次のURLを参照(libvirt terraform provider のラッパーである)。

補足

プロキシの設定

プロキシを設定する場合は、install-config.yaml を次のように書く
(本記事内 『OKD4 クラスタ設定ファイルの用意 』の install-config.yaml との違いは、 proxy および networking.machineNetwork を指定しているかどうか)。

install-config.yaml
---
apiVersion: v1
baseDomain: example.com
proxy:
  httpProxy: http://<username>:<pswd>@<ip>:<port>
  httpsProxy: https://<username>:<pswd>@<ip>:<port>
  noProxy: example.com
compute:
- hyperthreading: Enabled
  name: worker
  replicas: 2
controlPlane:
  hyperthreading: Enabled
  name: master
  replicas: 3
metadata:
  name: ocp4
networking:
  clusterNetwork:
  - cidr: 10.128.0.0/14
    hostPrefix: 23
  serviceNetwork:
  - 172.30.0.0/16
  networkType: OVNKubernetes
  machineNetwork:
  - cidr: 192.168.126.0/24
platform:
  none: {}
pullSecret: '{"auths":{"fake":{"auth":"aWQ6cGFzcwo="}}}'
sshKey: |
  ssh-ed25519 AAAA... user1@example.com
  ssh-ed25519 AAAA... user2@example.com

Proxy を指定する場合、machineNetwork(OpenShift クラスタを構成するノード間のネットワーク、本記事における 192.168.126.0/24)を明示すると、そのネットワークは自動的に noProxy 扱いになる。

Proxy を指定する場合、networking.machineNetwork[].cidrnetworking.clusterNetwork[].cidr、および networking.serviceNetwork[] は自動的に noProxy として扱われる 。
詳細は 1.3.7.3. インストール時のクラスター全体のプロキシーの設定 OpenShift Container Platform 4.6 | Red Hat Customer Portal を参照。

参考資料

OKD4 公式ドキュメント

OKD4 on other platforms:

libvirt for OKD 関連

関連記事

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?