Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Need some explaination of kubectl stdin and pipe

I'm daily user of kubectl, but not expert of linux. Recently I need edit some service type after deployment, so searched and used kubectl replace and it worked well.

cat yaml | kubectl replace -f -

service/tracs-pool-1sv replaced

But I don't understand why add a short dash - at the last. The doc only says:

Replace a pod based on the JSON passed into stdin.

I searched and found this SO question, and learned kubectl command may be that kind of command that does not read stdin(am I right?).

I tried

cat yaml |xargs kubectl replace -f

but error returned:

the path "apiVersion:" does not exist

So is the ending short dash(-) syntax built for kubectl ONLY? or is some more common syntax of linux bash stdin pipe? Can some one explain why xargs not work here and I must place a short dash(-) at the end?

like image 966
Lei Yang Avatar asked Jan 04 '19 02:01

Lei Yang


People also ask

What are kubectl commands?

Kubectl controls the Kubernetes Cluster. It is one of the key components of Kubernetes which runs on the workstation on any machine when the setup is done. It has the capability to manage the nodes in the cluster. Kubectl commands are used to interact and manage Kubernetes objects and the cluster.

What kubectl means?

kubectl is the main way in which you will interact with your Kubernetes cluster. Kubectl is a command line tool used to run commands against Kubernetes clusters. It does this by authenticating with the Master Node of your cluster and making API calls to do a variety of management actions.

How does kubectl apply work?

The command set kubectl apply is used at a terminal's command-line window to create or modify Kubernetes resources defined in a manifest file. This is called a declarative usage. The state of the resource is declared in the manifest file, then kubectl apply is used to implement that state.


2 Answers

This is a reasonably common, but not universal, Un*x convention. (It is mentioned in the POSIX specification and so most non-Linux Unices will support it as well.)

The important detail here is that the kubectl ... -f option expects a filename. If you have a file named x.yaml, a more direct way to write what you've shown is just

kubectl replace -f x.yaml

Where you say -f -, that ostensibly means "a file named -", but kubectl (along with many other tools) actually interprets this to mean "the process's standard input". For instance, you could use this for a very lightweight templating system, like

sed 's/TAG/1.2.3-20190103/g' x.yaml | kubectl replace -f -

For Un*x tooling in general, POSIX.1 states that, for many commands,

...an operand naming a file can be specified as '-', which means to use the standard input instead of a named file....

Some commands that support this include cat, grep, sort, and tar (not required by POSIX). One way to move a directory tree between two Linux machines, for instance, is to create a tar file on stdout, pipe that stream via ssh to a remote machine, and then unpack the tar file from stdin:

tar cf - . | ssh elsewhere tar xf - -C /other/dir

xargs is a tool that converts (most often) a list of filenames on standard input to command line arguments. For instance, find(1) can print a list of matching filenames to its stdout, so you could build a pipeline to delete shell backup files like

find . -name '*~' | xargs rm

You wouldn't usually use this with Kubernetes; your example tries to pass the YAML content itself as command-line arguments to kubectl, for example. You could apply kubectl across a directory tree with something like

find . name '*.yaml' | xargs -n1 kubectl apply -f

but since kubectl ... -f also supports directory names (not a universal convention) you could do the same thing more directly as

kubectl apply -f . # where . is the current directory
like image 78
David Maze Avatar answered Oct 06 '22 08:10

David Maze


Short dash(-) here represents stdin. This is a kubectl specific implementation. There are many other linux utilities as well that have similar implementation.

Apart from David's answer, there is another common format that we see used with kubectl. Its called Heredoc.

kubectl apply -f - <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
  name: kubectl-actions
  namespace: my-v2-restore
EOF

OR

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
  name: kubectl-actions
  namespace: my-v2-restore
EOF

Heredoc: is a way to send multiline string to the tool/command for processing.

  • https://tldp.org/LDP/abs/html/here-docs.html

  • https://linuxize.com/post/bash-heredoc/

like image 28
ns94 Avatar answered Oct 06 '22 08:10

ns94