3 Commits
Author SHA1 Message Date
claude cd7092be17 feat: Service を LoadBalancer 対応にしローカル LB の IP で管理画面へアクセス可能に (v2.1.263-a)
Helm Chart Release / release-chart (push) Successful in 7s
Build Session Image / build-push (push) Successful in 2m3s
- templates/service.yaml: service.type 既定を LoadBalancer に。annotations
  (kube-vip の VIP 指定等) / loadBalancerIP / loadBalancerClass /
  loadBalancerSourceRanges / externalTrafficPolicy / nodePort / labels を追加。
  Ingress 機能は変更なし(LoadBalancer と併用可)
- values.yaml / values.schema.json: service ブロックを拡張
- templates/NOTES.txt: LoadBalancer の EXTERNAL-IP 案内を追加
- examples/loadbalancer-oauth.values.yaml: Ingress 無効 + LB + source range 制限 +
  サブスクリプション認証 (authMode: oauth) の構成例を追加
- README: 「Claude 認証(API 課金なし / サブスクリプション)」「管理画面への
  アクセス(LoadBalancer / Ingress)」セクションを追加。claude setup-token →
  anthropic.authMode: oauth(CLAUDE_CODE_OAUTH_TOKEN 注入)でローカル実行と同一挙動
- helm lint / template 検証済み
2026-09-08 14:01:34 +09:00
claude 71d8db5b09 chore: update Claude Code to 2.1.263 (nginx 1.31.5-alpine, python 3.14-alpine) 2026-09-06 18:04:41 +00:00
claude 4913ceace7 docs: CLAUDE.md を階層化した共通ルールに合わせて整理し、GEMINI.md と .agents/rules(Antigravity 用参照)を追加
Helm Chart Release / release-chart (push) Successful in 4s
2026-09-04 13:23:58 +09:00
11 changed files with 370 additions and 56 deletions
+7
View File
@@ -0,0 +1,7 @@
---
trigger: always_on
description: Read the CLAUDE.md hierarchy via GEMINI.md before doing anything in this workspace
---
最初に、このディレクトリの `GEMINI.md` を読み、そこに列挙された CLAUDE.md を上から順にすべて読んで従うこと。
Read `GEMINI.md` in this directory first, then read and follow every CLAUDE.md it lists, in order.
+34
View File
@@ -0,0 +1,34 @@
# CHANGELOG 2.1.263-a — 手動リリース
v2.1.263(自動更新)の上に適用する手動リリース。
## 追加 / 変更
- **Service の LoadBalancer 対応(既定を `LoadBalancer` に変更)**
- `service.annotations` … LB 実装へのヒント。kube-vip の VIP 指定
(`kube-vip.io/loadbalancerIPs` / `kube-vip.io/vipHost`)、MetalLB のプール指定など。
- `service.loadBalancerIP` / `service.loadBalancerClass`
- `service.loadBalancerSourceRanges` … 接続元 CIDR を制限。Ingress を張らない構成での
第一の防御線。
- `service.externalTrafficPolicy` … `Local` で実クライアント IP を保持。
- `service.nodePort` … `type: NodePort` 時の固定ポート。
- `service.labels`
- Ingress 機能(`ingress.*`)は変更なし。LoadBalancer と併用できる。
- `templates/NOTES.txt` に LoadBalancer の EXTERNAL-IP 確認手順を追加。
- `examples/loadbalancer-oauth.values.yaml` を追加
(Ingress 無効 + `service.type: LoadBalancer` + kube-vip VIP + `loadBalancerSourceRanges`
によるローカルセグメント限定 + `anthropic.authMode: oauth`)。
## ドキュメント
- README に **「Claude 認証(API 課金なし / サブスクリプション)」** セクションを追加。
`claude setup-token` で発行した長期 OAuth トークンを `anthropic.oauthToken`
(`authMode: oauth`)に渡すと、API 従量課金を使わずローカルの Claude Code と同一の
挙動で動作する。トークンはセッション NS の Secret に保存し、セッション Pod へ
`CLAUDE_CODE_OAUTH_TOKEN` として注入。
- README に **「管理画面へのアクセス(LoadBalancer / Ingress)」** セクションを追加。
## バージョン
`version` = `2.1.263-a` / `appVersion` = `"2.1.263"`(主アプリ = Claude Code CLI は据え置き、
チャートのみ手動リリース)。
+35 -37
View File
@@ -1,5 +1,8 @@
# CLAUDE.md — claude-code Helm Chart # CLAUDE.md — claude-code Helm Chart
> **共通ルール(要約)** — 詳細は `P:\Claude\CLAUDE.md`(全体共通)と `P:\Claude\HelmChart\CLAUDE.md`(Helm チャート共通: リリースフロー・ワークフロー・Gitea Secrets)を参照。
> 作業前に pull / 機能変更時は README 更新 / 作業単位ごとに commit → push まで / コミットに AI クレジットを付けない / pull で入った変更を revert しない / Helm はローカル実行不可(Python のみ可)。
## リポジトリ概要 ## リポジトリ概要
Alpine Linux ベースの軽量コンテナで **Claude Code をリモート実行** するための Helm チャート。 Alpine Linux ベースの軽量コンテナで **Claude Code をリモート実行** するための Helm チャート。
@@ -11,6 +14,8 @@ Git リポジトリ(GitHub / Gitea など互換 Git 全般)をチェック
- **Helm リポジトリ**: `https://git.cafepieters.com/api/packages/helmchart/helm` - **Helm リポジトリ**: `https://git.cafepieters.com/api/packages/helmchart/helm`
- **セッションイメージ**: `git.cafepieters.com/helmchart/claude-code/session:<appVersion>`(CI で publish) - **セッションイメージ**: `git.cafepieters.com/helmchart/claude-code/session:<appVersion>`(CI で publish)
> **注意**: セッション Pod は Gitea からリポジトリ単体を clone するため、`P:\Claude` の上位階層 CLAUDE.md は届かない。各リポジトリの CLAUDE.md 先頭に「共通ルール(要約)」を置く理由はこれ。
## アーキテクチャ(要点) ## アーキテクチャ(要点)
| コンポーネント | 実体 | 役割 | | コンポーネント | 実体 | 役割 |
@@ -28,37 +33,16 @@ Git リポジトリ(GitHub / Gitea など互換 Git 全般)をチェック
- ファイル実体は `files/`(`.Files.Get` で ConfigMap 化): `manager.py` / `session-entrypoint.sh` - ファイル実体は `files/`(`.Files.Get` で ConfigMap 化): `manager.py` / `session-entrypoint.sh`
/ `gateway.conf.template` / `gateway-entrypoint.sh` / `Dockerfile.session`。 / `gateway.conf.template` / `gateway-entrypoint.sh` / `Dockerfile.session`。
## 実行環境について ## README 更新時の追加事項
**Helm はこのマシンにインストールされていない。** ローカルで `helm lint` / `template` は実行できない。 - values の新設キー、挙動変更、セキュリティ影響は README の該当セクションと values リファレンス表へ反映する。
テンプレートの検証はステージングのクラスタか CI(`helm-release.yaml` の lint ステップ)で行う。 - 手動リリース(`-a` 等)時は対応する `CHANGELOG-<version>.md` を追加し、README の「バージョン履歴」にも 1 行追加する(このリポジトリの慣行)。
## Git 運用ルール(このリポジトリで厳守) ## リリースフロー(組織ルールとの差分)
1. **機能を追加・変更したら、必ず `README.md` を更新してから作業完了とする。**
- values の新設キー、挙動変更、セキュリティ影響は README の該当セクションと
values リファレンス表へ反映する。
2. **変更は必ず Git Commit / Push する。**
- 作業単位ごとにコミットし、`origin/main` へ push するまでが作業完了。
3. **コミットメッセージに Claude クレジット(`Co-Authored-By` 等)を付けない。**
- `user.name = Claude` でコミットされるため、ユーザー名で判別可能。
4. `git pull` で取り込んだ変更は常に尊重する。revert して push することは禁止。
不適切と思われる場合はユーザーに改善提案を提示し、承認を得てから対応する。
### Git Commit 情報
| 項目 | 値 |
|------|-----|
| user.name | `Claude` |
| user.email | `claude@cafepieters.com` |
| SSH キー | `P:/Claude/.ssh/id_claude` |
| core.sshCommand | `ssh -i P:/Claude/.ssh/id_claude -F P:/Claude/.ssh/config -o StrictHostKeyChecking=no` |
## リリースフロー
- **バージョン番号**: `Chart.yaml` の `version` / `appVersion` は - **バージョン番号**: `Chart.yaml` の `version` / `appVersion` は
**主アプリ = Claude Code CLI(`@anthropic-ai/claude-code` の npm 最新版)と同一**にする。 **主アプリ = Claude Code CLI(`@anthropic-ai/claude-code` の npm 最新版)と同一**にする。
- **ワークフロー(3 本、他 Helm チャートプロジェクトと同じ思想)** - **ワークフロー(3 本)**
- `helm-release.yaml` — `main` への push で発火。`helm lint` の後、`Chart.yaml` の version が - `helm-release.yaml` — `main` への push で発火。`helm lint` の後、`Chart.yaml` の version が
未リリース(Gitea リリース・Package Registry 双方に存在しない)なら タグ + Gitea リリース + 未リリース(Gitea リリース・Package Registry 双方に存在しない)なら タグ + Gitea リリース +
チャート publish。リリース済みなら lint のみで終了(再 publish しない)。 チャート publish。リリース済みなら lint のみで終了(再 publish しない)。
@@ -69,20 +53,34 @@ Git リポジトリ(GitHub / Gitea など互換 Git 全般)をチェック
- `session-image.yaml` — `files/Dockerfile.session` 等の変更、または上記による `Chart.yaml` - `session-image.yaml` — `files/Dockerfile.session` 等の変更、または上記による `Chart.yaml`
更新で発火。セッションイメージを `linux/amd64,linux/arm64` でビルドして 更新で発火。セッションイメージを `linux/amd64,linux/arm64` でビルドして
Gitea Container Registry(`helmchart/claude-code/session:<appVersion>` + `latest`)へ push。 Gitea Container Registry(`helmchart/claude-code/session:<appVersion>` + `latest`)へ push。
- **手動リリース(臨時)**: 改修作業などで必要な場合はバージョン末尾にアルファベットを付与する - **手動リリース(臨時)**: 例 `2.1.259` → `2.1.259-a` → `2.1.259-b`。
(例 `2.1.259` → `2.1.259-a` → `2.1.259-b`)。対応する `CHANGELOG-<version>.md` を追加し、
README の「バージョン履歴」にも 1 行追加する。
## 必要な Gitea Secrets
| シークレット名 | 用途 |
|---|---|
| `GITEA_TOKEN` | Gitea API(リリース作成・タグ操作) |
| `REGISTRY_USER` | Gitea Package / Container Registry ユーザー名 |
| `REGISTRY_TOKEN` | Gitea Package / Container Registry トークン(`docker login` にも使用) |
## 改修履歴 ## 改修履歴
### Service の LoadBalancer 対応 + サブスクリプション認証手順の明文化(2026-09-08, v2.1.263-a)
**背景**: Ingress を張らずに、ローカルネットワークの LB(kube-vip 等)から払い出した IP で
管理画面へアクセスしたい、という運用要望。あわせて「Claude の API 課金を使わず、ローカルの
Claude Code と同様にサブスクリプションで使いたい」という確認があった。
**修正内容**:
- `templates/service.yaml` を書き換え、`service.type: LoadBalancer` を既定化。
`service.annotations`(kube-vip の `kube-vip.io/loadbalancerIPs` / `vipHost` 等)、
`loadBalancerIP` / `loadBalancerClass` / `loadBalancerSourceRanges` /
`externalTrafficPolicy` / `nodePort` / `labels` を追加。Ingress 機能は変更なし(併用可)。
- `values.yaml` の `service:` ブロック拡張、`values.schema.json` に対応プロパティ追加。
- `templates/NOTES.txt` に LoadBalancer の EXTERNAL-IP 案内を追加。
- `examples/loadbalancer-oauth.values.yaml` を追加(Ingress 無効 + LB + source range +
`authMode: oauth`)。
- README に「Claude 認証(API 課金なし / サブスクリプション)」「管理画面へのアクセス
(LoadBalancer / Ingress)」セクションを追加。サブスクリプション認証は
`claude setup-token` → `anthropic.authMode: oauth`(`CLAUDE_CODE_OAUTH_TOKEN` を
セッション Pod に注入)で、ローカル実行の Claude Code と同一挙動。
**対象ファイル**: `templates/service.yaml`, `values.yaml`, `values.schema.json`,
`templates/NOTES.txt`, `examples/loadbalancer-oauth.values.yaml`, `README.md`, `Chart.yaml`,
`CHANGELOG-2.1.263-a.md`
### 初版(2026-09-03, v2.1.259) ### 初版(2026-09-03, v2.1.259)
チャート新規作成。gateway + manager + 使い捨て session Pod + reaper CronJob の構成で、 チャート新規作成。gateway + manager + 使い捨て session Pod + reaper CronJob の構成で、
+2 -2
View File
@@ -6,8 +6,8 @@ description: >-
使い捨てコンテナで Git リポジトリ(GitHub / Gitea など)をチェックアウト・編集・ 使い捨てコンテナで Git リポジトリ(GitHub / Gitea など)をチェックアウト・編集・
検証・プッシュする。一定時間アイドルなセッションは自動破棄される。 検証・プッシュする。一定時間アイドルなセッションは自動破棄される。
type: application type: application
version: 2.1.259 version: 2.1.263-a
appVersion: "2.1.259" appVersion: "2.1.263"
keywords: keywords:
- claude-code - claude-code
- claude - claude
+24
View File
@@ -0,0 +1,24 @@
# GEMINI.md — Antigravity (Gemini) 用エントリポイント(HelmChart\claude-code)
このディレクトリのルールはすべて **`CLAUDE.md`** に記載されている。本ファイルにはルール本文を書かず、読むべき CLAUDE.md への参照だけを置く(正本は常に CLAUDE.md)。
## 必ず最初に実行すること
以下のファイルを**上から順に**読み込み、すべての指示に従うこと。上位ほど広い範囲に適用される共通ルールで、下位は上位を前提とした補足・例外である。
1. `P:\Claude\CLAUDE.md` — 全組織共通ルール(Git 運用・コミット書式・実行環境・情報記載の原則)
2. `P:\Claude\HelmChart\CLAUDE.md` — HelmChart 組織共通ルール
3. `P:\Claude\HelmChart\claude-code\CLAUDE.md` — claude-code リポジトリ固有ルール(このディレクトリ)
> Antigravity はワークスペース(または git ルート)直下のルールしか自動で読まず、親フォルダを遡らない。そのため上位階層のパスをここに明示している。`P:\Claude` はクラウド同期されており、デスクトップ・ノート PC とも同じパスで存在する。
## 読み替え
- CLAUDE.md 中の「Claude」「Claude Code」は、Antigravity で作業する場合は Gemini 自身のことと読み替える。
- Git のコミット者は Antigravity でも `user.name = Claude` / `user.email = claude@cafepieters.com` のまま使う(変更しない)。コミットメッセージに AI クレジットを付けない。
- Claude Code 固有の機能(`.claude/` 設定、スキル、メモリ等)に関する記述は無視してよい。
## 保守ルール
- ルールの追加・変更は **CLAUDE.md にのみ**行う。本ファイルと `.agents/rules/claude-md.md` は参照だけを保持し、内容を増やさない。
- CLAUDE.md を新しいディレクトリに追加したときは、同じ形式の `GEMINI.md` と `.agents/rules/claude-md.md` も併置する。
+137 -11
View File
@@ -21,6 +21,8 @@ Raspberry Pi などの ARM ベアメタル Kubernetes を主な対象にして
- [アーキテクチャ](#アーキテクチャ) - [アーキテクチャ](#アーキテクチャ)
- [セッションのライフサイクル](#セッションのライフサイクル) - [セッションのライフサイクル](#セッションのライフサイクル)
- [セキュリティモデル](#セキュリティモデル) - [セキュリティモデル](#セキュリティモデル)
- [Claude 認証(API 課金なし / サブスクリプション)](#claude-認証api-課金なし--サブスクリプション)
- [管理画面へのアクセス(LoadBalancer / Ingress)](#管理画面へのアクセスloadbalancer--ingress)
- [インストール](#インストール) - [インストール](#インストール)
- [使い方](#使い方) - [使い方](#使い方)
- [values リファレンス](#values-リファレンス) - [values リファレンス](#values-リファレンス)
@@ -32,7 +34,7 @@ Raspberry Pi などの ARM ベアメタル Kubernetes を主な対象にして
- [git — 接続先と認証アイデンティティ](#git--接続先と認証アイデンティティ) - [git — 接続先と認証アイデンティティ](#git--接続先と認証アイデンティティ)
- [session — 使い捨てセッション](#session--使い捨てセッション) - [session — 使い捨てセッション](#session--使い捨てセッション)
- [networkPolicy](#networkpolicy) - [networkPolicy](#networkpolicy)
- [ingress / service](#ingress--service) - [service / ingress](#ingress--service)
- [セッションイメージ](#セッションイメージ) - [セッションイメージ](#セッションイメージ)
- [運用](#運用) - [運用](#運用)
- [トラブルシューティング](#トラブルシューティング) - [トラブルシューティング](#トラブルシューティング)
@@ -111,13 +113,120 @@ manager / gateway / session-entrypoint の実体は `files/` にあり、`.Files
> **注意** — `values.yaml` に API キーや秘密鍵を書いてコミットしないでください。`helm get values` / > **注意** — `values.yaml` に API キーや秘密鍵を書いてコミットしないでください。`helm get values` /
> CI ログ / Git 履歴に残ります。`existingSecret` か CI からの `--set` を使ってください。 > CI ログ / Git 履歴に残ります。`existingSecret` か CI からの `--set` を使ってください。
## Claude 認証(API 課金なし / サブスクリプション)
このチャートは **Claude の API(従量課金)を使わずに**、ローカルの Claude Code と同じ
**サブスクリプション認証(Pro / Max プラン)** で動かせます。セッション内の `claude` の
挙動・機能はローカル実行と同一です(同じ CLI・同じログイン方式)。
1. 手元の PC(Claude にログイン済み)で長期トークンを発行:
```bash
claude setup-token
```
ブラウザで承認すると `CLAUDE_CODE_OAUTH_TOKEN` として使える長期トークンが表示されます。
2. それをチャートに渡す(`authMode: oauth`):
```bash
helm upgrade --install claude-code cafepieters/claude-code -n claude-code --create-namespace \
-f examples/loadbalancer-oauth.values.yaml \
--set anthropic.oauthToken="<発行されたトークン>"
```
Secret にしておく場合:
```bash
kubectl -n claude-code-sessions create secret generic claude-oauth \
--from-literal=CLAUDE_CODE_OAUTH_TOKEN="<トークン>"
# values: anthropic.existingSecret=claude-oauth
```
| 方式 | values | 認証情報 | 課金 |
|---|---|---|---|
| **サブスクリプション(推奨)** | `anthropic.authMode: oauth` | `anthropic.oauthToken`(`claude setup-token`) | Claude プランの利用枠を消費(API 課金なし) |
| API キー | `anthropic.authMode: apiKey` | `anthropic.apiKey`(`sk-ant-...`) | API 従量課金 |
- トークンは **セッション NS の Secret** に保存され、セッション Pod へ環境変数
`CLAUDE_CODE_OAUTH_TOKEN` として注入されます(`values.yaml` に平文で書かない)。
- 利用枠はローカルの Claude Code と共有です。複数セッションを同時に走らせると
プランのレート上限に早く達する点に注意してください。
- トークンには有効期限があります。失効したら `claude setup-token` で再発行し
`helm upgrade --set anthropic.oauthToken=...`(または Secret 更新 + Pod 再起動)します。
## 管理画面へのアクセス(LoadBalancer / Ingress)
管理画面(gateway)への到達経路は 2 つあり、**併用できます**。既定は LoadBalancer です。
### A. LoadBalancer でローカルネットワークの IP を使う(既定・Ingress 不要)
`service.type: LoadBalancer`(既定)にすると、クラスタの LB 実装
(**kube-vip** / MetalLB / Cilium LB-IPAM など)がローカルネットワークの IP を払い出します。
その IP をブラウザで開くだけでアクセスできます。ドメインも Ingress も TLS 終端も不要です。
```yaml
ingress:
enabled: false # Ingress は張らない
service:
type: LoadBalancer
port: 80
annotations:
kube-vip.io/loadbalancerIPs: "192.168.9.50" # 払い出す VIP(空きアドレス)
kube-vip.io/vipHost: "cpi11"
loadBalancerSourceRanges: # 接続元をローカルセグメントに限定(第一の防御線)
- 192.168.9.0/24
externalTrafficPolicy: Local # 実クライアント IP を保持
```
```bash
kubectl -n claude-code get svc claude-code # EXTERNAL-IP を確認
# → http://<EXTERNAL-IP>/ をブラウザで開く
```
| キー | 説明 |
|---|---|
| `service.type` | `LoadBalancer`(既定)/ `ClusterIP` / `NodePort` |
| `service.port` | 待受ポート(既定 `80`) |
| `service.annotations` | LB 実装へのヒント(kube-vip の VIP 指定、MetalLB のプール指定など) |
| `service.loadBalancerIP` | 払い出す IP を直接指定(annotations 指定を推奨) |
| `service.loadBalancerSourceRanges` | 接続を許可する CIDR。**Ingress を張らない構成では必ず設定して接続元を絞る** |
| `service.loadBalancerClass` | 複数 LB 実装がある場合の指定 |
| `service.externalTrafficPolicy` | `Local` で実クライアント IP を保持 |
| `service.nodePort` | `type: NodePort` 時の固定ポート |
> **セキュリティ** — LoadBalancer は L3/L4 でネットワークに口を開けます。`loadBalancerSourceRanges`
> で接続元を絞り、`auth.mode` は `token`(既定)以上にしてください。VIP セグメントは
> ルーターの DHCP 範囲と重複させないこと。
### B. Ingress でドメインアクセス(従来どおり維持)
`ingress.enabled: true` で Ingress を作成します。A と同時に有効化しても構いません。
WebSocket 用に `proxy-read-timeout` / `proxy-send-timeout` を既定 `3600` に設定します
(`ingress.annotations` で上書き可)。TLS は `ingress.tls` で設定します。
```yaml
ingress:
enabled: true
className: nginx
hosts:
- host: claude-code.example.com
paths: [{ path: /, pathType: Prefix }]
tls:
- secretName: claude-code-tls
hosts: [claude-code.example.com]
```
## インストール ## インストール
### 前提 ### 前提
- Kubernetes 1.25+(PodSecurity admission)、NetworkPolicy 対応 CNI(Calico / Cilium など) - Kubernetes 1.25+(PodSecurity admission)、NetworkPolicy 対応 CNI(Calico / Cilium など)
- Ingress コントローラー(外部公開する場合。WebSocket を通すため read/send timeout を延長) - 管理画面の公開方法に応じて **どちらか**:
- `ANTHROPIC_API_KEY`(または `claude setup-token` で発行した OAuth トークン) - LoadBalancer 実装(kube-vip / MetalLB / Cilium LB-IPAM など) … 既定
- Ingress コントローラー … `ingress.enabled: true` の場合
- どちらも無い場合は `service.type: ClusterIP` + `kubectl port-forward` で利用可
- Claude の認証情報 … `claude setup-token` の OAuth トークン(推奨)または `ANTHROPIC_API_KEY`
### Helm リポジトリから ### Helm リポジトリから
@@ -130,6 +239,22 @@ helm upgrade --install claude-code cafepieters/claude-code \
--set anthropic.apiKey="$ANTHROPIC_API_KEY" --set anthropic.apiKey="$ANTHROPIC_API_KEY"
``` ```
### ローカル LB の IP + サブスクリプション認証(API 不要・推奨構成)
```bash
claude setup-token # 手元の PC で長期 OAuth トークンを発行
helm upgrade --install claude-code cafepieters/claude-code \
-n claude-code --create-namespace \
-f examples/loadbalancer-oauth.values.yaml \
--set anthropic.oauthToken="<発行されたトークン>" \
--set-file git.identities.gitea-ssh.sshPrivateKey=P:/Claude/.ssh/id_claude \
--set-file git.identities.gitea-ssh.knownHosts=./known_hosts.gitea
```
`examples/loadbalancer-oauth.values.yaml` は Ingress 無効・`service.type: LoadBalancer` +
kube-vip の VIP 指定 + `loadBalancerSourceRanges` によるローカルセグメント限定の構成です。
### ローカルチャートから(GitHub 公開リポジトリだけ触る最小構成) ### ローカルチャートから(GitHub 公開リポジトリだけ触る最小構成)
```bash ```bash
@@ -159,11 +284,11 @@ ssh-keyscan 192.168.9.65 > known_hosts.gitea
## 使い方 ## 使い方
1. アクセス(Ingress 無効ならポートフォワード): 1. 管理画面を開く:
- **LoadBalancer(既定)**: `kubectl -n claude-code get svc claude-code` の `EXTERNAL-IP` を
```bash ブラウザで開く(`http://<IP>/`)
kubectl -n claude-code port-forward svc/claude-code 8080:80 - **Ingress**: 設定したドメイン(`https://claude-code.example.com/`)
``` - **どちらも無効**: `kubectl -n claude-code port-forward svc/claude-code 8080:80` → `http://localhost:8080/`
2. `auth.mode: token` の場合、トークンを取得して UI に貼り付け(または `?token=` で開く): 2. `auth.mode: token` の場合、トークンを取得して UI に貼り付け(または `?token=` で開く):
@@ -288,9 +413,8 @@ GitHub でも Gitea でも GitLab でも、SSH か HTTPS トークンで認証
### ingress / service ### ingress / service
`ingress.enabled: true` で Ingress を作成。WebSocket 用に `proxy-read-timeout` / → [管理画面へのアクセス(LoadBalancer / Ingress)](#管理画面へのアクセスloadbalancer--ingress) を参照。
`proxy-send-timeout` を既定 `3600` に設定します(`ingress.annotations` で上書き可)。 `service.type` の既定は `LoadBalancer`、`ingress.enabled` の既定は `false`(両者は併用可)。
`service.type` は `ClusterIP` 既定。
## セッションイメージ ## セッションイメージ
@@ -368,4 +492,6 @@ docker buildx build --platform linux/amd64,linux/arm64 \
| バージョン | Claude Code | 変更内容 | | バージョン | Claude Code | 変更内容 |
|---|---|---| |---|---|---|
| 2.1.263-a | 2.1.263 | Service を `LoadBalancer` 対応(kube-vip 等でローカル LB の IP から管理画面へアクセス、`loadBalancerSourceRanges` で接続元制限、既定を `LoadBalancer` に変更)。Ingress は従来どおり併用可。API を使わないサブスクリプション認証(`claude setup-token` → `authMode: oauth`)の手順を README に追記 |
| 2.1.263 | 2.1.263 | 自動更新 |
| 2.1.259 | 2.1.259 | 初版。gateway + manager + 使い捨て session Pod + reaper、GitHub/Gitea 対応、アイドル自動破棄、NetworkPolicy / RBAC 最小化 / restricted PodSecurity | | 2.1.259 | 2.1.259 | 初版。gateway + manager + 使い捨て session Pod + reaper、GitHub/Gitea 対応、アイドル自動破棄、NetworkPolicy / RBAC 最小化 / restricted PodSecurity |
+63
View File
@@ -0,0 +1,63 @@
# ローカルネットワーク限定の LoadBalancer で公開し、Claude のサブスクリプション
# (API 課金なし)で動かす構成。Ingress は張らない。
#
# 前提:
# - クラスタに LB 実装(kube-vip / MetalLB / Cilium LB-IPAM 等)がある
# - ローカルで `claude setup-token` を実行して長期 OAuth トークンを発行済み
#
# 実行例:
# helm upgrade --install claude-code cafepieters/claude-code \
# -n claude-code --create-namespace \
# -f examples/loadbalancer-oauth.values.yaml \
# --set anthropic.oauthToken="$(cat ~/.claude/oauth-token.txt)" \
# --set-file git.identities.gitea-ssh.sshPrivateKey=P:/Claude/.ssh/id_claude \
# --set-file git.identities.gitea-ssh.knownHosts=./known_hosts.gitea
# ---- Claude 認証: API を使わずサブスクリプション(Pro / Max)で動かす ----
anthropic:
authMode: oauth # ANTHROPIC_API_KEY ではなく CLAUDE_CODE_OAUTH_TOKEN を使う
# oauthToken は --set / --set-file / existingSecret で注入する(平文で書かない)
# ---- 管理画面はローカル LB の IP でアクセス(Ingress なし)----
ingress:
enabled: false
service:
type: LoadBalancer
port: 80
annotations:
# kube-vip で払い出す VIP を固定(この 192.168.9.x は空いているものを指定)
kube-vip.io/loadbalancerIPs: "192.168.9.50"
kube-vip.io/vipHost: "cpi11"
# 接続元をローカルセグメントに限定(Ingress を張らない構成での第一の防御線)
loadBalancerSourceRanges:
- 192.168.9.0/24
externalTrafficPolicy: Local # 実クライアント IP を保持(LB 実装が対応する場合)
# ---- ブラウザアクセスの認証: トークン(自動生成)----
auth:
mode: token
# token.value を空にすると install 時に自動生成される。
# 取得: kubectl -n claude-code get secret claude-code-auth -o jsonpath='{.data.token}' | base64 -d
# ---- Git 接続先 ----
git:
allowedHosts:
- github.com
- 192.168.9.65
- git.cafepieters.com
identities:
gitea-ssh:
type: ssh
# sshPrivateKey / knownHosts は --set-file で注入
# github-https:
# type: https-token
# username: "x-access-token"
session:
autoStartClaude: true
idleTimeoutSeconds: 1800
maxSessions: 5
# verifyCommand: "npm test"
# autoPush:
# enabled: true
+9 -1
View File
@@ -11,7 +11,15 @@ claude-code ({{ .Chart.Version }}) をデプロイしました。
{{- range .Values.ingress.hosts }} {{- range .Values.ingress.hosts }}
https://{{ .host }}/ https://{{ .host }}/
{{- end }} {{- end }}
{{- else }} {{- end }}
{{- if eq .Values.service.type "LoadBalancer" }}
ロードバランサーの IP を確認してブラウザで開いてください:
kubectl -n {{ .Release.Namespace }} get svc {{ include "claude-code.fullname" . }} -w
→ http://<EXTERNAL-IP>:{{ .Values.service.port }}/
{{- with .Values.service.loadBalancerSourceRanges }}
(接続元は {{ join ", " . }} に制限されています)
{{- end }}
{{- else if not .Values.ingress.enabled }}
kubectl -n {{ .Release.Namespace }} port-forward svc/{{ include "claude-code.fullname" . }} 8080:{{ .Values.service.port }} kubectl -n {{ .Release.Namespace }} port-forward svc/{{ include "claude-code.fullname" . }} 8080:{{ .Values.service.port }}
→ http://localhost:8080/ → http://localhost:8080/
{{- end }} {{- end }}
+23
View File
@@ -6,13 +6,36 @@ metadata:
labels: labels:
{{- include "claude-code.labels" . | nindent 4 }} {{- include "claude-code.labels" . | nindent 4 }}
app.kubernetes.io/component: control-plane app.kubernetes.io/component: control-plane
{{- with .Values.service.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.service.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec: spec:
type: {{ .Values.service.type }} type: {{ .Values.service.type }}
{{- if and (eq .Values.service.type "LoadBalancer") .Values.service.loadBalancerIP }}
loadBalancerIP: {{ .Values.service.loadBalancerIP | quote }}
{{- end }}
{{- with .Values.service.loadBalancerClass }}
loadBalancerClass: {{ . | quote }}
{{- end }}
{{- if and (eq .Values.service.type "LoadBalancer") .Values.service.loadBalancerSourceRanges }}
loadBalancerSourceRanges:
{{- toYaml .Values.service.loadBalancerSourceRanges | nindent 4 }}
{{- end }}
{{- with .Values.service.externalTrafficPolicy }}
externalTrafficPolicy: {{ . }}
{{- end }}
ports: ports:
- name: http - name: http
port: {{ .Values.service.port }} port: {{ .Values.service.port }}
targetPort: http targetPort: http
protocol: TCP protocol: TCP
{{- if and (eq .Values.service.type "NodePort") .Values.service.nodePort }}
nodePort: {{ .Values.service.nodePort }}
{{- end }}
selector: selector:
{{- include "claude-code.selectorLabels" . | nindent 4 }} {{- include "claude-code.selectorLabels" . | nindent 4 }}
app.kubernetes.io/component: control-plane app.kubernetes.io/component: control-plane
+8 -1
View File
@@ -236,7 +236,14 @@
"additionalProperties": false, "additionalProperties": false,
"properties": { "properties": {
"type": { "type": "string", "enum": ["ClusterIP", "NodePort", "LoadBalancer"] }, "type": { "type": "string", "enum": ["ClusterIP", "NodePort", "LoadBalancer"] },
"port": { "type": "integer", "minimum": 1, "maximum": 65535 } "port": { "type": "integer", "minimum": 1, "maximum": 65535 },
"nodePort": { "type": ["integer", "null"], "minimum": 1, "maximum": 65535 },
"annotations": { "type": "object" },
"loadBalancerIP": { "type": "string" },
"loadBalancerClass": { "type": "string" },
"loadBalancerSourceRanges": { "type": "array", "items": { "type": "string" } },
"externalTrafficPolicy": { "type": "string", "enum": ["", "Cluster", "Local"] },
"labels": { "type": "object" }
} }
}, },
+28 -4
View File
@@ -30,13 +30,13 @@ image:
gateway: gateway:
registry: docker.io registry: docker.io
repository: nginxinc/nginx-unprivileged repository: nginxinc/nginx-unprivileged
tag: "1.29.1-alpine" tag: "1.31.5-alpine"
pullPolicy: IfNotPresent pullPolicy: IfNotPresent
# 制御プレーン(Python 標準ライブラリのみ・追加 pip 不要) # 制御プレーン(Python 標準ライブラリのみ・追加 pip 不要)
manager: manager:
registry: docker.io registry: docker.io
repository: library/python repository: library/python
tag: "3.13-alpine" tag: "3.14-alpine"
pullPolicy: IfNotPresent pullPolicy: IfNotPresent
# セッションの使い捨てコンテナ。 # セッションの使い捨てコンテナ。
# 既定は CI(session-image.yaml)がビルドする事前ビルドイメージ # 既定は CI(session-image.yaml)がビルドする事前ビルドイメージ
@@ -50,7 +50,7 @@ image:
session: session:
registry: git.cafepieters.com registry: git.cafepieters.com
repository: helmchart/claude-code/session repository: helmchart/claude-code/session
tag: "2.1.259" tag: "2.1.263"
pullPolicy: IfNotPresent pullPolicy: IfNotPresent
imagePullSecrets: [] imagePullSecrets: []
@@ -308,8 +308,32 @@ ingress:
# - claude-code.example.com # - claude-code.example.com
service: service:
type: ClusterIP # LoadBalancer : ローカルネットワークの LB(kube-vip / MetalLB / Cilium LB-IPAM 等)から
# IP を払い出し、その IP で管理画面へアクセスする(Ingress 不要・既定)
# ClusterIP : Service IP のみ。port-forward か Ingress 経由でアクセス
# NodePort : 各ノードの高位ポートで公開
type: LoadBalancer
port: 80 port: 80
# NodePort を固定したい場合のみ(type: NodePort)
nodePort: null
# Service に付与するアノテーション。kube-vip で VIP を指定する例:
# kube-vip.io/loadbalancerIPs: "192.168.9.50"
# kube-vip.io/vipHost: "cpi11"
# MetalLB でプールを指定する例:
# metallb.universe.tf/address-pool: "lan"
annotations: {}
# 払い出す IP を直接指定(LB 実装が対応していれば)。annotations 指定を推奨。
loadBalancerIP: ""
loadBalancerClass: ""
# 接続元をローカルネットワークに限定する(LB 実装が対応していれば)。
# Ingress を張らない構成では、ここで許可レンジを絞ることが第一の防御線になる。
loadBalancerSourceRanges: []
# - 192.168.9.0/24
# - 10.0.0.0/8
# Local にすると実クライアント IP を保持する(kube-proxy/LB 実装依存)
externalTrafficPolicy: ""
# Service 自体への追加ラベル
labels: {}
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
# 制御プレーンの Pod / コンテナセキュリティ # 制御プレーンの Pod / コンテナセキュリティ