Содержание
Представьте себе: вы начинаете с малого. Один сервер, одна команда docker run
, и ваше приложение уже радует первых пользователей. Это время простоты и ясности. Инфраструктура — как уютная комната, где вы знаете, где лежит каждая вещь. Но что происходит, когда успех приходит? Когда пользователи валом врываются на ваш сайт, когда один микросервис превращается в десяток, а база данных начинает задыхаться под нагрузкой? Ваша уютная комната превращается в лабиринт, где вы бегаете от одного сервера к другому, пытаясь вручную запустить контейнеры, перенастроить балансировщики и молиться, чтобы ничего не упало. Именно в этот момент, когда хаос вот-вот поглотит вас, на горизонте появляется спаситель — Kubernetes. Это не просто инструмент, это операционная система для вашей распределенной инфраструктуры, превращающая стаю независимых VPS в единый, умный и саморегулирующийся организм.
Кубернетес: ваш цифровой диспетчер вселенной контейнеров
Что же такое Kubernetes на самом деле? Если говорить просто, это платформа с открытым исходным кодом, созданная Google и теперь управляемая Cloud Native Computing Foundation (CNCF), для автоматизации развертывания, масштабирования и управления контейнеризированными приложениями. Но за этим сухим определением скрывается нечто гораздо большее. Kubernetes — это абстракция над хаосом. Он берет на себя всю рутину, связанную с жизненным циклом ваших приложений, позволяя вам сосредоточиться на коде, а не на инфраструктуре.
Представьте себе оркестр. У вас есть множество музыкантов (ваши контейнеры), играющих на разных инструментах (ваши микросервисы: фронтенд, бэкенд, база данных, кэш, брокер сообщений). Без дирижера (Kubernetes) они играют каждый свою партию, когда захотят, и получается какофония. Дирижер же следит за тем, чтобы все начали и закончили вместе, чтобы громкость была правильной, чтобы если один скрипач внезапно упал в обморок, его немедленно заменил дублер из-за кулис. Вот что делает Kubernetes:
- Автоматическое масштабирование: Когда ваш интернет-магазин взрывается во время "Черной пятницы", Kubernetes не звонит вам в три часа ночи. Он самостоятельно запускает дополнительные копии вашего контейнера с веб-сервером, чтобы справиться с наплывом покупателей. А когда ажиотаж спадает, он так же спокойно останавливает лишние контейнеры, экономя ваши деньги.
- Самовосстановление: Если один из ваших VPS внезапно "умирает" (а такое бывает), Kubernetes мгновенно обнаруживает это и перезапускает все контейнеры, которые на нем работали, на других здоровых узлах кластера. Пользователи даже не заметят сбоя.
- Декларативная конфигурация: Вы не говорите Kubernetes "запусти контейнер, потом настрой сеть, потом смонтируй том". Вы описываете желаемое состояние ("я хочу, чтобы работало три копии моего приложения, и они должны быть доступны по порту 80"). Kubernetes делает все остальное, чтобы это состояние было достигнуто и поддерживалось, несмотря ни на что.
- Управление конфигурациями и секретами: Kubernetes позволяет безопасно хранить пароли, ключи API и конфигурационные файлы, изолируя их от самого кода приложения и обеспечивая их доставку только в нужные контейнеры.
В итоге, Kubernetes превращает вашу инфраструктуру из набора "лего-кубиков", которые вы собираете вручную, в живую, дышащую систему, способную адаптироваться к любым изменениям нагрузки и сбоям. Это переход от ремесла к инженерии.
Закладываем фундамент: подготовка ваших VPS-Серверов
Прежде чем мы сможем построить наш цифровой замок, нам нужны прочные кирпичи — наши VPS-серверы. Для демонстрации мы будем использовать три сервера под управлением Ubuntu 22.04 LTS (более актуальная версия, чем 20.04). Один будет управляющим узлом (Control Plane) — мозгом всей операции, а два других станут рабочими узлами (Worker Nodes) — "рабочими лошадками", на которых будут физически выполняться ваши приложения.
Выбор VPS-провайдера — дело вкуса и бюджета. Популярны решения от DigitalOcean, Hetzner, Vultr, или, как упоминалось, AdminVPS. Главное — убедиться, что у вас есть root-доступ и возможность настраивать сетевые параметры.
Теперь, приступим к подготовке каждого из трех серверов. Этот этап критически важен, и пропуск любого шага может привести к неработоспособности кластера.
-
Обновление системы: Начнем с чистого листа. Обновим все пакеты до последних версий, чтобы избежать конфликтов.
sudo apt update && sudo apt upgrade -y sudo reboot # Рекомендуется перезагрузка после обновления ядра
-
Отключение Swap: Kubernetes строго требует, чтобы подкачка (swap) была отключена. Это связано с тем, как планировщик Kubernetes управляет ресурсами памяти. Сначала отключим swap временно, а затем навсегда закомментируем его в конфигурационном файле.
sudo swapoff -a # Редактируем файл /etc/fstab, чтобы swap не включался после перезагрузки sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab # Проверим, что swap отключен free -h
-
Настройка сети и параметров ядра: 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
-
Настройка имени хоста и файла 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, но работает независимо.
Выполняем следующие команды на всех трех серверах (управляющем и рабочих узлах).
-
Установка 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.
-
# Добавляем ключ репозитория 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.
-
Установка 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). Именно здесь мы "запустим двигатель" всего кластера.
-
Инициализация кластера: Мы используем команду
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
Процесс инициализации может занять несколько минут. В конце вы увидите большой блок вывода. Сохраните его! В нем будет находиться самая важная команда — команда для присоединения рабочих узлов к кластеру. Она будет выглядеть примерно так:
Настройка kubectl для обычного пользователя: По умолчанию,kubeadm join 192.168.1.100:6443 --token <ваш_токен> \ --discovery-token-ca-cert-hash sha256:<ваш_хэш>
kubectl
требует root-прав для работы с кластером. Чтобы управлять кластером от имени вашего обычного пользователя, выполним следующие команды: -
# Создаем директорию для конфигурации 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
. Это нормально, так как мы еще не настроили сеть между подами. -
Установка сетевого плагина (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
. Это означает, что сеть настроена, и узел готов принимать рабочие нагрузки (хотя обычно на управляющем узле не запускают пользовательские приложения, если это не мини-кластер для тестирования).
Сбор армии: присоединение рабочих узлов к кластеру
Настало время превратить наших "рабочих лошадок" в полноценных членов кластера. Переходим на первый рабочий сервер (k8s-worker-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
. -
Повторяем для второго рабочего узла: Переходим на второй рабочий сервер (
k8s-worker-2
) и выполняем ту же самую команду присоединения. -
Проверка на управляющем узле: Возвращаемся на управляющий узел и проверяем статус всех узлов:
kubectl get nodes
Вы должны увидеть все три узла: один управляющий и два рабочих. Их статус может быть сначала
NotReady
, но через 1-2 минуты, после того как Flannel настроит сеть на новых узлах, статус должен смениться наReady
.Для более подробной информации можно использовать:
kubectl get nodes -o wide kubectl describe node <имя_узла>
Поздравляем! Ваш трехузловой кластер Kubernetes теперь жив и здоров. Он представляет собой единую, согласованную систему, готовую к работе.
Аудит империи: тщательная проверка состояния кластера
Прежде чем доверить нашему новому кластеру реальные приложения, необходимо провести всестороннюю проверку его здоровья. Это как техосмотр нового автомобиля.
-
Проверка состояния узлов: Мы уже делали это, но повторим. Все узлы должны быть в статусе
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
-
Проверка системных подов: В 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 — нормально при первом запуске). -
Проверка событий кластера: Команда
kubectl get events
покажет последние события в кластере. Полезно для поиска скрытых проблем.kubectl get events --sort-by='.metadata.creationTimestamp'
Если все проверки пройдены успешно, ваш кластер готов к боевым задачам. Если какой-то под не запускается, внимательно изучите его логи с помощью kubectl logs <имя_пода> -n kube-system
и описание с помощью kubectl describe pod <имя_пода> -n kube-system
. Чаще всего проблемы связаны с сетью или остатками swap.
Запуск первой миссии: развёртывание и масштабирование приложения
Наш кластер построен, проверен и ждет своего первого задания. Давайте развернем простое, но наглядное приложение — веб-сервер Nginx — и посмотрим, как Kubernetes управляет им.
-
Создание манифеста 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. Если одна копия упадет — немедленно запусти новую. Распредели их по разным узлам, если это возможно".
-
Применение манифеста: Отправим наше желаемое состояние в кластер.
kubectl apply -f nginx-deployment.yaml
В ответ вы увидите:
deployment.apps/nginx-deployment created
. -
Проверка подов: Посмотрим, что создалось.
kubectl get pods
Вы должны увидеть три пода с именами, начинающимися на
nginx-deployment-
, и статусомRunning
. Используйтеkubectl get pods -o wide
, чтобы увидеть, на каких именно рабочих узлах они запущены. -
Проверка Deployment: Посмотрим на сам Deployment.
Масштабирование: Давайте представим, что нагрузка на наш Nginx возросла. Мы можем легко масштабировать наше приложение до 5 реплик одной командой:kubectl get deployment nginx-deployment kubectl describe deployment nginx-deployment
-
kubectl scale deployment nginx-deployment --replicas=5
Проверим:
kubectl get pods
Через несколько секунд вы увидите 5 работающих подов. Kubernetes сам выбрал узлы для новых подов, основываясь на доступных ресурсах.
-
Имитация сбоя: Давайте проверим самовосстановление. Удалим один из подов вручную:
# Получим список подов kubectl get pods # Удалим один под (замените <имя_пода> на реальное имя) kubectl delete pod <имя_пода>
Сразу после этого снова выполните
kubectl get pods
. Вы увидите, что удаленный под находится в статусеTerminating
, а рядом уже появился новый под в статусеContainerCreating
илиRunning
. Через несколько секунд список снова будет содержать 5 работающих подов. Kubernetes мгновенно отреагировал на отклонение от желаемого состояния! -
Экспозиция приложения (Опционально): Чтобы получить доступ к нашему 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-образ.
Завершение эпопеи: от первого шага к бесконечным горизонтам
Итак, вы прошли путь от трех независимых 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-флота!