Install - Java Static Agent on a Containerized App running a Linux image using Sidecars
Overview
Docker Sidecars can be used for the vFunction Runtime and Static Agent 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:
- In the Build process of the Init Container, move the vFunction Controller Installation TGZ and application-specific YAML files onto the Container
- In the Build process of the Init Container, unpack the vFunction Controller TGZ and install the Runtime Agent and (potentially) Static Agent to the /tmp/ directory
- 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
- In the Startup process of the Static Agent Container, start the vFunction Viper process from within the /shared/ folder
- In the Startup process of the Application Container, add the vFunction Runtime Agent parameters as environmental variables and start the Application
Configuring the Init Container
- Download the latest vFunction Sudoless Controller Installation TGZ
- 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
- Create a folder for vFunction Init Container’s artifacts on the Docker Build Machine
- Add the vFunction Sudoless Controller Installation TGZ and the startup-init.sh to the folder you created
- Create the Init Container’s Dockerfile
FROM almalinux:9
### Modify this line to match the user that runs the Application
RUN adduser -l -u "1500" "appuser"
ENV VF_CONTROLLER_DEFAULT_JAVA_AGENT_APPLICATION_SERVER="other"
ENV VF_CONTROLLER_DEFAULT_JAVA_AGENT_APPLICATION_JAVA_VERSION=11
### See https://kb.vfunction.com/installations/configurable-settings/mono-dynamic-agent/java/linux for more details about each of the settings below
ENV VF_CONTROLLER_DEFAULT_JAVA_CONTROLLER_HOST="http://vfunction.myorg.com"
ENV VF_CONTROLLER_DEFAULT_JAVA_CONTROLLER_NAME="docker-agent"
ENV VF_CONTROLLER_DEFAULT_JAVA_CONTROLLER_ORG_ID="1111-11-11-1111"
ENV VF_CONTROLLER_DEFAULT_JAVA_CONTROLLER_APP_ID="1111-11-11-1111"
ENV VF_CONTROLLER_DEFAULT_JAVA_CONTROLLER_CLIENT_ID="1111-11-11-1111"
ENV VF_CONTROLLER_DEFAULT_JAVA_CONTROLLER_CLIENT_SECRET="1111-11-11-1111"
ENV VF_CONTROLLER_DEFAULT_JAVA_CONTROLLER_INSTANCE_ID="container"
ENV VF_CONTROLLER_DEFAULT_JAVA_CONTROLLER_TAG="prod"
### If installing Viper here also
ENV VF_CONTROLLER_VIPERINST_VIPER_ARCHIVES="/shared/binaries-for-viper/*.*"
### See https://kb.vfunction.com/installations/configurable-settings/mono-static-agent/java/linux for more details about each of the settings below
ENV VF_CONTROLLER_VIPERINST_CONTROLLER_HOST="http://vfunction.myorg.com"
ENV VF_CONTROLLER_VIPERINST_CONTROLLER_NAME="docker-viper"
ENV VF_CONTROLLER_VIPERINST_CONTROLLER_ORG_ID="1111-11-11-1111"
ENV VF_CONTROLLER_VIPERINST_CONTROLLER_APP_ID="1111-11-11-1111"
ENV VF_CONTROLLER_VIPERINST_CONTROLLER_CLIENT_ID="1111-11-11-1111"
ENV VF_CONTROLLER_VIPERINST_CONTROLLER_CLIENT_SECRET="1111-11-11-1111"
ENV VF_CONTROLLER_VIPERINST_CONTROLLER_INSTANCE_ID="vipercont"
ENV VF_CONTROLLER_VIPERINST_CONTROLLER_TAGS="prod"
COPY vfunction-controller-sudo-less-installation*.tgz /tmp/vfunction-controller-sudo-less-installation.tgz
COPY startup-init.sh /usr/bin/startup-init.sh
RUN mkdir /shared && cd /shared && mv /tmp/vfunction-controller-sudo-less-installation.tgz /shared/ && \
tar -xvzf /shared/vfunction-controller-sudo-less-installation.tgz && \
rm -rf /shared/vfunction-controller-sudo-less-installation.tgz && \
### If installing Static Agent here also
bash /shared/vfunction/opt/vfunction/controller-installation/create-instance.sh -i viperinst -t java -v && \
bash /shared/vfunction/opt/vfunction/controller-installation/install.sh -i default-java -n && \
### If installing Static Agent here also
bash /shared/vfunction/opt/vfunction/controller-installation/install.sh -i viperinst -n && \
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"]
- Build the Init Dockerfile
docker build . -t vf-init-container
- Push the Init Image to your Image Repository
docker push repository/vf-init-container:1
Configuring the Static Agent Container
- Create a folder for vFunction Static Agent Container’s artifacts on the Docker Build Machine
- Create the Static Agent Container’s startup-viper.sh script
#!/usr/bin/env bash
set -x
get_process_pid(){
binary=viper.jar
INSTANCE=viperinst
ps aux >/dev/null 2>&1
if [[ $? -eq 0 ]]; then
ps aux | grep $binary | grep -v grep | awk -v x="--instance=$INSTANCE" '{for (i=1;i<=NF;i++) if ($i==x) {print $0; next}}' | awk '{print $2}'
else
for proc in /proc/[0-9]*/cmdline; do echo $(basename $(dirname $proc)) $(cat $proc | tr "\0" " "); done | grep $binary | grep -v grep | awk -v x="--instance=$INSTANCE" '{for (i=1;i<=NF;i++) if ($i==x) {print $0; next}}' | awk '{print $1}'
fi
}
echo "Restarting the controller"
bash /shared/vfunction/opt/vfunction/controller-installation/restart-controller.sh -i viperinst || echo "Failed to restart the controller"
sleep 60
# loop until the viper process is not running - then kill the script
while true; do
pid=$(get_process_pid viper.jar)
if [[ -z $pid ]]; then
echo "Viper process is not running"
break
fi
sleep 5
done
- Create the Static Agent Container’s health-check-viper.sh script
#!/usr/bin/env bash
netstat -nlp | grep 8090 | grep tcp | grep -q LISTEN
exit $?
- Add the startup-viper.sh and health-check-viper.sh script to the folder for vFunction Viper artifacts on the Docker Build Machine
- Create the Viper Container’s Dockerfile
FROM almalinux:9
### 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
COPY health-check-viper.sh /usr/bin/health-check.sh
RUN chmod +x /usr/bin/startup-viper.sh && \
chmod -R 777 /usr/bin/
# vFunction healtcheck
HEALTHCHECK --interval=5s --retries=12 \
CMD /usr/bin/health-check.sh
### Modify this line to match the user that runs the Application
USER 1500
ENTRYPOINT ["/bin/sh"]
CMD ["/usr/bin/startup-viper.sh"]
- Build the Viper Dockerfile
docker build . -t vf-viper-container
- 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.
- 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.logging.logFile=/shared/vfunction/var/log/vfunction/instances/default-java/vfagent.log
- Apply the ConfigMap to the Cluster
kubectl apply -f java-tool-options-configmap.yaml
Configuring the Deployment Manifest
- 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
- Apply the Deployment Manifest in the Cluster
- Confirm that the Application comes up and functions as expected
- If any issues arise: