Sometimes there are variables in the deployment yaml file which are not pre-specified and will be known only during deployment (For example name and tag for the image of a container).
Normally we put a marker text (e.g. {{IMAGE_NAME}}) in the yaml file and use a bash text manipulation tools to change it with actual value in the deployment file.
Is there a way to use environment variables or other methods (like using arguments when running kubectl create) instead of text-replace tools?
What I've done is use envvars in the deployment configuration, then run apply/create with the output from an envsubst command:
deployment.yaml file:
[...]
spec:
replicas: $REPLICA_COUNT
revisionHistoryLimit: $HISTORY_LIM
[...]
during deploy:
$ export REPLICA_COUNT=10 HISTORY_LIM=10
$ envsubst < deployment.yaml | kubectl apply -f -
Unfortunately there is no way to use environment variables directly with kubectl. The common solution is to use some kind of a templating language + processing as you suggested.
Related
I am trying to set up kubemq in my cluster, and this is the command the shown in their README
kubectl apply -f https://deploy.kubemq.io/community
There are a lot of empty field in that yaml and I want to customize it. How can I override an external yaml file applied by kubectl?
In the Kubernetes world, It's generally an unsafe idea to run a command like the below unless you trust the URL:
kubectl apply -f <some/web/url>
This is essentially the same as the following in the non-Kubernetes world:
curl </some/web/url> |bash
In both cases, we aren't inspecting the content downloaded from the URL and directly executing them by feeding to kubectl and bash directly. What if the URL is compromised with some harmful code?
A better approach is to break the single step into parts:
Download the manifest file
Inspect the manifest file.
Run kubectl apply/create on it, only you are satisfied.
Example:
//download the file
curl -fsSL -o downloaded.yml https://deploy.kubemq.io/community
// inspect the file or edit the file
//Now apply the downloaded file after inspecting.
kubectl apply -f downloaded.yml
Why don't you just copy the content in a text file?
Change whatever you want and apply it.
I am trying to set environment variables to kubernetes deployment in following way.
env:
- name: username
value: $(cat /vault/secrets/config.txt | awk ' NR == 2')
For the environment variable value, I am trying to read the first line of a file. But, in application initialization, the environment variable is set as just the text value denoted above without evaluating the cat expression. How to set the environment variable in this scenario properly?. Thank you.
Best way to achieve your goal is described in Vault documentation: https://www.vaultproject.io/docs/platform/k8s/injector/examples#environment-variable-example
Does anyone face this issue. there is no other way if a secret is create it to ignore already exist error, below is the command which runs fine with out of secret/license configured as compared to secret/license created (which happens first time)
kubectl create secret generic license --save-config --dry-run=true --from-file=/tmp/ansibleworkspace/license -n {{ appNameSpace }} -o yaml | kubectl apply -f -
It runs fine if I run it on a k8s cluster
Below is the error while executing it through ansible.
Error: unknown shorthand flag: 'f' in -f
Examples:
# Create a new secret named my-secret with keys for each file in folder bar
kubectl create secret generic my-secret --from-file=path/to/bar
# Create a new secret named my-secret with specified keys instead of names on disk
kubectl create secret generic my-secret --from-file=ssh-privatekey=~/.ssh/id_rsa --from-file=ssh-publickey=~/.ssh/id_rsa.pub
# Create a new secret named my-secret with key1=supersecret and key2=topsecret
kubectl create secret generic my-secret --from-literal=key1=supersecret --from-literal=key2=topsecret
# Create a new secret named my-secret using a combination of a file and a literal
kubectl create secret generic my-secret --from-file=ssh-privatekey=~/.ssh/id_rsa --from-literal=passphrase=topsecret
# Create a new secret named my-secret from an env file
kubectl create secret generic my-secret --from-env-file=path/to/bar.env
Options:
--allow-missing-template-keys=true: If true, ignore any errors in templates when a field or map key is missing in the template. Only applies to golang and jsonpath output formats.
--append-hash=false: Append a hash of the secret to its name.
--dry-run=false: If true, only print the object that would be sent, without sending it.
--from-env-file='': Specify the path to a file to read lines of key=val pairs to create a secret (i.e. a Docker .env file).
--from-file=[]: Key files can be specified using their file path, in which case a default name will be given to them, or optionally with a name and file path, in which case the given name will be used. Specifying a directory will iterate each named file in the directory that is a valid secret key.
--from-literal=[]: Specify a key and literal value to insert in secret (i.e. mykey=somevalue)
--generator='secret/v1': The name of the API generator to use.
-o, --output='': Output format. One of: json|yaml|name|go-template|go-template-file|template|templatefile|jsonpath|jsonpath-file.
--save-config=false: If true, the configuration of current object will be saved in its annotation. Otherwise, the annotation will be unchanged. This flag is useful when you want to perform kubectl apply on this object in the future.
--template='': Template string or path to template file to use when -o=go-template, -o=go-template-file. The template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].
--type='': The type of secret to create
--validate=true: If true, use a schema to validate the input before sending it
Usage:
kubectl create secret generic NAME [--type=string] [--from-file=[key=]source] [--from-literal=key1=value1] [--dry-run] [options]
Use "kubectl options" for a list of global command-line options (applies to all commands).
unknown shorthand flag: 'f' in -f
Since you haven't given any details about the context you are running the command, I can only provide an answer based on my guess.
Explanation:
I suppose that you use the command module in your Ansible playbook and this is the cause of your issue. As you can read in module description:
The given command will be executed on all selected nodes. It will not be processed through the shell, so variables like $HOME and
operations like "<", ">", "|", ";" and "&" will not
work (use the shell module if you need these features).
and in your command you use "|" character, which cannot be interpreted properly as it is not processed through the shell. Note that the error you get:
Error: unknown shorthand flag: 'f' in -f
is related with incorrect use of kubectl create secret generic which simply doesn't have such option. Since "|" character is not interpreted by the command module, the proceeding command:
kubectl apply -f -
is treated as a part of:
kubectl create secret generic
(which is confirmed by the error you get, followed by the correct usage examples).
Solution:
As recommended in the above quoted docs, use the shell module instead:
If you want to run a command through the shell (say you are using <,
>, |, etc), you actually want the shell module instead.
I am new to helm chart. As part of the requirement I named my values.yaml to customize.yaml
To tell helm engine that I am using custom yaml file, I used the below command.
helm install mychart -f customize.yaml
but now the question is how should I not pass the name of the yaml (customize.yaml) file as part of the command, so the command should be like this
helm install mychart
and helm should know that it will get the values from customize.yaml
without explicitly mentioning it in the command. Is there a way to do this?
I tried to include it in _helpers.tpl but it didn't work
// ValuesfileName is the default values file name.
ValuesfileName = "values.yaml"
values.yaml have been defined as the default file in helm's source code. So, in your case, you may have to build helm from source with your changes.
Can I have multiple values.yaml files in a Helm chart?
Something like mychart/templates/internalValues.yaml, mychart/templates/customSettings.yaml, etc?
Accessing properties in a values.yaml file can be done by {{ .Values.property1 }}.
How would I reference the properties in these custom values.yaml files?
Yes, it's possible to have multiple values files with Helm. Just use the --values flag (or -f).
Example:
helm install ./path --values ./internalValues.yaml --values ./customSettings.yaml
You can also pass in a single value using --set.
Example:
helm install ./path --set username=ADMIN --set password=${PASSWORD}
From the official documentation:
There are two ways to pass configuration data during install:
--values (or -f): Specify a YAML file with overrides. This can be specified multiple times and the rightmost file will take precedence
--set (and its variants --set-string and --set-file): Specify overrides on the command line.
If both are used, --set values are merged into --values with higher precedence. Overrides specified with --set are persisted in a configmap. Values that have been --set can be viewed for a given release with helm get values . Values that have been --set can be cleared by running helm upgrade with --reset-values specified.
Helm by default will only use the values.yaml file in the root directory of your chart.
You can ask it to load additional values files when you install. For instance, if you have any settings that point to different databases in different environments:
helm install . -f values.production.yaml
You could also get a similar effect by bundling additional settings as a file, and asking Helm to read the bundled file. Helm provides an undocumented fromYaml template function which can parse the file, so in principle you can do something like
{{- $v := $.Files.Get "more-values.yaml" | fromYaml }}
foo: {{ $v.bar }}
Just to update : As per the current official documentation --set & --values will not be merged
To override values in a chart, use either the '--values' flag and pass in a file or use the '--set' flag and pass configuration from the command line, to force a string value use '--set-string'. In case a value is large and therefore you want not to use neither '--values' nor '--set', use '--set-file' to read the single large value from file.
Also :
You can specify the '--values'/'-f' flag multiple times. The priority will be given to the last (right-most) file specified.