<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Deploying CI360 Agents into Containers or Kubernetes environment in SAS Customer Intelligence</title>
    <link>https://communities.sas.com/t5/SAS-Customer-Intelligence/Deploying-CI360-Agents-into-Containers-or-Kubernetes-environment/m-p/929057#M2016</link>
    <description>&lt;P&gt;&lt;SPAN&gt;CI360 Agents are Java programs/executables that enable and facilitate CI360 integration with external systems, that are generally light weight and can run anywhere as long as they have connectivity to CI360 as well as any target internal or 3rd party systems they need to connect to.&lt;BR /&gt;&lt;BR /&gt;In many cases, although not all, they can be stateless and don’t require a lot of resources. This makes them good candidates for containerizing. When deployed and run as containers, agents can be easier to deploy, manage and scale, and leverage existing container management and deployment platforms and infrastructure.&lt;BR /&gt;&lt;BR /&gt;In this post, we look at how to deploy CI360 custom agents in containers, either in a simple Docker deployment or into a Kubernetes environment.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;This was written a while ago by two of us (Rob Sneath and Bojan Belovic) as part of internal Customer Intelligence knowledge base, but we believe it's useful for a broader Customer Intelligence 360 community.&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Where examples were necessary,&amp;nbsp;&lt;/SPAN&gt;we used our CI360 CAS Agent. Any references to CAS (SAS Cloud Analytic Services) streaming agent are just for illustration purposes, and this approach is applicable to any custom CI360 agent.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT size="5"&gt;Prerequisites&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;In our discussion around deploying agents as containers, we will assume that basic prerequisite is existence of a runnable agent, packaged with all its dependencies and necessary files. Several agents developed within SAS Customer Intelligence practice can be found on GitHub with Dockerfiles included that make this process easier.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Complete agent distribution generally contains:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Main agent JAR file(s)&lt;/LI&gt;
&lt;LI&gt;dependencies/libraries&lt;/LI&gt;
&lt;LI&gt;Start script, stop script and/or known command lines for starting the agent (which is used for Docker entry point)&lt;/LI&gt;
&lt;LI&gt;A command line to ensure agent is running (health check)&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;It is assumed that all the above are in place and that agent can already be executed standalone.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT size="5"&gt;Standalone CAS Agent Example&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Since we will be using our CAS agent as an example of agent container – here’s what it looks like and how it runs standalone:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT face="courier new,courier" size="2"&gt;-rw-r--r-- 1 bobelo&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 570 Mar 26&amp;nbsp; 2021 Dockerfile&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier" size="2"&gt;-rw-r--r-- 1 bobelo&amp;nbsp;&amp;nbsp; 10695 Dec&amp;nbsp; 8 14:53 README.md&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier" size="2"&gt;-rw-r--r-- 1 bobelo&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 769 Aug 11 12:20 agent.config&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier" size="2"&gt;-rw-r--r-- 1 bobelo&amp;nbsp;&amp;nbsp; 36604 Dec&amp;nbsp; 8 16:53 ci360-cas-agent-21.11.1.jar&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier" size="2"&gt;drwxr-xr-x 1 bobelo&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0 Dec&amp;nbsp; 8 16:53 dependency/&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier" size="2"&gt;drwxr-xr-x 1 bobelo&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0 Sep 22 11:36 k8/&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier" size="2"&gt;-rw-r--r-- 1 bobelo&amp;nbsp;&amp;nbsp;&amp;nbsp; 3586 Jan 26&amp;nbsp; 2021 logback.xml&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier" size="2"&gt;drwxr-xr-x 1 bobelo&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0 Aug 12 07:06 logs/&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier" size="2"&gt;-rw-r--r-- 1 bobelo&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 117 Mar&amp;nbsp; 9&amp;nbsp; 2020 run_agent.cmd&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier" size="2"&gt;-rwxr-xr-x 1 bobelo&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 321 Apr 17&amp;nbsp; 2020 run_agent.sh*&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier" size="2"&gt;-rw-r--r-- 1 bobelo&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 44 Mar 23&amp;nbsp; 2020 status.sh&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier" size="2"&gt;-rwxr-xr-x 1 bobelo&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 190 Feb 23&amp;nbsp; 2021 stop_agent.sh*&lt;/FONT&gt;&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The &lt;EM&gt;run_agent.sh&lt;/EM&gt; script contains the java executable line that starts the agent:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;java -Dlogback.configurationFile=logback.xml -DconfigFile=agent.config -jar ci360-cas-agent-21.11.1.jar&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT size="5"&gt;Building Docker Image&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Some of our agents contain a &lt;EM&gt;Dockerfile&lt;/EM&gt; as part of distribution or Git repository. In this case, &lt;EM&gt;Dockerfile&lt;/EM&gt; does not need to be created. Provided &lt;EM&gt;Dockerfile&lt;/EM&gt; should be sufficient without modification for most use cases but may have to be modified in some cases.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;If the &lt;EM&gt;Dockerfile&lt;/EM&gt; needs to be created for an agent that doesn’t have one (or if deploying a brand-new custom agent into a container), here are some basics about creating Dockerfiles:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Sample Dockerfile&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;FROM openjdk:8-jre-alpine
LABEL version="${project.version}"
LABEL company="SAS Institute"
# build arguments
ARG VERSION=${project.version}
# copy app into image
COPY . /opt/ci360-cas-agent/
# set working dir
WORKDIR /opt/ci360-cas-agent
# set HEALTHCHECK
HEALTHCHECK CMD ps -ef | grep java | grep ci360-cas-agent
# run application with this command line
ENTRYPOINT ["java", "-Dlogback.configurationFile=logback.xml", "-DconfigFile=agent.config", "-Djavax.net.ssl.trustStore=viya4_trustedcerts.jks", "-Xms32m", "-Xmx2048m", "-jar", "ci360-cas-agent-${project.version}.jar"]&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;Dockerfile&lt;/EM&gt; instructions explained:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;FROM&lt;/STRONG&gt; - The&amp;nbsp;FROM&amp;nbsp;instruction sets the Base Image from which our new image is built. Every &lt;EM&gt;Dockerfile&lt;/EM&gt; must start with a FROM instruction&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;COPY&lt;/STRONG&gt; - The&amp;nbsp;COPY&amp;nbsp;instruction copies new files or directories from&amp;nbsp;source directory (first argument)&amp;nbsp;and adds them to the filesystem of the container at the destination path&amp;nbsp;(second argument)&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;WORKDIR&lt;/STRONG&gt; - The&amp;nbsp;WORKDIR&amp;nbsp;instruction sets the working directory for any&amp;nbsp;RUN,&amp;nbsp;CMD,&amp;nbsp;ENTRYPOINT,&amp;nbsp;COPY&amp;nbsp;and&amp;nbsp;ADD&amp;nbsp;instructions that follow it in the&amp;nbsp;&lt;EM&gt;Dockerfile&lt;/EM&gt;. If we omit the WORKDIR instruction, we simply have to specify full path for all files referenced in ENTRYPOINT.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;ENTRYPOINT&lt;/STRONG&gt; - An&amp;nbsp;ENTRYPOINT&amp;nbsp;allows you to configure a container that will run as an executable. Command line specified as ENTRYPOINT will be executed when container is started.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;HEALTHCHECK&lt;/STRONG&gt; - The&amp;nbsp;HEALTHCHECK&amp;nbsp;instruction tells Docker how to test a container to check that it is still working.&amp;nbsp;When a container has a health check specified, it has a&amp;nbsp;health status&amp;nbsp;in addition to its normal status. This status is initially "&lt;EM&gt;starting&lt;/EM&gt;". Whenever a health check passes, it becomes "&lt;EM&gt;healthy"&amp;nbsp;&lt;/EM&gt;(whatever state it was previously in). After a certain number of consecutive failures, it becomes "&lt;EM&gt;unhealthy"&lt;/EM&gt;.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Building the image&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;From top directory of agent distribution (where distribution archive has been unzipped), run the following command:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;docker build -t ci360-cas-agent .&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;This will read &lt;EM&gt;Dockerfile&lt;/EM&gt; in current directory and build the image in local Docker repository with specified name.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT size="5"&gt;Publishing Docker Image&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Once image has been built, it can optionally be pushed/published to your chosen container registry.&amp;nbsp; In the example below we are pushing the image to a private AWS container registry:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Tag the image:&lt;/STRONG&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;docker tag ci360-cas-agent:latest xxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/ci360-cas-agent:latest&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Push the image:&lt;/STRONG&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;docker push xxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/ci360-cas-agent:latest&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Once pushed to a registry, an image can easily be used by others to deploy and run agent containers without the need to build the image themselves or even download agent distribution files.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS-Heading1"&gt;&lt;FONT size="5"&gt;Running Docker Container&lt;/FONT&gt;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;Since we can run multiple containers based on image we built, it is recommended that agent configuration file be maintained separately, on the host machine.&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;In our CAS Agent example, all agent files, including &lt;EM&gt;&lt;SPAN&gt;agent.config&lt;/SPAN&gt;&lt;/EM&gt; file, are located in &lt;EM&gt;&lt;SPAN&gt;/opt/ci360-cas-agent&lt;/SPAN&gt;&lt;/EM&gt; within the image. That means we could mount an external file to that location (/opt/ci360-cas-agent/agent.config) in order to override the config packaged with the agent. Agent entrypoint parameters point to this file and will read configuration from that location.&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;Once the agent image has been created, we can run the container using:&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;docker run -d --mount type=bind,source=/opt/install/cas/cas_agent_prd1.config,target=/opt/ci360-cas-agent/agent.config --name ci360-cas-prd1 ci360-cas-agent:latest&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;Mount option in the command line above is used to map a file on the host filesystem (/opt/install/cas/cas_agent_prd1.config) to the agent.config file within the container. We are also naming this container.&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;Since our goal is to run multiple instances, we could provide multiple different config files (if configuration between them is actually different) and container specific names. For example:&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;docker run -d --mount type=bind,source=/opt/install/cas/cas_agent_prd2.config,target=/opt/ci360-cas-agent/agent.config --name ci360-cas-prd2 ci360-cas-agent:latest

