Docker and K8S learning notes -- tips for efficient use of kubectl

Posted by scnjl on Thu, 17 Feb 2022 05:45:36 +0100

As our main tool for operating K8S, kubectl has a wealth of functions, but it is still inconvenient to use if it is not polished. Today, let's see how to polish our kubectl to make it easier to use.

1, Command auto completion

kubectl provides many commands. If it is too tired to manually type one character at a time, how to configure automatic completion? Take ubuntu system as an example:

1. Install the auto completion tool

$ sudo apt update
Hit:1 http://archive.ubuntu.com/ubuntu bionic InRelease
Hit:2 http://security.ubuntu.com/ubuntu bionic-security InRelease
Hit:3 http://archive.ubuntu.com/ubuntu bionic-updates InRelease
Hit:4 https://download.docker.com/linux/ubuntu bionic InRelease
Hit:5 http://archive.ubuntu.com/ubuntu bionic-backports InRelease
Reading package lists... Done
Building dependency tree
Reading state information... Done
144 packages can be upgraded. Run 'apt list --upgradable' to see them.
$ sudo apt install bash-completion
Reading package lists... Done
Building dependency tree
Reading state information... Done
bash-completion is already the newest version (1:2.8-1ubuntu1).
0 upgraded, 0 newly installed, 0 to remove and 144 not upgraded.

PS: for centos system, use yum install bash completion - y command to install

2. Configure automatic completion

Bash:

source <(kubectl completion bash)
echo "source <(kubectl completion bash)" >> ~/.bashrc

Zsh:

source <(kubectl completion zsh)
echo "[[ $commands[kubectl] ]] && source <(kubectl completion zsh)" >> ~/.zshrc

After configuration, you can use the Tab key to automatically complete the command!

2, Configure kubectl alias

We can simplify kubectl command and edit by setting alias bashrc file, add the following:

alias sudo='sudo '
alias k='kubectl'
alias ka='kubectl apply --recursive -f'
alias kex='kubectl exec -i -t'
alias klo='kubectl logs -f'
alias kg='kubectl get'
alias kd='kubectl describe'

PS: alias sudo is to solve the problem of unavailable aliases under sudo

Remember to execute source ~ /. After saving Bashrc ha, then let's experience:

$ sudo ka webapp_pod.yaml
pod/webapp created
$ sudo kg pods
NAME     READY   STATUS              RESTARTS   AGE
webapp   0/2     ContainerCreating   0          7s
$ sudo kd pod webapp
Name:         webapp
Namespace:    default
Priority:     0
Node:         ayato/172.16.194.135
Start Time:   Wed, 09 Feb 2022 14:04:44 +0000
Labels:       app=webapp
Annotations:  <none>
Status:       Running
IP:           172.17.0.6
IPs:
  IP:  172.17.0.6
Containers:
  webapp:
    Container ID:   docker://d9ddf9dd47de12b53f2119bf75df6706bee2e7711509638ad52adc9addeda704
    Image:          172.16.194.135:5000/webapp:1.0
    Image ID:       docker-pullable://172.16.194.135:5000/webapp@sha256:df3a447a013ada0642dec67bb31976f42f1a0699a68873d0452f514fa24e5c77
    Port:           5000/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Wed, 09 Feb 2022 14:04:46 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /tmp from webapp-logs (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-pcr2h (ro)
  busybox:
    Container ID:  docker://6a6a35a628a782fc643af3dd49986bbc77c23de1ae4726bc521c77f61abbbf5d
    Image:         busybox
    Image ID:      docker-pullable://busybox@sha256:afcc7f1ac1b49db317a7196c902e61c6c3c4607d63599ee1a82d702d249a0ccb
    Port:          <none>
    Host Port:     <none>
    Command:
      sh
      -c
      tail -f /logs/log.out
    State:          Running
      Started:      Wed, 09 Feb 2022 14:06:53 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /logs from webapp-logs (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-pcr2h (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  webapp-logs:
    Type:       EmptyDir (a temporary directory that shares a pod's lifetime)
    Medium:
    SizeLimit:  <unset>
  default-token-pcr2h:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-pcr2h
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                 node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type    Reason     Age    From               Message
  ----    ------     ----   ----               -------
  Normal  Scheduled  2m23s  default-scheduler  Successfully assigned default/webapp to ayato
  Normal  Pulled     2m22s  kubelet            Container image "172.16.194.135:5000/webapp:1.0" already present on machine
  Normal  Created    2m21s  kubelet            Created container webapp
  Normal  Started    2m21s  kubelet            Started container webapp
  Normal  Pulling    2m21s  kubelet            Pulling image "busybox"
  Normal  Pulled     15s    kubelet            Successfully pulled image "busybox" in 14.633078305s
  Normal  Created    15s    kubelet            Created container busybox
  Normal  Started    14s    kubelet            Started container busybox

It really feels like flying!!!

3, Context and Namespace switching

When we use kubectl on the company's container platform, we often need to switch between context and namespace, resulting in cumbersome commands. Is there a simple way—— kubectx

kubectx installation

$ sudo git clone https://github.com/ahmetb/kubectx /opt/kubectx
Cloning into '/opt/kubectx'...
remote: Enumerating objects: 1457, done.
remote: Counting objects: 100% (172/172), done.
remote: Compressing objects: 100% (115/115), done.
remote: Total 1457 (delta 85), reused 97 (delta 51), pack-reused 1285
Receiving objects: 100% (1457/1457), 905.30 KiB | 69.00 KiB/s, done.
Resolving deltas: 100% (817/817), done.
$ sudo ln -s /opt/kubectx/kubens /usr/local/bin/kubectl-ns
$ sudo ln -s /opt/kubectx/kubectx /usr/local/bin/kubectl-ctx

Let's look at the effect:

$ sudo k ctx
minikube
$ sudo k ctx minikube
Switched to context "minikube".
$ sudo k ns
default
kube-node-lease
kube-public
kube-system
kubernetes-dashboard
$ sudo k ns kube-public
Context "minikube" modified.
Active namespace is "kube-public".
$ sudo k ns default
Context "minikube" modified.
Active namespace is "default".

4, Track and view logs of multiple pods

We usually use kubectl logs command to view Pod logs, but it cannot track and view multiple Pod logs at the same time through the - f parameter, which is inconvenient. After all, each service in the actual production environment will have multiple pods. At this time, we can use stern, which has the following capabilities:

  • Allows you to use regular expressions to select the PodName you want to view
  • Show different colors for logs of different pods
  • During the tracking log process, if a new Pod that meets the rules is created, it will be automatically added to the output

First install Stern (it may be slow to download stern. You can try it several times):

wget https://github.com/wercker/stern/releases/download/1.11.0/stern_linux_amd64
sudo mv stern_linux_amd64 /usr/local/bin/kubectl-tail
sudo chomd +x /usr/local/bin/kubectl-tail

After installation, let me feel the charm of stern. There are two containers in my Pod: webapp and busybox. If you use kubectl logs, you have to specify a specific container, but there is no such restriction when using stern.

$ sudo k tail .
+ webapp › busybox
+ webapp › webapp
webapp busybox 14:04:53.197 [INFO ] [main] [org.apache.coyote.http11.Http11NioProtocol] Initializing ProtocolHandler ["http-nio-4567"]
webapp busybox 14:04:53.200 [INFO ] [main] [org.apache.catalina.core.StandardService] Starting service [Tomcat]
webapp busybox 14:04:53.201 [INFO ] [main] [org.apache.catalina.core.StandardEngine] Starting Servlet engine: [Apache Tomcat/9.0.41]
webapp busybox 14:04:53.324 [INFO ] [main] [org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/]] Initializing Spring embedded WebApplicationContext
webapp busybox 14:04:53.325 [INFO ] [main] [org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext] Root WebApplicationContext: initialization completed in 2952 ms
webapp busybox 14:04:53.801 [INFO ] [main] [org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor] Initializing ExecutorService 'applicationTaskExecutor'
webapp busybox 14:04:54.264 [WARN ] [main] [org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration$DefaultTemplateResolverConfiguration] Cannot find template location: classpath:/templates/ (please add some templates or check your Thymeleaf configuration)
webapp busybox 14:04:54.377 [INFO ] [main] [org.apache.coyote.http11.Http11NioProtocol] Starting ProtocolHandler ["http-nio-4567"]
webapp busybox 14:04:54.481 [INFO ] [main] [org.springframework.boot.web.embedded.tomcat.TomcatWebServer] Tomcat started on port(s): 4567 (http) with context path ''
webapp busybox 14:04:54.509 [INFO ] [main] [org.demo.webapp.todolist.TodoListApplication] Started TodoListApplication in 6.235 seconds (JVM running for 8.074)
webapp webapp
webapp webapp   .   ____          _            __ _ _
webapp webapp  /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
webapp webapp ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
webapp webapp  \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
webapp webapp   '  |____| .__|_| |_|_| |_\__, | / / / /
webapp webapp  =========|_|==============|___/=/_/_/_/
webapp webapp  :: Spring Boot ::                (v2.4.2)
webapp webapp
webapp webapp 14:04:50.124 [INFO ] [main] [org.demo.webapp.todolist.TodoListApplication] Starting TodoListApplication v1.0-SNAPSHOT using Java 1.8.0_111 on webapp with PID 1 (/opt/soft/webapp.jar started by root in /opt/soft)
webapp webapp 14:04:50.165 [INFO ] [main] [org.demo.webapp.todolist.TodoListApplication] No active profile set, falling back to default profiles: default
webapp webapp 14:04:53.158 [INFO ] [main] [org.springframework.boot.web.embedded.tomcat.TomcatWebServer] Tomcat initialized with port(s): 4567 (http)
webapp webapp 14:04:53.197 [INFO ] [main] [org.apache.coyote.http11.Http11NioProtocol] Initializing ProtocolHandler ["http-nio-4567"]
webapp webapp 14:04:53.200 [INFO ] [main] [org.apache.catalina.core.StandardService] Starting service [Tomcat]
webapp webapp 14:04:53.201 [INFO ] [main] [org.apache.catalina.core.StandardEngine] Starting Servlet engine: [Apache Tomcat/9.0.41]
webapp webapp 14:04:53.324 [INFO ] [main] [org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/]] Initializing Spring embedded WebApplicationContext
webapp webapp 14:04:53.325 [INFO ] [main] [org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext] Root WebApplicationContext: initialization completed in 2952 ms
webapp webapp 14:04:53.801 [INFO ] [main] [org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor] Initializing ExecutorService 'applicationTaskExecutor'
webapp webapp 14:04:54.264 [WARN ] [main] [org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration$DefaultTemplateResolverConfiguration] Cannot find template location: classpath:/templates/ (please add some templates or check your Thymeleaf configuration)
webapp webapp 14:04:54.377 [INFO ] [main] [org.apache.coyote.http11.Http11NioProtocol] Starting ProtocolHandler ["http-nio-4567"]
webapp webapp 14:04:54.481 [INFO ] [main] [org.springframework.boot.web.embedded.tomcat.TomcatWebServer] Tomcat started on port(s): 4567 (http) with context path ''
webapp webapp 14:04:54.509 [INFO ] [main] [org.demo.webapp.todolist.TodoListApplication] Started TodoListApplication in 6.235 seconds (JVM running for 8.074)