Премахване на остарял клон на функция в клъстер на Kubernetes

Премахване на остарял клон на функция в клъстер на Kubernetes

Привет! Функционален клон (известен още като deploy preview, review app) - това е, когато не само главният клон е разгърнат, но и всяка заявка за изтегляне към уникален URL адрес. Можете да проверите дали кодът работи в производствена среда; функцията може да бъде показана на други програмисти или продуктови специалисти. Докато работите в заявка за изтегляне, всяко ново прилагане на текущото разгръщане за стария код се изтрива и новото разгръщане за новия код се разгръща. Може да възникнат въпроси, когато обедините заявка за изтегляне в главния клон. Вече не се нуждаете от клона на функциите, но ресурсите на Kubernetes все още са в клъстера.

Повече за разклоненията на функциите

Един подход за създаване на разклонения на функции в Kubernetes е използването на пространства от имена. Накратко производствената конфигурация изглежда така:

kind: Namespace
apiVersion: v1
metadata:
  name: habr-back-end
...

kind: Deployment
apiVersion: apps/v1
metadata:
  namespace: habr-back-end
spec:
  replicas: 3
...

За клон на функция се създава пространство от имена с неговия идентификатор (например номер на заявка за изтегляне) и някакъв вид префикс/постфикс (например, -пр-):

kind: Namespace
apiVersion: v1
metadata:
  name: habr-back-end-pr-17
...

kind: Deployment
apiVersion: apps/v1
metadata:
  namespace: habr-back-end-pr-17
spec:
  replicas: 1
...

Общо взето писах Оператор Kubernetes (приложение, което има достъп до ресурсите на клъстера), връзка към проекта в Github. Той премахва пространства от имена, които принадлежат към стари разклонения на функции. В Kubernetes, ако изтриете пространство от имена, другите ресурси в това пространство от имена също се изтриват автоматично.

$ kubectl get pods --all-namespaces | grep -e "-pr-"
NAMESPACE            ... AGE
habr-back-end-pr-264 ... 4d8h
habr-back-end-pr-265 ... 5d7h

Можете да прочетете как да внедрите разклонения на функции в клъстер тук и тук.

Мотивиране

Нека да разгледаме типичен жизнен цикъл на заявка за изтегляне с непрекъсната интеграция (continuous integration):

  1. Изпращаме нов ангажимент към клона.
  2. При изграждането се изпълняват линтери и/или тестове.
  3. Конфигурациите на Kubernetes pull request се генерират в движение (например номерът му се вмъква в готовия шаблон).
  4. Използвайки kubectl apply, конфигурациите се добавят към клъстера (разгръщане).
  5. Заявката за изтегляне се обединява в главния клон.

Докато работите в заявка за изтегляне, всяко ново прилагане на текущото разгръщане за стария код се изтрива и новото разгръщане за новия код се разгръща. Но когато заявка за изтегляне се слее в главния клон, ще бъде изграден само главният клон. В резултат на това се оказва, че вече сме забравили за заявката за изтегляне и неговите ресурси на Kubernetes все още са в клъстера.

Как да използвате

Инсталирайте проекта с командата по-долу:

$ kubectl apply -f https://raw.githubusercontent.com/dmytrostriletskyi/stale-feature-branch-operator/master/configs/production.yml

Създайте файл със следното съдържание и го инсталирайте чрез kubectl apply -f:

apiVersion: feature-branch.dmytrostriletskyi.com/v1
kind: StaleFeatureBranch
metadata:
  name: stale-feature-branch
spec:
  namespaceSubstring: -pr-
  afterDaysWithoutDeploy: 3

Параметър namespaceSubstring необходими за филтриране на пространства от имена за заявки за изтегляне от други пространства от имена. Например, ако клъстерът има следните пространства от имена: habr-back-end, habr-front-end, habr-back-end-pr-17, habr-back-end-pr-33, тогава ще има кандидати за изтриване habr-back-end-pr-17, habr-back-end-pr-33.

Параметър afterDaysWithoutDeploy необходими за изтриване на стари пространства от имена. Например, ако е създадено пространство от имена 3 дня 1 час назад, а параметърът показва 3 дня, това пространство от имена ще бъде изтрито. Работи и в обратна посока, ако пространството от имена е създадено 2 дня 23 часа назад, а параметърът показва 3 дня, това пространство от имена няма да бъде изтрито.

Има още един параметър, той отговаря за това колко често да се сканират всички пространства от имена и да се проверяват дни без внедряване - checkEveryMinutes. По подразбиране е равно 30 минутам.

Как работи

На практика ще ви трябва:

  1. докер за работа в изолирана среда.
  2. Миникубе ще създаде локален клъстер на Kubernetes.
  3. kubectl — интерфейс на командния ред за управление на клъстери.

Създаваме клъстер на Kubernetes локално:

$ minikube start --vm-driver=docker
minikube v1.11.0 on Darwin 10.15.5
Using the docker driver based on existing profile.
Starting control plane node minikube in cluster minikube.

Посочваме kubectl използвайте локален клъстер по подразбиране:

$ kubectl config use-context minikube
Switched to context "minikube".

Изтеглете конфигурации за производствената среда:

$ curl https://raw.githubusercontent.com/dmytrostriletskyi/stale-feature-branch-operator/master/configs/production.yml > stale-feature-branch-production-configs.yml

Тъй като производствените конфигурации са конфигурирани да проверяват стари пространства от имена и нашият новоповдигнат клъстер ги няма, ние ще заменим променливата на средата IS_DEBUG на true. С тази стойност параметърът afterDaysWithoutDeploy не се взема предвид и пространствата от имена не се проверяват за дни без внедряване, а само за появата на подниза (-pr-).

Ако сте на Linux:

$ sed -i 's|false|true|g' stale-feature-branch-production-configs.yml

Ако сте на macOS:

$ sed -i "" 's|false|true|g' stale-feature-branch-production-configs.yml

Инсталиране на проекта:

$ kubectl apply -f stale-feature-branch-production-configs.yml

Проверка дали в клъстера се е появил ресурс StaleFeatureBranch:

$ kubectl api-resources | grep stalefeaturebranches
NAME                 ... APIGROUP                             ... KIND
stalefeaturebranches ... feature-branch.dmytrostriletskyi.com ... StaleFeatureBranch

Проверяваме дали в клъстера се е появил оператор:

$ kubectl get pods --namespace stale-feature-branch-operator
NAME                                           ... STATUS  ... AGE
stale-feature-branch-operator-6bfbfd4df8-m7sch ... Running ... 38s

Ако погледнете неговите регистрационни файлове, той е готов да обработва ресурси StaleFeatureBranch:

$ kubectl logs stale-feature-branch-operator-6bfbfd4df8-m7sch -n stale-feature-branch-operator
... "msg":"Operator Version: 0.0.1"}
...
... "msg":"Starting EventSource", ... , "source":"kind source: /, Kind="}
... "msg":"Starting Controller", ...}
... "msg":"Starting workers", ..., "worker count":1}

Монтираме готови fixtures (готови конфигурации за моделиране на клъстерни ресурси) за ресурс StaleFeatureBranch:

$ kubectl apply -f https://raw.githubusercontent.com/dmytrostriletskyi/stale-feature-branch-operator/master/fixtures/stale-feature-branch.yml

Конфигурациите показват търсене на пространства от имена с подниз -pr- веднъж вътре 1 минуту.:

apiVersion: feature-branch.dmytrostriletskyi.com/v1
kind: StaleFeatureBranch
metadata:
  name: stale-feature-branch
spec:
  namespaceSubstring: -pr-
  afterDaysWithoutDeploy: 1 
  checkEveryMinutes: 1

Операторът е отговорил и е готов да провери пространствата от имена:

$ kubectl logs stale-feature-branch-operator-6bfbfd4df8-m7sch -n stale-feature-branch-operator
... "msg":"Stale feature branch is being processing.","namespaceSubstring":"-pr-","afterDaysWithoutDeploy":1,"checkEveryMinutes":1,"isDebug":"true"}

инсталирам fixtures, съдържащ две пространства от имена (project-pr-1, project-pr-2) и тях deployments, services, ingress, и така нататък:

$ kubectl apply -f https://raw.githubusercontent.com/dmytrostriletskyi/stale-feature-branch-operator/master/fixtures/first-feature-branch.yml -f https://raw.githubusercontent.com/dmytrostriletskyi/stale-feature-branch-operator/master/fixtures/second-feature-branch.yml
...
namespace/project-pr-1 created
deployment.apps/project-pr-1 created
service/project-pr-1 created
horizontalpodautoscaler.autoscaling/project-pr-1 created
secret/project-pr-1 created
configmap/project-pr-1 created
ingress.extensions/project-pr-1 created
namespace/project-pr-2 created
deployment.apps/project-pr-2 created
service/project-pr-2 created
horizontalpodautoscaler.autoscaling/project-pr-2 created
secret/project-pr-2 created
configmap/project-pr-2 created
ingress.extensions/project-pr-2 created

Проверяваме дали всички ресурси по-горе са създадени успешно:

$ kubectl get namespace,pods,deployment,service,horizontalpodautoscaler,configmap,ingress -n project-pr-1 && kubectl get namespace,pods,deployment,service,horizontalpodautoscaler,configmap,ingress -n project-pr-2
...
NAME                              ... READY ... STATUS  ... AGE
pod/project-pr-1-848d5fdff6-rpmzw ... 1/1   ... Running ... 67s

NAME                         ... READY ... AVAILABLE ... AGE
deployment.apps/project-pr-1 ... 1/1   ... 1         ... 67s
...

Тъй като включихме debug, пространства от имена project-pr-1 и project-pr-2, следователно всички други ресурси ще трябва да бъдат изтрити незабавно, без да се взема предвид параметърът afterDaysWithoutDeploy. Това може да се види в дневниците на оператора:

$ kubectl logs stale-feature-branch-operator-6bfbfd4df8-m7sch -n stale-feature-branch-operator
... "msg":"Namespace should be deleted due to debug mode is enabled.","namespaceName":"project-pr-1"}
... "msg":"Namespace is being processing.","namespaceName":"project-pr-1","namespaceCreationTimestamp":"2020-06-16 18:43:58 +0300 EEST"}
... "msg":"Namespace has been deleted.","namespaceName":"project-pr-1"}
... "msg":"Namespace should be deleted due to debug mode is enabled.","namespaceName":"project-pr-2"}
... "msg":"Namespace is being processing.","namespaceName":"project-pr-2","namespaceCreationTimestamp":"2020-06-16 18:43:58 +0300 EEST"}
... "msg":"Namespace has been deleted.","namespaceName":"project-pr-2"}

Ако проверите наличието на ресурси, те ще бъдат в състояние Terminating (процес на изтриване) или вече изтрит (изходът на командата е празен).

$ kubectl get namespace,pods,deployment,service,horizontalpodautoscaler,configmap,ingress -n project-pr-1 && kubectl get namespace,pods,deployment,service,horizontalpodautoscaler,configmap,ingress -n project-pr-2
...

Можете да повторите процеса на създаване fixtures няколко пъти и се уверете, че са премахнати в рамките на минута.

алтернативи

Какво може да се направи вместо оператор, който работи в клъстер? Има няколко подхода, всички те са несъвършени (а недостатъците им са субективни) и всеки сам решава кое е най-добро за даден проект:

  1. Изтриване на клон на функция по време на изграждане на непрекъсната интеграция на главен клон.

    • За да направите това, трябва да знаете коя заявка за изтегляне се отнася до ангажимента, който се изгражда. Тъй като пространството от имена на клона на функцията съдържа идентификатора на заявката за изтегляне - неговия номер или името на клона, идентификаторът винаги ще трябва да бъде посочен в ангажимента.
    • Основните компилации на клонове се провалят. Например, имате следните етапи: изтегляне на проекта, изпълнение на тестове, изграждане на проекта, създаване на версия, изпращане на известия, изчистване на клона на функцията на последната заявка за изтегляне. Ако изграждането се провали при изпращане на известие, ще трябва да изтриете всички ресурси в клъстера ръчно.
    • Без подходящ контекст изтриването на клонове на функции в основната компилация не е очевидно.

  2. Използване на уеб кукички (пример).

    • Това може да не е вашият подход. Например в Дженкинс, само един тип тръбопровод поддържа възможността за запазване на неговите конфигурации в изходния код. Когато използвате webhooks, трябва да напишете свой собствен скрипт, за да ги обработвате. Този скрипт ще трябва да бъде поставен в интерфейса на Jenkins, който е труден за поддръжка.

  3. пиша Кронджоб и добавете клъстер на Kubernetes.

    • Прекарване на време за писане и поддръжка.
    • Операторът вече работи в подобен стил, документиран е и се поддържа.

Благодаря ви за вниманието към статията. Връзка към проекта в Github.

Източник: www.habr.com

Добавяне на нов коментар