Cloud Native Python

The road to being a first-class Kubernetes application

Floris Bruynooghe

flub@devork.be

@flubdevork

Contents

  • K8s background
  • Execution environment
  • Logging
  • Health Endpoints
  • Monitoring

Kubernetes Basics

Execution Environment

Skip boilerplate

Simple architecture

Make Errors Fatal

apiVersion: extensions/v1beta
kind: ReplicaSet
metadata:
  name: ...
spec:
  replicas: 3
  template:
    spec:
      containers:
        - image: ...
          args: ...
      restartPolicy: Always

Scale via process model

  • No Concurrency
  • Loadbalancer / Reverse Proxy

Logging

  • Default: stdout
  • Ops will aggregate
  • Configurable
spec:
  containers:
    - image: ...
      args:
        - --loglevel=DEBUG

Use Libraries

import logging

logging.info('Some message')
import sys, logbook

logbook.StreamHandler(sys.stdout).push_application()
log = logbook.Logger('main')
try:
    raise Exception('oops')
except Exception:
    log.exception('This is bad')
    sys.exit(1)
import structlog

log = structlog.get_logger()
log = log.bind(user='flub')
log.info('msg.parsed', valid=True)

Health Endpoints: Readiness

  • Refuse no connections

readinessProbe

containers:
  - name: spam
    readinessProbe:
      tcpSocket:
        port: 1234
  - name: ham
    readinessProbe:
      httpGet:
        path: /healthz
        port: 8080

Health Endpoint: Liveness

containers:
  - name: spam
    readinessProbe:
      ...
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
  - name: ham
    livenessProbe:
      httpGet:
        path: /heathz
        port: 8080

Termination

  • Handle sigterm
  • Finish your requests
import signal

signal.signal(signal.SIGTERM,
              lambda s, f: mainloop.signal_shutdown())

Monitoring

Prometheus

  • HTTP-poll based
import prometheus_client as prom

reqs = prom.Counter('requests', 'Number of requests')
failed_reqs = prom.Counter('requests.failed', 'Number of failed requests')

prom.start_http_server(8000)

def handle(req):
    reqs.inc()
    with failed_reqs.count_exceptions():
        ...

Thanks! Questions?

flub@devork.be | @flubdevork