O guia mostra como usar o operador Postgres da Zalando para implementar clusters Postgres no Google Kubernetes Engine (GKE).
O PostgreSQL é um sistema de base de dados relacional de objetos de código aberto potente com várias décadas de desenvolvimento ativo que lhe valeu uma forte reputação de fiabilidade, robustez de funcionalidades e desempenho.
Este guia destina-se a administradores de plataformas, arquitetos de nuvem e profissionais de operações interessados em executar o PostgreSQL como uma aplicação de base de dados no GKE em vez de usar o Cloud SQL para PostgreSQL.
Configure o seu ambiente
Para configurar o seu ambiente, siga estes passos
Defina variáveis de ambiente:
export PROJECT_ID=PROJECT_ID export KUBERNETES_CLUSTER_PREFIX=postgres export REGION=us-central1
Substitua
PROJECT_ID
pelo seu 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
Crie a infraestrutura do cluster
Nesta secção, executa um script do Terraform para criar um cluster do GKE privado, de alta disponibilidade e regional.
Pode instalar o operador através de um cluster padrão ou do Autopilot.
Standard
O diagrama seguinte mostra um cluster GKE padrão regional privado implementado em três zonas diferentes:
Implemente 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 lhe for pedido, escreva yes
. Este comando pode demorar vários minutos a ser concluído e o cluster a apresentar o estado pronto.
O Terraform cria os seguintes recursos:
- Uma rede VPC e uma sub-rede privada para os nós do Kubernetes
- Um router para aceder à Internet através de NAT
- Um cluster do GKE privado na região de
us-central1
- Um conjunto de nós com o dimensionamento automático ativado (um a dois nós por zona, um nó por zona no mínimo)
- Um
ServiceAccount
com autorizações de registo e monitorização - Cópia de segurança do GKE para recuperação de desastres
- Google Cloud Managed Service for Prometheus para monitorização de clusters
O resultado é semelhante ao seguinte:
...
Apply complete! Resources: 14 added, 0 changed, 0 destroyed.
...
Piloto automático
O diagrama seguinte mostra um cluster do GKE Autopilot regional privado:
Implemente 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 lhe for pedido, escreva yes
. Este comando pode demorar vários minutos a ser concluído e o cluster a apresentar o estado pronto.
O Terraform cria os seguintes recursos:
- Uma rede VPC e uma sub-rede privada para os nós do Kubernetes
- Um router para aceder à Internet através de NAT
- Um cluster do GKE privado na região de
us-central1
- Um
ServiceAccount
com autorização de registo e monitorização - Google Cloud Managed Service for Prometheus para monitorização de clusters
O resultado é semelhante ao seguinte:
...
Apply complete! Resources: 12 added, 0 changed, 0 destroyed.
...
Estabeleça ligação ao cluster
Configure o kubectl
para comunicar com o cluster:
gcloud container clusters get-credentials ${KUBERNETES_CLUSTER_PREFIX}-cluster --location ${REGION}
Implemente o operador Zalando no seu cluster
Implemente o operador Zalando no seu cluster do Kubernetes através de um gráfico Helm.
Adicione o repositório do gráfico Helm do operador Zalando:
helm repo add postgres-operator-charts https://opensource.zalando.com/postgres-operator/charts/postgres-operator
Crie um espaço de nomes para o operador Zalando e o cluster Postgres:
kubectl create ns postgres kubectl create ns zalando
Implemente o operador Zalando através da ferramenta de linha de comandos 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 pode configurar as definições
podAntiAffinity
diretamente no recurso personalizado que representa o cluster do Postgres. Em alternativa, defina aspodAntiAffinity
definições globalmente para todos os clusters do Postgres nas definições do operador.Verifique o estado da implementação do operador Zalando através do Helm:
helm ls -n zalando
O resultado é semelhante ao seguinte:
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
Implemente o Postgres
A configuração básica da instância do cluster Postgres inclui os seguintes componentes:
- Três réplicas do Postgres: um líder e duas réplicas em espera.
- Alocação de recursos de CPU de um pedido de CPU e dois limites de CPU, com 4 GB de pedidos e limites de memória.
- Tolerâncias,
nodeAffinities
etopologySpreadConstraints
configurados para cada carga de trabalho, garantindo a distribuição adequada pelos nós do Kubernetes, usando os respetivos node pools e diferentes zonas de disponibilidade.
Esta configuração representa a configuração mínima necessária para criar um cluster do Postgres pronto para produção.
O manifesto seguinte descreve um cluster do Postgres:
Este manifesto tem os seguintes campos:
spec.teamId
: um prefixo para os objetos de cluster que escolherspec.numberOfInstances
: o número total de instâncias para um clusterspec.users
: a lista de utilizadores com privilégiosspec.databases
: a lista de bases de dados no formatodbname: ownername
spec.postgresql
: parâmetros postgresspec.volume
: parâmetros do disco persistentespec.tolerations
: o modelo de pod de tolerâncias que permite agendar pods de cluster em nóspool-postgres
spec.nodeAffinity
: o modelo de agrupamentonodeAffinity
que indica ao GKE que os agrupamentos preferem ser agendados em nóspool-postgres
.spec.resources
: pedidos e limites para agrupamentos de podsspec.sidecars
: uma lista de contentores auxiliares, que contémpostgres-exporter
Para mais informações, consulte a referência do manifesto do cluster na documentação do Postgres.
Crie um cluster Postgres básico
Crie um novo cluster do Postgres com 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:
- Pedidos e limites de CPU e memória
- Taints e afinidades para distribuir as réplicas de pods aprovisionadas pelos nós do GKE.
- Uma base de dados
- Dois utilizadores com autorizações de proprietário da base de dados
- Um utilizador sem autorizações
Aguarde que o GKE inicie as cargas de trabalho necessárias:
kubectl wait pods -l cluster-name=my-cluster --for condition=Ready --timeout=300s -n postgres
Este comando pode demorar alguns minutos a ser concluído.
Verifique se o GKE criou as cargas de trabalho do Postgres:
kubectl get pod,svc,statefulset,deploy,pdb,secret -n postgres
O resultado é semelhante ao seguinte:
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 pods para o Postgres
- Um
PodDisruptionBudgets
, que garante um mínimo de uma réplica disponível - O
my-cluster
serviço, que segmenta apenas a réplica principal - O serviço
my-cluster-repl
, que expõe a porta do Postgres para ligações recebidas e para replicação entre réplicas do Postgres - O serviço sem interface gráfica
my-cluster-config
para obter a lista de réplicas de pods do Postgres em execução - Informações secretas com credenciais de utilizador para aceder à base de dados e à replicação entre nós do Postgres
Autentique-se no Postgres
Pode criar utilizadores do Postgres e atribuir-lhes autorizações de base de dados. Por exemplo, o seguinte manifesto descreve um recurso personalizado que atribui utilizadores e funções:
apiVersion: "acid.zalan.do/v1"
kind: postgresql
metadata:
name: my-cluster
spec:
...
users:
mydatabaseowner:
- superuser
- createdb
myuser: []
databases:
mydatabase: mydatabaseowner
Neste manifesto:
- O utilizador
mydatabaseowner
tem as funçõesSUPERUSER
eCREATEDB
, que permitem direitos de administrador completos (ou seja, gerir a configuração do Postgres, criar novas bases de dados, tabelas e utilizadores). Não deve partilhar este utilizador com os clientes. Por exemplo, o Cloud SQL não permite que os clientes tenham acesso a utilizadores com a funçãoSUPERUSER
. - O utilizador
myuser
não tem funções atribuídas. Isto segue a prática recomendada de usar oSUPERUSER
para criar utilizadores com o mínimo de privilégios. Os direitos detalhados são concedidos amyuser
pormydatabaseowner
. Para manter a segurança, só deve partilhar credenciaismyuser
com aplicações cliente.
Armazene palavras-passe
Deve usar o scram-sha-256
método recomendado para armazenar palavras-passe. Por exemplo, o seguinte manifesto descreve um recurso personalizado que especifica a encriptação scram-sha-256
através do campo postgresql.parameters.password_encryption
:
apiVersion: "acid.zalan.do/v1"
kind: postgresql
metadata:
name: my-cluster
spec:
...
postgresql:
parameters:
password_encryption: scram-sha-256
Rode as credenciais de utilizador
Pode
rodar as credenciais do utilizador
armazenadas em segredos do Kubernetes com o Zalando. Por exemplo, o seguinte manifesto descreve um recurso personalizado que define a rotação das credenciais do utilizador através do campo usersWithSecretRotation
:
apiVersion: "acid.zalan.do/v1"
kind: postgresql
metadata:
name: my-cluster
spec:
...
usersWithSecretRotation:
- myuser
- myanotheruser
- ...
Exemplo de autenticação: ligue-se ao Postgres
Esta secção mostra-lhe como implementar um exemplo de cliente Postgres e estabelecer ligação à base de dados através da palavra-passe de um segredo 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 utilizadores
myuser
emydatabaseowner
são retiradas dos segredos relacionados e montadas como variáveis de ambiente no pod.Ligue-se ao Pod quando estiver pronto:
kubectl wait pod postgres-client --for=condition=Ready --timeout=300s -n postgres kubectl exec -it postgres-client -n postgres -- /bin/bash
Associe-se ao Postgres e tente criar uma nova tabela com as seguintes
myuser
credenciais: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 deve 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 utilizadores sem privilégios atribuídos por predefinição só podem iniciar sessão no Postgres e listar bases de dados.
Crie uma tabela com as credenciais
mydatabaseowner
e conceda todos os privilégios na tabela amyuser
: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 é semelhante ao seguinte:
CREATE TABLE GRANT GRANT
Insira dados aleatórios na tabela com as 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 é semelhante ao seguinte:
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
Obtenha os valores que inseriu:
PGPASSWORD=$CLIENTPASSWORD psql \ -h my-cluster \ -U $CLIENTUSERNAME \ -d mydatabase \ -c "SELECT * FROM test;"
O resultado é semelhante ao seguinte:
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 da shell do Pod:
exit
Compreenda como o Prometheus recolhe métricas para o seu cluster do Postgres
O diagrama seguinte mostra como funciona a recolha de métricas do Prometheus:
No diagrama, um cluster privado do GKE contém:
- Um pod do Postgres que recolhe métricas no caminho
/
e na porta9187
- Recolhedores baseados no Prometheus que processam as métricas do pod do Postgres
- Um recurso
PodMonitoring
que envia métricas para o Cloud Monitoring
O Google Cloud Managed Service for Prometheus suporta a recolha de métricas no formato Prometheus. O Cloud Monitoring usa um painel de controlo integrado para métricas do Postgres.
A Zalando expõe métricas de cluster no formato Prometheus através do componente postgres_exporter como um contentor sidecar.
Crie o recurso
PodMonitoring
para extrair métricas porlabelSelector
:kubectl apply -n postgres -f manifests/03-prometheus-metrics/pod-monitoring.yaml
Na Google Cloud consola, aceda à página Painel de controlo de clusters do GKE.
Aceda ao painel de controlo de clusters do GKE
O painel de controlo mostra uma taxa de carregamento de métricas diferente de zero.
Na Google Cloud consola, aceda à página Painéis de controlo.
Abra o painel de controlo de vista geral do PostgreSQL Prometheus. O painel de controlo mostra o número de linhas obtidas. O aprovisionamento automático do painel de controlo pode demorar vários minutos.
Ligue-se ao pod do 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 Linhas e Blocos são atualizados para mostrar o estado real da base de dados.
Saia da shell do Pod:
exit