Пример манифеста Kubernetes для запуска Swagger
Опубликовано:
Используемые термины: Swagger, Kubernetes.
Swagger — стандартный способ дать любому REST API удобный интерфейс для просмотра и тестирования. В этой инструкции разберем манифесты для развертывания Swagger UI и Swagger Editor в кластере Kubernetes: ConfigMap, Deployment, Ingress и Service.
Создание манифестов
ConfigMap
Deployment
Ingress
Service
Применение манифестов
Пример использования Swagger для самого кубера
Решение возможных проблем
Что учесть для продакшена
Примеры манифестов для Swagger
Создадим каталог для файлов манифестов и перейдем в него:
mkdir -p /opt/swagger && cd /opt/swagger
Рассмотрим по отдельности минимальный набор манифестов.
ConfigMap с адресом Swagger-спецификации
Создадим ConfigMap, в котором зададим адрес OpenAPI-спецификации и базовый путь интерфейса:
vi config.yml
apiVersion: v1
kind: ConfigMap
metadata:
name: swagger-ui-config
namespace: default
labels:
app.kubernetes.io/name: swagger
app.kubernetes.io/part-of: swagger
data:
URL: "https://petstore.swagger.io/v2/swagger.json"
BASE_URL: /
* где:
- URL — адрес спецификации, которую загрузит Swagger UI. По умолчанию указан тестовый Petstore API, но сюда же можно подставить и Kubernetes API documentation в формате OpenAPI — тогда интерфейс покажет Kubernetes API reference прямо в браузере.
- BASE_URL — путь, по которому интерфейс будет доступен внутри контейнера.
Deployment для Swagger UI и Swagger Editor
В одном Deployment запустим два контейнера — интерфейс просмотра (ui) и редактор спецификаций (editor). Для обоих настроены запросы/лимиты ресурсов и проверки готовности и живучести. Отдельно зафиксируем стратегию обновления, чтобы при выкатке новой версии не было простоя:
vi deploy.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: swagger
namespace: default
labels:
app.kubernetes.io/name: swagger
app.kubernetes.io/part-of: swagger
spec:
replicas: 1
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app.kubernetes.io/name: swagger
template:
metadata:
labels:
app.kubernetes.io/name: swagger
app.kubernetes.io/part-of: swagger
spec:
containers:
- name: ui
image: swaggerapi/swagger-ui:v5.17.14
imagePullPolicy: IfNotPresent
ports:
- name: ui
containerPort: 8080
protocol: TCP
envFrom:
- configMapRef:
name: swagger-ui-config
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 200m
memory: 256Mi
readinessProbe:
httpGet:
path: /
port: ui
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /
port: ui
initialDelaySeconds: 10
periodSeconds: 20
- name: editor
image: swaggerapi/swagger-editor:v4.13.1
imagePullPolicy: IfNotPresent
env:
- name: PORT
value: "8081"
- name: BASE_URL
value: /editor
ports:
- name: editor
containerPort: 8081
protocol: TCP
resources:
requests:
cpu: 50m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
readinessProbe:
httpGet:
path: /editor
port: editor
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /editor
port: editor
initialDelaySeconds: 15
periodSeconds: 20
* readinessProbe и livenessProbe проверяют корневой путь каждого контейнера — если ответ не приходит вовремя, под будет перезапущен. strategy с maxUnavailable: 0 гарантирует, что при обновлении старый под не остановится, пока новый не пройдет readinessProbe.
Ingress для доступа по HTTPS
Настроим Ingress через Traefik: путь /editor ведет на Swagger Editor, а корневой / — на Swagger UI. Оба маршрута защищены TLS-сертификатом.
В вашем кластере кубернетис может использоваться другой ingress-контроллер. Необходимо уто учитывать и использовать свои настройки.
Создадим файл:
vi ingress.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: swagger
namespace: default
labels:
app.kubernetes.io/part-of: swagger
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: web,websecure
traefik.ingress.kubernetes.io/router.tls: "true"
traefik.ingress.kubernetes.io/router.tls.certresolver: default
spec:
ingressClassName: traefik
tls:
- hosts:
- swagger.dmosk.ru
rules:
- host: swagger.dmosk.ru
http:
paths:
- path: /editor
pathType: Prefix
backend:
service:
name: swagger
port:
name: editor
- path: /
pathType: Prefix
backend:
service:
name: swagger
port:
name: ui
* замените swagger.dmosk.ru на свой домен — от него зависит, для какого хоста будет выпущен TLS-сертификат.
Service для проксирования портов
Опишем Service, который свяжет порты Ingress с портами контейнеров ui и editor:
vi services.yml
apiVersion: v1
kind: Service
metadata:
name: swagger
namespace: default
labels:
app.kubernetes.io/name: swagger
app.kubernetes.io/part-of: swagger
spec:
type: ClusterIP
selector:
app.kubernetes.io/name: swagger
ports:
- name: ui
port: 80
targetPort: ui
protocol: TCP
- name: editor
port: 8081
targetPort: editor
protocol: TCP
Применение манифестов
Применим все файлы из каталога разом и проверим, что поды запустились:
kubectl apply -f ./
kubectl get pods
Мы должны увидеть один под swagger-xxx в статусе Running — внутри него работают оба контейнера, ui и editor. Swagger развернут и доступен через Ingress.
Просмотр Kubernetes API через Swagger UI
Рассмотрим, как можно применить наш свагер на практике.
Kubernetes API — тоже REST API, и он отдает свою спецификацию через discovery api по пути /openapi/v2 (Swagger 2.0) или /openapi/v3 (OpenAPI 3.0). Для быстрого просмотра поднимем прокси к API-серверу:
kubectl proxy --port=8001
* команда открывает локальный прокси к API-серверу кластера с авторизацией из текущего kubeconfig, но слушает только 127.0.0.1 — доступ есть только с вашей машины. Кластерный под со Swagger UI из предыдущих разделов до него не достучится, они в разных сетевых пространствах.
Для просмотра проще поднять отдельный локальный контейнер Swagger UI в сетевом режиме host — тогда он увидит localhost:8001 напрямую:
docker run --rm --network host -e URL=http://localhost:8001/openapi/v2 swaggerapi/swagger-ui
* режим --network host работает на Linux. На Docker Desktop (macOS/Windows) вместо localhost используем host.docker.internal.
Открываем http://localhost:8080 и получаем Kubernetes API reference: все встроенные ресурсы (pods, deployments, services) и агрегированные через Kubernetes APIService — например, metrics-server, если он установлен в кластере. Это удобная замена ручным запросам вида Kubernetes API curl — тот же результат, но с навигацией и возможностью отправить запрос прямо из браузера.
Решение проблем
Рассмотрим наиболее частые ошибки, с которыми можно столкнуться.
Ошибка сертификата
При попытке открыть страницу свагера по настройному URL-адресу мы видим предупреждение от системы безопасности браузера, что сертификат не проходит проверку подлинности.
Причина: сертификат для домена не выпускается, Ingress остается без TLS.
Решение: проверяем, что A-запись домена указывает на IP кластера, и что порт 80 доступен извне — без него Traefik не пройдет HTTP-01 challenge.
Не запускается pod для swagger
При просмотре статуса Pod видим, что swagger падает в CrashLoopBackOff.
Причина: приложение при запуске сталкивается с критической ошибкой, что приводит к перезапуску контейнера.
Решение: смотрим логи контейнера editor — чаще всего дело в занятом порту 8081 или в неверном значении BASE_URL, не совпадающем с путем в Ingress.
Что учесть для продакшена
Если Swagger UI начнет запрашивать свои статические файлы по абсолютным путям, единый Ingress с путями /editor и / может повести себя нестабильно — для продакшена надежнее развести UI и Editor по разным поддоменам. Также стоит добавить securityContext с runAsNonRoot: true, чтобы контейнеры не работали от root — конкретный UID нужно проверить в документации к используемым образам swagger-ui и swagger-editor.