diff --git a/sermant-injector/deployment/release/injector/templates/sermant-injector-configmap.yaml b/sermant-injector/deployment/release/injector/templates/sermant-injector-configmap.yaml index 3b8fe00acb..65cf50c4cc 100644 --- a/sermant-injector/deployment/release/injector/templates/sermant-injector-configmap.yaml +++ b/sermant-injector/deployment/release/injector/templates/sermant-injector-configmap.yaml @@ -21,5 +21,9 @@ data: # Injector injection action SERMANT_AGENT_INJECT_ACTION: {{ .Values.injector.action }} {{- if not (and .Values.configMap.enabled .Values.configMap.namespaces) }} + # External agent image address + SERMANT_AGENT_EXTERNALAGENT_IMAGEADDR: {{ .Values.externalAgent.imageAddr }} + # External agent file name in image + SERMANT_AGENT_EXTERNALAGENT_FILENAME: {{ .Values.externalAgent.fileName }} SERMANT_AGENT_CONFIGMAP: "" {{- end }} diff --git a/sermant-injector/deployment/release/injector/values.yaml b/sermant-injector/deployment/release/injector/values.yaml index b1fadc1be1..4ed9d6fa2e 100644 --- a/sermant-injector/deployment/release/injector/values.yaml +++ b/sermant-injector/deployment/release/injector/values.yaml @@ -26,6 +26,12 @@ agent: # Never(only local image is used, never pull) pullPolicy: IfNotPresent +externalAgent: + # external agent image address (for example: io.sermant/opentelemetry-javaagent:2.10.0) + imageAddr: + # external agent file name (for example: opentelemetry-javaagent.jar) + fileName: + config: # Configuration center type: ZOOKEEPER/KIE/NACOS type: ZOOKEEPER diff --git a/sermant-injector/images/external-agent/ExternalAgent.Dockerfile b/sermant-injector/images/external-agent/ExternalAgent.Dockerfile new file mode 100644 index 0000000000..956ee8ef4e --- /dev/null +++ b/sermant-injector/images/external-agent/ExternalAgent.Dockerfile @@ -0,0 +1,6 @@ +FROM alpine:latest + +WORKDIR /home + +# must copy agent file to /home, 'opentelemetry-javaagent.jar' is an example +COPY opentelemetry-javaagent.jar /home diff --git a/sermant-injector/images/external-agent/build-external-agent-image.sh b/sermant-injector/images/external-agent/build-external-agent-image.sh new file mode 100644 index 0000000000..d22d2bddb3 --- /dev/null +++ b/sermant-injector/images/external-agent/build-external-agent-image.sh @@ -0,0 +1,7 @@ +# image name of external-agent, 'opentelemetry-javaagent' is an example +imageName=io.sermant/opentelemetry-javaagent +# image version of external-agent +imageVersion=2.10.0 + +name=${imageName}:${imageVersion} +docker build -f dockerfile -t ${name} . diff --git a/sermant-injector/src/main/java/io/sermant/injection/controller/SermantInjectorController.java b/sermant-injector/src/main/java/io/sermant/injection/controller/SermantInjectorController.java index 5d107fe3fd..cbafb2a061 100644 --- a/sermant-injector/src/main/java/io/sermant/injection/controller/SermantInjectorController.java +++ b/sermant-injector/src/main/java/io/sermant/injection/controller/SermantInjectorController.java @@ -116,7 +116,7 @@ public class SermantInjectorController { private static final String IMAGE_PULL_POLICY_KEY = "imagePullPolicy"; - private static final String IMAGE_NAME = "sermant-agent"; + private static final String SERMANT_AGENT_INIT_CONTAINER_NAME = "sermant-agent"; private static final String VOLUME_DIR = "emptyDir"; @@ -180,6 +180,20 @@ public class SermantInjectorController { private static final String SERMANT_ENV_PREFIX = "env.sermant.io/"; + private static final String EXTERNAL_AGENT_INJECTION_CONFIG_KEY = "agent_config_externalAgent_injection"; + + private static final String EXTERNAL_AGENT_NAME_CONFIG_KEY = "agent_config_externalAgent_name"; + + private static final String EXTERNAL_AGENT_FILE_CONFIG_KEY = "agent_config_externalAgent_file"; + + private static final String EXTERNAL_AGENT_INIT_CONTAINER_NAME = "external-agent"; + + /** + * if external agent injection is to be enabled, the annotations should be config as + * 'env.sermant.io/external.agent.injection:"OTEL"' in spec -> template ->metadata -> annotations + */ + private static final String EXTERNAL_AGENT_INJECTION_ENV_IN_ANNOTATION = "external.agent.injection"; + @Autowired private ObjectMapper om; @@ -213,6 +227,12 @@ public class SermantInjectorController { @Value("${sermant-agent.inject.action:before}") private String action; + @Value("${sermant-agent.externalAgent.imageAddr:}") + private String externalAgentAddr; + + @Value("${sermant-agent.externalAgent.fileName:}") + private String externalAgentFileName; + /** * Admission controller * @@ -258,7 +278,9 @@ private Optional inject(ObjectNode body) { ArrayNode arrayNode = om.createArrayNode(); // Added initContainers node - injectInitContainer(arrayNode, specNode); + injectSermantInitContainer(arrayNode, specNode); + + injectExternalAgentInitContainer(arrayNode, annotationEnv); // Add volume nodes injectVolumes(arrayNode, specNode); @@ -308,6 +330,11 @@ private void setEnvByMap(JsonNode srcMap, Map tgtEnv) { String envKey = labelName.substring(prefixLength); String envValue = srcMap.findValue(labelName).textValue(); tgtEnv.put(envKey, envValue); + if (envKey.equals(EXTERNAL_AGENT_INJECTION_ENV_IN_ANNOTATION)) { + tgtEnv.put(EXTERNAL_AGENT_INJECTION_CONFIG_KEY, Boolean.TRUE.toString()); + tgtEnv.put(EXTERNAL_AGENT_NAME_CONFIG_KEY, envValue); + tgtEnv.put(EXTERNAL_AGENT_FILE_CONFIG_KEY, mountPath + PATH_SEPARATOR + externalAgentFileName); + } } } } @@ -327,31 +354,54 @@ private void setEnv(JsonNode containersPath, Map> c } } - private void injectInitContainer(ArrayNode arrayNode, JsonNode specPath) { - // Create an initContainer - ObjectNode initContainerNode = putOrAddObject(arrayNode, specPath, INIT_CONTAINERS_PATH, + private void injectSermantInitContainer(ArrayNode arrayNode, JsonNode specPath) { + ObjectNode sermantInitContainerNode = putOrAddObject(arrayNode, specPath, INIT_CONTAINERS_PATH, INIT_CONTAINERS_INJECT_PATH); + constructInitContainerNode(sermantInitContainerNode, SERMANT_AGENT_INIT_CONTAINER_NAME, imageAddr, + INIT_COMMAND); + } + + private void injectExternalAgentInitContainer(ArrayNode arrayNode, Map annotationEnv) { + if (!StringUtils.hasText(annotationEnv.get(EXTERNAL_AGENT_INJECTION_ENV_IN_ANNOTATION))) { + return; + } + + ObjectNode node = arrayNode.addObject(); + node.put(JSON_OPERATION_KEY, JSON_OPERATION_ADD); + node.put(PATH_KEY, INIT_CONTAINERS_INJECT_PATH + END_PATH); + + ObjectNode externalAgentInitContainerNode = node.putObject(VALUE_KEY); + List initCommandForExternalAgent = + Arrays.asList(new TextNode("cp"), new TextNode("/home/" + externalAgentFileName), + new TextNode(mountPath)); + constructInitContainerNode(externalAgentInitContainerNode, EXTERNAL_AGENT_INIT_CONTAINER_NAME, + externalAgentAddr, initCommandForExternalAgent); + } + + private void constructInitContainerNode(ObjectNode initContainerNode, String containerName, String image, + List command) { // Image name - initContainerNode.put(NAME_KEY, IMAGE_NAME); + initContainerNode.put(NAME_KEY, containerName); // Image address - initContainerNode.put(IMAGE_KEY, imageAddr); + initContainerNode.put(IMAGE_KEY, image); // Image pulling policy initContainerNode.put(IMAGE_PULL_POLICY_KEY, pullPolicy); // Initialization command - initContainerNode.putArray(COMMAND_KEY).addAll(INIT_COMMAND); + initContainerNode.putArray(COMMAND_KEY).addAll(command); // Create a volumeMount - ObjectNode initContainerVolumeMountNode = initContainerNode.putArray(VOLUME_MOUNTS_PATH).addObject(); + ObjectNode externalAgentVolumeMountNode = initContainerNode.putArray(VOLUME_MOUNTS_PATH) + .addObject(); // Disk name - initContainerVolumeMountNode.put(NAME_KEY, VOLUME_NAME); + externalAgentVolumeMountNode.put(NAME_KEY, VOLUME_NAME); // Disk path - initContainerVolumeMountNode.put(MOUNT_PATH, INIT_SERMANT_PATH); + externalAgentVolumeMountNode.put(MOUNT_PATH, INIT_SERMANT_PATH); } private void injectVolumes(ArrayNode arrayNode, JsonNode specPath) { diff --git a/sermant-injector/src/main/resources/application.yml b/sermant-injector/src/main/resources/application.yml index 09a29fa51f..aa2538d1d6 100644 --- a/sermant-injector/src/main/resources/application.yml +++ b/sermant-injector/src/main/resources/application.yml @@ -39,6 +39,9 @@ sermant-agent: # injection before the original variable (default), after indicates injection after the original variable, and # ignore indicates that injection is not performed action: before + externalAgent: + imageAddr: io.sermant/opentelemetry-javaagent:2.10.0 + fileName: opentelemetry-javaagent.jar management: endpoint: