Add e2e autoscaling test

Signed-off-by: Paul Meyer <49727155+katexochen@users.noreply.github.com>
This commit is contained in:
Paul Meyer 2022-10-24 18:47:03 +02:00
parent 7108304046
commit 95b8531fdd
10 changed files with 224 additions and 60 deletions

View File

@ -1,6 +1,6 @@
name: Constellation create
description: |
Create a new Constellation cluster using latest OS image.
description: Create a new Constellation cluster using latest OS image.
inputs:
workerNodesCount:
description: "Number of worker nodes to spawn."
@ -32,10 +32,17 @@ inputs:
azureResourceGroup:
description: "The resource group to use for Constellation cluster"
required: false
outputs:
kubeconfig:
description: "The kubeconfig for the cluster."
value: ${{ steps.constellation-init.outputs.KUBECONFIG }}
runs:
using: "composite"
steps:
- name: Constellation config generate
shell: bash
run: |
constellation config generate ${{ inputs.cloudProvider }}
@ -60,9 +67,11 @@ runs:
if [ ${{ inputs.kubernetesVersion != '' }} = true ]; then
yq eval -i "(.kubernetesVersion) = ${{ inputs.kubernetesVersion }}" constellation-conf.yaml
fi
shell: bash
- name: Set image
shell: bash
env:
CSP: ${{ inputs.cloudProvider }}
run: |
case $CSP in
azure)
@ -89,10 +98,6 @@ runs:
;;
esac
shell: bash
env:
CSP: ${{ inputs.cloudProvider }}
- name: Set instanceType
if: ${{ inputs.machineType && inputs.machineType != 'default' }}
shell: bash
@ -103,41 +108,45 @@ runs:
- name: Create serviceAccountKey.json
if: ${{ inputs.cloudProvider == 'gcp' }}
shell: bash
run: |
echo "$GCP_CLUSTER_SERVICE_ACCOUNT_KEY" > serviceAccountKey.json
env:
GCP_CLUSTER_SERVICE_ACCOUNT_KEY: ${{ inputs.gcpClusterServiceAccountKey }}
run: |
echo "$GCP_CLUSTER_SERVICE_ACCOUNT_KEY" > serviceAccountKey.json
- name: Enable debugCluster flag
if: ${{ inputs.isDebugImage == 'true' }}
shell: bash
run: |
yq eval -i '(.debugCluster) = true' constellation-conf.yaml
shell: bash
if: ${{ inputs.isDebugImage == 'true' }}
- name: Constellation create
shell: bash
run: |
echo "Creating cluster using config:"
cat constellation-conf.yaml
constellation create -c ${{ inputs.controlNodesCount }} -w ${{ inputs.workerNodesCount }} --name e2e-test -y
shell: bash
- name: Cdbg deploy
if: ${{ inputs.isDebugImage == 'true' }}
shell: bash
run: |
echo "::group::cdbg deploy"
chmod +x $GITHUB_WORKSPACE/build/cdbg
cdbg deploy --bootstrapper $GITHUB_WORKSPACE/build/bootstrapper
echo "::endgroup::"
shell: bash
if: ${{ inputs.isDebugImage == 'true' }}
- name: Constellation init
id: constellation-init
shell: bash
run: |
constellation init
echo "KUBECONFIG=$(pwd)/constellation-admin.conf" >> $GITHUB_OUTPUT
shell: bash
- name: Wait for nodes to join and become ready
shell: bash
env:
KUBECONFIG: "${{ steps.constellation-init.outputs.KUBECONFIG }}"
JOINTIMEOUT: "1200" # 20 minutes timeout for all nodes to join
run: |
echo "::group::Wait for nodes"
NODES_COUNT=$((${{ inputs.controlNodesCount }} + ${{ inputs.workerNodesCount }}))
@ -155,12 +164,13 @@ runs:
echo "$(kubectl get nodes -o json | jq '.items | length')/"${NODES_COUNT}" nodes have joined"
kubectl wait --for=condition=ready --all nodes --timeout=10m
echo "::endgroup::"
shell: bash
env:
KUBECONFIG: "${{ steps.constellation-init.outputs.KUBECONFIG }}"
JOINTIMEOUT: "1200" # 20 minutes timeout for all nodes to join
- name: Download boot logs
if: ${{ always() }}
continue-on-error: true
shell: bash
env:
CSP: ${{ inputs.cloudProvider }}
run: |
echo "::group::Download boot logs"
case $CSP in
@ -176,14 +186,10 @@ runs:
;;
esac
echo "::endgroup::"
shell: bash
env:
CSP: ${{ inputs.cloudProvider }}
continue-on-error: true
if: ${{ always() }}
- name: Upload boot logs
if: ${{ always() && !env.ACT }}
uses: actions/upload-artifact@83fd05a356d7e2593de66fc9913b3002723633cb # tag=v3.1.1
with:
name: serial-logs
path: "*.log"
if: ${{ always() && !env.ACT }}

