今天這篇文章我個人滿喜歡的,整個文章內容就是為了一個主題去探討,到底 Pod 是如何獲得 IP 地址的。

作者開頭闡述了一個常見的情況,就是 Kubernetes 架構龐大,元件複雜,每次談到所謂的網路模型的時候,大家都攘攘上口 CNI, CNI, CNI,但是又有多少人能夠清楚地描述整個 CNI 的運作過程,到底什麼時間點被呼叫,每次的呼叫做了什麼事情。

因此作者特別撰寫了這篇文章,打算從 CRI,CNI 兩個元件去按討,到底一個 Pod 起來到取得 IP 的過程中這些元件會如何互動

為了解釋這個過程,作者分別使用 Containerd 以及 Flannel 作為其 CRI/CNI 的解決方案,從過程中一步一步去解釋到底 Flannel 大概怎麼運作,IP 怎麼取得。

這邊要提醒的是,CNI 玩法百百種,Flannel 的做法是其中一種選擇,其他的 CNI 會有別的方式來設定 IP 地址,但是其源頭如何與 CRI 互動這部分是不會改變的。我認為大家有時間都要好好的看這篇文章,去學習一下到底底層元件的運作原理與流程,都能夠幫助自己更佳理解 Kubernetes 這龐大的怪獸

https://medium.com/cloud-belivers/how-kubernetes-pod-obtains-ip-address-3982ac9697b1
這篇文章探討的是 kubectl 於 1.18 對於 kubectl run/kubectl create 改動所造成的影響,這個影響我認為層面不會太大,但是對於習慣用 kubectl run 的人來是一個滿大的困擾,簡單來說就是移除了一些用法,但是卻沒有任何替代解決方案可以取代。

kubectl v1.18 以前,你有至少三種方法可以部署一個 Deployment 到 Kubernetes 中
1. 撰寫程式並且透過相關函式庫直接戳 kubernetes API server 來創建資源
2. 手動撰寫 YAML 檔案,透過 kubectl apply -f 等類似方式創建
3. 透過 kubectl run (e.g kubectl run nginx-1 --image=nginx --port=80 --restart=Always) 此方式來動態創建一個 deployment.

基於各種維護與管理考量,任何的生產環境都會基於 (1)/(2) 這類型可以控管的方式來部署應用程式,基本上不會使用 (3) 這種方式來創建,但是 (3) 某些情況下滿好用的,譬如

1. 新手測試,想要快速起一個 deployment 測試,但是卻不知道去哪邊找一個 deployment Yaml 的範例(Deployment YAML 本身結構多層,人腦難以記住全貌)
2. 一些 OSS 專案想要提供使用者一些範例去操作,會提供 kubectl run 的指令來創建資源

作者還表示可以將 (2) + (3) 給結合,譬如透過下列方式可以產生一個 YAML 內容
kubectl run nginx-1 --image=nginx:1.14.2 --port=80 \
    --restart=Always -o yaml --dry-run
    
接者透過這個範例去創建與修改來達到 (2) 的做法

不過這一切都隨者 kubectl v1.18 的改變而壞光了,因為 v1.18 後 kubectl run 不再支援 deployment 的創建,退而求其次要求使用者透過 kubectl create 去創建資源,但是其支援的參數比過往還要少,所以沒有辦法透過 kubectl create 取代 kubectl run 的所有用法。

詳細的一些內容與比較可以參閱全文


https://alexellisuk.medium.com/kubernetes-1-18-broke-kubectl-run-heres-what-to-do-about-it-2a88e5fb389a

PR: https://github.com/kubernetes/kubernetes/pull/87077
PR: https://github.com/kubernetes/kubectl/issues/898
今天的文章不是一個技術文,反而是探討身為一個軟體工程師,該怎麼撰寫相關的技術文件

鑑於 WFH (Work From Hoem) 習慣的興起,人與人面對面的溝通減少,這意味即時的訊息傳遞變少了,取而代之的是非同步的訊息傳遞,簡單來說就是技術文件。

