Install - Java Agent Controller on a Containerized App running a Linux image using Sidecars


Overview

Docker Sidecars can be used for the vFunction Controller installation to separate the vFunction components from the main application so that each component is running in a separate Container.

The vFunction Docker Sidecar Installation does the following:

  1. In the Build process of the Init Container, move the vFunction Controller Installation TGZ and application-specific YAML files onto the Container
  2. In the Build process of the Init Container, unpack the vFunction Controller TGZ and install the Controller, Agent and (potentially) Viper to the /tmp/ directory
  3. In the Startup process of the Init Container, move the /tmp/vfunction/ contents to a /shared/ folder that is used by each of the Sidecar Containers
  4. In the Startup process of the Controller Container, start the vFunction Controller process from within the /shared/ folder
  5. Optional if running Viper as a Sidecar in the same environment: In the Startup process of the Viper Container, start the vFunction Controller process from within the /shared/ folder
  6. In the Startup process of the Application Container, add the vFunction Agent parameters as environmental variables and start the Application

Configuring the Init Container

  1. Download the latest vFunction Sudoless Controller Installation TGZ
  2. Download a sample installation.yaml
  3. Modify the installation.yaml to be relevant to your environment
### Modify the CHANGE_ME values below
controller:
 name: CHANGE_ME #... use a string that indicates what and where this is, e.g. UAT tomcat1
 host: CHANGE_ME #... use the VF Server's address, e.g. http://10.0.0.49
 org_id: CHANGE_ME #... taken from the VF Server UI after you've created the Application
 app_id: CHANGE_ME #... taken from the VF Server UI after you've created the Application
 client_id: CHANGE_ME #... taken from the VF Server UI after you've created the Application
 client_secret: CHANGE_ME #... taken from the VF Server UI after you've created the Application
 instance_id: CHANGE_ME # ... use the same string as used in the "name" field
 type: java
 jolokia_port: 8778
 instrconf_additions:
   inclusions:
#      - a.b.c.
   exclusions:
#      - a.b.c.
 tags:
#    - CHANGE_ME # ... use the same string as used in the "name" field

server_application:
#  name:
#  include_classes: com.
#  allowed_users:

agent:
 ### Optional application servers: weblogic, websphere85, websphere9, liberty, tomcat, wildfly, payara, jeus, other ###
 application_server: other
 ### Indicate the application java version when greater than 8. (optional - default to 8) ###
#  application_java_version: 11
 override_properties:
#    - key=value

viper:
 port: 8090
 archives:
   - /opt/dummy
#    - /opt/<my-application>/**/*.jar
#    - /opt/<my-application>/**/*.
 ### Supported only for Oracle databases!
 stored_procedure:
#    db_url:
#    db_user:
#    db_password:
 spring:
   custom_context_roots:
#      - path/to/custom-conf.xml
#      - another-custom-conf.xml
   root_bean_classes:
#      - a.b.c.Foo
#      - a.b.c.Bar
  1. Create the Init Container’s startup-init.sh script
#!/usr/bin/env bash

set -x

echo "Moving controller files to shared folder"
mv /tmp/vfunction /shared/

### If you plan to deploy the Viper container as well
mkdir /shared/binaries-for-viper
  1. Create a folder for vFunction Init Container’s artifacts on the Docker Build Machine
  2. Add the vFunction Sudoless Controller Installation TGZ, the installation.yaml and the startup-init.sh to the folder you created
  3. Create the Init Container’s Dockerfile
FROM almalinux:9

ARG NAME
ARG VERSION
ARG RELEASE

ENV SUMMARY="Linux Java Sidecar application wrapper for vFunction Controller."          \
   DESCRIPTION="Linux Java Sidecar application wrapper for vFunction Controller."

LABEL summary="$SUMMARY"                                \
     description="$DESCRIPTION"                        \
     io.k8s.description="$DESCRIPTION"                 \
     name="vfunction/$NAME"                            \
     vendor="vFunction"                                \
     version="$VERSION"                                \
     release="$RELEASE"                                

### Modify this line to match the user that runs the Application
RUN adduser -l -u "1500" "appuser"

COPY vfunction-controller-sudo-less-installation*.tgz /tmp/vfunction-controller-sudo-less-installation.tgz
COPY installation.yaml /tmp/
COPY startup-init.sh /usr/bin/startup-init.sh