View File

@ -0,0 +1,104 @@
name: E2E autoscaling test
description: "Test autoscaling functionality of the operator."
inputs:
kubeconfig:
description: "The kubeconfig of the cluster to test."
required: true
runs:
using: "composite"
steps:
# This action assumes that the cluster is in an ready state, with all nodes joined and ready.
- name: Determine number of workers in cluster
id: worker_count
shell: bash
env:
KUBECONFIG: ${{ inputs.kubeconfig }}
run: |
worker_count=$(kubectl get nodes -o json --selector='!node-role.kubernetes.io/control-plane' | jq '.items | length')
echo "worker_count=${worker_count}" >> $GITHUB_OUTPUT
echo "The cluster currently has ${worker_count} nodes."
# The following step identifies the name of the worker scaling group. As the scaling group is
# a custom resource definition, we need to wait for its creation.
- name: Find worker scaling group
id: worker_name
shell: bash
env:
KUBECONFIG: ${{ inputs.kubeconfig }}
run: |
TIMEOUT=1200
WAIT=0
until [[ $(( "$(kubectl get scalinggroups -o json | jq '.items | length')" )) -ge 2 ]] || [[ $WAIT -gt $TIMEOUT ]];
do
echo "Waiting for creation of custom resource definitions..."
WAIT=$((WAIT+30))
sleep 30
done
if [[ $WAIT -gt $TIMEOUT ]]; then
echo "Timed out waiting for nodes to join"
exit 1
fi
worker_group=$(kubectl get scalinggroups -o json | jq -r '.items[].metadata.name | select(contains("worker"))')
echo "worker_name=${worker_group}" >> $GITHUB_OUTPUT
echo "The name of your worker scaling group is '${worker_group}'."
- name: Patch autoscaling to true
shell: bash
env:
KUBECONFIG: ${{ inputs.kubeconfig }}
run: |
worker_group=${{ steps.worker_name.outputs.worker_name }}
kubectl patch scalinggroups ${worker_group} --patch '{"spec":{"autoscaling": true}}' --type='merge'
kubectl get scalinggroup ${worker_group} -o jsonpath='{.spec}' | jq
- name: Set an autoscaling target/limit
id: scaling_limit
shell: bash
env:
KUBECONFIG: ${{ inputs.kubeconfig }}
run: |
worker_group=${{ steps.worker_name.outputs.worker_name }}
worker_count=${{ steps.worker_count.outputs.worker_count }}
worker_target=$((worker_count + 2))
echo "worker_target=${worker_target}" >> $GITHUB_OUTPUT
kubectl patch scalinggroups ${worker_group} --patch '{"spec":{"max": '${worker_target}'}}' --type='merge'
kubectl get scalinggroup ${worker_group} -o jsonpath='{.spec}' | jq
# Number of replicas that are deployed to trigger autoscaling of nodes can't be determined exact.
# The following steps calculates a value based on the limit of 110 pods per nodes, that is
# described at https://kubernetes.io/docs/setup/best-practices/cluster-large/.
# We try to fill the existing nodes and one additional node up to the limit,
# and add half capacity for the second additional node so we have some space to the upper and
# lower bound. If we deploy to many replicas, the deployment won't finish as we run into our
# scaling limit. If we deploy not enough replicas, we won't see the desired number of nodes.
- name: Deployment to trigger autoscaling
shell: bash
env:
KUBECONFIG: ${{ inputs.kubeconfig }}
run: |
worker_count=${{ steps.worker_count.outputs.worker_count }}
kubectl create -n default deployment nginx --image=nginx --replicas $(( 110 * (worker_count + 1) + 55 ))
- name: Wait for autoscaling and check result
shell: bash
env:
KUBECONFIG: ${{ inputs.kubeconfig }}
run: |
kubectl wait deployment nginx --for condition=available --timeout=15m
worker_count=$(kubectl get nodes -o json --selector='!node-role.kubernetes.io/control-plane' | jq '.items | length')
if [[ $(( "${{ steps.scaling_limit.outputs.worker_target }}" )) -ne $(( "${worker_count}" )) ]]; then
echo "::error::Expected worker count ${{ steps.scaling_limit.outputs.worker_target }}, but was ${worker_count}"
exit 1
fi
- name: Delete deployment
if: always()
shell: bash
env:
KUBECONFIG: ${{ inputs.kubeconfig }}
run: kubectl delete deployment nginx

