Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions .github/workflows/cilium-drift.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# cilium の値が git とクラスタでズレていないかを見る(読むだけ。権限は cilium-config の get だけ)。
# cilium は inlineManifest なので、人が render.sh → apply-config → upgrade-k8s を流すまで届かない。
# 当てるのは自動化しない(talos/README.md)。
# 当てるのは自動化しない(bootstrap/talos.md)。
name: cilium drift

on:
push:
branches: [main]
paths:
- bootstrap/cilium/**
- bootstrap/cilium-values.yaml
- .github/workflows/cilium-drift.yml
# クラスタ側だけ手でいじったときのため
schedule:
Expand All @@ -30,7 +30,7 @@ jobs:
id: v
run: |
set -euo pipefail
V=$(yq -r '.version' bootstrap/cilium/version.yaml)
V=$(sed -n '/^# version: /{s/^# version: *//p;q;}' bootstrap/cilium-values.yaml)
echo "chart=$V" >> "$GITHUB_OUTPUT"
echo "cilium chart $V"

Expand All @@ -44,24 +44,24 @@ jobs:
echo "::add-mask::${T}"
echo "token=${T}" >> "$GITHUB_OUTPUT"

- name: values.yaml から ConfigMap を描いて live と比べる
- name: cilium-values.yaml から ConfigMap を描いて live と比べる
env:
T: ${{ steps.token.outputs.token }}
run: |
set -euo pipefail
k() {
kubectl --server=https://ks.doany.io:6443 \
--certificate-authority=bootstrap/apiserver/ca.crt \
--certificate-authority=bootstrap/apiserver-ca.crt \
--token="$T" "$@"
}
# --kube-version が無いと helm の既定版で描かれて偽の差分が出る
KV=$(k version -o json | jq -r .serverVersion.gitVersion)
echo "kube-version=$KV"
export HOWTO="talos/README.md「inlineManifests を直したとき」の render.sh → apply-config → upgrade-k8s を流すこと"
export HOWTO="bootstrap/talos.md「inlineManifests を直したとき」の render.sh → apply-config → upgrade-k8s を流すこと"

helm repo add cilium https://helm.cilium.io >/dev/null
helm template cilium cilium/cilium --version "${{ steps.v.outputs.chart }}" \
-n kube-system -f bootstrap/cilium/values.yaml --kube-version "$KV" \
-n kube-system -f bootstrap/cilium-values.yaml --kube-version "$KV" \
--show-only templates/cilium-configmap.yaml \
| yq -o=json '.data' > rendered.json

