API Gateway meets OpenShift

Introduction

The purpose of this tutorial is to show how the API Gateway v10.5 Docker image from DockerHub can be deployed on an OpenShift cluster. The API Gateway image available on DockerHub is a fully functional free trial version limited to 90 days for non-production use.

About OpenShift

OpenShift is a platform that is based on Kubernetes, and it extends Kubernetes with own API objects and algorithms. In a nutshell, beyond Kubernetes' ability of orchestrating containerized applications, Openshift provides support for the complete CI/CD lifecycle of applications. For example, OpenShift can download the application sources from a GiT repository, build the application, package the application into a Docker image, and finally deploy the image and schedule it for execution. Of course there is a lot more, have a look at the Openshift home page and the OpenShift developer guide (v4.3 at the time of writing this article).

In particular, it is also possible to deploy already available docker images that have not been built by OpenShift, and this is the use case for this tutorial.

What is the difference to plain Kubernetes ?

It is possible to run the API Gateway Dockerhub image on a Kubernetes cluster, for example by describing it as a Deployment, so why are there special considerations for OpenShift? Actually with regard to API Gateway, there are two technical topics that have a specific solution for OpenShift.

ElasticSearch

The API Gateway Dockerhub image comes with an embedded ElasticSearch, and ElasticSearch is known to require a large virtual memory mmap count which needs to be available on the host system that runs the Docker container:

vm.max_map_count=262144

This is typically not available out of the box, and root permissions are required to change it. In a plain Kubernetes cluster this would usually be solved by adding a so-called initContainer to the pod specification, and the initContainer would run with root permissions and call sysctl to set the required mmap count.

OpenShift provides a very simple solution for this. Simply add the label tuned.openshift.io/elasticsearch to the pod specification:

  spec:
    template:
      metadata:
        labels:
          tuned.openshift.io/elasticsearch: ""

An OpenShift cluster has a daemon in the background which continuously monitors the active pods, and as soon as a pod appears with this label the daemon will set the mmap count on the current worker host to a value sufficient for ElasticSearch.

Container users

The second topic requiring attention is the management of container users that is imposed by OpenShift.

By default, OpenShift will ignore the user that is built into a Docker image (the so-called sagadmin user in case of the API gateway Docker image). Rather, when the container is started, OpenShift will inject an arbitrary generated user into the container, and this user is a member of the root group. According to OpenShift this is a security feature, which among others prevents images that are built with the root user to run in the cluster.

The API Gateway image meets the OpenShift expectations, which basically means that the relevant parts of the file system have permissions such that any member of the root group can perform the necessary operations (e.g., running scipts, writing to the file system, etc.).

Detailed steps

With that background the steps to deploy the API Gateway Dockerhub image on OpenShift are pretty straight forward. The description below assumes that you have the oc OpenShift command line tool available.

Create a new project

oc new-project apigateway-trial

Create a secret for DockerHub access

As the API Gateway Dockerhub image can only be accessed by logging into DockerHub the necessary credentials need to be made available via a secret. The secret needs to be linked to the service account that will start the pod. In our setup the OpenShift default service account is used, the name of which happens to be default:

oc create secret docker-registry hub-secret --docker-server=https://index.docker.io/v1/ --docker-username=<docker-hub-id> --docker-password=<pass> --docker-email=""
oc secrets link default hub-secret --for=pull

Create a template for the API Gateway deployment

