> ## 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.

# 公開エンドポイント

> サンドボックス内のサービスにパブリックアドレスを付与し、プラットフォームによる TLS または TLS パススルーで公開します。

<Note>
  `Sandbox.run(auth=...)` を省略している例では、`CWSANDBOX_API_KEY` に設定された CoreWeave API アクセストークンを使用します。Forge APIキーで認証する場合は、[はじめに](/ja/products/sandboxes/get-started#forge-api-key) の手順に従い、取得した `AuthHeaders` を操作に渡してください。
</Note>

このページでは、公開エンドポイントの仕組み、サンドボックスの作成時に公開エンドポイントを宣言する方法、および接続する方法を説明します。

公開エンドポイントは、サンドボックス内で実行されるサービスに、クライアントがインターネットからアクセスできるアドレスを提供します。サンドボックスの作成時に公開エンドポイントをリクエストすると、プラットフォームがルーティング、DNS、ネットワークアクセスを設定します。このアドレスは、サンドボックスが実行されている間、そのサンドボックスに割り当てられます。

エンドポイントには、TLS の終端場所が異なる 2 種類があります。

* **HTTPS**: プラットフォームが発行・更新する証明書を使用して、エッジで TLS を終端し、リクエストを平文の HTTP として指定したポートに転送します。
* **TLS パススルー**: プラットフォームは、接続を復号せずに、[Server Name Indication (SNI)](https://en.wikipedia.org/wiki/Server_Name_Indication) に基づいて指定したポートにルーティングします。ワークロードが TLS を終端し、独自の証明書を管理します。

相互 TLS、証明書をピン留めするクライアント、HTTP 以外のプロトコルなど、ワークロード自体が秘密鍵を保持する必要がある場合は、TLS パススルーを選択してください。

<h2 id="compare-the-two-kinds">
  2 種類の比較
</h2>

| | HTTPS | TLS パススルー |
| - | - | - |
| TLS の終端 | プラットフォームのエッジ | ユーザーのワークロード |
| 証明書の所有者 | プラットフォーム | ユーザー |
| 伝送できるもの | HTTP、HTTP Upgrade 経由の WebSocket、Server-Sent Events | TLS 上の任意のプロトコル |
| `endpoint.kind` | `HTTPS` | `TLS_PASSTHROUGH` |
| `endpoint.auth` | `OPEN` (必須) | 省略 |
| アドレスの取得元 | `service_urls` | `service_addresses` |

<Warning>
  どちらの種類もインターネットに公開されます。プラットフォームは呼び出し元を認証しないため、アクセス制御はエンドポイントの背後にあるサービス側で行う必要があります。
</Warning>

<h2 id="declare-an-endpoint">
  エンドポイントを宣言する
</h2>

サンドボックスを作成するときに `services` リストでエンドポイントを宣言します。ポートはサンドボックスの有効期間中固定されており、実行中のサンドボックスに対してポートを公開する呼び出しはありません。

サービスにエンドポイントを付与するには、`visibility=PUBLIC` と `endpoint` の値を設定します。`endpoint` の値がないサービスは、サンドボックス内部でポートをリッスンしますが、パブリックアドレスは取得しません。

HTTPS エンドポイントの場合は、`kind=EndpointKind.HTTPS` と `auth=EndpointAuth.OPEN` を設定します：

```python theme={"system"}
from cwsandbox import (
    Endpoint,
    EndpointAuth,
    EndpointKind,
    Sandbox,
    Service,
    ServiceVisibility,
)

sandbox = Sandbox.run(
    "python3", "-m", "http.server", "8080",
    container_image="python:3.11",
    services=[
        Service(
            port=8080,
            name="web",
            visibility=ServiceVisibility.PUBLIC,
            endpoint=Endpoint(kind=EndpointKind.HTTPS, auth=EndpointAuth.OPEN),
        ),
    ],
)
```

TLS パススルー エンドポイントの場合、`kind=EndpointKind.TLS_PASSTHROUGH` を設定し、`auth` を未設定のままにします。プラットフォームは接続を復号せずに転送するため、実行するコマンドはポート自体で TLS を終端する必要があります：

```python theme={"system"}
from cwsandbox import (
    Endpoint,
    EndpointKind,
    Sandbox,
    Service,
    ServiceVisibility,
)

sandbox = Sandbox.run(
    "python3", "/srv/serve_tls.py",
    container_image="python:3.11",
    services=[
        Service(
            port=8443,
            name="tls",
            visibility=ServiceVisibility.PUBLIC,
            endpoint=Endpoint(kind=EndpointKind.TLS_PASSTHROUGH),
        ),
    ],
)
```

1 つのサンドボックスで両方の種類を組み合わせることができます。すべての `services` エントリには、次のルールが適用されます。

* **ポートは一意である必要があり**、名前を設定する場合はその名前も一意である必要があります。名前は Kubernetes のコンテナーポート名にマッピングされ、コンテナーポート名は一意でなければなりません。
* **`endpoint` を設定する場合、`visibility` は `PUBLIC` にする必要があり**、`endpoint` を設定しない場合は `visibility` を未設定のままにする必要があります。可視性を設定しただけでは、エンドポイントもアドレスも作成されません。
* **`protocol` は `TCP` にするか、未設定のままにする必要があります。** プラットフォームは `UDP` および `SCTP` のエンドポイントを拒否します。
* **TLS パススルーの場合は `auth` と `request_timeout_seconds` を省略してください。** `0` ではなく `None` を渡してください。`0` は値が設定されているとみなされ、プラットフォームによって作成リクエストが拒否されます。
* **1 つのサンドボックスで宣言できるサービスの数には、プラットフォームによる上限があります。** 上限はオペレーターが設定し、多くのデプロイメントでは 5 に設定されています。

<h2 id="read-the-assigned-address">
  割り当てられたアドレスを取得する
</h2>

プラットフォームがアドレスを割り当てます。ホスト名を選択したり、独自のドメインを指定したりすることはできません。DNS ゾーンはクラスターごとに異なり、API の契約に含まれないため、アドレスを組み立てるのではなく、サンドボックスから取得してください。

TLS パススルーのアドレスは `service_addresses` に `host:port` 形式で返され、HTTPS URL は `service_urls` に返されます。これらのリストは別々に保持されます。TLS エンドポイントが `service_urls` に含まれることはありません。

```python theme={"system"}
for endpoint in sandbox.service_addresses:
    print(endpoint.port, endpoint.name, endpoint.address)
```

次のような出力が表示されます。

```text theme={"system"}
8443 tls 8443-2f8d41b6-9c3e-4a17-b5d2-7e0a13c64f89.a1b2c3d4.ep2.cwsandbox.com:443
```

アドバタイズされたポートは、プラットフォームの TLS リスナーポートであり、サンドボックス内でプロセスがバインドするポートではありません。この例では、ワークロードは `8443` でリッスンし、クライアントは `443` に接続します。

2 種類のアドレスは、サンドボックスの起動時の異なる時点で読み取り可能になります。

* **TLS パススルーアドレスは、サンドボックスが作成されたときに割り当てられます**。そのため、作成応答に含まれ、サンドボックスが作成中または実行中は利用可能です。
* **HTTPS URL は、サンドボックスが `RUNNING` に到達し、ルートにホスト名が設定されるまで空です**。URL が表示されるか、独自の期限が切れるまで、ループで `get_status()` を呼び出します。
* **どちらも、アプリケーションがサービスを提供していることを意味するわけではありません。** プラットフォームは、プロセスがポートにバインドするのを待たずにサンドボックスを実行中として報告するため、最初の接続を再試行してください。

プラットフォームは、サンドボックスが作成中または実行中の間はエンドポイントを報告し、その他の状態ではクリアします。停止中または完了したサンドボックスには到達可能なエンドポイントがありません。

<h2 id="connect-to-a-tls-passthrough-endpoint">
  TLS パススルー エンドポイントへの接続
</h2>

プラットフォームは接続を復号しないため、クライアントが受け取る証明書はワークロードが提示するものです。クライアントには以下の 2 点が該当します。

* **エンドポイント ホストを SNI サーバー名として送信します。** プラットフォームは SNI のみでルーティングするため、これを省略したり別の名前を送信したりすると、サンドボックスに到達しません。
* **ワークロードの証明書を信頼します。** エンドポイント ホスト名はプラットフォームが割り当てるため、自分で発行した証明書は、そのホスト名用に発行しない限り一致しません。クライアントを自分の証明書機関を信頼するように設定するか、証明書をピン留めしてください。

次のクライアントは、告知されたアドレスに接続しながらエンドポイント ホストを SNI として送信します。`[ENDPOINT-ADDRESS]` を `service_addresses` から読み取ったアドレスに置き換え、`[PATH-TO-CA-CERT]` をワークロードの証明書に署名した証明書機関へのパスに置き換えてください。

```python theme={"system"}
import socket
import ssl

address = "[ENDPOINT-ADDRESS]"  # service_addresses からの host:port
host, port = address.rsplit(":", 1)

context = ssl.create_default_context(cafile="[PATH-TO-CA-CERT]")

with socket.create_connection((host, int(port))) as sock:
    with context.wrap_socket(sock, server_hostname=host) as tls:
        print(tls.version(), tls.getpeercert()["subject"])
```

<h2 id="endpoint-lifetime">
  エンドポイントの有効期間
</h2>

エンドポイントは、それを所有するサンドボックスの有効期間と同じだけ存続します：

* **サンドボックスに紐づけられており、Pod には紐づけられていません。** 基盤となる Pod が再起動しても、アドレスは変わりません。
* **サンドボックスを削除すると、エンドポイントも削除されます。** アドレスは別のサンドボックスに移行せず、新しいサンドボックスには新しいアドレスが割り当てられます。
* **サンドボックス間で何も予約されません。** ホスト名を再利用のために保持することはできません。

<h2 id="troubleshoot-create-failures">
  作成リクエストの失敗をトラブルシュートする
</h2>

フリート内のどのランナーもリクエストされたエンドポイントの種類をサポートしていない場合、作成リクエストは失敗し、エンドポイントがサイレントでドロップされた状態でサンドボックスが開始されることはありません。

| 理由 | 意味 |
| - | - |
| `CWSANDBOX_TLS_PASSTHROUGH_ENDPOINTS_NOT_SUPPORTED` | アクセス可能なランナーが TLS パススルー用に設定されていません。ランナーで有効にするよう管理者に依頼してください。 |
| `CWSANDBOX_NO_SUITABLE_RUNNER` | サンドボックスが両方のエンドポイントの種類を宣言しており、両方をサポートするランナーがありません。応答の `unsupported_endpoint_kinds` メタデータに不足している種類が記載されています。 |
| `CWSANDBOX_INVALID_REQUEST` | `services` エントリが [エンドポイントを宣言する](#declare-an-endpoint) のいずれかのルールに違反しています (例: ポートの重複、または TLS パススルー エンドポイントへの `auth` の設定) 。 |
| `CWSANDBOX_NOT_IMPLEMENTED` | リクエストで `auth=TOKEN` など未実装の機能が使用されました。 |

<h2 id="related-pages">
  関連ページ
</h2>

* [サンドボックスの設定](/ja/products/sandboxes/client/guides/sandbox-configuration): リソース、ポート、シークレット、およびタイムアウト。

* [サンドボックスのアーキテクチャ](/ja/products/sandboxes/architecture): ランナー、プロフィール、およびコントロールプレーンがどのように相互作用するか。

* [サンドボックスのライフサイクル](/ja/products/sandboxes/client/guides/sandbox-lifecycle): サンドボックスが経る状態。
