刪除 Kubernetes 叢集中過時的功能分支

刪除 Kubernetes 叢集中過時的功能分支

Привет! 特徵分支 (又稱部署預覽、審查應用程式)-此時不僅部署了主分支,而且還部署了對唯一 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
...

對於功能分支,將使用其識別碼(例如,拉取請求編號)和某種前綴/後綴(例如, -pr-):

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. 在建置過程中,執行 linter 和/或測試。
  3. Kubernetes 拉取請求設定是動態產生的(例如,其編號插入到完成的範本中)。
  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

參數 命名空間子字串 需要過濾命名空間以查找來自其他命名空間的拉取請求。 例如,如果叢集具有以下命名空間: 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.

參數 沒有部署後的日子 需要刪除舊的命名空間。 例如,如果建立了命名空間 3 дня 1 час 返回,參數表示 3 дня,該命名空間將會被刪除。 如果創建了命名空間,它也會以相反的方向工作 2 дня 23 часа 返回,參數表示 3 дня,該命名空間不會被刪除。

還有一個參數,它負責掃描所有命名空間並檢查沒有部署的天數的頻率 - 每分鐘檢查一次。 預設是相等的 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_DEBUGtrue。 有了這個值參數 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

添加評論