不常見但是可以幫助開發效率的 Git 指令與功能
https://martinheinz.dev/blog/109


本篇文章介紹一些自從 2010 後所被開發出來的 Git 指令。
大部分開發者慣用的指令幾乎都是都是早期版本就有的指令,包含 chcckout, stash 等,而隨者 git 後期的開發,實際上有愈來愈多的指令與功能被開發出來改善效率,譬如文章中介紹的
1. switch
2. restore
3. sparse-checkout
4. worktree
5. bisect

這些指令都有適合的情境,譬如同時有多個 branch 需要開發,或是一個 monorepo 的檔案過大,每次 checkout 都要花費大量時間等,因此花一些時間研究一下這些新的指令說不定可以加速日常工作流程
大名鼎鼎的 Brendan Gregg 最近發佈了一篇文章提及系統上應該要有的除錯工具,從 CPU, Memory, Disk 到 Network 應有盡有

這些工具可以從下面的 package 安裝,文章內有更詳細每個 package 會提供哪些工具,以及大概可以處理什麼樣的資訊

procps, util-linux, sysstat, iproute2, numactl tcpdump, linux-tools-common, bpfcc-tools, bpftrace, trace-cmd, nicstat, ethtool, tiptop, cpuid, msr-tools


https://www.brendangregg.com/blog/2024-03-24/linux-crisis-tools.html
Kubernetes 內各種 GC 介紹

https://medium.com/overcast-blog/kubernetes-garbage-collection-a-practical-guide-22a5c7125257


寫應用程式的都聽過 Garbage Collection(GC) 的行為,而 Kubernetes 也是有類似這種行為的操作,目的都是清除用不到的資源,避免系統資源超載甚至影響整體效能。
文章提及三種相關的 GC,分別是
1. Container Image Garbage Collection (節點上的 Container Image 用量超過硬碟用量,需要 GC 移除以免之後踩到 Disk Pressue 導致 Node NotReady)
2. Evicted Pod Garbage Collection (觸發 Evicted 而被移動的 Pod 雖然會消失,但是對 etcd 來說還是會有一個狀態為 evicted 狀態的 Pod,可以從 etcd 中釋放用不到的資源)
3. Orphaned Resource Garbage Collection (Kubernetes 內的狀態很多有相關依賴性,有些會透過 owner reference 來連結這些物件,某些情況下可能資源刪除沒有完整,導致有一些資源其實已經用不到,但是當初其老爸被刪除的時候沒有把這些產物給一起刪除,最後就是 etcd 記錄了一些用不到的物件)

除了概念介紹外,也有分別介紹每個類別的實作方式。
Kubernetes 節點效能調校分享
https://medium.com/overcast-blog/kernel-tuning-and-optimization-for-kubernetes-a-guide-a3bdc8f7d255


本文章主要探討若要讓 Kubernetes 節點能夠有更好的效能,要如何從 Kernel 方面去針對 網路/檔案系統/記憶體/CPU/行程排程 等這些方面去設定 Kernel 參數,並且每個參數所帶來的效果有哪些,此外也有提到設定的前提是要先有足夠的指標監控系統,透過系統長期觀察每個參數帶來的效果才算是有效的調整,否則如無頭蒼蠅般的設定並不算是真正的瞭解系統。
文章內列舉的參數包含
1. net.core.somaxconn
2. net.ipv4.tcp_max_syn_backlog
3. net.ipv4.ip_loacl_port_range
4. vm.swappiness
5. vm.overcommit_memory
6. vm.dirty_background_ratio
7. vm.dirty_ratio
8. fs.file-max
9. fs.inotify.max_user_watches
10. kernel.sched_migration_cost_ns
11. kernel.sched_autogroup_enabled

此外 k8s 過往是不支援 swap 的,需要 1.22(alpha), 1.28(beta) 後的版本才可以開啟 SWAP,文章中提到的 CPU Affinity/Management 的 YAML 我自己看起來是完全達不到 CPU affinity 的用途,畢竟該功能需要仰賴 Guarantee QoS 的 Pod 且 CPU StaticManager 要有開啟才有辦法,否則預設情況下 Container 的 CPU 是無法由固定 CPU 處理的。
Title:
Netflix 分享跨地區的網路效能除錯經驗
Source:
https://medium.com/@netflixtechblog/investigation-of-a-cross-regional-network-performance-issue-422d6218fdf1


