0%

[閱讀筆記] - Week 6

使用 Open Policy Agent 來保護 Ingress 的誤用

Ref: 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 的使用方式

Container Image 的儲存挑戰

Ref: 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.
有興趣的記得點選下列原文來學習更多

Kubernetes Resource Limit/Request 誤用造成的錯誤

Ref: 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 等底層服務的運作。

DNS 5 秒 Dealy 的緣由

Ref: 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 是什麼
    之後會在跟大家分享目前一些解決方法怎麼做

NodeLocalDNS 來避免 DNS 5 秒

Ref: https://kubernetes.io/docs/tasks/administer-cluster/nodelocaldns/

今天這篇文章來分享一下對於昨天所談的 UDP Race Condition 的解法,主要是針對 Kubernetes dns 問題去探討,
一個作法就是透過 nodelocaldns 這種不同的架構,該架構下會於每個節點上部屬一個 DNS Cache,所有該節點上的 Pod 都會透過 UDP 與該 DNS Cache 溝通。 而這段網路請求因為發生於同節點上,所以 kube-proxy 產生的規則不會介入,因此那些 iptables/ipvs/conntrack 就不會影響到,就不會產生上次所說的 bug.
接者,每個節點上的 DNS cache 會透過 TCP 的方式去跟 kube-dns 來詢問最後的答案,透過 TCP 重送的方式來減緩封包遺失造成的 timeout 問題

三個加強 Kubernetes 服務穩定性的經驗

Ref: 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 給強制刪除。
    要解決這個問題可能就要從應用程式下手去看如何改善,或是透過修改 API server 來增加 GracePeroid 的數值

個人資訊

我目前於 Hiskio 平台上面有開設 Kubernetes 相關課程,歡迎有興趣的人參考並分享,裡面有我從底層到實戰中對於 Kubernetes 的各種想法

詳細可以參閱
線上課程詳細資訊: https://course.hwchiu.com/

另外,歡迎按讚加入我個人的粉絲專頁,裡面會定期分享各式各樣的文章,有的是翻譯文章,也有部分是原創文章,主要會聚焦於 CNCF 領域
https://www.facebook.com/technologynoteniu

如果有使用 Telegram 的也可以訂閱下列頻道來,裡面我會定期推播通知各類文章
https://t.me/technologynote

你的捐款將給予我文章成長的動力

Welcome to my other publishing channels