Skip to content

Commit e9a3a3f

Browse files
committed
Add docs about databases
Signed-off-by: Nikolai Rodionov <allanger@badhouseplants.net>
1 parent 5c212df commit e9a3a3f

3 files changed

Lines changed: 227 additions & 2 deletions

File tree

docs/database.md

Lines changed: 226 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,228 @@
11
# Database
22

3-
WIP
3+
**Database** might be considered the most important resource in the operator. It should be used to manage the lifecycle of databases and a users associated with them on the server.
4+
5+
## How to create and use a database
6+
7+
To create a `Database`, you first would need to have a running `DbInstance`. You can read about the `DbInstances` [here](dbinstance.md).
8+
9+
After you have a working `DbInstance` you can start creating a database.
10+
11+
Let's start by defining an instance on which the database should be deployed. Let's assume you have an instance called `cloudnative-pg`
12+
13+
```yaml
14+
apiVersion: kinda.rocks/v1beta1
15+
kind: Database
16+
metadata:
17+
name: my-database
18+
spec:
19+
instance: cloudnative-pg
20+
```
21+
22+
Then we need to define a name that is going to be used by the operator to create a `ConfigMap` and a `Secret`. If a secret with this name already exists, db-operator will try to use it, but let's talk about it [later](#reusing-an-existing-secret).
23+
24+
```yaml
25+
apiVersion: kinda.rocks/v1beta1
26+
kind: Database
27+
metadata:
28+
name: my-database
29+
spec:
30+
instance: cloudnative-pg
31+
secretName: my-database-creds
32+
```
33+
34+
And this is already enough to start using a database, after applying this manifest, operator will create a database and a user on a server, assign required permissions, and create a Secret and a ConfigMap in Kubernetes. Let's check
35+
36+
```sh
37+
$ kubectl get db my-database
38+
NAME STATUS PROTECTED DBINSTANCE OPERATORVERSION AGE
39+
my-database true false cloudnative-pg 2.19.0 3m33s
40+
41+
$ kubectl get secret my-database-creds
42+
NAME TYPE DATA AGE
43+
my-database-creds Opaque 4 4m44s
44+
45+
$ kubectl get cm my-database-creds
46+
NAME DATA AGE
47+
my-database-creds 4 4m46s
48+
```
49+
50+
The Secret should contain credentials to connect to the database generated by operator.
51+
52+
For postgres,
53+
```YAML
54+
apiVersion: v1
55+
kind: Secret
56+
metadata:
57+
labels:
58+
app.kubernetes.io/managed-by: db-operator
59+
kinda.rocks/used-by-kind: Database
60+
kinda.rocks/used-by-name: my-database
61+
name: my-database-creds
62+
type: Opaque
63+
data:
64+
POSTGRES_DB: << base64 encoded database name (generated by db operator) >>
65+
POSTGRES_PASSWORD: << base64 encoded password (generated by db operator) >>
66+
POSTGRES_USER: << base64 encoded user name (generated by db operator) >>
67+
CONNECTION_STRING: << base64 encoded database connection string >>
68+
```
69+
70+
For mysql,
71+
```YAML
72+
apiVersion: v1
73+
kind: Secret
74+
metadata:
75+
labels:
76+
app.kubernetes.io/managed-by: db-operator
77+
kinda.rocks/used-by-kind: Database
78+
kinda.rocks/used-by-name: my-database
79+
name: my-database-creds
80+
type: Opaque
81+
data:
82+
DB: << base64 encoded database name (generated by db operator) >>
83+
PASSWORD: << base64 encoded password (generated by db operator) >>
84+
USER: << base64 encoded user name (generated by db operator) >>
85+
CONNECTION_STRING: << base64 encoded database connection string >>
86+
```
87+
88+
89+
And the ConfigMap should contain connection information for database server access.
90+
91+
```YAML
92+
apiVersion: v1
93+
kind: ConfigMap
94+
metadata:
95+
labels:
96+
app.kubernetes.io/managed-by: db-operator
97+
kinda.rocks/used-by-kind: Database
98+
kinda.rocks/used-by-name: my-database
99+
name: my-database-creds
100+
data:
101+
DB_CONN: << database server address >>
102+
DB_PORT: << database server port >>
103+
DB_PUBLIC_IP: << database server public ip >>
104+
...
105+
```
106+
107+
By default, ConfigMap and Secret are created without owner references, so they won't be removed once the `Database` resource is removed. If you want them to be deleted too, you need to turn on the cleanup feature.
108+
109+
```YAML
110+
apiVersion: "kinda.rocks/v1beta1"
111+
kind: "Database"
112+
metadata:
113+
name: "example-db"
114+
spec:
115+
cleanup: true
116+
```
117+
118+
If ArgoCD is used to manage Databases and the `cleanup` is set to `true`, please make sure that the `PrunePropagationPolicy` is not set to `foreground`, because db-operator is using secrets to understand which Database must be removed, and with the `foreground` policy the secret is removed before the Database, that makes it impossible for the operator to finish the reconciliation.
119+
120+
If this feature is enabled, then `Database` becomes an owner of Secrets and ConfigMaps, and by removing a database, you'll also remove them.
121+
122+
With the Secret and the ConfigMap, we can connect to the database. Let's create a PostgreSQL Pod to test the connection.
123+
124+
```
125+
apiVersion: v1
126+
kind: Pod
127+
metadata:
128+
name: my-app
129+
spec:
130+
containers:
131+
- name: postgres-create-table
132+
image: postgres
133+
command:
134+
- psql
135+
args:
136+
- -c
137+
- "CREATE TABLE array_int (vector int[][]);"
138+
env:
139+
- name: PGPASSWORD
140+
valueFrom:
141+
secretKeyRef:
142+
name: my-database-creds
143+
key: POSTGRES_PASSWORD
144+
- name: PGUSER
145+
valueFrom:
146+
secretKeyRef:
147+
name: my-database-creds
148+
key: POSTGRES_USER
149+
- name: PGDATABASE
150+
valueFrom:
151+
secretKeyRef:
152+
name: my-database-creds
153+
key: POSTGRES_DB
154+
- name: PGHOST
155+
valueFrom:
156+
configMapKeyRef:
157+
name: my-database-creds
158+
key: DB_CONN
159+
imagePullPolicy: IfNotPresent
160+
restartPolicy: Never
161+
```
162+
163+
## Generic additional options
164+
165+
For production databases you might want to set `.spec.deletionProtected` to `true`. With this setting, db-operator will not remove the database from the server, if a Kubernetes resource is deleted.
166+
167+
DB operator is capable of generating custom connections strings using the information it has about a database, [here](templates.md) you can read more about templates.
168+
169+
It is possible to apply extra grants to databases, when it's enabled on the db-instance level.
170+
To enable it, one must set `.spec.allowExtraGrants` to `true` on an instance.
171+
172+
We have two types of access defined in the code:
173+
- readOnly
174+
- readWrite
175+
176+
It reflects the `DbUser` types of access.
177+
178+
The idea behind the extra grants is that there might be a database user that must have access to certain databases, that is not necessarily managed by the operator. Let's say the user is called `database-admin`.
179+
180+
Now for whatever reason, we want to let the admin access a database with readOnly permissions. In the db definition we need to add the following:
181+
```yaml
182+
kind: Database
183+
spec:
184+
extraGrants:
185+
- user: database-admin
186+
accessType: readOnly
187+
```
188+
189+
Now the `database-admin` should have enough permissions for reading data from this database. If access needs to be revoked or changed to `readWrite`, it should be enough to remove the entry from the spec or modify it.
190+
191+
192+
## Additional PostgreSQL options
193+
194+
PostgreSQL database can be additionally configured using the `.spec.postgres{}` section.
195+
196+
It's possible to drop ensure that the **public** schema is dropped by setting `.spec.postgres.dropPublicSchema`, and you can also create additional schemas that will be granted to the database user, managed by the operator, to do so, set the `.spec.postgres.schemas[]`
197+
198+
```YAML
199+
postgres:
200+
dropPublicSchema: true # Do not set it, or set to false if you don't want to drop the public schema
201+
schemas: # The user that's going to be created by db-operator, will be granted all privileges on these schemas
202+
- schema_1
203+
- schema_2
204+
```
205+
206+
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.
207+
208+
There is a support for [Postgres Database Templates](https://www.postgresql.org/docs/current/manage-ag-templatedbs.html). To create a database from template, you need to set `.spec.postgres.template`. It's referencing to a database on the Postgres server, but not to the k8s Database resource that is created by operator, so there is no validation on the db-operator side that a template exists.
209+
210+
## Reusing an existing secret
211+
212+
It's possible to connect DB Operator to an existing database. To do so you'll need to point the operator to an existing secret. It’s important that the secret follows the format expected by the operator.
213+
214+
For postgres:
215+
```YAML
216+
POSTGRES_DB: << base64 encoded database name (generated by db operator) >>
217+
POSTGRES_PASSWORD: << base64 encoded password (generated by db operator) >>
218+
POSTGRES_USER: << base64 encoded user name (generated by db operator) >>
219+
```
220+
221+
For mysql:
222+
```YAML
223+
DB: << base64 encoded database name (generated by db operator) >>
224+
PASSWORD: << base64 encoded password (generated by db operator) >>
225+
USER: << base64 encoded user name (generated by db operator) >>
226+
```
227+
228+
Then DB Operator will connect to an existing database and set up a user for it.
File renamed without changes.

docs/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ instance1 Running true
102102

103103
If `.status.Status` is `true`, it means that you can create Databases on this instance.
104104

105-
You can read more about DbInstances [here](dbinstances.md)
105+
You can read more about DbInstances [here](dbinstance.md)
106106

107107
## Create a Database
108108

0 commit comments

Comments
 (0)