feat: Alpine ベースの Claude Code リモート実行 Helm チャート初版 (v2.1.259)
Helm Chart Release / release-chart (push) Successful in 12s
Build Session Image / build-push (push) Successful in 2m15s

gateway(nginx) + manager(python 標準ライブラリ) + セッションごとの使い捨て Pod +
reaper CronJob の構成。ブラウザ(PC/スマホ)からアクセスし、セッション単位で
独立した Alpine コンテナに Git リポジトリ(GitHub/Gitea など)をチェックアウトして
編集・検証・プッシュする。無操作が続いたセッションは Pod ごと自動破棄。

- セキュリティ: セッション NS 分離 / restricted PodSecurity / RBAC はセッション NS の
  pods,services のみの Role / セッション Pod は SA トークン非マウント・非 root・
  readOnlyRootFilesystem・drop ALL caps・seccomp / NetworkPolicy で egress を
  DNS+HTTPS+SSH に限定 / Git ホスト allow-list / ResourceQuota+LimitRange
- ライフサイクル: idleTimeout(Pod 内ウォッチドッグ + manager 回収) / maxLifetime
  (activeDeadlineSeconds) / maxSessions / 予備の孤児掃除 CronJob
- 認証: token(既定) / basic / forward(外部SSO) / none。WebSocket は Cookie トークン
- Claude 認証: ANTHROPIC_API_KEY または CLAUDE_CODE_OAUTH_TOKEN
- CI: helm-release.yaml(未リリース版のみ tag+release+publish) /
  image-update-and-release.yaml(週次 npm 追従) / session-image.yaml(multi-arch build)
