Bootstrap FreeKB - OpenShift - Getting Started with the Red Hat build of Keycloak Operator
OpenShift - Getting Started with the Red Hat build of Keycloak Operator

Updated:   |  OpenShift articles

There are multiple ways to authenticate in OpenShift.

Here are my notes as I prepared for the Red Hat Certified Specialist in OpenShift Automation and Integration exam (EX380).

In the OpenShift console, at Operators > Operator Hub search for the Red Hat build of Keycloak Operator.

 

And follow the prompts to install the operator.

 

The Operator should create a deployment which should spawn a replica set which should spawn a pod.

~]$ oc get all --namespace keycloak
NAME                                 READY   STATUS    RESTARTS   AGE
pod/rhbk-operator-57b47d9d66-56q58   1/1     Running   0          13s
NAME                            READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/rhbk-operator   1/1     1            1           23h
NAME                                       DESIRED   CURRENT   READY   AGE
replicaset.apps/rhbk-operator-57b47d9d66   1         1         1       13s

 

If the pod is in an Error state.

~]$ oc get pods --namespace keycloak
NAME                                 READY   STATUS   RESTARTS   AGE
pod/rhbk-operator-65ffd96644-f4wvx   0/1     Error    0          6s

 

And the pod logs has something like this.

~]$ oc logs pod/rhbk-operator-65ffd96644-f4wvx
 --namespace keycloak
2025-10-02 01:13:02,481 ERROR [io.qua.run.Application] (main) Failed to start application: java.lang.RuntimeException: Failed to start quarkus
        at io.quarkus.runner.ApplicationImpl.doStart(Unknown Source)
        at io.quarkus.runtime.Application.start(Application.java:101)
        at io.quarkus.runtime.ApplicationLifecycleManager.run(ApplicationLifecycleManager.java:121)
        at io.quarkus.runtime.Quarkus.run(Quarkus.java:77)
        at io.quarkus.runtime.Quarkus.run(Quarkus.java:48)
        at io.quarkus.runtime.Quarkus.run(Quarkus.java:137)
        at io.quarkus.runner.GeneratedMain.main(Unknown Source)
        at io.quarkus.bootstrap.runner.QuarkusEntryPoint.doRun(QuarkusEntryPoint.java:68)
        at io.quarkus.bootstrap.runner.QuarkusEntryPoint.main(QuarkusEntryPoint.java:36)
Caused by: java.lang.IllegalArgumentException: Failure in creating proxy URL. Proxy port is required!

 

This may occur if your OpenShift cluster has a proxy configured.

In this scenario, you may need to adjust the proxy configurations in the keycloak deployment. For example, I resolved the pod being in an Error state by removing the following from my keycloak deployment.

- name: HTTP_PROXY
  value: http://proxy.example.com
- name: HTTPS_PROXY
  value: https://proxy.example.com
- name: NO_PROXY
  value: .cluster.local,.access.redhat.com,cloud.openshift.com,localhost,quay.io,registry.connect.redhat.com,registry.redhat.io

 

A stable pod should have logs that look something like this. Notice the pod is listening for connections on http://0.0.0.0:8080.

~]$ oc logs pod/rhbk-operator-57b47d9d66-56q58 --namespace keycloak
2025-10-02 01:14:26,319 WARN  [io.qua.config] (main) Unrecognized configuration key "quarkus.operator-sdk.bundle.package-name" was provided; it will be ignored; verify that the dependency extension for this configuration is set or that you did not make a typo
2025-10-02 01:14:27,500 INFO  [io.qua.ope.run.OperatorProducer] (main) Quarkus Java Operator SDK extension 7.1.1.redhat-00002 (commit: bbd08ea) built on Mon Apr 07 13:41:33 GMT 2025
2025-10-02 01:14:27,516 INFO  [io.jav.ope.Operator] (main) Registered reconciler: 'keycloakrealmimportcontroller' for resource: 'class org.keycloak.operator.crds.v2alpha1.realmimport.KeycloakRealmImport' for namespace(s): [keycloak]
2025-10-02 01:14:27,600 INFO  [io.jav.ope.Operator] (main) Registered reconciler: 'keycloakcontroller' for resource: 'class org.keycloak.operator.crds.v2alpha1.deployment.Keycloak' for namespace(s): [keycloak]
2025-10-02 01:14:27,600 INFO  [io.qua.ope.run.AppEventListener] (main) Starting operator.
2025-10-02 01:14:27,600 INFO  [io.jav.ope.Operator] (main) Operator SDK 5.0.4.redhat-00001 (commit: 2a58f2b) built on Thu Apr 03 15:50:23 GMT 2025 starting...
2025-10-02 01:14:27,600 INFO  [io.jav.ope.Operator] (main) Client version: 7.1.0.redhat-00001
2025-10-02 01:14:27,601 INFO  [io.jav.ope.pro.Controller] (Controller Starter for: keycloakrealmimportcontroller) Starting 'keycloakrealmimportcontroller' controller for reconciler: org.keycloak.operator.controllers.KeycloakRealmImportController, resource: org.keycloak.operator.crds.v2alpha1.realmimport.KeycloakRealmImport
2025-10-02 01:14:27,601 INFO  [io.jav.ope.pro.Controller] (Controller Starter for: keycloakcontroller) Starting 'keycloakcontroller' controller for reconciler: org.keycloak.operator.controllers.KeycloakController, resource: org.keycloak.operator.crds.v2alpha1.deployment.Keycloak
2025-10-02 01:14:27,800 WARN  [io.fab.kub.cli.dsl.int.VersionUsageUtils] (InformerWrapper [keycloakrealmimports.k8s.keycloak.org/v2alpha1] 27) The client is using resource type 'keycloakrealmimports' with unstable version 'v2alpha1'
2025-10-02 01:14:27,800 WARN  [io.fab.kub.cli.dsl.int.VersionUsageUtils] (InformerWrapper [keycloaks.k8s.keycloak.org/v2alpha1] 26) The client is using resource type 'keycloaks' with unstable version 'v2alpha1'
2025-10-02 01:14:29,394 INFO  [io.jav.ope.pro.Controller] (Controller Starter for: keycloakrealmimportcontroller) 'keycloakrealmimportcontroller' controller started
2025-10-02 01:14:29,697 INFO  [io.jav.ope.pro.Controller] (Controller Starter for: keycloakcontroller) 'keycloakcontroller' controller started
2025-10-02 01:14:29,716 INFO  [io.quarkus] (main) keycloak-operator 26.2.9.redhat-00001 on JVM (powered by Quarkus 3.20.2.redhat-00004) started in 4.293s. Listening on: http://0.0.0.0:8080
2025-10-02 01:14:29,716 INFO  [io.quarkus] (main) Profile prod activated.
2025-10-02 01:14:29,716 INFO  [io.quarkus] (main) Installed features: [cdi, kubernetes, kubernetes-client, openshift-client, operator-sdk, smallrye-context-propagation, smallrye-health, vertx]

 