好的技術文件能夠讓需要的人快速找到問題,解決疑惑,但是一個好的技術文件到底該怎麼寫,這部分其實非常困難,並不是向程式碼一樣可以 copy&paste 馬上看到成果的,反而是需要時間練習,將整個過程與思路消化起來,用自己習慣的語言與形式將其撰寫出來。

首先,作者非常推崇由 Google 撰寫的系列文章,Tech Writing Course,整個課程內容不到兩小時,從不同章節來跟大家分享如何撰寫技術文章

接者撰寫技術文章時,作者個人是喜歡 divio 這個平台,不過更重要的則是其推薦的分類模式,根據內容分類成四大項

1. Tutorials - 學習導向
2. How-To Guides - 問題解決導向
3. Explanation - 深度理解導向
4. Reference - 資運分享導向

Google: https://developers.google.com/tech-writing
Divio: https://www.divio.com/

最後寫作語法方面,作者認為寫出一個能夠被有效搜尋的文章是非常重要的,譬如透過 word 等方式上傳檔案到系統中反而是一個不利於搜尋的方式。
取而代之的是,作者認為可以採用 Markdown 類似的語法作為基礎去撰寫文章,這種方式對於維護與撰寫都相對容易

今天有任何 Diagrams 的畫圖需求,可以考慮使用 Mermaid 這套解決方案,對於 GitLab/Azure 的使用者來說,已經內建其中。 GitHub/Atlassian Confluence 則有相關的 Plugin 可以安裝使用

最後則是文章的樣版內容,針對特定的文章格式,已經有不少的範本可以參考,透過這些範本可以更清楚的去描述你的內容,讓整體文章看起來更佳簡潔與流暢

1. Software Architecture Review Template
2. Architecture Decision Record Template
3. Incident Postmortem Template
4. DevOps Runbook
5. Decision Template
6. Writing Guidelines
7. OKR Template
8. Etc.

有興趣的點選原文學習更多
https://medium.com/better-programming/best-practices-when-documenting-your-code-for-software-engineers-941f0897aa0
本篇不是一個技術文章,而是一個 DevOps 招募主管的經驗談,隨者 DevOps 需求提升,愈來愈多人開始轉往這個方向。對於作者來說,要如何從茫茫大海中挑到正確的人選其實並不容易。
作者的公司會對所有的招募人員有個第一次的技術訪談,該技術訪談著重的都是一些基本技能,是一些第一天上工可能會用到的知識與能力,譬如 TCP/IP 網路概念, Linux 工具使用,儲存相關概念等。然而另作者感到灰心的是,很多人的履歷寫得洋洋灑灑非常厲害,什麼東西都有碰過都會,但是實際上去問對方該技術是什麼該技術什麼怎麼做,都沒有辦法準確有信心的回答,這樣反而會讓面試官覺得該履歷是個打腫臉充胖子的行為。

因此本文後續作者就整理了一些關於 DevOps 面試的心得與經驗,譬如說

1. 不要造假履歷,履歷上面寫的東西都要能夠精準回答到基本等級,不論是程式語言或是 docker/kubernetes,只要敢寫上去,就要有信心去回答這些問題。
2. 對於所面試職位所需要的技能要真的會,舉例來說面試一個要使用 PostgresQL 的職位,結果連該技術都沒有用過,這樣其實真的會浪費彼此時間
3. 誠實面對所有問題,不知道的問題就勇敢的說不知道,瞎扯淡什麼太多的其實面試官都知道。

原文中還有不少段落,這邊就不一一列出,但是我認為本文真的算滿忠肯的,畢竟現在 CNCF 生態系這麼龐大,很多時候沒有一個扎實的基本功是很難快速地去學習不同領域的技術並且將其整合再一起,更不用說當遇到問題時,該如何除錯了。


https://lukeshaughnessy.medium.com/im-a-devops-hiring-manager-here-s-how-to-crack-my-technical-interviews-part-1-b53885e08655
談到如何包裝與客製化 Kubernetes 應用程式,Helm/Kustomize 我認為是當前最容易被拿來比較的兩大開源專案。
我個人認為這兩者的走向截然不同,光如何客製化就是採取不同的方式,一個主打 Template,一個則是 Template-free,此外 Helm 本身需要額外安裝 CLI 才可以使用,而 Kustomize 目前則是 Kubectl 該指令已經內建,因此使用上也不需要額外安裝任何指令即可

這篇文章是一個 Kustomize 的教學文,主要是用來介紹到底 Kustomize 是如何透過 template-free 的方式讓維運人員可以客製化其部署應用程式,如果本身對於 Kustomize 還不是很熟悉但是又想要理解的,推薦可以快速地看下這篇文章,會對 Kustomize 有個初步理解。


https://pavan1999-kumar.medium.com/introduction-to-kustomize-97f990dc2f44
不知道有多少人曾經想要挖掘過 Kubernetes 的原始碼?
本篇作者跟大家分享其閱讀 Kubernetes source code 的經驗,Kubernetes 基本上大部分的程式碼都是基於 golang 去撰寫的,能夠參透其中其實對於 golang 的一些用法與寫法會有很大的增廣見聞。
無法保證 Kubernetes 的寫法一定是最棒最好,但是我認為多看不同的原始碼,其實對於自己寫程式的能力與想法都是會有所長進。
此外如果已經有一些語言與框架的基礎,對於閱讀這些大型專案的程式碼都會有所幫助,譬如假如你熟悉 COBRA 這個 CLI 的框架,那你看 kubernetes 各種 CMD 都會覺得輕切,覺得閱讀起來輕鬆順手。

總之本篇文章就是作者簡介自己閱讀原始碼過程的經過,比較偏向給初學者探索的,讓初學者有方向可以去探索,一免一開始看到太龐大的專案然後無所適從,或是選擇了一個不會收斂的方向導致閱讀起來很沒有成就感。


https://medium.com/cloudlego/want-to-understand-kubernetes-source-code-this-is-how-you-can-start-exploring-6eea25e50a69
今天這篇是一個關於 Prometheus 的教學文,隨者 Kubernetes 架設與維運的要求日漸提升,可觀測性的重要程度也一直不斷上升,其包含三大面向
Monitoring,Logging 以及 Tracing。
而 Monitoring 中最知名的開源專案組合包就是 Prometheus 以及 Grafana。因此本文作者基於 GitLab Managemend Kubernetes 的前提下,跟大家分享如何創建 Prometheus 相關服務,並且如何把系統上運行的資訊與其整合。

如果本身對於 Prometheus 只有聽過但是還沒有實際玩過的人,不仿可以參考本文學習一下 Prometheus 的概念與想法。

https://medium.com/@thisiskj/lets-explore-prometheus-5f7d790338ac
作者今天想要針對自己的應用程式準備一個滿足下列的條件的運行環境

1. 該環境所需要的金錢成本盡可能地低
2. 能夠針對流量而自動地去 scale out/in 整個環境
3. API 後端應用程式是否能夠有 self healing 的能力

考量過後,作者考慮使用 Kubernetes 作為其運作平台,因此開始了成本探險之旅,想瞭解一個最便宜的 Kubernetes 服務可以多少錢。

為了滿足作者的應用程式,作者針對該 k8s 環境考慮了下列五個方向

1. K8s 的 Control Plane
2. 運作的 VM
3. Load Balancer
4. Disk 大小
5. Container Registry

作者針對三大公有雲,分別是 Azure/GCP/AWS 來進行分析,比較上述五大類型下分別的每個月成本多少

結果因為 Aks 的 Control Plane 目前不用錢,因此與其他兩家比起來價錢落差非常大。
考慮五個元件後, Azure/GCP/AWS 每個月最低價格為 $38.40 $102.75 $107.58

這也是為什麼作者的標題是用每天一美元的價格來運行一個 kubernetes cluster。

本文最有趣的應該是相同元件下,不同公有雲之間的比較與價目表,算是幫助大家去挖掘與比較,有興趣的可以參考原文

https://georgepaw.medium.com/how-to-run-the-cheapest-kubernetes-cluster-at-1-per-day-9287abb90cee
Kubernetes 中最常使用的工作單位就是 Deployment,而 Deployment 採用的更新策略是 RollingUpdate,意味者當更新發生時,會先產生出 n 個新版本的 Pod,並且透過 Readiness 去確認該 Pod 目前可視為正常工作後,就會移除先前版本的 n 個 Pod。

