Кластер Kubernetes на Oracle Linux за 15 минут

Автор: | 05.05.2024

Oracle Cloud Native Environment (OCNE) — интегрированный пакет для управления облачными приложениями. Это тщательно подобранный набор проектов с открытым исходным кодом, основанных на открытых стандартах и спецификациях. Актуальная версия на момент публикации — 1.8. Официальная документация: https://docs.oracle.com/en/operating-systems/olcne/index.html

OCNE состоит из нескольких компонентов. Для управления окружением используется Platform CLI (утилита olcnectl). Platform API Server взаимодействует с Platform Agent на каждом узле, а агенты отвечают за выполнение операций. И нужно это всё для управления «модулями», работающими на конечных узлах.

Модули поддерживаются самые разные и в текущей версии их 16. Но центральным компонентом, ради чего это всё и создано, является модуль Kubernetes. Далее будет рассмотрен вариант установки минимально рабочей конфигурации кластера Kubernetes из трёх узлов — одного узла управления и двух рабочих. Данная конфигурация не является отказоустойчивой, но ниже будут приведены необходимые команды для её создания, однако для этого потребуется минимум пять узлов, а лучше шесть.

Подготовка

Предварительно были подготовлены ВМ control, worker1 и worker2 с Oracle Linux Server 9.3 в варианте «Minimal Install» под управлением BHyVe. Роли распределились следующим образом:

ВМOperator¹Control plane²Worker³
control✔️✔️
worker1✔️
worker2✔️
¹ Узел, на который устанавливается API Server и который будет использоваться для выполнения развёртывания с помощью утилиты olcnectl. Можно совместить с узлом Kubernetes, но рекомендуется выносить на отдельную машину.
² Слой управления Kubernetes — предоставляет Kubernetes API, отвечает за основные операции кластера и обработку событий. Для отказоустойчивости необходимо минимум три узла, рекомендуется пять, но в любом случае должно быть нечётное число.
³ Рабочие узлы Kubernetes — непосредственно выполняют полезную нагрузку. Требуется два узла для обеспечения отказоустойчивости. Важно отметить, что хоть Kubernetes допускает совмещение ролей Control plane и Worker на одном узле и утилита olcnectl корректно принимает такую конфигурацию в параметрах, но в текущей версии попытка так сделать закончится ошибкой.

Подразумевается, что в сети есть работающий сервер DNS для разрешения имён ВМ в IP-адреса. В противном случае необходимо корректно заполнить файл /etc/hosts на всех узлах:

192.0.2.11	control control.example.com
192.0.2.12	worker1 worker1.example.com
192.0.2.13	worker2 worker2.example.com

Для отказоустойчивого кластера для корректной работы Kubernetes API требуется балансировщик нагрузки. Возможно использование как внешнего балансировщика, так и создание внутреннего посредством виртуального IP-адреса (VIP). В случае единственного узла для слоя управления балансировка не требуется.

Для взаимодействия между собой узлы кластера используют сертификаты X.509. Поддерживается работа с HashiCorp Vault и через центр сертификации. В статье будет рассмотрен пример с самоподписными сертификатами (Private CA).

Для работы Kubernetes необходимо, чтобы на всех узлах кластера было синхронизировано время. Сделать это можно с помощью NTP и демона chronyd:

sudo dnf install --yes chrony
sudo systemctl enable --now chronyd.service

Убедись, что у вас выключен файл подкачки (поведение по умолчанию для Oracle Linux 9) — это требование Kubernetes.

С узла оператора должен быть доступ на другие узлы по SSH с аутентификацией по ключу, а пользователю должно быть разрешено использование sudo без запроса пароля, либо использоваться пользователь root. В общем случае это можно сделать выполнив следующие команды:

ssh-keygen
ssh-copy-id control
ssh-copy-id worker1
ssh-copy-id worker2
sudo echo -e "<username>\\tALL=(ALL)\\tNOPASSWD: ALL" >/etc/sudoers.d/olcne

Чтобы не столкнуться с ошибкой «context deadline exceeded» во время установки, настоятельно рекомендую заранее загрузить необходимые образы на все узлы:

