Деплой Kotlin на Kubernetes: базовое руководство для начинающих
Kubernetes (K8s) стал стандартом де-факто для оркестрации контейнеров в современной разработке. Если вы пишете на Kotlin, будь то бэкенд на Spring Boot, микросервис на Ktor или консольное приложение, умение разворачивать его в кластере Kubernetes — критически важный навык. В этом руководстве мы пройдем путь от простого Kotlin-приложения до работающего пода в кластере. Материал рассчитан на начинающих: никаких сложных тем вроде Service Mesh или Helm — только база.
1. Подготовка Kotlin-приложения к контейнеризации
Прежде чем думать о Kubernetes, нужно упаковать наше приложение в Docker-образ. Рассмотрим пример простого REST API на Ktor — легковесного фреймворка, идеально подходящего для микросервисов.
Создадим файл build.gradle.kts с минимальными зависимостями:
plugins {
kotlin("jvm") version "1.9.0"
application
}
application {
mainClass.set("com.example.AppKt")
}
dependencies {
implementation("io.ktor:ktor-server-netty:2.3.0")
implementation("io.ktor:ktor-server-content-negotiation:2.3.0")
implementation("io.ktor:ktor-serialization-kotlinx-json:2.3.0")
}
Напишем простое приложение, которое отвечает на GET-запросы:
// src/main/kotlin/com/example/App.kt
package com.example
import io.ktor.server.engine.*
import io.ktor.server.netty.*
import io.ktor.server.routing.*
import io.ktor.server.response.*
import io.ktor.http.*
fun main() {
embeddedServer(Netty, port = 8080) {
routing {
get("/") {
call.respondText("Hello from Kotlin on Kubernetes!", ContentType.Text.Plain)
}
}
}.start(wait = true)
}
Приложение слушает порт 8080. Это важно запомнить — мы будем использовать этот порт в Dockerfile и манифестах.
2. Создание Docker-образа
Для сборки образа нам понадобится Dockerfile. Лучшая практика — использовать multi-stage сборку, чтобы итоговый образ был минимальным по размеру.
FROM gradle:7.6-jdk17 AS build
WORKDIR /app
COPY build.gradle.kts settings.gradle.kts ./
COPY src ./src
RUN gradle build --no-daemon
FROM openjdk:17-jre-slim
WORKDIR /app
COPY --from=build /app/build/libs/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
Соберем образ и загрузим его в реестр (например, Docker Hub):
docker build -t yourusername/kotlin-k8s-demo:v1 .
docker push yourusername/kotlin-k8s-demo:v1
Если у вас нет доступа к реестру, можно использовать minikube и загрузить образ локально командой minikube image load.
3. Основные манифесты Kubernetes
Теперь перейдем к самому интересному — написанию YAML-манифестов для развертывания приложения в кластере. Нам понадобятся два базовых объекта: Deployment (управляет репликами подов) и Service (обеспечивает доступ к подам).
3.1 Deployment
Deployment описывает желаемое состояние подов: какой образ использовать, сколько реплик, какие порты открывать.
apiVersion: apps/v1
kind: Deployment
metadata:
name: kotlin-app
spec:
replicas: 2
selector:
matchLabels:
app: kotlin-app
template:
metadata:
labels:
app: kotlin-app
spec:
containers:
- name: kotlin-app
image: yourusername/kotlin-k8s-demo:v1
ports:
- containerPort: 8080
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
readinessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 5
periodSeconds: 3
Обратите внимание на два важных блока:
- Resources — запросы и лимиты по CPU и памяти. Без них Kubernetes может «переполнить» ноду.
- Probes — проверки здоровья.
livenessProbeперезапускает под, если приложение зависло, аreadinessProbeотключает трафик от неподготовленного пода.
3.2 Service
Чтобы к нашему приложению можно было обратиться изнутри кластера или извне, создадим Service типа LoadBalancer (для облачных провайдеров) или NodePort (для локального тестирования).
apiVersion: v1
kind: Service
metadata:
name: kotlin-service
spec:
selector:
app: kotlin-app
ports:
- protocol: TCP
port: 80
targetPort: 8080
type: LoadBalancer
Service перенаправляет трафик с порта 80 (внешний) на порт 8080 (внутренний порт пода).
4. Запуск и проверка
Применим оба манифеста к кластеру:
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
Проверим статус подов:
kubectl get pods
Если все хорошо, вы увидите два пода в статусе Running. Проверим сервис:
kubectl get svc kotlin-service
Для локального кластера (Minikube) получите доступ к приложению:
minikube service kotlin-service
Откроется браузер, и вы увидите наше приветствие: Hello from Kotlin on Kubernetes!.
Попробуйте изменить количество реплик в манифесте (replicas: 3) и повторно применить kubectl apply -f deployment.yaml. Kubernetes автоматически создаст новый под — это и есть масштабирование на практике.
5. Полезные советы для начинающих
- Используйте Namespace: для изоляции разных сред (dev,