Skip to content

Commit 6579b62

Browse files
committed
add documentation on running e2e test locally
1 parent a5f0307 commit 6579b62

File tree

6 files changed

+623
-13
lines changed

6 files changed

+623
-13
lines changed

Makefile

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ E2E_CONF_FILE_ENVSUBST := $(ROOT_DIR)/test/e2e/config/azure-dev-envsubst.yaml
186186
SKIP_CLEANUP ?= false
187187
AZWI_SKIP_CLEANUP ?= false
188188
SKIP_LOG_COLLECTION ?= false
189+
MGMT_CLUSTER_TYPE ?= kind
189190
# @sonasingh46: Skip creating mgmt cluster for ci as workload identity needs kind cluster
190191
# to be created with extra mounts for key pairs which is not yet supported
191192
# by existing e2e framework. A mgmt cluster(kind) is created as part of e2e suite
@@ -317,8 +318,12 @@ install-tools: $(ENVSUBST) $(KUSTOMIZE) $(KUBECTL) $(HELM) $(GINKGO) $(KIND) $(A
317318

318319
.PHONY: create-management-cluster
319320
create-management-cluster: $(KUSTOMIZE) $(ENVSUBST) $(KUBECTL) $(KIND) ## Create a management cluster.
320-
# Create kind management cluster.
321-
$(MAKE) kind-create
321+
# Create management cluster based on type
322+
@if [ "$(MGMT_CLUSTER_TYPE)" = "aks" ]; then \
323+
$(MAKE) aks-create; \
324+
else \
325+
$(MAKE) kind-create; \
326+
fi
322327

323328
# Install cert manager and wait for availability
324329
./hack/install-cert-manager.sh
@@ -334,7 +339,9 @@ create-management-cluster: $(KUSTOMIZE) $(ENVSUBST) $(KUBECTL) $(KIND) ## Create
334339
timeout --foreground 300 bash -c "until curl --retry $(CURL_RETRIES) -sSL https://github.com/kubernetes-sigs/cluster-api-addon-provider-helm/releases/download/v0.2.5/addon-components.yaml | $(ENVSUBST) | $(KUBECTL) apply -f -; do sleep 5; done"
335340

336341
# Deploy CAPZ
337-
$(KIND) load docker-image $(CONTROLLER_IMG)-$(ARCH):$(TAG) --name=$(KIND_CLUSTER_NAME)
342+
@if [ "$(MGMT_CLUSTER_TYPE)" != "aks" ]; then \
343+
$(KIND) load docker-image $(CONTROLLER_IMG)-$(ARCH):$(TAG) --name=$(KIND_CLUSTER_NAME); \
344+
fi
338345
timeout --foreground 300 bash -c "until $(KUSTOMIZE) build config/default | $(ENVSUBST) | $(KUBECTL) apply -f - --server-side=true; do sleep 5; done"
339346

340347
# Wait for CAPI deployments
@@ -360,7 +367,6 @@ create-management-cluster: $(KUSTOMIZE) $(ENVSUBST) $(KUBECTL) $(KIND) ## Create
360367
timeout --foreground 300 bash -c "until $(KUBECTL) get clusters -A; do sleep 3; done"
361368
timeout --foreground 300 bash -c "until $(KUBECTL) get azureclusters -A; do sleep 3; done"
362369
timeout --foreground 300 bash -c "until $(KUBECTL) get kubeadmcontrolplanes -A; do sleep 3; done"
363-
@echo 'Set kubectl context to the kind management cluster by running "$(KUBECTL) config set-context kind-$(KIND_CLUSTER_NAME)"'
364370

365371
.PHONY: create-workload-cluster
366372
create-workload-cluster: $(ENVSUBST) $(KUBECTL) ## Create a workload cluster.
@@ -726,6 +732,25 @@ test-cover: test ## Run tests with code coverage and generate reports.
726732
kind-create-bootstrap: $(KUBECTL) ## Create capz kind bootstrap cluster.
727733
KIND_CLUSTER_NAME=capz-e2e ./scripts/kind-with-registry.sh
728734

735+
.PHONY: create-bootstrap
736+
create-bootstrap: $(KUBECTL) ## Create bootstrap cluster (AKS or KIND) for CAPZ testing. Default is KIND.
737+
@echo "Creating bootstrap cluster with type: $(MGMT_CLUSTER_TYPE)"
738+
@if [ "$(MGMT_CLUSTER_TYPE)" = "aks" ]; then \
739+
if [ -z "$(AZURE_SUBSCRIPTION_ID)" ]; then \
740+
echo "Error: AZURE_SUBSCRIPTION_ID is required for AKS bootstrap cluster" >&2; \
741+
exit 1; \
742+
fi; \
743+
MGMT_CLUSTER_NAME="$${MGMT_CLUSTER_NAME:-capz-e2e-$(shell date +%s)}" \
744+
AKS_RESOURCE_GROUP="$${AKS_RESOURCE_GROUP:-$$MGMT_CLUSTER_NAME}" \
745+
AKS_MGMT_VNET_NAME="$${AKS_MGMT_VNET_NAME:-$$MGMT_CLUSTER_NAME-vnet}" \
746+
AKS_MGMT_SUBNET_NAME="$${AKS_MGMT_SUBNET_NAME:-$$MGMT_CLUSTER_NAME-subnet}" \
747+
./scripts/aks-as-mgmt.sh || { echo "Failed to create AKS bootstrap cluster" >&2; exit 1; }; \
748+
else \
749+
KIND_CLUSTER_NAME="$${KIND_CLUSTER_NAME:-capz-e2e}" \
750+
./scripts/kind-with-registry.sh || { echo "Failed to create KIND bootstrap cluster" >&2; exit 1; }; \
751+
fi
752+
@echo "Bootstrap cluster created successfully"
753+
729754
.PHONY: cleanup-workload-identity
730755
cleanup-workload-identity: ## Cleanup CI workload-identity infra
731756
@if ! [ "$(AZWI_SKIP_CLEANUP)" == "true" ]; then \

docs/book/src/developers/development.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,8 @@ To run E2E locally, set `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`, `AZURE_SUBSCRI
504504
./scripts/ci-e2e.sh
505505
```
506506

507+
Note: Users that have a restrictive environment and want to leverage API Server ILB in their flavors and want to run e2e tests locally, refer to detailed explanation on achieving so in [running e2e tests locally leveraging apiserver ilb solution](./tilt-with-aks-as-mgmt-ilb.md#running-e2e-tests-locally-using-api-server-ilbs-networking-solution)
508+
507509
You can optionally set the following variables:
508510

509511
| Variable | Description | Default |

docs/book/src/developers/tilt-with-aks-as-mgmt-ilb.md

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,3 +124,153 @@ Once the tilt UI is up and running
124124
- Flavors that leverage internal load balancer are:
125125
- `apiserver-ilb`
126126
- `windows-apiserver-ilb`
127+
128+
### Running e2e tests locally using API Server ILB's networking solution
129+
130+
Building upon the [challenges and solutions](#challenges-and-solutions) from above, running an e2e test locally in a restricted environment calls from some workarounds to the prow templates and the e2e test itself.
131+
132+
1. We need the apiserver ilb with private endpoints, opinionated CIDRs to the workload cluster's VNet & Subnets, and pre-kubeadm commands updating the etc/hosts of the worker nodes of the workload cluster.
133+
134+
2. Once the template has been modified to be run in local environment using AKS as management cluster, we need to be able to peer the vnets, create private DNS zone for the FQDN of the workload cluster and re-enable blocked NSG ports.
135+
136+
**Note:**
137+
138+
- Following guidance is only for testing, and not a recommendation for any production environment.
139+
140+
- The below steps for self-managed templates only. Does not apply to AKS workload clusters.
141+
142+
#### Update prow template with apiserver ILB networking solution
143+
144+
There are three sections of a prow template that needs an update.
145+
146+
1. AzureCluster
147+
- `/spec/networkSpec/apiServerLB`
148+
- Add FrontendIP
149+
- Add an associated private IP to be leveraged by an intern ILB
150+
- `/spec/networkSpec/vnet/cidrBlocks`
151+
- Add VNet CIDR
152+
- `/spec/networkSpec/subnets/0/cidrBlocks`
153+
- Add Subnet CIDR for the control plane
154+
- `/spec/networkSpec/subnets/1/cidrBlocks`
155+
- Add Subnet CIDR for the worker node
156+
2. `KubeadmConfigTemplate` - linux node; Identifiable by `name: .*-md-0`
157+
- `/spec/template/spec/preKubeadmCommands/0`
158+
- Add prekubeadm command updating the `/etc/hosts` of the worker node of the type linux.
159+
3. `KubeadmConfigTemplate` - windows node; Identifiable by `name: .*-md-win`
160+
- `/spec/template/spec/preKubeadmCommands/0`
161+
- Add prekubeadm command updating the `/etc/hosts` of the worker node of the type windows.
162+
163+
A Sample kustomize command updating a prow template via its kustomization.yaml is pasted below.
164+
165+
```yaml
166+
- target:
167+
kind: AzureCluster
168+
patch: |-
169+
- op: add
170+
path: /spec/networkSpec/apiServerLB
171+
value:
172+
frontendIPs:
173+
- name: ${CLUSTER_NAME}-api-lb
174+
publicIP:
175+
dnsName: ${CLUSTER_NAME}-${APISERVER_LB_DNS_SUFFIX}.${AZURE_LOCATION}.cloudapp.azure.com
176+
name: ${CLUSTER_NAME}-api-lb
177+
- name: ${CLUSTER_NAME}-internal-lb-private-ip
178+
privateIP: ${AZURE_INTERNAL_LB_PRIVATE_IP}
179+
- target:
180+
kind: AzureCluster
181+
patch: |-
182+
- op: add
183+
path: /spec/networkSpec/vnet/cidrBlocks
184+
value: []
185+
- op: add
186+
path: /spec/networkSpec/vnet/cidrBlocks/0
187+
value: ${AZURE_VNET_CIDR}
188+
- target:
189+
kind: AzureCluster
190+
patch: |-
191+
- op: add
192+
path: /spec/networkSpec/subnets/0/cidrBlocks
193+
value: []
194+
- op: add
195+
path: /spec/networkSpec/subnets/0/cidrBlocks/0
196+
value: ${AZURE_CP_SUBNET_CIDR}
197+
- target:
198+
kind: AzureCluster
199+
patch: |-
200+
- op: add
201+
path: /spec/networkSpec/subnets/1/cidrBlocks
202+
value: []
203+
- op: add
204+
path: /spec/networkSpec/subnets/1/cidrBlocks/0
205+
value: ${AZURE_NODE_SUBNET_CIDR}
206+
- target:
207+
kind: KubeadmConfigTemplate
208+
name: .*-md-win
209+
patch: |-
210+
- op: add
211+
path: /spec/template/spec/preKubeadmCommands
212+
value: []
213+
- op: add
214+
path: /spec/template/spec/preKubeadmCommands/0
215+
value:
216+
powershell -Command "Add-Content -Path 'C:\\Windows\\System32\\drivers\\etc\\hosts' -Value '${AZURE_INTERNAL_LB_PRIVATE_IP} ${CLUSTER_NAME}-${APISERVER_LB_DNS_SUFFIX}.${AZURE_LOCATION}.cloudapp.azure.com'"
217+
- target:
218+
kind: KubeadmConfigTemplate
219+
name: .*-md-0
220+
patch: |-
221+
- op: add
222+
path: /spec/template/spec/preKubeadmCommands
223+
value: []
224+
- op: add
225+
path: /spec/template/spec/preKubeadmCommands/0
226+
value: echo '${AZURE_INTERNAL_LB_PRIVATE_IP} ${CLUSTER_NAME}-${APISERVER_LB_DNS_SUFFIX}.${AZURE_LOCATION}.cloudapp.azure.com' >> /etc/hosts
227+
```
228+
229+
#### Peer Vnets of the management cluster and the workload cluster
230+
231+
Peering VNets, creation of private DNS zone with the FQDN of the workload cluster and updating of NSGs of management and workload cluster can be achieved by `peer-vnets.sh` present in `scripts/peer-vnets.sh`
232+
233+
This script, `scripts/peer-vnets.sh`, should be run after triggering the test run locally and in a separate terminal.
234+
235+
#### Running the test locally
236+
237+
We recommend running the test individually while debugging the test failure. This implies that `GINKGO_FOCUS` as unique as possible. So for instance if you want to run `periodic-cluster-api-provider-azure-e2e-main`'s "With 3 control-plane nodes and 2 Linux and 2 Windows worker nodes" test,
238+
239+
1. We first need to add the following environment variables to the test itself. For example:
240+
241+
```go
242+
Expect(os.Setenv("EXP_APISERVER_ILB", "true")).To(Succeed())
243+
Expect(os.Setenv("AZURE_INTERNAL_LB_PRIVATE_IP", "10.0.0.101")).To(Succeed())
244+
Expect(os.Setenv("AZURE_VNET_CIDR", "10.0.0.0/8")).To(Succeed())
245+
Expect(os.Setenv("AZURE_CP_SUBNET_CIDR", "10.0.0.0/16")).To(Succeed())
246+
Expect(os.Setenv("AZURE_NODE_SUBNET_CIDR", "10.1.0.0/16")).To(Succeed())
247+
```
248+
249+
The above lines should be added before the `clusterctl.ApplyClusterTemplateAndWait()` is invoked.
250+
251+
252+
2. Open the terminal and run the below command:
253+
254+
```bash
255+
GINKGO_FOCUS="With 3 control-plane nodes and 2 Linux and 2 Windows worker nodes" USE_LOCAL_KIND_REGISTRY=false SKIP_CLEANUP="true" SKIP_LOG_COLLECTION="true" REGISTRY="<>" MGMT_CLUSTER_TYPE="aks" EXP_APISERVER_ILB=true AZURE_LOCATION="<>" scripts/ci-e2e.sh
256+
```
257+
258+
**Note:**
259+
260+
- Set `MGMT_CLUSTER_TYPE` to `"aks"` to leverage `AKS` as the management cluster.
261+
- Set `EXP_APISERVER_ILB` to `true` to enable the API Server ILB feature gate.
262+
263+
264+
265+
3. In a new terminal, wait for AzureClusters to be created by the above command. Check it using `kubectl get AzureClusters -A`. Note that this command will fail or will not output anything unless the above command, `GINKGO_FOCUS...`, has deployed the worker template and initiated workload cluster creation.
266+
267+
Once the worker cluster has been created, `export` the `CLUSTER_NAME` and `CLUSTER_NAMESPACE`.
268+
It is recommended that `AZURE_INTERNAL_LB_PRIVATE_IP` is set an IP of `10.0.0.x`, say `10.0.0.101`, to avoid any test updates.
269+
270+
Then open a new terminal at the root of the cluster api provider azure repo and run the below command.
271+
272+
```bash
273+
AZURE_INTERNAL_LB_PRIVATE_IP="<IP of your choice>" CLUSTER_NAME="<e2e workload cluster name>" CLUSTER_NAMESPACE="<e2e cluster namespace>" ./scripts/peer-vnets.sh ./tilt-settings.yaml
274+
```
275+
276+
You will see that the test progresses in the first terminal window that invoked `GINKGO_FOCUS=....`

e2e.mk

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@
55

66
##@ E2E Testing:
77
.PHONY: test-e2e-run
8-
test-e2e-run: generate-e2e-templates install-tools kind-create-bootstrap ## Run e2e tests.
9-
@$(ENVSUBST) < $(E2E_CONF_FILE) > $(E2E_CONF_FILE_ENVSUBST) && \
8+
test-e2e-run: generate-e2e-templates install-tools create-bootstrap ## Run e2e tests.
9+
if [ "$(MGMT_CLUSTER_TYPE)" == "aks" ]; then \
10+
source ./scripts/peer-vnets.sh && source_tilt_settings tilt-settings.yaml; \
11+
fi; \
12+
$(ENVSUBST) < $(E2E_CONF_FILE) > $(E2E_CONF_FILE_ENVSUBST) && \
1013
if [ -z "${AZURE_CLIENT_ID_USER_ASSIGNED_IDENTITY}" ]; then \
1114
export AZURE_CLIENT_ID_USER_ASSIGNED_IDENTITY=$(shell cat $(AZURE_IDENTITY_ID_FILEPATH)); \
1215
fi; \
@@ -18,21 +21,25 @@ test-e2e-run: generate-e2e-templates install-tools kind-create-bootstrap ## Run
1821
$(MAKE) cleanup-workload-identity
1922
$(MAKE) clean-release-git
2023

24+
2125
.PHONY: test-e2e
2226
test-e2e: ## Run "docker-build" and "docker-push" rules then run e2e tests.
27+
$(eval ARCH := $(if $(filter aks,$(MGMT_CLUSTER_TYPE)),amd64,$(ARCH)))
2328
PULL_POLICY=IfNotPresent MANAGER_IMAGE=$(CONTROLLER_IMG)-$(ARCH):$(TAG) \
2429
$(MAKE) docker-build docker-push \
2530
test-e2e-run
2631

2732
.PHONY: test-e2e-skip-push
2833
test-e2e-skip-push: ## Run "docker-build" rule then run e2e tests.
34+
$(eval ARCH := $(if $(filter aks,$(MGMT_CLUSTER_TYPE)),amd64,$(ARCH)))
2935
PULL_POLICY=IfNotPresent MANAGER_IMAGE=$(CONTROLLER_IMG)-$(ARCH):$(TAG) \
3036
$(MAKE) docker-build \
3137
test-e2e-run
3238

3339
.PHONY: test-e2e-skip-build-and-push
3440
test-e2e-skip-build-and-push:
35-
$(MAKE) set-manifest-image MANIFEST_IMG=$(CONTROLLER_IMG)-$(ARCH) MANIFEST_TAG=$(TAG) TARGET_RESOURCE="./config/capz/manager_image_patch.yaml"
36-
$(MAKE) set-manifest-pull-policy TARGET_RESOURCE="./config/capz/manager_pull_policy.yaml" PULL_POLICY=IfNotPresent
41+
$(eval ARCH := $(if $(filter aks,$(MGMT_CLUSTER_TYPE)),amd64,$(ARCH)))
42+
$(MAKE) set-manifest-image MANIFEST_IMG=$(CONTROLLER_IMG)-$(ARCH) MANIFEST_TAG=$(TAG) TARGET_RESOURCE="./config/capz/manager_image_patch.yaml" \
43+
$(MAKE) set-manifest-pull-policy TARGET_RESOURCE="./config/capz/manager_pull_policy.yaml" PULL_POLICY=IfNotPresent \
3744
MANAGER_IMAGE=$(CONTROLLER_IMG)-$(ARCH):$(TAG) \
3845
$(MAKE) test-e2e-run

0 commit comments

Comments
 (0)