From 931d23e82768cb5f793d2e1b51679d4fb174bf87 Mon Sep 17 00:00:00 2001 From: Ruk Doe Date: Sun, 1 Nov 2026 12:13:14 +0900 Subject: [PATCH 1/2] =?UTF-8?q?tools=E3=83=BBbootstrap:=20=E5=B9=B3?= =?UTF-8?q?=E6=96=87=E3=81=AE=20machine=20config=20=E3=82=92=E6=89=8B?= =?UTF-8?q?=E5=85=83=E3=81=AB=E6=AE=8B=E3=81=95=E3=81=AA=E3=81=84=E3=83=BB?= =?UTF-8?q?Git=20Bash=20=E3=81=AE=E5=85=A5=E5=8F=A3=E3=83=BB=E8=A1=8C?= =?UTF-8?q?=E3=81=8D=E5=85=88=E3=81=AE=E8=87=AA=E5=8B=95=E5=88=87=E3=82=8A?= =?UTF-8?q?=E6=9B=BF=E3=81=88=E3=83=BBTalos=20=E3=81=AE=E6=96=87=E6=9B=B8?= =?UTF-8?q?=E3=82=92=201=20=E6=9C=AC=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - bootstrap/apply.sh: render.sh で /dev/shm に描いて apply-config し、終わったら消す。 手元に bootstrap/clusterconfig/ を作らない。古い talos/ の .gitignore も外す - tools/t: Git Bash から t.ps1 を呼ぶ入口。MSYS のパス変換を止め、端末でなければ標準入力を 渡さない (閉じないパイプで終わらなかった)。渡すときは --stdin - tools/creds.sh: 10.10.0.4 に届かなければ 10.0.0.2 に繋ぐ (2026-11-01 に NIC を付け替えて 10.10 から届かなくなったとき、手で kubeconfig を書き換えた)。GITOPS_EP で決め打ちできる - docs/talos.md を bootstrap/talos.md にまとめた (DL360 の頃の記述、二重の schematic の例を落とす)。 参照も直した Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01T9PbUfqG4pPxus99UeLiJs --- .github/workflows/cilium-drift.yml | 2 +- .github/workflows/talos-boot.yml | 2 +- .gitignore | 3 +- README.md | 2 +- ROADMAP.md | 2 +- bootstrap/README.md | 10 +- bootstrap/apply.sh | 14 ++ bootstrap/render.sh | 2 +- bootstrap/talos.md | 210 +++++++++++++------------- bootstrap/talos.sops.yaml | 4 +- deploy/3proxy/namespace.yaml | 2 +- deploy/adguardhome/namespace.yaml | 2 +- deploy/backup/etcd-snapshot.yaml | 2 +- deploy/cloudflare-ddns/namespace.yaml | 2 +- deploy/forgejo/namespace.yaml | 2 +- deploy/matrix/namespace.yaml | 2 +- deploy/netbird/namespace.yaml | 2 +- deploy/rybbit/namespace.yaml | 2 +- deploy/smtp-relay/namespace.yaml | 2 +- docs/decisions.md | 2 +- docs/talos.md | 156 ------------------- recovery/README.md | 12 +- tools/README.md | 10 +- tools/creds.sh | 24 ++- tools/t | 16 ++ 25 files changed, 196 insertions(+), 293 deletions(-) create mode 100755 bootstrap/apply.sh delete mode 100644 docs/talos.md create mode 100755 tools/t diff --git a/.github/workflows/cilium-drift.yml b/.github/workflows/cilium-drift.yml index 226f4ef1..00c55a45 100644 --- a/.github/workflows/cilium-drift.yml +++ b/.github/workflows/cilium-drift.yml @@ -49,7 +49,7 @@ jobs: # --kube-version が無いと helm の既定版で描かれて偽の差分が出る KV=$(k version -o json | jq -r .serverVersion.gitVersion) echo "kube-version=$KV" - export HOWTO="bootstrap/talos.md「inlineManifests を直したとき」の render.sh → apply-config → upgrade-k8s を流すこと" + export HOWTO="bootstrap/talos.md「machine config と inlineManifests」の apply.sh → upgrade-k8s を流すこと" # chart の版は render.sh の bver と同じく先頭の `# version:` V=$(sed -n '/^# version: /{s/^# version: *//p;q;}' bootstrap/cilium-values.yaml) diff --git a/.github/workflows/talos-boot.yml b/.github/workflows/talos-boot.yml index 267f8e97..6473a3a6 100644 --- a/.github/workflows/talos-boot.yml +++ b/.github/workflows/talos-boot.yml @@ -1,6 +1,6 @@ # bootstrap/render.sh の machine config を runner の QEMU(KVM)で起動し、クラスタが立つところまで見る。 # 秘密はゼロ(使い捨てとダミー)。外に副作用を出さない: ArgoCD の extraObjects と通知先、 -# 本物の ClusterIssuer(自己署名に差し替え)、infisical の SMTP を抜く。手順の元は docs/talos.md。 +# 本物の ClusterIssuer(自己署名に差し替え)、infisical の SMTP を抜く。手順の元は bootstrap/talos.md。 name: talos boot on: diff --git a/.gitignore b/.gitignore index f4281d38..16017e59 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ +# 描いた machine config(秘密を平文で含む)は bootstrap/apply.sh がコンテナの /dev/shm に置いて消す。手で描いたときの置き場だけ入らないようにしておく bootstrap/clusterconfig/ -# 2026-10 までの出力先(talos/ を bootstrap/ にまとめる前)。手元に残っていても入らないように -/talos/ # **平文のまま置かないこと。** bootstrap/talos-secrets.sops.yaml と talos.sops.yaml は SOPS 済みのものをコミットする # (bootstrap/talos.md)。書きかけの平文はこの名前に逃がす。 bootstrap/talos-secrets.plain.yaml diff --git a/README.md b/README.md index 8e151dbb..7844bd61 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ | [`mado/`](mado/) | **`main` が落ちたときの入口**。JCOM 側の PC(10.10.0.2)で [mado](https://github.com/danything/mado)(OIDC でログインしてブラウザから RDP する exe)を動かす(`md.doany.io`。クラスタの外) | | [`recovery/`](recovery/) | **まっさらから建て直す入口**(手順・PV を戻す道具・暗号化した鍵)。git と restic だけで戻す | | [`tools/`](tools/) + `compose.yaml` | **手元の運用のコマンド(cf・sops・infisical・kubectl・talosctl など)はコンテナで動かす**。`tools/t.ps1 <コマンド>`(Windows の WSL コンテナ。wslc-compose)。手元にコマンドは入れない | -| [`docs/`](docs/) | [決定の記録](docs/decisions.md)、[Talos の作法と検証](docs/talos.md)、[Entra ID の認可](docs/entra.md)、[家のルーター](docs/router.md)、[Cloudflare の API トークン](docs/cloudflare-tokens.md) | +| [`docs/`](docs/) | [決定の記録](docs/decisions.md)、[Entra ID の認可](docs/entra.md)、[家のルーター](docs/router.md)、[Cloudflare の API トークン](docs/cloudflare-tokens.md) | | [`ROADMAP.md`](ROADMAP.md) | やることと進捗(なぜそうしたかは `docs/decisions.md`) | | `deploy/argocd.yaml` | このリポジトリ自身の Application 定義(他のリポジトリと同じ場所) | | [`.sops.yaml`](.sops.yaml) | `bootstrap/*.sops.yaml` を SOPS(age)で暗号化する規則 | diff --git a/ROADMAP.md b/ROADMAP.md index cbd3b7ca..3364323e 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -52,7 +52,7 @@ Z440 は Intel AMT 9.x(ME 9.1)を持つ。OS が止まっていても**電源の **別名(`LinkAliasConfig`)を別の NIC に付け替えると、古い NIC の住所と接続経路が残る。** `AddressSpec` の名前(`jcom0/10.10.0.4/24`)が同じなので Talos が消さない。#667 では古い経路が先に当たり、10.10 から一切届かなくなった。hostNetwork・`NET_ADMIN` の使い捨ての Pod で `ip addr del 10.10.0.4/24 dev ens3f1` をして直した(再起動でも直る)。付け替える前に 10.0 側から入れるようにしておく -(Wi-Fi で BL1500HM につなぎ、`talosctl -e 10.0.0.2 -n 10.0.0.2`、kubectl は server を `https://10.0.0.2:6443` に)。 +(Wi-Fi で BL1500HM につなぐ。`tools/t` は 10.10.0.4 に届かなければ 10.0.0.2 に繋ぐ)。 ## 済んだこと(記録) diff --git a/bootstrap/README.md b/bootstrap/README.md index 26a158c4..c9aa8777 100644 --- a/bootstrap/README.md +++ b/bootstrap/README.md @@ -6,7 +6,7 @@ ArgoCD はここを見ない(例外は [argocd-repos.yaml](argocd-repos.yaml) | | 何を | いつ | | --- | --- | --- | -| **machine config**(このディレクトリ) | Talos の設定、Helm で入れるもの(cilium・cert-manager・argocd・infisical・lvm-localpv)、`apiserver-rbac.yaml`、`storage.yaml`、SOPS 済みの Secret 2 つ | `render.sh` → `apply-config` → `upgrade-k8s`([talos.md](talos.md)「上げ方 / 当て直し方」) | +| **machine config**(このディレクトリ) | Talos の設定、Helm で入れるもの(cilium・cert-manager・argocd・infisical・lvm-localpv)、`apiserver-rbac.yaml`、`storage.yaml`、SOPS 済みの Secret 2 つ | `apply.sh` → `upgrade-k8s`([talos.md](talos.md)「当て方」) | | **ArgoCD**(`deploy/`) | 平文のマニフェスト(`ClusterIssuer`・Gateway・auth・`InfisicalSecret` など)。2026-10 まではここにあって、Application `bootstrap` が当てていた | main へのマージ(prune / selfHeal 付き) | ## ファイル @@ -16,7 +16,7 @@ ArgoCD はここを見ない(例外は [argocd-repos.yaml](argocd-repos.yaml) | ファイル | 中身 | | --- | --- | | [render.sh](render.sh) | machine config を組む。下のファイルを全部読む | -| [talos.md](talos.md) | Talos の組み立てと当て直し方 | +| [talos.md](talos.md) | Talos の組み立て・書き方・当て方 | | [talos.sops.yaml](talos.sops.yaml) | 手で書く machine config(`password` の値だけ SOPS)。先頭のコメントに Talos・Kubernetes・Gateway API の版と schematic | | [talos-secrets.sops.yaml](talos-secrets.sops.yaml) | クラスタの CA 一式(丸ごと SOPS) | | [cilium-values.yaml](cilium-values.yaml) | chart の値と版(下の「Helm で入れるもの」) | @@ -77,15 +77,15 @@ Namespace は chart が描かないので、`render.sh` が kube-system 以外 **cilium だけは [cilium-drift.yml](../.github/workflows/cilium-drift.yml) が見ている**(下の「cilium」)。**残りは見ていない。** 直したら流す(流し忘れたことは誰も教えてくれない)。描くたびに変わる値は潰してあるので、 -`apply-config --dry-run` に出る差分は全部本物([talos.md](talos.md)「inlineManifests を直したとき」)。 +`apply-config --dry-run` に出る差分は全部本物([talos.md](talos.md)「machine config と inlineManifests」)。 ## cilium **クラスタの土台。** CNI・kube-proxy の代替・Gateway API を全部これが担う。 決定の経緯は [../docs/decisions.md](../docs/decisions.md)「ルーティングの選定」。 -[cilium-values.yaml](cilium-values.yaml) を直したら **`render.sh` → `apply-config` → `upgrade-k8s`** -([talos.md](talos.md)「上げ方 / 当て直し方」)。`helm upgrade` は使わない。値はここが正本で、machine config は +[cilium-values.yaml](cilium-values.yaml) を直したら **`apply.sh` → `upgrade-k8s`** +([talos.md](talos.md)「当て方」)。`helm upgrade` は使わない。値はここが正本で、machine config は `render.sh` がここから描く派生物(二度書かない。decisions.md「machine config と Cilium の chart をどう連動させるか」)。 **どの設定が何のために要るかは [cilium-values.yaml](cilium-values.yaml) のコメントにある**(ここには写さない)。 diff --git a/bootstrap/apply.sh b/bootstrap/apply.sh new file mode 100755 index 00000000..715765b7 --- /dev/null +++ b/bootstrap/apply.sh @@ -0,0 +1,14 @@ +#!/bin/sh +# machine config を描いて、そのまま当てる(talos.md「当て方」)。引数は talosctl apply-config に渡す: +# tools/t --admin bootstrap/apply.sh --dry-run # 差分だけ見る +# tools/t --admin bootstrap/apply.sh --mode=try --timeout 10m # 試しに当てる(確定は --mode=no-reboot で当て直す) +# tools/t --admin bootstrap/apply.sh --mode=no-reboot +# tools/t --admin bootstrap/apply.sh --insecure -n -e # maintenance mode のノード(recovery/README.md の 3) +# 描いたものは秘密を平文で含むので、コンテナの tmpfs(/dev/shm)に置いて、終わったら消す。手元のディスクには書かない。 +# 中身を見たいときは `tools/t --admin sh -c './bootstrap/render.sh /dev/shm/c && less /dev/shm/c/controlplane.yaml'`。 +set -eu +cd "$(dirname -- "$0")/.." +out=$(mktemp -d /dev/shm/clusterconfig.XXXXXX) +trap 'rm -rf "$out"' EXIT INT TERM +./bootstrap/render.sh "$out" +talosctl apply-config "$@" -f "$out/controlplane.yaml" diff --git a/bootstrap/render.sh b/bootstrap/render.sh index 346325e6..049899b3 100755 --- a/bootstrap/render.sh +++ b/bootstrap/render.sh @@ -1,5 +1,5 @@ #!/bin/sh -# machine config を作る: ./bootstrap/render.sh bootstrap/clusterconfig +# machine config を作る: ./bootstrap/render.sh <出力先>。ふだんは bootstrap/apply.sh が /dev/shm に描いて当てる # chart の値と版は bootstrap/-values(.sops).yaml、Talos などの版は talos.sops.yaml の先頭のコメントが正本。ここに写さない(../docs/decisions.md)。 # SOPS は自分で復号する。CI は鍵が無いので SECRETS などの env にダミーを渡す。 # 出力は秘密を含み、出力先は丸ごと作り直す。当て方は talos.md。 diff --git a/bootstrap/talos.md b/bootstrap/talos.md index 17cb5e9c..2d3b219e 100644 --- a/bootstrap/talos.md +++ b/bootstrap/talos.md @@ -1,141 +1,147 @@ # talos -ノード `main`(HP ProLiant DL360 Gen9)の machine config。**v1.14 以降の型付きドキュメントの形で書いてある** -(1.13 以前とは別物。作法は [../docs/talos.md](../docs/talos.md))。 -**入れ方(まっさらから建てる手順)は [../recovery/README.md](../recovery/README.md)。** ここは組み立てと当て直し。 +ノード `main`(HP Z440。箱の中身は [../ROADMAP.md](../ROADMAP.md)「ノード main(HP Z440)」)の machine config の組み立てと当て直し。 +**入れ方(まっさらから建てる手順)は [../recovery/README.md](../recovery/README.md)。** +SSH もシェルも無く gRPC API だけなので、**障害時は「直さず作り直す」**。調べるのは `talosctl dmesg` / `logs` / `read` / `pcap`、debug コンテナ。 -**版と schematic の出どころは [talos.sops.yaml](talos.sops.yaml) の先頭のコメント(`# version:` と `# schematic:`)。** Renovate がそこを見て、 -新しい Talos が出たら PR を作る。**適用は自動化しない**(下の「適用は CI にやらせない」)。talhelper は使わない。 +## 3 つの層と、変えたときにやること -**組み立ては [render.sh](render.sh) が全部やる。** 手で書く部分は [talos.sops.yaml](talos.sops.yaml) の 1 本だけで、 -他から描いてくる部分(Cilium・cert-manager・argocd・infisical・lvm-localpv は `-values(.sops).yaml` から、 -StorageClass と thin プールは [storage.yaml](storage.yaml) から)と 1 か所で組む。**値をどこにも二度書かない**のが目的。 -CI([talos-boot](../.github/workflows/talos-boot.yml))も同じ `render.sh` を使う -(別の作り方をすると「CI は通るが実機では通らない」が起きる)。 +**3 つの経路があり、混ぜない。** どれを使うかは「何を変えたか」で決まる。コマンドは `tools/t --admin …`(PowerShell からは `tools/t.ps1 --admin …`)で打つ +(資格情報と行き先は t が用意する。[../tools/README.md](../tools/README.md)「クラスタの資格情報」)。 -```shell -./bootstrap/render.sh bootstrap/clusterconfig # 出力先は丸ごと消して作り直す(.gitignore 済み) -``` +| 層 | 変えたもの | やること | 停止 | +| --- | --- | --- | --- | +| イメージ | `talos.sops.yaml` の先頭の Talos の `# version:` か `# schematic:`(拡張・カーネル引数) | `talosctl upgrade`(下の「Talos 本体」) | **再起動** | +| machine config | `talos.sops.yaml` の本文と、`bootstrap/` の残りの全部(`*-values(.sops).yaml`・`apiserver-rbac.yaml`・`storage.yaml`) | `bootstrap/apply.sh` → `talosctl upgrade-k8s --to <今の版>`(下の「machine config と inlineManifests」) | 場合による | +| | `talos.sops.yaml` の先頭の Kubernetes の `# version:` | `bootstrap/apply.sh` → `talosctl upgrade-k8s --to <新しい版>` | 無し | +| Kubernetes | ワークロード | Argo CD(`deploy/`・各リポジトリの `deploy/`) | — | -描いた machine config はコミットしない(理由は [../docs/decisions.md](../docs/decisions.md)「machine config と Cilium の chart をどう連動させるか」)。 -**inlineManifest をファイルで指す仕組みは Talos に無い**(machine config はノードが読むので手元のパスは書けない。 -外を指せるのは URL の `KubeExternalManifestConfig` だけで、CRD はそれで渡している)。ファイルを包むのは render.sh の `inline`。 +**版と schematic の正は [talos.sops.yaml](talos.sops.yaml) の先頭のコメント。** Renovate がそこを見て PR を作る。**適用は自動化しない** +(1 ノードではマージが即停止になる。Talos API は mTLS だけで OIDC を受けないので、CI に `os:admin` の証明書を置くことになる)。 +**検出は自動、適用は手動。** talhelper は使わない。 -**Talos の秘密は 2 か所、どちらも SOPS でコミット済み**(暗号化の決まりは [README.md](README.md) の「ファイル」の下)。 -[talos-secrets.sops.yaml](talos-secrets.sops.yaml) はクラスタの CA 一式(`talosctl gen secrets` の形)で丸ごと、 -[talos.sops.yaml](talos.sops.yaml) は `password` の値(下の fj.doany.io の資格情報)**だけ**。 +## 組み立て -**`talos-secrets.sops.yaml` を作り直すと別のクラスタになる**(`apiserver-ca.crt` と Infisical の Kubernetes auth の CA も -替えることになる)ので触らない。まっさらから組むときだけ: +**組み立ては [render.sh](render.sh) が全部やる。** 手で書くのは [talos.sops.yaml](talos.sops.yaml) の 1 本だけで、ほかから描いてくる部分 +(Cilium・cert-manager・argocd・infisical・lvm-localpv は `-values(.sops).yaml` から、StorageClass と thin プールは [storage.yaml](storage.yaml) から)と +1 か所で組む。**値をどこにも二度書かない**のが目的。CI([talos-boot](../.github/workflows/talos-boot.yml))も同じ `render.sh` を使う。 -```shell -talosctl gen secrets -o bootstrap/talos-secrets.sops.yaml && sops -e -i bootstrap/talos-secrets.sops.yaml -``` +**描いたものは秘密を平文で含むので、手元に置かない。** [apply.sh](apply.sh) がコンテナの `/dev/shm` に描いて当て、終わったら消す。 +引数は `talosctl apply-config` に渡る(`--dry-run` で差分だけ見られる。何も変えていなければ差分は出ない。描くたびに変わる値は潰してある)。 +描いたものはコミットしない([../docs/decisions.md](../docs/decisions.md)「machine config と Cilium の chart をどう連動させるか」)。 -## fj.doany.io の資格情報 +**Talos の秘密は 2 か所、どちらも SOPS でコミット済み。** [talos-secrets.sops.yaml](talos-secrets.sops.yaml) はクラスタの CA 一式で丸ごと、 +[talos.sops.yaml](talos.sops.yaml) は `password` の値(下の fj.doany.io)**だけ**。**`talos-secrets.sops.yaml` を作り直すと別のクラスタになる** +(`apiserver-ca.crt` と Infisical の Kubernetes auth の CA も替わる)ので触らない。まっさらから組むときだけ +`talosctl gen secrets -o bootstrap/talos-secrets.sops.yaml && sops -e -i bootstrap/talos-secrets.sops.yaml`。 -ノード単位で持つので **namespace ごとの `imagePullSecrets` が要らない**(talos.sops.yaml の `machine.registries`)。 -持つのは **fj.doany.io**(Forgejo のコンテナレジストリ)だけで、Forgejo のユーザー `yui` の -`read:package` だけのトークン(全リポジトリ。Forgejo の名前は `talos-registry-pull`)。値は talos.sops.yaml の中で暗号化してある。 -`username` は Forgejo が見ない(トークンの持ち主で決まる。`info` のままにしてあるが、何でも通る)。無いと非公開のリポジトリの -イメージが引けない。ghcr.io に残るイメージは全部公開。 +**CI は PR ごとに使い捨ての秘密で `render.sh` を通し、QEMU で起動する**(talos-boot。`ENC[…]` は `ci-dummy` に置き換える)。 +`render.sh` は `talosctl validate --mode metal` に加えて、生成物に想定の設定が入っているかまで見る +(**`gen config` は知らないキーを警告なく捨てることがある**。needle は `render.sh` の末尾の 1 か所)。 +VM で確かめられないのは PT3 と bond の復旧方向。所要は apply → apid 75 秒 → Ready 200 秒 → bootstrap 層 120 秒。 -**fj.doany.io はこれだけでは取れない。** 公開 DNS の A(WAN 側)にはノードから届かないので、 -ノードの名前解決で fj.doany.io をノード自身(10.0.0.2 の Gateway)に向ける(talos.sops.yaml の `StaticHostConfig`)。 +### machine config の書き方(v1.14 以降) -CI には age の鍵を渡さないので、talos.sops.yaml の `ENC[…]` を `ci-dummy` に置き換えて経路だけ通している(`-values.sops.yaml` も同じやり方)。 +`talosctl gen config` は **型付きドキュメントの束**を吐き、同じ項目を v1alpha1 側にも書くと弾かれる(`... is already set in v1alpha1 config`)。 -**talos.sops.yaml は PR ごとに CI が検証する。** 使い捨ての秘密で `render.sh` を通す。`render.sh` は `talosctl validate --mode metal` に加えて、 -生成物に想定の設定(`ks.doany.io`・OIDC の issuer・bond の `balance-alb` など)が実際に入っているかまで見る -── **`gen config` は知らないキーを警告なく捨てることがある**ので、通ったことだけでは足りない。 -needle は `render.sh` の末尾の 1 か所だけに置く。 +| やりたいこと | 書き場所 | +| --- | --- | +| pod / service の CIDR | `KubeNetworkConfig`。**service の IPv6 は `/108` 以下** | +| インストール先ディスク | `UnattendedInstallConfig` の `provisioning.diskSelector.match`(CEL 式) | +| カーネル引数 | **schematic の `customization.extraKernelArgs`**(`machine.install.extraKernelArgs` は衝突する) | +| bond とそのメンバー | `BondConfig` / `LinkConfig`。NIC は名前でなく元の MAC で `LinkAliasConfig` の別名を付ける。**別名を別の NIC に付け替えると古い NIC の住所が残る**([../ROADMAP.md](../ROADMAP.md)「AMT」) | +| PV の置き場 | `RawVolumeConfig` を `LVMVolumeGroupConfig` で VG に(thin の LV は Talos では作れない。[README.md](README.md)「PVC の置き場」)。**ボリュームは未割り当ての領域にしか作られず、あとから `apply-config` しても黙って無視される** | +| control-plane への scheduling | `KubeNodeConfig` を `$patch: delete` して `labels` だけ書き戻す | +| CNI を止める | `KubeFlannelCNIConfig` を `$patch: delete`、`KubeProxyConfig` を `enabled: false`(Cilium に替えてある。[../docs/decisions.md](../docs/decisions.md)「ルーティングの選定」) | +| カーネルモジュール | `machine.kernel.modules`。名前の順に読まれる。v1.15.0-alpha.2 からはカーネルの要求でも読むので、書くのは自分からは読まれないものだけ | +| sysctl | **カーネルの名前で書く**(別名は使えない)。**無い名前の行を残さない**(`KernelParamSpecController` が止まり、後の sysctl が当たらない) | -**適用は CI にやらせない。** machine config の適用は再起動を伴うことがあり、1 ノードでは -マージが即停止になる。Talos API は mTLS のみで OIDC を受けないため、CI に渡すには -`os:admin` のクライアント証明書を置くことになる。**検出は自動、適用は手動**。 +- `talosctl` の `--nodes` / `--endpoints` はグローバルフラグではない(`talosctl get links --insecure -n … -e …` の順)。`apply-config -m reboot` は無い +- 受信の防火壁は Talos(`NetworkDefaultActionConfig`)ではなく **Cilium の Host Firewall**(`cilium-values.yaml` の `hostFirewall` と + `../deploy/cluster/host-firewall.yaml`)。Talos の防火壁は conntrack の invalid を捨てる規則を必ず入れ、Cilium は Envoy から Pod への帰りを + NOTRACK にするので、Pod からノードの IP の Gateway(fj.doany.io)への 2 つ目以降のパケットが捨てられた(#646 → #652 → #658)。 + talos-boot が「外から 10250 は通らない」「Pod からノードの IP の Gateway に届く」を見ている -## 上げ方 / 当て直し方 +### PSA のラベル -**3 つの経路があり、混ぜない。** どれを使うかは「何を変えたか」で決まる。下のコマンドは `tools/t.ps1 --admin` のシェルで打つ -(talosctl / kubectl の資格情報と行き先 10.10.0.4 は t.ps1 が用意する。[../tools/README.md](../tools/README.md)「クラスタの資格情報」)。 +`KubeAdmissionControlConfig` は `enforce: baseline`(例外は `kube-system`)。**`hostPath` / `privileged` / `hostNetwork` / `hostPort` を使う namespace は +`namespace.yaml` に `enforce: privileged` が要る。** 無いと Pod が作られず、ReplicaSet や DaemonSet の events に出るだけ。 +今あるのは netbird・denpa(**ラベルは denpa リポジトリの `deploy/namespace.yaml`**)・adguardhome・matrix・3proxy・cloudflare-ddns・forgejo。 +新しく足すときは `kubectl get pods -A -o json` で hostNetwork・privileged・capabilities・hostPort・hostPath を数えて洗い出す。 -| 変えたもの | やること | 停止 | -| --- | --- | --- | -| `talos.sops.yaml` の先頭の Talos の `# version:`(または `# schematic:`) | `talosctl upgrade --image factory.talos.dev/installer/:<版> --k8s-endpoint https://10.10.0.4:6443` | **再起動** | -| `talos.sops.yaml` の先頭の Kubernetes の `# version:` | `render.sh` → `apply-config` → `talosctl upgrade-k8s --to <新しい版>` | 無し | -| `talos.sops.yaml` の本文と、`bootstrap/` の残りの全部(`*-values(.sops).yaml`(2 つめのドキュメントの Secret も)・`apiserver-rbac.yaml`・`storage.yaml`) | `render.sh` → `apply-config` → `talosctl upgrade-k8s --to <今の版>`(下の「inlineManifests を直したとき」) | 場合による | +## 当て方 -**ノードの受信の防火壁は Talos(`NetworkDefaultActionConfig`・`NetworkRuleConfig`)ではなく Cilium の Host Firewall** -(`cilium-values.yaml` の `hostFirewall` と `../deploy/cluster/host-firewall.yaml`)。Talos の防火壁は conntrack の invalid を捨てる規則を -必ず入れ(`ingress: accept` でも残る)、Cilium は Envoy から Pod への帰りを raw の OUTPUT で NOTRACK にするので、Pod からノード自身の IP の -Gateway(Pod は fj.doany.io の AAAA = ノードの公開 IPv6 で Forgejo に来る)の 2 つ目以降のパケットが invalid として捨てられた -(2026-10-31。#646 で入れ、#652 で外し、#658 で Cilium にした。`nf_conntrack_tcp_be_liberal` では直らない)。 -talos-boot が「外から 10250 は通らない」「Pod からノードの IP の Gateway に届く」を見ている。 +### machine config と inlineManifests -**ネットワーク(`BondConfig`・`LinkConfig`・`LinkAliasConfig` など)を変えたら `--mode=try` で当てる。** -間違えると Talos の API ごと届かなくなるが、`try` なら時間が来れば元に戻る: +**Cilium・OpenEBS LVM・`apiserver-rbac.yaml`・ArgoCD・infisical・cert-manager と SOPS 済みの Secret 2 つは machine config の中にいる**ので、 +直しただけでは何も起きない。`apply-config` は起動時にしか inlineManifests を読まず、**`upgrade-k8s`(同じ版でも)が SSA とインベントリで更新も削除もする**: ```shell -talosctl apply-config --mode=try --timeout 5m -f bootstrap/clusterconfig/controlplane.yaml -# 5 分のうちに確かめる(talosctl get members・kubectl get nodes・外からの Web・DoT・NetBird) +tools/t --admin bootstrap/apply.sh --dry-run # 差分を見る +tools/t --admin bootstrap/apply.sh --mode=no-reboot # 再起動が要るなら当てずに止まる +tools/t --admin talosctl get manifests -o yaml | grep -c '<新しくなるはずの版(例: cilium:v1.20.4)>' # 反映を待つ +tools/t --admin talosctl upgrade-k8s --to --endpoint https://10.10.0.4:6443 ``` -**確定させるときは、時間内に同じファイルを当て直さない。** 動いている設定と同じなので `Apply was skipped: no changes detected` で -飛ばされ、**ディスクには残らないのに、元に戻す時計だけが止まる**(2026-10-31 に防火壁で踏んだ。再起動で消える状態になる)。 -元に戻るのを待ってから(`talosctl get nftableschains ingress` などで見る)`--mode=no-reboot` で当て直す。 -時計が止まってしまったら、動いている設定(`talosctl get mc v1alpha1 -o jsonpath='{.spec}'`)に害の無いドキュメントを 1 つ足して -`--mode=no-reboot` で当て、足す前の設定をもう一度当てると、ディスクに残る。 +- **`upgrade-k8s` には `--to` と `--endpoint` を付ける。** `--to` を省くと talosctl の既定の版に上がり、`--endpoint` を省くと 10.0.0.2 に行く +- **`apply-config` の直後に流さない。** `talosctl get manifests` に新しい版が出る前に流すと、古いマニフェストで「変更なし」で終わる +- **`upgrade-k8s` の前には必ず `apply.sh`。** 古い machine config のまま流すと、走っている Cilium が巻き戻る +- `argocd-redis-secret-init`(argocd)や `cert-manager-startupapicheck` の Job で時間切れ・`field is immutable` になったら、 + その Job を消して流し直す(終わると 60 秒で消えるので、待っている間に消えて後ろの Deployment まで当たらないことがある) -### inlineManifests を直したとき +### ネットワークを変えたとき -**Cilium・OpenEBS LVM(`storage.yaml` も)・`apiserver-rbac.yaml`・ArgoCD・infisical・ -cert-manager と、SOPS 済みの Secret 2 つは machine config の中にいる。** -だから**マニフェストを直しただけでは何も起きない。** 描き直して当てる: +**`BondConfig`・`LinkConfig`・`LinkAliasConfig` などを変えたら `--mode=try` で当てる。** 間違えると API ごと届かなくなるが、時間が来れば元に戻る: ```shell -./bootstrap/render.sh bootstrap/clusterconfig -talosctl apply-config --mode=no-reboot -f bootstrap/clusterconfig/controlplane.yaml # 再起動が要るなら当てずに止まる -talosctl get manifests -o yaml | grep -c '<新しくなるはずの版(例: cilium:v1.20.4)>' # 反映を待つ(下) -talosctl upgrade-k8s --to --endpoint https://10.10.0.4:6443 # ← これが inlineManifests を reconcile する +tools/t --admin bootstrap/apply.sh --mode=try --timeout 10m +# 時間内に確かめる(talosctl get links・kubectl get nodes・外からの Web・DoT・NetBird)→ 確定 +tools/t --admin bootstrap/apply.sh --mode=no-reboot ``` -`render.sh` は出力先を丸ごと消すので、`bootstrap/clusterconfig/` に置いたものは消える。 - -- **`upgrade-k8s` には必ず `--to` を付ける。** 省くと talosctl の既定の版に上がる(Talos の alpha の talosctl なら Kubernetes も alpha)。 - 版を変えないなら `talos.sops.yaml` の先頭の今の版を渡す -- **`--endpoint https://10.10.0.4:6443` も付ける。** `upgrade-k8s` は Kubernetes の API に直接繋ぎに行き、既定ではクラスタの - endpoint(10.0.0.2)へ行くので作業用 PC からは届かない -- **`apply-config` の直後に流さない。** machine config から `manifests` の資源が作り直されるまで少しかかり、その前に流すと**古いマニフェストで - 「変更なし」のまま終わる**(2026-10-23 に Cilium 1.20.4 で踏んだ)。`talosctl get manifests` に新しい版が出てから流す - -- **`apply-config` だけでは inlineManifests は動かない。** 起動時にしか読まれない -- **`upgrade-k8s` は版を上げなくても reconcile する。** SSA とインベントリで**更新も削除も**する - ([../docs/talos.md](../docs/talos.md)「inlineManifests は「更新できない」ではない」) -- **したがって `upgrade-k8s` の前には必ず `render.sh` → `apply-config`。** 古い machine config のまま流すと**走っている Cilium が巻き戻る** -- **`timeout waiting for: [Job/argocd/argocd-redis-secret-init status: 'NotFound']` で終わったら、もう一度流す。** 逆に `argocd-redis-secret-init` が `field is immutable` で落ちたら、前の回の Job が残っている。完了済みなので `kubectl -n argocd delete job argocd-redis-secret-init` してから流し直す。 - cert-manager を上げたときの `cert-manager-startupapicheck` も同じ(`kubectl -n cert-manager delete job cert-manager-startupapicheck`。2026-10-24 に 1.21.3 で踏んだ)。 - この Job は終わると 60 秒で消える(`ttlSecondsAfterFinished`)ので、待っている間に消えて時間切れになり、 - その後ろの Deployment まで当たらないことがある。 - 当て終わったら `kubectl -n argocd get deploy -o wide` でイメージの版を見る -- **何も変えていなければ `apply-config --dry-run` の差分は出ない。** 描くたびに変わる値は潰してある - (Hubble の証明書はクラスタの中で作る、infisical の `postgres-password` は infisical-values.sops.yaml に固定、`updatedAt` は `render.sh` が落とす)。 - 差分が出たら、それは本当に変わったもの +- 10.10.0.4 に届かなくなったら、Wi-Fi などで 10.0 側につなぐ。t は 10.10.0.4 に届かなければ 10.0.0.2 に繋ぐ +- 確定で `Apply was skipped: no changes detected` と出たら、**ディスクには残らずに元に戻す時計だけが止まっている**(2026-10-31 に踏んだ。 + 2026-11-01 の NIC の付け替えでは skip されずに確定した)。そのときは元に戻るのを待ってから当て直すか、動いている設定に害の無い + ドキュメントを 1 つ足して当て、足す前のものをもう一度当てる ### Talos 本体 ```shell -talosctl upgrade --image factory.talos.dev/installer/:<版> --k8s-endpoint https://10.10.0.4:6443 +tools/t --admin talosctl upgrade --image factory.talos.dev/installer/:<版> --k8s-endpoint https://10.10.0.4:6443 ``` -**`--k8s-endpoint` を必ず付ける。** 再起動の前にノードを cordon するが、既定では kubeconfig の endpoint(10.0.0.2)へ行き、 -作業用 PC からは届かない。付け忘れると `error cordoning node … i/o timeout` で**再起動せずに止まる**(書き込みは済んでいるので、付けて打ち直せばよい。 -2026-10-29 に alpha.2 で踏んだ。このフラグは v1.15.0-alpha.2 の talosctl から)。再起動の待ちは長いので、Claude Code の `!` では裏に回る。 +- **`--k8s-endpoint` を必ず付ける。** 付け忘れると cordon が 10.0.0.2 に行って `i/o timeout` で**再起動せずに止まる**(書き込みは済んでいるので、付けて打ち直す) +- 再起動の前に drain する。denpa は録画やエンコードが終わるまで止まらない(猶予 6 時間)ので、時間切れになったら Pod を消して進める +- **A/B なので失敗すれば前のイメージに戻る。** ノードが 1 台なので再起動 = 全停止で、だから自動化しない +- 再起動の待ちは長いので、Claude Code の `!` では裏に回る -**A/B なので失敗すれば前のイメージに戻る。** ノードが 1 台なので再起動 = 全停止で、だから自動化しない -(tuppr / system-upgrade-controller はどちらも自分が乗っているノードは上げないので 1 台では成立しない)。 -**schematic を変えたとき(拡張やカーネル引数)も同じコマンド。** ISO を焼き直す必要はない。 +### schematic(イメージ) + +Talos は拡張とカーネル引数を焼き込んだイメージを https://factory.talos.dev で作る。中身(**schematic**)は YAML で、その内容のハッシュが ID になる。 +今の中身は [talos.sops.yaml](talos.sops.yaml) の先頭のコメントに書いてある(`https://factory.talos.dev/schematics/` でも引ける)。変えるときは: + +```shell +curl -X POST --data-binary @schematic.yaml https://factory.talos.dev/schematics # => {"id":"…"}。ID を talos.sops.yaml の `# schematic:` に +``` -### 当てても効かないもの +ISO は `https://factory.talos.dev/image//<版>/metal-amd64.iso`(Secure Boot 用は使わない)、`upgrade` と `--install-image` は +`factory.talos.dev/installer/:<版>`。プレリリースも同じ形。schematic を変えても ISO を焼き直す必要はない。 + +## fj.doany.io の資格情報 + +ノード単位で持つので **namespace ごとの `imagePullSecrets` が要らない**(`machine.registries`)。持つのは fj.doany.io(Forgejo のレジストリ)だけで、 +Forgejo のユーザー `yui` の `read:package` だけのトークン(名前は `talos-registry-pull`。`username` は見られない)。ghcr.io に残るイメージは全部公開。 +公開 DNS の A(WAN 側)にはノードから届かないので、ノードの名前解決で fj.doany.io をノード自身に向けている(`StaticHostConfig`)。 + +## etcd スナップショットから戻す(近道) + +主経路は git から建て直すほう([../recovery/README.md](../recovery/README.md))。git に無い状態(Application の同期状態、発行済みの証明書など)まで +一度に戻したいときだけ。日次で [../deploy/backup/etcd-snapshot.yaml](../deploy/backup/etcd-snapshot.yaml) が `/etcd` に取っている +(`restic snapshots --host etcd` → `restic dump /work/etcd.snapshot > etcd.snapshot`)。 + +```shell +# 同じ talos-secrets.sops.yaml で描いた machine config を ISO のノードに当てたあと(PKI が一致しないと戻せない) +talosctl bootstrap --recover-from=./etcd.snapshot # etcd が上がるまで `bootstrap is not available yet`。数分待って再試行 +``` -**ディスクの割り方**(talos.sops.yaml の `VolumeConfig` / `UserVolumeConfig`)。ボリュームは**まだ確保されていないときにしか -効かない**ので、あとから `apply-config` しても黙って無視される。変えるには入れ直し。 +PV の中身は戻らないので、そのあと VolSync で戻す(etcd が先。PV オブジェクトが無いと戻す先が決まらない)。 diff --git a/bootstrap/talos.sops.yaml b/bootstrap/talos.sops.yaml index 084d9835..edc360fe 100644 --- a/bootstrap/talos.sops.yaml +++ b/bootstrap/talos.sops.yaml @@ -5,12 +5,12 @@ # パスワードを変えるときは `sops edit bootstrap/talos.sops.yaml`。render.sh が `sops -d` してから渡す。 # 各ドキュメントの末尾の `sops:` は SOPS のメタデータ(触らない)。 # -# 型付きドキュメントと v1alpha1 で書く場所が決まっている(../docs/talos.md「machine config の作法」)。 +# 型付きドキュメントと v1alpha1 で書く場所が決まっている(talos.md「machine config の書き方(v1.14 以降)」)。 # ドキュメントは上から順に当たる(KubeNodeConfig の delete → 書き戻し は順番に意味がある)。 # # Talos・Kubernetes・Gateway API の版と schematic。chart の -values.yaml と同じく、`# renovate:` の次の # `# version:` の行を Renovate が上げ、render.sh が読む(値にすると machine config に混ざるのでコメント)。 -# 適用は手で(ノード 1 台なので upgrade は全停止)。手順は talos.md「上げ方 / 当て直し方」。 +# 適用は手で(ノード 1 台なので upgrade は全停止)。手順は talos.md「当て方」。 # # Talos。Factory のレジストリはタグ一覧を返さないので github-releases で追う。tools/Dockerfile の talosctl と同じ depName。 # dvb-pt3 が v1.15.0-alpha.1 からなので alpha に乗っている(Renovate は次の alpha / beta も出す)。 diff --git a/deploy/3proxy/namespace.yaml b/deploy/3proxy/namespace.yaml index 9b7fb0a0..e9e90276 100644 --- a/deploy/3proxy/namespace.yaml +++ b/deploy/3proxy/namespace.yaml @@ -1,5 +1,5 @@ # PSA は privileged。理由: hostPort 3129(TLS 終端サイドカー)が baseline に通らない。 -# 一覧と背景は docs/talos.md「PSA のラベル」。 +# 一覧と背景は bootstrap/talos.md「PSA のラベル」。 apiVersion: v1 kind: Namespace metadata: diff --git a/deploy/adguardhome/namespace.yaml b/deploy/adguardhome/namespace.yaml index 0e026eea..90e0b409 100644 --- a/deploy/adguardhome/namespace.yaml +++ b/deploy/adguardhome/namespace.yaml @@ -1,5 +1,5 @@ # PSA は privileged。理由: hostPort 53 / 853 が baseline に通らない。 -# 一覧と背景は docs/talos.md「PSA のラベル」。 +# 一覧と背景は bootstrap/talos.md「PSA のラベル」。 apiVersion: v1 kind: Namespace metadata: diff --git a/deploy/backup/etcd-snapshot.yaml b/deploy/backup/etcd-snapshot.yaml index 0b5545a0..203d6dad 100644 --- a/deploy/backup/etcd-snapshot.yaml +++ b/deploy/backup/etcd-snapshot.yaml @@ -3,7 +3,7 @@ # **戻すときの主経路ではない。** 主経路は「git から Argo CD で建て直して PV を VolSync で戻す」 # (recovery/README.md)。こちらは git に無い状態 # (Argo CD が作った Application の同期状態、cert-manager の発行済み証明書など)まで含めて**一瞬で戻したいとき**の近道。 -# 戻し方は docs/talos.md「etcd スナップショットからの復旧」の `bootstrap --recover-from`。 +# 戻し方は bootstrap/talos.md「etcd スナップショットから戻す(近道)」。 # # Talos API への権限は `os:etcd:backup` だけ(bootstrap/talos.sops.yaml)。 # 下の ServiceAccount を見て Talos が同名の Secret に talosconfig を書く。 diff --git a/deploy/cloudflare-ddns/namespace.yaml b/deploy/cloudflare-ddns/namespace.yaml index bd0f9682..e01e8b91 100644 --- a/deploy/cloudflare-ddns/namespace.yaml +++ b/deploy/cloudflare-ddns/namespace.yaml @@ -1,5 +1,5 @@ # PSA は privileged。理由: hostNetwork が baseline に通らない。 -# 一覧と背景は docs/talos.md「PSA のラベル」。 +# 一覧と背景は bootstrap/talos.md「PSA のラベル」。 apiVersion: v1 kind: Namespace metadata: diff --git a/deploy/forgejo/namespace.yaml b/deploy/forgejo/namespace.yaml index e6f3a65a..ca3d8bec 100644 --- a/deploy/forgejo/namespace.yaml +++ b/deploy/forgejo/namespace.yaml @@ -1,5 +1,5 @@ # PSA は privileged。理由: Runner の docker(dind)が privileged で動く(runner.yaml)。 -# 一覧と背景は docs/talos.md「PSA のラベル」。 +# 一覧と背景は bootstrap/talos.md「PSA のラベル」。 apiVersion: v1 kind: Namespace metadata: diff --git a/deploy/matrix/namespace.yaml b/deploy/matrix/namespace.yaml index d88b8fa4..aa4494fb 100644 --- a/deploy/matrix/namespace.yaml +++ b/deploy/matrix/namespace.yaml @@ -1,5 +1,5 @@ # PSA は privileged。理由: LiveKit が hostPort 8443(UDP・TCP。通話の音声と映像)を持ち、baseline に通らない。 -# 一覧と背景は docs/talos.md「PSA のラベル」。 +# 一覧と背景は bootstrap/talos.md「PSA のラベル」。 apiVersion: v1 kind: Namespace metadata: diff --git a/deploy/netbird/namespace.yaml b/deploy/netbird/namespace.yaml index ff457f08..f52c9acd 100644 --- a/deploy/netbird/namespace.yaml +++ b/deploy/netbird/namespace.yaml @@ -1,4 +1,4 @@ -# PSA は privileged。理由: routing peer の hostPort(WireGuard の 51820)と NET_ADMIN が baseline に通らない。一覧と背景は docs/talos.md「PSA のラベル」。 +# PSA は privileged。理由: routing peer の hostPort(WireGuard の 51820)と NET_ADMIN が baseline に通らない。一覧と背景は bootstrap/talos.md「PSA のラベル」。 apiVersion: v1 kind: Namespace metadata: diff --git a/deploy/rybbit/namespace.yaml b/deploy/rybbit/namespace.yaml index 2b5bae4e..dffa7de0 100644 --- a/deploy/rybbit/namespace.yaml +++ b/deploy/rybbit/namespace.yaml @@ -1,5 +1,5 @@ # PSA は baseline。hostPort も privileged も無い(ClickHouse は uid 101、postgres は起動時に root から落とすだけ)。 -# 一覧と背景は docs/talos.md「PSA のラベル」。 +# 一覧と背景は bootstrap/talos.md「PSA のラベル」。 apiVersion: v1 kind: Namespace metadata: diff --git a/deploy/smtp-relay/namespace.yaml b/deploy/smtp-relay/namespace.yaml index 9977c87f..59ab5677 100644 --- a/deploy/smtp-relay/namespace.yaml +++ b/deploy/smtp-relay/namespace.yaml @@ -1,4 +1,4 @@ -# PSA は restricted(特権も hostPort も要らない)。baseline に通らない namespace の一覧は docs/talos.md「PSA のラベル」で、ここは載らない。 +# PSA は restricted(特権も hostPort も要らない)。baseline に通らない namespace の一覧は bootstrap/talos.md「PSA のラベル」で、ここは載らない。 apiVersion: v1 kind: Namespace metadata: diff --git a/docs/decisions.md b/docs/decisions.md index 5076e1e0..76a0e249 100644 --- a/docs/decisions.md +++ b/docs/decisions.md @@ -119,7 +119,7 @@ Talos には helm-controller が無く、inlineManifests は Helm を実行で `bootstrap/cilium-values.yaml` の先頭の `# version:` を見ていて、machine config は毎回そこから描き直されるだけ。 **`helm upgrade` は使わない。** 更新経路は「`cilium-values.yaml` を直す → 描き直す → `upgrade-k8s`」。古い machine config のまま -`upgrade-k8s` を流すと走っている Cilium が巻き戻る([../bootstrap/talos.md](../bootstrap/talos.md)「上げ方 / 当て直し方」)。 +`upgrade-k8s` を流すと走っている Cilium が巻き戻る([../bootstrap/talos.md](../bootstrap/talos.md)「当て方」)。 流し忘れは [cilium-drift.yml](../.github/workflows/cilium-drift.yml) が週次で live と突き合わせる。 bootstrap のあとに `helm install` する案は、再構築のたびに「CNI が無いので何も動かない」状態での手作業が増えるので採らない。 diff --git a/docs/talos.md b/docs/talos.md deleted file mode 100644 index 669489fe..00000000 --- a/docs/talos.md +++ /dev/null @@ -1,156 +0,0 @@ -# Talos Linux — イメージと machine config の作法 - -対象: HP Z440(2026-10-31 から。箱の中身は [../ROADMAP.md](../ROADMAP.md)「ノード main(HP Z440)」、遠隔管理は AMT の 10.10.0.3)。 -ディスクは **SATA の SSD(Radeon R7、447 GB)**で、Linux からは `/dev/sda`。それより前は DL360 Gen9(iLO は 10.0.0.3。SSD は Smart Array 越し)。 -版は [bootstrap/talos.sops.yaml](../bootstrap/talos.sops.yaml) の先頭のコメント(`# version:`)が正。 -入れ方は [recovery/README.md](../recovery/README.md)、組み立てと当て直しは [bootstrap/talos.md](../bootstrap/talos.md)。 - -## Image Factory の schematic - -Talos は必要な system extension を焼き込んだイメージを https://factory.talos.dev で作る。 -組み合わせは **schematic** という YAML で表し、その内容のハッシュが schematic ID になる(同じ YAML なら誰が作っても同じ ID)。 - -この箱に要る extension は intel-ucode と dvb-pt3(BCM5719 の tg3、bonding、AHCI は Talos のカーネルに入っている)。 -dvb-pt3 は PT3 チューナーのドライバ([decisions.md](decisions.md)「PT3 チューナー」)。 -**カーネル引数もここに入れる。** v1.14 以降は `machine.install` が `UnattendedInstallConfig` と衝突して machine config 側に -書けないため。 - -```yaml -# schematic.yaml (本番用) -customization: - extraKernelArgs: - - intel_iommu=on # 元は PT3 を KubeVirt に渡すため。dvb-pt3 が入ったいまは要らないが、パススルーの道として残す - - iommu=pt - - console=tty0 # AMT の SOL(ttyS0)。後に書いたほうが /dev/console になる - - console=ttyS0,115200n8 - systemExtensions: - officialExtensions: - - siderolabs/dvb-pt3 - - siderolabs/i915 # Arc A310 - - siderolabs/intel-ucode - - siderolabs/mei # Arc の HuC(bootstrap/talos.sops.yaml の先頭のコメント) -``` - -```shell -curl -X POST --data-binary @schematic.yaml https://factory.talos.dev/schematics -# => {"id":"96371c8f956f7f5f9d09925bb49fe096c0cad05c5cf5bdb464790982c0b067ca"} -``` - -| 用途 | URL | -| --- | --- | -| ISO(Secure Boot オフ) | `https://factory.talos.dev/image//<版>/metal-amd64.iso`(Secure Boot 用の `metal-amd64-secureboot.iso` は UEFI に鍵登録が要るので使わない) | -| `--install-image` と `talosctl upgrade --image` | `factory.talos.dev/installer/:<版>` | - -プレリリース(alpha / beta)も同じ形の URL で取れる。extension を足したくなったら schematic を作り直して ID を差し替え、 -`talosctl upgrade` で当てる(ISO を焼き直す必要はない)。 - -## machine config の作法(v1.14 で確認) - -**1.13 以前の書き方は通らない。** `talosctl gen config` は v1alpha1 の 1 枚ではなく**型付きドキュメントの束**を吐き、 -同じ項目を v1alpha1 側にも書くと apply が弾かれる(`... is already set in v1alpha1 config`)。 - -| やりたいこと | 書き場所 | -| --- | --- | -| pod / service の CIDR | `KubeNetworkConfig` の `podSubnets` / `serviceSubnets`。**service の IPv6 は `/108` 以下**(`fd43::/64` は `too large` で弾かれる) | -| インストール先ディスク | `UnattendedInstallConfig` の `provisioning.diskSelector.match`(**CEL 式**。例 `disk.dev_path == "/dev/sda"`) | -| カーネル引数 | `machine.install.extraKernelArgs` は使えない(同じく衝突)。**schematic の `customization.extraKernelArgs`** | -| host DNS | `ResolverConfig`。**既定で有効**なので普通は書かなくてよい | -| bond とそのメンバー | `BondConfig` / `LinkConfig`。v1alpha1 の `machine.network.interfaces` は bond の MAC を指定できない([talos.sops.yaml](../bootstrap/talos.sops.yaml)) | -| PV の置き場 | `RawVolumeConfig`(フォーマットしないパーティション。ラベルは `r-`)を `LVMVolumeGroupConfig` で VG にする。thin の LV は Talos では作れない([talos.sops.yaml](../bootstrap/talos.sops.yaml)、[bootstrap/README.md](../bootstrap/README.md)「PVC の置き場」)。ボリュームは**未割り当ての領域にしか作られない**ので、切り方を変えるのは入れ直すときだけ | -| control-plane への scheduling 許可 | v1alpha1 の `allowSchedulingOnControlPlanes` は弾かれる。**`KubeNodeConfig` を `$patch: delete` して `labels` だけ書き戻す**([talos.sops.yaml](../bootstrap/talos.sops.yaml)) | -| CNI を止める | `KubeFlannelCNIConfig` を `$patch: delete`、`KubeProxyConfig` を `enabled: false`([talos.sops.yaml](../bootstrap/talos.sops.yaml))。**v1alpha1 の `cni.name: none` はもう書けない** | -| カーネルモジュール | `machine.kernel.modules`。**並べた順ではなく名前の順に読まれる**。v1.15.0-alpha.2 からはカーネルの要求(`request_module`)でも読むので、書くのは自分からは読まれないものだけでよい(PT3 は `earth-pt3` だけ。OpenEBS の thin プールの `dm_thin_pool` も書いてある。[talos.sops.yaml](../bootstrap/talos.sops.yaml)、[decisions.md](decisions.md)「PT3 チューナー」) | - -### PSA のラベル(Pod Security Admission が既定で `baseline`) - -`KubeAdmissionControlConfig` に `enforce: baseline`(例外は `kube-system` のみ)が入っている。 -**`hostPath` / `privileged` / `hostNetwork` / `hostPort` を使う workload は namespace にラベルが要る**(baseline は hostPort も弾く)。 -ラベルが無いと Pod が作られない(ReplicaSet や DaemonSet の events に出るだけで、Pod の一覧には何も出ない)。 - -| namespace | baseline に通らない理由 | -| --- | --- | -| `kube-system` | Cilium(privileged・hostNetwork・hostPath・SYS_ADMIN/NET_ADMIN・hostPort)、OpenEBS LVM と `lvm-thinpool`(privileged・hostPath の `/dev`)。**Talos の側で例外にしてある** | -| `netbird` | hostPort 51820(routing peer の WireGuard)、NET_ADMIN 等、hostPath | -| `denpa` | privileged・hostPath(`/dev/dvb`・`/dev/bus`・`/dev/dri`)。**ラベルは denpa リポジトリの `deploy/namespace.yaml`** にあり、gitops だけを grep すると抜けて見える | -| `adguardhome` | hostPort 53 / 853 | -| `matrix` | hostPort 8443(LiveKit) | -| `3proxy` | hostPort 3129(TLS 終端サイドカー) | -| `cloudflare-ddns` | hostNetwork | -| `forgejo` | Runner の docker(dind)が privileged | - -どれも `namespace.yaml` に `enforce: privileged` が入っている。**baseline が足せる capability は `NET_BIND_SERVICE` だけ。** -新しく足すときは Pod の spec を直接数えて洗い出す: - -```shell -kubectl get pods -A -o json | jq -r '.items[] | . as $p | [$p.metadata.namespace] + - (if $p.spec.hostNetwork then ["hostNetwork"] else [] end) + - ($p.spec.containers[] | (.securityContext.privileged // false | if . then ["privileged"] else [] end) + - ((.securityContext.capabilities.add // []) | map("cap:"+.)) + - ((.ports // []) | map(select(.hostPort)) | map("hostPort:"+(.hostPort|tostring)))) + - (($p.spec.volumes // []) | map(select(.hostPath)) | map("hostPath")) | @tsv' | sort -u -``` - -## etcd スナップショットからの復旧(VM で検証済み) - -```shell -talosctl etcd snapshot ./etcd.snapshot # 1.8 MB / 394 keys (検証時) -``` - -復旧は、**同じ `secrets.yaml` で machine config を作り直す**のが肝(PKI が一致しないと復旧できない)。 - -```shell -# まっさらなディスクに ISO から入れ直したあと -talosctl apply-config --insecure -n -f controlplane.yaml -talosctl bootstrap --recover-from=./etcd.snapshot # etcd が上がるまで `bootstrap is not available yet`。数分待って再試行 -``` - -**PV の中身は戻らない**(etcd は「PVC がこの PV に紐づいている」という事実しか持っていない)ので、 -このあと PV データを VolSync で戻す。順序は etcd が先(PV オブジェクトが無いと戻す先が決まらない)。 - -**主経路ではない。** 主経路は git から建て直すほう([recovery/README.md](../recovery/README.md)。スナップショットの鮮度に左右されない)。 -こちらは git に無い状態(Application の同期状態、発行済みの証明書など)まで一度に戻したいときの近道。 -日次で取っているのは [deploy/backup/etcd-snapshot.yaml](../deploy/backup/etcd-snapshot.yaml)(リポジトリ `/etcd`)。取り出しは: - -```shell -restic snapshots --host etcd -restic dump /work/etcd.snapshot > etcd.snapshot -``` - -## inlineManifests は「更新できない」ではない(VM で実測) - -Sidero のドキュメントの「Talos only creates missing resources from inline manifests」は起動時の適用の話で、 -**`talosctl apply-config` では更新も削除もされないが、`talosctl upgrade-k8s`(同じ版でも)を通せば SSA とインベントリで更新も削除もされる** -(prune は既定で有効)。当て直しの手順は [bootstrap/talos.md](../bootstrap/talos.md)「上げ方 / 当て直し方」。 - -## VM ブートドリル - -[.github/workflows/talos-boot.yml](../.github/workflows/talos-boot.yml) が PR ごとに描いた machine config を QEMU で起動して見る。 -見つけた穴は直した場所(`bootstrap/talos.sops.yaml`・`bootstrap/render.sh`)に理由を書いてある。 - -VM では確かめられないもの: PT3(実機のカードが要る)、bond のフェイルオーバーの復旧方向(落とす方向は 8 秒以内で `talosctl` は途切れない)。 - -- **v1.14 以降の `talosctl` は `--nodes` / `--endpoints` がグローバルフラグではない。** `talosctl get links --insecure -n … -e …` の順で書く。 - `talosctl apply-config -m reboot` は無い(`auto` / `no-reboot` / `staged` / `try`) -- infisical の起動直後の `CreateContainerConfigError: failed to sync secret cache` は optional な Secret の同期待ちで、放っておくと直る -- 所要: `apply-config` → apid 復帰 75 秒 → ノード Ready 200 秒 → bootstrap 層が全部 Running まで 120 秒 - -Z440 に移すときに変わるもの(NIC の名前・ディスク・AMT・GPU)は [../ROADMAP.md](../ROADMAP.md)「ノード main(HP Z440)」。 - -## ネットワークまわりの前提 - -Talos の既定(Flannel + kube-proxy)を止めて **Cilium に替えてある**(decisions.md「ルーティングの選定」。 -CNI の交換は構築時にやる ── 稼働中の差し替えは全 Pod 再起動が前提)。Cilium の値は [bootstrap/cilium-values.yaml](../bootstrap/cilium-values.yaml)。 -LoadBalancer とクライアント IP も decisions.md「ルーティングの選定」。 - -- `NetworkDefaultActionConfig: block`(Talos の受信の防火壁)は Cilium の Gateway(hostNetwork)と噛み合わないので使わない。防火壁は Cilium の Host Firewall([../bootstrap/talos.md](../bootstrap/talos.md)) - -## 管理モデル(3 つのレイヤーを混同しない) - -| レイヤー | 決めること | 変更手段 | -| --- | --- | --- | -| イメージ | カーネル引数、system extension(GPU ドライバ等) | Image Factory で schematic を作って `talosctl upgrade` | -| machine config | CNI、kube-proxy、ディスク、ネットワーク、`bootstrap/` の chart と SOPS のファイル | `render.sh` → `apply-config`(inlineManifests は `upgrade-k8s` まで) | -| Kubernetes | ワークロード | Argo CD(`deploy/`・各リポジトリの `deploy/`) | - -SSH もシェルもパッケージマネージャも無く gRPC API だけなので、**障害時は「直さず作り直す」**。 -デバッグは `talosctl dmesg` / `logs` / `read`、debug コンテナ。 diff --git a/recovery/README.md b/recovery/README.md index 9c51ace7..7341f125 100644 --- a/recovery/README.md +++ b/recovery/README.md @@ -39,7 +39,7 @@ base64 recovery/env.age recovery/sops-age.key.age # 印刷して封筒へ | ほかの PV データ | **VolSync の `ReplicationDestination`**([pv.sh](pv.sh)) | etcd のスナップショット(リポジトリ `/etcd`、[../deploy/backup/etcd-snapshot.yaml](../deploy/backup/etcd-snapshot.yaml))は -git に無い状態まで一度に戻したいときの近道で、主経路ではない([../docs/talos.md](../docs/talos.md)「etcd スナップショットからの復旧」)。 +git に無い状態まで一度に戻したいときの近道で、主経路ではない([../bootstrap/talos.md](../bootstrap/talos.md)「etcd スナップショットから戻す(近道)」)。 ## 道具と経路 @@ -60,12 +60,12 @@ talosconfig も管理者の kubeconfig も `bootstrap/talos-secrets.sops.yaml` ```shell mkdir -p ~/.config/sops/age && age -d -o ~/.config/sops/age/keys.txt recovery/sops-age.key.age # パスフレーズ -./bootstrap/render.sh bootstrap/clusterconfig # `valid for metal mode` まで出ること +./bootstrap/render.sh /dev/shm/c && rm -rf /dev/shm/c # 描けるかだけ見る。`valid for metal mode` まで出ること ``` - **`bootstrap/talos-secrets.sops.yaml` を作り直さない。** 作り直すと別のクラスタ CA になり、`bootstrap/apiserver-ca.crt`・ Infisical の Kubernetes auth(7)が合わなくなる -- **`render.sh` は出力先を丸ごと消して作り直す。** `bootstrap/clusterconfig/` に kubeconfig などを置いていたら消える +- **描いたものは手元に置かない**(秘密が平文で入る)。当てるときは 3 の `apply.sh` がその場で描いて消す - 版は [../bootstrap/talos.sops.yaml](../bootstrap/talos.sops.yaml) の先頭のコメント。**上げるなら建て直しの日ではない日に** ## 2. ISO で起動する @@ -92,7 +92,7 @@ talosctl get disks --insecure -n $IP -e $IP ## 3. 当てる(インストールは無人で進む) ```shell -talosctl apply-config --insecure -n $IP -e $IP -f bootstrap/clusterconfig/controlplane.yaml +./bootstrap/apply.sh --insecure -n $IP -e $IP # 描いて当てる(描いたものは /dev/shm に置いて消す) ``` `UnattendedInstallConfig` があるので、ディスクに書いて自分で再起動する。**ここで SSD が上書きされる。** @@ -231,9 +231,9 @@ rm -f ~/.config/restic.env ~/infisical-load.log | | | | --- | --- | | ノードが上がらない | AMT の SOL(インストール済みのノードのカーネルのコンソール)。ダッシュボード(版と健全性)は Arc につないだモニタ | -| Pod が Pending | **PSA のラベル**([../docs/talos.md](../docs/talos.md)「PSA のラベル」)か、control-plane の taint | +| Pod が Pending | **PSA のラベル**([../bootstrap/talos.md](../bootstrap/talos.md)「PSA のラベル」)か、control-plane の taint | | PVC が Bound しない | `kubectl -n kube-system logs ds/lvm-thinpool -c pool`(VG `data` が無い = `talosctl get volumestatus` の `r-lvm`)、ノードに `doany.io/lvm-thinpool=ready` が付いて `lvm-localpv-node` が動いているか、`kubectl -n kube-system logs ds/lvm-localpv-node -c openebs-lvm-plugin` | | 非公開イメージが引けない | `bootstrap/talos.sops.yaml` の fj.doany.io の `password` が machine config に入っているか、Forgejo が戻っているか(8) | | cilium-drift が TLS で落ちる | `talos-secrets.sops.yaml` を作り直した。`bootstrap/apiserver-ca.crt` を新しい `talos-secrets.sops.yaml` の Kubernetes の CA(`certs.k8s.crt` を base64 で戻したもの)にする | | Application が `OutOfSync / Missing` のまま | `retry`(約 33 分)で自力で戻る。30 分以上動かなければ `kubectl -n argocd patch application <名前> --type=merge -p '{"operation":{"sync":{"revision":"HEAD"},"initiatedBy":{"username":"me"}}}'`。**chart のものは `HEAD` ではなく `spec.source.targetRevision` の値** | -| inlineManifest を直したのに効かない | `render.sh` → `apply-config` → **`upgrade-k8s`**([../bootstrap/talos.md](../bootstrap/talos.md)「上げ方 / 当て直し方」) | +| inlineManifest を直したのに効かない | `apply.sh` → **`upgrade-k8s`**([../bootstrap/talos.md](../bootstrap/talos.md)「当て方」) | diff --git a/tools/README.md b/tools/README.md index 94236479..5a8930b3 100644 --- a/tools/README.md +++ b/tools/README.md @@ -12,6 +12,10 @@ tools/t.ps1 --admin kubectl apply -f x.yaml # 書くときだけ管理者(下 tools/t.ps1 # 引数なしならシェルに入る ``` +**Git Bash からは [t](t) を使う**(`tools/t kubectl get pods -A` のように t.ps1 と同じ引数)。Git Bash から pwsh を直に呼ぶと、 +`/` で始まる引数が Windows のパスに書き換えられ(`/proc/cmdline` → `C:/Program Files/Git/proc/cmdline`)、 +閉じない標準入力で終わらなくなる。`t` はパスの書き換えを止め、端末でなければ標準入力を渡さない。渡すときは `tools/t --stdin … < x`。 + | 入っているもの | 用途 | | --- | --- | | cf | Cloudflare(R2 など) | @@ -63,9 +67,9 @@ tools/t.ps1 # 引数なしならシェルに入る - **talosconfig は保存しない**([../docs/decisions.md](../docs/decisions.md)「手で持つもの」)。`secrets.yaml` から毎回作る - **管理者の kubeconfig も保存しない。** 毎回その場で作るので、作り直しも期限切れも無い。 `talosctl kubeconfig` は 1 年もつ証明書を呼ぶたびに出す(取り消せない)ので使わない -- 行き先はどれも `10.10.0.4`(ノードの、作業用 PC の LAN 側の口。`creds.sh` の `ep`)。`bootstrap/render.sh` の `10.0.0.2` は - クラスタの LAN で手元から届かず、NetBird はクラスタの上で動くので落ちたときに使えない。API は外に開かない。 - 外からは mado で作業用 PC に入って打つ。`10.10.0.4` は Talos の証明書の SAN に入っている。`KUBECONFIG` / `TALOSCONFIG` や `--kubeconfig` / `--talosconfig` / +- 行き先は `10.10.0.4`(ノードの、作業用 PC の LAN 側の口)。**届かなければ `10.0.0.2` に繋ぐ**(Wi-Fi などで 10.0 側につないだとき。`creds.sh` の `ep`。`GITOPS_EP` で決め打ちできる)。`10.0.0.2` は + ふだん手元から届かず、NetBird はクラスタの上で動くので落ちたときに使えない。API は外に開かない。 + 外からは mado で作業用 PC に入って打つ。どちらも Talos の証明書の SAN に入っている。`KUBECONFIG` / `TALOSCONFIG` や `--kubeconfig` / `--talosconfig` / `--server` を自分で渡したときは何もしない。繋がないもの(`kubectl kustomize`、`helm template`、`talosctl gen`、`--client` など)も同じ 平文の `kubeconfig` / `talosconfig` という名前のファイルは `.gitignore` 済み(手で書き出したものを誤って入れないように)。 diff --git a/tools/creds.sh b/tools/creds.sh index f1c4dd57..5c7c40cb 100755 --- a/tools/creds.sh +++ b/tools/creds.sh @@ -75,8 +75,28 @@ mint() { [ $rc = 0 ] || { rm -f "$3".*; die "証明書を作れなかった(bootstrap/talos-secrets.sops.yaml を age の鍵で開けるか)"; } } -# 作業用 PC の LAN 側のノードの口(10.0.0.2 は手元から届かず、NetBird はクラスタが落ちると使えない) -ep=10.10.0.4 +# ノードの口。作業用 PC は 10.10 側なので 10.10.0.4 を先に試し、届かなければ 10.0.0.2(Wi-Fi などで 10.0 側につないだとき。 +# 2026-11-01 に NIC を付け替えて 10.10 から届かなくなったときはこれで入った)。GITOPS_EP で決め打ちできる。 +# 届くかは TCP がつながるかだけで見る(curl の 7 は拒否、28 は時間切れ。TLS の失敗はつながった扱い) +reach() { + set +e + curl -sk -m 2 -o /dev/null "https://$1:$2/" 2>/dev/null + r=$? + set -e + [ $r != 7 ] && [ $r != 28 ] +} +if [ "$tool" = talosctl ]; then port=50000; else port=6443; fi +ep=${GITOPS_EP:-} +if [ -z "$ep" ]; then + if reach 10.10.0.4 $port; then + ep=10.10.0.4 + elif reach 10.0.0.2 $port; then + ep=10.0.0.2 + echo "$tool: 10.10.0.4 に届かないので 10.0.0.2 に繋ぐ" >&2 + else + ep=10.10.0.4 + fi +fi # talosconfig を作って置き場所を返す($1 = admin / readonly) talosconfig() { diff --git a/tools/t b/tools/t new file mode 100755 index 00000000..7c4d9a32 --- /dev/null +++ b/tools/t @@ -0,0 +1,16 @@ +#!/bin/sh +# Git Bash から tools/t.ps1 を呼ぶ入口(tools/README.md)。PowerShell からは t.ps1 を直接呼ぶ。 +# tools/t kubectl get pods -A +# tools/t --admin talosctl read /proc/cmdline +# tools/t --stdin kubectl apply -f - < x.yaml # 標準入力を渡すときだけ --stdin +# Git Bash から pwsh を呼ぶと 2 つ詰まる: +# - `/` で始まる引数が Windows のパスに書き換えられる(/proc/cmdline → C:/Program Files/Git/proc/cmdline)。MSYS_NO_PATHCONV で止める +# - 標準入力が閉じないパイプだと、t.ps1 がそれを渡し続けて終わらない。端末でなければ /dev/null にする(t.ps1 は NUL を空のパイプに置き換える) +export MSYS_NO_PATHCONV=1 +t=$(dirname -- "$0")/t.ps1 +if [ "${1:-}" = --stdin ]; then + shift + exec pwsh -NoProfile -File "$t" "$@" +fi +if [ -t 0 ]; then exec pwsh -NoProfile -File "$t" "$@"; fi +exec pwsh -NoProfile -File "$t" "$@" Date: Sun, 1 Nov 2026 12:14:47 +0900 Subject: [PATCH 2/2] =?UTF-8?q?tools=E3=83=BBapply.sh:=20=E3=83=AC?= =?UTF-8?q?=E3=83=93=E3=83=A5=E3=83=BC=E3=81=AE=E6=8C=87=E6=91=98=20(?= =?UTF-8?q?=E4=BD=9C=E6=A5=AD=E5=A0=B4=E6=89=80=E3=82=82=20tmpfs=E3=83=BB-?= =?UTF-8?q?-stdin=20=E3=81=AE=E9=A0=86=E3=83=BB=E4=B8=AD=E6=96=AD=E3=81=A7?= =?UTF-8?q?=E6=AD=A2=E3=81=BE=E3=82=8B=E3=83=BB=E3=81=A9=E3=81=A1=E3=82=89?= =?UTF-8?q?=E3=81=AB=E3=82=82=E5=B1=8A=E3=81=8B=E3=81=AA=E3=81=84=E3=81=A8?= =?UTF-8?q?=E7=9F=A5=E3=82=89=E3=81=9B=E3=82=8B)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01T9PbUfqG4pPxus99UeLiJs --- bootstrap/apply.sh | 5 ++++- tools/README.md | 2 +- tools/creds.sh | 1 + tools/t | 19 ++++++++++++------- 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/bootstrap/apply.sh b/bootstrap/apply.sh index 715765b7..63029b38 100755 --- a/bootstrap/apply.sh +++ b/bootstrap/apply.sh @@ -9,6 +9,9 @@ set -eu cd "$(dirname -- "$0")/.." out=$(mktemp -d /dev/shm/clusterconfig.XXXXXX) -trap 'rm -rf "$out"' EXIT INT TERM +# render.sh の作業場所(復号した入力を置く)も tmpfs に +export TMPDIR=/dev/shm +trap 'rm -rf "$out"' EXIT +trap 'exit 130' INT TERM ./bootstrap/render.sh "$out" talosctl apply-config "$@" -f "$out/controlplane.yaml" diff --git a/tools/README.md b/tools/README.md index 5a8930b3..bd9b21d7 100644 --- a/tools/README.md +++ b/tools/README.md @@ -14,7 +14,7 @@ tools/t.ps1 # 引数なしならシェルに入る **Git Bash からは [t](t) を使う**(`tools/t kubectl get pods -A` のように t.ps1 と同じ引数)。Git Bash から pwsh を直に呼ぶと、 `/` で始まる引数が Windows のパスに書き換えられ(`/proc/cmdline` → `C:/Program Files/Git/proc/cmdline`)、 -閉じない標準入力で終わらなくなる。`t` はパスの書き換えを止め、端末でなければ標準入力を渡さない。渡すときは `tools/t --stdin … < x`。 +閉じない標準入力で終わらなくなる。`t` はパスの書き換えを止め、端末でなければ標準入力を渡さない。渡すときは `tools/t --stdin … < x`(`--admin` と並べる順は問わない)。 | 入っているもの | 用途 | | --- | --- | diff --git a/tools/creds.sh b/tools/creds.sh index 5c7c40cb..4fb3c03e 100755 --- a/tools/creds.sh +++ b/tools/creds.sh @@ -95,6 +95,7 @@ if [ -z "$ep" ]; then echo "$tool: 10.10.0.4 に届かないので 10.0.0.2 に繋ぐ" >&2 else ep=10.10.0.4 + echo "$tool: 10.10.0.4 にも 10.0.0.2 にも届かない(ノードが止まっているか、網が違う)" >&2 fi fi diff --git a/tools/t b/tools/t index 7c4d9a32..ac95c56f 100755 --- a/tools/t +++ b/tools/t @@ -2,15 +2,20 @@ # Git Bash から tools/t.ps1 を呼ぶ入口(tools/README.md)。PowerShell からは t.ps1 を直接呼ぶ。 # tools/t kubectl get pods -A # tools/t --admin talosctl read /proc/cmdline -# tools/t --stdin kubectl apply -f - < x.yaml # 標準入力を渡すときだけ --stdin +# tools/t --admin --stdin kubectl apply -f - < x.yaml # 標準入力を渡すときだけ --stdin(--admin の前でも後でもよい) # Git Bash から pwsh を呼ぶと 2 つ詰まる: # - `/` で始まる引数が Windows のパスに書き換えられる(/proc/cmdline → C:/Program Files/Git/proc/cmdline)。MSYS_NO_PATHCONV で止める # - 標準入力が閉じないパイプだと、t.ps1 がそれを渡し続けて終わらない。端末でなければ /dev/null にする(t.ps1 は NUL を空のパイプに置き換える) export MSYS_NO_PATHCONV=1 t=$(dirname -- "$0")/t.ps1 -if [ "${1:-}" = --stdin ]; then - shift - exec pwsh -NoProfile -File "$t" "$@" -fi -if [ -t 0 ]; then exec pwsh -NoProfile -File "$t" "$@"; fi -exec pwsh -NoProfile -File "$t" "$@"