Примеры развёртывания в Kubernetes
Этот раздел содержит готовые к продакшену манифесты Kubernetes для развёртывания NORA.
Быстрый запуск
Заголовок раздела «Быстрый запуск»# Развернуть с конфигурацией по умолчаниюkubectl apply -k .
# Проверить развёртываниеkubectl get pods -n nora-systemkubectl get svc -n nora-systemnamespace.yaml— определение Namespacepvc.yaml— PersistentVolumeClaim для хранилищаdeployment.yaml— Deployment NORAservice.yaml— Service (ClusterIP)ingress-nginx.yaml— Ingress для nginxingress-contour.yaml— HTTPProxy для Contourconfigmap.yaml— ConfigMap конфигурации (опционально)secret.yaml— Secret с секретами (опционально)kustomization.yaml— оверлей Kustomize
namespace.yaml
Заголовок раздела «namespace.yaml»apiVersion: v1kind: Namespacemetadata: name: nora-system labels: name: nora-systempvc.yaml
Заголовок раздела «pvc.yaml»apiVersion: v1kind: PersistentVolumeClaimmetadata: name: nora-storage namespace: nora-systemspec: accessModes: - ReadWriteOnce resources: requests: storage: 100Gi storageClassName: fast-ssd # Измените на ваш StorageClassdeployment.yaml
Заголовок раздела «deployment.yaml»apiVersion: apps/v1kind: Deploymentmetadata: name: nora namespace: nora-system labels: app: noraspec: replicas: 1 # NORA пока не поддерживает несколько реплик strategy: type: Recreate # Обязательно для томов с режимом RWO selector: matchLabels: app: nora template: metadata: labels: app: nora spec: containers: - name: nora image: ghcr.io/getnora-io/nora:latest imagePullPolicy: Always ports: - name: http containerPort: 4000 protocol: TCP env: # Хранилище - name: NORA_STORAGE_PATH value: /data
# Лимиты запросов (значения для продакшена) - name: NORA_RATE_LIMIT_UPLOAD_RPS value: "2000" - name: NORA_RATE_LIMIT_UPLOAD_BURST value: "5000" - name: NORA_RATE_LIMIT_GENERAL_RPS value: "1000" - name: NORA_RATE_LIMIT_GENERAL_BURST value: "2000"
# Логирование - name: NORA_LOG_LEVEL value: info - name: NORA_LOG_FORMAT value: json
# Метрики - name: NORA_METRICS_ENABLED value: "true"
volumeMounts: - name: storage mountPath: /data
resources: requests: cpu: 500m memory: 256Mi limits: cpu: 2000m memory: 1Gi
livenessProbe: httpGet: path: /health port: 4000 initialDelaySeconds: 10 periodSeconds: 30 timeoutSeconds: 5
readinessProbe: httpGet: path: /health port: 4000 initialDelaySeconds: 5 periodSeconds: 10 timeoutSeconds: 3
securityContext: runAsNonRoot: true runAsUser: 1000 allowPrivilegeEscalation: false readOnlyRootFilesystem: false capabilities: drop: - ALL
volumes: - name: storage persistentVolumeClaim: claimName: nora-storage
# Опционально: привязка к узлам с SSD # affinity: # nodeAffinity: # requiredDuringSchedulingIgnoredDuringExecution: # nodeSelectorTerms: # - matchExpressions: # - key: storage-type # operator: In # values: # - ssdservice.yaml
Заголовок раздела «service.yaml»apiVersion: v1kind: Servicemetadata: name: nora namespace: nora-system labels: app: noraspec: type: ClusterIP ports: port: 4000 targetPort: 4000 - name: http port: 4000 targetPort: 4000 protocol: TCP selector: app: noraingress-nginx.yaml
Заголовок раздела «ingress-nginx.yaml»Для Ingress Controller на базе nginx:
apiVersion: networking.k8s.io/v1kind: Ingressmetadata: name: nora namespace: nora-system annotations: cert-manager.io/cluster-issuer: letsencrypt-prod nginx.ingress.kubernetes.io/proxy-body-size: "0" # Без ограничения размера загрузки nginx.ingress.kubernetes.io/proxy-read-timeout: "600" nginx.ingress.kubernetes.io/proxy-send-timeout: "600"spec: ingressClassName: nginx tls: - hosts: - nora.example.com secretName: nora-tls rules: - host: nora.example.com http: paths: # Docker Registry API - path: /v2 pathType: Prefix backend: service: name: nora port: number: 4000 # NORA API/UI - path: /api pathType: Prefix backend: service: name: nora port: number: 4000 # Корневой маршрут (реестр) - path: / pathType: Prefix backend: service: name: nora port: number: 4000ingress-contour.yaml
Заголовок раздела «ingress-contour.yaml»Для Ingress Controller Contour (HTTPProxy):
apiVersion: projectcontour.io/v1kind: HTTPProxymetadata: name: nora namespace: nora-systemspec: virtualhost: fqdn: nora.example.com tls: secretName: nora-tls routes: # Docker Registry API - conditions: - prefix: /v2 services: - name: nora port: 4000 timeoutPolicy: response: 10m # Для загрузки больших образов нужен длительный таймаут
# NORA API - conditions: - prefix: /api services: - name: nora port: 4000
# Метрики (ограниченный доступ) - conditions: - prefix: /metrics services: - name: nora port: 4000 # Опционально: разрешённые IP-адреса # ipAllowPolicy: # - cidr: 10.0.0.0/8
# Маршрут по умолчанию (реестр) - conditions: - prefix: / services: - name: nora port: 4000configmap.yaml (опционально)
Заголовок раздела «configmap.yaml (опционально)»Для конфигурации на основе YAML:
apiVersion: v1kind: ConfigMapmetadata: name: nora-config namespace: nora-systemdata: config.yaml: | storage: type: local path: /data
rate_limits: upload: rps: 2000 burst: 5000 general: rps: 1000 burst: 2000
logging: level: info format: json
metrics: enabled: trueПодключение в Deployment:
volumes:- name: config configMap: name: nora-configvolumeMounts:- name: config mountPath: /etc/nora/config.yaml subPath: config.yamlsecret.yaml (опционально)
Заголовок раздела «secret.yaml (опционально)»Для хранения учётных данных аутентификации:
apiVersion: v1kind: Secretmetadata: name: nora-auth namespace: nora-systemtype: OpaquestringData: username: admin password: changemeИспользование в Deployment:
env:- name: NORA_AUTH_TYPE value: basic- name: NORA_AUTH_USERNAME valueFrom: secretKeyRef: name: nora-auth key: username- name: NORA_AUTH_PASSWORD valueFrom: secretKeyRef: name: nora-auth key: passwordkustomization.yaml
Заголовок раздела «kustomization.yaml»apiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomization
namespace: nora-system
resources:- namespace.yaml- pvc.yaml- deployment.yaml- service.yaml- ingress-nginx.yaml # Или ingress-contour.yaml
# Опционально# - configmap.yaml# - secret.yaml
commonLabels: app.kubernetes.io/name: nora app.kubernetes.io/component: registry
images:- name: ghcr.io/getnora-io/nora newTag: latest # В продакшене укажите конкретную версиюРазвёртывание
Заголовок раздела «Развёртывание»С помощью kubectl
Заголовок раздела «С помощью kubectl»# Создать namespacekubectl apply -f namespace.yaml
# Развернуть хранилищеkubectl apply -f pvc.yaml
# Развернуть NORAkubectl apply -f deployment.yamlkubectl apply -f service.yaml
# Развернуть Ingress (выберите один вариант)kubectl apply -f ingress-nginx.yaml# ИЛИkubectl apply -f ingress-contour.yaml
# Дождаться завершения выкатаkubectl rollout status deployment/nora -n nora-systemС помощью Kustomize
Заголовок раздела «С помощью Kustomize»# Развернуть всёkubectl apply -k .
# Проверитьkubectl get all -n nora-systemС помощью Helm (при наличии)
Заголовок раздела «С помощью Helm (при наличии)»helm install nora . -n nora-system --create-namespaceПроверка
Заголовок раздела «Проверка»# Проверить статус подаkubectl get pods -n nora-system
# Посмотреть логиkubectl logs -n nora-system -l app=nora -f
# Проверить сервисkubectl get svc -n nora-system
# Тест изнутри кластераkubectl run -it --rm debug --image=curlimages/curl --restart=Never -- \ curl http://nora.nora-system.svc.cluster.local:5000/v2/
# Тест снаружи (после настройки Ingress)curl https://nora.example.com/v2/Настройка клиентов
Заголовок раздела «Настройка клиентов»Авторизация Docker
Заголовок раздела «Авторизация Docker»docker login nora.example.comdocker tag myapp:latest nora.example.com/myapp:latestdocker push nora.example.com/myapp:latestKubernetes ImagePullSecrets
Заголовок раздела «Kubernetes ImagePullSecrets»# Создать секретkubectl create secret docker-registry nora-registry \ --docker-server=nora.example.com \ --docker-username=admin \ --docker-password=changeme \ -n default
# Использование в подеspec: imagePullSecrets: - name: nora-registry containers: - name: myapp image: nora.example.com/myapp:latestВыбор хранилища
Заголовок раздела «Выбор хранилища»Локальное хранилище
Заголовок раздела «Локальное хранилище»Преимущества:
- Высокая скорость
- Простота настройки
Недостатки:
- Не масштабируется
- Под привязан к конкретному узлу
Подходит для: одноузловых кластеров, среды разработки
NFS/NAS
Заголовок раздела «NFS/NAS»Преимущества:
- Доступ с нескольких узлов
- Простое резервное копирование
Недостатки:
- Сетевая задержка
- Единая точка отказа
Подходит для: небольших кластеров, локальной инфраструктуры
Облачное хранилище (S3-совместимое)
Заголовок раздела «Облачное хранилище (S3-совместимое)»Преимущества:
- Высокая доступность
- Неограниченная ёмкость
- PVC не требуется
Недостатки:
- Зависимость от сети
- Стоимость
Конфигурация:
env:- name: NORA_STORAGE_TYPE value: s3- name: NORA_S3_BUCKET value: nora-registry- name: NORA_S3_REGION value: us-east-1- name: NORA_S3_ENDPOINT value: https://s3.amazonaws.com- name: AWS_ACCESS_KEY_ID valueFrom: secretKeyRef: name: s3-creds key: access-key-id- name: AWS_SECRET_ACCESS_KEY valueFrom: secretKeyRef: name: s3-creds key: secret-access-keyПодходит для: продакшена, мультирегиональных развёртываний
Мониторинг
Заголовок раздела «Мониторинг»Prometheus ServiceMonitor
Заголовок раздела «Prometheus ServiceMonitor»apiVersion: monitoring.coreos.com/v1kind: ServiceMonitormetadata: name: nora namespace: nora-systemspec: selector: matchLabels: app: nora endpoints: - port: api path: /metrics interval: 30sДашборд Grafana
Заголовок раздела «Дашборд Grafana»Готовый JSON дашборда описан в руководстве по мониторингу.
Устранение неполадок
Заголовок раздела «Устранение неполадок»Проблема: под завис в состоянии Pending
kubectl describe pod -n nora-system -l app=noraПроверьте статус PVC и правила привязки к узлам (node affinity).
Проблема: CrashLoopBackOff
kubectl logs -n nora-system -l app=nora --previousПроверьте права доступа к тому и конфигурацию.
Проблема: ошибка 404 на /v2/
Проверьте конфигурацию Ingress и endpoints сервиса:
kubectl get endpoints -n nora-systemkubectl describe ingress nora -n nora-systemУсиление безопасности
Заголовок раздела «Усиление безопасности»- Включите аутентификацию (basic или OIDC)
- Используйте NetworkPolicy для ограничения доступа
- Включите Pod Security Standards
- Регулярно меняйте учётные данные
- Сканируйте образ NORA на наличие уязвимостей
- Используйте read-only корневую файловую систему где возможно
- Ограничьте потребление ресурсов с помощью ResourceQuotas