Skip to main content

· 3 min read

連結: https://medium.com/kudos-engineering/increasing-resilience-in-kubernetes-b6ddc9fecf80

今天這篇文章作者跟大家分享一些如何加強 Kubernetes 服務穩定的方式,這篇文章這邊做個簡單摘要一下 發生問題: 作者的 k8s 是基於 Google Kubernetes Service (GKE)的叢集,運作過程中有時候會發現部分節點當掉,最後導致部分的服務不能正確使用。這邊作者團隊從兩個角度出發去改善

  1. 研究為什麼節點會一直當掉,與 Google Supporte Team 來回信件最後有找到問題點
  2. 強化 Kubernetes 服務的韌性,就算有部分節點壞掉也要讓服務能夠繼續運行 ,本文主要的一些觀點也都是基於這邊發展 強化方式
  3. 修正 Deployment 的數量,並且加上 Anti-Affinity,讓這些 Deployment 的副本能夠散落到不同的節點上,避免所有 Pod 都塞到同個節點,最後該節點出問題導致 Pod 全部出問題。
  4. 所有需要被 Service 存取的服務都加上 Readess Probe 來確保這些服務都準備好後才會收到服務,避免一些請求被送過來確又不能正確處理
  5. 加入 Pre-Stop 的使用,再裡面透過 sleep 10的方式,讓 Pod 要被刪除能夠將手上的封包請求給處理完畢 (請看註解補充) 註: 我個人認為第三點其實不太需要,比較漂亮的作法應該是實作 Singal Handler 去處理 SIGTERM 的訊號,收到此訊號後就不要再接受任何 Request 並且把剩下的工作處理完畢,當然如果這部份處理的時間過長,超過預設的 GracePeriod (30sec),就會被 SIGKILL 給強制刪除。 要解決這個問題可能就要從應用程式下手去看如何改善,或是透過修改 Pod Spec 來提昇 GracePeriodTemination 的長短

· 2 min read

連結: https://www.weave.works/blog/racy-conntrack-and-dns-lookup-timeouts

今天跟大家分享一個 UDP 於 Linux Kernel 內的 Race Condition 問題。這問題我以前於 Linux Kernel 3.14 也有採過一樣的雷,但是到今日都還沒有一個很漂亮的解決方案,這邊就快速的跟大家介紹一下這個問題> 是什麼,以及跟 k8s 有什麼關係

發生前提

  1. 使用 UDP 這種沒有重送機制的協定
  2. Kernel 有開啟 conntrack 此功能

發生條件

相同的 Client 短時間內透過 UDP (也許是不同 thread) 送出兩個 UDP 封包到外面,對於 Linux Kernel 來說,會希望透過 conntrack 來追蹤每一條連線,但是底層建立的時候會有一些會有一些機制,因此當兩個封 包同時進入的時候,有可能就會因為先後順序導致第二個封包被丟棄

可能發生問題

DNS 的請求封包預設情況下會同時透過 UDP 送出 A & AAAA 兩個封包,而這兩個封包如果很巧的採到這個情況,然後你的 A 封包就沒有辦法順利解出 DNS,最後就要等五秒的 timeout 來重新發送 下偏這篇文章就是 weave works 遇到 DNS 5秒 timeout 的問題,然後仔細的將我上面所寫的總結給解釋清楚,每一個步驟發生什麼事情,什麼是 conntrack 以及暫時的 workaround 是什麼 之後會在跟大家分享目前一些解決方法怎麼做

· 3 min read

連結: https://itnext.io/how-to-set-kubernetes-resource-requests-and-limits-a-saga-to-improve-cluster-stability-and-a7b1800ecff1

