Deploying Keycloak On GKE With HTTPS A Comprehensive Guide
Deploying applications on Google Kubernetes Engine (GKE) can be a complex process, especially for those new to Kubernetes and cloud environments. One common challenge arises when deploying applications like Keycloak, which often require HTTPS for security and proper functionality. This article will guide you through deploying Keycloak on GKE with HTTPS enabled, addressing the "Https is Required" error and providing a comprehensive understanding of the process. We will delve into the intricacies of Kubernetes Ingress, Helm charts, and Google Cloud Platform configurations, ensuring a secure and robust deployment.
When deploying Keycloak on GKE, encountering the "Https is Required" error typically indicates that Keycloak is configured to enforce HTTPS connections, but the incoming requests are being served over HTTP. This mismatch can occur if the Ingress controller is not properly configured to handle HTTPS traffic, or if the Keycloak instance itself is not aware of the HTTPS termination occurring at the Ingress level. To resolve this, we need to ensure that the Ingress controller is configured to handle HTTPS traffic and that Keycloak is aware that it is running behind a proxy that terminates SSL.
Before we begin, ensure you have the following prerequisites in place:
- A Google Cloud Platform (GCP) account with billing enabled.
- The Google Cloud SDK (gcloud) installed and configured.
- kubectl installed and configured to interact with your GKE cluster.
- Helm installed for managing Kubernetes packages.
- A domain name and a TLS certificate for your domain.
1. Create a GKE Cluster
First, we need to create a GKE cluster. You can do this using the gcloud command-line tool. Choose a region and zone that are appropriate for your needs. Make sure to select a machine type that meets the requirements of Keycloak and other applications you plan to deploy.
gcloud container clusters create keycloak-cluster \
--region us-central1 \
--machine-type n1-standard-2 \
--num-nodes 3
This command creates a cluster named keycloak-cluster
in the us-central1
region with three nodes. The machine type is set to n1-standard-2
, which provides a good balance of CPU and memory for most workloads. Adjust these parameters as needed for your specific requirements.
After the cluster is created, configure kubectl
to connect to it:
gcloud container clusters get-credentials keycloak-cluster --region us-central1
2. Install Helm
Helm is a package manager for Kubernetes, which simplifies the deployment and management of applications. If you haven't already, install Helm on your local machine. You can download the appropriate binary from the Helm GitHub repository or use a package manager like brew
on macOS.
Once Helm is installed, initialize it in your cluster:
helm init --service-account tiller
kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
The first command initializes Helm in your cluster, and the second command grants the Tiller service account the necessary permissions to manage resources in your cluster. This is required for Helm to function correctly.
3. Install the Nginx Ingress Controller
The Nginx Ingress Controller is responsible for routing external traffic to your services within the cluster. It also handles SSL termination, which is crucial for enabling HTTPS. We will use Helm to install the Nginx Ingress Controller.
First, add the Helm repository for the Nginx Ingress Controller:
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
Next, install the Ingress Controller:
helm install ingress-nginx/ingress-nginx \
--name ingress-nginx \
--namespace ingress-nginx \
--set controller.service.type=LoadBalancer
kubectl create namespace ingress-nginx
This command installs the Nginx Ingress Controller in the ingress-nginx
namespace and exposes it using a LoadBalancer service. The LoadBalancer service will provision a Google Cloud Load Balancer, which will handle external traffic and forward it to the Ingress Controller.
After installation, it may take a few minutes for the Load Balancer to be provisioned. You can check the status by running:
kubectl get service -n ingress-nginx
Look for the EXTERNAL-IP
field in the output. This IP address is the entry point for your cluster, and you will need it to configure your DNS records.
4. Obtain a TLS Certificate
To enable HTTPS, you need a TLS certificate for your domain. You can obtain a certificate from a Certificate Authority (CA) like Let's Encrypt. Let's Encrypt provides free TLS certificates and can be easily automated using tools like Cert-Manager.
Install Cert-Manager using Helm:
helm repo add jetstack https://charts.jetstack.io
helm repo update
helm install cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--version v1.8.0 \
--set installCRDs=true
This command installs Cert-Manager in the cert-manager
namespace and creates the necessary Custom Resource Definitions (CRDs). Cert-Manager automates the process of obtaining and renewing TLS certificates.
Next, create a ClusterIssuer resource that tells Cert-Manager how to obtain certificates. For Let's Encrypt, you can use the following YAML:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
email: [email protected]
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- selector:
dnsNames:
- your-domain.com
dns01:
cloudDNS:
project: your-gcp-project-id
serviceAccountSecretRef:
name: clouddns-dns01-solver-svc-acc
key: key.json
Replace [email protected]
with your email address, your-domain.com
with your domain, and your-gcp-project-id
with your GCP project ID. You will also need to create a service account with the necessary permissions for Cloud DNS and store its credentials in a secret named clouddns-dns01-solver-svc-acc
. Consult the Cert-Manager documentation for detailed instructions on setting up the Cloud DNS solver.
Apply the ClusterIssuer:
kubectl apply -f cluster-issuer.yaml
5. Deploy Keycloak using Helm
Now that we have the Ingress Controller and Cert-Manager set up, we can deploy Keycloak using Helm. Add the Keycloak Helm repository:
helm repo add codecentric https://codecentric.github.io/helm-charts
helm repo update
Create a values.yaml
file to customize the Keycloak deployment. Here's an example configuration:
image:
tag: 17.0.1
service:
type: ClusterIP
name: keycloak
ingress:
enabled: true
className: nginx
hostname: your-keycloak-domain.com
tls:
enabled: true
secretName: keycloak-tls
extraEnvVars:
- name: KEYCLOAK_PROXY_ADDRESS_FORWARDING
value: "true"
- name: KC_HOSTNAME_ADMIN
value: your-keycloak-domain.com
- name: KC_HOSTNAME
value: your-keycloak-domain.com
- name: KC_HTTPS_PORT
value: "443"
resources:
requests:
cpu: 1
memory: 2Gi
limits:
cpu: 2
memory: 4Gi
postgresql:
enabled: true
resources:
requests:
cpu: 500m
memory: 1Gi
limits:
cpu: 1
memory: 2Gi
Replace your-keycloak-domain.com
with your domain name. This configuration enables Ingress, configures TLS using a secret named keycloak-tls
, and sets the KEYCLOAK_PROXY_ADDRESS_FORWARDING
environment variable to true
. This is crucial for Keycloak to correctly handle proxied requests and generate the correct URLs. Also, KC_HOSTNAME_ADMIN
and KC_HOSTNAME
are set to the domain name, and KC_HTTPS_PORT
is set to 443 to ensure Keycloak is aware of the HTTPS configuration.
Deploy Keycloak using Helm:
helm install keycloak codecentric/keycloak \
--namespace keycloak \
--create-namespace \
-f values.yaml
This command installs Keycloak in the keycloak
namespace using the configuration in values.yaml
.
6. Create an Ingress Resource
To expose Keycloak to the outside world, we need to create an Ingress resource. This resource defines how traffic should be routed to Keycloak.
Create a keycloak-ingress.yaml
file with the following content:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: keycloak-ingress
namespace: keycloak
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/proxy-body-size: "20m"
nginx.ingress.kubernetes.io/configuration-snippet: |
proxy_set_header X-Forwarded-Proto https;
spec:
tls:
- hosts:
- your-keycloak-domain.com
secretName: keycloak-tls
rules:
- host:
your-keycloak-domain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: keycloak
port:
number: 8080
Replace your-keycloak-domain.com
with your domain name. This Ingress resource configures the Nginx Ingress Controller to route traffic to the Keycloak service on port 8080. It also configures Cert-Manager to obtain a TLS certificate for your domain and stores it in a secret named keycloak-tls
. The annotations nginx.ingress.kubernetes.io/proxy-body-size
and nginx.ingress.kubernetes.io/configuration-snippet
are crucial for handling large requests and ensuring that Keycloak receives the X-Forwarded-Proto
header, which indicates that the request is coming over HTTPS.
Apply the Ingress resource:
kubectl apply -f keycloak-ingress.yaml
7. Verify the Deployment
After deploying Keycloak, it's essential to verify that everything is working correctly. Check the status of the Keycloak pods:
kubectl get pods -n keycloak
Ensure that all pods are in the Running
state. If any pods are in a different state, check the logs for errors.
Check the status of the Ingress resource:
kubectl describe ingress -n keycloak keycloak-ingress
Look for the Address
field in the output. This is the external IP address of the Load Balancer. You should also see that a certificate has been issued by Cert-Manager.
Finally, access Keycloak in your browser using the HTTPS protocol (e.g., https://your-keycloak-domain.com
). If everything is configured correctly, you should be able to access the Keycloak admin console.
8. Configure DNS Records
To make Keycloak accessible via your domain, you need to configure DNS records. Create an A record that points your domain to the external IP address of the Load Balancer.
It may take some time for DNS changes to propagate, so be patient if you can't access Keycloak immediately after configuring the DNS records.
If you encounter issues during the deployment process, here are some common troubleshooting tips:
- "Https is Required" Error: Ensure that the
KEYCLOAK_PROXY_ADDRESS_FORWARDING
environment variable is set totrue
and that the Ingress resource includes thenginx.ingress.kubernetes.io/configuration-snippet
annotation to set theX-Forwarded-Proto
header. - Certificate Issues: Check the Cert-Manager logs for errors. Ensure that your ClusterIssuer is configured correctly and that your DNS records are properly set up.
- Pod Errors: Check the logs of the Keycloak pods for errors. Common issues include database connection problems and configuration errors.
- Ingress Errors: Check the logs of the Nginx Ingress Controller for errors. Ensure that the Ingress resource is configured correctly and that the Load Balancer is provisioned.
Deploying Keycloak on GKE with HTTPS can be challenging, but by following this guide, you should be able to successfully deploy Keycloak and other applications securely. Remember to configure the Ingress Controller, obtain a TLS certificate, and set the necessary environment variables for Keycloak to function correctly behind a proxy. With these steps, you can ensure a robust and secure deployment of Keycloak on GKE. This comprehensive guide should help you navigate the complexities of Kubernetes and Google Cloud Platform, allowing you to deploy your applications with confidence. By addressing the "Https is Required" error and providing a step-by-step approach, this article equips you with the knowledge and tools necessary for a successful Keycloak deployment on GKE.