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

სერტიფიკატებს ვადა გრაფიკით გაუვიდა. ალერტი ერთი კვირა ყვიროდა — სიცარიელეში

kubeadm კლასტერმა control plane დაკარგა ინსტალაციიდან ზუსტად ერთი წლის შემდეგ. ალერტი შვიდი დღე იწვოდა, მაგრამ Alertmanager-ს მხოლოდ null მიმღები ჰქონდა.

ერთ დილით Optimacros-ის bare-metal კლასტერზე ყოველი kubectl გამოძახება ერთი და იმავე ხაზით ვარდებოდა:

x509: certificate has expired or is not yet valid: current time ... is after 2026-10-09T04:52:15Z

გაშვებული პოდები ტრაფიკს ისევ ემსახურებოდნენ, ამიტომ გარედან არაფერი ჩანდა გაფუჭებული. შიგნით კი controller-manager და scheduler crash-loop-ში იყვნენ — თითოეულს 28–31 რესტარტი. ახალი არაფერი იგეგმებოდა და არაფერი რეკონსილირდებოდა. CI ჯობები, რომლებსაც ახალი პოდები სჭირდებოდათ, უბრალოდ ვარდებოდნენ.

ზუსტად ერთი წელი

თარიღმა ყველაფერი გასცა. კლასტერი kubespray-ით 2025-10-09-ს დაყენდა და მას შემდეგ არასდროს განახლებულა. kubeadm ფოთლოვან სერტიფიკატებს — API სერვერის, kubelet კლიენტის, front-proxy-ს და admin, controller-manager, scheduler kubeconfig-ებს — ერთი წლით გასცემს. kubeadm upgrade მათ თან ახლავს და აახლებს, ამიტომ რეგულარულად განახლებული კლასტერები ამას ვერ ამჩნევენ. ეს კი არავის შეხებია, kubespray-ის auto_renew_certificates კი გამორთული იყო. ყველას ვადა ერთ წამში გაუვიდა.

შეკეთებისთვის ისიც მნიშვნელოვანია, რა არ დაზარალდა: CA ათი წლით არის, kubespray-ის etcd სერტიფიკატები — ასი წლით, kubelet-ის კლიენტური სერტიფიკატები კი თავად როტირდება. ანუ ეს განახლებაა და არა თავიდან აწყობა.

ალერტი იმუშავა

პირველი ფიქრი იყო „ამაზე ალერტი არ გვქონდა”. აღმოჩნდა, რომ ეს არასწორია, სიმართლე კი უარესია. kube-prometheus-stack ყუთიდანვე შეიცავს KubeClientCertificateExpiration-ს. მისი ისტორია Prometheus-ში ვნახე:

count_over_time(ALERTS{alertname="KubeClientCertificateExpiration",alertstate="firing"}[10d])

დაახლოებით შვიდი დღე warning-ად იწვოდა და ბოლო დღე — critical-ად. შემდეგ Alertmanager-ის დაგენერირებული კონფიგი გავხსენი. ერთადერთი მიმღები იყო "null" — ჩარტის ნაგულისხმევი მნიშვნელობა, რადგან Argo CD Application-ს alertmanager.config არასდროს დაუყენებია. ალერტი იდეალურად მუშაობდა. უბრალოდ წასასვლელი არსად ჰქონდა.

შეკეთება — თითო მასტერი

კლასტერს სამი control-plane ნოდი აქვს, ამიტომ სათითაოდ ვაახლებდი და თითოეულს ვამოწმებდი, სანამ შემდეგს შევეხებოდი:

  1. /etc/kubernetes-ის ბექაპი არქივში.
  2. kubeadm certs renew all კლასტერის kubeadm კონფიგით. SAN-ები ინახება.
  3. static pod-ების მანიფესტების გატანა, ლოდინი, სანამ API სერვერი, controller-manager და scheduler გაქრება, მანიფესტების დაბრუნება.
  4. readyz-ის და, რაც მთავარია, რეალურად გაცემული სერტიფიკატის შემოწმება:
echo | openssl s_client -connect <master>:6443 2>/dev/null | openssl x509 -noout -enddate

მე-3 ნაბიჯს ხშირად გამოტოვებენ. kubeadm certs renew მხოლოდ ფაილებს წერს. გაშვებული პროცესები ძველ სერტიფიკატს მეხსიერებაში ინახავენ, სანამ static pod-ები არ გადაიტვირთება, ამიტომ „ფაილები ახალია” არაფერს ამტკიცებს.

ლეპტოპის kubeconfig-იც ახალი admin.conf-ით უნდა შეცვლილიყო. კიდევ ერთი ხაფანგი: kubespray server:-ს 127.0.0.1:6443-ზე წერს, ამიტომ დაკოპირებული ფაილი connection refused-ს იძლევა, სანამ მისამართს არ გადაწერ.

რომ აღარ განმეორდეს

პრევენცია: ყოველთვიური systemd ტაიმერი, რომელიც სერტიფიკატებს აახლებს — იმის კლონი, რასაც kubespray auto_renew_certificates: true-ით დააყენებდა, მასტერებზე გადანაწილებული დროით, რომ ერთდროულად არასდროს გადაიტვირთონ. ერთხელ ხელით გავუშვი და გაცემული სერტიფიკატი ისევ შევამოწმე: ტაიმერი, რომლის წარმატებაც არ გინახავს, იმედია და არა კონტროლი.

ნამდვილი ხვრელი მიწოდებაშია და ის ამ კლასტერზე ფართოა: ალერტი მიმღების გარეშე დეკორაციაა. Alertmanager-ის მიწოდების GitOps-ით მიერთება ცალკე გადაწყვეტილებად ჩაიწერა, საკუთარი ტრიგერით.

დასკვნები

  • kubeadm კლასტერი, რომელსაც წელიწადში ერთხელ მაინც არ აახლებენ, control plane-ს ინსტალაციის წლისთავზე დაკარგავს.
  • სერტიფიკატების განახლების შემდეგ შეამოწმე, რას გასცემს ენდპოინტი და არა რა დევს დისკზე.
  • „ალერტი არ გვქონდა” და „ალერტი არსად წავიდა” ინციდენტის დროს ერთნაირად გამოიყურება. ყველა კლასტერზე შეამოწმე receivers — მარტოხელა null ნიშნავს, რომ არავინ უსმენს.
  • სხვა მასტერზე ცალკე admin kubeconfig შეინახე: როცა პირველი გადაიტვირთება, შესასვლელი მაინც გექნება.