This article demonstrates how to deploy sample Daytrader7 as a WebSphere Liberty Application on Azure Kubernetes Service (AKS) using WebSphere Liberty Operator (WLO). For more information about the WebSphere Liberty Operator, see blog
Prerequisites
Steps
Step 1: Login AKS cluster
Step 2: Install cert-manager in the AKS cluster or bring your own certificates for transport layer security (TLS) in WebSphere Liberty Operator and ingress controller.
- Run the following command to install cert-manager with kubectl command. Check out https://cert-manager.io/docs/installation/supported-releases/ for the supported cert-manager releases.
$ kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.9.1/cert-manager.yaml
- Verify that pods in cert-manager namespace are in running state
$ kubectl get pods -n cert-manager
NAME READY STATUS RESTARTS AGE
cert-manager-6544c44c6b-sc67k 1/1 Running 0 25h
cert-manager-cainjector-5687864d5f-2f4tr 1/1 Running 0 25h
cert-manager-webhook-785bb86798-hnh82 1/1 Running 0 25h
Step 3: Create a
certificate authority (CA) cluster issuer.
- Cert-manager requires Issuer or ClusterIssuer Kubernetes resource. Apply the following sample cluster-issuer.yaml file with command 'kubectl apply -f cluster-issuer.yaml' to create the ClusterIssuer resource with Let’s Encrypt certificates.
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: MY_EMAIL_ADDRESS
privateKeySecretRef:
name: letsencrypt
solvers:
- http01:
ingress:
class: nginx
podTemplate:
spec:
nodeSelector:
"kubernetes.io/os": linux
Step 4: Create 'A' record in Azure DNS zone
- Now I am going to configure the NGINX ingress controller which I already installed on my AKS cluster (this is one of the prerequisites). Let's view ingress-nginx-controller service to see the ingress public IP address which will be used for creating 'A' record in Azure DNS
$ kubectl get service ingress-nginx-controller -n ingress-basic
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller LoadBalancer 10.0.96.27 20.124.61.44 80:32290/TCP,443:32039/TCP 41d
- Next I will create 'A' record in Azure DNS zone to map a name to the ingress public IP address. You can do this using Azure CLI or using Azure portal console. In the following example, I use az CLI to add 'A' record to an existing Azure DNS zone 'green-chesterfield.com' in my Azure subscription ID with name 'svtdemo' and IPv4 address of the ingress external IP address which is '20.124.61.44' from the example above.
$ az network dns record-set a add-record --resource-group openshift4-terraform --zone-name green-chesterfield.com --record-set-name svtdemo --ipv4-address 20.124.61.44
{
"aRecords": [
{
"ipv4Address": "20.124.61.44"
}
],
"etag": "e3c35982-2a14-48fa-9a7b-8bd929824155",
"fqdn": "svtdemo.green-chesterfield.com.",
"id": "/subscriptions/0e0a4287-8719-4849-bb0b-5242e4507709/resourceGroups/openshift4-terraform/providers/Microsoft.Network/dnszones/green-chesterfield.com/A/svtdemo",
"metadata": null,
"name": "svtdemo",
"provisioningState": "Succeeded",
"resourceGroup": "openshift4-terraform",
"targetResource": {
"id": null
},
"ttl": 3600,
"type": "Microsoft.Network/dnszones/A"
}
-
Now I have a fully qualified domain name (FQDN) of 'svtdemo.green-chesterfield.com' which is mapped to the ingress public IP address. This FQDN will be used in spec.route.host field of the WebSphereLibertyApplication deploy yaml file in step 8 below.
Step 5: Install WebSphere Liberty Operator
You can install the WebSphere Liberty Operator (WLO) with Operator Lifecycle Manager (OLM) or without it. I choose to install WLO without OLM to avoid the extra step of installing OLM.
- Create custom resource definitions (CRDs)
$ kubectl apply -f https://raw.githubusercontent.com/WASdev/websphere-liberty-operator/main/deploy/releases/1.0.2/kubectl/websphereliberty-app-crd.yaml
customresourcedefinition.apiextensions.k8s.io/webspherelibertyapplications.liberty.websphere.ibm.com created
customresourcedefinition.apiextensions.k8s.io/webspherelibertydumps.liberty.websphere.ibm.com created
customresourcedefinition.apiextensions.k8s.io/webspherelibertytraces.liberty.websphere.ibm.com created
- Create environment variables. Set WLO_TARGET_NAMESPACE='""' to watch all namespaces
$ WLO_NAMESPACE=wlo-namespace
$ WLO_TARGET_NAMESPACE='""'
- Install WebSphere Liberty Operator
$ curl -L https://raw.githubusercontent.com/WASdev/websphere-liberty-operator/main/deploy/releases/1.0.2/kubectl/websphereliberty-app-operator.yaml | sed -e "s/WEBSPHERE_LIBERTY_WATCH_NAMESPACE/${WLO_TARGET_NAMESPACE}/" | kubectl apply -n ${WLO_NAMESPACE} -f -
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 7331 100 7331 0 0 37263 0 --:--:-- --:--:-- --:--:-- 37984
serviceaccount/wlo-controller-manager created
role.rbac.authorization.k8s.io/wlo-leader-election-role created
role.rbac.authorization.k8s.io/wlo-manager-role created
rolebinding.rbac.authorization.k8s.io/wlo-leader-election-rolebinding created
rolebinding.rbac.authorization.k8s.io/wlo-manager-rolebinding created
deployment.apps/wlo-controller-manager created
-
Verify that WLO controller is running
$ kubectl get pods -n $WLO_NAMESPACE
NAME READY STATUS RESTARTS AGE
wlo-controller-manager-7c6d4fcb69-ctvd7 1/1 Running 0 87s
Step 6: Build sample-daytrader7 application image (You can skip this steps if you want to use prebuilt sample image 'docker.io/dguinan/sample-daytrader7:latest')
- Clone the application Git repo to your machine.
- git clone https://github.com/WASdev/sample.daytrader7.git
- cd sample.daytrader7 and run 'mvn install' to compile and create application ear file.
- Build application image sample-daytrader7 with command 'docker build -t sample-daytrader7 -f Containerfile_db2 .'
- Upload the sample-daytrader7 image to a repo that your cluster can access such as Docker Hub. For example,
- docker tag sample-daytrader7 docker.io/mydockerid/sample-daytrader7
- docker push docker.io/mydockerid/sample-daytrader7
Step 7: Create DB2 for daytrader7 application. If you already have DB2 for daytrader7 application, you can skip this step and provide your DB2 information in spec.env of daytrader7-deploy.yaml in step 8.
- The sample daytrader7 application uses database which can be DB2. The following steps are example of creating a DB2 container for daytrader7 on AKS cluster. Please note that this is a sample DB2 image and it is not recommended for production.
- Create daytrader7 namespace:
$ kubectl create namespace daytrader7
- In the directory where you download the sample.daytrader7 repo in step 6. Go to 'sample.daytrader7/deploy' folder, and apply the following yaml files to deploy DB2 to AKS.
$ kubectl -n daytrader7 apply -f db2-role-n-sa.yaml
$ kubectl -n daytrader7 apply -f db2-secret.yaml
$ kubectl -n daytrader7 apply -f tradedb-service.yaml
$ kubectl -n daytrader7 apply -f tradedb.yaml
- Verify that db2 pod is in running state
$ kubectl -n daytrader7 get pods
NAME READY STATUS RESTARTS AGE
trade-db2-7c9686d5b7-mqk7t 1/1 Running 0 27s
Step 8: Deploy daytrader7 application to Azure Kubernetes Service
- Create WebSphereLibertyApplication yaml file to deploy daytrader7 to AKS. See the following sample daytrader7-deploy.yaml file. You might need to update the following fields:
- spec.applicationImage: location of your application image that was built in step 6 such as 'docker.io/mydockerid/sample-daytrader7:latest' or prebuilt image 'docker.io/dguinan/sample-daytrader7:latest'
- spec.route.annotations.kubernetes.io/ingress.class: your ingress class
- spec.route.annotations.cert-manager.io/cluster-issuer: your Issuer or ClusterIssuer resource name created in step 3
- spec.route.host: full hostname which is the FQDN generated in step 4
Sample daytrader7-deploy.yaml file:
apiVersion: liberty.websphere.ibm.com/v1
kind: WebSphereLibertyApplication
metadata:
name: daytrader7
spec:
license:
accept: true
edition: IBM WebSphere Application Server
productEntitlementSource: Standalone
metric: Virtual Processor Core (VPC)
applicationImage: 'docker.io/dguinan/sample-daytrader7:latest'
pullPolicy: Always
replicas: 1
route:
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
nginx.ingress.kubernetes.io/affinity: "cookie"
nginx.ingress.kubernetes.io/session-cookie-name: "route"
nginx.ingress.kubernetes.io/session-cookie-max-age: "172800"
host: svtdemo.green-chesterfield.com
certificateSecretRef: tls-secret
path: /daytrader
pathType: Prefix
expose: true
service:
port: 9443
type: ClusterIP
probes:
startup: {}
liveness: {}
readiness: {}
env:
- name: tradeDbHost
value: trade-db2
- name: tradeDbPort
value: "50000"
- name: tradeDbName
value: TRADEDB
- name: dbUser
value: db2inst1
- name: dbPass
valueFrom:
secretKeyRef:
name: db-credential
key: dbpw
resources:
requests:
cpu: 500m
memory: 1024Mi
limits:
cpu: 500m
memory: 2048Mi
-
- Deploy daytrader7 application to AKS
$ kubectl -n daytrader7 apply -f daytrader7-deploy.yaml
webspherelibertyapplication.liberty.websphere.ibm.com/daytrader7 created
Step 9: Run daytrader7 application
- View ingress URL of daytrader7 application
$ kubectl -n daytrader7 get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
daytrader7 <none> svtdemo.green-chesterfield.com 20.124.61.44 80, 443 11m
- Now I can run the daytrader7 application using the ingress URL and 'daytrader' context root. For example 'https://svtdemo.green-chesterfield.com/daytrader/'
- Click on “Trading & Portfolios” tab and login with default user and password, you will see the following page with data from the DB2 container.