From 72bc4243be912c9703f11ab52448793836015727 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Va=C5=A1ek?= Date: Thu, 7 May 2026 16:17:25 +0200 Subject: [PATCH 1/9] test: IPv6 only cluster MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Matej Vašek --- hack/cluster.sh | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/hack/cluster.sh b/hack/cluster.sh index 296ab0f4c5..09758a7ef2 100755 --- a/hack/cluster.sh +++ b/hack/cluster.sh @@ -108,19 +108,23 @@ kubernetes() { cat < Date: Thu, 7 May 2026 20:29:29 +0200 Subject: [PATCH 2/9] fix: countour components listen on :: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Matej Vašek --- hack/cluster.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hack/cluster.sh b/hack/cluster.sh index 09758a7ef2..658a89ead1 100755 --- a/hack/cluster.sh +++ b/hack/cluster.sh @@ -252,8 +252,9 @@ networking() { echo "Installing a configured Contour." curl -sSL "https://github.com/knative/net-contour/releases/download/knative-${contour_version}/contour.yaml" \ + | $YQ '(select(.kind == "Deployment" and .metadata.name == "contour").spec.template.spec.containers[0].args[] | select(. == "--xds-address=0.0.0.0")) = "--xds-address=::"' \ | $YQ '(select(.kind == "Deployment" and .metadata.name == "contour").spec.template.spec.containers[0].args) - += ["--envoy-service-http-address=::", "--envoy-service-https-address=::"]' \ + += ["--envoy-service-http-address=::", "--envoy-service-https-address=::", "--stats-address=::"]' \ | $KUBECTL apply -f - sleep 5 From e1c1f5b65a7be81a0f22ee8cbcabd3c73abc3c71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Va=C5=A1ek?= Date: Thu, 7 May 2026 20:31:12 +0200 Subject: [PATCH 3/9] fix: workaroud for bug in autoscaler on IPv6-only clusters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Matej Vašek --- hack/cluster.sh | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/hack/cluster.sh b/hack/cluster.sh index 658a89ead1..6439571d8f 100755 --- a/hack/cluster.sh +++ b/hack/cluster.sh @@ -162,7 +162,17 @@ serving() { curl -L -s https://github.com/knative/serving/releases/download/knative-$knative_serving_version/serving-core.yaml | $KUBECTL apply -f - sleep 2 - $KUBECTL wait pod --for=condition=Ready -l '!job-name' -n knative-serving --timeout=5m + # Exclude autoscaler: it crash-loops on IPv6-only clusters due to upstream + # Knative bug (EndpointSlice rejects IPv6 addresses as "must be an IPv4 address"). + $KUBECTL wait pod --for=condition=Ready -l '!job-name,app!=autoscaler' -n knative-serving --timeout=5m + + # Disable scale-to-zero: the autoscaler crash-loops on IPv6-only clusters + # (upstream Knative bug: EndpointSlice hardcodes AddressType IPv4). + # Disabling scale-to-zero avoids depending on the broken autoscaler. + $KUBECTL patch configmap/config-autoscaler \ + --namespace knative-serving \ + --type merge \ + --patch '{"data":{"enable-scale-to-zero":"false"}}' $KUBECTL get pod -A echo "${green}✅ Knative Serving${reset}" @@ -278,7 +288,9 @@ networking() { kubectl patch -n contour-external svc/envoy --type merge --patch '{"spec":{"ipFamilyPolicy":"PreferDualStack"}}' $KUBECTL wait pod --for=condition=Ready -l '!job-name' -n contour-external --timeout=10m - $KUBECTL wait pod --for=condition=Ready -l '!job-name' -n knative-serving --timeout=10m + # Exclude autoscaler: it crash-loops on IPv6-only clusters due to upstream + # Knative bug (EndpointSlice rejects IPv6 addresses as "must be an IPv4 address"). + $KUBECTL wait pod --for=condition=Ready -l '!job-name,app!=autoscaler' -n knative-serving --timeout=10m echo "${green}✅ Ingress${reset}" } From a0619ea9b537e1bcdfd451c6453429ff46dc4748 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Va=C5=A1ek?= Date: Fri, 8 May 2026 00:20:59 +0200 Subject: [PATCH 4/9] fix: use fixed scaler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Matej Vašek --- hack/cluster.sh | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/hack/cluster.sh b/hack/cluster.sh index 6439571d8f..76f919772a 100755 --- a/hack/cluster.sh +++ b/hack/cluster.sh @@ -161,18 +161,14 @@ serving() { curl -L -s https://github.com/knative/serving/releases/download/knative-$knative_serving_version/serving-core.yaml | $KUBECTL apply -f - + # Patch autoscaler image: upstream Knative bug hardcodes EndpointSlice + # AddressType to IPv4, crashing the autoscaler on IPv6-only clusters. + # This patched image detects the IP family from POD_IP. + $KUBECTL set image deployment/autoscaler -n knative-serving \ + autoscaler="quay.io/mvasek/knative/autoscaler@sha256:6a2f328833e9ed516dd281aba891923082ddaa69e5907f0f0cef6d2402732e4c" + sleep 2 - # Exclude autoscaler: it crash-loops on IPv6-only clusters due to upstream - # Knative bug (EndpointSlice rejects IPv6 addresses as "must be an IPv4 address"). - $KUBECTL wait pod --for=condition=Ready -l '!job-name,app!=autoscaler' -n knative-serving --timeout=5m - - # Disable scale-to-zero: the autoscaler crash-loops on IPv6-only clusters - # (upstream Knative bug: EndpointSlice hardcodes AddressType IPv4). - # Disabling scale-to-zero avoids depending on the broken autoscaler. - $KUBECTL patch configmap/config-autoscaler \ - --namespace knative-serving \ - --type merge \ - --patch '{"data":{"enable-scale-to-zero":"false"}}' + $KUBECTL wait pod --for=condition=Ready -l '!job-name' -n knative-serving --timeout=5m $KUBECTL get pod -A echo "${green}✅ Knative Serving${reset}" @@ -288,9 +284,7 @@ networking() { kubectl patch -n contour-external svc/envoy --type merge --patch '{"spec":{"ipFamilyPolicy":"PreferDualStack"}}' $KUBECTL wait pod --for=condition=Ready -l '!job-name' -n contour-external --timeout=10m - # Exclude autoscaler: it crash-loops on IPv6-only clusters due to upstream - # Knative bug (EndpointSlice rejects IPv6 addresses as "must be an IPv4 address"). - $KUBECTL wait pod --for=condition=Ready -l '!job-name,app!=autoscaler' -n knative-serving --timeout=10m + $KUBECTL wait pod --for=condition=Ready -l '!job-name' -n knative-serving --timeout=10m echo "${green}✅ Ingress${reset}" } From 9222768aab3261323d5f034000f3ae8ed5c327b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Va=C5=A1ek?= Date: Fri, 8 May 2026 00:20:32 +0200 Subject: [PATCH 5/9] test: disable coverage upload MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Matej Vašek --- .github/workflows/functions.yaml | 49 -------------------------------- 1 file changed, 49 deletions(-) diff --git a/.github/workflows/functions.yaml b/.github/workflows/functions.yaml index 7d809102e8..6dcb410b0a 100644 --- a/.github/workflows/functions.yaml +++ b/.github/workflows/functions.yaml @@ -77,14 +77,6 @@ jobs: - name: Run Unit Tests run: make test - - uses: codecov/codecov-action@v5 - with: - files: ./coverage.txt - flags: unit ${{ matrix.os }} - fail_ci_if_error: true - verbose: true - token: ${{ secrets.CODECOV_TOKEN }} - # -------------- # TEMPLATE TESTS # -------------- @@ -175,14 +167,6 @@ jobs: - name: Run Integration Tests run: make test-integration - - uses: codecov/codecov-action@v5 - with: - files: ./coverage.txt - flags: integration - fail_ci_if_error: true - verbose: true - token: ${{ secrets.CODECOV_TOKEN }} - # Preserve Cluster Logs - name: Dump Cluster Logs if: always() @@ -231,14 +215,6 @@ jobs: - name: Run Basic E2E Tests (core, metadata, remote) run: make test-e2e - - uses: codecov/codecov-action@v5 - with: - files: ./coverage.txt - flags: e2e - fail_ci_if_error: true - verbose: true - token: ${{ secrets.CODECOV_TOKEN }} - # Preserve Cluster Logs - name: Dump Cluster Logs if: always() @@ -294,14 +270,6 @@ jobs: - name: Run E2E Podman Tests run: make test-e2e-podman - - uses: codecov/codecov-action@v5 - with: - files: ./coverage.txt - flags: e2e - fail_ci_if_error: true - verbose: true - token: ${{ secrets.CODECOV_TOKEN }} - # Preserve Cluster Logs - name: Dump Cluster Logs if: always() @@ -383,15 +351,6 @@ jobs: - name: Run Test - ${{ matrix.runtime }} run: make test-e2e-matrix - # Coverage and Logs - - uses: codecov/codecov-action@v5 - with: - files: ./coverage.txt - flags: e2e ${{ matrix.runtime }} - fail_ci_if_error: true - verbose: true - token: ${{ secrets.CODECOV_TOKEN }} - # Preserve Cluster Logs - name: Dump Cluster Logs if: always() @@ -439,14 +398,6 @@ jobs: - name: Run Config CI E2E Tests run: make test-e2e-config-ci - - uses: codecov/codecov-action@v5 - with: - files: ./coverage.txt - flags: e2e-config-ci - fail_ci_if_error: true - verbose: true - token: ${{ secrets.CODECOV_TOKEN }} - # Preserve Cluster Logs - name: Dump Cluster Logs if: always() From d6c2277aa10ff0eed7b8e27f099490cb0685fbfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Va=C5=A1ek?= Date: Sun, 10 May 2026 17:56:37 +0200 Subject: [PATCH 6/9] gh fake ipv6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Matej Vašek --- .github/workflows/functions.yaml | 10 ++ .github/workflows/test-podman-next.yaml | 2 + hack/cluster.sh | 9 ++ hack/configure-nat64.sh | 165 ++++++++++++++++++++++++ 4 files changed, 186 insertions(+) create mode 100755 hack/configure-nat64.sh diff --git a/.github/workflows/functions.yaml b/.github/workflows/functions.yaml index 6dcb410b0a..9531b0c81d 100644 --- a/.github/workflows/functions.yaml +++ b/.github/workflows/functions.yaml @@ -153,6 +153,8 @@ jobs: - name: Install Binaries run: ./hack/binaries.sh + - name: Configure IPv6 + run: ./hack/configure-nat64.sh - name: Allocate Cluster run: ./hack/cluster.sh - name: Start Local Registry @@ -205,6 +207,8 @@ jobs: - name: Install Binaries run: ./hack/binaries.sh + - name: Configure IPv6 + run: ./hack/configure-nat64.sh - name: Allocate Cluster run: ./hack/cluster.sh - name: Start Local Registry @@ -262,6 +266,8 @@ jobs: - name: Install Binaries run: ./hack/binaries.sh + - name: Configure IPv6 + run: ./hack/configure-nat64.sh - name: Allocate Cluster run: ./hack/cluster.sh - name: Start Local Registry @@ -341,6 +347,8 @@ jobs: # Allocate Cluster - name: Install Binaries run: ./hack/binaries.sh + - name: Configure IPv6 + run: ./hack/configure-nat64.sh - name: Allocate Cluster run: ./hack/cluster.sh - name: Start Local Registry @@ -388,6 +396,8 @@ jobs: - name: Install Binaries run: ./hack/binaries.sh + - name: Configure IPv6 + run: ./hack/configure-nat64.sh - name: Allocate Cluster run: ./hack/cluster.sh - name: Start Local Registry diff --git a/.github/workflows/test-podman-next.yaml b/.github/workflows/test-podman-next.yaml index 38a77aeb2d..7f19ed9a97 100644 --- a/.github/workflows/test-podman-next.yaml +++ b/.github/workflows/test-podman-next.yaml @@ -35,6 +35,8 @@ jobs: - uses: knative/actions/setup-go@main - name: Install Binaries run: ./hack/binaries.sh + - name: Configure IPv6 + run: ./hack/configure-nat64.sh - name: Allocate Cluster run: ./hack/cluster.sh - name: Local Registry diff --git a/hack/cluster.sh b/hack/cluster.sh index 76f919772a..cdc0207f34 100755 --- a/hack/cluster.sh +++ b/hack/cluster.sh @@ -119,12 +119,21 @@ nodes: - containerPort: 80 hostPort: 80 listenAddress: "::1" + - containerPort: 80 + hostPort: 80 + listenAddress: "127.0.0.1" - containerPort: 443 hostPort: 443 listenAddress: "::1" + - containerPort: 443 + hostPort: 443 + listenAddress: "127.0.0.1" - containerPort: 30022 hostPort: 30022 listenAddress: "::1" + - containerPort: 30022 + hostPort: 30022 + listenAddress: "127.0.0.1" containerdConfigPatches: - |- [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:50000"] diff --git a/hack/configure-nat64.sh b/hack/configure-nat64.sh new file mode 100755 index 0000000000..d384bf5093 --- /dev/null +++ b/hack/configure-nat64.sh @@ -0,0 +1,165 @@ +#!/usr/bin/env bash + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# +# Configure DNS64 (Unbound) + NAT64 (TAYGA) on a GitHub Actions runner +# to provide fake IPv6 internet connectivity. This must run before cluster.sh. +# +# Network flow after setup: +# DNS query -> Unbound (dns64-synthall) -> AAAA 64:ff9b:: +# IPv6 packet to 64:ff9b::/96 -> TAYGA -> IPv4 -> internet +# + +set -o errexit +set -o nounset +set -o pipefail + +source "$(cd "$(dirname "$0")" && pwd)/common.sh" + +readonly NAT64_PREFIX="64:ff9b::/96" +readonly TAYGA_IPV4="192.168.255.1" +readonly TAYGA_POOL="192.168.255.0/24" +readonly TAYGA_DEV="nat64" + +main() { + echo "${blue}Configuring DNS64 + NAT64${reset}" + + local upstream_dns + upstream_dns="$(get_upstream_dns)" + echo "Upstream DNS: ${upstream_dns}" + + install_packages + configure_dns64 "${upstream_dns}" + configure_nat64 + verify + + echo "${green}✅ DNS64 + NAT64${reset}" +} + +get_upstream_dns() { + local dns="" + if [[ -f /run/systemd/resolve/resolv.conf ]]; then + dns="$(awk '/^nameserver/ { print $2; exit }' /run/systemd/resolve/resolv.conf)" + fi + if [[ -z "${dns}" ]]; then + dns="8.8.8.8" + fi + echo "${dns}" +} + +install_packages() { + echo "${blue}Installing unbound and tayga${reset}" + sudo apt-get update -qq + sudo apt-get install -y -qq unbound tayga +} + +configure_dns64() { + local upstream_dns="$1" + + echo "${blue}Configuring Unbound (DNS64)${reset}" + + # Stop systemd-resolved so we can take over port 53 + sudo systemctl stop systemd-resolved || true + sudo systemctl disable systemd-resolved || true + + # Point the system resolver at our local Unbound + sudo tee /etc/resolv.conf > /dev/null < /dev/null < /dev/null < ${aaaa}" + + # Verify NAT64 connectivity + if ! curl -6 --max-time 10 -sSf -o /dev/null https://github.com; then + echo "${red}NAT64 verification failed: cannot reach github.com over IPv6${reset}" + exit 1 + fi + echo "NAT64 OK: curl -6 github.com succeeded" +} + +main "$@" From 240744ad1b659bd2298b9d0ce8e4f538ed22c9dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Va=C5=A1ek?= Date: Sun, 10 May 2026 14:08:10 +0200 Subject: [PATCH 7/9] use my dapr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Matej Vašek --- hack/cluster.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/hack/cluster.sh b/hack/cluster.sh index cdc0207f34..9b769a44be 100755 --- a/hack/cluster.sh +++ b/hack/cluster.sh @@ -441,6 +441,7 @@ dapr_runtime() { if [ "${GITHUB_ACTIONS:-false}" = "true" ]; then dapr_flags="--image-registry=ghcr.io/dapr --log-as-json" fi + dapr_flags="--image-registry=quay.io/mvasek/dapr --log-as-json" # Install Dapr Runtime # shellcheck disable=SC2086 From 93f9a5e86dcf02b8b6c91c7e37484c99863c0786 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Va=C5=A1ek?= Date: Sun, 10 May 2026 17:59:17 +0200 Subject: [PATCH 8/9] update dapr CLI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Matej Vašek --- hack/binaries.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/binaries.sh b/hack/binaries.sh index 1b1b313c23..69d558390b 100755 --- a/hack/binaries.sh +++ b/hack/binaries.sh @@ -28,7 +28,7 @@ install_binaries() { local kubectl_version=1.33.1 local kind_version=0.31.0 - local dapr_version=1.16.0 + local dapr_version=1.17.1 local helm_version=3.18.0 local stern_version=1.32.0 local kn_version=1.18.0 From 763f19ea102e09ce7770afce94d4c73cbe12e4ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Va=C5=A1ek?= Date: Sun, 10 May 2026 18:03:26 +0200 Subject: [PATCH 9/9] fixup tayga MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Matej Vašek --- hack/configure-nat64.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hack/configure-nat64.sh b/hack/configure-nat64.sh index d384bf5093..d34b8a69e2 100755 --- a/hack/configure-nat64.sh +++ b/hack/configure-nat64.sh @@ -29,6 +29,7 @@ source "$(cd "$(dirname "$0")" && pwd)/common.sh" readonly NAT64_PREFIX="64:ff9b::/96" readonly TAYGA_IPV4="192.168.255.1" +readonly TAYGA_IPV6="fd00:64:64::1" readonly TAYGA_POOL="192.168.255.0/24" readonly TAYGA_DEV="nat64" @@ -110,10 +111,13 @@ configure_nat64() { echo "${blue}Configuring TAYGA (NAT64)${reset}" # Write TAYGA config + # ipv6-addr is required when using the well-known prefix 64:ff9b::/96 + # with a non-global (RFC 1918) ipv4-addr. sudo tee /etc/tayga.conf > /dev/null <