Развертывание K3S в моей домашней лаборатории

· 6 минуты на чтение
Развертывание K3S в моей домашней лаборатории

Как и у большинства технических энтузиастов, у меня дома есть сервера, и я всегда нахожусь в поиске новых технологий, которые могут меня заинтересовать. На работе у нас есть полноценный управляемый Kubernetes, но хотелось проверить его в деле не боясь что-то сломать. Я уже знал, что K8S довольно тяжелый и его сложно конфигурировать. В поисках легковесной альтернативы я наткнулся на K3S, легкий и простой в использовании дистрибутив Kubernetes, и решил попробовать его в своей домашней лаборатории. В этой статье я поделюсь своим опытом установки и использования k3s, а также приведу несколько практических примеров того, как я использовал его для развертывания таких приложений, как NetBox, популярного инструмента управления IP-адресами и инфраструктурой центров обработки данных.

Установка k3s

Установка k3s была простой и быстрой. Просто выполнил команду из официальной документации по процессу установки. Сразу рекомендую отключить traefik и встроенный балансер.

curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="server --disable=traefik --disable=servicelb --cluster-init" sh -s -

cluster-init нужен, если вы хотите установать дополнительные ноды. После кортокой установки я проверил работоспособность k3s, проверив статус службы k3s и используя команду kubectl для получения списка доступных узлов.
Для виртуализации я использую proxmox и если у вас, как и у меня возникла идея развернуть ноду в lxc контейнере, имеет смысл пробовать только с локальным хранением данных без longhorn. После плясок с бубном мне удалось его заставить работать, но он напрочь не хочет работать с longhorn, там какой-то баг с iscsi.

Итак, чтобы развернуть k3s в lxc контейнер proxmox, нужен дистрибутив с ubuntu. Затем убедитесь, что на хостовой машине гипервизора включены модули ядра.
Для работы k3s в контейнере LXC, необходимо включить модули ядра overlay и br_netfilter. Добавьте их в файл /etc/modules:

overlay
br_netfilter

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

  /sbin/lsmod | /bin/grep overlay || /sbin/modprobe overlay
  /sbin/lsmod | /bin/grep br_netfilter || /sbin/modprobe br_netfilter

У меня Proxmox версии 6, в 7 параметры отличаются. Добавьте следующие настройки к стандартным параметрам контейнера LXC в Proxmox:

mp0: /lib/modules,mp=/lib/modules
lxc.hook.autodev: sh -c "mknod -m 0644 ${LXC_ROOTFS_MOUNT}/dev/kmsg c 1 11"
lxc.apparmor.profile: unconfined
lxc.cap.drop:
lxc.cgroup.devices.allow: a
lxc.mount.auto: proc:rw sys:rw

После установки k3s, отредактируйте файл /etc/systemd/system/k3s-agent.service и добавьте следующую строку перед первым ExecStartPre:

ExecStartPre=mount --make-rshared /

Эта настройка позволяет k3s-agent использовать разделяемые монтирования корневой файловой системы. После выполнения этих шагов, вы сможете успешно развернуть k3s в контейнере LXC на платформе Proxmox и использовать его для управления вашими контейнеризированными приложениями.

Для корректного завершения работы виртуальной машины с k3s и остановки всех связанных процессов при выключении системы, рекомендуется добавить специальную системную службу. Эта служба будет запускать скрипт k3s-killall.sh перед завершением работы системы. Иначе остановка всех процессов виртуальной машины может занять до 10 минут.
Создайте файл /etc/systemd/system/shutdown-k3s.service с следующим содержимым:

[Unit]
Description=Kill containerd-shims on shutdown
DefaultDependencies=false
Before=shutdown.target umount.target

[Service]
ExecStart=/usr/local/bin/k3s-killall.sh
Type=oneshot

[Install]
WantedBy=shutdown.target

После создания файла активируйте службу с помощью команды:

systemctl enable shutdown-k3s.service

Обратите внимание, что имя этой службы shutdown-k3s не должно начинаться с k3s-. В противном случае скрипт k3s-killall.sh будет пытаться остановить эту службу, что может вызвать проблемы.
Добавление и активация этой службы гарантирует корректное завершение работы всех связанных с k3s процессов при выключении системы и предотвращает возможные проблемы, связанные с неконтролируемым завершением работы контейнеров.

Развертывание NetBox

Начинать нужно создания namespace. Одним из важнейших аспектов эффективного управления ресурсами Kubernetes является использование пространств имен. Создавая новое пространство имен для каждого ресурса, вы можете лучше организовать, изолировать и управлять приложениями и компонентами в кластере k3s. Есть несколько преимуществ:

  • группировка связанных ресурсов в одном пространстве имен помогает поддерживать более чистую и понятную структуру кластера. Такой подход упрощает задачи управления и облегчает поиск определенных ресурсов в случае необходимости
  • изоляция ресурсов. Разделение ресурсов на отдельные пространства имен обеспечивает дополнительный уровень изоляции, гарантируя, что проблема в одном пространстве имен не окажет прямого влияния на ресурсы в другом пространстве имен.
  • настраиваемые ограничения ресурсов: пространства имен позволяют устанавливать определенные лимиты ресурсов и квоты для различных групп ресурсов, что упрощает управление потреблением ресурсов в кластере. Выделяя соответствующие лимиты ресурсов для каждого пространства имен, вы можете гарантировать, что ни одно приложение или компонент не будет перегружать ресурсы за счет других.
  • контроль доступа: такой подход позволяет предоставлять определенные разрешения пользователям или командам, позволяя им управлять ресурсами в пределах назначенных пространств имен и ограничивая доступ к другим частям кластера.
apiVersion: v1
kind: Namespace
metadata:
  name: netbox

Затем нам потребуется БД postgresql, устанавливать его я буду с помощью Helm и чарта Bitnami. Практически везде предлагают устанавливать Helm чарты командой helm install, однако я рекомендую использовать для этого манифест:

apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
  name: netbox-postgresql
  namespace: kube-system
spec:
  chart: postgresql
  repo: https://charts.bitnami.com/bitnami
  targetNamespace: netbox
  version: 12.2.6
  valuesContent: |-
    auth:
      database: "netbox"
      username: "netbox"
      existingSecret: netbox-postgresql-secrets
    persistence.size: 1Gi
    primary:
      persistence:
        enabled: true
        existingClaim: netbox-postgresql-pvc
  • apiVersion: helm.cattle.io/v1: эта строка указывает версию API для ресурса HelmChart, предоставляемого проектом Rancher.
  • kind: HelmChart: тип создаваемого ресурса.
  • metadata: этот раздел содержит метаданные о ресурсе HelmChart, включая имя и пространство имен.
  • name: имя ресурса HelmChart.
  • namespace: kube-system: пространство имен, в котором будет создан ресурс HelmChart. В данном случае это пространство имен "kube-system".
  • spec: этот раздел содержит спецификацию для ресурса HelmChart, включая информацию о чарте, репозитории и значениях конфигурации.
  • chart: postgresql: название чарта Helm, которая будет развернута, в данном случае - PostgreSQL.
  • repo: https://charts.bitnami.com/bitnami: URL-адрес репозитория Helm.
  • targetNamespace: netbox: пространство имен, в котором будет создан deployment PostgreSQL.
  • version: 12.2.6: версия образа PostgreSQL, который будет развернут, рекомендуется указывать конкретное значение, а не latest, чтобы не было сюрпризов с обновлением.
  • valuesContent: в этом разделе содержатся пользовательские значения.
  • auth: этот подраздел содержит конфигурации, связанные с аутентификацией.
  • database: "netbox": название создаваемой базы данных.
  • username: "netbox": имя пользователя для базы данных.
  • existingSecret: netbox-postgresql-secrets: имя существующего секрета Kubernetes, содержащего учетные данные базы данных.
  • persistence.size: 1Gi: размер постоянного хранилища, выделяемого для базы данных PostgreSQL.

