Creating a fast Kubernetes Development Workflow

Creating a fast Kubernetes Development Workflow

Kubernetes is very powerful in orchestrating where your services are running, but building docker images, writing and updating all the necessary YAML files and applying them to your cluster can still become an annoying maintenance overhead.
In this talk you will learn how to create a fast, low friction development workflow with Kubernetes and tools like Telepresence and Forge which enables you to quickly and safely build, test and deploy your services.

8e82eb7e128a14a16d642ae55227339b?s=128

Bastian Hofmann

October 19, 2018
Tweet

Transcript

  1. @BastianHofmann Creating a fast Kubernetes Development Workflow Bastian Hofmann

  2. None
  3. Container orchestration platform

  4. Deploy, run and scale your services in isolated containers

  5. Very Powerful

  6. Large community

  7. Lot’s of large company backers

  8. No vendor lock in

  9. Runs on

  10. Your laptop

  11. Included in Docker Desktop Clients

  12. Bare metal

  13. Cloud Providers

  14. AWS

  15. Azure

  16. Google Cloud Platform

  17. And if you don't want to install and maintain Kubernetes

    yourself
  18. Managed Kubernetes

  19. Google GKE

  20. Amazon EKS

  21. SysEleven MetaKube

  22. Easy upgrades

  23. Easy scaling

  24. Load Balancing

  25. Distributed Persistent Storage

  26. Backups

  27. Premium support

  28. We monitor you cluster, ensure it's working and tell you

    if something is wrong
  29. German company with German datacenters

  30. You can focus on what is important

  31. But this talk is about how to use Kubernetes

  32. Not only for production workloads

  33. But in your development workflows

  34. Kubernetes has standardized apis

  35. More and more integrations

  36. Great tools

  37. Agenda

  38. Introduction to Kubernetes

  39. Deployment of a simple application

  40. Deployment of a micro-service application

  41. Some tools for development with Kubernetes

  42. But first

  43. Why containers?

  44. Services run in isolation

  45. Everything needed to run a service in one image

  46. Decouple Ops and Dev

  47. Make things …

  48. Easier to deploy

  49. Easier to upgrade system dependencies

  50. Easier to scale

  51. Easier to develop

  52. Kubernetes helps you deploying containers

  53. Kubernetes helps you running containers

  54. Kubernetes helps you scaling containers

  55. Let’s define some core concepts and terminology first

  56. Kubernetes Cluster

  57. • A docker image built from a Dockerfile that contains

    everything a service needs to run Image
  58. • A container runs a docker image. • Only 1

    process can run inside of a container Container
  59. • A group of 1 or more containers • Same

    port space • Ports are not accessible from outside of the pod Pod
  60. • Defines and manages how many instances of a pod

    should run Replica Set
  61. • Manages updates and rollbacks of replica sets Deployment

  62. • Makes a port of a pod accessible to other

    pods Service
  63. • Makes a service accessible to the outside of Kubernetes

    Ingress
  64. Volumes, ConfigMaps, Secrets, PersistentVolumeClaims, CronJobs, StatefulSets, ...

  65. Everything is a resource

  66. You interact with Kubernetes by creating, receiving, updating and deleting

    resources
  67. Kubernetes has controllers to listen on these interactions and get

    the cluster in the desired state
  68. kind: Deployment apiVersion: extensions/v1beta1 metadata: name: symfony-demo spec: template: spec:

    containers: - name: symfony-demo image: symfony-demo:1.1.0 ports: - containerPort: 80
  69. $ kubectl create -f deployment.yaml

  70. $ kubectl get deployments NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE

    symfony-demo 1 1 1 1 21h
  71. $ kubectl get deployment symfony-demo -o yaml apiVersion: extensions/v1beta1 kind:

    Deployment metadata: annotations: ... spec: ... template: ... spec: containers: - name: symfony-demo image: symfony-demo:1.1.0
  72. $ kubectl delete deployment symfony-demo

  73. Practical example

  74. Preparations

  75. We need a cluster

  76. None
  77. None
  78. None
  79. Let’s deploy the symfony demo app

  80. https:/ /github.com/symfony/demo

  81. Demo

  82. Dockerfile

  83. Copy our code

  84. Build the project

  85. Composer install

  86. yarn install

  87. yarn run build

  88. https:/ /docs.docker.com/develop/develop- images/multistage-build/

  89. Build the image

  90. docker build -t symfony-demo:2.0.0 .

  91. Now we have to tell Kubernetes what to do with

    the image
  92. Resources are defined in YAML or JSON

  93. Deployment

  94. kind: Deployment apiVersion: extensions/v1beta1 metadata: name: symfony-demo spec: template: metadata:

    labels: app: symfony-demo spec: containers: - name: symfony-demo image: symfony-demo:1.0.0 ports:
  95. containers: - name: symfony-demo image: symfony-demo:1.0.0 ports: - containerPort: 80

    livenessProbe: httpGet: path: / port: 80 timeoutSeconds: 1 initialDelaySeconds: 10 readinessProbe: httpGet: path: /
  96. Many more options configurable

  97. Many more options • Setting environment variables • Mounting volumes

    • Requesting resources • Defining upgrade strategies • Defining command • Configure networking • Configure the scheduler • Listen on lifecycle events • Configure system capabilities for the container • …
  98. Service

  99. kind: Service apiVersion: v1 metadata: name: symfony-demo spec: ports: -

    name: http port: 80 targetPort: 80 protocol: TCP selector: app: symfony-demo
  100. Ingress

  101. kind: Ingress apiVersion: extensions/v1beta1 metadata: name: symfony-demo spec: rules: -

    host: symfony-demo.local.k8s http: paths: - path: / backend: serviceName: symfony-demo servicePort: 80
  102. Creating everything

  103. kubectl apply -f deployment/webapp.yaml

  104. None
  105. Rolling Deployments

  106. kind: Deployment apiVersion: extensions/v1beta1 metadata: name: symfony-demo spec: template: spec:

    containers: - name: symfony-demo image: symfony-demo:1.1.0 ports: - containerPort: 80
  107. kubectl apply -f deployment/webapp.yaml

  108. Writing this YAML files is tedious

  109. YAML files are tied to a specific version and a

    specific environment
  110. Production

  111. Staging

  112. Development

  113. Per Development team

  114. Per branch

  115. Per developer

  116. Built-in

  117. Namespaces

  118. Still we'd need to maintain multiple very similar YAML files

    with slightly different versions and configuration.
  119. "Templating"

  120. Great tools because of standardized Kubernetes API

  121. Helm

  122. None
  123. Allows to install applications

  124. So called "charts"

  125. Writing your own charts if fairly easy

  126. Charts can depend on other charts

  127. Multiple deployments of one chart possible

  128. Different namespaces

  129. Different release names

  130. Configuration over values

  131. None
  132. Different versions

  133. Different ingress urls

  134. $ helm install stable/wordpress --namespace bastian --name my-wordpress --values dev.yaml

    --values bastian.yaml
  135. Still:

  136. Make a code change

  137. Build docker image

  138. Push docker image

  139. Run helm install/upgrade with new image version

  140. Can this be quicker?

  141. Forge

  142. None
  143. Similar templating to helm

  144. Services can depend on other services

  145. $ forge deploy

  146. Supports different profiles

  147. $ forge --profile staging deploy

  148. $ forge --profile bastian deploy

  149. Different profiles can deploy to different namespaces with different ingress

    hostnames
  150. Default profile can be dependent on the branch you are

    building from
  151. You can use the branch name in templates

  152. Demo application

  153. web quote-svc hello-svc

  154. Not all services have an ingress

  155. Accessing Kubernetes from the outside

  156. web quote-svc hello-svc

  157. Getting a shell in a running container

  158. $ kubectl exec $POD_NAME -i -t -- /bin/bash

  159. Port forwarding through kubectl

  160. $ kubectl port-forward pod/$POD_NAME 8080:80

  161. $ kubectl port-forward service/$SERVICE_NAME 8080:80

  162. Still, if you make a code change you have to

    commit, push, build, deploy
  163. Takes some time

  164. What about step debugging?

  165. Of course you can run everything locally

  166. But you develop only on one service

  167. There may be lots of services

  168. Telepresence

  169. None
  170. Creates a two-way proxy between the Kubernetes cluster and you

  171. $ telepresence T: Starting proxy with method 'vpn-tcp'... @fhgbvx65xg|bash-3.2$ curl

    http://quote-svc/quote | jq '.' [ { "ID": 503, "title": "stefan sagmeister", "content": "<p>...</p>\n", "link": "https://quotesondesign.com/stefan- sagmeister-2/" } ]
  172. Swap a running deployment in the cluster with a local

    process
  173. ... or a locally running docker container

  174. $ telepresence --swap-deployment quote-svc --namespace dev-flow-demo --expose 3000 --run npm

    run debug T: Starting proxy with method 'vpn-tcp',... T: Forwarding remote port 3000 to local port 3000.... > quote-svc@1.0.0 debug /Users/bhofmann/forge_test/quote- svc > nodemon --inspect quote-svc.js [nodemon] watching: *.* [nodemon] starting `node --inspect quote-svc.js` Debugger listening on ws://127.0.0.1:9229/83aa27ac- d879-4b50-a228-440354cca791 quote svc listening on port 3000!
  175. Demo

  176. Summary

  177. Powerful

  178. Helpful

  179. Great tooling because of common APIs

  180. Especially great if you have multiple services and don't want

    to run everything locally
  181. http:/ /speakerdeck.com/ u/bastianhofmann

  182. mail@bastianhofmann.de https:/ /twitter.com/BastianHofmann