Kafka 94 %-ით სავსე დისკზე, 17 საათის მარაგი და retention, რომელიც ორჯერ მეტს ინახავდა
ტრაფიკი 150-ჯერ გაიზარდა, ტომები კი არავის გადაუხედავს. უარესი: სეგმენტების ნაგულისხმევი როლინგის დროს 7-დღიანი retention სინამდვილეში 7–14 დღეს ნიშნავდა.
Gambchamp-ში ალერტი ამოქმედდა: Kafka თავის ტომებს ავსებდა. კითხვა ჩვეულებრივი იყო — დილამდე მოითმენს?
არ მოითმენდა. სამივე ბროკერი 39,1 GiB-დან 36,6-ზე იდგა, 94 %. ზრდა საშუალოდ დღეში 3,37 GiB იყო, საღამოს პიკში კი დღეში ~5 GiB-მდე. რჩებოდა დაახლოებით 17 საათი, ანუ დისკი შუაღამისას, პიკის დროს ამოიწურებოდა. retention-ის შემდეგი ავტომატური გაწმენდა მხოლოდ ორი დღის შემდეგ იყო მოსალოდნელი.
არაფერი გატეხილა
მიზეზი ორი იყო და არც ერთი გაუმართაობა არ ყოფილა.
ტრაფიკი დაახლოებით 150-ჯერ გაიზარდა. აგვისტოს დასაწყისში წამში ~5 შეტყობინებიდან პროდუქტის გაშვების შემდეგ წამში ~780 შეტყობინების პლატომდე. კონსიუმერების lag ნულოვანი იყო, ბროკერების ლოგებში შეცდომები არ იყო, under-replicated პარტიციები არ იყო. 40 GiB-იანი ტომები უბრალოდ სხვა დატვირთვისთვის იყო დაპროექტებული.
retention სინამდვილეში 7–14 დღე იყო და არა 7. ბროკერების კონფიგი retention-ს საერთოდ არ აწესებდა, Kafka-ს ნაგულისხმევი მნიშვნელობები მოქმედებდა: log.retention.hours=168 და log.roll.hours=168, 1 GiB-იანი სეგმენტებით. retention მხოლოდ დახურულ სეგმენტებს შლის. ჩვენი პარტიციები კვირაში რამდენიმე ასეულ მეგაბაიტს აგროვებდა და 1 GiB-მდე ვერ იზრდებოდა, ამიტომ სეგმენტი 7-დღიანი ტაიმერით იხურებოდა — და მხოლოდ მაშინ იწყებოდა მისი retention-ის ათვლა. აქედანაა „ხერხი“ დისკის გრაფიკზე: დიდი ვარდნა კვირაში ერთხელ, შუალედში არაფერი თავისუფლდება.
პრაქტიკული დასკვნა: ასეთი ტომი ვერ დაიგეგმება როგორც „7 დღე × სიჩქარე“. ამ ნაგულისხმევი მნიშვნელობებით — 14.
დროის მოგება
ტომები გაფართოებად gp3 კლასზე იყო, ამიტომ პირველი ნაბიჯი PVC-ის ონლაინ გაფართოება იყო 40-დან 100 GiB-მდე. გადატვირთვების გარეშე, under-replicated პარტიციების გარეშე, GitOps-აპლიკაცია სინქრონიზებული დარჩა — PVC-ები volumeClaimTemplates-იდან იქმნება და Git-ში არ არის, ამიტომ self-heal-ს დასაბრუნებელი არაფერი ჰქონდა. პირდაპირ 100, და არა 60, რადგან AWS ტომის შეცვლას ექვს საათში ერთხელ უშვებს.
მიზეზის აღმოფხვრა
მეორე დღეს გაირკვა, რომ 7-დღიანი retention ბექენდის არქიტექტორების რეალური მოთხოვნა იყო. ამან გამოსწორების აზრი შეაბრუნა: სისტემა ნაკლებს კი არ ინახავდა, არამედ მოთხოვნილზე თითქმის ორჯერ მეტს. სეგმენტების როლინგი ყოველ 12 საათში (log.roll.ms=43200000) რეალურ შენახვას 7–7,5 დღეს უბრუნებს log.retention.hours-ის შეცვლის გარეშე.
4-ჯერადი ზრდის პროგნოზით სტაციონარი გამოდიოდა ~185 GiB არსებული კონფიგით და ~99 GiB 12-საათიანი სეგმენტებით, ამიტომ სამიზნე ტომი 200 GiB გახდა. გამტარუნარიანობა, IOPS, ფაილის დესკრიპტორები და CPU ზღვრებისგან შორს იყო — ჭერი მოცულობაში იყო და არა წარმადობაში.
სამი ხაფანგი გზაზე
- არასწორი გასაღები, რომელზეც „Completed“ გვიპასუხეს. ჯერ
log.segment.msდავაყენეთ — ბროკერს ასეთი პარამეტრი არ აქვს (ტოპიკის დონეზე მასsegment.msჰქვია).kafka-configs.sh-მაCompleted updating default configუპასუხა და არაფერი შეცვალა. სწორი სახელიაlog.roll.ms, რეალურად რა მოქმედებს, მხოლოდ--describe --allაჩვენებს. - დინამიკური override ფაილს ფარავს. ბროკერის დინამიკური კონფიგი
server.properties-ზე პრიორიტეტულია. სანამ override მოხსნილი არ არის, Git-ში არსებული მნიშვნელობა დეკორატიულია — ხოლო თუ ძალიან ადრე მოხსნი, როლინგი ცოტა ხნით 168 საათს დაუბრუნდება. - StatefulSet-ის „უსაფრთხო“ ხელახალმა შექმნამ ყველა ბროკერი გადატვირთა. ცოცხალ pod template-ში დარჩენილი იყო ძველი ანოტაცია
kubectl.kubernetes.io/restartedAt, რომელიც Git-ის რენდერში არ იყო — ჰეში შეიცვალა და ყველა ბროკერი გადაიტვირთა. სათითაოდ, შტატურად, მაგრამ დაუგეგმავად.
ცვლილებების შემდეგ: 200 GiB-იანი ტომები 21 %-ით დაკავებული, ყველაფერი Git-იდან მოდის, სეგმენტები დღეში ორჯერ იცვლება.
დასკვნები
- შევსებამდე დრო პიკური სიჩქარით დაითვალეთ და retention-ის შემდეგ ვარდნას შეადარეთ. თუ ვარდნა უფრო გვიანაა — ლოდინი არ შეიძლება.
- მოთხოვნა, რომელიც ნაგულისხმევს დაემთხვა, ჩაუწერელი მოთხოვნაა. retention ცალსახად დააყენეთ, თუნდაც მნიშვნელობა ნაგულისხმევის ტოლი იყოს.
kafka-configs.shწარმატებას უცნობ გასაღებებზეც აცხადებს. შეამოწმეთ--describe --all-ით.delete sts --cascade=orphan-მდე შეამოწმეთ, ხომ არ არის pod template-შიrestartedAtანოტაცია.