App Connect

App Connect

Join this online user group to communicate across IBM product users and experts by sharing advice and best practices with peers and staying up to date regarding product enhancements.

 View Only

Introduction to Serverless with the App Connect Operator

By Rob Convery posted Tue November 29, 2022 06:59 AM

  

With the release of the latest IBM App Connect operator v6.2.0 we have introduced a new resource type - an "IntegrationRuntime". For those familiar with the existing IntegrationServer resource, consider this as an IntegrationServer++. It will be able to do everything that an IntegrationServer did and more. This blog is going to concentrate on one of the new "+" features we have introduced support for - Serverless.

What is Serverless

Before diving into the implementation in our operator it's worth a few words to summarise that server less is and how it can help your systems.

Serverless architecture is ideal for asynchronous, stateless apps that can be started instantaneously. Likewise, serverless is a good fit for use cases that see infrequent, unpredictable surges in demand.

Think of a task like batch processing of incoming image files, which might run infrequently but also must be ready when a large batch of images arrives all at once. Or a task like watching for incoming changes to a database and then applying a series of functions, such as checking the changes against quality standards, or automatically translating them.

Serverless apps are also a good fit for use cases that involve incoming data streams, chat bots, scheduled tasks, or business logic.

For further information on server less please refer to https://developer.ibm.com/learningpaths/get-started-serverless/

There are many different server less technologies and different styles of transaction require different technologies i.e. integrations driven via http requests may use kNative Serving where as an Integration driven by messages appearing on a queue may be driven by Keda.

Serverless with App Connect

The first server less capacity with the App Connect offering is the ability to run Designer "Flows for API" bar files in a kNative serverless environment.

To start with this capability is only available using our FREE licenses i.e. AppConnectEnterpriseNonProductionFREE and CloudPakForIntegrationNonProductionFREE and thus cannot be deployed to production environments but hopefully this will enable you to try out the technology and provide feedback on your experience.



Worked Example

I have developed a flow in Designer Authoring which provides my customers an API to be able to query my local weather station. I don't expect many people to use the API and so don't want to have an Integration Runtime running all the time. To provide this capability I am going to deploy an IntegrationRuntime with server less enabled.

Installing kNative.

To enable the server less capability some extra prerequisite need to be installed.

1. Find the "Red Hat OpenShift Serverless" operator in the OperatorHub


2. Install the operator using the default options. This will result in the operator being installed cluster wise. Once installed it will create a project called "knative-serving"

3. Create an instance of kNative Serving by deploying the following yaml (via yaml or the Redhat UI)

apiVersion: operator.knative.dev/v1alpha1
kind: KnativeServing
metadata:
name: knative-serving
namespace: knative-serving
spec: {}

You can check if it's all configured by running oc get knativeserving.operator.knative.dev/knative-serving -n knative-serving --template='{{range .status.conditions}}{{printf "%s=%s\n" .type .status}}{{end}}'. When it returns "Ready=True" continue.

4. There are a couple of kNative features that we need to enable to allow the App Connect operator to function correctly - EmptyDir and FieldRef support.
To enable this on a knative installation you will need to edit a ConfigMap. This can be found in the knative-serving namespace with the name config-features. Note when editing the configmap it may warn about it being owned, this is OK and you can save the file without concern
Uncomment and update the following flag - kubernetes.podspec-volumes-emptydir: enabled
Uncomment and update the following flag - kubernetes.podspec-fieldref: enabled

5. One of the requirements of using App Connect with kNative is a pullSecret needs to be defined to access the App Connect images. Obtain an Entitlement key from IBM Container Library. Create a docker registry secret using the following command: oc create secret docker-registry ibm-entitlement-key --docker-username=cp --docker-password=<entitlement-key> --docker-server=cp.icr.io --namespace=<target namespace>

NOTE: If you already have a global secret configure which provides access to all required images you must still create a secret called "ibm-entitlement-key" but you can include random data i.e. oc create secret docker-registry ibm-entitlement-key --docker-username=random --docker-password=random --docker-server=random

Deploying your application


Install the App Connect operator as per the documentation at https://www.ibm.com/docs/en/app-connect/containers_cd?topic=overview

Obtain a bar file for you Application by exporting it from Designer Authoring - For further information on this please refer to https://www.ibm.com/docs/en/app-connect/containers_cd?topic=servers-exporting-flow-bar-file. For this tutorial the bar file has been uploaded to a file repository (Artifactory) but you can also upload it to an ACE Dashboard and use the BarURL to refer to it.

As the barflies is on an exeternal repository we need to provide credentials to access it. This is done by creating a Configuration resource of type barauth, which contains the username and password to your endpoint. First, create the JSON content that contains the appropriate credentials:

{"authType":"BASIC_AUTH","credentials":{"username":"fakeuser@uk.ibm.com","password":"fakePassword"}}

Next, Base64-encode this content to enable it to be embedded in the Configuration resource: echo '{"authType":"BASIC_AUTH","credentials":{"username":"fakeuser@uk.ibm.com","password":"fakePassword"}}' | base64

Finally, define the Configuration resource values by using YAML code such as this. Note that **spec.data** is used to specify the generated Base64-encoded value.

apiVersion: appconnect.ibm.com/v1beta1
kind: Configuration
metadata:
name: artifactory-creds
namespace: ace
spec:
type: barauth
description: Credentials for Artifactory
data: eyJhdXRoVHlwZSI6IkJBU0lDX0FVVEgiLCJjcmVkZW50aWFscyI6eyJ1c2VybmFtZSI6ImZha2V1c2VyQHVrLmlibS5jb20iLCJwYXNzd29yZCI6ImZha2VQYXNzd29yZCJ9fQo=


This results in a new configuration object called artifactory-creds. If you look at the resource YAML code, you'll see that it's been updated with a new field called `secretName`, which is a reference to the secret that now contains the credentials.

For this example the Integration flow needs to access an external system. This requires some account information so a configuration called "httpaccount" has been created. For further information on creating account configurations please refer to xxxx

Next create the IntegrationServer CR as per below:

apiVersion: appconnect.ibm.com/v1beta1
kind: IntegrationRuntime
metadata:
name: weatherstation
namespace: ace
spec:
license:
accept: true
license: L-APEH-CJUCNR
use: AppConnectEnterpriseProduction
flowType:
designerAPIFlow: true
logFormat: basic
barURL:
- https://na.artifactory.swg-devops.com/artifactory/appconnect-iib/acecc/test/weatherstation.bar
serverless:
knativeService:
enabled: true
forceFlowBasicAuth:
enabled: true
configurations:
- httpaccount
- artifactory-creds
version: '12.0'


Once created you should be able to see the IntegrationRuntime in the Redhat UI


After a short period of time the phase should switch to "Ready"

Once the IntegrationRuntime is ready you can also view the kNativeService that has been created. This is the definition of the resource which enables your integration to be server less.

The next area to check are the running pods. You should see no pods in relation to your deployed resource. If the same flow was deployed with serverless disabled you would observe a running pod. (There may be other pods if you have other resources such as a local operator, dashboard etc)


Testing your API


Using the IntegrationRuntime CR you can find out your Integrations endpoint by running the command
oc get IntegrationRuntime/weatherstation --output="jsonpath={.status.endpoints[].uri}" - this will return the base URL of your integration. Use this combined with the path configured in your Integration to build the endpoint you need to connect to i.e.

oc get IntegrationRuntime/weatherstation --output="jsonpath={.status.endpoints[].uri}
https://weatherstation-ir-ace.apps.acecc.cp.fyre.ibm.com

The path to the api is stokeparkwoodweather/stokeparkwoodweather/1 thus the url is https://weatherstation-ir-ace.apps.acecc.cp.fyre.ibm.com/stokeparkwoodweather/stokeparkwoodweather/1

As mentioned previously by default there will be no running pod. When you make a request to your API, kNative will start a pod to allow your api to process the request. The first request can sometimes take a little longer to respond because it needs to start up the IntegrationRuntime from scratch. Any subsequent request would be near instant. The pod will then stay up for a period of time (approx 5 minutes by default) .

Send some messages through your API

root@jumpbox1:~# time curl -k https://weatherstation-ir-ace.apps.acecc-monza-clusterwide.cp.fyre.ibm.com/stokeparkwoodweather/stokeparkwoodweather/1

{"id":"weather {\"station_id\":33047,\"station_name\":\"Rosewood\",\"public_name\":\"Stoke Park Wood\",\"latitude\":50.97088,\"longitude\":-1.31891,\"timezone\":\"Europe/London\",\"elevation\":19.812,\"is_public\":true,\"status\":{\"status_code\":0,\"status_message\":\"SUCCESS\"},\"station_units\":{\"units_temp\":\"c\",\"units_wind\":\"mph\",\"units_precip\":\"mm\",\"units_pressure\":\"hpa\",\"units_distance\":\"mi\",\"units_direction\":\"cardinal\",\"units_other\":\"imperial\"},\"outdoor_keys\":[\"timestamp\",\"air_temperature\",\"barometric_pressure\",\"station_pressure\",\"pressure_trend\",\"sea_level_pressure\",\"relative_humidity\",\"precip\",\"precip_accum_last_1hr\",\"precip_accum_local_day\",\"precip_accum_local_yesterday\",\"precip_minutes_local_day\",\"precip_minutes_local_yesterday\",\"wind_avg\",\"wind_direction\",\"wind_gust\",\"wind_lull\",\"solar_radiation\",\"uv\",\"brightness\",\"lightning_strike_last_epoch\",\"lightning_strike_last_distance\",\"lightning_strike_count\",\"lightning_strike_count_last_1hr\",\"lightning_strike_count_last_3hr\",\"feels_like\",\"heat_index\",\"wind_chill\",\"dew_point\",\"wet_bulb_temperature\",\"wet_bulb_globe_temperature\",\"delta_t\",\"air_density\"],\"obs\":[{\"timestamp\":1669400681,\"air_temperature\":7.6,\"barometric_pressure\":1019.3,\"station_pressure\":1019.3,\"sea_level_pressure\":1022.1,\"relative_humidity\":90,\"precip\":0.0,\"precip_accum_last_1hr\":0.0,\"precip_accum_local_day\":0.0,\"precip_accum_local_yesterday\":2.046751,\"precip_minutes_local_day\":0,\"precip_minutes_local_yesterday\":54,\"wind_avg\":0.6,\"wind_direction\":297,\"wind_gust\":1.1,\"wind_lull\":0.3,\"solar_radiation\":0,\"uv\":0.0,\"brightness\":0,\"lightning_strike_last_epoch\":1669361334,\"lightning_strike_last_distance\":24,\"lightning_strike_count\":0,\"lightning_strike_count_last_1hr\":0,\"lightning_strike_count_last_3hr\":0,\"feels_like\":7.6,\"heat_index\":7.6,\"wind_chill\":7.6,\"dew_point\":6.1,\"wet_bulb_temperature\":6.8,\"wet_bulb_globe_temperature\":11.5,\"delta_t\":0.8,\"air_density\":1.26477,\"pressure_trend\":\"rising\"}]}"}

real 0m11.633s
user 0m0.015s
sys 0m0.015s

root@jumpbox1:~# time curl -k https://weatherstation-ir-ace.apps.acecc-monza-clusterwide.cp.fyre.ibm.com/stokeparkwoodweather/stokeparkwoodweather/1

{"id":"weather {\"station_id\":33047,\"station_name\":\"Rosewood\",\"public_name\":\"Stoke Park Wood\",\"latitude\":50.97088,\"longitude\":-1.31891,\"timezone\":\"Europe/London\",\"elevation\":19.812,\"is_public\":true,\"status\":{\"status_code\":0,\"status_message\":\"SUCCESS\"},\"station_units\":{\"units_temp\":\"c\",\"units_wind\":\"mph\",\"units_precip\":\"mm\",\"units_pressure\":\"hpa\",\"units_distance\":\"mi\",\"units_direction\":\"cardinal\",\"units_other\":\"imperial\"},\"outdoor_keys\":[\"timestamp\",\"air_temperature\",\"barometric_pressure\",\"station_pressure\",\"pressure_trend\",\"sea_level_pressure\",\"relative_humidity\",\"precip\",\"precip_accum_last_1hr\",\"precip_accum_local_day\",\"precip_accum_local_yesterday\",\"precip_minutes_local_day\",\"precip_minutes_local_yesterday\",\"wind_avg\",\"wind_direction\",\"wind_gust\",\"wind_lull\",\"solar_radiation\",\"uv\",\"brightness\",\"lightning_strike_last_epoch\",\"lightning_strike_last_distance\",\"lightning_strike_count\",\"lightning_strike_count_last_1hr\",\"lightning_strike_count_last_3hr\",\"feels_like\",\"heat_index\",\"wind_chill\",\"dew_point\",\"wet_bulb_temperature\",\"wet_bulb_globe_temperature\",\"delta_t\",\"air_density\"],\"obs\":[{\"timestamp\":1669400681,\"air_temperature\":7.6,\"barometric_pressure\":1019.3,\"station_pressure\":1019.3,\"sea_level_pressure\":1022.1,\"relative_humidity\":90,\"precip\":0.0,\"precip_accum_last_1hr\":0.0,\"precip_accum_local_day\":0.0,\"precip_accum_local_yesterday\":2.046751,\"precip_minutes_local_day\":0,\"precip_minutes_local_yesterday\":54,\"wind_avg\":0.6,\"wind_direction\":297,\"wind_gust\":1.1,\"wind_lull\":0.3,\"solar_radiation\":0,\"uv\":0.0,\"brightness\":0,\"lightning_strike_last_epoch\":1669361334,\"lightning_strike_last_distance\":24,\"lightning_strike_count\":0,\"lightning_strike_count_last_1hr\":0,\"lightning_strike_count_last_3hr\":0,\"feels_like\":7.6,\"heat_index\":7.6,\"wind_chill\":7.6,\"dew_point\":6.1,\"wet_bulb_temperature\":6.8,\"wet_bulb_globe_temperature\":11.5,\"delta_t\":0.8,\"air_density\":1.26477,\"pressure_trend\":\"rising\"}]}"}

