Демо (скрипты и прочее) тестировалось на master ветке kubespray для установки кластера версии 1.23.5! Все плейбуки написаны по быстрому и раcчитаны на OS семейства RedHat 8.x
Предположим, что нам необходимо развернуть кластер kubernetes в ЦОД, в котором закрыт прямой выход в Internet.
Установка кластера kubernetes offline при помощи kebespray требует несколько подготовительных этапов.
- Подготовка файлов приложений и образов контейнеров.
- Создание в "закрытом контуре" хранилища файлов и контейнеров. Перенос файлов и контейнеров в хранилище.
- Настройка kubespray на использование хранилища.
В нашем тестовом варианте подготовка файлов приложений, образов контейнеров и развёртывание хранилища будет производиться на одном и том же сервере: starter.kryukov.local
В DNS, отвечающем за зону kryukov.local, добавлены две машины starter и nexus. Где nexus - это запись CNAME, ссылающаяся на машину starter.
Для быстрой установки будет использоваться ansible. Файлы плейбуков находятся в директории 00-ansible. Плейбук prepare-hosts.yaml разворачивает всё необходимое для дальнейшей работы на машине starter.
- Устанавливает необходимое ПО.
- Создаёт certificate authority. При помощи которого будут подписаны некоторые сертифкаты для вспомогателных приложений.
- Устанавливает docker.
- Устанавливает Nexus и nginx, выполняющий функцию reverse proxy.
После запуска плейбука необходимо зайти в nexus и настроить два хранилища:
- files, типа raw hosted. Для сохранения файлов приложений.
- doker-hub, типа docker hosted. Для хранения образов контейнеров:
Так же добавим роль:
И пользователя:
Для упрощения работы, установим ему пароль password.
Для скачивания базового набора мы можем воспользоваться возможностями kubespray.
Подготовим виртуальную среду для kubespray.
mkdir kubenv && cd kubenv
python3 -m venv env
source env/bin/activate
cd
Клонируем kubespray.
git clone https://github.com/kubernetes-sigs/kubespray.git
cd kubespray
Отредактируйте файлы inventory так, как если бы вы устанавливали кластер kubernetes.
cp -r inventory/sample inventory/cluster-offline
Подготовим директорию, куда будут скачаны файлы приложений.
mkdir /root/docker-images/
vim inventory/cluster-offline/group_vars/k8s_cluster/k8s-cluster.yml
В файле изменим параметр: local_release_dir: "/root/docker-images/"
Отредактируем inventory:
[all]
starter.kryukov.local ansible_host=192.168.218.178
[kube_control_plane]
starter.kryukov.local
[etcd]
starter.kryukov.local
[kube_node]
starter.kryukov.local
[calico_rr]
[k8s_cluster:children]
kube_control_plane
kube_node
calico_rr
Сгенерируем ssh ключ и скопируем его на этот же сервер:
ssh-keygen
ssh-copy-id starter.kryukov.local
Установим необходимые зависимости:
pip3 install -r requirements.txt
Запустим процедуру скачивания:
ansible-playbook -i inventory/cluster-offline/inventory.ini cluster.yml -e download_run_once=true \
-e download_localhost=true --tags download --skip-tags upload,upgrade
Получаем ошибку. В скачанных бинарниках в директории /root/docker-images/
ищем архив containerd-*.tgz
из него
вытаскиваем приложение ctr
в /usr/local/bin
.
Создаём директорию, куда будут помещены файлы образов контейнеров:
mkdir -p /tmp/kubespray_cache/images
Повторно запускаем ansible-playbook.
ansible-playbook -i inventory/cluster-offline/inventory.ini cluster.yml -e download_run_once=true \
-e download_localhost=true --tags download --skip-tags upload,upgrade
Создаём директорию, где будут храниться образы контейнеров и переносим в неё файлы из временной директории:
mkdir /root/k8s-images
mv /tmp/kubespray_cache/images/* /root/k8s-images
Ещё нам потребуются контейнеры, список которых выдаст kubeadm. Эти контейнеры kubespray по умолчанию не скачивает.
/root/docker-images/kubeadm-*-amd64 config images list
При помощи скрипта load-i.sh создадим недостающий файлы образов.
#!/usr/bin/env bash
for I in $(/root/docker-images/kubeadm-*-amd64 config images list); do
echo ========================
echo $I
nerdctl pull $I
ARCHIVE=$(echo $I | tr \/ _ | tr \: _ )
nerdctl save $I -o $ARCHIVE.tar
nerdctl rmi $I
done
# Кое что приходится фиксить руками для kubespray :(
nerdctl pull quay.io/coreos/etcd:v3.5.1
nerdctl save quay.io/coreos/etcd:v3.5.1 -o /root/k8s-images/quay.io_coreos_etcd_v3.5.1.tar
nerdctl rmi quay.io/coreos/etcd:v3.5.1
mv -f k8s.gcr.*.tar /root/k8s-images
Необходимые для установки файлы находятся в двух директориях: /root/k8s-images
и /root/docker-images/
. Перенесите
их на сервер, где будет установлено хранилище файлов.
2. Создание в "закрытом контуре" хранилища файлов и контейнеров. Перенос файлов и контейнеров в хранилище.
В нашем случае хранилище файлов находится там же, где мы собирали необходимые файлы. Поэтому нам достаточно залить файлы в наш nexus.
Мы воспользуемся двумя скриптами:
- tags.sh
- Поместит образы контейнеров из файлов контейнеров в docker на текущей машине.
- Добавит контейнерам необходимые теги.
- Зальёт контейнеры в nexus.
- upload-file.sh - загружает файлы в хранилище files nexus.
Поскольку для ssl сертификата nexux-proxy (nginx) мы использовали свой собственный CA. Что бы всё работало, нам потребуется добавить этот сертификат в список доверенный СА сертифкатов на всех, серверах, куда мы будем устанавливать kubernetes. Для этого воспользуемся простейшим плейбуком prepare-cluster.yaml.
ansible-playbook prepare-cluster.yaml
Прежде чем мы их загрузим, залогинимся в хранилище контейнеров.
docker login --username=docker-user --password=password starter.kryukov.local
tags.sh
#!/usr/bin/env bash
DOCKER_HUB="starter.kryukov.local"
cd
echo "Load images from files"
for I in $(ls k8s-images); do
echo " Load k8s-images/$I"
docker load < k8s-images/$I
done
echo "Start tags & push images"
for IMAGE in $(docker images | sed -e '1d' | awk '{ print $1 ":" $2 }' | grep -v 'sonatype/nexus3' | grep -v kubespray | grep -v 'nginx:1.21.6-alpine')
do
echo "==========================================================="
if $(echo $IMAGE | grep -E '^k8s.gcr.io|^quay.io' > /dev/null); then
TEMP=$(echo "${IMAGE##k8s.gcr.io\/}")
NEW_IMAGE="$DOCKER_HUB/$(echo ${TEMP##quay.io\/})"
else
NEW_IMAGE="$DOCKER_HUB/library/$IMAGE"
fi
echo "$IMAGE --> $NEW_IMAGE"
docker tag $IMAGE $NEW_IMAGE
docker push $NEW_IMAGE
done
upload-file.sh
#!/usr/bin/env bash
NEXUS=nexus.kryukov.local
SRC_DIR=/root/docker-images
KUBE_VERSION=v1.23.5
cd
for FILE in $( ls $SRC_DIR )
do
if [ -f $SRC_DIR/$FILE ]; then
echo "upload $SRC_DIR/$FILE"
curl -v -u docker-user:password --upload-file $SRC_DIR/$FILE http://$NEXUS/repository/files/k8s/$KUBE_VERSION/$FILE
fi
done
Для настройки kubespray мы изменим два файла:
- inventory/cluster-offline/group_vars/all/offline.yml
- inventory/cluster-offline/group_vars/all/containerd.yml
Ниже приведены только значащие строки из итогового offline.yml
registry_host: "starter.kryukov.local"
files_repo: "http://docker-user:[email protected]/repository/files/k8s"
yum_repo: "http://nexus.kryukov.local/rpm"
kube_image_repo: "{{ registry_host }}"
gcr_image_repo: "{{ registry_host }}"
github_image_repo: "{{ registry_host }}"
docker_image_repo: "{{ registry_host }}"
quay_image_repo: "{{ registry_host }}"
kubeadm_download_url: "{{ files_repo }}/{{ kube_version }}/kubeadm-{{ kube_version }}-amd64"
kubectl_download_url: "{{ files_repo }}/{{ kube_version }}/kubectl-{{ kube_version }}-amd64"
kubelet_download_url: "{{ files_repo }}/{{ kube_version }}/kubelet-{{ kube_version }}-amd64"
cni_download_url: "{{ files_repo }}/{{ kube_version }}/cni-plugins-linux-{{ image_arch }}-{{ cni_version }}.tgz"
crictl_download_url: "{{ files_repo }}/{{ kube_version }}/crictl-{{ crictl_version }}-{{ ansible_system | lower }}-{{ image_arch }}.tar.gz"
etcd_download_url: "{{ files_repo }}/{{ kube_version }}/etcd-{{ etcd_version }}-linux-amd64.tar.gz"
calicoctl_download_url: "{{ files_repo }}/{{ kube_version }}/calicoctl"
runc_download_url: "{{ files_repo }}/{{ kube_version }}/runc"
containerd_download_url: "{{ files_repo }}/{{ kube_version }}/containerd-{{ containerd_version }}-linux-{{ image_arch }}.tar.gz"
nerdctl_download_url: "{{ files_repo }}/{{ kube_version }}/nerdctl-{{ nerdctl_version }}-{{ ansible_system | lower }}-{{ image_arch }}.tar.gz"
Файл containerd.yml
containerd_registries:
"starter.kryukov.local": "https://starter.kryukov.local"
containerd_registry_auth:
- registry: "starter.kryukov.local"
username: docker-user
password: password
Предполагается, что данных из файла containerd.yml достаточно, что бы приложения могли логиниться в хаб. Но... нет. Последняя версия nerdctl (используется в kybespray для работы с контейнерами) перестала работать с [plugins."io.containerd.grpc.v1.cri"] config.
Поэтому запускаем установку кластера первый раз. Получаем ошибку. Затем "вручную" логинимся в хабе на каждой ноде при помощи плейбука nerd-login.yaml. И повторно запускаем kubespray.
Telegramm: https://t.me/arturkryukov/26