Skip to content

Instantly share code, notes, and snippets.

@earthquakesan
Last active November 25, 2025 00:01
Show Gist options
  • Select an option

  • Save earthquakesan/77ccb43adb576c117d9a4aae7b674d13 to your computer and use it in GitHub Desktop.

Select an option

Save earthquakesan/77ccb43adb576c117d9a4aae7b674d13 to your computer and use it in GitHub Desktop.
gke-l7-cross-regional-internal-managed-mc gateway class in GKE with TLS termination (gcloud cli example)
# Cluster creation
export GKE_PROJECT="ADDME"
export GKE_PROJECT_NUMBER="ADDME"
export NETWORK="projects/${GKE_PROJECT}/global/networks/default"
export US_CENTRAL_SUBNET="projects/${GKE_PROJECT}/regions/${CLUSTER_REGION}/subnetworks/default"
export CLUSTER_REGION="us-central1"
export CLUSTER_NAME="cluster-1"
gcloud config set project ${GKE_PROJECT}
gcloud beta container \
clusters create-auto "${CLUSTER_NAME}" \
--region "${CLUSTER_REGION}" \
--release-channel "regular" \
--tier "standard" \
--enable-ip-access \
--no-enable-google-cloud-access \
--network ${NETWORK} \
--subnetwork ${US_CENTRAL_SUBNET} \
--cluster-ipv4-cidr "/17" \
--binauthz-evaluation-mode=DISABLED \
--fleet-project=${GKE_PROJECT}
gcloud services enable \
trafficdirector.googleapis.com \
multiclusterservicediscovery.googleapis.com \
multiclusteringress.googleapis.com \
--project=${GKE_PROJECT}
gcloud container fleet multi-cluster-services enable \
--project ${GKE_PROJECT}
gcloud projects add-iam-policy-binding ${GKE_PROJECT} \
--member "serviceAccount:${GKE_PROJECT}.svc.id.goog[gke-mcs/gke-mcs-importer]" \
--role "roles/compute.networkViewer" \
--project=${GKE_PROJECT}
gcloud container fleet multi-cluster-services describe --project=${GKE_PROJECT}
gcloud container fleet ingress enable \
--config-membership=projects/${GKE_PROJECT}/locations/${CLUSTER_REGION}/memberships/${CLUSTER_NAME} \
--project=${GKE_PROJECT}
gcloud projects add-iam-policy-binding ${GKE_PROJECT} \
--member "serviceAccount:service-${GKE_PROJECT_NUMBER}@gcp-sa-multiclusteringress.iam.gserviceaccount.com" \
--role "roles/container.admin" \
--project=${GKE_PROJECT}
gcloud container fleet ingress describe --project=${GKE_PROJECT}
gcloud container clusters get-credentials --region=${CLUSTER_REGION} ${CLUSTER_NAME}
kubectl get gatewayclasses
export CERT_NAME=store-example-com-cert
export MAP_NAME=store-example-com-map
export PRIVATE_KEY_FILE=store-example-com-key
openssl genrsa -out ${PRIVATE_KEY_FILE} 2048
cat <<'EOF' > cert.config
[req]
default_bits = 2048
req_extensions = extension_requirements
distinguished_name = dn_requirements
prompt = no
[extension_requirements]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @sans_list
[dn_requirements]
countryName = DE
stateOrProvinceName = Brandenburg
localityName = Berlin
0.organizationName = Organization
organizationalUnitName = Cloud
commonName = store.example.com
emailAddress = admin@example.com
[sans_list]
DNS.1 = store.example.com
DNS.2 = store.internal.localhost
EOF
openssl req -new -key ${PRIVATE_KEY_FILE} \
-out csr \
-config cert.config
openssl x509 -req \
-signkey ${PRIVATE_KEY_FILE} \
-in csr \
-out ${CERT_NAME} \
-extfile cert.config \
-extensions extension_requirements \
-days 90
openssl x509 -in ${CERT_NAME} -text -noout
gcloud certificate-manager certificates create ${CERT_NAME} \
--scope=ALL_REGIONS \
--certificate-file="${CERT_NAME}" \
--private-key-file="${PRIVATE_KEY_FILE}"
gcloud certificate-manager maps create ${MAP_NAME}
gcloud certificate-manager maps entries create ${MAP_NAME}-entry \
--map=${MAP_NAME} \
--hostname=store.example.com \
--certificates=${CERT_NAME}
gcloud compute addresses create my-static-internal-ip \
--project=${GKE_PROJECT} \
--region=${CLUSTER_REGION} \
--subnet=${US_CENTRAL_SUBNET} \
--purpose=SHARED_LOADBALANCER_VIP
gcloud compute networks subnets create proxy-only-subnet \
--purpose=GLOBAL_MANAGED_PROXY \
--role=ACTIVE \
--region=${CLUSTER_REGION} \
--network=${NETWORK} \
--range=10.1.2.0/24 \
--project=${GKE_PROJECT}
# TLS Termination using cert manager cert directly (works!)
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Namespace
metadata:
name: internal-gw
---
kind: Gateway
apiVersion: gateway.networking.k8s.io/v1
metadata:
name: internal-https-mc-gateway
namespace: internal-gw
spec:
gatewayClassName: gke-l7-cross-regional-internal-managed-mc
addresses:
- type: networking.gke.io/named-address-with-region
value: "regions/${CLUSTER_REGION}/addresses/my-static-internal-ip"
listeners:
- name: http
protocol: HTTP
port: 80
allowedRoutes:
kinds:
- kind: HTTPRoute
- name: https
protocol: HTTPS
port: 443
tls:
mode: Terminate
options:
networking.gke.io/cert-manager-certs: ${CERT_NAME}
allowedRoutes:
kinds:
- kind: HTTPRoute
EOF
kubectl -n internal-gw describe gateaway internal-https-mc-gateway
NAME CLASS ADDRESS PROGRAMMED AGE
internal-https-mc-gateway gke-l7-cross-regional-internal-managed-mc 10.128.0.8 True 16h
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment