Вопрос или проблема
Как выполнить exec в K8s узел?
До сих пор я нашел только способы выполнить exec в контейнеры, работающие на узле.
Я хотел бы избежать ssh
.
Слой выше пода (и их контейнеров) – это операционная система (исключая логические слои k8s).
Нет инструментов (о которых я знаю), которые являются частью инструментов управления Kubernetes, которые делают это – для этого используется SSH.
Вы можете использовать kubectl-node-shell
kubectl-node-shell: запускает root shell в хостовой ОС узла.
Использование:
# Получить стандартный bash shell
kubectl node-shell <node>
Для этого необходимо уметь запускать привилегированные контейнеры.
В зависимости от того, чего вы хотите достичь, вы можете запустить под с большими привилегиями.
Например, вы можете сделать hostpath монтирование на /. С некоторыми знаниями Linux этого должно быть достаточно.
apiVersion: v1
kind: Pod
metadata:
name: evil-pod
spec:
containers:
- image: busybox
name: evil
command: ["/bin/sh"]
args: "-c" ,"sleep infinity"]
volumeMounts:
- mountPath: /host
name: host-root
volumes:
- hostPath:
path: /
type: ""
name: host-root
Учтите, что это, конечно, проблема безопасности, и в безопасном кластере это не должно быть возможно.
Если вам нужно обслуживать узел, используйте SSH, как предложил самсон.
Если вам нужен доступ к базовым узлам вашего кластера Kubernetes (и у вас нет прямого доступа – обычно, если вы размещаете Kubernetes где-то еще), вы можете использовать следующее развертывание для создания подов, где вы можете войти с kubectl exec
, и у вас есть доступ ко всей файловой системе узла под /node-fs
. Чтобы получить консоль узла, как если бы вы использовали SSH, после входа выполните chroot /node-fs
. Настоятельно не рекомендуется оставлять это запущенным, но если вам нужен доступ к узлу, это поможет. Поскольку это DaemonSet, он запускает один из этих подов на каждом узле.
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: privpod
spec:
selector:
matchLabels:
mydaemon: privpod
template:
metadata:
labels:
mydaemon: privpod
spec:
hostNetwork: true
hostPID: true
hostIPC: true
containers:
- name: privcontainer
image: johnnyb61820/network-toolkit
securityContext:
privileged: true
command:
- tail
- "-f"
- /dev/null
volumeMounts:
- name: nodefs
mountPath: /node-fs
- name: devfs
mountPath: /dev
volumes:
- name: nodefs
hostPath:
path: /
- name: devfs
hostPath:
path: /dev
Это из приложения C.13 книги Облачные приложения с Docker и Kubernetes. Я нашел это полезным, особенно если мне нужно работать с физическими дисками или чем-то подобным. Это не то, что следует оставлять работающим, но помогает в сложных ситуациях.
Этот скрипт выполняет простой контейнер в пространстве хоста IPC, сети и PID. Затем он использует nsenter, чтобы переключиться на другие пространства имен и запустить BASH, предоставляя вам полностью функциональный root shell на выбранном узле (или случайном узле, если аргумент не предоставлен).
#!/bin/bash
host="$1"
json='
{
"apiVersion": "v1",
"spec": {
"hostIPC": true,
"hostNetwork": true,
"hostPID": true
';
if ! [[ -z "$host" ]]; then
json+=",
\"nodeSelector\" : {
\"kubernetes.io/hostname\" : \"$host\"
}
";
fi
json+='
}
}
'
kubectl run -ti --image alpine:3.8 --rm --privileged --restart=Never --overrides="$json" root --command -- nsenter -t 1 -m -u -n -i -- bash -l
Текущая версия скрипта расположена в этом репозитории GitHub.
Ответ или решение
Введение в Kubernetes и его архитектуру может помочь понять, что "экзек" в узел (node) с использованием kubectl
является нетипичной задачей, поскольку командный инструментарий kubectl
в первую очередь предназначен для управления ресурсами на уровне контейнеров и подов Kubernetes. Однако существуют альтернативные способы, позволяющие достичь этой цели, не прибегая к SSH, решения которых описаны ниже.
Теоретическое обоснование
Kubernetes управляет кластером из узлов, каждый из которых может будет выполнять контейнеризированные приложения в подах. Стандартный рабочий процесс для работы с приложениями в Kubernetes включает взаимодействие с контейнерами и подами, а не с самими узлами. Узлы обычно управляются администраторами через SSH для выполнения задач на уровне операционной системы.
Зачем может понадобиться доступ к узлу? Иногда администратору может потребоваться выполнить диагностику или обслуживание прямо на узле, для чего обычно используется SSH. Однако в случае, если этот подход неприемлем, можно воспользоваться функциональностью, имитирующей SSH доступ через Kubernetes.
Примеры и инструменты
-
kubectl-node-shell: Это инструмент, который можно использовать для получения доступа к оболочке операционной системы узла. Он создает привилегированный контейнер на узле и позволяет выполнить команды с полномочиями root.
Пример использования:
kubectl node-shell <имя-узла>
При использовании
kubectl-node-shell
, важно иметь разрешения на запуск привилегированных контейнеров. -
Создание специальных Pod-ов: Вы можете создать под, который будет монтировать файловую систему узла с необходимыми привилегиями. Пример такого манифеста приведен ниже:
apiVersion: v1 kind: Pod metadata: name: privileged-pod spec: containers: - image: busybox name: host-shell command: ["/bin/sh"] args: ["-c", "sleep infinity"] securityContext: privileged: true volumeMounts: - mountPath: /host name: host-root volumes: - hostPath: path: / type: "" name: host-root
После деплоя этого пода можно подключиться к нему и использовать команду
chroot /host
для доступа к корневой файловой системе узла. -
Использование DaemonSet: Этот подход включает создание
DaemonSet
, который запускает контейнеры на всех узлах кластера, тем самым предоставляя точку доступа к каждому из них.apiVersion: apps/v1 kind: DaemonSet metadata: name: node-access spec: selector: matchLabels: name: node-access template: metadata: labels: name: node-access spec: hostNetwork: true hostPID: true hostIPC: true containers: - name: node-access-container image: yourcustomimage securityContext: privileged: true command: - sleep - "3600" volumeMounts: - name: node-root mountPath: /node-root volumes: - name: node-root hostPath: path: /
После создания такого
DaemonSet
можно подключаться к подам и, используяchroot
, получить доступ к файловой системе узлов.
Применение
Применение описанных выше решений позволяет получить доступ к узлам кластера без SSH, что может быть полезно в конфигурациях, где SSH доступ ограничен. Однако важно помнить, что такие методы открывают потенциальные уязвимости. Рекомендуется использовать такие решения только в случае крайней необходимости и исключительно на доверенных и безопасных кластерах.
Кроме того, при использовании привилегированных контейнеров обеспечьте, чтобы они не оставались активными дольше необходимого срока, чтобы минимизировать риски нарушения безопасности.
Тем не менее, если вопрос касается регулярного сопровождения и обслуживания узлов, настоятельно рекомендуется придерживаться стандартных процедур, включая использование SSH, так как они обеспечивают более безопасное и традиционное управление серверами.