成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

兩年云原生落地實踐在運維和開發側踩過的六個坑

新聞 云計算
云原生落地之路并不是一帆風順的,無論是在運維側還是研發側,我們都走過不少冤枉路,下面把曾經遇到的“坑”匯總到一起,分享給在云原生之路探索的你。

運維側的教訓

運維側最核心的目標就是保障 Kubernetes 集群的穩定性,在搭建 Kubernetes 集群的過程中,我們遇到了 2 個比較嚴重的問題,一個是容器產生僵尸進程,另一個是內核 Bug 引起的 Kubelet 負載飆升。

1.1 容器產生僵尸進程

Web 終端僵尸進程是困擾我們很久的問題,表現為當研發人員重啟 Pod 時,發現集群中存在偶發的一些狀態為 Not Ready 的節點,非常詭異,百思不得其解。后來發現原來是過多的 Bash 進程觸發了 containerd-shim 的一個 Bug 所致。讓我們一起來剖析問題的前因后果。

問題描述

在集群正常運行過程中,運維人員隔一段時間就會收到集群節點 Not Ready 的告警,當 Not Ready 狀態持續一段時間后,Kubernetes 集群為了保持服務的高可用就會自動觸發保護機制,進行整機遷移。

導致節點狀態變為 Not Ready 的原因有很多,經排查發現,狀態變為 Not Ready 的 Node 上存在一些處于 terminating 狀態的 Pod,這些 Pod 的狀態一直停留在 terminating,無法正常終止。同時,在 Node 上執行 docker ps 命令,發現命令無法正常輸出,一直在等待 Docker 返回結果。由于 Kubelet 同樣依賴 Docker 相關命令探測容器狀態,就會導致 Kubelet 內部的健康檢查超時,進而引發 Node 狀態被標記為 Not Ready。為什么 docker ps 命令會卡死呢?經過進一步排查發現,所有出現問題的 Node 上均存在僵尸進程,并且這些僵尸進程均是由這些持續處于 terminating 狀態的 Pod 所創建。

問題原因

為了便于開發人員調試和實時查看容器日志,發布平臺提供了 Web 終端功能,讓研發人員可以在瀏覽器中直接進入容器,并執行各種命令。

Web 終端通過 WebSocket 技術連接一個后端服務,該后端服務會調用 API Server 提供的 exec API(通過 client-go 實現),在容器中啟動一個 Bash 進程,并將該 Bash 進程的標準輸入、輸出流與 WebSocket 連接到一起,最終實現了基于 Web 技術的終端。

問題就出現在這個 Bash 進程上,由于該進程并不是由容器父進程(Pid 0)派生的,而是由 containerd-shim 派生出來的,如圖 17-1 所示,因此當容器被關閉時,Bash 進程無法收到容器父進程發送的退出信號,需要等待 Kubelet 通知 containerd-shim,由 containerd-shim 發送 killall 指令給容器內的所有進程,并等待這些進程退出。

圖片

圖 17-1 Bash 僵尸進程原理圖

containerd-shim 在實現這一步時,使用了一個長度為 32 的阻塞 Channel(Golang 的一種數據結構)來偵聽子進程的退出事件,如果子進程較多,觸發的退出事件會充滿整個 Channel,進而觸發 containerd-shim 出現死鎖,無法正確回收子進程,從而導致產生了僵尸進程。而在 containerd-shim 發生死鎖后,Kubelet 一旦運行 docker inspect 命令查看該容器狀態,對應的線程便會掛起,最終導致 Node 進入 Not Ready 狀態。

解決方案

定位到問題后,解決問題的核心思路是減少 containerd-shim 下派生的子進程 Bash 的數量上,我們通過 4 步來解決該問題。

  1. 優化 Web 終端代碼,在用戶關閉瀏覽器窗口后(WebSocket 連接斷開),模擬發送 CTRL+C 和 exit 命令給 Bash 進程,觸發 Bash 進程主動退出,如圖 17-2 所示。
  2. 設置 Web 終端的超時時間,在 Web 終端空閑 10 分鐘后(WebSocket 上沒有數據傳輸),觸發其主動退出。
  3. 如果用戶使用了 Vim 等會搶占終端輸入流的命令,便無法使用第 1 步的方法退出 Bash 進程,我們在每臺 Node 上添加了定時任務,主動清理存活 30 分鐘以上的 Bash 進程。
  4. 盡量避免使用 exec 類型的探針,而是使用 HTTP 探針替代,exec 探針同樣是在 containerd-shim 下派生子進程,也容易造成子進程過多。

圖片

圖17-2通過exit命令主動關閉終端進程

1.2 內核 Bug 引起的 Kubelet 負載飆升

問題描述

