You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: site/content/docs/development/_index.md
+10-13Lines changed: 10 additions & 13 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -77,16 +77,13 @@ make test-e2e-container
77
77
78
78
## Local Kubernetes Test Setup
79
79
80
-
For end-to-end integration testing in a local Kubernetes environment:
81
-
82
-
1.**Start Kind Cluster**:
83
-
Ensure you have a Kind cluster running.
84
-
2.**Build and Load Images**:
85
-
```bash
86
-
make docker-build-node
87
-
make docker-build-hub
88
-
kind load docker-image sam-node:local
89
-
kind load docker-image sam-hub:local
90
-
```
91
-
3.**Deploy Config Templates**:
92
-
Deploy and template configuration files located under `.github/k8s/` or `development/kind/` to spin up local nodes and vLLM inference engines.
80
+
For end-to-end integration testing in a local Kubernetes environment, the repository provides `make` targets that stand up a complete mesh in `kind` with a single command:
81
+
82
+
```bash
83
+
make kind-up # create the sam-kind cluster, build+load images, deploy hub + nodes
84
+
make kind-local-node # enroll a locally-built ./bin/sam-node into the mesh
85
+
make kind-e2e-mesh # run the end-to-end discover-and-call check
86
+
make kind-down # tear the cluster down
87
+
```
88
+
89
+
`make kind-up` builds the `sam-hub:local` and `sam-node:local` images, creates a `sam-kind` cluster, and deploys the hub plus the nodes declared in `development/kind/mesh-config.yaml`. See the [Kubernetes Deployment and Local Testing Guide](kubernetes-deployment/#1-local-testing-with-kind) for details.
title: "Kubernetes Deployment and Local Testing Guide"
3
3
linkTitle: "Kubernetes Deployment and Local Testing Guide"
4
4
---
5
-
This guide explains how to deploy the `sam-hub` in a Kubernetes cluster and how to test it locally using `kind` and`cloud-provider-kind`.
5
+
This guide explains how to deploy the `sam-hub` in a Kubernetes cluster and how to test it locally with `kind` — using the bundled `make kind-*` targets for a one-command mesh, or a manual setup with`cloud-provider-kind`.
6
6
7
7
> [!TIP]
8
8
> This guide focuses on local development sandboxing. For production-grade Kubernetes deployments (GKE, EKS, AKS), see the [Production Kubernetes Deployment](../../user/kubernetes-deployment/) guide.
9
9
10
-
This guide supports using either **Google OIDC** or a **Mock OIDC Provider** for authentication. The mock provider is recommended for quick local testing as it does not require creating external credentials.
10
+
---
11
+
12
+
## 1. Local Testing with Kind
13
+
14
+
The repository ships a one-command local mesh under `development/kind/`, driven by `make` targets. This is the fastest way to get a running hub and a few nodes on your machine.
15
+
16
+
### Automated Mesh (Recommended)
17
+
18
+
```bash
19
+
make kind-up
20
+
```
21
+
22
+
This creates a `sam-kind` cluster (one control-plane plus workers for the hub and `node-a`, `node-b`, `node-c`), builds the `sam-hub:local` and `sam-node:local` images, loads them into the cluster, and deploys:
23
+
24
+
- The **hub**, configured to trust the cluster's own OIDC issuer.
25
+
- Three **nodes** declared in `development/kind/mesh-config.yaml`: `node-a` (bare), `node-b` (hosts the `calc-mcp` example service), and `node-c` (hosts the `greeter-mcp` example service).
26
+
27
+
Nodes authenticate to the hub via **Workload Identity Federation** (projected ServiceAccount tokens), so no static secrets or mock OIDC provider are needed. The hub is exposed to the host on `127.0.0.1:9090` (HTTP enroll) and `127.0.0.1:4001` (libp2p) via a NodePort and the cluster's `extraPortMappings` — `cloud-provider-kind` is not required.
28
+
29
+
Once everything is up, `make kind-up` opens a tmux session with live per-pod logs (hub and each node in its own pane). Manage the mesh with:
30
+
31
+
```bash
32
+
make kind-up ARGS=-s # bring the mesh up without attaching the log view
33
+
make kind-logs # (re)attach the live-logs tmux session
34
+
make kind-down # delete the sam-kind cluster
35
+
```
36
+
37
+
### Mesh Layout (`mesh-config.yaml`)
38
+
39
+
The nodes that make up the dev mesh are declared in `development/kind/mesh-config.yaml`. Each entry maps a node to an optional service:
40
+
41
+
```yaml
42
+
# node -> service. A blank value means a bare node (no service, e.g. a caller).
43
+
# The service value is a folder name under development/examples/.
44
+
node-a:
45
+
node-b: calc-mcp
46
+
node-c: greeter-mcp
47
+
```
48
+
49
+
- The key is the node's name. The cluster currently ships with a hub plus these **three** agent nodes; each is pinned to a matching worker via the `sam-role` labels in `kind-config.yaml`.
50
+
- A **blank** value is a bare node — a `sam-node` with no local service, useful as a caller/consumer.
51
+
- A **non-blank** value is a folder name under `development/examples/`. That service is built and deployed as a **sidecar** next to the node, and the node is configured to advertise it to the mesh.
52
+
53
+
When a node has a service, `make kind-up` builds the service image from its `Dockerfile`, loads it into the cluster, and mounts the service's `sam-node-config.yaml` into the node. Because `make kind-up` only runs against a fresh cluster (it refuses if `sam-kind` already exists), **services are (re)deployed on cluster recreation** — after editing `mesh-config.yaml` or a service, run `make kind-down && make kind-up` to pick up the change.
54
+
55
+
### Adding and Testing a New Service
56
+
57
+
A service is any backend a node advertises to the mesh. Its kind is set by the `type` field in `sam-node-config.yaml`. SAM currently supports `mcp` (an MCP server) and `inference` (an LLM inference endpoint). The repository ships example MCP services under `development/examples/` (`calc-mcp`, `greeter-mcp`, `code-reviewer-mcp`, and `everything-mcp`) which are the easiest starting point. Using `calc-mcp` as a template:
58
+
59
+
1. **Create the service folder** `development/examples/my-mcp/` with:
60
+
- The service backend (e.g. `my_server.py`) listening on a local port, plus a `Dockerfile` and any `requirements.txt`.
61
+
- A `sam-node-config.yaml` declaring the service. Set `type` to the service kind and point `target_url` at the backend's local port:
62
+
```yaml
63
+
version: "v1alpha1"
64
+
attenuation:
65
+
policies:
66
+
services:
67
+
- type: "mcp"
68
+
name: "my-service"
69
+
description: "What it does"
70
+
target_url: "http://127.0.0.1:7779/mcp"
71
+
```
72
+
The sidecar and `sam-node` share the pod's network, so `target_url` is always `127.0.0.1:<port>`, where `<port>` matches the port your service listens on.
73
+
74
+
2. **Assign it to a node** in `mesh-config.yaml` — replace an existing mapping or use a free node slot (`node-a`, `node-b`, `node-c`):
75
+
```yaml
76
+
node-a: my-mcp
77
+
node-b: calc-mcp
78
+
node-c: greeter-mcp
79
+
```
80
+
> [!NOTE]
81
+
> There are three node slots because `kind-config.yaml` defines three workers labeled `sam-role: node-a|node-b|node-c`. To host more than three services at once, add a matching labeled worker there too.
82
+
83
+
3. **Recreate the cluster** so the new service is built and deployed:
84
+
```bash
85
+
make kind-down && make kind-up
86
+
```
87
+
88
+
4. **Discover and call it** from another node — enroll a local node and use the MCP client:
`find_remote_tools`lists the discovered tools (e.g. `mcp://my-service/...`) and the peer hosting them; pass that `peer_id` and `tool_name` to `call_remote_tool` to invoke it.
95
+
96
+
### Enrolling a Local Node
97
+
98
+
To iterate on `sam-node` without rebuilding the image, enroll a locally-built binary into the running mesh:
99
+
100
+
```bash
101
+
make build # produce ./bin/sam-node
102
+
make kind-local-node
103
+
```
104
+
105
+
This mints a ServiceAccount token and runs `./bin/sam-node` against the hub at `127.0.0.1:9090`, exposing its MCP API on `127.0.0.1:9099` with the API token `devtoken`. Extra flags pass through via `ARGS`, e.g. to host an example service:
106
+
107
+
```bash
108
+
make kind-local-node ARGS="--config development/examples/calc-mcp/sam-node-config.yaml"
109
+
```
110
+
111
+
You can then drive it with the bundled MCP client:
To verify the full discovery-and-call path against a freshly built mesh:
120
+
121
+
```bash
122
+
make kind-e2e-mesh
123
+
```
124
+
125
+
This enrolls a local node, waits for it to discover `mcp://calculator/add` (hosted by `node-b`), calls `add(2, 3)`, and asserts the result is `5`.
11
126
12
127
---
13
128
14
-
## 1. Mock OIDC Provider Manifests (Optional)
129
+
## 2. Manual Deployment
130
+
131
+
If you'd rather deploy the pieces by hand — for example to exercise the Mock OIDC provider or wire up Google OIDC — you can apply the manifests below to a cluster yourself. SAM supports either a **Mock OIDC Provider** (recommended for quick local testing, since it needs no external credentials) or **Google OIDC** for authentication. The local `kind` path below uses `cloud-provider-kind` to allocate LoadBalancer IPs.
132
+
133
+
### Mock OIDC Provider Manifests (Optional)
15
134
16
135
The manifests for the mock OIDC provider are available in [mock-oidc.yaml](manifests/mock-oidc.yaml).
You can use the following command to extract the allocated IP into an environment variable:
78
191
79
192
```bash
@@ -82,7 +195,7 @@ HUB_IP=$(kubectl get svc sam-hub -o jsonpath='{.status.loadBalancer.ingress[0].i
82
195
83
196
---
84
197
85
-
## 5. Connecting an Agent
198
+
## 3. Connecting an Agent
86
199
87
200
To connect a `sam-node` to the hub, you just need the hub's external IP and port.
88
201
@@ -120,7 +233,7 @@ sam-node run
120
233
121
234
---
122
235
123
-
## 6. Automating Node Deployment
236
+
## 4. Automating Node Deployment
124
237
125
238
To automate the deployment of `sam-nodes` in Kubernetes and have them fetch the JWT token automatically, you can use a standard Kubernetes `Deployment` or `StatefulSet`.
126
239
@@ -213,7 +326,7 @@ sam-node run \
213
326
214
327
---
215
328
216
-
## 7. Configuring Workload Identity in Kubernetes
329
+
## 5. Configuring Workload Identity in Kubernetes
217
330
218
331
Workload Identity allows `sam-node` pods to authenticate with the `sam-hub` using their Kubernetes ServiceAccount token, removing the need for static credentials.
0 commit comments