Блог / Статьи

Полезная информация для вашего хостинга

От одиночного сервера к оркестрованной империи: путь к собственному Kubernetes-кластеру на VPS

От одиночного сервера к оркестрованной империи: путь к собственному Kubernetes-кластеру на VPS

Представьте себе: вы начинаете с малого. Один сервер, одна команда docker run, и ваше приложение уже радует первых пользователей. Это время простоты и ясности. Инфраструктура — как уютная комната, где вы знаете, где лежит каждая вещь. Но что происходит, когда успех приходит? Когда пользователи валом врываются на ваш сайт, когда один микросервис превращается в десяток, а база данных начинает задыхаться под нагрузкой? Ваша уютная комната превращается в лабиринт, где вы бегаете от одного сервера к другому, пытаясь вручную запустить контейнеры, перенастроить балансировщики и молиться, чтобы ничего не упало. Именно в этот момент, когда хаос вот-вот поглотит вас, на горизонте появляется спаситель — Kubernetes. Это не просто инструмент, это операционная система для вашей распределенной инфраструктуры, превращающая стаю независимых VPS в единый, умный и саморегулирующийся организм.

Кубернетес: ваш цифровой диспетчер вселенной контейнеров

Что же такое Kubernetes на самом деле? Если говорить просто, это платформа с открытым исходным кодом, созданная Google и теперь управляемая Cloud Native Computing Foundation (CNCF), для автоматизации развертывания, масштабирования и управления контейнеризированными приложениями. Но за этим сухим определением скрывается нечто гораздо большее. Kubernetes — это абстракция над хаосом. Он берет на себя всю рутину, связанную с жизненным циклом ваших приложений, позволяя вам сосредоточиться на коде, а не на инфраструктуре.

Представьте себе оркестр. У вас есть множество музыкантов (ваши контейнеры), играющих на разных инструментах (ваши микросервисы: фронтенд, бэкенд, база данных, кэш, брокер сообщений). Без дирижера (Kubernetes) они играют каждый свою партию, когда захотят, и получается какофония. Дирижер же следит за тем, чтобы все начали и закончили вместе, чтобы громкость была правильной, чтобы если один скрипач внезапно упал в обморок, его немедленно заменил дублер из-за кулис. Вот что делает Kubernetes:

  • Автоматическое масштабирование: Когда ваш интернет-магазин взрывается во время "Черной пятницы", Kubernetes не звонит вам в три часа ночи. Он самостоятельно запускает дополнительные копии вашего контейнера с веб-сервером, чтобы справиться с наплывом покупателей. А когда ажиотаж спадает, он так же спокойно останавливает лишние контейнеры, экономя ваши деньги.
  • Самовосстановление: Если один из ваших VPS внезапно "умирает" (а такое бывает), Kubernetes мгновенно обнаруживает это и перезапускает все контейнеры, которые на нем работали, на других здоровых узлах кластера. Пользователи даже не заметят сбоя.
  • Декларативная конфигурация: Вы не говорите Kubernetes "запусти контейнер, потом настрой сеть, потом смонтируй том". Вы описываете желаемое состояние ("я хочу, чтобы работало три копии моего приложения, и они должны быть доступны по порту 80"). Kubernetes делает все остальное, чтобы это состояние было достигнуто и поддерживалось, несмотря ни на что.
  • Управление конфигурациями и секретами: Kubernetes позволяет безопасно хранить пароли, ключи API и конфигурационные файлы, изолируя их от самого кода приложения и обеспечивая их доставку только в нужные контейнеры.

В итоге, Kubernetes превращает вашу инфраструктуру из набора "лего-кубиков", которые вы собираете вручную, в живую, дышащую систему, способную адаптироваться к любым изменениям нагрузки и сбоям. Это переход от ремесла к инженерии.

kubernet04

Закладываем фундамент: подготовка ваших VPS-Серверов

Прежде чем мы сможем построить наш цифровой замок, нам нужны прочные кирпичи — наши VPS-серверы. Для демонстрации мы будем использовать три сервера под управлением Ubuntu 22.04 LTS (более актуальная версия, чем 20.04). Один будет управляющим узлом (Control Plane) — мозгом всей операции, а два других станут рабочими узлами (Worker Nodes) — "рабочими лошадками", на которых будут физически выполняться ваши приложения.

Выбор VPS-провайдера — дело вкуса и бюджета. Популярны решения от DigitalOcean, Hetzner, Vultr, или, как упоминалось, AdminVPS. Главное — убедиться, что у вас есть root-доступ и возможность настраивать сетевые параметры.

