kubernetes-sigs / kustomize

Customization of kubernetes YAML configurations
Apache License 2.0
10.99k stars 2.25k forks source link

Enhancement: Literal vars #318

Closed ssboisen closed 4 years ago

ssboisen commented 6 years ago

Sometimes I have vars that doesn't necessarily make sense to put into a configmap. Currently I use a configMapGenerator with literal values and then refer to that from the vars section of kustomization.yaml. However that is the only reason I'm creating the configmap and thus being able to do the following would be nice.

vars:
  - name: MY_VAR
    literal: "my var value"
Liujingfang1 commented 6 years ago

In this case, it's better to use JSON patch once it's available #169

ssboisen commented 6 years ago

that sounds great, looking forward to a JSON patch example :)

thanks!

saturnism commented 5 years ago

quick que - how does json patch solve the literal var problem?

jonathanunderwood commented 5 years ago

A JSON patch doesnt solve this use case. Can we reopen this?

jkubrynski commented 5 years ago

+1 for reopening this issue. Json patch doesn't help here at all

b2cbre commented 5 years ago

@Liujingfang1 how does the JSON patch feature address setting literal variables without going through hoops like @ssboisen stated in his opening post?

dirien commented 5 years ago

Hi,

i would like express the need vor having vars with literall. Especially, when we want to use the vars in the data value of a configmap.

At the moment i use varReference to expand vars in the data value of a configMap.

Is there a chance to address this request?

micke commented 5 years ago

I would also like to see this being reopened. I've been using a configmap literal as a workaround but it adds a lot of unnecessary complexity...

tkellen commented 5 years ago

Add a another request to the pile. I am doing the same seemingly contorted dance of generating a configmap that will never be used so I can reference values in it. If a PR would be considered I would be happy to implement this.

cabrinha commented 5 years ago

It seems that defining environment variables for containers, with different values per environment would be one of the first problems solved with a templating tool.

Somehow, this is still a very confusing topic with almost no documentation or usage examples.

What is the right way to have environment variables configured in different environments/overlays using Kustomize?

tkellen commented 5 years ago

@cabrinha There is no right way, this is considered an antipattern within kustomize. Here is a relevant section in the documentation: https://github.com/kubernetes-sigs/kustomize/blob/master/docs/eschewedFeatures.md#build-time-side-effects-from-cli-args-or-env-variables

The basic concept is that within a given manifest (that is, the output of kustomize build), you can mix and match values between the resources in a structured way (see vars).

This prevents kustomize from devolving into a general purpose programming language like every other templating solution out there.

If this issue tracker is any evidence, the way people are getting per-environment values into kustomize is by generating a configmap or crd-type file with the "global" variables for a given environment and then using references to values within it throughout the rest of their resources. This works wonderfully but the whole process could be greatly simplified by simply allowing literal values to be specified in a file and version controlled.

/cc @jbrette

jonathanunderwood commented 5 years ago

@tkellen that's a great summary of the situation, nicely put.

jbrette commented 5 years ago

@ssboisen @jonathanunderwood @tkellen @ian-howell @cabrinha Another occurrence where I think that this Automatic Creation of 'vars:' and 'varReferences:' sections

Have a look at: issue 0318 but mainly at issue 0318 b.