View File

@ -1,12 +1,15 @@
name: E2E test
description: "Run Constellation e2e test."
name: E2E meta test
description: "This test does the infrastructure management and runs the e2e test of your choice."
inputs:
workerNodesCount:
description: "Number of worker nodes to spawn."
required: true
required: false
default: "2"
controlNodesCount:
description: "Number of control-plane nodes to spawn."
required: true
required: false
default: "3"
cloudProvider:
description: "Which cloud provider to use."
required: true
@ -36,13 +39,23 @@ inputs:
azureResourceGroup:
description: "The resource group to use"
required: false
sonobuoyTestSuiteCmd:
description: "Which tests should be run? Check README for guidance!"
test:
description: "The test to run. Can currently be one of [sonobuoy full, sonobuoy fast, autoscaling]."
required: true
sonobuoyTestSuiteCmd:
description: "The sonobuoy test suite to run."
required: false
runs:
using: "composite"
steps:
- name: Check input
if: ${{ !contains(fromJson('["sonobuoy full", "sonobuoy fast", "autoscaling"]'), inputs.test) }}
shell: bash
run: |
echo "Invalid input for test field: ${{ inputs.test }}"
exit 1
- name: Determine build target
id: determine-build-target
shell: bash
@ -68,24 +81,25 @@ runs:
- name: Build the bootstrapper
id: build-bootstrapper
uses: ./.github/actions/build_bootstrapper
if: inputs.isDebugImage == 'true' && runner.os != 'macOS'
uses: ./.github/actions/build_bootstrapper
- name: Build cdbg
id: build-cdbg
uses: ./.github/actions/build_cdbg
if: inputs.isDebugImage == 'true'
uses: ./.github/actions/build_cdbg
with:
targetOS: ${{ steps.determine-build-target.outputs.hostOS }}
targetArch: ${{ steps.determine-build-target.outputs.hostArch }}
- name: Login to GCP
if: inputs.cloudProvider == 'gcp'
uses: ./.github/actions/gcp_login
with:
gcp_service_account_json: ${{ inputs.gcp_service_account_json }}
if: inputs.cloudProvider == 'gcp'
- name: Create cluster
id: constellation-create
uses: ./.github/actions/constellation_create
with:
cloudProvider: ${{ inputs.cloudProvider }}
@ -99,7 +113,27 @@ runs:
azureClientSecret: ${{ inputs.azureClientSecret }}
azureResourceGroup: ${{ inputs.azureResourceGroup }}
- name: Run e2e tests
#
# Test payloads
#
- name: Run sonobuoy fast test
if: inputs.test == 'sonobuoy fast'
uses: ./.github/actions/sonobuoy
with:
sonobuoyTestSuiteCmd: ${{ inputs.sonobuoyTestSuiteCmd }}
sonobuoyTestSuiteCmd: "--mode quick"
kubeconfig: ${{ steps.constellation-create.outputs.kubeconfig }}
- name: Run sonobuoy full test
if: inputs.test == 'sonobuoy full'
uses: ./.github/actions/sonobuoy
with:
# TODO: Remove E2E_SKIP once AB#2174 is resolved
sonobuoyTestSuiteCmd: '--plugin e2e --plugin-env e2e.E2E_FOCUS="\[Conformance\]" --plugin-env e2e.E2E_SKIP="for service with type clusterIP|HostPort validates that there is no conflict between pods with same hostPort but different hostIP and protocol" --plugin https://raw.githubusercontent.com/vmware-tanzu/sonobuoy-plugins/master/cis-benchmarks/kube-bench-plugin.yaml --plugin https://raw.githubusercontent.com/vmware-tanzu/sonobuoy-plugins/master/cis-benchmarks/kube-bench-master-plugin.yaml'
kubeconfig: ${{ steps.constellation-create.outputs.kubeconfig }}
- name: Run autoscaling test
if: inputs.test == 'autoscaling'
uses: ./.github/actions/e2e_autoscaling
with:
kubeconfig: ${{ steps.constellation-create.outputs.kubeconfig }}