Теперь, приступим к подготовке каждого из трех серверов. Этот этап критически важен, и пропуск любого шага может привести к неработоспособности кластера.

  1. Обновление системы: Начнем с чистого листа. Обновим все пакеты до последних версий, чтобы избежать конфликтов.

    
    
    sudo apt update && sudo apt upgrade -y
    sudo reboot # Рекомендуется перезагрузка после обновления ядра
  2. Отключение Swap: Kubernetes строго требует, чтобы подкачка (swap) была отключена. Это связано с тем, как планировщик Kubernetes управляет ресурсами памяти. Сначала отключим swap временно, а затем навсегда закомментируем его в конфигурационном файле.

    
    
    sudo swapoff -a
    # Редактируем файл /etc/fstab, чтобы swap не включался после перезагрузки
    sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
    # Проверим, что swap отключен
    free -h
  3. Настройка сети и параметров ядра: Kubernetes полагается на определенные сетевые возможности ядра Linux. Нам нужно включить модули ядра и настроить параметры sysctl.

    
    
    # Загружаем необходимые модули ядра
    sudo modprobe overlay
    sudo modprobe br_netfilter
    
    # Добавляем настройки в конфигурационный файл
    cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
    overlay
    br_netfilter
    EOF
    
    # Настраиваем параметры sysctl для Kubernetes
    cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
    net.bridge.bridge-nf-call-iptables  = 1
    net.bridge.bridge-nf-call-ip6tables = 1
    net.ipv4.ip_forward                 = 1
    EOF
    
    # Применяем настройки без перезагрузки
    sudo sysctl --system
  4. Настройка имени хоста и файла hosts (Опционально, но рекомендуется): Для удобства можно задать осмысленные имена хостам и прописать их в локальный файл /etc/hosts на каждом сервере, чтобы они могли резолвить друг друга по именам, а не только по IP.

    
    
    # На управляющем узле
    sudo hostnamectl set-hostname k8s-control-plane
    
    # На рабочих узлах
    sudo hostnamectl set-hostname k8s-worker-1
    sudo hostnamectl set-hostname k8s-worker-2
    
    # На ВСЕХ узлах добавляем записи в /etc/hosts (замените IP на реальные)
    cat <<EOF | sudo tee -a /etc/hosts
    192.168.1.100 k8s-control-plane
    192.168.1.101 k8s-worker-1
    192.168.1.102 k8s-worker-2
    EOF

После выполнения этих шагов на всех трех серверах, наша "строительная площадка" готова. Мы создали единое, предсказуемое окружение, на котором сможем развернуть наш кластер.

Сборка ядра: установка компонентов Kubernetes через kubeadm

Теперь, когда серверы подготовлены, пришло время установить сам Kubernetes. Самый простой и рекомендуемый способ для новичков и даже для многих production-сред — это использование утилиты kubeadm. Это "волшебная палочка", которая автоматизирует сложный процесс инициализации кластера. Но прежде чем установить kubeadm, нам нужен контейнерный runtime — среда выполнения, которая будет запускать наши контейнеры. Хотя Docker когда-то был стандартом, сейчас Kubernetes официально поддерживает несколько runtime'ов через интерфейс CRI (Container Runtime Interface). Мы установим containerd — легковесный и эффективный runtime, который является частью экосистемы Docker, но работает независимо.

Выполняем следующие команды на всех трех серверах (управляющем и рабочих узлах).

  1. Установка containerd:

     

    # Устанавливаем containerd
    sudo apt install -y containerd
    
    # Создаем конфигурационный каталог для containerd
    sudo mkdir -p /etc/containerd
    
    # Генерируем конфигурационный файл containerd по умолчанию
    containerd config default | sudo tee /etc/containerd/config.toml
    
    # Включаем и запускаем службу containerd
    sudo systemctl enable containerd
    sudo systemctl start containerd
    Добавление официального репозитория Kubernetes: Чтобы получить последние стабильные версии, мы добавим официальный GPG-ключ и репозиторий от Google.

     

  2. 
    
    # Добавляем ключ репозитория
    curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key   | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
    
    # Добавляем репозиторий в sources.list.d (для Ubuntu 22.04)
    echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.30/deb/   /' | sudo tee /etc/apt/sources.list.d/kubernetes.list

    Примечание: Версия v1.30 в URL — это пример. Всегда проверяйте актуальную стабильную версию на официальном сайте Kubernetes.

  3. Установка kubelet, kubeadm и kubectl: Эти три инструмента — основа нашей работы.

    • kubelet: Агент, который работает на каждом узле (и управляющем, и рабочем) и обеспечивает запуск контейнеров в подах (Pods).
    • kubeadm: Инструмент для инициализации и настройки кластера.
    • kubectl: Командная строка для управления кластером. Нужна в первую очередь на управляющем узле, но часто устанавливается и на рабочих для отладки.
    # Обновляем список пакетов с новым репозиторием
    sudo apt update
    
    # Устанавливаем компоненты
    sudo apt install -y kubelet kubeadm kubectl
    
    # "Замораживаем" версии, чтобы они не обновлялись автоматически через apt
    # Это важно, так как обновление должно происходить контролируемо через kubeadm
    sudo apt-mark hold kubelet kubeadm kubectl
    

