Naŭ Konsiletoj pri Regado de Kubernetes

Naŭ Konsiletoj pri Regado de Kubernetes

Saluton al ĉiuj! Mi nomiĝas Oleg Sidorenkov, mi laboras ĉe DomClick kiel infrastruktura teamgvidanto. Ni uzas la Kubon por vendo dum pli ol tri jaroj, kaj dum ĉi tiu tempo ni spertis multajn malsamajn interesajn momentojn kun ĝi. Hodiaŭ mi rakontos al vi kiel, kun la ĝusta aliro, vi povas elpremi eĉ pli da rendimento el vanila Kubernetes por via areto. Preta iras!

Vi ĉiuj scias tre bone, ke Kubernetes estas skalebla malfermkoda sistemo por ujo-instrumentado; nu, aŭ 5 binaroj kiuj faras magion administrante la vivociklon de viaj mikroservoj en servila medio. Krome, ĉi tio estas sufiĉe fleksebla ilo, kiu povas esti kunvenita kiel Lego-konstruanto por maksimuma personigo por malsamaj taskoj.

Kaj ĉio ŝajnas esti bona: ĵetu servilojn en la areton, kiel brullignon en fajrokeston, kaj ne konas funebron. Sed se vi estas por la medio, tiam vi pensos: "Kiel mi povas konservi la fajron en la forno kaj bedaŭri la arbaron?". Alivorte, kiel trovi manierojn plibonigi infrastrukturon kaj redukti kostojn.

1. Konservu la teamajn kaj aplikajn rimedojn

Naŭ Konsiletoj pri Regado de Kubernetes

Unu el la plej banalaj sed efikaj metodoj estas la enkonduko de petoj/limoj. Apartigu aplikojn per nomspacoj, kaj nomspacojn per evoluteamoj. Agordu la aplikaĵon antaŭ ol disfaldi valorojn por la konsumo de procesora tempo, memoro, efemera stokado.

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

Per sperto, ni alvenis al la konkludo: ne indas ŝveligi petojn el limoj pli ol dufoje. La grandeco de areto estas kalkulita surbaze de petoj, kaj se vi agordas la aplikaĵon al diferenco en rimedoj, ekzemple, je 5-10 fojojn, tiam imagu, kio okazos al via nodo kiam ĝi pleniĝos de balgoj kaj subite ricevos ŝarĝon. Nenio bona. Minimume, strekante, kaj maksimume, adiaŭu la laboriston kaj ricevu ciklan ŝarĝon sur la resto de la nodoj post kiam la balgoj komencas moviĝi.

Krome, kun la helpo limitranges vi povas agordi valorojn de rimedoj por la ujo komence - minimuma, maksimuma kaj defaŭlta:

➜  ~ 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

Memoru limigi la nomspacajn rimedojn por ke unu komando ne povu preni ĉiujn rimedojn de la aro:

➜  ~ 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

Kiel vi povas vidi el la priskribo resourcequotas, se la ops-komando volas deploji podojn, kiuj konsumos pliajn 10 cpu-on, tiam la planilo ne permesos ĝin fari kaj eligos eraron:

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

Por solvi similan problemon, vi povas skribi ilon, ekzemple, kiel ĉi tio, kiu povas stoki kaj transigi la staton de komandaj rimedoj.

2. Elektu la plej bonan konservadon de dosieroj

Naŭ Konsiletoj pri Regado de Kubernetes

Ĉi tie mi ŝatus tuŝi la temon de konstantaj volumoj kaj la disksubsistemo de Kubernetes-labornodoj. Mi esperas, ke neniu uzas la "Kubon" sur la HDD en produktado, sed foje eĉ regula SSD jam ne sufiĉas. Ni alfrontis tian problemon, ke la protokoloj mortigis la diskon per I/O-operacioj, kaj ne estas tre multaj solvoj ĉi tie:

  • Uzu alt-efikecajn SSD-ojn aŭ ŝanĝu al NVMe (se vi administras vian propran aparataron).

  • Malpliigu la nivelon de arbohakado.

  • Faru "inteligentan" ekvilibron de balgoj kiuj seksperfortas la diskon (podAntiAffinity).

