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

An Introduction To Kubernetes ☸

An Introduction To Kubernetes ☸

My talk from EuroPython 2021

Markus H

July 28, 2021
Tweet

More Decks by Markus H

Other Decks in Technology

Transcript

  1. @m_holtermann
    An Introduction To
    Kubernetes

    View Slide

  2. @m_holtermann
    What is Kubernetes?

    View Slide

  3. @m_holtermann
    Hi, I’m
    Markus Holtermann

    View Slide

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

    View Slide

  5. @m_holtermann
    A system to run containers

    View Slide

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

    View Slide

  7. @m_holtermann
    Eventually consistent

    View Slide

  8. @m_holtermann
    @m_holtermann
    Cluster

    View Slide

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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  13. @m_holtermann
    Concepts

    View Slide

  14. @m_holtermann
    Everything is a resource

    View Slide

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

    View Slide

  16. @m_holtermann
    cluster-scoped or
    namespace-scoped

    View Slide

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

    View Slide

  18. @m_holtermann
    Namespaces

    View Slide

  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

    View Slide

  20. @m_holtermann
    Pods

    View Slide

  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

    View Slide

  22. @m_holtermann
    Services

    View Slide

  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

    View Slide

  24. @m_holtermann
    Ingresses

    View Slide

  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

    View Slide

  26. @m_holtermann
    Configmaps & Secrets

    View Slide

  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

    View Slide

  28. @m_holtermann
    Deployments

    View Slide

  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

    View Slide

  30. @m_holtermann
    Kubernetes & Django

    View Slide

  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=

    View Slide

  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()}

    View Slide

  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

    View Slide

  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

    View Slide

  35. @m_holtermann
    This is Kubernetes!

    View Slide