✅ ExternalName Service 定義例(Freee用)
apiVersion: v1
kind: Service
metadata:
name: freee-api
spec:
type: ExternalName
externalName: api.freee.co.jp
これで、Kubernetes内のアプリは以下のように書けます:
import requests
response = requests.get("https://freee-api.default.svc.cluster.local/v1/partners", headers=headers)
→ 実際は DNS で api.freee.co.jp に変換され、通常通りAPIが呼ばれます。
✅ ExternalName の利用メリット(外部API一般に共通)
| メリット | 内容 |
|---|
| ✅ 接続先を抽象化 | SaaSホストを svc名.namespace.svc.cluster.local で管理できる(コードにホスト名をハードコーディングしない) |
| ✅ マルチ環境対応 | staging → prod で externalName のみ変更すればOK(コード変更不要) |
| ✅ Kubernetes的に統一 | 他のServiceと同じ形式で扱えるので CI/CD も一貫性あり |
| ✅ Helmで管理可能 | values.yaml で外部APIホスト名を切り替え可能にできる |
🔐 注意点と補足
| ポイント | 説明 |
|---|
| 🔒 TLSはそのまま利用可能 | ExternalName は単なるDNS CNAMEなので https:// アクセスも問題なし(証明書はFreeeが持っている) |
| ❌ ポート定義不可 | ports: の指定はできない(エラーになります) |
| ⚠ ネットワーク制御できない | Podから直接インターネットへ出る構成になるので、Egress制限やFW制御が必要な場合は別途対策が必要 |
| 📊 死活監視やロードバランスは不可 | ExternalName はService Discoveryの置き換えではないので、リトライやフォールバックはアプリ側実装が必要です |
✅ 他の外部APIにも応用できる例
| SaaS/API | ExternalName例 |
|---|
| Freee会計 | api.freee.co.jp → freee-api.svc.cluster.local |
| Stripe | api.stripe.com → stripe-api.svc.cluster.local |
| Salesforce | login.salesforce.com → sfdc-login.svc.cluster.local |
| OpenAI API | api.openai.com → openai-api.svc.cluster.local |
🧭 外部API接続の全体像(技術スタック)
| 層 | 技術 | 役割 |
|---|
| アプリケーション層 | Python/Node.js など | API呼び出し処理を実装(requests/axiosなど) |
| Service抽象化層 | ExternalName | 接続先ホストの抽象化・環境分離 |
| セキュリティ層 | Kubernetes Secret / Env | APIキー、OAuth2トークンの保護 |
| 通信制御層 | NetworkPolicy / Egress制御 | SaaSアクセス許可/通信制限管理 |
| 運用層 | Helm / ConfigMap | 接続先切替や環境ごとの設定注入 |
複数のアカウントを扱う場合は下記が良い
✅ ゴール:
- Freeeのアカウント(=OAuth2トークン + company_id)を安全に・動的に・容易に管理
- 新しいアカウントが増えてもコード・構成を極力変えずに連携対象を追加できる
🧩 方法別比較(アカウント追加に対する管理性)
| 方法 | 管理方法 | アカウント追加の作業負荷 | 備考 |
|---|
| ❌ PodごとにJob/Secretを個別作成 | Job・Secretを1セットずつ | ✖:増えるごとにYAML追加・CI変更 | 保守コスト大 |
| ❌ 環境変数にベタ書き | FREEE_ACCESS_TOKEN=xxx | ✖:アプリ再ビルドが必要 | セキュリティ・柔軟性低い |
| ⚠️ ConfigMapに一覧管理 | 1つのYAMLで全アカウントを管理 | △:巨大化・マウントが複雑に | 読み込みは簡単だが運用は微妙 |
| ✅ Secret+IDベース動的読み込み(推奨) | 各アカウントをSecretで個別に管理し、ランタイムでID指定 | ◎:増やすだけで済む | 最小限の追加、ロジック変更不要 |
| ✅ 外部ストレージ(DBやVault)で動的管理 | DBにアカウント情報を保持 | ◎◎:Webで登録可、完全自動化 | 本格運用向き。構成は複雑化するが最強 |
✅ ベストプラクティス:Secretをアカウント単位で作成+ランタイム動的参照
🎯 なぜこれが良いのか?
- HelmやDeployment YAMLは変更不要
- Secretだけ追加すればよい
- 複数Podで共有できる
SECRET_NAME=freee-account-1234 のように アカウントIDで切替可能
シングルアカウント(=1社分のFreeeアカウント)に固定でアクセスする用途であれば、ExternalName を使うのは「有効かつシンプル」な選択肢です。
ただし、ExternalNameはホスト名の抽象化だけを行うものであり、Freeeの認証トークン(OAuth2)などは別途管理が必要です。
✅ 結論:
| 利用ケース | ExternalNameの利用価値 |
|---|
| ✅ シングルアカウント | ◎ 有効。ホスト名をK8s内で抽象化できて便利 |
| ❌ マルチアカウント | ✖ 意味がない。APIホストは同じ、切り替えるのはトークンだから |
🧠 ExternalNameを使うと何が嬉しいか
例:
yamlコピーする編集するapiVersion: v1
kind: Service
metadata:
name: freee-api
spec:
type: ExternalName
externalName: api.freee.co.jp
アプリはこう呼び出します:
pythonコピーする編集するrequests.get("https://freee-api.default.svc.cluster.local/v1/partners", headers={...})
✅ メリット
| 項目 | 説明 |
|---|
| コードからホスト名を隠せる | api.freee.co.jp を直接書かない |
| 環境ごとの切り替えが簡単 | externalName を dev/prod 切り替えるだけ(Helm valuesで管理可能) |
| 他のKubernetes Serviceと同じ形で統一 | 保守性が高まる・CI/CD管理が楽 |
🔐 トークン(認証)はどうするの?
ExternalName は DNS だけなので、以下のような認証トークンは必ず別で管理が必要です:
- OAuth2の
access_token(FreeeのAPI認証)
client_id, client_secret(もしリフレッシュ対応もするなら)
管理方法:
| 方法 | 適切か | コメント |
|---|
| Kubernetes Secret に格納 | ✅ 安全・推奨 | |
| 環境変数で注入 | △ 実行時は使えるがセキュリティ注意 | |
| ConfigMap(平文) | ❌ セキュリティNG | |
✅ おすすめ構成(シングルアカウント)
| 構成要素 | 内容 |
|---|
Service | ExternalName で freee-api.svc.cluster.local にする |
Secret | access_token を保持、アプリPodにマウント or 環境変数で注入 |
Deployment | 固定トークンでFreee APIにアクセス(会社IDは指定可) |
Helm values | トークン/host名を環境別に定義し切り替え可能にしておくと便利 |
✅ まとめ
| 質問 | 回答 |
|---|
| シングルアカウントならExternalNameで十分? | ✅ はい。ホスト名抽象化に有効で、運用が簡単になります。 |
| 認証トークンはどうする? | 🔑 Secret や環境変数で別途安全に管理 |
| 他と組み合わせるべきものは? | Deployment や CronJob からFreee APIを呼び出すスクリプトと併用 |
コメントを残す