Deploying Kotlin on Kubernetes: A Basic Guide for Beginners
\n\nKubernetes (K8s) has become the de facto standard for container orchestration in modern development. If you write in Kotlin, whether it's a Spring Boot backend, a Ktor microservice, or a console application, knowing how to deploy it in a Kubernetes cluster is a critically important skill. In this guide, we will go from a simple Kotlin application to a running pod in a cluster. The material is designed for beginners: no complex topics like Service Mesh or Helm — just the basics.
\n\n1. Preparing a Kotlin Application for Containerization
\n\nBefore thinking about Kubernetes, we need to package our application into a Docker image. Let's look at an example of a simple REST API on Ktor — a lightweight framework ideal for microservices.
\n\nLet's create a build.gradle.kts file with minimal dependencies:
plugins {\n kotlin("jvm") version "1.9.0"\n application\n}\n\napplication {\n mainClass.set("com.example.AppKt")\n}\n\ndependencies {\n implementation("io.ktor:ktor-server-netty:2.3.0")\n implementation("io.ktor:ktor-server-content-negotiation:2.3.0")\n implementation("io.ktor:ktor-serialization-kotlinx-json:2.3.0")\n}\n\nLet's write a simple application that responds to GET requests:
\n\n// src/main/kotlin/com/example/App.kt\npackage com.example\n\nimport io.ktor.server.engine.*\nimport io.ktor.server.netty.*\nimport io.ktor.server.routing.*\nimport io.ktor.server.response.*\nimport io.ktor.http.*\n\nfun main() {\n embeddedServer(Netty, port = 8080) {\n routing {\n get("/") {\n call.respondText("Hello from Kotlin on Kubernetes!", ContentType.Text.Plain)\n }\n }\n }.start(wait = true)\n}\n\nThe application listens on port 8080. This is important to remember — we will use this port in the Dockerfile and manifests.
\n\n2. Creating a Docker Image
\n\nTo build the image, we need a Dockerfile. The best practice is to use a multi-stage build so that the final image is minimal in size.
\n\nFROM gradle:7.6-jdk17 AS build\nWORKDIR /app\nCOPY build.gradle.kts settings.gradle.kts ./\nCOPY src ./src\nRUN gradle build --no-daemon\n\nFROM openjdk:17-jre-slim\nWORKDIR /app\nCOPY --from=build /app/build/libs/*.jar app.jar\nEXPOSE 8080\nENTRYPOINT ["java", "-jar", "app.jar"]\n\nLet's build the image and upload it to a registry (e.g., Docker Hub):
\n\ndocker build -t yourusername/kotlin-k8s-demo:v1 .\ndocker push yourusername/kotlin-k8s-demo:v1\n\nIf you don't have access to a registry, you can use minikube and load the image locally with the command minikube image load.
3. Basic Kubernetes Manifests
\n\nNow let's move on to the most interesting part — writing YAML manifests to deploy the application in a cluster. We will need two basic objects: Deployment (manages pod replicas) and Service (provides access to pods).
3.1 Deployment
\n\nA Deployment describes the desired state of pods: which image to use, how many replicas, which ports to open.
\n\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: kotlin-app\nspec:\n replicas: 2\n selector:\n matchLabels:\n app: kotlin-app\n template:\n metadata:\n labels:\n app: kotlin-app\n spec:\n containers:\n - name: kotlin-app\n image: yourusername/kotlin-k8s-demo:v1\n ports:\n - containerPort: 8080\n resources:\n requests:\n memory: "256Mi"\n cpu: "250m"\n limits:\n memory: "512Mi"\n cpu: "500m"\n livenessProbe:\n httpGet:\n path: /\n port: 8080\n initialDelaySeconds: 10\n periodSeconds: 5\n readinessProbe:\n httpGet:\n