Men-deploy PostgreSQL ke GKE menggunakan CloudNativePG


Panduan ini menunjukkan cara men-deploy cluster PostgreSQL di Google Kubernetes Engine (GKE) menggunakan operator CloudNativePG.

PostgreSQL adalah database relasional objek open source dengan pengembangan aktif selama beberapa dekade, yang memastikan performa klien yang stabil. Layanan ini menawarkan berbagai fitur, termasuk replikasi, pemulihan titik waktu, fitur keamanan, dan kemampuan untuk diperluas. PostgreSQL kompatibel dengan sistem operasi utama dan sepenuhnya mematuhi standar ACID (Atomicity, Consistency, Isolation, Durability).

Panduan ini ditujukan untuk administrator platform, arsitek cloud, dan tenaga profesional operasi yang tertarik untuk men-deploy cluster Postgres di GKE. Menjalankan Postgres di GKE, bukan menggunakan Cloud SQL, dapat memberikan lebih banyak fleksibilitas dan kontrol konfigurasi kepada administrator database yang berpengalaman.

Manfaat

CloudNativePG adalah operator open source yang dikembangkan oleh EDB berdasarkan lisensi Apache 2. Fitur ini menghadirkan fitur berikut ke deployment PostgreSQL:

  • Cara deklaratif dan native Kubernetes untuk mengelola dan mengonfigurasi serta cluster PostgreSQL
  • Pengelolaan pencadangan menggunakan snapshot volume atau Cloud Storage
  • Koneksi TLS terenkripsi dalam pengiriman, kemampuan untuk menggunakan certificate authority Anda sendiri, dan integrasi dengan Certificate Manager untuk penerbitan dan rotasi sertifikat TLS otomatis
  • Update rolling untuk rilis minor PostgreSQL
  • Penggunaan server Kubernetes API untuk mempertahankan status cluster PostgreSQL dan failover untuk ketersediaan tinggi tanpa memerlukan alat tambahan
  • Konfigurasi pengekspor Prometheus bawaan melalui metrik yang ditentukan pengguna yang ditulis dalam SQL

Tujuan

  • Merencanakan dan men-deploy infrastruktur GKE untuk Postgres
  • Men-deploy dan mengonfigurasi operator Postgres CloudNativePG dengan Helm
  • Men-deploy cluster PostgreSQL
  • Mengonfigurasi autentikasi dan visibilitas PostgreSQL

Arsitektur deployment

PostgreSQL memiliki berbagai opsi deployment dari server database mandiri ke cluster yang direplikasi dan sangat tersedia. Tutorial ini berfokus pada deployment cluster yang sangat tersedia ke GKE.

Dalam deployment ini, beban kerja cluster PostgreSQL didistribusikan di beberapa zona ketersediaan dalam cluster GKE regional, sehingga memastikan ketersediaan dan redundansi yang tinggi. Untuk mengetahui informasi selengkapnya, lihat cluster regional.

Diagram berikut menunjukkan cluster Postgres yang berjalan di beberapa node dan zona dalam cluster GKE:

Cluster Postgres di GKE

  • Penyiapan default mencakup satu server PostgreSQL utama dan dua server cadangan yang siap mengambil alih jika server utama gagal, sehingga memastikan ketersediaan database yang berkelanjutan.

  • Resource operator CloudNativePG menggunakan namespace terpisah dari cluster GKE untuk isolasi resource yang lebih baik dan pendekatan microservice yang direkomendasikan dari satu database per cluster PostgreSQL. Database dan pengguna yang sesuai (pengguna aplikasi) ditentukan dalam resource kustom Kubernetes yang mewakili cluster.

  • Penyimpanan adalah komponen penting saat membahas database. Penyimpanan harus berperforma efisien, memastikan ketersediaan berkelanjutan, dan menjamin konsistensi data. Karena alasan ini, sebaiknya gunakan class penyimpanan premium-rwo, yang didasarkan pada disk SSD. Operator CloudNativePG secara otomatis membuat PersistentVolumeClaims sesuai kebutuhan saat menyiapkan Pod untuk cluster PostgreSQL.

Biaya

Dalam dokumen ini, Anda menggunakan komponen Google Cloud yang dapat ditagih berikut:

Untuk membuat perkiraan biaya berdasarkan proyeksi penggunaan Anda, gunakan kalkulator harga. Pengguna baru Google Cloud mungkin memenuhi syarat untuk mendapatkan uji coba gratis.

Setelah menyelesaikan tugas yang dijelaskan dalam dokumen ini, Anda dapat menghindari penagihan berkelanjutan dengan menghapus resource yang Anda buat. Untuk mengetahui informasi selengkapnya, lihat Pembersihan.

Sebelum memulai

Cloud Shell telah diinstal dengan software yang Anda perlukan untuk tutorial ini, termasuk kubectl, gcloud CLI, Helm, dan Terraform. Jika tidak menggunakan Cloud Shell, Anda harus menginstal gcloud CLI.

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. Install the Google Cloud CLI.
  3. To initialize the gcloud CLI, run the following command:

    gcloud init
  4. Buat atau pilih project Google Cloud.

    • Membuat project Google Cloud:

      gcloud projects create PROJECT_ID

      Ganti PROJECT_ID dengan nama untuk project Google Cloud yang Anda buat.

    • Pilih project Google Cloud yang Anda buat:

      gcloud config set project PROJECT_ID

      Ganti PROJECT_ID dengan nama project Google Cloud Anda.

  5. Make sure that billing is enabled for your Google Cloud project.

  6. Aktifkan API Compute Engine, IAM, GKE, Resource Manager:

    gcloud services enable compute.googleapis.com iam.googleapis.com container.googleapis.com cloudresourcemanager.googleapis.com
  7. Install the Google Cloud CLI.
  8. To initialize the gcloud CLI, run the following command:

    gcloud init
  9. Buat atau pilih project Google Cloud.

    • Membuat project Google Cloud:

      gcloud projects create PROJECT_ID

      Ganti PROJECT_ID dengan nama untuk project Google Cloud yang Anda buat.

    • Pilih project Google Cloud yang Anda buat:

      gcloud config set project PROJECT_ID

      Ganti PROJECT_ID dengan nama project Google Cloud Anda.

  10. Make sure that billing is enabled for your Google Cloud project.

  11. Aktifkan API Compute Engine, IAM, GKE, Resource Manager:

    gcloud services enable compute.googleapis.com iam.googleapis.com container.googleapis.com cloudresourcemanager.googleapis.com
  12. Grant roles to your user account. Run the following command once for each of the following IAM roles: roles/compute.securityAdmin, roles/compute.viewer, roles/container.clusterAdmin, roles/container.admin, roles/iam.serviceAccountAdmin, roles/iam.serviceAccountUser

    gcloud projects add-iam-policy-binding PROJECT_ID --member="user:USER_IDENTIFIER" --role=ROLE
    • Replace PROJECT_ID with your project ID.
    • Replace USER_IDENTIFIER with the identifier for your user account. For example, user:myemail@example.com.

    • Replace ROLE with each individual role.

Menyiapkan lingkungan Anda

Untuk menyiapkan lingkungan Anda, ikuti langkah-langkah berikut:

  1. Menetapkan variabel lingkungan:

    export PROJECT_ID=PROJECT_ID
    export KUBERNETES_CLUSTER_PREFIX=postgres
    export REGION=us-central1
    

    Ganti PROJECT_ID dengan project ID Google Cloud Anda.

  2. Buat clone repositori GitHub:

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
    
  3. Ubah ke direktori kerja:

    cd kubernetes-engine-samples/databases/postgresql-cloudnativepg
    

Membuat infrastruktur cluster

Di bagian ini, Anda akan menjalankan skrip Terraform untuk membuat cluster GKE regional pribadi yang sangat tersedia.

Anda dapat menginstal operator menggunakan cluster Standard atau Autopilot.

Standard

Diagram berikut menunjukkan cluster GKE Standard regional pribadi yang di-deploy ke tiga zona yang berbeda:

Untuk men-deploy infrastruktur ini, jalankan perintah berikut:

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}

Saat diminta, ketik yes. Anda mungkin perlu menunggu beberapa menit agar perintah ini selesai dan cluster akan menampilkan status siap.

Terraform membuat resource berikut:

  • Jaringan VPC dan subnet pribadi untuk node Kubernetes
  • Router untuk mengakses internet melalui NAT
  • Cluster GKE pribadi di region us-central1
  • Node pool dengan penskalaan otomatis diaktifkan (satu hingga dua node per zona, minimum satu node per zona)

Outputnya mirip dengan hal berikut ini:

...
Apply complete! Resources: 14 added, 0 changed, 0 destroyed.
...

Autopilot

Diagram berikut menunjukkan cluster GKE Autopilot regional pribadi:

Untuk men-deploy infrastruktur, jalankan perintah berikut:

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}

Saat diminta, ketik yes. Anda mungkin perlu menunggu beberapa menit agar perintah ini selesai dan cluster akan menampilkan status siap.

Terraform membuat resource berikut:

  • Jaringan VPC dan subnet pribadi untuk node Kubernetes
  • Router untuk mengakses internet melalui NAT
  • Cluster GKE pribadi di region us-central1
  • ServiceAccount dengan izin logging dan pemantauan
  • Google Cloud Managed Service for Prometheus untuk pemantauan cluster

Outputnya mirip dengan hal berikut ini:

...
Apply complete! Resources: 12 added, 0 changed, 0 destroyed.
...

Hubungkan ke cluster

Konfigurasi kubectl untuk berkomunikasi dengan cluster:

gcloud container clusters get-credentials ${KUBERNETES_CLUSTER_PREFIX}-cluster --region ${REGION}

Men-deploy operator CloudNativePG

Deploy CloudNativePG ke cluster Kubernetes Anda menggunakan diagram Helm:

  1. Tambahkan repositori Helm Chart operator CloudNativePG:

    helm repo add cnpg https://cloudnative-pg.github.io/charts
    
  2. Deploy operator CloudNativePG menggunakan alat command line Helm:

    helm upgrade --install cnpg \
        --namespace cnpg-system \
        --create-namespace \
        cnpg/cloudnative-pg
    

    Outputnya mirip dengan hal berikut ini:

    Release "cnpg" does not exist. Installing it now.
    NAME: cnpg
    LAST DEPLOYED: Fri Oct 13 13:52:36 2023
    NAMESPACE: cnpg-system
    STATUS: deployed
    REVISION: 1
    TEST SUITE: None
    ...
    

Men-deploy Postgres

Manifes berikut menjelaskan cluster PostgreSQL seperti yang ditentukan oleh resource kustom operator CloudNativePG:

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: gke-pg-cluster
spec:
  description: "Standard GKE PostgreSQL cluster"
  imageName: ghcr.io/cloudnative-pg/postgresql:16.2
  enableSuperuserAccess: true
  instances: 3
  startDelay: 300
  primaryUpdateStrategy: unsupervised
  postgresql:
    pg_hba:
      - host all all 10.48.0.0/20 md5
  bootstrap:
    initdb:
      database: app
  storage:
    storageClass: premium-rwo
    size: 2Gi
  resources:
    requests:
      memory: "1Gi"
      cpu: "1000m"
    limits:
      memory: "1Gi"
      cpu: "1000m"
  affinity:
    enablePodAntiAffinity: true
    tolerations:
    - key: cnpg.io/cluster
      effect: NoSchedule
      value: gke-pg-cluster
      operator: Equal
    additionalPodAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: app.component
              operator: In
              values:
              - "pg-cluster"
          topologyKey: topology.kubernetes.io/zone
  monitoring:
    enablePodMonitor: true

Manifes ini memiliki kolom berikut:

  • spec.instances: jumlah Pod cluster
  • spec.primaryUpdateStrategy: strategi update bertahap:
    • Unsupervised: mengupdate node cluster utama secara mandiri setelah node replika
    • Supervised: pengalihan manual diperlukan untuk node cluster utama
  • spec.postgresql: Penggantian parameter file postgres.conf, seperti aturan pg-hba, LDAP, dan persyaratan agar replika sinkronisasi terpenuhi.
  • spec.storage: setelan terkait penyimpanan, seperti class penyimpanan, ukuran volume, dan setelan log tulis-di-depan.
  • spec.bootstrap: parameter database awal yang dibuat di cluster, kredensial pengguna, dan opsi pemulihan database
  • spec.resources: permintaan dan batas untuk Pod cluster
  • spec.affinity: aturan afinitas dan anti-afinitas dari workload cluster

Membuat cluster Postgres dasar

  1. Buat namespace

    kubectl create ns pg-ns
    
  2. Buat cluster PostgreSQL menggunakan resource kustom:

    kubectl apply -n pg-ns -f manifests/01-basic-cluster/postgreSQL_cluster.yaml
    

    Pemrosesan perintah ini mungkin memerlukan waktu beberapa menit.

  3. Periksa status cluster:

    kubectl get cluster -n pg-ns --watch
    

    Tunggu hingga output menampilkan status Cluster in healthy state sebelum Anda melanjutkan ke langkah berikutnya.

    NAME             AGE     INSTANCES   READY   STATUS                     PRIMARY
    gke-pg-cluster   2m53s   3           3       Cluster in healthy state   gke-pg-cluster-1
    

Memeriksa resource

Pastikan GKE membuat resource untuk cluster:

kubectl get cluster,pod,svc,pvc,pdb,secret,cm -n pg-ns

Outputnya mirip dengan hal berikut ini:

NAME                                        AGE   INSTANCES   READY   STATUS                     PRIMARY
cluster.postgresql.cnpg.io/gke-pg-cluster   32m   3           3       Cluster in healthy state   gke-pg-cluster-1

NAME                   READY   STATUS    RESTARTS   AGE
pod/gke-pg-cluster-1   1/1     Running   0          31m
pod/gke-pg-cluster-2   1/1     Running   0          30m
pod/gke-pg-cluster-3   1/1     Running   0          29m

NAME                        TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE
service/gke-pg-cluster-r    ClusterIP   10.52.11.24   <none>        5432/TCP   32m
service/gke-pg-cluster-ro   ClusterIP   10.52.9.233   <none>        5432/TCP   32m
service/gke-pg-cluster-rw   ClusterIP   10.52.1.135   <none>        5432/TCP   32m

NAME                                     STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/gke-pg-cluster-1   Bound    pvc-bbdd1cdd-bdd9-4e7c-8f8c-1a14a87e5329   2Gi        RWO            standard       32m
persistentvolumeclaim/gke-pg-cluster-2   Bound    pvc-e7a8b4df-6a3e-43ce-beb0-b54ec1d24011   2Gi        RWO            standard       31m
persistentvolumeclaim/gke-pg-cluster-3   Bound    pvc-dac7f931-6ac5-425f-ac61-0cfc55aae72f   2Gi        RWO            standard       30m

NAME                                                MIN AVAILABLE   MAX UNAVAILABLE   ALLOWED DISRUPTIONS   AGE
poddisruptionbudget.policy/gke-pg-cluster           1               N/A               1                     32m
poddisruptionbudget.policy/gke-pg-cluster-primary   1               N/A               0                     32m

NAME                                TYPE                       DATA   AGE
secret/gke-pg-cluster-app           kubernetes.io/basic-auth   3      32m
secret/gke-pg-cluster-ca            Opaque                     2      32m
secret/gke-pg-cluster-replication   kubernetes.io/tls          2      32m
secret/gke-pg-cluster-server        kubernetes.io/tls          2      32m
secret/gke-pg-cluster-superuser     kubernetes.io/basic-auth   3      32m

