I’m packaging a Python app for use within a Kubernetes cluster. In the code base this method exists :
def get_pymongo_client(self):
username = test;
password = 'test';
url = ‘test
conn_str = "mongodb+srv://" + username + ":" + password + “/”+ url
return pymongo.MongoClient(conn_str)
I’m attempting to secure the username, password & URL fields so that they are not viewable within the src code. For this, I plan to use secrets.
The URL https://kubernetes.io/docs/tasks/configmap-secret/managing-secret-using-kubectl/ details how to create a secret. But I’m not sure how to read the secret from the Python app.
.Dockerfile for my app:
#https://docs.docker.com/language/python/build-images/
FROM python:3.8-slim-buster
WORKDIR /app
COPY requirements.txt requirements.txt
RUN pip3 install -r requirements.txt
COPY . .
CMD [ "python3", "-m" , "flask", "run", "--host=0.0.0.0"]
Reading Python flask application access to docker secrets in a swarm details the use of secrets in a docker-compose file, is this also required for Kubernetes? What steps are involved in order to read secret parameters from the Python src code file?
The traditional way is via environment variable
spec:
containers:
- name: your-app
# ...
env:
- name: PYMONGO_USERNAME
valueFrom:
secretKeyRef:
name: your-secret-name-here
key: PYMONGO_USERNAME
Or you can make that yaml less chatty by using a well-formed Secret and the "envFrom:" field
kind: Secret
metadata:
name: pymongo
stringData:
PYMONGO_USERNAME: test
PYMONGO_PASSWORD: sekrit
---
spec:
containers:
- name: your-app
envFrom:
- secretRef:
name: pymongo
# and now the pod has all environment variables matching the keys in the Secret
and then your code would just read it from its environment as normal
def get_pymongo_client(self):
username = os.getenv('PYMONGO_USERNAME')
password = os.getenv('PYMONGO_PASSWORD')
# etc
An alternative, but similar idea, is to mount the Secret onto the filesystem, and then read in the values as if they were files
spec:
containers:
- name: your-app
env:
# this part is 100% optional, but allows for easier local development
- name: SECRETS_PATH
value: /secrets
volumeMounts:
- name: pymongo
mountPath: /secrets
volumes:
- name: pymongo
secret:
secretName: your-secret-name-here
then:
def get_pymongo_client(self):
sec_path = os.getenv('SECRETS_PATH', './secrets')
with open(os.path.join(sec_path, 'PYMONGO_USERNAME')) as fh:
username = fh.read()