3

I want to have a Kustomize manifest where value for some attribute comes from entire contents of some file or URI.

How can I do this?

Ark-kun
  • 6,358
  • 2
  • 34
  • 70

3 Answers3

2

Usually with kustomize what you are going to use is an overlay and patches (which is one or multiple files) that are kind of merged into your base file. A Patch overrides an attribute. With those two features you predefine some probable manifest-compositions and just combine them right before you apply them to your cluster.

You can add or edit/set some specific attributes with patches or with kustomize subcommands like so:

kustomize edit set image your-registry.com:$image_tag

# just to identify version in metadata sections for service/deployment/pods - not just via image tag
kustomize edit add annotation appVersion:$image_tag
kustomize build . | kubectl -n ${your_ns} apply -f -

But if you want to have a single manifest file and manipulate the same attributes over and over again (on the fly), you should consider using helm's templating mechanism. This is also an option if kustomize does not allow you to edit that single specific attribute you want to alter.

You just need a values.yaml file (containing key/value pairs) and a template.yaml file. You can pre-set some attributes in the values.yaml - on demand you can override them per CLI. The tool will generate you a k8s manifest with those values backed in.

template file:

---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: {{ .Values.appSettings.appName }}
  namespace: {{ .Values.appSettings.namespace }}
  labels:
    name: {{ .Values.appSettings.appName }}
spec:
  replicas: 1
  template:
    metadata:
      labels:
        name: {{ .Values.appSettings.appName }}
    spec:
      containers:
        - name: {{ .Values.appSettings.appName }}
          image: "{{ .Values.appSettings.image }}"
          ports:
            - containerPort: 8080
[...]

---
apiVersion: v1
kind: Service
metadata:
  name: {{ .Values.appSettings.appName }}-svc
  namespace: {{ .Values.appSettings.namespace }}
  labels:
    name: {{ .Values.appSettings.appName }}
spec:
  ports:
    - port: 8080
      targetPort: 8080
  selector:
    name: {{ .Values.appSettings.appName }}

Values file:

appSettings:  
  appName: your-fancy-app
  appDomain: please_override_via_cli
  namespace: please_override_via_cli

CLI:

helm template
  --set appSettings.image=your-registry.com/service:$(cat versionTag.txt)
  --set appSettings.namespace=your-ns
  --set appSettings.appDomain=your-domain.com
  ./ -f ./values.yaml | kubectl apply -f -
fuma
  • 5,067
  • 4
  • 35
  • 39
  • Thank you for the detailed explanation. I wanted to verify the following: There is no way to use the whole file (not just part of it as in values.yaml) as a value for an attribute. Is that correct? The use case is the following: Suppose I want to create a deployment where the container command is some script. I'd like that script to exist in a script.sh and only be included in the deployment.yaml manifest when it's applied to Kubernetes cluster. – Ark-kun Nov 06 '19 at 18:59
1

You can include a remote kustomization.yml file but not a single value. You could build your own transformer plugin if you really wanted to, but it's not really in the spirit of Kustomize.

coderanger
  • 52,400
  • 4
  • 52
  • 75
1

The typical pattern to import complete files with Kustomize is to use ConfigMaps or Secrets

With configMapGenerator and secretGenerator you can import config files or environment variables, that you can then use in a Pod or Deployment by mounting them as volumes (for files) or using envFrom for environment variables.

For example:

configMapGenerator:
- name: my-env-cm
  namespace: my-namespace
  envs:
  - params.env
- name: my-config-file
  behavior: replace
  files:
  - config.json=config.json # <file name>=<local file to use>
  - other_config.json=other_config_file.json

where params.env is:

FOO=bar
BAZ=qux

The Deployment then looks like:

volumes:
- name: config-file
  configMap:
    name: my-config-file
containers:
- name: myapp
  env:
  - name: FOO_FROM_CM
    valueFrom:
      configMapKeyRef:
        name: my-env-cm
        key: FOO
# or directly import all env variables
  envFrom:
  - configMapRef:
    name: my-env-cm
# for files:  
  volumeMounts:
  - mountPath: /etc/config
    name: config-file
    # config.json and other_config.json will be mounted under /etc/config/

I've even seen people mounting scripts in ConfigMaps to pass as a parameter to their pod (which admittedly can raise security concerns)

MrE
  • 19,584
  • 12
  • 87
  • 105