Preparazione per Kubernetes

local.py vs env

in kubernetes è molto più pratico gestire variabili d’ambiente che non file di configurazione. È quindi opportuno evitare di scrivere local.py e usare invece variabili, che poi verranno definite in .env per docker e in ConfigMap per kubernetes.

Ci viene in aiuto il pacchetto `django-environ`_ che permette di scrivere il file di conf (base.py, production.py, …) usando una sintassi più concisa. Alcuni esempi sono di seguito.

SECRET_KEY & SENTRY

È l’esempio più semplice. Nel file:

SECRET_KEY = env('SECRET_KEY', default='chiave segretisssima!')
SENTRY_DSN_KEY = env('SENTRY_DNS_KEY')

La variabile:

SECRET_KEY=akhrkhdglhlkfjhsldkjh
SENTRY_DSN_KEY=oiupiourpoiusprioun.poinoi

database

invece di splittare il db su tante varibili, possiamo usarne una sola.

Nel file:

import environ

env = environ.Env()   # possono esserci args
DATABASES= {
  'default': env.db(),
  'old_apps': env.db('DATABASE_URL_OLD')
}

La variabile:

DATABASE_URL='postgresql://user:pwd@host:5433/dbname'
DATABASE_URL_OLD='sqlite:////tmp/db.sqlite'

ALLOWED_HOSTS

Quest’esempio mostra come possiamo trattare una list, di fatto splittando rispetto alla «,».

Nel file:

ALLOWED_HOSTS = env.list('ALLOWED_HOSTS', default=['grazievecchie.thux.dev'])

la variabile:

ALLOWED_HOSTS=thux.it,www.thux.it

EMAIL_URL

Nel File:

# The email() method is an alias for email_url().
EMAIL_CONFIG = env.email(
    'EMAIL_URL',
    default='smtp://user:password@localhost:25'
)

vars().update(EMAIL_CONFIG)

La variabile:

EMAIL_URL=smtp://user:password@wash01.thundersystems.it:25

settings.py

in ambiente docker non è pratico dovere creare il link simbolico, è molto più efficente caricare un file di conf basandosi su una variabile, per noi ENV. Ho quindi riscritto settings/__init__.py in modo che carichi dev.py, staging.py o production.py.

Logs

Quando l’applicazione è distribuita su più nodi è opportuno che i log non siano su file quindi modifichiamo uwsgi.ini in modo da evitare di scrivere su file:

# req-logger
# logger

Questo paragrafo sarà espanso quando cominceremo ad usare

Health

è necessario avere un endpoint che viene usato da kubernetes per sapere se il container risponde correttamente. Es.:

/api/health

che può essere implementato:

class Health(APIView):

    def get(self, request):
        return http.HttpResponse("ok", content_type="text/plain")

Decideremo in seguito se fare una query che tocchi il db