$30 off During Our Annual Pro Sale. View Details »

Should Kubernetes have a DSL for configuration?

Should Kubernetes have a DSL for configuration?

Slides used for the introduction to my Birds of a Feather session at KubeCon EU in Berlin. A discussion of various approaches to using programming languages to configure Kubernetes rather than writing the raw data.

Gareth Rushgrove

March 30, 2017
Tweet

More Decks by Gareth Rushgrove

Other Decks in Technology

Transcript

  1. (without introducing more risk)
    Should Kubernetes
    have a DSL?
    Puppet
    Gareth Rushgrove
    Alternative configuration options for K8

    View Slide

  2. (without introducing more risk)
    @garethr

    View Slide

  3. (without introducing more risk)
    Gareth Rushgrove

    View Slide

  4. (without introducing more risk)
    What we’ll cover
    This session

    View Slide

  5. - Setting the scene
    - Open discussion
    - Summary
    Gareth Rushgrove

    View Slide

  6. (without introducing more risk)
    The argument
    Why not (only) YAML

    View Slide

  7. Gareth Rushgrove
    Brian Grant, Google, Kubernetes Config SIG
    “We've had a few complaints that YAML is
    ugly, error prone, hard to read, etc. Are
    there any other alternatives we might want
    to support?

    View Slide

  8. Gareth Rushgrove

    View Slide

  9. (without introducing more risk)
    Gareth Rushgrove
    API wire format as user interface
    template:
    metadata:
    labels:
    app: guestbook
    tier: frontend
    spec:
    containers:
    - name: php-redis
    image: gcr.io/google_samples/gb-frontend:v4
    resources:
    requests:
    cpu: 100m
    memory: 100Mi
    env:

    View Slide

  10. The language to represent the data should
    be a simple, data-only format such as JSON
    or YAML, and programmatic modification of
    this data should be done in a real
    programming language
    Gareth Rushgrove
    Borg, Omega, and Kubernetes, ACM Queue, Volume 14, issue 1 http://queue.acm.org/detail.cfm?id=2898444

    View Slide

  11. The reality is probably closer to most people
    hand writing YAML files
    Gareth Rushgrove

    View Slide

  12. Code allows us to
    - Avoid repetition
    - Combine external inputs
    - Enforce correctness
    - Introduce abstractions
    Gareth Rushgrove

    View Slide

  13. (without introducing more risk)
    Configuration language for JSON data
    Jsonnet

    View Slide

  14. (without introducing more risk)
    jsonnet.org

    View Slide

  15. (without introducing more risk)
    kubernetes examples

    View Slide

  16. (without introducing more risk)
    kubecfg

    View Slide

  17. (without introducing more risk)
    Gareth Rushgrove
    Jsonnet template
    $ cat squid.jsonnet
    local squid = {
    namespace:: "squid",
    squid_service: kube.Service("proxy") {
    metadata+: { namespace: $.namespace },
    target_pod: $.squid.spec.template,
    port: 80,
    },
    squid_data: kube.PersistentVolumeClaim("proxy") {
    metadata+: { namespace: $.namespace },

    View Slide

  18. (without introducing more risk)
    A REPL for Kubernetes
    Kubeplay

    View Slide

  19. (without introducing more risk)
    errordeveloper/kubeplay

    View Slide

  20. (without introducing more risk)
    Gareth Rushgrove
    A REPL for Kubernetes
    $ ./kubeplay
    kubeplay (namespace="*")> pods # list pods in the cluster

    kubeplay (namespace="*")> @pod = _.any # pick a random pod from the list
    kubeplay (namespace="*")> puts @pod.to_json # output the pod definition
    {
    "metadata": {
    ...
    },
    "spec": {
    ...
    "containers": [
    {

    View Slide

  21. (without introducing more risk)
    Gareth Rushgrove
    Ruby based DSL
    @metadata = replicasets("*/").to_ruby.items.map do |k,v|
    v.metadata
    end
    @metadata.each do |i|
    puts "Name:\t#{i.name}"
    puts "Labels:\t#{i.labels}"
    puts
    end

    View Slide

  22. (without introducing more risk)
    Declarative Domain Specific Language
    Puppet

    View Slide

  23. (without introducing more risk)
    garethr/garethr-kubernetes

    View Slide

  24. (without introducing more risk)
    Gareth Rushgrove
    Puppet DSL
    kubernetes_pod { 'sample-pod':
    ensure => present,
    metadata => {
    namespace => 'default',
    },
    spec => {
    containers => [{
    name => 'container-name',
    image => 'nginx',
    }]
    },
    }

    View Slide

  25. (without introducing more risk)
    More Domain Specific Language
    Terraform

    View Slide

  26. (without introducing more risk)
    maxmanuylov/terraform-provider-kubernetes

    View Slide

  27. (without introducing more risk)
    Gareth Rushgrove
    Terraform provider
    resource "kubernetes_resource" "mypod" {
    # Required, must link on the corresponding "kubernetes_cluster" data s
    cluster = "${data.kubernetes_cluster.main.cluster}"
    collection = "pods"
    name = "mypod"
    labels {
    a = "b"
    }
    }

    View Slide

  28. (without introducing more risk)
    A compiled typed JVM language for config
    Kotlin DSL

    View Slide

  29. (without introducing more risk)
    k8-kotlin-dsl

    View Slide

  30. (without introducing more risk)
    Gareth Rushgrove
    Ingress in Kotlin
    import com.fkorotkov.kubernetes.*
    import io.fabric8.kubernetes.api.model.IntOrString
    import io.fabric8.kubernetes.client.DefaultKubernetesClient
    fun main(args: Array) {
    val client = DefaultKubernetesClient().inNamespace("default")
    client.extensions().ingresses().createOrReplace(
    ingress {
    metadata {
    name = "example-ingress"
    }
    spec {
    backend {

    View Slide

  31. (without introducing more risk)
    A scala language for kubernetes config
    Skuber

    View Slide

  32. (without introducing more risk)
    Skuber

    View Slide

  33. (without introducing more risk)
    Gareth Rushgrove
    RC in Scala
    import skuber._
    import skuber.json.format._
    val nginxSelector = Map("app" -> "nginx")
    val nginxContainer = Container("nginx",image="nginx").exposePort(80)
    val nginxController=
    ReplicationController("nginx",nginxContainer,nginxSelector)
    .withReplicas(5)
    val nginxService = Service("nginx")
    .withSelector(nginxSelector)
    .exposeOnNodePort(30001 -> 80)
    import scala.concurrent.ExecutionContext.Implicits.global

    View Slide

  34. (without introducing more risk)
    Useful parts of potential solutions
    Notable mentions

    View Slide

  35. (without introducing more risk)
    JSON Schema

    View Slide

  36. (without introducing more risk)
    Open API/Swagger

    View Slide

  37. (without introducing more risk)
    Discussion
    And thanks for listening

    View Slide