Also, the deployment should have label name: rhbk-operator.

~]$ oc get pod/rhbk-operator-57b47d9d66-56q58 --namespace keycloak --output jsonpath="{.metadata.labels}"
{"name":"rhbk-operator","pod-template-hash":"57b47d9d66"}

 

Keycloak Service

Next let's create a file named keycloak_service.yml that contains the following YAML. In this example since the pod has label name: rhbk-operator the service then has selector name: rhbk-operator.

apiVersion: v1
kind: Service
metadata:
  name: keycloak
  namespace: keycloak
spec:
  internalTrafficPolicy: Cluster
  ipFamilies:
  - IPv4
  ipFamilyPolicy: SingleStack
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    name: rhbk-operator
  sessionAffinity: None
  type: ClusterIP  

 

And then the oc apply command can be used to create the service.

oc apply --filename service.yaml

 

And the oc describe command should show that the service Endpoint is pointing to the IP address and port of the keycloak pod.

~]$ oc describe service --namespace keycloak
Name:              keycloak
Namespace:         keycloak
Labels:            <none>
Annotations:       <none>
Selector:          app=keycloak
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                172.30.245.108
IPs:               172.30.245.108
Port:              <unset>  8080/TCP
TargetPort:        8080/TCP
Endpoints:         10.128.3.72:8080
Session Affinity:  None
Events:            <none>

 

Keycloak Route

Next let's create a file named keycloak_route.yml that contains the following YAML, replacing "keycloak.apps.openshift.example.com" with the URL you want to use for your keycloak route.

apiVersion: route.openshift.io/v1
kind: Route
metadata:
  labels:
    app: keycloak
    route-type: internal
  name: keycloak
  namespace: keycloak
spec:
  host: keycloak.apps.openshift.example.com
  tls:
    termination: edge
  to:
    kind: Service
    name: keycloak
    weight: 100
  wildcardPolicy: None

 

And then the oc apply command can be used to create the route.

oc apply --filename route.yaml

 

And the oc describe command should show that the route is exposed on one of the OpenShift routes and is forwarding onto the keycloak service, which is turns forwards onto the keycloak pod. Notice in this example that the route HOST/PORT is keycloak-keycloak.apps.openshift.example.com.

~]$ oc describe route keycloak --namespace keycloak
Name:                   keycloak
Namespace:              keycloak
Created:                7 days ago
Labels:                 app=keycloak
                        route-type=default
Description:            Route for application's service.
Annotations:            openshift.io/host.generated=true
Requested Host:         keycloak.apps.openshift.example.com
                           exposed on router default-router (host router-default-router.apps.openshift.example.com) 1 minute ago
Path:                   <none>
TLS Termination:        edge
Insecure Policy:        <none>
Endpoint Port:          <all endpoint ports>
Service:        keycloak
Weight:         100 (100%)
Endpoints:      <none>

 

Now you can go to the URL of your route and if all goes according to plan, you should be presented with the admin console sign in page. Awesome! 

 

You should be able to sign into the console using the KC_BOOTSTRAP_ADMIN_USERNAME and KC_BOOTSTRAP_ADMIN_PASSWORD, which is admin and itsasecret in this example.

~]$ oc exec pod/keycloak-c857bfb4-4jkxr --namespace keycloak -- printenv
KC_BOOTSTRAP_ADMIN_USERNAME=admin
KC_BOOTSTRAP_ADMIN_PASSWORD=itsasecret

 

 

Once signed into the console, you should see something like this.

 


 




Did you find this article helpful?

If so, consider buying me a coffee over at Buy Me A Coffee



Comments


Add a Comment


Please enter 4f297c in the box below so that we can be sure you are a human.