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
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.
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:
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:
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
Ĉ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
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:
Reduktita retoŝarĝo sur la tuta areto.
Malpliigita ujo-komenca tempo.
Pli malgranda grandeco de via tuta Docker-registro.
4. Uzu DNS-kaŝmemoron
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
Ĉ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.
Bildo 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.
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.
Bildo 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
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, Gt aŭ Lt. 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 NoSchedule aŭ NoExecute:
Estas ankaŭ notinde, ke la makulmekanismo subtenas tri ĉefajn efikojn: NoSchedule, NoExecute и PreferNoSchedule.
NoSchedulesignifas 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.
Ĉ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 PriorityClasskaj kampopriskriboj priorityClassNameen 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
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.
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:
Havu bonan aparataron, bazitan sur la grandeco de la areto (vi povas legi tie).
Ŝ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.