今天這篇文章探討的則是 resources 底下的 request/limit 問題。 本文作者之前遇到一個非常規律的服務警告問題,花了非常多時間與步驟去查詢,最後才發現是 Pod 裡面 Resource 的設定不夠嚴謹與完善。 舉例來說, resources: limit: cpu: 1000m request: cpu: 100m 今天假設有一個服務描述,我對 cpu 的最低要求是 0.1顆,但是極限是 1顆 且有一個節點本身有 3 顆 CPU,這種情況下,我們對該服務設定多副本運行(10個). 那根據 request 的要求,10個副本頂多只需要 1 顆 cpu,所以非常輕鬆的可以將 10 個服務運行起來,但是如何今天遇到尖峰流量 ,每個 pod 都瘋狂使用 CPU會發生什麼事情? 每個副本的極限都是 1 顆,因此 10 個副本就可以衝到 10 顆 CPU..而系統上只有 3顆,這就會造成 CPU 完全不夠使用,最後導致每個應用程式都在搶 CPU 使用,如果沒有特別設定相關的 nice 值來處理,可能會造 成關鍵 process 無法回應(案例中就是kubelet)。 這案例中 limit/request = 10x,作者認為這數字太大,它覺得合理的大概是 2x ~ 5x,並且最重要的是要定期去檢視系統上資源的用量, limit 要設定的合理,如果本身有很大量需求,建議還要搭配 node select, affinity/anti-affinity 讓每個 pod 最好找到適合的配置方式,然後也要避免尖峰流量到來時,系統資源被吃光甚至影響到 kubelet/kube-proxy 等底層服務的運作。

· 3 min read

連結: https://medium.com/flant-com/cleaning-up-container-images-with-werf-ec35b5d46569

不知道大家有沒有遇過本地儲存空間滿了,再也抓不了 docker image 的慘痛經驗呢? 本文就想要探討的是遠方 Container Image 上的管理問題,隨者時間演進,愈來愈多的版本產生,那作為管理者,我們要怎麼去> 看待這些 image,放任他們無限擴張嘛? 這些資源背後都代表一個儲存空間,也就意味額外的成本開銷。 作者想要解決的問題是,如何設計一套自動機制去刪除用不到的 image tag,保留會用到的,為了解決這個問題,要先定義什麼叫做 "用得到的 image tag". 本文列舉了四種需要保留 image tag的情況 1) Production 環境正在使用的 image tag, 如果刪除了,遇到 ImagePullPolicy:Always 的情況那可真的麻煩了 2) 遇到緊急情況,應用程式需要退版,因此保留的 image tag 可不能只有當前版本,過往穩定版本也都要保留 3) 從開發角度來看需要的 image tag, 譬如我們開了一個 PR,這個 PR 有一個對應的 image tag, 再這個 PR 還沒有結束前,這個 image tag 應該都要保留讓開發者去驗證與使用 4) 最後則是特定版本號或是code name等專屬名稱 作者使用 werf 這套 k8s 建置佈署工具來幫忙,這工具除了常見的 build/deploy 外,還可以刪除遠方的 container image。 因此作者整合一套演算法,將其與 werf 整合,讓整個 CI/CD 的過程中能夠自動去產生新 的 image,並且根據需求去移除用不到的 image. 有興趣的記得點選下列原文來學習更多

· 2 min read

連結: https://www.cncf.io/blog/2020/09/29/enforce-ingress-best-practices-using-opa/

不知道大家有沒有聽過 Open Policy Agent (OPA) 這個 CNCF 專案? 有滿多專案的背後都使用基於 OPA 的語言 Rego 來描述各式各樣的 Policy,譬如可以使用 conftest 來幫你的 kubernetes yaml 檢查語意是否有符合事先設定的 Policy。 本篇文章則是跟大家分享如何使用 OPA 來針對 Ingress 資源進行相關防呆與除錯,一個最基本的範例就是如何避免有多個 Ingress 使用相同的 hostname 卻指向不同的 backend service. 過往可能都是靠人工去維護 ,確保沒有一致的名稱,但是透過 OPA 的概念我們可以再佈署 Ingress 到 Kubernetes 前先進行一次動態的比對,確保當前設定符合所有 Policy,得到所謂的 Approved 後才能夠佈署進去。 有興趣的人可以看看這篇文章,甚至學習一下 OPA 的使用方式

