Kubernetes има неколку опции за ажурирање на ресурсите: примени, уреди, закрпи и замени. Постои конфузија околу тоа што прави секој од нив и кога да ги користи. Ајде да го сфатиме.
Ако kubectl patch
, што не вклучува споредба apply
и patch
. Оваа статија ќе ги разгледа различните опции, како и правилната употреба на секоја од нив.
За време на животниот циклус на ресурсот на Kubernetes (услуга, распоредување, влез итн.), понекогаш треба да промените, додадете или отстраните некои својства на овој ресурс. На пример, додадете белешка, зголемете или намалете го бројот на реплики.
Kubernetes CLI
Ако веќе работите со кластерите на Kubernetes преку CLI, веќе сте запознаени apply
и edit
. Тим apply
ја чита спецификацијата на ресурсите од датотеката и прави „upsert“ во кластерот Kubernetes, т.е. го создава ресурсот доколку не постои и го ажурира доколку постои. Тим edit
чита ресурс преку API, а потоа ја запишува спецификацијата на ресурсите во локална датотека, која потоа се отвора во текстуален уредувач. Откако ќе ја уредите и зачувате датотеката, kubectl
ќе ги испрати промените направени назад преку API, кој внимателно ќе ги примени овие промени на ресурсот.
Не сите ги знаат командите patch
и replace
. Тим patch
ви овозможува да промените дел од спецификацијата на ресурсите, обезбедувајќи го само променетиот дел на командната линија. Тим replace
работи исто како edit
, но сè треба да се направи рачно: треба да ја преземете тековната верзија на спецификацијата на ресурсите, на пример, користејќи kubectl get -o yaml
, уредете го, па употребете replace
за ажурирање на ресурс според изменета спецификација. Тим replace
нема да работи ако се случат какви било промени помеѓу читањето и заменувањето на ресурсот.
Kubernetes API
Веројатно сте запознаени со методите CoreV1().Pods().Update()
, replaceNamespacedService
или patch_namespaced_deployment
, ако работите со кластери преку PUT
и PATCH
... При што update
и replace
употреба PUT
И patch
, колку и да е тривијално, користи PATCH
.
Треба да се напомене дека kubectl
работи и со кластери преку API. Со други зборови, kubectl
е обвивка на врвот на библиотеката на клиентите за јазикот Go, кој во голема мера обезбедува можност за обезбедување на подкоманди во покомпактна и почитлива форма покрај стандардните API способности. На пример, како што веќе сте забележале, методот apply
не беше споменато погоре во претходниот став. Во моментов (мај 2020 г., прибл. преведувач) целата логика kubectl apply
, т.е. создавање непостоечки ресурси и ажурирање на постојните, работи целосно на страната на кодот kubectl
. Се прават напори apply
на страната на API, но сè уште е во бета верзија. Подолу ќе напишам подетално.
Закрпи стандардно
Најдобро се користи patch
, ако сакате да го ажурирате ресурсот. Вака работат двете библиотеки на клиенти на врвот на Kubernetes API и kubectl
(не е изненадувачки, бидејќи тоа е обвивка за библиотеката на клиентите, прибл. преведувач).
Работете стратешки
Сите тимови kubectl
apply
, edit
и patch
користете го методот PATCH
во HTTP бара ажурирање на постоечки ресурс. Ако истражувате подетално во спроведувањето на командите, тогаш сите го користат пристапот patch
може да користи други пристапи (повеќе за ова подолу). Пристапот за поправање на стратегиско спојување се обидува да го „добие правилно“ со спојување на испорачаната спецификација со постоечката спецификација. Поконкретно, се обидува да ги комбинира и објектите и низите, што значи дека промените имаат тенденција да бидат адитивни. На пример, извршување на командата patch
со нова променлива на животната средина во спецификацијата на контејнерот на pod, предизвикува таа променлива на животната средина да се додаде на постојните променливи на животната средина наместо да ги презапише. За да го отстраните користејќи го овој пристап, мора да ја присилите вредноста на параметарот да биде нула во дадената спецификација. Кој од тимовите kubectl
Дали е најдобро да се користи за ажурирање?
Ако креирате и управувате со вашите ресурси користејќи kubectl apply
, при ажурирање е подобро секогаш да се користи kubectl apply
така што kubectl
може да управува со конфигурацијата и правилно да ги следи бараните промени од апликација до апликација. Предност секогаш користете apply
е тоа што ја следи претходно применетата спецификација, овозможувајќи му да знае кога својствата на спецификацијата и елементите на низата се експлицитно отстранети. Ова ви овозможува да користите apply
да се отстранат својствата и елементите на низата, додека нормалното стратегиско спојување нема да работи. Тимови edit
и patch
не ажурирајте белешки дека kubectl apply
користи за следење на неговите промени, така што сите промени што се следат и направени преку Kubernetes API, но направени преку команди edit
и patch
, невидлив за следните команди apply
Што е, apply
не ги отстранува дури и ако не се појавуваат во влезната спецификација за apply
(Документацијата го кажува тоа edit
и patch
направете ажурирања на користените белешки apply
, но во пракса - не).
Ако не ја користите командата apply
, може да се користи како edit
И patch
, избирајќи ја командата што најмногу одговара на промената што се прави. При додавање и менување на својствата на BOM, двата пристапи се приближно исти. При бришење на својствата на спецификацијата или елементите на низата edit
се однесува како еднократно лансирање apply
, вклучувајќи следење на тоа каква била спецификацијата пред и по нејзиното уредување, за да можете експлицитно да ги отстраните својствата и елементите на низата од ресурсот. Треба експлицитно да ја поставите вредноста на имотот како нула во спецификацијата за patch
да го отстраните од ресурсот. Отстранувањето на елемент од низа со користење на стратешко-спојување е покомплексно бидејќи бара употреба на директиви за спојување. Погледнете ги другите пристапи за надградба подолу за поодржливи алтернативи.
Да се имплементираат методи за ажурирање во библиотеката на клиентите кои се однесуваат слично на командите погоре kubectl
, треба да се постави во барањата content-type
в application/strategic-merge-patch+json
. Ако сакате да ги отстраните својствата во спецификација, треба експлицитно да ги поставите нивните вредности како нула на сличен начин kubectl patch
. Ако треба да ги отстраните елементите на низата, треба да вклучите директиви за спојување во спецификацијата за ажурирање или да користите различен пристап кон ажурирањата.
Други пристапи за ажурирања
Kubernetes поддржува два други пристапи за ажурирање: kubectl patch --type=merge
. Кога работите со Kubernetes API, треба да го користите методот на барање PATCH
и инсталација content-type
в application/merge-patch+json
.
Пристапот за закрпи JSON, наместо да обезбедува делумна спецификација на ресурсот, користи обезбедување на промените што сакате да ги направите на ресурсот како низа, во која секој елемент од низата претставува опис на промената што се прави на ресурсот. Овој пристап е пофлексибилен и помоќен начин за изразување на промените што се прават, но по цена да се наведат промените направени во посебен, не-Kubernetes формат, наместо да се испраќа делумна спецификација на ресурсите. ВО kubectl
можете да изберете JSON лепенка користејќи kubectl patch --type=json
. Кога се користи Kubernetes API, овој пристап работи со методот на барање PATCH
и инсталација content-type
в application/json-patch+json
.
Потребна ни е доверба - користете заменете
Во некои случаи, треба да бидете сигурни дека не се прават промени на некој ресурс помеѓу времето кога ресурсот се чита и кога се ажурира. Со други зборови, треба да бидете сигурни дека сите промени ќе бидат атомски. Во овој случај, за ажурирање на ресурсите што треба да ги користите replace
. На пример, ако имате ConfigMap со бројач што се ажурира од повеќе извори, треба да бидете сигурни дека два извора не го ажурираат бројачот истовремено, што предизвикува ажурирањето да се изгуби. За да покажете, замислете секвенца на настани користејќи го пристапот patch
:
- А и Б ја добиваат моменталната состојба на ресурсот од API
- Секој од нив локално ја ажурира спецификацијата со зголемување на бројачот за еден и исто така додавање на „A“ или „B“, соодветно на белешката „updated-by“
- И малку побрзо го ажурира ресурсот
- Б го ажурира ресурсот
Како резултат на тоа, ажурирањето А е изгубено. Последна операција patch
победи, бројачот се зголемува за еден наместо за два, а вредноста на белешката „updated-by“ завршува со „B“ и не содржи „A“. Ајде да го споредиме горенаведеното со она што се случува кога ажурирањата се вршат со користење на пристапот replace
:
- А и Б ја добиваат моменталната состојба на ресурсот од API
- Секој од нив локално ја ажурира спецификацијата со зголемување на бројачот за еден и исто така додавање на „A“ или „B“, соодветно на белешката „updated-by“
- И малку побрзо го ажурира ресурсот
- Б се обидува да го ажурира ресурсот, но ажурирањето е одбиено од API бидејќи верзијата на ресурсите е во спецификацијата
replace
не се совпаѓа со тековната верзија на ресурсот во Кубернетес бидејќи верзијата на ресурсот беше зголемена со операцијата за замена на А.
Во горенаведениот случај, B ќе мора повторно да го преземе ресурсот, да направи промени во новата состојба и да се обиде повторно replace
. Ова ќе предизвика бројачот да се зголеми за два и белешката „updated-by“ да го вклучи „AB“ на крајот.
Горенаведениот пример имплицира дека при извршувањето replace
Целиот ресурс е целосно заменет. Спецификација што се користи за replace
, не смее да биде делумно, или во делови како во apply
, но комплетен, вклучувајќи го и додатокот resourceVersion
во метаподатоците на спецификацијата. Ако не сте овозможиле resourceVersion
или верзијата што ја давате не е актуелна, замената ќе биде одбиена. Така, најдобриот пристап за употреба е replace
– прочитајте го ресурсот, ажурирајте го и заменете го веднаш. Користење на kubectl
, може да изгледа вака:
$ kubectl get deployment my-deployment -o json
| jq '.spec.template.spec.containers[0].env[1].value = "new value"'
| kubectl replace -f -
Вреди да се напомене дека следните две команди, извршени последователно, ќе се извршат успешно, бидејќи deployment.yaml
не содржи имот .metadata.resourceVersion
$ kubectl create -f deployment.yaml
$ kubectl replace -f deployment.yaml
Се чини дека ова е во спротивност со она што беше кажано погоре, т.е. “, додавајќи resourceVersion
во метаподатоците за спецификацијата." Дали е погрешно да се каже тоа? Не, не е, затоа што ако kubectl
известувања што не сте ги навеле resourceVersion
, ќе го прочита од ресурсот и ќе го додаде во спецификацијата што ја наведовте и дури потоа ќе ја изврши replace
. Бидејќи ова е потенцијално опасно ако се потпрете на атомичноста, магијата работи целосно на страна kubectl
, не треба да се потпирате на него кога користите библиотеки на клиенти кои работат со API. Во овој случај, ќе треба да ја прочитате тековната спецификација на ресурсите, да ја ажурирате и потоа да ја извршите PUT
барање.
Не можете да направите лепенка - правиме замена
Понекогаш треба да направите некои промени со кои API не може да се справи. Во овие случаи, можете да присилите замена на ресурсот со бришење и повторно создавање. Ова се прави со користење kubectl replace --force
. Извршувањето на командата веднаш ги отстранува ресурсите и потоа ги пресоздава од испорачаната спецификација. Во API нема управувач за „force replace“, а за да го направите тоа преку API, треба да извршите две операции. Прво треба да го избришете ресурсот со поставување за него gracePeriodSeconds
до нула (0) и propagationPolicy
во „Позадина“ и потоа повторно креирајте го овој ресурс со саканата спецификација.
Предупредување: Овој пристап е потенцијално опасен и може да доведе до недефинирана состојба.
Примени на страната на серверот
Како што споменавме погоре, развивачите на Kubernetes работат на спроведување на логиката apply
на kubectl
во Kubernetes API. Логики apply
достапно во Kubernetes 1.18 преку kubectl apply --server-side
или преку API користејќи го методот PATCH
с content-type
application/apply-patch+YAML
.
Забелешка: JSON е исто така валиден YAML, така што можете да ја испратите спецификацијата како JSON дури и ако
content-type
ќеapplication/apply-patch+yaml
.
Покрај таа логика kubectl
станува достапен за секого преку API, apply
на страната на серверот, следи кој е одговорен за полињата во спецификацијата, со што овозможува безбеден повеќекратен пристап за негово уредување без конфликти. Со други зборови, ако apply
на страната на серверот ќе стане пошироко распространет, ќе се појави универзален безбеден интерфејс за управување со ресурси за различни клиенти, на пример, kubectl, Pulumi или Terraform, GitOps, како и самонапишани скрипти кои користат библиотеки на клиенти.
Резултатите од
Се надевам дека овој краток преглед на различни начини за ажурирање на ресурсите во кластерите беше корисен за вас. Добро е да се знае дека не е само примена наспроти замена, можно е да се ажурира ресурс со примена, уредување, закрпи или замена. На крајот на краиштата, во принцип, секој пристап има своја област на примена. За атомски промени, се претпочита замена, во спротивно, треба да користите закрпа за стратегиско спојување преку апликација; Во најмала рака, очекувам да разберете дека не можете да му верувате на Google или StackOerflow кога пребарувате за „kubernetes применуваат против замени“. Барем додека овој напис не го замени сегашниот одговор.
Извор: www.habr.com