Dokuz Kubernetes Performans İpucu

Dokuz Kubernetes Performans İpucu

Herkese selam! Adım Oleg Sidorenkov, DomClick'te altyapı ekibinin başı olarak çalışıyorum. Kubik'i üç yılı aşkın süredir üretimde kullanıyoruz ve bu süre zarfında onunla birçok farklı ilginç an yaşadık. Bugün size doğru yaklaşımla kümeniz için standart Kubernetes'ten nasıl daha fazla performans elde edebileceğinizi anlatacağım. Hazır olun, istikrarlı bir şekilde ilerleyin!

Kubernetes'in konteyner orkestrasyonu için ölçeklenebilir, açık kaynaklı bir sistem olduğunu hepiniz çok iyi biliyorsunuz; ya da bir sunucu ortamında mikro hizmetlerinizin yaşam döngüsünü yöneterek sihirli bir şekilde çalışan 5 ikili dosya. Ayrıca farklı görevler için maksimum kişiselleştirme sağlamak üzere Lego gibi birleştirilebilen oldukça esnek bir araçtır.

Ve her şey yolunda görünüyor: Sunucuları, yakacak odunun ateş kutusuna atılması gibi, kümeye atın ve hiçbir üzüntü yaşamayacaksınız. Ama çevreden yanaysanız şöyle düşüneceksiniz: “Ateşi nasıl canlı tutabilirim ve ormanı nasıl koruyabilirim?” Başka bir deyişle, altyapıyı iyileştirmenin ve maliyetleri azaltmanın yollarını nasıl bulacağız?

1. Ekip ve uygulama kaynaklarını izleyin

Dokuz Kubernetes Performans İpucu

En yaygın fakat etkili yöntemlerden biri, isteklerin/sınırların getirilmesidir. Uygulamaları ad alanlarına ve ad alanlarını da geliştirme ekiplerine göre bölün. Dağıtımdan önce işlemci zamanı, bellek ve geçici depolama tüketimine ilişkin uygulama değerlerini ayarlayın.

resources:
   requests:
     memory: 2Gi
     cpu: 250m
   limits:
     memory: 4Gi
     cpu: 500m

Deneyimlerimiz sonucunda şu sonuca vardık: Limitlerdeki talepleri iki kattan fazla artırmamalısınız. Kümenin hacmi isteklere göre hesaplanır ve uygulamalara örneğin 5-10 kez kaynak farkı verirseniz, düğümünüz pod'larla dolduğunda ve aniden yük aldığında başına ne geleceğini hayal edin. Hiçbir şey iyi değil. Minimumda, kısıtlama ve maksimumda, çalışana veda edeceksiniz ve bölmeler hareket etmeye başladıktan sonra kalan düğümlerde döngüsel bir yük alacaksınız.

Ayrıca yardımıyla limitranges Başlangıçta, kapsayıcı için kaynak değerlerini (minimum, maksimum ve varsayılan) ayarlayabilirsiniz:

➜  ~ kubectl describe limitranges --namespace ops
Name:       limit-range
Namespace:  ops
Type        Resource           Min   Max   Default Request  Default Limit  Max Limit/Request Ratio
----        --------           ---   ---   ---------------  -------------  -----------------------
Container   cpu                50m   10    100m             100m           2
Container   ephemeral-storage  12Mi  8Gi   128Mi            4Gi            -
Container   memory             64Mi  40Gi  128Mi            128Mi          2

Bir ekibin kümenin tüm kaynaklarını devralamaması için ad alanı kaynaklarını sınırlamayı unutmayın:

➜  ~ kubectl describe resourcequotas --namespace ops
Name:                   resource-quota
Namespace:              ops
Resource                Used          Hard
--------                ----          ----
limits.cpu              77250m        80
limits.memory           124814367488  150Gi
pods                    31            45
requests.cpu            53850m        80
requests.memory         75613234944   150Gi
services                26            50
services.loadbalancers  0             0
services.nodeports      0             0

Açıklamasından da anlaşılacağı üzere resourcequotas, eğer operasyon ekibi başka bir 10 işlemci tüketecek bölmeleri dağıtmak isterse, zamanlayıcı buna izin vermeyecek ve bir hata verecektir:

Error creating: pods "nginx-proxy-9967d8d78-nh4fs" is forbidden: exceeded quota: resource-quota, requested: limits.cpu=5,requests.cpu=5, used: limits.cpu=77250m,requests.cpu=53850m, limited: limits.cpu=10,requests.cpu=10

Böyle bir sorunu çözmek için örneğin şöyle bir araç yazabilirsiniz: bu, komuta kaynaklarının durumunu saklayabilir ve gerçekleştirebilir.

2. En uygun dosya depolama alanını seçin

Dokuz Kubernetes Performans İpucu

Burada kalıcı birimler konusuna ve Kubernetes çalışan düğümlerinin disk alt sistemine değinmek istiyorum. Umarım hiç kimse üretimde bir HDD'deki "Küp"ü kullanmaz, ancak bazen normal bir SSD artık yeterli değildir. G/Ç işlemleri nedeniyle günlüklerin diski sonlandırdığı bir sorunla karşılaştık ve çok fazla çözüm yok:

  • Yüksek performanslı SSD'ler kullanın veya NVMe'ye geçin (kendi donanımınızı yönetiyorsanız).

  • Günlük düzeyini azaltın.

  • Diske tecavüz eden kapsüllerin “akıllı” dengelemesini yapın (podAntiAffinity).

Yukarıdaki ekran, erişim_logları günlüğü etkinleştirildiğinde (~12 bin günlük/sn) nginx-ingress-controller altında diskte neler olduğunu gösterir. Bu durum elbette bu düğümdeki tüm uygulamaların bozulmasına yol açabilir.

PV'ye gelince, ne yazık ki her şeyi denemedim türleri Kalıcı Hacimler. Size uygun en iyi seçeneği kullanın. Tarihsel olarak ülkemizde hizmetlerin küçük bir kısmının RWX hacimleri gerektirdiği olmuştur ve uzun zaman önce bu görev için NFS depolamayı kullanmaya başlamışlardır. Ucuz ve... yeterli. Elbette o ve ben bok yedik, çok şükür ama bunu görmezden gelmeyi öğrendik ve artık başım ağrımıyor. Mümkünse S3 nesne depolamaya geçin.

3. Optimize edilmiş görselleri toplayın

Dokuz Kubernetes Performans İpucu

Kubernetes'in bunları daha hızlı alıp daha verimli bir şekilde yürütebilmesi için kapsayıcı için optimize edilmiş görüntüleri kullanmak en iyisidir. 

Optimize edilmiş, görsellerin şu anlama geldiği anlamına gelir:

  • yalnızca bir uygulamayı içerir veya yalnızca bir işlevi gerçekleştirir;

  • boyutu küçüktür, çünkü büyük görüntüler ağ üzerinden daha kötü iletilir;

  • Kesinti durumunda Kubernetes'in harekete geçmesine olanak tanıyan sağlık ve hazırlık uç noktalarına sahip olun;

  • yapılandırma hatalarına karşı daha dayanıklı olan konteyner dostu işletim sistemlerini (Alpine veya CoreOS gibi) kullanın;

  • çok aşamalı yapıları kullanın, böylece eşlik eden kaynakları değil, yalnızca derlenmiş uygulamaları dağıtabilirsiniz.

Görüntüleri anında kontrol etmenize ve optimize etmenize olanak tanıyan birçok araç ve hizmet vardır. Bunların her zaman güncel tutulması ve güvenlik açısından test edilmesi önemlidir. Sonuç olarak şunları elde edersiniz:

  1. Kümenin tamamında azaltılmış ağ yükü.

  2. Konteyner başlatma süresinin azaltılması.

  3. Docker kayıt defterinizin tamamının daha küçük boyutu.

4. DNS önbelleğini kullanın

Dokuz Kubernetes Performans İpucu

Yüksek yüklerden bahsedersek, kümenin DNS sistemini ayarlamadan hayat oldukça berbat demektir. Bir zamanlar Kubernetes geliştiricileri kube-dns çözümlerini destekliyorlardı. Burada da uygulandı ancak bu yazılım, basit bir görev gibi görünmesine rağmen özel olarak ayarlanmadı ve gerekli performansı üretmedi. Daha sonra coredns ortaya çıktı, biz de geçiş yaptık ve hiçbir sorun yaşamadık; daha sonra K8'lerde varsayılan DNS hizmeti haline geldi. Bir noktada DNS sistemine 40 bin rps'ye çıktık, bu çözüm de yetersiz kalmaya başladı. Ancak şans eseri, Nodelocaldn'ler ortaya çıktı, yani yerel düğüm önbelleği, yani DüğümYerel DNSCache.

Bunu neden kullanıyoruz? Linux çekirdeğinde, UDP üzerinden bağlantı NAT üzerinden birden fazla çağrı yapıldığında, bağlantı tablolarındaki girişler için yarış durumuna yol açan ve NAT üzerinden trafiğin bir kısmının kaybolduğu (Hizmet üzerinden yapılan her yolculuk NAT'tır) bir hata vardır. Nodelocaldns, NAT'tan kurtularak ve TCP bağlantısını yukarı akış DNS'ye yükselterek ve ayrıca yukarı akış DNS sorgularını yerel olarak önbelleğe alarak (5 saniyelik kısa bir negatif önbellek dahil) bu sorunu çözer.

5. Bölmeleri yatay ve dikey olarak otomatik olarak ölçeklendirin

Dokuz Kubernetes Performans İpucu

Tüm mikro hizmetlerinizin yükte iki ila üç kat artışa hazır olduğunu güvenle söyleyebilir misiniz? Kaynakları uygulamalarınıza doğru şekilde nasıl tahsis edebilirsiniz? Birkaç kapsülün iş yükünün ötesinde çalışmasını sağlamak gereksiz olabilir, ancak bunları arka arkaya tutmak, hizmete gelen trafikte ani bir artış nedeniyle kesinti riski doğurur. Gibi hizmetler Yatay Pod Otomatik Ölçekleyici и Dikey Kapsül Otomatik Ölçekleyici.

VPA Gerçek kullanıma bağlı olarak bölmedeki kapsayıcılarınızın isteklerini/sınırlarını otomatik olarak yükseltmenize olanak tanır. Nasıl faydalı olabilir? Herhangi bir nedenle yatay olarak ölçeklendirilemeyen bölmeleriniz varsa (ki bu tamamen güvenilir değildir), kaynaklarındaki değişiklikleri VPA'ya emanet etmeyi deneyebilirsiniz. Özelliği, metrik sunucudan gelen geçmiş ve güncel verilere dayalı bir öneri sistemidir; dolayısıyla istekleri/limitleri otomatik olarak değiştirmek istemiyorsanız, konteynerleriniz için önerilen kaynakları kolayca izleyebilir ve CPU'dan tasarruf etmek için ayarları optimize edebilirsiniz. kümedeki bellek.

Dokuz Kubernetes Performans İpucuResim https://levelup.gitconnected.com/kubernetes-autoscaling-101-cluster-autoscaler-horizontal-pod-autoscaler-and-vertical-pod-2a441d9ad231 adresinden alınmıştır.

Kubernetes'teki zamanlayıcı her zaman isteklere dayalıdır. Oraya ne değer koyarsanız koyun, zamanlayıcı buna göre uygun bir düğüm arayacaktır. Küpün, pod'u ne zaman kısacağını veya sonlandıracağını anlaması için sınır değerlerine ihtiyaç vardır. Tek önemli parametre istek değeri olduğundan VPA onunla çalışacaktır. Bir uygulamayı dikey olarak ölçeklendirdiğinizde isteklerin ne olması gerektiğini tanımlarsınız. O zaman sınırlar ne olacak? Bu parametre de orantılı olarak ölçeklendirilecektir.

Örneğin, olağan bölme ayarları şunlardır:

resources:
   requests:
     memory: 250Mi
     cpu: 200m
   limits:
     memory: 500Mi
     cpu: 350m

Öneri motoru, uygulamanızın düzgün çalışması için 300m CPU ve 500Mi gerektirdiğini belirler. Aşağıdaki ayarları alacaksınız:

resources:
   requests:
     memory: 500Mi
     cpu: 300m
   limits:
     memory: 1000Mi
     cpu: 525m

Yukarıda belirtildiği gibi bu, bildirimdeki istek/sınır oranına dayalı orantılı ölçeklendirmedir:

  • CPU: 200 m → 300 m: oran 1:1.75;

  • Bellek: 250Mi → 500Mi: oran 1:2.

göre HPA, o zaman çalışma mekanizması daha şeffaftır. CPU ve bellek gibi metrikler eşiklenir ve tüm replikaların ortalaması eşiği aşarsa, değer eşiğin altına düşene veya maksimum replika sayısına ulaşılana kadar uygulama +1 alt ölçeklendirilir.

Dokuz Kubernetes Performans İpucuResim https://levelup.gitconnected.com/kubernetes-autoscaling-101-cluster-autoscaler-horizontal-pod-autoscaler-and-vertical-pod-2a441d9ad231 adresinden alınmıştır.

CPU ve bellek gibi olağan ölçümlere ek olarak, Prometheus'tan özel ölçümleriniz için eşikler ayarlayabilir ve uygulamanızı ne zaman ölçeklendireceğinize dair en doğru göstergenin bu olduğunu düşünüyorsanız onlarla çalışabilirsiniz. Uygulama belirtilen metrik eşiğin altında stabil hale geldiğinde HPA, bölmeleri minimum kopya sayısına veya yük belirtilen eşiğe ulaşana kadar ölçeklendirmeye başlayacaktır.

6. Node Affinity ve Pod Affinity'yi unutmayın

Dokuz Kubernetes Performans İpucu

Tüm düğümler aynı donanımda çalışmaz ve tüm bölmelerin yoğun bilgi işlem gerektiren uygulamaları çalıştırması gerekmez. Kubernetes, kullanarak düğümlerin ve bölmelerin uzmanlığını ayarlamanıza olanak tanır. Düğüm Yakınlığı и Kapsül Yakın İlgi Alanı.

Yoğun bilgi işlem işlemlerine uygun düğümleriniz varsa maksimum verimlilik için uygulamaları ilgili düğümlere bağlamak daha iyidir. Bunu yapmak için kullanın nodeSelector bir düğüm etiketi ile.

Diyelim ki iki düğümünüz var: biri CPUType=HIGHFREQ ve çok sayıda hızlı çekirdek, bir diğeri MemoryType=HIGHMEMORY daha fazla bellek ve daha hızlı performans. En kolay yol, dağıtımı bir düğüme atamaktır HIGHFREQbölüme ekleyerek spec bu seçici:

…
nodeSelector:
	CPUType: HIGHFREQ

Bunu yapmanın daha pahalı ve özel bir yolu kullanmaktır. nodeAffinity alanında affinity bölüm spec. İki seçenek var:

  • requiredDuringSchedulingIgnoredDuringExecution: sabit ayar (zamanlayıcı, bölmeleri yalnızca belirli düğümlere (ve başka hiçbir yere) dağıtmaz);

  • preferredDuringSchedulingIgnoredDuringExecution: yumuşak ayar (zamanlayıcı belirli düğümlere konuşlandırmayı deneyecektir ve bu başarısız olursa, bir sonraki kullanılabilir düğüme konuşlandırmayı deneyecektir).

Düğüm etiketlerini yönetmek için aşağıdaki gibi belirli bir sözdizimi belirtebilirsiniz: In, NotIn, Exists, DoesNotExist, Gt veya Lt. Ancak uzun etiket listelerindeki karmaşık yöntemlerin kritik durumlarda karar vermeyi yavaşlatacağını unutmayın. Başka bir deyişle, işi basit tutun.

Yukarıda belirtildiği gibi Kubernetes, mevcut podların benzeşimini ayarlamanıza olanak tanır. Yani, belirli bölmelerin aynı kullanılabilirlik bölgesindeki (bulutlarla ilgili) veya düğümlerdeki diğer bölmelerle birlikte çalıştığından emin olabilirsiniz.

В podAffinity поля affinity bölüm spec durumunda olduğu gibi aynı alanlar mevcuttur nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution и preferredDuringSchedulingIgnoredDuringExecution. Tek fark şu ki matchExpressions bölmeleri, zaten bu etikete sahip bir bölmeyi çalıştıran bir düğüme bağlayacaktır.

Kubernetes ayrıca bir alan sunuyor podAntiAffinity, aksine, bölmeyi belirli bölmelere sahip bir düğüme bağlamaz.

İfadeler hakkında nodeAffinity Aynı tavsiye şu şekilde verilebilir: kuralları basit ve mantıklı tutmaya çalışın, bölme spesifikasyonunu karmaşık kurallar dizisiyle aşırı yüklemeye çalışmayın. Kümenin koşullarıyla eşleşmeyecek, zamanlayıcı üzerinde gereksiz yük oluşturacak ve genel performansı düşürecek bir kural oluşturmak çok kolaydır.

7. Kusurlar ve Toleranslar

Zamanlayıcıyı yönetmenin başka bir yolu var. Yüzlerce düğüme ve binlerce mikro hizmete sahip büyük bir kümeniz varsa belirli düğümlerin belirli düğümlerde barındırılmasına izin vermemek çok zordur.

Kusur mekanizması (kuralları yasaklamak) buna yardımcı olur. Örneğin, belirli senaryolarda belirli düğümlerin bölmeleri çalıştırmasını yasaklayabilirsiniz. Belirli bir düğüme leke uygulamak için bu seçeneği kullanmanız gerekir taint kubectl'de. Anahtarı ve değeri belirtin ve ardından leke gibi NoSchedule veya NoExecute:

$ kubectl taint nodes node10 node-role.kubernetes.io/ingress=true:NoSchedule

Ayrıca koku mekanizmasının üç ana etkiyi desteklediğini de belirtmekte fayda var: NoSchedule, NoExecute и PreferNoSchedule.

  • NoSchedule şimdilik bölme spesifikasyonunda buna karşılık gelen bir giriş olmayacağı anlamına gelir tolerationsdüğümde konuşlandırılamayacak (bu örnekte) node10).

  • PreferNoSchedule - basitleştirilmiş versiyon NoSchedule. Bu durumda zamanlayıcı, eşleşen girişi olmayan bölmeleri tahsis etmemeye çalışacaktır. tolerations düğüm başına, ancak bu zor bir sınırlama değildir. Kümede kaynak yoksa bölmeler bu düğümde dağıtılmaya başlayacaktır.

  • NoExecute - bu etki, karşılık gelen girişi olmayan bölmelerin derhal boşaltılmasını tetikler tolerations.

