← ყველა სტატია

პროდაქშენის Postgres-ის გადატანა RDS Multi-AZ instance-დან Multi-AZ DB cluster-ზე

დაგეგმილი cutover თითქმის მონაცემების დაკარგვის გარეშე — და სამი ხაფანგი: „ტექსამუშაოები“, რომლებმაც ჩაწერა ვერ შეაჩერეს, პაროლები, რომელთა კოპირებასაც RDS არ იძლევა, და დამპი 25 წუთში VPN-ით 31 წამის წინააღმდეგ VPC-ში.

Gambchamp-ში ცოცხალ პროდაქშენის PostgreSQL-ს ვაგადატანდით RDS Multi-AZ instance-დან Multi-AZ DB cluster-ზე: writer პლუს ორი წასაკითხი standby და ცალკე reader-endpoint. აპლიკაცია უნდა გადაგვერთო, როლები, მონაცემები და გრანტები ერთი ერთზე გადაგვეტანა, მონაცემების დანაკარგი კი თითქმის ნულამდე დაგვეყვანა.

ეს დაგეგმილი მიგრაცია იყო და არა ინციდენტი. სამმა რამემ მაინც გვიკბინა.

პირველი ხაფანგი: „ტექსამუშაოებმა“ ჩაწერა ვერ შეაჩერეს

აპლიკაცია ტექსამუშაოების რეჟიმში გადავიყვანეთ და ცხრილების მიხედვით სტრიქონების ზუსტი რაოდენობა ორ მომენტში შევადარეთ. ხუთი ცხრილი ისევ იცვლებოდა: გადახდის პროვაიდერების callback-ები, შეტყობინებები და ვიზიტები ისევ ემატებოდა. ცოცხალი წყაროს ერთი დამპი ყოველთვის ჩამორჩება.

ნამდვილი გაყინვა — ყველა ჩამწერის ნულამდე დასკეილება და ამის დამტკიცება: რაოდენობები სტაბილურია, ჩამწერი კავშირები არ არის, idle-in-transaction სესიები არ არის. ამას ზემოდან, წყაროზე:

ALTER DATABASE app SET default_transaction_read_only = on;

პლუს აპლიკაციის დარჩენილი კავშირების დასრულება. ეს ბლოკავს ნებისმიერ დაგვიანებულ ჩაწერას და გადართვის შემდეგ split-brain-საც უშლის ხელს.

მეორე ხაფანგი: RDS პაროლებს არ გაძლევთ

pg_dumpall --globals-only როლების გადატანის ჩვეულებრივი გზაა. RDS-ზე master-საც კი არ შეუძლია pg_authid-ის წაკითხვა, ამიტომ იქიდან ვერც ჰეშებს მიიღებთ, ვერც სხვა რამეს. pg_dumpall -g --no-role-passwords მაინც იძლევა ზუსტ ატრიბუტებს, წევრობებსა და როლების პარამეტრებს — ეს ღირს.

პაროლები სხვაგან უნდა აგვეღო. აპლიკაციის როლმა პროდაქშენის პაროლი შეინარჩუნა — ის აპლიკაციის Kubernetes-საიდუმლოდან ავიღეთ და წყაროზე რეალური ლოგინით შევამოწმეთ. დამხმარე როლებმა ახალი პაროლები მიიღეს. როლი, რომელსაც უკვე ვადა ჰქონდა გასული, ვადაგასულად შეიქმნა.

მესამე ხაფანგი: ყველაფერი ქსელმა გადაწყვიტა

დამპი VPN-ით ძლივს მიდიოდა: 110 MB დაახლოებით 25 წუთში. იგივე pg_dump იმავე VPC-ში მყოფი EC2-ჰოსტიდან 31 წამში დასრულდა. პაროლები stdin-ით გადაეცემოდა და არასოდეს — ბრძანების არგუმენტებით.

აღდგენის დეტალები, რომლებიც ადვილად გამოგრჩებათ

  • RDS-ზე master ბაზის მფლობელი არ არის, ამიტომ DROP DATABASE არ გადის. სუფთა სამიზნე public სქემის წაშლითა და ხელახლა შექმნით გავაკეთეთ მფლობელი როლის სახელით. CREATE EXTENSION-ს ისევ master სჭირდება.
  • აღდგენისას ორი შეცდომა მოსალოდნელია. ALTER DEFAULT PRIVILEGES FOR ROLE <app> master-ით ეცემა და იმ როლის სახელით უნდა გამეორდეს. publication already exists ჩნდება, რადგან პუბლიკაციები ბაზის დონის ობიექტებია და DROP SCHEMA-ს გადაურჩებიან.

შემოწმება გახსნამდე

  • ცხრილების მიხედვით რაოდენობების სრული diff ნულის ტოლია;
  • თითოეული sequence შედარებულია თავისი სვეტის მაქსიმუმთან — ჩამორჩენილი sequence პირველივე ჩაწერისას duplicate key-ს ნიშნავს;
  • რეალური ლოგინი ყოველი როლით და საცდელი ჩაწერა აპლიკაციის როლით.

მხოლოდ ამის შემდეგ გადავიყვანეთ აპლიკაციის ჰოსტი კლასტერის writer-endpoint-ზე, კითხვა კი reader-endpoint-ზე. ძველი instance იზოლირებული დარჩა: read-only და აპლიკაციის არც ერთი კავშირის გარეშე.

დაბრუნება მარტივია, სანამ პირველი ჩაწერა კლასტერში არ მოხვდა: ძველ instance-ზე default_transaction_read_only გადატვირთეთ და ჰოსტი დააბრუნეთ. პირველი ჩაწერის შემდეგ — დაუბრუნებლობის წერტილია.

დასკვნები

  • გაყინვა რაოდენობების diff-ით დაამტკიცეთ. Callback-ები და webhook-ები „ტექსამუშაოების“ შემდეგაც წერენ.
  • RDS-ზე დაგეგმეთ პაროლების ხელახლა გაცემა ან აიღეთ ისინი აპლიკაციის საიდუმლოებიდან; ბაზიდან მათ ვერ დააკოპირებთ.
  • დამპი და აღდგენა VPC-ის შიგნიდან გაუშვით. აქ ეს დაახლოებით 50-ჯერ უფრო სწრაფი იყო.
  • ჩაწერის გახსნამდე sequence-ები სვეტებთან შეადარეთ.
  • მონიტორინგი ბაზას თავისით არ მიჰყვება — აპლიკაციის გადართვა cutover-ის მხოლოდ ნახევარია.