View File

@ -1,5 +1,6 @@
name: sonobuoy
description: "Executed the e2e test framework sonobuoy."
inputs:
sonobuoyVersion:
description: "Version of sonobuoy test CLI to use."
@ -7,37 +8,48 @@ inputs:
required: true
sonobuoyTestSuiteCmd:
description: "Which tests should be run?"
kubeconfig:
description: "The kubeconfig of the cluster to test."
required: true
runs:
using: "composite"
steps:
- name: Install sonobuoy
shell: bash
run: |
HOSTOS="$(go env GOOS)"
HOSTARCH="$(go env GOARCH)"
curl -sLO https://github.com/vmware-tanzu/sonobuoy/releases/download/v${{ inputs.sonobuoyVersion }}/sonobuoy_${{ inputs.sonobuoyVersion }}_${HOSTOS}_${HOSTARCH}.tar.gz
tar -xzf sonobuoy_${{ inputs.sonobuoyVersion }}_${HOSTOS}_${HOSTARCH}.tar.gz
install sonobuoy /usr/local/bin
shell: bash
- name: Sonobuoy version
run: sonobuoy version
shell: bash
- name: Run quick e2e test
shell: bash
env:
KUBECONFIG: ${{ inputs.kubeconfig }}
run: sonobuoy run --wait=300 ${{ inputs.sonobuoyTestSuiteCmd }} --kubeconfig constellation-admin.conf
shell: bash
- name: Download results
run: sonobuoy retrieve -x --kubeconfig constellation-admin.conf
shell: bash
env:
KUBECONFIG: ${{ inputs.kubeconfig }}
run: sonobuoy retrieve -x --kubeconfig constellation-admin.conf
- name: Upload test results
if: ${{ always() && !env.ACT }}
uses: actions/upload-artifact@83fd05a356d7e2593de66fc9913b3002723633cb # tag=v3.1.1
with:
name: "junit_01.xml"
path: "**/junit_01.xml"
if: ${{ always() && !env.ACT }}
- name: Publish test results
uses: mikepenz/action-junit-report@ab07dd7abefd456d92ecbeb22f81392fafe3d528 # tag=v3.5.2
if: ${{ !env.ACT }}
uses: mikepenz/action-junit-report@ab07dd7abefd456d92ecbeb22f81392fafe3d528 # tag=v3.5.2
with:
report_paths: "**/junit_01.xml"
fail_on_failure: true

View File

@ -50,7 +50,7 @@ jobs:
workerNodesCount: "2"
controlNodesCount: "3"
cloudProvider: "azure"
sonobuoyTestSuiteCmd: '--plugin e2e --plugin-env e2e.E2E_FOCUS="\[Conformance\]" --plugin-env e2e.E2E_SKIP="for service with type clusterIP|HostPort validates that there is no conflict between pods with same hostPort but different hostIP and protocol" --plugin https://raw.githubusercontent.com/vmware-tanzu/sonobuoy-plugins/master/cis-benchmarks/kube-bench-plugin.yaml --plugin https://raw.githubusercontent.com/vmware-tanzu/sonobuoy-plugins/master/cis-benchmarks/kube-bench-master-plugin.yaml'
test: "sonobuoy full"
kubernetesVersion: ${{ matrix.version }}
azureClientSecret: ${{ secrets.AZURE_E2E_CLIENT_SECRET }}
azureResourceGroup: ${{ steps.az_resource_group_gen.outputs.res_group_name }}

View File

@ -47,8 +47,7 @@ jobs:
cloudProvider: "azure"
azureClientSecret: ${{ secrets.AZURE_E2E_CLIENT_SECRET }}
azureResourceGroup: ${{ steps.az_resource_group_gen.outputs.res_group_name }}
# TODO: Remove E2E_SKIP once AB#2174 is resolved
sonobuoyTestSuiteCmd: '--plugin e2e --plugin-env e2e.E2E_FOCUS="\[Conformance\]" --plugin-env e2e.E2E_SKIP="for service with type clusterIP|HostPort validates that there is no conflict between pods with same hostPort but different hostIP and protocol" --plugin https://raw.githubusercontent.com/vmware-tanzu/sonobuoy-plugins/master/cis-benchmarks/kube-bench-plugin.yaml --plugin https://raw.githubusercontent.com/vmware-tanzu/sonobuoy-plugins/master/cis-benchmarks/kube-bench-master-plugin.yaml'
test: "sonobuoy full"
- name: Always terminate cluster
if: always()
@ -119,7 +118,7 @@ jobs:
cloudProvider: "azure"
azureClientSecret: ${{ secrets.AZURE_E2E_CLIENT_SECRET }}
azureResourceGroup: ${{ steps.az_resource_group_gen.outputs.res_group_name }}
sonobuoyTestSuiteCmd: "--mode quick"
test: "sonobuoy quick"
kubernetesVersion: ${{ matrix.version }}
- name: Always terminate cluster

View File

@ -31,7 +31,7 @@ jobs:
cloudProvider: "gcp"
gcp_service_account_json: ${{ secrets.GCP_SERVICE_ACCOUNT }}
gcpClusterServiceAccountKey: ${{ secrets.GCP_CLUSTER_SERVICE_ACCOUNT }}
sonobuoyTestSuiteCmd: '--plugin e2e --plugin-env e2e.E2E_FOCUS="\[Conformance\]" --plugin-env e2e.E2E_SKIP="for service with type clusterIP|HostPort validates that there is no conflict between pods with same hostPort but different hostIP and protocol" --plugin https://raw.githubusercontent.com/vmware-tanzu/sonobuoy-plugins/master/cis-benchmarks/kube-bench-plugin.yaml --plugin https://raw.githubusercontent.com/vmware-tanzu/sonobuoy-plugins/master/cis-benchmarks/kube-bench-master-plugin.yaml'
test: "sonobuoy full"
kubernetesVersion: ${{ matrix.version }}
- name: Always terminate cluster

View File

