diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4216171434..ffff03cd0d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -222,6 +222,14 @@ jobs: id-token: write # for docker/login to login to NGINX registry secrets: inherit + verify-ipv6: + name: Verify IPv6 Environment + needs: [vars, build-oss, build-plus] + uses: ./.github/workflows/verify-ipv6.yml + with: + image-repository: nginx-gateway-fabric + image-tag: ${{ github.sha }} + functional-tests: name: Functional tests needs: [vars, build-oss, build-plus] diff --git a/.github/workflows/verify-ipv6.yaml b/.github/workflows/verify-ipv6.yaml new file mode 100644 index 0000000000..7aad9c2b80 --- /dev/null +++ b/.github/workflows/verify-ipv6.yaml @@ -0,0 +1,218 @@ +name: Verify IPv6 Functionality + +on: + workflow_call: + inputs: + image-repository: + required: true + type: string + image-tag: + required: true + type: string + +jobs: + verify-ipv6: + name: Verify IPv6 Functionality + runs-on: ubuntu-24.04 + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Setup Golang Environment + uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 + with: + go-version: stable + cache-dependency-path: | + go.sum + + - name: Enable IPv6 on Docker + run: | + # Configure Docker daemon to support IPv6 + echo '{ + "ipv6": true, + "fixed-cidr-v6": "2001:db8:1::/64", + "experimental": true, + "ip6tables": true + }' | sudo tee /etc/docker/daemon.json + + # Restart Docker service + sudo systemctl restart docker + + - name: Create Kind Cluster with IPv6 + uses: helm/kind-action@v1.8.0 + with: + config: | + kind: Cluster + apiVersion: kind.x-k8s.io/v1alpha4 + name: kind-ipv6 + networking: + ipFamily: ipv6 + apiServerAddress: "127.0.0.1" + nodes: + - role: control-plane + + - name: Wait for Cluster to be Ready + run: | + echo "Waiting for cluster to be ready..." + kubectl wait --for=condition=Ready nodes --all --timeout=180s + kubectl get nodes -o wide + kubectl cluster-info + + + - name: Load Images to Kind + run: | + kind load docker-image ${{ join(fromJSON(steps.ngf-meta.outputs.json).tags, ' ') }} ${{ join(fromJSON(steps.nginx-meta.outputs.json).tags, ' ') }} --name ${{ github.run_id }} + + - name: Install NGF via Helm + run: | + # Install CRDs + kubectl kustomize config/crd | kubectl apply --server-side -f - + + # Install NGF + + + - name: Wait for NGF to be Ready + run: | + kubectl wait --for=condition=Ready pod -l app.kubernetes.io/component=controller -n nginx-gateway --timeout=120s + kubectl wait --for=condition=Ready pod -l app.kubernetes.io/component=nginx -n nginx-gateway --timeout=120s + kubectl get pods -n nginx-gateway -o wide + + - name: Deploy Test Application + run: | + # Create a simple test application + cat <> $GITHUB_ENV + + # Get IPv6 address of the worker node + NODE_IPV6=$(kubectl get nodes -l kubernetes.io/hostname!=kind-ipv6-control-plane -o jsonpath='{.items[0].status.addresses[?(@.type=="InternalIP")].address}' | head -1) + echo "NODE_IPV6=$NODE_IPV6" >> $GITHUB_ENV + + echo "NGF is accessible at [$NODE_IPV6]:$NODE_PORT" + + - name: Verify Connectivity with Curl + run: | + # Install curl with IPv6 support if needed + sudo apt-get update + sudo apt-get install -y curl iputils-ping + + # Test ping first to verify basic connectivity + ping6 -c 4 ${{ env.NODE_IPV6 }} + + # Test HTTP connection using curl with IPv6 + echo "Testing connection to echo-server via NGF..." + curl -v --retry 5 --retry-delay 2 -H "Host: echo-server" http://[${{ env.NODE_IPV6 }}]:${{ env.NODE_PORT }}/ + + # Verify response + RESPONSE=$(curl -s -H "Host: echo-server" http://[${{ env.NODE_IPV6 }}]:${{ env.NODE_PORT }}/) + if [[ "$RESPONSE" == *"echo-server"* ]]; then + echo "✅ Successfully verified IPv6 connectivity to the application through NGF!" + else + echo "❌ Failed to get correct response from application" + exit 1 + fi + + - name: Cleanup Resources + if: always() + run: | + echo "Cleaning up resources..." + # Delete Gateway and HTTPRoute + kubectl delete httproute echo-route --ignore-not-found + kubectl delete gateway gateway --ignore-not-found + + # Delete Application + kubectl delete service echo-server --ignore-not-found + kubectl delete deployment echo-server --ignore-not-found + + # Uninstall NGF + helm uninstall ngf + + echo "All resources cleaned up" + + - name: Collect Logs on Failure + if: failure() + run: | + echo "Collecting logs for troubleshooting..." + kubectl get pods -A + kubectl logs -l app.kubernetes.io/component=controller -n nginx-gateway --tail=100 || true + kubectl logs -l app.kubernetes.io/component=nginx -n nginx-gateway --tail=100 || true + kubectl describe gateway gateway || true + kubectl describe httproute echo-route || true + kubectl describe service -n nginx-gateway || true + kubectl describe nodes \ No newline at end of file diff --git a/config/cluster/kind-cluster.yaml b/config/cluster/kind-cluster.yaml index d61c10ca6f..df3161737a 100644 --- a/config/cluster/kind-cluster.yaml +++ b/config/cluster/kind-cluster.yaml @@ -1,7 +1,8 @@ kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 -nodes: -- role: control-plane +name: kind-ipv6 networking: - ipFamily: dual - apiServerAddress: 127.0.0.1 + ipFamily: ipv6 + apiServerAddress: "127.0.0.1" +nodes: + - role: control-plane