因此本文想要探討的是,如果你想要使用不同的更新策略,你可以怎麼做?

該文章的架構是基於 Argo RollOuts 這個工具來如何達到金絲雀部署與藍綠部署

1. Argo RollOut 的安裝非常簡單,主要操作都是透過 CRD 來完成
2. 對於已經現存的 Deployment 物件,可以非常輕鬆的轉換到 Argo RollOut 的 CRD

#金絲雀部署
金絲雀部署的狀況下,我們會希望能夠把部分的流量先行導入到新的應用程式,接者逐漸調高比例直到最後全面切換過去。這部分可以想像成類似下列的步驟

假設本來有10個舊有應用程式 v1, 現在要升級成 v2.
1. 先部署兩個新版本的應用程式,直到 Readiness 完成後,移除舊有的兩個應用程式
2. 部署人員確認目前狀況良好,決定繼續往下推動,再次部署兩個新的
3. 部署人員再次確認,依序往下部署新的應用程式直到十個都全面替換完成

而上述的過程再 Argo RollOut 會依賴兩個部分完成
1. Yaml 中定義這些步驟
2. 透過 kubectl argo (Plugin) 的方式告訴 Controller 請繼續往下

譬如下列檔案定義步驟
```
  strategy:
    canary:
      steps:
      - setWeight: 20
      - pause: {}
      - setWeight: 40
      - pause: {duration: 10}
      - setWeight: 60
      - pause: {duration: 10}
      - setWeight: 80
      - pause: {duration: 10}
```
維運人員透過指令要求繼續往下執行

文章後續還有探討如何用 Argo RollOut 來完成藍綠部署,同時部署兩個完整群體,並且透過切換 Service 來指向不同版本的群體

對於想要嘗試不同更新策略的玩家,可以詳細閱讀本文並且玩轉看看 Argo RollOut。


https://medium.com/@ptran32/control-your-kubernetes-deployment-with-argo-rollouts-adb54c4e9b7d
不知道作為服務供應者的各位如果內部服務需要維護時,都會如何對外公告之後會有一個維護時間?

今天這篇文章來自於 env0 這間產品的親身體用經驗,當今天產品不論是前端或是後端需要有一個維護時間去公告來告訴使用者,這個解決方案該如何有系統性地去設計與實作。

作者希望該解決方案可以滿足
1. 能夠透過 IaC 的架構來完成,因為目前整個產品都是基於 IaC 來設定
2. 能夠輕鬆的於工作模式與維護模式中來回切換,每次的切換都能夠自動化完成,盡量減少人為操作
3. 該解決方案盡量能夠靈活彈性,針對不同雲端廠商都要能夠適用,避免未來轉移時整個方案要砍掉重練
4. 希望本身要能夠提供後門供開發人員去進行修復與測試
5. 順利地告知使用者我們正在維護

由於該公司所有的產品目前都是基於 AWS 架構下,因此作者後來想出了以下的系統設計

1. 使用 Github Pages 存放網頁,該網頁用來描述當前處於維護模式
2. 不同模式之間的切換決定透過 DNS 的方式來處理,當處於維修模式時,相關的連結都會指向 Github Pages。
3. 透過 Route53 以及 CloudFront(CDN) 的方式來設定相關操作
4. 透過產品本來的機制,當一切自動化完成後會自動通知使用者當前屬於維護模式

最後整個系統操作流程如下
1. 透過 Terraform 去創建 AWS 所需資源,包含 Route53, CloudFront
2. 透過 Terraform 去創建 GitHub Page, 這部分因為 Provider 沒有完全符合需求,還需要額外的 scripts 直接跟 Github API 溝通
3. Terraform 執行時,會透過變數來切換當前是屬於工作模式還是維護模式
4. 如果是維護模式,就會修改 Route53, 將 CNAME 給指向 Github Page,因此使用者去訪問時都會導向 Github Page
5. 如果是工作模式,就會修改 Route53, 將 CNAME 給指向 CloudFront 內的 IP,因此使用者訪問時都會導向真正的產品


如果團隊本身也有這種需求,希望能夠將公告/維護等相關操作也都整合到日常工作流中,也許可以參考這種思路去思考,該如何自動化一切設定,讓所有的操作都盡可能的減少人為介入

https://medium.com/env0/building-a-maintenance-mode-with-terraform-and-github-pages-3dadd009f7bd
這篇文章要介紹的是 Jenkins Operator 這個有趣的應用程式,Operator 的概念先前有不少文章再探討其架構與意義,因此本篇文章會專注於 Jenkins Operator 這個應用程式能夠為 Jenkins 的環境與應用帶來什麼樣的變化。

首先本文開始前,要先準備三個東西
1. Kubernetes Cluster
2. Helm 安裝環境
3. 一個放有你 Jenkins pipeline 與 script 的 SCM(Source Code Management),通常都是 Git

接下來作者透過 Helm 安裝了 Jenkins Operator 該控制器到 Kubernetes 內並且準備了相關的 CRD 用來控制 Jenkins.

範例中的 CRD 主要會做兩件事情
1. 設定 Jenkins 本身,包含要安裝哪些 Plugin 等
2. SeedJobs: 可以將外部 SCM 內所描述的 Job 內容給直接設定到 Jenkins 內

當該 CRD 給套用到 Kubernetes 後,該 Jenkins Operator 就會幫忙初始化整個 Jenkins 以及相關的 Plugin。最後將 SeedJobs 內所描述的資訊給整合到 Jenkins 中來創建相關的 Job.

透過這整個 CRD 操作帶來的好處我認為有
1. 整個過程盡量減少手動操作,全部都依賴 Yaml 與 Pipeline 等程式碼的方式去維護
2. 與 Kubernetes 整合,對於熟悉 Kubernetes 的操作人員來說,學習過程不會太痛苦。
3. 把 Jenkins 變得稍微簡單一些,一些繁瑣過程讓 Jenkins Operator 去操作

我自己看完後,目前看到的壞處有
1. Jenkins 功能太多,生態系太複雜,我懷疑這種 Operaotr 只是一時的專案,沒有一直保持更新的話一定會有些功能終究還是要手動操作
2. 設定的內容我認為不如 Jenkins 生態系中的 Configuration as Code 這套 Plugin 來的專業與強大
3. Job 的設定部分我個人還是偏好使用 Jenkins Job Builder 這套基於 YAML 的解決方案來管理與定義全部

結論:
1. 我個人是當作一個新東西看看,但是不會有想要嘗試的慾望,因為覺得事情其實沒有變得簡單多少,甚至擔心引入一個半成品,導致多一個東西要維護..

https://medium.com/swlh/introduction-to-jenkins-operator-f4cb7ebc2e0b
#備份 #Velero #etcd

今天這篇文章是作者分享其維運 Kubernetes 叢集中關於備份還原的經驗
對於 Kubernetes 來說,其控制平面由幾大元件組成,分別是 API Server, Controller, Scheduler 以及 ETCD。其中的 Controller 更是整個叢集狀態維護的推手,使用者透過各種方式,不論是 API,Yaml 或是其他方式來新增資源,其實背後的深層目的都是告訴 Controller,我想要達到什麼狀態,而 Controller 透過永無止盡的迴圈與檢查,確保叢集當前的狀態可以符合使用者預期的狀態。

作者工作的經驗中,遇到了想要對 Kubernetes 進行備份與還原的需求,因此思考如何將所有運行狀態的資源狀態給取出,並且當還原時可以將前述備份的資料都寫回去。

作者這邊採用的是一個名為 Velero 的開源工具,透過該工具去還原與備份 Kubernetes ETCD 的資料,並且可以將資料給同步到遠方的儲存空間,譬如 S3, GCS 等

如果對於 ETCD 的備份與還原有興趣的人,可以參考這篇文章,看看別人用 Velero 這個工具來處理,同時也可以想想目前團隊中有沒有這方面的解決方案


https://adrafiq-52.medium.com/kubernetes-backup-and-disaster-recovery-88d6cb8c5bf7
#ingress #network #traefikv2

