Чтобы развернуть готовый кластер Kubernetes, можно использовать разные способы — например, самому подготовить виртуальные машины или выделенные серверы, настроить операционную систему и установить необходимые программы. Однако данный способ может показаться довольно долгим и затратным (если арендовать ресурсы ВМ). 

Также можно арендовать уже готовый кластер (Kubernetes как услуга). Наконец, можно развернуть кластер локально на своем устройстве при помощи утилиты minikube. Однако при ее использовании необходимо, чтобы процессор устройства поддерживал виртуализацию, а еще понадобится установить программу-гипервизор. 

Но существует еще один способ, при помощи которого кластер Kubernetes можно запустить, прилагая минимум усилий. Сегодня речь пойдет об утилите kind.

Описание утилиты kind

kind (сокращение от Kubernetes in Docker — Kubernetes в Docker) — это инструмент, при помощи которого можно развернуть готовый кластер Kubernetes прямо на своем устройстве — будь то стационарный компьютер или ноутбук. Kind полагается на систему контейнеризации Docker. Вместо Docker можно использовать podman или nerdctl. Ноды (узлы) кластера kind представляют собой запущенные Docker-контейнеры — kind использует метод Docker-in-Docker (DinD). Это немного противоречит концепции Kubernetes, где каждая нода — это отдельная физическая или виртуальная машина, на которой запущен агент kubelet.

kind можно применять для тестирования своих сервисов в кластере Kubernetes, с целью использования в локальной разработке и для встраивания в процессы CI.

Преимущества использования kind

Главные преимущества kind:

  • Простая и быстрая установка Kubernetes-кластера на устройстве;

  • Поддержка мультинодовых кластеров (2 и более нод);

  • Кроссплатформенность — установить и использовать kind можно на ОС Windows, Linux и macOS;

  • Проект разрабатывается под эгидой CNCF — некоммерческой организации, которая разрабатывает и поддерживает различные сетевые и DevOps-утилиты с открытым исходным кодом.

Предварительные требования

Сперва необходимо установить Docker. Для этого воспользуйтесь официальной документацией, предварительно выбрав нужный Linux-дистрибутив. kind поставляется с встроенным инструментом командной строки для управления кластером, но можно установить и использовать kubectl. Инструкция по установке утилиты kubectl приведена по ссылке.

Установка kind

kind можно установить на все популярные операционные системы — Windows, Linux, macOS. Дополнительно доступна установка из файлов исходного кода при помощи утилиты make и go install

Мы будем устанавливать утилиту на Ubuntu версии 22.04. Инструкции по установке на остальные ОС приведены по ссылке. Все команды, перечисленные ниже, необходимо выполнять из-под имени root пользователя или из-под обычного пользователя, у которого есть права sudo.

1) Скачиваем бинарный файл kind (для архитектуры AMD64 / x86_64):

[ $(uname -m) = x86_64 ] && curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.24.0/kind-linux-amd64

2) Делаем файл исполняемым:

chmod +x ./kind

3) Перемещаем kind в директорию /usr/local/bin/kind:

mv ./kind /usr/local/bin/kind

4) Проверяем, что установка была успешно выполнена путем вывода версии kind:

kind --version

Как можно увидеть на скриншоте выше, kind отобразил версию, а это значит, что утилита была успешно установлена.

Создание кластера

При создании кластера можно указать необходимый образ с тегом (версией). Т. к. у нас используется kubectl с версией 31.0,

kubectl version --client

то развернем кластер тоже с версией 31.0. Образы kind доступны на Docker Hub

При работе с любым кластером Kubernetes важно соблюдать версии компонентов кластера — они должны быть одинаковыми во избежание потенциальных проблем работоспособности. Также на этапе инициализации кластера можно задать имя. Наша команда для создания кластера будет следующей:

kind create cluster --image=kindest/node:v1.31.0 --name=my-first-cluster

Процесс создания кластера занимает считанные минуты. В нашем примере был создан один нодовый кластер с именем my-first-cluster. Если имя не было задано, то по умолчанию будет использоваться имя node.

Когда кластер будет готов, можно проверить запущенные контейнеры docker:

docker ps

А также воспользоваться утилитой kubectl, например, для вывода всех нод кластера:

kubectl get nodes

Создание кластера с несколькими нодами

Ранее мы создали кластер, состоящий только из одной master-ноды. Kind поддерживает установку кластера с двумя и более нодами, но для этого необходимо воспользоваться конфигурационным файлом. Конфигурационный файл — файл на языке разметки YAML. Точно такие же используются при работе с обычными кластерами Kubernetes. С синтаксисом конфигурационного файла можно ознакомиться по ссылке. Ниже приведен пример конфигурации для кластера состоящего из 3 нод — 1 мастер ноды и 2 рабочие ноды:

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
kubeadmConfigPatches:
- |
  apiVersion: kubelet.config.k8s.io/v1beta1
  kind: KubeletConfiguration
  evictionHard:
    nodefs.available: "0%"
kubeadmConfigPatchesJSON6902:
- group: kubeadm.k8s.io
  version: v1beta3
  kind: ClusterConfiguration
  patch: |
    - op: add
      path: /apiServer/certSANs/-
      value: my-hostname
nodes:
- role: control-plane
- role: worker
- role: worker

Сохраним конфигурацию выше в отдельный файл и передадим данный файл команде kind create:

kind create cluster --config test-cluster-config.yaml --image=kindest/node:v1.31.0 --name=my-second-cluster

Проверяем статус и количество нод кластера:

Кластер, состоящий из 3 нод, был успешно создан.

Создание кластера с двумя и более control plane-нодами

Kind поддерживает создание отказоустойчивых кластеров с 2 и более control plane-нодами. Для этого в конфигурационном файле достаточно указать необходимое количество control plane-нод. Например, создадим кластер с 2 control plane-нодами и одной рабочей нодой:

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
…
nodes:
- role: control-plane
- role: control-plane
- role: worker

Полная конфигурация:

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
kubeadmConfigPatches:
- |
  apiVersion: kubelet.config.k8s.io/v1beta1
  kind: KubeletConfiguration
  evictionHard:
    nodefs.available: "0%"
kubeadmConfigPatchesJSON6902:
- group: kubeadm.k8s.io
  version: v1beta3
  kind: ClusterConfiguration
  patch: |
    - op: add
      path: /apiServer/certSANs/-
      value: my-hostname
nodes:
- role: control-plane
- role: control-plane
- role: worker

Сохраняем конфигурацию в файл и создаем кластер:

kind create cluster --config cluster-wth-two-cp-node.yaml --image=kindest/node:v1.31.0 --name=my-third-cluster

Проверим ноды кластера:

kubectl get nodes

При использовании кластера с 2 и более control plane-нодами, kind в качестве балансировщика запросов использует HAProxy:

Ранее мы уже упоминали, что одна нода кластера kind равна одному запущенному контейнеру в Docker. На скриншоте выше это отчетливо видно.

Удаление кластера

Чтобы удалить запущенный кластер, достаточно выполнить команду:

kind delete cluster --name=<имя-кластера>

Чтобы узнать имя кластера, необходимо выполнить команду:

kind get clusters

Удалим кластер с именем test-first-cluster:

kind delete cluster --name=test-first-cluster

Если при создании кластера вы не задали имя, то по умолчанию кластер будет создан с именем kind. Для удаления кластера с дефолтным именем достаточно выполнить команду:

kind delete cluster

Установка Calico CNI

По умолчанию в качестве сетевого плагина (CNI — container network interface) в kind используется собственная реализация под названием kindnetd, основанная на плагинах ptp и host-local. Вместо kindnetd можно установить другой сетевой интерфейс — заявлена поддержка Calico, Cilium, Flannel. В качестве теста рассмотрим процесс установки Calico.

1) Перед установкой стороннего CNI-плагин, необходимо выключить дефолтный плагин. Подготовим конфигурацию со следующим содержимым:

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
networking:
  disableDefaultCNI: true
  podSubnet: 192.168.0.0/16
nodes:
- role: control-plane
- role: worker

Где:

disableDefaultCNI: true выключает стандартный CNI-плагин;
podSubnet: 192.168.0.0/16 — задается подсеть для подов. 192.168.0.0/16 — стандартная подсеть, для Calico используемая по умолчанию.

2) Создаем кластер:

kind create cluster --config cluster-with-calico.yaml --image=kindest/node:v1.31.0 --name=cluster-with-calico

3) Когда кластер будет готов, в статусе нод будет отображено NotReady:

Это связано с тем, что на данный момент у нас отсутствует CNI-плагин, а стандартный мы выключили.

4) Установим Calico при помощи официального манифеста:

kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.28.1/manifests/calico.yaml

5) Убедимся, что поды с Calico были успешно запущены:

watch kubectl get pods -l k8s-app=calico-node -A

Как можно увидеть на скриншоте выше, Calico был успешно установлен.

Разворачиваем тестовое приложение в кластере kind

Kind кластер отлично подходит для тестирования приложений. Развернем тестовый Nginx, предварительно собрав его образ.

1) Создадим конфигурацию, включающую в себя 3 ноды — 1 мастер-ноду и 2 рабочие:

vim test-deployment-app.yaml
apiVersion: kind.x-k8s.io/v1alpha4
kind: Cluster
nodes:
- role: control-plane
  extraPortMappings:
  - containerPort: 25400
    hostPort: 32700
    listenAddress: "0.0.0.0"
    protocol: tcp
- role: worker
- role: worker

