Деплой Swift на Kubernetes: базовое руководство на практике

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Деплой Swift на Kubernetes: от локальной сборки до production-кластера

Swift — это не только язык для iOS и macOS. Благодаря фреймворкам вроде Vapor и Kitura, Swift всё чаще используется для написания серверных приложений. Но как доставить такое приложение пользователям? Ответ — Kubernetes. В этом руководстве мы разберём, как упаковать Swift-приложение в Docker, настроить CI/CD и развернуть его в кластере K8s. Вы узнаете, какие нюансы есть при сборке Swift под Linux, как оптимизировать образ и как написать правильные манифесты для Kubernetes.

1. Подготовка Swift-приложения для контейнеризации

Первое, с чем сталкивается разработчик — Swift на Linux. Если вы пишете на macOS, вам нужно кросс-компилировать приложение для Linux (amd64/arm64). Рассмотрим пример на базе Vapor 4.

Создадим простое HTTP-приложение:

// Sources/App/routes.swift
import Vapor

func routes(_ app: Application) throws {
    app.get { req async in
        "Hello from Swift on Kubernetes!"
    }
    app.get("health") { req async in
        "OK"
    }
}

Для сборки под Linux используем официальный образ Swift. Создадим Dockerfile с двухэтапной сборкой:

# Первый этап: сборка
FROM swift:5.9-focal as builder
WORKDIR /app
COPY Package.swift Package.resolved ./
RUN swift package resolve
COPY . .
RUN swift build -c release --static-swift-stdlib

# Второй этап: минимальный образ
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y ca-certificates libsqlite3-0 && rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY --from=builder /app/.build/release/Run .
EXPOSE 8080
CMD ["./Run"]

Ключевой момент — флаг --static-swift-stdlib. Он включает статическую линковку стандартной библиотеки Swift, что уменьшает размер образа и упрощает деплой. Без него образ может весить 1+ ГБ.

2. Сборка образа и загрузка в registry

Собираем образ и пушим в Docker Hub (или любой другой registry):

# Сборка
docker build -t myrepo/swift-k8s-demo:1.0.0 .

# Проверка локально
docker run -p 8080:8080 myrepo/swift-k8s-demo:1.0.0
curl http://localhost:8080
# Ответ: Hello from Swift on Kubernetes!

# Пуш в registry
docker push myrepo/swift-k8s-demo:1.0.0

Оптимизация размера: образ на основе ubuntu:22.04 весит ~150 МБ. Если использовать alpine — можно уменьшить до 50 МБ, но придётся решать проблему с glibc (Swift требует её). Рекомендуется использовать официальные образы Ubuntu или Debian.

3. Манифесты Kubernetes для Swift-приложения

Теперь развернём наше приложение в кластере. Создадим Deployment и Service.

deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: swift-app
  labels:
    app: swift-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: swift-app
  template:
    metadata:
      labels:
        app: swift-app
    spec:
      containers:
      - name: swift-app
        image: myrepo/swift-k8s-demo:1.0.0
        ports:
        - containerPort: 8080
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 3
          periodSeconds: 5
        resources:
          requests:
            memory: "64Mi"
            cpu: "100m"
          limits:
            memory: "128Mi"
            cpu: "250m"

service.yaml:

apiVersion: v1
kind: Service
metadata:
  name: swift-app-service
spec:
  selector:
    app: swift-app
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080
  type: ClusterIP

Обратите внимание на probes (пробы). Swift-приложение стартует быстро, но мы добавили initialDelaySeconds: 5 для уверенности. Ресурсы указаны минимальные — Swift-приложение на Vapor потребляет около 30-50 МБ RAM в простое.

Применяем манифесты:

kubectl apply -f deployment.yaml
kubectl apply -f service.yaml

# Проверка
kubectl get pods
kubectl get svc swift-app-service

4. Продвинутые сценарии: Ingress, ConfigMap и масштабирование

Для внешнего доступа добавим Ingress (например, с nginx-ingress):

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: swift-app-ingress
spec:
  rules:
  - host: swift.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: swift-app-service
            port:
              number: 80

Конфигурацию (например, строку подключения к БД) лучше вынести в ConfigMap:

apiVersion: v1
kind: ConfigMap
metadata:
  name: swift-config
data:
  DATABASE_URL: "postgres://user:pass@postgres-service:5432/swiftdb"

В коде Swift используем переменные окружения:

// В configure.swift
if let dbURL = Environment.get("DATABASE_URL") {
    app.databases.use(.postgres(url: dbURL), as: .psql)
}

Масштабирование: для Swift-приложений с Vapor хорошо работает горизонтальное масштабирование. Используйте HPA (Horizontal Pod Autoscaler):

kubectl autoscale deployment swift-app --cpu-percent=50 --min=2 --max=10

Заключение

Мы прошли полный путь от Swift-приложения до работающего сервиса в Kubernetes. Ключевые выводы:

  • Swift на сервере — это реально. Vapor и другие фреймворки позволяют создавать высокопроизводительные API.
  • Статическая сборка — обязательна для уменьшения размера образа и совместимости.
  • Пробы и ресурсы — критичны для стабильной работы в K8s.
  • CI/CD — автоматизируйте сборку

Блоги

Рекомендаций по книгам