NAME                                DATA   AGE
configmap/cnpg-default-monitoring   1      32m
configmap/kube-root-ca.crt          1      135m

Operator membuat resource berikut:

  • Resource kustom cluster yang mewakili cluster PostgreSQL yang dikontrol oleh operator
  • Resource PersistentVolumeClaim dengan Volume Persisten yang sesuai
  • Secret dengan kredensial pengguna untuk mengakses database dan replikasi di antara node Postgres.
  • Tiga layanan endpoint database: <name>-rw, <name>-ro, dan <name>-r untuk terhubung ke cluster. Untuk informasi selengkapnya, lihat Arsitektur PostgreSQL.

Melakukan autentikasi ke Postgres

Anda dapat terhubung ke database PostgreSQL dan memeriksa akses melalui berbagai endpoint layanan yang dibuat oleh operator. Untuk melakukannya, Anda menggunakan Pod tambahan dengan klien PostgreSQL dan kredensial pengguna aplikasi yang disinkronkan yang dipasang sebagai variabel lingkungan.

  1. Jalankan Pod klien untuk berinteraksi dengan cluster Postgres Anda:

    kubectl apply -n pg-ns -f manifests/02-auth/pg-client.yaml
    
  2. Jalankan perintah exec di Pod pg-client dan login ke Layanan gke-pg-cluster-rw:

    kubectl wait --for=condition=Ready -n pg-ns pod/pg-client --timeout=300s
    kubectl exec -n pg-ns -i -t pg-client -- /bin/sh
    
  3. Login ke database menggunakan Layanan gke-pg-cluster-rw untuk membuat koneksi dengan hak istimewa Baca-Tulis:

    psql postgresql://$CLIENTUSERNAME:$CLIENTPASSWORD@gke-pg-cluster-rw.pg-ns/app
    

    Terminal dimulai dengan nama database Anda:

    app=>
    
  4. Buat tabel:

    CREATE TABLE travel_agency_clients (
    client VARCHAR ( 50 ) UNIQUE NOT NULL,
    address VARCHAR ( 50 ) UNIQUE NOT NULL,
    phone VARCHAR ( 50 ) UNIQUE NOT NULL);
    
  5. Sisipkan data ke dalam tabel:

    INSERT INTO travel_agency_clients(client, address, phone)
    VALUES ('Tom', 'Warsaw', '+55555')
    RETURNING *;
    
  6. Lihat data yang Anda buat:

    SELECT * FROM travel_agency_clients ;
    

    Outputnya mirip dengan hal berikut ini:

    client | address |  phone
    --------+---------+---------
    Tom    | Warsaw  | +55555
    (1 row)
    
  7. Logout dari sesi database saat ini:

    exit
    
  8. Login ke database menggunakan Layanan gke-pg-cluster-ro untuk memverifikasi akses hanya baca. Layanan ini mengizinkan kueri data, tetapi membatasi operasi menulis:

    psql postgresql://$CLIENTUSERNAME:$CLIENTPASSWORD@gke-pg-cluster-ro.pg-ns/app
    
  9. Coba masukkan data baru:

    INSERT INTO travel_agency_clients(client, address, phone)
    VALUES ('John', 'Paris', '+55555')
    RETURNING *;
    

    Outputnya mirip dengan hal berikut ini:

    ERROR:  cannot execute INSERT in a read-only transaction
    
  10. Mencoba membaca data:

    SELECT * FROM travel_agency_clients ;
    

    Outputnya mirip dengan hal berikut ini:

    client | address |  phone
    --------+---------+---------
    Tom    | Warsaw  | +55555
    (1 row)
    
  11. Logout dari sesi database saat ini:

    exit
    
  12. Keluar dari shell Pod:

    exit
    

Memahami cara Prometheus mengumpulkan metrik untuk cluster Postgres Anda

Diagram berikut menunjukkan cara kerja pengumpulan metrik Prometheus:

Dalam diagram, cluster pribadi GKE berisi:

  • Pod Postgres yang mengumpulkan metrik di jalur / dan port 9187
  • Pengumpul berbasis Prometheus yang memproses metrik dari Pod Postgres
  • Resource PodMonitoring yang mengirim metrik ke Cloud Monitoring

Untuk mengaktifkan pengumpulan metrik dari Pod Anda, lakukan langkah-langkah berikut:

  1. Buat resource PodMonitoring:

    kubectl apply -f manifests/03-observability/pod-monitoring.yaml -n pg-ns
    
  2. Di konsol Google Cloud, buka halaman Metrics Explorer:

    Buka Metrics Explorer

    Dasbor menampilkan rasio penyerapan metrik yang bukan nol.

  3. Di Select a metric, masukkan Prometheus Target.

  4. Di bagian Active Metric Categories, pilih Cnpg.

Membuat dasbor metrik

Untuk memvisualisasikan metrik yang diekspor, buat dasbor metrik.

  1. Men-deploy dasbor:

    gcloud --project "${PROJECT_ID}" monitoring dashboards create --config-from-file manifests/03-observability/gcp-pg.json
    
  2. Di Konsol Google Cloud, buka halaman Dashboards.

    Buka Dashboards

  3. Pilih dasbor PostgresQL Prometheus Overview.

    Untuk meninjau cara dasbor memantau fungsi, Anda dapat menggunakan kembali tindakan dari bagian Autentikasi database, dan menerapkan permintaan baca dan tulis pada database, lalu meninjau visualisasi metrik yang dikumpulkan di dasbor.

  4. Menghubungkan ke Pod klien:

    kubectl exec -n pg-ns -i -t pg-client -- /bin/sh
    
  5. Menyisipkan data acak:

    psql postgresql://$CLIENTUSERNAME:$CLIENTPASSWORD@gke-pg-cluster-rw.pg-ns/app -c "CREATE TABLE test (id serial PRIMARY KEY, randomdata VARCHAR ( 50 ) NOT NULL);INSERT INTO test (randomdata) VALUES (generate_series(1, 1000));"
    
  6. Muat ulang dasbor. Grafik diperbarui dengan metrik yang aktual.

  7. Keluar dari shell Pod:

    exit
    

Pembersihan

Menghapus project

    Menghapus project Google Cloud:

    gcloud projects delete PROJECT_ID

Menghapus resource satu per satu

  1. Menetapkan variabel lingkungan.

    export PROJECT_ID=${PROJECT_ID}
    export KUBERNETES_CLUSTER_PREFIX=postgres
    export REGION=us-central1
    
  2. Jalankan perintah terraform destroy:

    export GOOGLE_OAUTH_ACCESS_TOKEN=$(gcloud auth print-access-token)
    terraform  -chdir=terraform/FOLDER destroy \
      -var project_id=${PROJECT_ID} \
      -var region=${REGION} \
      -var cluster_prefix=${KUBERNETES_CLUSTER_PREFIX}
    

    Ganti FOLDER dengan gke-autopilot atau gke-standard.

    Saat diminta, ketik yes.

  3. Temukan semua disk yang tidak terpasang:

    export disk_list=$(gcloud compute disks list --filter="-users:* AND labels.name=${KUBERNETES_CLUSTER_PREFIX}-cluster" --format "value[separator=|](name,zone)")
    
  4. Hapus disk:

    for i in $disk_list; do
      disk_name=$(echo $i| cut -d'|' -f1)
      disk_zone=$(echo $i| cut -d'|' -f2|sed 's|.*/||')
      echo "Deleting $disk_name"
      gcloud compute disks delete $disk_name --zone $disk_zone --quiet
    done
    

Langkah berikutnya