Kubernetes Kullanırken Yapılan 10 Yaygın Hata

Not. tercüme: Bu makalenin yazarları küçük bir Çek şirketi olan pipetail'in mühendisleridir. Kubernetes kümelerinin işleyişiyle ilgili [bazen sıradan ama yine de] çok acil sorunların ve yanlış anlamaların harika bir listesini bir araya getirmeyi başardılar.

Kubernetes Kullanırken Yapılan 10 Yaygın Hata

Kubernetes'i kullandığımız yıllar boyunca çok sayıda kümeyle (GCP, AWS ve Azure'da hem yönetilen hem de yönetilmeyen) çalıştık. Zamanla bazı hataların sürekli tekrarlandığını fark etmeye başladık. Ancak bunda utanılacak bir şey yok: çoğunu kendimiz yaptık!

Makale en yaygın hataları içerir ve ayrıca bunların nasıl düzeltileceğinden de bahseder.

1. Kaynaklar: istekler ve sınırlar

Bu öğe kesinlikle en yakın ilgiyi ve listede ilk sırayı hak ediyor.

CPU isteği genellikle ya hiç belirtilmemiş ya da çok düşük bir değere sahip (her düğüme mümkün olduğunca çok bölme yerleştirmek için). Böylece düğümler aşırı yüklenmiş olur. Yükün yüksek olduğu zamanlarda düğümün işlem gücü tamamen kullanılır ve belirli bir iş yükü yalnızca "talep ettiği" şeyi alır. CPU kısıtlaması. Bu, uygulama gecikmesinin artmasına, zaman aşımlarına ve diğer hoş olmayan sonuçlara yol açar. (Bu konuda daha fazlasını diğer yeni çevirimizde okuyun: “Kubernetes'te CPU sınırları ve agresif kısıtlama" - yakl. çeviri.)

En iyi çaba (aşırı boyutta hayır tavsiye edilen):

resources: {}

Son derece düşük CPU isteği (son derece hayır tavsiye edilen):

   resources:
      Requests:
        cpu: "1m"

Öte yandan, bir CPU sınırının varlığı, düğüm işlemcisi tam olarak yüklenmemiş olsa bile, saat döngülerinin bölmeler tarafından makul olmayan şekilde atlanmasına yol açabilir. Bu da yine gecikmelerin artmasına neden olabilir. Parametre etrafında tartışmalar devam ediyor CPU CFS kotası Linux çekirdeğinde ve belirlenen sınırlara bağlı olarak CPU kısılmasında ve ayrıca CFS kotasının devre dışı bırakılmasında... Ne yazık ki, CPU sınırları çözebileceğinden daha fazla soruna neden olabilir. Bununla ilgili daha fazla bilgiyi aşağıdaki bağlantıda bulabilirsiniz.

Aşırı seçim (aşırı taahhüt) hafıza sorunları daha büyük sorunlara yol açabilir. CPU sınırına ulaşmak saat döngülerinin atlanmasını gerektirirken bellek sınırına ulaşılması kapsülün öldürülmesini gerektirir. Hiç gözlemledin mi OOMöldür? Evet, tam da bundan bahsediyoruz.

Bunun gerçekleşme olasılığını en aza indirmek ister misiniz? Belleği aşırı tahsis etmeyin ve bellek isteğini sınıra ayarlayarak (aşağıdaki örnekte olduğu gibi) Garantili QoS (Hizmet Kalitesi) kullanın. Bu konuda daha fazlasını okuyun Henning Jacobs sunumları (Zalando'da Baş Mühendis).

patlayabilir (OOM'un öldürülmesi ihtimali daha yüksek):

   resources:
      requests:
        memory: "128Mi"
        cpu: "500m"
      limits:
        memory: "256Mi"
        cpu: 2

Garantili:

   resources:
      requests:
        memory: "128Mi"
        cpu: 2
      limits:
        memory: "128Mi"
        cpu: 2

Kaynakları ayarlarken potansiyel olarak ne yardımcı olabilir?

Ile metrik sunucusu mevcut CPU kaynak tüketimini ve bellek kullanımını bölmelere (ve bunların içindeki kaplara) göre görebilirsiniz. Büyük ihtimalle zaten kullanıyorsunuz. Sadece aşağıdaki komutları çalıştırın:

kubectl top pods
kubectl top pods --containers
kubectl top nodes

Ancak yalnızca mevcut kullanımı gösterirler. Size büyüklük sırası hakkında kabaca bir fikir verebilir, ancak sonuçta ihtiyacınız olacak Zaman içinde metriklerdeki değişikliklerin geçmişi (“En yüksek CPU yükü neydi?”, “Dün sabahki yük neydi?” gibi soruları yanıtlamak için). Bunun için kullanabilirsiniz Prometheus, DataDog ve diğer araçlar. Basitçe metrik sunucusundan metrikleri alıp saklarlar ve kullanıcı bunları sorgulayabilir ve buna göre çizebilir.

VerticalPodOtomatik Ölçekleyici verir otomatikleştirmek bu süreç. CPU ve bellek kullanım geçmişini takip eder ve bu bilgilere dayanarak yeni istekler ve limitler belirler.

Bilgi işlem gücünü verimli bir şekilde kullanmak kolay bir iş değildir. Sürekli Tetris oynamak gibi. Düşük ortalama tüketimle (mesela ~%10) bilgi işlem gücüne çok fazla para ödüyorsanız, AWS Fargate veya Virtual Kubelet tabanlı ürünlere bakmanızı öneririz. Sunucusuz/kullanım başına ödemeli faturalandırma modeli üzerine kuruludurlar ve bu gibi durumlarda daha ucuz olabilir.

2. Canlılık ve hazırlık araştırmaları

Varsayılan olarak Kubernetes'te canlılık ve hazırlık kontrolleri etkin değildir. Ve bazen onları açmayı unutuyorlar...

Ancak ölümcül bir hata durumunda hizmetin yeniden başlatılmasını başka nasıl başlatabilirsiniz? Yük dengeleyici bir kapsülün trafiği kabul etmeye hazır olduğunu nasıl biliyor? Veya daha fazla trafiği kaldırabileceğini mi?

Bu testler sıklıkla birbiriyle karıştırılır:

  • Canlılık - başarısız olması durumunda bölmeyi yeniden başlatan "hayatta kalma" kontrolü;
  • hazır olma — hazırlık kontrolü; başarısız olursa bölmenin Kubernetes hizmetiyle olan bağlantısını keser (bu, kullanılarak kontrol edilebilir) kubectl get endpoints) ve bir sonraki kontrol başarıyla tamamlanana kadar trafik ona ulaşmaz.

Bu kontrollerin her ikisi de POD'UN TÜM YAŞAM DÖNGÜSÜ BOYUNCA GERÇEKLEŞTİRİLDİ. Bu çok önemli.

Yaygın bir yanılgı, hazırlık problarının yalnızca başlangıçta çalıştırılması ve böylece dengeleyicinin bölmenin hazır olduğunu bilmesidir (Ready) ve trafiği işlemeye başlayabilir. Ancak bu, kullanım seçeneklerinden yalnızca biridir.

Bir diğeri ise bölmedeki trafiğin aşırı olduğunu öğrenme ve aşırı yükler (veya bölme yoğun kaynak gerektiren hesaplamalar gerçekleştirir). Bu durumda hazırlık kontrolü yardımcı olur bölme üzerindeki yükü azaltın ve onu "soğutun". Gelecekte bir hazırlık kontrolünün başarıyla tamamlanması, bölme üzerindeki yükü tekrar artırın. Bu durumda (hazırlık testi başarısız olursa), canlılık testinin başarısız olması son derece verimsiz olacaktır. Sağlıklı ve çok çalışan bir kapsülü neden yeniden başlatalım ki?

Bu nedenle, bazı durumlarda, yanlış yapılandırılmış parametrelerle bunları etkinleştirmektense hiç kontrol yapmamak daha iyidir. Yukarıda belirtildiği gibi eğer canlılık kontrolü kopyalar hazırlık kontrolü, o zaman başınız büyük belada. Olası seçenek yapılandırmaktır yalnızca hazırlık testiVe tehlikeli canlılık bir kenara bırakın.

Ortak bağımlılıklar başarısız olduğunda her iki denetim türü de başarısız olmamalıdır; aksi takdirde bu, tüm bölmelerde basamaklı (çığ benzeri) bir arızaya yol açacaktır. Başka bir deyişle, kendine zarar verme.

3. Her HTTP hizmeti için LoadBalancer

Büyük olasılıkla kümenizde dış dünyaya iletmek istediğiniz HTTP hizmetleriniz var.

Hizmeti şu şekilde açarsanız: type: LoadBalancer, denetleyicisi (hizmet sağlayıcısına bağlı olarak) harici bir LoadBalancer sağlayacak ve pazarlık yapacaktır (L7'de çalışması gerekmez, hatta L4'te bile çalışır) ve bu, maliyeti etkileyebilir (harici statik IPv4 adresi, bilgi işlem gücü, saniye başına faturalandırma) ) bu tür çok sayıda kaynak yaratma ihtiyacı nedeniyle.

Bu durumda tek bir harici yük dengeleyici kullanmak, hizmetleri şu şekilde açmak çok daha mantıklıdır: type: NodePort. Veya daha iyisi, şunun gibi bir şeyi genişletin: nginx-giriş denetleyicisi (ya Traefik), tek kişi kim olacak Düğüm Bağlantı Noktası harici yük dengeleyiciyle ilişkili uç nokta ve kümedeki trafiği kullanarak yönlendirir giriş-Kubernetes kaynakları.

Birbirleriyle etkileşime giren diğer küme içi (mikro) hizmetler, aşağıdaki hizmetleri kullanarak "iletişim kurabilir": Küme IP'si ve DNS aracılığıyla yerleşik bir hizmet bulma mekanizması. Gecikmeyi etkileyebileceği ve bulut hizmetlerinin maliyetini artırabileceği için genel DNS/IP'lerini kullanmayın.

4. Bir kümenin özelliklerini dikkate almadan otomatik ölçeklendirme

Bir kümeye düğüm eklerken ve bunları kümeden kaldırırken, bu düğümlerdeki CPU kullanımı gibi bazı temel ölçümlere güvenmemelisiniz. Pod planlaması birçok şeyi hesaba katmalıdır kısıtlamalarPod/düğüm benzeşimi, kusurlar ve toleranslar, kaynak istekleri, QoS vb. gibi. Bu nüansları dikkate almayan harici bir otomatik ölçekleyicinin kullanılması sorunlara yol açabilir.

Belirli bir bölmenin programlanması gerektiğini, ancak mevcut tüm CPU gücünün istendiğini/dağıtıldığını ve bölmenin bir durumda sıkışıp kalıyor Pending. Harici otomatik ölçekleyici ortalama mevcut CPU yükünü görür (istenen yükü değil) ve genişletmeyi başlatmaz (ölçeklendirme) - başka bir düğüm eklemez. Sonuç olarak bu bölme planlanmayacak.

Bu durumda ters ölçeklendirme (ölçek büyütme) — Bir düğümü kümeden kaldırmanın uygulanması her zaman daha zordur. Durum bilgisi olan bir bölmeniz olduğunu (kalıcı depolama bağlıyken) hayal edin. Kalıcı hacimler genellikle aittir özel kullanılabilirlik bölgesi ve bölgede çoğaltılmaz. Bu nedenle, harici bir otomatik ölçekleyici bu bölmeye sahip bir düğümü silerse, zamanlayıcı bu bölmeyi başka bir düğümde planlayamaz çünkü bu yalnızca kalıcı depolamanın bulunduğu kullanılabilirlik bölgesinde yapılabilir. Pod durumunda takılı kalacak Pending.

Kubernetes topluluğunda çok popüler küme-otomatik ölçekleyici. Bir küme üzerinde çalışır, büyük bulut sağlayıcılarının API'lerini destekler, tüm kısıtlamaları dikkate alır ve yukarıdaki durumlarda ölçeklenebilir. Ayrıca belirlenen tüm limitleri korurken ölçeklenebilir ve böylece paradan tasarruf edebilir (aksi takdirde kullanılmayan kapasiteye harcanacaktır).

5. IAM/RBAC yeteneklerinin ihmal edilmesi

Kalıcı sırlara sahip IAM kullanıcılarını kullanmamaya dikkat edin. makineler ve uygulamalar. Rolleri ve hizmet hesaplarını kullanarak geçici erişimi düzenleyin (hizmet hesapları).

Erişim anahtarlarının (ve sırların) uygulama yapılandırmasında sabit kodlandığı ve Cloud IAM erişimine sahip olmamıza rağmen sırların rotasyonunun ihmal edildiği gerçeğiyle sıklıkla karşılaşıyoruz. Uygun olduğunda kullanıcılar yerine IAM rollerini ve hizmet hesaplarını kullanın.

Kubernetes Kullanırken Yapılan 10 Yaygın Hata

Kube2iam'i unutun ve doğrudan hizmet hesapları için IAM rollerine gidin (bkz. aynı isimli not Štěpán Vraný):

apiVersion: v1
kind: ServiceAccount
metadata:
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/my-app-role
  name: my-serviceaccount
  namespace: default

Bir açıklama. O kadar da zor değil, değil mi?

Ayrıca hizmet hesaplarına ve örnek profil ayrıcalıklarına izin vermeyin admin и cluster-admineğer ihtiyaçları yoksa. Bunun uygulanması özellikle RBAC K8'lerde biraz daha zordur, ancak kesinlikle çabaya değer.

6. Kapsüller için otomatik anti-afiniteye güvenmeyin

Bir düğümde bazı dağıtımın üç kopyasına sahip olduğunuzu hayal edin. Düğüm ve onunla birlikte tüm kopyalar düşer. Hoş olmayan bir durum, değil mi? Peki neden tüm kopyalar aynı düğümdeydi? Kubernetes'in yüksek kullanılabilirlik (HA) sağlaması gerekmiyor mu?

Maalesef Kubernetes zamanlayıcısı kendi inisiyatifiyle ayrı varoluş kurallarına uymuyor (karşıt yakınlık) baklalar için. Açıkça belirtilmeleri gerekir:

// опущено для краткости
      labels:
        app: zk
// опущено для краткости
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchExpressions:
                  - key: "app"
                    operator: In
                    values:
                    - zk
              topologyKey: "kubernetes.io/hostname"

Bu kadar. Artık bölmeler farklı düğümlerde planlanacak (bu durum yalnızca planlama sırasında kontrol edilir, ancak operasyonları sırasında kontrol edilmez; dolayısıyla requiredDuringSchedulingIgnoredDuringExecution).

Burada bahsediyoruz podAntiAffinity farklı düğümlerde: topologyKey: "kubernetes.io/hostname", - ve farklı kullanılabilirlik bölgeleriyle ilgili değil. Tam teşekküllü bir HA uygulamak için bu konuyu daha derinlemesine incelemeniz gerekecek.

7. PodDisruptionBütçelerini Göz Ardı Etme

Bir Kubernetes kümesinde üretim yükünüz olduğunu düşünün. Periyodik olarak, düğümlerin ve kümenin kendisinin güncellenmesi (veya hizmet dışı bırakılması) gerekir. PodDisruptionBudget (PDB), küme yöneticileri ve kullanıcılar arasındaki hizmet garantisi sözleşmesine benzer bir şeydir.

PDB, düğüm eksikliğinden kaynaklanan hizmet kesintilerini önlemenize olanak tanır:

apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
  name: zk-pdb
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: zookeeper

Bu örnekte, kümenin bir kullanıcısı olarak yöneticilere şunları söylüyorsunuz: "Hey, benim bir zookeeper hizmetim var ve ne yaparsanız yapın, bu hizmetin en az 2 kopyasının her zaman kullanılabilir olmasını istiyorum."

Bu konuda daha fazlasını okuyabilirsiniz burada.

8. Ortak bir kümede birden fazla kullanıcı veya ortam

Kubernetes ad alanları (ad alanları) güçlü yalıtım sağlamaz.

Yaygın bir yanılgı şu ki, üretim olmayan bir yükü bir ad alanına ve bir üretim yükünü diğerine dağıtırsanız, o zaman hiçbir şekilde birbirini etkilemeyecek... Bununla birlikte, kaynak istekleri/sınırlamaları, kotaların belirlenmesi ve öncelik Sınıflarının ayarlanması kullanılarak belirli bir düzeyde izolasyon elde edilebilir. Veri düzlemindeki bazı "fiziksel" izolasyonlar yakınlıklar, hoşgörüler, kusurlar (veya düğüm seçiciler) tarafından sağlanır, ancak bu tür bir ayırma oldukça zor uygulamak.

Her iki tür iş yükünü aynı kümede birleştirmesi gerekenler karmaşıklıkla uğraşmak zorunda kalacak. Böyle bir ihtiyaç yoksa ve bir tane almaya gücünüz yetiyorsa bir küme daha (mesela genel bir bulutta), o zaman bunu yapmak daha iyidir. Bu çok daha yüksek bir yalıtım seviyesine ulaşacaktır.

9. externalTrafficPolicy: Küme

Çoğu zaman küme içindeki tüm trafiğin, varsayılan politikanın ayarlandığı NodePort gibi bir hizmet aracılığıyla geldiğini görüyoruz. externalTrafficPolicy: Cluster. Bu demektir ki Düğüm Bağlantı Noktası kümedeki her düğümde açıktır ve istediğiniz hizmetle (bölme kümesi) etkileşimde bulunmak için bunlardan herhangi birini kullanabilirsiniz.

Kubernetes Kullanırken Yapılan 10 Yaygın Hata

Aynı zamanda, yukarıda bahsedilen NodePort hizmetiyle ilişkili gerçek bölmeler genellikle yalnızca belirli bir platformda mevcuttur. bu düğümlerin alt kümesi. Yani gerekli pod’a sahip olmayan bir node’a bağlanırsam trafiği başka bir node’a iletecek, bir atlama ekleme ve gecikme süresinin artması (düğümler farklı kullanılabilirlik bölgelerinde/veri merkezlerinde bulunuyorsa gecikme oldukça yüksek olabilir; ayrıca çıkış trafiği maliyetleri de artacaktır).

Öte yandan, belirli bir Kubernetes hizmetinin bir politika seti varsa externalTrafficPolicy: Local, NodePort yalnızca gerekli bölmelerin gerçekte çalıştığı düğümlerde açılır. Durumu kontrol eden harici bir yük dengeleyici kullanıldığında (sağlık kontrolü) uç noktalar (nasıl yapılır AWS ELB), O trafiği yalnızca gerekli düğümlere gönderecekgecikmeler, bilgi işlem ihtiyaçları, çıkış faturaları (ve sağduyu da aynısını gerektirir) üzerinde faydalı bir etkiye sahip olacaktır.

Zaten böyle bir şey kullanıyor olma ihtimaliniz yüksek Traefik veya nginx-giriş denetleyicisi HTTP giriş trafiğini yönlendirmek için bir NodePort uç noktası (veya NodePort'u da kullanan LoadBalancer) olarak kullanılır ve bu seçeneğin ayarlanması, bu tür isteklere yönelik gecikmeyi önemli ölçüde azaltabilir.

В bu yayın externalTrafficPolicy, avantajları ve dezavantajları hakkında daha fazla bilgi edinebilirsiniz.

10. Kümelere bağlanmayın ve kontrol düzlemini kötüye kullanmayın

Daha önce sunucuları özel adlarla çağırmak gelenekseldi: Anton, HAL9000 ve Colossus... Bugün bunların yerini rastgele oluşturulmuş tanımlayıcılar aldı. Ancak alışkanlık devam etti ve artık özel isimler kümelere ayrılıyor.

Tipik bir hikaye (gerçek olaylara dayanan): her şey bir konseptin kanıtlanmasıyla başladı, dolayısıyla küme gurur verici bir isme sahip oldu test yapmak… Aradan yıllar geçti ve HALA üretimde kullanılıyor ve herkes ona dokunmaya korkuyor.

Salkımların evcil hayvana dönüşmesinin hiç eğlenceli bir yanı yok, bu yüzden pratik yaparken onları periyodik olarak kaldırmanızı öneririz. felaket kurtarma (Bu yardımcı olacak kaos mühendisliği - yaklaşık. çeviri.). Ayrıca kontrol katmanı üzerinde çalışmaktan zarar gelmez (kontrol Paneli). Ona dokunmaktan korkmak iyiye işaret değil. vb. ölü? Arkadaşlar, başınız gerçekten belada!

Öte yandan, onu manipüle etmeye de kapılmamalısınız. Zamanla kontrol katmanı yavaşlayabilir. Büyük olasılıkla, bunun nedeni çok sayıda nesnenin döndürülmeden oluşturulmasıdır (Helm'i varsayılan ayarlarla kullanırken yaygın bir durum, bu nedenle yapılandırma haritaları/gizli dizilerdeki durumu güncellenmiyor - sonuç olarak binlerce nesne birikiyor) kontrol katmanı) veya kube-api nesnelerinin sürekli düzenlenmesiyle (otomatik ölçeklendirme için, CI/CD için, izleme, olay günlükleri, denetleyiciler vb. için).

Ayrıca yönetilen Kubernetes sağlayıcı ile yapılan SLA/SLO anlaşmalarını kontrol etmenizi ve garantilere dikkat etmenizi öneririz. Satıcı garanti edebilir kontrol katmanı kullanılabilirliği (veya alt bileşenleri), ancak ona gönderdiğiniz isteklerin p99 gecikmesi değil. Başka bir deyişle girebilirsiniz kubectl get nodesve yalnızca 10 dakika sonra yanıt alırsınız; bu, hizmet sözleşmesi şartlarının ihlali olmayacaktır.

11. Bonus: En son etiketi kullanmak

Ama bu zaten bir klasik. Son zamanlarda bu tekniğe daha az rastladık, çünkü çoğu kişi acı deneyimlerden ders alarak etiketi kullanmayı bıraktı. :latest ve versiyonları sabitlemeye başladım. Yaşasın!

ECR resim etiketlerinin değişmezliğini korur; Bu olağanüstü özelliği tanımanızı öneririz.

Özet

Her şeyin bir gecede işe yaramasını beklemeyin: Kubernetes her derde deva değildir. Kötü uygulama Kubernetes'te bile bu şekilde kalacak (ve muhtemelen daha da kötüleşecek). Dikkatsizlik, aşırı karmaşıklığa, kontrol katmanının yavaş ve stresli çalışmasına yol açacaktır. Ayrıca olağanüstü durum kurtarma stratejisinden mahrum kalma riskiyle karşı karşıya kalırsınız. Kubernetes'in kullanıma hazır izolasyon ve yüksek kullanılabilirlik sunmasını beklemeyin. Uygulamanızı gerçekten bulutta yerel hale getirmek için biraz zaman ayırın.

Çeşitli ekiplerin başarısız deneyimlerini tanıyabilirsiniz. bu hikaye koleksiyonu Henning Jacobs tarafından.

Bu yazıda verilen hatalar listesine eklemek isteyenler Twitter'dan bizimle iletişime geçebilirler (@MarekBartik, @MstrsObserver).

çevirmenden PS

Blogumuzda da okuyun:

Kaynak: habr.com

Yorum ekle