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 point-in-time, fitur keamanan, dan perluasan. PostgreSQL kompatibel dengan sistem operasi utama dan sepenuhnya mematuhi standar ACID (Atomicity, Consistency, Isolation, Durability).

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

Manfaat

CloudNativePG adalah operator open source yang dikembangkan oleh EBD di bawah lisensi Apache 2. Rilis ini menghadirkan fitur berikut ke deployment PostgreSQL:

  • Cara deklaratif dan berbasis Kubernetes untuk mengelola dan mengonfigurasi cluster PostgreSQL dan
  • 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 berkelanjutan untuk rilis kecil 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 dan 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 kemampuan observasi PostgreSQL

Arsitektur deployment

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

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

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

Gugus 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 mendapatkan isolasi resource yang lebih baik dan pendekatan microservice yang direkomendasikan untuk satu database per cluster PostgreSQL. Database dan penggunanya (pengguna aplikasi) yang sesuai ditentukan dalam resource kustom Kubernetes yang mewakili cluster.

  • Penyimpanan adalah komponen penting ketika mendiskusikan {i>database<i}. Penyimpanan harus berperforma efisien, memastikan ketersediaan yang berkelanjutan, dan menjamin konsistensi data. Karena alasan ini, kami merekomendasikan kelas 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. Login ke akun Google Cloud Anda. Jika Anda baru menggunakan Google Cloud, buat akun untuk mengevaluasi performa produk kami dalam skenario dunia nyata. Pelanggan baru juga mendapatkan kredit gratis senilai $300 untuk menjalankan, menguji, dan men-deploy workload.
  2. Menginstal Google Cloud CLI.
  3. Untuk initialize gcloud CLI, jalankan perintah berikut:

    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. Pastikan penagihan telah diaktifkan untuk project Google Cloud Anda.

  6. Enable the Compute Engine, IAM, GKE, Resource Manager APIs:

    gcloud services enable compute.googleapis.com iam.googleapis.com container.googleapis.com cloudresourcemanager.googleapis.com
  7. Menginstal Google Cloud CLI.
  8. Untuk initialize gcloud CLI, jalankan perintah berikut:

    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. Pastikan penagihan telah diaktifkan untuk project Google Cloud Anda.

  11. Enable the Compute Engine, IAM, GKE, Resource Manager APIs:

    gcloud services enable compute.googleapis.com iam.googleapis.com container.googleapis.com cloudresourcemanager.googleapis.com
  12. Berikan peran ke Akun Google Anda. Jalankan perintah berikut satu kali untuk setiap peran IAM berikut: 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:EMAIL_ADDRESS" --role=ROLE
    • Ganti PROJECT_ID dengan project ID Anda.
    • Ganti EMAIL_ADDRESS dengan alamat email Anda.
    • Ganti ROLE dengan setiap peran individual.

Menyiapkan lingkungan Anda

Untuk menyiapkan lingkungan, 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 ID project 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 Standar atau Autopilot.

Standar

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
  • {i>Router<i} untuk mengakses internet melalui NAT
  • Cluster GKE pribadi di region us-central1
  • Kumpulan node 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
  • {i>Router<i} 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

Men-deploy CloudNativePG ke cluster Kubernetes Anda menggunakan chart 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 Postgre

Manifes berikut menjelaskan cluster PostgreSQL seperti yang didefinisikan 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 berkelanjutan:
    • Unsupervised: memperbarui node cluster utama secara mandiri setelah node replika
    • Supervised: peralihan manual diperlukan untuk node cluster utama
  • spec.postgresql: Penggantian parameter file postgres.conf, seperti aturan pg-hba, LDAP, dan persyaratan untuk replika sinkronisasi yang harus dipenuhi.
  • spec.storage: setelan terkait penyimpanan, seperti kelas penyimpanan, ukuran volume, dan setelan write-ahead log.
  • 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 beban kerja 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 dapat 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 telah 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 merepresentasikan cluster PostgreSQL yang dikontrol oleh operator
  • Resource PersistentVolumeClaim dengan Volume Persisten yang terkait
  • 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 mengetahui 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, gunakan Pod tambahan dengan klien PostgreSQL dan kredensial pengguna aplikasi tersinkronisasi 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 Service gke-pg-cluster-rw:

    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. Menyisipkan data ke dalam tabel:

    INSERT INTO travel_agency_clients(client, address, phone)
    VALUES ('Tom', 'Warsaw', '+55555')
    RETURNING *;
    
  6. Lihat data yang telah 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 pembuatan kueri data, tetapi membatasi operasi tulis:

    psql postgresql://$CLIENTUSERNAME:$CLIENTPASSWORD@gke-pg-cluster-ro.pg-ns/app
    
  9. Upaya menyisipkan 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 gugus Postgres

Diagram berikut menunjukkan cara kerja pengumpulan metrik Prometheus:

Dalam diagram, cluster pribadi GKE berisi:

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

Agar metrik dapat dikumpulkan 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 Category, 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, serta menerapkan permintaan baca dan tulis di database, kemudian 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 diaktualkan.

  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 selanjutnya