Netflix 團隊中遇到一個跨地區的網路問題,Client Application 團隊初期覺得是網路問題,因此請網路團隊幫忙除錯,網路團隊藉由錄製封包等行為觀察出下列現象
1. Client 已非常固定的時間,啟動 30 秒後就會自己發送 FIN 去關閉連線
2. 檢查 Client & Server 的封包,發現 Server 回傳的封包都有順利送到,沒有任何 Packet Loss 的現象

由上述觀察,網路團隊認為問題應該是 Client Application 本身,因為是 Client Application 自己關閉網路連線的,但是檢查了一下,發現
1. Client Version
2. Server Version
3. Network Infra
上述三個版本短期內都沒有變動,甚至 Server 還是一年多前的版本,然後有觀察到 Client 內有設定一個 Timeout 30 秒的時間,若時間內沒有辦法收完資料就會關閉連線。

最後團隊開始懷疑這個問題是由 Kernel 導致的,經過一連串的實驗與觀察,最後發現這個問題真的跟 Kernel 升級有關,使用舊版本 6.5.13 的時候, Client 只要 22 秒就可以送完資料,但是升級到 6.6.10 的時候則需要 39 秒,就會超過 timeout 導致斷線。

文章最後有詳細解釋原因,主要是跟 TCP Receive Windows 的計算方式改變有關,有興趣的可以閱讀全文
CNI 效能評比 2024 版本

https://medium.com/itnext/benchmark-results-of-kubernetes-network-plugins-cni-over-40gbit-s-network-2024-156f085a5e4e


作者先前於 2018,2019,2020 都有撰寫過相關的 CNI 分析,而這次 2024 也針對當前的 K8s 1.26(RKE2), Ubuntu 22.04 再次進行了效能分析。

首先要先針對 CNI 進行挑選,作者根據下列性質挑選出數個 CNI 解決方案
1. 12 個月內有 commit 更新
2. 跟廠商/硬體無關
3. 非 Meta CNI(Multus)
4. 最好支援 Network Policy
5. 好安裝於 K8s 上

因此選出來的評比對象分別是,其中每個又有特別強調使用的設定
1. Antrea 1.15.0
2. Calico 3.27.2
3. Canal 3.27.2
4. Cilium 1.15.2
5. Kube-OVN 1.12.8
6. Kube-Router .1.0

環境:
1. Supermicro 的機器
2. Supermicro 40Gbit switch
3. 以 DDAC SFP+ Cable 相連
4. 大家都同 VLAN,設定 MTU 9000

測試的面向非常多,包含
1. Pod to Pod
2. Pod to Service
3. TCP/UDP
4. Single Stream/Multi Stram
5. ...等
為什麼系統架構這麼難
https://medium.com/@ozanani/software-architecture-is-hard-71fe3ddafb60


作者敘述自己有一段時間一直被附近施工的聲音吵醒,因此起了搬家的念頭,為了確保搬家地點不會被施工聲音給干擾,於是作者去尋找該施工相關的文件報告,一看發現對方文件寫得非常清除,未來三年的施工計畫,每個地區估計的時間點都寫得非常明瞭,即使完全不懂都市工程的人都有辦法輕易閱讀。

作者就開始思考,那為什麼軟體架構方便則沒有辦法這麼清晰地去描述?
原因可能有
1. 團隊內負責架構設計的人能力不均
2. 大家對於架構的理解不同,撰寫出來的內容與抽象層度也不一定完全相同
3. 對於非功能面的理解,如 Reliability, Security. Privay, Scale 等不同,因此撰寫的東西也都不同

而過往很常見的作法則是採取 Top-Down 的架構,團隊內會有一個專職的架構師,由該架構師去進行統一的架構設計與規劃,底下的工程團隊根據敘述與藍圖進行施工,這種運行模式下,架構師基本上就負責整個架構權責,包含設計與文件等。
然而現在逐漸有另外一種 Bottom-Up 的運行模式,採取的是去中心化的架構設計分案,讓團隊內所有的工程師一起設計架構,一起完善整個系統,而並非由單一的架構師說了算。