Expand Down
44 changes: 20 additions & 24 deletions .github/workflows/talos-boot.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# talos/render.sh の machine config を runner の QEMU(KVM)で起動し、クラスタが立つところまで見る。
# bootstrap/render.sh の machine config を runner の QEMU(KVM)で起動し、クラスタが立つところまで見る。
# 秘密はゼロ(使い捨てとダミー)。外に副作用を出さない: ArgoCD の extraObjects と通知先、
# 本物の ClusterIssuer(自己署名に差し替え)、infisical の SMTP を抜く。手順の元は docs/talos.md。
name: talos boot
Expand All @@ -7,13 +7,9 @@ on:
pull_request:
# YAML のアンカーは読むが、マージキー `<<:` は読まない
paths: &paths
- talos/**
- bootstrap/cilium/**
- bootstrap/cert-manager/**
- bootstrap/argocd/**
- bootstrap/infisical/**
- bootstrap/gateway/**
- bootstrap/apiserver/**
- bootstrap/**
- apps/argocd/httproute.yaml
- apps/gateway/**
- .github/workflows/talos-boot.yml
push:
branches: [main]
Expand Down Expand Up @@ -46,13 +42,13 @@ jobs:
steps:
- uses: actions/checkout@v7

- name: versions.yaml から版と schematic を読む
- name: bootstrap/versions.yaml から版と schematic を読む
id: v
run: |
set -euo pipefail
VER=$(yq -r '.talos.version' talos/versions.yaml)
SCH=$(yq -r '.talos.schematic' talos/versions.yaml)
K8S=$(yq -r '.kubernetes.version' talos/versions.yaml)
VER=$(yq -r '.talos.version' bootstrap/versions.yaml)
SCH=$(yq -r '.talos.schematic' bootstrap/versions.yaml)
K8S=$(yq -r '.kubernetes.version' bootstrap/versions.yaml)
echo " talos=$VER schematic=$SCH k8s=$K8S"
echo "version=$VER" >> "$GITHUB_OUTPUT"
echo "schematic=$SCH" >> "$GITHUB_OUTPUT"
Expand Down Expand Up @@ -102,32 +98,32 @@ jobs:
run: |
set -euo pipefail
talosctl gen secrets -o /tmp/secrets.yaml
# controlplane.yaml は password(fj.doany.io)だけ暗号化してある。ダミーに置き換える
# talos.sops.yaml は password(fj.doany.io)だけ暗号化してある。ダミーに置き換える
# (ダミーは fj.doany.io に置いたまま。ghcr.io に置くと kubelet の取得が 403 で落ちる)
yq 'del(.sops) | (.. | select(tag == "!!str" and test("^ENC\\["))) |= "ci-dummy"' \
talos/controlplane.yaml > /tmp/controlplane.yaml
# values.yaml は本物、secret-values.sops.yaml だけダミー(通知先もそこにしか無い)。
bootstrap/talos.sops.yaml > /tmp/controlplane.yaml
# *-values.yaml は本物、*-secret-values.sops.yaml だけダミー(通知先もそこにしか無い)。
# extraObjects は app-of-apps と repo-creds。CI で本物を同期させない
echo 'extraObjects: []' > /tmp/argocd-secret-values.yaml
# SMTP の env を抜く(リストなので丸ごと置き換える)
yq '{"infisical": {"extraEnv": [.infisical.extraEnv[] | select(.name | test("^SMTP_") | not)]},
"postgresql": {"auth": {"password": "ci-dummy"}}, "redis": {"auth": {"password": "ci-dummy"}}}' \
bootstrap/infisical/values.yaml > /tmp/infisical-secret-values.yaml
bootstrap/infisical-values.yaml > /tmp/infisical-secret-values.yaml
# ENCRYPTION_KEY は 16 バイトの hex でないと infisical が起動しない
yq -I4 "del(.sops) | del(.stringData.CLIENT_ID_GITHUB_LOGIN) | del(.stringData.CLIENT_SECRET_GITHUB_LOGIN)
| .stringData.ENCRYPTION_KEY = \"$(openssl rand -hex 16)\"
| .stringData.AUTH_SECRET = \"$(openssl rand -base64 32)\"
| .stringData.TELEMETRY_ENABLED = \"false\"" \
bootstrap/infisical/secrets.sops.yaml > /tmp/infisical-secret.yaml
bootstrap/infisical-secrets.sops.yaml > /tmp/infisical-secret.yaml
yq 'del(.sops) | (.. | select(tag == "!!str" and test("^ENC\\["))) |= "ci-dummy"' \
bootstrap/cert-manager/cloudflare-secret.sops.yaml > /tmp/cloudflare-secret.yaml
bootstrap/cert-manager-cloudflare-secret.sops.yaml > /tmp/cloudflare-secret.yaml
for f in /tmp/controlplane.yaml /tmp/infisical-secret.yaml /tmp/cloudflare-secret.yaml; do
! grep -q 'ENC\[' "$f" || { echo "::error::$f に暗号文が残っている"; exit 1; }
done
SECRETS=/tmp/secrets.yaml CONTROLPLANE=/tmp/controlplane.yaml \
ARGOCD_SECRET_VALUES=/tmp/argocd-secret-values.yaml INFISICAL_SECRET_VALUES=/tmp/infisical-secret-values.yaml \
INFISICAL_SECRET=/tmp/infisical-secret.yaml CLOUDFLARE_SECRET=/tmp/cloudflare-secret.yaml \
./talos/render.sh /tmp/out
./bootstrap/render.sh /tmp/out
talosctl config endpoint 127.0.0.1
talosctl config node "$NODE"

Expand Down Expand Up @@ -234,7 +230,7 @@ jobs:
selfSigned: {}
YAML
until kubectl apply -f /tmp/issuer.yaml 2>/dev/null; do sleep 5; done
until kubectl apply -f bootstrap/gateway/gateway.yaml -f bootstrap/gateway/redirect-https.yaml -f bootstrap/argocd/httproute.yaml; do sleep 5; done
until kubectl apply -f apps/gateway/gateway.yaml -f apps/gateway/redirect-https.yaml -f apps/argocd/httproute.yaml; do sleep 5; done
kubectl -n kube-system wait --for=condition=Ready certificate --all --timeout=3m
kubectl -n kube-system wait --for=condition=Programmed gateway/doany --timeout=3m
# http は https への 301、https は argocd-server まで
Expand All @@ -261,17 +257,17 @@ jobs:
echo " volume $v: $P"
done

WANT=$(yq -r 'select(.kind == "BondConfig") | .hardwareAddr' talos/controlplane.yaml)
WANT=$(yq -r 'select(.kind == "BondConfig") | .hardwareAddr' bootstrap/talos.sops.yaml)
GOT=$(talosctl get links bond0 -o json | jq -r .spec.hardwareAddr)
[ "$GOT" = "$WANT" ] || fail "bond0 の MAC が $GOT(controlplane.yaml は $WANT)"
[ "$GOT" = "$WANT" ] || fail "bond0 の MAC が $GOT(talos.sops.yaml は $WANT)"
echo " bond0 hardwareAddr: $GOT"

# 以下は forwarding=1 のあとで見ないと意味が無い(controlplane.yaml の accept_ra)
# 以下は forwarding=1 のあとで見ないと意味が無い(talos.sops.yaml の accept_ra)
F=$(talosctl read /proc/sys/net/ipv6/conf/bond0/forwarding)
[ "$F" = 1 ] || fail "bond0 の forwarding が $F。前提が成り立っていない"

# グローバルな IPv6 は静的な ::2 だけ(SLAAC は autoconf=0 で止めている)
STATIC=$(yq -r 'select(.kind == "BondConfig") | .addresses[].address | select(test(":"))' talos/controlplane.yaml)
STATIC=$(yq -r 'select(.kind == "BondConfig") | .addresses[].address | select(test(":"))' bootstrap/talos.sops.yaml)
GLOBAL=$(talosctl get addresses -o json \
| jq -rs '.[] | select(.spec.linkName == "bond0" and .spec.family == "inet6" and .spec.scope != "link") | .spec.address' | sort)
echo " bond0 の IPv6(link-local 以外): $(echo $GLOBAL)"
Expand Down
10 changes: 6 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
talos/clusterconfig/
# **平文のまま置かないこと。** talos/secrets.yaml と controlplane.yaml は SOPS 済みのものをコミットする
# (talos/README.md)。書きかけの平文はこの名前に逃がす。
talos/secrets.plain.yaml
bootstrap/clusterconfig/
# 2026-10 までの出力先(talos/ を bootstrap/ にまとめる前)。手元に残っていても入らないように
/talos/
# **平文のまま置かないこと。** bootstrap/talos-secrets.sops.yaml と talos.sops.yaml は SOPS 済みのものをコミットする
# (bootstrap/talos.md)。書きかけの平文はこの名前に逃がす。
bootstrap/talos-secrets.plain.yaml
# 平文の kubeconfig / talosconfig も置かない。どちらも tools/t.ps1 が毎回その場で作る
# (tools/README.md「クラスタの資格情報」)。talosctl kubeconfig と gen config がこの名前で書き出す
kubeconfig
Expand Down
19 changes: 10 additions & 9 deletions .sops.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,22 @@
# (env.age と同じパスフレーズ)。復号は
# tools/t.ps1 sh -c 'mkdir -p ~/.config/sops/age && age -d -o ~/.config/sops/age/keys.txt recovery/sops-age.key.age'
# のあと `tools/t.ps1 sops -d`(tools/t.ps1 の中の ~ はリポジトリの .home/)。
# 上から順に見て、最初に当たった規則を使う。
creation_rules:
# secret-values.sops.yaml は秘密しか入れないので丸ごと
- path_regex: ^bootstrap/[^/]+/secret-values\.sops\.yaml$
age: age1sgnnkn67wpt4wgjsff4c36w3cmjkk557ng504e4aczx2lzls9y6ssy0x9r
# 残りはキーだけ(構造をレビューできるように)。bootstrap/ で暗号化するファイルは `.sops.yaml` で終える
# (ArgoCD の `bootstrap` はその名前で外す)。
- path_regex: ^bootstrap/.*\.sops\.yaml$
encrypted_regex: ^(ENCRYPTION_KEY|AUTH_SECRET|CLIENT_ID_GITHUB_LOGIN|CLIENT_SECRET_GITHUB_LOGIN|CF_DNS_API_TOKEN)$
# <name>-secret-values.sops.yaml は秘密しか入れないので丸ごと
- path_regex: ^bootstrap/[^/]+-secret-values\.sops\.yaml$
age: age1sgnnkn67wpt4wgjsff4c36w3cmjkk557ng504e4aczx2lzls9y6ssy0x9r
# 手で書く machine config。秘密は password の値だけ(fj.doany.io)。平文の部分は sops を通さず直接直せるよう
# mac_only_encrypted(MAC が暗号化した値だけを見る)。SOPS はドキュメントごとに sops: を付け、インデントを 4 にする
- path_regex: ^talos/controlplane\.yaml$
- path_regex: ^bootstrap/talos\.sops\.yaml$
encrypted_regex: ^password$
mac_only_encrypted: true
age: age1sgnnkn67wpt4wgjsff4c36w3cmjkk557ng504e4aczx2lzls9y6ssy0x9r
# 全部が秘密なので丸ごと(CA 一式)
- path_regex: ^talos/secrets\.yaml$
- path_regex: ^bootstrap/talos-secrets\.sops\.yaml$
age: age1sgnnkn67wpt4wgjsff4c36w3cmjkk557ng504e4aczx2lzls9y6ssy0x9r
# 残りはキーだけ(構造をレビューできるように)。上に当たらなかった bootstrap/ の `*.sops.yaml` はここに落ちるので最後に置く。
# bootstrap/ で暗号化するファイルは `.sops.yaml` で終える(どの規則もその名前にしか当たらない)。
- path_regex: ^bootstrap/[^/]+\.sops\.yaml$
encrypted_regex: ^(ENCRYPTION_KEY|AUTH_SECRET|CLIENT_ID_GITHUB_LOGIN|CLIENT_SECRET_GITHUB_LOGIN|CF_DNS_API_TOKEN)$
age: age1sgnnkn67wpt4wgjsff4c36w3cmjkk557ng504e4aczx2lzls9y6ssy0x9r
Loading
Loading