Kubernetes Gateway API and securing it with a custom domain and a free, auto-renewing Google-managed SSL certificate.
Architecture Overview
The final architecture will use the GKE Gateway Controller to manage an external load balancer.
The load balancer will use a Certificate Map to handle SSL/TLS for a custom domain,
routing traffic to the appropriate backend services based on rules defined in an HTTPRoute.
Prerequisites
A GKE Cluster: You must have a GKE cluster with the Gateway API enabled.
A GKE Cluster: You must have a GKE cluster with the Gateway API enabled.
You can use a sample Terraform project to create a private GKE cluster.
A Registered Domain Name: You must own or control the domain you wish to use (e.g., global-ub-abc-dev.com).
Backend Kubernetes Service: You need at least one Kubernetes Service (e.g., store-german) running in your cluster that you want to expose.
Configuring a Cloud DNS Zone Using gcloud
1. Enable the Cloud DNS API
gcloud services enable dns.googleapis.com
2. Create a Public DNS Zone
export CLOUD_DNS_ZONE_NAME="global-ub-abc-dev-com"
export DOMAIN_NAME="global-ub-abc-dev.com"
export PROJECT_ID="abc-project-386112"
gcloud dns managed-zones create "$CLOUD_DNS_ZONE_NAME" \
--dns-name="${DOMAIN_NAME}." \
--description="DNS zone for ${DOMAIN_NAME}" \
--visibility="public" \
--project="$PROJECT_ID"
3. Get Nameservers to Update Domain Registrar
gcloud dns managed-zones describe "$CLOUD_DNS_ZONE_NAME" --project="$PROJECT_ID" \
--format="value(nameServers)"
Update your domain registrar (e.g., GoDaddy, Namecheap) with the returned nameservers.
4. Add DNS Records (CNAME or A)
gcloud dns record-sets transaction start --zone="$CLOUD_DNS_ZONE_NAME" --project="$PROJECT_ID"
# Example: CNAME for certificate verification
gcloud dns record-sets transaction add "CNAME_VALUE" \
--name="_acme-challenge.${DOMAIN_NAME}." \
--ttl="300" \
--type="CNAME" \
--zone="$CLOUD_DNS_ZONE_NAME" \
--project="$PROJECT_ID"
# Example: A record for load balancer
gcloud dns record-sets transaction add "34.149.207.45" \
--name="${DOMAIN_NAME}." \
--ttl="300" \
--type="A" \
--zone="$CLOUD_DNS_ZONE_NAME" \
--project="$PROJECT_ID"
gcloud dns record-sets transaction execute --zone="$CLOUD_DNS_ZONE_NAME" --project="$PROJECT_ID"
Step 1: Set Up Environment Variables
# Core Project Configuration
export PROJECT_ID="abc-project-386112"
export REGION="europe-north1"
# Domain and DNS Configuration
export DOMAIN_NAME="global-ub-abc-dev.com"
export CLOUD_DNS_ZONE_NAME="global-ub-abc-dev-com"
# Resource Names
export CERTIFICATE_MAP_NAME="cert-map-global-ub-abc-dev-com"
export CERTIFICATE_NAME="cert-global-ub-abc-dev-com"
export DOMAIN_AUTHORIZATION_NAME="dns-auth-global-ub-abc-dev"
export CERTIFICATE_MAP_ENTRY_NAME="cert-map-entry-global-ub-abc-dev"
Step 2: Create Certificate Manager Resources
Create DNS Authorization
gcloud certificate-manager dns-authorizations create $DOMAIN_AUTHORIZATION_NAME \
--domain="$DOMAIN_NAME" \
--project $PROJECT_ID
Get CNAME Record for Verification
export CNAME_DATA=$(gcloud certificate-manager dns-authorizations describe $DOMAIN_AUTHORIZATION_NAME --project $PROJECT_ID --format="value(dnsResourceRecord.data)")
echo "CNAME data to add to DNS: ${CNAME_DATA}"
Update Cloud DNS with the CNAME Record
gcloud dns record-sets transaction start --zone="$CLOUD_DNS_ZONE_NAME" --project $PROJECT_ID
gcloud dns record-sets transaction add "$CNAME_DATA" \
--name="_acme-challenge.${DOMAIN_NAME}." \
--ttl="30" \
--type="CNAME" \
--zone="$CLOUD_DNS_ZONE_NAME" \
--project $PROJECT_ID
gcloud dns record-sets transaction execute --zone="$CLOUD_DNS_ZONE_NAME" --project $PROJECT_ID
Create the Google-Managed Certificate
gcloud certificate-manager certificates create $CERTIFICATE_NAME \
--domains="$DOMAIN_NAME" \
--dns-authorizations="$DOMAIN_AUTHORIZATION_NAME" \
--project $PROJECT_ID
Monitor the status:
gcloud certificate-manager certificates describe $CERTIFICATE_NAME
Ensure status is ACTIVE before proceeding.
Create Certificate Map and Entry
# Create the certificate map
gcloud certificate-manager maps create $CERTIFICATE_MAP_NAME --project $PROJECT_ID
# Create the certificate map entry
gcloud certificate-manager maps entries create $CERTIFICATE_MAP_ENTRY_NAME \
--map="$CERTIFICATE_MAP_NAME" \
--certificates="$CERTIFICATE_NAME" \
--hostname="$DOMAIN_NAME" \
--project $PROJECT_ID
Step 3: Provision the Load Balancer using Gateway API
gateway.yaml
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
name: external-http
annotations:
networking.gke.io/certmap: cert-map-global-ub-abc-dev-com
spec:
gatewayClassName: gke-l7-global-external-managed
listeners:
- name: https
protocol: HTTPS
port: 443
- name: http
protocol: HTTP
port: 80
http-route.yaml
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
name: store-external
spec:
parentRefs:
- kind: Gateway
name: external-http
hostnames:
- "global-ub-abc-dev.com"
rules:
- matches:
- path:
value: /de
backendRefs:
- name: store-german
port: 8080
Apply resources:
kubectl apply -f gateway.yaml
kubectl apply -f http-route.yaml
Step 4: Retrieve the Load Balancer’s IP Address
kubectl describe gateway external-http
Check the Status section:
Addresses:
- Type: IPAddress
Value: 34.149.207.45
Store it in a variable:
export LOAD_BALANCER_IP=$(kubectl describe gateway external-http -o=jsonpath='{.status.addresses[0].value}')
echo "Load Balancer IP: ${LOAD_BALANCER_IP}"
Step 5: Update DNS with an A Record
gcloud dns record-sets transaction start --zone="$CLOUD_DNS_ZONE_NAME" --project $PROJECT_ID
gcloud dns record-sets transaction add "$LOAD_BALANCER_IP" \
--name="$DOMAIN_NAME." \
--ttl="300" \
--type="A" \
--zone="$CLOUD_DNS_ZONE_NAME" \
--project $PROJECT_ID
gcloud dns record-sets transaction execute --zone="$CLOUD_DNS_ZONE_NAME" --project $PROJECT_ID
Step 6: Update Target HTTPS Proxy (if needed)
In some cases, especially with pre-provisioned HTTP proxies, you may need to explicitly associate your certificate map with the target HTTPS proxy:
List HTTPS Proxies
gcloud compute target-https-proxies list
Update the Proxy with Certificate Map
gcloud compute target-https-proxies update gkegw1-e3is-default-external-http-jy9mc97xb5yh \
--certificate-map="$CERTIFICATE_MAP_NAME" \
--global
Verify the Configuration
gcloud compute target-https-proxies describe gkegw1-e3is-default-external-http-jy9mc97xb5yh \
--global \
--format="get(sslCertificates)"
No comments:
Post a Comment