0
votes

We have several microservices and all of this microservices has their own helm chart and SCM repository. We have also two different cluster per stage and production environment.One of the microservice needs to use PostgreSQL. Due to company policy we had a separate team that created Helm Charts for Postgre and we should use this and need to deploy independently to our k8s cluster. Because of we do not have our own Helm repository I guess we need to use ConfigMap, or Secrets or both to integrate PostgreSQL to our microservice.

It might be a general question but I did not able to find specific examples how to integrate database without using dependency. So ı guess ı need to add database information as a ENV in deployment.yaml as below but what is the best practices to use Configmap, or Secrets and how should they look like in templates and how should ı pass the url,username,password per environment with safely way?

  env:
    - name: SPRING_DATASOURCE_URL
      valueFrom:
        configMapKeyRef: 
          name: postgres-production
          key: jdbc-url
    - name: SPRING_DATASOURCE_USERNAME
      valueFrom:
        secretKeyRef:
          name: postgres-production
          key: username
    - name: SPRING_DATASOURCE_PASSWORD
      valueFrom:
        secretKeyRef:
          name: postgres-production
          key: password

Microservice's Tree

├── helm
│   └── oneapihub-mp
│       ├── Chart.yaml
│       ├── charts
│       ├── templates
│       │   ├── NOTES.txt
│       │   ├── _helpers.tpl
│       │   ├── deployment.yaml
│       │   ├── ingress.yaml
│       │   ├── networkpolicy.yaml
│       │   ├── service.yaml
│       │   ├── serviceaccount.yaml
│       │   └── tests
│       │       └── test-connection.yaml
│       ├── values.dev.yaml
│       ├── values.prod.yaml
│       ├── values.stage.yaml
2

2 Answers

0
votes

I think this mysql helm chart answer your question.

There are 3 yamls you should check.

You can create your own password in values.yaml.

 ## Create a database user
 ##  
 # mysqlUser:
 ## Default: random 10 character string
 # mysqlPassword:

Which will be taken in secret and encoded using base64.

mysql-password: {{ .Values.mysqlPassword | b64enc | quote }}

Then it will be taken by deployment.

- name: MYSQL_PASSWORD
          valueFrom:
            secretKeyRef:
              name: {{ template "mysql.secretName" . }}
              key: mysql-password

And a bit more about secrets based on kubernetes documentation.

Kubernetes Secrets let you store and manage sensitive information, such as passwords, OAuth tokens, and ssh keys. Storing confidential information in a Secret is safer and more flexible than putting it verbatim in a Pod definition or in a container image

Based on my knowledge that's how it should be done.


EDIT

I add mysql just as example, there is postgres chart. Idea is still the same.

I am confuse how should ı create config and secret yaml in my application?

You can create secret before the chart, but you can make a secret.yaml in templates and make a secret there, which will be created with the rest of the yamls when installing chart and will take the credentials from values.dev,prod,stage.yamls.

using only this env variable is enough?

Yes, as you can see in the answer if you create some password in values.yaml then it will be taken in secret through deployment with secretKeyRef.

should I deploy my application in same namespace?

I don't understand this question, you can specify namespace for your application or you can deploy everything in the default namespace.

I hope it answer your question. Let me know if you have any more questions.

0
votes

If you have a requirement to install and manage the database separately from your container, you essentially need to treat it as an external database. Aside from the specific hostname, it doesn't really make any difference whether the database is running in the same namespace, a different namespace, or outside the cluster altogether.

If your ops team's PostgreSQL container generates the specific pair of ConfigMap and Secret you show in the question, and it will always be in the same Kubernetes namespace, then the only change I'd make is to make it parametrizable where exactly that deployment is.

# values.yaml

# postgresName has the name of the PostgreSQL installation.
postgresName: postgres-production
env:
  - name: SPRING_DATASOURCE_URL
    valueFrom:
      configMapKeyRef: 
        name: {{ .Values.postgresName }}
        key: jdbc-url

If these are being provided as configuration values to Helm...

# values.yaml
postgres:
  url: ...
  username: ...
  password: ...

...I'd probably put the username and password parts in a Secret and incorporate them as you've done here. I'd probably directly inject the URL part, though. There's nothing wrong with using a ConfigMap here and it matches the way you'd do things without Helm, but there's not a lot of obvious value to the extra layer of indirection.

env:
  - name: SPRING_DATASOURCE_URL
    value: {{ .Values.postgres.url | quote }}
  - name: SPRING_DATASOURCE_USERNAME
    valueFrom:
      secretKeyRef:
        name: {{ template "chart.name" . }}
        key: postgresUsername

When you go to deploy the chart, you can provide an override set of Helm values. Put some sensible set of defaults in the chart's values.yaml file, but then maintain a separate values file for each environment.

helm upgrade --install myapp . -f values.qa.yaml
# where values.qa.yaml has database settings for your test environment