Не удается правильно подключить Synology NAS к Kubernetes.

Вопрос или проблема

Я пытался настроить NFS-шару на моем Synology NAS, но когда подключаю ее к своему кластеру RKE2, кажется, что доступ только для чтения или какая-то проблема с правами доступа для моих подов.

Моя текущая настройка

Synology NAS: DS923+
DSM Version: DSM 7.2.2-72806
Kubernetes node versions: v1.25.12+rke2r1 и v1.26.9+rke2r1 (кластер из трех мастер-узлов)
Kubernetes nodes OS: Ubuntu Server 22.04.5 LTS (Jammy Jellyfish)
pfSense Firewall: 2.7.0-RELEASE

Настройка брандмауэра

Брандмауэр находится между узлами и NAS с ПРАВИЛОМ РАЗРЕШЕНИЯ на этих портах ОТ Kubernetes Net К НАС Net:

548 AFP
137 CIFS/SMB
445 CIFS/SMB
20 FTP
3260 iSCSI
3263 iSCSI
3265 iSCSI
111 NFS
892 NFS
2049 NFS
69 TFTP
5005 HTTPS
138 CIFS/SMB
139 CIFS/SMB
21 FTP
5006 HTTPS
5555 Synology DiskStation Management API
875 NFS Locking

Настройка NAS

Я следовал этому руководству (virtualizationhowto) для настройки, так что настройки должны быть такими же, как показано в руководстве.

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

[x] Включить службу NFS
Максимальный протокол NFS: NFSv4.1

Права доступа общего папки NFS:

Имя хоста или IP: 10.0.8.0/24
Права: Чтение/запись
Squash: Назначить всех пользователей администратору
Безопасность: sys
[x] Включить асинхронный режим
[x] Разрешить подключения с непривилегированных портов (порты выше 1024)
[x] Разрешить пользователям доступ к подключенным подпапкам

Настройки общего тома:

Имя: k8sdata
Расположение: Том 1: Btrfs
[x] скрыть эту общую папку в "Моих сетевых местах"
[ ] Скрыть подпапки и файлы от пользователей без разрешений
[ ] Включить корзину

Когда я попробовал проверить настройку NFS с помощью mount -t nfs x.x.x.x:/volume1/k8sdata /mnt, все подключилось без проблем. Я смог создавать файлы и редактировать их также.

Для настройки подключения NFS в Kubernetes:

helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/

helm install nfs-subdir-external-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \
    --set nfs.server=x.x.x.x \
    --set nfs.path=/exported/path

Настройка развертывания

Я использовал Jellyfin для этого примера, но получаю тот же результат с nginx.

PVC.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: media
  namespace: media
spec:
  storageClassName: nfs-client
  accessModes: [ReadWriteOnce]
  resources: { requests: { storage: 18Ti } }

deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: jellyfin-app
  name: jellyfin-app
  namespace: media
spec:
  progressDeadlineSeconds: 600
  replicas: 1
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
    type: RollingUpdate
  selector:
    matchLabels:
      app: jellyfin-app
  template:
    metadata:
      labels:
        app: jellyfin-app
    spec:
      nodeSelector:
        cputype: kvm64
      volumes:
      - name: media-ssd
        persistentVolumeClaim:
          claimName: media
      securityContext:
        fsGroupChangePolicy: "OnRootMismatch"
      containers:
      - env:
        - name: JELLYFIN_PublishedServerUrl 
          value: <IP одного из мастеров Kubernetes> # IP адрес вашего сервера Jellyfin (см. конфигурацию службы)
        - name: PGID
          value: "\x36\x35\x35\x34\x31" # < ASCII код для '65541'
        - name: PUID
          value: "\x31\x30\x34\x34" #< ACII код для '1044'
        - name: TZ
          value: Europe/Oslo
        image: ghcr.io/linuxserver/jellyfin:10.9.11
        imagePullPolicy: Always
        name: jellyfin-app
        ports:
        - containerPort: 8096
          name: http-tcp
          protocol: TCP
        - containerPort: 8920
          name: https-tcp
          protocol: TCP
        - containerPort: 1900
          name: dlna-udp
          protocol: UDP
        - containerPort: 7359
          name: discovery-udp
          protocol: UDP      
        resources: {}
        stdin: true
        tty: true
        volumeMounts:
        - mountPath: /config
          subPath: "configs/jellyfin"
          name: media-ssd
        - mountPath: /data
          subPath: "downloads/transmission"
          name: media-ssd
        - mountPath: /usr/share/jellyfin/web
          subPath: "configs/jellyfin-web/"
          name: media-ssd
      dnsPolicy: ClusterFirst
      restartPolicy: Always