- files/ 実体を .Files.Get で ConfigMap 化。helm lint / template 検証済み
This commit is contained in:
2026-09-03 08:10:12 +09:00
parent 457a81a17f
commit 1bd0fec23a
39 changed files with 3745 additions and 1 deletions
+338
View File
@@ -0,0 +1,338 @@
# ==========================================================================
# claude-code — Claude Code リモート実行 Helm チャート
# --------------------------------------------------------------------------
# 構成:
# gateway ... 受付 nginx。ブラウザ ↔ セッションの単一入口。認証・WebSocket
# プロキシ・アクティビティ計測を担う。
# manager ... 制御プレーン(Python 標準ライブラリのみ)。セッションの
# 作成/一覧/破棄 API、Web UI、アイドル回収ループ。
# session ... セッションごとに作られる使い捨て Pod。Alpine ベースで
# git clone → 編集 → 検証 → push を行い、claude を ttyd 経由で
# ブラウザに提供する。アイドルで自動破棄。
#
# セキュリティ上の注意(必読):
# - この values.yaml に平文の API キー / SSH 秘密鍵 / トークンを書かない。
# Git にコミットしない。実値は CI の --set / --set-file か existingSecret で注入する。
# - セッション Pod は API サーバーへアクセスできない(SA トークン非マウント)。
# - セッション Pod の egress は Git ホストと api.anthropic.com のみに制限される
# (networkPolicy.enabled: true のとき)。
# - 詳細は README.md「セキュリティモデル」を参照。
# ==========================================================================
nameOverride: ""
fullnameOverride: ""
# --------------------------------------------------------------------------
# image: すべて Alpine ベース / linux/arm64 対応イメージ
# --------------------------------------------------------------------------
image:
# 受付 nginx(非 root 版)
gateway:
registry: docker.io
repository: nginxinc/nginx-unprivileged
tag: "1.29.1-alpine"
pullPolicy: IfNotPresent
# 制御プレーン(Python 標準ライブラリのみ・追加 pip 不要)
manager:
registry: docker.io
repository: library/python
tag: "3.13-alpine"
pullPolicy: IfNotPresent
# セッションの使い捨てコンテナ。
# 既定は CI(session-image.yaml)がビルドする事前ビルドイメージ
# (git + openssh + ttyd + node + @anthropic-ai/claude-code 同梱、非 root 実行)。
# restricted PodSecurity / readOnlyRootFilesystem 下で確実に動くのはこの方式。
#
# 事前ビルドを使わず素の node:alpine 等を指定することも可能だが、その場合
# ブート時に $HOME へ claude を npm インストールし、ttyd が同梱されていないと
# 起動に失敗する(apk は非 root では不可)。フォールバック例:
# registry: docker.io / repository: library/node / tag: "22-alpine"
session:
registry: git.cafepieters.com
repository: helmchart/claude-code/session
tag: "2.1.259"
pullPolicy: IfNotPresent
imagePullSecrets: []
# --------------------------------------------------------------------------
# gateway: 受付・ルーティング
# --------------------------------------------------------------------------
gateway:
replicaCount: 1
# gateway コンテナの待受ポート(Service / Ingress のバックエンド)
port: 8080
resources:
requests:
cpu: 25m
memory: 32Mi
limits:
cpu: 250m
memory: 128Mi
# --------------------------------------------------------------------------
# manager: 制御プレーン
# --------------------------------------------------------------------------
manager:
# debug | info | warning | error
logLevel: info
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 500m
memory: 256Mi
# --------------------------------------------------------------------------
# sessionsNamespace: セッション Pod を隔離するネームスペース
# --------------------------------------------------------------------------
sessionsNamespace:
# 空 = リリース先ネームスペースを使う。セキュリティ上、専用ネームスペースを推奨。
name: "claude-code-sessions"
# true ならこのチャートがネームスペースを作成し PodSecurity ラベルを付与する。
# 既存ネームスペースを使う場合は false にし、下記ラベルを手動で付与すること。
create: true
# PodSecurity admission レベル(restricted 準拠のセッション Pod を強制)
podSecurityLevel: restricted
# セッション NS 全体の使用量上限(暴走・過剰生成のブラスト半径を限定)
resourceQuota:
enabled: true
# 省略値は session.maxSessions と session.resources から算出される。
# 明示指定するとそのまま ResourceQuota.spec.hard になる。
hard: {}
# requests.cpu: "4"
# requests.memory: 8Gi
# limits.cpu: "16"
# limits.memory: 32Gi
# セッション NS のコンテナ既定値 / 上限
limitRange:
enabled: true
max:
cpu: "4"
memory: 4Gi
default:
cpu: "1"
memory: 1Gi
defaultRequest:
cpu: 100m
memory: 256Mi
# --------------------------------------------------------------------------
# auth: ブラウザからのアクセス認証
# --------------------------------------------------------------------------
auth:
# token : Bearer トークン / Cookie / ?token= で検証(既定)
# basic : HTTP Basic 認証(htpasswd)
# forward : 外部認証プロキシ(oauth2-proxy 等)へ auth_request を委譲
# none : 認証なし(信頼済みネットワーク限定・非推奨)
mode: token
token:
# 空なら install 時に自動生成される(helm get manifest で参照可能なため、
# 運用では existingSecret を使うのが望ましい)。
value: ""
existingSecret: ""
existingSecretKey: "token"
basic:
# `htpasswd -nbB user pass` の出力を1行以上。existingSecret 優先。
users: []
existingSecret: ""
existingSecretKey: "htpasswd"
forward:
# nginx auth_request の転送先(例: http://oauth2-proxy.auth.svc.cluster.local:4180/oauth2/auth)
url: ""
# 未認証時のリダイレクト先(任意)
signInUrl: ""
# --------------------------------------------------------------------------
# anthropic: Claude Code の認証情報
# --------------------------------------------------------------------------
anthropic:
# apiKey : ANTHROPIC_API_KEY を使う
# oauth : CLAUDE_CODE_OAUTH_TOKEN を使う(`claude setup-token` で発行)
authMode: apiKey
apiKey: ""
oauthToken: ""
# 上記の代わりに既存 Secret を参照
existingSecret: ""
existingSecretKeyApiKey: "ANTHROPIC_API_KEY"
existingSecretKeyOauthToken: "CLAUDE_CODE_OAUTH_TOKEN"
# 全セッションへ渡す追加環境変数(例: ANTHROPIC_BASE_URL / ANTHROPIC_MODEL)
extraEnv: {}
# --------------------------------------------------------------------------
# git: 接続先ホストと認証アイデンティティ
# --------------------------------------------------------------------------
git:
# チェックアウトを許可するホスト allow-list。manager はこれ以外のホストを拒否する。
allowedHosts:
- github.com
- gitlab.com
- 192.168.9.65
- git.cafepieters.com
# allow-list を無効化し任意 URL を許可する(非推奨)
allowArbitraryRepos: false
# コミット時の既定 author(セッション作成時に上書き可)
defaultAuthorName: "Claude"
defaultAuthorEmail: "claude@cafepieters.com"
# 認証アイデンティティ。セッション作成時に名前で選択する。
# GitHub / Gitea / GitLab など SSH または HTTPS トークンで認証する任意のホストに対応。
identities: {}
# gitea-ssh:
# type: ssh # ssh | https-token
# # --- ssh のとき ---
# sshPrivateKey: "" # PEM 形式。existingSecret 優先
# knownHosts: "" # `ssh-keyscan <host>` の出力(必須/ホスト鍵TOFUを無効化)
# # --- 既存 Secret を使う場合 ---
# existingSecret: ""
# existingSecretKeyPrivateKey: "id"
# existingSecretKeyKnownHosts: "known_hosts"
# github-https:
# type: https-token
# username: "x-access-token" # GitHub は任意文字列、Gitea はユーザー名
# token: "" # PAT。existingSecret 優先
# existingSecret: ""
# existingSecretKeyToken: "token"
# --------------------------------------------------------------------------
# session: 使い捨てセッションの挙動とライフサイクル
# --------------------------------------------------------------------------
session:
# ブート完了後に `claude` を自動起動する(false ならログインシェルで待受)
autoStartClaude: true
# リポジトリを clone する作業ディレクトリ
workspaceDir: /workspace
# ttyd の待受ポート(Pod 内からのみ到達可能)
ttydPort: 7681
# ブート時に追加インストールする apk パッケージ(言語ランタイム等)
extraApkPackages: []
# インストールする @anthropic-ai/claude-code のバージョン(空 = チャート appVersion)
claudeCodeVersion: ""
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: "2"
memory: 2Gi
ephemeral-storage: 4Gi
# ---- lifecycle: 破棄条件 ----
# 無通信がこの秒数継続したセッションを破棄する(Pod 内ウォッチドッグ + manager 回収)
idleTimeoutSeconds: 1800
# 生成からの最大寿命(Pod の activeDeadlineSeconds)。到達で強制終了。
maxLifetimeSeconds: 43200
reaper:
# manager 内アイドル回収ループの実行間隔
intervalSeconds: 60
# 予備の孤児掃除 CronJob(manager 障害時の保険)
cronjob:
enabled: true
schedule: "*/15 * * * *"
# 同時に存在できるセッション数の上限(manager が enforce)
maxSessions: 10
# ---- verify / push ----
# セッション内の `claude-verify` が実行するコマンド(例: "npm test" / "make check")
verifyCommand: ""
autoPush:
# true でもデフォルトブランチや protectedBranches への push、--force は禁止。
enabled: false
branchPrefix: "claude/"
protectedBranches:
- main
- master
- develop
- release
# セッション Pod への追加メタデータ / スケジューリング
podLabels: {}
podAnnotations: {}
nodeSelector: {}
tolerations: []
# セッション Pod の優先度クラス(任意)
priorityClassName: ""
# --------------------------------------------------------------------------
# networkPolicy: 通信制限(CNI が NetworkPolicy 対応であること)
# --------------------------------------------------------------------------
networkPolicy:
enabled: true
# DNS 解決を許可する kube-dns の namespace セレクタ
dnsNamespaceSelector:
kubernetes.io/metadata.name: kube-system
# api.anthropic.com / GitHub は IP 固定できないため、既定でセッションの
# 443/tcp(HTTPS git・Claude API)と 22/tcp(SSH git)の外向きを許可する。
# 完全に閉じる場合は egress プロキシを用意し false にする。
allowInternetHttps: true
allowSshGit: true
# allowInternetHttps 時に egress から除外する CIDR(SSRF 対策)。
# クラウドのメタデータ IP は既定で遮断。自クラスターの Pod/Service CIDR を
# 追加すると、セッションから内部サービスへの到達を防げる。
blockedEgressCIDRs:
- 169.254.169.254/32
# 追加で許可する egress(社内ミラー / プロキシ用)
sessionEgressExtra: []
# - cidr: 10.0.0.0/8
# ports:
# - protocol: TCP
# port: 443
# --------------------------------------------------------------------------
# ingress / service
# --------------------------------------------------------------------------
ingress:
enabled: false
className: ""
annotations: {}
# nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
# nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
hosts:
- host: claude-code.example.com
paths:
- path: /
pathType: Prefix
tls: []
# - secretName: claude-code-tls
# hosts:
# - claude-code.example.com
service:
type: ClusterIP
port: 80
# --------------------------------------------------------------------------
# 制御プレーンの Pod / コンテナセキュリティ
# --------------------------------------------------------------------------
podSecurityContext:
runAsNonRoot: true
runAsUser: 65532
runAsGroup: 65532
fsGroup: 65532
seccompProfile:
type: RuntimeDefault
containerSecurityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
# 全リソースへ付与する追加ラベル / アノテーション
commonLabels: {}
commonAnnotations: {}
podDisruptionBudget:
enabled: false
minAvailable: 1