Примеры развёртывания в Kubernetes
Здесь представлены готовые к продакшену манифесты Kubernetes для развёртывания NORA.
Быстрый старт
Заголовок раздела «Быстрый старт»# Deploy with default configurationkubectl apply -k .
# Verify deploymentkubectl 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— конфигурация (необязательно)secret.yaml— секреты (необязательно)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 # Adjust to your storage classdeployment.yaml
Заголовок раздела «deployment.yaml»apiVersion: apps/v1kind: Deploymentmetadata: name: nora namespace: nora-system labels: app: noraspec: replicas: 1 # NORA does not support multi-replica yet strategy: type: Recreate # Required for RWO volumes 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: # Storage - name: NORA_STORAGE_PATH value: /data
# Rate Limits (production values) - 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"
# Logging - name: NORA_LOG_LEVEL value: info - name: NORA_LOG_FORMAT value: json
# Metrics - 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
# Optional: Specify node affinity for SSD nodes # 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»Для nginx Ingress Controller:
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" # Unlimited upload size 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 # Root (registry) - path: / pathType: Prefix backend: service: name: nora port: number: 4000ingress-contour.yaml
Заголовок раздела «ingress-contour.yaml»Для Contour Ingress Controller (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 # Large uploads need long timeout
# NORA API - conditions: - prefix: /api services: - name: nora port: 4000
# Metrics (restricted) - conditions: - prefix: /metrics services: - name: nora port: 4000 # Optional: IP allowlist # ipAllowPolicy: # - cidr: 10.0.0.0/8
# Default route (registry) - 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 # Or ingress-contour.yaml
# Optional# - configmap.yaml# - secret.yaml
commonLabels: app.kubernetes.io/name: nora app.kubernetes.io/component: registry
images:- name: ghcr.io/getnora-io/nora newTag: latest # Pin to specific version in productionРазвёртывание
Заголовок раздела «Развёртывание»С помощью kubectl
Заголовок раздела «С помощью kubectl»# Create namespacekubectl apply -f namespace.yaml
# Deploy storagekubectl apply -f pvc.yaml
# Deploy NORAkubectl apply -f deployment.yamlkubectl apply -f service.yaml
# Deploy ingress (choose one)kubectl apply -f ingress-nginx.yaml# ORkubectl apply -f ingress-contour.yaml
# Wait for rolloutkubectl rollout status deployment/nora -n nora-systemС помощью Kustomize
Заголовок раздела «С помощью Kustomize»# Deploy everythingkubectl apply -k .
# Verifykubectl get all -n nora-systemС помощью Helm (если доступен)
Заголовок раздела «С помощью Helm (если доступен)»helm install nora . -n nora-system --create-namespaceПроверка
Заголовок раздела «Проверка»# Check pod statuskubectl get pods -n nora-system
# Check logskubectl logs -n nora-system -l app=nora -f
# Check servicekubectl get svc -n nora-system
# Test from inside clusterkubectl run -it --rm debug --image=curlimages/curl --restart=Never -- \ curl http://nora.nora-system.svc.cluster.local:4000/v2/
# Test from outside (after 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»# Create secretkubectl create secret docker-registry nora-registry \ --docker-server=nora.example.com \ --docker-username=admin \ --docker-password=changeme \ -n default
# Use in podspec: 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 и affinity узлов.
Проблема: CrashLoopBackOff
kubectl logs -n nora-system -l app=nora --previousПроверьте права доступа к томам и конфигурацию.
Проблема: 404 на /v2/
Проверьте конфигурацию Ingress и эндпоинты сервиса:
kubectl get endpoints -n nora-systemkubectl describe ingress nora -n nora-systemУсиление безопасности
Заголовок раздела «Усиление безопасности»- Включите аутентификацию (базовую или OIDC)
- Используйте NetworkPolicies для ограничения доступа
- Включите Pod Security Standards
- Регулярно выполняйте ротацию учётных данных
- Сканируйте образ NORA на уязвимости
- Используйте файловую систему только для чтения где возможно
- Ограничьте потребление ресурсов с помощью ResourceQuotas