本篇文章探討的也是資安系列問題,而這次的目標主角則是 MAC 系統上廣為流傳的 Homebrew 系統。
結論:
作者透過觀察 Homebrew 的 Github Action 流程,成功得上傳一個會列印一行的程式碼到 iterm2 套件中,讓所有安裝的使用者都會於 Terminal 上看到一行作者客製化的訊息。
本次的漏洞是作者刻意從 Homebrew 的 Vulnerability Disclosure Program 專案中去嘗試尋找可能的問題,所有的操作都有跟官方專案的人探討過流程,並且一切的 PoC 都是單純證明該攻擊的可行性,所以有興趣研究的人請遵循一樣的想法去做,不要認真的想攻擊。
原因:
1. Homebrew 透過 Github Action 執行 CI/CD 動作
2. Homebrew 撰寫了一個自動合併 Pull Request 的 Action
3. CI 內會透過一個Ruby的 Git Diff 第三方函式庫來驗證,只要符合下列條件就可以自動合併
- Modifying only 1 file
- Not moving/creating/deleting file
- Target filepath matches \ACasks/[^/]+\.rb\Z
- Line count of deletions/additions are same
- All deletions/additions matches /\A[+-]\s*version "([^"]+)"\Z/ or - -\A[+-]\s*sha256 "[0-9a-f]{64}"\Z
- No changes to format of versions (e.g. 1.2.3 => 2.3.4)
作者一開始想要從該規則下手,找尋有沒有可能塞入惡意攻擊並且騙過系統讓其自動合併,然而這些規則看起來沒有什麼太多問題,於是作者轉往其他領域去找尋問題,其中一個想法就是到底該 Ruby 的 Git Diff 是如何實作,也許從實作下手更有辦法去欺騙這一切。
很順利的是,作者真的於該函式庫中找到問題,對於一個 Git Diff 的結果來說,該函式庫會透過 +++ "?b/(.*) 這樣的正規表達式來判別檔案路徑的資訊而並非程式修改內容,譬如下列 diff
```
diff --git a/source file path b/destination file path
index parent commit hash..current commit hash filemode
--- a/source file path
+++ b/destination file path
@@ line information @@
Details of changes (e.g.: `+asdf`,`-zxcv`)
```
作者就開始思考,如果讓程式碼可以符合 +++ "?b/(.*) 的規則,是否有辦法讓程式碼不被視為一個檔案的修改,因此就可以修改多行程式碼但是讓 CI 系統認為只有一行程式碼於是進行自動合併
作者最初的想法如下,第一行用來放惡意程式碼,第二行用來偽裝檔案路徑,經過一番嘗試後作者真的成功塞入了類似 PRINTF 的程式碼到環境中並觸發自動合併。接者各地使用者透過 brew 安裝 iterm 版本都會看到使用者塞入的程式碼。
```
++ "b/#{Arbitrary codes here}"
++ b/Casks/cask.rb
```
原文還有更多作者的思路過程,有興趣的不要錯過
原文:
https://blog.ryotak.me/post/homebrew-security-incident-en/#fn:7
測試用PR:
https://github.com/Homebrew/homebrew-cask/pull/104191
結論:
作者透過觀察 Homebrew 的 Github Action 流程,成功得上傳一個會列印一行的程式碼到 iterm2 套件中,讓所有安裝的使用者都會於 Terminal 上看到一行作者客製化的訊息。
本次的漏洞是作者刻意從 Homebrew 的 Vulnerability Disclosure Program 專案中去嘗試尋找可能的問題,所有的操作都有跟官方專案的人探討過流程,並且一切的 PoC 都是單純證明該攻擊的可行性,所以有興趣研究的人請遵循一樣的想法去做,不要認真的想攻擊。
原因:
1. Homebrew 透過 Github Action 執行 CI/CD 動作
2. Homebrew 撰寫了一個自動合併 Pull Request 的 Action
3. CI 內會透過一個Ruby的 Git Diff 第三方函式庫來驗證,只要符合下列條件就可以自動合併
- Modifying only 1 file
- Not moving/creating/deleting file
- Target filepath matches \ACasks/[^/]+\.rb\Z
- Line count of deletions/additions are same
- All deletions/additions matches /\A[+-]\s*version "([^"]+)"\Z/ or - -\A[+-]\s*sha256 "[0-9a-f]{64}"\Z
- No changes to format of versions (e.g. 1.2.3 => 2.3.4)
作者一開始想要從該規則下手,找尋有沒有可能塞入惡意攻擊並且騙過系統讓其自動合併,然而這些規則看起來沒有什麼太多問題,於是作者轉往其他領域去找尋問題,其中一個想法就是到底該 Ruby 的 Git Diff 是如何實作,也許從實作下手更有辦法去欺騙這一切。
很順利的是,作者真的於該函式庫中找到問題,對於一個 Git Diff 的結果來說,該函式庫會透過 +++ "?b/(.*) 這樣的正規表達式來判別檔案路徑的資訊而並非程式修改內容,譬如下列 diff
```
diff --git a/source file path b/destination file path
index parent commit hash..current commit hash filemode
--- a/source file path
+++ b/destination file path
@@ line information @@
Details of changes (e.g.: `+asdf`,`-zxcv`)
```
作者就開始思考,如果讓程式碼可以符合 +++ "?b/(.*) 的規則,是否有辦法讓程式碼不被視為一個檔案的修改,因此就可以修改多行程式碼但是讓 CI 系統認為只有一行程式碼於是進行自動合併
作者最初的想法如下,第一行用來放惡意程式碼,第二行用來偽裝檔案路徑,經過一番嘗試後作者真的成功塞入了類似 PRINTF 的程式碼到環境中並觸發自動合併。接者各地使用者透過 brew 安裝 iterm 版本都會看到使用者塞入的程式碼。
```
++ "b/#{Arbitrary codes here}"
++ b/Casks/cask.rb
```
原文還有更多作者的思路過程,有興趣的不要錯過
原文:
https://blog.ryotak.me/post/homebrew-security-incident-en/#fn:7
測試用PR:
https://github.com/Homebrew/homebrew-cask/pull/104191
blog.ryotak.net
Remote code execution in Homebrew by compromising the official Cask repository
この記事は日本語でも投稿されています: https://blog.ryotak.net/post/homebrew-security-incident/
(もし日本語が読める場合、筆者は英語がそこまで得意ではないため、日本語の記事を読むことをお勧めします。)
(Official blog post about this incident is available here: https://brew.sh/2021/04/21/security-incident-disclosure/)
Preface…
(もし日本語が読める場合、筆者は英語がそこまで得意ではないため、日本語の記事を読むことをお勧めします。)
(Official blog post about this incident is available here: https://brew.sh/2021/04/21/security-incident-disclosure/)
Preface…
這篇文章探討的是關於 Serverless 使用上的經驗分享
作者基於自身實戰經驗探討於 AWS 上使用 Serverless 的七種架構模式
模式一:
作者認為最簡單的模式,使用 API Gateway, Lambda Functions 配上 DynamoDB 來處理商業需求
團隊可以透過 API Gateway 來達到快取,限速等不同的調整
模式二:
針對微服務的架構調整,基於模式一進行延伸。
因為 API Gateway 以及 Lambda 相關的限制都是基於帳戶設定的(可以聯絡客服調高),因此模式二就是用更多的帳戶來處理更多的服務,藉此讓這些限制不會被許多服務共享。
模式三:
該模式是標準有前(SPA)後端應用程式的架構。
前端(Single Page Application)網頁放到不公開的 S3,前方透過 AWS CloudFront 來處理應用並且將 Request 給 Proxy 到後方 S3。而後端則是如同模式一的方式去部署
模式四:
模式三的延伸,如果需要使用者是來自於不同的地理位置,想要針對地理位置去進行更多處理時,會透過 CloudFront 作為 Proxy 來處理 Regional API Gateway.
剩下三種模式就不詳述,有興趣的可以閱讀原文看看七種模式
https://waswani.medium.com/serverless-architecture-patterns-in-aws-edeab0e46a32
作者基於自身實戰經驗探討於 AWS 上使用 Serverless 的七種架構模式
模式一:
作者認為最簡單的模式,使用 API Gateway, Lambda Functions 配上 DynamoDB 來處理商業需求
團隊可以透過 API Gateway 來達到快取,限速等不同的調整
模式二:
針對微服務的架構調整,基於模式一進行延伸。
因為 API Gateway 以及 Lambda 相關的限制都是基於帳戶設定的(可以聯絡客服調高),因此模式二就是用更多的帳戶來處理更多的服務,藉此讓這些限制不會被許多服務共享。
模式三:
該模式是標準有前(SPA)後端應用程式的架構。
前端(Single Page Application)網頁放到不公開的 S3,前方透過 AWS CloudFront 來處理應用並且將 Request 給 Proxy 到後方 S3。而後端則是如同模式一的方式去部署
模式四:
模式三的延伸,如果需要使用者是來自於不同的地理位置,想要針對地理位置去進行更多處理時,會透過 CloudFront 作為 Proxy 來處理 Regional API Gateway.
剩下三種模式就不詳述,有興趣的可以閱讀原文看看七種模式
https://waswani.medium.com/serverless-architecture-patterns-in-aws-edeab0e46a32
Medium
Serverless Architecture Patterns in AWS
Serverless architecture is a way to build and run applications and services without having to manage infrastructure. The approach helps…
這篇文章是個專案教學文,探討的是如何使用由 Rancher 所開發維護的 Harvester(HCI, 超融合基礎架構)專案。
雲端架構的特性能夠應付大部分的應用與場景,但是部分的應用則必須要繼續使用地端實體機器去架設服務。
虛擬化的時代,要如何將一個又一個硬體機器轉變成簡單好用的 VM 供上層應用程式使用則是一個有趣但困難的操作,開源的 Openstack 或是各種商業軟體則是眾多企業過往的選擇。
當這一切碰到 Kubernetes 時又變得複雜,主要是 Openstack 等專案強大卻難以駕馭,複雜的元件與架構讓它沒有辦法如 Kubernetes 一樣簡單好用,輕易上手。
如何讓一群硬體機器上面部署一個 Kubernetes 叢集不是一個困難問題,目前有眾多的解決方案幫忙處理,但是如何讓一群硬體機器上面跑出各種不同的 VM,並且於 VM 上面運行 Kubernetes 則是一個難以搞定但確實存在的需求。
Rancher 本身很擅長如何於一群 VM 上運行這些 Kubernetes 叢集,因此其發展了 Harvester 這個專案,該專案基於 Rancher 的 K3OS 作為底層作業系統。接者透過 Kubevirt 專案來管理與創建 VMs,儲存方面則是使用 Longhorn 來管理,網路的話則是 Kubevirt 本身已經導入 Multus CNI 來提供更多的網路操作。
這個專案還非常新,還在持續開發中,對於地端環境部署有需求的話,可以持續關注這個專案
https://blog.linnovate.net/baremetal-kubernetes-with-harvester-and-k3s-25fe9e7ab695
雲端架構的特性能夠應付大部分的應用與場景,但是部分的應用則必須要繼續使用地端實體機器去架設服務。
虛擬化的時代,要如何將一個又一個硬體機器轉變成簡單好用的 VM 供上層應用程式使用則是一個有趣但困難的操作,開源的 Openstack 或是各種商業軟體則是眾多企業過往的選擇。
當這一切碰到 Kubernetes 時又變得複雜,主要是 Openstack 等專案強大卻難以駕馭,複雜的元件與架構讓它沒有辦法如 Kubernetes 一樣簡單好用,輕易上手。
如何讓一群硬體機器上面部署一個 Kubernetes 叢集不是一個困難問題,目前有眾多的解決方案幫忙處理,但是如何讓一群硬體機器上面跑出各種不同的 VM,並且於 VM 上面運行 Kubernetes 則是一個難以搞定但確實存在的需求。
Rancher 本身很擅長如何於一群 VM 上運行這些 Kubernetes 叢集,因此其發展了 Harvester 這個專案,該專案基於 Rancher 的 K3OS 作為底層作業系統。接者透過 Kubevirt 專案來管理與創建 VMs,儲存方面則是使用 Longhorn 來管理,網路的話則是 Kubevirt 本身已經導入 Multus CNI 來提供更多的網路操作。
這個專案還非常新,還在持續開發中,對於地端環境部署有需求的話,可以持續關注這個專案
https://blog.linnovate.net/baremetal-kubernetes-with-harvester-and-k3s-25fe9e7ab695
今天這篇文章要跟大家介紹的是 kubectl 一個好用的 plguin, flame,這個名稱就是大家所熟悉的火焰圖,所以長話短多。 kubectl flame 用來幫助維運人員針對任何已經運行的 Container 透過不同的 proflier 來進行效能分析,並且畫出相對應的火焰圖供研究。
對於維運人員來,透過 profiling 分析程式碼中存在的效能瓶頸是個非常常見的行為,有效的工具能夠幫助開發人員更快速的找到效能瓶頸並加以修正,而火焰圖則是一個非常知名的視覺化方式,將這些 profiling 的結果透過 stack 的方式顯示出來,讓開發人員一目了然地找到痛點。
雖然 profiling 聽起來如此強大,但是要於 Kubernetes 中針對運行的應用程式進行效能分析並不是如此簡單,主要是 profiling 通常會伴隨兩個條件
1. 程式碼需要修改,加入相對應的參數或是函數才能夠正確地將 function symbol 給顯示出來
2. 針對正式生產環境的除錯同時也會帶來效能影響的取捨,為了分析應用程式的效能意味者 profiler 必須要針對應用程式進行取樣與分析,這些都會帶整體效能上的影響。
更重要的事,如果今天要對一個已經運行的應用程式加上 profiling 需要的修改與參數,代表整個 Pod 會需要重啟來部署新版本的 Container Image。這類型的重啟可能會導致效能問題消失,整個除錯過程變得非常困難。
Kubectl flame 透過部署一個全新的 Container 到目標 Container 所在的節點上,同時透過 PIDNamespace 與 MountFilesystem 等方式來達到透過外部應用程式來幫忙進行 profiling,不過要注意的是不同的 profilter 所支援的程式語言不同。
有興趣的可以參考下列文章,甚至可以使用 pyroscope 這套 continuous profiling platform 來達成長時間的效能分析。
https://medium.com/swlh/introducing-kubectl-flame-effortless-profiling-on-kubernetes-4b80fc181852
對於維運人員來,透過 profiling 分析程式碼中存在的效能瓶頸是個非常常見的行為,有效的工具能夠幫助開發人員更快速的找到效能瓶頸並加以修正,而火焰圖則是一個非常知名的視覺化方式,將這些 profiling 的結果透過 stack 的方式顯示出來,讓開發人員一目了然地找到痛點。
雖然 profiling 聽起來如此強大,但是要於 Kubernetes 中針對運行的應用程式進行效能分析並不是如此簡單,主要是 profiling 通常會伴隨兩個條件
1. 程式碼需要修改,加入相對應的參數或是函數才能夠正確地將 function symbol 給顯示出來
2. 針對正式生產環境的除錯同時也會帶來效能影響的取捨,為了分析應用程式的效能意味者 profiler 必須要針對應用程式進行取樣與分析,這些都會帶整體效能上的影響。
更重要的事,如果今天要對一個已經運行的應用程式加上 profiling 需要的修改與參數,代表整個 Pod 會需要重啟來部署新版本的 Container Image。這類型的重啟可能會導致效能問題消失,整個除錯過程變得非常困難。
Kubectl flame 透過部署一個全新的 Container 到目標 Container 所在的節點上,同時透過 PIDNamespace 與 MountFilesystem 等方式來達到透過外部應用程式來幫忙進行 profiling,不過要注意的是不同的 profilter 所支援的程式語言不同。
有興趣的可以參考下列文章,甚至可以使用 pyroscope 這套 continuous profiling platform 來達成長時間的效能分析。
https://medium.com/swlh/introducing-kubectl-flame-effortless-profiling-on-kubernetes-4b80fc181852
Medium
Introducing Kubectl Flame: Effortless Profiling on Kubernetes
A kubectl plugin that allows you to profile production applications with low-overhead by generating FlameGraphs
本篇是一個 Kubernetes 的入門介紹文,探討 Kubernetes 內要如何透過 SSL/TLS 憑證來加強應用程式之間的連線。
本篇文章不使用任何第三方套件,反而是從 Kubernetes 內建的資源功能出發去探討,理解 Kubernetes 的能力與極限其實長久下來對於評估各種專案都滿有幫助的。
Kubernetes 的 Secret 除了使用 base64 作為編碼技術外,其實本身也提供不少類型方便管理人員使用,譬如本文提到的 tls 類型, container registry credential 以及最廣泛使用的 generic 等。
Secret(tls類型)本身創建時會吃兩個參數,分別是 tls.crt 與 tls.key,接者這類型的 secret 可以與 ingress 進行整合,將 TLS 給掛載到 Ingress 物件中並且同時執行 TLS Termination,讓 Ingres 與外部連線使用 HTTPS 而內部服務則使用 HTTP 來溝通。
文章中提到如何透過 openssl 創建一個 self-signed 的憑證,並且針對 self-signed 的特性進行討論,其列出了四個 self-signed 的缺點
1. 瀏覽器連接到這些 self-signed 憑證的網站時都會露出警告告知使用者,因此這類型的憑證不適合任何正式生產環境使用
2. 因為 self-signed 就是開發者自行創造,缺少第三方可信任機關的認證,因此惡意攻擊者可以輕鬆換掉服務上的簽證,畢竟瀏覽器本來就覺得簽證有問題,無法分辨到底是先前的自簽憑證還是被替換的憑證。
3. 第三方CA都會針對發行的憑證給予一些保固與服務,這部分是自簽沒有辦法擁有的
4. 愈來愈多的使用者會不太願意瀏覽與使用沒有合法且信任憑證的網站
作者提到 Kubernetes 內部雖然有一個 CA,但是不推薦把任何服務相關的憑證都跟其扯上關係,
因為該 CA 是給 Kubernetes 內部控制平面使用的,譬如 kubelet, API Server, Controller, Scheduler 等元件彼此溝通中間使用的。
文章最後作者示範透過 cfssl 的該指令幫一個內部服務創建一個憑證,由於內部服務會透過 Kubernetes Service 提供的 DNS 來存取,因此創建憑證時會於 CN 欄位補上 alternative 的名稱,把 service.svc.... 之類的全部都補上。
https://medium.com/avmconsulting-blog/how-to-secure-applications-on-kubernetes-ssl-tls-certificates-8f7f5751d788
本篇文章不使用任何第三方套件,反而是從 Kubernetes 內建的資源功能出發去探討,理解 Kubernetes 的能力與極限其實長久下來對於評估各種專案都滿有幫助的。
Kubernetes 的 Secret 除了使用 base64 作為編碼技術外,其實本身也提供不少類型方便管理人員使用,譬如本文提到的 tls 類型, container registry credential 以及最廣泛使用的 generic 等。
Secret(tls類型)本身創建時會吃兩個參數,分別是 tls.crt 與 tls.key,接者這類型的 secret 可以與 ingress 進行整合,將 TLS 給掛載到 Ingress 物件中並且同時執行 TLS Termination,讓 Ingres 與外部連線使用 HTTPS 而內部服務則使用 HTTP 來溝通。
文章中提到如何透過 openssl 創建一個 self-signed 的憑證,並且針對 self-signed 的特性進行討論,其列出了四個 self-signed 的缺點
1. 瀏覽器連接到這些 self-signed 憑證的網站時都會露出警告告知使用者,因此這類型的憑證不適合任何正式生產環境使用
2. 因為 self-signed 就是開發者自行創造,缺少第三方可信任機關的認證,因此惡意攻擊者可以輕鬆換掉服務上的簽證,畢竟瀏覽器本來就覺得簽證有問題,無法分辨到底是先前的自簽憑證還是被替換的憑證。
3. 第三方CA都會針對發行的憑證給予一些保固與服務,這部分是自簽沒有辦法擁有的
4. 愈來愈多的使用者會不太願意瀏覽與使用沒有合法且信任憑證的網站
作者提到 Kubernetes 內部雖然有一個 CA,但是不推薦把任何服務相關的憑證都跟其扯上關係,
因為該 CA 是給 Kubernetes 內部控制平面使用的,譬如 kubelet, API Server, Controller, Scheduler 等元件彼此溝通中間使用的。
文章最後作者示範透過 cfssl 的該指令幫一個內部服務創建一個憑證,由於內部服務會透過 Kubernetes Service 提供的 DNS 來存取,因此創建憑證時會於 CN 欄位補上 alternative 的名稱,把 service.svc.... 之類的全部都補上。
https://medium.com/avmconsulting-blog/how-to-secure-applications-on-kubernetes-ssl-tls-certificates-8f7f5751d788
Medium
How to secure applications running on Kubernetes (SSL/TLS Certificates)?
Securing an application running on Kubernetes (SSL/TLS Certificates)
本篇是一個入門介紹文,探討的議題是微服務架構下的監控架構要有什麼樣的元件與功能
Observability 基本上現在已經是個顯學,任何的叢集架構都需要有一個匹配的監控系統來(主動or被動)告知當前各種元件的狀況,讓維運人員能夠儘早地針對問題處理,減少任何損失。
普遍主流認為可觀測性底下目前有三大類別,分別是
- Metrics
- Logs
- Tracing
監控系統必須要能夠讓維運人員知道什麼元件壞掉以及為什麼,維運人員能夠快速簡單的定位問題的可能點,並且快速的找到真正的 root cause。作者認為發生問題時最重要的就是要找對地方,就算今天環境中架設了各式各樣的儀表板並且收集了四面八方的資料,如果發生問題時沒有辦法準確的找到進入點,那再多的工具也都沒有用途。
作者列舉了四個必須要從任何服務都要收集的相關 Metrics,包含
- Latency: 每個服務請求花費的時間
- Errors: 系統中發生錯誤的訊息,甚至是沒有辦法被正確處理的請求
- Traffic
- Saturation: 服務用量的測量,譬如CPU/Memory/Disk/Network
接者要針對每個 Metrics 選決定一個適合的觀察類別,譬如說
1. Counters: 透過數值來表示各種可累積的 metrics,譬如 request 的數量, error 的數量。
2. Gauges: 透過數值來表示一種會上下起伏變化的 metrics, 譬如跟 database 的連線數量, 記憶體/CPU 的使用量,系統平均負載值
3. Histograms: 需要將取樣觀察結果依照不同類別來分類顯示,譬如 I/O latency
當監控系統建置完畢後,接下來就要有能力使用該系統來進行主動回報,也就是所謂的 Alert 系統。
當元件的狀況符合預先設定的條件時,就要通知維運人員來檢查與處理,這邊作者特別提到針對 Alert 的規則必須要仔細的設定分類與優先度,特別是當某些服務或是底層架構觸發時,可能會一口氣觸發多個 Alert 通知,這時候要如何快速的從眾多警報中找到真正的源頭就經驗搭配良好的系統規劃。
https://medium.com/@milan.brankovic/monitoring-microservices-e0f89496fa9e
Observability 基本上現在已經是個顯學,任何的叢集架構都需要有一個匹配的監控系統來(主動or被動)告知當前各種元件的狀況,讓維運人員能夠儘早地針對問題處理,減少任何損失。
普遍主流認為可觀測性底下目前有三大類別,分別是
- Metrics
- Logs
- Tracing
監控系統必須要能夠讓維運人員知道什麼元件壞掉以及為什麼,維運人員能夠快速簡單的定位問題的可能點,並且快速的找到真正的 root cause。作者認為發生問題時最重要的就是要找對地方,就算今天環境中架設了各式各樣的儀表板並且收集了四面八方的資料,如果發生問題時沒有辦法準確的找到進入點,那再多的工具也都沒有用途。
作者列舉了四個必須要從任何服務都要收集的相關 Metrics,包含
- Latency: 每個服務請求花費的時間
- Errors: 系統中發生錯誤的訊息,甚至是沒有辦法被正確處理的請求
- Traffic
- Saturation: 服務用量的測量,譬如CPU/Memory/Disk/Network
接者要針對每個 Metrics 選決定一個適合的觀察類別,譬如說
1. Counters: 透過數值來表示各種可累積的 metrics,譬如 request 的數量, error 的數量。
2. Gauges: 透過數值來表示一種會上下起伏變化的 metrics, 譬如跟 database 的連線數量, 記憶體/CPU 的使用量,系統平均負載值
3. Histograms: 需要將取樣觀察結果依照不同類別來分類顯示,譬如 I/O latency
當監控系統建置完畢後,接下來就要有能力使用該系統來進行主動回報,也就是所謂的 Alert 系統。
當元件的狀況符合預先設定的條件時,就要通知維運人員來檢查與處理,這邊作者特別提到針對 Alert 的規則必須要仔細的設定分類與優先度,特別是當某些服務或是底層架構觸發時,可能會一口氣觸發多個 Alert 通知,這時候要如何快速的從眾多警報中找到真正的源頭就經驗搭配良好的系統規劃。
https://medium.com/@milan.brankovic/monitoring-microservices-e0f89496fa9e
Medium
Microservices: monitoring and observability
Observing and reacting to potential problems in the system
本篇文章要介紹的是 2021 年熱門的日誌視覺化分析工具,作者於本篇文章列出 8 種不同的工具,分別是
1. Logiq.ai (2019 創立)
2. Datadog (2010 創立)
4. Dynatrace (2005 創立)
5. Logz.io (2014 創立)
6. Graylog (2009 創立)
7. Google Cloud Logging
8. Scalyr (2011 創立)
9. LOGalyze (開源專案,但是官網連 HTTPS 都沒有....)
作者列出的基本上都是商業解決方案,要使用開源方案還是商業解決方案一直以來都沒有絕對的答案,畢竟一個解決方案除了功能完整性之外,技術支援也是非常重要的一環。
好奇上述的解決方案大家有沒有相關使用經驗?
https://medium.com/nerd-for-tech/top-log-visualization-tools-in-2021-fa0a2d897ad1
1. Logiq.ai (2019 創立)
2. Datadog (2010 創立)
4. Dynatrace (2005 創立)
5. Logz.io (2014 創立)
6. Graylog (2009 創立)
7. Google Cloud Logging
8. Scalyr (2011 創立)
9. LOGalyze (開源專案,但是官網連 HTTPS 都沒有....)
作者列出的基本上都是商業解決方案,要使用開源方案還是商業解決方案一直以來都沒有絕對的答案,畢竟一個解決方案除了功能完整性之外,技術支援也是非常重要的一環。
好奇上述的解決方案大家有沒有相關使用經驗?
https://medium.com/nerd-for-tech/top-log-visualization-tools-in-2021-fa0a2d897ad1
Medium
Top Log Visualization Tools in 2021
New year, new log visualization tools for your DevOps team?
今天帶來的內容是關於 DevSecOps 的介紹,由 synk 這間公司所撰寫的 DevSecOps 介紹,與其說是文章更像是一個專欄,內文非常豐富,從基本的介紹,到文化,人員組成,運作流程以及相關技術探討都包含其中,我認為對這個領域有興趣的人很值得花些時間咀嚼一下這系列文章,來看看到底別人認知的 DevSecOps 到底是什麼。
本篇文章針對 overview 的部分進行介紹,其餘詳細部分請到連結中閱讀囉
What is DevSecOps:
1. 將 Security 的概念帶入到 DevOps 的軟體交付流程
2. Dev & Ops 共享責任來交付安全的應用與軟體
從功能面來看,盡可能地於整個軟體開發交付流程中盡可能早的發現安全並且修復,要特別注意的是"安全是所有人共享的責任"並不是單純 DevOps 團隊人員的責任,大夥還是努力合作一起解決問題,就如同 DevOps 的概念一致。
6 Benefits of the DevSecOps Model
- Faster delivery: 將 Security 等概念整合到軟體交付流程中時,可以讓任何漏洞於正式部署前就發現與解決,這樣可以使得整體的開發流程更加順利與快速。
- Improved security posture: 資安不再是個上線後才要擔心的議題,而是打成軟體設計開發初期就要關注的點,透過這個方式才有辦法把資安跟建置,部署進行一個緊密的整合
- Reduced costs: 正式部署前能夠定位找到任何 vulnerabilities 能夠有效率地減少各種維運上的風險成本。
...等
原文非常有趣,非常推薦有興趣的閱讀這整篇專欄
https://snyk.io/devsecops/
本篇文章針對 overview 的部分進行介紹,其餘詳細部分請到連結中閱讀囉
What is DevSecOps:
1. 將 Security 的概念帶入到 DevOps 的軟體交付流程
2. Dev & Ops 共享責任來交付安全的應用與軟體
從功能面來看,盡可能地於整個軟體開發交付流程中盡可能早的發現安全並且修復,要特別注意的是"安全是所有人共享的責任"並不是單純 DevOps 團隊人員的責任,大夥還是努力合作一起解決問題,就如同 DevOps 的概念一致。
6 Benefits of the DevSecOps Model
- Faster delivery: 將 Security 等概念整合到軟體交付流程中時,可以讓任何漏洞於正式部署前就發現與解決,這樣可以使得整體的開發流程更加順利與快速。
- Improved security posture: 資安不再是個上線後才要擔心的議題,而是打成軟體設計開發初期就要關注的點,透過這個方式才有辦法把資安跟建置,部署進行一個緊密的整合
- Reduced costs: 正式部署前能夠定位找到任何 vulnerabilities 能夠有效率地減少各種維運上的風險成本。
...等
原文非常有趣,非常推薦有興趣的閱讀這整篇專欄
https://snyk.io/devsecops/
Snyk
What is DevSecOps? | DevSecOps Model | Snyk
What is DevSecOps? Learn more about DevSecOps - an integration of security practices into a DevOps software delivery model.
本篇文章是ㄧ個 Kubernetes 相關工具經驗分享文,作者認為即使是前端開發工程師也必須要瞭解一下 Kubernetes 這個容器管理平台,作者認為 k8s 基本上已經算是這個領域的標準(de-facto)。
因此作者於本篇文章介紹一些搭建一個 K8s 叢集時需要注意的工具,透過這些自動化工具來減少反覆動作的執行藉此簡化每天的工作流程。
工具包含
1. ArgoCD
2. MetalLB
3. External-secrets
4. Cert-manager
5. External-dns
Simplify deploying of new apps
作者大力推薦使用 ArgoCD 來簡化部署應用程式,作者提到一開始使用 ArgoCD 時也是感到無比煩感,因為心中一直存在要於 `GitLab CI/CD pipeline` 透過 kubectl apply 的方式來部署應用程式,並不想要導入其他的元件來加入更多的複雜性。
然而當作者嘗試 ArgoCD 後,第一眼發現的是其架構不如想像中複雜,完全依賴 GitOps 的原則來簡化整個部署流程,同時透過一個 WebUI 的方式來呈現當前應用程式的部署狀況
Load balancer for your on-prem clusters
地端環境的 Load-Balancer,沒什麼好說就是 MetalLB。
Managing your secrets
Secrets 是 Kubernetes 內一個非常重要的物件,然而大部分的團隊都會思考如何有效且安全的去管理 Kubernetes 內的 Secret 物件。雲端供應商譬如 AWS Secrets Manager, Azure Key Vault 或是廣受熱門的 HashiCorp Vault.
作者推薦使用 external-secrets operator 這個專案來將外部的管理系統給同步到 Kubernetes 內並且產生對於的 secrets。
詳細全文可以參考下列原文
https://chris-blogs.medium.com/tools-that-should-be-used-in-every-kubernetes-cluster-38969ed3e603
因此作者於本篇文章介紹一些搭建一個 K8s 叢集時需要注意的工具,透過這些自動化工具來減少反覆動作的執行藉此簡化每天的工作流程。
工具包含
1. ArgoCD
2. MetalLB
3. External-secrets
4. Cert-manager
5. External-dns
Simplify deploying of new apps
作者大力推薦使用 ArgoCD 來簡化部署應用程式,作者提到一開始使用 ArgoCD 時也是感到無比煩感,因為心中一直存在要於 `GitLab CI/CD pipeline` 透過 kubectl apply 的方式來部署應用程式,並不想要導入其他的元件來加入更多的複雜性。
然而當作者嘗試 ArgoCD 後,第一眼發現的是其架構不如想像中複雜,完全依賴 GitOps 的原則來簡化整個部署流程,同時透過一個 WebUI 的方式來呈現當前應用程式的部署狀況
Load balancer for your on-prem clusters
地端環境的 Load-Balancer,沒什麼好說就是 MetalLB。
Managing your secrets
Secrets 是 Kubernetes 內一個非常重要的物件,然而大部分的團隊都會思考如何有效且安全的去管理 Kubernetes 內的 Secret 物件。雲端供應商譬如 AWS Secrets Manager, Azure Key Vault 或是廣受熱門的 HashiCorp Vault.
作者推薦使用 external-secrets operator 這個專案來將外部的管理系統給同步到 Kubernetes 內並且產生對於的 secrets。
詳細全文可以參考下列原文
https://chris-blogs.medium.com/tools-that-should-be-used-in-every-kubernetes-cluster-38969ed3e603
Medium
Tools that should be used in every Kubernetes cluster
Every web developer nowadays should be aware of Kubernetes. It is the de-facto standard for orchestrating large websites that are built…
本篇文章是經驗分享文,作者分享為什麼其跟最初學習 Kubernetes 使用的 minikube 說掰掰,而轉換到新歡 KIND 的故事
作者之前演講分享時,透過 minikube 架設所有 demo 環境,平常使用都好好的然而活動前幾天開始覺得叢集有點慢,但是作者並沒有特別注意去處理。
活動當天 demo 直接爆炸,系統變得很慢,不論是 pod 的各種操作都很慢,作者沒有辦法很漂亮的清除 minikube 內的環境,最後只好砍掉VM全部重來。
活動結束後作者重新創建了一次整個 VM(使用 VirtualBox),結果整個系統還是很慢,作者開始思考有沒有其他的替代方案,後來找到了 Kind 這套解決方案。
KIND 是 Kubernetes In Docker 的縮寫,透過 Docker Container 的方式創建節點並基於該節點創建 Kubernetes 叢集。
這邊要注意的是 KIND 透過 Docker 創建節點,而節點內卻使用 Contaeinrd 作為 k8s 的 CRI 解決方案。
除了 KIND 之外, Rancher 維護的 K3D 也是一樣類型的創建方式,其中 K3D 支持動態加入與移除節點,KIND 只能一開始創建時就定好 cluster 的大小。
https://nfrankel.medium.com/goodbye-minikube-340070edc5af
作者之前演講分享時,透過 minikube 架設所有 demo 環境,平常使用都好好的然而活動前幾天開始覺得叢集有點慢,但是作者並沒有特別注意去處理。
活動當天 demo 直接爆炸,系統變得很慢,不論是 pod 的各種操作都很慢,作者沒有辦法很漂亮的清除 minikube 內的環境,最後只好砍掉VM全部重來。
活動結束後作者重新創建了一次整個 VM(使用 VirtualBox),結果整個系統還是很慢,作者開始思考有沒有其他的替代方案,後來找到了 Kind 這套解決方案。
KIND 是 Kubernetes In Docker 的縮寫,透過 Docker Container 的方式創建節點並基於該節點創建 Kubernetes 叢集。
這邊要注意的是 KIND 透過 Docker 創建節點,而節點內卻使用 Contaeinrd 作為 k8s 的 CRI 解決方案。
除了 KIND 之外, Rancher 維護的 K3D 也是一樣類型的創建方式,其中 K3D 支持動態加入與移除節點,KIND 只能一開始創建時就定好 cluster 的大小。
https://nfrankel.medium.com/goodbye-minikube-340070edc5af
Medium
Goodbye minikube
I’ve been using minikube as my local cluster since I started to learn Kubernetes. But I’ve decided to let it go in favor of kind. Here’s…
本篇文章是一個經驗分享文,作者探討使用 Rancher 遇到的問題,以及最後是如何使用 Kubecost 來解決成本使用的分析問題。
作者認為 Rancher 對自己公司的 DevOps Team 來說是個非常好用的工具,透過 Rancher 的視覺化工具,任何人都可以清楚的去管理以及檢視當前 K8s 叢集內的各種資訊,對於任何加入團隊還不熟悉 Kubernetes 的開發者來說,Rancher 的特色讓這些新開發者容易上手,熟悉概念後再轉往理解 kubectl 等工具的使用。
不過作者公司團隊遇到的問題是 Kubernetes 內不同專案彼此的成本用量難以計算,雖然 Rancher 內有再提供一個 Project 的抽象介面,可以控管 Project 底下的 CPU/Memory 以及相關物件的分配。
但是這樣還是有三個問題沒有辦法解決
1. 無法有效且快速的知道每個 namsepace 底下於 Node 上所佔的資源比例
2. 當一個 Team 本身會使用到多個 namespace 時上述的計算會變得更加麻煩。
3. 團隊看透過 kubectl top 去計算,或是使用 Prometheus/Grafana 來整合計算,但是實際上還是一個困難的麻煩事
作者最後從 Rancher 的線上研討會中,聽到了 Kubecost 有趣的專案,該專案可以順利的與 Rancher 整合,基於 Rancher Project 作為基本分類,來檢視每個 Project 底下各種資源的使用量,同時搭配金額的分配還可以把使用量轉換成實際的金額,團隊更有能力去估算使用量。
有興趣的可以閱讀全文並且嘗試看看 kubecost 這個工具
https://itnext.io/kubecost-rancher-saved-df30fe77135b
作者認為 Rancher 對自己公司的 DevOps Team 來說是個非常好用的工具,透過 Rancher 的視覺化工具,任何人都可以清楚的去管理以及檢視當前 K8s 叢集內的各種資訊,對於任何加入團隊還不熟悉 Kubernetes 的開發者來說,Rancher 的特色讓這些新開發者容易上手,熟悉概念後再轉往理解 kubectl 等工具的使用。
不過作者公司團隊遇到的問題是 Kubernetes 內不同專案彼此的成本用量難以計算,雖然 Rancher 內有再提供一個 Project 的抽象介面,可以控管 Project 底下的 CPU/Memory 以及相關物件的分配。
但是這樣還是有三個問題沒有辦法解決
1. 無法有效且快速的知道每個 namsepace 底下於 Node 上所佔的資源比例
2. 當一個 Team 本身會使用到多個 namespace 時上述的計算會變得更加麻煩。
3. 團隊看透過 kubectl top 去計算,或是使用 Prometheus/Grafana 來整合計算,但是實際上還是一個困難的麻煩事
作者最後從 Rancher 的線上研討會中,聽到了 Kubecost 有趣的專案,該專案可以順利的與 Rancher 整合,基於 Rancher Project 作為基本分類,來檢視每個 Project 底下各種資源的使用量,同時搭配金額的分配還可以把使用量轉換成實際的金額,團隊更有能力去估算使用量。
有興趣的可以閱讀全文並且嘗試看看 kubecost 這個工具
https://itnext.io/kubecost-rancher-saved-df30fe77135b
Medium
Kubecost + Rancher = $$$ saved
I’ve written a few articles about how Rancher Cluster Manager (from Rancher acquired by SuSE) has been wonderful to our DevOps team. It’s…
本篇文章是一個技術探討文,探討 Docker 是如何使用硬碟空間以及當維運人員發現空間不足時應該要如何清理系統上的空間。
Docker 的便利使用方式使得開發人員可以非常簡的透過的 Container 的概念來運行各式各樣的應用程式,這中間牽扯包含 Image 的建置,抓取以及透過其產生出一個運行的 Container。
隨者時間愈用愈久,系統內可用的空間也會愈來愈少,這時候可以透過 docker system df 來觀看一下目前系統上的空間資訊,主要包含下列四種類型,而每個類型也會包含目前使用量以及可以回收的量有多少
1. Images
2. Containers
3. Local Volumes
4. Build Cache(只有 docker 18.09 後使用 buildkit 才會有)
當 Contaienr 被創建時, /var/lib/docker 底下會有很多檔案以及資料夾都被創建出來,譬如
- /var/lib/docker/containers/ID (資料夾):如果 container 使用的是預設的 logging driver,則 log 檔案都會以 JSON 的格式存放於這個資料夾底下。
所以要注意,當 contaienr 有太多 log 時,其會透過這個方式影響節點檔案系統的容量
- /var/lid/docker/overlay2 (資料夾): 這邊包含了 containers 本身的 read-write layer 的檔案,大部分 Linux 發行版預設都會使用 overlay2 來管理。此外 contaienr 內如果有存放任何額外檔案於系統中,實際上都會放這節點上的這個資料夾內。
接下來作者透過一個實際的範例,讓一個全新的 contaienr 內透過 dd 指令來產生一些檔案,並且觀察上述資料夾的變化以及 docker system df 的結果,最後介紹 docker prune 以及 docker rm 針對 contaienr 的處理。
關於 image 的部分,除了常規使用的 Image 外,還有
1. Dangling images: 不再被參考使用的 image,譬如 ID/Tag 都是 None 的
這邊可以透過 docker image ls -f dangling=true 的指令
文章後半部分還有介紹 docker volume 以及 build cache 的部分,這篇文章非常推薦大家閱讀,除了基本使用外還會介紹底層 docker 實際上用到的資料夾,有了這些概念未來對於如何清除 docker 環境就會更有概念,知道要刪除哪些資料夾以及為什麼要刪除。
https://betterprogramming.pub/docker-tips-clean-up-your-local-machine-35f370a01a78
Docker 的便利使用方式使得開發人員可以非常簡的透過的 Container 的概念來運行各式各樣的應用程式,這中間牽扯包含 Image 的建置,抓取以及透過其產生出一個運行的 Container。
隨者時間愈用愈久,系統內可用的空間也會愈來愈少,這時候可以透過 docker system df 來觀看一下目前系統上的空間資訊,主要包含下列四種類型,而每個類型也會包含目前使用量以及可以回收的量有多少
1. Images
2. Containers
3. Local Volumes
4. Build Cache(只有 docker 18.09 後使用 buildkit 才會有)
當 Contaienr 被創建時, /var/lib/docker 底下會有很多檔案以及資料夾都被創建出來,譬如
- /var/lib/docker/containers/ID (資料夾):如果 container 使用的是預設的 logging driver,則 log 檔案都會以 JSON 的格式存放於這個資料夾底下。
所以要注意,當 contaienr 有太多 log 時,其會透過這個方式影響節點檔案系統的容量
- /var/lid/docker/overlay2 (資料夾): 這邊包含了 containers 本身的 read-write layer 的檔案,大部分 Linux 發行版預設都會使用 overlay2 來管理。此外 contaienr 內如果有存放任何額外檔案於系統中,實際上都會放這節點上的這個資料夾內。
接下來作者透過一個實際的範例,讓一個全新的 contaienr 內透過 dd 指令來產生一些檔案,並且觀察上述資料夾的變化以及 docker system df 的結果,最後介紹 docker prune 以及 docker rm 針對 contaienr 的處理。
關於 image 的部分,除了常規使用的 Image 外,還有
1. Dangling images: 不再被參考使用的 image,譬如 ID/Tag 都是 None 的
這邊可以透過 docker image ls -f dangling=true 的指令
文章後半部分還有介紹 docker volume 以及 build cache 的部分,這篇文章非常推薦大家閱讀,除了基本使用外還會介紹底層 docker 實際上用到的資料夾,有了這些概念未來對於如何清除 docker 環境就會更有概念,知道要刪除哪些資料夾以及為什麼要刪除。
https://betterprogramming.pub/docker-tips-clean-up-your-local-machine-35f370a01a78
Medium
Docker Tips: Clean Up Your Local Machine
Understand disk space usage and reclaiming the unused part
這篇文章是 Tekton 這套號稱完全針對 Cloud-Native 所發展的 CI/CD 工具教學文,作者從基本概念到如何使用都詳細的介紹一番,讓讀者看完就對 Tekton 能夠有基本的認知。
就如同其他常見的 Pipeline 系統一樣,Tekton 的工作流程是由 Step, Task 以及 Pipeline 組成。Tekton 使用 Step 描述每個最小工作事項,而每個 Task 則由數個 Step 組成,這些 Step 會依序執行,且彼此會共用相同環境,譬如 Volume.
Pipeline 則是由數個 Task 所組成,不過比較特別的是這些 Task 可以有更為靈活的執行順序,譬如依序執行,平行執行,甚至是 DAG 這種有向無環圖的執行順序。
Tekton 的一大特色是其完全寄生於 Kubernetes 內,必須要搭配 k8s 的環境來使用,也因此上述的 Step,Task 以及 Pipeline 實質上都是屬於 K8s 的 CRD 一種,部署時需要透過 YAML 來撰寫,並且用常見的方式 (kubectl, helm, kustomize) 來安裝到 k8s 內去設定 Tekton。
這種模式帶來的一個好處就是每個元件都是獨立的 YAML 檔案與類別,因此相同的部分可以非常輕易的被重複使用,舉例來說一個運行 Git-Clone 的 Task 就可以被多個不同的 Pipeline 重複使用,而有需求需要修改的時候也只需要修改一個 Task 即可。
對於 Tekton 這套解決方案有興趣的可以參閱下列全文玩耍看看
https://lambda.grofers.com/adopting-tekton-cloud-native-ci-solution-67fb229f4992
就如同其他常見的 Pipeline 系統一樣,Tekton 的工作流程是由 Step, Task 以及 Pipeline 組成。Tekton 使用 Step 描述每個最小工作事項,而每個 Task 則由數個 Step 組成,這些 Step 會依序執行,且彼此會共用相同環境,譬如 Volume.
Pipeline 則是由數個 Task 所組成,不過比較特別的是這些 Task 可以有更為靈活的執行順序,譬如依序執行,平行執行,甚至是 DAG 這種有向無環圖的執行順序。
Tekton 的一大特色是其完全寄生於 Kubernetes 內,必須要搭配 k8s 的環境來使用,也因此上述的 Step,Task 以及 Pipeline 實質上都是屬於 K8s 的 CRD 一種,部署時需要透過 YAML 來撰寫,並且用常見的方式 (kubectl, helm, kustomize) 來安裝到 k8s 內去設定 Tekton。
這種模式帶來的一個好處就是每個元件都是獨立的 YAML 檔案與類別,因此相同的部分可以非常輕易的被重複使用,舉例來說一個運行 Git-Clone 的 Task 就可以被多個不同的 Pipeline 重複使用,而有需求需要修改的時候也只需要修改一個 Task 即可。
對於 Tekton 這套解決方案有興趣的可以參閱下列全文玩耍看看
https://lambda.grofers.com/adopting-tekton-cloud-native-ci-solution-67fb229f4992
Medium
Adopting Tekton — Cloud Native CI Solution
I have been exploring Tekton as a CI platform recently for my office and off-office work. So I thought to share all my findings with you…
本篇文章是個經驗分享系列文,作者探討 Kubernetes 內 15 種不被建議的部署策略與模式。
作者之前曾經撰寫過 Contianer 架構底下的部署模式探討,而本系列文(三篇)則是著重於如何將這些 containers 透過 Kubernetes 給部署到生產環境,總共會探討十五種不推薦的模式,接下來的三篇文章將會介紹各五種不好的模式。
Using containers with the latest tag in Kubernetes deployments
任何 container 的 image 都不應該使用 latest,因為 latest 本身沒有任何意義,這會使得維運人員沒有辦法掌握到底當前部署的版本是什麼,更嚴重的情況適當 latest 搭配 PullPolicy:Always 時會產生更為嚴重的問題。因為 Always 的策略導致每次 Pod 部署時都會重新抓取 image,所以一個 deployment 中,多個使用 latest tag 的 Pod 但是其實使用的 image hash 是不同的。
作者認為比較好的做法有
1. 所有 container image 都是不可修改的,一旦建立就禁止覆蓋,有任何改動就進版
2. 部署用的 image tag 使用有意義的版本名稱
補充: 實際上 pull image 也可以使用 sha256,譬如 "docker pull hwchiu/kubectl-tools@sha256:acfb56059e6d60bf4a57946663d16dda89e12bfb1f8d7556f277e2818680e4c8"
Baking the configuration inside container images
任何 contaienr image 建置的時候應該都要往通用的方向去設計,而不是參雜各種設定在裡面。著名的 12-factor app 裡面也有提到類似個概念,建置好的 image 應該要可以 build once, run everywhere,動態的方式傳入不同的設定檔案,而不是把任何跟環境有關的資訊都寫死
舉例來說,如果 image 內包含了下列設定(舉例,包含不限於)
1. 任何 IP 地址
2. 任何帳號密碼
3. 任何寫死的 URL
作者認為比較好的做法有
1. 透過動態載入的方式來設定運行時的設定,譬如Kubernetes configmaps, Hashicorp Consul, Apache Zookeeper 等
2. 根據不同程式語言與框架甚至可以做到不需要重啟容器就可以載入新的設定
Coupling applications with Kubernetes features/services for no reason
作者認為除了很明確專門針對 Kubernetes 使用,或是用來控制 Kubernetes 的應用程式外,大部分的 應用程式包裝成 Container 時就不應該假設只能運行在 Kubernetes 內。作者列舉了幾個常見的使用範例,譬如
1. 從 K8s label/annotation 取得資訊
2. 查詢當前 Pod 運行的資訊
3. 呼叫其他 Kubernetes 服務(舉例,假設環境已經存在 Vault,因此直接呼叫 vault API 來取得資訊)
作者認為這類型的綁定都會使得該應用程式無法於沒有 Kubernetes 的環境運行,譬如就沒有辦法使用 Docker-compose 來進行本地開發與測試,這樣就沒有辦法滿足 12-factor 中的精神。
對於大部分的應用程式測試,除非其中有任何依賴性的服務是跟外部 Kubernetes 綁定,否則這些測試應該都要可以用 docker-compose 來叫起整個服務進行測試與處理。
服務需要使用的資訊應該是運行期間透過設定檔案,環境變數等塞入到 Container 內,這樣也呼應上述的不要將與環境有關的任何資訊都放入 image 內。
Mixing application deployment with infrastructure deployment (e.g. having
Terraform deploying apps with the Helm provider)
作者認為近年來伴隨者 IaC 概念的熱門,愈來愈多的團隊透過 Terraform/Pulumi 這類型的工具來部署架構,作者認為將部署架構與部署應用程式放到相同一個 Pipeline 則是一個非常不好的做法。
將基礎架構與應用程式同時放在相同 pipeline 可以降低彼此傳遞資訊的困難性,能夠一次部署就搞定全部,然而這種架構帶來的壞處有
1. 通常應用程式改動的頻率是遠大於基礎架構的改變,因此兩者綁在一起會浪費許多時間在架構上
假如部署基礎架構需要 25 分鐘而應用
作者之前曾經撰寫過 Contianer 架構底下的部署模式探討,而本系列文(三篇)則是著重於如何將這些 containers 透過 Kubernetes 給部署到生產環境,總共會探討十五種不推薦的模式,接下來的三篇文章將會介紹各五種不好的模式。
Using containers with the latest tag in Kubernetes deployments
任何 container 的 image 都不應該使用 latest,因為 latest 本身沒有任何意義,這會使得維運人員沒有辦法掌握到底當前部署的版本是什麼,更嚴重的情況適當 latest 搭配 PullPolicy:Always 時會產生更為嚴重的問題。因為 Always 的策略導致每次 Pod 部署時都會重新抓取 image,所以一個 deployment 中,多個使用 latest tag 的 Pod 但是其實使用的 image hash 是不同的。
作者認為比較好的做法有
1. 所有 container image 都是不可修改的,一旦建立就禁止覆蓋,有任何改動就進版
2. 部署用的 image tag 使用有意義的版本名稱
補充: 實際上 pull image 也可以使用 sha256,譬如 "docker pull hwchiu/kubectl-tools@sha256:acfb56059e6d60bf4a57946663d16dda89e12bfb1f8d7556f277e2818680e4c8"
Baking the configuration inside container images
任何 contaienr image 建置的時候應該都要往通用的方向去設計,而不是參雜各種設定在裡面。著名的 12-factor app 裡面也有提到類似個概念,建置好的 image 應該要可以 build once, run everywhere,動態的方式傳入不同的設定檔案,而不是把任何跟環境有關的資訊都寫死
舉例來說,如果 image 內包含了下列設定(舉例,包含不限於)
1. 任何 IP 地址
2. 任何帳號密碼
3. 任何寫死的 URL
作者認為比較好的做法有
1. 透過動態載入的方式來設定運行時的設定,譬如Kubernetes configmaps, Hashicorp Consul, Apache Zookeeper 等
2. 根據不同程式語言與框架甚至可以做到不需要重啟容器就可以載入新的設定
Coupling applications with Kubernetes features/services for no reason
作者認為除了很明確專門針對 Kubernetes 使用,或是用來控制 Kubernetes 的應用程式外,大部分的 應用程式包裝成 Container 時就不應該假設只能運行在 Kubernetes 內。作者列舉了幾個常見的使用範例,譬如
1. 從 K8s label/annotation 取得資訊
2. 查詢當前 Pod 運行的資訊
3. 呼叫其他 Kubernetes 服務(舉例,假設環境已經存在 Vault,因此直接呼叫 vault API 來取得資訊)
作者認為這類型的綁定都會使得該應用程式無法於沒有 Kubernetes 的環境運行,譬如就沒有辦法使用 Docker-compose 來進行本地開發與測試,這樣就沒有辦法滿足 12-factor 中的精神。
對於大部分的應用程式測試,除非其中有任何依賴性的服務是跟外部 Kubernetes 綁定,否則這些測試應該都要可以用 docker-compose 來叫起整個服務進行測試與處理。
服務需要使用的資訊應該是運行期間透過設定檔案,環境變數等塞入到 Container 內,這樣也呼應上述的不要將與環境有關的任何資訊都放入 image 內。
Mixing application deployment with infrastructure deployment (e.g. having
Terraform deploying apps with the Helm provider)
作者認為近年來伴隨者 IaC 概念的熱門,愈來愈多的團隊透過 Terraform/Pulumi 這類型的工具來部署架構,作者認為將部署架構與部署應用程式放到相同一個 Pipeline 則是一個非常不好的做法。
將基礎架構與應用程式同時放在相同 pipeline 可以降低彼此傳遞資訊的困難性,能夠一次部署就搞定全部,然而這種架構帶來的壞處有
1. 通常應用程式改動的頻率是遠大於基礎架構的改變,因此兩者綁在一起會浪費許多時間在架構上
假如部署基礎架構需要 25 分鐘而應用
本文延續前一篇文章,作者探討十五種 Kubernetes 不該使用的部署與維運模式,總共三篇,每篇五種。
Using Kubectl as a debugging tool
作者認為一個良好的 Kubernetes 叢集必定要有一個相對應個可觀測性工具,包含 Metrics/Log/Tracing 等。對於一個維運人說來說,今天要處理事情時,第一件事情如果還是慢慢的用 kubectl 來執行 get, describe ,log 等指令找問題的話就太慢了,這類型的工具都應該只是輔助使用,真正還是要依賴有效的監控系統,不論是常見的系統指標,應用程式狀態甚至是應用程式獨特的指標等,將這些資訊整合到一個方便顯示的儀表板,甚至搭配對應的 Alert 功能來達到主動通知。
Misunderstanding Kubernetes network concepts
Kubernetes 內提供的網路功能很容易被搞混,Service(ClusterIP, NodePort, LoadBalancer) 與 Ingress 的差異到底是什麼,很多初次踏入 Kubernetes 的玩家沒有特別去理解差異,只知道應用程式部署後就可以通了。Service Mesh 這個概念作者也推薦去學習與瞭解,知道這個概念是什麼,以及想要什麼解決問題就好,因為並非不是每個叢集都真的需要一套 Service Mesh 的解決方案,但是理解這個概念未來就有能力知道什麼時候需要導入。
Using permanent staging environments instead of dynamic environments
對於應用程式開發者來說,如何於 Kubernetes 環境上測試新功能一直都是一個困難的問題。大部分的團隊中都會有 QA/Staging/Production/Dev(甚至更多)的環境,假設 Dev 環境可以供開發者測試,這些開發者要如何確保自己的修改沒有問題且通過整合測試。
一個常見的問題是假如多個開發者同事部署自己的程式碼到固定環境中,有可能會造成互相干擾,導致問題發生時沒有辦法正確的判別問題是誰產生的。
作者提到一種作法就是透過預借的概念,確保每個開發者使用叢集時都不會有他人干擾,然而這個問題也會引發其他問題,譬如開發者間要互相協調時間,同時每個人用完環境後都要還原成穩定的狀態,以免干擾下一位的使用。
作者推薦使用動態叢集的方式來進行測試,使用 Github PR 為範例,當 PR 開啟時,動態創建 Kubernetes 叢集供測試,當 PR 合併後就會將該 Cluster 給移除。透過這種範例每個開發者都可以有獨立的環境進行測試彼此不干擾,同時也會隨者程式碼的合併而自動回收環境,也不需要擔心環境污染問題。
Mixing production and non-production clusters
任何團隊一定要有正式生產環境的叢集跟其他叢集分隔開來,千萬不能使用 namespace 的方式於一個叢集中同時維護生產與非生產環境。譬如
1. 任何人操作 Kubernetes 都很容易失誤,譬如指令下錯,指向錯的物件。這類型的操作都有可能導致該叢集上生產環境被誤刪
2. namespace 的隔離性不好,實際上很多物件彼此還是可以互相存與溝通,這部分也有其他的隱憂
詳細原文可以參考下列連結。
https://medium.com/containers-101/kubernetes-deployment-antipatterns-part-2-2af25a710bc0
Using Kubectl as a debugging tool
作者認為一個良好的 Kubernetes 叢集必定要有一個相對應個可觀測性工具,包含 Metrics/Log/Tracing 等。對於一個維運人說來說,今天要處理事情時,第一件事情如果還是慢慢的用 kubectl 來執行 get, describe ,log 等指令找問題的話就太慢了,這類型的工具都應該只是輔助使用,真正還是要依賴有效的監控系統,不論是常見的系統指標,應用程式狀態甚至是應用程式獨特的指標等,將這些資訊整合到一個方便顯示的儀表板,甚至搭配對應的 Alert 功能來達到主動通知。
Misunderstanding Kubernetes network concepts
Kubernetes 內提供的網路功能很容易被搞混,Service(ClusterIP, NodePort, LoadBalancer) 與 Ingress 的差異到底是什麼,很多初次踏入 Kubernetes 的玩家沒有特別去理解差異,只知道應用程式部署後就可以通了。Service Mesh 這個概念作者也推薦去學習與瞭解,知道這個概念是什麼,以及想要什麼解決問題就好,因為並非不是每個叢集都真的需要一套 Service Mesh 的解決方案,但是理解這個概念未來就有能力知道什麼時候需要導入。
Using permanent staging environments instead of dynamic environments
對於應用程式開發者來說,如何於 Kubernetes 環境上測試新功能一直都是一個困難的問題。大部分的團隊中都會有 QA/Staging/Production/Dev(甚至更多)的環境,假設 Dev 環境可以供開發者測試,這些開發者要如何確保自己的修改沒有問題且通過整合測試。
一個常見的問題是假如多個開發者同事部署自己的程式碼到固定環境中,有可能會造成互相干擾,導致問題發生時沒有辦法正確的判別問題是誰產生的。
作者提到一種作法就是透過預借的概念,確保每個開發者使用叢集時都不會有他人干擾,然而這個問題也會引發其他問題,譬如開發者間要互相協調時間,同時每個人用完環境後都要還原成穩定的狀態,以免干擾下一位的使用。
作者推薦使用動態叢集的方式來進行測試,使用 Github PR 為範例,當 PR 開啟時,動態創建 Kubernetes 叢集供測試,當 PR 合併後就會將該 Cluster 給移除。透過這種範例每個開發者都可以有獨立的環境進行測試彼此不干擾,同時也會隨者程式碼的合併而自動回收環境,也不需要擔心環境污染問題。
Mixing production and non-production clusters
任何團隊一定要有正式生產環境的叢集跟其他叢集分隔開來,千萬不能使用 namespace 的方式於一個叢集中同時維護生產與非生產環境。譬如
1. 任何人操作 Kubernetes 都很容易失誤,譬如指令下錯,指向錯的物件。這類型的操作都有可能導致該叢集上生產環境被誤刪
2. namespace 的隔離性不好,實際上很多物件彼此還是可以互相存與溝通,這部分也有其他的隱憂
詳細原文可以參考下列連結。
https://medium.com/containers-101/kubernetes-deployment-antipatterns-part-2-2af25a710bc0
Medium
Kubernetes Deployment Antipatterns — part 2
This is the second part in our Kubernetes Anti-patterns series. See also part 1 for for the previous part and part 3 for the next part.
本篇文章是個經驗分享文,作者分享使用 Docker 作為開發環境時值得注意的 Best practices,透過這些經驗分享希望能夠讓開發者少走一些冤枉路。
原文提出了 15 個經驗談,這邊幫大家節錄幾個,有興趣的可以點選原文瞭解更多!
1. One thing at a time
2. Be ephemeral
3. Utilize .dockerignore
4. Less is more
5. Secrets should be secret
6. PID 1 is your birth right
7. Share and Care
8. Vulnerability Scan
9. Tag like you mean it
10. Permissions are costly
11. Source of Truth
12. Always official
13. Don’t include debug
14. Use entry point script smartly
15. Size does matter
One thing at a time
建置 Image 的時候專注做好一件事情,每個 Image 應該有一個專心要解決的問題,譬如一個應用程式,一個小工具等。對於 Nginx 這類型的 Image 來說,應該沒有人會期望於裡面看到有 Apache 的應用程式吧?
Be ephemeral
這個主要探討的是該 Image 本身建置時應該要以 stateless 的概念去處理,未來不論是透過 docker 或是 Kubernetes 來管理部署時,Contaienr 都很有機會被重啟,每次的重啟都意味該容器是重新啟動。所以千萬不要讓你的 Image 變成多次重啟會導致應用程式出問題的形式,任何的這類型資料應該都要透過外部取得,不要塞到你的 Image 內
Utilize .dockerignore
善用 .dockerignore 這個檔案來將不必要的檔案從 build 過程給排除,使用方法與 .gitignore 類似。透過這個檔案的設定可以避免 docker build 的時候不會把一些過大或是完全不需要的檔案都送給 docker daemon,不當浪費時間也浪費空間。
Less is more
避免安裝任何無關或是非必要的套件到你的 image 中,特別是那些 "nice to have" 的理由。
註: 我個人是滿討厭把 Image 弄得很乾淨的,除錯什麼工具都沒有,連 ash/sh/busybox/bash 都沒有的 image 更是我討厭中的排行榜冠軍
Secrets should be secret
任何機密資訊都應該要於運行期間動態載入,而不是建置期間塞入。請使用其他工具譬如 Vault 來管理這些機密資訊,並且執行期間讓 Container 能夠存取到正確的值。
PID 1 is your birth right
Linux 環境下會使用 SIGTERN, SIGKILL 等相關的 Singal 來戳你的應用程式,請確保你運行的應用程式要能夠攔截這些訊號來處理並完成有效的 Graceful shutdown.
Share and Care
如果環境中有多個 Image 彼此有共享相同的工具與功能,與其每個 Image 都單獨建置維護不如建置一個 Base Image,接者讓所有要使用的 image 去載入使用即可。
透過這種方式可以讓整體的維護性與管理性更為簡單,每個 image 可以減少重複的程式碼,同時要升級時只要針對 base Image 處理即可。
https://medium.com/pradpoddar/avoid-costly-mistakes-using-advanced-docker-development-best-practices-acd812784109
原文提出了 15 個經驗談,這邊幫大家節錄幾個,有興趣的可以點選原文瞭解更多!
1. One thing at a time
2. Be ephemeral
3. Utilize .dockerignore
4. Less is more
5. Secrets should be secret
6. PID 1 is your birth right
7. Share and Care
8. Vulnerability Scan
9. Tag like you mean it
10. Permissions are costly
11. Source of Truth
12. Always official
13. Don’t include debug
14. Use entry point script smartly
15. Size does matter
One thing at a time
建置 Image 的時候專注做好一件事情,每個 Image 應該有一個專心要解決的問題,譬如一個應用程式,一個小工具等。對於 Nginx 這類型的 Image 來說,應該沒有人會期望於裡面看到有 Apache 的應用程式吧?
Be ephemeral
這個主要探討的是該 Image 本身建置時應該要以 stateless 的概念去處理,未來不論是透過 docker 或是 Kubernetes 來管理部署時,Contaienr 都很有機會被重啟,每次的重啟都意味該容器是重新啟動。所以千萬不要讓你的 Image 變成多次重啟會導致應用程式出問題的形式,任何的這類型資料應該都要透過外部取得,不要塞到你的 Image 內
Utilize .dockerignore
善用 .dockerignore 這個檔案來將不必要的檔案從 build 過程給排除,使用方法與 .gitignore 類似。透過這個檔案的設定可以避免 docker build 的時候不會把一些過大或是完全不需要的檔案都送給 docker daemon,不當浪費時間也浪費空間。
Less is more
避免安裝任何無關或是非必要的套件到你的 image 中,特別是那些 "nice to have" 的理由。
註: 我個人是滿討厭把 Image 弄得很乾淨的,除錯什麼工具都沒有,連 ash/sh/busybox/bash 都沒有的 image 更是我討厭中的排行榜冠軍
Secrets should be secret
任何機密資訊都應該要於運行期間動態載入,而不是建置期間塞入。請使用其他工具譬如 Vault 來管理這些機密資訊,並且執行期間讓 Container 能夠存取到正確的值。
PID 1 is your birth right
Linux 環境下會使用 SIGTERN, SIGKILL 等相關的 Singal 來戳你的應用程式,請確保你運行的應用程式要能夠攔截這些訊號來處理並完成有效的 Graceful shutdown.
Share and Care
如果環境中有多個 Image 彼此有共享相同的工具與功能,與其每個 Image 都單獨建置維護不如建置一個 Base Image,接者讓所有要使用的 image 去載入使用即可。
透過這種方式可以讓整體的維護性與管理性更為簡單,每個 image 可以減少重複的程式碼,同時要升級時只要針對 base Image 處理即可。
https://medium.com/pradpoddar/avoid-costly-mistakes-using-advanced-docker-development-best-practices-acd812784109
Medium
Avoid costly mistakes using advanced Docker development Best Practices
Learn how to become a Top Docker developer applying these best practices used by senior developers in real world applications.
本文延續前一篇文章,作者探討十五種 Kubernetes 不該使用的部署與維運模式,總共三篇,每篇五種。
Misusing Health probes
Kubernetes 內有設定三種不同的 Probe,分別是 Readiness, Liveness 以及 Startup,前兩者 Probe 比較常被提到而且會不停的執行,而 Startup 則是會被運行一次的 Probe。
作者認為所有開發者都要去研究這三種的差異並且小心使用。
文章中列舉一些常見的錯誤用法
1. 用相同的 endpoint 同時處理 liveness 以及 readiness
2. 繼續沿用過往針對 VM 所設計的 health endpoint,應該要針對容器環境重新設計
3. Health 的檢查過於複雜,導致需要花費一個不可預測的時間
..
等
Not using the Helm package manager
作者認為目前 Kubernetes 生態系中只有一個 Package Manager,也就是 Helm,就像是常見的 apt/rpm 等套件般去管理不同的應用程式。
然而 Helm 卻很容易被誤解並拿去跟其他工具比較,譬如 Kustomize, Jsonnet.. 等。
從本質上來看 Helm, Helm 本身有 Package 的管理能力,同時也透過 Template 的方式來產生適合於不同環境的 YAML 檔案。 而上述其他的比較解決方案基本上都只能完成後者,透過如 overlay (kustomize) 等不同的方式來產生不同的 YAML,但是本身卻沒有去管理這些安裝好的應用程式。
如何產生 YAML 這些是部署前的流程,而上述的那些工具對於檔案部署到 Kubernetes 後就無能為力了,譬如想要刪除任何安裝到 Kubernetes 資源的應用程式,必須要找到原始的 YAML 檔案。而 Helm 則不一樣,本身會於 Cluster 內去記錄這些這些資訊,讓你可以透過 helm 的指令去刪除這些安裝好的應用程式。
作者認為除非團隊很明確的瞭解與設計其工作流程,確保 Helm 帶來的部署與管理流程不需要,否則推薦任何團隊都可以採用 Helm,特別是之前因為 Helm2 Tiller 而厭惡的人必須要來試試看 Helm3
Not having a strategy for secrets
如同先前探討的 Configuration 不應該直接嵌入 Contaienr Image 一樣,Secret 這類型的物件也一樣,作者看到團隊常有下列錯誤
1. 使用各種不同的方式來管理 Secret 物件
2. 沒有區分好運行期需要的 Secret 與建制時期需要的 Secret
3. 過於複雜的處理方式導致本地測試與開發過於困難
相反的,團隊應該要
1. 選擇一個策略
2. 所有團隊使用該策略來處理 Secret
3. 所有的 Secret 應該都要用相同的方式處理
4. 這樣的機制使得 secret 的管理與追蹤更為容易
Attempting to solve all problems with Kubernetes
永遠不要認為 Kubernetes 能夠解決所有問題,團隊必須要理解到 Kubernetes 帶來的優點與缺點,團隊本身的部署與工作流程是否適合使用 Kubernetes。
也不要想說要把所有服務都搬到 Kubernetes 內,譬如 databases, caching 等,這些本來就存在的解決方案依然可以使用本來的方式繼續部署,不要一相情願地覺得這些東西放到 Kubernetes 內就一定會更好。
詳細原文可以參考下列連結。
https://medium.com/containers-101/kubernetes-deployment-antipatterns-part-3-dfbdd2fd3292
Misusing Health probes
Kubernetes 內有設定三種不同的 Probe,分別是 Readiness, Liveness 以及 Startup,前兩者 Probe 比較常被提到而且會不停的執行,而 Startup 則是會被運行一次的 Probe。
作者認為所有開發者都要去研究這三種的差異並且小心使用。
文章中列舉一些常見的錯誤用法
1. 用相同的 endpoint 同時處理 liveness 以及 readiness
2. 繼續沿用過往針對 VM 所設計的 health endpoint,應該要針對容器環境重新設計
3. Health 的檢查過於複雜,導致需要花費一個不可預測的時間
..
等
Not using the Helm package manager
作者認為目前 Kubernetes 生態系中只有一個 Package Manager,也就是 Helm,就像是常見的 apt/rpm 等套件般去管理不同的應用程式。
然而 Helm 卻很容易被誤解並拿去跟其他工具比較,譬如 Kustomize, Jsonnet.. 等。
從本質上來看 Helm, Helm 本身有 Package 的管理能力,同時也透過 Template 的方式來產生適合於不同環境的 YAML 檔案。 而上述其他的比較解決方案基本上都只能完成後者,透過如 overlay (kustomize) 等不同的方式來產生不同的 YAML,但是本身卻沒有去管理這些安裝好的應用程式。
如何產生 YAML 這些是部署前的流程,而上述的那些工具對於檔案部署到 Kubernetes 後就無能為力了,譬如想要刪除任何安裝到 Kubernetes 資源的應用程式,必須要找到原始的 YAML 檔案。而 Helm 則不一樣,本身會於 Cluster 內去記錄這些這些資訊,讓你可以透過 helm 的指令去刪除這些安裝好的應用程式。
作者認為除非團隊很明確的瞭解與設計其工作流程,確保 Helm 帶來的部署與管理流程不需要,否則推薦任何團隊都可以採用 Helm,特別是之前因為 Helm2 Tiller 而厭惡的人必須要來試試看 Helm3
Not having a strategy for secrets
如同先前探討的 Configuration 不應該直接嵌入 Contaienr Image 一樣,Secret 這類型的物件也一樣,作者看到團隊常有下列錯誤
1. 使用各種不同的方式來管理 Secret 物件
2. 沒有區分好運行期需要的 Secret 與建制時期需要的 Secret
3. 過於複雜的處理方式導致本地測試與開發過於困難
相反的,團隊應該要
1. 選擇一個策略
2. 所有團隊使用該策略來處理 Secret
3. 所有的 Secret 應該都要用相同的方式處理
4. 這樣的機制使得 secret 的管理與追蹤更為容易
Attempting to solve all problems with Kubernetes
永遠不要認為 Kubernetes 能夠解決所有問題,團隊必須要理解到 Kubernetes 帶來的優點與缺點,團隊本身的部署與工作流程是否適合使用 Kubernetes。
也不要想說要把所有服務都搬到 Kubernetes 內,譬如 databases, caching 等,這些本來就存在的解決方案依然可以使用本來的方式繼續部署,不要一相情願地覺得這些東西放到 Kubernetes 內就一定會更好。
詳細原文可以參考下列連結。
https://medium.com/containers-101/kubernetes-deployment-antipatterns-part-3-dfbdd2fd3292
Medium
Kubernetes Deployment Antipatterns — part 3
This is the third and last part in our Kubernetes Anti-patterns series. See also part 1 and part 2 for the previous anti-patterns.
本篇文章是 Netflix 的內部架構技術分享文,本篇文章要探討的是當 Netflix 內部大量採用 Google Drives(Sheets, DDocs, Slides...etc)進行檔案分享時所遇到的問題,以及 Netflix 是如何解決這些問題的。
問題: 對 Netflix 來說,由於下列兩個理由,導致目前 Google Drive 上大概有兩千萬的檔案
1. Netflix Studio 的合作夥伴大量使用 Google Service 來傳輸資料
2. 資料科學家需要將資料複製回本地的 Data 倉庫進行分析。
Netflix 內部為了方便存取這些資料,透過程式化的方式透過 Google API 來存取這些大量成長的資料,然而這樣的方式卻導致了兩個很麻煩的問題
1. 應用程式開發者與資料科學家必須要各自維護存取 Google 服務的帳號密碼,同時很多程式碼會大量的被重複開發。
2. 從可觀測性系統來說,到底有哪些檔案資料從 Google Drive 與 Data 倉庫移動是很不清楚的。
Netflix 為了解決這些問題,決定自行打造一個 Service Proxy 來處理所有流向 Google Services 的請求。透過這個中介層的服務,Google 服務認證的部分就可以有效率的於 Proxy 這層來處理掉,同時也能夠透過 Log 的方式來記錄到底哪些檔案目前正在移動,彌補了過往可觀性系統的缺失。
文中先介紹了關於 Google API 的架構,Netflix 內部原先大部分都透過 Python 或 Java 等程式語言來撰寫 Client 端的應用程式。為了讓整個 Proxy 能夠更有效的處理 Credential 的部分,Netflix 這邊還導入的內部工具(Metatron) 來管理這些資訊。
其他相關資訊還有
1. Proxy 基於 Java 開發
2. 使用 gRPC 來產生不同語言的 endpoints,統一由 Proxy 將請求轉為 HTTP 送往 Google 處理
此外,為了讓 Netflix 內部的所有人都可以很輕鬆的於 Google Drive 與 Data 倉庫間來更動資料, Netflix 為此打造一個可排程的 Job 來默默執行。文章後半段主要在介紹這個 Job 的架構與用法
對於全文有興趣的都歡迎閱讀~
https://netflixtechblog.medium.com/data-movement-for-google-services-at-netflix-9a77ca69f7c4
問題: 對 Netflix 來說,由於下列兩個理由,導致目前 Google Drive 上大概有兩千萬的檔案
1. Netflix Studio 的合作夥伴大量使用 Google Service 來傳輸資料
2. 資料科學家需要將資料複製回本地的 Data 倉庫進行分析。
Netflix 內部為了方便存取這些資料,透過程式化的方式透過 Google API 來存取這些大量成長的資料,然而這樣的方式卻導致了兩個很麻煩的問題
1. 應用程式開發者與資料科學家必須要各自維護存取 Google 服務的帳號密碼,同時很多程式碼會大量的被重複開發。
2. 從可觀測性系統來說,到底有哪些檔案資料從 Google Drive 與 Data 倉庫移動是很不清楚的。
Netflix 為了解決這些問題,決定自行打造一個 Service Proxy 來處理所有流向 Google Services 的請求。透過這個中介層的服務,Google 服務認證的部分就可以有效率的於 Proxy 這層來處理掉,同時也能夠透過 Log 的方式來記錄到底哪些檔案目前正在移動,彌補了過往可觀性系統的缺失。
文中先介紹了關於 Google API 的架構,Netflix 內部原先大部分都透過 Python 或 Java 等程式語言來撰寫 Client 端的應用程式。為了讓整個 Proxy 能夠更有效的處理 Credential 的部分,Netflix 這邊還導入的內部工具(Metatron) 來管理這些資訊。
其他相關資訊還有
1. Proxy 基於 Java 開發
2. 使用 gRPC 來產生不同語言的 endpoints,統一由 Proxy 將請求轉為 HTTP 送往 Google 處理
此外,為了讓 Netflix 內部的所有人都可以很輕鬆的於 Google Drive 與 Data 倉庫間來更動資料, Netflix 為此打造一個可排程的 Job 來默默執行。文章後半段主要在介紹這個 Job 的架構與用法
對於全文有興趣的都歡迎閱讀~
https://netflixtechblog.medium.com/data-movement-for-google-services-at-netflix-9a77ca69f7c4
Medium
Data movement for Google services at Netflix
By Raghuram Onti Srinivasan and Tianlong Chen
本篇文章是一個入門文章,主要探討 GitOps 相關的起源與概念,同時介紹不少關於 GitOps 的工具
起源: Weaveworks 於 2017 年針對 Kubernetes 的工作環境產生了不同的部署方式,而 GitOps 這個詞也就那時開始萌芽發展
概念: 透過 Git PR 的方式來驗證與自動的部署所有與系統有關的修改。今天有任何部署的需求時,團隊要做的事情就是 1) 產生 Git PR 2)進行 Review 3) 合併 接者就是等任何修改被自動部署
Git 於整個環節中扮演者 Single Source of Truth 的角色,所有的修改都必須發生於 Git 本身,也因為是基於 Git 來使用,所以不論是 GitHub, Gitlab, Bitbucket, Gerrit 等系統都可以使用。
註: Bitbucket 還針對 GitOps 這種形式取了一個名為 BDDA 的名稱,意義為 Build-Diff-Deploy-Apply
好處:
1. 稽核性: 透過 Git 可以針對所有的修改去查閱,知道誰於什麼時間點進行什麼修改
2. 由於不需要將 Kubeconfig 等資源放到外部叢集,資安方面會比傳統外部直接Push/Apply 來得更好
3. 開發人員可以更容易地去部署應用,不需要仰賴Ops幫忙
4. ...etc
註: GitOps 並不是只能適用於 Kubernetes 本身,事實上整個系統架構都可以套用這種方式,譬如搭配 Terraform 等相關的 IaC 工具時,就可以透過 GitOps 來搭建整個系統,包含底層架構,k8s叢集以及最重要的應用程式
相關工具(文章列出滿多工具):
1. ArgoCD
2. Atlantis: Terraform PR 的自動化工具
3. Autoapply
4. CloudBees Rollout
5. FlexCD
6. Helm Operator
7. Flagger
8. Ignite
9. Faros
10. Gitkube
11. Jenkins X
12. KubeStack
13. Weave Cloud
14. Werf
15. PipeCD
https://medium.com/searce/gitops-the-next-big-thing-for-devops-and-automation-2a9597e51559
起源: Weaveworks 於 2017 年針對 Kubernetes 的工作環境產生了不同的部署方式,而 GitOps 這個詞也就那時開始萌芽發展
概念: 透過 Git PR 的方式來驗證與自動的部署所有與系統有關的修改。今天有任何部署的需求時,團隊要做的事情就是 1) 產生 Git PR 2)進行 Review 3) 合併 接者就是等任何修改被自動部署
Git 於整個環節中扮演者 Single Source of Truth 的角色,所有的修改都必須發生於 Git 本身,也因為是基於 Git 來使用,所以不論是 GitHub, Gitlab, Bitbucket, Gerrit 等系統都可以使用。
註: Bitbucket 還針對 GitOps 這種形式取了一個名為 BDDA 的名稱,意義為 Build-Diff-Deploy-Apply
好處:
1. 稽核性: 透過 Git 可以針對所有的修改去查閱,知道誰於什麼時間點進行什麼修改
2. 由於不需要將 Kubeconfig 等資源放到外部叢集,資安方面會比傳統外部直接Push/Apply 來得更好
3. 開發人員可以更容易地去部署應用,不需要仰賴Ops幫忙
4. ...etc
註: GitOps 並不是只能適用於 Kubernetes 本身,事實上整個系統架構都可以套用這種方式,譬如搭配 Terraform 等相關的 IaC 工具時,就可以透過 GitOps 來搭建整個系統,包含底層架構,k8s叢集以及最重要的應用程式
相關工具(文章列出滿多工具):
1. ArgoCD
2. Atlantis: Terraform PR 的自動化工具
3. Autoapply
4. CloudBees Rollout
5. FlexCD
6. Helm Operator
7. Flagger
8. Ignite
9. Faros
10. Gitkube
11. Jenkins X
12. KubeStack
13. Weave Cloud
14. Werf
15. PipeCD
https://medium.com/searce/gitops-the-next-big-thing-for-devops-and-automation-2a9597e51559
Medium
GitOps : The Next Big Thing for DevOps and Automation!
If you have similar questions like: “What’s GitOps?”, “Why we are moving towards this?”, “How and when one can implement this strategy in…
本篇文章是個經驗談,作者想要聊聊是如何將一個 4vCPU 的VM給調整到可以達到每秒處理 1.2M(120萬)個 JSON Reuqest,本篇文章非常的長,所以會分多天來介紹。
整篇文章探討的是各種 turning 的步驟,來聊聊如何從最初每秒 224k(22萬四千) 給調整到每秒 1.2M 的處理能力。
整個過程分成九大步驟,後面同時標示每個過程後的每秒請求能力
1. Application Optimizations (347k)
2. Speculative Execution Migtigations (446k)
3. Syscall Auditing/Blocking (495k)
4. Disabling iptables/netfilter (603k)
5. Perfect Locality (834k)
6. Interrypt Optimizations (1.06M)
7. The Case of the Nosy Neighbor (1.12M)
8. The Battle Against the Spin Lock (1.15M)
9. This Gost to Twelv (1.20M)
作者強調,上述的過程不一定適合你的應用程式,但是透過這些步驟能夠讓你更佳瞭解應用程式的運作行為,同時也有機會發現一些潛在的瓶頸問題。
環境介紹
1. 團隊使用 Techempower 來進行 JSON Serialization 的測試
2. 使用 libreactor(event-driven框架) 來搭建一個簡單的 API Server
3. HTTP 的解析使用 picohttpparser,同時使用 libclo 來處理 JSON 的編碼
4. 硬體環境
- Server: 4 vCPU, c5n.xlarge AWS VM
- Client: 16 vCPU, c5n.4xlarge AWS VM (clinet太弱會變成瓶頸)
- Network: Server/Client 屬於同一個可用區域(AZ)
5. 軟體環境
- 作業系統: Amazon Linux2 (Kernel 4.14)
- Server: 使用 libreactor (使用不同版本,分別是 Round18 以及 Round20)
- Client: 修改 wrk 這個知名的工具並重新命名為 twrk,詳細差異自己看文章內部,主要都跟顯示有關
6. 實驗方式
- 每個測試跑三次,取中間值
- 256 連線,16 threads,同時每個 thread 都會 pin 到一個固定的 CPU
- 每個實驗都有兩秒的暖機時間來建立連線
Ground Zero
第一個要探討的就是什麼最佳化都還沒有使用前,到底當前應用程式可能的瓶頸在哪裏
首先團隊將該應用程式與其他常見的應用程式或是開發框架比較,譬如 Netty, Nginx, Actix, aspcore 等, libreactor 的效能不錯,有中上水準。
接者作者使用火焰圖(Flame Graphs)來 Profile 該伺服器,作者很好心地將文章中所有的火焰圖都調整了一下,讓所有的 user-space 相關的 function call 都轉成藍色,而剩下跟 kernel 相關都維持紅色。
1. 大部分的時間都在 Kernel 處理
2. 主要是花費在收封包與送封包
3. 應用程式本身主要是分兩大部分,解析 HTTP 的封包以及處理請求與回應。
從上述兩點來看,作者認為目前的應用程式寫得算不錯,因為瓶頸很明顯是卡在 Kernel 端
接下來就正式進入到各種 Turning 的章節探討
Application Optimizations
長話短說:
- 作者基於 libreactor Round18 的框架進行修改,並且所有的修改都已經被合併到 Round20 的版本中,而這些修改主要是實作方面的強化以及整個框架的最佳化。
1. 作者首先透過 htop 觀察運行過程,發現 Server 只有使用 2vCPU 而已(系統有 4vCPU),因此這是作者進行的第一個修改,讓 Server 使用了 4vCPU,這個簡單調整就讓效能提升 25%
註: 作者特別強調,不要覺得從 2vCPU 變成 4vCPU 效能就可以變成兩倍,主要是1) 沒有使用的 vCPU 還有很多其他的工作要處理,因此不是完全都送給你應用程式處理。2)基於 hypter-thread vCPU 的架構,環境只有兩個真正的 CPU 而是透過邏輯的方式產生四個抽象的 CPU,所以全用一定會變快,但是基於很多資源還是要競爭與共用,數字不是單純翻倍
2. 作者自己的應用程式本身使用 gcc 建置時有使用 "-o3" 的方式來最佳化處理,然而框架本身卻沒有使用 "-o3" 的方式來弄,因此作者也針對這個部分來處理,讓建制框架時能夠使用 -o3
3. 從實作方面來看,作者觀察到 libreactor 1.0 版本使用的是 read/write 這兩個常見的方式來處理封包的送收,作者將其修改成 recv/send 整個效能就提升了將近 10%。
註: write(針對 FD,更全面廣泛的用法) 與 send(針對 Socket,更針對的用法) 使用上差異不大,但是 write 於底層 Kernel 最終還是會呼叫到 send 來處理,所以基本上可以理解就是在沒有特別參數需求時,可以直接跳過幾個 kernel function 來達到加速的效果。
write kernel 內的走向: sys_write -> vfs_write -> __vfs_write -> sock_write_iter -> sock_sendmsg
send kernel 內的走向: sendto -> sock_sendmsg
4. 作者觀察到火焰圖中有一些 pthread 相關的資料,進而發現 libreactor 會創造一個 thread pool 來處理非同步的 DNS 名稱解析問題。對於一個 HTTP Client 來說,如果今天要發送請求到多個不同的 domain,而每個 domain 都會需要進行一個 blocking 的解析過程,透過這種方式可以減少 DNS 解析造成的 blocking 問題。然而對於 HTTP Server 來說,這個使用情境帶來的效益似乎就稍微低了些,畢竟 Server 只有 Bind Socket 之前可能會需要去解析一次 DNS 而已。
大部分的情境下, thread pool 都是應用程式初期會去創造而接者就不太會管她,但是對於錙銖必較的效能除錯人來說,任何能夠調整的部分都可能是個值得探討的地方。
作者透過修改 Server 端(準確來說是 libreactor 框架內的程式碼)關於 Thread Pool 的一些用法,成長的讓整個效能提升了 2~3%
結論來說,透過上述四個概念來提升的程式碼效能。
1. vCPU 盡量使用: 25%-27%
2. 使用 gcc -O3 來建置框架的程式碼: 5%-10%
3. 使用 march=native 等參數來建置最後的 server 應用程式: 5%-10%
4. 使用 send/recv 而非 write/read: 5%-10%
5. 修改 pthread 的用法: 2%-3%
註: 作者強調每個最佳化的結果並非是單純累積的概念,反而還會有互補的效果。
可能前述的操作實際上也會讓後續的操作達到更好的效果,
譬如如果先跑 vCPU 的調整,效能大概提升 25%,但是如果先執行別的最佳化過程,最後再來調整 vCPU,就可以達到 40% 的效果,主要是 CPU 可以共有效率的去執行程式。
最後,這個部分讓整個處理封包能力從 224k 提升了 55% 到 347k (req/s)。
從火焰圖來看,整個 user-space 的範圍縮小許多,同時 send/recv 的處理也有使得整體的高度下降一點點(大概四格..)
為了避免文章過長,本篇文章就探討第一個最佳化的過程,剩下的就敬請期待後續!
https://talawah.io/blog/extreme-http-performance-tuning-one-point-two-million/
整篇文章探討的是各種 turning 的步驟,來聊聊如何從最初每秒 224k(22萬四千) 給調整到每秒 1.2M 的處理能力。
整個過程分成九大步驟,後面同時標示每個過程後的每秒請求能力
1. Application Optimizations (347k)
2. Speculative Execution Migtigations (446k)
3. Syscall Auditing/Blocking (495k)
4. Disabling iptables/netfilter (603k)
5. Perfect Locality (834k)
6. Interrypt Optimizations (1.06M)
7. The Case of the Nosy Neighbor (1.12M)
8. The Battle Against the Spin Lock (1.15M)
9. This Gost to Twelv (1.20M)
作者強調,上述的過程不一定適合你的應用程式,但是透過這些步驟能夠讓你更佳瞭解應用程式的運作行為,同時也有機會發現一些潛在的瓶頸問題。
環境介紹
1. 團隊使用 Techempower 來進行 JSON Serialization 的測試
2. 使用 libreactor(event-driven框架) 來搭建一個簡單的 API Server
3. HTTP 的解析使用 picohttpparser,同時使用 libclo 來處理 JSON 的編碼
4. 硬體環境
- Server: 4 vCPU, c5n.xlarge AWS VM
- Client: 16 vCPU, c5n.4xlarge AWS VM (clinet太弱會變成瓶頸)
- Network: Server/Client 屬於同一個可用區域(AZ)
5. 軟體環境
- 作業系統: Amazon Linux2 (Kernel 4.14)
- Server: 使用 libreactor (使用不同版本,分別是 Round18 以及 Round20)
- Client: 修改 wrk 這個知名的工具並重新命名為 twrk,詳細差異自己看文章內部,主要都跟顯示有關
6. 實驗方式
- 每個測試跑三次,取中間值
- 256 連線,16 threads,同時每個 thread 都會 pin 到一個固定的 CPU
- 每個實驗都有兩秒的暖機時間來建立連線
Ground Zero
第一個要探討的就是什麼最佳化都還沒有使用前,到底當前應用程式可能的瓶頸在哪裏
首先團隊將該應用程式與其他常見的應用程式或是開發框架比較,譬如 Netty, Nginx, Actix, aspcore 等, libreactor 的效能不錯,有中上水準。
接者作者使用火焰圖(Flame Graphs)來 Profile 該伺服器,作者很好心地將文章中所有的火焰圖都調整了一下,讓所有的 user-space 相關的 function call 都轉成藍色,而剩下跟 kernel 相關都維持紅色。
1. 大部分的時間都在 Kernel 處理
2. 主要是花費在收封包與送封包
3. 應用程式本身主要是分兩大部分,解析 HTTP 的封包以及處理請求與回應。
從上述兩點來看,作者認為目前的應用程式寫得算不錯,因為瓶頸很明顯是卡在 Kernel 端
接下來就正式進入到各種 Turning 的章節探討
Application Optimizations
長話短說:
- 作者基於 libreactor Round18 的框架進行修改,並且所有的修改都已經被合併到 Round20 的版本中,而這些修改主要是實作方面的強化以及整個框架的最佳化。
1. 作者首先透過 htop 觀察運行過程,發現 Server 只有使用 2vCPU 而已(系統有 4vCPU),因此這是作者進行的第一個修改,讓 Server 使用了 4vCPU,這個簡單調整就讓效能提升 25%
註: 作者特別強調,不要覺得從 2vCPU 變成 4vCPU 效能就可以變成兩倍,主要是1) 沒有使用的 vCPU 還有很多其他的工作要處理,因此不是完全都送給你應用程式處理。2)基於 hypter-thread vCPU 的架構,環境只有兩個真正的 CPU 而是透過邏輯的方式產生四個抽象的 CPU,所以全用一定會變快,但是基於很多資源還是要競爭與共用,數字不是單純翻倍
2. 作者自己的應用程式本身使用 gcc 建置時有使用 "-o3" 的方式來最佳化處理,然而框架本身卻沒有使用 "-o3" 的方式來弄,因此作者也針對這個部分來處理,讓建制框架時能夠使用 -o3
3. 從實作方面來看,作者觀察到 libreactor 1.0 版本使用的是 read/write 這兩個常見的方式來處理封包的送收,作者將其修改成 recv/send 整個效能就提升了將近 10%。
註: write(針對 FD,更全面廣泛的用法) 與 send(針對 Socket,更針對的用法) 使用上差異不大,但是 write 於底層 Kernel 最終還是會呼叫到 send 來處理,所以基本上可以理解就是在沒有特別參數需求時,可以直接跳過幾個 kernel function 來達到加速的效果。
write kernel 內的走向: sys_write -> vfs_write -> __vfs_write -> sock_write_iter -> sock_sendmsg
send kernel 內的走向: sendto -> sock_sendmsg
4. 作者觀察到火焰圖中有一些 pthread 相關的資料,進而發現 libreactor 會創造一個 thread pool 來處理非同步的 DNS 名稱解析問題。對於一個 HTTP Client 來說,如果今天要發送請求到多個不同的 domain,而每個 domain 都會需要進行一個 blocking 的解析過程,透過這種方式可以減少 DNS 解析造成的 blocking 問題。然而對於 HTTP Server 來說,這個使用情境帶來的效益似乎就稍微低了些,畢竟 Server 只有 Bind Socket 之前可能會需要去解析一次 DNS 而已。
大部分的情境下, thread pool 都是應用程式初期會去創造而接者就不太會管她,但是對於錙銖必較的效能除錯人來說,任何能夠調整的部分都可能是個值得探討的地方。
作者透過修改 Server 端(準確來說是 libreactor 框架內的程式碼)關於 Thread Pool 的一些用法,成長的讓整個效能提升了 2~3%
結論來說,透過上述四個概念來提升的程式碼效能。
1. vCPU 盡量使用: 25%-27%
2. 使用 gcc -O3 來建置框架的程式碼: 5%-10%
3. 使用 march=native 等參數來建置最後的 server 應用程式: 5%-10%
4. 使用 send/recv 而非 write/read: 5%-10%
5. 修改 pthread 的用法: 2%-3%
註: 作者強調每個最佳化的結果並非是單純累積的概念,反而還會有互補的效果。
可能前述的操作實際上也會讓後續的操作達到更好的效果,
譬如如果先跑 vCPU 的調整,效能大概提升 25%,但是如果先執行別的最佳化過程,最後再來調整 vCPU,就可以達到 40% 的效果,主要是 CPU 可以共有效率的去執行程式。
最後,這個部分讓整個處理封包能力從 224k 提升了 55% 到 347k (req/s)。
從火焰圖來看,整個 user-space 的範圍縮小許多,同時 send/recv 的處理也有使得整體的高度下降一點點(大概四格..)
為了避免文章過長,本篇文章就探討第一個最佳化的過程,剩下的就敬請期待後續!
https://talawah.io/blog/extreme-http-performance-tuning-one-point-two-million/
talawah.io
Extreme HTTP Performance Tuning: 1.2M API req/s on a 4 vCPU Instance
This post will walk you through the performance tuning steps that I took to serve 1.2 million JSON 'API' requests per second from a 4 vCPU AWS EC2 instance.
本文延續前篇效能校正的經驗談,上篇文章探討了關於應用程式本身可以最佳化的部分,包含了應用程式以及框架兩個部分。本篇文章將繼續剩下最佳化步驟的探討。
Speculative Execution Mitigations
接下來探討這個最佳化步驟對於效能有顯著的提升,但是本身卻是一個非常具有爭議性的步驟,因為其涉及到整個系統的安全性問題。
如果大家對前幾年非常著名的安全性漏洞 Spectre/Meltdown 還有印象的話,本次這個最佳化要做的就是關閉這類型安全性漏洞的處理方法。
標題的名稱 Speculative Execution Migitations 主要跟這漏洞的執行概念與 Pipeline 有關,有興趣理解這兩種漏洞的可以自行研究。
作者提到,大部分情況下這類型的防護能力都應該打開,不應該關閉。不過作者認為開關與否應該是一個可以討論的空間,特別是如果已經確認某些特別情境下,關閉防護能力帶來的效能如果更好,其實也是一個可以考慮的方向。
舉例來說,假設今天你運行了基於 Linux 使用者權限控管與 namespaces 等機制來建立安全防護的多使用者系統,那這類型的防護能力就不能關閉,必須要打開來防護確保整體的 Security Boundary 是完整的。 但是如果今天透過 AWS EC2 運行一個單純的 API Server,假設整個機器不會運行任何不被信任的程式碼,同時使用 AWS Nitro Enclaves 來保護任何的機密資訊,那這種情況下是否有機會可以關閉這類型的檢查?
作者根據 AWS 對於安全性的一系列說明認為 AWS 本身針對記憶體的部分有很強烈的保護,包含使用者之間沒有辦法存取 Hyperviosr 或是彼此 instance 的 Memory。
總之針對這個議題,有很多的空間去討論是否要關閉,以下就單純針對關閉防護能力帶來的效能提升。
作者總共關閉針對四種攻擊相關的處理能力,分別是
1 Spectre V1 + SWAPGS
2 Spectre V2
3 Spectre V3/Meltdown
4 MDS/Zombieload, TSX Anynchronous Abort
5 與此同時也保留剩下四個,如 iTLB multihit, SRBDS 等
這種設定下,整體的運作效能再次提升了 28% 左右,從 347k req/s 提升到 446k req/s。
註: 任何安全性的問題都不要盲從亂遵循,都一定要評估判斷過
Syscall Auditing/Blocking
大部分的情況下,Linux/Docker 處理關於系統呼叫 Auditing/Blocking 兩方面所帶來的效能影響幾乎微乎其微,不過當系統每秒執行數百萬個系統呼叫時,這些額外的效能負擔則不能忽視,如果仔細觀看前述的火焰圖的話就會發線 audit/seccomp 等數量也不少。
Linux Kernel Audit 子系統提供了一個機制來收集與紀錄任何跟安全性有關的事件,譬如存取敏感的機密檔案或是呼叫系統呼叫。透過這些內容可以幫助使用者去除錯任何不被預期的行為。
Audit 子系統於 Amazon Linux2 的環境下預設是開啟,但是本身並沒有被設定會去紀錄系統呼叫的資訊。
即使 Audit 子系統沒有真的去紀錄系統呼叫的資訊,該子系統還是會對每次的系統呼叫產生一點點的額外處理,所以作者透過
註: 根據 Redhat bugzilla issue #1117953, Fedora 預設是關閉這個行為的
Docker/Container 透過一連串 Linux Kernel 的機制來隔離與控管 Container 的執行權限,譬如 namespace, Linux capabilities., cgroups 以及 seccomp。
Seccomp 則是用來限制這些 Container 能夠執行的系統呼叫類型
大部分的容器化應用程式即使沒有開啟 Seccomp 都能夠順利的執行,執行 docker 的時候可以透過
將這兩個機制關閉後,系統帶來的效能提升了 11%,從 446k req/s 提升到 495k req/s。
從火焰圖來看,關閉這兩個設定後,syscall_trace_enter 以及 syscall_slow_exit_work 這兩個系統呼叫也從火焰圖中消失,此外作者發現 Amazon Linux2 預設似乎沒有啟動 Apparmor 的防護,因為不論有沒有關閉效能都沒有特別影響。
Disabling iptables/netfilter
再來的最佳化則是跟網路有關,大名鼎鼎的 netfilter 子系統,其中非常著名的應用 iptables 可以提供如防火牆與 NAT 相關功能。根據前述的火焰圖可以觀察到,netfilter 的進入 function nf_hook_slow 佔據了大概 18% 的時間。
將 iptables 關閉相較於安全性來說比較沒有爭議,反而是功能面會不會有應用程式因為 iptables 關閉而不能使用。預設情況下 docker 會透過 iptables 來執行 SNAT與 DNAT(有-p的話)。
作者認為現在環境大部分都將 Firewall 的功能移到外部 Cloud 來處理,譬如 AWS Security Group 了,所以 Firewall 的需求已經減少,至於 SNAT/DNAT 這類型的處理可以讓容器與節點共享網路來處理,也就是運行的時候給予 “–network=host” 的模式來避免需要 SNAT/DNAT 的情境。
作者透過修改腳本讓開機不會去預設載入相關的 Kernel Module 來達到移除的效果,測試起來整體的效能提升了 22%,從 495k req/s 提升到 603k req/s
註: 這個議題需要想清楚是否真的不需要,否則可能很多應用都會壞掉
作者還特別測試了一下如果使用 iptables 的下一代框架 nftables 的效能,發現 nftables 的效能好非常多。載入 nftables 的kernel module 並且沒有規則的情況下,效能幾乎不被影響(iptables 則相反,沒有規則也是會影響速度)。作者認為採用 nftables 似乎是個更好的選擇,能夠有效能的提升同時也保有能力的處理。
不過 nftables 的支援相較於 iptables 來說還是比較差,不論是從 OS 本身的支援到相關第三方工具的支援都還沒有這麼完善。就作者目前的認知, Debian 10, Fedora 32 以及 RHEL 8 都已經轉換到使用 nftables 做為預設的處理機制,同時使用 iptables-nft 這一個中介層的轉換者,讓所有 user-space 的規則都會偷偷的轉換為底層的 nftables。
Ubuntu 似乎要到 20.04/20.10 的正式版本才有嘗試轉移到的動作,而 Amazon Linux 2 依然使用 iptables 來處理封包。
下篇文章會繼續從剩下的五個最佳化策略繼續介紹
https://talawah.io/blog/extreme-http-performance-tuning-one-point-two-million/
Speculative Execution Mitigations
接下來探討這個最佳化步驟對於效能有顯著的提升,但是本身卻是一個非常具有爭議性的步驟,因為其涉及到整個系統的安全性問題。
如果大家對前幾年非常著名的安全性漏洞 Spectre/Meltdown 還有印象的話,本次這個最佳化要做的就是關閉這類型安全性漏洞的處理方法。
標題的名稱 Speculative Execution Migitations 主要跟這漏洞的執行概念與 Pipeline 有關,有興趣理解這兩種漏洞的可以自行研究。
作者提到,大部分情況下這類型的防護能力都應該打開,不應該關閉。不過作者認為開關與否應該是一個可以討論的空間,特別是如果已經確認某些特別情境下,關閉防護能力帶來的效能如果更好,其實也是一個可以考慮的方向。
舉例來說,假設今天你運行了基於 Linux 使用者權限控管與 namespaces 等機制來建立安全防護的多使用者系統,那這類型的防護能力就不能關閉,必須要打開來防護確保整體的 Security Boundary 是完整的。 但是如果今天透過 AWS EC2 運行一個單純的 API Server,假設整個機器不會運行任何不被信任的程式碼,同時使用 AWS Nitro Enclaves 來保護任何的機密資訊,那這種情況下是否有機會可以關閉這類型的檢查?
作者根據 AWS 對於安全性的一系列說明認為 AWS 本身針對記憶體的部分有很強烈的保護,包含使用者之間沒有辦法存取 Hyperviosr 或是彼此 instance 的 Memory。
總之針對這個議題,有很多的空間去討論是否要關閉,以下就單純針對關閉防護能力帶來的效能提升。
作者總共關閉針對四種攻擊相關的處理能力,分別是
1 Spectre V1 + SWAPGS
2 Spectre V2
3 Spectre V3/Meltdown
4 MDS/Zombieload, TSX Anynchronous Abort
5 與此同時也保留剩下四個,如 iTLB multihit, SRBDS 等
這種設定下,整體的運作效能再次提升了 28% 左右,從 347k req/s 提升到 446k req/s。
註: 任何安全性的問題都不要盲從亂遵循,都一定要評估判斷過
Syscall Auditing/Blocking
大部分的情況下,Linux/Docker 處理關於系統呼叫 Auditing/Blocking 兩方面所帶來的效能影響幾乎微乎其微,不過當系統每秒執行數百萬個系統呼叫時,這些額外的效能負擔則不能忽視,如果仔細觀看前述的火焰圖的話就會發線 audit/seccomp 等數量也不少。
Linux Kernel Audit 子系統提供了一個機制來收集與紀錄任何跟安全性有關的事件,譬如存取敏感的機密檔案或是呼叫系統呼叫。透過這些內容可以幫助使用者去除錯任何不被預期的行為。
Audit 子系統於 Amazon Linux2 的環境下預設是開啟,但是本身並沒有被設定會去紀錄系統呼叫的資訊。
即使 Audit 子系統沒有真的去紀錄系統呼叫的資訊,該子系統還是會對每次的系統呼叫產生一點點的額外處理,所以作者透過
auditctl -a never,task 這個方式來將整體關閉。註: 根據 Redhat bugzilla issue #1117953, Fedora 預設是關閉這個行為的
Docker/Container 透過一連串 Linux Kernel 的機制來隔離與控管 Container 的執行權限,譬如 namespace, Linux capabilities., cgroups 以及 seccomp。
Seccomp 則是用來限制這些 Container 能夠執行的系統呼叫類型
大部分的容器化應用程式即使沒有開啟 Seccomp 都能夠順利的執行,執行 docker 的時候可以透過
--security-opt seccomp=unconfined 這些參數告訴系統運行 Container 的時候不要套用任何 seccomp 的 profile.將這兩個機制關閉後,系統帶來的效能提升了 11%,從 446k req/s 提升到 495k req/s。
從火焰圖來看,關閉這兩個設定後,syscall_trace_enter 以及 syscall_slow_exit_work 這兩個系統呼叫也從火焰圖中消失,此外作者發現 Amazon Linux2 預設似乎沒有啟動 Apparmor 的防護,因為不論有沒有關閉效能都沒有特別影響。
Disabling iptables/netfilter
再來的最佳化則是跟網路有關,大名鼎鼎的 netfilter 子系統,其中非常著名的應用 iptables 可以提供如防火牆與 NAT 相關功能。根據前述的火焰圖可以觀察到,netfilter 的進入 function nf_hook_slow 佔據了大概 18% 的時間。
將 iptables 關閉相較於安全性來說比較沒有爭議,反而是功能面會不會有應用程式因為 iptables 關閉而不能使用。預設情況下 docker 會透過 iptables 來執行 SNAT與 DNAT(有-p的話)。
作者認為現在環境大部分都將 Firewall 的功能移到外部 Cloud 來處理,譬如 AWS Security Group 了,所以 Firewall 的需求已經減少,至於 SNAT/DNAT 這類型的處理可以讓容器與節點共享網路來處理,也就是運行的時候給予 “–network=host” 的模式來避免需要 SNAT/DNAT 的情境。
作者透過修改腳本讓開機不會去預設載入相關的 Kernel Module 來達到移除的效果,測試起來整體的效能提升了 22%,從 495k req/s 提升到 603k req/s
註: 這個議題需要想清楚是否真的不需要,否則可能很多應用都會壞掉
作者還特別測試了一下如果使用 iptables 的下一代框架 nftables 的效能,發現 nftables 的效能好非常多。載入 nftables 的kernel module 並且沒有規則的情況下,效能幾乎不被影響(iptables 則相反,沒有規則也是會影響速度)。作者認為採用 nftables 似乎是個更好的選擇,能夠有效能的提升同時也保有能力的處理。
不過 nftables 的支援相較於 iptables 來說還是比較差,不論是從 OS 本身的支援到相關第三方工具的支援都還沒有這麼完善。就作者目前的認知, Debian 10, Fedora 32 以及 RHEL 8 都已經轉換到使用 nftables 做為預設的處理機制,同時使用 iptables-nft 這一個中介層的轉換者,讓所有 user-space 的規則都會偷偷的轉換為底層的 nftables。
Ubuntu 似乎要到 20.04/20.10 的正式版本才有嘗試轉移到的動作,而 Amazon Linux 2 依然使用 iptables 來處理封包。
下篇文章會繼續從剩下的五個最佳化策略繼續介紹
https://talawah.io/blog/extreme-http-performance-tuning-one-point-two-million/
talawah.io
Extreme HTTP Performance Tuning: 1.2M API req/s on a 4 vCPU Instance
This post will walk you through the performance tuning steps that I took to serve 1.2 million JSON 'API' requests per second from a 4 vCPU AWS EC2 instance.