這種流程下,團隊內不同經驗的工程師會負責的不同的領域,譬如比較資淺的可以負責較小的元件設計,而資深的工程師則會設計更大的範疇。該流程希望可以達到
1. 讓所有工程師一起學習成長
2. 提升每個工程師對該專案與的掌握度
3. 消除單點故障(架構師)的影響
4. 團隊內共享更多知識

然後說得好聽實作難,實作上可能會遇到
1. 經驗不一的人設計出來的架構品質不一致,團隊內可能最後會產生出四不像的架構
2. 設計流程過多,不同人的接受程度不同。譬如整個流程過於繁瑣且過大的負擔,可能會讓工程師花費更多時間在處理這些設計而非真正的實作,反過來則有可能根本沒有涉獵過多設計,所料想的優點一個都沒有,因此尺度拿捏上非常難。

作者最後介紹了 C4 Model 的實作範例,推薦所有團隊都先嘗試基於 C4 Model 來描述自己系統的架構,先熟悉這種描述的方式以及理解分四種模型對於整個文件與架構帶來的幫助,熟悉後對於後續的各種流程才會加速並且更游刃有餘。
Kubernetes 網路概論詳解

https://medium.com/devops-dev/networking-in-kubernetes-5bc2d574fd95


本篇文章巨細彌遺的解釋 CNI (Container Netwowrk Interface) 這個標準的用途,從最早期的 Docker 到後期 Kubernetes 這不同架構下是怎麼看待容器網路建置這件事情說起。
以 Kubernetes 來說,每個容器的網路基本需求就是
1. 一個不衝突的 IP
2. 能夠跟同節點上的 Pod 互相存取
3. 能夠跟不同節點上的 Pod 互相存取,且最好不需要經過 SNAT 與 DNAT

三個簡單的需求實作上有各種不同的可能性,因此 Kubernetes 則是專心使用介面,將所有的實作都下放給不同的專案,譬如 Cilium, Calico 等。
文章中以 Weave Network 為範例,以 weave network 的 CNI 探討上述流程的運作以及 Kubernetes 與 Kubelet 是如何設定 CNI 來幫容器設定所有網路功能的。
Kubernetes 1.0 發展之路回顧

https://itnext.io/kubernetes-the-road-to-1-0-525a9420fdf0


今年是 Kubernetes 發展十週年,世界各地都有相關的慶祝活動,本篇文章作者作為當初 Google 內部 Kuberetnes 開發人員之一,就以自己的記憶跟大家回顧 Kubernetes 誕生期間的種種發展。

1. 網路上最常見到的說法是 Google 內部 Borg 專案為 Kubernetes 的前身,但是作者認為更精準的說法應該是 Omega 才對, Omega 作為 Borg 的繼任者,改善更多使用上與操作上的問題,最後才順水推舟將一切好的設計保留到 Kubernetes 上。
2. Labels/Annotation 等概念設計都不是 Borg 一開始就有的,都是內部使用者回饋出來的機制,內部使用者希望透過一些方式以邏輯的方式分類物件,最終才產生這些設計
3. 最早期是採用 Task 來描述運算資源,後期才改為 Pod
4. 初期沒有 Kubelet 的設計,都是由 Kube-Proxy 直接跟 etcd 溝通取得相關計算
5. 節點最早期稱為 minion,後期才改名為 Node
6. ...等,文章內還有許多發展初期的討論
K8s 從 cgroupv1 升級到 cgroupb2 的踩雷經驗
https://zouyee.medium.com/a-tragedy-caused-by-a-single-kubernetes-command-7b6126b06513

隨者 CentOS EOF 的到來,團隊決定轉移整個 OS 的同時順便將 Cgroup v1 給轉移到 Cgroup v2,然而轉移過去時,過去用來收集 CPU 使用情況的參數 "-enable_laod_reader" 則會使得 kubelet panic,沒有辦法正常運作。

本篇文章主要著重於
1. Container Metrics 如何被產生
2. Kubernetes 如何監控 Container Metrics
3. CPU Load 是如何被計算的

文章開頭先簡介 CAdvisor 的概念,透過程式碼解術 "-enable_load_reader" 該參數是如何影響 CAdvisor 要不要收集 CPU 的指標。
此外,自從 K8s 1.19 後, CAdvisor 已經被內建於 Kubelet 內,所以使用者也都不需要自行安裝,

當 CAdvisor 要收集 CPU Load Average 時,會透過 netlink 的方式去跟 kernel 溝通來獲取資訊,使用的指令是 "CGROUPSTATS_CMD_GET",結果底層的實作只有
支援 cgroup v1 的類型,遇到 v2 就會回傳 EINVAL 的錯誤。

作者諮詢過 cgroup2 的維護者,其推薦改使用 PSI 的指標來獲得 CPU 的資訊,不在需要透過 CAdvisor 的方式來獲取 CPU 的資訊,文章內也有附上其他相關 issue.
圖解 JuiceFS 創建 Pod 過程中 CSI 的流程
https://arthurchiao.art/blog/k8s-juicefs-csi-workflow-zh/

JuiceFS 是一個以 Object Storage 為基底並且提供 Filesystem 介面供使用者操作的檔案系統,文章內先簡述 JuiceFS 的架構,以及這類型的服務搭配 Kubernetes CSI 的操作概念,以 JuiceFS 來說則是會以 Fuse 為基底,並且透過 sidecar 或是 agent 的方式來動態的將遠方的空間掛載到目標 Pod 節點上。

文章後半部分透過操作來仔細解釋所有流程,搭配各種 log 來觀察 kubelet, CSI, Agent 等元件的互動流程。
為什麼會有想要取代 Helm 後繼方案

https://itnext.io/finally-a-viable-helm-replacement-388d538f9e1f


Helm 作為 Kubernetes 內最成熟且最多人使用的應用程式打包與發佈框架,這邊的應用程式代表的是用一堆 YAML 來描述的應用程式。

Helm 透過
1. 支援不同版本的設定與打包
2. 從早期的 www server 到後來的 OCI Server,有不同的方式可以發佈與讓人下載各種打包好的 Helm Chart (一整包 YAML)
3. 透過 Template 的方式讓使用者可以客製化 YAML 的內容,減少重複撰寫同時又可以滿足各種使用情境

Helm 有很多好處,但是使用上也有很多限制與問題,譬如
1. 部署狀況不明確,需要使用者自己去除錯
2. 沒有明確的 dry-run 模式,只能透過產生 YAML 去判別
3. Template 的撰寫很複雜,寫得過於複雜雖然功能強大,但是維護上又很困難

諸多特性讓很多 Helm 的使用者又愛又恨
此外 Helm 目前最大的隱憂也就是 Maintainer 的數量以及相關 feature 的演進速度已經逐漸放慢,整個專案的發展進入停滯的狀況。

因此目前也有不少專案開始嘗試重新設計,希望可以吸取 Helm 的經驗重新打造一個更適合的 K8s 應用程式打包框架。
本篇文章介紹的 Werf 就是一個對 Helm 完全相容的新框架,該框架嘗試基於 Helm 的經驗並且解決各種已知問題,譬如部署下去還會自動收集當前部署狀態,並且回傳相關 log 讓使用者可以知道部署狀況,並且也有自動 rollback 的機制。
矽谷牛的耕田筆記
為什麼會有想要取代 Helm 後繼方案 https://itnext.io/finally-a-viable-helm-replacement-388d538f9e1f Helm 作為 Kubernetes 內最成熟且最多人使用的應用程式打包與發佈框架,這邊的應用程式代表的是用一堆 YAML 來描述的應用程式。 Helm 透過 1. 支援不同版本的設定與打包 2. 從早期的 www server 到後來的 OCI Server,有不同的方式可以發佈與讓人下載各種打包好的 Helm Chart (一整包…
Google & Amazon 對於 CI/CD 的設計經驗談
https://carloarg02.medium.com/how-amazon-and-google-view-ci-cd-in-an-entirely-different-way-824b9c36777e


