昨天受邀參加 CNTUG 社群所舉行的一場線上分享會,來跟大家探討一下最近 Kubernetes 1.20 的議題,也就是 dockershim 的退休倒數計畫
為了能夠更加充分地去理解這次的改動,我們必須要對 Docker, Kubernetes, CRI 以及 OCI 這四個關鍵字有所瞭解,當你對這些東西的彼此關係都熟悉與清楚後,你就會發現這次的改動其實沒太大影響,對於開發者來說幾乎是毫無感覺。而系統維運者甚至服務提供者則是會因為底層軟體的變動而會有一些轉移的過程需要去思索該怎麼做。
昨天與會人數將近125人,討論非常踴躍,等會議錄影處理完畢後會再釋出,到時候大家可以再次回味。
這邊用比較簡單的敘述去幫大家稍微釐清一下標題四個元件的差異。
以下概念我們主要探討的是 2020 當下的架構,過往舊版的架構不列入考慮之中,有心力與興趣的可以再去挖掘這些架構演進
1. Docker 是 Contianer 的解決方案之一,除了 Docker 外也有別的方案可以提供 Container 的應用與環境,因此要注意,不要再說 Container 就是 Docker。 這句話於現在是一個完全錯誤的說法
2. 有一個叫做 OCI (Open Container Initiative) 的概念,旨於標準化 Container 環境,該標準定義了兩大項,分別是 Runtime 以及 Image.
Runtime 定義了該如何運行一個 Container,而 Image 則定義了 Image 的格式
4. Docker 解決方案產生出的 image 是完全遵循 OCI Image 格式,而 Docker 運行的 Container 也是遵循 OCI Runtime。
精準的說 Docker 指令會把內容送給 Dockerd,而 dockerd 會再把運行的指令送給 containerd,而 containerd 最後會叫起一個基於 OCI Runtime 標準實作的解決方案 Runc,最後產生出運行的 Container。
4. 根據上述架構,Docker 產生出的 image 以及運行的 container 其實最後都跟 OCI 標準脫不了勾
5. Kubernetes 一開始就表明我是 Container 管理平台,不是 Docker 管理平台,希望能夠支援不同的 Container 解決方案。 Docker 只是其中之一罷了
6. Kubernetes 希望透過 CRI (Container Runtime Interface) 來銜接各式各樣的容器解決方案
7. Docker 出世的時間早於 Kubernetes,因此 Kubernetes 無法使用 CRI 來直接銜接 Docker
8. 因此 Kubernetes 設計與實作了一個名為 dockershim 的中間層,該層透過 CRI 與 Kubernetes 溝通,同時往下與 docker 溝通來創建最後的 container.
9. 一旦 dockershim 被移除後, kubernetes 還是繼續使用 CRI 的介面與 Container 解決方案溝通,只是 docker 這邊就找不到一個很好的角色來串接彼此的對話。
10. 其他的解決方案,譬如 containerd, CRI-O,其底層的實作也都相容於 OCI 標準。這意味你透過 docker build 產生的 image 是可以於上述兩個解決方案去運行的。
因為大家都是基於 OCI 標準
所以這次的影響對於開發者來說毫無感覺,繼續使用 docker 還是可以讓你的服務交給 Kubernetes 處理,只要底層使用的解決方案也是相容 OCI 標準。
相關影片: https://www.youtube.com/watch?v=nc3mBN3LzvM&feature=youtu.be
相關投影片: https://www2.slideshare.net/hongweiqiu/the-relationship-between-docker-kubernetes-and-cri
docker概念 在 矽谷牛的耕田筆記 Facebook 八卦
本篇文章是一個技術探討文,探討 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概念 在 矽谷牛的耕田筆記 Facebook 八卦
本篇文章是個經驗分享系列文,作者探討 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 分鐘而應用
https://codefresh.io/kubernete.../kubernetes-antipatterns-1/
docker概念 在 Docker 基本架構概念教學3D圖解教學 - YouTube 的八卦
圖片式 Docker 教學與入門basic concept is a tutorial for docker beginners about how containers interact with docker images across multiple ... ... <看更多>