В конфигурационном файле мы используем опцию extraPortMappings (перенаправление портов), чтобы получить доступ к запускаемому контейнеру в кластере kind с хостовой ОС. В качестве портов можно указать любой порт, который находится в диапазоне — с 30000 до 32767.

Параметр listenAddress: "0.0.0.0" означает, что запросы будут прослушиваться на всех сетевых адресах.

2) Создаем кластер:

kind create cluster --config test-deployment-app.yaml --image=kindest/node:v1.31.0 --name=test-deployment

Проверяем, что все ноды кластера запущены:

kubectl get nodes

3) Создаем структуру папок для тестового образа:

mkdir -p test-k8s/files

4) Создадим html-страницу в директории test-k8s/files/:

vim test-k8s/files/index.html
<html>
  <head>
    <title>Test-deployment</title>
  </head>
  <body>
      <h1>Nginx test</h1>
      <p>This Nginx pod is running in kind Kubernetes cluster</p>
    </div>
  </body>
</html>

5) Подготовим конфигурационный файл для Nginx:

vim test-k8s/files/default.conf
server {
    listen 80 default_server;

    

    root /usr/share/nginx/html;
    index index.html index.htm;
    server_name _;
    location / {
        try_files $uri $uri/ =404;
    }
}

6) Создаем Dockerfile:

vim test-k8s/Dockerfile
FROM ubuntu:24.04  
RUN  apt -y update && apt -y install nginx
COPY files/default /etc/nginx/sites-available/default
COPY files/index.html /usr/share/nginx/html/index.html
EXPOSE 80
CMD ["/usr/sbin/nginx", "-g", "daemon off;"]

7) Переходим в директорию с Dockerfile и собираем образ:

cd test-k8s

docker build -t nginx-test:01 .

8) Собранный образ отправляем в кластер:

kind load docker-image nginx-test:01 --name test-deployment

9) Чтобы загрузить готовый образ в Kubernetes-кластер, его необходимо «упаковать», используя тип объекта deployment:

vim nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-nginx
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: test-nginx
  template:
    metadata:
      labels:
        app: test-nginx
    spec:
      containers:
      - name: nginx-test-kind
        image: nginx-test:01
        imagePullPolicy: Never
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: test-nginx-service
  namespace: default
spec:
  selector:
    app: test-nginx
  type: NodePort
  ports:
  - name: http
    port: 80
    targetPort: 80
    nodePort: 32700

В примере выше мы создали 2 объекта — deployment и сервис со значением NodePort.

10) Создаем deployment в кластере:

kubectl apply -f nginx-deployment.yaml

11) Проверяем статус пода:

kubectl get po

12) Т. к. в качестве сетевого взаимодействия при инициализации кластера мы выбрали перенаправление портов, необходимо открыть туннель между локальным портом кластера и портом запущенного приложения (где test-nginx-service это имя ранее созданного сервиса):

kubectl port-forward service/test-nginx-service 32700:80

13) Отправим запрос на локальный адрес и порт приложения:

curl -i localhost:32700

В ответ мы получили ранее созданную страницу Nginx.

Экспорт логов кластера

В kind присутствует функционал для экспорта логов кластера. Для этого достаточно выполнить команду (где valuable-cluster это имя запущенного кластера):

kind export logs --name=valuable-cluster

Лог-файлы будут сохранены в директории /tmp в специальной папке (в данном примере в директории 3791338842):

Логи для нод кластера будут сохранены в отдельных директориях:

Утилита Kind может оказаться полезной для быстрого развертывания готового кластера Kubernetes. Вам потребуется только установить Docker и, при желании, инструмент командной строки kubectl. Kind хорошо подходит для разработчиков, которым необходимо быстро поднять кластер Kubernetes и протестировать свое приложение.


НЛО прилетело и оставило здесь промокод для читателей нашего блога:
-15% на заказ любого VDS (кроме тарифа Прогрев) — HABRFIRSTVDS

Комментарии (3)


  1. Sleuthhound
    17.09.2024 11:12

    Привет. Чем еще кроме поддержки многонодовых кластеров kind лучше чем кнопка Enable Kubernetes в Docker Desktop? ИМХО разработчику намного проще жамкнуть именно Enable Kubernetes в Docker Desktop и получить рабочий k8s.


    1. 1shaman Автор
      17.09.2024 11:12

      Здравствуйте, мне лично проще использовать сторонние утилиты для разворачивания кластеров, которые сразу работают на Linux. Для Docker Desktop нужно производить лишние телодвижения, связанные с установкой или WSL или hyperv. У меня, например, на рабочем компьютере Docker Desktop работает плохо или он кладет систему и становится невозможно работать или просто не запускается..


  1. Drno
    17.09.2024 11:12

    Итого у нас -
    Dedicate, на котором VM, на которой lxc контейнре, на которой докер, на которой кубер...в котором докер....)