Теперь создадим PVC для предоставления хранилища для базы данных PostgreSQL, указав размер хранилища 1Gi и используя класс хранилища Longhorn.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: netbox-postgresql-pvc
  namespace: netbox
spec:
  storageClassName: longhorn
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

Хранение учетных данных базы данных в Kubernetes Secret
Затем я создал секрет Kubernetes Secret для безопасного хранения учетных данных базы данных, включая имя базы данных NetBox, имя пользователя и пароль, а также пароль PostgreSQL. Позже этот секрет был использован в конфигурации HelmChart для развертывания PostgreSQL.

Обратите внимание, что при использовании data вам потребуется все значения преобразовать в base64 с ключом -n:

echo -n 'password123' | base64   
cGFzc3dvcmQxMjM=

Можно использовать stringData, тогда перобразовывать не нужно, однако вы можете столкнуться с ограничениями yaml по содержанию спец. символов.

apiVersion: v1
kind: Secret
metadata:
  name: netbox-postgresql-secrets
  namespace: netbox
type: Opaque
data:
  database: bmV0Ym94
  username: bmV0Ym94
  password: cGFzc3dvcmQxMjM=
  postgres-password: cGFzc3dvcmQxMjM=

Еще нам нужен Redis, развернем и его:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: netbox-redis-pvc
  namespace: netbox
spec:
  storageClassName: longhorn
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

---

apiVersion: v1
kind: Secret
metadata:
  name: netbox-redis-secrets
  namespace: netbox
type: Opaque
data:
  password: cGFzc3dvcmQxMjM=

---

apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
  name: netbox-redis
  namespace: kube-system
spec:
  chart: redis
  repo: https://charts.bitnami.com/bitnami
  targetNamespace: netbox
  version: 17.9.2
  valuesContent: |-
    master:
      persistence:
        enabled: true
        existingClaim: netbox-redis-pvc
    replica:
      replicaCount: 0
      persistence:
        enabled: false
    auth:
      enabled: true
      existingSecret: netbox-redis-secrets
      existingSecretPasswordKey: "password"

Ну и сам Netbox:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: netbox-pvc
  namespace: netbox
spec:
  storageClassName: longhorn
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

---

apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
  name: netbox
  namespace: kube-system
spec:
  chart: netbox
  repo: https://charts.boo.tc
  targetNamespace: netbox
  version: 4.1.1
  valuesContent: |-
    replicaCount: 1
    postgresql:
      enabled: false
      postgresqlUsername: "netbox"
      postgresqlDatabase: "netbox"
    redis:
      enabled: false
    persistence:
      enabled: true
      existingClaim: "netbox-pvc"
    externalDatabase:
      host: "netbox-postgresql"
      existingSecretName: netbox-postgresql-secrets
      existingSecretKey: password
    cachingRedis:
      host: "netbox-redis-master"
      existingSecretName: netbox-redis-secrets
      existingSecretKey: "password"
    tasksRedis:
      host: "netbox-redis-master"
      existingSecretName: netbox-redis-secrets
      existingSecretKey: "password"
    secretKey: "XXXXXXXXXX"

И остался ingress, для того, чтобы можно было получить к интерфейсу доступ по доменному имени, ограничим доступ локальной сетью:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: netbox-ingress
  namespace: netbox
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
    nginx.ingress.kubernetes.io/whitelist-source-range: 192.168.1.0/24
spec:
  ingressClassName: nginx
  rules:
  - host: netbox.example.com
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: netbox
            port:
              number: 80
  tls:
    - hosts:
      - netbox.example.com
      secretName: netbox-secret-tls

Заключение

Мой опыт использования k3s в домашней лаборатории был неоднозначным. Простота установки и администрирования k3s мне понравилась. Но на изучение манифестов и понимание логики у меня ушло более недели времени по вечерам. Я рекомендую вам тоже испытать эти неземные ощущения от использования Kubernetes дома.