So, I'm just starting with YAML and k8s and maybe this questions comes from lack of understanding how YAML and Helm works together. But I was wondering if I can declare a variable inside Values.YAML file that will be changed during the run of the scripts? I was thinking about accumulating value for each pod I am starting, that will be saved as an environment variable in each pod. I can manually create different value for each pod but I was wondering if there is an automatic way to do so? Hope my question is clear :)
CodePudding user response:
Helm allows for conditionals using its templating. For example, I can have this in my values.yaml
environment: preprod
And then this inside a yaml within my helm chart
{{ if eq .Values.environment "preprod" }}
## Do preprod stuff here
{{ end }}
{{ if eq .Values.environment "prod" }}
## Do prod stuff here
{{ end }}
This means if I ran helm install
, then .Values.environment
would resolve to "preprod" and the block within the {{ if eq .Values.environment "preprod" }}...{{ end }}
would be printed in the yaml.
If I wanted to override that default, I can by adding the --set
switch (details here)
helm install --set environment=prod
Which would cause the .Values.environment
variable to resolve to "prod" instead, and the block within {{ if eq .Values.environment "prod" }} ... {{ end }}
would be output instead.
CodePudding user response:
Helm templates are stateless, and the variables structure is immutable.
Can I declare a variable inside the
values.yaml
file that will be changed during the run of the scripts?
That's not possible, no.
If you have experience with functional programming, there are some related tricks you can use in the context of Helm templates. A template only takes one parameter, but you can make that parameter be a list, and then pass some state forward through a series of recursive template calls. If you're tempted to do this, consider writing a Kubernetes operator instead: even if you have to learn Go to do it, the language is much more mainstream and practical than the template language, and it's much easier to test.
This having been said:
... accumulating value for each pod I am starting ...
If all you're asking for is a set of Pods that are very similar except that they have sequential names, this is one of the things a StatefulSet provides.
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: some-name
spec:
replicas: 5
The Pods generated by this StatefulSet will be named some-name-0
, some-name-1
, and so on. Your application code can see these names via the hostname
command and language-specific equivalents. That could meet your needs.
If you need something more complex, you can also use a template range
loop to generate a series of documents. Each document needs to begin with a ---
YAML start-of-document marker. You need to be aware that range
rebinds the .
special template variable as appears in constructs like .Values
, and I tend to save that away.
{{- $top := . }}
{{- $i := range until 5 }}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ template "mychart.fullname" $top }}-{{ $i }}
spec: { ... }
{{- end }}
You should almost always use higher-level constructs like Deployments, StatefulSets, or Jobs instead of creating bare Pods. Trying to fit within their patterns will usually be a little easier than trying to manually create several very slightly different Pods.