Kubernetes'te otomatik ölçeklendirme ve kaynak yönetimi (inceleme ve video raporu)

27 Nisan konferansta Grev 2019“DevOps” bölümü kapsamında “Kubernetes'te otomatik ölçeklendirme ve kaynak yönetimi” raporu verildi. Uygulamalarınızın yüksek düzeyde kullanılabilirliğini sağlamak ve performansı en üst düzeye çıkarmak için K8'leri nasıl kullanabileceğinizi anlatıyor.

Kubernetes'te otomatik ölçeklendirme ve kaynak yönetimi (inceleme ve video raporu)

Geleneğimizi sunmaktan mutluluk duyuyoruz raporun videosu (44 dakika, makaleden çok daha bilgilendirici) ve ana özetin metin biçiminde olması. Gitmek!

Raporun konusunu kelime kelime analiz edip sondan başlayalım.

Kubernetes

Diyelim ki hostumuzda Docker konteynerlerimiz var. Ne için? Tekrarlanabilirliği ve yalıtımı sağlamak için, bu da basit ve iyi bir dağıtıma olanak tanır, CI/CD. Bunun gibi çok sayıda konteynerli araçlarımız var.

Kubernetes bu durumda ne sağlıyor?

  1. Bu makineleri düşünmeyi bırakıp “bulut”la çalışmaya başlıyoruz konteyner kümesi veya bölmeler (kap grupları).
  2. Üstelik tek tek kapsülleri düşünmüyoruz, daha fazlasını yönetiyoruzоdaha büyük gruplar. Çok üst düzey ilkeller Belirli bir iş yükünü çalıştırmak için bir şablon olduğunu ve onu çalıştırmak için gereken örnek sayısını burada belirttiğimizi söylememize izin verin. Daha sonra şablonu değiştirirsek tüm örnekler değişecektir.
  3. Ile bildirimsel API Bir dizi spesifik komutu yürütmek yerine Kubernetes tarafından oluşturulan “dünyanın yapısını” (YAML'de) tanımlıyoruz. Ve tekrar ediyorum: Açıklama değiştiğinde gerçek görünümü de değişecektir.

Büyük resim

işlemci

Sunucuda nginx, php-fpm ve mysql çalıştıralım. Bu hizmetler aslında her biri bilgi işlem kaynakları gerektiren daha fazla işlemi çalıştıracak:

Kubernetes'te otomatik ölçeklendirme ve kaynak yönetimi (inceleme ve video raporu)
(slayttaki sayılar “papağanlardır”, yani her sürecin bilgi işlem gücüne olan soyut ihtiyacı)

Bununla çalışmayı kolaylaştırmak için süreçleri gruplar halinde birleştirmek mantıklıdır (örneğin, tüm nginx işlemleri tek bir "nginx" grubunda). Bunu yapmanın basit ve açık bir yolu, her grubu bir kaba koymaktır:

Kubernetes'te otomatik ölçeklendirme ve kaynak yönetimi (inceleme ve video raporu)

Devam etmek için konteynerin ne olduğunu (Linux'ta) hatırlamanız gerekir. Çekirdekteki uzun zaman önce uygulanan üç temel özellik sayesinde görünümleri mümkün oldu: yetenekleri, ad и Cgroups. Ve diğer teknolojiler (Docker gibi kullanışlı "kabuklar" dahil) daha fazla gelişmeyi kolaylaştırdı:

Kubernetes'te otomatik ölçeklendirme ve kaynak yönetimi (inceleme ve video raporu)

Raporun bağlamında yalnızca ilgilendiğimiz konular Cgroupsçünkü kontrol grupları, kaynak yönetimini uygulayan konteynerlerin (Docker vb.) işlevselliğinin bir parçasıdır. İstediğimiz gibi gruplar halinde birleştirilen süreçler kontrol gruplarıdır.

Bu işlemler ve şimdi de işlem grupları için CPU gereksinimlerine dönelim:

Kubernetes'te otomatik ölçeklendirme ve kaynak yönetimi (inceleme ve video raporu)
(Tüm sayıların kaynak ihtiyacının soyut bir ifadesi olduğunu tekrar ediyorum)

Aynı zamanda CPU'nun kendisi de belirli bir sınırlı kaynağa sahiptir. (örnekte bu 1000'dir)Herkesin eksik olabileceği (tüm grupların ihtiyaçlarının toplamı 150+850+460=1460). Bu durumda ne olacak?

Çekirdek, kaynakları dağıtmaya başlar ve bunu "adil bir şekilde" yaparak her gruba aynı miktarda kaynak verir. Ancak ilk durumda, ihtiyaç duyulandan daha fazlası vardır (333>150), dolayısıyla fazlalık (333-150=183) yedekte kalır ve bu da diğer iki konteyner arasında eşit olarak dağıtılır:

Kubernetes'te otomatik ölçeklendirme ve kaynak yönetimi (inceleme ve video raporu)

Sonuç olarak: İlk konteyner yeterli kaynağa sahipti, ikincisi yeterli kaynağa sahip değildi, üçüncüsü ise yeterli kaynağa sahip değildi. Bu eylemlerin sonucudur Linux'ta "dürüst" zamanlayıcı - CFS. Çalışması atama kullanılarak ayarlanabilir ağırlık konteynerlerin her biri. Örneğin şöyle:

Kubernetes'te otomatik ölçeklendirme ve kaynak yönetimi (inceleme ve video raporu)

İkinci kaptaki (php-fpm) kaynak eksikliği durumuna bakalım. Tüm kapsayıcı kaynakları işlemler arasında eşit olarak dağıtılır. Sonuç olarak, ana süreç iyi işliyor ancak tüm çalışanlar yavaşlıyor ve ihtiyaç duyduklarının yarısından azını alıyorlar:

Kubernetes'te otomatik ölçeklendirme ve kaynak yönetimi (inceleme ve video raporu)

CFS zamanlayıcısı bu şekilde çalışır. Ayrıca konteynerlere atadığımız ağırlıkları da çağıracağız. istekler. Bu neden böyle - daha fazla bakın.

Bütün duruma diğer taraftan bakalım. Bildiğiniz gibi tüm yollar Roma'ya ve bilgisayar söz konusu olduğunda CPU'ya çıkar. Bir CPU, birçok görev; bir trafik ışığına ihtiyacınız var. Kaynakları yönetmenin en basit yolu "trafik ışığı"dır: Bir işleme CPU'ya, ardından diğerine vb. sabit bir erişim süresi verirler.

Kubernetes'te otomatik ölçeklendirme ve kaynak yönetimi (inceleme ve video raporu)

Bu yaklaşıma katı kotalar denir (sert sınırlama). Basitçe hatırlayalım sınırları. Ancak sınırları tüm konteynerlere dağıtırsanız bir sorun ortaya çıkar: MySQL yol boyunca ilerliyordu ve bir noktada CPU ihtiyacı sona erdi, ancak diğer tüm işlemler CPU gelene kadar beklemek zorunda kaldı. Boşta.

Kubernetes'te otomatik ölçeklendirme ve kaynak yönetimi (inceleme ve video raporu)

Linux çekirdeğine ve onun CPU ile etkileşimine dönelim - genel resim aşağıdaki gibidir:

Kubernetes'te otomatik ölçeklendirme ve kaynak yönetimi (inceleme ve video raporu)

cgroup'un iki ayarı vardır - esasen bunlar, şunları belirlemenizi sağlayan iki basit "bükülmedir":

  1. konteynerin ağırlığı (talepler) hisse;
  2. konteyner görevleri (sınırları) üzerinde çalışmak için toplam CPU süresinin yüzdesi kota.

CPU nasıl ölçülür?

Farklı yollar vardır:

  1. Ne papağankimse bilmiyor - her zaman pazarlık yapmanız gerekiyor.
  2. faiz daha net ama göreceli: 50 çekirdekli bir sunucunun ve 4 çekirdekli bir sunucunun %20'si tamamen farklı şeylerdir.
  3. Daha önce bahsedilenleri kullanabilirsiniz ağırlıkLinux bunu biliyor ama aynı zamanda göreceli.
  4. En uygun seçenek bilgi işlem kaynaklarını ölçmektir. saniye. Onlar. gerçek zamanlı saniyelere göre saniye cinsinden işlemci süresi: 1 gerçek saniye başına 1 saniyelik işlemci süresi verildi - bu, bir CPU çekirdeğinin tamamıdır.

Konuşmayı daha da kolaylaştırmak için doğrudan ölçüm yapmaya başladılar. çekirdekler, gerçek zamana göre aynı CPU zamanı anlamına gelir. Linux ağırlıkları anladığı, ancak CPU zamanını/çekirdeklerini çok fazla anlamadığı için, birinden diğerine çeviri yapacak bir mekanizmaya ihtiyaç vardı.

3 CPU çekirdeğine sahip bir sunucuyla basit bir örnek düşünelim; burada üç bölmeye ağırlıklar (500, 1000 ve 1500) verilecek ve bunlar kendilerine tahsis edilen çekirdeklerin karşılık gelen kısımlarına (0,5, 1 ve 1,5) kolayca dönüştürülecek.

Kubernetes'te otomatik ölçeklendirme ve kaynak yönetimi (inceleme ve video raporu)

İki kat daha fazla çekirdeğin (6) olacağı ikinci bir sunucuyu alıp aynı bölmeleri oraya yerleştirirseniz, çekirdeklerin dağılımı basitçe 2 ile çarpılarak (sırasıyla 1, 2 ve 3) kolayca hesaplanabilir. Ancak bu sunucuda, kolaylık sağlamak için ağırlığı 3000 olacak dördüncü bir bölme göründüğünde önemli bir an meydana gelir. CPU kaynaklarının bir kısmını (çekirdeklerin yarısı) alır ve geri kalan bölmeler için yeniden hesaplanır (yarıya bölünür):

Kubernetes'te otomatik ölçeklendirme ve kaynak yönetimi (inceleme ve video raporu)

Kubernetes ve CPU kaynakları

Kubernetes'te CPU kaynakları genellikle şu şekilde ölçülür: miliadraxyani Taban ağırlık olarak 0,001 çekirdek alınmıştır. (Linux/cgroups terminolojisinde aynı şeye CPU paylaşımı denir, ancak daha kesin olarak 1000 miliçekirdek = 1024 CPU paylaşımıdır.) K8s, sunucuya tüm bölmelerin ağırlıklarının toplamına karşılık gelen CPU kaynaklarından daha fazla bölme yerleştirmemesini sağlar.

Bu nasıl oluyor? Bir Kubernetes kümesine sunucu eklediğinizde, sunucunun kaç adet CPU çekirdeğine sahip olduğu bildirilir. Ve yeni bir kapsül oluştururken Kubernetes planlayıcısı bu bölmenin kaç çekirdeğe ihtiyaç duyacağını bilir. Böylece pod, yeterli sayıda çekirdeğin bulunduğu bir sunucuya atanacaktır.

Eğer ne olacak? hayır istek belirtildi mi (yani bölmenin ihtiyaç duyduğu belirli sayıda çekirdeğe sahip değil)? Kubernetes'in kaynakları genel olarak nasıl saydığını bulalım.

Bir bölme için hem istekleri (CFS zamanlayıcı) hem de sınırları (trafik ışıklarını hatırladınız mı?) belirtebilirsiniz:

  • Eşit olarak belirtilirlerse bölmeye bir QoS sınıfı atanır garanti. Bu sayıda çekirdeğin her zaman kullanılabilir olması garanti edilir.
  • İstek limitin altındaysa - QoS sınıfı patlayabilir. Onlar. Örneğin bir pod'un her zaman 1 çekirdek kullanmasını bekleriz ancak bu değer onun için bir sınırlama değildir: bazen pod daha fazlasını kullanabilir (sunucunun bunun için boş kaynakları olduğunda).
  • Ayrıca bir QoS sınıfı da var en iyi çaba — isteğin belirtilmediği bölmeleri içerir. Kaynaklar onlara en son verilir.

Bellek

Bellekte de durum benzer, ancak biraz farklıdır - sonuçta bu kaynakların doğası farklıdır. Genel olarak benzetme şu şekildedir:

Kubernetes'te otomatik ölçeklendirme ve kaynak yönetimi (inceleme ve video raporu)

İsteklerin bellekte nasıl uygulandığını görelim. Bölmelerin sunucuda yaşamasına izin verin, bellek tüketimini değiştirin, ta ki içlerinden biri çok büyüyüp belleği bitene kadar. Bu durumda, OOM katili ortaya çıkıyor ve en büyük süreci sonlandırıyor:

Kubernetes'te otomatik ölçeklendirme ve kaynak yönetimi (inceleme ve video raporu)

Bu her zaman bize yakışmıyor, dolayısıyla hangi süreçlerin bizim için önemli olduğunu ve öldürülmemesi gerektiğini düzenlemek mümkün. Bunu yapmak için parametreyi kullanın oom_score_adj.

CPU'nun QoS sınıflarına dönelim ve pod'lar için bellek tüketimi önceliklerini belirleyen oom_score_adj değerleri ile bir benzetme yapalım:

  • Bir bölme için en düşük oom_score_adj değeri - -998 - böyle bir bölmenin en son öldürülmesi gerektiği anlamına gelir, bu garanti.
  • En yüksek - 1000 - en iyi çaba, bu tür kapsüller ilk önce öldürülür.
  • Kalan değerleri hesaplamak için (patlayabilir) özü, bir bölmenin ne kadar çok kaynak talep etmesi, öldürülme olasılığının o kadar az olduğu gerçeğine dayanan bir formül var.

Kubernetes'te otomatik ölçeklendirme ve kaynak yönetimi (inceleme ve video raporu)

İkinci "bükülme" - limit_in_bytes - sınırlar için. Bununla her şey daha basit: sadece verilen maksimum bellek miktarını atarız ve burada (CPU'nun aksine) bunun nasıl ölçüleceğine (bellek) dair bir soru yoktur.

Toplam

Kubernetes'teki her bölme, requests и limits - CPU ve bellek için her iki parametre:

  1. isteklere göre, bölmeleri sunucular arasında dağıtan Kubernetes zamanlayıcı çalışır;
  2. tüm parametrelere dayalı olarak bölmenin QoS sınıfı belirlenir;
  3. Göreceli ağırlıklar CPU isteklerine göre hesaplanır;
  4. CFS zamanlayıcısı CPU isteklerine göre yapılandırılır;
  5. OOM katili, bellek isteklerine göre yapılandırılır;
  6. CPU sınırlarına göre bir "trafik ışığı" yapılandırılır;
  7. Bellek sınırlarına bağlı olarak grup için bir sınır yapılandırılır.

Kubernetes'te otomatik ölçeklendirme ve kaynak yönetimi (inceleme ve video raporu)

Genel olarak bu resim, Kubernetes'te kaynak yönetiminin ana kısmının nasıl gerçekleştiğine dair tüm soruları yanıtlıyor.

otomatik ölçeklendirme

K8s küme-otomatik ölçekleyici

Kümenin tamamının zaten dolu olduğunu ve yeni bir pod oluşturulması gerektiğini düşünelim. Bölme görüntülenemese de durumu askıda kalıyor Kadar. Görünmesi için kümeye yeni bir sunucu bağlayabiliriz veya... küme otomatik ölçekleyiciyi yükleyebiliriz, bu bizim için yapacaktır: bulut sağlayıcısından bir sanal makine sipariş edin (bir API isteği kullanarak) ve onu kümeye bağlayın , ardından kapsül eklenecektir .

Kubernetes'te otomatik ölçeklendirme ve kaynak yönetimi (inceleme ve video raporu)

Bu, Kubernetes kümesinin otomatik ölçeklendirilmesidir ve harika çalışır (deneyimlerimize göre). Ancak her yerde olduğu gibi burada da bazı nüanslar var...

Cluster boyutunu arttırdığımız sürece her şey yolundaydı fakat Cluster büyüyünce ne olacak? kendini özgürleştirmeye başladı? Sorun, bölmelerin taşınmasının (ana bilgisayarları serbest bırakmak için) teknik olarak çok zor ve kaynaklar açısından pahalı olmasıdır. Kubernetes tamamen farklı bir yaklaşım kullanıyor.

Dağıtımı olan 3 sunucudan oluşan bir küme düşünün. 6 bölmesi var: artık her sunucu için 2 bölme var. Bazı nedenlerden dolayı sunuculardan birini kapatmak istedik. Bunu yapmak için şu komutu kullanacağız: kubectl drain, Hangi:

  • bu sunucuya yeni kapsüllerin gönderilmesini yasaklayacak;
  • sunucudaki mevcut bölmeleri silecektir.

Kubernetes kapsül sayısının (6) korunmasından sorumlu olduğundan, yeniden yaratacak bunları diğer düğümlerde kullanır, ancak devre dışı bırakılan düğümde değil, çünkü zaten yeni bölmeleri barındırmak için kullanılamaz olarak işaretlenmiştir. Bu Kubernetes için temel bir mekanizmadır.

Kubernetes'te otomatik ölçeklendirme ve kaynak yönetimi (inceleme ve video raporu)

Ancak burada da bir nüans var. Benzer bir durumda StatefulSet için (Deployment yerine) eylemler farklı olacaktır. Artık durum bilgisi olan bir uygulamamız var - örneğin MongoDB'li üç bölme, bunlardan birinde bir tür sorun var (veriler bozuldu veya bölmenin doğru şekilde başlatılmasını engelleyen başka bir hata oluştu). Ve yine bir sunucuyu devre dışı bırakmaya karar veriyoruz. Ne olacak?

Kubernetes'te otomatik ölçeklendirme ve kaynak yönetimi (inceleme ve video raporu)

MongoDB could ölür çünkü bir yeter sayıya ihtiyaç duyar: üç kurulumdan oluşan bir küme için en az ikisinin çalışması gerekir. ama, bu Olmuyor - sayesinde PodDisruptionBütçe. Bu parametre gerekli minimum çalışma bölmesi sayısını belirler. MongoDB bölmelerinden birinin artık çalışmadığını bilmek ve PodDisruptionBudget'ın MongoDB için ayarlandığını görmek minAvailable: 2Kubernetes bir kapsülü silmenize izin vermez.

Sonuç olarak: küme serbest bırakıldığında bölmelerin hareketinin (ve aslında yeniden oluşturulmasının) doğru çalışması için PodDisruptionBudget'ı yapılandırmak gerekir.

Yatay ölçeklendirme

Başka bir durumu ele alalım. Kubernetes'te Deployment olarak çalışan bir uygulama var. Kullanıcı trafiği bölmelerine gelir (örneğin, üç tane vardır) ve içlerinde belirli bir göstergeyi ölçeriz (örneğin CPU yükü). Yük arttığında bunu bir programa kaydedip istekleri dağıtmak için pod sayısını artırıyoruz.

Bugün Kubernetes'te bunun manuel olarak yapılmasına gerek yok: ölçülen yük göstergelerinin değerlerine bağlı olarak kapsül sayısında otomatik bir artış/azalış yapılandırılıyor.

Kubernetes'te otomatik ölçeklendirme ve kaynak yönetimi (inceleme ve video raporu)

Buradaki ana sorular şunlardır: tam olarak ne ölçülmeli и nasıl yorumlanır elde edilen değerler (bakla sayısını değiştirmeye karar vermek için). Pek çok şeyi ölçebilirsiniz:

Kubernetes'te otomatik ölçeklendirme ve kaynak yönetimi (inceleme ve video raporu)

Bunun teknik olarak nasıl yapılacağı - ölçümlerin toplanması vb. — Raporda ayrıntılı olarak konuştum İzleme ve Kubernetes. Ve en uygun parametreleri seçmenin ana tavsiyesi deney!

Var KULLANIM yöntemi (Kullanım Doygunluğu ve Hatalar), anlamı aşağıdaki gibidir. Örneğin php-fpm gibi ölçeklendirme hangi temelde mantıklıdır? İşçilerin tükendiği gerçeğine dayanarak, bu kullanım. Ve eğer işçiler bittiyse ve yeni bağlantılar kabul edilmiyorsa bu zaten doyma. Bu parametrelerin her ikisinin de ölçülmesi ve değerlere bağlı olarak ölçeklendirme yapılması gerekmektedir.

Bunun yerine bir sonuca

Raporun devamı var: dikey ölçeklendirme ve doğru kaynakların nasıl seçileceği hakkında. Bundan sonraki videolarda bundan bahsedeceğim YouTube'umuz - abone olun, böylece kaçırmayın!

Videolar ve slaytlar

Gösteriden video (44 dakika):

Raporun sunumu:

PS

Blogumuzdaki Kubernetes ile ilgili diğer raporlar:

Kaynak: habr.com

Yorum ekle