Kubernetes [0] — 組成架構基本概念

Yu-Jing Lin
19 min readJun 18, 2024

--

一個真正厲害的工程師,是可以把技術概念講的連你阿嬤都聽的懂,那才是真的懂。

這句話是一位貴人告訴我的,到現在我都還謹記在心。當你透徹了解一個概念、或是一個服務,能用自己的話,甚至是用對方聽得懂的比喻來告訴對方,這差不多就代表你真的懂了。

很早就想說要寫個學習記錄了,但一直拖一直拖,直到最近終於下定決心(其實是看了一堆理論概念實作啊怕忘記幹哈哈哈哈)

第一篇的複習文!老實講從工作以來我都很不愛寫文件,更不要說是寫這種(我覺得)很硬的架構概念釐清文,因為我要他媽的能說服我自己不要寫出連自己都覺得恩你公三小?的內容(ㄏ)

跟k8s糾纏了這些年我到底懂不懂你,來吧!

歡迎各路高手前輩前來鞭,有錯誤的話請儘管留言讓我知道,先跪謝了~

用任何服務或應用之前當然要知道為什麼要用吧?所以咱先來從…

Agenda

  1. 什麼是微服務(Microservice)?
  2. Kubernetes是什麼?為什麼要用它?
  3. 基本架構和物件

1. 什麼是微服務?

試想看看,你是一個住在單人雅房的人,這房間你除了睡覺之外在床上滑手機基本上就是在這空間活動。有一天突然你升官加薪了,哇靠太爽辣我要提升我的生活品質!

於是你隨口就亂提一個想法,跟房屋仲介說:欸,我想要改善我的生活空間。

但房仲跟你說,恩~醬子喔~那您可以:

  1. 把你的包袱款款欸,搬去套房
  2. 把你的包袱再款款欸,搬去更大間的雅房
  3. 哇嗚那你有沒有考慮要搬去信義區更好的房間呀?多買/組一間當工作室?
  4. 哇哇哇嗚那你有沒有要再…….(你已經懶得聽下去了)

那就看你怎麼決定,但這幾件事情對你來說都很麻煩啊?

欸不是,收行李欸?

超煩的我不行,你要打包你所有的東西(光想到我要把我的衣服保養化妝品飾品包包裝起來就已經夠嗆的了),而且你還要重新擺設東西會不會因為忘記漏掉搬的過程中傢俱或你的物品會不會損壞而且你還要聯絡搬家公司或自己很吃力地想辦法來搬家

很麻煩吧?

所以微服務就這樣出現了。(三小?)

開玩笑的啦,是大概這種的感覺,所以微服務的概念就這樣產生了。

當一個公司或是一個項目,隨著也許是時間,它的需求越來越不同樣,或是服務的對象數量越來越多….等等各式各項的需要把它變成能負荷各種狀況。

有需求才會有供應嘛,所以為啥在講k8s之前要講到微服務?

因為它是從這個概念衍生出來的應用。

如果以前面的比喻例子來說,那微服務的特性和優點有什麼?

比白話/技術的來說…

(以下的技術部份會在後面詳細聊)

  1. 方便打包(Portable)
    - 一個房間裡面的所有東西通通打包在一起,連桌子椅子的方位樣子都可以包在一起,誰都不會被漏掉,直接變魔術一樣丟到新空間裡!
    - 將項目的內容變成image更新到repo裡,只要下載image之後compose起來在宿主的機器上,就可直接進入到項目使用其項目!
  2. 可延展(extensible)
    - 想要租更大間的,不需要將房間打通,直接空間變大或是多租幾間屬於你的房間,可以活動和邀請的朋友來的更多!
    - 假設一個網站的client端請求變多,或是服務本身需要的資源增加,只需要在設定檔中修改。
  3. 服務種類劃分(Specialized)
    - 只能睡覺的雅房不能滿足我,我要廚房要浴室要巴拉巴拉其他功能的空間!
    - 應用的邏輯或功能增加,新增的服務和原有的服務互不影響,資源另外分配。
  4. 不用停機的更新(Autonomous)
    - 新家會自己佈置好,不用很可憐的先搬一些過去,等到全部搬完或是必需品搬完先住到新家還是留在舊家。而且你的傢俱還不會壞掉,跟之前一樣!
    - 在需要不能有downtime的服務中,先建立可承接client端的instance們,讓使用者感覺不到有停機時間。
  5. 更新便捷(Agility)
    - 今天我裝了一般的單門冰箱,但隔天看到雙門豪華冰箱在特價而且我現在就超他媽想要它!現在right now就出現在我的家裡!
    - 配合CI/CD部署,實現版本快速更新,縮短開發週期。
  6. 抗錯力(Resilience)
    - 三小為什麼我房間有蟑螂?阿熱水器怎麼不熱了叫我洗冷水澡喔還是要我自己燒柴?之前不是好好的嗎?叫我先搬到其他間去住?你在跟我開玩笑逆?(沒有)
    - 有時候服務的某一個instance掛掉了,系統會自動起一個新的instance,將錯誤的instance殺死,幾乎對使用者來說並沒有影響使用體驗。

