From 9a9d3225d47eee8bac2f8414cdf8e55311e0fa49 Mon Sep 17 00:00:00 2001 From: majiayu000 <1835304752@qq.com> Date: Fri, 2 Jan 2026 03:04:52 +0800 Subject: [PATCH 1/2] feat(vpa): use Helm chart for local E2E testing and dev deployment Replace shell script based kubectl apply deployment with Helm chart for local VPA deployments. This provides: - Consistent deployment via Helm for both local dev and E2E testing - Helm-managed webhook certificate generation - Simplified component selection via Helm values - Feature gates support via extraArgs - Clean uninstall via helm uninstall Changes: - Add values-e2e-local.yaml for local KIND cluster configuration - Modify deploy-for-e2e-locally.sh to use helm install - Update run-e2e-locally.sh to use helm uninstall for cleanup - Add helm to required commands in both scripts Fixes #8984 Signed-off-by: majiayu000 <1835304752@qq.com> --- .../hack/deploy-for-e2e-locally.sh | 114 ++++++++++++++---- .../hack/dev-deploy-locally.sh | 1 + .../hack/e2e/values-e2e-local.yaml | 51 ++++++++ .../hack/run-e2e-locally.sh | 4 +- 4 files changed, 146 insertions(+), 24 deletions(-) create mode 100644 vertical-pod-autoscaler/hack/e2e/values-e2e-local.yaml diff --git a/vertical-pod-autoscaler/hack/deploy-for-e2e-locally.sh b/vertical-pod-autoscaler/hack/deploy-for-e2e-locally.sh index 42057b451aad..ab701efc6c01 100755 --- a/vertical-pod-autoscaler/hack/deploy-for-e2e-locally.sh +++ b/vertical-pod-autoscaler/hack/deploy-for-e2e-locally.sh @@ -67,35 +67,103 @@ esac export REGISTRY=${REGISTRY:-localhost:5001} export TAG=${TAG:-latest} -rm -f ${SCRIPT_ROOT}/hack/e2e/vpa-rbac.yaml -patch -c ${SCRIPT_ROOT}/deploy/vpa-rbac.yaml -i ${SCRIPT_ROOT}/hack/e2e/vpa-rbac.diff -o ${SCRIPT_ROOT}/hack/e2e/vpa-rbac.yaml -kubectl apply -f ${SCRIPT_ROOT}/hack/e2e/vpa-rbac.yaml -# Other-versioned CRDs are irrelevant as we're running a modern-ish cluster. -kubectl apply -f ${SCRIPT_ROOT}/deploy/vpa-v1-crd-gen.yaml +# Deploy metrics server for E2E tests kubectl apply -f ${SCRIPT_ROOT}/hack/e2e/k8s-metrics-server.yaml +# Build and load Docker images for each component for i in ${COMPONENTS}; do + COMPONENT_NAME=$i if [ $i == recommender-externalmetrics ] ; then - i=recommender + COMPONENT_NAME=recommender fi - if [ $i == admission-controller ] ; then - (cd ${SCRIPT_ROOT}/pkg/${i} && bash ./gencerts.sh e2e || true) - kubectl apply -f ${SCRIPT_ROOT}/deploy/admission-controller-service.yaml - fi - ALL_ARCHITECTURES=${ARCH} make --directory ${SCRIPT_ROOT}/pkg/${i} docker-build REGISTRY=${REGISTRY} TAG=${TAG} - docker tag ${REGISTRY}/vpa-${i}-${ARCH}:${TAG} ${REGISTRY}/vpa-${i}:${TAG} - kind load docker-image ${REGISTRY}/vpa-${i}:${TAG} + ALL_ARCHITECTURES=${ARCH} make --directory ${SCRIPT_ROOT}/pkg/${COMPONENT_NAME} docker-build REGISTRY=${REGISTRY} TAG=${TAG} + docker tag ${REGISTRY}/vpa-${COMPONENT_NAME}-${ARCH}:${TAG} ${REGISTRY}/vpa-${COMPONENT_NAME}:${TAG} + kind load docker-image ${REGISTRY}/vpa-${COMPONENT_NAME}:${TAG} done +# Prepare Helm values +HELM_CHART_PATH="${SCRIPT_ROOT}/charts/vertical-pod-autoscaler" +VALUES_FILE="${SCRIPT_ROOT}/hack/e2e/values-e2e-local.yaml" +HELM_RELEASE_NAME="vpa" +HELM_NAMESPACE="kube-system" + +# Build dynamic Helm set arguments based on components +HELM_SET_ARGS="" + +# Enable components based on suite for i in ${COMPONENTS}; do - if [ $i == recommender-externalmetrics ] ; then - kubectl delete namespace monitoring --ignore-not-found=true - kubectl create namespace monitoring - kubectl apply -f ${SCRIPT_ROOT}/hack/e2e/prometheus.yaml - kubectl apply -f ${SCRIPT_ROOT}/hack/e2e/prometheus-adapter.yaml - kubectl apply -f ${SCRIPT_ROOT}/hack/e2e/metrics-pump.yaml - kubectl apply -f ${SCRIPT_ROOT}/hack/e2e/${i}-deployment.yaml - else - REGISTRY=${REGISTRY} TAG=${TAG} ${SCRIPT_ROOT}/hack/vpa-process-yaml.sh ${SCRIPT_ROOT}/deploy/${i}-deployment.yaml | kubectl apply -f - - fi + case $i in + recommender|recommender-externalmetrics) + HELM_SET_ARGS="${HELM_SET_ARGS} --set recommender.enabled=true" + HELM_SET_ARGS="${HELM_SET_ARGS} --set recommender.image.repository=${REGISTRY}/vpa-recommender" + HELM_SET_ARGS="${HELM_SET_ARGS} --set recommender.image.tag=${TAG}" + ;; + updater) + HELM_SET_ARGS="${HELM_SET_ARGS} --set updater.enabled=true" + HELM_SET_ARGS="${HELM_SET_ARGS} --set updater.image.repository=${REGISTRY}/vpa-updater" + HELM_SET_ARGS="${HELM_SET_ARGS} --set updater.image.tag=${TAG}" + ;; + admission-controller) + HELM_SET_ARGS="${HELM_SET_ARGS} --set admissionController.enabled=true" + HELM_SET_ARGS="${HELM_SET_ARGS} --set admissionController.image.repository=${REGISTRY}/vpa-admission-controller" + HELM_SET_ARGS="${HELM_SET_ARGS} --set admissionController.image.tag=${TAG}" + ;; + esac done + +# Add feature gates if specified +if [ -n "${FEATURE_GATES:-}" ]; then + # Add feature gates to each enabled component + for i in ${COMPONENTS}; do + case $i in + recommender|recommender-externalmetrics) + HELM_SET_ARGS="${HELM_SET_ARGS} --set recommender.extraArgs[0]=--feature-gates=${FEATURE_GATES}" + ;; + updater) + HELM_SET_ARGS="${HELM_SET_ARGS} --set updater.extraArgs[0]=--feature-gates=${FEATURE_GATES}" + ;; + admission-controller) + HELM_SET_ARGS="${HELM_SET_ARGS} --set admissionController.extraArgs[0]=--feature-gates=${FEATURE_GATES}" + ;; + esac + done +fi + +# Uninstall any existing VPA Helm release +helm uninstall ${HELM_RELEASE_NAME} --namespace ${HELM_NAMESPACE} 2>/dev/null || true + +# Install VPA using Helm chart +echo " ** Installing VPA via Helm chart" +helm install ${HELM_RELEASE_NAME} ${HELM_CHART_PATH} \ + --namespace ${HELM_NAMESPACE} \ + --values ${VALUES_FILE} \ + ${HELM_SET_ARGS} \ + --wait + +# Handle external metrics special case +if [[ "${SUITE}" == "recommender-externalmetrics" ]]; then + echo " ** Setting up external metrics infrastructure" + + # Apply extra RBAC for external metrics + rm -f ${SCRIPT_ROOT}/hack/e2e/vpa-rbac.yaml + patch -c ${SCRIPT_ROOT}/deploy/vpa-rbac.yaml -i ${SCRIPT_ROOT}/hack/e2e/vpa-rbac.diff -o ${SCRIPT_ROOT}/hack/e2e/vpa-rbac.yaml + kubectl apply -f ${SCRIPT_ROOT}/hack/e2e/vpa-rbac.yaml + + # Deploy Prometheus and adapter for external metrics + kubectl delete namespace monitoring --ignore-not-found=true + kubectl create namespace monitoring + kubectl apply -f ${SCRIPT_ROOT}/hack/e2e/prometheus.yaml + kubectl apply -f ${SCRIPT_ROOT}/hack/e2e/prometheus-adapter.yaml + kubectl apply -f ${SCRIPT_ROOT}/hack/e2e/metrics-pump.yaml + + # Upgrade Helm release with external metrics configuration + echo " ** Updating recommender with external metrics args" + helm upgrade ${HELM_RELEASE_NAME} ${HELM_CHART_PATH} \ + --namespace ${HELM_NAMESPACE} \ + --values ${VALUES_FILE} \ + ${HELM_SET_ARGS} \ + --set "recommender.extraArgs[0]=--use-external-metrics=true" \ + --set "recommender.extraArgs[1]=--external-metrics-cpu-metric=cpu" \ + --set "recommender.extraArgs[2]=--external-metrics-memory-metric=mem" \ + --wait +fi diff --git a/vertical-pod-autoscaler/hack/dev-deploy-locally.sh b/vertical-pod-autoscaler/hack/dev-deploy-locally.sh index 426060a145f3..2dc828a010d5 100755 --- a/vertical-pod-autoscaler/hack/dev-deploy-locally.sh +++ b/vertical-pod-autoscaler/hack/dev-deploy-locally.sh @@ -32,6 +32,7 @@ REQUIRED_COMMANDS=" docker git go +helm kubectl make " diff --git a/vertical-pod-autoscaler/hack/e2e/values-e2e-local.yaml b/vertical-pod-autoscaler/hack/e2e/values-e2e-local.yaml new file mode 100644 index 000000000000..f53cdf1576f4 --- /dev/null +++ b/vertical-pod-autoscaler/hack/e2e/values-e2e-local.yaml @@ -0,0 +1,51 @@ +# Helm values for local E2E testing +# Used by deploy-for-e2e-locally.sh + +# Image settings - will be overridden via --set at install time +# admissionController.image.repository, admissionController.image.tag, etc. + +# Pod security context +podSecurityContext: + runAsNonRoot: true + runAsUser: 65534 + +# Component configurations optimized for local KIND cluster +admissionController: + enabled: false # Enabled dynamically based on suite + replicas: 1 + image: + pullPolicy: Never + # Disable pod anti-affinity for single-node clusters + affinity: {} + podDisruptionBudget: + enabled: false + # Use Helm-managed webhook (certgen creates certificates) + registerWebhook: false + certGen: + enabled: true + +recommender: + enabled: false # Enabled dynamically based on suite + replicas: 1 + image: + pullPolicy: Never + # Disable pod anti-affinity for single-node clusters + affinity: {} + podDisruptionBudget: + enabled: false + # Disable leader election for single replica + leaderElection: + enabled: false + +updater: + enabled: false # Enabled dynamically based on suite + replicas: 1 + image: + pullPolicy: Never + # Disable pod anti-affinity for single-node clusters + affinity: {} + podDisruptionBudget: + enabled: false + # Disable leader election for single replica + leaderElection: + enabled: false diff --git a/vertical-pod-autoscaler/hack/run-e2e-locally.sh b/vertical-pod-autoscaler/hack/run-e2e-locally.sh index 9a31af75d2e9..f4075881a0a1 100755 --- a/vertical-pod-autoscaler/hack/run-e2e-locally.sh +++ b/vertical-pod-autoscaler/hack/run-e2e-locally.sh @@ -45,6 +45,7 @@ SUITE=$1 REQUIRED_COMMANDS=" docker go +helm kind kubectl make @@ -97,7 +98,8 @@ fi case ${SUITE} in recommender|recommender-externalmetrics|updater|admission-controller|actuation|full-vpa) - ${SCRIPT_ROOT}/hack/vpa-down.sh + # Cleanup any existing VPA Helm release + helm uninstall vpa --namespace kube-system 2>/dev/null || true echo " ** Deploying for suite ${SUITE}" ${SCRIPT_ROOT}/hack/deploy-for-e2e-locally.sh ${SUITE} From bf47ae116164b29058464c32022332eb9b51d49a Mon Sep 17 00:00:00 2001 From: majiayu000 <1835304752@qq.com> Date: Fri, 2 Jan 2026 03:09:32 +0800 Subject: [PATCH 2/2] fix(vpa): prevent extraArgs index conflict with feature gates When FEATURE_GATES and external metrics are both enabled, the extraArgs indices would overlap, overwriting feature gate settings. This fix dynamically calculates the starting index for external metrics arguments to avoid conflicts. Signed-off-by: majiayu000 <1835304752@qq.com> --- .../hack/deploy-for-e2e-locally.sh | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/vertical-pod-autoscaler/hack/deploy-for-e2e-locally.sh b/vertical-pod-autoscaler/hack/deploy-for-e2e-locally.sh index ab701efc6c01..dd088ecf51e0 100755 --- a/vertical-pod-autoscaler/hack/deploy-for-e2e-locally.sh +++ b/vertical-pod-autoscaler/hack/deploy-for-e2e-locally.sh @@ -158,12 +158,17 @@ if [[ "${SUITE}" == "recommender-externalmetrics" ]]; then # Upgrade Helm release with external metrics configuration echo " ** Updating recommender with external metrics args" + # Determine starting index for external metrics args (after feature gates if set) + EXTERNAL_METRICS_START_INDEX=0 + if [ -n "${FEATURE_GATES:-}" ]; then + EXTERNAL_METRICS_START_INDEX=1 + fi helm upgrade ${HELM_RELEASE_NAME} ${HELM_CHART_PATH} \ --namespace ${HELM_NAMESPACE} \ --values ${VALUES_FILE} \ ${HELM_SET_ARGS} \ - --set "recommender.extraArgs[0]=--use-external-metrics=true" \ - --set "recommender.extraArgs[1]=--external-metrics-cpu-metric=cpu" \ - --set "recommender.extraArgs[2]=--external-metrics-memory-metric=mem" \ + --set "recommender.extraArgs[${EXTERNAL_METRICS_START_INDEX}]=--use-external-metrics=true" \ + --set "recommender.extraArgs[$((EXTERNAL_METRICS_START_INDEX + 1))]=--external-metrics-cpu-metric=cpu" \ + --set "recommender.extraArgs[$((EXTERNAL_METRICS_START_INDEX + 2))]=--external-metrics-memory-metric=mem" \ --wait fi