İlginç bir şekilde bu davranış, tolerans mekanizması kullanılarak iptal edilebilir. Bu, "yasak" bir düğüm olduğunda ve üzerine yalnızca altyapı hizmetlerini yerleştirmeniz gerektiğinde kullanışlıdır. Nasıl yapılır? Yalnızca uygun toleransın olduğu bölmelere izin verin.

Pod spesifikasyonunun şu şekilde görüneceği:

spec:
   tolerations:
     - key: "node-role.kubernetes.io/ingress"
        operator: "Equal"
        value: "true"
        effect: "NoSchedule"

Bu, bir sonraki yeniden dağıtımın bu belirli düğüme düşeceği anlamına gelmez; bu, Düğüm Yakınlığı mekanizması değildir ve nodeSelector. Ancak çeşitli özellikleri birleştirerek çok esnek zamanlayıcı ayarları elde edebilirsiniz.

8. Pod Dağıtım Önceliğini Ayarlayın

Düğümlere atanmış bölmelerinizin olması, tüm bölmelerin aynı öncelikle ele alınması gerektiği anlamına gelmez. Örneğin, bazı bölmeleri diğerlerinden önce dağıtmak isteyebilirsiniz.

Kubernetes, Pod Önceliğini ve Ön Alma'yı yapılandırmak için farklı yollar sunar. Ayar birkaç bölümden oluşur: nesne PriorityClass ve alan açıklamaları priorityClassName bölme spesifikasyonunda. Bir örneğe bakalım:

apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: high-priority
value: 99999
globalDefault: false
description: "This priority class should be used for very important pods only"

Biz yaratırız PriorityClass, ona bir ad, açıklama ve değer verin. Daha yüksek valueöncelik ne kadar yüksek olursa. Değer, 32'dan küçük veya ona eşit herhangi bir 1 bit tamsayı olabilir. Daha yüksek değerler, genellikle önlenemeyen kritik görev sistem bölmeleri için ayrılmıştır. Yer değiştirme yalnızca yüksek öncelikli bir bölmenin dönecek yeri olmadığında meydana gelir ve belirli bir düğümdeki bölmelerden bazıları tahliye edilir. Bu mekanizma size çok katı geliyorsa seçeneği ekleyebilirsiniz. preemptionPolicy: Never, ve bu durumda herhangi bir ön alım olmayacak, bölme kuyrukta ilk sırada duracak ve zamanlayıcının kendisi için ücretsiz kaynaklar bulmasını bekleyecektir.

Daha sonra, adını belirttiğimiz bir bölme oluşturuyoruz priorityClassName:

apiVersion: v1
kind: Pod
metadata:
  name: static-web
  labels:
    role: myrole
 spec:
  containers:
    - name: web
      image: nginx
      ports:
        - name: web
          containerPort: 80
          protocol: TCP
  priorityClassName: high-priority
          

