jenkinsci / google-compute-engine-plugin

https://plugins.jenkins.io/google-compute-engine/
Apache License 2.0
57 stars 88 forks source link

Dual-stack support (IPv6 mode) #434

Closed Artmorse closed 10 months ago

Artmorse commented 10 months ago

This PR wants to add the configuration to set up dual-stack compute engine instance with an external IPv6 address.

I made manual testing with a GCP project.

Manual testing

Set up

I created a test environment on GCP.

More info :arrow_down:

I created a GSA (google service account) with the good roles (more details [here](https://github.com/jenkinsci/google-compute-engine-plugin/blob/develop/docs/Home.md#iam-credentials)) then I generated a private key to use this GSA in the plugin. ```bash export PROJECT_ID="MY_GCP_PROJECT_ID" export REGION="MY_REGION" export ZONE="MY_ZONE" gcloud auth login gcloud config set project ${PROJECT_ID} export SA_NAME="my-sa-name" export SA_DESC="my-sa-desc" # https://cloud.google.com/iam/docs/service-accounts-create#iam-service-accounts-create-gcloud gcloud iam service-accounts create ${SA_NAME} \ --description="${SA_DESC}" \ --display-name="${SA_NAME}" # https://cloud.google.com/compute/docs/access/iam gcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member="serviceAccount:${SA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com" \ --role="roles/compute.instanceAdmin" gcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member="serviceAccount:${SA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com" \ --role="roles/compute.networkAdmin" gcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member="serviceAccount:${SA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com" \ --role="iam/compute.serviceAccountUser" # check GSA roles gcloud projects get-iam-policy ${PROJECT_ID} \ --flatten="bindings[].members" \ --format='table(bindings.role)' \ --filter="bindings.members:${SA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com" # https://cloud.google.com/iam/docs/keys-create-delete export KEY_FILE="${SA_NAME}-private-key.json" gcloud iam service-accounts keys create "${KEY_FILE}" \ --iam-account="${SA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com" ``` I also created a network and a subnetwork with dual-stack mode. ```bash # create network export NETWORK_NAME="my-network" gcloud compute networks create ${NETWORK_NAME} --project=${PROJECT_ID} --subnet-mode=custom --mtu=1460 --bgp-routing-mode=regional gcloud compute networks list # this one don't seem to be required export FIREWALL_ALLOW_ALL_NAME="my-firewall-allow-all-custom" gcloud compute firewall-rules create ${FIREWALL_ALLOW_ALL_NAME} --project=${PROJECT_ID} --network=projects/${PROJECT_ID}/global/networks/${NETWORK_NAME} --description="Allows connection from any source to any instance on the network using custom protocols." --direction=INGRESS --priority=65534 --source-ranges=10.0.0.0/24 --action=ALLOW --rules=all # this one is a single-stack subnetwork, not required for our tests export SINGLE_STACK_SUBNETWORK_NAME="my-single-stack-subnetwork" gcloud compute networks subnets create ${SINGLE_STACK_SUBNETWORK_NAME} --project=${PROJECT_ID} --range=10.0.0.0/16 --stack-type=IPV4_ONLY --region=${REGION} --network=${NETWORK_NAME} # this one is a dual-stack subnetwork export DUAL_STACK_SUBNETWORK_NAME="my-dual-stack-bis-subnetwork" gcloud compute networks subnets create ${DUAL_STACK_SUBNETWORK_NAME} --project=${PROJECT_ID} --range=10.2.0.0/16 --stack-type=IPV4_IPV6 --ipv6-access-type=EXTERNAL --network=${NETWORK_NAME} --region=${REGION} ``` In the plugin, I created a Cloud configuration from the GSA private JSON key. In the _Machine Configuration_ I used an `e2-standard-4` machine type with the networks I created then I played with the new options I added: ![image](https://github.com/jenkinsci/google-compute-engine-plugin/assets/24521660/affa2fe1-d46c-43a5-8ba0-bba06686f473)

Testing

You'll find the tests I did below with the subnetwork configured in dual-mode (IPV4_IPV6).

plugin configuration GCP configuration telnet ADDRESS 22 plugin SSH connection
IPV4_only with IPV4 external address OK :green_circle: IPv4: OK :green_circle: OK :green_circle: (IPv4 address used)
IPV4_IPV6 with IPv4 external address NOK but it's normal :green_circle: (IPv6 address is mandatory on network interface dual-stack mode) IPv4: OK :green_circle: / IPv6: NOK :orange_circle: (Network Unreachable) NOK :orange_circle: (IPv6 has the priority on IPv4 and is unreachable)
IPV4_IPV6 with both IPv4 and IPv6 external addresses OK :green_circle: IPv4: OK :green_circle: / IPv6: NOK :orange_circle: (Network Unreachable) NOK :orange_circle: (IPv6 has the priority on IPv4 and is unreachable)
IPV4_IPV6 with IPv6 external address OK :green_circle: (IPv4 is not mandatory on network interface dual-stack mode compared to IPv6) IPv6: NOK :orange_circle: (Network Unreachable) NOK :orange_circle: (IPv6 is unreachable)
IPV4_IPv6 without any external addresses NOK but it's normal :green_circle: (IPv6 address is mandatory on network interface dual-stack mode) IPv6: NOK :orange_circle: (Network Unreachable) NOK :orange_circle: (IPv6 is unreachable)

:information_source: The :orange_circle: are only related to my local network configuration. I can't access IPv6 for now but I'm currently trying to configure it (my ISP needs to provide IPv6 address and I need to configure my local router to use DHCPv6). Other than that, the GCP configuration works well. :tada:

Testing done

### Submitter checklist
- [x] Make sure you are opening from a **topic/feature/bugfix branch** (right side) and not your main branch!
- [x] Ensure that the pull request title represents the desired changelog entry
- [x] Please describe what you did
- [ ] Link to relevant issues in GitHub or Jira
- [x] Link to relevant pull requests, esp. upstream and downstream changes
- [ ] Ensure you have provided tests - that demonstrates feature works or fixes the issue