docker run -d --mount type=bind,source=/opt/install/cas/cas_agent_demo1.config,target=/opt/ci360-cas-agent/agent.config --name ci360-cas-demo1 ci360-cas-agent:latest&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;We can see that we are launching two new containers, named &lt;EM&gt;ci360-cas-prd2&lt;/EM&gt; and &lt;EM&gt;ci360-cas-demo1&lt;/EM&gt;, with two local files cas_agent_prd2.config and cas_agent_demo1.config as their configuration files respectively.&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="multiple_containers.jpg" style="width: 434px;"&gt;&lt;img src="https://communities.sas.com/t5/image/serverpage/image-id/96636iF2DB2427A3189F02/image-size/large?v=v2&amp;amp;px=999" role="button" title="multiple_containers.jpg" alt="multiple_containers.jpg" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;Of course, we can also run multiple containers that use the same configuration file, where &lt;BR /&gt;multiple instances simply provide horizontal scaling and failover capabilities. This will be a &lt;BR /&gt;common scenario for a single agent with always on and high-volume requirements.&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="multiple_containers_single_tenant.jpg" style="width: 455px;"&gt;&lt;img src="https://communities.sas.com/t5/image/serverpage/image-id/96637iA04C4D4F609C4E93/image-size/large?v=v2&amp;amp;px=999" role="button" title="multiple_containers_single_tenant.jpg" alt="multiple_containers_single_tenant.jpg" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&lt;FONT size="5"&gt;Deployment Steps for Kubernetes&lt;/FONT&gt;&lt;BR /&gt;In order to deploy the agent to Kubernetes environment, we will assume that agent image has &lt;BR /&gt;been built, it can be deployed and executed standalone in a Docker environment (e.g., desktop), &lt;BR /&gt;and it has been pushed to a container registry.&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&lt;STRONG&gt;&lt;FONT size="4"&gt;Create Kubernetes Artifacts&lt;/FONT&gt;&lt;/STRONG&gt;&lt;BR /&gt;Manifest YAML file needs to be created for deployment to Kubernetes. A sample YAML file &lt;BR /&gt;(ci360-cas-agent.yaml) is provided in its entirety below, and can also be found in SAS CI GitLab &lt;BR /&gt;repository:&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&lt;A href="https://github.com/sassoftware/ci360-extensions/blob/main/code/ci360-cas-agent/k8/ci360-cas-agent.yaml" target="_self"&gt;https://github.com/sassoftware/ci360-extensions/blob/main/code/ci360-cas-agent/k8/ci360-cas-agent.yaml&lt;/A&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;Take a copy of ci360-cas-agent.yaml manifest from the k8 directory of the agent as this will be &lt;BR /&gt;used to create the K8s artifacts. The YAML file contain definitions for creating a PersistentVolumeClaim, ConfigMap, Deployment &lt;BR /&gt;and a HorizontalPodAutoscaler. Part of the YAML file is configuration map, which in our example contains CI360 connection &lt;BR /&gt;information including CI360 gateway URL and credentials, as well as CAS details.&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&lt;BR /&gt;You will generally need to edit this YAML file to provide details of your ci360.gatewayHost, &lt;BR /&gt;ci360.tenantID, ci360.clientSecret, cas.username and cas.password which can be found in the &lt;BR /&gt;ConfigMap section:&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;ci360.gatewayHost=extapigwservice-demo.cidemo.sas.com
ci360.tenantID=0bf01xxxxxxxa3a2cacaa
ci360.clientSecret=MTAxOTIxxxxxxxxxxxxxxxxxxxN2ZpaWpp
cas.username=sasdemo
cas.password=xxxxxxxx&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;In this example, you will also need to update the Deployment section to provided details of your &lt;BR /&gt;“containers - image” and “imagePullSecrets - name” (if deployed to a private container registry):&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;imagePullSecrets:
- name: aws-pull-v2
containers:
- image: xxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/ci360-cas-agent:latest&lt;/PRE&gt;
&lt;P&gt;You should now be ready to apply this manifest your K8s cluster:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;kubectl apply -f ./ci360-cas-agent.yaml –namespace &amp;lt;YOUR NAMESPACE&amp;gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;To facilitate mapping of config file in the YAML file, and to show an example where change of Dockerfile is needed, we have slightly modified the ENTRYPOINT line in the Dockerfile before building and pushing the agent image:&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&lt;STRONG&gt;Old:&lt;/STRONG&gt;&lt;/P&gt;
&lt;PRE&gt;ENTRYPOINT ["java", "-Dlogback.configurationFile=logback.xml", "-DconfigFile=agent.config", "-Djavax.net.ssl.trustStore=viya4_trustedcerts.jks", "-Xms32m", "-Xmx2048m", "-jar", "ci360-cas-agent-21.09.1.jar"]&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;New:&lt;/STRONG&gt;&lt;/P&gt;
&lt;PRE&gt;RYPOINT ["java", "-Dlogback.configurationFile=/ci360-cas-agent-config/logback.xml", "-DconfigFile=/ci360-cas-agent-config/agent.config", "-Djavax.net.ssl.trustStore=viya4_trustedcerts.jks", "-Xms32m", "-Xmx2048m", "-jar", "ci360-cas-agent-21.09.1.jar"]
&lt;/PRE&gt;
&lt;P&gt;All we are doing is changing the location within the image that agent will use to read logging &lt;BR /&gt;configuration and agent configuration files, and we will use those same locations within our &lt;BR /&gt;YAML file.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Mon, 20 May 2024 15:52:08 GMT</pubDate>
    <dc:creator>BojanBelovic</dc:creator>
    <dc:date>2024-05-20T15:52:08Z</dc:date>
    <item>
      <title>Deploying CI360 Agents into Containers or Kubernetes environment</title>
      <link>https://communities.sas.com/t5/SAS-Customer-Intelligence/Deploying-CI360-Agents-into-Containers-or-Kubernetes-environment/m-p/929057#M2016</link>
      <description>&lt;P&gt;&lt;SPAN&gt;CI360 Agents are Java programs/executables that enable and facilitate CI360 integration with external systems, that are generally light weight and can run anywhere as long as they have connectivity to CI360 as well as any target internal or 3rd party systems they need to connect to.&lt;BR /&gt;&lt;BR /&gt;In many cases, although not all, they can be stateless and don’t require a lot of resources. This makes them good candidates for containerizing. When deployed and run as containers, agents can be easier to deploy, manage and scale, and leverage existing container management and deployment platforms and infrastructure.&lt;BR /&gt;&lt;BR /&gt;In this post, we look at how to deploy CI360 custom agents in containers, either in a simple Docker deployment or into a Kubernetes environment.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;This was written a while ago by two of us (Rob Sneath and Bojan Belovic) as part of internal Customer Intelligence knowledge base, but we believe it's useful for a broader Customer Intelligence 360 community.&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Where examples were necessary,&amp;nbsp;&lt;/SPAN&gt;we used our CI360 CAS Agent. Any references to CAS (SAS Cloud Analytic Services) streaming agent are just for illustration purposes, and this approach is applicable to any custom CI360 agent.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT size="5"&gt;Prerequisites&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;In our discussion around deploying agents as containers, we will assume that basic prerequisite is existence of a runnable agent, packaged with all its dependencies and necessary files. Several agents developed within SAS Customer Intelligence practice can be found on GitHub with Dockerfiles included that make this process easier.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Complete agent distribution generally contains:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Main agent JAR file(s)&lt;/LI&gt;