Я пытался менять значения PGID и PUID, но безуспешно.

id admin на Synology показывает:

uid=1024(admin) gid=100(users) groups=100(users),101(administrators)

и другой пользователь, которого я использую на Synology, имеет uid=1026 с тем же gid и группами.
Поэтому я также пробовал такую конфигурацию в развертывании:

- name: PGID
  value: "\x31\x30\x31" #101  #"\x36\x35\x35\x34\x31" # < ASCII код для '65541'
- name: PUID
  value: "\x31\x30\x32\x34" # 1026    #"\x31\x30\x34\x34" #< ACII код для '1044'

service.yaml

kind: Service
apiVersion: v1
metadata:
  name: jellyfin-app-tcp       # < имя службы
  namespace: media      # < пространство имен, где размещается служба
spec:
  selector:
    app: jellyfin-app          # < ссылка на развертывание (соединяет службу с развертыванием)
  ports:
  - port: 80             # < порт для открытия снаружи на сервере
    targetPort: 8096       # < целевой порт. порт на поде для прохода
    name: http-tcp         # < справочное имя для порта в yaml-ке развертывания
    protocol: TCP
  - port: 8920
    targetPort: 8920
    name: https-tcp
  type: ClusterIP
  sessionAffinity: ClientIP 

certificate-ingress.yaml

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: cert-ingress
  namespace: media
spec:
  secretName: cert-ingress
  issuerRef:
    name: acme-issuer
    kind: ClusterIssuer
  dnsNames:
    - REDACTED.REDACTED.com

---

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: jellyfin-wan
  namespace: media

spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - REDACTED.REDACTED.com
    secretName: cert-ingress
  rules:
  - host: REDACTED.REDACTED.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: jellyfin-app-tcp
            port:
              number: 80

Описание PVC:

Name:          media
Namespace:     media
StorageClass:  nfs-client
Status:        Bound
Volume:        pvc-acd165ef-2224-4691-a2a1-bfd84f3f5382
Labels:        <none>
Annotations:   pv.kubernetes.io/bind-completed: yes
               pv.kubernetes.io/bound-by-controller: yes
               volume.beta.kubernetes.io/storage-provisioner: cluster.local/nfs-subdir-external-provisioner
               volume.kubernetes.io/storage-provisioner: cluster.local/nfs-subdir-external-provisioner
Finalizers:    [kubernetes.io/pvc-protection]
Capacity:      18Ti
Access Modes:  RWO
VolumeMode:    Filesystem
Used By:       jellyfin-app-6cf67755b4-r2hrr
Events:
  Type    Reason                 Age                From                                                                                                                                 Message
  ----    ------                 ----               ----                                                                                                                                 -------
  Normal  ExternalProvisioning   48m (x2 over 48m)  persistentvolume-controller                                                                                                          waiting for a volume to be created, either by external provisioner "cluster.local/nfs-subdir-external-provisioner" or manually created by system administrator
  Normal  Provisioning           48m                cluster.local/nfs-subdir-external-provisioner_nfs-subdir-external-provisioner-7ddbf6bcf9-sxg9j_f5477ff7-35be-4b93-9d82-de781bf7af56  External provisioner is provisioning volume for claim "media/media"
  Normal  ProvisioningSucceeded  48m                cluster.local/nfs-subdir-external-provisioner_nfs-subdir-external-provisioner-7ddbf6bcf9-sxg9j_f5477ff7-35be-4b93-9d82-de781bf7af56  Successfully provisioned volume pvc-acd165ef-2224-4691-a2a1-bfd84f3f5382

Вывод kubectl logs -n media jellyfin-app-6cf67755b4-r2hrr :

