Code Monkey home page Code Monkey logo

sbt-kubeyml's Introduction

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

sbt-kubeyml's People

Contributors

antoniasymeonidou avatar dragonisle avatar georgeonisiforou2022 avatar ngmms453 avatar scala-steward avatar shadpro avatar vaslabs avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

sbt-kubeyml's Issues

Check if hostname is valid

It would be good if it checked whether the hostname in the ingress is valid first then getting an error later on:

The Ingress "backend" is invalid: spec.rules[0].host: Invalid value: "runner-EcDQy-nU-project-306-concurrent-0": a DNS-1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')

Import

import kubeyml.deployment._ breaks sbt

Add Helm 3 support

Create option to generate helm 3 artifacts instead of kubernetes manifests

Add nodeSelector

To do bulkheading in kubernetes with the core API we'll need to support nodeSelector and tolerations

Update to sbt 1.6

There are a bunch of warnings that fail compilation, fix and release a compatible version

Automate release process

Release everything through github actions, everytime a push to master happens and tests are passing

Default cpu requests to 10%

There's no apparent reason to reserve 500m of cpu by default (in the requests section).

A company running with a 16 node cluster of 4 cores each can deploy about 128 pods with the current defaults.

Anyone that needs the requests cpu to be higher can still do so by giving a different configuration.

Change the default and document in README and microsite

Update ingress api version

From kubernetes version 1.22 networking.k8s.io/v1 will permanently replace networking.k8s.io/v1betav1

Task: we set networking.k8s.io/v1 as the default and networking.k8s.io/v1betav1 as the legacy, dropping support for the external old one

Allow modification of the deployment using the API

If every parameter becomes an sbt key, everything will become bloated.
At some point we need to stop adding sbt keys and allow the users to modify the Deployment via the api.

Possibly an sbt key that exposes the deployment object

Starting from clean issue

[error] java.io.FileNotFoundException: /builds/eng/facebook-review-app/backend/service/target/kubeyml/deployment.yml (No such file or directory)

Generate service

Give a command to generate the yml for the service definition

Add support for config map

In deployment:

envFrom:
            - configMapRef:
                name: <service name>
- secretRef:
                name:  <service name>

Config map ref name should also be configurable

Plugin to configure Akka cluster

  • Generate the needed roles for the namespace
  • add Akka management ports to the deployment
  • choice is available via additional plugin

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.