&lt;LI&gt;dependencies/libraries&lt;/LI&gt;
&lt;LI&gt;Start script, stop script and/or known command lines for starting the agent (which is used for Docker entry point)&lt;/LI&gt;
&lt;LI&gt;A command line to ensure agent is running (health check)&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;It is assumed that all the above are in place and that agent can already be executed standalone.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT size="5"&gt;Standalone CAS Agent Example&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Since we will be using our CAS agent as an example of agent container – here’s what it looks like and how it runs standalone:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT face="courier new,courier" size="2"&gt;-rw-r--r-- 1 bobelo&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 570 Mar 26&amp;nbsp; 2021 Dockerfile&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier" size="2"&gt;-rw-r--r-- 1 bobelo&amp;nbsp;&amp;nbsp; 10695 Dec&amp;nbsp; 8 14:53 README.md&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier" size="2"&gt;-rw-r--r-- 1 bobelo&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 769 Aug 11 12:20 agent.config&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier" size="2"&gt;-rw-r--r-- 1 bobelo&amp;nbsp;&amp;nbsp; 36604 Dec&amp;nbsp; 8 16:53 ci360-cas-agent-21.11.1.jar&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier" size="2"&gt;drwxr-xr-x 1 bobelo&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0 Dec&amp;nbsp; 8 16:53 dependency/&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier" size="2"&gt;drwxr-xr-x 1 bobelo&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0 Sep 22 11:36 k8/&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier" size="2"&gt;-rw-r--r-- 1 bobelo&amp;nbsp;&amp;nbsp;&amp;nbsp; 3586 Jan 26&amp;nbsp; 2021 logback.xml&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier" size="2"&gt;drwxr-xr-x 1 bobelo&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0 Aug 12 07:06 logs/&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier" size="2"&gt;-rw-r--r-- 1 bobelo&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 117 Mar&amp;nbsp; 9&amp;nbsp; 2020 run_agent.cmd&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier" size="2"&gt;-rwxr-xr-x 1 bobelo&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 321 Apr 17&amp;nbsp; 2020 run_agent.sh*&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier" size="2"&gt;-rw-r--r-- 1 bobelo&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 44 Mar 23&amp;nbsp; 2020 status.sh&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier" size="2"&gt;-rwxr-xr-x 1 bobelo&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 190 Feb 23&amp;nbsp; 2021 stop_agent.sh*&lt;/FONT&gt;&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The &lt;EM&gt;run_agent.sh&lt;/EM&gt; script contains the java executable line that starts the agent:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;java -Dlogback.configurationFile=logback.xml -DconfigFile=agent.config -jar ci360-cas-agent-21.11.1.jar&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT size="5"&gt;Building Docker Image&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Some of our agents contain a &lt;EM&gt;Dockerfile&lt;/EM&gt; as part of distribution or Git repository. In this case, &lt;EM&gt;Dockerfile&lt;/EM&gt; does not need to be created. Provided &lt;EM&gt;Dockerfile&lt;/EM&gt; should be sufficient without modification for most use cases but may have to be modified in some cases.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;If the &lt;EM&gt;Dockerfile&lt;/EM&gt; needs to be created for an agent that doesn’t have one (or if deploying a brand-new custom agent into a container), here are some basics about creating Dockerfiles:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Sample Dockerfile&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;FROM openjdk:8-jre-alpine
LABEL version="${project.version}"
LABEL company="SAS Institute"
# build arguments
ARG VERSION=${project.version}
# copy app into image
COPY . /opt/ci360-cas-agent/
# set working dir
WORKDIR /opt/ci360-cas-agent
# set HEALTHCHECK
HEALTHCHECK CMD ps -ef | grep java | grep ci360-cas-agent
# run application with this command line
ENTRYPOINT ["java", "-Dlogback.configurationFile=logback.xml", "-DconfigFile=agent.config", "-Djavax.net.ssl.trustStore=viya4_trustedcerts.jks", "-Xms32m", "-Xmx2048m", "-jar", "ci360-cas-agent-${project.version}.jar"]&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;Dockerfile&lt;/EM&gt; instructions explained:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;FROM&lt;/STRONG&gt; - The&amp;nbsp;FROM&amp;nbsp;instruction sets the Base Image from which our new image is built. Every &lt;EM&gt;Dockerfile&lt;/EM&gt; must start with a FROM instruction&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;COPY&lt;/STRONG&gt; - The&amp;nbsp;COPY&amp;nbsp;instruction copies new files or directories from&amp;nbsp;source directory (first argument)&amp;nbsp;and adds them to the filesystem of the container at the destination path&amp;nbsp;(second argument)&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;WORKDIR&lt;/STRONG&gt; - The&amp;nbsp;WORKDIR&amp;nbsp;instruction sets the working directory for any&amp;nbsp;RUN,&amp;nbsp;CMD,&amp;nbsp;ENTRYPOINT,&amp;nbsp;COPY&amp;nbsp;and&amp;nbsp;ADD&amp;nbsp;instructions that follow it in the&amp;nbsp;&lt;EM&gt;Dockerfile&lt;/EM&gt;. If we omit the WORKDIR instruction, we simply have to specify full path for all files referenced in ENTRYPOINT.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;ENTRYPOINT&lt;/STRONG&gt; - An&amp;nbsp;ENTRYPOINT&amp;nbsp;allows you to configure a container that will run as an executable. Command line specified as ENTRYPOINT will be executed when container is started.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;HEALTHCHECK&lt;/STRONG&gt; - The&amp;nbsp;HEALTHCHECK&amp;nbsp;instruction tells Docker how to test a container to check that it is still working.&amp;nbsp;When a container has a health check specified, it has a&amp;nbsp;health status&amp;nbsp;in addition to its normal status. This status is initially "&lt;EM&gt;starting&lt;/EM&gt;". Whenever a health check passes, it becomes "&lt;EM&gt;healthy"&amp;nbsp;&lt;/EM&gt;(whatever state it was previously in). After a certain number of consecutive failures, it becomes "&lt;EM&gt;unhealthy"&lt;/EM&gt;.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Building the image&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;From top directory of agent distribution (where distribution archive has been unzipped), run the following command:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;docker build -t ci360-cas-agent .&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;This will read &lt;EM&gt;Dockerfile&lt;/EM&gt; in current directory and build the image in local Docker repository with specified name.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT size="5"&gt;Publishing Docker Image&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Once image has been built, it can optionally be pushed/published to your chosen container registry.&amp;nbsp; In the example below we are pushing the image to a private AWS container registry:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Tag the image:&lt;/STRONG&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;docker tag ci360-cas-agent:latest xxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/ci360-cas-agent:latest&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Push the image:&lt;/STRONG&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;docker push xxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/ci360-cas-agent:latest&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Once pushed to a registry, an image can easily be used by others to deploy and run agent containers without the need to build the image themselves or even download agent distribution files.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS-Heading1"&gt;&lt;FONT size="5"&gt;Running Docker Container&lt;/FONT&gt;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;Since we can run multiple containers based on image we built, it is recommended that agent configuration file be maintained separately, on the host machine.&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;In our CAS Agent example, all agent files, including &lt;EM&gt;&lt;SPAN&gt;agent.config&lt;/SPAN&gt;&lt;/EM&gt; file, are located in &lt;EM&gt;&lt;SPAN&gt;/opt/ci360-cas-agent&lt;/SPAN&gt;&lt;/EM&gt; within the image. That means we could mount an external file to that location (/opt/ci360-cas-agent/agent.config) in order to override the config packaged with the agent. Agent entrypoint parameters point to this file and will read configuration from that location.&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;Once the agent image has been created, we can run the container using:&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;docker run -d --mount type=bind,source=/opt/install/cas/cas_agent_prd1.config,target=/opt/ci360-cas-agent/agent.config --name ci360-cas-prd1 ci360-cas-agent:latest&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;Mount option in the command line above is used to map a file on the host filesystem (/opt/install/cas/cas_agent_prd1.config) to the agent.config file within the container. We are also naming this container.&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;Since our goal is to run multiple instances, we could provide multiple different config files (if configuration between them is actually different) and container specific names. For example:&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;docker run -d --mount type=bind,source=/opt/install/cas/cas_agent_prd2.config,target=/opt/ci360-cas-agent/agent.config --name ci360-cas-prd2 ci360-cas-agent:latest

