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

სამი ინციდენტი, რომელიც ერთი აღმოჩნდა: კონფიგში ჩაწერილი მონაცემთა ბაზის IP

500 შესვლისას, CrashLoopBackOff-ში მყოფი ბექენდები და გაჭედილი დეპლოი სამ პრობლემად გამოიყურებოდა. სამივე pgbouncer-ის კონფიგში ჩაწერილი ერთი IP აღმოჩნდა.

შეტყობინება ჩვეულებრივი იყო: „სტენდი არ მუშაობს“. ეს იყო Gambchamp-ის დატვირთვის სატესტო გარემო და გარედან მას ერთდროულად სამი სხვადასხვა პრობლემა ჰქონდა.

  • ადმინ-პანელში შესვლა 500-ს აბრუნებდა.
  • ბექენდის რამდენიმე პოდი CrashLoopBackOff-ში იყო ასობით გადატვირთვით.
  • დეპლოი შუა გზაზე გაიჭედა: ახალი პოდები readiness-ს ვერ გადიოდნენ, ძველები ტრაფიკს ემსახურებოდნენ.

ასეთ დროს სამი ცალკე ამოცანის გახსნა გინდება. ეს სამი არასწორი გამოძიება იქნებოდა.

პირველი არასწორი ვარაუდი

აპლიკაციის ლოგები ამით იყო სავსე:

asyncpg.exceptions.ConnectionDoesNotExistError: connection was closed in the middle of operation

ერთი შეხედვით, კოდის ხარვეზს ან კლასტერის შიგნით არასტაბილურ ქსელს ჰგავს. მაგრამ ყველა ბექენდი PostgreSQL-ს საერთო pgbouncer-ის გავლით უკავშირდებოდა, მისი ლოგი კი უფრო ზუსტი იყო:

pooler error: server login has been failing, cached error: connect failed (server_login_retry)

connect failed ადვილად შეიძლება ავთენტიფიკაციის შეცდომად მივიჩნიოთ. ეს ის არ არის. pgbouncer-ს ბაზის სერვერთან TCP კავშირის გახსნაც კი არ შეეძლო. აპლიკაციის შეცდომა მხოლოდ ამის გამოძახილი იყო.

მტკიცება კლასტერის შიგნიდან

pgbouncer-ის პოდიდან ორმა read-only ბრძანებამ საკითხი გადაწყვიტა: პროვაიდერის მასტერის სტაბილური სახელის რეზოლვი და ჩვენი მანიფესტის მისამართზე 5432 პორტის გახსნის მცდელობა. სახელი ახალ მისამართზე მიუთითებდა. ძველი მისამართი აღარ უსმენდა.

პროვაიდერმა managed PostgreSQL-ის ნოდა თავიდან შექმნა და მან ახალი IP მიიღო. GitOps რეპოზიტორიაში სწორედ ეს გარემო pgbouncer-სა და postgres exporter-ს ბაზაზე IP მისამართით მიმართავდა. ყველა სხვა გარემო მასტერის FQDN-ს იყენებდა, რომელიც ნოდის ხელახალი შექმნისა და failover-ის დროს მიმდინარე მასტერს მიჰყვება.

ისტორია სურათს კიდევ უფრო აუარესებდა: რეპოში ძველი კომიტი იყო „point exporter at correct DB IP“. ეს უკვე მომხდარიყო და მაშინაც იგივე მყიფე გზით გამოასწორეს.

გამოსწორება

  1. IP შევცვალეთ მასტერის FQDN-ით pgbouncer-ის კონფიგსა და exporter-ში, ჩარტი ლოკალურად დავარენდერეთ და დავმერჯეთ.
  2. Argo CD-მ Secret დაასინქრონა, რადგან self-heal ჩართული იყო.
  3. pgbouncer ხელით გადავტვირთეთ. ამ ნაბიჯის დავიწყება ადვილია: pgbouncer.ini ფაილად არის მიმაგრებული, pgbouncer მას თავიდან არ კითხულობს, ამ Deployment-ზე კი reloader-ის ანოტაცია არ იყო. exporter-ზეც იგივე ითქმის.

გადატვირთვის შემდეგ ახალი პოდი ნორმალურ login attempt ჩანაწერებს წერდა და არც ერთ connect failed-ს. ბექენდები crash loop-იდან თავად გამოვიდნენ, გაჭედილი rollout კი თავისით დასრულდა.

რატომ ჩანდა ეს სამ პრობლემად

ბექენდების startup და liveness პრობები ბაზას მიმართავდნენ. როცა ბაზა მიუწვდომელი გახდა, Kubernetes გაფუჭებულ პოდებს ხედავდა და მათ გადატვირთავდა, ახალი ReplicaSet კი მზადყოფნას ვერ აღწევდა. ერთმა დაკარგულმა დამოკიდებულებამ სამი სრულიად განსხვავებული სიმპტომი გამოიწვია.

რა უნდა დავიმახსოვროთ

  • connect failed (server_login_retry) pgbouncer-ში მკვდარ endpoint-ს ნიშნავს და არა არასწორ პაროლს. ჯერ მისამართს შეხედე, მერე კრედენშალებს.
  • Crash loop, გაჭედილი დეპლოი და 500 შესვლისას შეიძლება ერთი მიზეზი იყოს ერთი დონით ქვემოთ. ჯერ საერთო დამოკიდებულება მოძებნე.
  • კლიენტები managed ბაზის სტაბილურ FQDN-ს დაუკავშირე და არასოდეს ნოდის IP-ს. IP მანიფესტში ნაღმია და არა პარამეტრი.
  • თუ კონფიგი ფაილად არის მიმაგრებული და პროცესი მას არ ადევნებს თვალს, GitOps-ის სინქრონიზაცია ცვლილების მხოლოდ ნახევარია. ან reloader დაამატე, ან გადატვირთვა პროცედურის ნაწილად აქციე.