最近學完了,docker基礎就想學習學習k8s,花了一段時間搭建好了。但是現在要從那些地方入手,學習呢。感覺網上系統性的資料太少,都很零散。所以求助知乎大神,給個建議的學習路線。 我是做運維的。 開發路線就不要推薦了。謝謝。


我半年前剛接觸K8S的時候,跟LZ遇到一樣的問題!特別能夠體會這種感受,所以花了很大力氣學習之後決心要把K8S整理分享出來,希望能夠有所幫助。

回顧整個學習的過程,我個人的建議是:先了解K8S是什麼?做什麼的?以及K8S幾個重要的、常見的概念(在K8S中被稱為資源)。有了K8S大概的認知之後,再去深入了解更多的概念(資源)、以及更深入了解其機制。循序漸進,豈不更好?

在正式介紹之前,先自薦一波自己的文章(更多後續的文章,還在路上),歡迎交流學習:

我是小北挖哈哈:K8S系列一:概念入門?

zhuanlan.zhihu.com圖標我是小北挖哈哈:K8S系列二:實戰入門?

zhuanlan.zhihu.com圖標

首先,K8S是什麼?

K8S是Kubernetes的全稱,官方稱其是:

Kubernetes is an open source system for managing containerized applications across multiple hosts. It provides basic mechanisms for deployment, maintenance, and scaling of applications.

用於自動部署、擴展和管理「容器化(containerized)應用程序」的開源系統。

翻譯成大白話就是:「K8S是負責自動化運維管理多個Docker程序的集群」。那麼問題來了:為什麼要用K8S,它有什麼優勢?

再來,為什麼是K8S?

試想下傳統的後端部署辦法:把程序包(包括可執行二進位文件、配置文件等)放到伺服器上,接著運行啟動腳本把程序跑起來,同時啟動守護腳本定期檢查程序運行狀態、必要的話重新拉起程序。

有問題嗎?顯然有!最大的一個問題在於:如果服務的請求量上來,已部署的服務響應不過來怎麼辦?傳統的做法往往是,如果請求量、內存、CPU超過閾值做了告警,運維馬上再加幾台伺服器,部署好服務之後,接入負載均衡來分擔已有服務的壓力。

問題出現了:從監控告警到部署服務,中間需要人力介入!那麼,有沒有辦法自動完成服務的部署、更新、卸載和擴容、縮容呢?

這,就是K8S要做的事情:自動化運維管理Docker(容器化)程序

最後,K8S怎麼做?

我們已經知道了K8S的核心功能:自動化運維管理多個容器化程序。那麼K8S怎麼做到的呢?這裡,我們從宏觀架構上來學習K8S的設計思想。首先看下圖,圖片來自文章Components of Kubernetes Architecture:

K8S是屬於主從設備模型(Master-Slave架構),即有Master節點負責核心的調度、管理和運維,Slave節點則在執行用戶的程序。但是在K8S中,主節點一般被稱為Master Node或者Head Node(本文採用Master Node稱呼方式),而從節點則被稱為Worker Node或者Node(本文採用Worker Node稱呼方式)。

總結來看,K8S的Master Node具備:請求入口管理(API Server),Worker Node調度(Scheduler),監控和自動調節(Controller Manager),以及存儲功能(etcd);而K8S的Worker Node具備:狀態和監控收集(Kubelet),網路和負載均衡(Kube-Proxy)、保障容器化運行環境(Container Runtime)、以及定製化功能(Add-Ons)。

到這裡,相信你已經對K8S究竟是做什麼的,有了大概認識。接下來,再來認識下K8S的Deployment、Pod、Replica Set、Service等,但凡談到K8S,就繞不開這些名詞,而這些名詞也是最讓K8S新手們感到頭疼、困惑的。


Pod實例

官方對於Pod的解釋是:

Pod是可以在 Kubernetes 中創建和管理的、最小的可部署的計算單元。

這樣的解釋還是很難讓人明白究竟Pod是什麼,但是對於K8S而言,Pod可以說是所有對象中最重要的概念了!因此,我們必須首先清楚地知道「Pod是什麼」,再去了解其他的對象。

從官方給出的定義,聯想下「最小的xxx單元」,是不是可以想到本科在學校里學習「進程」的時候,教科書上有一段類似的描述:資源分配的最小單位;還有」線程「的描述是:CPU調度的最小單位。什麼意思呢?」最小xx單位「要麼就是事物的衡量標準單位,要麼就是資源的閉包、集合。前者比如長度米、時間秒;後者比如一個」進程「是存儲和計算的閉包,一個」線程「是CPU資源(包括寄存器、ALU等)的閉包。

同樣的,Pod就是K8S中一個服務的閉包。這麼說的好像還是有點玄乎,更加雲里霧裡了。簡單來說,Pod可以被理解成一群可以共享網路、存儲和計算資源的容器化服務的集合。再打個形象的比喻,在同一個Pod里的幾個Docker服務/程序,好像被部署在同一台機器上,可以通過localhost互相訪問,並且可以共用Pod里的存儲資源(這裡是指Docker可以掛載Pod內的數據卷,數據卷的概念,後文會詳細講述,暫時理解為「需要手動mount的磁碟」)。筆者總結Pod如下圖,可以看到:同一個Pod之間的Container可以通過localhost互相訪問,並且可以掛載Pod內所有的數據卷;但是不同的Pod之間的Container不能用localhost訪問,也不能掛載其他Pod的數據卷