sudo dnf install --yes podman
sudo podman pull \
container-registry.oracle.com/olcne/coredns:v1.10.1-1 \
container-registry.oracle.com/olcne/etcd:3.5.10 \
container-registry.oracle.com/olcne/flannel:v0.22.3-2 \
container-registry.oracle.com/olcne/kube-apiserver:v1.28.8 \
container-registry.oracle.com/olcne/kube-controller-manager:v1.28.8 \
container-registry.oracle.com/olcne/kube-proxy:v1.28.8 \
container-registry.oracle.com/olcne/kube-scheduler:v1.28.8 \
container-registry.oracle.com/olcne/speaker:v0.13.10-1
sudo dnf install --yes podman
sudo podman pull \
container-registry.oracle.com/olcne/controller:v0.13.10-1 \
container-registry.oracle.com/olcne/coredns:v1.10.1-1 \
container-registry.oracle.com/olcne/flannel:v0.22.3-2 \
container-registry.oracle.com/olcne/kube-proxy:v1.28.8 \
container-registry.oracle.com/olcne/kubernetes-dashboard:v2.7.0-2 \
container-registry.oracle.com/olcne/module-operator:v1.8.0 \
container-registry.oracle.com/olcne/speaker:v0.13.10-1

При настройке отказоустойчивого кластера с внутренним балансировщиком добавьте в список для Control plane образ container-registry.oracle.com/olcne/nginx:1.17.7-1. Актуальный список версий находится в файле /etc/olcne/modules/kubernetes/1.0.0/kubernetes.yaml, который будет доступен после установки olcne-api-server.

Установка

Установку проводим с ВМ оператора (в нашем случае это control). Установим утилиту olcnectl:

sudo dnf install --yes oracle-olcne-release-el9
sudo dnf install --enablerepo ol9_olcne18 --yes olcnectl

Подготовим конфигурационные файлы для модулей Kubernetes и MetalLB — балансировщика сетевой нагрузки для предоставления внешнего доступа к сервисам внутри кластера посредством выделения VIP:

environments:
  - environment-name: myenvironment
    globals:
      api-server: control.example.com:8091
#     api-server: operator.example.com:8091
      log-level: info
    modules:
      - module: kubernetes
        name: cluster
        args:
          compact: true
          container-registry: container-registry.oracle.com/olcne
          control-plane-nodes:
            - control.example.com::8090
#           - control1.example.com:8090
#           - control2.example.com:8090
#           - control3.example.com:8090
#         load-balancer: lb.example.com:6443
          restrict-service-externalip: false
#         virtual-ip: 192.0.2.10
          worker-nodes:
            - worker1.k8s.onlyfriends.local:8090
            - worker2.k8s.onlyfriends.local:8090
      - module: metallb
        name: cluster-lb
        args:
          metallb-config: metallb-config.yaml
          metallb-kubernetes-module: cluster
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: default
  namespace: metallb
spec:
  addresses:
    - 192.0.2.200-192.0.2.254
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: default
  namespace: metallb
spec:
  ipAddressPools:
    - default

Данная конфигурация предполагает создание окружения myenvironment с распределением ролей согласно ранее обозначенного плана. IP-адреса из пула для MetalLB должны быть свободны, при этом назначать их заранее на узлы не требуется. Если необходим отказоустойчивый кластер, то в control-plane-nodes указываем минимум три узла и дополнительно задаём load-balancer в случае внешнего балансировщика или virtual-ip для создания внутреннего. Выполним развёртывание кластера:

olcnectl provision \
--config-file config-file.yaml

В ходе выполнения команды сгенерируются необходимые сертификаты, после чего будет запрошено подтверждение на внесение изменений, а именно:

  • применение ролей control-plane и api-server на узел control;
  • применение роли worker на узлы worker1 и worker2.

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

? Apply control-plane, api-server configuration on control.example.com:
* Install oracle-olcne-release
* Enable olcne18 repo
* Install API Server
    Add firewall port 8091/tcp
* Configure firewall rule:
    Add interface cni0 to trusted zone
    Add ports: 8090/tcp 10250/tcp 10255/tcp 9100/tcp 8472/udp 6443/tcp
* Disable swap
* Load br_netfilter module
* Load Bridge Tunable Parameters:
    net.bridge.bridge-nf-call-ip6tables = 1
    net.bridge.bridge-nf-call-iptables = 1
    net.ipv4.ip_forward = 1
* Set SELinux to permissive
* Install and enable olcne-agent

Proceed? yes/no(default) yes
? Apply worker configuration on worker1.example.com:
* Install oracle-olcne-release
* Enable olcne18 repo
* Configure firewall rule:
    Add interface cni0 to trusted zone
    Add ports: 8090/tcp 10250/tcp 10255/tcp 9100/tcp 8472/udp
* Disable swap
* Load br_netfilter module
* Load Bridge Tunable Parameters:
    net.bridge.bridge-nf-call-ip6tables = 1
    net.bridge.bridge-nf-call-iptables = 1
    net.ipv4.ip_forward = 1
* Set SELinux to permissive
* Install and enable olcne-agent

Proceed? yes/no(default) yes
? Apply worker configuration on worker2.example.com:
* Install oracle-olcne-release
* Enable olcne18 repo
* Configure firewall rule:
    Add interface cni0 to trusted zone
    Add ports: 8090/tcp 10250/tcp 10255/tcp 9100/tcp 8472/udp
