Kubernetes 提示和技巧:關於本地開發和網真

Kubernetes 提示和技巧:關於本地開發和網真

我們越來越多地詢問有關在 Kubernetes 中開發微服務的問題。 開發人員(尤其是解釋語言的開發人員)希望在他們最喜歡的 IDE 中快速更正程式碼並查看結果,而無需等待建置/部署 - 只需按 F5。 當涉及單體應用程式時,本機安裝資料庫和 Web 伺服器(在 Docker、VirtualBox 中...)就足夠了,然後立即享受開發。 隨著單體應用被切割成微服務以及 Kubernetes 的到來,隨著相互依賴的出現,一切都變得簡單。 變得有點困難了。 這些微服務越多,問題就越多。 為了再次享受開發的樂趣,你需要啟動一兩個以上的 Docker 容器,有時甚至是十幾個……總的來說,這一切可能會花費相當多的時間,因為它也需要保持最新狀態。

在不同的時間我們嘗試了不同的解決方案來解決問題。 我將從累積的解決方法或簡單的“拐杖”開始。

1.拐杖

大多數 IDE 都能夠使用 FTP/SFTP 直接在伺服器上編輯程式碼。 這條路非常明顯,我們立即決定使用它。 其本質可歸結為以下幾點:

  1. 在開發環境(dev/review)的 Pod 中,啟動一個具有 SSH 存取權限的附加容器,並轉發將提交/部署應用程式的開發人員的公共 SSH 金鑰。
  2. 在初始化階段(在容器內 prepare-app)將代碼傳輸到 emptyDir可以從應用程式容器和 SSH 伺服器存取程式碼。

Kubernetes 提示和技巧:關於本地開發和網真

為了更好地理解該方案的技術實現,我將提供 Kubernetes 中涉及的 YAML 配置的片段。

配置

1.1. 值.yaml

ssh_pub_key:
  vasya.pupkin: <ssh public key in base64> 

這裡 vasya.pupkin 是變數的值 ${GITLAB_USER_LOGIN}.

1.2. 部署.yaml

...
{{ if eq .Values.global.debug "yes" }}
      volumes:
      - name: ssh-pub-key
        secret:
          defaultMode: 0600
          secretName: {{ .Chart.Name }}-ssh-pub-key
      - name: app-data
        emptyDir: {}
      initContainers:
      - name: prepare-app
{{ tuple "backend" . | include "werf_container_image" | indent 8 }}
        volumeMounts:
        - name: app-data
          mountPath: /app-data
        command: ["bash", "-c", "cp -ar /app/* /app-data/" ]
{{ end }}
      containers:
{{ if eq .Values.global.debug "yes" }}
      - name: ssh
        image: corbinu/ssh-server
        volumeMounts:
        - name: ssh-pub-key
          readOnly: true
          mountPath: /root/.ssh/authorized_keys
          subPath: authorized_keys
        - name: app-data
          mountPath: /app
        ports:
        - name: ssh
          containerPort: 22
          protocol: TCP
{{ end }}
      - name: backend
        volumeMounts:
{{ if eq .Values.global.debug "yes" }}
        - name: app-data
          mountPath: /app
{{ end }}
        command: ["/usr/sbin/php-fpm7.2", "--fpm-config", "/etc/php/7.2/php-fpm.conf", "-F"]
...

1.3. 秘密.yaml

{{ if eq .Values.global.debug "yes" }}
apiVersion: v1
kind: Secret
metadata:
  name: {{ .Chart.Name }}-ssh-pub-key
type: Opaque
data:
  authorized_keys: "{{ first (pluck .Values.global.username .Values.ssh_pub_key) }}"
{{ end }}

最後的觸摸

之後剩下的就是轉移 所需的 gitlab-ci.yml 變量:

dev:
  stage: deploy
  script:
   - type multiwerf && source <(multiwerf use 1.0 beta)
   - type werf && source <(werf ci-env gitlab --tagging-strategy tag-or-branch --verbose)
   - werf deploy
     --namespace ${CI_PROJECT_NAME}-stage
     --set "global.env=stage"
     --set "global.git_rev=${CI_COMMIT_SHA}"
     --set "global.debug=yes"
     --set "global.username=${GITLAB_USER_LOGIN}"
 tags:
   - build

瞧:啟動部署的開發人員可以透過服務名稱進行連線(如何安全地授予對叢集的存取權限, 我們已經告訴過)透過 SFTP 從桌面編輯程式碼,而無需等待程式碼傳送到叢集。

這是一個完全可行的解決方案,但從實現的角度來看,它有明顯的缺點:

  • 需要細化 Helm 圖表,這使得將來難以閱讀;
  • 只能由部署該服務的人使用;
  • 你需要記住然後將其與程式碼同步到本地目錄並提交到Git。

2. 網真

項目 網真 已經為人所知很長時間了,但正如他們所說,我們“沒有抽出時間在實踐中認真嘗試。” 然而,需求已經完成了它的工作,現在我們很高興分享我們的經驗,這可能對我們博客的讀者有用 - 特別是因為中心上還沒有關於網真的其他材料。

總之,一切變得沒有那麼可怕了。 我們將需要開發人員執行的所有操作放置在名為的 Helm 圖表文字檔案中 NOTES.txt。 因此,將服務部署到 Kubernetes 後,開發人員會在 GitLab 作業日誌中看到啟動本機開發環境的說明:

!!! Разработка сервиса локально, в составе Kubernetes !!!

* Настройка окружения
* * Должен быть доступ до кластера через VPN
* * На локальном ПК установлен kubectl ( https://kubernetes.io/docs/tasks/tools/install-kubectl/ )
* * Получить config-файл для kubectl (скопировать в ~/.kube/config)
* * На локальном ПК установлен telepresence ( https://www.telepresence.io/reference/install )
* * Должен быть установлен Docker
* * Необходим доступ уровня reporter или выше к репозиторию https://gitlab.site.com/group/app
* * Необходимо залогинится в registry с логином/паролем от GitLab (делается один раз):

#########################################################################
docker login registry.site.com
#########################################################################

* Запуск окружения

#########################################################################
telepresence --namespace {{ .Values.global.env }} --swap-deployment {{ .Chart.Name  }}:backend --mount=/tmp/app --docker-run -v `pwd`:/app -v /tmp/app/var/run/secrets:/var/run/secrets -ti registry.site.com/group/app/backend:v8
#########################################################################

我們不會詳細討論本說明中所述的步驟......除了最後一個步驟。 網真推出期間會發生什麼事?

使用網真

在啟動時(使用上面說明中指定的最後一個命令),我們設定:

  • 微服務運作所在的命名空間;
  • 我們想要滲透的部署和容器的名稱。

其餘參數是可選的。 如果我們的服務與 Kubernetes API 互動並為 Kubernetes API 交互 服務帳戶已建立,我們需要在桌面上安裝憑證/令牌。 為此,請使用該選項 --mount=true (或者 --mount=/dst_path),這會將根目錄(/)從 Kubernetes 容器掛載到我們的桌面。 之後,我們可以(取決於作業系統和應用程式的啟動方式)使用叢集中的「密鑰」。

首先,讓我們看看運行應用程式最通用的選項 - 在 Docker 容器中。 為此,我們將使用密鑰 --docker-run 並將包含程式碼的目錄掛載到容器中: -v `pwd`:/app

請注意,這假設從專案目錄運行。 應用程式程式碼將被掛載到目錄中 /app 在一個容器中。

下一篇: -v /tmp/app/var/run/secrets:/var/run/secrets — 將帶有憑證/令牌的目錄掛載到容器中。

該選項最後後面是應用程式將在其中運行的映像。 NB:建構鏡像時,必須指定 CMDENTRYPOINT!

接下來到底會發生什麼事?

  • 在 Kubernetes 中,對於指定的 Deployment,副本數將變更為 0。相反,將啟動一個新的 Deployment - 使用替代容器 backend.
  • 桌面上將啟動 2 個容器:第一個容器包含 Telepresence(它將代理來自/發送到 Kubernetes 的請求),第二個容器包含正在開發的應用程式。
  • 如果我們將應用程式執行到容器中,那麼部署期間 Helm 傳輸的所有 ENV 變數都將可供我們使用,並且所有服務也將可用。 剩下的就是在您最喜歡的 IDE 中編輯程式碼並享受結果。
  • 工作結束時,您只需關閉執行 Telepresence 的終端機(使用 Ctrl+C 終止會話)即可 - Docker 容器將停止在桌面上,而在 Kubernetes 中,一切都會返回其初始狀態。 剩下的就是提交、發出 MR 並將其轉移到審核/合併/…(取決於您的工作流程)。

如果我們不想在 Docker 容器中運行應用程式 - 例如,我們不是用 PHP 開發,而是用 Go 開發,並且仍然在本地建置它 - 啟動 Telepresence 會更簡單:

telepresence --namespace {{ .Values.global.env }} --swap-deployment {{ .Chart.Name  }}:backend --mount=true

如果應用程式存取 Kubernetes API,則需要掛載金鑰目錄 (https://www.telepresence.io/howto/volumes)。 有一個適用於 Linux 的實用程式 :

proot -b $TELEPRESENCE_ROOT/var/run/secrets/:/var/run/secrets bash

啟動 Telepresence 後沒有選項 --docker-run 所有環境變數都將在目前終端中可用,因此必須在其中啟動應用程式。

NB:例如,在使用 PHP 時,必須記住禁用各種 op_cache、apc 和其他加速器進行開發 - 否則編輯程式碼將不會得到所需的結果。

結果

使用 Kubernetes 進行本地開發是一個問題,其解決方案隨著該平台的普及而不斷增長。 在收到開發人員(來自我們的客戶)的相關請求後,我們開始使用第一種可用的方法來解決這些問題,但從長遠來看,這並沒有證明自己的能力。 幸運的是,這不僅現在變得顯而易見,而且不僅對我們來說已經變得顯而易見,因此世界上已經出現了更合適的手段,而網真就是其中最著名的(順便說一句,還有 腳手架 來自Google)。 我們的使用體驗還不是很好,但它已經讓我們有理由向我們的“店裡同事”推薦它 - 嘗試一下!

聚苯乙烯

K8s 提示和技巧系列中的其他內容:

來源: www.habr.com

添加評論