Deployment 和 ReplicaSet(簡稱RS)

除了Pod之外,K8S中最常聽到的另一個對象就是Deployment了。那麼,什麼是Deployment呢?官方給出了一個要命的解釋:

一個 Deployment 控制器為 Pods 和 ReplicaSets 提供聲明式的更新能力。

你負責描述 Deployment 中的 目標狀態,而 Deployment 控制器以受控速率更改實際狀態, 使其變為期望狀態。你可以定義 Deployment 以創建新的 ReplicaSet,或刪除現有 Deployment,並通過新的 Deployment 收養其資源。

翻譯一下:Deployment的作用是管理和控制Pod和ReplicaSet,管控它們運行在用戶期望的狀態中。哎,打個形象的比喻,Deployment就是包工頭,主要負責監督底下的工人Pod幹活,確保每時每刻有用戶要求數量的Pod在工作。如果一旦發現某個工人Pod不行了,就趕緊新拉一個Pod過來替換它。

新的問題又來了:那什麼是ReplicaSets呢?

ReplicaSet 的目的是維護一組在任何時候都處於運行狀態的 Pod 副本的穩定集合。 因此,它通常用來保證給定數量的、完全相同的 Pod 的可用性。

再來翻譯下:ReplicaSet的作用就是管理和控制Pod,管控他們好好乾活。但是,ReplicaSet受控於Deployment。形象來說,ReplicaSet就是總包工頭手下的小包工頭

筆者總結得到下面這幅圖,希望能幫助理解:

K8S Deployment、ReplicaSet和Pod關係圖

新的問題又來了:如果都是為了管控Pod好好乾活,為什麼要設置Deployment和ReplicaSet兩個層級呢,直接讓Deployment來管理不可以嗎?

回答:不清楚,但是私以為是因為先有ReplicaSet,但是使用中發現ReplicaSet不夠滿足要求,於是又整了一個Deployment(有清楚Deployment和ReplicaSet聯繫和區別的小夥伴歡迎留言啊)。

但是,從K8S使用者角度來看,用戶會直接操作Deployment部署服務,而當Deployment被部署的時候,K8S會自動生成要求的ReplicaSet和Pod。在K8S官方文檔中也指出用戶只需要關心Deployment而不操心ReplicaSet:

This actually means that you may never need to manipulate ReplicaSet objects: use a Deployment instead, and define your application in the spec section.

這實際上意味著您可能永遠不需要操作ReplicaSet對象:直接使用Deployments並在規範部分定義應用程序。

補充說明:在K8S中還有一個對象 --- ReplicationController(簡稱RC),官方文檔對它的定義是:

ReplicationController 確保在任何時候都有特定數量的 Pod 副本處於運行狀態。 換句話說,ReplicationController 確保一個 Pod 或一組同類的 Pod 總是可用的。

怎麼樣,和ReplicaSet是不是很相近?在Deployments, ReplicaSets, and pods教程中說「ReplicationController是ReplicaSet的前身」,官方也推薦用Deployment取代ReplicationController來部署服務。

Service和Ingress

吐槽下K8S的概念/對象/資源是真的多啊!前文介紹的Deployment、ReplicationController和ReplicaSet主要管控Pod程序服務;那麼,Service和Ingress則負責管控Pod網路服務

我們先來看看官方文檔中Service的定義:

將運行在一組 Pods 上的應用程序公開為網路服務的抽象方法。

使用 Kubernetes,您無需修改應用程序即可使用不熟悉的服務發現機制。 Kubernetes 為 Pods 提供自己的 IP 地址,並為一組 Pod 提供相同的 DNS 名, 並且可以在它們之間進行負載均衡。

翻譯下:K8S中的服務(Service)並不是我們常說的「服務」的含義,而更像是網關層,是若干個Pod的流量入口、流量均衡器。

那麼,為什麼要Service呢

私以為在這一點上,官方文檔講解地非常清楚:

Kubernetes Pod 是有生命周期的。 它們可以被創建,而且銷毀之後不會再啟動。 如果您使用 Deployment 來運行您的應用程序,則它可以動態創建和銷毀 Pod。

每個 Pod 都有自己的 IP 地址,但是在 Deployment 中,在同一時刻運行的 Pod 集合可能與稍後運行該應用程序的 Pod 集合不同。

這導致了一個問題: 如果一組 Pod(稱為「後端」)為群集內的其他 Pod(稱為「前端」)提供功能, 那麼前端如何找出並跟蹤要連接的 IP 地址,以便前端可以使用工作量的後端部分?

補充說明:K8S集群的網路管理和拓撲也有特別的設計,以後會專門出一章節來詳細介紹K8S中的網路。這裡需要清楚一點:K8S集群內的每一個Pod都有自己的IP(是不是很類似一個Pod就是一台伺服器,然而事實上是多個Pod存在於一台伺服器上,只不過是K8S做了網路隔離),在K8S集群內部還有DNS等網路服務(一個K8S集群就如同管理了多區域的伺服器,可以做複雜的網路拓撲)。

