Senin, 09 September 2024

KUBERNETES-operator dg zalando

 

Pengalaman kami dengan Operator Postgres untuk Kubernetes oleh Zalando

Upaya kami dalam menganalisis operator Kubernetes yang ada untuk PostgreSQL menghasilkan  perbandingan ini . Dan sekarang kami ingin berbagi pengalaman praktis dan pelajaran menarik yang kami peroleh saat menggunakan solusi pilihan kami — Operator Postgres oleh Zalando .

Menginstal dan memulai

Untuk menerapkan operator, unduh rilis terkini dari GitHub dan terapkan file YAML dari  direktori manifests . Atau, Anda dapat menggunakan  OperatorHub .

Setelah instalasi selesai, lanjutkan ke pengaturan penyimpanan log dan cadangan . Hal ini dilakukan melalui  postgres-operatorConfigMap di namespace tempat operator diinstal. Baiklah, mari kita lanjutkan ke penerapan klaster PostgreSQL pertama.

Berikut manifest penyebaran kami:

apiVersion: acid.zalan.do/v1
kind: postgresql
metadata:
 name: staging-db
spec:
 numberOfInstances: 3
 patroni:
   synchronous_mode: true
 postgresql:
   version: "12"
 resources:
   limits:
     cpu: 100m
     memory: 1Gi
   requests:
     cpu: 100m
     memory: 1Gi
 sidecars:
 - env:
   - name: DATA_SOURCE_URI
     value: 127.0.0.1:5432
   - name: DATA_SOURCE_PASS
     valueFrom:
       secretKeyRef:
         key: password
         name: postgres.staging-db.credentials
   - name: DATA_SOURCE_USER
     value: postgres
   image: wrouesnel/postgres_exporter
   name: prometheus-exporter
   resources:
     limits:
       cpu: 500m
       memory: 100Mi
     requests:
       cpu: 100m
       memory: 100Mi
 teamId: staging
 volume:
   size: 2Gi

Manifes ini membuat kluster yang terdiri dari tiga instans dengan kontainer sidecar postgres_exporter terlampir yang digunakan untuk mengekspor metrik server PostgreSQL. Seperti yang dapat Anda lihat, prosesnya sangat mudah, dan Anda dapat menyebarkan kluster sebanyak yang Anda inginkan.

Yang perlu diperhatikan adalah  antarmuka grafis “untuk pengalaman pengguna database-sebagai-layanan yang nyaman” yang disebut postgres-operator-ui . Antarmuka ini dibundel dengan operator dan memungkinkan Anda membuat dan menghapus kluster serta mengelola dan memulihkan cadangan operator.

Daftar cluster PostgreSQL
Mengelola cadangan

Fitur lain yang mengesankan dari operator ini adalah dukungan untuk  Teams API . Teams API secara otomatis membuat peran PostgreSQL menggunakan daftar nama pengguna. Kemudian, ia dapat menampilkan daftar pengguna yang perannya dibuat secara otomatis.

Masalah dan solusi

Namun, kami mencatat beberapa kekurangan yang mendesak pada operator:

  • ketidakmampuan untuk menonaktifkan cadangan;
  • masalah dengan kluster PostgreSQL sinkron;
  • hak istimewa tidak ditetapkan secara default saat membuat database;
  • terkadang, dokumentasinya tidak tersedia atau sudah kedaluwarsa.

Untungnya, banyak di antaranya yang dapat dipecahkan. Mari kita mulai dari akhir ( dokumentasinya kurang baik ) dan lanjutkan ke awal daftar.

Suatu hari, Anda mungkin menemukan bahwa tidak ada deskripsi terperinci dalam dokumentasi tentang cara mendaftarkan cadangan dalam konfigurasi dan cara menghubungkan bucket cadangan ke UI Operator. PR ini dapat membantu Anda dalam memecahkan masalah ini:

  • Anda harus membuat rahasia;
  • dan meneruskannya ke  pod_environment_secret_nameparameter yang ditentukan dalam CRD pengaturan operator atau dalam ConfigMap (tergantung pada cara operator diinstal).

Namun, ternyata hal ini tidak memungkinkan. Itulah sebabnya kami membuat versi operator kami sendiri dengan beberapa tambahan dari pihak ketiga; di bawah ini, Anda akan menemukan informasi lebih lanjut mengenai hal tersebut.

Jika Anda meneruskan parameter cadangan ke operator (yaitu, wal_s3_bucketdan kunci untuk mengakses AWS S3), operator akan membuat cadangan basis data produksi dan pementasan. Kami sama sekali tidak menyukai perilaku seperti itu.

Namun, kami menemukan celah menarik dalam deskripsi parameter Spilo (Spilo adalah pembungkus Docker dasar untuk PgSQL): ternyata, Anda dapat meneruskan WAL_S3_BUCKETparameter kosong, sehingga menonaktifkan pencadangan. Untungnya, kami menemukan  PR siap pakai yang mengimplementasikan fungsionalitas tersebut, dan kami segera menggabungkannya ke dalam fork kami. Sekarang Anda hanya perlu menambahkan parameter  enableWALArchiving: falseke konfigurasi sumber daya klaster PostgreSQL.

Sebenarnya, ada pilihan lain: kita dapat menjalankan dua operator terpisah, satu untuk lingkungan staging (dengan pencadangan dinonaktifkan) dan satu lagi untuk lingkungan produksi. Namun, cara yang kita pilih membantu kita menangani semuanya hanya dengan satu operator.

Oke, kami telah menemukan cara untuk menentukan parameter S3 dalam konfigurasi basis data, dan cadangan mulai masuk ke penyimpanan. Namun, bagaimana Anda mengonfigurasi UI Operator agar berfungsi dengan cadangan?

Ternyata, Anda perlu menambahkan tiga variabel berikut ke UI Operator:

  • SPILO_S3_BACKUP_BUCKET
  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY

Setelah itu, Anda akan dapat mengelola cadangan. Dalam kasus kami, ini menyederhanakan pengoperasian lingkungan pementasan, yang memungkinkan Anda menambahkan snapshot produksi ke dalamnya tanpa skrip tambahan.

Di atas, kami menyebutkan Teams API dan opsi ekstensifnya untuk membuat basis data dan peran menggunakan operator sebagai keuntungan yang jelas. Namun, peran  yang dibuat tidak memiliki hak istimewa yang sesuai secara default . Dengan kata lain, pengguna dengan akses "baca" tidak dapat membaca tabel baru.

Mengapa demikian? Masalahnya adalah, meskipun kode tersebut telah menetapkan semua GRANT yang diperlukan, GRANT tersebut tidak selalu diterapkan. Ada 2 metode: syncPreparedDatabasesdan  syncDatabases. Metode ini  syncPreparedDatabasestidak menerapkan hak istimewa secara default (meskipun kunci defaultRolesdan  defaultUsersditetapkan di  preparedDatabasesbagian manifes). Saat ini, kami sedang mempersiapkan patch untuk menetapkan hak istimewa ini secara otomatis.

Masalah yang disebutkan dengan kluster PgSQL sinkron dilaporkan di sini .

Apa yang kita dapatkan pada akhirnya?

Saat mencoba memecahkan semua masalah ini, Operator Postgres oleh Zalando di-fork di sini , tempat kami menerapkan semua patch yang diperlukan. Dan kami juga telah membangun  image Docker demi kenyamanan.

Berikut adalah daftar PR yang digabungkan ke dalam fork kami:

Harap dukung PR ini agar dapat masuk ke hulu pada versi operator berikutnya (1.7).

Migrasi produksi: kisah sukses kami

Sementara itu, kami ingin berbagi pengalaman migrasi kami. Ya, ada cara untuk memigrasikan produksi yang aktif dan berjalan dengan waktu henti minimal menggunakan Operator Zalando Postgres dan templat Patroni.

Dengan citra Spilo Docker, Anda dapat menyebarkan klaster siaga menggunakan penyimpanan S3 dan  WAL-E . Dalam kasus ini, log biner PgSQL pertama-tama disimpan ke penyimpanan S3, lalu ditarik oleh replika. Namun, bagaimana jika Anda tidak memiliki WAL-E di infrastruktur lama?

Dalam kasus ini, Anda dapat menggunakan replikasi logis PostgreSQL. Namun, kami tidak akan membahas detail pembuatan publikasi/langganan untuk ini, karena... yah, rencana kami telah gagal.

Masalahnya adalah basis data kami memiliki beberapa tabel yang sangat banyak memuat jutaan baris, dan baris-baris ini terus diperbarui dan dihapus. Langganancopy_data berbasis sederhana (ketika replika baru menyalin semua data dari master) tidak dapat mengimbangi master. Ia menyalin konten selama seminggu penuh tetapi tidak pernah mengejar master. Pada akhirnya, kami menggunakan metode  yang diusulkan oleh rekan-rekan Avito kami: kami mentransfer data menggunakan . Jadi, berikut ini versi algoritme mereka (yang sedikit dimodifikasi).pg_dump

Idenya adalah membuat langganan "kosong" yang ditautkan ke slot replikasi yang ada, lalu memperbaiki nomor LSN. Dalam kasus kami, ada dua replika produksi. Ini penting karena replika dapat membantu Anda membuat dump yang konsisten dan terus mendapatkan data dari master.

Kami akan menggunakan penunjukan host berikut saat menjelaskan proses migrasi:

  • master — server sumber;
  • replica1 — replika streaming dalam produksi “lama”;
  • replica2 — replika logis yang baru.

Rencana migrasi

  1. Buat langganan ke semua tabel dalam  publicskema database  dbnamedi master:
    psql -h master -d dbname -c "CREATE PUBLICATION dbname FOR ALL TABLES;"
  2. Buat slot replikasi pada master:
    psql -h master -c "select pg_create_logical_replication_slot('repl', 'pgoutput');"
  3. Hentikan replikasi pada replika lama:
    psql -h replica1 -c "select pg_wal_replay_pause();"

    Dapatkan LSN di master:

    psql -h master -c "select replay_lsn from pg_stat_replication where client_addr = 'replica1';"
  4. Buang data pada replika lama (Anda dapat menggunakan beberapa utas untuk mempercepat proses):
    pg_dump -h replica1 --no-publications --no-subscriptions -O -C -F d -j 8 -f dump/ dbname
  5. Unggah dump ke server baru:
    pg_restore -h replica2 -F d -j 8 -d dbname dump/
  6. Setelah pengunggahan selesai, lanjutkan replikasi pada replika streaming:
    psql -h replica1 -c "select pg_wal_replay_resume();"
  7. Buat langganan pada replika logis baru:
    psql -h replica2 -c "create subscription oldprod connection 'host=replica1 port=5432 user=postgres password=secret dbname=dbname' publication dbname with (enabled = false, create_slot = false, copy_data = false, slot_name='repl');"
  8. Dapatkan tambahan langganan:
    psql -h replica2 -d dbname -c "select oid, * from pg_subscription;"
  9. Misalnya, oid kita sama dengan 1000. Terapkan LSN ke langganan:
    psql -h replica2 -d dbname -c "select pg_replication_origin_advance('pg_1000', 'AA/AAAAAAAA');"
  10. Aktifkan replikasi:
    psql -h replica2 -d dbname -c "alter subscription oldprod enable;"
  11. Periksa status langganan; replikasi harus berjalan:
    psql -h replica2 -d dbname -c "select * from pg_replication_origin_status;"
    psql -h master -d dbname -c "select slot_name, restart_lsn, confirmed_flush_lsn from pg_replication_slots;"
  12. Jika replikasi berjalan normal dan basis data tersinkronisasi, Anda dapat beralih ke host baru.
  13. Setelah replikasi dinonaktifkan, Anda perlu memperbaiki urutannya. (Deskripsi terperinci tentang proses ini tersedia di wiki.postgresql.org .)

Berkat rencana ini, migrasi berlangsung dengan penundaan minimal.

Beberapa catatan lainnya

Dengan menggunakan Operator Postgres oleh Zalando setiap hari, kami telah menghadapi berbagai tantangan. Berikut ini beberapa kasus yang kami tangani.

1. Repositori pribadi

Suatu kali kami perlu menjalankan kontainer SFTP di kluster PostgreSQL kami melalui operator untuk mengambil data basis data dalam format CSV. Server SFTP dengan semua parameter yang diperlukan disimpan dalam registri pribadi.

Kami terkejut saat mengetahui bahwa operator tidak dapat menangani rahasia registri. Untungnya, masalah ini cukup umum, dan kami segera menyelesaikannya menggunakan metode yang dirancang oleh rekan-rekan dalam  masalah ini . Ternyata kami hanya perlu menambahkan nama dan rahasia registri ke definisi ServiceAccount:

pod_service_account_definition: '{ "apiVersion": "v1", "kind": "ServiceAccount", "metadata": { "name": "zalando-postgres-operator" }, "imagePullSecrets": [ { "name": "my-fine-secret" } ] }'

2. Penyimpanan tambahan dan kontainer init

Dalam kasus SFTP, kami juga perlu menetapkan izin direktori yang benar agar chroot dapat berfungsi. Anda mungkin menyadari fakta bahwa server OpenSSH memerlukan hak akses direktori khusus. Misalnya, agar pengguna dapat menggunakan direktori home-nya ( /home/user), induk ( /homedirektori ) harus dimiliki oleh root dan memerlukan 755 izin. Kami memutuskan untuk menggunakan kontainer init yang akan memperbaiki izin tersebut.

Namun kemudian kami menemukan bahwa operator tidak dapat memasang volume tambahan dalam kontainer init! Untungnya, kami menemukan  PR terkait dan menambahkannya ke  build kami .

3. Membuat ulang kontainer

Berikut ini adalah masalah menarik terakhir (tetapi tidak kalah pentingnya). Dalam  rilis operator sebelumnya , sidecar global baru telah ditambahkan. Sekarang Anda dapat mendefinisikannya dalam CRD operator. Pengembang kami memperhatikan restart berkala pada basis data. Log operator berisi informasi berikut:

time="2020-10-28T20:58:25Z" level=debug msg="spec diff between old and new statefulsets: \n
Template.Spec.Volumes[2].VolumeSource.ConfigMap.DefaultMode: &int32(420) != nil\n
Template.Spec.Volumes[3].VolumeSource.ConfigMap.DefaultMode: &int32(420) != nil\n
Template.Spec.Containers[0].TerminationMessagePath: \"/dev/termination-log\" != \"\"\nTemplate.Spec.Containers[0].TerminationMessagePolicy: \"File\" != \"\"\nTemplate.Spec.Containers[1].Ports[0].Protocol: \"TCP\" != \"\"\n
Template.Spec.Containers[1].TerminationMessagePath: \"/dev/termination-log\" != \"\"\nTemplate.Spec.Containers[1].TerminationMessagePolicy: \"File\" != \"\"\nTemplate.Spec.RestartPolicy: \"Always\" != \"\"\n
Template.Spec.DNSPolicy: \"ClusterFirst\" != \"\"\n
Template.Spec.DeprecatedServiceAccount: \"postgres-pod\" != \"\"\n
Template.Spec.SchedulerName: \"default-scheduler\" != \"\"\n
VolumeClaimTemplates[0].Status.Phase: \"Pending\" != \"\"\nRevisionHistoryLimit: &int32(10) != nil\n
" cluster-name=test/test-psql pkg=cluster worker=0

Seperti yang Anda ketahui, ada beberapa perintah yang tidak didefinisikan tetapi tetap ditambahkan selama pembuatan pod dan container. Perintah-perintah ini meliputi:

  • Kebijakan DNS;
  • NamaPenjadwal;
  • KebijakanMulai Ulang;
  • KebijakanPesanPenghentian;

Tampaknya masuk akal untuk berasumsi bahwa operator mempertimbangkan hal ini. Namun ternyata operator memperlakukan  portsbagian tersebut dengan tidak semestinya:

   ports:
    - name: sftp
      containerPort: 22

Protokol TCP ditambahkan secara otomatis saat membuat pod. Namun, operator mengabaikannya. Untuk mengatasi masalah di atas, Anda perlu menghapus port atau menambahkan protokol.

Kesimpulan

Operator Kubernetes mengotomatiskan berbagai tugas dengan menggunakan sumber daya khusus untuk mengelola aplikasi dan komponennya. Namun, otomatisasi yang mengesankan ini menghadirkan beberapa nuansa yang tidak terduga, jadi pilihlah operator Anda dengan bijak.

Pengalaman kami menunjukkan bahwa Anda tidak boleh berharap dapat menyelesaikan semua masalah dengan cepat dan ajaib. Dengan menggunakan Postgres Operator by Zalando, kami telah melalui beberapa kesulitan, tetapi kami tetap puas dengan hasilnya dan berencana untuk memperluas pengalaman kami ke instalasi PostgreSQL lainnya.

Tidak ada komentar:

Posting Komentar