落落長舉了這一串,不外乎就是圍繞在三件事情上:

可彈性延展,部署或更新快速,服務可靠性提升。

以前在微服務出現之前,大家頂多就是用在伺服器上裝上vm(虛擬環境)以分割資源,但是這樣還是在原本的作業系統上分割出其他作業系統來乘載著應用服務啊~還是很佔空間。

隨著container的概念出現,Docker這個應用被廣泛使用。這種利用只裝載所需要用到的應用程式以及對應的資源環境的方式,大大減少了宿主資源的佔用,而且在不同平台上都可以實現。

咱來看看下圖:
infrastrucrure就是你的硬體設備
Host Operating System就是你的作業系統(OS),可能是類linux系列,也有可能是windows,都可以,只要你有裝Docker 在你的OS裡
再來就是Docker,透過它,你只要拉取別人寫好的image,或是自己編寫image,之後compose起來後,就可以透過指令進入該container(ex:AppA, AppB, …., AppF)

ref:https://www.docker.com/resources/what-container/

講了這麼多從原生os進化到container化,那乾Kubernetes有啥關係?
有喔,你這麼有錢買這麼多房間或空間,阿你要怎麼管?

這時候你需要一個管家/執事,幫你管理你的大!平!台!

真的先不用我去吐等等回來

2. Kubernetes是什麼?為什麼要用它?

再試想一下,你現在有一堆application,總不能每次都 $ docker ps去看他們的狀態吧?

誰死了誰還活著我還要用一些指令grep啦 awk啦 去篩選掉我不要的output
早期有Docker Swarm,這邊就不細展開了,有興趣的可以自己去官方文件看看定義。
簡言之Docker Swarm和Kubernetes的差別是,Docker Swarm一但application的種類變複雜了,不同架構的服務出現,很難進行有效的管理,Kubernetes在這塊就能處理你的問題。
當然,這並不是就代表Kubernestes就是唯一所有情境的解,還是要看需求是什麼,再來選擇要用哪種工具來管理你的container們

好啊那Kubernetes聽起來很屌,那是一個怎樣的工具?
先來看一下官方定義:

Kubernetes is a portable, extensible, open source platform for managing containerized workloads and services, that facilitates both declarative configuration and automation. It has a large, rapidly growing ecosystem. Kubernetes services, support, and tools are widely available.

