Non-Helm Service Dependencies in Helm Service Builds

This page will describe the process for creating a Helm chart for a skaffold/kustomize service so that it can be included as an HMP dependency for build and test.

From a deployment perspective, one of the biggest differences between skaffold/kustomize and HMP projects is that the skaffold/kustomize projects use kubernetes configMaps instead of consul. The chart produced in the example includes the creation of the configMap that the skaffold/kustomize service will need in order to deploy correctly.

  • No transitive dependencies will be included in the chart built below. It will be necessary for the HMP service owner to determine which dependencies are needed by the skaffold/kustomize service and to include those dependencies in their metadata.yaml.

The scenario described here adds a Helm chart for mobile-mvi-service:1.33.0 (skaffold/kustomize) for use as a dependency in enterprise-patient-search-service (the HMP service).

Create and locally publish a Helm chart for the skaffold/kustomize service

  1. Create helm chart

    1. Create a directory named helm-dependency/mobile-mvi-service (or name of your choice) under the service directory

    2. If service was originally an HMP-based service ,then copy the service helm/chart directory from the last HMP-based version to the new directory

    3. If service was created as a skaffold/kustomize service:

      1. Copy an existing project’s service/helm/chart directory to the directory created above

  2. Remove any chart/local- or remote-test-override-values.yaml files as they won’t be needed for this chart

  3. Update files in the directory created above:

    1. add to chart/templates/deployment-configmap.yaml in the spec.template.spec.containers section:

                envFrom:
                - configMapRef:
                    name: {{ .Release.Name }}-env-configmap
    2. add file env-configmap.yaml to chart/templates dir with content:

                  apiVersion: v1
                  kind: ConfigMap
                  metadata:
                    name: {{ .Release.Name }}-env-configmap
                  data:
                  {{- $envFile := .Files.Get "dev-application.env" }}
                  {{- range $line := $envFile | splitList "\n" }}
                    {{- $pair := $line | splitList "=" }}
                    {{- if ge (len $pair) 2 }}
                    {{ trim (index $pair 0) }}: {{ trim (rest $pair | join "=") | quote }}
                    {{- end }}
                  {{- end}}
    3. add file dev-application.env to helm/chart dir. This file should be populated with entries from common-app-config (https://coderepo.mobilehealth.va.gov/projects/CKM/repos/common-app-config/browse/dev), kubernetes/components/dev/application.env (from the service repo that you are trying to use), and values defined for vault in kubernetes/components/secrets (from the service repo that you are trying to use). See the dev-application.env example below.

    4. changes to helm/chart/values.yaml (see Chart/values.yaml (before) and Chart/values.yaml (after))

      1. set serviceName to name of service being updated

      2. set dtrpath value to reflect correct project (ex: CKM, CES, etc.)

      3. set version field to skaffold/kustomize service version

      4. set chartVersion to skaffold/kustomize service version

      5. update majorVersion if necessary

      6. change imagePullPolicy to IfNotPresent (optional)

      7. remove all consul definitions

      8. remove all definitions for dependencies (wiremock, redis, etc.)

    5. changes to Chart.yaml:

      1. set appVersion to match skaffold/kustomize service version

      2. set version to match skaffold/kustomize service version

Update HMP service to use new chart.

  1. Determine what dependencies the skaffold/kustomize project needs that are NOT already provided by the service being tested. To find the dependencies see the skaffold/kustomize service /kubernetes/dev-with-dependencies directory. For example, mobile-mvi-service has redis-v7 and wiremock as dependencies. enterprise-patient-search-service already provides wiremock so we just need to add the redis-v7 dependency.

  2. Update pom.xml to specify the skaffold/kustomize version of the dependent service

    1. Update mobile-mvi-client.version to 1.33

    2. Update mobile.mvi.service.version to 1.33.0

  3. Add plugin to pom.xml to copy chart for build/test

    1. Add the following plugin to the <build><plugins> section of pom.xml:

                  <plugin>
                      <groupId>org.apache.maven.plugins</groupId>
                      <artifactId>maven-resources-plugin</artifactId>
                      <executions>
                          <execution>
                              <id>copy-dependent-helm-chart</id>
                              <goals>
                                  <goal>copy-resources</goal>
                              </goals>
                              <phase>package</phase>
                              <configuration>
                                  <resources>
                                      <resource>
                                          <directory>${project.basedir}/helm-dependency/mobile-mvi-service/chart</directory>
                                          <includes>**/*</includes>
                                      </resource>
                                  </resources>
                                  <outputDirectory>${project.build.directory}/helm/${project.artifactId}-${project.version}/charts/mobile-mvi-service</outputDirectory>
                              </configuration>
                          </execution>
                      </executions>
                  </plugin>
  4. Update metadata.yaml

    1. Update helm.dependencies in metadata.yaml with

      - group: gov.va.mobile.mock
        name: redis
        version: 7.0.15.0
    2. Remove existing mobile-mvi-service dependency from `helm.dependencies

  5. Test the changes by running mvn clean verify

Examples

dev-application.env

#- from common.env
SBA_PATH=http://spring-boot-admin-service:8080/sba/v1
JWT_PUBLIC_KEY=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwRs7d+tRAuK4soDInuKp51lTTTXWN8okXR3/gSHiIB+q7vZeAGWA8ULjCYuECLde8tS6OxzZwSj/oM0kZBXuHKYq2ukWKjTEmOwlpQW4vBpX60bcx5rXwoEjbcWghK9oVWwY4OwbAJ4TYklkUHZC5buQ+8RU59u6FIWSv2N3D9VBkfYsHvp3O4aXVaE8dZ0dxldUdv/WePoLkCeUYgLsGyDg/zsZvDrX1+yvNsjNNmB/ksJSoptMv9CfyUpSXsfov+8GhBCtgzDvgn32kw79wPsrTkgnC0DRtuv+y3qCXX+ZJ6cbJ31tVus9AadUn2CrWJur6/KRYsniQaEnfA43hwIDAQAB
#- from components/dev/application.env
MVI_URL=http://wiremock:8080/mvi/mockVAIdMPort
MVI_READ_TIMEOUT=5000
MVI_CONNECT_TIMEOUT=5000
REDIS_HOST=redis-v7
LOGGING_LEVEL_GOV_VA_VAMF_MVI_V1=DEBUG
MOBILE_MVI_SERVICE_CACHING_SAMPLING_RATE=2
RESILIENCE4J_CIRCUITBREAKER_CONFIGS_MPI_WAIT_DURATION_IN_OPEN_STATE=2s
RESILIENCE4J_CIRCUITBREAKER_CONFIGS_MPI_MINIMUM_NUMBER_OF_CALLS=20
RESILIENCE4J_CIRCUITBREAKER_CONFIGS_MPI_SLIDING_WINDOW_SIZE=5
RESILIENCE4J_CIRCUITBREAKER_CONFIGS_MPI_SLOW_CALL_DURATION_THRESHOLD=2s
RESILIENCE4J_CIRCUITBREAKER_CONFIGS_CACHE_SLOW_CALL_DURATION_THRESHOLD=10s
ENABLE_AUDIT_EVENTS=false
#- from components/secrets
CACHE_ENC_PASS=local_PBE_123
SVC_KEY_P12_PWD=password
SVC_KEY_P12=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

Chart/values.yaml (before)

global:
  includeResourceConstraints: false
  imagePullPolicy: Always
  consulServer: http://consul:8500/v1/kv
  consulPathContext: ckm
  disableLivenessProbeAll: true
  disableVaultAll: true
  jacocoImagePath: ckm/jacoco-agent-docker:0.8.8
  jacocoInitContainerCommand: '[''sh'', ''-c'', ''cp /jacoco/lib/jacocoagent.jar /jacoco-shared/jacoco-agent.jar'']'
  consulInitContainerImagePath: macm/byrnedo/alpine-curl:0.1.8
serviceName: mobile-mvi-service
serviceType: ClusterIP
servicePort: 8080
containerPort: 8080
debugPort: 8000
cpuLimit: 1000m
memoryLimit: 1Gi
maxUnavailable: 0
livenessProbe:
  enabled: true
  type: tcpSocket
  period: 20
  tcpSocketPort: 8080
  httpPort: 8081
  httpPath: /actuator/health/liveness
readinessProbe:
  enabled: true
  type: http
  period: 10
  tcpSocketPort: 8080
  httpPort: 8081
  httpPath: /actuator/health/readiness
startupProbe:
  enabled: true
  type: http
  httpPath: /actuator/health/liveness
  httpPort: 8081
  period: 1
  failureThreshold: 300
enableEnvConsul: true
enableVault: false
jacocoImage: dtr.mapsandbox.net/macm/ictu/jacoco-agent-docker:0.8.3
jacocoInitContainerCommand: '[''sh'', ''-c'', ''cp /jacoco/lib/jacocoagent.jar /jacoco-shared/jacoco-agent.jar'']'
jacocoPort: 6300
consulInitContainerImage: byrnedo/alpine-curl:0.1.8
dtr: dtr.mapsandbox.net
dtrPath: ckm
imagePullSecret: dtrsecret
envConfigs:
  staging:
    dtr: utility.apps.va.gov
    jacocoImage: utility.apps.va.gov/macm/ictu/jacoco-agent-docker:0.8.3
    consulInitContainerImage: utility.apps.va.gov/macm/byrnedo/alpine-curl:0.1.8
additionalServicePorts:
- port: 8081
  name: actuator
  targetPort: 8081
consul:
  appConfig:
    JWT_PUBLIC_KEY: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwRs7d+tRAuK4soDInuKp51lTTTXWN8okXR3/gSHiIB+q7vZeAGWA8ULjCYuECLde8tS6OxzZwSj/oM0kZBXuHKYq2ukWKjTEmOwlpQW4vBpX60bcx5rXwoEjbcWghK9oVWwY4OwbAJ4TYklkUHZC5buQ+8RU59u6FIWSv2N3D9VBkfYsHvp3O4aXVaE8dZ0dxldUdv/WePoLkCeUYgLsGyDg/zsZvDrX1+yvNsjNNmB/ksJSoptMv9CfyUpSXsfov+8GhBCtgzDvgn32kw79wPsrTkgnC0DRtuv+y3qCXX+ZJ6cbJ31tVus9AadUn2CrWJur6/KRYsniQaEnfA43hwIDAQAB
    MVI_URL: http://wiremock:8080/mvi/mockVAIdMPort
    MVI_READ_TIMEOUT: 5000
    MVI_CONNECT_TIMEOUT: 5000
    REDIS_HOST: redis-v5
    CACHE_ENC_PASS: local_PBE_123
    LOGGING_LEVEL_GOV_VA_VAMF_MVI_V1: DEBUG
    MOBILE_MVI_SERVICE_CACHING_SAMPLING_RATE: 2
    RESILIENCE4J_CIRCUITBREAKER_CONFIGS_MPI_WAIT_DURATION_IN_OPEN_STATE: 2s
    RESILIENCE4J_CIRCUITBREAKER_CONFIGS_MPI_MINIMUM_NUMBER_OF_CALLS: 20
    RESILIENCE4J_CIRCUITBREAKER_CONFIGS_MPI_SLIDING_WINDOW_SIZE: 5
    RESILIENCE4J_CIRCUITBREAKER_CONFIGS_MPI_SLOW_CALL_DURATION_THRESHOLD: 2s
    RESILIENCE4J_CIRCUITBREAKER_CONFIGS_CACHE_SLOW_CALL_DURATION_THRESHOLD: 10s
    ENABLE_AUDIT_EVENTS: false
  apigatewayConfig:
    location: /mvi/v1
    service: mobile-mvi-service-v1
    external: 'true'
    port: '8080'
    redirect: 'off'
    headers:
      X-Forwarded-Host: $http_host
      X-Forwarded-proto: $scheme
    Host: http_host
version: 1.31.1
chartVersion: 1.31.1
majorVersion: '1'
wiremock:
  jacocoImage: dtr.mapsandbox.net/macm/ictu/jacoco-agent-docker:0.8.3
  consulInitContainerImage: dtr.mapsandbox.net/macm/byrnedo/alpine-curl:0.1.8
redis:
  jacocoImage: dtr.mapsandbox.net/macm/ictu/jacoco-agent-docker:0.8.3
  consulInitContainerImage: dtr.mapsandbox.net/macm/byrnedo/alpine-curl:0.1.8
consul-bootstrap-dev:
  jacocoImage: dtr.mapsandbox.net/macm/ictu/jacoco-agent-docker:0.8.3
  consulInitContainerImage: dtr.mapsandbox.net/macm/byrnedo/alpine-curl:0.1.8

Chart/values.yaml (after)

global:
  includeResourceConstraints: false
  imagePullPolicy: IfNotPresent
  disableLivenessProbeAll: true
  disableVaultAll: true
  jacocoImagePath: ckm/jacoco-agent-docker:0.8.8
  jacocoInitContainerCommand: '[''sh'', ''-c'', ''cp /jacoco/lib/jacocoagent.jar /jacoco-shared/jacoco-agent.jar'']'
serviceName: mobile-mvi-service
serviceType: ClusterIP
servicePort: 8080
containerPort: 8080
debugPort: 8000
cpuLimit: 1000m
memoryLimit: 1Gi
maxUnavailable: 0
livenessProbe:
  enabled: true
  type: tcpSocket
  period: 20
  tcpSocketPort: 8080
  httpPort: 8081
  httpPath: /actuator/health/liveness
readinessProbe:
  enabled: true
  type: http
  period: 10
  tcpSocketPort: 8080
  httpPort: 8081
  httpPath: /actuator/health/readiness
startupProbe:
  enabled: true
  type: http
  httpPath: /actuator/health/liveness
  httpPort: 8081
  period: 1
  failureThreshold: 300
enableEnvConsul: false
enableVault: false
jacocoImage: dtr.mapsandbox.net/macm/ictu/jacoco-agent-docker:0.8.3
jacocoInitContainerCommand: '[''sh'', ''-c'', ''cp /jacoco/lib/jacocoagent.jar /jacoco-shared/jacoco-agent.jar'']'
jacocoPort: 6300
dtr: dtr.mapsandbox.net
dtrPath: ckm
imagePullSecret: dtrsecret
envConfigs:
  staging:
    dtr: utility.apps.va.gov
    jacocoImage: utility.apps.va.gov/macm/ictu/jacoco-agent-docker:0.8.3
additionalServicePorts:
- port: 8081
  name: actuator
  targetPort: 8081
version: 1.33.0
chartVersion: 1.33.0
majorVersion: '1'