Dynamically update the configmap values - kubernetes

I have following configmaps
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
application.properties: |+
key1: value1
key2: value2
keyN: valueN
Configmaps is mounted to pod and works fine.
My requirement is to programmatically replace the value for some of the keys.
I can run shell/python script and I can run any kubectl command.

You can use kubectl patch command to update K8s resources.
kubectl patch configmap/test \
--type=json \
'-p=[{"op": "replace","path": "/data/key1", "value": "test1"}]'
An important point to note as mentioned by Henry is that the application also has to re-read the properties after they have been changed.

You can use Bash script to dynamically replace some keys and values in your ConfigMaps.
I've created simple bash script to illustrate how it may works on my kubeadm cluster v1.20:
#!/bin/bash
keyName="key1"
value="value100"
read -p 'Enter ConfigMap name: ' configmapName
if kubectl get cm ${configmapName} 1> /dev/null 2>&1; then
echo "ConfigMap name to modify: ${configmapName}"
else
echo "ERROR: bad ConfigMap name"
exit 1
fi
kubectl patch cm ${configmapName} -p "{\"data\":{\"${keyName}\":\"${value}\"}}"
In the above example you need to pass ConfigMap name and set what you want to modify.
In addition you may want to pass keyName and value values as command line arguments in similar way to configmapName value.
You can see an example of how the above script works:
root#kmaster:~# ./replaceValue.sh
Enter ConfigMap name: test
ConfigMap name to modify: test
configmap/test patched
root#kmaster:~# kubectl describe cm test
Name: test
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
application.properties:
----
key1:
----
value100
key2:
----
value2
keyN:
----
valueN
Events: <none>
root#kmaster:~#
Note: If you want to use kubectl replace instead of kubectl patch, you can use below command (e.g. sourceValue="key1: value1" and destinationValue="key1: value100")
kubectl get cm ${configmapName} -o yaml | sed "s/${sourceValue}/${destinationValue}/" | kubectl replace -f -

Related

One liner command to get secret name and secret's token

What's the one liner command to replace 2 commands like below to get the Kubernetes secret's token? Example usecase will be getting token from kubernetes-dashboard-admin's secret to login and view kubernetes-dashboard.
Command example:
$ kubectl describe serviceaccount default
Name: default
Namespace: default
Labels: <none>
Annotations: <none>
Image pull secrets: <none>
Mountable secrets: default-token-zvxf4
Tokens: default-token-zvxf4
Events: <none>
$ kubectl describe secret default-token-zvxf4
Name: default-token-zvxf4
Namespace: default
Labels: <none>
Annotations: kubernetes.io/service-account.name: default
kubernetes.io/service-account.uid: 809835e7-2564-439f-82f3-14762688ca80
Type: kubernetes.io/service-account-token
Data
====
ca.crt: 1025 bytes
namespace: 7 bytes
token: TOKENHERE
Answer that I discovered was below. By using jsonpath to retrieve and xargs to pass the secret name/output to second command. Will need to decode the encrypted token with base64 at the end.
$ kubectl get serviceaccount default -o=jsonpath='{.secrets[0].name}' | xargs kubectl get secret -ojsonpath='{.data.token}' | base64 --decode
TOKENHERE%
The tailing % is not part of the token
This should be able to work on MacOS without install additional app like jq which should be able to do the same. Hope this is helpful for others.
You generally don't need to run either command. Kubernetes will automatically mount the credentials to /var/run/secrets/kubernetes.io/serviceaccount/token in a pod declared using that service account, and the various Kubernetes SDKs know to look for credentials there. Accessing the API from a Pod in the Kubernetes documentation describes this setup in more detail.
Configure Service Accounts for Pods describes the Pod-level setup that's possible to do, though there are reasonable defaults for these.
apiVersion: v1
kind: Pod # or a pod spec embedded in a Deployment &c.
spec:
serviceAccountName: my-service-account # defaults to "default"
automountServiceAccountToken: true # defaults to true
I wouldn't try to make requests from outside the cluster as a service account. User permissions are better suited for this use case. As a user you could launch a Job with service-account permissions if you needed to.
Example using kubectl describe instead of kubectl get and adding the namespace definition:
kubectl -n kube-system describe secret $(kubectl -n kube-system describe sa default | grep 'Mountable secrets' | awk '{ print $3 }') | grep 'token:' | awk '{ print $2 }'

