skip to Main Content

In our project, which also uses Kustomize, our base deployment.yaml file looks like this:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:IMAGE_TAG # <------------------------------
        ports:
        - containerPort: 80

Then we use sed to replace IMAGE_TAG with the version of the image we want to deploy.

Is there a more sophisticated way to do this, rather than editing the text yaml file using sed?

3

Answers


  1. There is a specific transformer for this called the images transformer.
    You can keep your deployment as it is, with or without tag:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-deployment
      labels:
        app: nginx
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - name: nginx
            image: nginx
            ports:
            - containerPort: 80
    

    and then in your kustomization file:

    apiVersion: kustomize.config.k8s.io/v1beta1
    kind: Kustomization
    
    resources:
      - deployment.yaml
    
    images:
      - name: nginx
        newTag: MYNEWTAG
    

    Do keep in mind that this will replace the tag of all the nginx images of all the resources included in your kustomization file. If you need to run multiple versions of nginx you can replace the image name in your deployment by a placeholder and have different entries in the transformer.

    Login or Signup to reply.
  2. It is possible to use an image tag from an environment variable, without having to edit files for each different tag. This is useful if your image tag needs to vary without changing version-controlled files.

    Standard kubectl is enough for this purpose. In short, use a configMapGenerator with data populated from environment variables. Then add replacements that refer to this ConfigMap data to replace relevant image tags.

    Example

    Continuing with your example deployment.yaml, you could have a kustomization.yaml file in the same folder that looks like so:

    apiVersion: kustomize.config.k8s.io/v1beta1
    kind: Kustomization
    
    # Generate a ConfigMap based on the environment variables in the file `.env`.
    configMapGenerator:
      - name: my-config-map
        envs:
          - .env
    
    replacements:
      - source:
          # Replace any matches by the value of environment variable `MY_IMAGE_TAG`.
          kind: ConfigMap
          name: my-config-map
          fieldPath: data.MY_IMAGE_TAG
        targets:
          - select:
              # In each Deployment resource …
              kind: Deployment
            fieldPaths:
              # … match the image of container `nginx` …
              - spec.template.spec.containers.[name=nginx].image
            options:
              # … but replace only the second part (image tag) when split by ":".
              delimiter: ":"
              index: 1
    
    resources:
      - deployment.yaml
    

    In the same folder, you need a file .env with the environment variable name only (note: just the name, no value assigned):

    MY_IMAGE_TAG
    

    Now MY_IMAGE_TAG from the local environment is integrated as the image tag when running kubectl kustomize, kubectl apply --kustomize, etc.

    Demo:

    MY_IMAGE_TAG=foobar kubectl kustomize .
    

    This prints the generated image tag, which is foobar as desired:

    # …
    spec:
      # …
      template:
        # …
        spec:
          containers:
            - image: nginx:foobar
              name: nginx
              ports:
                - containerPort: 80
    

    Alternatives

    Keep the following in mind from the configMapGenerator documentation:

    Note: It’s recommended to use the local environment variable population functionality sparingly – an overlay with a patch is often more maintainable. Setting values from the environment may be useful when they cannot easily be predicted, such as a git SHA.

    If you are simply looking to share a fixed image tag between multiple files, see the already suggested images transformer.

    Login or Signup to reply.
  3. @evolutics answer is probably "proper" way to do it but if you are customizing only image tag every deployment you could consider putting $IMAGE_TAG variable in deployment.yaml and using envsubst command.

    Example:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-deployment
      labels:
        app: nginx
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - name: nginx
            image: nginx:$IMAGE_TAG
            ports:
            - containerPort: 80
    
    IMAGE_TAG=my_image_tag envsubst '${IMAGE_TAG}' < deployment.yaml > final_deployment.yaml
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search