今天這篇文章是一個教學文,主要是從頭開始搭建一個基於 Traefik-v2 Ingress Controller 的分享文。
熟悉 Kubernetes 的人會知道關於網路存取這一塊, Kubernetes 內部提供了兩大類型的抽象操作,分別是 Service 以及 Ingress。
Service 內部又有不同類型,譬如 ClusterIP, NodePort, LoadBalancer 以及 Headless,而部分的實作也可以分成 iptables 或是 ipvs 等不同技術。
而 Ingress 則有點不同,Kubernetes 本身則不控管與維護任何實作面的操作,只定義相關的介面,這意味所有的 Ingress 的解決方案都需要自己實作相關的 Controoler,去觀察資源的改變並作出相對應的動作。

本篇文章內容不會太艱深,從如何安裝 Traefik 開始介紹,有哪一些 kubernetes 的資源需要被安裝,而這些資源代表什麼功能提起,接者用幾個小範例去介紹如何使用 Tarefik 架構下的 IngressRoute 該如何使用。

對 Ingress 不熟的人還是可以參考參考,當作一個學習

https://pete8s.medium.com/getting-started-with-traefik-v2-on-kubernetes-c23504389f4c
本篇文章作者認為透過 Kubernetes Operator 的設計與精神,是有辦法達到夢寐以求中的 Zero-touch Ops,甚至發展到所謂的 AIOps,維運人員盡可能地減少主動去管理應用程式的部署。

一開始探討到微服務架構與 DevOps 文化的興起,愈來愈多的叢集與資源需要管理,但是如果今天應用程式本身難以管理的話,維運人員則必須要花費大量的精力與時間來部署這些應用程式,這無疑是種本末倒置的行為。

本文一開始作者先快速地複習什麼是 Operator,基本上可以當作是 k8s controller 的延伸版本,畢竟 K8s controller 其運作原理也是透過一個無止盡的迴圈,根據使用者輸入事先定義的好的資源格式,來確保當前叢集內的運行狀態有符合需求。Operator 基於這個概念上,讓使用者可以使用 CRD 這種自定義的格式來定義自己的資源,不單純只是所謂的 deployment/pod/service 等,可以是更符合應用程式需求的抽象資源,譬如 GitRepo, Network, PrometheusService 等

文章內還有更多關於 Operator 的介紹,包含如何透過 SDK 來撰寫開發一個 Operator,有興趣瞭解的
不可錯過。

文章後半部在探討關於 AIOPs 如何達成 Zero-Touch Ops 的願景,文中先以一張圖片來解釋 AIOps 的架構,最後提到如何將 AIOPs 與 Operator 的架構整合為一,該架構中整合了不少常見服務來滿足不同面向的要求,譬如 Grafana, Prometheus, ServiceMesh/istio, Ansible 等。



https://medium.com/faun/kubernetes-operators-to-realize-the-dream-of-zero-touch-ops-5bc8c3e5e11b
從本篇開始,接下來將幫大家介紹 k8s.af 裡面關於各種 Kubernetes 維運上遇到的各種問題。

本篇主題: 為什麼我們要在兩小時內從 fluent-bit 轉換到 fluentd
症狀: 某日下午,開發者通知疑似某些生產環境上面的日誌出現問題,沒有看到任何更新。

作者的團隊已經使用 fluent-bit 來轉發應用程式日誌已經三年多了,過去的經驗表示 fluent-bit 表現良好,有個良好的效能,設定也相對簡單。

問題發生時,首先觀察 fluent-bit 相關的資訊,從中得到關於 ElasticSearch 拒絕接受相關請求的錯誤訊息,最後輾轉從 ElasticSearch 去解決,再也沒有任何錯誤訊息出現了。但是實際的問題還是存在,該看到的日式

