O guia mostra como usar o operador Zalando Postgres para implantar clusters do Postgres no Google Kubernetes Engine (GKE).
O PostgreSQL é um poderoso sistema de banco de dados relacional de objetos de código aberto com várias décadas de desenvolvimento ativo. Ele ganhou uma forte reputação de confiabilidade, robustez de recursos e desempenho.
Este guia é destinado a administradores de plataformas, arquitetos de nuvem e profissionais de operações interessados em executar o PostgreSQL como um aplicativo de banco de dados no GKE, em vez de usar o Cloud SQL para PostgreSQL.
Configurar o ambiente
Para configurar seu ambiente, siga estas etapas:
Defina as variáveis de ambiente:
export PROJECT_ID=PROJECT_ID export KUBERNETES_CLUSTER_PREFIX=postgres export REGION=us-central1
Substitua
PROJECT_ID
pelo Google Cloud ID do projeto.Clone o repositório do GitHub:
git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
Mude para o diretório de trabalho:
cd kubernetes-engine-samples/databases/postgres-zalando
Criar a infraestrutura do cluster
Nesta seção, você executa um script do Terraform para criar um cluster regional do GKE privado e altamente disponível.
É possível instalar o operador usando um cluster padrão ou Autopilot.
Padrão
O diagrama a seguir mostra um cluster regional padrão particular do GKE implantado em três zonas diferentes:
Implante esta infraestrutura:
export GOOGLE_OAUTH_ACCESS_TOKEN=$(gcloud auth print-access-token)
terraform -chdir=terraform/gke-standard init
terraform -chdir=terraform/gke-standard apply \
-var project_id=${PROJECT_ID} \
-var region=${REGION} \
-var cluster_prefix=${KUBERNETES_CLUSTER_PREFIX}
Quando solicitado, digite yes
. Pode levar vários minutos para que esse comando seja concluído e o cluster mostre um status pronto.
O Terraform cria os seguintes recursos:
- Uma rede VPC e uma sub-rede particular para os nós do Kubernetes.
- Um roteador para acessar a Internet usando NAT.
- Um cluster particular do GKE na região
us-central1
. - Um pool de nós com escalonamento automático ativado (de um a dois nós por zona, um nó por zona no mínimo);
- Um
ServiceAccount
com permissões de registro e monitoramento - Backup do GKE para recuperação de desastres.
- Google Cloud Managed Service para Prometheus para monitoramento de clusters.
O resultado será assim:
...
Apply complete! Resources: 14 added, 0 changed, 0 destroyed.
...
Piloto automático
O diagrama a seguir mostra um cluster particular regional do Autopilot do GKE:
Implante a infraestrutura:
export GOOGLE_OAUTH_ACCESS_TOKEN=$(gcloud auth print-access-token)
terraform -chdir=terraform/gke-autopilot init
terraform -chdir=terraform/gke-autopilot apply \
-var project_id=${PROJECT_ID} \
-var region=${REGION} \
-var cluster_prefix=${KUBERNETES_CLUSTER_PREFIX}
Quando solicitado, digite yes
. Pode levar vários minutos para que esse comando seja concluído e o cluster mostre um status pronto.
O Terraform cria os seguintes recursos:
- Uma rede VPC e uma sub-rede particular para os nós do Kubernetes.
- Um roteador para acessar a Internet usando NAT.
- Um cluster particular do GKE na região
us-central1
. - Um
ServiceAccount
com permissão de geração de registros e monitoramento. - Google Cloud Managed Service para Prometheus para monitoramento de clusters.
O resultado será assim:
...
Apply complete! Resources: 12 added, 0 changed, 0 destroyed.
...
Conexão ao cluster
Configure kubectl
para se comunicar com o cluster:
gcloud container clusters get-credentials ${KUBERNETES_CLUSTER_PREFIX}-cluster --location ${REGION}
Implantar o operador do Zalando no cluster
Implante o operador Zalando no cluster do Kubernetes usando um gráfico do Helm.
Adicionar o repositório de gráficos Helm do operador Zalando:
helm repo add postgres-operator-charts https://opensource.zalando.com/postgres-operator/charts/postgres-operator
Criar um namespace para o operador Zalando e o cluster do Postgres:
kubectl create ns postgres kubectl create ns zalando
Implantar o operador do Zalando usando a ferramenta de linha de comando Helm:
helm install postgres-operator postgres-operator-charts/postgres-operator -n zalando \ --set configKubernetes.enable_pod_antiaffinity=true \ --set configKubernetes.pod_antiaffinity_preferred_during_scheduling=true \ --set configKubernetes.pod_antiaffinity_topology_key="topology.kubernetes.io/zone" \ --set configKubernetes.spilo_fsgroup="103"
Não é possível definir as configurações de
podAntiAffinity
diretamente no recurso personalizado que representa o cluster do Postgres. Em vez disso, defina as configurações depodAntiAffinity
globalmente para todos os clusters do Postgres nas configurações do operador.Verifique o status da implantação do operador do Zalando usando o Helm:
helm ls -n zalando
O resultado será assim:
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION postgres-operator zalando 1 2023-10-13 16:04:13.945614 +0200 CEST deployed postgres-operator-1.10.1 1.10.1
Implantar o Postgres
A configuração básica da instância do cluster do Postgres inclui os seguintes componentes:
- Três réplicas do Postgres: uma líder e duas réplicas em espera.
- Alocação de recursos da CPU de uma solicitação de CPU e dois limites de CPU, com solicitações e limites de memória de 4 GB.
- As tolerâncias,
nodeAffinities
etopologySpreadConstraints
configurados para cada carga de trabalho, garantindo a distribuição adequada entre os nós do Kubernetes, utilizando os respectivos pools de nós e as diferentes zonas de disponibilidade.
Essa configuração representa a configuração mínima necessária para criar um cluster do Postgres pronto para produção.
O manifesto a seguir descreve um cluster do Postgres:
Esse manifesto tem os seguintes campos:
spec.teamId
: um prefixo para os objetos de cluster escolhidosspec.numberOfInstances
: o número total de instâncias de um clusterspec.users
: a lista de usuários com privilégiosspec.databases
: a lista de bancos de dados no formatodbname: ownername
.spec.postgresql
: parâmetros postgresspec.volume
: parâmetros do Persistent Diskspec.tolerations
: o modelo de pod de tolerância que permite que os pods de cluster sejam programados em nóspool-postgres
.spec.nodeAffinity
: o modelo de podnodeAffinity
que informa ao GKE que os pods de cluster preferem ser programados nos nóspool-postgres
.spec.resources
: solicitações e limites para pods de clusterspec.sidecars
: uma lista de contêineres de arquivos secundários, que contémpostgres-exporter
.
Para mais informações, consulte a Referência do manifesto de cluster na documentação do Postgres.
Criar um cluster básico do Postgres
Crie um novo cluster do Postgres usando a configuração básica:
kubectl apply -n postgres -f manifests/01-basic-cluster/my-cluster.yaml
Este comando cria um recurso personalizado do PostgreSQL do operador Zalando com:
- Solicitações e limites de CPU e memória
- Taints e afinidades para distribuir as réplicas de pod provisionadas entre os nós do GKE.
- Um banco de dados.
- Dois usuários com permissões de proprietário do banco de dados
- Um usuário sem permissões
Aguarde o GKE iniciar as cargas de trabalho necessárias:
kubectl wait pods -l cluster-name=my-cluster --for condition=Ready --timeout=300s -n postgres
Isso pode demorar alguns minutos.
Verifique se o GKE criou as cargas de trabalho do Postgres:
kubectl get pod,svc,statefulset,deploy,pdb,secret -n postgres
O resultado será assim:
NAME READY STATUS RESTARTS AGE pod/my-cluster-0 1/1 Running 0 6m41s pod/my-cluster-1 1/1 Running 0 5m56s pod/my-cluster-2 1/1 Running 0 5m16s pod/postgres-operator-db9667d4d-rgcs8 1/1 Running 0 12m NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/my-cluster ClusterIP 10.52.12.109 <none> 5432/TCP 6m43s service/my-cluster-config ClusterIP None <none> <none> 5m55s service/my-cluster-repl ClusterIP 10.52.6.152 <none> 5432/TCP 6m43s service/postgres-operator ClusterIP 10.52.8.176 <none> 8080/TCP 12m NAME READY AGE statefulset.apps/my-cluster 3/3 6m43s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/postgres-operator 1/1 1 1 12m NAME MIN AVAILABLE MAX UNAVAILABLE ALLOWED DISRUPTIONS AGE poddisruptionbudget.policy/postgres-my-cluster-pdb 1 N/A 0 6m44s NAME TYPE DATA AGE secret/my-user.my-cluster.credentials.postgresql.acid.zalan.do Opaque 2 6m45s secret/postgres.my-cluster.credentials.postgresql.acid.zalan.do Opaque 2 6m44s secret/sh.helm.release.v1.postgres-operator.v1 helm.sh/release.v1 1 12m secret/standby.my-cluster.credentials.postgresql.acid.zalan.do Opaque 2 6m44s secret/zalando.my-cluster.credentials.postgresql.acid.zalan.do Opaque 2 6m44s
O operador cria os seguintes recursos:
- Um StatefulSet do Postgres, que controla três réplicas de pod para o Postgres
- Uma
PodDisruptionBudgets
, garantindo pelo menos uma réplica disponível - O serviço
my-cluster
, que segmenta apenas a réplica líder - O serviço
my-cluster-repl
, que expõe a porta Postgres para conexões de entrada e para replicação entre as réplicas do Postgres - O serviço sem comando
my-cluster-config
para receber a lista de réplicas de pod do Postgres em execução. - Secrets com credenciais de usuário para acessar o banco de dados e a replicação entre os nós do Postgres
Autenticar no Postgres
É possível criar usuários do Postgres e atribuir a eles permissões de banco de dados. Por exemplo, o manifesto a seguir descreve um recurso personalizado que atribui usuários e papéis:
apiVersion: "acid.zalan.do/v1"
kind: postgresql
metadata:
name: my-cluster
spec:
...
users:
mydatabaseowner:
- superuser
- createdb
myuser: []
databases:
mydatabase: mydatabaseowner
Nesse manifesto:
- O usuário
mydatabaseowner
tem os papéisSUPERUSER
eCREATEDB
, que permitem todos os direitos de administrador, (por exemplo, gerenciar a configuração do Postgres, criar novos bancos de dados tabelas e usuários). Não compartilhe esse usuário com clientes. Por exemplo, o Cloud SQL não permite que os clientes tenham acesso a usuários com o papelSUPERUSER
. - O usuário
myuser
não tem papéis atribuídos. Isso segue a prática recomendada de usarSUPERUSER
para criar usuários com privilégios mínimos. Direitos granulares são concedidos amyuser
pormydatabaseowner
. Para manter a segurança, só compartilhe credenciaismyuser
com aplicativos clientes.
Armazenar senhas
Use o
método scram-sha-256
recomendado para armazenar senhas. Por exemplo, o manifesto a seguir descreve um recurso
personalizado que especifica a criptografia scram-sha-256
usando o
campo postgresql.parameters.password_encryption
:
apiVersion: "acid.zalan.do/v1"
kind: postgresql
metadata:
name: my-cluster
spec:
...
postgresql:
parameters:
password_encryption: scram-sha-256
Alternar credenciais do usuário
É possível alternar as credenciais de usuários armazenadas em secrets do Kubernetes com o Zalando. Por exemplo, o manifesto
abaixo descreve um recurso personalizado que define a rotação de credenciais do usuário usando
o campo usersWithSecretRotation
:
apiVersion: "acid.zalan.do/v1"
kind: postgresql
metadata:
name: my-cluster
spec:
...
usersWithSecretRotation:
- myuser
- myanotheruser
- ...
Exemplo de autenticação: conectar ao Postgres
Nesta seção, mostramos como implantar um exemplo de cliente Postgres e se conectar ao banco de dados usando a senha de um secret do Kubernetes.
Execute o pod cliente para interagir com o cluster do Postgres:
kubectl apply -n postgres -f manifests/02-auth/client-pod.yaml
As credenciais dos usuários
myuser
emydatabaseowner
são recebidas dos secrets relacionados e montadas como variáveis de ambiente para o pod.Conecte-se ao pod quando ele estiver pronto:
kubectl wait pod postgres-client --for=condition=Ready --timeout=300s -n postgres kubectl exec -it postgres-client -n postgres -- /bin/bash
Conecte-se ao Postgres e tente criar uma nova tabela usando as credenciais
myuser
:PGPASSWORD=$CLIENTPASSWORD psql \ -h my-cluster \ -U $CLIENTUSERNAME \ -d mydatabase \ -c "CREATE TABLE test (id serial PRIMARY KEY, randomdata VARCHAR ( 50 ) NOT NULL);"
O comando falhará com um erro semelhante ao seguinte:
ERROR: permission denied for schema public LINE 1: CREATE TABLE test (id serial PRIMARY KEY, randomdata VARCHAR...
O comando falha porque os usuários sem privilégios atribuídos por padrão só podem fazer login no Postgres e listar bancos de dados.
Crie uma tabela com as credenciais
mydatabaseowner
e conceda todos os privilégios na tabela paramyuser
:PGPASSWORD=$OWNERPASSWORD psql \ -h my-cluster \ -U $OWNERUSERNAME \ -d mydatabase \ -c "CREATE TABLE test (id serial PRIMARY KEY, randomdata VARCHAR ( 50 ) NOT NULL);GRANT ALL ON test TO myuser;GRANT ALL ON SEQUENCE test_id_seq TO myuser;"
O resultado será assim:
CREATE TABLE GRANT GRANT
Insira dados aleatórios na tabela usando credenciais
myuser
:for i in {1..10}; do DATA=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 13) PGPASSWORD=$CLIENTPASSWORD psql \ -h my-cluster \ -U $CLIENTUSERNAME \ -d mydatabase \ -c "INSERT INTO test(randomdata) VALUES ('$DATA');" done
O resultado será assim:
INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1
Acesse os valores que você inseriu:
PGPASSWORD=$CLIENTPASSWORD psql \ -h my-cluster \ -U $CLIENTUSERNAME \ -d mydatabase \ -c "SELECT * FROM test;"
O resultado será assim:
id | randomdata ----+--------------- 1 | jup9HYsAjwtW4 2 | 9rLAyBlcpLgNT 3 | wcXSqxb5Yz75g 4 | KoDRSrx3muD6T 5 | b9atC7RPai7En 6 | 20d7kC8E6Vt1V 7 | GmgNxaWbkevGq 8 | BkTwFWH6hWC7r 9 | nkLXHclkaqkqy 10 | HEebZ9Lp71Nm3 (10 rows)
Saia do shell do pod:
exit
Entender como o Prometheus coleta métricas para seu cluster do Redis
No diagrama a seguir, mostramos como funciona a coleta de métricas do Prometheus:
No diagrama, um cluster particular do GKE contém os seguintes componentes:
- Um pod Postgres que coleta métricas no caminho
/
e na porta9187
. - Coletores baseados em Prometheus que processam as métricas do pod do Postgres.
- Um recurso
PodMonitoring
que envia métricas ao Cloud Monitoring.
O Google Cloud Managed Service para Prometheus é compatível com a coleta de métricas no formato do Prometheus. O Cloud Monitoring usa um painel integrado para métricas do Postgres.
O Zalando expõe as métricas de cluster no formato do Prometheus usando o componente postgres_exporter como um contêiner de arquivo secundário.
Crie o recurso
PodMonitoring
para coletar métricas porlabelSelector
:kubectl apply -n postgres -f manifests/03-prometheus-metrics/pod-monitoring.yaml
No console do Google Cloud , acesse a página Painel de clusters do GKE.
Acessar o painel de clusters do GKE
O painel mostra uma taxa de ingestão de métricas diferente de zero.
No console Google Cloud , acesse a página Painéis.
Abra o painel Visão geral do Prometheus do PostgreSQL. O painel mostra o número de linhas buscadas. Pode levar vários minutos para que o painel seja provisionado automaticamente.
Conecte-se ao pod cliente:
kubectl exec -it postgres-client -n postgres -- /bin/bash
Inserir dados aleatórios:
for i in {1..100}; do DATA=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 13) PGPASSWORD=$CLIENTPASSWORD psql \ -h my-cluster \ -U $CLIENTUSERNAME \ -d mydatabase \ -c "INSERT INTO test(randomdata) VALUES ('$DATA');" done
Atualize a página. Os gráficos de Linhas e Blocos são atualizados para mostrar o estado real do banco de dados.
Saia do shell do pod:
exit