Поздравляем! На всех трех серверах теперь установлены все необходимые компоненты Kubernetes. Мы готовы к самому важному шагу — рождению нашего кластера.

Рождение мозга: инициализация управляющего узла

Теперь мы сосредоточимся исключительно на сервере, который будет нашим управляющим узлом (Control Plane). Именно здесь мы "запустим двигатель" всего кластера.

  1. Инициализация кластера: Мы используем команду kubeadm init. Ключевой параметр здесь — --pod-network-cidr. Он определяет диапазон IP-адресов, которые будут назначаться подам (Pods) — минимальным развертываемым единицам в Kubernetes, внутри которых работают один или несколько контейнеров. Мы выберем 10.244.0.0/16, так как он совместим с популярным сетевым плагином Flannel, который мы установим позже.

    
    
    sudo kubeadm init --pod-network-cidr=10.244.0.0/16

    Процесс инициализации может занять несколько минут. В конце вы увидите большой блок вывода. Сохраните его! В нем будет находиться самая важная команда — команда для присоединения рабочих узлов к кластеру. Она будет выглядеть примерно так:

    
    
    kubeadm join 192.168.1.100:6443 --token <ваш_токен> \
            --discovery-token-ca-cert-hash sha256:<ваш_хэш>
    
    Настройка kubectl для обычного пользователя: По умолчанию, kubectl требует root-прав для работы с кластером. Чтобы управлять кластером от имени вашего обычного пользователя, выполним следующие команды:
  2. 
    
    # Создаем директорию для конфигурации kubectl
    mkdir -p $HOME/.kube
    
    # Копируем конфигурационный файл администратора
    sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
    
    # Меняем владельца файла на текущего пользователя
    sudo chown $(id -u):$(id -g) $HOME/.kube/config

    Теперь вы можете использовать kubectl без sudo. Проверим, что кластер частично работает:

    
    
    kubectl get nodes

    Вы должны увидеть один узел — ваш управляющий узел, но его статус будет NotReady. Это нормально, так как мы еще не настроили сеть между подами.

  3. Установка сетевого плагина (CNI): Kubernetes не предоставляет собственную сетевую подсистему. Вместо этого он полагается на плагины, соответствующие спецификации CNI (Container Network Interface). Мы установим Flannel, простой и надежный плагин, который идеально подходит для начала. Именно здесь пригодится тот манифест, который вы предоставили. Мы применим его с помощью kubectl.

    
    
    kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml

    Примечание: Репозиторий был перемещен из coreos/flannel в flannel-io/flannel.

    Этот манифест создает несколько объектов в кластере: пространство имен kube-flannel, роли и привязки ролей для безопасности, сервисную учетную запись, ConfigMap с конфигурацией сети и DaemonSet, который гарантирует, что на каждом узле (включая управляющий) будет запущен под с агентом Flannel.

    Подождите пару минут, чтобы все компоненты Flannel запустились. Затем снова проверим статус узла:

    
    
    kubectl get nodes

    Теперь статус вашего управляющего узла должен измениться на Ready. Это означает, что сеть настроена, и узел готов принимать рабочие нагрузки (хотя обычно на управляющем узле не запускают пользовательские приложения, если это не мини-кластер для тестирования).

kubernet02

Сбор армии: присоединение рабочих узлов к кластеру

Настало время превратить наших "рабочих лошадок" в полноценных членов кластера. Переходим на первый рабочий сервер (k8s-worker-1).

  1. Присоединение к кластеру: Вспоминаем ту волшебную команду, которую мы сохранили после kubeadm init. Она выглядит примерно так (ваши токен и хэш будут другими!):

    
    
    sudo kubeadm join 192.168.1.100:6443 --token abcdef.0123456789abcdef \
        --discovery-token-ca-cert-hash sha256:1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef

    Выполняем эту команду с sudo. Процесс займет несколько минут. В конце вы должны увидеть сообщение: This node has joined the cluster.

  2. Повторяем для второго рабочего узла: Переходим на второй рабочий сервер (k8s-worker-2) и выполняем ту же самую команду присоединения.

  3. Проверка на управляющем узле: Возвращаемся на управляющий узел и проверяем статус всех узлов:

    
    
    kubectl get nodes

    Вы должны увидеть все три узла: один управляющий и два рабочих. Их статус может быть сначала NotReady, но через 1-2 минуты, после того как Flannel настроит сеть на новых узлах, статус должен смениться на Ready.

    Для более подробной информации можно использовать:

    
    
    kubectl get nodes -o wide
    kubectl describe node <имя_узла>

