Migrate WebLogic domain to Verrazzano multi-cluster environment — Part 1

Omid Izadkhasti
Oracle Developers
Published in
9 min readJun 23, 2022

One of biggest challenges of existing customers running their workload on WebLogic environment is modernization of legacy environment without performing a major re-architecture.

In this article I will explain how to migrate existing WebLogic domain to a managed Kubernetes cluster (OKE in my case) and in subsequent articles I will leverage Verrazzano and migrate existing WebLogic domain to a multi-cluster Verrazzano environment.

Here is the high level target architecture:

Let us begin!

Oracle Kubernetes Toolkit, provides a comprehensive set of tooling to help existing WebLogic customers migrate their workload to Kubernetes environment.

This toolkit consists of following products:

  1. Oracle WebLogic Deploy Tooling (WDT) that helps customers lift-and-shift existing domain and configuration to images and Kubernetes.

2. Oracle WebLogic Image Tool that allows you to automate building, patching, and updating your WebLogic Server Docker images, including your own customized images.

3. WebLogic Kubernetes Operator that extends Kubernetes to enable creation, configuration, and management of a WebLogic Server domain.

4. WebLogic Kubernetes Toolkit UI that facilitates the provisioning and deployment of WebLogic domains and applications to Kubernetes.

5. Oracle WebLogic Monitoring Exporter that exports WebLogic Server metrics to Prometheus where domains and deployments can be monitored and seen in Grafana dashboards.

6. Oracle WebLogic Logging Exporter that provides an easy to configure, robust, and production-ready solution to access WLS log information through Elasticsearch and Kibana.

To migrate existing WebLogic domain to Kubernetes you should perform the following steps:

  1. Install Kubernetes Cluster or using one of managed Kubernetes environments like Oracle OKE, Google GKS, AWS EKS, etc. in this article I am going to use Oracle Kubernetes Engine (OKE).
  2. Deploy Oracle WebLogic Operator in Kubernetes cluster. you can follow this link to learn how to install WebLogic operator in your Kubernetes cluster (I will explain it later in this article).
  3. Use WebLogic Deploy Tool (WDT) to create model, property, and archive files from existing WebLogic domain. Model is a version-independent description of a WebLogic Server domain configuration in yaml format. Property file is a key/value files that contains user defined values for domain variables like user and passwords, database connection strings, etc. And the archive file is used to deploy binaries and other file resources to the target domain (in zip format). I will explain these files in following sections. You can find more information regarding to WDT and how to use it in this link.
  4. Download WebLogic and JDK archive files from Oracle website (versions that you want to use for your domain) and use WebLogic Image Tool to create a Docker image. WebLogic Image Tool accepts WebLogic archive, JDK archive, WDT archive, domain model, domain property file and domain archive file as parameter and generates a Docker image that contains all binaries (WebLogic, JDK and WDT) and domain files. This is the model in image deployment type used by WebLogic Kubernetes operator. You can use this link for more information.

Here is high level process diagram to migrate existing WebLogic domain to Kubernetes:

Create OKE Cluster

First you need to create your Kubernetes cluster in the Oracle Cloud Infrastructure (OCI) region of your choice. I am not going to cover all steps in this article, and you’ll need to have access to OCI tenancy (you can create your own tenancy by following this link).

After logging in to your tenancy, you should create a compartment to provision Kubernetes cluster (I have created an apps compartment under root compartment in my case).

Then, you should provision an OKE cluster in your tenancy, and you can use OCI console to provision the cluster or use terraform script to provision your cluster. We can use OCI console for now and in next article I will use terrafrom to provision a multi-cluster environment.

Navigate to Developer Services -> Kubernetes Cluster (OKE) and after changing your compartment, select “Create cluster”. I recommend choosing “Quick create” so it will provision all resources (VCN, subnets, gateways, firewall rules, routing and Kubernetes resources). You can use “Custom create” but you need to carefully follow documentation to create all resources before provision the OKE cluster.

I am using “Public Endpoint” then I can access OKE API server from everywhere (I recommend using “Private Endpoint” for your production workload) and only select two worker nodes.

It will take few minutes to provision all resources for you.

Now you can use cloud shell to connect to Kubernetes cluster. Execute cloud shell and copy and execute cloud shell access commands from Kubernetes cluster.

Discover source WebLogic domain

I have a very simple WebLogic domain in source (on-premises) environment with one managed server in simple WebLogic cluster and simple web applications deployed in the cluster.

I can use following command to discover source environment (generate model, property, and application archive files).

weblogic-deploy/bin/discoverDomain.sh -oracle_home $MW_HOME     -domain_home $DOMAIN_HOME -archive_file app-archive.zip     -model_file app-model.yaml -variable_file app.properties -target wko    -output_dir .

