Skip to content

Commit 788f9c8

Browse files
authored
implement user-server(service-proxy), provide user a https server to access managed cluster service on the hub side. (#244)
Signed-off-by: xuezhaojun <[email protected]>
1 parent b5114a9 commit 788f9c8

File tree

203 files changed

+23825
-2423
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

203 files changed

+23825
-2423
lines changed

.github/workflows/go-presubmit.yml

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -90,25 +90,11 @@ jobs:
9090
run: curl -L https://raw.githubusercontent.com/open-cluster-management-io/clusteradm/main/install.sh | bash
9191
- name: Create k8s Kind Cluster
9292
uses: helm/[email protected]
93-
- name: Prepare OCM testing environment
94-
run: |
95-
clusteradm init --output-join-command-file join.sh --wait
96-
sh -c "$(cat join.sh) loopback --force-internal-endpoint-lookup"
97-
clusteradm accept --clusters loopback --wait 30
98-
kubectl wait --for=condition=ManagedClusterConditionAvailable managedcluster/loopback
93+
with:
94+
cluster_name: e2e
9995
- name: Build image
100-
run: |
101-
make images
102-
kind load docker-image quay.io/open-cluster-management/cluster-proxy:latest --name chart-testing
103-
- name: Install latest cluster-proxy
104-
run: |
105-
helm install \
106-
-n open-cluster-management-addon --create-namespace \
107-
cluster-proxy charts/cluster-proxy/ \
108-
--set tag=latest --set installByPlacement.placementName=default
109-
- name: Build&Run e2e test
110-
run: |
111-
kubectl wait --for=condition=ProxyServerDeployed=true managedproxyconfiguration cluster-proxy --timeout=60s
112-
kubectl wait --for=condition=Available deployment/cluster-proxy --timeout=60s -n open-cluster-management-addon
113-
kubectl port-forward -n open-cluster-management-addon services/proxy-entrypoint 8090:8090 &
114-
make test-e2e
96+
run: make images
97+
- name: Setup environment
98+
run: make setup-env-for-e2e && make deploy-cluster-proxy-e2e
99+
- name: Run e2e tests
100+
run: make test-e2e

Makefile

Lines changed: 136 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,15 @@ IMG ?= controller:latest
33
IMAGE_REGISTRY_NAME ?= quay.io/open-cluster-management
44
IMAGE_NAME = cluster-proxy
55
IMAGE_TAG ?= latest
6-
E2E_TEST_CLUSTER_NAME ?= loopback
6+
E2E_TEST_CLUSTER_NAME ?= e2e
77
CONTAINER_ENGINE ?= docker
88
# Produce CRDs that work back to Kubernetes 1.11 (no version conversion)
99
CRD_OPTIONS ?= "crd:crdVersions={v1},allowDangerousTypes=true,generateEmbeddedObjectMeta=true"
1010

11+
# Label filter for e2e tests (Ginkgo v2 label filter expression)
12+
# Examples: "install", "connectivity", "certificate && !rotation", etc.
13+
LABEL_FILTER ?=
14+
1115
# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
1216
ifeq (,$(shell go env GOBIN))
1317
GOBIN=$(shell go env GOPATH)/bin
@@ -56,11 +60,7 @@ fmt: ## Run go fmt against code.
5660
vet: ## Run go vet against code.
5761
go vet ./...
5862

59-
golint:
60-
go install github.com/golangci/golangci-lint/cmd/[email protected]
61-
golangci-lint run --timeout=3m ./...
62-
63-
verify: fmt vet golint
63+
verify: fmt vet
6464

6565
test: manifests generate fmt vet ## Run tests.
6666
go test ./pkg/... -coverprofile cover.out
@@ -70,6 +70,7 @@ test: manifests generate fmt vet ## Run tests.
7070
build: generate fmt vet
7171
go build -o bin/addon-manager cmd/addon-manager/main.go
7272
go build -o bin/addon-agent cmd/addon-agent/main.go
73+
go build -o bin/cluster-proxy cmd/cluster-proxy/main.go
7374

7475
docker-build: test ## Build docker image with the manager.
7576
$(CONTAINER_ENGINE) build -t ${IMG} .
@@ -81,7 +82,7 @@ docker-push: ## Push docker image with the manager.
8182

8283
CONTROLLER_GEN = $(shell pwd)/bin/controller-gen
8384
controller-gen: ## Download controller-gen locally if necessary.
84-
$(call go-get-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@v0.18.0)
85+
$(call go-get-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@v0.19.0)
8586

8687
KUSTOMIZE = $(shell pwd)/bin/kustomize
8788
kustomize: ## Download kustomize locally if necessary.
@@ -117,6 +118,16 @@ images:
117118
--build-arg ADDON_AGENT_IMAGE_NAME=$(IMAGE_REGISTRY_NAME)/$(IMAGE_NAME):$(IMAGE_TAG) \
118119
-t $(IMAGE_REGISTRY_NAME)/$(IMAGE_NAME):$(IMAGE_TAG) .
119120

121+
images-amd64:
122+
$(CONTAINER_ENGINE) buildx build \
123+
--platform linux/amd64 \
124+
--load \
125+
-f cmd/Dockerfile \
126+
--build-arg ADDON_AGENT_IMAGE_NAME=$(IMAGE_REGISTRY_NAME)/$(IMAGE_NAME):$(IMAGE_TAG) \
127+
-t $(IMAGE_REGISTRY_NAME)/$(IMAGE_NAME):$(IMAGE_TAG) .
128+
129+
## Integration Testing
130+
120131
ENVTEST_ASSETS_DIR=$(shell pwd)/testbin
121132
test-integration: manifests generate fmt vet
122133
mkdir -p ${ENVTEST_ASSETS_DIR}
@@ -126,13 +137,124 @@ test-integration: manifests generate fmt vet
126137
setup_envtest_env $(ENVTEST_ASSETS_DIR); \
127138
go test ./test/integration/... -coverprofile cover.out
128139

129-
e2e-job-image:
140+
## E2E Testing
141+
142+
# Note: here we use internal service ns as the entrypointAddress. The test cluster should be registered to itself as a managed cluster.
143+
setup-env-for-e2e:
144+
@echo "Setting up environment for e2e tests..."
145+
./test/e2e/env/init.sh
146+
.PHONY: setup-env-for-e2e
147+
148+
# load cluster-proxy image into kind cluster
149+
load-cluster-proxy-image-kind:
150+
@echo "Loading cluster-proxy image into kind cluster..."
151+
kind load docker-image $(IMAGE_REGISTRY_NAME)/$(IMAGE_NAME):$(IMAGE_TAG) --name $(E2E_TEST_CLUSTER_NAME)
152+
.PHONY: load-cluster-proxy-image-kind
153+
154+
# delete cluster-proxy image from kind cluster nodes
155+
delete-cluster-proxy-image-from-kind:
156+
@echo "Deleting cluster-proxy image from kind cluster nodes..."
157+
@for node in $$(kind get nodes --name $(E2E_TEST_CLUSTER_NAME) 2>/dev/null || echo ""); do \
158+
if [ -n "$$node" ]; then \
159+
docker exec $$node crictl rmi $(IMAGE_REGISTRY_NAME)/$(IMAGE_NAME):$(IMAGE_TAG) 2>/dev/null || true; \
160+
fi; \
161+
done
162+
.PHONY: delete-cluster-proxy-image-from-kind
163+
164+
deploy-cluster-proxy-e2e: delete-cluster-proxy-image-from-kind load-cluster-proxy-image-kind
165+
@echo "Deploying cluster-proxy..."
166+
helm install \
167+
-n open-cluster-management-addon --create-namespace \
168+
cluster-proxy charts/cluster-proxy \
169+
--set registry=$(IMAGE_REGISTRY_NAME) \
170+
--set image=$(IMAGE_NAME) \
171+
--set tag=$(IMAGE_TAG) \
172+
--set proxyServerImage=$(IMAGE_REGISTRY_NAME)/$(IMAGE_NAME) \
173+
--set proxyAgentImage=$(IMAGE_REGISTRY_NAME)/$(IMAGE_NAME) \
174+
--set proxyServer.entrypointAddress="proxy-entrypoint.open-cluster-management-addon.svc" \
175+
--set proxyServer.port=8091 \
176+
--set enableServiceProxy=true
177+
@echo "Cluster-proxy deployed successfully!"
178+
.PHONY: deploy-cluster-proxy-e2e
179+
180+
# Build e2e test container image
181+
build-e2e-image:
182+
@echo "Building e2e test container image..."
130183
$(CONTAINER_ENGINE) build \
131-
-f test/e2e/job/Dockerfile \
132-
-t $(IMAGE_REGISTRY_NAME)/$(IMAGE_NAME)-e2e-job:$(IMAGE_TAG) .
184+
-f test/e2e/Dockerfile \
185+
-t $(IMAGE_REGISTRY_NAME)/$(IMAGE_NAME)-e2e:$(IMAGE_TAG) .
186+
.PHONY: build-e2e-image
187+
188+
# Load e2e image into kind cluster (for local testing)
189+
load-e2e-image-kind:
190+
@echo "Loading e2e image into kind cluster..."
191+
kind load docker-image $(IMAGE_REGISTRY_NAME)/$(IMAGE_NAME)-e2e:$(IMAGE_TAG) --name $(E2E_TEST_CLUSTER_NAME)
192+
.PHONY: load-e2e-image-kind
193+
194+
# Delete e2e image from kind cluster nodes (for rapid iteration)
195+
delete-e2e-image-from-kind:
196+
@echo "Deleting e2e image from kind cluster nodes..."
197+
@for node in $$(kind get nodes --name $(E2E_TEST_CLUSTER_NAME) 2>/dev/null || echo ""); do \
198+
if [ -n "$$node" ]; then \
199+
docker exec $$node crictl rmi $(IMAGE_REGISTRY_NAME)/$(IMAGE_NAME)-e2e:$(IMAGE_TAG) 2>/dev/null || true; \
200+
fi; \
201+
done
202+
.PHONY: delete-e2e-image-from-kind
203+
204+
# Run e2e tests in cluster using container image (Kubernetes-native approach)
205+
# Use LABEL_FILTER to run specific tests, e.g.: make test-e2e LABEL_FILTER="install"
206+
test-e2e: delete-e2e-image-from-kind build-e2e-image load-e2e-image-kind
207+
@echo "Deleting existing e2e test job if present..."
208+
@kubectl delete job cluster-proxy-e2e -n open-cluster-management-addon --ignore-not-found
209+
@echo "Deploying e2e test job..."
210+
@if [ -n "$(LABEL_FILTER)" ]; then \
211+
echo "Running tests with label filter: $(LABEL_FILTER)"; \
212+
fi
213+
@sed -e '/name: LABEL_FILTER/{n;s|value: ""|value: "$(LABEL_FILTER)"|;}' \
214+
-e 's|image: quay.io/open-cluster-management/cluster-proxy-e2e:latest|image: $(IMAGE_REGISTRY_NAME)/$(IMAGE_NAME)-e2e:$(IMAGE_TAG)|g' \
215+
test/e2e/env/job.yaml | kubectl apply -f -
216+
@./test/e2e/env/wait-for-job.sh cluster-proxy-e2e open-cluster-management-addon 1200
217+
.PHONY: test-e2e
218+
219+
# Rapid iteration workflow for e2e tests (cleans up everything first)
220+
# Use LABEL_FILTER to run specific tests, e.g.: make retest-e2e LABEL_FILTER="connectivity"
221+
retest-e2e: clean-e2e delete-e2e-image-from-kind build-e2e-image load-e2e-image-kind
222+
@echo "Deleting existing e2e test job if present..."
223+
@kubectl delete job cluster-proxy-e2e -n open-cluster-management-addon --ignore-not-found
224+
@echo "Deploying e2e test job..."
225+
@if [ -n "$(LABEL_FILTER)" ]; then \
226+
echo "Running tests with label filter: $(LABEL_FILTER)"; \
227+
fi
228+
@sed -e '/name: LABEL_FILTER/{n;s|value: ""|value: "$(LABEL_FILTER)"|;}' \
229+
-e 's|image: quay.io/open-cluster-management/cluster-proxy-e2e:latest|image: $(IMAGE_REGISTRY_NAME)/$(IMAGE_NAME)-e2e:$(IMAGE_TAG)|g' \
230+
test/e2e/env/job.yaml | kubectl apply -f -
231+
@./test/e2e/env/wait-for-job.sh cluster-proxy-e2e open-cluster-management-addon 1200
232+
.PHONY: retest-e2e
133233

134-
build-e2e:
135-
go test -c -o bin/e2e ./test/e2e/
234+
# Clean up e2e test job and related resources
235+
clean-e2e:
236+
@echo "Cleaning up e2e test resources..."
237+
kubectl delete job/cluster-proxy-e2e -n open-cluster-management-addon --ignore-not-found=true
238+
kubectl delete serviceaccount/cluster-proxy-e2e -n open-cluster-management-addon --ignore-not-found=true
239+
kubectl delete clusterrolebinding/cluster-proxy-e2e --ignore-not-found=true
240+
kubectl delete clusterrole/cluster-proxy-e2e --ignore-not-found=true
241+
.PHONY: clean-e2e
136242

137-
test-e2e: build-e2e
138-
./bin/e2e --test-cluster $(E2E_TEST_CLUSTER_NAME)
243+
# Quick verify of user-server
244+
# Example result:
245+
# {
246+
# "kind": "APIVersions",
247+
# "versions": [
248+
# "v1"
249+
# ],
250+
# "serverAddressByClientCIDRs": [
251+
# {
252+
# "clientCIDR": "0.0.0.0/0",
253+
# "serverAddress": "172.17.0.2:6443"
254+
# }
255+
# ]
256+
# }
257+
verify-user-server:
258+
@echo "Verifying user-server..."
259+
TOKEN=$$(kubectl create token default -n default) && POD=$$(kubectl get pods -n open-cluster-management-addon -l component=cluster-proxy-addon-user --field-selector=status.phase=Running -o jsonpath='{.items[0].metadata.name}') && kubectl debug -it $$POD -n open-cluster-management-addon --image=praqma/network-multitool -- sh -c "curl -k -H 'Authorization: Bearer $$TOKEN' https://cluster-proxy-addon-user.open-cluster-management-addon.svc.cluster.local:9092/loopback/api"
260+
.PHONY: verify-user-server

charts/cluster-proxy/Chart.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ apiVersion: v2
22
name: cluster-proxy
33
description: A Helm chart for Cluster-Proxy OCM Addon
44
type: application
5-
version: 0.8.0
6-
appVersion: 1.0.0
5+
version: 0.9.0
6+
appVersion: 1.1.0

charts/cluster-proxy/README.md

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
# Cluster Proxy Helm Chart
2+
3+
This Helm chart installs the Cluster Proxy addon for Open Cluster Management (OCM), which enables accessing services in isolated managed clusters through reverse proxy tunnels.
4+
5+
## Prerequisites
6+
7+
- Kubernetes cluster
8+
- Helm 3.x
9+
- Open Cluster Management (OCM) installed
10+
11+
## Installation
12+
13+
```bash
14+
helm install cluster-proxy ./charts/cluster-proxy \
15+
--namespace open-cluster-management-addon \
16+
--create-namespace
17+
```
18+
19+
## Configuration
20+
21+
### Values
22+
23+
| Parameter | Description | Default |
24+
| --------------------------------------- | ---------------------------------- | ----------------------------------------------- |
25+
| `registry` | Image registry | `quay.io/open-cluster-management` |
26+
| `image` | Image name | `cluster-proxy` |
27+
| `tag` | Image tag | Chart version |
28+
| `replicas` | Number of replicas | `1` |
29+
| `spokeAddonNamespace` | Namespace for spoke addon | `open-cluster-management-cluster-proxy` |
30+
| `proxyServerImage` | Proxy server image | `quay.io/open-cluster-management/cluster-proxy` |
31+
| `proxyAgentImage` | Proxy agent image | `quay.io/open-cluster-management/cluster-proxy` |
32+
| `proxyServer.entrypointLoadBalancer` | Enable LoadBalancer for entrypoint | `false` |
33+
| `proxyServer.entrypointAddress` | Custom entrypoint address | `""` |
34+
| `proxyServer.port` | Proxy server port | `8091` |
35+
| `installByPlacement.placementName` | Placement name for installation | `""` |
36+
| `installByPlacement.placementNamespace` | Placement namespace | `""` |
37+
| `enableServiceProxy` | Enable user server deployment | `false` |
38+
39+
### User Server Configuration
40+
41+
The user server provides an API endpoint for managing cluster proxy connections. To enable it:
42+
43+
```bash
44+
helm install cluster-proxy ./charts/cluster-proxy \
45+
--set enableServiceProxy=true
46+
```
47+
48+
#### Important Prerequisites for User Server
49+
50+
**Before enabling the user server, you MUST create the following secret in the installation namespace:**
51+
52+
**cluster-proxy-user-serving-cert** - TLS certificate for the user server
53+
54+
```yaml
55+
apiVersion: v1
56+
kind: Secret
57+
type: kubernetes.io/tls
58+
metadata:
59+
name: cluster-proxy-user-serving-cert
60+
namespace: <release-namespace>
61+
data:
62+
tls.crt: <base64-encoded-certificate>
63+
tls.key: <base64-encoded-private-key>
64+
```
65+
66+
**Automatically Created Secrets:**
67+
68+
The following secrets will be automatically created by the controller and do NOT need to be created manually:
69+
70+
- **proxy-server-ca** - CA certificate for the proxy server
71+
- **proxy-client** - Client certificate for proxy authentication
72+
73+
**⚠️ Warning:** If the `cluster-proxy-user-serving-cert` secret is not present before installation, the user-server deployment will remain in **Pending** state and pods will fail to start.
74+
75+
To verify the secret is created:
76+
77+
```bash
78+
kubectl get secret -n <release-namespace> cluster-proxy-user-serving-cert
79+
```
80+
81+
## Examples
82+
83+
### Basic Installation
84+
85+
```bash
86+
helm install cluster-proxy ./charts/cluster-proxy
87+
```
88+
89+
### With User Server Enabled
90+
91+
```bash
92+
# First, create the required secret
93+
kubectl create secret tls cluster-proxy-user-serving-cert \
94+
--cert=path/to/tls.crt \
95+
--key=path/to/tls.key \
96+
-n open-cluster-management-addon
97+
98+
# Then install with user server enabled
99+
# Note: proxy-server-ca and proxy-client secrets will be created automatically by the controller
100+
helm install cluster-proxy ./charts/cluster-proxy \
101+
--namespace open-cluster-management-addon \
102+
--set enableServiceProxy=true
103+
```
104+
105+
### Custom Image and Replicas
106+
107+
```bash
108+
helm install cluster-proxy ./charts/cluster-proxy \
109+
--set image=my-custom-proxy \
110+
--set tag=v1.0.0 \
111+
--set replicas=3
112+
```
113+
114+
## Upgrading
115+
116+
```bash
117+
helm upgrade cluster-proxy ./charts/cluster-proxy
118+
```
119+
120+
## Uninstallation
121+
122+
```bash
123+
helm uninstall cluster-proxy
124+
```
125+
126+
## Troubleshooting
127+
128+
### User Server Pods Stuck in Pending
129+
130+
**Symptom:** After enabling `enableServiceProxy=true`, the deployment pods remain in Pending state.
131+
132+
**Solution:** Verify that the required secret exists in the namespace:
133+
134+
```bash
135+
kubectl get secret -n <namespace> cluster-proxy-user-serving-cert
136+
```
137+
138+
If the secret is missing, create it:
139+
140+
```bash
141+
kubectl create secret tls cluster-proxy-user-serving-cert \
142+
--cert=path/to/tls.crt \
143+
--key=path/to/tls.key \
144+
-n <namespace>
145+
```
146+
147+
Note: The `proxy-server-ca` and `proxy-client` secrets are created automatically by the controller and do not need manual creation.
148+
149+
### ImagePullBackOff Errors
150+
151+
**Solution:** Verify the image registry and credentials:
152+
153+
```bash
154+
helm upgrade cluster-proxy ./charts/cluster-proxy \
155+
--set registry=<your-registry> \
156+
--set image=<your-image> \
157+
--set tag=<your-tag>
158+
```
159+
160+
## More Information
161+
162+
For more details about the Cluster Proxy project, visit the [GitHub repository](https://github.com/open-cluster-management-io/cluster-proxy).

0 commit comments

Comments
 (0)