Chuleta de PSQL
Aunque te hayas pegado a menudo con una base de datos postgresql, normalmente, se tocan de uvas a peras. Es difícil acordarse de todo, y por ello, hoy os dejo mi chuleta personal cuando no me acuerdo de algo.
Ficheros de configuración
/var/lib/postgresql/11/main' # use data in another directory
/etc/postgresql/11/main/postgresql.conf' #default conf file
/etc/postgresql/11/main/pg_hba.conf' # host-based authentication file
Conectarse desde cliente psql
Para hacer login en la BD postgres, utilizaremos la siguiente sintaxis:
psql -h [HOST] -U [user] [BD]
Ejemplo:
psql -h localhost -U user_name db_name
Visualizar ROLES
\du
Resultado:
Lista de roles
Nombre de rol | Atributos | Miembro de
-----------------+------------------------------------------------+------------
postgres | Superusuario, Crear rol, Crear BD, Replicación | {}
xxxxxxxxx | Superusuario | {}
yyyyyyyyyyy | | {}
Crear un GRUPO
CREATE ROLE nombre [ [ WITH ] opción [ ... ] ]
Donde opción puede ser:
SUPERUSER | NOSUPERUSER
| CREATEDB | NOCREATEDB
| CREATEROLE | NOCREATEROLE
| CREATEUSER | NOCREATEUSER
| INHERIT | NOINHERIT
| LOGIN | NOLOGIN
| REPLICATION | NOREPLICATION
| CONNECTION LIMIT límite_conexiones
| [ ENCRYPTED | UNENCRYPTED ] PASSWORD 'contraseña'
| VALID UNTIL 'fecha_hora'
| IN ROLE nombre_de_rol [, ...]
| IN GROUP nombre_de_rol [, ...]
| ROLE nombre_de_rol [, ...]
| ADMIN nombre_de_rol [, ...]
| USER nombre_de_rol [, ...]
| SYSID uid
Ejemplo:
CREATE GROUP dev WITH LOGIN NOCREATEDB NOSUPERUSER NOCREATEROLE;
Dar permisos de conexión sobre una BD
GRANT { { CREATE | CONNECT | TEMPORARY | TEMP } [,...] | ALL [ PRIVILEGES ] }
ON DATABASE database_name [, ...]
TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ]
Para más info de GRANT sobre postgres, visitar:
Postgres GRANT
Ejemplo:
GRANT CONNECT ON DATABASE tellmegen TO dev;
Mostrar todos los SCHEMA disponibles
select schema_name from information_schema.schemata;
Resultado:
schema_name
--------------------
isisaudit
isiscommand
isissecurity
isissessionlogger
pg_toast
pg_temp_1
pg_toast_temp_1
pg_catalog
information_schema
public
Dar permisos de SELECT, INSERT… sobre SCHEMA
GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER }
[,...] | ALL [ PRIVILEGES ] }
ON { [ TABLE ] table_name [, ...]
| ALL TABLES IN SCHEMA schema_name [, ...] }
TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ]
Ejemplo:1
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO dev;
Crear usuario y agregarlo a grupo
Utilizaremos la misma sintaxis que para crear un grupo. Ejemplo:
CREATE ROLE user_name WITH LOGIN NOCREATEDB NOSUPERUSER NOCREATEROLE CONNECTION LIMIT 1 PASSWORD 'password' IN GROUP dev;
Es interesante establecer CONNECTION LIMIT 1, para evitar suplantación de identidad del usuario
Cambiar de grupo al usuario
Eliminar usuario del grupo:
REVOKE user_name FROM group_name;
Modificar el fichero de conexión pg_hba.conf
Para permitir el acceso del usuario, hay que modificar el fichero pg_hba.conf. Esta configuración no funciona para usuarios, así que para permitir el acceso, habrá que añadir a cada usuario de manera individual.
/var/lib/pgsql/9.3/data/pg_hba.conf
o o para postgres11:
/etc/postgresql/11/main/pg_hba.conf
La sintaxis del fichero debe de llevar alguna de las siguientes formas:
# local DATABASE USER METHOD [OPTIONS]
# host DATABASE USER ADDRESS METHOD [OPTIONS]
# hostssl DATABASE USER ADDRESS METHOD [OPTIONS]
# hostnossl DATABASE USER ADDRESS METHOD [OPTIONS]
Ejemplo para login local:
local database_name user_name peer
Ejemplo para login remoto / pgadmin:
host database_name user_name ip/32 trust
Reiniciar siempre el servicio de postgres para aplicar cambios:
service postgresql-9.3.service restart
Problema resuelto!
Snapshots periódicos de un PVC en GCP con Google SDK + Bash + CronJob
Pues ahí va la historia de este script:
Resulta que queremos mover una base de datos, la típica postgresql, de una maquina virtual a un pod de kubernetes. Hay muchos factores a tener en cuenta: Si se va a hacer subida de versión, como importar una copia de la base de datos, persistencia de discos… Aunque el que más me preocupaba era el disaster recovery.
Con una VM era sencillo. Script sacado de un blog de google y adaptado al entorno GCP, cambiando el almacenamiento local por un bucket de Storage. Pero claro, la mayoría de imágenes de postgresql vienen sobre alpine, que viene con las funcionalidades más que justas para que su consumo sea mínimo.
Se me ocurrieron un par de soluciones para abordar el problema:
- Instalar cron en el archivo Dockerfile de la imagen. Importar también los scripts actuales de la VM a dicha imágen. En definitiva, emular la VM en el entorno GKE.
- Levantar una imagen google/cloud-sdk, copiar un script .sh que trabajara con snapshots de Kubernetes y ejecutarlo desde un CronJob.
Al final, la que me pareció más adecuada fue la segunda. Y es que hace poco, intentando implementar ELK, descubrí «nuevos» tipos de carga de trabajo más allá de los deployments: Los CronJobs.
Un CronJob es un tipo de carga de trabajo que permite ejecutar trabajos en una programación basada en el tiempo. Estos trabajos automatizados se ejecutan como tareas Cron en un sistema Linux o UNIX.
Este tipo de carga de trabajo, junto a la potencia del SDK de Google, que permite trabajar con cuentas de servicio de permisos limitados, hacen posible que este script funcione. Eh aquí mis archivos «mágicos»:
Dockerfile
FROM google/cloud-sdk:latest
RUN mkdir /scripts
COPY ./[service-account-key].json /scripts
COPY ./snapshot_creation.sh /scripts
RUN chmod +x /scripts/snapshot_creation.sh
CMD tail -f /dev/null
Para poder utilizar GKE de forma desatendida, es necesario utilizar una cuenta de servicio. Os dejó aquí un enlace de como activar y empezar a usar una cuenta de servicio con GCP.
Script en Bash
#VAR definition
account_service_email="[account-service-email]"
account_service_json_dir="/scripts/.[service-account-key].json"
cluster_name="[cluster-name]"
cluster_zone="[cluster-zone]"
date=$(date +%Y%m%d-%H%M)
gcp_project_name="[gcp-project-name]"
pvc_name="pvc-[id]"
snapshot_name=$date-prod-psql-snapshot
snapshot_namespace="[kubernetes-namespace]"
#Create YAML
printf "apiVersion: snapshot.storage.k8s.io/v1beta1 \n" > snapshot.yaml
printf "kind: VolumeSnapshot \n" >> snapshot.yaml
printf "metadata: \n" >> snapshot.yaml
printf " name: $snapshot_name \n" >> snapshot.yaml
printf " namespace: $snapshot_namespace \n" >> snapshot.yaml
printf "spec: \n" >> snapshot.yaml
printf " source: \n" >> snapshot.yaml
printf " persistentVolumeClaimName: $pvc_name" >> snapshot.yaml
#Create snapshot
gcloud auth activate-service-account $account_service_email --key-file=$account_service_json_dir --project=$gcp_project_name
gcloud container clusters get-credentials $cluster_name --zone $cluster_zone --project $gcp_project_name
kubectl create -f snapshot.yaml --save-config
#Remove old versions
snapshot_count=`kubectl get volumesnapshot | grep prod-psql-snapshot | wc -l`
digest_array=(`kubectl get volumesnapshot | grep prod-psql-snapshot | awk '{print $1}'`)
if [ $snapshot_count -gt 14 ]
then
oldest_snapshot=`echo ${digest_array[0]}`
kubectl delete volumesnapshot $oldest_snapshot
fi
Lo que hago con este script es generar el YAML de un VolumeSnapshot, me autentico con la cuenta de servicio y creo ese snapshot. Para dejarlo todo limpio, cuento el número de copias al finalizar, y si pasan de 14, borro las últimas. Para más info acerca de como trabajar con los VolumeSnapshots en GCP, podéis consultarlo aquí.
CronJob
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: snapshot
spec:
schedule: "01 0 * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: backup
image: gcr.io/[project-name]/[image_name]
args:
- /bin/sh
- -c
- sh /scripts/snapshot_creation.sh
restartPolicy: Never
Y ya estaría! Problema resuelto!