> ## Documentation Index
> Fetch the complete documentation index at: https://docs.coreweave.com/llms.txt
> Use this file to discover all available pages before exploring further.

# サンドボックスから tailnet 上のサービスにアクセスする

> サンドボックスの外向き通信を Tailscale プロキシ経由でルーティングし、tailnet 上にのみ存在するサービスにアクセスします。

Tailscale のクラスター外向き通信を使用すると、ご自身の CoreWeave Kubernetes Service (CKS) クラスター上のサンドボックスから、tailnet 上のデバイスに接続できます。接続先の例としては、社内 API、企業ネットワーク内のデータベース、ワークステーション上のモデルサーバーなどがあります。Tailscale Kubernetes オペレーターは、tailnet デバイスを Kubernetes Service としてパブリッシュします。サンドボックスの外向き通信ルールによって、その Service の背後にあるプロキシへのアクセスがサンドボックスにグラントされます。

このページは、CKS クラスター上でマネージドサンドボックスランナーを運用している管理者を対象としています。この例ではスタンドアロンの外向き通信を使用し、オペレーターは `tailscale` namespace にインストールされているものとします。設定にあたっては、次の 2 つのプラットフォームの動作を考慮する必要があります。

* Tailscale オペレーターを通じてクラスター内の Service を公開すると、tailnet デバイスからその Service に接続できるようになります。一方、Pod から tailnet デバイスへの外向き接続には、[Tailscale のクラスター外向き通信機能](https://tailscale.com/kb/1438/kubernetes-operator-cluster-egress)が必要です。
* サンドボックスの外向き通信ルールは、デフォルトですべて拒否するベースラインの上に許可のみを追加する方式で、`EgressRule(any=True)` はクラスター内部のアドレスを対象外とします。そのため、Tailscale プロキシなどのクラスター内の送信先には、`selector` ルールまたは `tenant` ルールを使用しなければアクセスできません。

## 前提条件

* `installStatus` が `READY` のマネージドサンドボックスランナーを備えた CKS クラスター。[独自のコンピューティングリソースを使用する](https://docs.coreweave.com/ja/products/sandboxes/get-started-cks.md)を参照してください。
* そのクラスターに Tailscale Kubernetes Operator がインストールされ、tailnet ポリシーファイルが CKS 向けに設定されていること。[Tailscale Kubernetes Operator をデプロイする](https://docs.coreweave.com/products/cks/auth-access/tailscale-operator.md)を参照してください。
* 接続先の tailnet デバイスの MagicDNS 名(例: `db-host.[TAILNET-NAME].ts.net`)と、サービスがリッスンしているポート。
* このセレクターの外向き通信ルールを許可するランナーのポリシー。`any` エンタイトルメントはセレクターには適用されないため、`allowed_egress` が空でないポリシーには、形式が一致する `selector` エンタイトルメントが必要です。具体的には、`namespace_labels` も設定されていること、そのラベルがサンドボックスで宣言されたラベルのサブセットであること、ポートフィルターが TCP ポート 8080 を含んでいることが条件です。[`SelectorBlock`](https://docs.coreweave.com/ja/products/sandboxes/reference/profile#selectorblock) を参照してください。
* [CKS への配置用の認証情報](https://docs.coreweave.com/ja/products/sandboxes/placement.md)が設定済みの `cwsandbox` Python SDK と、`curl` および `getent` がインストールされたサンドボックスイメージ。
* `default` namespace で Service を作成または更新し、オペレーターの namespace で Pod を一覧表示できる `kubectl` のアクセス権。
* 外向き通信プロキシから対象デバイスおよびアプリケーションポートへの接続を許可する tailnet ポリシー。

## Tailscale の外向き通信用 Service を作成する

tailnet デバイスの MagicDNS 名をアノテーションに指定した `ExternalName` Service を作成します。オペレーターは自身の namespace にプロキシ Pod とヘッドレス Service を作成し、`ExternalName` Service がそのヘッドレス Service を指すように設定します。以下の例では、リンク先のインストールガイドと同じく `tailscale` を使用しています。オペレーターを別の namespace にインストールした場合は、以下のコマンドと `namespace_labels` を適宜変更してください。

`[TAILNET-FQDN]` をデバイスの MagicDNS 名に置き換えてください。この例では Service を `default` に作成し、その完全修飾 DNS 名を使用することで、他の namespace にあるサンドボックスからも接続できるようにしています。また、ポート 8080 で `/health` エンドポイントを公開する HTTP サービスを想定しています。ポートとパスはご利用のサービスに合わせて調整してください。

```yaml title="tailnet-egress.yaml" theme={"system"}
apiVersion: v1
kind: Service
metadata:
  name: internal-api
  namespace: default
  annotations:
    tailscale.com/tailnet-fqdn: "[TAILNET-FQDN]"
spec:
  type: ExternalName
  externalName: placeholder.tailscale.internal # Kubernetes では必須ですが、オペレーターによって上書きされます
```

```bash theme={"system"}
kubectl apply -f tailnet-egress.yaml
```

サンドボックスは `internal-api.default.svc.cluster.local:8080` に接続します。短縮名 `internal-api:8080` は、Service と同じ namespace 内からしか使用できません。クラスターで `cluster.local` 以外の DNS 接尾辞を使用している場合は、例に含まれる接尾辞をその値に置き換えてください。

オペレーターがプロキシ Pod を作成したことを確認します。

```bash theme={"system"}
kubectl get pods -n tailscale \
  -l 'tailscale.com/parent-resource=internal-api,tailscale.com/parent-resource-ns=default'
```

プロキシが準備完了になるまで待ちます。出力例 (生成される Pod 名は環境によって異なります) ：

```text theme={"system"}
NAME                     READY   STATUS    RESTARTS   AGE
ts-internal-api-k4x7p-0  1/1     Running   0          32s
```

## サンドボックスにプロキシへの外向き通信を許可する

`EgressRule` で、ラベルを使用してプロキシ Pod を選択します。このルールには、次の両方のラベルセットが必要です。

* `pod_labels` は、オペレーターが付与する `tailscale.com/parent-resource` ラベルと `tailscale.com/parent-resource-ns` ラベルを使用して、プロキシをその背後にある Service によって識別します。別の namespace にある同名の Service 用プロキシにもルールが一致してしまわないよう、namespace ラベルも含めてください。
* `namespace_labels` は `tailscale` namespace を選択します。これを指定しない場合、ルールはサンドボックス自身の namespace にのみ適用され、別の namespace にあるプロキシには到達できません。

`ports` には、サービスがリッスンしているポートと同じポートを設定します。`[RUNNER-ID]` は、Service を作成したクラスター上のランナーの ID に置き換えてください。`runner_ids` を指定しない場合、CKS の配置では組織内の対象となる任意のランナーが使用される可能性があり、プロキシが存在しないクラスター上のランナーが選ばれることもあります。

```python theme={"system"}
from cwsandbox import EgressRule, NetworkOptions, Sandbox, SelectorBlock

tailscale_egress = EgressRule(
    selector=SelectorBlock(
        pod_labels={
            "tailscale.com/parent-resource": "internal-api",
            "tailscale.com/parent-resource-ns": "default",
        },
        namespace_labels={"kubernetes.io/metadata.name": "tailscale"},
    ),
    ports=[8080],
)

with Sandbox.run(
    placement_mode="cks",
    runner_ids=["[RUNNER-ID]"],
    network=NetworkOptions(egress=[tailscale_egress]),
) as sandbox:
    result = sandbox.exec([
        "curl", "-sS", "--include", "--max-time", "15",
        "http://internal-api.default.svc.cluster.local:8080/health",
    ]).result()
    print(result.stdout)
    print(result.stderr)
```

これらのセレクターとポートは、スタンドアロンの外向き通信用です。外向き通信用の `ProxyGroup` は共有のプロキシ Pod を使用してポートを再マッピングするため、このモードではこのルールだけでは設定として不十分です。詳しくは、[Tailscale の高可用性外向き通信ガイド](https://tailscale.com/docs/kubernetes-operator/egress#high-availability-ha-egress)を参照してください。

ランナーのポリシーが `dns_egress` 制約で DNS の外向き通信を拒否していない限り、クラスター DNS には引き続き到達できます。そのため、追加のルールがなくても、サンドボックスは Service 名を解決できます。

## 接続を検証する

この例では、HTTP レスポンスのヘッダーと本文に加え、curl のエラーがあればそれも出力します。ステータス 200 を返すヘルスチェック用エンドポイントであれば、`HTTP/1.1 200 OK` のようなステータス行に続いて、サービスの健全性を示すレスポンスが表示されます。401 や 404 などの HTTP エラーが返された場合は、HTTP サーバー自体は応答しています。アプリケーションの認証設定またはリクエストしたパスを確認してください。

タイムアウトや接続エラーは、サンドボックスとプロキシの間、プロキシと tailnet デバイスの間、またはアプリケーション側で発生する可能性があります。DNS と HTTP のやり取りを個別に確認するには、ランナー ID を指定して次の診断例を実行してください。

```python theme={"system"}
from cwsandbox import EgressRule, NetworkOptions, Sandbox, SelectorBlock

tailscale_egress = EgressRule(
    selector=SelectorBlock(
        pod_labels={
            "tailscale.com/parent-resource": "internal-api",
            "tailscale.com/parent-resource-ns": "default",
        },
        namespace_labels={"kubernetes.io/metadata.name": "tailscale"},
    ),
    ports=[8080],
)

with Sandbox.run(
    placement_mode="cks",
    runner_ids=["[RUNNER-ID]"],
    network=NetworkOptions(egress=[tailscale_egress]),
) as sandbox:
    dns_result = sandbox.exec([
        "getent", "hosts", "internal-api.default.svc.cluster.local",
    ]).result()
    print(dns_result.stdout)
    print(dns_result.stderr)
    http_result = sandbox.exec([
        "curl", "-sv", "--max-time", "15", "-o", "/dev/null",
        "http://internal-api.default.svc.cluster.local:8080/health",
    ]).result()
    print(http_result.stderr)
```

DNS ルックアップが成功すると、少なくとも 1 つのアドレスが表示されます。curl の出力で、プロキシのアドレスへの接続と HTTP レスポンスステータスが表示されていることを確認してください。DNS の解決に成功しただけでは、プロキシがターゲットに到達できるかどうかは確認できません。

## トラブルシューティング

| 症状 | 考えられる原因 | 対処法 |
| - | - | - |
| 外向き通信ルールで作成が失敗する | 空でない `allowed_egress` が、セレクターのラベル、namespace のラベル、または要求されたポートをカバーしていません。 | 一致する namespace の形式、宣言されたラベルのサブセット、および TCP 8080 をカバーするポートフィルターを指定したセレクターを許可するよう、ポリシー管理者に依頼してください。 |
| 名前が解決されない | DNS 名の namespace またはクラスターの接尾辞が誤っているか、オペレーターがまだ Service を設定していないか、DNS の外向き通信が拒否されています。 | Service の `externalName` を確認して完全な Service 名を使用し、ランナーの DNS 外向き通信ポリシーを確認してください。 |
| 名前は解決されるが接続がタイムアウトする | ルールが誤った Pod または namespace を選択しているか、tailnet ポリシーがターゲットをブロックしているか、ターゲットがリッスンしていません。 | プロキシのラベルと namespace、tailnet のアクセスルール、およびターゲットアプリケーションのアドレスとポートを確認してください。 |
| 1 つのポートでしか接続できない | 外向き通信ルールの `ports` リストに他のポートが含まれていません。 | 不足しているポートを外向き通信ルールに追加してください。 |
| `tailscale` namespace にプロキシ Pod が表示されない | オペレーターが別の namespace にインストールされているか、リコンサイルが失敗したか、オペレーターの認証情報またはタグが承認されていません。 | オペレーターの namespace とログを確認したうえで、[オペレーターのタグを設定する](https://docs.coreweave.com/products/cks/auth-access/tailscale-operator.md#configure-operator-tags)を参照してください。 |

## 関連ページ

* [Tailscale Kubernetes Operator をデプロイする](https://docs.coreweave.com/products/cks/auth-access/tailscale-operator.md): CKS 上でオペレーターをデプロイして設定します。
* [ネットワークルール](https://docs.coreweave.com/ja/products/sandboxes/client/ref/networking/network-rules.md): `EgressRule` と `SelectorBlock` の完全なリファレンスです。
* [ポリシーリファレンス](https://docs.coreweave.com/ja/products/sandboxes/reference/profile.md): 宣言する外向き通信ルールは、ここで定義されるポリシーのエンタイトルメントの範囲内に収める必要があります。
* [公開エンドポイント](https://docs.coreweave.com/ja/products/sandboxes/public-endpoints.md): サンドボックス内のサービスに公開アドレスを割り当てます。
