為什麼在Kubernetes上開發很糟糕? | Tilt部落格

banq發表於2019-09-03

Kubernetes改變了我執行軟體的方式,但是,當我編寫軟體時,Kuberentes會讓事情變得更難。在這篇文章中,我想敘述我自己在Kubernetes上開發軟體時遇到的所有問題。完全披露:雖然我在Tilt工作是我工作的一部分,我們的目的是解決其中的一些問題,但我的另一部分工作是編寫在Kubernetes上執行的軟體。當有另一種工具比Tilt更好地解決問題時,我會使用它。

無數的開發環境

MinikubeMicroK8s適用於Mac的DockerKIND,所有這些都是本地的Kubernetes環境。換句話說:它們是Kubernetes,只是在你的膝上型電腦上。您無需前往網路與大型Kubernetes叢集(可能與生產資料互動)進行通訊,您可以在膝上型電腦上啟動一個小型叢集來檢查問題。
當你想在這些叢集中的多個叢集上執行程式碼/ Kubernetes配置時會出現問題,因為它們各自擁有自己的......怪癖。它們的行為彼此不同,或者與真正的Kubernetes叢集完全相同。我不會在這裡列舉這些差異,但在討論網路和身份驗證等棘手問題時,我會在整篇部落格文章中提到這個問題。
除了在雲中真正的Kubernetes叢集中進行開發之外,沒有任何我知道的工具可以解決這些問題,這是我最近工作的方式。如果您在本地開發群集的市場中,我們最近釋出了一個選擇開發群集指南,以幫助理解所有選項。

許可權/驗證
如果您正在使用Kubernetes開發軟體,那麼您可能正在使用Kubernetes進行生產。如果您在生產中使用Kubernetes,則可能已鎖定身份驗證設定。例如,常見的設定是隻允許開發人員訪問在一個名稱空間中建立/編輯物件。要做到這一點,你需要設定一些東西:

  • 一名角色
  • 一個角色繫結
  • 一個secret

如果您正在使用“真正的”Kubernetes叢集,這非常有用,但只要您開始使用本地Kuberentes設定,事情就會變得奇怪。還記得那些本地開發環境嗎?事實證明,其中一些處理RBAC的方式與您預期的完全不同。我遇到了一個問題,kubeadm有訪問控制設定允許一切。結果,我有一種虛假的信心會刺激我的設定實際上限制了許可權,而事實上他們沒有起效。當然,kubeadm-dind-cluster已被棄用,但它表明並非所有Kubernetes叢集都是相同的。我還遇到了另一個問題,試圖在Docker for Mac的Kubernetes叢集中重現該問題,其中沒有強制執行RBAC規則
像NetworkPolicies這樣的測試也很充實。NetworkPolicies在Docker for Mac或microk8s上根本不起作用,並且需要Minikube的特殊標誌

網路除錯
網路入口是Kubernetes最重要的事情之一。不幸的是,入口由不同的雲提供商以不同的方式實現,因此很難測試。不同的實現還支援不同的擴充套件,通常配置標籤,這些擴充套件在環境之間絕對不可移植。我很幸運能夠訪問一個臨時叢集來測試入口更改,但即使這樣,更改也可能需要30分鐘才能生效,並且可能導致不可思議的錯誤訊息。如果你在當地的Kubernetes環境中,你幾乎沒有運氣。
網路是我最不喜歡在Kubernetes工作的東西,而且我認為這個領域仍然需要最多的愛。但是,有一些工具可以提供幫助。
至少可以看到您的服務如何連線的一個很好的工具是Octant。Octant為您提供所有pod的視覺概覽以及它們所屬的服務。至少在Octant中,我可以輕鬆地從一段程式碼轉到連線到網際網路的方式。
對於複雜的Kubernetes物件,如在不同雲平臺上表現不同的入口Kubespy是一個非常寶貴的工具。Kubespy向您展示建立物件時引擎蓋下發生的事情。例如,如果我建立一個服務,它會顯示哪些IP地址Kubespy將為其提供流量的Pod:

> kubespy trace svc test-frontend
<p class="indent">[ADDED v1/Service] default/test-frontend

<p class="indent">[ADDED v1/Endpoints] default/test-frontend
   Directs traffic to the following live Pods:
    - [Ready] test-frontend-f6d6ff44-b7jzd @ 192.168.1.1


登入到容器並做事情
每個開發人員都會遇到的一個常見問題是SSH。也許在將來,SSH將像軟盤圖示一樣不合時宜,但是現在,我想登入到一個容器,四處尋找,看看狀態是什麼,並且可能執行一些命令,如strace或tcpdump。
Kubernetes並不容易。工作流程如下所示: kubectl get pods 查詢我的pod名稱 kubectl exec -it $podname -- /bin/bash
事情變得很煩人。

> kubectl exec -it dan-test-75d7b88d8f-4p45c -- /bin/bash
OCI runtime exec failed: exec failed: container_linux.go:345: starting container process caused "exec: \"/bin/bash\": stat /bin/bash: no such file or directory": unknown
command terminated with exit code 126


這到底是什麼?我知道在製作中我希望我的容器映象很小(考慮映象推送效能和安全性),但這些資訊有點多。

我最喜歡的解決這個問題的工具之一是Kubebox。Kubebox可讓您輕鬆檢視所有pod,只需按“r”即可將遠端shell新增到其中一個。
無論如何,大映象在本地叢集上應該不是問題,對嗎?

推/拉映象
在你的膝上型電腦上推映象應該超級快,因為沒有必要去網路。不幸的是,無數本地Kubernetes設定再一次暴露了醜陋。
讓我們來談談快樂的道路:Minikube和Docker for Mac。這兩個設定都執行一個Docker守護程式,您可以從本地膝上型電腦和Kubernetes叢集內部進行通訊。這意味著你需要做的就是將映象放入Kubernetes中來構建它; 您的pod可以直接從本地登錄檔“拉”它,而不需要處理透過網路移動資料。
MicroK8s預設情況下不附帶群集內登錄檔,但可以使用標誌輕鬆啟用。
相比之下,KIND是另一頭野獸。它有一個特殊的命令,用於將映象載入到叢集中kind load。不幸的是,這是無法忍受的緩慢。

$ time kind load docker-image golang:1.12

real    0m39.225s
user    0m0.438s
sys    0m2.159s


這是因為KIND會複製映象的每一層,並且只進行非常原始的內容協商。這意味著如果您只更改1.5 GB映象的最後15 KB圖層中的一個檔案,KIND可以複製整個1.5 GB映象。
幸運的是,那些致力於KIND專案的人們最近對映象載入做了很多改進。我們還發布了在KIND中執行登錄檔的概念證明,這有助於進一步提高速度。
如果我要使用本地開發環境,我傾向於使用Docker for Mac或MicroK8s,儘管如前所述,這些天我更喜歡在真正的雲Kubernetes叢集中進行開發。這個領域也出現了很好的工具。Garden在遠端登錄檔中快取映象層,減少每個開發人員需要重建的內容。使用live_update可以幫助我完全不需要推送和拉取映象,這就是我用來解決這個問題的方法。

安裝/檔案同步
即使您在推送映象時可以避免上網,只需構建映象也會很長時間。特別是如果您不使用多階段構建,特別是如果您使用具有額外依賴性的特殊開發映象。與熱重新載入本地JavaScript設定相比,即使是最快的映象構建也可能太慢。
我想要做的只是將檔案同步到我的pod。手工完成這個過程相對簡單,但很乏味:

kubectl cp <file-spec-src> <file-spec-dest>


此外,如果您的容器因任何原因重新啟動,例如,如果您的程式崩潰或pod被驅逐,您將丟失所有更改。
有像ksyncskaffold和Tilt這樣的工具可以幫助解決這個問題,儘管他們需要投入一些資金來設定。

日誌/觀測/活動
在開發中,我想tail相關的日誌,這樣我就可以看到我在做什麼。Kubernetes並不那麼容易。每個Kubernetes pod都有自己的日誌,我必須單獨查詢,每個日誌都有很多容器。真地,很容易看到只有一個pod(kubectl logs podname)的日誌。但是,要檢視聚合檢視,您需要了解很多關於pod的組織方式,比如哪些標籤適用於應用程式的哪些部分,以便您可以執行命令kubectl logs -l app=myapp。
然後是Kubernetes事件,您可以透過完全獨立的命令觀察。這很糟糕,因為它在事件日誌中我會找到重要的開發資訊,比如我的pod無法安排或者我推出的新映象無法執行。
我可以使用一組很好的可觀察性工具來幫助生成這些工具,但我不想在本地執行它們。有時我買不起資源 - 我的膝上型電腦相當受限制。雖然這些工具在各自的利基中都非常出色,但我寧願使用一種工具來輕鬆完成常見任務。換句話說,我應該始終能夠在一個視窗中開始除錯。有些問題可能是如此獨特或特殊,以至於我最終會使用其他工具來解決這些問題,但我不能透過十二個視窗來檢查一個問題。
我在另一篇部落格文章中探討了這個問題,我認為Tilt解決了這個問題,特別是現在它包括Kubernetes事件和pod日誌。前面提到的Kubebox花園是另外兩個很棒的選擇。

結論
雖然在Kubernetes上的開發仍然很糟糕,但在過去的一年裡我們已經走了很長的路。其最大漏洞是網路。如果我們想讓開發人員能夠建立端到端的完整堆疊微服務架構,我們需要提供一些方法來解決網路問題。在此之前,最後一次推向生產將始終揭示隱藏的網路問題。

相關文章