本文發表於一年多前。舊文章可能包含過時內容。請檢查頁面中的資訊自發布以來是否已變得不正確。
每週 Kubernetes 社群環聊筆記 - 2015 年 4 月 10 日
每週,Kubernetes 貢獻者社群都會透過 Google Hangouts 進行虛擬會議。我們希望所有感興趣的人都能瞭解這個論壇討論了什麼。
議程
- kubectl 工具、滾動更新、部署、命令式命令。
- Downward API / 環境變數替換,以及可能的先決條件/依賴項。
會議紀要
1. kubectl 改進
使其更易於使用,完成滾動更新,引入更高級別的部署概念。
滾動更新
當前
可以透過檔案替換一個 RC 為另一個 RC。
沒有明確的回滾支援,可以透過對舊版本進行滾動更新來實現。
我們透過 RC 上的註釋來跟蹤所需的例項數量;回滾情況下無法正常工作,因為不對稱。
需要不可變映象 ID;目前沒有與映象、版本對應的 UUID,所以如果有人在上面推送,你會重新拉取;在 API 伺服器中,我們應該將映象轉換為 UUID(儘可能接近邊緣)。
最好能自動生成新的 RC,而不是讓使用者更新它(例如,當更改容器的映象標籤等時;目前需要更改 RC 名稱和標籤值;可以自動化生成新的 RC)。
將 RC 視為“寵物”而非“牲畜”。
"從 v1 滾動到 v2"(或 v2 滾動到 v1)——對於大多數人來說已經足夠了。不關心過去發生了什麼。
我們提供 Ansible 可以呼叫的模組來完成任務。
如何跟蹤多個模板;目前我們使用多個 RC。
如果我們有一個部署控制器;部署配置生成執行滾動更新的 pod;觸發器是基於級別的映象倉庫更新。
替代短期方案:建立舊 RC 的克隆作為新 RC,調整計數使新 RC 變為舊 RC,反之亦然,將前一個命名的 RC(寵物)降至零,然後使用新模板將其恢復(這與 Borg 進行作業更新的方式非常相似)。
- 如果我們無論如何都想要部署,這樣做值得嗎?是的,因為我們已經有很多概念了;需要簡化。
部署控制器跟蹤多個模板,這是滾動更新和金絲雀部署所需的。
建立新物件的唯一原因是將程序從客戶端轉移到伺服器端嗎?
可能不需要將其作為 API 物件;應該提供一種非 API 物件,僅在客戶端側的體驗。
現在需要一種體驗,所以需要在客戶端完成,因為物件在 1.0 之前不會落地。
為那些只想使用 RC 的人提供簡化的體驗。
回滾如何工作:ctrl-c,回滾 v2 到 v1。回滾模式可以在人們腦海中形成。兩種回滾:我已經處於穩定狀態並想回滾,以及我進行了金絲雀部署,但按下 ctrl-c 後如何刪除金絲雀部署(例如新版本失敗)。ctrl-c 可能不起作用。刪除金絲雀控制器及其 pod。希望有一個命令可以同時刪除 pod(有 -- kbectl stop)。不重用名稱的理由是:當你向前推進時,你可以停止新的東西,這樣就沒問題,而如果你替換舊的並建立了一個副本,如果你按下 ctrl-c,你就沒有什麼可以停止的了。但你可以等到最後再翻轉名稱,使用命名約定以便了解發生了什麼等等。
兩種不同的體驗:(1)我正在使用版本控制,本週有上週釋出版本歷史,用兩個檔案進行滾動更新 -> 建立 v2,??? v1,沒有寵物 - 進入版本控制的世界,其中有累積歷史記錄;(2)命令式 kubectl v1 v2,系統負責細節,這就是我們使用快照模式的地方。
其他命令式命令
run-container(或只用 run):在命令列上指定命令,使其更類似於 docker run;但不支援多容器 pod。
--forever 與否(透過簡單命令進行一次性執行)。
希望它能互動式執行 - run -it 並在叢集中執行,但您有一個互動式終端與您的程序互動。
命令列引數如何工作。可以說多次 --image。cobra 會支援嗎?在 Openshift 中,我們有巧妙的語法來分組引數。不適用於真正的結構化引數。
替代方案:建立 pod;新增容器新增容器...;執行 pod -- 構建,直到“執行 pod”才執行物件。
-- 分隔容器引數。
建立一個 pod,在執行它之前對其進行變異 - 就像初始化器模式一樣。
型別發現
如果我們執行一個命令,有時它建立 RC,有時不建立,那麼如果使用者想要刪除他們透過執行建立的任何東西,他們如何知道要刪除什麼?
bburns 提出一個建議,如果你執行停止、刪除等命令,不要指定型別;讓 kubectl 自己判斷。
替代方案:允許您定義從名稱到一組資源型別的別名,例如,刪除所有,它將遵循該別名(所有可以表示某個名稱空間中的所有內容,或未限定範圍等) - 某人明確地將某些內容新增到集合中,而不是像節點那樣意外出現。
希望將其擴充套件到允許工具指定自己的別名(而不僅僅是使用者);例如,resize 可以說我可以處理 RC,delete 可以說我可以處理所有東西,等等,這樣我們就可以自動完成這些事情,而無需使用者指定內容。但需要正確的機制。
resourcebuilder 具有根據我們如何適應目標命令來執行這種擴充套件的概念。例如,如果你想向 pod 和 RC 添加捲,你需要一些東西來找到 pod 模板並更改它。這其中有搜尋部分(刪除 nginx -> 你必須弄清楚它們指的是哪個物件),然後命令可以說我有一個 pod,我知道如何處理 pod。
替代啟發式方法:如果所有命令的預設目標都是部署會怎樣。kubectl run -> 部署。工作量太大,清理現有 CLI 更容易。為此敞開大門。宏物件可以,但要使其工作需要更多工作。最終將需要索引來提高效率。可以更多地依賴 Swagger 來告訴我們型別。
2. paul/向下 API:環境變數替換
- 建立臨時環境變數,如字串,例如 k8s_pod_name,該變數將由系統在物件中替換。
- 允許人們建立引用 k8s 物件欄位的環境變數,而無需從容器內部查詢 API;在某些情況下,可以從容器內部查詢 API(例如傳遞物件名稱、名稱空間);例如,sidecar 容器需要這個來從 API 伺服器拉取資料。
- 另一個類似的建議:不是像環境變數那樣的名稱,而是使用類似 JSON-path 的語法來引用物件欄位名稱;例如,$.metadata.name 引用當前物件的名稱,也許有一種語法可以引用相關物件,如 pod 所在的節點。類似 JSON path 語法的優點是它不那麼隨意。缺點是您只能引用物件的欄位。
- 對於兩者,如果填充環境變數,那麼缺點是欄位只有在容器建立時才設定。但這耦合度最低——現成的容器,容器不需要知道如何與 k8s API 對話。將 k8s 概念保留在控制平面中。
- 我們正在趨向於類似 JSON path 的方法。但需要原型或至少更深入的提案進行演示。
- paul:一個變體是,除了 value 欄位,環境變數還可以有不同的來源,你可以在其中插入,例如,你用來描述物件欄位的語法;另一個來源是描述主機資訊的來源。有部分原型。映象和控制平面之間有清晰的分離。可以將源思想用於卷外掛。
- 用例:為 sidecar 容器提供聯絡 API 伺服器的資訊。
- 用例:傳遞唯一識別符號或使用 UID 作為唯一識別符號。
- clayton:對於更復雜的事情,為每個 pod 提供 rocket 或 gce 元資料服務;大多數容器都希望找到服務的端點。
3. 前提條件/依賴關係
- 當您建立與服務通訊的 pod 時,只有當您按正確順序建立物件時,服務環境變數才會填充。如果使用 DNS,問題會少一些,但有些應用程式很脆弱。如果它們依賴的服務不存在,可能會崩潰,可能需要很長時間才能重新啟動。建議設定前提條件,阻止啟動 pod,直到它們依賴的物件存在。
- 如果我們要求人們宣告他們想要哪些環境變數,或者在 pod、RC 或物件級別設定依賴機制,說明此物件在此其他物件存在之前不會啟用,則自動推斷。
- 可以使用事件鉤子嗎?只有應用程式所有者知道其依賴關係或服務何時準備好提供服務。
- 一個建議是使用 pre-start 鉤子。另一個是前提條件探測 - pre-start 鉤子可以進行探測。當我訪問此服務地址或 IP 時是否有任何響應,然後探測失敗。可以在 pre-start 鉤子中實現。比 post-start 更實用。是 rkt 規範的一部分。有階段 0、1、2。目前在 docker 中很難做到,在 rocket 中很容易。
- 容器中的 pre-start 鉤子:如果使用 pre-start 鉤子實現,容器可能會有一個鎖,直到滿足某些任意條件,這將如何影響 readiness 探測?如果有一個鉤子,kubelet 何時執行 readiness/liveness 探測,必須有一些補償。Systemd 對程序生命週期的各個階段都有超時。
- 如果我們採用容器的黑盒模型,pre-start 是有意義的;如果容器規範對程序模型更具描述性,就像 systemd 那樣,那麼 kubelet 是否需要更多地瞭解程序模型才能做正確的事情?
- 理想情況下,容器內部會發出訊息,說明已完成所有預啟動操作。systemd 的 sdnotify 就是這樣做的。你告訴 systemd 你已完成,它會通知其他依賴項你已啟動。
- 但是……有人可以在他們的容器內部實現前提條件。這使得在不更改映象的情況下更容易調整應用程式。替代方案是隻提供一個他們自己如何做的模式,但我們不為他們做。