Featured image of post Установка Kubernetes без интернета

Установка Kubernetes без интернета

Kubespray offline install. Пошаговая инструкция по установке Kubernetes кластера.

Собираю единомышленников в телеграм канале. Там же отвечаю на вопросы.
Присоединяйся Telegram

Гайд по онлайн установке здесь

В корпоративных средах безопасность имеет первостепенное значение.
Одной из распространенных мер безопасности является изоляция критической инфраструктуры от интернета.
Это создает проблемы при развертывании сложных распределенных систем, таких как Kubernetes, для установки которых обычно требуется загрузка многочисленных пакетов и образов контейнеров.
Если вы когда-либо пытались настроить Kubernetes в изолированной от интернета среде, вы знаете, насколько это сложно.
Стандартные процедуры установки предполагают наличие подключения к интернету, поэтому вам нет необходимости вручную собирать и переносить десятки зависимостей.
В этом гайде представлен мощный подход с использованием Kubespray настроенным на offline развертывание Kubernetes в закрытых средах без доступа к сети.
Этот метод не только решает проблему безопасности, но и обеспечивает более быструю установку благодаря предварительной загрузке необходимых компонентов, что делает его идеальным для развертывания с помощью скриптов и автоматизации рабочих задач.
Гайд составлялся на протяжении недели, с дебагом кучи ошибок и зависимостей. Не скупитесь тапнуть палец вверх внизу заметки, если она была полезной. Поехали!

Шаг 1. Вводные

Требуемые ресурсы

RoleCPURAMSSDOSIPReq
pc-inet2420Ubuntu 24.04192.168.1.99INET
harbor2450Ubuntu 24.04192.168.1.100TLS
master-1-k8s2450Ubuntu 24.04192.168.1.101ansible, python3
master-2-k8s2450Ubuntu 24.04192.168.1.102
master-3-k8s2450Ubuntu 24.04192.168.1.103
node-1-k8s48100Ubuntu 24.04192.168.1.104
node-2-k8s48100Ubuntu 24.04192.168.1.105
MetallB----192.168.1.200
  • pc-inet с доступом в интернет (чтобы скачать пакеты)
  • 3 Мастер узла
  • 2 Воркера
  • Доступ ssh с мастера к воркерам по sudo
  • Сервер Harbor настроенный на https
  • Свободный IP адрес или пул в той же сети, для MetallB
  • Пользователь с root правами, в моём примере admin

Что будет установлено

ComponentVersion
Kubesprayv2.29.1
Kubernetesv1.34.3
Ciliumv.1.18.5
MetalLBv0.13.9
Ingress-nginxv1.13.3

Шаг 2. Подготовка виртуальных серверов

В отличии от гайда, который я составлял ранее по online установке kubespray, в этом, настройку VM для кубера я переложу на ansible-плейбук.
Предполагается установка ОС Ubuntu 24.04 на все хосты.

Сервер с инетом pc-inet.
Клонируем репозиторий:

1
git clone https://github.com/ZM56/k8s-ans-bootstrap.git

Переносим на сервер: master-1-k8s
На master-1-k8s создаём SSH-ключ для подключения к другим машинам:

1
ssh-keygen -t rsa

И копируем его на все сервера:

1
2
3
4
ssh-copy-id admin@192.168.1.102
ssh-copy-id admin@192.168.1.103
ssh-copy-id admin@192.168.1.104
ssh-copy-id admin@192.168.1.105

Переходим:

1
cd k8s-ans-bootstrap

Меняем в inventory на свои адреса, имена и переменные в group_vars.
Устанавливаем ansible:

1
sudo apt install ansible-core -y

Запускаем

1
ansible-playbook -i inventory.ini play.yml -u admin

Машины готовы.

Шаг 3. Подготовка образов.

На машине с интернетом pc-inet

Готовим окружение

Мы не сможем поставить все зависимости питона на хосты без инета.
Здесь два варианта:

  1. Использовать докер образ kubespray и собирать с помощью него.
  2. Создать окружение на машине с выходом в инет и затем скопировать на целевые хосты.
    Я выбрал второе, так как в докер образе kubespray Trivy увидел high critical CVE, такое СБ не пропустят, а морочиться с пересборкой образа не наша основная задача.
1
2
3
4
5
mkdir /opt/kuber_off && cd /opt/kuber_off
apt update -y
apt install python3.12-venv -y
python3.12 -m venv venv
source venv/bin/activate

Клонируем репозиторий:

1
git clone --branch v2.29.1 --single-branch https://github.com/kubernetes-sigs/kubespray.git

Переходим в директорию:

1
cd kubespray

Проверяем версию:

1
git describe --tags

Должно быть: v2.29.1

Готовим инвентори:

1
2
cp -r /opt/kuber_off/kubespray/inventory/sample /opt/kuber_off/kubespray/inventory/offline_cluster
nano /opt/kuber_off/kubespray/inventory/offline_cluster/inventory.ini

Удаляем всё и добавляем pc-inet хост:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
[all]
pc-inet ansible_host=192.168.1.99 ip=192.168.1.99

[kube_control_plane]
pc-inet

[etcd]
pc-inet

[kube_node]
pc-inet

[k8s_cluster:children]
kube_control_plane
kube_node

Добавляем переменные:

1
nano /opt/kuber_off/kubespray/inventory/offline_cluster/group_vars/k8s_cluster/addons.yml

Включаем установку HELM, Ingress Nginx и MetalLB:

1
2
3
4
5
6
7
8
# Helm deployment
helm_enabled: true

# Включаем ingress-nginx
ingress_nginx_enabled: true

# MetalLB deployment
metallb_enabled: true

Контейнерный движок я выбрал containerd.
Почему не cri-o?
Containerd плюсы:

  • default в Kubespray
  • меньше сюрпризов в оффлайн-режиме
  • лучше тестируется в CI Kubespray
  • меньше зависимостей ОС
    Минусы:
  • чуть больше “общего” функционала

Cri-o плюсы:

  • tight-интеграция с Kubernetes
  • любят в OpenShift-мире
    Минусы:
  • в Kubespray требует больше ручных правок

Добавляем переменные и даём название кластеру:

1
nano /opt/kuber_off/kubespray/inventory/offline_cluster/group_vars/k8s_cluster/k8s-cluster.yml

Устанавливаем cilium плагин, поэтому выставляем соответствующие настройки. Указанные поддерживаемые версии я брал отсюда: https://github.com/kubernetes-sigs/kubespray
Раздел: Supported components

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
kube_owner: root

# Этой строчки нет, вписываем ручками
kube_proxy_remove: true

kube_network_plugin: cilium
# Этой строчки тоже нет, добавляем
cilium_version: "1.18.5"

kube_proxy_strict_arp: true

# Доменное имя вашего будущего кластера
cluster_name: k8s.domain.local

## Default: containerd
container_manager: containerd

Открываем файл etcd:

1
nano /opt/kuber_off/kubespray/inventory/offline_cluster/group_vars/all/etcd.yml

Меняем (сверяем) параметр:

1
etcd_deployment_type: host

Открываем конфиг cilium:

1
nano /opt/kuber_off/kubespray/inventory/offline_cluster/group_vars/k8s_cluster/k8s-net-cilium.yml

Укажем что proxy теперь cilium, а не kube-proxy и mtu 1450:

1
2
3
cilium_mtu: "1450"
cilium_kube_proxy_replacement: true
cilium_tunnel_mode: geneve

Включаем Hubble

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# Hubble
### Enable Hubble without install
cilium_enable_hubble: true
### Enable Hubble-ui
### Installed by default when hubble is enabled. To disable set to false
cilium_enable_hubble_ui: "{{ cilium_enable_hubble }}"
### Enable Hubble Metrics
cilium_enable_hubble_metrics: true
### if cilium_enable_hubble_metrics: true
cilium_hubble_metrics:
 - dns
 - drop
 - tcp
 - flow
 - icmp
 - http

Открываем файл offline установки:

1
nano /opt/kuber_off/kubespray/inventory/offline_cluster/group_vars/all/offline.yml

И добавляем в самое начало файла параметры загрузки:

1
2
3
4
5
6
---
download_run_once: true
download_localhost: true
download_keep_remote_cache: true
download_force_cache: true
download_cache_dir: /opt/kubespray-cache

Запускаем загрузку

1
cd /opt/kubespray

Устанавливаем зависимости питона:

1
pip install -r requirements.txt

Создадим директории и на всякий установим containerd:

1
2
3
apt install containerd -y
mkdir -p /opt/kubespray-cache/images/
mkdir /opt/kubespray-releases/

Если в инет ходишь через прокси, то укажи здесь

1
nano /opt/kuber_off/kubespray/inventory/offline_cluster/group_vars/all/all.yml

Заполни и расскоментируй:

1
2
# http_proxy: ""
# https_proxy: ""

