App Connect Enterprise on K8S

Kok Sing Khong
7 min readMar 25, 2023

--

The following is tested on Azure Kubernetes Server (AKS).

Tools to be installed:

  1. Kubernetes CLI (kubectl)
  2. Helm CLI (helm)
  3. Operator SDK (olm)
  4. Curl

Install certificate manager

(1) Run the following command to install the cert-manager resources from a YAML manifest file on GitHub:

% kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.8.0/cert-manager.yaml

(2) To verify the installation

% kubectl get pods --namespace cert-manager
NAME READY STATUS RESTARTS AGE
cert-manager-655bf9748f-4t5fd 1/1 Running 0 41s
cert-manager-cainjector-7985fb445b-7hfpb 1/1 Running 0 42s
cert-manager-webhook-6dc9656f89-qcf5n 1/1 Running 0 40s

(3) Run the following command to patch your deployment. Do not replace ${POD_NAMESPACE} in this command; this value is referenced within the cert-manager.yaml file. When the command completes, it adds a flag to ensure that any auto-generated secrets that store certificates are automatically removed when necessary.

% kubectl patch deployment \
cert-manager \
--namespace cert-manager \
--type='json' \
-p='[{"op": "replace", "path": "/spec/template/spec/containers/0/args", "value": [
"--v=2",
"--cluster-resource-namespace=$(POD_NAMESPACE)",
"--leader-election-namespace=kube-system",
"--enable-certificate-owner-ref"
]}]'

Install Operator Lifecycle Manager

(1) Before this, you need to install Operator SDK on MacOS.

% brew install operator-sdk

(2) Install Operator Lifecycle Manager in your cluster. This command creates the relevant custom resources definition.

% operator-sdk olm install

The output is:

INFO[0003] Fetching CRDs for version "latest"           
INFO[0003] Fetching resources for resolved version "latest"
INFO[0018] Creating CRDs and resources
INFO[0018] Creating CustomResourceDefinition "catalogsources.operators.coreos.com"
INFO[0019] Creating CustomResourceDefinition "clusterserviceversions.operators.coreos.com"
INFO[0020] Creating CustomResourceDefinition "installplans.operators.coreos.com"
INFO[0021] Creating CustomResourceDefinition "olmconfigs.operators.coreos.com"
INFO[0021] Creating CustomResourceDefinition "operatorconditions.operators.coreos.com"
INFO[0021] Creating CustomResourceDefinition "operatorgroups.operators.coreos.com"
INFO[0022] Creating CustomResourceDefinition "operators.operators.coreos.com"
INFO[0022] Creating CustomResourceDefinition "subscriptions.operators.coreos.com"
INFO[0022] Creating Namespace "olm"
INFO[0023] Creating Namespace "operators"
INFO[0023] Creating ServiceAccount "olm/olm-operator-serviceaccount"
INFO[0023] Creating ClusterRole "system:controller:operator-lifecycle-manager"
INFO[0023] Creating ClusterRoleBinding "olm-operator-binding-olm"
INFO[0024] Creating OLMConfig "cluster"
INFO[0025] Creating Deployment "olm/olm-operator"
INFO[0025] Creating Deployment "olm/catalog-operator"
INFO[0025] Creating ClusterRole "aggregate-olm-edit"
INFO[0026] Creating ClusterRole "aggregate-olm-view"
INFO[0026] Creating OperatorGroup "operators/global-operators"
INFO[0026] Creating OperatorGroup "olm/olm-operators"
INFO[0027] Creating ClusterServiceVersion "olm/packageserver"
INFO[0027] Creating CatalogSource "olm/operatorhubio-catalog"
INFO[0027] Waiting for deployment/olm-operator rollout to complete
INFO[0028] Waiting for Deployment "olm/olm-operator" to rollout: 0 of 1 updated replicas are available
INFO[0030] Deployment "olm/olm-operator" successfully rolled out
INFO[0030] Waiting for deployment/catalog-operator rollout to complete
INFO[0030] Deployment "olm/catalog-operator" successfully rolled out
INFO[0030] Waiting for deployment/packageserver rollout to complete
INFO[0031] Waiting for Deployment "olm/packageserver" to rollout: 0 of 2 updated replicas are available
INFO[0036] Deployment "olm/packageserver" successfully rolled out
INFO[0042] Successfully installed OLM version "latest" olm CatalogSource Installed

(3) Verify the CRDs installed.

% kubectl get crds

The output is:

NAME                                            NAMESPACE    KIND                        STATUS
catalogsources.operators.coreos.com CustomResourceDefinition Installed
clusterserviceversions.operators.coreos.com CustomResourceDefinition Installed
installplans.operators.coreos.com CustomResourceDefinition Installed
olmconfigs.operators.coreos.com CustomResourceDefinition Installed
operatorconditions.operators.coreos.com CustomResourceDefinition Installed
operatorgroups.operators.coreos.com CustomResourceDefinition Installed
operators.operators.coreos.com CustomResourceDefinition Installed
subscriptions.operators.coreos.com CustomResourceDefinition Installed
olm Namespace Installed
operators Namespace Installed
olm-operator-serviceaccount olm ServiceAccount Installed
system:controller:operator-lifecycle-manager ClusterRole Installed
olm-operator-binding-olm ClusterRoleBinding Installed
cluster OLMConfig Installed
olm-operator olm Deployment Installed
catalog-operator olm Deployment Installed
aggregate-olm-edit ClusterRole Installed
aggregate-olm-view ClusterRole Installed
global-operators operators OperatorGroup Installed
olm-operators olm OperatorGroup Installed
packageserver olm ClusterServiceVersion Installed
operatorhubio-catalog olm CatalogSource Installed

Create Operator Group for IBM App Connect Operator

(1) Create a namespace ace of App Connect Operator

% kubectl create namespace ace

(2) Create OperatorGroup (ace as the namespace) using the yaml file below

## 
## appconn-operator-group.yaml
##
apiVersion: operators.coreos.com/v1
kind: OperatorGroup
metadata:
name: ace-operator-group
namespace: ace
spec:
targetNamespaces:
- ace
% kubectl apply -f appconn-operator-group.yaml

Create the IBM App Connect Operator catalog

(1) Create a CatalogSource object for the IBM App Connect Operator using the yaml file below.

## 
## appconn-catalog-source.yaml
##
apiVersion: operators.coreos.com/v1alpha1
kind: CatalogSource
metadata:
name: ibm-appconnect-catalog
namespace: olm
spec:
displayName: "IBM App Connect Operator Catalog k8S"
publisher: IBM
sourceType: grpc
image: icr.io/cpopen/appconnect-operator-catalog-k8s
updateStrategy:
registryPoll:
interval: 45m
grpcPodConfig:
securityContextConfig: restricted
% kubectl apply -f appconn-catalog-source.yaml -n olm

(2) Verify the installation.

% kubectl get CatalogSources ibm-appconnect-catalog -n olm
NAME DISPLAY TYPE PUBLISHER AGE
ibm-appconnect-catalog IBM App Connect Operator Catalog k8S grpc IBM 2m21s

(3) If there is problem, check the pods and CatalogSource resources

% kubectl get catalogsource,pods -n olm
NAME DISPLAY TYPE PUBLISHER AGE
catalogsource.operators.coreos.com/ibm-appconnect-catalog IBM App Connect Operator Catalog k8S grpc IBM 4m6s
catalogsource.operators.coreos.com/operatorhubio-catalog Community Operators grpc OperatorHub.io 5h32m

NAME READY STATUS RESTARTS AGE
pod/catalog-operator-655fb46cd4-gzfvn 1/1 Running 0 5h32m
pod/ibm-appconnect-catalog-vjdsj 1/1 Running 0 4m6s
pod/olm-operator-67fdb4b99d-sdklb 1/1 Running 0 5h32m
pod/operatorhubio-catalog-jbmkg 1/1 Running 0 5h32m
pod/packageserver-586d76ddcf-9rhbp 1/1 Running 0 5h32m
pod/packageserver-586d76ddcf-cc4mx 1/1 Running 0 5h32m

Create the IBM App Connect Operator subscription

(1) Create Subscription object for IBM App Connect Operator.

##
## appconn-sub.yaml
##
kind: Subscription
metadata:
name: ibm-appconnect
namespace: ace
spec:
channel: v7.2
name: ibm-appconnect
source: ibm-appconnect-catalog
sourceNamespace: olm
% kubectl apply -f appconn-sub.yaml

(2) Check progress of installation — view the logs for the Catalog Operator pod in the olm namespace.

% kubectl logs catalog-operator-655fb46cd4-gzfvn -n olm

Add entitlement key to namespace

(1) Obtain the entitlement key from this IBM Container software library.

(2) Create a secret that holds the entitlement key.

% oc create secret docker-registry ibm-entitlement-key \
--docker-username=cp \
--docker-password=myEntitlementKey \
--docker-server=cp.icr.io \
--namespace=ace

Creating ingress definitions for external access to your IBM App Connect instances

(1) Create namespace for ingress

% kubectl create namespace ingress

(2) Add the NGINX ingress controller chart repository and then update all Helm repositories in your system.

% helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
% helm repo update

(3) Install the Helm chart in the ingress namespace.

% helm install nginx-ingress ingress-nginx/ingress-nginx \
--namespace ingress \
--set controller.replicaCount=2 \
--set controller.nodeSelector."beta\.kubernetes\.io/os"=linux \
--set defaultBackend.nodeSelector."beta\.kubernetes\.io/os"=linux \
--set controller.admissionWebhooks.patch.nodeSelector."beta\.kubernetes\.io/os"=linux

Result output:

NAME: nginx-ingress
LAST DEPLOYED: Fri Mar 24 22:31:05 2023
NAMESPACE: ingress
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
The ingress-nginx controller has been installed.
It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status by running 'kubectl --namespace ingress get services -o wide -w nginx-ingress-ingress-nginx-controller'

(4) To check the status for the Load Balancer IP.