14:21:12] [ERR] [1] Main: Ожидается, что сервер будет размещать веб-клиент, но предоставленный каталог содержимого либо недействителен, либо пустой: /usr/share/jellyfin/web. Если вы не хотите размещать веб-клиент на сервере, вы можете установить флаг командной строки '--nowebclient', или установить 'hostwebclient=false' в настройках конфигурации
[14:21:13] [INF] [1] Main: Версия Jellyfin: 10.9.11
[14:21:13] [INF] [1] Main: Переменные окружения: ["[JELLYFIN_APP_TCP_SERVICE_PORT, 80]", "[JELLYFIN_APP_TCP_PORT_80_TCP_PROTO, tcp]", "[JELLYFIN_TCP_PORT, tcp://10.43.107.94:8096]", "[JELLYFIN_LOG_DIR, /config/log]", "[JELLYFIN_TCP_PORT_8096_TCP_PORT, 8096]", "[JELLYFIN_APP_TCP_SERVICE_HOST, 10.43.45.121]", "[JELLYFIN_CONFIG_DIR, /config]", "[JELLYFIN_APP_TCP_PORT_80_TCP_PORT, 80]", "[JELLYFIN_CACHE_DIR, /config/cache]", "[JELLYFIN_APP_TCP_PORT_8920_TCP_ADDR, 10.43.45.121]", "[JELLYFIN_TCP_SERVICE_HOST, 10.43.107.94]", "[JELLYFIN_PublishedServerUrl, 10.0.8.2]", "[JELLYFIN_TCP_SERVICE_PORT, 8096]", "[JELLYFIN_APP_TCP_PORT_8920_TCP_PORT, 8920]", "[JELLYFIN_TCP_SERVICE_PORT_HTTP_TCP, 8096]", "[JELLYFIN_TCP_PORT_8096_TCP_PROTO, tcp]", "[JELLYFIN_TCP_PORT_8096_TCP_ADDR, 10.43.107.94]", "[JELLYFIN_APP_TCP_PORT, tcp://10.43.45.121:80]", "[JELLYFIN_APP_TCP_PORT_80_TCP, tcp://10.43.45.121:80]", "[JELLYFIN_APP_TCP_PORT_8920_TCP_PROTO, tcp]", "[JELLYFIN_APP_TCP_SERVICE_PORT_HTTPS_TCP, 8920]", "[JELLYFIN_TCP_PORT_8096_TCP, tcp://10.43.107.94:8096]", "[JELLYFIN_DATA_DIR, /config/data]", "[JELLYFIN_WEB_DIR, /usr/share/jellyfin/web]", "[JELLYFIN_APP_TCP_SERVICE_PORT_HTTP_TCP, 80]", "[JELLYFIN_APP_TCP_PORT_80_TCP_ADDR, 10.43.45.121]", "[JELLYFIN_APP_TCP_PORT_8920_TCP, tcp://10.43.45.121:8920]"]
[14:21:13] [INF] [1] Main: Аргументы: ["/usr/lib/jellyfin/bin/jellyfin.dll", "--ffmpeg=/usr/lib/jellyfin-ffmpeg/ffmpeg"]
[14:21:13] [INF] [1] Main: Операционная система: Ubuntu 24.04.1 LTS
[14:21:13] [INF] [1] Main: Архитектура: X64
[14:21:13] [INF] [1] Main: 64-битный процесс: True
[14:21:13] [INF] [1] Main: Взаимодействие с пользователем: True
[14:21:13] [INF] [1] Main: Количество процессоров: 10
[14:21:13] [INF] [1] Main: Путь к данным программы: /config/data
[14:21:13] [INF] [1] Main: Путь к каталогу логов: /config/log
[14:21:13] [INF] [1] Main: Путь к каталогу конфигураций: /config
[14:21:13] [INF] [1] Main: Путь к кэшу: /config/cache
[14:21:13] [INF] [1] Main: Путь к веб-ресурсам: /usr/share/jellyfin/web
[14:21:13] [INF] [1] Main: Каталог приложения: /usr/lib/jellyfin/bin/
[14:21:13] [ERR] [1] Main: Ожидается, что сервер будет размещать веб-клиент, но предоставленный каталог содержимого либо недействителен, либо пустой: /usr/share/jellyfin/web. Если вы не хотите размещать веб-клиент на сервере, вы можете установить флаг командной строки '--nowebclient', или установить 'hostwebclient=false' в настройках конфигурации

Папки создаются, но файлы практически не создаются.

tree /mnt/media-media-pvc-acd165ef-2224-4691-a2a1-bfd84f3f5382

.
├── configs
│   ├── jellyfin
│   │   ├── cache
│   │   ├── data
│   │   │   ├── data
│   │   │   ├── plugins
│   │   │   │   └── configurations
│   │   │   └── transcodes
│   │   ├── log
│   │   │   └── log_20250208.log
│   │   └── logging.default.json
│   └── jellyfin-web
└── downloads
    └── transmission

12 directories, 2 files

Вопросы