The rest is more or less known from Kubernetes, or similar to Kubernetes. The following YAML objects need to be created:

  • a DeploymentConfig (OpenShift's specialized version of a Kubernetes Deployment)
  • a Service to make the API Gateway accessible within the cluster
  • Routes to make the service and its ports visible outside the cluster

In OpenShift, these YAML artefacts can be collected in a so-called template. The template also has a variable section for named variables and their default values. The YAML artefacts can use these variables with a ${PARAM} notation. When the template will be deployed from the command line the default values can be overwritten, so that for example the API Gateway can easily be deployed under a different name. For more details see the OpenShift template documentation (v4.3 at the time of writing this article).

Download the complete template from the attachment section.

The DeploymentConfig

Beyond the usual boilerplate settings for deployments these are the special settings for the API Gateway:

  • the tuned.openshift.io/elasticsearch label,
  • liveness and readiness probes,
  • resource requirements that allow OpenShift to deploy the pods on worker nodes that have sufficient resources available.
    In particular, as the free trial image comes with an embedded ElasticSearch, there is a high memory requirement.

Note that the Docker image is not addressed directly, but rather via an ImageStreamTag.

  apiVersion: apps.openshift.io/v1
  kind: DeploymentConfig
  metadata:
    name: ${NAME}
  spec:
    replicas: 1
    revisionHistoryLimit: 10
    selector:
      deploymentconfig: ${NAME}
    strategy:
      activeDeadlineSeconds: 21600
      resources: {}
      rollingParams:
        intervalSeconds: 1
        maxSurge: 25%
        maxUnavailable: 25%
        timeoutSeconds: 600
        updatePeriodSeconds: 1
      type: Rolling
    template:
      metadata:
        labels:
          deploymentconfig: ${NAME}
          tuned.openshift.io/elasticsearch: ""
      spec:
        containers:
        - imagePullPolicy: IfNotPresent
          name: ${NAME}
          ports:
          - containerPort: 5555
            protocol: TCP
          - containerPort: 9072
            protocol: TCP
          - containerPort: 9999
            protocol: TCP
          resources:
            requests:
              memory: 4G
              cpu: 100m
          terminationMessagePath: /dev/termination-log
          terminationMessagePolicy: File
          livenessProbe:
            failureThreshold: 4
            initialDelaySeconds: 90
            periodSeconds: 10
            successThreshold: 1
            tcpSocket:
              port: 5555
            timeoutSeconds: 2
          readinessProbe:
            failureThreshold: 3
            httpGet:
              path: /rest/apigateway/health
              port: 5555
              scheme: HTTP
            initialDelaySeconds: 90
            periodSeconds: 10
            successThreshold: 2
            timeoutSeconds: 2
        dnsPolicy: ClusterFirst
        restartPolicy: Always
        schedulerName: default-scheduler
        securityContext: {}
        terminationGracePeriodSeconds: 30
    triggers:
    - type: ConfigChange
    - imageChangeParams:
        automatic: true
        containerNames:
        - ${NAME}
        from:
          kind: ImageStreamTag
          name: apigateway-trial:${IMAGE_TAG}
      type: ImageChange

The ImageStream

The ImageStream represents the Docker image to be started by the DeploymentConfig. In partilular, it contains the fully qualified image name:

kind: ImageStream
apiVersion: image.openshift.io/v1
metadata:
  name: apigateway-trial
spec:
  lookupPolicy:
    local: false
  tags:
  - from:
      kind: DockerImage
      name: store/softwareag/apigateway-trial:${IMAGE_TAG}
    importPolicy: {}
    name: '10.5'
    referencePolicy:
      type: Source

The Service

The service exposes the well-known ports for API Gateway and the underlying Integration server:

  apiVersion: v1
  kind: Service
  metadata:
    name: ${NAME}
  spec:
    ports:
    - name: 5555-tcp
      port: 5555
      protocol: TCP
      targetPort: 5555
    - name: 9072-tcp
      port: 9072
      protocol: TCP
      targetPort: 9072
    - name: 9999-tcp
      port: 9999
      protocol: TCP
      targetPort: 9999
    selector:
      deploymentconfig: ${NAME}
    sessionAffinity: None
    type: ClusterIP

The Routes

In order to work with the API gateway from outside the cluster we need to expose port 9072 for the API gateway UI, and port 5555 for REST calls to the API Gateway as well as for the administration UI of the Integration server. In OpenShift this is achieved with routes, which assign a DNS name to each of the ports. The DNS name should be based on the cluster URL. For example, when you used api.myopenshift.org to login to the oc command line tool, then your route DNS names should have the suffix .apps.myopenshift.org. In a typical setup the DNS system will be configured such that the name *.apps.myopenshift.org can be resolved. On case of doubt contact your friendly OpenShift cluster administrator.

  apiVersion: route.openshift.io/v1
  kind: Route
  metadata:
    name: ${GATEWAY_ROUTE_NAME}
  spec:
    host: ${GATEWAY_ROUTE_NAME}.apps.${CLUSTER_BASE_URL}
    port:
      targetPort: 9072-tcp
    subdomain: ""
    to:
      kind: Service
      name: ${NAME}
      weight: 100
    wildcardPolicy: None           

  apiVersion: route.openshift.io/v1
  kind: Route
  metadata:
    name: ${IS_ROUTE_NAME}
  spec:
    host: ${IS_ROUTE_NAME}.apps.${CLUSTER_BASE_URL}
    port:
      targetPort: 5555-tcp
    subdomain: ""
    to:
      kind: Service
      name: ${NAME}
      weight: 100
    wildcardPolicy: None

Deploy the template

Now deploy the template using your cluster base URL and watch the API Gateway pod starting. Inspect the template to see whether you like the default values, and override them on the command line with the -p option.

# deploy template
oc process -f apigateway-dockerhub-template.yaml -p CLUSTER_BASE_URL="myopenshift.org" | oc apply -f - 

# watch the pod
oc get pods

Access the API Gateway

Once the API Gateway pod reports as "Running" and "Ready 1/1" the API Gateway UI can be accessed. With the default settings in the template the route DNS name has been created as apigateway-ui.apps.myopenshift.org. Paste the URL into your favorite browser and login to the API Gateway UI.

Free Trial Restrictions

Full-featured version of the webMethods API Gateway, free trial is limited to 90 days for non-production use.

License

License terms for this product can be found here: http://www.softwareag.com/license

If you wish to purchase a commercial license for webMethods API Gateway, please contact us here: http://www.softwareag.com/contact

Base Image

This product references the official CentOS (https://store.docker.com/images/centos) image as its base image. Software AG is not responsible for the contents of this base image.

Attachments

apigateway-dockerhub-template.zip