По умолчанию некоторые файлы скачиваются в /tmp/releases, с помощью переменной local_release_dir изменяем путь на /opt/kubespray-releases Запускаемся:

1
2
3
4
5
/opt/kuber_off/venv/bin/ansible-playbook -i inventory/offline_cluster/inventory.ini cluster.yml \
-e local_release_dir=/opt/kubespray-releases \
--tags download \
--skip-tags upload,upgrade -b \
-u admin

Получаем ошибку

1
2
3
TASK [download : Download_container | Download image if required]
task path: /opt/kuber_off/kubespray/roles/download/tasks/download_container.yml:57
fatal: [pc-inet -> localhost]: FAILED! => {"attempts": 4, "changed": false, "cmd": "/usr/local/bin/nerdctl -n k8s.io pull --quiet quay.io/cilium/cilium:v1.18.5", "msg": "[Errno 2] No such file or directory: b'/usr/local/bin/nerdctl'", >

Идём исправлять:

1
cp /opt/kubespray-releases/nerdctl /opt/kubespray-releases/crictl /usr/local/bin

Делаем линк:

1
sudo ln -sf /usr/bin/ctr /usr/local/bin/ctr

И проверить:

1
/usr/local/bin/nerdctl --version

Перезапускаем:

1
2
3
4
5
/opt/kuber_off/venv/bin/ansible-playbook -i inventory/offline_cluster/inventory.ini cluster.yml \
-e local_release_dir=/opt/kubespray-releases \
--tags download \
--skip-tags upload,upgrade -b \
-u admin

Должно завершиться успешно, без ошибок.

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

1
2
cd /opt/
nano download_k8s_images.sh

Вставляем:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#!/bin/bash
# На машине с ИНТЕРНЕТОМ
set -e
echo "Получаю список образов от kubeadm..."
# Ваш путь к kubeadm
KUBEADM_PATH="/opt/kubespray-cache/kubeadm-*-amd64"
# Получаем список образов
IMAGES=$($KUBEADM_PATH config images list 2>/dev/null | grep -v "WARN" || $KUBEADM_PATH config images list)

echo "Найдено образов: $(echo "$IMAGES" | wc -l)"
echo "$IMAGES"
echo ""

# Идём в директорию с images
DOWNLOAD_DIR="/opt/kubespray-cache/images"
cd "$DOWNLOAD_DIR"

echo "Начинаю скачивание в: $DOWNLOAD_DIR"
echo "=========================================="

# Скачиваем каждый образ
for IMAGE in $IMAGES; do
    echo ""
    echo "Обрабатываю: $IMAGE"

    # Скачиваем
    echo "   Pulling..."
    nerdctl pull "$IMAGE"

    # Генерируем имя файла
    FILENAME=$(echo "$IMAGE" | sed 's|/|_|g; s|:|_|g').tar
    echo "   Saving to: $FILENAME"

    # Сохраняем
    nerdctl save "$IMAGE" -o "$FILENAME"

    # Удаляем образ из локального nerdctl
    echo "   Removing from local nerdctl..."
    nerdctl rmi "$IMAGE"

    # Информация о файле
    SIZE=$(du -h "$FILENAME" | cut -f1)
    echo "Сохранено: $FILENAME ($SIZE)"
done

echo ""
echo "=========================================="
echo "Все образы скачаны!"
echo "Итого файлов: $(ls -1 *.tar | wc -l)"

Запускаемся:

1
2
3
chmod +x /opt/kubespray-cache/kube*
chmod +x download_k8s_images.sh
./download_k8s_images.sh

И ещё докачиваем образ:

1
2
nerdctl pull quay.io/cilium/operator-generic:v1.18.5
nerdctl save -o /opt/kubespray-cache/images/quay.io_cilium_operator-generic_v1.18.5.tar quay.io/cilium/operator-generic:v1.18.5

Далее скачаем Helm чарт для Cilium
Копируем helm бинарник:

1
cp /opt/kubespray-releases/helm-3.18.4/linux-amd64/helm /usr/local/bin/

Проверяем:

1
helm version

Закачиваем:

1
2
3
4
5
helm repo add cilium https://helm.cilium.io
helm repo update
helm pull cilium/cilium --version 1.18.5
# появится файл cilium-1.18.5.tgz
mv cilium-1.18.5.tgz /opt/cilium-1.18.5.tgz

Упаковать:

1
2
tar -C /opt -czf kubespray-code.tar.gz kuber_off
tar -C /opt -czf kubespray-offline-bundle.tar.gz kubespray-cache kubespray-releases cilium-1.18.5.tgz

Далее: Перетаскиваем файлы на закрытый контур без инета (хост master-1-k8s).

Шаг 4. Подготовка окружения оффлайн установки

Заливаем образы в Harbor

Ставим докер (Предполагается что он есть в ваших закрытых репозиториях Убунты):

1
2
sudi apt install docker.io -y
systemctl enable docker --now

Хост: master-1-k8s

1
2
tar -xzf /home/admin/kubespray-code.tar.gz -C /opt/
tar -xzf /home/admin/kubespray-offline-bundle.tar.gz -C /opt

Копируем бинари:

1
cp /opt/kubespray-releases/crictl /opt/kubespray-releases/nerdctl /usr/local/bin

И проверить:

1
2
/usr/local/bin/nerdctl --version
/usr/local/bin/crictl --version

Предполагается, что Harbor также находится в закрытой зоне сети, поэтому первым шагом мы зальём образы в репо.
Идём в Harbor создаём новый проект с названием k8s и другой с названием helm.
Репозиторий k8s измените с приватного на публичный. Это связано с тем, что containerd роль не считывает логин и пароль от репо из файла.
Решения у разрабов kubespray не нашел.
Helm репозиторий можно оставить приватным.

Делаем переменные окружения:

1
2
3
4
5
6
# Имя репозитория harbor
export HARBOR="harbor.domain.local"
# Проект в Harbor
export PROJECT="k8s"
# Где лежат *.tar
export IMG_DIR="/opt/kubespray-cache/images"

Логинимся

1
2
3
docker login $HARBOR
# Если x509, то проблема с сертами на Harbor. Гуглите.
cd $IMG_DIR

Грузим все образы в локальный докер

1
2
3
4
for f in *.tar; do
  echo "Loading $f"
  docker load -i "$f"
done

Тегируем:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
docker images --format '{{.Repository}}:{{.Tag}}' \
  | grep -E '^(quay\.io|registry\.k8s\.io|docker\.io|gcr\.io)/|^nginx:' \
  | while read img; do
      if [[ "$img" == nginx:* ]]; then
        img="docker.io/library/${img}"
      fi
      new="${HARBOR}/${PROJECT}/${img}"
      echo "TAG  $img -> $new"
      docker tag "$img" "$new"
      echo "PUSH $new"
      docker push "$new"
    done

Пушим все образы в локальный репозиторий:

1
2
3
4
5
6
docker images --format '{{.Repository}}:{{.Tag}}' \
  | grep -E "^${HARBOR}/${PROJECT}/(quay\.io|registry\.k8s\.io|docker\.io|gcr\.io)/" \
  | while read img; do
      echo "PUSH $img"
      docker push "$img"
    done

У меня получился 21 образ в Harbor

Готовим конфиги

Открываем файл:

1
nano /opt/kuber_off/kubespray/inventory/offline_cluster/group_vars/all/offline.yml

Изменяем конфигурацию kubespray чтобы смотрел в локальный репо:

1
2
3
4
5
6
7
8
9
# Репозиторий СВОЙ указываем
registry_host: "harbor.domain.local"
kube_image_repo: "{{ registry_host }}/k8s/registry.k8s.io"
gcr_image_repo: "{{ registry_host }}/k8s/gcr.io"
docker_image_repo: "{{ registry_host }}/k8s/docker.io"
quay_image_repo: "{{ registry_host }}/k8s/quay.io"

#Строки нет, добавить:
cilium_install_extra_flags: "--repository oci://{{registry_host}}/helm/cilium"

Здесь тоже поменяем, но на момент написания мануала это не работало, именно поэтому мы сделали репозиторий k8s в Harbor открытым.

1
nano /opt/kuber_off/kubespray/inventory/offline_cluster/group_vars/all/containerd.yml

Вставить в самый низ:

1
2
3
4
5
containerd_registry_auth:
  - registry: harbor.domain.local
    prefix: harbor.domain.local
    username: admin
    password: password_ot_harbor

При загрузке в репозиторий Harbor SHA у образов изменяется, поэтому отключим их сопоставление:

1
nano /opt/kuber_off/kubespray/inventory/offline_cluster/group_vars/k8s_cluster/k8s-net-cilium.yml

В самый низ файла:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
cilium_extra_values:
  image:
    useDigest: false
    digest: ""
  operator:
    image:
      useDigest: false
      digest: ""
  envoy:
    image:
      useDigest: false
      digest: ""
  hubble:
    relay:
      image:
        useDigest: false
        digest: ""
    ui:
      backend:
        image:
          useDigest: false
          digest: ""
      frontend:
        image:
          useDigest: false
          digest: ""

Добавляем образы в helm-репо

Копируем helm бинарник:

1
cp /opt/kubespray-releases/helm-3.18.4/linux-amd64/helm /usr/local/bin/

Проверяем:

1
helm version

Авторизовываемся:

1
helm registry login $HARBOR

И пушим наш образ для Cilium:

1
helm push /opt/cilium-1.18.5.tgz oci://$HARBOR/helm

Подготовка нод.

Открываем файл с хостами:

1
nano /opt/kuber_off/kubespray/inventory/offline_cluster/inventory.ini

Переписываем inventory на наши хосты:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
[all]
master-1-k8s    ansible_host=192.168.1.101
master-2-k8s    ansible_host=192.168.1.102
master-3-k8s    ansible_host=192.168.1.103
node-1-k8s      ansible_host=192.168.1.104
node-2-k8s      ansible_host=192.168.1.105

[kube_control_plane]
master-1-k8s
master-2-k8s
master-3-k8s

[kube_node]
node-1-k8s
node-2-k8s

[etcd]
master-1-k8s

[k8s_cluster:children]
kube_control_plane
kube_node

Шаг 5. Установка оффлайн кластера Kubespray

Доустанавливаем на master-1-k8s пакеты:

1
apt install docker.io -y

Если указывался прокси

1
nano /opt/kuber_off/kubespray/inventory/offline_cluster/group_vars/all/all.yml

Тогда нужно удалить здесь:

1
2
# http_proxy: ""
# https_proxy: ""

И запускаем установку:

1
2
3
4
cd /opt/kuber_off/
source venv/bin/activate
cd kubespray/
ansible-playbook -i inventory/offline_cluster/inventory.ini cluster.yml -b -u admin

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

Шаг 6. Настройка Ingress и MetallB для Hubble

Для вебки нужно раскатать конфиг MetalLB, для этого выбираем свободный пул адресов (я использую 1 адрес) из той же подсети где и кубер.

1
2
3
mkdir kube-manifests
cd kube-manifests
nano metallb.yml

Вставляем:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: ingress-pool
  namespace: metallb-system
spec:
  addresses:
  - 192.168.1.200/32
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: ingress-l2
  namespace: metallb-system
spec:
  ipAddressPools:
  - ingress-pool

Также создаём deployment ingress контроллера и адрес по которому будет открываться вебка Hubble

1
nano ingress-hubble-ui.yml

Вставляем:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: hubble-ui
  namespace: kube-system
spec:
  ingressClassName: nginx
  rules:
  - host: hubble.k8s.domail.local
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: hubble-ui
            port:
              number: 80

Применить:

1
kubectl apply -f .

Настрой DNS (или временно C:\Windows\System32\drivers\etc\hosts) Тебе нужно, чтобы hubble.k8s.domain.local резолвился в 192.168.1.200. Ingress будет слушать IP адрес MetalLB контроллера.

Всё готово!

Проблемы и решения

  1. Есть проблемы с авторизацией по containerd, поэтому репозиторий k8s делаем открытым.
  2. Проблема с образом cilium

Failed to pull image “harbor.domain.local/k8s/quay.io/cilium/cilium:v1.18.5@sha256:2c92fb05962a346eaf0ce11b912ba434dc10bd54b9989e970416681f4a069628”: > rpc error: code = NotFound desc = failed to pull and unpack image “harbor.domain.local”

В файле

1
inventory/offline_cluster/group_vars/k8s_cluster/k8s-net-cilium.yml

Не находит образ с sha. Отключаем.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
cilium_extra_values:
  image:
    useDigest: false
    digest: ""
  operator:
    image:
      useDigest: false
      digest: ""
  envoy:
    image:
      useDigest: false
      digest: ""
  hubble:
    relay:
      image:
        useDigest: false
        digest: ""
    ui:
      backend:
        image:
          useDigest: false
          digest: ""
      frontend:
        image:
          useDigest: false
          digest: ""
  1. Ошибка с image Cilium-operator image operator-generic не закачивается автоматом. Выкачать и закинуть в наш репозиторий.

Failed to pull image “harbor.domain.local/k8s/quay.io/cilium/operator-generic:v1.18.5”: rpc error: code = NotFound desc = failed to pull an>

1
2
3
4
docker pull quay.io/cilium/operator-generic:v1.18.5
docker tag quay.io/cilium/operator-generic:v1.18.5 harbor.domain.local/k8s/quay.io/cilium/operator-generic:v1.18.5
docker push harbor.domain.local/k8s/quay.io/cilium/operator-generic:v1.18.5
kubectl delete po -n kube-system -l name=cilium-operator

Возможно потребуется перепулить image, поэтому меняем политику на Always, пулим и возвращаем на Default

1
2
3
4
kubectl -n kube-system get deploy cilium-operator -o jsonpath='{.spec.template.spec.containers[0].imagePullPolicy}{"\n"}'
kubectl -n kube-system patch deploy cilium-operator --type='json' -p='[{"op":"replace","path":"/spec/template/spec/containers/0/imagePullPolicy","value":"Always"}]'
kubectl delete po -n kube-system -l name=cilium-operator
kubectl -n kube-system patch deploy cilium-operator --type='json' -p='[{"op":"replace","path":"/spec/template/spec/containers/0/imagePullPolicy","value":"IfNotPresent"}]'
  1. Не поднимается hubble-relay (Не резолвит DNS)

A record lookup error: lookup hubble-peer.kube-system.svc.k8s.domain.local. on 169.254.25.10:53: read udp 10.233.67.64:56328->169.254.25.10:53: i/o timeout" connectionTimeout=30s

Добавить в k8s-net-cilium.yml значение true, перезапустить плейбук с сетевыми тегами и удалить под, чтобы он пересоздался:

1
2
3
cilium_kube_proxy_replacement: true
ansible-playbook -i inventory/offline_cluster/inventory.ini cluster.yml -b --tags "cilium,network,kubernetes-apps" -v
kubectl delete po -l k8s-app=hubble-relay -n kube-system
  1. Проблема:

cp: cannot create regular file ‘/hostbin/cilium-mount’: Permission denied
В файле

1
opt/kuber_off/kubespray/inventory/offline_cluster/group_vars/k8s_cluster/k8s-cluster.yaml

Доюавить root

1
2
3
# This is the user that owns the cluster installation.
# Note: cilium needs to set kube_owner to root https://kubespray.io/#/docs/CNI/cilium?id=unprivileged-agent-configuration
kube_owner: root
  1. Ошибка. Не все ноды Cilium поднимаются. Раскопал, что VMware неочень дружит с Cilium на дефолтном порту. Вывод смена порта или tunnel_mode. Я выбрал второе.
    Про это написано здесь
    Статус:
1
kubectl -n kube-system exec -it ds/cilium -- cilium status | egrep -i 'KubeProxyReplacement|Cluster health'

Вывод:

1
2
KubeProxyReplacement:    True   [ens33  192.168.0.104 (Direct Routing)]
Cluster health:          1/5 reachable   (2026-01-30T09:34:21Z)   (Probe interval: 2m23.873716367s)

Файл:

1
nano /opt/kuber_off/kubespray/inventory/offline_cluster/group_vars/k8s_cluster/k8s-net-cilium.yml

Параметры:

1
2
3
4
# Overlay Network Mode
cilium_tunnel_mode: geneve
cilium_mtu: "1450"
#tunnelPort: 8223  # Это не сработало для vxlan, поэтому выбрал geneve

Запуск повторно:

1
2
3
4
ansible-playbook -i inventory/offline_cluster/inventory.ini cluster.yml -b --tags "cilium,network" -v
kubectl -n kube-system rollout restart ds/cilium
kubectl -n kube-system rollout status ds/cilium
kubectl -n kube-system exec -it ds/cilium -- cilium status | grep "Cluster health"

Post Install

Как управлять всем этим?
Управление самим Kubernetes (нодами, сетью, ПО)
Через Kubespray:

ЗадачаКак делать
Добавить нодудобавить в inventory + scale.yml
Обновить k8s версиюпоменять kube_version + upgrade-cluster.yml
Изменить сеть Ciliumправить group_vars/k8s_cluster/k8s-network-cilium.yml + –tags cilium
  • Kubespray = железо кластера.
  • Управление Cilium (сеть и безопасность)
ЧтоКак управлять
Политики сетиCRD CiliumNetworkPolicy
Диагностика сетиcilium status, cilium health, hubble observe
Информацию можно использовать в свободном доступе, с указанием ссылки на сайт
Telegram GitHub YouTube