La supra ekrankopio montras, kio okazas sub nginx-ingress-controller kun disko kiam access_logs estas ebligita (~12k protokoloj/s). Tia stato, kompreneble, povas konduki al la degenero de ĉiuj aplikoj sur ĉi tiu nodo.

Pri PV, ve, mi ne provis ĉion. vidpunktoj Konstantaj volumoj. Uzu la plej bonan eblon, kiu konvenas al vi. Historie okazis en nia lando, ke malgranda parto de servoj bezonas RWX-volumojn, kaj antaŭ longa tempo ili komencis uzi NFS-stokadon por ĉi tiu tasko. Malmultekosta kaj ... sufiĉe. Kompreneble, ni manĝis fekon kun li - estu sana, sed ni lernis kiel agordi lin, kaj lia kapo ne plu doloras. Kaj se eble, ŝanĝu al S3-objekta stokado.

3. Konstruu Optimumigitajn Bildojn

Naŭ Konsiletoj pri Regado de Kubernetes

Plej bone estas uzi ujo-optimumigitajn bildojn por ke Kubernetes povu preni ilin pli rapide kaj plenumi ilin pli efike. 

Optimumigo signifas, ke bildoj:

  • enhavi nur unu aplikaĵon aŭ plenumi nur unu funkcion;

  • malgranda grandeco, ĉar grandaj bildoj estas pli malbone transdonitaj tra la reto;

  • havi sanajn kaj pretajn finpunktojn, kiujn Kubernetes povas uzi por ekagi en okazo de malfunkcio;

  • uzu ujo-amikajn operaciumojn (kiel Alpine aŭ CoreOS), kiuj estas pli rezistemaj al agordaj eraroj;

  • uzu plurŝtupajn konstruojn por ke vi nur povu disfaldi kompilitajn aplikaĵojn kaj ne la akompanajn fontojn.

Estas multaj iloj kaj servoj kiuj permesas vin kontroli kaj optimumigi bildojn sur la flugo. Gravas ĉiam teni ilin ĝisdatigitaj kaj sekuraj. Kiel rezulto, vi ricevas:

  1. Reduktita retoŝarĝo sur la tuta areto.

  2. Malpliigita ujo-komenca tempo.

  3. Pli malgranda grandeco de via tuta Docker-registro.

4. Uzu DNS-kaŝmemoron

Naŭ Konsiletoj pri Regado de Kubernetes

Se ni parolas pri altaj ŝarĝoj, tiam sen agordi la DNS-sistemon de la grapolo, la vivo estas sufiĉe malbona. Iam, la programistoj de Kubernetes subtenis sian solvon kube-dns. Ĝi ankaŭ estis efektivigita en nia lando, sed ĉi tiu programaro ne aparte agordis kaj ne donis la bezonatan agadon, kvankam, ŝajnas, la tasko estas simpla. Tiam aperis koredns, al kiuj ni ŝanĝis kaj ne konis malĝojon, poste ĝi fariĝis la defaŭlta DNS-servo en K8s. En iu momento, ni kreskis ĝis 40 mil rps al la DNS-sistemo, kaj ĉi tiu solvo ankaŭ ne sufiĉis. Sed, per bonŝanca ŝanco, aperis Nodelocaldns, alinome node loka kaŝmemoro, alinome NodeLocal DNSCache.

Kial ni uzas ĝin? Estas cimo en la Linukso-kerno, kiu, kiam multoblaj aliroj tra conntrack NAT super UDP, kondukas al raskondiĉo por skribi al la conntrack-tabeloj, kaj parto de la trafiko tra NAT estas perdita (ĉiu vojaĝo tra la Servo estas NAT). Nodelocaldns solvas ĉi tiun problemon per forigo de NAT kaj ĝisdatigo al TCP-konekteco al kontraŭflua DNS, kaj ankaŭ konservante kontraŭfluajn DNS-demandojn loke (inkluzive de mallonga 5 sekunda negativa kaŝmemoro).

5. Skali podojn horizontale kaj vertikale aŭtomate

Naŭ Konsiletoj pri Regado de Kubernetes

Ĉu vi povas diri kun konfido, ke ĉiuj viaj mikroservoj estas pretaj por du-ĝis-triobla pliiĝo de ŝarĝo? Kiel ĝuste asigni rimedojn al viaj aplikoj? Teni kelkajn podojn kurantajn pli ol la laborkvanton povas esti superflua, kaj konservi ilin reen kontraŭ dorso riskas malfunkcion de subita pliiĝo de trafiko al la servo. La ora meznombro helpas atingi la sorĉon de multipliko tiaj servoj kiel Horizontala Pod Autoscaler и Vertikala Pod Autoscaler.

VPA permesas vin aŭtomate altigi la petojn/limojn de viaj ujoj en pod bazita sur reala uzado. Kiel ĝi povas esti utila? Se vi havas Pods kiuj ial ne povas esti malgrandigitaj horizontale (kio ne estas tute fidinda), tiam vi povas provi fidi VPA por ŝanĝi ĝiajn rimedojn. Ĝia funkcio estas rekomenda sistemo bazita sur historiaj kaj aktualaj datumoj de metriko-servilo, do se vi ne volas aŭtomate ŝanĝi petojn/limojn, vi povas simple monitori la rekomenditajn rimedojn por viaj ujoj kaj optimumigi la agordojn por ŝpari CPU kaj memoron. en la areto.

Naŭ Konsiletoj pri Regado de KubernetesBildo prenita de https://levelup.gitconnected.com/kubernetes-autoscaling-101-cluster-autoscaler-horizontal-pod-autoscaler-and-vertical-pod-2a441d9ad231

La planilo en Kubernetes ĉiam baziĝas sur petoj. Kian ajn valoron vi metas tien, la planisto serĉos taŭgan nodon bazitan sur ĝi. La limvaloro estas bezonata de la kubleto por scii kiam stroli aŭ mortigi balgon. Kaj ĉar la sola grava parametro estas la valoro de petoj, VPA funkcios kun ĝi. Kiam ajn vi skalas vian aplikaĵon vertikale, vi difinas kiajn petojn devus esti. Kaj kio do okazos al limoj? Ĉi tiu parametro ankaŭ estos proporcie skalita.

Ekzemple, jen la tipaj pod-agordoj:

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

La rekomendmotoro determinas, ke via aplikaĵo bezonas 300m CPU kaj 500Mi por funkcii ĝuste. Vi ricevos ĉi tiujn agordojn:

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

Kiel menciite supre, ĉi tio estas proporcia skalo bazita sur la petoj/limoj-proporcio en la manifesto:

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

  • Memoro: 250Mi → 500Mi: 1:2 rilatumo.

Koncerne al HPA, tiam la mekanismo de operacio estas pli travidebla. Sojloj estas fiksitaj por metrikoj kiel procesoro kaj memoro, kaj se la mezumo de ĉiuj kopioj superas la sojlon, tiam la aplikaĵo skalas je +1 pod ĝis la valoro falas sub la sojlo, aŭ ĝis la maksimuma nombro da kopioj estas atingita.

Naŭ Konsiletoj pri Regado de KubernetesBildo prenita de https://levelup.gitconnected.com/kubernetes-autoscaling-101-cluster-autoscaler-horizontal-pod-autoscaler-and-vertical-pod-2a441d9ad231

Krom la kutimaj metrikoj kiel CPU kaj Memoro, vi povas agordi sojlojn sur viaj kutimaj Prometheus-metrikoj kaj labori kun ili se vi opinias, ke ĉi tio estas la plej preciza maniero determini kiam grimpi vian aplikaĵon. Post kiam la aplikaĵo stabiliĝos sub la specifita metrika sojlo, HPA komencos malpliigi la Podojn al la minimuma nombro da kopioj aŭ ĝis la ŝarĝo renkontos la sojlon.

6. Ne Forgesu Pri Noda Afineco kaj Pod Afineco

Naŭ Konsiletoj pri Regado de Kubernetes

Ne ĉiuj nodoj funkcias per la sama aparataro, kaj ne ĉiuj podoj bezonas ruli komputigajn aplikojn. Kubernetes permesas vin specifi la specialiĝon de nodoj kaj podoj uzante Noda Afineco и Pod Afineco.

Se vi havas nodojn taŭgajn por komputilaj intensaj operacioj, tiam por maksimuma efikeco, estas pli bone ligi aplikojn al la taŭgaj nodoj. Por fari tion, uzu nodeSelector kun noda etikedo.

Ni diru, ke vi havas du nodojn: unu kun CPUType=HIGHFREQ kaj granda nombro da rapidaj kernoj, alia kun MemoryType=HIGHMEMORY pli da memoro kaj pli rapida rendimento. La plej facila maniero estas asigni pod-deplojon al nodo HIGHFREQaldonante al la sekcio spec elektilo kiel ĉi tiu:

…
nodeSelector:
	CPUType: HIGHFREQ

Pli multekosta kaj specifa maniero fari tion estas uzi nodeAffinity en kampo affinity sekcio spec. Estas du opcioj:

  • requiredDuringSchedulingIgnoredDuringExecution: malmola agordo (planilo nur disfaldigos podojn sur specifaj nodoj (kaj nenie aliloke));

  • preferredDuringSchedulingIgnoredDuringExecution: mola agordo (la planisto provos deploji al specifaj nodoj, kaj se ĝi malsukcesas, ĝi provos deploji al la sekva disponebla nodo).

Vi povas specifi specifan sintakson por administri nodajn etikedojn, ekzemple, In, NotIn, Exists, DoesNotExist, GtLt. Tamen memoru, ke kompleksaj metodoj en longaj listoj de etikedoj malrapidigos decidon en kritikaj situacioj. Alivorte, ne tro kompliku.

Kiel menciite supre, Kubernetes permesas vin agordi la ligadon de nunaj podoj. Tio estas, vi povas igi certajn podojn funkcii kune kun aliaj podoj en la sama havebleczono (rilata por nuboj) aŭ nodoj.

В podAffinity kampoj affinity sekcio spec la samaj kampoj disponeblas kiel en la kazo de nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution и preferredDuringSchedulingIgnoredDuringExecution. La sola diferenco estas tio matchExpressions ligos podojn al nodo, kiu jam funkcias pod kun tiu etikedo.

Pli da Kubernetes ofertas kampon podAntiAffinity, kiu, kontraste, ne ligas balgon al nodo kun specifaj balgoj.

Pri esprimoj nodeAffinity la saman konsilon oni povas doni: provu konservi la regulojn simplaj kaj logikaj, ne provu troŝarĝi la podspecifon per kompleksa aro de reguloj. Estas tre facile krei regulon, kiu ne kongruas kun la kondiĉoj de la areto, metante kroman ŝarĝon sur la planilon kaj malbonigante ĝeneralan rendimenton.

7. Makuloj & Toleroj

Estas alia maniero administri la planilon. Se vi havas grandan areton kun centoj da nodoj kaj miloj da mikroservoj, estas tre malfacile malhelpi, ke iuj podoj estu gastigitaj de certaj nodoj.

La mekanismo de makuloj - malpermesantaj reguloj - helpas pri tio. Ekzemple, vi povas malhelpi certajn nodojn ruli podojn en certaj scenaroj. Por apliki makulon al specifa nodo, uzu la opcion taint en kubectl. Specifu ŝlosilon kaj valoron kaj poste makulu kiel NoScheduleNoExecute:

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

Estas ankaŭ notinde, ke la makulmekanismo subtenas tri ĉefajn efikojn: NoSchedule, NoExecute и PreferNoSchedule.

  • NoSchedule signifas ke ĝis estas responda eniro en la podspecifo tolerations, ĝi ne povas esti deplojita al la nodo (en ĉi tiu ekzemplo node10).

  • PreferNoSchedule - simpligita versio NoSchedule. En ĉi tiu kazo, la planisto provos ne asigni podojn kiuj ne havas kongruan eniron. tolerations po nodo, sed ĉi tio ne estas malfacila limo. Se ne estas rimedoj en la areto, tiam la podoj komencos disfaldi sur ĉi tiu nodo.

  • NoExecute - ĉi tiu efiko ekigas tujan evakuadon de balgoj kiuj ne havas kongruan eniron tolerations.

Kurioze, ĉi tiu konduto povas esti malfarita per la mekanismo de toleroj. Ĉi tio estas oportuna kiam estas "malpermesita" nodo kaj vi devas meti nur infrastrukturajn servojn sur ĝin. Kiel fari ĝin? Permesu nur tiujn gusojn por kiuj estas taŭga toleremo.

