Session persistence for applications running on WebLogic for OKE

Bogdan Eremia
Oracle Developers
Published in
5 min readJan 4, 2021

--

Photo from Pexels

I’ve been recently more and more playing with Oracle’s Cloud Marketplace solution for deploying WebLogic domains running on OCI’s Container Engine for Kubernetes (shortly called OKE). If you haven’t heard yet about this solution that spares you of manual installation of WebLogic on top of Kubernetes — and of many more!, check this blog post for a good introduction and starting point: Oracle WebLogic Server for OKE.

WebLogic for OKE components reference architecture

Naturally, at some point during my tests, I deployed a sample ADF application and got this familiar warning message when interacting with the app:

ADF warning message linked with expired an session

I remembered that this annoying popup was usually a result of an expired session. Technically, the JSESSIONID cookie sent by the browser was no longer associated with a valid session on WebLogic Server — or unknown — and clicking the OK button would force reloading the page. This would lead to redirection to a Login or an SSO page or, in case of public pages, instantly re-generation of a new session with a fresh JSESSIONID. But it was not the case in my scenario.

A bit of context: in my WebLogic for OKE topology, I have a Kubernetes cluster with two worker nodes associated with the Weblogic Node Pool (dedicated node pool for running WebLogic related pods) and four running WebLogic Managed Servers pods. From the WebLogic Server perspective, a WebLogic cluster with four managed servers. In front, a public OCI Load Balancer distributes the traffic to my Kubernetes cluster and, subsequently, a preconfigured NGINX Ingress Controller that routes application traffic to the WebLogic Managed Servers pods. So, most probably in my case, the calls were each time served by a different pod that was not recognizing the session cookie created by a peer pod. This makes sense as my sample ADF application is not configured for session replication.

How to quickly fix this issue? Configure the associated Kubernetes Ingress Resource to support pod affinity! I’m logged in to the Admin Host (check the reference components architecture above) as it has all CLI tools installed and configured with the Kubernetes cluster. Listing all Ingress Resources, we see three distinct ones:

$ kubectl get ingress -A
NAMESPACE NAME HOSTS ADDRESS PORTS AGE
jenkins-ns jenkins-dashboard-ingress * 10.0.3.4 80 20d
wlsoke07-domain-ns wls-admin-ingress * 10.0.3.4 80 20d
wlsoke07-domain-ns wls-cluster-ingress * 193.133.3.17 80 20d

The wls-cluster-ingress handles the external traffic, and we can see that it’s using a different NGINX Ingress Controller instance:

$ kubectl get ingress -A -o custom-columns=NAME:.metadata.name,CLASS:.metadata.annotations."kubernetes\.io/ingress\.class"
NAME CLASS
jenkins-dashboard-ingress nginx
wls-admin-ingress nginx
wls-cluster-ingress nginx-applications

To setup session persistence, we need to add at least two annotations to the wls-cluster-ingress Ingress:

nginx.ingress.kubernetes.io/affinity: cookie
nginx.ingress.kubernetes.io/affinity-mode: persistent

Besides, we also need to map a hostname for the default route. In my case, I’m setting up the host wlsoke.com (I also need to edit my local /etc/hosts file to map it with the public load balancer IP address). To edit the Ingress:

$ kubectl edit ingress wls-cluster-ingress -n wlsoke07-domain-ns

After adding the above, the .yaml file should look like this:

Saving the file as in any other editor like vi or vim automatically triggers the Ingress configuration reload:

$ kubectl edit ingress wls-cluster-ingress -n wlsoke07-domain-ns
ingress.extensions/wls-cluster-ingress edited

Listing now the Ingress Resources, we see the host mapped:

$ kubectl get ingress -A
NAMESPACE NAME HOSTS ADDRESS PORTS AGE
jenkins-ns jenkins-dashboard-ingress * 10.0.3.4 80 20d
wlsoke07-domain-ns wls-admin-ingress * 10.0.3.4 80 20d
wlsoke07-domain-ns wls-cluster-ingress wlsoke 193.133.3.17 80 20d

Now the sample ADF application runs as expected:

ADF Calendar Component

If we check the application cookies, we see a new one called INGRESSCOOKIE. This one gets generated by the NGINX Ingress Controller and ensures session stickiness to a particular WebLogic Managed Server pod.

One more thing I would change: making the architecture truly HA by increasing the replica number for the external ingress controller:

$ kubectl get deployments -A
NAMESPACE NAME READY UP-TO-DATE AVAILABLE AGE
ingress-nginx nginx-ingress-controller 1/1 1 1 20d
ingress-nginx nginx-ingress-controller-external 1/1 1 1 20d
jenkins-ns jenkins-deployment 1/1 1 1 20d
kube-system coredns 4/4 4 4 20d
kube-system kube-dns-autoscaler 1/1 1 1 20d
wlsoke07-operator-ns weblogic-operator 1/1 1 1 20d

Of course, in the case when the Kubernetes worker node running the only nginx-ingress-controller-external pod falls, another instance will be automatically spun up on the other worker node, but this could mean a few seconds of downtime. Not if we increase the replica number to always have two instances up & running:

$ kubectl scale --replicas=2 deployment/ninx-ingress-controller-external -n ingress-nginx
deployment.apps/nginx-ingress-controller-external scaled
$ kubectl get deployments -A
NAMESPACE NAME READY UP-TO-DATE AVAILABLE AGE
ingress-nginx nginx-ingress-controller 1/1 1 1 20d
ingress-nginx nginx-ingress-controller-external 2/2 2 2 20d
jenkins-ns jenkins-deployment 1/1 1 1 20d
kube-system coredns 4/4 4 4 20d
kube-system kube-dns-autoscaler 1/1 1 1 20d
wlsoke07-operator-ns weblogic-operator 1/1 1 1 20d

Checking the two instances running on different worker nodes (NODE column):

$ kubectl get pods -o wide -n ingress-nginx
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-ingress-controller-84dbddc6dd-tzck6 1/1 Running 0 20d 10.244.0.131 10.0.4.3 <none> <none>
nginx-ingress-controller-external-85c7889d47-5hxm5 1/1 Running 0 25h 10.244.0.161 10.0.4.3 <none> <none>
nginx-ingress-controller-external-85c7889d47-gfvk6 1/1 Running 0 2m32s 10.244.2.12 10.0.4.8 <none> <none>

If just for fun, we kill any of the NGINX external ingress controller pods, the ADF application remains accessible, so truly high available:

$ kubectl delete pods nginx-ingress-controller-external-85c7889d47-gfvk6 — grace-period=0 — force -n ingress-nginx
warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.
pod “nginx-ingress-controller-external-85c7889d47-gfvk6” force deleted

--

--