Как выполнить вход в узел (а не контейнер) с помощью kubectl

Вопрос или проблема

Как выполнить 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.

Примеры и инструменты

  1. kubectl-node-shell: Это инструмент, который можно использовать для получения доступа к оболочке операционной системы узла. Он создает привилегированный контейнер на узле и позволяет выполнить команды с полномочиями root.

    Пример использования:

    kubectl node-shell <имя-узла>

    При использовании kubectl-node-shell, важно иметь разрешения на запуск привилегированных контейнеров.

  2. Создание специальных 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 для доступа к корневой файловой системе узла.

  3. Использование 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, так как они обеспечивают более безопасное и традиционное управление серверами.

Оцените материал
Добавить комментарий

Капча загружается...