patch a configmap from file or with json

I want to edit a configmap from aws-auth during a vagrant deployment to give my vagrant user access to the EKS cluster. I need to add a snippet into the existing aws-auth configmap. How do i do this programmatically?
If you do a kubectl edit -n kube-system configmap/aws-auth you get
apiVersion: v1
data:
mapRoles: |
- groups:
- system:bootstrappers
- system:nodes
rolearn: arn:aws:iam::123:role/nodegroup-abc123
username: system:node:{{EC2PrivateDNSName}}
kind: ConfigMap
metadata:
creationTimestamp: "2019-05-30T03:00:18Z"
name: aws-auth
namespace: kube-system
resourceVersion: "19055217"
selfLink: /api/v1/namespaces/kube-system/configmaps/aws-auth
uid: 0000-0000-0000
i need to enter this bit in there somehow.
mapUsers: |
- userarn: arn:aws:iam::123:user/sergeant-poopie-pants
username: sergeant-poopie-pants
groups:
- system:masters
I've tried to do a cat <<EOF > {file} EOF then patch from file. But that option doesn't exist in patch only in the create context.
I also found this: How to patch a ConfigMap in Kubernetes
but it didn't seem to work. or perhaps i didn't really understand the proposed solutions.
There are a few ways to automate things. The direct way would be kubectl get configmap -o yaml ... > cm.yml && patch ... < cm.yml > cm2.yml && kubectl apply -f cm2.yml or something like that. You might want to use a script that parses and modifies the YAML data rather than a literal patch to make it less brittle. You could also do something like EDITOR="myeditscript" kubectl edit configmap ... but that's more clever that I would want to do.
First, note that the mapRoles and mapUsers are actually treated as a string, even though it is structured data (yaml).
While this problem is solvable by jsonpatch, it is much easier using jq and kubectl apply like this:
kubectl get cm aws-auth -o json \
| jq --arg add "`cat add.yaml`" '.data.mapUsers = $add' \
| kubectl apply -f -
Where add.yaml is something like this (notice the lack of extra indentation):
- userarn: arn:aws:iam::123:user/sergeant-poopie-pants
username: sergeant-poopie-pants
groups:
- system:masters
See also https://docs.aws.amazon.com/eks/latest/userguide/add-user-role.html for more information.
Here is a kubectl patch one-liner for patching the aws-auth configmap:
kubectl patch configmap -n kube-system aws-auth -p '{"data":{"mapUsers":"[{\"userarn\": \"arn:aws:iam::0000000000000:user/john\", \"username\": \"john\", \"groups\": [\"system:masters\"]}]"}}'

How to edit configmap in kubernetes and override the values from a different yaml file?

I want to edit the configmap and replace the values. But it should be done using a different YAML in I ll specify overriding values as part of that file.
I was trying using kubectl edit cm -f replace.yaml but this didn't work so i want to know the structure in which the new file should be.
apiVersion: v1
kind: ConfigMap
metadata:
name: int-change-change-management-service-configurations
data:
should_retain_native_dn: "False"
NADC_IP: "10.11.12.13"
NADC_USER: "omc"
NADC_PASSWORD: "hello"
NADC_PORT: "991"
plan_compare_wait_time: "1"
plan_prefix: ""
ingress_ip: "http://10.12.13.14"
Now lets us assume NADC_IP should be changed and So I would like to know how should be structure of the YAML file and using which command it can be served?
The override taking place should only be during helm test for example when i run
helm test <release-name>?
kubectl replace -f replace.yaml
If you have a configmap in place like this:
apiVersion: v1
kind: ConfigMap
metadata:
name: my-configmap
data:
should_retain_native_dn: "False"
NADC_IP: "10.11.12.13"
and you want to change the value of NADC_IP create a manifest file like this:
apiVersion: v1
kind: ConfigMap
metadata:
name: my-configmap
data:
should_retain_native_dn: "False"
NADC_IP: "12.34.56.78" # the new IP
and run kubectl replace -f replace.yaml
To update variable in configmap you need to take two steps:
First, update the value of variable:
kubectl create configmap <name_of_configmap> --from-literal=<var_name>=<new_value> -o yaml --dry-run | kubectl replace -f -
So in your case it will looks like this:
kubectl create configmap int-change-change-management-service-configurations --from-literal=NADC_IP=<new_value> -o yaml --dry-run | kubectl replace -f -
Second step, restart the pod:
kubectl delete pod <pod_name>
App will use new value from now. Let me know, if it works for you.
kubectl get cm {configmap name} -o=yaml --export > filename.yaml
You can try this it will give you yaml format
kubectl get configmap
int-change-change-management-service-configurations -o yaml
You can copy the content and replace it inside new yaml file and apply the changes
EDIT : 1
If you want to edit over terminal you can run
kubectl edit configmap {configmap name}
It will use vim editor and you can replace value from terminal using edit command.
EDIT : 2
kubectl get cm {configmap name} -o=yaml --export > filename.yaml

Unable to read my newly created Kubernetes secret

I set my secret like this:
$ kubectl create secret generic aws-region VAL=eu-west-1 \
> -o yaml --dry-run | kubectl replace -f -
secret "aws-region" replaced
Seems to be set:
kubectl get secret | ack region
aws-region Opaque 0 20m
An I try to read it like this:
76 - name: AWS_REGION
77 valueFrom:
78 secretKeyRef:
79 name: aws-region
80 key: VAL
But that gives a CreateContainerConfigError when I run kubectl apply -f service.yml
What am I doing wrong?
Since you're only showing us a small part of service.yaml it's impossible to tell where the error comes from but I can confirm the following works (using a test pod I created here):
$ kubectl create secret generic aws-region --from-literal=VAL=eu-west-1
$ kubectl apply -f pod.yaml
$ kubectl describe po/envfromsecret
Name: envfromsecret
Namespace: default
...
Environment:
AWS_REGION: <set to the key 'VAL' in secret 'aws-region'> Optional: false
UPDATE: I now noticed that the DATA column in the output of your kubectl get secret command is actually 0, that is, it's empty. Consider using the form I used above (with --from-literal=) to create the secret.

kubernetes configmaps for binary file

My kubernetes version is 1.10.4.
I am trying to create a ConfigMap for java keystore files:
kubectl create configmap key-config --from-file=server-keystore=/home/ubuntu/ssl/server.keystore.jks --from-file=server-truststore=/home/ubuntu/ssl/server.truststore.jks --from-file=client--truststore=/home/ubuntu/ssl/client.truststore.jks --append-hash=false
It says configmap "key-config" created.
But when I describe the configmap I am getting null value:
$ kubectl describe configmaps key-config
Name: key-config
Namespace: prod-es
Labels: <none>
Annotations: <none>
Data
====
Events: <none>
I know my version kubernetes support binary data as configmaps or secrets but I am not sure what is wrong with my approach.
Any input on this is highly appreciated.
kubectl describe does not show binary data in ConfigMaps at the moment (kubectl version v1.10.4); also the DATA column of the kubectl get configmap output does not include the binary elements:
$ kubectl get cm
NAME DATA AGE
key-config 0 1m
But the data is there, it's just a poor UI experience at the moment. You can verify that with:
kubectl get cm key-config -o json
Or you can use this friendly command to check that the ConfigMap can be mounted and the projected contents matches your original files:
kubectl run cm-test --image=busybox --rm --attach --restart=Never --overrides='{"spec":{"volumes":[{"name":"cm", "configMap":{"name":"key-config"}}], "containers":[{"name":"cm-test", "image":"busybox", "command":["sh","-c","md5sum /cm/*"], "volumeMounts":[{"name":"cm", "mountPath":"/cm"}]}]}}'