然而其實主體問題還在,日誌還是沒有被收集起來送出去,因此這時候團隊就開始思考該怎麼做。其中嘗試過升級降級已經修改不同參數,但是都沒有辦法解決問題,最後於 GitHub 上面找到一個相關 issue(https://github.com/fluent/fluent-bit/issues/2416),問題情況一樣類似而且沒有解決方法,所以幫助不大,但是至少知道自己並不孤單。

一切都明瞭後,作者團隊知道沒有辦法針對 fluent-bit 的這個錯誤去修改,因此開始思考其他的替代方案,最後選擇使用了 fluentd 來替代。整個抽換過程是緩慢的,先從出問題的節點開始,慢慢的部署 fluentd 並且移除 fluent-bit,其中還透過了 node Affinity 以及 anti-affinity 來幫忙調整部署的選擇。 

最後有興趣的話建議點選原文,幫自己增廣見聞一下

原文: https://prometheuskube.com/why-we-switched-from-fluent-bit-to-fluentd-in-2-hours
Kubernetes 維運經驗分享篇
主題: 解除 CPU 來提升服務效能
關鍵字: CPU Limit, CPU throtting, 高延遲性

本篇文章是探討的是使用 CPU Limit 的經驗,熟悉這個機制的讀者應該都知道能夠這個設定來確保每個 Container 能夠使用的 CPU 數量,同時也可以透過這個機制去確保每個節點上都有足夠的 CPU 資源供原生服務,譬如 kubelet, kubeproxy 來使用。

本篇作者團隊要分享的是設定 CPU Limit 卻導致效能更差的故事,當 CPU 設定為 800ms 的時候,卻發現實際運行的效能最高只有 200ms,反覆查找卻得到是 Linux Kernel 的臭蟲導致。

一個直接的做法就是針對那些本來就沒有過高 CPU 使用量服務取消其 CPU Limit,作者於文章中也探討了一些機制要如何保護與應對這些被移除 CPU 限制的服務。

這個臭蟲於 Linux Kernel 4.19 後已經修復,但是要注意你使用的發行版本是否有有包含這個修復,作者也於文章中列出一些已知的發行版本修復狀況

原文: https://erickhun.com/posts/kubernetes-faster-services-no-cpu-limits/
最近都在跟網路通靈,不免最後又來跟 rp_filter 打交道,因此今天這篇文章來幫大家複習一下 rp_filter 這個系統參數

設定位置: /proc/sys/net/ipv4/conf/$iface/rp_filter

介紹:
rp_filter 全名為 Reverse Path Filtering,是一個 Linux Kernel 用來過濾封包的機制。當封包到達一個網卡時, kernel 會根據該封包的 source IP 去進行反向(Reverse Path)檢查,當系統檢查當前的 routing table 確認該 source IP 是可以轉發的,且轉發出去的網卡與收到的網卡是一致時,封包就可以正確地接收,反之則會丟棄。

目前常見系統上 rp_filter 有三種數值可以設定
0: 請關閉 rp_filter 的功能,請不要對封包的來源進行檢查,一切都收起來。
1: 如前段所述,嚴格的針對 source IP 進行反向查找
2: (1)的不嚴格版本,一樣會對 source IP 進行反向查找,但是反向的網卡不需要與收到的網卡一致,只要確認該封包可以出去即可

大部分的情況下不建議關閉 rp_filter, rp_filter 可以用來驗證 source IP 是否合法,對於抵擋 Spoffing IP 這類型的攻擊可以起到一定的效用。
此外如果有安裝 Calico CNI 的也要注意一下這個設定,因為這種基於 routing 的 CNI 解決方式很容易會因為 rp_fitler 導致功能不正常。

https://www.theurbanpenguin.com/rp_filter-and-lpic-3-linux-security/
關鍵字: EKS, AWS CNI Plugin
影響: 連結服務時頻繁地看到連線失敗

今天這個案例是作者團隊想要嘗試從 kops 轉移到 EKS 上遇到的問題,最初的症狀是整個平台運作起來非常慢。作者提到最初想要轉移到 EKS 上的一個理由就是其擁有更好的網路效能,然而當前的問題症狀很像網路問題,因此團隊最後直接諮詢 AWS 支援來尋求網路專家的支援。

再錄製封包之後終於觀察到了一些現況。所有叢集內的網路流量都運作得非常良好沒有問題,然而外界與叢集內的封包則沒有如此順利,觀察到大量的 TCP 重送封包。

中間與 AWS 來來回回長達一個月,協助錄製各種封包但是還是沒有解決問題,最後作者觀察到一些現象,有些節點會有存取變慢的問題,但是上面的Pod卻沒有事情。而有些則是節點本身沒有問題,但是上面的Pod卻有問題。

後面又有一次的視訊多人會議,中間弄弄整個網路全壞光了,這時候聽從 AWS 的建議開啟了一個 AWS_VPC_K8S_CNI_EXTERNALSNAT=true 的設定,然後網路就全面好了..

文章最後介紹一下整個事情的發生的原因,以及為什麼開啟 AWS_VPC_K8S_CNI_EXTERNALSNAT=true 就一切沒有問題了,有興趣的可以點選全文研究研究

https://yashmehrotra.com/post/2020-03-16-case-of-missing-packet/
關鍵字: conntrack, DNS, CoreDNS-autoscaler
影響: 部分正式生產環境崩壞

整個問題是簡單來說就是正式叢集再不預期的情況下,發生了 DNS 的問題,導致內部服務大概有 15000 筆 query 失敗。造成錯誤的原因是因為 kube-proxy 沒有順利地去移除過期的 conntrack,導致有些 DNS封包被導向到一個已經不存在的Pod。

這個問題的發生前提是,因為某些情境的發生,譬如系統負載過低, CoreDNS-autoscaler 就被觸發起來,將運行的 Pod 數量從三個降為兩個。所以系統上能夠處理 DNS 的Pod剩下兩個,但是如果有節點上的 conntrack 沒有順利清理乾淨,導致所有的封包都被導向那個被刪除的 CoreDNS,問題就這樣發生了。

詳細的過程跟一些學習重點可以參考原文

註:想要掌握 kubernetes 網路,對於 conntrack 的認識絕對不可以少,有太多太多的問題都跟 conntrack 有關,從 race condition, max 等眾多選項都牽扯所有運行的封包。有時間的話一定要好好的複習一下 conntrack 的概念

https://medium.com/preply-engineering/dns-postmortem-e169efd45afd
關鍵字: GKE, CPU Limit, CPU throttling
影響: 服務出現高延遲性,甚至出現錯誤

總結: 作者推薦關閉 Kubernetes 內任何 CPU Limit 的功能(或是從 kubelet 關閉 CFS quota)直到節點上的系統都已經修復 CFS 的相關問題,這個問題會導致不必要的 CPU throttling 並可能導致應用程式短暫時間卡住不回應。

這篇文章內容非常豐富,開頭介紹 container & kubernetes 的基本概念,接下來探討到底 CPU request/limit 是如何實作的,並且透過一個範例來介紹為什麼 kernel bug 會導致整個應用程式卡住


原文下方還有列出各種相關連結,包含 kernel 內的相關文件以及 kubernetes 內探討這個問題的 issue。

https://medium.com/omio-engineering/cpu-limits-and-aggressive-throttling-in-kubernetes-c5b20bd8a718
關鍵字: KIAM, DNS, AWS IAM, latency
影響: 存取服務會花上高達十倍的延遲時間

這篇文章準確的說,問題其實跟 Kubernetes 本身關係不大,反而是遷移 Kubernetes 到系統中常見的溝通問題。作者的標題是真真實實來自 Dev Team 的回饋,當應用程式搬移到 kubernetes 後得到的效果不如預期,也許最後不是 kubernetes 的問題,但是 SRE/DevOps 還是得必須針對這些質疑去探討,找出最後真正的原因。

作者團隊當初要將一個微服務從 EC2 上給整合到 Kubernetes內,卻發現存取該服務的延遲性相對於直接部署到 EC2 上大幅度上升十倍。根據團隊的調查,EC2 的應用程式只需要 20ms 左右回覆請求,而 kubernetes 版本則需要 200ms 左右。

最後來來回回除錯找到問題根源,主要是 AWS Jave SDK 裏面的用法於不同的情境下會有不同的效果。其於 Kubernetes 下會發生每個 request 都強迫去刷新當前的 certificate 資訊,因此每個 request 都還會額外發送一個新的 request 去取得 certificate。

基本上整個問題都跟 Kubernetes 的架構無關,單純是 AWS 架構的用法,如果你有使用 KIAM 相關的服務,同時也有使用 AWS Java SDK,可以參考本篇的問題

https://srvaroa.github.io/kubernetes/migration/latency/dns/java/aws/microservices/2019/10/22/kubernetes-added-a-0-to-my-latency.html