-
Notifications
You must be signed in to change notification settings - Fork 5
Add proxyagent docs #1076
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
tr0njavolta
merged 9 commits into
upbound:main
from
markandersontrocme:add-proxyagent-docs
Feb 20, 2026
Merged
Add proxyagent docs #1076
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
8bf3d6e
add private-network-agent docs
markandersontrocme 1fd90c0
wording
markandersontrocme 87f3e9c
lint
markandersontrocme e76b3dc
vale
markandersontrocme f2157a1
private preview
markandersontrocme 7ee7737
docs tweaks and add crd
markandersontrocme 2aa9821
Update private-network-agent version in documentation
markandersontrocme 2b064ca
Apply suggestions from code review
markandersontrocme 63e3258
Updates some language
tr0njavolta File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
375 changes: 375 additions & 0 deletions
375
docs/manuals/spaces/howtos/cloud-spaces/private-network-agent.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,375 @@ | ||
| --- | ||
| title: Private Network Agent | ||
| sidebar_position: 5 | ||
| description: Connect an Upbound Cloud control plane to resources in your private network without exposing public endpoints | ||
| --- | ||
|
|
||
| <!-- vale Google.We = NO --> | ||
| :::important | ||
| Private Network Agent is in private preview. For more information, [contact us][contact-us]. | ||
| ::: | ||
| <!-- vale Google.We = YES --> | ||
|
|
||
| The Private Network Agent lets an Upbound Cloud control plane manage Kubernetes | ||
| and Helm resources inside private networks. No public endpoints, inbound | ||
| firewall rules, or VPC peering required. | ||
|
|
||
| ## Architecture overview | ||
|
|
||
| The Private Network Agent reverses the traditional connection model. Instead of | ||
| the control plane reaching into your private network, a lightweight agent inside | ||
| your network connects outbound to the control plane. The control plane sends | ||
| requests through this connection and receives responses through the same | ||
| channel. | ||
|
|
||
| This approach: | ||
|
|
||
| - Requires only outbound connectivity from your private network. | ||
| - Eliminates inbound firewall exceptions, VPC peering, and publicly exposed Kubernetes API servers. | ||
| - Keeps a minimal footprint in your environment. | ||
|
|
||
| The system has two components: | ||
|
|
||
| - **Proxy**: Runs inside your Upbound managed control plane. Upbound manages this automatically. | ||
| - **Private Network Agent**: Runs inside your private network. You deploy and manage this via a Helm chart. | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| Before you begin, make sure you have: | ||
|
|
||
| - An Upbound organization and a managed control plane. | ||
| - `Admin` role on the control plane (required to create a `Proxy` resource). | ||
| - A destination Kubernetes cluster in your private network. | ||
| - Outbound connectivity from the private network to `connect.upbound.io:4222` (TCP/TLS). No inbound rules required. | ||
| - `kubectl` access to both the managed control plane and the destination cluster. | ||
| - The [Upbound CLI](/manuals/cli/overview/) (`up`) installed. | ||
| - Helm v3 installed. | ||
|
|
||
| ## Set up the destination cluster | ||
|
|
||
| On your **destination cluster**, create a service account that | ||
| `provider-kubernetes` uses. | ||
|
|
||
| Create the service account and bind it to a role, for example `cluster-admin`: | ||
|
|
||
| ```bash | ||
| kubectl create serviceaccount provider-kubernetes -n default | ||
|
|
||
| kubectl create clusterrolebinding provider-kubernetes-binding \ | ||
| --clusterrole=cluster-admin \ | ||
| --serviceaccount=default:provider-kubernetes | ||
| ``` | ||
|
|
||
| Create a long-lived service account token: | ||
|
|
||
| ```bash | ||
| kubectl create -f - <<EOF | ||
| apiVersion: v1 | ||
| kind: Secret | ||
| metadata: | ||
| name: provider-kubernetes-token | ||
| annotations: | ||
| kubernetes.io/service-account.name: provider-kubernetes | ||
| type: kubernetes.io/service-account-token | ||
| EOF | ||
| ``` | ||
|
|
||
| Retrieve the token: | ||
|
|
||
| ```bash | ||
| TOKEN=$(kubectl get secret provider-kubernetes-token -o jsonpath='{.data.token}' | base64 -d) | ||
| ``` | ||
|
|
||
| Set the cluster's certificate authority data (from your cloud provider's console | ||
| or kubeconfig) as an environment variable: | ||
|
|
||
| ```bash | ||
| export CLUSTER_CA_DATA=<certificate-authority-data> | ||
| ``` | ||
|
|
||
| ## Configure the control plane | ||
|
|
||
| Switch your `kubectl` context to your **Upbound managed control plane**. | ||
|
|
||
| ### Install provider-kubernetes | ||
|
|
||
| Install `provider-kubernetes` on the control plane: | ||
|
|
||
| ```yaml | ||
| kubectl apply -f - <<EOF | ||
| apiVersion: pkg.crossplane.io/v1 | ||
| kind: Provider | ||
| metadata: | ||
| name: upbound-provider-kubernetes | ||
| spec: | ||
| package: xpkg.upbound.io/upbound/provider-kubernetes:v1.1.0 | ||
| packagePullPolicy: IfNotPresent | ||
| EOF | ||
| ``` | ||
|
|
||
| ### Create the kubeconfig secret | ||
|
|
||
| Create a secret containing the destination cluster's kubeconfig. Point the | ||
| `server` field to your API server—use | ||
| `https://kubernetes.default.svc.cluster.local` if the agent runs in the | ||
| destination cluster: | ||
|
|
||
| ```bash | ||
| kubectl create -f - <<EOF | ||
| apiVersion: v1 | ||
| kind: Secret | ||
| metadata: | ||
| name: private-cluster-kubeconfig | ||
| namespace: crossplane-system | ||
| type: Opaque | ||
| stringData: | ||
| kubeconfig: | | ||
| apiVersion: v1 | ||
| kind: Config | ||
| clusters: | ||
| - cluster: | ||
| certificate-authority-data: $CLUSTER_CA_DATA | ||
| server: https://kubernetes.default.svc.cluster.local | ||
| name: private-cluster | ||
| contexts: | ||
| - context: | ||
| cluster: private-cluster | ||
| user: private-cluster | ||
| name: private-cluster | ||
| current-context: private-cluster | ||
| users: | ||
| - name: private-cluster | ||
| user: | ||
| token: $TOKEN | ||
| EOF | ||
| ``` | ||
|
|
||
| ### Create a ProviderConfig | ||
|
|
||
| Create a `ProviderConfig` that references the kubeconfig secret: | ||
|
|
||
| ```yaml | ||
| kubectl apply -f - <<EOF | ||
| apiVersion: kubernetes.crossplane.io/v1alpha1 | ||
| kind: ProviderConfig | ||
| metadata: | ||
| name: private-cluster | ||
| spec: | ||
| credentials: | ||
| source: Secret | ||
| secretRef: | ||
| name: private-cluster-kubeconfig | ||
| namespace: crossplane-system | ||
| key: kubeconfig | ||
| EOF | ||
| ``` | ||
|
|
||
| ### Create a robot token | ||
|
|
||
| Create a robot and token in your Upbound organization. Both proxy and agent use | ||
| this token to authenticate. | ||
|
|
||
| ```bash | ||
| export UPBOUND_ORG=<your-organization> | ||
|
|
||
| up robot create proxyagent -a $UPBOUND_ORG | ||
| up robot token create proxyagent private-cluster -f ./token.json -a $UPBOUND_ORG | ||
|
|
||
| ROBOT_TOKEN=$(cat token.json | jq -r .token) | ||
| ``` | ||
|
|
||
| Create a Kubernetes secret containing the token on the Upbound control plane: | ||
|
|
||
| ```bash | ||
| kubectl create -f - <<EOF | ||
| apiVersion: v1 | ||
| kind: Secret | ||
| metadata: | ||
| name: robot-token | ||
| namespace: default | ||
| type: Opaque | ||
| stringData: | ||
| token: $ROBOT_TOKEN | ||
| EOF | ||
| ``` | ||
|
|
||
| ### Create the `Proxy` resource | ||
|
|
||
| Create a `Proxy` resource in the managed control plane. This deploys the proxy | ||
| component and configures provider pods to route traffic through it. Each control | ||
| plane supports only one `Proxy`. | ||
|
|
||
| :::warning | ||
| Creating a `Proxy` requires the `Admin` role. | ||
| ::: | ||
|
|
||
| ```yaml | ||
| kubectl apply -f - <<EOF | ||
| apiVersion: spaces.upbound.io/v1alpha1 | ||
| kind: Proxy | ||
| metadata: | ||
| name: private-cluster | ||
| namespace: default | ||
| spec: | ||
| secretRef: | ||
| name: robot-token | ||
| key: token | ||
| podSelector: | ||
| matchLabels: | ||
| pkg.crossplane.io/provider: upbound-provider-kubernetes | ||
| EOF | ||
| ``` | ||
|
|
||
| Retrieve the generated agent ID: | ||
|
|
||
| ```bash | ||
| AGENT_ID=$(kubectl get proxy private-cluster -o jsonpath='{.status.agentID}') | ||
| ``` | ||
|
|
||
| <!-- vale Google.Headings = NO --> | ||
| ## Install the Private Network Agent | ||
| <!-- vale Google.Headings = YES --> | ||
|
|
||
|
|
||
| Switch your `kubectl` context back to the **destination cluster**. | ||
|
|
||
| Create the robot token secret in the destination cluster: | ||
|
|
||
| ```bash | ||
| kubectl create -f - <<EOF | ||
| apiVersion: v1 | ||
| kind: Secret | ||
| metadata: | ||
| name: robot-token | ||
| namespace: default | ||
| type: Opaque | ||
| stringData: | ||
| token: $ROBOT_TOKEN | ||
| EOF | ||
| ``` | ||
|
|
||
| Install the Private Network Agent using Helm: | ||
|
|
||
| ```bash | ||
| helm upgrade --install private-network-agent \ | ||
| oci://xpkg.upbound.io/spaces-artifacts/private-network-agent \ | ||
| --version 0.0.0-1015.g358e4c6 \ | ||
| --set agent.connectUrl=tls://connect.upbound.io \ | ||
| --set agent.organization=$UPBOUND_ORG \ | ||
| --set agent.agentId=$AGENT_ID \ | ||
| --set agent.tokenSecret=robot-token | ||
| ``` | ||
|
|
||
| When the agent connects, the `Proxy` status changes to `Connected`. | ||
|
|
||
| ## Verify the connection | ||
|
|
||
| From the control plane, confirm the proxy status shows `Connected`: | ||
|
|
||
| ```bash | ||
| kubectl get proxy private-cluster | ||
| ``` | ||
|
|
||
| Create a test resource to verify end-to-end connectivity: | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How to Debug connectivity Problems ? Logs etc ?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this should be in a pylon knowledge base article |
||
|
|
||
| ```yaml | ||
| kubectl apply -f - <<EOF | ||
| apiVersion: kubernetes.crossplane.io/v1alpha2 | ||
| kind: Object | ||
| metadata: | ||
| name: test-configmap | ||
| spec: | ||
| forProvider: | ||
| manifest: | ||
| apiVersion: v1 | ||
| kind: ConfigMap | ||
| metadata: | ||
| name: test-configmap | ||
| namespace: default | ||
| data: | ||
| message: "Hello from control plane via private network agent!" | ||
| providerConfigRef: | ||
| name: private-cluster | ||
| EOF | ||
| ``` | ||
|
|
||
| Verify the `Object` becomes `Ready`: | ||
|
|
||
| ```bash | ||
| kubectl get object test-configmap | ||
| ``` | ||
|
|
||
| On the destination cluster, confirm the ConfigMap exists: | ||
|
|
||
| ```bash | ||
| kubectl get configmap test-configmap -n default -o yaml | ||
| ``` | ||
|
|
||
| ## Proxy resource reference | ||
|
|
||
| ```yaml | ||
| apiVersion: spaces.upbound.io/v1alpha1 | ||
markandersontrocme marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| kind: Proxy | ||
| metadata: | ||
| name: prod-eks-us-east-1 | ||
| namespace: default | ||
| spec: | ||
| # Human-readable description | ||
| description: "Production EKS cluster in us-east-1" | ||
|
|
||
| # Reference to the secret containing the robot token | ||
| secretRef: | ||
| name: robot-token | ||
| key: token | ||
|
|
||
| # Optional: Set a specific agent ID to share an agent across | ||
| # multiple proxies. If omitted, a UUID is autogenerated. | ||
| agentID: "550e8400-e29b-41d4-a716-446655440000" | ||
|
|
||
| # Label selector for provider pods that should route through the proxy | ||
| podSelector: | ||
| matchLabels: | ||
| pkg.crossplane.io/provider: provider-kubernetes | ||
| ``` | ||
|
|
||
| ### Status fields | ||
|
|
||
| | Field | Description | | ||
| |---|---| | ||
| | `status.agentID` | The effective agent ID (from `spec.agentID` or generated UUID). | | ||
| | `status.phase` | `WaitingForProxy`: proxy created, agent hasn't connected yet. `Connected`: agent is actively connected. `Disconnected`: agent connection dropped. | | ||
|
|
||
| ## Connect multiple proxies to one agent | ||
|
|
||
| To connect multiple control plane proxies to a single Private Network Agent, set | ||
| the same `agentId` on each `Proxy` resource: | ||
|
|
||
| ```yaml | ||
| spec: | ||
| agentID: "550e8400-e29b-41d4-a716-446655440000" | ||
| ``` | ||
|
|
||
| Proxies in different control planes can share the same agent, letting one agent | ||
| serve multiple control planes that access the same private network. The agent | ||
| supports multiple concurrent connections with full isolation. | ||
|
|
||
| ## Connectivity options | ||
|
|
||
| ### Public internet | ||
|
|
||
| By default, the Private Network Agent connects to `connect.upbound.io` over the | ||
| public internet using TLS 1.3. | ||
|
|
||
| The agent requires **outbound (egress)** connectivity to `connect.upbound.io` on | ||
| port `4222` (TCP/TLS). If your cluster enforces network policies, firewall | ||
| rules, or egress restrictions, you must allow this destination before installing | ||
| the agent. | ||
|
|
||
| | Field | Value | | ||
| |---|---| | ||
| | Hostname | `connect.upbound.io` | | ||
| | Port | `4222` | | ||
| | Protocol | TCP/TLS 1.3 | | ||
| | Direction | Outbound (egress) | | ||
|
|
||
| [contact-us]: https://www.upbound.io/contact-us | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.