有沒有發現一些關鍵字?(剛剛上面我有偷抄(欸
這些關鍵字正好打中現在的大部分公司的開發需求。要擴容、要能快速部署、功能種類不同、設定上的修改便利及統一….等等的。

當你的量一開始大、邏輯變複雜,你就得去思考你要怎麼有效率的管理你的application們了

Kubernetes就是應映這種狀況產生出來的一個容器管理平台。

在官方文件中,有很明確地指出它的特性可以解決什麼樣的情形,挑幾個(我覺得大家比較常提到的)用簡單的用白話說:

  1. Service discovery and load balancing: 部署在k8s裡的服務一定是有很多很多很多種類或是同個服務會被頻繁的拜訪,k8s就提供三種不同的服務(ingress, serivce port, pod port)可以被外界拜訪(expose)的方式。同時,如果服務被頻繁的拜訪,k8s也提供LB(load balancing)的功能,來維持服務的穩定度
  2. Storage orchestration: 在存儲這塊,由於container本身的目標是提供服務,並不包含把一些生產出來的log或是本身因邏輯需要去讀取存儲空間一起包進container,於是k8s提供多種不同的存儲方式,你可以是連結使用公用雲,或是自己的私有存儲空間,例如可以掛載Ceph作為你的存儲空間
  3. Automated rollouts and rollbacks: 身為維運,咱服務對象當然有我們的後端夥伴們,當他們今天在進行部署的時候,提供給他們方便的CI/CD流程之外,建立該應用程式的所需資源和特性都可以透過設定檔進行部署
  4. Automatic bin packing: 和第一點有點關聯,由於需要承接著大量的traffic,所以一個節點的資源不夠,那就多起幾個節點,k8s只要在指定好服務起起來的設定,就可以根據目前個節點資源使用狀況自動分配到各個集群內。
  5. Self-healing: 這就是我們前面提到的Autonomous,k8s會自動監控目前服務的穩定狀況,如果有哪個pod掛掉了,他會趕快湊齊起設定值需要的pod數且確定是可以被client端正常訪問的,再殺掉掛掉的pod,釋出資源。
  6. Secret and configuration management: 有些參數不適合哈扣寫在程式裡,例如用環境變數來隱藏明文密碼,k8s就有提供這種功能,而且可以根據不同的serivce來制定相關規定
  7. Horizontal scaling: 所謂的橫向擴容,指的可以是一個serivce的pod數或cluster中的slave/worker node的增加或減少,目的是讓資源可以充分的被利用最大化。

講完了他的好處,那當然有些事情不是k8s擅長的、準確來說,是不適合拿來用k8s來處理你的需求。

以我自己的經驗,在官方文件中最有感的是這段

Does not provide application-level services, such as middleware (for example, message buses), data-processing frameworks (for example, Spark), databases (for example, MySQL), caches, nor cluster storage systems (for example, Ceph) as built-in services. Such components can run on Kubernetes, and/or can be accessed by applications running on Kubernetes through portable mechanisms, such as the Open Service Broker.

以上的核心重點就是:沒有必要就不要全部服務上k8啦!
那這時候你應該會

阿哩洗咧?

什麼叫做必要? 什麼叫做沒必要?
舉個最簡單的例子,文中提到的存儲服務-MySQL, Ceph
兩者本身的目的是用來存儲資料,重點並不在提供服務邏輯。
今天你把他上了k8s,container化了,但他每次的動作都會去讀取另外和k8s連結的storage裡的內容,那是不是很沒必要?container裡本身並不會有1TB的disk儲存空間給單一那個container呀,更何況你起mysql這個服務只可能起一個pod嗎?那這樣跟你找一台伺服器或一個vm環境就是專門做mysql這個服務的是不是差不多?

Spark也是類似邏輯,在得到任務後,經過stage的劃分,不同節點要運算的task會動用到的資源不一定能讓每個container可以順利的完成,當然詳細還是要看你怎麼去部署spark,但這在部署起來上會麻煩許多,還不如單一一個spark cluster去執行任務來的方便,這就是我覺得的不必要。在之後我會繼續寫複習spark的運作原理。

再來列出一些官方文件中提及,個人有感的幾個點:

  1. 沒有提供CI/CD的功能,k8s只協助你讓你制定的規則可以有效地被管理和運行
  2. 如果你想要知道部署在上頭的log檔,你沒有在你的應用程式裡把log印出來或是導出到另外的存儲服務或是資料流中,你是找不到你的log的。還是那句話,k8s只幫你導出你應用程式有吐出來的內容,他不會自己去幫你抓的。所以在log部分的制訂和導出也是相當自由。

總結的來說,Kubernetes只是一個平台,協助你去管理你的產品們,所有的一切都由你來定義,他就是照著你給的定義去運行,去維護。他並不是一個萬靈丹,所有服務都上他(?)就可以解決了,更多的是要思考:

這個服務適合在container上運行嗎?

這句話也許很白話也存在很多漏洞,這是目前我覺得最直白的思考方向。(還請多指點)

3. 基本架構和物件

好這次沒有要試想了阿哈哈哈哈哈,要來結實的討論一下Kubernetes的基本架構!

從物理層面來看,Kubernestes的集群會分成主從兩種(master-slave)。

在Master中,作為主要的腦袋(也就是control plane)是作為發號司令的端口。
而在Slave(Worker),Node 1, Node 2這種就是worker node。所有的服務都會起在這邊的node上。

上圖是代表一個Kubernetes集群基本的組成架構,可以看到在Master裡面,有幾個主要的物件(Components):

  1. kube-apiserver
    可以想像是發號指令的司令台,負責接收來自其他物件的reponse和發送resquest。那發號指令的人就是user我們本人,平常下的kubectl都會透過api server去調動其他物件動起來去部署。
  2. scheduler
    負責調度新的pod去哪個/些node。依照k8s自帶的邏輯(會有一個評比標準)根據條件去判斷pod的去向,也就是放在哪個node上最適合。
  3. controller manager
    這個物件其實分成很多thread執行,因為有太多resouce種類要去監控,主要的功能就是去監控目前worker上的資源調度狀況,以維持集群的運行狀況正常。
    以下幾個是常見的controller: Node controller, Job controller, EndpointSlice controller(service<>pod), Deployment Controller…還有很多種。
  4. etcd
    主要的功能是用來儲存和備份整個cluster的metadata,例如儲存每個物件的api key、 操作信息日誌、物件們的設定信息。它本身是一個key-value型態的分布式儲存系統,同時,他也身兼如果master掛掉了,它寫入的metadata就可以恢復之前的設定。

再來就是實際上我們部署的application跑在上面的worker node啦!他們比較命苦,就是實際上做事的人,啊剛剛那個master就是出一張嘴的那種(?

  1. kubelet
    每個worker node上一定會有kubelet,他的工作就是負責跟出一張嘴的master回報現在我的工作量是多少,也就是現在他身上有多少個pod,然後運行狀況怎麼樣。因此這樣api server好將要增減的服務要部署的pod指揮下去。當scheduler決定要在你這台node上部署增/減的pod的時候,scheduler會把pod的相關配置設定告訴kubelet, 由kubelet去進行pod的更改
  2. kube-proxy
    像是作為這個集群的網路管理員的一樣,會出現在每個worker node上,主要的作用是維護每個node上的network rules。這些network rules允許從集群內部或外部的網路與 Pod 進行通訊。
  3. pod
    是k8s裡面最小的一個單位,雖然說沒有在官方文件裡表示它是一個component,但我通篇一直講到它所以還是放在worker node裡講。第一,它只會存在在worker node,因為它是運行服務的基本單位。不管今天是你自己起的web serivce或是什麼鬼東西,重要的是,剛剛提到的每個 component,它們實際上都是會起pod的(啊不然是要怎麼跑,用想的喔),如果你檢查kube-system這個namespace裡的pod有哪些,你就會發現有一坨他們(?

另外,有一個特別來賓,它在官方文檔和其他大神們分享的文章中定位是在master和worker node上都會跑的一個物件,他實際上的在做的事情就是建container,跑跑跑跑跑,哇死掉了,那再摸一蓋(?)它就叫container runtime!
官方文檔對它的描述很抽象:

A fundamental component that empowers Kubernetes to run containers effectively. It is responsible for managing the execution and lifecycle of containers within the Kubernetes environment.

粗暴的來說,一般它會是docker,你所有的pod裡的container是他在跑的,也可以大概的說他就是container們,我找了又找看到

The container runtime in Kubernetes is a foundational technology that powers the execution of containers across a cluster. It’s responsible for image management, container execution, networking, and storage, providing the necessary isolation and resource management required by containers

以上引用自國外大神的敘述,這裡明確的指出他是實際執行container的一個應用。

但是!

前面有說,k8s是一個容器的管控平台,docker並不是唯一一個可以container化的engine,所以其實還有別的可以選,例如cri-o, container-d。這些被通稱為CRI(Container Runtime Interface),講跑太抽象了,我們要有一個中介、一個協定去讓這些container建起來,他們的狀態怎麼樣,這些都是落到CRI上。各種container runtime的程序提供符合CRI的接口,這樣kubelet就可以知道這些container在每個node上面的狀況了。

聽起來這兩個東西好像沒什麼差,就差那一點點?

幹這東西太抽象我到底要怎麼解釋

不,他們差一點點就差很多,你必須且一定要有裝CRI,所以你的container才會有人去理他。少它不行~

以上是Kubernetes的基本介紹,有任何錯誤跪請各路大神指正,也歡迎底下留言跟我討論,咱下一篇,運行流程,還有常用的resource type(面試最愛考的啊deployment跟replication set差在哪裡啦~statefulset, deamonset差在哪裡啊~)

下!篇!見!

靠邀寫文章真的好耗力氣

在此致上最大的敬意給每一位分享技術文章的大大們

好人一生平安(夠ㄌ

--

--

Yu-Jing Lin

Data / DevOps / SRE engineer. Ex-Microsoft, Ex-Garena