The Kubernetes client, kubectl
is the primary method of interacting with a Kubernetes cluster. Getting to know it
is essential to using Kubernetes itself.
- Syntax Structure
- Context and kubeconfig
- kubectl Basics
- Accessing the Cluster
- Cleaning up
- Helpful Resources
kubectl
uses a common syntax for all operations in the form of:
kubectl <command> <type> <name> <flags>
- command - The command or operation to perform. e.g.
apply
,create
,delete
, andget
. - type - The resource type or object.
- name - The name of the resource or object.
- flags - Optional flags to pass to the command.
Examples
$ kubectl create -f mypod.yaml
$ kubectl get pods
$ kubectl get pod mypod
$ kubectl delete pod mypod
kubectl
allows a user to interact with and manage multiple Kubernetes clusters. To do this, it requires what is known
as a context. A context consists of a combination of cluster
, namespace
and user
.
- cluster - A friendly name, server address, and certificate for the Kubernetes cluster.
- namespace (optional) - The logical cluster or environment to use. If none is provided, it will use the default
default
namespace. - user - The credentials used to connect to the cluster. This can be a combination of client certificate and key, username/password, or token.
These contexts are stored in a local yaml based config file referred to as the kubeconfig
. For *nix based
systems, the kubeconfig
is stored in $HOME/.kube/config
for Windows, it can be found in
%USERPROFILE%/.kube/config
This config is viewable without having to view the file directly.
Command
$ kubectl config view
Example
❯ kubectl config view
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://127.0.0.1:46347
name: kind-kind
contexts:
- context:
cluster: kind-kind
user: kind-kind
name: kind-kind
current-context: kind-kind
kind: Config
preferences: {}
users:
- name: kind-kind
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
Managing all aspects of contexts is done via the kubectl config
command. Some examples include:
- See the active context with
kubectl config current-context
. - Get a list of available contexts with
kubectl config get-contexts
. - Switch to using another context with the
kubectl config use-context <context-name>
command. - Add a new context with
kubectl config set-context <context name> --cluster=<cluster name> --user=<user> --namespace=<namespace>
.
There can be quite a few specifics involved when adding a context, for the available options, please see the Configuring Multiple Clusters Kubernetes documentation.
Objective: Create a new context called kind-dev
and switch to it.
- View the current contexts.
$ kubectl config get-contexts
- Create a new context called
kind-dev
within thekind-kind
cluster with thedev
namespace, as thekind-kind
user.
$ kubectl config set-context kind-dev --cluster=kind-kind --user=kind-kind --namespace=dev
- View the newly added context.
kubectl config get-contexts
- Switch to the
kind-dev
context usinguse-context
.
$ kubectl config use-context kind-dev
- View the current active context.
$ kubectl config current-context
Summary: Understanding and being able to switch between contexts is a base fundamental skill required by every
Kubernetes user. As more clusters and namespaces are added, this can become unwieldy. Installing a helper
application such as kubectx can be quite helpful. Kubectx allows a user to quickly
switch between contexts and namespaces without having to use the full kubectl config use-context
command.
There are several kubectl
commands that are frequently used for any sort of day-to-day operations. get
, create
,
apply
, delete
, describe
, and logs
. Other commands can be listed simply with kubectl --help
, or
kubectl <command> --help
.
kubectl get
fetches and lists objects of a certain type or a specific object itself. It also supports outputting the
information in several different useful formats including: json, yaml, wide (additional columns), or name
(names only) via the -o
or --output
flag.
Command
kubectl get <type>
kubectl get <type> <name>
kubectl get <type> <name> -o <output format>
Examples
$ kubectl get namespaces
NAME STATUS AGE
default Active 4h
kube-public Active 4h
kube-system Active 4h
$
$kubectl get pod mypod -o wide
NAME READY STATUS RESTARTS AGE IP NODE
mypod 1/1 Running 0 5m 172.17.0.6 kind-control-plane
kubectl create
creates an object from the commandline (stdin
) or a supplied json/yaml manifest. The manifests can be
specified with the -f
or --filename
flag that can point to either a file, or a directory containing multiple
manifests.
Command
kubectl create <type> <parameters>
kubectl create -f <path to manifest>
Examples
$ kubectl create namespace dev
namespace "dev" created
$
$ kubectl create -f manifests/mypod.yaml
pod "mypod" created
kubectl apply
is similar to kubectl create
. It will essentially update the resource if it is already created, or
simply create it if does not yet exist. When it updates the config, it will save the previous version of it in an
annotation
on the created object itself. WARNING: If the object was not created initially with
kubectl apply
it's updating behavior will act as a two-way diff. For more information on this, please see the
kubectl apply
documentation.
Just like kubectl create
it takes a json or yaml manifest with the -f
flag or accepts input from stdin
.
Command
kubectl apply -f <path to manifest>
Examples
$ kubectl apply -f manifests/mypod.yaml
Warning: kubectl apply should be used on resource created by either kubectl create --save-config or kubectl apply
pod "mypod" configured
kubectl edit
modifies a resource in place without having to apply an updated manifest. It fetches a copy of the
desired object and opens it locally with the configured text editor, set by the KUBE_EDITOR
or EDITOR
Environment
Variables. This command is useful for troubleshooting, but should be avoided in production scenarios as the changes
will essentially be untracked.
Command
$ kubectl edit <type> <object name>
Examples
kubectl edit pod mypod
kubectl edit service myservice
kubectl delete
deletes the object from Kubernetes.
Command
kubectl delete <type> <name>
Examples
$ kubectl delete pod mypod
pod "mypod" deleted
kubectl describe
lists detailed information about the specific Kubernetes object. It is a very helpful
troubleshooting tool.
Command
kubectl describe <type>
kubectl describe <type> <name>
Examples
$ kubectl describe pod mypod
Name: mypod
Namespace: dev
Node: kind-control-plane/192.168.99.100
Start Time: Sat, 10 Mar 2018 13:12:53 -0500
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"name":"mypod","namespace":"dev"},"spec":{"containers":[{"image":...
Status: Running
IP: 172.17.0.6
Containers:
nginx:
Container ID: docker://5a0c100de6599300b1565e73e64e8917f9a4f4b06325dc4890aad980d582cf04
Image: nginx:stable-alpine
Image ID: docker-pullable://nginx@sha256:db5acc22920799fe387a903437eb89387607e5b3f63cf0f4472ac182d7bad644
Port: 80/TCP
State: Running
Started: Sat, 10 Mar 2018 13:12:53 -0500
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-s2xd7 (ro)
Conditions:
Type Status
Initialized True
Ready True
PodScheduled True
Volumes:
default-token-s2xd7:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-s2xd7
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 5s default-scheduler Successfully assigned mypod to kind-control-plane
Normal SuccessfulMountVolume 5s kubelet, kind-control-plane MountVolume.SetUp succeeded for volume "default-token-s2xd7"
Normal Pulled 5s kubelet, kind-control-plane Container image "nginx:stable-alpine" already present on machine
Normal Created 5s kubelet, kind-control-plane Created container
Normal Started 5s kubelet, kind-control-plane Started container
kubectl logs
outputs the combined stdout
and stderr
logs from a pod. If more than one container exist in a
pod
the -c
flag is used and the container name must be specified.
Command
kubectl logs <pod name>
kubectl logs <pod name> -c <container name>
Examples
$ kubectl logs mypod
172.17.0.1 - - [10/Mar/2018:18:14:15 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.57.0" "-"
172.17.0.1 - - [10/Mar/2018:18:14:17 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.57.0" "-"
Objective: Explore the basics. Create a namespace, a pod, then use the kubectl
commands to describe and delete
what was created.
NOTE: You should still be using the kind-dev
context created earlier.
- Create the
dev
namespace.
kubectl create namespace dev
- Apply the manifest
manifests/mypod.yaml
.
kubectl apply -f manifests/mypod.yaml
- Get the yaml output of the created pod
mypod
.
kubectl get pod mypod -o yaml
- Describe the pod
mypod
.
kubectl describe pod mypod
- Clean up the pod by deleting it.
kubectl delete pod mypod
Summary: The kubectl
"CRUD" commands are used frequently when interacting with a Kubernetes cluster. These
simple tasks become 2nd nature as more experience is gained.
kubectl
provides several mechanisms for accessing resources within the cluster remotely. For this tutorial, the focus
will be on using kubectl exec
to get a remote shell within a container, and kubectl proxy
to gain access to the
services exposed through the API proxy.
kubectl exec
executes a command within a Pod and can optionally spawn an interactive terminal within a remote
container. When more than one container is present within a Pod, the -c
or --container
flag is required, followed
by the container name.
If an interactive session is desired, the -i
(--stdin
) and -t
(--tty
) flags must be supplied.
Command
kubectl exec <pod name> -- <arg>
kubectl exec <pod name> -c <container name> -- <arg>
kubectl exec -i -t <pod name> -c <container name> -- <arg>
kubectl exec -it <pod name> -c <container name> -- <arg>
Example
$ kubectl exec mypod -c nginx -- printenv
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=mypod
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
KUBERNETES_SERVICE_HOST=10.96.0.1
KUBERNETES_SERVICE_PORT=443
NGINX_VERSION=1.12.2
HOME=/root
$
$ kubectl exec -i -t mypod -c nginx -- /bin/sh
/ #
/ # cat /etc/alpine-release
3.5.2
Objective: Use kubectl exec
to both initiate commands and spawn an interactive shell within a Pod.
- If not already created, create the Pod
mypod
from the manifestmanifests/mypod.yaml
.
$ kubectl create -f manifests/mypod.yaml
- Wait for the Pod to become ready (
running
).
$ kubectl get pods --watch
- Use
kubectl exec
tocat
the file/etc/os-release
.
$ kubectl exec mypod -- cat /etc/os-release
It should output the contents of the os-release
file.
- Now use
kubectl exec
and supply the-i -t
flags to spawn a shell session within the container.
$ kubectl exec -i -t mypod -- /bin/sh
If executed correctly, it should drop you into a new shell session within the nginx container.
- use
ps aux
to view the current processes within the container.
/ # ps aux
There should be two nginx processes along with a /bin/sh
process representing your interactive shell.
- Exit out of the container simply by typing
exit
. With that the shell process will be terminated and the only running processes within the container should once again be nginx and its worker process.
Summary: kubectl exec
is not often used, but is an important skill to be familiar with when it comes to Pod
debugging.
kubectl proxy
enables access to both the Kubernetes API-Server and to resources running within the cluster
securely using kubectl
. By default it creates a connection to the API-Server that can be accessed at
127.0.0.1:8001
or an alternative port by supplying the -p
or --port
flag.
Command
kubectl proxy
kubectl proxy --port=<port>
Examples
$ kubectl proxy
Starting to serve on 127.0.0.1:8001
<from another terminal>
$ curl 127.0.0.1:8001/version
{
"major": "",
"minor": "",
"gitVersion": "v1.9.0",
"gitCommit": "925c127ec6b946659ad0fd596fa959be43f0cc05",
"gitTreeState": "clean",
"buildDate": "2018-01-26T19:04:38Z",
"goVersion": "go1.9.1",
"compiler": "gc",
"platform": "linux/amd64"
}
The Kubernetes API-Server has the built in capability to proxy to running services or pods within the cluster. This
ability in conjunction with the kubectl proxy
command allows a user to access those services or pods without having
to expose them outside of the cluster.
http://<proxy_address>/api/v1/namespaces/<namespace>/<services|pod>/<service_name|pod_name>[:port_name]/proxy
- proxy_address - The local proxy address -
127.0.0.1:8001
- namespace - The namespace owning the resources to proxy to.
- service|pod - The type of resource you are trying to access, either
service
orpod
. - service_name|pod_name - The name of the
service
orpod
to be accessed. - [:port] - An optional port to proxy to. Will default to the first one exposed.
Example
http://127.0.0.1:8001/api/v1/namespaces/default/pods/mypod/proxy/
Objective: Examine the capabilities of the proxy by accessing a pod's exposed ports.
- Create the Pod
mypod
from the manifestmanifests/mypod.yaml
. (if not created previously)
$ kubectl create -f manifests/mypod.yaml
- Start the
kubectl proxy
with the defaults.
$ kubectl proxy
- Access the Pod through the proxy.
http://127.0.0.1:8001/api/v1/namespaces/dev/pods/mypod/proxy/
You should see the "Welcome to nginx!" page.
Summary: Being able to access the exposed Pods and Services within a cluster without having to consume an external IP, or create firewall rules is an incredibly useful tool for troubleshooting cluster services.
NOTE: If you are proceeding with the next tutorials, simply delete the pod with:
$ kubectl delete pod mypod
The namespace and context will be reused.
To remove everything that was created in this tutorial, execute the following commands:
kubectl delete namespace dev
kubectl config delete-context kind-dev