This page details how to set up init and sidecar containers on Appian custom resources for self-managed customers.
Init containers run before applications containers run in a pod, and sidecar containers run alongside application containers in a pod. One use for init containers is to bootstrap Appian with RDBMS/JDBC drivers not included in the Webapp Docker image (for example, MySQL or IBM Db2).
Init containers are specialized containers that run before application containers run in a pod. Init containers support many of the features of application containers. Like application containers, init containers can access their Pods' shared storage volumes.
The Appian operator and Appian custom resource definition (CRD) support specifying init containers via the .spec.<COMPONENT>.initContainers
fields on Appian custom resources.
1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: crd.k8s.appian.com/v1alpha1
kind: Appian
metadata:
name: appian-k8s
spec:
serviceManager:
initContainers:
- name: test
image: alpine
command:
- "/bin/sh"
- "-c"
- "echo 'I am an init container'"
To better understand how to use volumes and volume mounts with init containers, see the Specifying Volumes section below.
Init containers for Webapp pods can be used to add JARs to Tomcat's classpath prior to site startup. This is useful, for example, for bootstrapping Appian with RDBMS/JDBC drivers not included in the Webapp Docker image (for example, MySQL or IBM Db2).
Appian configures Tomcat to search for JARs in /usr/local/appian/ae/tomcat/apache-tomcat/lib/ext
. All Webapp pods define a volume mount for the webapp
container in which Tomcat runs from the storage
volume to this directory with a sub-path of ae/tomcat/apache-tomcat/lib/ext
:
1
2
3
- name: storage
subPath: ae/tomcat/apache-tomcat/lib/ext
mountPath: /usr/local/appian/ae/tomcat/apache-tomcat/lib/ext
By defining an init container with the same volume mount, it's possible to bootstrap Tomcat with JARs prior to site startup by placing them in /usr/local/appian/ae/tomcat/apache-tomcat/lib/ext
in the init container. The following custom resource, for example, uses init containers to download the MySQL RDBMS/JDBC driver. Note how it also leverages the tmp
volume so that /tmp
is writable in case the container's file system is read-only.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
apiVersion: crd.k8s.appian.com/v1alpha1
kind: Appian
metadata:
name: appian-k8s
spec:
webapp:
initContainers:
- name: mysql-jdbc-download
image: alpine
command:
- "/bin/sh"
- "-c"
- "set -exo pipefail;
wget https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-5.1.49.tar.gz -O /tmp/mysql-connector-java-5.1.49.tar.gz;
[ \"$(md5sum /tmp/mysql-connector-java-5.1.49.tar.gz | awk '{print $1}')\" == \"e7bc11a55398bad0ea8548163deabaa8\" ];
tar -xzf /tmp/mysql-connector-java-5.1.49.tar.gz -C /tmp;
cp /tmp/mysql-connector-java-5.1.49/mysql-connector-java-5.1.49.jar /usr/local/appian/ae/tomcat/apache-tomcat/lib/ext"
volumeMounts:
- name: storage
subPath: ae/tomcat/apache-tomcat/lib/ext
mountPath: /usr/local/appian/ae/tomcat/apache-tomcat/lib/ext
- name: tmp
mountPath: /tmp
While the init container above uses the alpine Docker image to download the MySQL RDBMS/JDBC driver, it's also possible to build and publish your own image containing the driver instead. Imagine, for example, that you've built the following Dockerfile and published the resulting Docker image as registry.example.com/mysql-jdbc
:
1
2
3
4
5
6
7
8
FROM alpine
RUN \
wget https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-5.1.49.tar.gz -O /tmp/mysql-connector-java-5.1.49.tar.gz && \
[ \"$(md5sum /tmp/mysql-connector-java-5.1.49.tar.gz | awk '{print $1}')\" == \"e7bc11a55398bad0ea8548163deabaa8\" ] && \
tar -xzf /tmp/mysql-connector-java-5.1.49.tar.gz -C /tmp && \
mkdir /opt/jdbc && \
cp /tmp/mysql-connector-java-5.1.49/mysql-connector-java-5.1.49.jar /opt/jdbc
Then, you could simplify your init container like so:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: crd.k8s.appian.com/v1alpha1
kind: Appian
metadata:
name: appian-k8s
spec:
webapp:
initContainers:
- name: mysql-jdbc-copy
image: registry.example.com/mysql-jdbc
command:
- "/bin/sh"
- "-c"
- "set -exo pipefail;
cp /opt/jdbc/mysql-connector-java-5.1.49.jar /usr/local/appian/ae/tomcat/apache-tomcat/lib/ext"
volumeMounts:
- name: storage
subPath: ae/tomcat/apache-tomcat/lib/ext
mountPath: /usr/local/appian/ae/tomcat/apache-tomcat/lib/ext
Sidecar containers are containers that run along with the main container in a pod. You can define any number of sidecar containers to run along side the main container. Like application containers, sidecar containers can access their pods' shared storage volumes.
The Appian operator and Appian custom resource definition (CRD) support specifying sidecar containers via the .spec.<COMPONENT>.sidecarContainers
fields on Appian custom resources.
1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: crd.k8s.appian.com/v1alpha1
kind: Appian
metadata:
name: appian-k8s
spec:
serviceManager:
sidecarContainers:
- name: test
image: alpine
command:
- "/bin/sh"
- "-c"
- "while true; do echo 'I am a sidecar container'; sleep 5; done"
To better understand how to use volumes and volume mounts with sidecar containers, see the "Specifying Volumes" section below.
The Appian operator and Appian custom resource definition (CRD) allow specifying volumes and volume mounts for init containers, sidecar containers, and the main containers that make up the Appian application. These volumes can either be existing volumes or additional volumes.
Each of the core Appian service pods define the following existing, shared storage volumes — all of which are available to init and sidecar containers.
Name | Type | Details |
---|---|---|
storage |
persistentVolumeClaim | Persistent storage perceived to be rooted at /usr/local/appian . |
distributed |
persistentVolumeClaim | Persistent, distributed storage perceived to be rooted at /usr/local/appian/ae . Only available if .spec.webapp.haExistingClaim is specified |
tmp |
emptyDir | Ephemeral storage tied to the lifecycle of the pod. Useful for circumnavigating read-only file systems. Typically mounted to /tmp |
Name | Type | Details |
---|---|---|
storage |
persistentVolumeClaim | Persistent storage perceived to be rooted at /usr/local/appian . |
distributed |
persistentVolumeClaim | Persistent, distributed storage perceived to be rooted at /usr/local/appian/ae . Only available if .spec.serviceManager.haExistingClaim is specified |
Name | Type | Details |
---|---|---|
storage |
persistentVolumeClaim | Persistent storage perceived to be rooted at /usr/local/appian . |
Name | Type | Details |
---|---|---|
storage |
persistentVolumeClaim | Persistent storage perceived to be rooted at /usr/local/appian . |
Name | Type | Details |
---|---|---|
storage |
persistentVolumeClaim | Persistent storage perceived to be rooted at /usr/local/appian . |
Name | Type | Details |
---|---|---|
storage |
persistentVolumeClaim | Persistent storage perceived to be rooted at /usr/local/appian . |
The following example shows a Webapp initContainer using the existing storage
volume.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
apiVersion: crd.k8s.appian.com/v1alpha1
kind: Appian
metadata:
name: appian-k8s
spec:
webapp:
initContainers:
- name: test
image: alpine
command:
- "/bin/sh"
- "-c"
- "ls /ext"
volumeMounts:
- name: storage
subPath: ae/tomcat/apache-tomcat/lib/ext
mountPath: /ext
If either a sidecar container or an init container needs access to a separate volume in the Kubernetes cluster, that volume can be made accessible to the sidecar or init container using the .spec.<COMPONENT>.additionalVolumes
field on the Appian custom resource.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: crd.k8s.appian.com/v1alpha1
kind: Appian
metadata:
name: appian-k8s
spec:
webapp:
initContainers:
- name: test
image: alpine
command:
- "/bin/sh"
- "-c"
- "echo 'other-data' > /other-data/file.txt"
volumeMounts:
- name: other-data
mountPath: /other-data
additionalVolumes:
- name: other-data
emptyDir: {}