TT Lab
はじめる
学ぶ 学習パス コース

Kubespray と Terraform でクラスターを構築する

インベントリ 1 枚がクラスターの形を決める

TT Labで続きを見る

目標

kubespray v2.32.0のサンプルインベントリで、ノード1台のクラスターのインベントリを設計し、バージョンをgroup_varsに固定して、変数がどの層で勝つかと、グループ名を間違えたときに何が壊れるかを、自分で確認します。クラスターはまだ構築しません。

なぜ重要なのか

kubesprayでクラスターを構築するとき、人が直接書くのは、事実上インベントリとgroup_varsだけです。プレイブックはそのままにして、この2つだけを変えて、クラスターの形(誰がコントロールプレーンで、誰がetcdか)と内容(どのバージョン、どのCNI、どのランタイムか)を決めます。 そのため、インストールがうまくいかない原因も、たいていここにあります。グループ名を1つ間違えると、インストールの1分後に見当違いのエラーで止まり、バージョンを書かないと、同じインベントリがkubesprayを上げるたびに異なるKubernetesをインストールします。長いインストールを実行する前に、インベントリツールで展開された値を確認する習慣が、このモジュールの目標です。

ステップ

  1. /opt/ks/kubespray/inventory/sampleを丸ごとコピーしてください(コピー先: /root/ks/inventory/lab)。group_vars/all/all.ymlとgroup_vars/k8s_cluster/k8s-cluster.ymlが、その下にある必要があります。
  2. ノードnode1をkube_control_planeとkube_nodeのグループに入れ、etcdはkube_control_planeを子グループとして受け取る([etcd:children])ように書いてください(書き込み先: /root/ks/inventory/lab/inventory.ini)。k8s_clusterも、kube_control_planeとkube_nodeを子として受け取る([k8s_cluster:children])ように書きます。接続方式は、インベントリの行ではなく、ansible_connection: localとして置いてください(置き場所: /root/ks/inventory/lab/host_vars/node1.yml)。inventory.iniにはansible_connectionがない必要があります。
  3. /opt/ks/kubesprayでansible-inventory --listを2回実行して、パースされたホスト数を数え、次のフィールドを書いてください(書き込み先: /root/ks/parse.json)。dir_hosts(-i /root/ks/inventory/labでディレクトリを渡したとき)、file_hosts(-i /root/ks/inventory/lab/inventory.ini)、ignored_ext(kubesprayのansible.cfgがインベントリのディレクトリでスキップする拡張子のうち、inventory.iniを隠すもの、ドットを含む文字列)です。
  4. /root/ks/inventory/lab/group_vars/k8s_cluster/k8s-cluster.ymlにkube_version: 1.35.8を追加してください(サンプルにはありません)。そのあとansible-inventory --host node1で実際に展開された値を読み取り、kube_version、container_manager、kube_network_plugin、kube_proxy_mode、kube_service_addresses、kube_pods_subnetの6つを文字列として書いてください(書き込み先: /root/ks/vars.json)。
  5. /root/ks/inventory/lab/group_vars/all/all.ymlの末尾にkube_version: 1.34.11を一時的に追加してから、ansible -i /root/ks/inventory/lab/inventory.ini node1 -m debug -a var=kube_versionで実際の値を確認し、同じコマンドに-e kube_version=1.36.4を付けてもう一度確認してください。次のフィールドを書いてください(書き込み先: /root/ks/precedence.json)。all_yml(all.ymlに入れた値)、effective(-eなしで勝った値)、extra_vars(-eを指定したときの値)、winner_file(-eなしで勝った値が書かれたファイルの、インベントリを基準にした相対パス)です。そのあと、all.ymlに入れた行は削除します。
  6. /root/ks/broken/inventory.iniは、誰かが[masters]と書いたインベントリです。直さずに、/opt/ks/kubesprayでansible-playbook -i /root/ks/broken/inventory.ini playbooks/boilerplate.ymlを実行してみてください。次のフィールドを書いてください(書き込み先: /root/ks/broken.json)。failed_task(失敗したタスクの名前、ロールの接頭辞なし)、node1_groups(このインベントリでnode1が属するグループ名のソートした配列、allとungroupedを除く)、missing_group(空であるはずがないのに空になっているkubesprayのグループ名)です。
  7. /opt/ks/kubesprayでansible-playbook -i /root/ks/inventory/lab/inventory.ini playbooks/boilerplate.ymlを実行して、出力の全体を保存してください(保存先: /root/ks/logs/boilerplate.log)。PLAY RECAPでfailed=0である必要があります。
  8. 次のフィールドを書いてください(書き込み先: /root/ks/report.json)。kubespray_tag(git -C /opt/ks/kubespray describe --tags)、ansible_core(ansible --versionの1行目のバージョン番号。例: 2.19.0)、kube_version_default(このバージョンのデフォルトのkube_version)、kube_version_min(このバージョンが受け入れる最も低いバージョン)です。

参考

サンプルインベントリを自分の場所にコピーする

/opt/ks/kubespray/inventory/sampleを丸ごとコピーしてください(コピー先: /root/ks/inventory/lab)。group_vars/all/all.ymlとgroup_vars/k8s_cluster/k8s-cluster.ymlが、その下にある必要があります。

kubesprayは、インベントリのディレクトリの隣にあるgroup_varsを読み取ります。サンプルを直さずにコピーする理由は、次のバージョンに上げるときにサンプルが変わるからです。コピー先のディレクトリがすでにあると、cp -rはその中にsampleというサブディレクトリをもう1つ作ります。

ノード1台を3つのグループに入れる

ノードnode1をkube_control_planeとkube_nodeのグループに入れ、etcdはkube_control_planeを子グループとして受け取る([etcd:children])ように書いてください(書き込み先: /root/ks/inventory/lab/inventory.ini)。k8s_clusterも、kube_control_planeとkube_nodeを子として受け取る([k8s_cluster:children])ように書きます。接続方式は、インベントリの行ではなく、ansible_connection: localとして置いてください(置き場所: /root/ks/inventory/lab/host_vars/node1.yml)。inventory.iniにはansible_connectionがない必要があります。

このVMはコントロールノードであり対象ノードでもあるので、sshの代わりにlocal接続を使います。その事実をhost_varsに置いておけば、ノードが増えるとき、インベントリには名前だけを追加して、接続方式はノードごとのファイルで変えればよくなります。グループ名は、kubesprayが決めたつづりのままである必要があります。サンプルのinventory.iniにはk8s_clusterがありません。kubesprayがプレイブックの中で作るためですが、そうするとプレイブックの外のツール(ansible-inventory、ansibleのアドホック)は、group_vars/k8s_clusterを読み取れません。

ディレクトリを渡すとホストが0個になる

/opt/ks/kubesprayでansible-inventory --listを2回実行して、パースされたホスト数を数え、次のフィールドを書いてください(書き込み先: /root/ks/parse.json)。dir_hosts(-i /root/ks/inventory/labでディレクトリを渡したとき)、file_hosts(-i /root/ks/inventory/lab/inventory.ini)、ignored_ext(kubesprayのansible.cfgがインベントリのディレクトリでスキップする拡張子のうち、inventory.iniを隠すもの、ドットを含む文字列)です。

ホスト数は、--listの結果の_meta.hostvarsのキーの個数で数えられます。ansible-inventoryがどの設定ファイルを読み取るかはansible-config dump --only-changedで見られ、そのファイルは現在のディレクトリから探します。

バージョンをgroup_varsに固定する

/root/ks/inventory/lab/group_vars/k8s_cluster/k8s-cluster.ymlにkube_version: 1.35.8を追加してください(サンプルにはありません)。そのあとansible-inventory --host node1で実際に展開された値を読み取り、kube_version、container_manager、kube_network_plugin、kube_proxy_mode、kube_service_addresses、kube_pods_subnetの6つを文字列として書いてください(書き込み先: /root/ks/vars.json)。

kube_versionを書かないと、kubesprayのバージョンごとにデフォルト値が変わり、同じインベントリで別の日に別のKubernetesがインストールされます。ファイルに書いたものと、Ansibleが実際に展開した値が同じかどうかは、インベントリツールで確認します。YAMLでは1.35のようにドット1つの数字は実数として読まれますが、3つの区切りのバージョン番号は文字列です。

同じ変数が3か所にあるとき

/root/ks/inventory/lab/group_vars/all/all.ymlの末尾にkube_version: 1.34.11を一時的に追加してから、ansible -i /root/ks/inventory/lab/inventory.ini node1 -m debug -a var=kube_versionで実際の値を確認し、同じコマンドに-e kube_version=1.36.4を付けてもう一度確認してください。次のフィールドを書いてください(書き込み先: /root/ks/precedence.json)。all_yml(all.ymlに入れた値)、effective(-eなしで勝った値)、extra_vars(-eを指定したときの値)、winner_file(-eなしで勝った値が書かれたファイルの、インベントリを基準にした相対パス)です。そのあと、all.ymlに入れた行は削除します。

Ansibleでは、より具体的なグループのgroup_varsがallに勝ちます。k8s_clusterはallの子です。-eで渡したextra varsは、何よりも勝ちます。そのため、kubesprayのドキュメントは、-eを「内部変数を上書きするとき」に限って使うよう書いています。コマンドは、kubesprayのディレクトリで実行してください。

グループ名を間違えると何が壊れるのか

/root/ks/broken/inventory.iniは、誰かが[masters]と書いたインベントリです。直さずに、/opt/ks/kubesprayでansible-playbook -i /root/ks/broken/inventory.ini playbooks/boilerplate.ymlを実行してみてください。次のフィールドを書いてください(書き込み先: /root/ks/broken.json)。failed_task(失敗したタスクの名前、ロールの接頭辞なし)、node1_groups(このインベントリでnode1が属するグループ名のソートした配列、allとungroupedを除く)、missing_group(空であるはずがないのに空になっているkubesprayのグループ名)です。

エラーの文言は、グループ名が間違っているとは教えてくれません。失敗した条件式が、どのグループを探して失敗したかを読み取ってください。古い名前のkube-masterはkubesprayが自動で移してくれますが、mastersは違います。ノードが属するグループ(子グループを経由したものも含む)は、ansible ... -m debug -a var=group_namesで見られます。

自分のインベントリは検査を通過するか

/opt/ks/kubesprayでansible-playbook -i /root/ks/inventory/lab/inventory.ini playbooks/boilerplate.ymlを実行して、出力の全体を保存してください(保存先: /root/ks/logs/boilerplate.log)。PLAY RECAPでfailed=0である必要があります。

boilerplate.ymlは、cluster.yml・upgrade-cluster.yml・reset.ymlのすべてが、先頭で呼び出す検査のまとまりです。ここで止まるのは、インストールを始める前に止まるということなので、インストールの前に別に実行しておけば、長いプレイブックを実行して1分で止まることを避けられます。

このバージョンのkubesprayが受け入れる範囲

次のフィールドを書いてください(書き込み先: /root/ks/report.json)。kubespray_tag(git -C /opt/ks/kubespray describe --tags)、ansible_core(ansible --versionの1行目のバージョン番号。例: 2.19.0)、kube_version_default(このバージョンのデフォルトのkube_version)、kube_version_min(このバージョンが受け入れる最も低いバージョン)です。

kubesprayは、デフォルトのバージョンと最小のバージョンを別に書いておらず、roles/kubespray_defaults/vars/main/checksums.ymlのkubeletのチェックサム一覧から、最初のキーと最後のキーで計算します(roles/kubespray_defaults/defaults/main/main.yml)。チェックサムがないバージョンはインストールできないという意味です。