作者過去 20 多年內,先後待過 Amazon, Google, Amazon(回鍋) 內關於 CI/CD 的相關部門。
作者透過自身的經驗觀察到這兩家大公司對於 CI/CD 的設計哲學是截然不同的,而這個截然不同主要體現於
1. Pre-Summit: 程式合併前的各種操作
2. Post-Summit: 程式合併後的各種操作

以經驗來看, Google 的 Pre-Summit 做得非常完善,而 Amazon 則是 Post-Summit 更為完善。

作者認為造成這兩種近乎對立截然不同的結果的成因在於程式碼的架構。
Google 採取的是超級 monorepo,全公司的程式碼都放到一個共同的 Git Repo,所有改進都會曠日廢時,以作者當年的經驗來說,部署一個應用程式到 Production 可能是幾天後。但是也因為這種框架,使得 Google 非常專注設計 Local Dev Environment 的設計,所有開發者都要有辦法能夠於本地進行完整的 E2E 測試,確保測試完畢後才有機會合併到最終的 Repo.

與之相反的是 Amazon 則是各種 microrepo 的概念,應用程式散落到不同的 Git repo 中,每個都有自己獨立的開發與部署流程,彼此之間互相不干擾,因此 Production 的部署也不會被其他人影響,速度很快,但是相反的是 Pre-Summit 前的操作則是因為整個 E2E 牽扯過多的 Repo,導致設計上變得困難。

作者以自身的經驗來想,並沒有覺得兩個解決方案是絕對勝利的,畢竟 Google & Amazon 兩者也都走到了今天,公司也還在繼續成長茁壯,軟體的發展也是一直持續前進,與其說某種架構是絕對正確的,不如說每個環境有適合的架構。
從 mongodb 轉移到 PostgreSQL 的心路歷程
https://medium.com/@tony.infisical/the-great-migration-from-mongodb-to-postgresql-fa3978bc143b

本篇文章作者描述團隊從 MongoDB 轉移到 PostgreSQL 的整個心路歷程。

團隊初期追求的是快速搭建環境確認商業模式可行,所以一開始透過 MongoDB 以及 Moongose ORM 來建置整個 DB 系統。

然而隨著環境上的使用者愈來愈多,使用情境逐漸變得複雜,有愈來愈多功能限制使得團隊感覺綁手綁腳,譬如
1. 沒有 transaction 的概念
2. 沒有關聯性資料庫的相關功能,如 CASCADE 搭配刪除的機制去清理
3. 因為授權機制的改變,大部分的 Cloud Provider 都沒有支援 mongoDB
4. 技術缺乏,大部分的工程師都更熟悉 SQL 類型的操作與部署

因為這些考量所以團隊決定進行資料庫架構轉移,包含
1. 架構評估
2. 效能評估
3. 資料轉移的步驟

其中如何把MongoDB 的資料轉移到 PostgeeSQL scheme 則是最困難的部分。
詳細的轉移步驟與流程請參閱內文
架構轉移到 Event Driven 遇到的各種挫折
https://medium.com/@shiiyan/how-i-failed-in-event-driven-architecture-86eb493082fa


本篇文章分享的是作者嘗試導入 event driven 架構來改善目前環境的心路歷程。

以目前的環境下架構來說,作者觀察到有很多物件彼此之間都有關聯性,常常 A 更新後也要去更新B, 最後還會呼叫到物件 C 的更新。

於是作者就希望可以透過 event driven 的架構來簡化這些流程,讓彼此之間的關係不要強烈綁定,透過 events 去定義每個物件的概念,有事情就呼叫相關的event 來處理。

然而真的實作後,作者發現事情沒有這麼簡單,實務上的轉移遇到一堆問題,並沒有辦法直接轉換過去,更是有很多實作上的問題,包含
1. 單向溝通的限制,不同於過往緊密的實作限制,A 呼叫B, 但是 B 不方便把自己的結果退回去給A.
2. Event Chain 可能會很複雜,複雜的情況下若要保持先後順序又是一大挑戰
2. 因為都是event 非同步處理,所以偏向 eventually consistency 的架構

文章內有更多關於實作上的辛酸血淚
Kubernetes 1.31 如何透過 consistent read 來提升整體效能
https://kubernetes.io/blog/2024/08/15/consistent-read-from-cache-beta/


Kubernetes 於 2024/08/13 釋出了 1.31 版本,其中一個進入到 Beta 階段的功能就是 consistent read。
這個功能對 Kubernetes 的使用者來說無感,但是對於 Kubernetes 的叢集管理人員來說則是一大福音,該功能改善了 Kubelet 與 API Server 存取的流程。
過往的 Kubelet 都會對 API Server 詢問所有 K8s 上的 Pod 資訊並且過濾到跟自己節點有關的 Pod,而理想狀況應該是只要詢問跟該節點有關的 Pod 就好。
為了達到這個理想機制, Kubernetes 內部針對 Cache 的部分進行調整與改善,引入了 etcd 的一些功能最終達成如標題所述的 consistent read 的功能,

根據官方測試,引入這個功能帶來了
1. 降低 etcd 的負擔與壓力 (25%)
2. 透過快取提升了 pod LIST 相關操作的存取速度 (提升3倍)
3. API Server 的 CPU 使用率下降 30%
K8s API Server 是如何與 Pod 處理相關的身份驗證

https://learnk8s.io/authentication-kubernetes

本篇文章非常詳細介紹 K8s API Server 是如何處理身份驗證的問題,這個領域包含兩個部分
1. Kubernetes 內部使用者
2. Kubernetes 外部使用者
(1) 的部分就是常見的 Service Account,文章中以 1.24 為分水嶺,分別介紹
a. 1.24 以前是如何透過 secret 的方式來提供 service account 的存取方式
b. 1.24 以後為了解決 secret 不會過期的問題(不夠安全) 而採取 volume projected 的方式來處理

(2) 的部分則是透過 static token file 作為範例來示範如何讓外部的使用者可以透過 curl 打 api-server 並且被辨認為特定的使用者,接者搭配 RBAC 的設定來給予特定的權限。

文章針對這些機制的來龍去脈解釋得非常清楚,能夠讓人更加理解這些機制的運作原理
CRI-O 1.31 新功能介紹
https://www.cncf.io/blog/2024/09/12/whats-new-in-cri-o-1-31/


隨者 Kubernetes 1.31 的發佈,其底下的 CRI-O 也正式推出 1.31 版本,而 1.31 有幾個重大改動
1. 底層 container 的實作從 runc 改成 crun, crun 相對於 runc 有更好的效能與資源使用效率,同時對於 contianer 啟動的速度也更快。
2. 支援 cosign 來搭配 Kuberneres namespace 達到更細部的簽章認證
3. 各種bug修復以及相關小功能的改變
Kubecon China 2024 回顧
https://moelove.info/2024/09/03/Kubecon-China-2024-Recap/


KubeCon China 最近剛結束,本篇文章記錄與會人員這幾天會議中的經驗分享
1. Linus 本人認為 AI 的流行使得 NVIDIA 對於 Linux Kernel 內的開發與貢獻更加活躍
2. Istio 的發展,其中 Sidecar mode 與 Ambient mode 的對比很類似過往 VM & Container 的比較,都是資源耗損浪費為痛點出發去改變,Ambient Mode 減少資源浪費但時也會增加爆炸半徑,這與所有 Contianer 都共享主機 Kernel 是一樣的概念
3. Kubernetes Ingress NGINX 的發展,將逐漸轉往 Gateway API 的實作,並且移除各種內建 annoation 的用法,未來都將透過 Gateway API 來描述與操作
Title: Istio DNS Proxy 提升 DNS 效能的能力
Source: https://medium.com/@espinaladrinaldi/how-istio-dns-proxy-improve-dns-performance-capabilities-to-resolve-dns-inter-mesh-cluster-or-546e03a44610


主要觀點:
- 討論 Istio DNS Proxy 的工作原理,以及如何透過此工具改善 DNS 的效能
- 提供了實際上可以怎麼使用這個功能改善應用程式的 DNS 以及 Kubernetes 的 DNS 存取問題
關鍵功能:
- 改善 DNS 查詢速度
- 提高 DNS 解析的可靠性
結論:
- Istio DNS Proxy 提供類似 Cache 的功能來改善整個 DNS 的存取問題,同時透過 istio 的架構可以達到無侵入式的修改,讓 app 無感。