One of the first challenges associated with owning the control plane of Kubernetes is that you are responsible for authz and authn.
While there are some great resources for getting set up with some form of identity management, ultimately the correct solution will depend on your existing on-premise setup. If you already have something like Active Directory or LDAP configured, then it probably makes sense to integrate with those.
Thankfully, Kubernetes provides a rich set of possibilities for authentication; from standards like OIDC right through to just sharing a token to figure out who the current user is.
Objective
In this post, I’ll demonstrate how to setup OIDC authentication with the kube-apiserver, which will allow user identity to be established. If you’re lucky, your enterprise will already have an OIDC provider such as Okta., or the Google IAM services. Even if you’re starting from scratch, it’s relatively simple to set up a bridge to LDAP or AD.
In order to follow along, you’ll need a Kubernetes cluster on which you are able to run kubectl.
The procedure for getting keycloak up and running on top of kubernetes is relatively well documented elsewhere, so I’ll assume you’re able to get that up and running. If you’re using minikube for this, then I would recommend this project.
Setting up access to the service
Once you have a Keycloak pod running, you’ll navigate to the Keycloak end. Given that we have no solution for ingress yet, our best option is to expose the service on a nodeport.
This is achieved by adding some definitions to the existing service definition. The default keycloak service definition will be something like this:
---
apiVersion: v1
kind: Service
metadata:
labels:
app: keycloak
component: keycloak
name: keycloak
namespace: default
spec:
clusterIP: None
ports:
- name: http
port: 80
protocol: TCP
targetPort: http
selector:
app: keycloak
component: keycloak
type: ClusterIP
Nodeports cannot be added to services of type ClusterIP, but we can take advantage of Kubernetes service abstraction to simply create a new service for our nodeport. We will start by grabbing the existing one:
$ kubectl get svc keycloak -o yaml > keycloak-nodeport.yaml
Now we can simply edit it to look like this (notice how similar these services look)
---
apiVersion: v1
kind: Service
metadata:
labels:
app: keycloak
component: keycloak
name: keycloak-nodeport
namespace: default
spec:
ports:
- name: http
port: 80
nodePort: 32080
protocol: TCP
targetPort: http
selector:
app: keycloak
component: keycloak
sessionAffinity: None
type: NodePort
In fact, the diff is tiny:
7c7
< name: keycloak
---
> name: keycloak-nodeport
10d9
< clusterIP: None
13a13
> nodePort: 32080
20c20
< type: ClusterIP
---
> type: NodePort
Accessing the Keycloak service
If you used the minikube and oidckube script, then you should have keycloak available at https://keycloak.devlocal. You should see this page, and be able to click through to the Administration Console.


The username is ‘keycloak’ and the password is ‘keycloak.’ It is hashed and available in a secret resource:
$ kubectl get secret keycloak-admin-user -o yaml
apiVersion: v1
data:
password: THIS_IS_THE_PASSWORD_HASH
kind: Secret
metadata:
labels:
app: keycloak
component: keycloak
name: keycloak-admin-user
namespace: default
type: Opaque
So we now have Keycloak installed and running. Stick around for Part 2.