İstediğiniz kadar öncelikli sınıf oluşturabilirsiniz, ancak buna kapılmamanız tavsiye edilir (örneğin, kendinizi düşük, orta ve yüksek önceliklerle sınırlandırın).

Böylece gerekirse nginx-ingres-controller, coredns vb. gibi kritik hizmetlerin dağıtımının verimliliğini artırabilirsiniz.

9. ETCD kümesini optimize edin

Dokuz Kubernetes Performans İpucu

ETCD, tüm kümenin beyni olarak adlandırılabilir. Cube'daki işlemlerin hızı buna bağlı olduğundan bu veritabanının çalışmasını yüksek seviyede tutmak çok önemlidir. Oldukça standart ve aynı zamanda iyi bir çözüm, kube-apserver'da minimum gecikmeyi sağlamak için ETCD kümesini ana düğümlerde tutmak olacaktır. Bunu yapamıyorsanız, ETCD'yi katılımcılar arasında bant genişliği iyi olacak şekilde mümkün olduğunca yakına yerleştirin. Ayrıca ETCD'den kaç düğümün kümeye zarar vermeden düşebileceğine de dikkat edin

Dokuz Kubernetes Performans İpucu

Bir kümedeki üye sayısını aşırı artırmanın, performans pahasına hata toleransını artırabileceğini unutmayın; her şey ölçülü olmalıdır.

Hizmeti kurma hakkında konuşursak, birkaç öneri var:

  1. Kümenin boyutuna bağlı olarak iyi bir donanıma sahip olun (okuyabilirsiniz) burada).

  2. Bir kümeyi bir çift DC veya ağınız arasında dağıttıysanız ve diskler arzu edilenden çok şey bırakıyorsa, birkaç parametrede ince ayar yapın (okuyabilirsiniz) burada).

Sonuç

Bu yazıda ekibimizin uymaya çalıştığı noktalar anlatılmaktadır. Bu, eylemlerin adım adım açıklaması değildir, ancak küme yükünü optimize etmek için yararlı olabilecek seçeneklerdir. Her kümenin kendine göre benzersiz olduğu ve yapılandırma çözümlerinin büyük ölçüde farklılık gösterebileceği açıktır; dolayısıyla Kubernetes kümenizi nasıl izleyeceğiniz ve performansını nasıl geliştireceğiniz konusunda geri bildirimlerinizi almak ilginç olacaktır. Deneyiminizi yorumlarda paylaşın, bilmek ilginç olacak.

Kaynak: habr.com