Deploying Kotlin on Kubernetes: A Basic Guide
Modern development is unthinkable without containerization and orchestration. Kubernetes (K8s) has become the standard for managing microservices, and Kotlin is one of the most popular languages for building reliable backend applications. In this guide, we will walk through the journey from a simple Kotlin application to its full deployment in a Kubernetes cluster. You will learn how to package code into a Docker image, write manifests, and configure access to the service.
1. Preparing the Kotlin Application
For this example, we will use a simple REST API built with Ktor — a lightweight framework for Kotlin. Let's create a file Main.kt:
import io.ktor.server.engine.*import io.ktor.server.netty.*import io.ktor.server.routing.*import io.ktor.http.*import io.ktor.server.response.*
fun main() { embeddedServer(Netty, port = 8080) { routing { get("/") { call.respondText("Hello from Kotlin on K8s!", ContentType.Text.Plain) } get("/health") { call.respondText("OK", ContentType.Text.Plain) } } }.start(wait = true)}This code starts a server on port 8080 with two endpoints: a root endpoint and a health check. Make sure that the Ktor and Netty dependencies are included in build.gradle.kts.
2. Building the Docker Image
For deployment in Kubernetes, the application must be packaged into a container. Let's create a Dockerfile in the project root:
FROM gradle:8.5-jdk21 AS buildWORKDIR /appCOPY build.gradle.kts settings.gradle.kts ./COPY src ./srcRUN gradle build --no-daemon
FROM openjdk:21-jdk-slimWORKDIR /appCOPY --from=build /app/build/libs/*.jar app.jarEXPOSE 8080ENTRYPOINT ["java", "-jar", "app.jar"]The build is done in two stages: first, compilation using Gradle, then copying the JAR file into a clean image. Build the image with the command:
docker build -t my-kotlin-app:1.0 .To publish to a registry (e.g., Docker Hub), run:
docker tag my-kotlin-app:1.0 yourusername/my-kotlin-app:1.0docker push yourusername/my-kotlin-app:1.03. Kubernetes Manifests
Now let's create YAML files for deployment in the cluster. Start with deployment.yaml:
apiVersion: apps/v1kind: Deploymentmetadata: name: kotlin-appspec: replicas: 2 selector: matchLabels: app: kotlin-app template: metadata: labels: app: kotlin-app spec: containers: - name: kotlin-app image: yourusername/my-kotlin-app:1.0 ports: - containerPort: 8080 livenessProbe: httpGet: path: /health port: 8080 initialDelaySeconds: 5 periodSeconds: 10 readinessProbe: httpGet: path: /health port: 8080 initialDelaySeconds: 3 periodSeconds: 5This manifest creates two replicas of the application and adds liveness and readiness probes. Next, service.yaml:
apiVersion: v1kind: Servicemetadata: name: kotlin-app-svcspec: selector: app: kotlin-app ports: - port: 80 targetPort: 8080 type: ClusterIPThe service routes traffic from port 80 to port 8080 of the container. If external access is needed, change the type to NodePort or LoadBalancer.
4. Configuring Ingress and Deployment
For routing requests from outside, use an Ingress controller. Create ingress.yaml:
apiVersion: networking.k8s.io/v1kind: Ingressmetadata: name: kotlin-app-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: /spec: rules: - host: kotlin.example.com http: