Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

vaslabs/sbt-kubeyml

Repository files navigation

sbt-kubeyml

Codacy Badge Maven Central Scala Steward badge

Sbt kubeyml logo

An sbt plugin to generate typesafe kubernetes deployment plans for scala projects

Deployment plugin

Add the plugin to your plugins.sbt

addSbtPlugin("org.vaslabs.kube" % "sbt-kubeyml" % "0.4.1")

Add the plugin in your project and enable it

enablePlugins(KubeDeploymentPlugin)

The plugin depends on DockerPlugin from sbt-native-packager

enablePlugins(DockerPlugin)

Try to run

kubeyml:gen

Properties

sbt key description default
namespace The kubernetes namespace of the deployment Default value is project name
application The name of the deployment Default value is project name
dockerImage The docker image to deploy in a single container Default is the picked from sbt-native-packager
ports List of container ports optionally tagged with name dockerExposedPorts from docker plugin
livenessProbe Healthcheck probe HttpProbe(HttpGet("/health", 8080, List.empty), 0 seconds, 1 second, 10 seconds, 3, 1)
readinessProbe Probe to check when deployment is ready to receive traffic livenessProbe
annotations Map[String, String] for spec template annotations (e.g. aws roles) empty
replicas the number of replicas to be deployed 2
imagePullPolicy Image pull policy for kubernetes, set to IfNotPresent or Always IfNotPresent
command Command for the container empty
args arguments for the command empty Seq
envs Map of environment variables, raw, field path or secret are supported empty
resourceRequests Resource requests (cpu in the form of m, memory in the form of MiB Resource(Cpu(100), Memory(256))
resourceLimits Resource limits (cpu in the form of m, memory in the form of MiB Resource(Cpu(1000), Memory(512))
target The directory to output the deployment.yml target in ThisProject / kubeyml
deployment The key to access the whole Deployment definition, exposed for further customisation Instance with above defaults
persistentVolumes Persistent volumes that should be used by deployment pods empty Seq

Recipes

Single namespace, two types of deployments with secret and dependency

import kubeyml.deployment._
import kubeyml.deployment.api._
import kubeyml.deployment.plugin.Keys._
lazy val deploymentName = sys.env.getOrElse("DEPLOYMENT_NAME", "myservice-test")
lazy val secretsName = sys.env.getOrElse("SECRETS_NAME", "myservice-test-secrets")
lazy val serviceDependencyConnection = sys.env.getOrElse("MY_DEPENDENCY", "https://localhost:8080")
lazy val deploymentSettings = Seq(
 kube / namespace := "my-namespace", //default is ThisProject / name 
 kube / application := deploymentName, //default is ThisProject / name
 kube / command := Some("webserver"),
 kube / args := Seq("-c","/path/to/config"),
 kube / envs := Map(
 EnvName("JAVA_OPTS") -> EnvRawValue("-Xms256M -Xmx2048M"),
 EnvName("MY_DEPENDENCY_SERVICE") -> EnvRawValue(serviceDependencyConnection),
 EnvName("MY_SECRET_TOKEN") -> EnvSecretValue(name = secretsName, key = "my-token")
 ),
 kube / resourceLimits := Resource(Cpu.fromCores(2), Memory(2048+512)),
 kube / resourceRequests := Resource(Cpu(500), Memory(512)),
 //if you want you can use something like the below to modify any part of the deployment by hand
 kube / deployment := (kube / deployment).value.pullDockerImage(IfNotPresent)
)

Gitlab CI/CD usage (followup from previous)

stages:
 - publish-image
 - deploy
.publish-template:
 stage: publish-image
 script:
 - sbt docker:publish
 - sbt kubeyml:gen
 artifacts:
 untracked: false
 paths:
 - target/kubeyml/deployment.yml
.deploy-template:
 stage: deploy
 image: docker-image-that-has-your-kubectl-config
 script:
 - kubectl apply -f target/kubeyml/deployment.yml
publish-test:
 before_script:
 export MY_DEPENDENCY=${MY_TEST_DEPENDENCY}
 extends: .publish-template
deploy-test:
 extends: .deploy-template
 dependencies:
 - publish-test
publish-prod:
 before_script:
 - export MY_DEPENDENCY=${MY_PROD_DEPENDENCY}
 - export SECRETS_NAME=${MY_PROD_SECRET_NAME}
 - export DEPLOYMENT_NAME=my-service-prod
 extends: .publish-template
deploy-prod:
 extends: .deploy-template
 dependencies:
 - publish-prod

Service plugin

This plugin depends on the deployment plugin and every property is derived from that.

There's some room for customisation.

enablePlugins(KubeServicePlugin)

Then your gitlab publish template will look like (example extended from above)

.publish-template:
 stage: publish-image
 script:
 - sbt docker:publish
 - sbt kubeyml:gen
 artifacts:
 untracked: false
 paths:
 - target/kubeyml/deployment.yml
 - target/kubeyml/service.yml

And deploy with

.deploy-template:
 stage: deploy
 image: docker-image-that-has-your-kubectl-config
 script:
 - kubectl apply -f target/kubeyml/deployment.yml 
 - kubectl apply -f target/kubeyml/service.yml

Properties

sbt key description default
portMappings Port mappings against the deployment (service to pod) Derived from deployment
service Key configuration for modifying the service properties Derived from deployment

Ingress Plugin

This plugin depends on the service plugin. It provides some safety nets to make sure the service name and service ports are mapped properly to the ingress configuration.

To extend on the above, you can configure ingress generation with the following steps.

  1. Enable the plugin
enablePlugins(KubeIngressPlugin)
  1. Set an ingress name and a hostname
lazy val ingressEnvName = sys.env.getOrElse("HELLO_INGRESS_NAME", "helloworld-ingress-test")
lazy val hostName = sys.env.getOrElse("YOUR_HOST_NAME", "your-hostname.yourdomain.smth")
  1. Configure the plugin
 import kubeyml.protocol.{NonEmptyString, Host}
 import kubeyml.deployment.plugin.Keys._
 import kubeyml.ingress.api._
 import kubeyml.ingress.plugin.Keys._
 import kubeyml.service.plugin.Keys._
 import kubeyml.ingress.{HttpRule, ServiceMapping, Path => IngressPath}
 
 val ingressSettings = Seq(
 (kube / ingressName) := ingressEnvName,
 (kube / ingressRules) := List(
 HttpRule(Host(hostName), List(
 IngressPath(ServiceMapping((kube / service).value.name, 8085), "/hello-world")
 ))
 ),
 (kube / ingressAnnotations) := Map(
 Annotate.nginxIngress(), // this adds kubernetes.io/ingress.class: nginx
 Annotate.nginxRewriteTarget("/hello-world"), //this adds nginx.ingress.kubernetes.io/rewrite-target: /hello-world
 NonEmptyString("your-own-annotation-key") -> "value"
 )
 )

The command to generate the ingress is the same kubeyml:gen which will generate 3 yml files.

Gitlab CI extension

Potentially the CI configuration evolves to

.publish-template:
 stage: publish-image
 script:
 - sbt docker:publish
 - sbt kubeyml:gen
 artifacts:
 untracked: false
 paths:
 - target/kubeyml/deployment.yml
 - target/kubeyml/service.yml
 - target/kubeyml/ingress.yml
.deploy-template:
 stage: deploy
 image: docker-image-that-has-your-kubectl-config
 script:
 - kubectl apply -f target/kubeyml/deployment.yml
 - kubectl apply -f target/kubeyml/service.yml
 - kubectl apply -f target/kubeyml/ingress.yml

Properties

sbt key description default
ingressRules A list of Rules (currently only supports HttpRule N/A
ingressName The name of the ingress The application name from deployment
ingress Key configuration for modifying the ingress properties Some values are derived from service

AltStyle によって変換されたページ (->オリジナル) /