在測試階段發現,當集群運行一段時間后,研發人員在發布新應用時 Pod 的創建非常緩慢,Web 終端連接超時,Prometheus 獲取數據經常丟失,集群宿主機 CPU 負載飆升。

問題分析

從 Pod 創建的過程開始排查,我們使用 kubectl describe 命令查看 Pod 的創建過程,發現從 Pod 資源對象的創建到調度到具體 Node 的耗時很短,說明調度器沒有問題。而在 Pod 調度完成后,Kubelet 拉取鏡像和創建容器等動作耗時較長,我們懷疑是 Kubelet 的問題,經查看發現 Kubelet 使用的 CPU 時間片偶爾會達到 400%左右,系統調用占比較高,最高達到 40%,隨后開始對 Kubelet 進行 CPU 性能分析。

GitHub 上有相同的問題, ?https://github.com/google/cadvisor/issues/1774?

紅帽官方也有此 Bug 的討論地址為 https://bugzilla.redhat.com/show_bug.cgi?id=1795049

博文很長,總結要點如下。

在 Kubernetes 集群中,網絡延遲會升高到 100ms。這是由于內核做了太多的工作(在 memcg_stat_show 中)導致網絡依賴出現軟中斷。文章中的例子和我們遇到的場景類似,都

是因為 cAdvisor 從/sys/fs/cgroup/memory/memory.stat 中獲取監控數據引發的。

解決方案

  1. 使用 shell 命令檢查耗時,如果耗時大于 1s,甚至超過 10s,那么可以判定當前系統的內核存在上面描述的 Bug。
  2. 使用 shell 命令/proc/sys/vm/drop_caches>可以減緩網絡延時,但治標不治本。
  3. 禁止 Kubelet 使用 cAdvisor 收集 Cgroup 信息,這樣會失去部分監控數據。
  4. 升級內核版本。

其中方案 1、2、3 屬于臨時方案,推薦使用方案 4,升級內核版本,我們將內核版本升級到 4.19.113-300.el7.x86_64 后,就避免了這個問題。

開發側的教訓

除了運維側踩了很多坑,開發側同樣也遇到了不少棘手的問題。

2.1 運營問題(使用方式和習慣的改變)

在平臺推廣初期,盡管新平臺相較老平臺在各方面都有了很大程度的提升,但平臺的推廣并沒有收到令人滿意的效果。這里主要存在開發習慣、遷移成本以及對于一個新產品的不信任等因素,因此,基礎架構團隊經過深入的用戶調研和分析后,決心大力運營平臺推廣,主要從技術手段和人力手段兩個維度并行展開。

在技術層面,針對老平臺提供一鍵遷移代碼倉庫、一鍵托管配置文件等效率工具,幫助用戶低成本地從老平臺遷移到新平臺,避免因為煩瑣的操作而耗費用戶的耐心。

在人力層面,為公司的每個業務技術團隊分配專人進行推進,手把手協助業務團隊做應用遷移。這一步看似低效,在實際執行中效果非常好。人與人、面對面的溝通,更容易建立業務線技術團隊對新平臺的信任,幫助他們初步遷移幾個應用后,后續的遷移均是由各個業務線研發人員自主進行的,實際消耗時間成本并不高。同時,在手把手幫助業務線遷移的過程中,可以從用戶視角觀察產品交互效果,這個過程也幫助我們找到了很多平臺存在的缺陷,大大促進了平臺的進一步優化。

2.2 IP 白名單訪問控制

在應用進行容器化部署的過程中,也暴露出了現有架構不合理的地方,比如在解決訪問鑒權問題時,過度依賴 IP 白名單。IP 白名單是一種低成本且能初步滿足需求的鑒權機制,但存在不靈活、不易擴展等問題,例如很容易出現上游應用部署實例進行變更或者擴容時,下游應用沒有及時修改 IP 白名單,導致訪問被拒絕,從而引發線上故障。同時 IP 白名單也不是一種足夠安全的鑒權機制,尤其是 IP 可能會被回收并重新分配給其他應用使用,這時如果沒有及時回收原有 IP 上的授權,很有可能引發權限泄漏。

在應用進行容器化改造后,由于我們直接使用的是原生的網絡方案,在容器被重新調度后,容器的 IP 會發生改變,這樣便無法沿用 IP 白名單鑒權機制。為此我們從訪問方以及服務提供方兩個方向入手,制定了 3 個階段的改造方案。

第一階段,添加代理層。我們在訪問方與服務提供方二者之間,部署了一套 Nginx 代理服務器,將 Kubernetes Ingress 的 IP 作為服務提供方的上游客戶端地址,配置進入 Nginx 相應域名的上游客戶端。對訪問方進行改造,將原始服務提供方的域名替換為代理服務器的域名。改造后,從服務提供方視角觀察到的訪問方 IP 變為代理服務器的 IP,這時將代理服務器的 IP 配置進服務提供方的 IP 白名單后,無論訪問方的 IP 如何變化,都不會被服務提供方的 IP 白名單限制了。

