Upgrade to Pro — share decks privately, control downloads, hide ads and more …

An Introduction To Kubernetes ☸

An Introduction To Kubernetes ☸

My talk from EuroPython 2021

Cd7648c536b4dbe940246b74044fbc52?s=128

Markus H

July 28, 2021
Tweet

Transcript

  1. @m_holtermann An Introduction To Kubernetes

  2. @m_holtermann What is Kubernetes?

  3. @m_holtermann Hi, I’m Markus Holtermann

  4. @m_holtermann Hi, I’m Markus Holtermann W e're hiring

  5. @m_holtermann A system to run containers

  6. @m_holtermann An API server you interact with using kubectl

  7. @m_holtermann Eventually consistent

  8. @m_holtermann @m_holtermann Cluster

  9. @m_holtermann @m_holtermann Cluster Node 1 Node 2 Node 3

  10. @m_holtermann @m_holtermann Cluster Node 1 Node 2 Node 3 Pod

    Pod Pod Pod Pod Pod Pod Pod Pod Pod Pod Pod Pod
  11. @m_holtermann @m_holtermann Cluster Node 1 Node 2 Node 3 Pod

    Pod Pod Pod Pod Pod Pod Pod Pod Pod Pod Pod Pod
  12. @m_holtermann @m_holtermann Cluster Node 1 Node 2 Node 3 Pod

    Container Pod Container Container Pod Container Pod Container Pod Container Pod Container Pod Container Container Pod Container Container Pod Container Container Pod Container Container Pod Container Pod Container Pod Container
  13. @m_holtermann Concepts

  14. @m_holtermann Everything is a resource

  15. @m_holtermann Key attributes: kind, apiVersion, meta, spec

  16. @m_holtermann cluster-scoped or namespace-scoped

  17. @m_holtermann Building Blocks https://kubernetes.io/docs/reference/kubernetes-api/

  18. @m_holtermann Namespaces

  19. @m_holtermann @m_holtermann apiVersion: v1 kind: Namespace metadata: name: myapp $

    kubectl get namespaces NAME STATUS AGE default Active 32d kube-system Active 32d $ kubectl apply -f k8s-namespace.yaml namespace/myapp created $ kubectl get namespaces NAME STATUS AGE default Active 32d kube-system Active 32d myapp Active 5s
  20. @m_holtermann Pods

  21. @m_holtermann @m_holtermann apiVersion: v1 kind: Pod metadata: name: whoami namespace:

    myapp labels: app.kubernetes.io/instance: whoami spec: containers: - image: traefik/whoami:latest name: whoami ports: - containerPort: 80 name: http protocol: TCP $ kubectl -n myapp get pods No resources found in myapp namespace. $ kubectl apply -f k8s-pod.yaml pod/whoami created $ kubectl -n myapp get pods NAME READY STATUS RESTARTS AGE whoami 1/1 Running 0 8s
  22. @m_holtermann Services

  23. @m_holtermann @m_holtermann apiVersion: v1 kind: Service metadata: name: whoami namespace:

    myapp spec: ports: - name: http port: 8080 protocol: TCP targetPort: http selector: app.kubernetes.io/instance: whoami $ kubectl -n myapp get services No resources found in myapp namespace. $ kubectl apply -f k8s-service.yaml service/whoami created $ kubectl -n myapp get services NAME TYPE CLUSTER-IP PORT(S) AGE whoami ClusterIP 10.240.28.82 8080/TCP 2s
  24. @m_holtermann Ingresses

  25. @m_holtermann @m_holtermann apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: whoami namespace:

    myapp spec: rules: - host: example.com http: paths: - path: / pathType: Prefix backend: service: name: whoami port: name: http $ kubectl -n myapp get ingress No resources found in myapp namespace. $ kubectl -n myapp apply -f k8s-ingress.yaml ingress.networking.k8s.io/whoami created $ kubectl -n myapp get ingress NAME HOSTS ADDRESS PORTS AGE whoami example.com 80 3s
  26. @m_holtermann Configmaps & Secrets

  27. @m_holtermann @m_holtermann apiVersion: v1 kind: ConfigMap metadata: name: whoami namespace:

    myapp data: WHOAMI_NAME: "Darth Vader" $ kubectl -n myapp get configmaps No resources found in myapp namespace. $ kubectl -n myapp apply -f k8s-configmap.yaml configmap/whoami created $ kubectl -n myapp get configmaps NAME DATA AGE whoami 1 3s apiVersion: v1 kind: Secret metadata: name: whoami namespace: myapp type: Opaque data: a-key: THVrZSwgSSdtIHlvdXIgZmF0aGVyIQo= $ kubectl -n myapp get secrets No resources found in myapp namespace. $ kubectl -n myapp apply -f k8s-secret.yaml secret/whoami created $ kubectl -n myapp get secrets NAME TYPE DATA AGE whoami Opaque 1 3s
  28. @m_holtermann Deployments

  29. @m_holtermann @m_holtermann apiVersion: apps/v1 kind: Deployment ... spec: replicas: 3

    selector: matchLabels: app.kubernetes.io/instance: whoami template: metadata: labels: app.kubernetes.io/instance: whoami spec: containers: - image: traefik/whoami:latest name: whoami env: - name: SOME_SECRET valueFrom: secretKeyRef: name: whoami key: a-key envFrom: - configMapRef: name: whoami ports: - containerPort: 80 name: http protocol: TCP $ kubectl -n myapp get deployments No resources found in myapp namespace. $ kubectl -n myapp apply -f k8s-deployment.yaml deployment.apps/whoami created $ kubectl -n myapp get deployments NAME READY UP-TO-DATE AVAILABLE AGE whoami 3/3 3 3 4s $ kubectl -n myapp get pods NAME READY STATUS RESTART AGE whoami 1/1 Running 0 10m Whoami-66bc5b-jtpjs 1/1 Running 0 23s whoami-66bc5b-pv7kv 1/1 Running 0 23s Whoami-66bc5b-sk2f8 1/1 Running 0 23s
  30. @m_holtermann Kubernetes & Django

  31. @m_holtermann @m_holtermann --- apiVersion: v1 kind: ConfigMap metadata: name: myapp

    namespace: mynamespace data: ALLOWED_HOSTS: "myapp.com,myapp.mynamespace.svc.cluster.local " --- apiVersion: v1 kind: Secret metadata: name: myapp namespace: mynamespace type: Opaque data: # postgres://user:pw@pgserver:5432/dbname DATABASE_URL: cG9zdGdyZXM6Ly91c2VyOnB3QHBnc2VydmVyOjU0MzIvZGJuYW1l= SECRET_KEY: KzVAYmpkbXhqd2koYjQoeHFrOWwkdCZidjB5QCF4bXpfI2k3PSVlKmhpdnUqdTdmXng=
  32. @m_holtermann @m_holtermann import os import dj_database_url SECRET_KEY = os.environ["SECRET_KEY"] DEBUG

    = os.getenv("DEBUG", "") == "true" ALLOWED_HOSTS = os.getenv("ALLOWED_HOSTS", "").split(",") DATABASES = {"default": dj_database_url. config()}
  33. @m_holtermann @m_holtermann apiVersion: apps/v1 kind: Deployment metadata: name: myapp namespace:

    mynamespace spec: replicas: 2 selector: matchLabels: app.kubernetes.io/name : myapp template: metadata: labels: app.kubernetes.io/name : myapp spec: containers: - envFrom: - configMapRef: name: myapp - secretRef: name: myapp image: path.to.my/docker/image:tag imagePullPolicy : IfNotPresent name: web ports: - containerPort: 8080 name: http protocol: TCP restartPolicy: Always
  34. @m_holtermann @m_holtermann # Dockerfile # ... ENTRYPOINT ["/entrypoint.sh "] CMD

    ["gunicorn", "-b", ":8080", "-w", "4", "--log-level", "INFO", "--access-logfile ", "-", "--error-logfile ", "-", "myapp.wsgi"] # ... # /entrypoint.sh #!/bin/sh set -e cmd="$@" until django-admin dbshell -- --command '\q'; do >&2 echo "Postgres is unavailable - sleeping " sleep 5 done django-admin migrate -v 2 django-admin collectstatic -v 2 --no-input exec $cmd
  35. @m_holtermann This is Kubernetes!