Skip to content

Latest commit

 

History

History
249 lines (217 loc) · 8.73 KB

creatingdatabases.md

File metadata and controls

249 lines (217 loc) · 8.73 KB

Creating Databases

Before start

First of all, in order to create a Database resource, a DbInstance resource is necessary. This defines the target server where the database must be created. Database resources require DbInstance. One or more DbInstance(s) are necessary for creating Database(s)

Check if DbInstance exists on cluster and running.

$ kubectl get dbin

The result should be like below.

NAME              PHASE      STATUS
example-generic   Running   false

If you get No resources found., go to how to create DbInstance

For more details about how it works check here

Next

CreatingDatabases

Create Database custom resource

apiVersion: "kci.rocks/v1beta1"
kind: "Database"
metadata:
  name: "example-db"
spec:
  secretName: example-db-credentials # DB Operator will create secret with this name. it contains db name, user, password
  instance: example-gsql # This has to be match with DbInstance name
  deletionProtected: false # Protection to not delete database when custom resource is deleted
  backup:
    enable: false # turn it to true when you want to use back up feature. currently only support postgres
    cron: "0 0 * * *"
  secretsTemplates:
    CONNECTION_STRING: "jdbc:{{ .Protocol }}://{{ .UserName }}:{{ .Password }}@{{ .DatabaseHost }}:{{ .DatabasePort }}/{{ .DatabaseName }}" 
    PASSWORD_USER: "{{ .Password }}_{{ .UserName }}"

With secretsTemplates you can add fields to the database secret that are composed by any string and by any of the following templated values:

- Protocol: Depending on db engine. Possible values are mysql/postgresql
- UserName: The same value as for database user in the creds secret
- Password: The same value as for password in the creds secret
- DatabaseHost: The same value as for db host in the connection configmap 
- DatabasePort: The same value as for db port in the connection configmap 
- DatabaseName: The same value as for db host in the creds secret

If no secretsTemplates are specified, the default one will be used:

CONNECTION_STRING: "jdbc:{{ .Protocol }}://{{ .UserName }}:{{ .Password }}@{{ .DatabaseHost }}:{{ .DatabasePort }}/{{ .DatabaseName }}" 

For postgres it's also possible to drop the Public schema after the database creation, or to create additional schemas. To do that, you need to provide these fields:

postgres:
  dropPublicSchema: true # Do not set it, or set to false if you don't want to drop the public schema
  schemas: # The user that's going to be created by db-operator, will be granted all privileges on these schemas
    - schema_1
    - schema_2

If you initialize a database with dropPublicSchema: false and then later change it to true, or add schemas with the schemas field and later try to remove them by updating the manifest, you may be unable to do that. Because db-operator won't use DROP CASCADE for removing schemas, and if there are objects depending on a schema, someone with admin access will have to remove these objects manually.

After successful Database creation, you must be able to get a secret named like example-db-credentials.

$ kubectl get secret example-db-credentials

It contains credentials to connect to the database generated by operator.

For postgres,

apiVersion: v1
kind: Secret
metadata:
  labels:
    created-by: db-operator
  name: example-db-credentials
type: Opaque
data:
  POSTGRES_DB: << base64 encoded database name (generated by db operator) >>
  POSTGRES_PASSWORD: << base64 encoded password (generated by db operator) >>
  POSTGRES_USER: << base64 encoded user name (generated by db operator) >>
  CONNECTION_STRING: << base64 encoded database connection string >>

For mysql,

apiVersion: v1
kind: Secret
metadata:
  labels:
    created-by: db-operator
  name: example-db-credentials
type: Opaque
data:
  DB: << base64 encoded database name (generated by db operator) >>
  PASSWORD: << base64 encoded password (generated by db operator) >>
  USER: << base64 encoded user name (generated by db operator) >>
  CONNECTION_STRING: << base64 encoded database connection string >>

You should be able to get configmap with same name as secret like example-db-credentials.

$ kubectl get configmap example-db-credentials

It contains connection information for database server access.

apiVersion: v1
kind: ConfigMap
metadata:
  labels:
    created-by: db-operator
  name: example-db-credentials
data:
  DB_CONN: << database server address >>
  DB_PORT: << database server port >>
  DB_PUBLIC_IP: << database server public ip >>
  ...

By default ConfigMaps and Secrets are created without an Owner Reference, so they won't be removed if the Database resource is removed. If you want it to be deleted too, you need to turn on the cleanup function.

apiVersion: "kci.rocks/v1beta1"
kind: "Database"
metadata:
  name: "example-db"
spec:
  cleanup: true

If this feature is enabled, then Database becomes an owner of Secrets and ConfigMaps, and by removing a database, you'll also remove them.

ConnectingToTheDatabase

By using the secret and the configmap created by operator after database creation, pods in Kubernetes can connect to the database. The following deployment is an example of how application pods can connect to the database.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: example-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: example
  template:
    metadata:
      labels:
        app: example
    spec:
      containers:
      - name: example-app
        image: "appimage:latest"
        imagePullPolicy: Always
        env:
        - name: POSTGRES_PASSWORD_FILE
          value: /run/secrets/postgres/POSTGRES_PASSWORD
        - name: POSTGRES_USERNAME
          valueFrom:
            secretKeyRef:
              key: POSTGRES_USER
              name: example-db-credentials # has to be same with spec.secretName of Database custom resource
        - name: POSTGRES_DB
          valueFrom:
            secretKeyRef:
              key: POSTGRES_DB
              name: example-db-credentials # has to be same with spec.secretName of Database custom resource
        - name: POSTGRES_HOST
          valueFrom:
            configMapKeyRef:
              key: DB_CONN
              name: example-db-credentials # has to be same with spec.secretName of Database custom resource
        volumeMounts:
        - mountPath: /run/secrets/postgres/
          name: db-secret
          readOnly: true
      volumes:
      - name: db-secret
        secret:
          defaultMode: 420
          secretName: example-db-credentials # has to be same with spec.secretName of Database custom resource

CheckingDatabaseStatus

To check Database status

kubectl get db example-db

The output should be like

NAME          PHASE   STATUS   PROTECTED   DBINSTANCE         AGE
example-db    Ready   true     false       example-generic    4h39m

Possible phases and meanings

Phase Description
Creating On going creation of database in the database server
InfoConfigMapCreating Generating and building configmap data with database server information
InstanceAccessSecretCreating When instance type is google, it's creating access secret in the namespace where Database exists.
BackupJobCreating Creating backup Cronjob when backup is enabled in the spec
Finishing Setting status of Database to true
Ready Database is created and all the configs are applied. Healthy status.
Deleting Database is being deleted.

PostgreSQL

PostgreSQL extensions listed under spec.extensions will be enabled by DB Operator. DB Operator execute CREATE EXTENSION IF NOT EXISTS on the target database.

apiVersion: "kci.rocks/v1beta1"
kind: "Database"
metadata:
  name: "example-db"
spec:
  secretName: example-db-credentials
  instance: example-gsql
  deletionProtected: false
  extensions:
    - pgcrypto
    - uuid-ossp
    - plpgsql

When monitoring is enabled on DbInstance spec, pg_stat_statements extension will be enabled. If below error occurs during database creation, the module must be loaded by adding pg_stat_statements to shared_preload_libraries in postgresql.conf on the server side.

ERROR: pg_stat_statements must be loaded via shared_preload_libraries