第二階段,提供服務方改造。在第一階段實施完成后,雖然訪問方實現了容器化改造,但在服務提供方留下了安全漏洞,只要獲取新加入的代理層 IP,即可將自己偽裝成剛剛完成容器化改造的應用,并以該應用的身份調用服務提供方。在第二階段,我們要對服務提供方進行改造,讓其支持 API Key、對稱簽名等與 IP 無關的訪問控制機制,以抵御代理層引入的安全風險。

第三階段,訪問方改造。在服務提供方完成與 IP 無關的訪問控制機制后,訪問方應隨之做改造,以支持新的訪問控制方式。這時訪問方就可以將服務提供方的地址從代理服務器切換回服務提供方的真實地址了。在經過一段時間的驗證后,訪問方即可將代理服務器的 IP 從 IP 白名單列表中移除,最終完成整個改造方案。

2.3 流量平滑遷移

在平臺推廣初期,除去試水的新應用,很大一批應用是從老發布平臺遷移到容器化平臺上的。在遷移過程中,我們必須幫助用戶將老平臺的流量平滑、逐步遷移到新平臺上。

我們通過在原有 Nginx 代理中,添加 Kubernetes Ingress IP 的方式,進行一段時間的灰度發布,逐漸調高 Kubernetes 流量的權重,直至將 100%的流量遷移至 Kubernetes。在切換初期,我們并不會直接調整 DNS,而是將 Ingress IP 加入域名的上游客戶端,例如以下 Nginx 配置代碼片段。

圖片

其中 10.16.55.*段是應用的原始服務節點,而 10.216.15.96 與 10.216.15.196 是 Ingress 的 IP 地址,將 Ingress IP 加入域名的上游客戶端中后,流量就可以根據我們配置的 weight 參數再均攤到多個節點中。通過逐步增大 Ingress 節點的 weight 值,將應用原節點的 weight 值降為 0,再持續運行一段時間后,即可將 DNS 直接配置解析到 Ingress 中,完成流量的最終切換。

在切換過程中,有以下需要注意的問題。

  • 在遷移過程中,新需求上線時,業務線研發需要在新/老兩個平臺上同時上線,切記不能忘記更新原有平臺的應用代碼。
  • 由于額外添加了一層代理,外部觀察到的容器響應時間會比實際的高,這時需要從應用本身去觀測性能指標,并與老平臺的應用進行對比。
  • 額外的代理層除了會對響應時間造成影響,還會額外記錄一份響應日志,即訪問會在原 Nginx 服務器上記錄一次,同時在 Ingress 服務器上也記錄一次。在遷移過程中,很難完全排查這部分統計誤差。

2.4 上線后的分支要不要刪除?

Aone Flow 分支模型雖然靈活,但會在代碼倉庫中創建大量短生命周期的分支,有兩種分支需要進行定期清理。

第一種是發布分支。每次有特性分支從發布分支退出時,就會導致相應環境的發布分支被重新創建,如圖 17-3 所示。

圖片

圖17-3特性分支退出并重建發布分支

在特性分支(feature/001)退出后,我們會創建新的發布分支(release/daily/20211105),這時舊發布分支(release/daily/20211102)的生命周期便結束了,特性分支(feature/002)的后續提交均會合并到新的發布分支(release/daily/20211105)上,此時舊發布分支便可以被安全地刪除。

注意,雖然刪除發布分支一般不會導致代碼丟失,但如果在該發布分支上解決過代碼合并沖突,這部分解決合并沖突的工作需要在新的發布分支上重新進行一次。如果之前發生沖突時,是在特性分支上解決的,就無需重復進行沖突的解決了。這也是遇到分支沖突時,推薦在特性分支上解決沖突的原因。

第二種需要清理的分支是特性分支。在特性分支被發布到正式環境,并且合并到主干分支后,即可標記特性分支為可以被刪除。與發布分支重建后,老發布分支可被立刻刪除不同,我們對特性分支采取了延遲刪除的策略,每周將歷史上已經處于凍結狀態的特性分支進行清理。

為什么不立刻刪除已經上線的特性分支呢?這是因為雖然特性分支已經被合并到主干分支,但可能在上線后發現代碼存在 Bug,需要進行及時修復,這時最高效的方式是在引入 Bug 的特性分支上進行代碼修改,并立刻進行回歸測試,然后重新上線修復。但特性分支在上線后,狀態會被標記為已凍結,無法重新上線,這時發布平臺可以從已凍結的特性分支中快速復制并得到一個新的分支,進行上線修復。如果我們在特性分支上線后,立刻刪除該特性分支,就無法做到這一點了。