RUN mkdir /shared && cd /shared && mv /tmp/vfunction-controller-sudo-less-installation.tgz /shared/     && \
   tar zxvf /shared/vfunction-controller-sudo-less-installation.tgz      && \
   rm -rf /shared/vfunction-controller-sudo-less-installation.tgz        && \
   mv /tmp/installation.yaml /shared/vfunction/etc/sysconfig/vfunction/installation/instances/default-java/  && \
   ### If running Viper
   ### bash /shared/vfunction/opt/vfunction/controller-installation/install.sh -i default-java -n    && \
   ### If only running the Agent
   bash /shared/vfunction/opt/vfunction/controller-installation/install.sh -i default-java -n -a   && \
   mv /shared/vfunction /tmp/      && \
   rm -rf /shared                  && \
   chmod +x /usr/bin/startup-init.sh      && \
   chmod -R 777 /usr/bin/ /tmp/vfunction  && \
   ### Modify this line to match the user that runs the Application
   chown -R appuser:appuser /tmp/vfunction/

### Modify this line to match the user that runs the Application
USER 1500

ENTRYPOINT ["/bin/sh"]
CMD ["/usr/bin/startup-init.sh"]
  1. Build the Init Dockerfile
docker build . -t vf-init-container
  1. Push the Init Image to your Image Repository
docker push repository/vf-init-container:1

Configuring the Controller Container

  1. Create a folder for vFunction Controller Container’s artifacts on the Docker Build Machine
  2. Create the Controller Container’s startup-controller.sh script
#!/usr/bin/env bash

set -x

echo "Starting the controller"

bash /shared/vfunction/opt/vfunction/controller/instances/default-java/bin/vf-controller start || echo "Failed to start the controller"

while true; do
 sleep 600
 echo "Still alive..." 
done
  1. Add the startup-controller.sh script to the folder for vFunction Controller artifacts on the Docker Build Machine
  2. Create the Controller Container’s Dockerfile
FROM almalinux:9

ARG NAME
ARG VERSION
ARG RELEASE

ENV SUMMARY="Linux Java Sidecar application wrapper for vFunction Controller."          \
   DESCRIPTION="Linux Java Sidecar application wrapper for vFunction Controller."

LABEL summary="$SUMMARY"                                \
     description="$DESCRIPTION"                        \
     io.k8s.description="$DESCRIPTION"                 \
     name="vfunction/$NAME"                            \
     vendor="vFunction"                                \
     version="$VERSION"                                \
     release="$RELEASE"                                

### Modify this line to match the user that runs the Application
RUN adduser -l -u "1500" "appuser"

COPY startup-controller.sh /usr/bin/startup-controller.sh

RUN chmod +x /usr/bin/startup-controller.sh                                                 && \
   chmod -R 777 /usr/bin/

### Modify this line to match the user that runs the Application
USER 1500

ENTRYPOINT ["/bin/sh"]
CMD ["/usr/bin/startup-controller.sh"]
  1. Build the Controller Dockerfile
docker build . -t vf-controller-container
  1. Push the Controller Image to the Image Repository
docker push repository/vf-controller-container:1

Configuring the Viper Container

Viper is the most resource intensive vFunction process when compared with the Agent and Controller. Some organizations choose to run Viper in a separate location and skip the step of setting up the Viper Container as a Sidecar.

  1. Create a folder for vFunction Viper Container’s artifacts on the Docker Build Machine
  2. Create the Viper Container’s startup-viper.sh script
#!/usr/bin/env bash

set -x

echo "Starting Viper"

bash /shared/vfunction/opt/vfunction/viper/instances/default-java/bin/vf-viper start || echo "Failed to start viper"
  1. Add the startup-viper.sh script to the folder for vFunction Viper artifacts on the Docker Build Machine
  2. Create the Viper Container’s Dockerfile
FROM almalinux:9

ARG NAME
ARG VERSION
ARG RELEASE

ENV SUMMARY="Linux Java Sidecar application wrapper for vFunction Controller."          \
   DESCRIPTION="Linux Java Sidecar application wrapper for vFunction Controller."

LABEL summary="$SUMMARY"                                \
     description="$DESCRIPTION"                        \
     io.k8s.description="$DESCRIPTION"                 \
     name="vfunction/$NAME"                            \
     vendor="vFunction"                                \
     version="$VERSION"                                \
     release="$RELEASE"                                

### Modify this line to match the user that runs the Application
RUN adduser -l -u "1500" "appuser"                             && \
   mkdir -p /opt/application/lib

