Building Extensions for Zowe containerization
{Core} If you have read our other blog about Open Mainframe Project’s Zowe Kubernetes Overview, you may have grabbed the idea of what is container and Kubernetes and how to run Zowe in Kubernetes. In this blog we will explain how to build and use the extensions in Zowe containerization.
Following are the major steps to build and use the Zowe extensions in K8s Environment.
1. Build and create an extension image.
An extension must have a container image to run in a Zowe container environment. To create such images, you need to:
a) prepare docker build context, using a shell script, that will provide reference to the files and directories, needed to build the docker image.
b) write a Dockerfile, to create the docker image using the docker build context.
2. Publish the extension image to a registry
After a component image is built, it is recommended that you publish it to a container registry before adding it to the Zowe container environment. Alternatively, you can use docker save and docker load commands to copy the offline images to your Kubernetes nodes.
3. Define a deployment or job object.
To start your component in Kubernetes, you must define a Deployment if your extension has built-in web services, or a Job object if your extension is a Zowe Application Framework plug-in without built-in web services.
4 .Start the extension from the deployment or job definition.
After you define your component Deployment or Job object, you can run kubectl apply -f /path/to/your/component.yaml to apply it to the Kubernetes cluster that runs Zowe.
- If it’s a Deployment, you should be able to see that the component pod is started and eventually reached the Running status.
- If it’s a Job, you should be able to see that the plug-in pod is started and eventually reached the Completed status.
Now you can follow common Kubernetes practice to manage your component workload.
# Example:
This example will show, how the docker image of sample-node-api extension is created and used in the Zowe’s Kubernetes environment.
1. Build and create an extension image to a registry.
a) We have created a file prepare.sh, to prepare the docker build context, which accepts two parameters linux-distro and cpu-arch.
Execution of this script will:
- copy the Dockerfile to /container/linux-ditro/cpu-arch folder.
- copy other necessary files, such as LICENCE, package.json, package-lock.json and readme.md to /container/linux-ditro/cpu-arch/component folder.
- build the source code and copy the content of /dist folder /dist folder /container/linux-ditro/cpu-arch/component location. ( /dist contains the source code and /bin folder, that gets copies at the time of build)
- prepare the manifest.yaml and Dockerfile files needed to create docker image.
Typically this script is called by a Github Actions action (zowe-actions/docker-prepare), an example is provided at here.
b) We have created a DockerFile, that has steps to create the docker image of sample-node-api extension, using the docker build context and building it via npm install — only=prod.
This Dockerfile has two instructions:
i. ENTRYPOINT =[ “bin/start.sh” ]. This instruction allows you to configure a container that will run as an executable.
ii. EXPOSE 18000. It exposes the port 18000 with a TCP protocol inside a Docker Container.In the simplest term, the EXPOSE instruction tells Docker to get all its information required during the runtime from a specified Port.
2. Publish the extension image to a registry.
We have used the Github Actions workflow sample-node-api-images.yml to create and release the sample-node-api extension’s docker image. In order to release the images, run this workflow with release input value set as true.
This workflow, contains the job steps:
- to create ubuntu-amd64 and ubuntu-s390x docker images and their manifest.
- to create ubi-amd64 and ubi-s390x docker images and their manifest.
The following GitHub Actions are used by the core components to build conformant images. They might not be completely reusable for you, but are provided as an example.
- zowe-actions/shared-actions/docker-prepare will prepare required environment variables used by following steps.
- zowe-actions/shared-actions/docker-build-local can build the Docker image directory on the GitHub Actions virtual machine. By default, the Docker image directory is ubuntu-latest. You can use this action to build images for amd64 CPU architecture.
- zowe-actions/shared-actions/docker-build-zlinux can build Docker image on a Linux on Z virtual machine. This is useful if you want to build images for s390x CPU architecture.
- zowe-actions/shared-actions/docker-manifest can collect all related images and define them as Docker manifests. This is useful for users to automatically pull the correct image based on cluster node CPU architecture, and also pull images based on popular tags such as latest and latest-ubuntu.
3. Define a deployment or job object.
To use and start the sample-node-api extension in Kubernetes, you have to define a Deployment if your extension has built-in web services, or a Job object if your extension is a Zowe Application Framework plug-in without built-in web services.
In this example we have used the former scenario i.e. creating the deployment and created a Deployment file named as sample-node-api.yml.
This deployment fulfills the following purposes:
— pulls the specified docker image of sample-node-api defined under containers.name.image.
— sets the memory and cpu lower and upper limits required to run this container.
— specifies the container port to be exposed and the protocol. In this case it is 18000.
How to create/define the deployment :
To define Deployment for your component, you can copy from samples/sample-deployment.yaml and modify all occurrences of the following variables:
- <my-component-name>: this is your component name. For example, sample-node-api.
- <my-component-image>: this is your component image described in Build and publish an extension image to a registry. For example, zowe-docker-release.jfrog.io/ompzowe/sample-node-api:latest-ubuntu.
- <my-component-port>: this is the port of your service. For example, 18000.
Continue to customize the specification to fit in your component requirements:
- spec.template.spec.containers[0].resources: defines the memory and CPU resource required to start the container.
- metadata.annotations, spec.template.spec.volumes and spec.template.spec.securityContext and so on.
To define Job for your component, you can also copy from samples/sample-deployment.yaml. Then, modify all entries mentioned above and make the following changes:
- Change kind: Deployment to kind: Job,
- Add restartPolicy: OnFailure under spec.template.spec.
4 .Start the extension from the deployment or job definition.
After you define your component Deployment or Job object, you can run kubectl apply -f /container/sample-node-api.yml to apply it to the Kubernetes cluster that runs Zowe.
Now you should be able to see that the component pod is started and eventually reached the Running status.
If you enjoyed this blog checkout more Zowe blogs here. Or, ask a question and join the conversation on the Open Mainframe Project Slack Channel #Zowe-dev, #Zowe-user or #Zowe-onboarding. If this is your first time using the Open Mainframe Project Slack, register here.