Kubectl Exec Flags
Posted August 15, 2021 by quy-le ‐ 5 min read
What exactly does the -t and -i flags in kubectl exec means?
1$ kubectl help exec
2Execute a command in a container.
3
4Examples:
5 # Switch to raw terminal mode, sends stdin to 'bash' in ruby-container from pod mypod
6 # and sends stdout/stderr from 'bash' back to the client
7 kubectl exec mypod -c ruby-container -i -t -- bash -il
8
9 # Get output from running 'date' command from the first pod of the deployment mydeployment, using the first container
10by default
11 kubectl exec deploy/mydeployment -- date
12
13Options:
14 -i, --stdin=false: Pass stdin to the container
15 -t, --tty=false: Stdin is a TTY
A program works by this flow: [Accept input data] => [Process] => [Return]
.
When a Unix program started up, by default there will be 3 file descriptors (“channels”) attaches to the process (stdin, stdout and stderr, fd=0,1,2
).
- The process can choose to listen on the stdin for input data (e.g.: sh/bash/vi command listens on stdin for user input-ed commands) or not (e.g.: date/ls/cd commands).
- And also, process can print the result into stdout/stderr (e.g.: ls/pwd command) or print nothing (e.g.: cd command).
For commands (which will be executed inside the container) that DON’T NEED to accept any input from user’s terminal, we can execute it directly without -i -t
flags as below.
Exec command simply execute the command inside the container and print the result (if exists) back to the user’s terminal.
1$ kc exec nettools-5-2869s date
2kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
3Sun Jun 6 07:07:44 UTC 2021
4
5$ kc exec nettools-5-2869s -- date
6Sun Jun 6 07:07:52 UTC 2021
7
8# => With or without 2 dashes (--) is the same, but with dashes is preferred, especially if the input command has arguments.
9
10$ kc exec nettools-5-2869s -- sleep 1
11# Exec command ends after 1s without printing anything else to the terminal (sleep command doesn't write anything to stdout/stderr).
For commands (which will be executed inside the container) that NEED to accept any input from user’s terminal, we have to provide -i
flags for exec command.
-i
means passing user’s input from the terminal into the stdin of the command being executed in the container. Also, the stdout/stderr of the executing command (inside container) will be forwarded back to the user’s terminal (stdout/stderr respectively). E.g.:kc exec pod1 -i -- sh
=> Pass anything user has typed (on their terminal stdin) into the stdin ofsh
command inside the container. So the sh command can “see” what user has typed and execute those. Also, the result fromsh
will be forwarded back and printed on user’s terminal now.
1$ kc exec nettools-5-2869s -i -- sh
2pwd # Command I typed in the terminal being passed into the sh's stdin
3/home/nuser
4cd / # Command I typed in the terminal being passed into the sh's stdin
5ls # Command I typed in the terminal being passed into the sh's stdin
6bin
7# [...]
8usr
9var
10whoami # Command I typed in the terminal being passed into the sh's stdin
11whoami: unknown uid 1000510000
12exit # Command I typed in the terminal being passed into the sh's stdin
13command terminated with exit code 1
-i
is enough to interact with the command being executed inside the container but to get more from it, we need to init/upgrade to TTY session too (still looking for what is the benefits here though), so-t
flags is also needed. Note:- I don’t have pods with TTY enabled on k8s so switching to Docker here.
- Actually it’s PTS here, not TTY as we will see below: https://www.golinuxcloud.com/difference-between-pty-vs-tty-vs-pts-linux/#PTS
1# Case 1: Run container without -t option enabled. 2$ docker run --rm --name nt -d lnquy/nettools:0.0.7 3$ docker exec nt tty 4not a tty # Exec without -t => inside container is not a TTY 5$ docker exec -t nt tty 6/dev/pts/0 # Exec with -t => inside container is a TTY (PTS) now 7 8# Case 2: Run container with -t option enabled. 9$ docker run --rm --name nt -d -t lnquy/nettools:0.0.7 10$ docker exec nt tty 11not a tty 12$ docker exec -t nt tty 13/dev/pts/1 # TTY with diferent id now, /dev/pts/0 was reserved from docker run -t, I guess 14$ docker exec nt ls /dev/pts 150 16ptmx 17# We don't see 1 because the session ended after tty command executed and exited on line #12 18 19 20# If we use -t alone in exec, the TTY still can be created, but we canot sending any data into the container stdin 21# which makes the TTY session useless. 22# => Use combined -it or not using it at all. 23$ docker exec -t nt sh 24~ $ # Show TTY established, but cannot input anything. 25$ docker exec -t nt bash 26bash-4.4$ # Same as above
When using combined -it
, it means establishing a TTY session to the container (-t
) and also link the container stdin/stdout/stderr with user’s terminal stdin/stdout/stderr respectively (-i
).
- When user input anything on their terminal’s stdin, these data will be forwarded into container’s stdin.
- The command running inside container accept those data, process/execute it and returns the result back in container’s stdout/stderror which will be forwarded back to user terminal’s stdout/stderr.
=> Use combined -it
or not using it at all.