real 0m0.340s
user 0m0.014s
sys 0m0.014s

root@jumpbox1:~# time curl -k https://weatherstation-ir-ace.apps.acecc-monza-clusterwide.cp.fyre.ibm.com/stokeparkwoodweather/stokeparkwoodweather/1

{"id":"weather {\"station_id\":33047,\"station_name\":\"Rosewood\",\"public_name\":\"Stoke Park Wood\",\"latitude\":50.97088,\"longitude\":-1.31891,\"timezone\":\"Europe/London\",\"elevation\":19.812,\"is_public\":true,\"status\":{\"status_code\":0,\"status_message\":\"SUCCESS\"},\"station_units\":{\"units_temp\":\"c\",\"units_wind\":\"mph\",\"units_precip\":\"mm\",\"units_pressure\":\"hpa\",\"units_distance\":\"mi\",\"units_direction\":\"cardinal\",\"units_other\":\"imperial\"},\"outdoor_keys\":[\"timestamp\",\"air_temperature\",\"barometric_pressure\",\"station_pressure\",\"pressure_trend\",\"sea_level_pressure\",\"relative_humidity\",\"precip\",\"precip_accum_last_1hr\",\"precip_accum_local_day\",\"precip_accum_local_yesterday\",\"precip_minutes_local_day\",\"precip_minutes_local_yesterday\",\"wind_avg\",\"wind_direction\",\"wind_gust\",\"wind_lull\",\"solar_radiation\",\"uv\",\"brightness\",\"lightning_strike_last_epoch\",\"lightning_strike_last_distance\",\"lightning_strike_count\",\"lightning_strike_count_last_1hr\",\"lightning_strike_count_last_3hr\",\"feels_like\",\"heat_index\",\"wind_chill\",\"dew_point\",\"wet_bulb_temperature\",\"wet_bulb_globe_temperature\",\"delta_t\",\"air_density\"],\"obs\":[{\"timestamp\":1669400741,\"air_temperature\":7.6,\"barometric_pressure\":1019.3,\"station_pressure\":1019.3,\"sea_level_pressure\":1022.1,\"relative_humidity\":90,\"precip\":0.0,\"precip_accum_last_1hr\":0.0,\"precip_accum_local_day\":0.0,\"precip_accum_local_yesterday\":2.046751,\"precip_minutes_local_day\":0,\"precip_minutes_local_yesterday\":54,\"wind_avg\":0.7,\"wind_direction\":283,\"wind_gust\":1.0,\"wind_lull\":0.4,\"solar_radiation\":0,\"uv\":0.0,\"brightness\":0,\"lightning_strike_last_epoch\":1669361334,\"lightning_strike_last_distance\":24,\"lightning_strike_count\":0,\"lightning_strike_count_last_1hr\":0,\"lightning_strike_count_last_3hr\":0,\"feels_like\":7.6,\"heat_index\":7.6,\"wind_chill\":7.6,\"dew_point\":6.1,\"wet_bulb_temperature\":6.8,\"wet_bulb_globe_temperature\":11.5,\"delta_t\":0.8,\"air_density\":1.26477,\"pressure_trend\":\"rising\"}]}"}

real 0m0.371s
user 0m0.014s
sys 0m0.005s


As you can see from the results, the first request took 11 seconds but subsequent requests were sub second.

Below you can see how a pod has been started as a result of the request being made

This is just a small insight to what is possible with knative. There are various tuning parameters available such as controlling how quickly the pod shuts down after its serviced a request etc. Further details on these are available in https://knative.dev/docs/serving/services/. If customisation of the kNative service is required this can be performed via the CR i.e. the example below shows how to change limit the number of replicas.

apiVersion: appconnect.ibm.com/v1beta1
kind: IntegrationRuntime
metadata:
name: weatherstation
namespace: ace
spec:
license:
accept: true
license: L-APEH-CJUCNR
use: AppConnectEnterpriseNonProductionFREE
flowType:
designerAPIFlow: true
logFormat: basic
barURL:
- https://na.artifactory.swg-devops.com/artifactory/appconnect-iib/acecc/test/weatherstation.bar
serverless:
knativeService:
enabled: true
template:
metadata:
annotations:
autoscaling.knative.dev/max-scale: "3"
configurations:
- httpaccount
- artifactory-creds
version: '12.0'
0 comments
122 views

Permalink