此外,筆者推薦k8s外網如何訪問業務應用對於Service的介紹,不過對於新手而言,推薦閱讀前半部分對於service的介紹即可,後半部分就太複雜了。我這裡做了簡單的總結:

Service是K8S服務的核心,屏蔽了服務細節,統一對外暴露服務介面,真正做到了「微服務」。舉個例子,我們的一個服務A,部署了3個備份,也就是3個Pod;對於用戶來說,只需要關注一個Service的入口就可以,而不需要操心究竟應該請求哪一個Pod。優勢非常明顯:一方面外部用戶不需要感知因為Pod上服務的意外崩潰、K8S重新拉起Pod而造成的IP變更,外部用戶也不需要感知因升級、變更服務帶來的Pod替換而造成的IP變化,另一方面,Service還可以做流量負載均衡

但是,Service主要負責K8S集群內部的網路拓撲。那麼集群外部怎麼訪問集群內部呢?這個時候就需要Ingress了,官方文檔中的解釋是:

Ingress 是對集群中服務的外部訪問進行管理的 API 對象,典型的訪問方式是 HTTP。

Ingress 可以提供負載均衡、SSL 終結和基於名稱的虛擬託管。

翻譯一下:Ingress是整個K8S集群的接入層,複雜集群內外通訊。

最後,筆者把Ingress和Service的關係繪製網路拓撲關係圖如下,希望對理解這兩個概念有所幫助:

K8S Ingress、Service和Pod關係圖

amespace 命名空間

和前文介紹的所有的概念都不一樣,namespace跟Pod沒有直接關係,而是K8S另一個維度的對象。或者說,前文提到的概念都是為了服務Pod的,而namespace則是為了服務整個K8S集群的。

那麼,namespace是什麼呢?

上官方文檔定義:

Kubernetes 支持多個虛擬集群,它們底層依賴於同一個物理集群。 這些虛擬集群被稱為名字空間。

翻譯一下:namespace是為了把一個K8S集群劃分為若干個資源不可共享的虛擬集群而誕生的

也就是說,可以通過在K8S集群內創建namespace來分隔資源和對象。比如我有2個業務A和B,那麼我可以創建ns-a和ns-b分別部署業務A和B的服務,如在ns-a中部署了一個deployment,名字是hello,返回用戶的是「hello a」;在ns-b中也部署了一個deployment,名字恰巧也是hello,返回用戶的是「hello b」(要知道,在同一個namespace下deployment不能同名;但是不同namespace之間沒有影響)。前文提到的所有對象,都是在namespace下的;當然,也有一些對象是不隸屬於namespace的,而是在K8S集群內全局可見的,官方文檔提到的可以通過命令來查看,具體命令的使用辦法,筆者會出後續的實戰文章來介紹,先貼下命令:

# 位於名字空間中的資源
kubectl api-resources --namespaced=true
?
# 不在名字空間中的資源
kubectl api-resources --namespaced=false

不在namespace下的對象有:

在namespace下的對象有(部分):


一般做一件事情都是要有內驅力,或者工作需求。

所以,你直接問怎麼學k8s,這個會讓人難以回答的讓你可以執行。

我拋幾個問題吧,在解決問題的過程中學習,才是最好的學習方法,要麼你就把k8s文檔一篇不少的全吸收完。

1. deployment, pod, job有什麼區別?什麼場景用他們?2. service是幹嘛的?可以解決些什麼問題?3. 我想部署一些有狀態的服務,比如MySQL,用k8s怎麼做?就這麼三個問題吧,其它的,等你有問題了再談。

首先得把所有的知識點好好捋一遍,官方文檔是個不錯的選擇,如果英文不好,還是買本書吧,現在也就只有kubernetes權威指南比較靠譜,知識點,概念都有解釋

本地建他五六個虛擬機,搭個k8s集群出來,知識點一個一個的實踐一下。國內有牆,注意鏡像的掛起狀態,多看日誌,有可能就是被牆了

在生產環境下,如果是暴露到了公網環境,安全問題就很重要了,節點,程序之間的加密通訊要著重掌握

去github上看k8s這個項目就能知道,幾小時內就能有好幾次提交,一周一個版本司空見慣,官方文檔都已經跟不上了,好多文檔上沒有的東西,就只能去代碼里看了


可以看看https://zhuanlan.zhihu.com/p/56159304


幫你頂帖,我也是運維,docker的方方面面基本上摸了一遍,一看k8s就感覺兩眼迷茫無從下手,很多文檔感覺都不系統,希望有大神出來指教一二


  • 了解docker
  • 了解kubernetes概念,坦白說還是很有門檻的
  • 了解kubernetes的架構
  • 學習kubernetes的安裝運維、網路存儲、日誌
  • 劃重點:學習如何管理應用
  • kubernetes的擴展開發

  • 官方文檔就可以了


    推薦閱讀:
    相关文章