· 2 min read

連結: https://adam-toy.medium.com/implementing-gitops-on-kubernetes-using-k3s-rancher-vault-and-argocd-f8e770297d3a

這邊跟大家分享一篇 GitOps 實作心路歷程,這篇文章中總共使用下列工具

  1. AWS, 所有環境都基於 AWS 此 cloud provider
  2. K3S, 一套由 Rancher 開發的輕量級 Kubernetes 發行版本
  3. Rancher, 管理 K3S 介面
  4. Cert-Manager, 與 Let's Encrypt 連動,管理相關憑證
  5. Vault, Secret 管理工具
  6. ArgoCD GitOps 使用工具,連動 Git Repo 與 K8s
  7. Terraform, IaaC 的一種工具 這篇文章從頭開始介紹如何整合上述工具,並且完成一個簡易的範例,透過這些範例也讓你理解每個元件對應的功能,如何使用,共重要的是從一個大範圍的視角來看,這些元件的地位,更可以幫助你瞭解整體架構 有興趣的可以閱讀全文

· 2 min read

連結: https://www.dex.dev/dex-videos/development-clusters

不知道大家第一次接觸 kubernetes 的時候都是使用哪套解決方案來打造你的 K8s 叢集? 亦或是作為一個開發者,你平常都怎麼架設 K8s 來本地測試? 這篇文章提到了作為一個 Local Kubernetes Cluster 幾個選擇,並且點出了三個需要解決的問題

  1. Container Registry, 作為一個開發環境,應該不會想要每次測試都要將 Container Image 給推到遠方,譬如 dockerHub, Quay,這樣整體效率低落
  2. Builder, 如何有效率的幫忙建置你的應用程式,並且與 Kubernete 整合,讓開發者可以更專心於本地開發,而不要擔心太多 k8s 之間的設定 https://www.dex.dev/dex-videos/development-clusters
  3. Runtime, 底層使用哪套 Container Runtime, 譬如 docker/containerd/cri-o 註: 我個人對第三點其實沒太多感覺,不覺得本地測試這個會影響太多 後面列舉了當前知名的相關專案,譬如 KIND, K3D, MicroK8S, Minikube 以及 Docker for desktop. 並且簡單的比較了一下這些本地開發的差異。 不知道大家平常本地開發時,都會用哪一套? 我個人是比較常使用 KIND 來測試,畢竟輕量化且同時支援多節點,環境也乾淨,測試起來也方便。

· 2 min read

連結: https://blog.cloudflare.com/the-sad-state-of-linux-socket-balancing/

今天要來跟大家分享一個單一節點如何提高應用程式吞吐量與服務能力的方式 這個方式主要探討的是應用程式對於網路連線的 I/O 模型,試想一個常見的使用範例。 一個主要的 Process 會去聽取一個固定的 port number (ex port 80),並且通知後面眾多的 worker 來幫忙處理這些封包連線,而這些 worker 的工作就是處理連線。 整個架構中是一個 1 v.s N 的狀況, 一個負責 Listen ,N個負責處理連線內容 而今天要分享的則是想要讓架構變成 N v.s N 的狀況, 會有 N 個 Process, 每個 Process 配上一個 Worker。 而這 N個 process 同時共享一樣的 Port (ex, port 80) 這種情況下可以減少多個 worker 共享一個 listen socket 時的各種保護機制,取而代之的則是每個 listen socket 配上一個專屬的 worker 來處理。 要達成這樣的架構非常簡單,只要透過 SO_REUSEPORT 這個 socket option 告 訴 Kernel 當前這個 PORT 可以重複使用。 當封包送到 kernel 後則是由 kernel 幫你分配封包到所有使用相同地址的 Listen Socket (Process) 根據 nginx 官方文章的測試,這種架構下對於 RPS (Request per second) 有顯著的提升,有興趣的可以看看下列兩篇文章