Поздравляем! Ваш трехузловой кластер Kubernetes теперь жив и здоров. Он представляет собой единую, согласованную систему, готовую к работе.

Аудит империи: тщательная проверка состояния кластера

Прежде чем доверить нашему новому кластеру реальные приложения, необходимо провести всестороннюю проверку его здоровья. Это как техосмотр нового автомобиля.

  1. Проверка состояния узлов: Мы уже делали это, но повторим. Все узлы должны быть в статусе Ready.

    
    
    kubectl get nodes
    NAME                 STATUS   ROLES           AGE   VERSION
    k8s-control-plane    Ready    control-plane   10m   v1.30.0
    k8s-worker-1         Ready    <none>          5m    v1.30.0
    k8s-worker-2         Ready    <none>          4m    v1.30.0
  2. Проверка системных подов: В Kubernetes есть множество системных подов, которые обеспечивают его работу (DNS, сетевой плагин, прокси и т.д.). Убедимся, что они все работают. Они находятся в пространстве имен kube-system.

    
    
    kubectl get pods -n kube-system

    Вы должны увидеть несколько подов, например:

    • coredns-* (обычно 2 экземпляра): Служба DNS кластера.
    • kube-flannel-ds-* (по одному на каждый узел): Агенты Flannel.
    • kube-proxy-* (по одному на каждый узел): Сетевой прокси для сервисов.
    • etcd-*, kube-apiserver-*, kube-controller-manager-*, kube-scheduler-* (на управляющем узле): Компоненты Control Plane.

    Статус всех этих подов должен быть Running, а количество рестартов (RESTARTS) — 0 или очень небольшое число (1-2 — нормально при первом запуске).

  3. Проверка событий кластера: Команда kubectl get events покажет последние события в кластере. Полезно для поиска скрытых проблем.

    
    
    kubectl get events --sort-by='.metadata.creationTimestamp'

Если все проверки пройдены успешно, ваш кластер готов к боевым задачам. Если какой-то под не запускается, внимательно изучите его логи с помощью kubectl logs <имя_пода> -n kube-system и описание с помощью kubectl describe pod <имя_пода> -n kube-system. Чаще всего проблемы связаны с сетью или остатками swap.

Запуск первой миссии: развёртывание и масштабирование приложения