docker run -d --mount type=bind,source=/opt/install/cas/cas_agent_demo1.config,target=/opt/ci360-cas-agent/agent.config --name ci360-cas-demo1 ci360-cas-agent:latest&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;We can see that we are launching two new containers, named &lt;EM&gt;ci360-cas-prd2&lt;/EM&gt; and &lt;EM&gt;ci360-cas-demo1&lt;/EM&gt;, with two local files cas_agent_prd2.config and cas_agent_demo1.config as their configuration files respectively.&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="multiple_containers.jpg" style="width: 434px;"&gt;&lt;img src="https://communities.sas.com/t5/image/serverpage/image-id/96636iF2DB2427A3189F02/image-size/large?v=v2&amp;amp;px=999" role="button" title="multiple_containers.jpg" alt="multiple_containers.jpg" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;Of course, we can also run multiple containers that use the same configuration file, where &lt;BR /&gt;multiple instances simply provide horizontal scaling and failover capabilities. This will be a &lt;BR /&gt;common scenario for a single agent with always on and high-volume requirements.&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="multiple_containers_single_tenant.jpg" style="width: 455px;"&gt;&lt;img src="https://communities.sas.com/t5/image/serverpage/image-id/96637iA04C4D4F609C4E93/image-size/large?v=v2&amp;amp;px=999" role="button" title="multiple_containers_single_tenant.jpg" alt="multiple_containers_single_tenant.jpg" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&lt;FONT size="5"&gt;Deployment Steps for Kubernetes&lt;/FONT&gt;&lt;BR /&gt;In order to deploy the agent to Kubernetes environment, we will assume that agent image has &lt;BR /&gt;been built, it can be deployed and executed standalone in a Docker environment (e.g., desktop), &lt;BR /&gt;and it has been pushed to a container registry.&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&lt;STRONG&gt;&lt;FONT size="4"&gt;Create Kubernetes Artifacts&lt;/FONT&gt;&lt;/STRONG&gt;&lt;BR /&gt;Manifest YAML file needs to be created for deployment to Kubernetes. A sample YAML file &lt;BR /&gt;(ci360-cas-agent.yaml) is provided in its entirety below, and can also be found in SAS CI GitLab &lt;BR /&gt;repository:&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&lt;A href="https://github.com/sassoftware/ci360-extensions/blob/main/code/ci360-cas-agent/k8/ci360-cas-agent.yaml" target="_self"&gt;https://github.com/sassoftware/ci360-extensions/blob/main/code/ci360-cas-agent/k8/ci360-cas-agent.yaml&lt;/A&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;Take a copy of ci360-cas-agent.yaml manifest from the k8 directory of the agent as this will be &lt;BR /&gt;used to create the K8s artifacts. The YAML file contain definitions for creating a PersistentVolumeClaim, ConfigMap, Deployment &lt;BR /&gt;and a HorizontalPodAutoscaler. Part of the YAML file is configuration map, which in our example contains CI360 connection &lt;BR /&gt;information including CI360 gateway URL and credentials, as well as CAS details.&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&lt;BR /&gt;You will generally need to edit this YAML file to provide details of your ci360.gatewayHost, &lt;BR /&gt;ci360.tenantID, ci360.clientSecret, cas.username and cas.password which can be found in the &lt;BR /&gt;ConfigMap section:&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;ci360.gatewayHost=extapigwservice-demo.cidemo.sas.com
ci360.tenantID=0bf01xxxxxxxa3a2cacaa
ci360.clientSecret=MTAxOTIxxxxxxxxxxxxxxxxxxxN2ZpaWpp
cas.username=sasdemo
cas.password=xxxxxxxx&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;In this example, you will also need to update the Deployment section to provided details of your &lt;BR /&gt;“containers - image” and “imagePullSecrets - name” (if deployed to a private container registry):&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;imagePullSecrets:
- name: aws-pull-v2
containers:
- image: xxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/ci360-cas-agent:latest&lt;/PRE&gt;
&lt;P&gt;You should now be ready to apply this manifest your K8s cluster:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;kubectl apply -f ./ci360-cas-agent.yaml –namespace &amp;lt;YOUR NAMESPACE&amp;gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;To facilitate mapping of config file in the YAML file, and to show an example where change of Dockerfile is needed, we have slightly modified the ENTRYPOINT line in the Dockerfile before building and pushing the agent image:&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="SAS" style="margin-left: 0in;"&gt;&lt;STRONG&gt;Old:&lt;/STRONG&gt;&lt;/P&gt;
&lt;PRE&gt;ENTRYPOINT ["java", "-Dlogback.configurationFile=logback.xml", "-DconfigFile=agent.config", "-Djavax.net.ssl.trustStore=viya4_trustedcerts.jks", "-Xms32m", "-Xmx2048m", "-jar", "ci360-cas-agent-21.09.1.jar"]&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;New:&lt;/STRONG&gt;&lt;/P&gt;
&lt;PRE&gt;RYPOINT ["java", "-Dlogback.configurationFile=/ci360-cas-agent-config/logback.xml", "-DconfigFile=/ci360-cas-agent-config/agent.config", "-Djavax.net.ssl.trustStore=viya4_trustedcerts.jks", "-Xms32m", "-Xmx2048m", "-jar", "ci360-cas-agent-21.09.1.jar"]
&lt;/PRE&gt;
&lt;P&gt;All we are doing is changing the location within the image that agent will use to read logging &lt;BR /&gt;configuration and agent configuration files, and we will use those same locations within our &lt;BR /&gt;YAML file.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Mon, 20 May 2024 15:52:08 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Customer-Intelligence/Deploying-CI360-Agents-into-Containers-or-Kubernetes-environment/m-p/929057#M2016</guid>
      <dc:creator>BojanBelovic</dc:creator>
      <dc:date>2024-05-20T15:52:08Z</dc:date>
    </item>
  </channel>
</rss>

