Эрик Гебельбекер
Контейнеры упрощают переносимость и доставку приложений. Они используют ресурсы более эффективно, чем пустые или виртуальные машины. Они более портативные, легкие и компактные, что облегчает их развертывание в любом месте, независимо от того, какой облачный провайдер или локальный центр вам нужен для выполнения кода.
Kubernetes (k8s) усиливает контейнерную инфраструктуру за счет встроенного масштабирования, надежности и еще более эффективного использования ресурсов. Но k8s также добавляет дополнительный уровень абстракции. Многие административные задачи работают не совсем так, как вы ожидаете. Иногда бывает трудно пробиться сквозь дополнительные слои абстракции и увидеть, что происходит внутри кластера.
В этом посте мы рассмотрим kubectl exec. Мы увидим, как с помощью этого инструмента можно заглянуть внутрь контейнеров Kubernetes. Мы рассмотрим, что может предложить exec, и несколько примеров того, как стоит и как не стоит использовать его для управления кластерами Kubernetes.
Если вы хотите следовать примерам в этой статье, вам понадобится система, работающая под управлением Docker с установленным и запущенным Minikube.
Что такое Kubectl Exec?
Kubectl
Kubectl — это инструмент командной строки для взаимодействия с кластерами Kubernetes через Kubernetes API. Вы можете использовать его для мониторинга состояния Kubernetes, применения файлов манифеста, редактирования ресурсов и многого другого. Это общий инструмент администрирования для кластеров k8s.
В зависимости от вашей операционной системы, вам может потребоваться отдельная установка kubectl. Пакеты для Docker и Kubernetes могут установить его за вас.
Kubectl Exec
Exec — один из самых полезных инструментов kubectl. С его помощью вы можете выполнить команду внутри контейнера. Если вы знакомы с Docker, exec в kubectl может напомнить вам команду exec в Docker.
Давайте начнем с примера.
Kubectl и пространства имен
Прежде чем выполнить команду в контейнере, нам нужно знать его имя, а прежде чем составлять список контейнеров, нам нужно знать их пространства имен. Итак, давайте начнем с просмотра пространств имен внутри нашего кластера.
Во-первых, начните с kubectl get namespace:
% kubectl get namespace
NAME STATUS AGE
default Active 2d23h
kube-node-lease Active 2d23h
kube-public Active 2d23h
kube-system Active 2d23h
У нас есть четыре пространства имен: default, kube-node-lease, kube-public и kube-system.
Далее мы получим список контейнеров с помощью get pods и пространство имен, добавив аргумент командной строки —namespace.
% kubectl --namespace=default get pods
No resources found in default namespace.
Я еще ничего не запускал на своем кластере Minikube, поэтому пространство имен по умолчанию пустое. Давайте посмотрим на kube-system:
% kubectl --namespace=kube-system get pods
NAME READY STATUS RESTARTS AGE
coredns-6d4b75cb6d-xsqnx 1/1 Running 0 3d
etcd-minikube 1/1 Running 0 3d
kube-apiserver-minikube 1/1 Running 0 3d
kube-controller-manager-minikube 1/1 Running 0 3d
kube-proxy-hqxbp 1/1 Running 0 3d
kube-scheduler-minikube 1/1 Running 0 3d
storage-provisioner 1/1 Running 287 (46h ago) 3d
В этом пространстве имен есть несколько контейнеров. Давайте посмотрим на них.
Выполнение оболочки в контейнере Kubernetes
Теперь мы можем запустить оболочку в одном из контейнеров Kubernetes. Давайте воспользуемся kube-proxy-hqxbp:
% kubectl exec --namespace=kube-system kube-proxy-hqxbp -it -- sh
# ls
bin boot dev etc go-runner home lib media mnt opt proc root run sbin srv sys tmp usr var
# pwd
/
Kubectl запустил оболочку Bourne внутри контейнера и перенаправил ввод и вывод обратно в мою оболочку. Далее я перечислил каталог, в который меня поместил sh, а затем использовал pwd для отображения его имени.
Давайте разберем эту командную строку.
- exec — это подкоманда, которую мы хотим запустить.
- —name=kube-system указывает kubectl, в каком пространстве имен запущен контейнер.
- kube-proxy-hqxbp — это контейнер.
- -it указывает exec перенаправить входные и выходные потоки оболочки обратно в управляющую оболочку. Это должно выглядеть знакомо, если вы использовали команду exec в Docker. I указывает exec направить стандартный ввод в вашу оболочку. Параметр t указывает exec, что входные данные поступают с tty.
- Следующий набор аргументов — это два тире (—), за которыми следует команда, которую вы хотите, чтобы exec выполнил. В данном случае это sh, оболочка Bourne. Два тире отделяют аргументы команды от аргументов kubectl.
Примеры Kubectl Exec
Теперь, когда мы поняли, как запустить exec, мы можем рассмотреть несколько примеров.
Нам не нужно было запускать и выходить из оболочки, чтобы получить содержимое корневого каталога. Мы можем передать команду ls в sh и попросить exec вернуть нам результаты.
% kubectl exec --namespace=kube-system kube-proxy-hqxbp -it -- sh -c ls
bin dev go-runner lib mnt proc run srv tmp var
На самом деле, это не интерактивная команда, поэтому нам не нужен параметр -it. Давайте попробуем сделать это без нее.
% kubectl exec --namespace=kube-system kube-proxy-hqxbp -- sh -c "ls"
bin
boot
dev
etc
go-runner
home
lib
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
Это интересно! В результате отсутствия -it поведение ls изменилось. Он не использует более одного столбца для вывода результатов не в терминал. Это значительно упрощает разбор результатов в сценариях оболочки.
Давайте заглянем в каталог /bin и посмотрим, что еще можно сделать в этом контейнере.
% kubectl exec --namespace=kube-system kube-proxy-hqxbp -- sh -c "ls -l /bin"
total 3384
-rwxr-xr-x 1 root root 39832 Sep 22 2020 cat
-rwxr-xr-x 1 root root 64512 Sep 22 2020 chgrp
-rwxr-xr-x 1 root root 60368 Sep 22 2020 chmod
-rwxr-xr-x 1 root root 64528 Sep 22 2020 chown
-rwxr-xr-x 1 root root 138896 Sep 22 2020 cp
-rwxr-xr-x 1 root root 129544 Dec 10 2020 dash
-rwxr-xr-x 1 root root 101384 Sep 22 2020 date
-rwxr-xr-x 1 root root 80984 Sep 22 2020 dd
-rwxr-xr-x 1 root root 89824 Sep 22 2020 df
-rwxr-xr-x 1 root root 143088 Sep 22 2020 dir
lrwxrwxrwx 1 root root 8 Nov 7 2019 dnsdomainname -> hostname
lrwxrwxrwx 1 root root 8 Nov 7 2019 domainname -> hostname
-rwxr-xr-x 1 root root 35632 Sep 22 2020 echo
-rwxr-xr-x 1 root root 28 Nov 9 2020 egrep
(trimmed)
В этом контейнере установлен ограниченный набор инструментов командной строки, поэтому мы можем сделать с ним не так много. Давайте рассмотрим более подходящий контейнер.
Kubectl Exec с пользовательским контейнером
Сначала запустите контейнер Ubuntu в пространстве имен по умолчанию. Официальный контейнер не имеет команды по умолчанию, поэтому запустите его с помощью интерактивной оболочки:
% kubectl run --namespace=default -it exec-test-ubuntu --image=ubuntu bash
If you don't see a command prompt, try pressing enter.
root@exec-test-ubuntu:/# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 18:39 pts/0 00:00:00 bash
root 11 1 0 18:39 pts/0 00:00:00 ps -ef
Обратите внимание, что на этот раз вы должны передать аргумент -it, иначе bash выйдет. Это переводит нас в оболочку. Командная строка соответствует имени контейнера. В этом контейнере есть команда ps, поэтому мы можем посмотреть, что запущено внутри контейнера. Здесь показан процесс bash, с которым мы взаимодействуем, и сама команда ps.
Далее в другом окне выполните shell в том же контейнере.
% kubectl exec -it exec-test-ubuntu -- bash
root@exec-test-ubuntu:/#
Теперь вернитесь к первому командному интерпретатору и запустите листинг процесса:
root@exec-test-ubuntu:/# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 18:39 pts/0 00:00:00 bash
root 12 0 0 18:39 pts/1 00:00:00 bash
root 21 1 0 18:39 pts/0 00:00:00 ps -ef
Теперь есть две сессии bash! Итак, ясно, что у нас есть две оболочки в одном контейнере и представление о том, как работает exec.
Заметки о Kubectl Exec
Как мы видели из приведенных выше примеров, exec дает вам возможность делать с контейнером все, что угодно, но это не значит, что вы должны это делать. Exec — это инструмент для осмотра контейнеров, а не для запуска приложений или изменения конфигурации контейнера.
Если вам нужно обновить конфигурацию или код контейнера, создайте и разверните новый образ. Запуск Exec в контейнер и установка новых пакетов или копирование новых файлов приведет к проблемам воспроизводимости и нарушит дух контейнеризации.
Kubectl Exec для проверки контейнеров
Мы рассмотрели функцию exec в kubectl и то, как она работает. Мы увидели, как выяснить, в каком пространстве имен работают ваши контейнеры. Затем мы использовали exec для выполнения программы внутри нужного контейнера. Мы увидели, как можно использовать kubectl exec для запуска как интерактивных оболочек, так и команд, которые просто возвращают результаты. Далее мы запустили контейнер в пространстве имен по умолчанию и использовали exec для его проверки.
Kubectl exec — это мощный инструмент для просмотра состояния и содержимого контейнеров в кластерах Kubernetes. Теперь, когда вы знакомы с его работой, вы можете использовать его для обеспечения бесперебойной работы ваших кластеров k8s!
Этот пост был написан Эриком Гебельбекером. Эрик 25 лет проработал на финансовых рынках в Нью-Йорке, разрабатывая инфраструктуру для рыночных данных и сетей протокола обмена финансовой информацией (FIX). Он любит говорить о том, что делает команды эффективными (или не очень эффективными!).