Kubernetes 1.32-დან 1.37-მდე ერთ დღეში, ხუთი ჰოპი, იმ kubespray-ის გარეშე, რომლითაც კლასტერი აიწყო
EOL ვერსიაზე მყოფი bare-metal კლასტერი, დაკარგული kubespray ინვენტარი და ბინარები პაკეტების მენეჯერის გარეთ. როგორ გავიდა kubeadm-ის ხუთი ჰოპი ერთ დღეში და ხაფანგები, რომლებიც არც ერთ გეგმაში არ იყო.
Optimacros-ის bare-metal კლასტერი Kubernetes 1.32.8-ზე იყო — ტოტზე, რომელიც უკვე მხარდაჭერის მიღმა იყო. გეგმა — 1.37-მდე აყვანა: ხუთი minor ჰოპი, რადგან kubeadm minor-ს არასდროს ახტება:
1.32.8 → 1.33.13 → 1.34.12 → 1.35.9 → 1.36.5 → 1.37.1
რასთან გვქონდა საქმე
კლასტერი kubespray-ით აიწყო, ინვენტარი კი დაიკარგა. ბინარები /usr/local/bin-ში იდო, არც ერთ პაკეტს არ ეკუთვნოდა, Kubernetes-ის apt რეპოზიტორია არ იყო — ამიტომ apt install kubeadm=… არ გამოდგებოდა: ყოველი ჰოპი ოფიციალური რელიზების საიტიდან ჩამოტვირთული ბინარების ჩანაცვლებას ნიშნავდა. სამი მასტერი, ოთხი დიდი ვორკერი, გარე etcd systemd-ის ქვეშ, Calico kubespray-ის მანიფესტებიდან, kube-proxy ipvs რეჟიმში.
ვორკერებზე იყო 124 local-path ტომი სატესტო სტენდებისთვის ბექაპის გარეშე. drain მათ არსად გადაიტანდა, ამიტომ ვორკერები ადგილზე, drain-ის გარეშე განახლდა. ალერტინგი კი null მიმღებში მიდიოდა, ამიტომ მთელი ოპერაცია დაშბორდებზე დაკვირვებით მიმდინარეობდა და არა პეიჯერით — გადაწყვეტილება, ჩაწერილი დაწყებამდე და არა მოგვიანებით აღმოჩენილი.
მომზადება ისე, რომ ერთ ჯერზე ერთი რამ იცვლებოდეს
წინა დღეს კლასტერმა მიიღო:
- მოძველებული API-ების აუდიტი
pluto-თი 1.37-ის მიმართ — ნული აღმოჩენა ცოცხალ ობიექტებსა და ყველა 17 Helm რელიზში; - etcd-ის დეფრაგმენტაცია: ბაზის ფაილი 743 MB იყო 73 MB მონაცემზე — 90% ფრაგმენტაცია, ინსტალაციის შემდეგ დეფრაგმენტაცია არ ყოფილა. სათითაოდ, ლიდერი ბოლოს, თითოეული წამზე ნაკლები: 82 MB;
- etcd-ის სნეპშოტი ასლზე შემოწმებით, კონფიგების ბექაპები შვიდივე ნოდიდან და კლასტერის ობიექტების ექსპორტი;
- ოს-ის რელიზ-განახლება ცალკე ფანჯარაში, რომ Kubernetes-ის ჰოპები ერთადერთი ცვლადი ყოფილიყო.
კომპონენტების წესი: თითოეულის აყვანა იმ ჰოპამდე, რომელსაც მისი მიმდინარე ვერსია არ უჭერს მხარს, და ყოველი ჰოპის წინ თავსებადობის მატრიცების თავიდან შემოწმება — ისინი იცვლება.
ჰოპები
ყოველი ჰოპი ერთი სცენარით მიდიოდა: ახალი kubeadm და kubelet საკონტროლო ჯამების შემოწმებით, kubeadm upgrade apply პირველ მასტერზე, upgrade node დანარჩენ ორზე, შემდეგ ვორკერები სათითაოდ — cordon, upgrade, kubelet, Ready, uncordon, დაახლოებით ათი წამი თითოზე. მიღება ყოველი ჰოპის შემდეგ: ნოდები, etcd, kube-system, საცავი, Argo CD, ბაზის ოპერატორი, Gateway-ის მარშრუტები, პოლიტიკების ძრავის smoke და ქსელური ტესტი „ახალი პოდი ↔ ახალი პოდი” ტაიმერით.
პირველმა და მეორე ჰოპმა თითო დაახლოებით ათი წუთი წაიღო. ხუთივე იმავე დღეს დასრულდა.
ხაფანგები, რომლებიც არც ერთ გეგმაში არ იყო
- Calico kubespray-იდან აფსტრიმის CRD-ებსა და ClusterRole-ებს მოითხოვდა და არა მხოლოდ ახალ იმიჯებს: kubespray-ის RBAC მკაცრი ქვესიმრავლეა. ახალი ვერსია კი XDP პროგრამაზე გაიჭედა, რომლის მოხსნაც ვერ შეძლო, და ახალი პოდები 42 წამამდე მიუწვდომელი იყო, სანამ XDP არ გამოვრთეთ.
--apiserver-countწაიშალა kube-apiserver 1.35-ში. kubespray მას kubeadm კონფიგში დებს, ამიტომupgrade apply-მდე უნდა წაგვეშალა. ეს დაიჭირა ყოველი ჰოპის წინ ფლაგების ახალი იმიჯის--help-თან შედარებამ.- Longhorn 1.11 მოითხოვს Kubernetes 1.34-ს ან უფრო ახალს, 1.10 კი მხოლოდ 1.33-მდე უჭერს მხარს. ანუ Longhorn უნდა აგვეყვანა 1.34 ჰოპის მაშინვე შემდეგ, მკაცრად თითო minor-ით.
- CoreDNS kubeadm-ის გარეთაა kubespray-ის კლასტერებში — დამატების ფაზა გამორთულია, — ამიტომ ძველ ვერსიაზე რჩება, სანამ ხელით არ განაახლებ.
- kubelet კითხულობს kubespray-ის საკუთარ კონფიგს და არა იმას, რასაც
kubeadm upgrade nodeწერს.clusterDNSყოველი ჰოპის შემდეგ სწორ ფაილში უნდა შემოწმდეს. - Argo CD კლასტერის ვერსიას ქეშავს. ყოველი ჰოპის შემდეგ მისი application controller Helm-ს ძველი
--kube-version-ით არენდერებდა და ჩარტი, რომელიც 1.34+-ს მოითხოვს, არ რენდერდებოდა. კონტროლერის გადატვირთვა ყოველი ჰოპის შემდეგ ამას კურნავდა. - etcd 3.6 ცალმხრივი კარია: მინიმალური საწყისი ვერსია 3.5.32-ია, v2-store-ის შემოწმება ყველა მონაწილეზე უნდა გავიდეს, ხოლო როცა ბოლო მონაწილე 3.6-ზეა, უკან გზა მხოლოდ სნეპშოტით არსებობს.
- მეზობელ ფრონტზე ingress-ის Envoy Gateway-ზე გადატანამ kube-proxy-ის
strictARP-ის ნაგულისხმევი მნიშვნელობა გამოაჩინა, რის გამოც LoadBalancer IP-ებზე ARP-ს ყველა ნოდი პასუხობდა.
ბარიერი, რომელიც შეგნებულად მოვხსენით
გეგმაში 1.37-მდე მკაცრი ბარიერი იყო: Longhorn-სა და პოლიტიკების ძრავას 1.37 თავიანთ მხარდაჭერის მატრიცებში უნდა ჰქონოდათ. იმ დღეს — არ ჰქონდათ. ბარიერი შეგნებულად მოვხსენით და ჩავწერეთ რატომ: მატრიცის მიღმა მყოფი ყველა კომპონენტი მხოლოდ სტაბილურ API-ებს იყენებდა და 1.37-ზე ფუნქციური smoke გაიარა — PVC-ში ჩაწერა, webhook და generate წესები, მარშრუტები, ახალი პოდების ქსელი. Calico-ს სრულიად ახალ x.0 რელიზზე გადახტომა, რომელიც DaemonSet-ს გარდაქმნის, უფრო დიდ რისკად გამოიყურებოდა, ვიდრე წინა ვერსია მატრიცის ოდნავ მიღმა.
დასკვნები
- ორიგინალური ინსტალერის გარეშე kubeadm ხელით ნორმალურია, მაგრამ პროცედურა ერთხელ დაწერე და ყოველ ჰოპზე ერთნაირად შეასრულე.
- კომპონენტები იმ ჰოპამდე აიყვანე, რომელიც მათ ტეხს, და მატრიცები ყოველ ჯერზე თავიდან წაიკითხე.
- etcd დაწყებამდე დეფრაგმენტირება და სნეპშოტი გაუკეთე: ეს იაფია, ფრაგმენტაცია კი 90% იყო.
- წაშლილი ფლაგები ახალ ბინართან
upgrade apply-მდე შეამოწმე. - გადატვირთე ყველაფერი, რაც კლასტერის ვერსიას ქეშავს — უპირველეს ყოვლისა Argo CD.
- ბარიერის მოხსნა შეიძლება, მაგრამ მხოლოდ წერილობითი დასაბუთებითა და ფუნქციური ტესტით, არასდროს ჩუმად.