Так что, думаю, мои вопросы следующие:

  1. Почему я получаю доступ только для чтения/проблемы с разрешениями на NFS-монтаж в Kubernetes?

  2. Есть ли какие-либо конфигурации, которые я упускаю в экспорте NFS или настройке Kubernetes, которые могли бы вызвать это?

  3. Может ли проблема быть связана с разрешениями файловой системы на Synology NAS или чем-то в Kubernetes (например, securityContext, fsGroup и т.д.)?

Любая помощь будет очень полезна!!

Ответ или решение

Для успешного подключения Synology NAS к вашему кластеру RKE2 на Kubernetes, важно разобраться в нескольких аспектах, связанных с конфигурацией NFS и параметрами безопасности как на стороне кластера, так и на стороне NAS. Рассмотрим основные причины и пути решения проблемы доступа, с которой вы столкнулись.

Теория

  1. Аутентификация и авторизация в NFS:

    • NFS (Network File System) — это сетевой протокол, позволяющий серверу и клиенту обмениваться файлами. Одной из ключевых особенностей NFS является использование uid и gid для контроля прав доступа. Проблема часто возникает из-за несоответствия идентификаторов пользователей и групп (PUID и PGID) между контейнерами Kubernetes и сервером NAS.
  2. Параметры доступа (accessModes):

    • В Kubernetes, PersistentVolumeClaims (PVC) имеют различные режимы доступа, такие как ReadWriteOnce (RWO), ReadOnlyMany (ROX) и ReadWriteMany (RWX). Неправильный выбор accessModes может ограничить доступ к ресурсу.
  3. SecurityContext и fsGroup:

    • Эти параметры управляют тем, как контейнеры взаимодействуют с файловой системой. Важным аспектом является назначение правильного fsGroup, чтобы обеспечить доступ контейнеров к файлам с нужными правами.

Пример

Ваши настройки указаны следующим образом:

  • NAS: Вы используете Synology DS923+ с DSM версии 7.2.2. NFS настроен на NFSv4.1.
  • Кластер Kubernetes: С версии RKE2 установлены несколько мастер-узлов на Ubuntu Server 22.04.

Ваши действия:

  • Конфигурация NFS на Synology позволяет доступы для IP-адресов в диапазоне 10.0.8.0/24, с правами чтения и записи, и, что важно, вы установили squash для отображения всех пользователей как admin.
  • Вы используете helm-чарт nfs-subdir-external-provisioner для установки внешнего провайдера на кластер Kubernetes. Однако, столкнулись с проблемой только чтения на уровне контейнеров.

Применение

Рекомендации по устранению проблемы:

  1. Проверка разрешений NFS на NAS:

    • Убедитесь, что файлы и директории на NAS имеют правильные права доступа. Убедитесь, что uid=1024 и gid=100 действительно обладают правами на чтение и запись в указанные директории.
    • Проверьте, что параметр squash установлен корректно. Map all users to admin может создавать конфликт, если идентификаторы пересекаются с уже имеющимися.
  2. Корректировка SecurityContext и fsGroup в Kubernetes:

    • Убедитесь, что в ваших деплойментах securityContext указан правильно и что используется корректное значение fsGroup, соответствующее gid пользователя NAS (что, судя по логам, gid=100).
  3. Тестирование доступа вне Kubernetes:

    • Подключитесь к NFS-серверу напрямую из любой машины в сети (например, из узла кластера), как это было сделано через команду mount, для проверки на уровне ОС, чтобы изолировать проблему между сетевым доступом и Kubernetes.
  4. Обновление статуса PVC:

    • Проверьте статус PVC и объемы журнала событий для любой ошибки или предупреждений. Это даст больше информации о том, какие проблемы возникают при первичном подключении.
  5. Отладка параметров helm-чарта:

    • Перепроверьте параметры, заданные в helm-команде для развертывания nfs-subdir-external-provisioner, убедитесь, что адрес сервера и путь не содержат ошибок и соответствуют тем, что работают при ручном подключении NFS.

Потенциальные улучшения:

  • Включите и проверьте логи как на стороне NFS-сервера, так и внутри Kubernetes. Это может дать более информативную подсказку относительно проблем с переговорами и аутентификацией протоколов.

  • Опыт других пользователей показывает, что иногда помогает установка NFS обратно на более стабильный NFSv3.

В результате, целостный подход к анализу всех уровней взаимодействия — от сети до параметров NFS, а также внутренняя политика управления доступом и безопасности Kubernetes, помогут устранить текущие проблемы с доступом к Synology NAS.

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

Капча загружается...