Наш кластер построен, проверен и ждет своего первого задания. Давайте развернем простое, но наглядное приложение — веб-сервер Nginx — и посмотрим, как Kubernetes управляет им.

  1. Создание манифеста Deployment: В Kubernetes мы описываем желаемое состояние с помощью YAML-файлов. Создадим файл nginx-deployment.yaml.

    
    
    apiVersion: apps/v1 # Версия API для Deployment
    kind: Deployment # Тип объекта — Deployment (управляет репликами подов)
    metadata:
      name: nginx-deployment # Имя нашего Deployment
      labels:
        app: nginx # Метка для идентификации
    spec:
      replicas: 3 # Желаемое количество реплик пода
      selector:
        matchLabels:
          app: nginx # Deployment будет управлять подами с этой меткой
      template: # Шаблон для создания подов
        metadata:
          labels:
            app: nginx # Метка, которую будут иметь созданные поды
        spec:
          containers:
          - name: nginx # Имя контейнера в поде
            image: nginx:1.25-alpine # Образ контейнера (легковесная версия)
            ports:
            - containerPort: 80 # Порт, который слушает контейнер
            resources: # (Опционально) Запросы и лимиты ресурсов
              requests:
                memory: "64Mi"
                cpu: "250m"
              limits:
                memory: "128Mi"
                cpu: "500m"

    Этот манифест говорит Kubernetes: "Я хочу, чтобы всегда работало 3 копии пода с контейнером Nginx. Если одна копия упадет — немедленно запусти новую. Распредели их по разным узлам, если это возможно".

  2. Применение манифеста: Отправим наше желаемое состояние в кластер.

    
    
    kubectl apply -f nginx-deployment.yaml

    В ответ вы увидите: deployment.apps/nginx-deployment created.

  3. Проверка подов: Посмотрим, что создалось.

    
    
    kubectl get pods

    Вы должны увидеть три пода с именами, начинающимися на nginx-deployment-, и статусом Running. Используйте kubectl get pods -o wide, чтобы увидеть, на каких именно рабочих узлах они запущены.

  4. Проверка Deployment: Посмотрим на сам Deployment.

    
    
    kubectl get deployment nginx-deployment
    kubectl describe deployment nginx-deployment
    
    Масштабирование: Давайте представим, что нагрузка на наш Nginx возросла. Мы можем легко масштабировать наше приложение до 5 реплик одной командой:
  5. kubectl scale deployment nginx-deployment --replicas=5
    

    Проверим:

    
    
    kubectl get pods

    Через несколько секунд вы увидите 5 работающих подов. Kubernetes сам выбрал узлы для новых подов, основываясь на доступных ресурсах.

  6. Имитация сбоя: Давайте проверим самовосстановление. Удалим один из подов вручную:

    
    
    # Получим список подов
    kubectl get pods
    # Удалим один под (замените <имя_пода> на реальное имя)
    kubectl delete pod <имя_пода>

    Сразу после этого снова выполните kubectl get pods. Вы увидите, что удаленный под находится в статусе Terminating, а рядом уже появился новый под в статусе ContainerCreating или Running. Через несколько секунд список снова будет содержать 5 работающих подов. Kubernetes мгновенно отреагировал на отклонение от желаемого состояния!

  7. Экспозиция приложения (Опционально): Чтобы получить доступ к нашему Nginx извне кластера, нам нужно создать объект Service. Создадим файл nginx-service.yaml:

    
    
    apiVersion: v1
    kind: Service
    metadata:
      name: nginx-service
    spec:
      selector:
        app: nginx # Выбираем поды с этой меткой
      ports:
        - protocol: TCP
          port: 80 # Порт сервиса
          targetPort: 80 # Порт на подах
      type: NodePort # Тип сервиса, открывающий порт на каждом узле
    Применим его:
    
    kubectl apply -f nginx-service.yaml
    kubectl get service nginx-service

    В колонке NODE-PORT будет указан порт (например, 31234). Теперь вы можете обратиться к вашему приложению, открыв в браузере http://<IP_любого_рабочего_узла>:<NODE-PORT>. Kubernetes автоматически перенаправит запрос на один из работающих подов Nginx.

Вы только что развернули, масштабировали и испытали отказоустойчивость своего первого приложения в Kubernetes! Это был Nginx, но принцип абсолютно тот же для любого вашего собственного приложения, упакованного в Docker-образ.

kubernet03

Завершение эпопеи: от первого шага к бесконечным горизонтам

Итак, вы прошли путь от трех независимых VPS до единого, самовосстанавливающегося и масштабируемого кластера Kubernetes. Это не просто техническое достижение, это фундаментальное изменение подхода к управлению вашей инфраструктурой. Вы перешли от ручного, реактивного управления к декларативному, проактивному и автоматизированному.

Что вы получили?

  • Гибкость: Легко добавлять новые узлы в кластер для наращивания мощности.
  • Надежность: Приложения автоматически перезапускаются при сбоях, обеспечивая высокую доступность.
  • Эффективность: Ресурсы используются оптимально, Kubernetes сам распределяет нагрузку по узлам.
  • Стандартизацию: Все приложения разворачиваются и управляются единообразно через YAML-манифесты.

Это только начало. Ваш кластер — это холст, на котором вы можете рисовать все более сложные архитектуры:

  • CI/CD: Интегрируйте свой кластер с Jenkins, GitLab CI или GitHub Actions для автоматического развертывания при обновлении кода.
  • Мониторинг: Установите Prometheus и Grafana для сбора метрик и визуализации состояния кластера и приложений.
  • Логирование: Разверните EFK (Elasticsearch, Fluentd, Kibana) или Loki для централизованного сбора и анализа логов.
  • Безопасность: Настройте Role-Based Access Control (RBAC), политики безопасности подов (Pod Security Policies/Admission Controllers) и сетевые политики (Network Policies).
  • Хранилище: Интегрируйте постоянные тома (Persistent Volumes) для баз данных и других stateful-приложений.

Создание кластера Kubernetes на хостинге для VPS — это не конечная цель, а отправная точка. Это инвестиция в будущее вашего проекта, дающая вам инструменты для роста, масштабирования и инноваций без страха перед сложностью инфраструктуры. Ваша цифровая империя построена. Теперь пора ее населять и развивать. Удачи в ваших начинаниях, капитан вашего Kubernetes-флота!