This command will generate three outputs:

  • Domain model

In this file value of all variables start with @@PROP will populated from property file and value of all variables start with @@SECRET will populated from Kubernetes secrets (during creation of domain at runtime).

This means you should create these secrets in Kubernetes before deploying the application.

  • Domain properties
  • Compress file that contains application archives (ear, war and jar files) in following folder structure:
wlsdeploy/applications

Create Docker image and push it in OCIR

We will use imagetool utility to create docker image using domain model, property, and application archive.

Also, this utility needs fusion middleware, jdk and WDT binaries as input.

imagetool/bin/imagetool.sh cache addInstaller --type wdt --version latest --path weblogic-deploy.zip --forceimagetool/bin/imagetool.sh cache addInstaller --type=jdk --version=8u291 --path jdk-8u291-linux-x64.tar.gz --forceimagetool/bin/imagetool.sh cache addInstaller --type=fmw --version=12.2.1.4 --path fmw_12.2.1.4.0_wls_quick_slim_Disk1_1of1.zip --forceimagetool/bin/imagetool.sh create --tag mel.ocir.io/apaccpt03/app-repo/appdomain:1.0 --version 12.2.1.4 --jdkVersion 8u202 --wdtModel app-model.yaml --wdtVariables app.properties --wdtArchive app-archive.zip --wdtDomainHome /u01/domains/appdomain --wdtModelOnly

Finally create private repository (app-repo/appdomain) in OCIR and push the image to OCIR.

docker login <region name>.ocir.io
Username:
<tenancy namespace>/oracleidentitycloudservice/<user>
Password:
Login Succeeded
## Password is user auth tokendocker push <region name>.ocir.io/<tenancy namespace>/app-repo/appdomain:1.0
the helm repo

Install WebLogic operator in Kubernetes cluster

In this step, I will install WLS operator in our k8s cluster. First, I need to connect to cloud shell and configure access to the cluster (as I described before).

Then I will create a namespace for WebLogic operator.

omid_izadk@cloudshell:~ (ap-melbourne-1)$ kubectl create namespace weblogic-operator-ns
namespace/weblogic-operator-ns created

I am using WL operator helm chart to install the operator, so to do that first I need to add the helm repository using the following command:

omid_izadk@cloudshell:~ (ap-melbourne-1)$ helm repo add weblogic-operator https://oracle.github.io/weblogic-kubernetes-operator/charts --force-update  
"weblogic-operator" has been added to your repositories

I am using latest version of operator image in this article (3.4.1)

omid_izadk@cloudshell:~ (ap-melbourne-1)$ helm show values weblogic-operator/weblogic-operator | grep image
# image specifies the container image containing the operator.
image: "ghcr.io/oracle/weblogic-kubernetes-operator:3.4.1"

Finally, use the following command to install WL operator inside weblogic-operator-ns namespace.

omid_izadk@cloudshell:~ (ap-melbourne-1)$ helm install weblogic-operator \
> weblogic-operator/weblogic-operator \
> --namespace weblogic-operator-ns \
> --set "enableClusterRoleBinding=true" \
> --set "domainNamespaceSelectionStrategy=LabelSelector" \
> --set "domainNamespaceLabelSelector=weblogic-operator\=enabled" \
> --wait

NAME: weblogic-operator
LAST DEPLOYED: Sun Jun 19 04:11:32 2022
NAMESPACE: weblogic-operator-ns
STATUS: deployed
REVISION: 1
TEST SUITE: None

I will use the following command to confirm operator is up and running.

omid_izadk@cloudshell:~ (ap-melbourne-1)$ kubectl get all -n weblogic-operator-ns
NAME READY STATUS RESTARTS AGE
pod/weblogic-operator-9c5bd58f5-85gkf 1/1 Running 0 2m43s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/internal-weblogic-operator-svc ClusterIP 10.96.130.244 <none> 8082/TCP 2m44s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/weblogic-operator 1/1 1 1 2m46s
NAME DESIRED CURRENT READY AGE
replicaset.apps/weblogic-operator-9c5bd58f5 1 1 1 2m46s

Install NGINX ingress controller

I will install NGINX ingress controller to enable access to WebLogic managed servers from public internet using following commands (you can use any ingress controller instead of NGINX if you like).

#add nginx helm repository
omid_izadk@cloudshell:~ (ap-melbourne-1)$ helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx --force-update
"ingress-nginx" has been added to your repositories
#Create namespace
omid_izadk@cloudshell:~ (ap-melbourne-1)$ kubectl create namespace nginx
namespace/nginx created
#install nginx helm chart
omid_izadk@cloudshell:~ (ap-melbourne-1)$ helm install nginx-operator ingress-nginx/ingress-nginx --namespace nginx
NAME: nginx-operator
LAST DEPLOYED: Sun Jun 19 04:23:01 2022
NAMESPACE: nginx
STATUS: deployed
REVISION: 1
TEST SUITE: None

Create and deploy WebLogic domain

This is final step to create domain file (in yaml format) and create the domain in k8s. The WebLogic operator will pick up the domain configuration and will create admin and managed servers accordingly.

First, we need to create domain.yaml file that is using image we created in previous steps. Here is the domain.yaml file.

Before you create a domain, you need to create namespace and secrets for OCIR registry username and password, WebLogic credentials and runtime encryption password.

omid_izadk@cloudshell:wls-oke (ap-melbourne-1)$ kubectl create namespace appdomain
namespace/appdomain created
omid_izadk@cloudshell:wls-oke (ap-melbourne-1)$ kubectl -n appdomain create secret generic weblogic-credentials --from-literal=username=weblogic --from-literal=password=Welcome123#
secret/appdomain-weblogic-credentials created
omid_izadk@cloudshell:wls-oke (ap-melbourne-1)$ kubectl label secret appdomain-weblogic-credentials -n appdomain weblogic.domainUID=appdomain
secret/appdomain-weblogic-credentials labeled
omid_izadk@cloudshell:wls-oke (ap-melbourne-1)$ kubectl -n appdomain create secret generic appdomain-runtime-encryption-secret --from-literal=password=Welcome123#omid_izadk@cloudshell:wls-oke (ap-melbourne-1)$ kubectl create secret docker-registry ocir-secret --docker-server=mel.ocir.io --docker-username='<tenancy namespace>/oracleidentitycloudservice/omid.izadkhasti@oracle.com' --docker-password='<User Auth Token>' --docker-email='omid.izadkhasti@oracle.com' -n appdomain
secret/ocir-secret created

Because we are using a label from WebLogic operator, we should label domain namespace using following command:

omid_izadk@cloudshell:wls-oke (ap-melbourne-1)$ kubectl label ns appdomain weblogic-operator=enabled
namespace/appdomain labeled

Now we can create the domain using the following command:

omid_izadk@cloudshell:wls-oke (ap-melbourne-1)$ kubectl apply -f domain.yaml 
domain.weblogic.oracle/appdomain configured

After few minutes you will see admin and managed servers are up and running.

omid_izadk@cloudshell:wls-oke (ap-melbourne-1)$ kubectl get pods -n appdomain
NAME READY STATUS RESTARTS AGE
appdomain-adminserver 1/1 Running 0 7m51s
appdomain-managedserver-1 1/1 Running 0 7m8s

To access the application (SimpleHTML application) you can create following:

appdomain-managedserver-1 is Kubernetes service name that created for managed server and port 7003 is a service listening address. You can find service name and listen address using following command:

mid_izadk@cloudshell:wls-oke (ap-melbourne-1)$ kubectl get services -n appdomain
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
appdomain-adminserver ClusterIP None <none> 7001/TCP 24m
appdomain-cluster-appcluster ClusterIP 10.96.197.58 <none> 7003/TCP 24m
appdomain-managedserver-1 ClusterIP None <none> 7003/TCP 24m

Now you can use following command to access application from public internet:

http://<<NGINX LB Public IP>>/SimpleHTML

You can find NGINX public IP address using following command:

omid_izadk@cloudshell:wls-oke (ap-melbourne-1)$ kubectl get services -n nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-operator-ingress-nginx-controller LoadBalancer 10.xx.xx.xx <<public IP>> 80:31893/TCP,443:30600/TCP 4h10m
nginx-operator-ingress-nginx-controller-admission ClusterIP 10.xx.xx.xx <none> 443/TCP 4h10m

Finally, you should see following screen (if everything working as expected):

I hope you now understand basic architecture of WebLogic application in Kubernetes and how can you migrate your simple applications to k8s. Don’t worry this is just a beginning, and in coming articles I will explain how to have more complex domains (i.e. domains with data sources) and how to manage lifecycle of domain in Kubernetes.

Also, I will explain how to install Verrazzano and deploy WebLogic domains in Verrazzano and finally how can we deploy same domain in multi-cluster environment.

Want to discuss? While you’re waiting for more, drop into our public Slack channel!

--

--

Omid Izadkhasti
Oracle Developers

Principal Cloud Solution Architect @Oracle. The views expressed on this blog are my own and do not necessarily reflect the views of Oracle.