11.3. App Updates for Postgres#
Your application is not ready to use Postgres yet. This lab will take you through the steps to update it.
Install Postgres Support#
You should also install the pyscopg2
package in your development environment. The psycopg2
package provides Python programs a way to access a Postgres database:
$ pip install psycopg2
Change the Database Setting#
In the mysite/settings.py
file you should update your database configuration to match this:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': os.environ['POSTGRES_DB'],
'USER': os.environ['POSTGRES_USER'],
'PASSWORD': os.environ['POSTGRES_PASSWORD'],
'HOST': os.environ['POSTGRES_HOSTNAME'],
},
}
This creates four new mandatory environment variables that have to be set in order to run your application.
Test the Updates#
The development copy of your app is now set to use the Postgres database instead of the built-in SQLite database. But how to test it? There are a few options, you could create a Postgres database in your dev environment. However, since we already have one running in Kubernetes let’s use the kubeclt port-forward
command to make that database accessible to the dev environment:
$ kubectl port-forward service/postgres-postgresql 5432:5432
In a separate terminal set all of the necessary environment variables and run the development server:
$ export POSTGRES_DB="mysite"
$ export POSTGRES_USER="mysiteuser"
$ export POSTGRES_PASSWORD="this-is-a-bad-password"
$ export POSTGRES_HOSTNAME="localhost"
$ python ./manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
...
If you see the usual output from migrate
you can also run the createsuperuser
command:
$ python ./manage.py createsuperuser
Once you are able to perform the migrate
and createsuperuser
commands you have completed the setup of your Postgres database. The changes will stick as long as you don’t delete the PersistentVolumeClaim
associated with Postgres.
Note
Remember this procedure. You will need to initialize the database using the development server again.
Rebuild the Container#
Now that you have updated your application it’s important to carry those updates through to your Dockerfile
so that new cloud versions of your app see the changes. Update your Dockerfile
to contain the new environment variables:
ENV POSTGRES_DB="mysite"
ENV POSTGRES_USER="mysiteuser"
ENV POSTGRES_PASSWORD="this-is-a-bad-password"
ENV POSTGRES_HOSTNAME="localhost"
You can remove the DATA_DIR
environment variable. It will not be used anymore. Also make sure that the new image is built with psycopg2
by updating the pip install
line:
RUN pip install Django==4.2.9 psutil psycopg2
Rebuild your container with the changes you’ve made to the Dockerfile
:
$ docker build -t mysite
Building is the easy part. But how do you test? It’s more complicated now that the site requires a database to be present. This is one of the harder things that you do in Kubernetes. To properly test your container we need to do two things:
Open a tunnel to Postgres in your cluster:
$ kubectl port-forward service/postgres-postgresql 5432:5432 Forwarding from 127.0.0.1:5432 -> 5432 Handling connection for 5432
Launch the container using
host
mode networking so the container can “see”localhost
:$ docker run -it --rm --network host mysite /bin/bash root@cs-1000282563330-default:/mysite# python manage.py migrate
Once you push the new code to GitHub your container will be ready to scale!
Update Configuration and Secrets#
Add these environment variables to your deployment/secret.yaml
file:
POSTGRES_PASSWORD: "this-is-a-bad-password"
POSTGRES_USER: "mysiteuser"
Add these environment variables to your deployment/config.yaml
file:
POSTGRES_DB: "mysite"
POSTGRES_HOSTNAME: "postgres-postgresql"
Note
In Kubernetes each Service
is reachable by a hostname that matches the name
key in the service. You can find the name of a service from kubectl get all
. For example:
$ kubectl get all
NAME READY STATUS RESTARTS AGE
pod/mysite-deployment-69b9b76c87-25sz2 1/1 Running 5 (46m ago) 51m
pod/postgres-postgresql-0 1/1 Running 0 47m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 34.118.224.1 <none> 443/TCP 25h
service/postgres-postgresql ClusterIP 34.118.237.116 <none> 5432/TCP 47m
service/postgres-postgresql-hl ClusterIP None <none> 5432/TCP 47m
The name of the Postgres service is postgres-postgresql
so the hostname inside of other containers is postgres-postgresql
.
Don’t forget to use kubectl apply
to update the secrets in your cluster.