Jen kiel aspektus la podspeco:

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

Ĉi tio ne signifas, ke dum la sekva redeplojo, la pod trafos ĝuste ĉi tiun nodon, ĉi tio ne estas la mekanismo de Node Affinity kaj nodeSelector. Sed kombinante plurajn funkciojn, vi povas atingi tre flekseblan agordon de planilo.

8. Agordu Pod Deployment Priority

Nur ĉar vi agordis pod-al-nodajn ligojn ne signifas, ke ĉiuj podoj estu traktataj kun la sama prioritato. Ekzemple, vi eble volas disfaldi kelkajn Pods antaŭ aliaj.

Kubernetes ofertas malsamajn manierojn agordi Pod Priority kaj Preemption. La agordo konsistas el pluraj partoj: objekto PriorityClass kaj kampopriskriboj priorityClassName en la podspecifo. Konsideru ekzemplon:

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"

Ni kreas PriorityClass, donu al ĝi nomon, priskribon kaj valoron. Ju pli alta value, des pli alta la prioritato. La valoro povas esti ajna 32-bita entjero malpli ol aŭ egala al 1 000 000 000. Pli altaj valoroj estas rezervitaj por misi-kritikaj sistemaj balgoj, kiuj kutime ne povas esti antaŭitaj. La eldomigo okazos nur se la altprioritata balgo havas nenien por turniĝi, tiam kelkaj el la balgoj de aparta nodo estos evakuitaj. Se ĉi tiu mekanismo estas tro rigida por vi, tiam vi povas aldoni la opcion preemptionPolicy: Never, kaj tiam ne estos antaŭzorgo, la pod estos la unua en la atendovico kaj atendos ke la planisto trovos senpagajn rimedojn por ĝi.

Poste, ni kreas pod, en kiu ni specifas la nomon 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
          

Vi povas krei tiom da prioritataj klasoj kiom vi volas, kvankam oni rekomendas ne forlogi ĉi tion (diru, limigu vin al malalta, meza kaj alta prioritato).

Tiel, se necese, vi povas pliigi la efikecon de deplojado de kritikaj servoj, kiel ekzemple nginx-ingress-controller, coredns, ktp.

9. Optimumigu vian ETCD-grupon

Naŭ Konsiletoj pri Regado de Kubernetes

ETCD povas esti nomita la cerbo de la tuta areto. Estas tre grave konservi la funkciadon de ĉi tiu datumbazo je alta nivelo, ĉar la rapideco de operacioj en la "Kubo" dependas de ĝi. Sufiĉe norma, kaj samtempe, bona solvo estus konservi ETCD-areton sur la majstraj nodoj por havi minimuman prokraston al kube-apiserver. Se tio ne eblas, tiam metu la ETCD kiel eble plej proksime, kun bona bendolarĝo inter partoprenantoj. Ankaŭ atentu kiom da nodoj de ETCD povas elfali sen damaĝo al la areto.

Naŭ Konsiletoj pri Regado de Kubernetes

Memoru, ke troa kresko de la nombro da partoprenantoj en la areto povas pliigi misfunkciadon koste de agado, ĉio estu modere.

Se ni parolas pri agordo de la servo, tiam estas malmultaj rekomendoj:

  1. Havu bonan aparataron, bazitan sur la grandeco de la areto (vi povas legi tie).

  2. Ŝanĝu kelkajn parametrojn se vi disvastigis areton inter paro da DC-oj aŭ via reto kaj diskoj lasas multon por deziri (vi povas legi tie).

konkludo

Ĉi tiu artikolo priskribas la punktojn, kiujn nia teamo provas plenumi. Ĉi tio ne estas paŝo-post-paŝa priskribo de agoj, sed opcioj, kiuj povas esti utilaj por optimumigi la supraĵon de areto. Estas klare, ke ĉiu areto estas unika en sia propra maniero, kaj agordaj solvoj povas multe varii, do estus interese ricevi komentojn de vi: kiel vi kontrolas vian Kubernetes-grupon, kiel vi plibonigas ĝian rendimenton. Kunhavigu vian sperton en la komentoj, estos interese scii ĝin.

fonto: www.habr.com