### Replace the APPLICATION_BINARIES with the path to the Archives for the Application
COPY /APPLICATION_ASSEMBLIES /shared/binaries-for-viper/
COPY startup-viper.sh /usr/bin/startup-viper.sh

RUN chmod +x /usr/bin/startup-viper.sh                     && \
   chmod -R 777 /usr/bin/

### Modify this line to match the user that runs the Application
USER 1500

ENTRYPOINT ["/bin/sh"]
CMD ["/usr/bin/startup-viper.sh"]
  1. Build the Viper Dockerfile
docker build . -t vf-viper-container
  1. Push the Viper Image to the Image Repository
docker push repository/vf-viper-container:1

Create a ConfigMap for the Application Container

This ConfigMap adds the vFunction Agent parameters to the Java Tool Options which will get picked up by the Application when the JVM launches.

  1. Create the Java Tool Options ConfigMap in a text editor
apiVersion: v1
kind: ConfigMap
metadata:
  name: java-tool-options-configmap
  namespace: default
data:
  ### Remove the line --add-opens=java.base/java.util=ALL-UNNAMED if using Java 8
  JAVA_TOOL_OPTIONS: |
        -agentpath:/shared/vfunction/opt/vfunction/agent/libJVMTIAgent.so=conf=/shared/vfunction/etc/sysconfig/vfunction/agent/instances/default-java/native-conf.json -javaagent:/shared/vfunction/opt/vfunction/agent/runtime-agent.jar=ConfigLocation=/shared/vfunction/etc/sysconfig/vfunction/agent/instances/default-java/vfunction-runtime-override.properties --add-opens=java.base/java.util=ALL-UNNAMED -Dcom.vfunction.runtime.shared.folder=/shared/vfunction/opt/vfunction/controller/instances/default-java/temp/ -Dcom.vfunction.runtime.offload.tmpFolder=/shared/vfunction/opt/vfunction/agent/instances/default-java/temp/ -Dcom.vfunction.logging.logFile=/shared/vfunction/var/log/vfunction/instances/default-java/vfagent.log
  1. Apply the ConfigMap to the Cluster
kubectl apply -f java-tool-options-configmap.yaml

Configuring the Deployment Manifest

  1. Modify the manifest for the environment to ensure that (A) the Volumes are created and accessible for each Container, (B) The Init Container is created, (C) The Controller Container is created, (D) The Viper Container is created [if applicable] and (E) The Java Tool Options are added to the JVM
apiVersion: v1
kind: Deployment
metadata:
 name: application-with-vfunction-controller
 namespace: vfunction
 labels:
   app: application-with-vfunction-controller
spec:
 replicas: 1
 selector:
   matchLabels:
     app: application-with-vfunction-controller
 template:
   metadata:
     labels:
       app: application-with-vfunction-controller
   spec:
     initContainers:
         ### Modify to match the Image Repository
       - image: REPOSITORY/vf-init-container:1
         imagePullPolicy: IfNotPresent
         name: init
         securityContext:
           runAsNonRoot: true
           ### Modify to match the user that runs the Application
           runAsUser: 1500
         volumeMounts:
           - mountPath: /shared/
             name: shared
     containers:
       - name: application
         image: REPOSITORY/APPLICATION
         imagePullPolicy: Always
         ports:
           - containerPort: 8080
             protocol: TCP
         securityContext:
           runAsNonRoot: true
           ### Modify to match the user that runs the Application
           runAsUser: 1500
         volumeMounts:
           - mountPath: /shared/
             name: shared
         envFrom:
           - configMapRef:
             name: java-tool-options-configmap
       - name: controller
         image: REPOSITORY/vf-controller-container
         imagePullPolicy: IfNotPresent
         securityContext:
           runAsNonRoot: true
           ### Modify to match the user that runs the Application
           runAsUser: 1500
         volumeMounts:
           - mountPath: /shared/
             name: shared
       - name: viper
         image: REPOSITORY/vf-viper-container:1
         imagePullPolicy: IfNotPresent
         securityContext:
           runAsNonRoot: true
           ### Modify to match the user that runs the Application
           runAsUser: 1500
         volumeMounts:
           - mountPath: /shared/
             name: shared
     volumes:
       - emptyDir: {}
         name: shared

Deploy the Application and vFunction Sidecars

  1. Apply the Deployment Manifest in the Cluster
  2. Confirm that the Application comes up and functions as expected
  3. If any issues arise: