SSH vs.Kubectl exec
本文轉載自微信公眾號「新鈦云服」,作者祝祥 翻譯 。轉載本文請聯系新鈦云服公眾號。
讓我們看一下打開遠程shell的兩種流行方法:ssh與kubectl exec。
下面,我們將只看“ kubectl exec”子命令及相關的命令。kubectl本身就是所有Kubernetes的瑞士軍刀。。將所有這些與ssh進行比較就像將systemd與BSD init進行比較一樣。
另外,我將使用“SSH”來表示“OpenSSH”,這是SSH協議實現的事實標準。但大多數討論要點都適用于任何SSH實現。
Apples to Oranges
乍一看,這是一個奇怪的比較。
OpenSSH已經存在了二十年,遠遠早于云技術的 誕生。它的設計是假設您要管理幾臺服務器,并正在仔細配置和調整它們的各個方面。SSH也已被用作SFTP和Ansible之類的傳輸層協議。
另一方面,kubectl誕生于云時代。它處理成千上萬的遠程機器(或容器)。kubectl exec只是其中的一小部分,用于在出現問題時進行調試。
但是,如果您如果仔細觀則會發現:kubectl exec與ssh目的相同。它可以在遠程計算機上運行程序,而不會給您本地終端帶來麻煩,并嘗試與各種終端功能集成在一起,從而使您感覺好像已將鍵盤和顯示器插入了數據中心機架。
順便說一句,讓我們深入探討它們的異同。
Authn/z
讓我們從每個人最喜歡的主題開始:安全性。
TL; DR:SSH身份驗證非常容易定制,但是大規模管理很麻煩。kubectl處理授權要好得多,但是身份驗證通常是不透明的,很難調整。
注意:這里我們不會討論身份驗證方法的優缺點,這是另外一個話題,我們下次再討論。
SSH協議
SSH支持多種身份驗證選項:
- 基本密碼
- 非對稱加密密鑰
- 以明文形式在磁盤上
- 在使用密碼加密的磁盤上
- 使用硬件令牌(例如YubiKey)
- 證書(但不是X.509類型)鏈接到專用CA
- 上面有用于存儲私鑰的所有選項
- 通過GSS AP或PAM的可插拔外部身份驗證
- 例如Active Directory,LDAP,OIDC等
- 2FA
- 基于本地的硬件令牌
- 或通過PAM使用TOTP(例如Google Authenticator)或Duo等進行關聯
要對服務器進行身份驗證,您可以獲得非對稱公鑰或證書。默認情況下,SSH使用首次使用信任(TOFU),因此作為預防措施,您可能希望在客戶端計算機上管理?/.ssh/known_hosts。
作為用戶,您可以選擇所需的身份驗證方法以及如何在兩側進行配置!
當涉及授權時,情況并不理想。授權粒度基本上是:“ 用戶X可以登錄到服務器Y ”,沒有分組。您必須通過將用戶的公共密鑰寫入?/.ssh/authorized_keys并為其創建本地UNIX用戶,來配置用戶可能分別登錄的每個服務器。將CA與SSH證書一起使用可以幫助分發密鑰。PAM管道也可以為您創建用戶。無論如何,這將需要一些額外工作。
幸運的是,如果您愿意擴展工具,可以使用更高級別的軟件來解決這些問題。
Kubectl
大多數時候,大家都會認為kubeconfig管理kubernetns中的所有憑證。當使用托管的Kubernetes平臺,您甚至可能不會注意到平臺后臺會自動生成它。很少有人會直接修改kubeconfig內容,大多數情況下,您將使用云或身份驗證提供程序生成的內容。
這是一個不錯的用戶體驗,但下面有一些常見的問題點:
- HTTP基本身份驗證(用戶名+密碼為純文本)
- TLS客戶端證書(磁盤上的私鑰以純文本格式)
- 不透明的令牌(在磁盤上以純文本格式)
- 云提供商插件
- 這些被編譯成 kubectl code itself
- 慢慢地逐步淘汰以減少Kubernetes代碼依賴性
- Exec插件
- 在每個請求上,執行一個外部二進制文件以獲取承載令牌或TLS客戶端密鑰/證書
- 由云提供商使用,以與其定制的身份驗證系統集成
- 如果您想要2FA,這可能是可行的方法
服務器使用TLS進行身份驗證,通常在kubeconfig中嵌入一個私有CA。
這里的授權比SSH好得多!這里沒有類似SSH的(例如每個pod)設計,因為Kubernetes pod是短暫的非持久的。
Kubernetes通過RBAC本地處理授權。所有kubectl exec請求都通過Kubernetes API服務器進行傳輸,該服務器執行RBAC規則。它需要一些學習,從Internet復制粘貼的YAML并對其進行調整。但是,當您完成操作后,您可以說:“ 項目中的每個人都可以登錄到默認的namespace(名稱空間),但是只有核心人員可以管理生產namespace(名稱空間)* ”。
“最難”的部分是確保每個員工都擁有一個kubeconfig與您的RBAC規則相匹配的正確身份。幸運的是,SSO集成在大多數托管平臺上都相當不錯。
Shell UX
這個其實很接近。SSH和kubectl都處理終端顏色、轉義代碼、交互命令甚至窗口大小調整事件。SSH和kubectl在99%的CLI應用程序中應該都能很好地工作。
SSH確實增加了一些比較好的功能:
- 環境變量定制
- kubectl總是在啟動時設置提供給容器的環境變量
- ssh主要依賴于系統登錄shell的程序配置(但也可以通過PermitUserEnvironment或SendEnv/AcceptEnv接受用戶的環境)
- 轉義序列(不要與ANSI轉義代碼混淆)
- 超級方便,可以關閉掛起的SSH會話,而不必等待超時觸發
- 下次使用ssh時可以嘗試輸入“~?”
Non-shell features
文件傳輸
ssh和kubectl都支持在您和服務器之間傳輸文件。
SSH協議
SSH有多種工具可以將其作為傳輸工具使用:
- 有內置的SCP和更新一點的SFTP
- 盡管需要獨立安裝,但還有一個更好的rsync工具
- 您甚至可以使用一些管道符進行文件的傳輸
KUBECTL
kubectl cp命令可以復制文件,但基本上是kubectl exec + tar的簡單封裝。而且,如果您要處理的容器尚未包含tar命令的話,那么就會很遺憾。
您可以使用掛載volume的方式去實現傳輸文件,但這在創建Pod時需要提前計劃好,非常不方便。
Port forwarding
SSH協議
- SSH具有非常靈活的端口轉發支持:
- 本地端口轉發(本地端口->服務器->任何位置)ssh -L 8080:example.com:80 server
- 遠程端口轉發(任何地方->服務器端口->本地端口)ssh -R 80:localhost:8080 server
動態端口轉發(通過SOCKS5)ssh -D 1080 server
您可以通過它去實現各種轉發需求!當然也可以在生產環境中留下后門...
KUBECTL
kubectl port-forward使您可以通過本地端口通信到Pod上的遠程端口。這是SSH本地端口轉發所不能實現的部分。
Jump hosts
SSH協議
使用SSH時,通常會設置跳轉主機(也稱為堡壘機),通過對堡壘機權限的控制而實現訪問的控制。
您確實需要手動設置它,適當地配置客戶機和服務器,還需要考慮在該機上使用多租戶。它會成為維護的負擔。
KUBECTL
在Kubernetes中,API服務器實際上是您的“跳轉主機”。
X11 forwarding
使用SSH,您可以圖形化的管理遠程應用程序:
- user@local $ ssh -X server
- user@server % firefox
它就像一個遠程桌面,但是您在服務器上啟動的應用程序自然會融合到本地桌面中,而不是擁有嵌套的桌面。
性能
從用戶角度來看,SSH和kubectl的性能都很好。您可能會感覺到一些卡頓,尤其是在網絡不穩定的情況下,但是兩者之間的速度都明顯慢。
但是我仍然想獲得一些實際參考數據,因此讓我們運行一些人為的基準測試!
TL; DR:kubectl exec在建立連接時速度更快,但是SSH在發送/接收會話數據時速度更快。
以下結果并不準確,但仍代表了實際使用情況:在有無線網絡連接的筆記本電腦上進行測試。
客戶端是OpenSSH v8.3和kubectl v1.18。在Kubernetes方面,我使用的是一個基于busybox創建的簡單容器kubectl run -it busybox --image=busybox。
本地服務器是OpenSSH v8.3和運行Kubernetes v1.18的minikube。
遠程服務器是OpenSSH v8.2和GKE v1.14(相當老,是的)。兩者都在同一區域的GCP上運行。
Login/setup latency
首先,讓我們衡量一下建立會話所需的時間。
在這兩種情況下,我將遠程運行echo foo 100次,并使用hyperfine測量計時。結果測量了建立連接、執行authn/z、打開遠程shell然后斷開連接所需的時間。實際的echo command耗時<1ms,不應影響結果。
本地
- $ hyperfine 'ssh localhost echo foo' 'kubectl exec -it busybox echo foo' -r 100
- Benchmark #1: ssh localhost echo foo
- Time (mean ± σ): 156.2 ms ± 15.9 ms [User: 14.0 ms, System: 2.1 ms]
- Range (min … max): 112.4 ms … 220.9 ms 100 runs
- Benchmark #2: kubectl exec -it busybox echo foo
- Time (mean ± σ): 113.9 ms ± 16.1 ms [User: 72.4 ms, System: 12.7 ms]
- Range (min … max): 95.8 ms … 157.2 ms 100 runs
- Summary
- 'kubectl exec -it busybox echo foo' ran
- 1.37 ± 0.24 times faster than 'ssh localhost echo foo'
kubectl 最快,快37%!
遠程
如果我們把網絡加入其中呢?
- $ hyperfine 'ssh ubuntu echo foo' 'kubectl exec -it busybox echo foo' -r 100
- Benchmark #1: ssh ubuntu echo foo
- Time (mean ± σ): 689.1 ms ± 42.6 ms [User: 41.1 ms, System: 6.1 ms]
- Range (min … max): 653.6 ms … 1022.0 ms 100 runs
- Benchmark #2: kubectl exec -it busybox echo foo
- Time (mean ± σ): 445.7 ms ± 45.3 ms [User: 130.1 ms, System: 31.2 ms]
- Range (min … max): 372.3 ms … 655.2 ms 100 runs
- Summary
- 'kubectl exec -it busybox echo foo' ran
- 1.55 ± 0.18 times faster than 'ssh ubuntu echo foo'
再一次kubectl獲得最佳:速度提高55%!
吞吐量
原始數據吞吐量如何?
我將通過OpenSSH發送約32MB的數據,并在遠端將其回顯。
本地
- $ hyperfine 'find . -type f | xargs cat | ssh localhost cat' 'find . -type f | xargs cat | kubectl exec -it busybox cat' -r 10
- Benchmark #1: find . -type f | xargs cat | ssh localhost cat
- Time (mean ± σ): 5.457 s ± 0.167 s [User: 4.464 s, System: 1.259 s]
- Range (min … max): 5.202 s … 5.657 s 10 runs
- Benchmark #2: find . -type f | xargs cat | kubectl exec -it busybox cat
- Time (mean ± σ): 27.628 s ± 1.725 s [User: 9.920 s, System: 7.203 s]
- Range (min … max): 25.044 s … 30.926 s 10 runs
- Summary
- 'find . -type f | xargs cat | ssh localhost cat' ran
- 5.06 ± 0.35 times faster than 'find . -type f | xargs cat | kubectl exec -it busybox cat'
好吧,這很有趣。SSH通過發送數據的速度快約5倍!
SSH需要大約5.45s,大約6000 KB/s。
kubectl 大約需要27.62s,大約1200 KB/s。
遠程
- $ hyperfine 'find . -type f | xargs cat | ssh ubuntu cat' 'find . -type f | xargs cat | kubectl exec -it busybox cat' -r 10
- Benchmark #1: find . -type f | xargs cat | ssh ubuntu cat
- Time (mean ± σ): 28.794 s ± 0.627 s [User: 10.525 s, System: 5.018 s]
- Range (min … max): 27.788 s … 29.921 s 10 runs
- Benchmark #2: find . -type f | xargs cat | kubectl exec -it busybox cat
- Time (mean ± σ): 33.299 s ± 2.679 s [User: 10.831 s, System: 8.902 s]
- Range (min … max): 30.964 s … 40.292 s 10 runs
- Summary
- 'find . -type f | xargs cat | ssh ubuntu cat' ran
- 1.16 ± 0.10 times faster than 'find . -type f | xargs cat | kubectl exec -it busybox cat'
SSH仍然更快,但僅提高了約16%。
結論
SSH和kubectl之間有很多相似之處,它們都有各自的優點和缺點。雖然SSH在架構上是一成不變的,但是在管理一些機器時,高級軟件可以從Kubernetes那里學到一些關于集中配置的東西。SSH還可以借用kubeconfig中的憑證管理方法(即“將所有客戶機憑據和服務器信息放入一個可以復制的文件中”)。
kubectl可以改善其no-shell功能,例如端口轉發和文件傳輸。它原始數據吞吐量也不足,這使其無法成為像SSH這樣的傳輸層協議。實際上,這些工具是互補的,可以用于不同的任務,而不是僅僅使用其中一個。希望這篇文章對您有所幫助!
原文:https://gravitational.com/blog/ssh-vs-kubectl/