* Disable swap
* Load br_netfilter module
* Load Bridge Tunable Parameters:
    net.bridge.bridge-nf-call-ip6tables = 1
    net.bridge.bridge-nf-call-iptables = 1
    net.ipv4.ip_forward = 1
* Set SELinux to permissive
* Install and enable olcne-agent

Proceed? yes/no(default) yes

Соглашаемся, ждём несколько минут и если не было ошибок (на ошибки «Could not parse version «»: Invalid Semantic Version» внимания не обращаем), то кластер готов к работе. При необходимости изменить состав узлов внесите изменения в config-file.yaml и выполните команду повторно.

Использование

Для начала настроим Kubernetes CLI:

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
export KUBECONFIG=$HOME/.kube/config
echo 'export KUBECONFIG=$HOME/.kube/config' >> $HOME/.bashrc

И убедимся, что всё работает:

kubectl get nodes --all-namespaces
#NAME                  STATUS   ROLES           AGE   VERSION
#control.example.com   Ready    control-plane   5m    v1.28.3+3.el9
#worker1.example.com   Ready    <none>          5m    v1.28.3+3.el9
#worker2.example.com   Ready    <none>          5m    v1.28.3+3.el9

kubectl get deployments.apps --all-namespaces
#NAMESPACE              NAME                         READY   UP-TO-DATE   AVAILABLE   AGE
#kube-system            coredns                      2/2     2            2           5m
#kubernetes-dashboard   kubernetes-dashboard         1/1     1            1           5m
#metallb                metallb-crds-controller      1/1     1            1           5m
#ocne-modules           verrazzano-module-operator   1/1     1            1           5m

Далее получим доступ к Kubernetes Dashboard. Наиболее простым вариантом будет назначение внешнего IP-адреса с помощью MetalLB, а для этого необходимо изменить тип сервиса с ClusterIP на LoadBalancer. Также нам потребуется токен для аутентификации.

kubectl patch service --namespace kubernetes-dashboard kubernetes-dashboard --patch='{"spec":{"type":"LoadBalancer"}}'

kubectl get services --namespace kubernetes-dashboard
#NAME                   TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)         AGE
#kubernetes-dashboard   LoadBalancer   10.100.34.108   192.0.2.200   443:31329/TCP   5m

kubectl create token --namespace kubernetes-dashboard admin-user

Смотрим какой ExternalIP был присвоен и открываем его в браузере.

Для примера развернём nginx. Для этого в правом верхнем углу находим ➕ Create new resource, копируем туда данный набор манифестов и нажимаем Upload:

apiVersion: v1
kind: Namespace
metadata:
  name: hello-world
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: hello-world
  labels:
    app: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - image: container-registry.oracle.com/olcne/nginx:1.17.7 
          name: nginx
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  namespace: hello-world
spec:
  ports:
    - name: http
      port: 80
      targetPort: 80
  selector:
    app: nginx
  type: LoadBalancer

Дожидаемся завершения развёртывания, переходим в раздел Services и в колонке External Endpoints будет ссылка на наш «Hello, world!». На этом всё, плодотворного изучения.

Обновление

Раздел добавлен 18.05.2024.

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

sudo dnf update --yes oracle-olcne-release-el9
sudo dnf config-manager --disable ol9_olcne18
sudo dnf config-manager --enable ol9_olcne19

В остальном процедура сводится к трём шагам:

  1. Обновление узла оператора.
  2. Обновление окружения.
  3. Обновление модулей.

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

sudo systemctl stop olcne-api-server.service
sudo dnf update --yes olcnectl olcne-api-server olcne-utils
sudo systemctl start olcne-api-server.service

После обновления узла оператора выполним обновление окружения, что фактически означает обновление агентов:

olcnectl environment update olcne \
--api-server control.example.com:8091 \
--environment-name myenvironment \
--update-config \
--log-level info

Обратите внимание на параметр --update-config — при его указании нам больше не потребуется использовать --api-server для данного окружения. Перед выполнением следующего шага рекомендую сделать резервную копию ВМ с ролью Control plane. Обновим модуль Kubernetes:

olcnectl module update \
--environment-name myenvironment \
--kube-version 1.28.8 \
--log-level info \
--name cluster

Указание --kube-version является обязательным. Актуальную версию можно узнать в Release Notes или в упомянутом выше файле /etc/olcne/modules/kubernetes/1.0.0/kubernetes.yaml. После обновления основного модуля Kubernetes можно обновить другие установленные модули. Например, модуль MetalLB:

olcnectl module update \
--environment-name myenvironment \
--log-level info \
--metallb-version 0.13.10 \
--name cluster-lb

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *