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

kubectl patch --type merge-მა CoreDNS წაშალა, ყველა შემოწმება კი მწვანე დარჩა

იმიჯის ერთხაზიანმა განახლებამ კონტეინერის მთელი სპეციფიკაცია შეცვალა. CoreDNS-მა კონფიგი დაკარგა, ჩუმად whoami პლაგინზე გადავიდა და ყველაფერს NOERROR-ით პასუხობდა პასუხის გარეშე.

ჩემს სახლის ლაბორატორიაში მთელი კლასტერის DNS ახალი მოთხოვნებისთვის მოკვდა, ჯანმრთელობის ყველა სიგნალი კი მწვანე დარჩა. პოდები ნებისმიერ სახელზე bad address-ით ვარდებოდნენ, მაგრამ IP-ით დაკავშირება მუშაობდა. CoreDNS-ის პოდები — 1/1 Running, Ready, ნული გადატვირთვა. Argo CD Synced, Postgres ჯანმრთელი, ყველა საჯარო ენდპოინტი 200-ს აბრუნებს. CoreDNS-ის ლოგები ცოცხალი და ჯანმრთელი ჩანდა: NOERROR-ის თანაბარი ნაკადი. dig კი ამბობდა status: NOERROR და ANSWER: 0.

ყველაფერი, რაც უკვე დაკავშირებული იყო, მუშაობას აგრძელებდა. მხოლოდ ახალი მოთხოვნები ვარდებოდა, ამიტომ პრობლემის დანახვაც კი მაშინვე ვერ მოხერხდა.

ცვლილება, რომელმაც ყველაფერი გამოიწვია

CoreDNS-ის იმიჯი იმით განვაახლე, რაც უწყინარ ერთხაზიანს ჰგავდა:

kubectl -n kube-system patch deploy coredns --type merge \
  -p '{"spec":{"template":{"spec":{"containers":[{"name":"coredns","image":"…"}]}}}}'

--type merge არის JSON Merge Patch (RFC 7386), merge patch კი მასივებს მთლიანად ცვლის. ის სიის ელემენტებს სახელით არ აერთიანებს — ამას strategic merge patch აკეთებს. შედეგად მთელი containers მასივი ჩემი ერთელემენტიანი ობიექტით შეიცვალა და ყველაფერი, რაც არ გავიმეორე, წაიშალა: არგუმენტი -conf /etc/coredns/Corefile, ტომების მიმაგრება, პორტები, ორივე probe და რესურსები.

რატომ ჩანდა ჯანმრთელად

-conf-ის გარეშე CoreDNS მიმაგრებულ Corefile-ს არ კითხულობს. ის ჩაშენებულ ნაგულისხმევზე ირთვება — ერთ სერვერულ ბლოკზე whoami პლაგინით.

whoami ყოველ მოთხოვნას NOERROR-ით პასუხობს, კლიენტის საკუთარ მისამართს ADDITIONAL სექციაში დებს, კლიენტის პორტით SRV ჩანაწერს ამატებს და ANSWER-ს ცარიელს ტოვებს. რეზოლვერები ცარიელ პასუხს ხედავდნენ და ვარდებოდნენ; dig +short არაფერს ბეჭდავდა, რაც „პასუხი არ არის“-დ იკითხება; ლოგები ჩვეულებრივ NOERROR ტრაფიკს ჰგავდა. პოდები კი Ready იყო, რადგან readiness probe იმავე პატჩმა წაშალა — probe-ის გარეშე კონტეინერი ყოველთვის მზადაა.

როგორ ვიპოვე

დრო დამაჯერებელ ცრუ კვალს მოვანდომე: Cilium-ის სერვისების eBPF რუკაში გავრცელების შემდეგ ცოტა ხნით CoreDNS-ის ორიდან ერთი ბექენდი იყო, აგენტის გადატვირთვის შემდეგ ენდპოინტები restoring მდგომარეობაში იყო, და Cilium-ის DNS პროქსის პარამეტრიც კი გადავრთე. არცერთი მათგანი მიზეზი არ იყო.

იმუშავა ნოდიდან გაგზავნილმა ნედლმა DNS მოთხოვნამ საკონტროლო წერტილით: იგივე მოთხოვნამ ცნობილად გამართულ რეზოლვერთან ერთი პასუხი დააბრუნა, CoreDNS-მა კი ნული პასუხი და ორი დამატებითი ჩანაწერი. ბაიტების გარჩევამ აჩვენა A ჩანაწერი ჩემი საკუთარი მისამართით და SRV ჩანაწერი TTL 0-ით — whoami-ის ანაბეჭდი. სწრაფმა შემოწმებამ დაადასტურა: ნამდვილი CoreDNS დამატებით /ready-ს 8181-ზე და მეტრიკებს 9153-ზე აბრუნებს, ეს კი მხოლოდ 53-ე პორტს უსმენდა.

გამოსწორება

Deployment ცვლილებამდე აღებული დამპიდან აღვადგინე — წუთების საქმე. კონტეინერის სპეციფიკაციის მეხსიერებით აღდგენა სულ სხვა საქმე იქნებოდა. იმავე დღეს მოგვიანებით განახლება kubectl set image-ით გავიმეორე და ახალი ვერსია სრულიად უპრობლემო აღმოჩნდა.

დასკვნები

  • --type merge ყველაფრისთვის, სადაც სიაა, დამანგრეველია. კონტეინერები, ტომები, env, პორტები, tolerations — ყველა მასივია. გამოიყენეთ kubectl set image, strategic merge patch (ნაგულისხმევი kubectl patch) ან სრული მანიფესტი.
  • Ready იმდენს ნიშნავს, რამდენსაც მის უკან მდგომი probe. თუ კომპონენტი „Ready-ა, მაგრამ არასწორად მუშაობს“, შეამოწმეთ, საერთოდ არსებობს თუ არა probe.
  • dig +short მალავს პასუხებს, სადაც მხოლოდ ADDITIONAL არის. სანამ გადაწყვეტთ, რომ პასუხი არ ყოფილა, მთლიანად წაიკითხეთ.
  • დიაგნოსტიკა საკონტროლო წერტილით გააკეთეთ. ცნობილად გამართულ რეზოლვერთან შედარება „ჩემი ხელსაწყო ტყუის“-ს „სერვერი გაფუჭებულია“-სგან ჰყოფს.
  • პლატფორმის კომპონენტის ხელით რედაქტირებამდე ობიექტის დამპი აიღეთ და გავრცელებას მანამ ნუ ენდობით, სანამ არ შეამოწმებთ, რომ სპეციფიკაცია გადარჩა.