@ -26,8 +26,7 @@ jobs:
cloudProvider: "gcp"
gcp_service_account_json: ${{ secrets.GCP_SERVICE_ACCOUNT }}
gcpClusterServiceAccountKey: ${{ secrets.GCP_CLUSTER_SERVICE_ACCOUNT }}
# TODO: Remove E2E_SKIP once AB#2174 is resolved
sonobuoyTestSuiteCmd: '--plugin e2e --plugin-env e2e.E2E_FOCUS="\[Conformance\]" --plugin-env e2e.E2E_SKIP="for service with type clusterIP|HostPort validates that there is no conflict between pods with same hostPort but different hostIP and protocol" --plugin https://raw.githubusercontent.com/vmware-tanzu/sonobuoy-plugins/master/cis-benchmarks/kube-bench-plugin.yaml --plugin https://raw.githubusercontent.com/vmware-tanzu/sonobuoy-plugins/master/cis-benchmarks/kube-bench-master-plugin.yaml'
test: "sonobuoy full"
- name: Always terminate cluster
if: always()
@ -74,7 +73,7 @@ jobs:
machineType: "n2d-standard-4"
gcp_service_account_json: ${{ secrets.GCP_SERVICE_ACCOUNT }}
gcpClusterServiceAccountKey: ${{ secrets.GCP_CLUSTER_SERVICE_ACCOUNT }}
sonobuoyTestSuiteCmd: "--mode quick"
test: "sonobuoy quick"
kubernetesVersion: ${{ matrix.version }}
- name: Always terminate cluster

View File

@ -17,11 +17,15 @@ on:
options:
- "gcp"
- "azure"
default: "gcp"
default: "azure"
required: true
sonobuoyTestSuiteCmd:
description: "Which tests should be run? Check README for guidance!"
default: "--mode quick"
test:
description: "The test to run."
type: choice
options:
- "sonobuoy fast"
- "sonobuoy full"
- "autoscaling"
required: true
kubernetesVersion:
description: "Kubernetes version to create the cluster from."
@ -84,7 +88,7 @@ jobs:
steps:
- name: Install the basics
shell: bash
run: brew install coreutils kubectl
run: brew install coreutils kubectl bash
- name: Check out repository
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3.1.0
@ -123,7 +127,7 @@ jobs:
machineType: ${{ github.event.inputs.machineType }}
gcp_service_account_json: ${{ secrets.GCP_SERVICE_ACCOUNT }}
gcpClusterServiceAccountKey: ${{ secrets.GCP_CLUSTER_SERVICE_ACCOUNT }}
sonobuoyTestSuiteCmd: ${{ github.event.inputs.sonobuoyTestSuiteCmd }}
test: ${{ github.event.inputs.test }}
kubernetesVersion: ${{ github.event.inputs.kubernetesVersion }}
azureClientSecret: ${{ secrets.AZURE_E2E_CLIENT_SECRET }}
azureResourceGroup: ${{ steps.az_resource_group_gen.outputs.res_group_name }}

View File

@ -17,11 +17,15 @@ on:
options:
- "gcp"
- "azure"
default: "gcp"
default: "azure"
required: true
sonobuoyTestSuiteCmd:
description: "Which tests should be run? Check README for guidance!"
default: "--mode quick"
test:
description: "The test to run."
type: choice
options:
- "sonobuoy fast"
- "sonobuoy full"
- "autoscaling"
required: true
kubernetesVersion:
description: "Kubernetes version to create the cluster from."
@ -54,6 +58,8 @@ jobs:
steps:
- name: Check out repository
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3.1.0
with:
ref: ${{ github.head_ref }}
- name: Setup Go environment
uses: actions/setup-go@c4a742cab115ed795e34d4513e2cf7d472deb55f # tag=v3.3.1
@ -85,7 +91,7 @@ jobs:
machineType: ${{ github.event.inputs.machineType }}
gcp_service_account_json: ${{ secrets.GCP_SERVICE_ACCOUNT }}
gcpClusterServiceAccountKey: ${{ secrets.GCP_CLUSTER_SERVICE_ACCOUNT }}
sonobuoyTestSuiteCmd: ${{ github.event.inputs.sonobuoyTestSuiteCmd }}
test: ${{ github.event.inputs.test }}
kubernetesVersion: ${{ github.event.inputs.kubernetesVersion }}
azureClientSecret: ${{ secrets.AZURE_E2E_CLIENT_SECRET }}
azureResourceGroup: ${{ steps.az_resource_group_gen.outputs.res_group_name }}