In 0318_b we almost doing exactly what you are proposing. Simply instead of putting that in the kustomization.yaml we add that to values.yaml. We can then using strategicMergePatch, jsonPatch...on that values.yaml. Currently kustomize needs a special transformer to filter the Values resource from the output, but it could be builtin. (The same we don't render the kustomization.yaml)

monopole commented 5 years ago

@tkellen Thanks for the summary. As you've alluded, there's no point to letting kustomize become yet another templating system or domain-specific language. Plenty of choices there already.

We want to see if its possible to maintain the base YAML in such a way that it's entirely functional - i.e. you can apply it to a cluster and it works. Any mutation mechanism that requires one to place dollar variables in the base breaks this, as it converts the base into a template that cannot be used without processing. Further, dollar variables open the door to unstructured edits, which breaks many wonderful things in a git rebase workflow. Baby tossed with bath-water.

What about something like

replacements:
- value: someValue
  targets:
  -  gvk: Deployment
     path: some/path
  -  gvk: Deployment
     path: some/other/path

The value of someValue could be a literal (e.g. 8080) or a reflection style address to some other resource path in scope for the kustomization. This is just another form of patching.

aside: we know we already allow dollar vars in the base - but we're looking to back away from that feature rather than make it more sophisticated for reasons already mentioned.

tkellen commented 5 years ago

Thanks for re-opening this @monopole (also thanks to you and anyone else involved in illuminating this method of managing config, I'm a complete convert even with the rough edges!)

I'm not 100% sure I'm following what you've suggested here, but I think I can share succinctly a config format that would solve every use-case I can think of and eliminate the usage of dollar variables in any context other than inside a kustomization.yml.

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
nameSuffix: -$(vars.name)
commonLabels:
  app: $(resources.base.vars.type)-$(vars.name)
images:
  - name: container
    newName: $(resources.base.vars.env.registry)/$(commonLabels.app)
    newTag: $(vars.version)
resources:
- name: base
  path: ../../shared/kubernetes/dev/ingestor
patches:
  - target: extensions/v1beta1/Ingress/$(commonLabels.app)
    patch: |-
    - op: replace
      path: /spec/rules/0/host
      value: $(branch)poller.$(resources.base.vars.env.domain)
  - target: apps/v1/Deployment/$(commonLabels.app)
    patch: |-
    - op: add
      path: /spec/template/spec/containers/0/env/0
      value:
          name: APP_PGHOST
          value: $(resources.base.vars.env.rds_host)
    - op: add
      path: /spec/template/spec/containers/0/env/0
      value:
          name: APP_SECRET_PATH_PGPASSWORD
          value: $(resources.base.vars.env.secret_prefix)/$(commonLabels.app)/pgpassword
vars:
  name: salesforce
  branch:
    path: branch
    type: text/plain
    defaultValue: master
  version:
    path: version
    type: text/plain
    defaultValue: $(vars.branch)

Below, I've enumerated what the external files referenced above would contain:

../../shared/kubernetes/dev/ingestor/kustomization.yml

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
 - ../../base/ingestor/deployment.yml
 - ../../base/ingestor/service.yml
 - ../../base/ingestor/ingress.yml
vars:
  type: ingestor
  env:
    path: ../cluster/env.yml
    type: text/yaml

../cluster/env.yml

domain: dev.domain.com
rds_host: demo-dev-ci.ct5hetunyyge.us-east-1.rds.amazonaws.com
registry: 925201748409.dkr.ecr.us-east-1.amazonaws.com/demo
secret_prefix: /org-project

branch (generated by CI, only present during feature branch deployments to an isolated namespace):

feature-123

version (generated by CI, checked into repo):

b85e67a06c5e332271e36b29c45afc000cf8248d

This, in conjunction with @jbrette's autovar work for mixing and matching values between resources without having to specify varReferences by hand would be amazing. Again, in this proposal it would not be possible to use dollar vars directly within the source k8s yaml files.

What do you think? Does any subset of this fit within the boundaries of what you think kustomize should do? I wish I had the time to implement this.

jonathanunderwood commented 5 years ago

The proposal by @tkellen captures exactly and completely my use case.

Liujingfang1 commented 5 years ago

Opened a PR for adding a replacements field. It supports reading a literal values or reading a fieldref from a resource and replace a fieldref in another resource.

monopole commented 4 years ago

modulo @tkellen 's comment, this issue is asking for kustomize to become a general template engine.

That's a non-goal of this project. That linked text mentions templating tools you could use instead. If you want to stick with kustomize (yay), but want to break glass and use general VAR's until we figure this out, you can use the SedTransformer (or roll your own transformer in a similar vein). Try to think about how your situation can be modified to avoid it, while we get replacement transformers working.

@tkellen, it's an interesting idea to confine vars to just the kustomization file, and thanks for recognizing the spirit of what we're trying to do. however, let's see how far we can get with replacements before succumbing to $vars in any form.

Although kustomizations are currently client side objects only there are many reasons for them to remain valid k8s objects (valid YAML, valid KRM), and we want to build on them as such.