% kubectl --namespace ingress get services -o wide nginx-ingress-ingress-nginx-controller
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
nginx-ingress-ingress-nginx-controller LoadBalancer 10.0.169.121 xxx.xxx.xxx.xxx 80:30461/TCP,443:30688/TCP 4m6s app.kubernetes.io/component=controller,app.kubernetes.io/instance=nginx-ingress,app.kubernetes.io/name=ingress-nginx

(5) Note down the external IP address. We will used this to configure our Ingress objects later.

Deploy App Connect Dashboard

(1) Create Storage Class for writing purpose.

##
## my-azurefile-csi-premium.yaml
##
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: my-azurefile-csi-premium
provisioner: kubernetes.io/azure-file
mountOptions:
- mfsymlinks
- actimeo=30
- dir_mode=0777
- file_mode=0777
- uid=1000
- cache=strict
parameters:
skuName: Premium_LRS
reclaimPolicy: Delete
volumeBindingMode: Immediate
% oc apply -f my-azurefile-csi-premium.yaml

(2) Create App Connect Dashboard. See https://ibm.biz/acelicense for license and use fields.

##
## appconn-ace-dashboard.yaml
##
apiVersion: appconnect.ibm.com/v1beta1
kind: Dashboard
metadata:
name: ace-dashboard
namespace: ace
spec:
license:
accept: true
license: L-APEH-CJUCNR
use: AppConnectEnterpriseNonProductionFREE
pod:
containers:
content-server:
resources:
limits:
cpu: 250m
memory: 512Mi
requests:
cpu: 50m
memory: 50Mi
control-ui:
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 50m
memory: 125Mi
replicas: 1
storage:
size: 5Gi
type: persistent-claim
class: my-azurefile-csi-premium
useCommonServices: false
version: '12.0.7-lts'
% kubectl apply -f appconn-ace-dashboard.yaml  -n ace

(3) Create ingress route for App Connect Dashboard. Since you do not have DNS, we will use nip.io to configure the host name. Use the External IP you have noted earlier.

##
## appconn-ingress-dashboard.yaml
##
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
name: ace-dashboard-ingress
namespace: ace
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/backend-protocol: HTTPS
spec:
tls:
- hosts:
- ace-dashboard.XXX.XXX.XXX.XXX.nip.io
rules:
- host: ace-dashboard.XXX.XXX.XXX.XXX.nip.io
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: ace-dashboard-dash
port:
number: 8300
% kubectl apply -f appconn-ingress-dashboard.yaml -n ace

(4) Check the status of the Dashboard.

% kubectl get dashboard -n ace
NAME RESOLVEDVERSION REPLICAS CUSTOMIMAGES STATUS URL AGE
ace-dashboard 12.0.7.0-r4 1 false Ready https:// 11h

(5) Finally, you can access the Dashboard using the URL

https://ace-dashboard.XXX.XXX.XXX.XXX.nip.io

Deploy App Connect Integration Server

(1) Before we start, we are going to use this sample BAR file.

https://github.com/khongks/cp4i-ace-books/raw/main/BARfiles/Books.bar

(2) Create a Configuration object that contains authentication information to git repository.

##
## github-barauth.yaml
##
apiVersion: appconnect.ibm.com/v1beta1
kind: Configuration
metadata:
name: github-barauth
namespace: ace
spec:
description: Stores bar auth
data: eyJhdXRoVHlwZSI6IkJBU0lDX0FVVEgiLCJjcmVkZW50aWFscyI6eyJ1c2VybmFtZSI6IiIsInBhc3N3b3JkIjoiIn19Cg==
type: baraut
% oc apply -f github-barauth.yaml -n ace

Note that the data field contains a base64 encoding of the authentication information.

{"authType":"BASIC_AUTH","credentials":{"username":"","password":""}}

(3) Create App Connect Integration Server. See https://ibm.biz/acelicense for license and use fields.

##
## appconn-ingress-intserverhttp.yaml
##
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ace-books-ingress
namespace: ace
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/backend-protocol: HTTP
spec:
tls:
- hosts:
- ace-books.xxx.xxx.xxx.xxx.nip.io
rules:
- host: ace-books.xxx.xxx.xxx.xxx..nip.io
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: ace-books-is
port:
number: 7800

(4) Check the status of the Integration Server.

% kubectl get integrationserver -n ace
NAME RESOLVEDVERSION REPLICAS AVAILABLEREPLICAS CUSTOMIMAGES STATUS AGE
ace-books 12.0.7.0-r4 1 1 false Ready 11h

(5) Finally, you can test the REST API running on the Integration Server.

curl -kv https://ace-books.xxx.xxx.xxx.xxx..nip.io/api/v1/books

Reference Links:

https://community.ibm.com/community/user/integration/blogs/joel-gomez1/2022/02/15/installing-the-ibm-app-connect-operator-on-amazon

https://learn.microsoft.com/en-us/troubleshoot/azure/azure-kubernetes/connection-issues-application-hosted-aks-cluster

--

--

Kok Sing Khong
Kok Sing Khong

Responses (2)