自如官方深度復盤云原生落地全過程,云原生和DevOps實踐標準讀物,沈劍、孫玄、喬新亮、史海峰等17位專家力薦.

會額外記錄一份響應日志,即訪問會在原Nginx服務器上記錄一次,同時在Ingress服務器上也記錄一次。在遷移過程中,很難完全排查這部分統計誤差。

3.上線后的分支要不要刪除?

Aone Flow分支模型雖然靈活,但會在代碼倉庫中創建大量短生命周期的分支,有兩種分支需要進行定期清理。

第一種是發布分支。每次有特性分支從發布分支退出時,就會導致相應環境的發布分支被重新創建,如圖17-3所示。

圖片

圖17-3特性分支退出并重建發布分支


在特性分支(feature/001)退出后,我們會創建新的發布分支(release/daily/20211105),這時舊發布分支(release/daily/20211102)的生命周期便結束了,特性分支(feature/002)的后續提交均會合并到新的發布分支(release/daily/20211105)上,此時舊發布分支便可以被安全地刪除。

注意,雖然刪除發布分支一般不會導致代碼丟失,但如果在該發布分支上解決過代碼合并沖突,這部分解決合并沖突的工作需要在新的發布分支上重新進行一次。如果之前發生沖突時,是在特性分支上解決的,就無需重復進行沖突的解決了。這也是遇到分支沖突時,推薦在特性分支上解決沖突的原因。

第二種需要清理的分支是特性分支。在特性分支被發布到正式環境,并且合并到主干分支后,即可標記特性分支為可以被刪除。與發布分支重建后,老發布分支可被立刻刪除不同,我們對特性分支采取了延遲刪除的策略,每周將歷史上已經處于凍結狀態的特性分支進行清理。

為什么不立刻刪除已經上線的特性分支呢?這是因為雖然特性分支已經被合并到主干分支,但可能在上線后發現代碼存在Bug,需要進行及時修復,這時最高效的方式是在引入Bug的特性分支上進行代碼修改,并立刻進行回歸測試,然后重新上線修復。但特性分支在上線后,狀態會被標記為已凍結,無法重新上線,這時發布平臺可以從已凍結的特性分支中快速復制并得到一個新的分支,進行上線修復。如果我們在特性分支上線后,立刻刪除該特性分支,就無法做到這一點了。

責任編輯:張燕妮 來源: 中生代技術
相關推薦

2021-02-21 09:28:24

kafka系統并發量

2024-04-01 08:05:27

Go開發Java

2022-09-30 13:32:25

云原生云原生開發

2022-07-15 08:20:54

Java基礎知識

2022-04-01 12:23:03

云原生云安全

2024-05-06 00:00:00

緩存高并發數據

2023-09-11 13:33:10

2013-03-06 09:26:20

云服務云實踐精準管理

2021-07-19 10:06:30

數據治理數字化轉型CIO

2020-06-03 07:59:12

2020-04-14 10:22:50

零信任安全架構網絡安全

2025-04-29 10:17:42

2017-07-17 15:46:20

Oracle并行機制

2021-10-28 14:07:50

零信任網絡安全網絡攻擊

2023-12-14 17:34:22

Kubernetes集群K8s

2018-05-11 09:25:46

全閃存陣列實踐

2009-07-08 11:27:05

敏捷方法

2022-12-15 11:26:44

云原生

2023-04-26 11:29:58

Jenkins版本Java 11

2018-01-10 13:40:03

數據庫MySQL表設計
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日本在线中文 | 中文字幕在线不卡 | www.天天操 | 久久成人激情 | 久久精品国产99国产精品 | 成人在线精品视频 | 久久久久国产一区二区三区 | 亚洲三区在线观看 | www.99热 | 日本精品一区二区三区在线观看 | 综合久久综合久久 | 日韩一区二区三区四区五区六区 | 日本一区二区在线视频 | 福利社午夜影院 | 蜜臀网站 | 亚洲 欧美 日韩在线 | 久久久毛片 | 久久久久久久久久久91 | 国产精品日韩高清伦字幕搜索 | 99久久久久久久 | 久久久女女女女999久久 | 成人乱人乱一区二区三区软件 | 拍戏被cao翻了h承欢 | 91九色在线观看 | 久综合| 日韩精品视频一区二区三区 | 国产精品久久片 | 久久久久国产精品一区二区 | 精品三级| 欧美日韩免费在线 | 自拍偷拍亚洲欧美 | 精品一区二区三区在线播放 | 日本久草视频 | 欧美成人精品激情在线观看 | 欧美精品一区二区三区视频 | 91网站在线播放 | 中文字幕国产视频 | 浮生影院免费观看中文版 | 亚洲a在线观看 | 99久久精品国产一区二区三区 | 欧美午夜视频 |