Error from server (NotFound): pods "\nmongo-client-79667cc85d-tsg72" not found - bash

I'm trying to make a backup from Mongo / K8S with this script
export POD=$(kubectl get pods -l app=mongo-client -o custom-columns=:metadata.name -n espace-client)
kubectl exec "$POD" sh -c 'mongodump --archive' > ~/backup/mongo/$(date +%F).db.dump
I get this error:
Error from server (NotFound): pods "\nmongo-client-79667cc85d-tsg72" not found
When I check the pods, I can see mongo-client-79667cc85d-tsg72
When I put the name without variable, it works well, so it might be because of initial \n. How can I avoid it ?
How can I remove it from name ?

Your kubectl get pods command is constrained with a namespace selector -n espace-client. Your kubectl exec command also needs the namespace flag.

The output of your kubectl get pods command has a newline before the pod name because the first line of the output is the column header (which is empty in your case).
To prevent this and get only the name as output, you can suppress the column headers with the --no-headers flag:
kubectl get pods -l app=mongo-client -o custom-columns=:metadata.name -n espace-client --no-headers

Related

grep for pods and select each result and pass a command in loop

I have few pods running in my kubernetes cluster. I am developing a shell script and I want to grep for few pods and want to select each pod from the grep result to execute a command.
Lets say I grep few pods by command :
kubectl get pods | grep test
the results are:
Test-0
Test-1
Test-2
From the result, I want to select each pod and execute a command for it in a loop.
for example:
for first pod:
kubectl exec -it Test-0 -- mysqldump.......
after finishing the first pod, it has to process the second pod and so on
for pod in $(kubectl get pod -oname |grep -i Test ); do
kubectl exec "$pod" -- ls -ltr ;
done
Replace ls -ltr with mysqldump .....
Get pods name and then use "for" to execute command in each pod
#!/bin/bash
pods=$(kubectl get pods | awk '{print $2}' | grep -i test)
for i in $pods
do
kubectl exec -it $i -- echo "test"
done
Select your target pods using labels is less error prone and can do multiple matching:
kubectl get pods --selector <key>=<value>,<key>=<value> --namespace <name> -oname | xargs -I{} kubectl exec -it {} --namespace <name> -- mysqldump ...

Jenkins - Assign variable inside sh script

I would like to create a variable name as POD inside script to assign kubectl output and then pass this variable while running kubectl port-forward pods..
But I received below error
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
WorkflowScript: 151: illegal string body character after dollar sign;
solution: either escape a literal dollar sign "\$5" or bracket the value expression "${5}" # line 151, column 80.
e-context ${KUBE_CLUSTER_STAGE}
Here is my script.
environment {
POD = ''
}
steps {
script {
withCredentials([file(credentialsId: 'mbtkubeconfig', variable: 'config')]){
try {
// Expose PostreSQL
sh '''#!/bin/sh
chmod ug+w ${config}
export KUBECONFIG=\${config}
kubectl config use-context ${KUBE_CLUSTER_STAGE}
kubectl config set-context --current --namespace=database
POD = `$(kubectl get po -n database --selector='role==master' -o jsonpath="{.items[0].metadata.name}")`
kubectl port-forward pods/$POD 5432:64000 & echo \$! > filename.txt
'''
When I tried without variable there is no any error.Here is the script running without any error.
sh """#!/bin/sh
chmod ug+w ${config}
export KUBECONFIG=\${config}
kubectl config use-context ${KUBE_CLUSTER_STAGE}
kubectl config set-context --current --namespace=database
kubectl get pods -n database
kubectl port-forward pods/my-postgres-postgresql-helm-0 5432:64000 & echo \$! > filename.txt
"""
When you run commands with sh make sure you are using " not '. Groovy variables will only be resolved when using "${config}".
By the way, it is considered best practice to mark variables with env. although not needed to resolve the variable. For instance, try to mark your cluster stage with ${env.KUBE_CLUSTER_STAGE}

Remove the header line returned by kubectl command

I'm using kubernetes, and I want to get podname from the app name. Here is the command I use.
POD=$(kubectl get pods -l app=influxdb-local -o custom-columns=:metadata.name -n influx)
Then I would like to use the result in:
kubectl exec -it -n influx $POD -- influx -username user -password "user" -execute "CREATE DATABASE db"
but the first line is empty, and the second line contains pod name, so the second command doesn't work.
How should I remove the first white line ?
Add --no-headers to skip the header line
kubectl get pods -l app=influxdb-local -o custom-columns=:metadata.name -n influx --no-headers
Custom Columns
Using the flag -o custom-columns=<header-name>:<field> will let you customize the output.
Example with resource name, under header NAME
kubectl get pods -o custom-columns=NAME:metadata.name
output
NAME
myapp-5b77df6c48-dbvnh
myapp-64d5985fdb-mcgcn
httpd-9497b648f-9vtbl
Empty header name: you used the flag as -o custom-columns=:metadata.name - the first line is the header line, but with an empty header.
Omit headers
the proper solution to omit the header line is by using the flag --no-headers
kubectl get pods -o custom-columns=NAME:metadata.name --no-headers
Example output
myapp-5b77df6c48-dbvnh
myapp-64d5985fdb-mcgcn
httpd-9497b648f-9vtbl

Trying to copy files to Pods with `kubectl cp`, But getting Error: unknown flag: --all-namespaces

Trying to copy and execute a bash script in a POD (which has one container)
kubectl cp ../docker/scripts/upload_javadumps.sh ${POD}:/opt -n apm
This commands works perfectly, But we have multiple Namespaces, Hence I wanted to use --all-namespaces like shown below
which errors out saying, Error: unknown flag: --all-namespaces
How Do I use --all-namspaces in kubectl cp command?
kubectl cp ../docker/scripts/upload_javadumps.sh ${POD}:/opt --all-namespaces
echo "Successfully copied the upload_javadumps.sh script"```
For kubectl cp flag --all-namespaces doesn't exist, you can check it with kubectl cp -h.
In your case I would go with simple bash loop like this:
for ns in namespace1 namespace2; do kubectl cp ../docker/scripts/upload_javadumps.sh ${POD}:/opt -n $ns;done

How to edit a kubernetes resource from a shell script

I went through the documentation to edit kubernetes resource using kubectl edit command. Once I execute the command, the file in YAML-format is opened in the editor where I can change the values as per requirement and save it. I am trying to execute these steps by means of sed. How can the following steps be achieved?
Execute kubectl edit for a deployment resource
Set a value from true to false (using sed)
Save the changes
I tried to achieve this in the following way :
$ kubectl edit deployment tiller-deploy -n kube-system | \
sed -i "s/\(automountServiceAccountToken:.*$\)/automountServiceAccountToken: true/g"`
Your command is missing a backtick. But even though you put it there, it won't work. The reason is because when you do kubectl edit ..., it edits the file on vim. I am not sure sed would work on vim though. Even though if it does, the output goes to a file, so you get the Vim: Warning: Output is not to a terminal error, which I don't know how to solve.
I would recommend you to get the file and save it. Replace the desired parameters and run it again:
kubectl get deploy tiller-deploy -n kube-system -o yaml > tiller.yaml && sed -i "s/automountServiceAccountToken:.*$/automountServiceAccountToken: true/g" tiller.yaml && kubectl replace -f tiller.yaml
I tried the command above and it worked.
Note: no need to add -n kube-system as the yaml file already contains the namespace.
I just found a less convoluted way of doing this:
KUBE_EDITOR="sed -i s/SOMETHING TO CHANGE/CHANGED/g" kubectl edit resource -n your-ns
I automate through piping the commands through sed command without creating a temporary file. Take the below example, where I am replacing nameserver 8.8.8.8 with 1.1.1.1
$ kubectl -n kube-system get configmap/kube-dns -o yaml | sed "s/8.8.8.8/1.1.1.1/" | kubectl replace -f -
Thanks, #suren for giving what I really looking for, but you don't need to save it in a file. you can directly do kubectl replace using pipe operations
kubectl get deploy test-deploy -o yaml | sed "s/find/replace/g" | kubectl replace -f -
An easy way to do this, just use kubectl-patch instead of sed.
$ kubectl patch deployment tiller-deploy -n kube-system --patch '{"map": {"to": {"the": {"key": {"automountServiceAccountToken": "true"}}}}}'
I don't know kubectl but doc seems to explain that it extract data, edit from an editor than send back, not sure sed pipe work in this case
if piping wokrs
Don't use -i, you don't change a file in a pipe
kubectl edit deployment tiller-deploy -n kube-system | \
sed 's/automountServiceAccountToken:.*$/automountServiceAccountToken: true/g'
if editing a file (and using group in sed)
kubectl edit deployment tiller-deploy -n kube-system > YourCOnfigFile && \
sed -i 's/\(automountServiceAccountToken:\).*$/\1 true/g' YourConfigFile \
&& Some kubectl to send back YourConfigFile

Resources