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
9 changes: 2 additions & 7 deletions apps/3proxy/3proxy-secrets.yaml
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
# Secret 3proxy は Infisical (il.doany.io) のフォルダ /3proxy/3proxy にあり、
# Infisical 純正 operator (apps/infisical-operator) が Secret にする。
# 値は Infisical の UI で書き換えるだけ(push-bridge が数秒で同期。auto-reload 注釈のある
# Deployment は自動で入れ替わる)。
# Secret 3proxy を Infisical (/3proxy/3proxy) から作る。
apiVersion: secrets.infisical.com/v1alpha1
kind: InfisicalSecret
metadata:
name: 3proxy
namespace: 3proxy
# 2 つとも必須。前者は operator が作る Secret を prune させないため、後者は
# CRD がまだ無いクラスタで apps/ の同期が丸ごと落ちるのを防ぐため。
# bootstrap/README.md「InfisicalSecret には sync-options を 2 つ付けること」。
# 2 つとも必須。bootstrap/README.md「InfisicalSecret には sync-options を 2 つ付けること」。
annotations:
argocd.argoproj.io/sync-options: Prune=false,SkipDryRunOnMissingResource=true
spec:
Expand Down
3 changes: 0 additions & 3 deletions apps/3proxy/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,6 @@ spec:
ports:
# Gateway は使わない。443 では TLS 終端(HTTPS リスナー)と passthrough が共存できず
# ProtocolConflict になるため(docs/decisions.md)、このサイドカーがホストのポートで直接受ける。
#
# 3proxy 自身の平文が 3128(プロキシの慣用ポート)なので、その TLS 版として隣の 3129。
# コンテナ側の待ち受けと同じ番号なので読み替えも要らない。
- name: proxy-tls
containerPort: 3129
hostPort: 3129
Expand Down
1 change: 0 additions & 1 deletion apps/adguardhome/certificate.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,4 @@ spec:
kind: ClusterIssuer
dnsNames:
# 命名規則(../../README.md「ホスト名の付け方」)どおり、AdGuard Home の 2 語で `ah`。
# 以前は `d.doany.io` で、2026-09-07 に端末の設定を移してから外した。
- ah.doany.io
21 changes: 6 additions & 15 deletions apps/adguardhome/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,10 @@ metadata:
name: adguardhome
namespace: adguardhome
annotations:
# AdGuard 自身の認証は切ってある(`users: []`、2026-09-07)。守っているのは前段の
# oauth2-proxy(bootstrap/auth/adguard-proxy.yaml)で、通るのは Entra のアプリロール
# `admin` を持つ人だけ。AdGuard には SSO も利用者管理も無く、上流の認証プロキシ対応も
# 2020 年から open のままなので、認証を 1 か所(Entra)に寄せた。
# AdGuard 自身の認証は切ってある(`users: []`)。守っているのは前段の oauth2-proxy
# (bootstrap/auth/adguard-proxy.yaml、Entra のアプリロール `admin`)。
# Web の口はクラスタ内からは無認証になる。外からは Gateway 経由だけで、その手前に SSO がある。
#
# AdGuard の設定の正本は initContainer の `CONFIG`(下)。UI で変えた設定は Pod が作り直されると戻る (2026-10-07 から)。
#
# クエリログの保持は 90d だと querylog.json だけで 2 GB に育ち、毎日のバックアップに乗るので
# 7d に縮めた (2026-09-06。`CONFIG` の querylog.interval)。
# クエリログの保持(querylog.interval)は 90d だと querylog.json が 2 GB に育ちバックアップに乗るので 7d。
spec:
replicas: 1
# hostPort を持つので同じポートを 2 つの Pod が同時に掴めない。RollingUpdate だと
Expand All @@ -30,8 +24,7 @@ spec:
spec:
# 設定の正本は下の `CONFIG`。起動のたびに PVC の AdGuardHome.yaml に書き戻してから AdGuard を起動する
# (AdGuard は設定ファイルを書き換えるので、読み取り専用の ConfigMap を直接マウントしない)。
# **Pod の定義の中に置くのは、設定を変えれば Pod が作り直されるようにするため**(ConfigMap だと変えても
# Pod は古い設定のまま動き続け、2026-10-18 まではハッシュの注釈と CI で見張っていた)。
# **Pod の定義の中に置くのは、設定を変えれば Pod が作り直されるようにするため**(ConfigMap だと Pod は古い設定のまま)。
initContainers:
- name: config
image: busybox:1.38
Expand Down Expand Up @@ -244,11 +237,10 @@ spec:
schema_version: 34
containers:
- name: adguardhome
# 版を固定する (2026-10-07 まで latest)。上げると起動時に設定を移行する (schema_version) ので、
# Renovate の PR の中で renovate-post-upgrade.sh が config.yaml も移行しておく。その PR は自動マージする
# 版を上げる Renovate の PR では renovate-post-upgrade.sh が `CONFIG` も移行する(上の注記)。その PR は自動マージする
image: adguard/adguardhome:v0.107.79
# LoadBalancer は使わず、ノードの全アドレスで受けるために hostPort を持つ(docs/decisions.md「LoadBalancer をどう置き換えるか」)。
# hostPort は送信元 IP を保つので、AdGuard のクライアント別統計も従来どおり。
# hostPort は送信元 IP を保つので、AdGuard のクライアント別統計が取れる。
ports:
- name: dns-udp
containerPort: 53
Expand Down Expand Up @@ -295,7 +287,6 @@ spec:
name: doh-proxy
# DoT(853)用の証明書。cert-manager が ah.doany.io で発行した Secret を、
# AdGuard の設定が見ているファイル名(server.crt / server.key)に読み替えて渡す。
# 以前は Traefik の acme.json を監視する acme-watcher が PVC に書き出していた。
- name: adguardhome-ssl
secret:
secretName: adguard-dot-tls
Expand Down
2 changes: 1 addition & 1 deletion apps/adguardhome/doh-proxy-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#
# なぜ要るのか。AdGuard は DoH を HTTPS の口(443)でしか出さない。平文の 80 では 404 になる。
# Gateway が backend へ平文で繋ぐ構成だと DoH が死に、これを「セキュア DNS」に入れている
# ブラウザや端末は名前解決が全部できなくなる(2026-09-07 に実際に起きた)。
# ブラウザや端末は名前解決が全部できなくなる。
#
# なぜ BackendTLSPolicy ではないのか。Cilium 1.20.1 は BackendTLSPolicy を Accepted にするが
# 実際には Envoy の cluster に transport_socket を付けない。backend に平文で繋いだままなので
Expand Down
6 changes: 2 additions & 4 deletions apps/adguardhome/httproute.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,9 @@ spec:
type: PathPrefix
value: /
backendRefs:
# 管理画面は SSO の後ろ。AdGuard 自身には SSO が無いので oauth2-proxy を
# 前段に置く(bootstrap/auth/adguard-proxy.yaml)。名前空間をまたぐので
# auth 側に ReferenceGrant がある。
# 管理画面は oauth2-proxy(bootstrap/auth/adguard-proxy.yaml)の後ろ。auth 側に ReferenceGrant がある。
# `/dns-query` は上のルールで先に拾われる。ここを通すと DoH に認証がかかって
# 名前解決が止まる(2026-09-07 朝の障害)。
# 名前解決が止まる。
- name: auth-adguard
namespace: auth
port: 4180
6 changes: 2 additions & 4 deletions apps/adguardhome/pvc.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# 2 本ともファイルとして k8up に取らせる(`k8up.io/backup: "true"`)。
# 設定・フィルタ・クエリログで、書き換わっても部分的に古いだけで壊れない類い。
# operator は `BACKUP_SKIP_WITHOUT_ANNOTATION=true` なので、注釈が無い PVC は素通りする
#。つまりこの 2 行が「取る」という宣言そのもの(apps/k8up/README.md)。
# 2 本とも k8up に取らせる(書き換わっても部分的に古いだけで壊れない類い)。注釈が無い PVC は
# 取られないので、`k8up.io/backup: "true"` が「取る」という宣言そのもの(apps/k8up/README.md)。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
Expand Down
4 changes: 1 addition & 3 deletions apps/adguardhome/service-dns.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ metadata:
spec:
# ClusterIP でよい理由は docs/decisions.md「ルーティングの選定」の hostPort の表
type: ClusterIP
# Dual-stack: without this the Service is IPv4-only, yet the CNI still
# installs hostPort DNAT rules for v6 :53 -- so IPv6 queries reach the
# svclb pod and are dropped there (klipper-lb only gets SRC_RANGES for v4).
# 無いと IPv4 だけの Service になり、IPv6 で来た DNS(:53)を受けられない。
ipFamilyPolicy: RequireDualStack
ipFamilies:
- IPv4
Expand Down
9 changes: 2 additions & 7 deletions apps/cloudflare-ddns/cloudflare-ddns-secrets.yaml
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
# Secret cloudflare-ddns-secrets は Infisical (il.doany.io) のフォルダ /cloudflare-ddns/cloudflare-ddns-secrets にあり、
# Infisical 純正 operator (apps/infisical-operator) が Secret にする。
# 値は Infisical の UI で書き換えるだけ(push-bridge が数秒で同期。auto-reload 注釈のある
# Deployment は自動で入れ替わる)。
# Secret cloudflare-ddns-secrets を Infisical (/cloudflare-ddns/cloudflare-ddns-secrets) から作る。
apiVersion: secrets.infisical.com/v1alpha1
kind: InfisicalSecret
metadata:
name: cloudflare-ddns-secrets
namespace: cloudflare-ddns
# 2 つとも必須。前者は operator が作る Secret を prune させないため、後者は
# CRD がまだ無いクラスタで apps/ の同期が丸ごと落ちるのを防ぐため。
# bootstrap/README.md「InfisicalSecret には sync-options を 2 つ付けること」。
# 2 つとも必須。bootstrap/README.md「InfisicalSecret には sync-options を 2 つ付けること」。
annotations:
argocd.argoproj.io/sync-options: Prune=false,SkipDryRunOnMissingResource=true
spec:
Expand Down
4 changes: 2 additions & 2 deletions apps/external-dns/application.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ExternalDNS。**Cloudflare を通すアプリの DNS レコードを、アプリの HTTPRoute から作る**(2026-10-06)。
# ExternalDNS。**Cloudflare を通すアプリの DNS レコードを、アプリの HTTPRoute から作る**。
#
# 方針(本人):
# 方針:
# - 社内用や通信量が多いアプリは**直接つなぐ**。何もしない ── `*.doany.io` のワイルドカード
# (proxied ではない CNAME)で引ける
# - SaaS のように外へ出すアプリは **Cloudflare のプロキシを通す**。アプリのリポジトリの HTTPRoute に
Expand Down
5 changes: 2 additions & 3 deletions apps/external-dns/external-dns-secrets.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
# Secret external-dns は Infisical (il.doany.io) のフォルダ /external-dns/external-dns にあり、
# Infisical 純正 operator (apps/infisical-operator) が Secret にする。
# Secret external-dns を Infisical (/external-dns/external-dns) から作る。
#
# cloudflare-api-token Cloudflare の Account API token「external-dns (doany.io DNS write)」。
# 権限は doany.io のゾーンだけの Zone Read + DNS Write(2026-10-06 に作った)
# 権限は doany.io のゾーンだけの Zone Read + DNS Write
apiVersion: secrets.infisical.com/v1alpha1
kind: InfisicalSecret
metadata:
Expand Down
4 changes: 1 addition & 3 deletions apps/forgejo/forgejo-secrets.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ kind: InfisicalSecret
metadata:
name: forgejo-db
namespace: forgejo
# 2 つとも必須。前者は operator が作る Secret を prune させないため、後者は
# CRD がまだ無いクラスタで apps/ の同期が丸ごと落ちるのを防ぐため。
# bootstrap/README.md「InfisicalSecret には sync-options を 2 つ付けること」。
# 2 つとも必須。bootstrap/README.md「InfisicalSecret には sync-options を 2 つ付けること」。
annotations:
argocd.argoproj.io/sync-options: Prune=false,SkipDryRunOnMissingResource=true
spec:
Expand Down
12 changes: 5 additions & 7 deletions apps/forgejo/forgejo.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,12 @@
#
# **chart(forgejo-helm)は使わない。** chart は app.ini の元と init のスクリプトを Secret で作るが、
# このクラスタの ArgoCD は Secret を丸ごと管理対象から外している(bootstrap/argocd/values.yaml の
# resource.exclusions)ので、それらが作られず Pod が起動しない(2026-09-15 に踏んだ)。
# resource.exclusions)ので、それらが作られず Pod が起動しない。
# 設定は環境変数(FORGEJO__<section>__<KEY>)で渡し、イメージの docker-setup.sh が app.ini に書く。
#
# 版は最新を追う(LTS に留めない。2026-09-15 に 15.0.8 → 16.0.4)。Renovate が PR を出す。
# メジャーを上げるときはリリースノートの破壊的変更を読んでから。
# 版は最新を追う(LTS に留めない)。メジャーを上げるときはリリースノートの破壊的変更を読んでから。
#
# 名前が forgejo-web / forgejo-repos なのは、chart 時代の Application が消えるときに
# 同名のリソース(forgejo / forgejo-http / forgejo-data)を消すので、それに巻き込まれないように。
# 名前が forgejo-web / forgejo-repos なのは chart 時代のリソース(forgejo / forgejo-http / forgejo-data)と被らないようにした名残。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
Expand Down Expand Up @@ -85,7 +83,7 @@ data:
--group-claim-name tid \
--group-team-map '{"22ac977d-b140-4dc8-8150-90d645d3475b": {"doa": ["members"]}}'
# 一覧はタブ区切り(ID Name Type Enabled)。--vertical-bars の出力は空白の入り方が一定でなく、
# grep で拾えずに 2 回目の起動で add-oauth が「already exists」で落ちた(2026-09-15)
# 拾い損ねると 2 回目の起動で add-oauth が「already exists」で落ちる
id=$(gitea admin auth list | awk '$2 == "entra" {print $1}')
if [ -z "$id" ]; then
gitea admin auth add-oauth "$@"
Expand Down Expand Up @@ -260,7 +258,7 @@ data:
FORGEJO__actions__DEFAULT_ACTIONS_URL: https://github.com
FORGEJO__repository__DEFAULT_BRANCH: main
FORGEJO__repository__DEFAULT_PRIVATE: private
# マージはスカッシュだけにする方針(GitHub の頃と同じ)。組織単位で縛る設定は Forgejo に無いので、
# マージはスカッシュだけにする方針。組織単位で縛る設定は Forgejo に無いので、
# 既定のマージ方法だけここで決め、許すマージ方法はリポジトリごとに API で絞る(README「マージはスカッシュ」)
FORGEJO__repository_0X2E_pull_0X2D_request__DEFAULT_MERGE_STYLE: squash
FORGEJO__session__COOKIE_SECURE: "true"
Expand Down
31 changes: 10 additions & 21 deletions apps/forgejo/runner.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,21 @@
#
# ネットワークは**ジョブごとに別**(container.network: "")。Runner がジョブごとに dind の中に bridge の
# ネットワーク(WORKFLOW-…)を作り、ジョブ(と services)のコンテナをそこに置き、終わったら消す。
# 前は host(全ジョブが Pod のネットワークを分け合う)だった。それだと、どれかのジョブが dind でコンテナを
# 起こすたびに、全ジョブから見えるところに veth(IPv6 のリンクローカル付き)が出入りし、Chromium が
# ERR_NETWORK_CHANGED で読み込みを切って e2e が落ちた(doa/todoroku#366)。同じ番号のポート(4173 など)も取り合っていた。
# host(全ジョブが Pod のネットワークを分け合う)にしないこと。ほかのジョブの veth が出入りするたびに Chromium が
# ERR_NETWORK_CHANGED で読み込みを切って e2e が落ち(doa/todoroku#366)、同じ番号のポートも取り合う。
#
# ジョブの中から docker を使う(イメージを作る・docker run)ときは、forgejo の docs の「docker-access」の DIND の形:
# ジョブの中から docker を使うときは、forgejo の docs の「docker-access」の DIND の形:
# - ジョブには `--add-host=dind.docker.internal:host-gateway` を足す。host-gateway は dind の docker0 の
# 住所(172.17.0.1。dind 自身 = Pod のネットワーク名前空間の住所)で、dockerd は 0.0.0.0:2376 で待っている。
# ジョブのネットワークからでも、宛先が dind 自身なので届く(別のネットワークのコンテナへの転送とは違い、遮られない)
# 住所(172.17.0.1 = dind 自身)で、dockerd は 0.0.0.0:2376 で待っているので、ジョブのネットワークからも届く
# - ジョブの DOCKER_HOST は tcp://dind.docker.internal:2376。TLS はそのまま(証明書は valid_volumes で渡す)。
# dind のサーバー証明書の SAN にこの名前を足す(DOCKER_TLS_SAN)
# 渡しているのは今までと同じ「dind を丸ごと操れる鍵」なので、できることは host のときと変わらない
# (capacity が 2 以上なので、ジョブは docker の CLI で同時に走っているほかのジョブのコンテナも見える。前から同じ)。
# Runner 自身は今までどおり localhost:2376(Pod の中)で dind に話す。
# キャッシュ(ACTIONS_CACHE_URL)は Runner が自分の Pod の IP で出す。ジョブのネットワークから見ても dind の
# 自分の IP なので届く。
# 渡しているのは「dind を丸ごと操れる鍵」なので、ジョブは同時に走っているほかのジョブのコンテナも見える。
# Runner 自身は localhost:2376 で dind に話す。キャッシュ(ACTIONS_CACHE_URL)は Pod の IP で出すので、ジョブからも届く。
#
# **ジョブのネットワークにも IPv6 を付ける(enable_ipv6)。** 無いと fj.doany.io に届かない。
# fj.doany.io は AAAA(ノード)と A(家の外向きの IPv4)を返し、Pod からは IPv4 の方はヘアピンで届かない
# (curl -4 は時間切れ)。host の頃は Pod の IPv6 で届いていた。checkout・API・upload-artifact・OIDC は
# ジョブの中から fj.doany.io に行くので、IPv4 だけのネットワークでは全部止まる。
# enable_ipv6 にすると dind がネットワークごとに ULA の /64 を割り当て、外へは NAT66(Pod の IPv6)で出るので、
# 外向きは host の頃と同じ形になる(2026-10-07 に本番の dind で確かめた)。
# docker login / push は dind(Pod のネットワーク)が自分で名前を引くので、これまでどおり。
# fj.doany.io は AAAA(ノード)と A(家の外向きの IPv4)を返し、Pod からは IPv4 の方はヘアピンで届かない。
# checkout・API・upload-artifact・OIDC はジョブの中から fj.doany.io に行くので、IPv4 だけでは全部止まる。
# enable_ipv6 にすると dind がネットワークごとに ULA の /64 を割り当て、外へは NAT66(Pod の IPv6)で出る。
# Cilium は vxlan なので Pod の MTU は 1500 より小さい。dind の既定 1500 のままだと大きいパケットが落ちる。
# --mtu は既定の bridge(docker0)にしか効かないので、ジョブのネットワークの分は --default-network-opt で揃える。
apiVersion: v1
Expand Down Expand Up @@ -71,10 +63,7 @@ data:
log:
level: info
runner:
# 同時に受けるジョブの数。ワークフローが 2 本(test と claude-review)ある PR を
# 3 リポジトリぶん積むと 2 では順番待ちが長い。ノードは 44 コア / 46 GiB で
# 使用率は CPU 8% / メモリ 16%、CPU は余っているので詰まるのは下の dind のメモリ。
# 8 本のうち重いのは e2e(ブラウザ)くらいで、それが同時に何本も来ることは稀
# 同時に受けるジョブの数。CPU は余っているので、上限は dind のメモリ(下の limits)で決まる
capacity: 8
timeout: 3h
labels:
Expand Down
4 changes: 2 additions & 2 deletions apps/headlamp/application.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Kubernetes の Web UI。Portainer の置き換え(2026-09-09 に入れ替えた)。h.doany.io。
# Kubernetes の Web UI。h.doany.io。
#
# Resource Map が Gateway / HTTPRoute / GRPCRoute を最初から知っていて、
# parentRefs と backendRefs の線も定義済みなので、公開経路が 1 枚で出る。
Expand All @@ -10,7 +10,7 @@
#
# コールバックは Headlamp が要求のホストから組み立てる(Envoy が x-forwarded-proto を
# 付ける)ので指定しない。Entra 側の redirect URI は登録済み
# (https://h.doany.io/oidc-callback、2026-09-09)。
# (https://h.doany.io/oidc-callback)。
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
Expand Down
Loading
Loading