{"id":27627536,"url":"https://github.com/lotharschulz/ktorjib","last_synced_at":"2025-04-23T13:55:08.348Z","repository":{"id":46705478,"uuid":"170760921","full_name":"lotharschulz/ktorjib","owner":"lotharschulz","description":"Continuous Delivery to Kubernetes with Kotlin, Ktor, Gradle, Jib, Skaffold and Kubernetes (EKS)","archived":false,"fork":false,"pushed_at":"2023-05-15T22:00:31.000Z","size":181,"stargazers_count":17,"open_issues_count":0,"forks_count":5,"subscribers_count":3,"default_branch":"main","last_synced_at":"2023-05-15T23:20:51.756Z","etag":null,"topics":["container","docker","eks","jib","kotlin","ktor","kubernetes","minikube"],"latest_commit_sha":null,"homepage":"https://www.lotharschulz.info/2019/10/17/deploy-kotlin-applications-to-kubernetes-without-dockerfiles/","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lotharschulz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-02-14T21:32:01.000Z","updated_at":"2023-05-15T23:20:51.756Z","dependencies_parsed_at":"2023-01-19T22:18:46.324Z","dependency_job_id":null,"html_url":"https://github.com/lotharschulz/ktorjib","commit_stats":null,"previous_names":[],"tags_count":null,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lotharschulz%2Fktorjib","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lotharschulz%2Fktorjib/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lotharschulz%2Fktorjib/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lotharschulz%2Fktorjib/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lotharschulz","download_url":"https://codeload.github.com/lotharschulz/ktorjib/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250444595,"owners_count":21431673,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["container","docker","eks","jib","kotlin","ktor","kubernetes","minikube"],"created_at":"2025-04-23T13:55:06.478Z","updated_at":"2025-04-23T13:55:07.989Z","avatar_url":"https://github.com/lotharschulz.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Continuous Delivery to Kubernetes with [Kotlin](https://kotlinlang.org/), [Ktor](https://github.com/ktorio/ktor), [Gradle](https://gradle.org/), [Jib](https://github.com/GoogleContainerTools/jib#what-is-jib), [Skaffold](https://skaffold.dev/docs/getting-started/#installing-skaffold) and [Kubernetes](https://kubernetes.io/) ([EKS](https://aws.amazon.com/eks/) \u0026 [Minikube](https://kubernetes.io/docs/setup/minikube/))  \n\n## Tech preconditions\n- [Minikube](https://kubernetes.io/docs/tasks/tools/#minikube) (v1.29.0)\n  - ```minikube start```\n- [Kubernetes](https://kubernetes.io/) (v1.24.3 on Docker 20.10.17 on minikube v1.26.1, 1.23.7 on EKS)\n- [Java 17](https://jdk.java.net/17/)\n- [Kotlin](https://kotlinlang.org/) (1.6.21)\n- [Gradle](https://gradle.org/) (v7.3)\n- [Skaffold](https://skaffold.dev/docs/getting-started/#installing-skaffold) (v2.3.0)\n- [Ktor](https://ktor.io/) (2.1.0)\n- [Jib](https://github.com/GoogleContainerTools/jib) (3.3.0)\n  - [Jib Gradle Plugin](https://github.com/GoogleContainerTools/jib/tree/master/jib-gradle-plugin)\n\n## Continuous delivery\n```\nskaffold dev\n```\nother terminal:\n```\n./web-eks.sh # EKS on AWS\n# or\n./web.sh # local minikube\n```\nThe bash script checks the service endpoint for code changes becoming effective. \nThe `web-eks.sh` script assumes kubernetes runs on [EKS](web-eks.sh#L12) and the [web kubernetes service is already deployed](web-eks.sh#L13).\nThe `web.sh` script assumes kubernetes runs on [minikube](web.sh#L9) and the [web kubernetes service is already deployed](web.sh#L10).\n\n### Screencasts\n\n#### Skaffold deployment to [EKS](https://aws.amazon.com/eks/) with [ECR](https://aws.amazon.com/ecr/) ([AWS](https://aws.amazon.com/))\n[![asciicast](https://asciinema.org/a/321763.svg)](https://asciinema.org/a/321763?t=20)\n\n#### Skaffold deployment to Minikube\n[![asciicast](https://asciinema.org/a/vfx729qpylmfdroBTXJmTH2bw.svg)](https://asciinema.org/a/vfx729qpylmfdroBTXJmTH2bw?t=14)\n\n\n## Skaffold deployment to [EKS](https://aws.amazon.com/eks/) with [ECR](https://aws.amazon.com/ecr/) ([AWS](https://aws.amazon.com/))\n\nThe steps below assume an EKS Kubernetes cluster is in place. \nThe canonical way to create an EKS cluster would be [eksctl](https://eksctl.io/usage/creating-and-managing-clusters/): `eksctl create cluster ... `. \nThat is a similar setup as in [ALB INGRESS Controller CrashLoopBackOffs in AWS EKS on FARGATE](https://www.lotharschulz.info/2020/01/29/alb-ingress-controller-crashloopbackoffs-in-aws-eks-on-fargate/).\nThe steps below assume an _ENV_ variable `$CLUSTER_NAME` that holds the Kubernetes cluster name in the terminal session.\n\n1. Define additional ENV variables for later use.\n\n```\nENDPOINT_URL=$(aws eks describe-cluster --name $CLUSTER_NAME --query cluster.endpoint --output text)\necho $ENDPOINT_URL\nCA_CERT=$(aws eks describe-cluster --name $CLUSTER_NAME --query cluster.certificateAuthority.data --output text)\necho $CA_CERT\nAWS_PROFILE=test\necho $AWS_PROFILE\nAWS_REGION=$(aws configure get region)\necho $AWS_REGION\n```\n\n2. Configure `kubectl` with EKS cluster via `KUBECONFIG` ENV variable\n```\nll ~/.kube\n# in case the folder does not exists\nmkdir -p ~/.kube\n```\n\n```\ncat \u003c\u003c KBCFG \u003e ~/.kube/config-${CLUSTER_NAME}\napiVersion: v1\nclusters:\n- cluster:\n    certificate-authority-data: $CA_CERT\n    server: $ENDPOINT_URL\n  name: $CLUSTER_NAME\ncontexts:\n- context:\n    cluster: $CLUSTER_NAME\n    user: $CLUSTER_NAME\n  name: $CLUSTER_NAME\ncurrent-context: $CLUSTER_NAME\nkind: Config\npreferences: {}\nusers:\n- name: $CLUSTER_NAME\n  user:\n    exec:\n      apiVersion: client.authentication.k8s.io/v1alpha1\n      args:\n      - --region\n      - $AWS_REGION\n      - eks\n      - get-token\n      - --cluster-name\n      - $CLUSTER_NAME\n      command: aws\n      env:\n      - name: AWS_PROFILE\n        value: $AWS_PROFILE\nKBCFG\n```\n\n```\nexport KUBECONFIG=$KUBECONFIG:~/.kube/config-${CLUSTER_NAME}\necho $KUBECONFIG\n```\n\n3. ECR login\n\n```\n# assuming aws cli v2 - https://aws.amazon.com/blogs/developer/aws-cli-v2-is-now-generally-available/\naws --version\n\n# ecr login (https://github.com/aws/aws-cli/issues/4962)\necho $(aws ecr get-login-password)|docker login --password-stdin --username AWS https://$(aws sts get-caller-identity --query 'Account' --output text).dkr.ecr.${AWS_REGION}.amazonaws.com\n```\n\n4. ECR repository\n\n```\n# use an existing ECR repository or create one: `aws ecr create-repository --repository-name ... `\nexport ECRREPO_NAME=[ktorjib]\necho $ECRREPO_NAME\nexport ECRREPO_URI=$(aws ecr describe-repositories --repository-names $ECRREPO_NAME --query 'repositories[0].repositoryUri' --output text)\necho $ECRREPO_URI\n```\n\n5. Kube secret to configure docker registry\n\n```\nexport KUBE_SECRET_LABEL=$(aws sts get-caller-identity --query 'Account' --output text)--${AWS_REGION}--${AWS_PROFILE}--ecr--registry--secret\necho $KUBE_SECRET_LABEL\nexport KUBE_SECRET_PASSWORD=$(aws ecr get-authorization-token --output text --query 'authorizationData[0].authorizationToken' | base64 -d | cut -d: -f2)\necho $KUBE_SECRET_PASSWORD\nKUBE_SECRET_EMAIL=[me@you.com]\necho $KUBE_SECRET_EMAIL\n\n# configure kubectl to log into ECR\nkubectl delete secret --ignore-not-found $KUBE_SECRET_LABEL\nkubectl create secret docker-registry $KUBE_SECRET_LABEL \\\n --docker-server=https://${ECRREPO_URI} \\\n --docker-username=AWS \\\n --docker-password=\"${KUBE_SECRET_PASSWORD}\" \\\n --docker-email=\"${KUBE_SECRET_EMAIL}\"\n```\n\n6. Set up kubernetes namespace\n\n```\nexport KTORJIB_K8S_NAMESPACE=ktorjib\necho ${KTORJIB_K8S_NAMESPACE}\nkubectl create namespace ${KTORJIB_K8S_NAMESPACE}\nkubectl get namespaces\n```\n\n7. Skaffold config\n\n```\n# set up skaffold config\ncat \u003c\u003c SKFLDCFG \u003e skaffold.yaml\n# inspired by https://github.com/GoogleContainerTools/skaffold/blob/master/examples/jib-gradle/skaffold.yaml @ 2020 04 19\napiVersion: skaffold/v2beta2\nkind: Config\nbuild:\n  artifacts:\n    #- image: gcr.io/ktor-jib/kjib-image\n    - image: ${ECRREPO_URI}\n      jib: {}\nSKFLDCFG\n\n# optional: copy the skaffold config file for backup\ncp skaffold.yaml skaffold-ecr.yaml_\n```\n\n8. Start skaffold flow \n\n```\nskaffold dev --namespace KTORJIB_K8S_NAMESPACE\n```\n\n_note_: kubernetes namespace can be specified with ENV var `SKAFFOLD_NAMESPACE` or cli parameter `--namespace` \n\n### Links\n- https://github.com/stelligent/skaffold_on_aws\n- https://github.com/aws-samples/aws-microservices-deploy-options/blob/master/skaffold.md\n\n## Skaffold deployment to Minikube\n```\n#mac\nminikube start  --driver=hyperkit --kubernetes-version=1.21.2\n#linux\nminikube start  --driver=docker --kubernetes-version=1.21.2\n\n# start skaffold flow\nskaffold dev\n```\n\n------\n\n### Run application w/o Kubernetes\n\n#### Run application with Jib \u0026 Docker\n```\n./gradlew jibDockerBuild --image=myimagename \u0026\u0026 docker run --rm -p 8080:8080 myimagename\n```\naccess the endpoint:\n```\ncurl http://0.0.0.0:8080\n```\n\n#### Run application with Gradle\n```\n./gradlew run\n```        \naccess the endpoint:\n```\ncurl http://0.0.0.0:8080\n```\n\n### Test application\n```\n./gradlew test\n```\n\n### Clean up with Gradle\n```\n./gradlew clean \u0026\u0026\ndocker stop $(docker ps -aq) \u0026\u0026\ndocker rm $(docker ps -aq) \u0026\u0026\ndocker rmi $(docker images -q)\n```\n\n------\n\n## Troubleshooting\n\n### Java versions\n\n```\nFAILURE: Build failed with an exception\n....\n* What went wrong:\nScript compilation error:\n\n  Line 29: java.sourceCompatibility = JavaVersion.VERSION_13\n                                                  ^ Unresolved reference: VERSION_13\n\n1 error\n```\n\n```\nFAILURE: Build failed with an exception.\n...\n* What went wrong:\nScript compilation error:\n\n  Line 29: java.sourceCompatibility = JavaVersion.VERSION_14\n                                                  ^ Unresolved reference: VERSION_14\n\n1 error\n```\n\n```\n// works:\n...\nJavaVersion.VERSION_12\n...\nimage = \"openjdk:14\"\n\n// but for consistency\n...\nJavaVersion.VERSION_12\n...\nimage = \"openjdk:12\"\n```\n\n------\n\n### Links\n- https://github.com/GoogleContainerTools/jib/search?q=java+14\u0026type=Code\n- https://github.com/GoogleContainerTools/jib/blob/master/jib-core/CHANGELOG.md\n- https://github.com/GoogleContainerTools/jib/issues/2015\n- https://github.com/GoogleContainerTools/jib/pull/2017/files\n- https://github.com/GoogleContainerTools/jib/issues/2015#issuecomment-534168864\n- https://asm.ow2.io/versions.html\n- java 8 or 11 -\u003e https://github.com/GoogleContainerTools/distroless/tree/master/java\n- https://github.com/GoogleContainerTools/distroless/tree/master/java#image-contents\n- https://github.com/GoogleContainerTools/distroless/blob/master/examples/java/Dockerfile\n- https://console.cloud.google.com/gcr/images/distroless/GLOBAL/java?gcrImageListsize=30\u0026gcrImageListsort=-uploaded (version 11)\n\n# Blog posts\n- [Deploy Kotlin Applications to Kubernetes without Dockerfiles on lotharschulz.info](https://www.lotharschulz.info/2019/10/17/deploy-kotlin-applications-to-kubernetes-without-dockerfiles/)\n- [Kotlin Continuous Delivery to Kubernetes on lotharschulz.info](https://www.lotharschulz.info/2019/02/17/Kotlin-Continuous-Delivery-to-Kubernetes/)\n\n# Further reading\n- [Ktor](github.com/ktorio/ktor)\n- [Jib](github.com/GoogleContainerTools/jib)\n- [Skaffold](github.com/GoogleContainerTools/skaffold/)\n- [Jib 1.0.0 is GA—building Java Docker images has never been easier](https://cloud.google.com/blog/products/application-development/jib-1-0-0-is-ga-building-java-docker-images-has-never-been-easier)\n- [What is Jib?](https://github.com/GoogleContainerTools/jib#what-is-jib)\n- [Containerize your Gradle Java project](https://github.com/GoogleContainerTools/jib/tree/master/jib-gradle-plugin)\n- [Containerize a Ktor application with Jib](https://github.com/GoogleContainerTools/jib/tree/master/examples/ktor)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flotharschulz%2Fktorjib","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flotharschulz%2Fktorjib","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flotharschulz%2Fktorjib/lists"}