Перейти к содержимому

Примеры развёртывания в Kubernetes

Этот раздел содержит готовые к продакшену манифесты Kubernetes для развёртывания NORA.

Окно терминала
# Развернуть с конфигурацией по умолчанию
kubectl apply -k .
# Проверить развёртывание
kubectl get pods -n nora-system
kubectl get svc -n nora-system

  • namespace.yaml — определение Namespace
  • pvc.yaml — PersistentVolumeClaim для хранилища
  • deployment.yaml — Deployment NORA
  • service.yaml — Service (ClusterIP)
  • ingress-nginx.yaml — Ingress для nginx
  • ingress-contour.yaml — HTTPProxy для Contour
  • configmap.yaml — ConfigMap конфигурации (опционально)
  • secret.yaml — Secret с секретами (опционально)
  • kustomization.yaml — оверлей Kustomize

apiVersion: v1
kind: Namespace
metadata:
name: nora-system
labels:
name: nora-system

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nora-storage
namespace: nora-system
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Gi
storageClassName: fast-ssd # Измените на ваш StorageClass

apiVersion: apps/v1
kind: Deployment
metadata:
name: nora
namespace: nora-system
labels:
app: nora
spec:
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:
# - ssd

apiVersion: v1
kind: Service
metadata:
name: nora
namespace: nora-system
labels:
app: nora
spec:
type: ClusterIP
ports:
port: 4000
targetPort: 4000
- name: http
port: 4000
targetPort: 4000
protocol: TCP
selector:
app: nora

Для Ingress Controller на базе nginx:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
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: 4000

Для Ingress Controller Contour (HTTPProxy):

apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: nora
namespace: nora-system
spec:
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: 4000

Для конфигурации на основе YAML:

apiVersion: v1
kind: ConfigMap
metadata:
name: nora-config
namespace: nora-system
data:
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-config
volumeMounts:
- name: config
mountPath: /etc/nora/config.yaml
subPath: config.yaml

Для хранения учётных данных аутентификации:

apiVersion: v1
kind: Secret
metadata:
name: nora-auth
namespace: nora-system
type: Opaque
stringData:
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: password

apiVersion: kustomize.config.k8s.io/v1beta1
kind: 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 # В продакшене укажите конкретную версию

Окно терминала
# Создать namespace
kubectl apply -f namespace.yaml
# Развернуть хранилище
kubectl apply -f pvc.yaml
# Развернуть NORA
kubectl apply -f deployment.yaml
kubectl 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
Окно терминала
# Развернуть всё
kubectl apply -k .
# Проверить
kubectl get all -n nora-system
Окно терминала
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 login nora.example.com
docker tag myapp:latest nora.example.com/myapp:latest
docker push nora.example.com/myapp:latest
Окно терминала
# Создать секрет
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

Преимущества:

  • Высокая скорость
  • Простота настройки

Недостатки:

  • Не масштабируется
  • Под привязан к конкретному узлу

Подходит для: одноузловых кластеров, среды разработки

Преимущества:

  • Доступ с нескольких узлов
  • Простое резервное копирование

Недостатки:

  • Сетевая задержка
  • Единая точка отказа

Подходит для: небольших кластеров, локальной инфраструктуры

Преимущества:

  • Высокая доступность
  • Неограниченная ёмкость
  • 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

Подходит для: продакшена, мультирегиональных развёртываний


apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: nora
namespace: nora-system
spec:
selector:
matchLabels:
app: nora
endpoints:
- port: api
path: /metrics
interval: 30s

Готовый 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-system
kubectl describe ingress nora -n nora-system

  1. Включите аутентификацию (basic или OIDC)
  2. Используйте NetworkPolicy для ограничения доступа
  3. Включите Pod Security Standards
  4. Регулярно меняйте учётные данные
  5. Сканируйте образ NORA на наличие уязвимостей
  6. Используйте read-only корневую файловую систему где возможно
  7. Ограничьте потребление ресурсов с помощью ResourceQuotas