k8s基本對象概念html
Kubernetes 中的全部內容都被抽象爲「資源」,如 Pod、Service、Node 等都是資源。「對象」就是「資源」的實例,是持久化的實體。如某個具體的 Pod、某個具體的 Node。Kubernetes 使用這些實體去表示整個集羣的狀態。
對象的建立、刪除、修改都是經過 「Kubernetes API」,也就是 「Api Server」 組件提供的 API 接口,這些是 RESTful 風格的 Api,與 k8s 的「萬物皆對象」理念相符。命令行工具 「kubectl」,實際上也是調用 kubernetes api。
K8s 中的資源類別有不少種,kubectl 能夠經過配置文件來建立這些 「對象」,配置文件更像是描述對象「屬性」的文件,配置文件格式能夠是 「JSON」 或 「YAML」,經常使用 「YAML」。node
ps: 本文不會刻意說 「對象」 這一詞,對於某個具體的 Pod、Node,有時候可能也說成是 「資源」,這其實也是合理的,對象是資源的實例,因此對象也是資源,沒必要要鑽牛角尖,理解意思便可。 nginx
對象是用來完成一些任務的,是持久的,是有目的性的,所以 kubernetes 建立一個對象後,將持續地工做以確保對象存在。固然,kubernetes 並不僅是維持對象的存在這麼簡單,kubernetes 還管理着對象的方方面面。每一個Kubernetes對象包含兩個嵌套的對象字段,它們負責管理對象的配置,他們分別是 「spec」 和 「status」 。程序員
「spec」 是 「規約」、「規格」 的意思,spec 是必需的,它描述了對象的指望狀態(Desired State)—— 但願對象所具備的特徵。當建立 Kubernetes 對象時,必須提供對象的規約,用來描述該對象的指望狀態,以及關於對象的一些基本信息(例如名稱)。以 Pod 爲例,以下是一個簡單的建立 Pod 的 yaml 文件模板:數據庫
apiVersion: v1 kind: Pod metadata: name: myapp-pod labels: app: myapp spec: containers: - name: myapp-container image: busybox command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']
上面的模板描述了一個對象,對象的類型是 「Pod」,對象名爲 「myapp-pod」,包含一個 「app: myapp」 標籤。「spec」 指定了該 Pod 對象的特徵——對象包含一個名爲 「myapp-container」 的容器,容器根據 「busybox」 鏡像生成,容器運行的命令是 「 ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600'] 」。
除 「spec」 字段外,在建立一個Pod及Pod的控制器對象時,還要像上面模板所示同樣,還要有這三個字段:
「apiVersion」——「建立該對象所使用的 Kubernetes API 的版本」;
「kind」——「想要建立的對象的類型」;
「metadata」——「幫助識別對象惟一性的數據,包括一個 name 字符串、UID 和可選的 namespace。」json
status 描述了對象的 實際狀態(Actual State) ,它是由 Kubernetes 系統提供和更新的。在任什麼時候刻,Kubernetes 控制面一直努力地管理着對象的實際狀態以與指望狀態相匹配。segmentfault
k8s 中每一個對象都有 uid ,uid 是 k8s 自動爲對象生成的,能夠惟一標識該對象的字符串。uid 是用於給 k8s 自己管理對象的標識,對人類來講其可讀性太差,所以對象還具備另外一個屬性 —— 可讀性相對更好的,有必定意義的 「名稱」 。在建立對象時能夠給對象指定名稱。不屬於同一類別的對象能夠有相同的名稱,而同一種類型的對象,想要賦予相同的名稱,則須要用到 namespace。後端
不少地方都有 namespace 的概念,如 Linux 中的 namespace 、C++ 中的 namespace 等等。 C++ 用 namespace 來解決命名衝突(兩個不一樣的 namespace 能夠存在同名的類),k8s 中 的 namespace 也有這樣的做用——不一樣的 namespace 中能夠存在同名的資源對象(即便這些對象是相同的類型)。然而,k8s 中的 namespace,更多的是爲了提升資源的管理效率。
在 k8s 中, namespace (命名空間) 也稱爲虛擬集羣。namespace 用來在邏輯上對資源進行分組(是的,namespace 用來給資源分組,namespace 自己也是資源...)。怎樣個分組法?譬如,一個 k8s 集羣上部署兩個應用——一個是商城,叫 sMall;另外一個是視頻類應用,叫 iQipa。那麼能夠建立兩個 namespace,而後給前者全部資源分配名爲 「sMall」 的 namespace,後者分配 「iQipa」,這樣,兩個不一樣的項目各自管理本身的資源,互不干擾。
能夠用 「kubectl get」 命令羅列在集羣中存在的某一類資源的對象,例如想要獲取 「sMall」 的全部 pod,能夠輸入命令:api
kubectl get pods --namespace=sMall
對應的,若是想要獲取 iQipa 的 service,則輸入命令安全
kubectl get services --namespace=iQipa
k8s 集羣搭建好後,會建立一個名爲 "default" 的 namespace,當沒有爲資源明確指定 namespace 時,會默認分配該 namespace。kubernetes 的組件,分配的是名爲 「kube-system」 的 namespace。
命名空間爲名稱提供了一個範圍。對象的名稱須要在命名空間內是惟一的,但不能跨命名空間。命名空間不能相互嵌套,每一個 Kubernetes 對象只能在一個命名空間中。大多數 kubernetes 資源的對象(例如 Pod、Service、副本控制器等)都位於某些命名空間中。可是命名空間資源自己並不在命名空間中。並且底層資源,例如 nodes 和持久化卷不屬於任何命名空間。可使用命令查看哪些資源在 namespace 中,哪些不在:
# 列出在命名空間中的資源 kubectl api-resources --namespaced=true # 列出不在命名空間中的資源 kubectl api-resources --namespaced=false
更多資料:
label (標籤)是附加到 Kubernetes 對象(好比 Pods)上的鍵值對,用於區分對象(好比Pod、Service)。 label 旨在用於指定對用戶有意義且相關的對象的標識屬性,但不直接對核心系統有語義含義。 label 能夠用於組織和選擇對象的子集。label 能夠在建立時附加到對象,隨後能夠隨時添加和修改。能夠像 namespace 同樣,使用 label 來獲取某類對象,但 label 能夠與 selector 一塊兒配合使用,用表達式對條件加以限制,實現更精確、更靈活的資源查找。
label 與 selector 配合,能夠實現對象的「關聯」,「Pod 控制器」 與 Pod 是相關聯的 —— 「Pod 控制器」依賴於 Pod,能夠給 Pod 設置 label,而後給「控制器」設置對應的 selector,這就實現了對象的關聯。
每一個對象均可以定義一組鍵/值標籤。每一個鍵對於給定對象必須是惟一的。如:
"metadata": { "labels": { "app1" : "iQipa", "app2" : "sMall" } }
更多資料:
「Kubectl」 這個命令行工具提供了與 k8s 交互的接口,能夠經過 kubectl 來建立、更改、查看、刪除對象,這裏只稍微講解下對象信息的獲取,其它放到 Kubectl 有關的文章中再介紹。要查看當前 k8s 集羣中存在的某一類資源,可使用 kubectl 的 「get」 選項:
kubectl get <resource_type> --namespace=<namespace>
參數說明:
<resource_type> 就是資源的類別,能夠是 pod、node 或其它全部類別的名稱。這裏能夠輸入資源的單數形式、複數形式,好比 「pod」 還能夠寫成 「pods」;對於稍微長一點的資源名,還可使用縮寫,好比 「service」,能夠輸入其縮寫 「svc」。
<namespace> <namespace>後面的 「=」 無關緊要。namespace 是對象所在的 namespace,namespace 能夠看作是對象的分組的組名,下文會簡單介紹。k8s 集羣初始化後會建立名爲 「default」 的 namespace,在建立對象時若是沒有指定 namespace,默認使用這個 namespace。若是在使用 「kubectl get」 時不指定 「--namespace」這個參數,獲取的是 「default」 namespace 下的對象。 另外 「--namespace」 能夠簡寫成 「-n」,若是想獲取全部 namespace 下的對象,則能夠寫成 「--all-namespaces」。
幾個示例:
kubectl get namespace
kubectl get node
kubectl get pods --all-namespaces
kubectl get svc -n kube-system
「get」 選項只是羅列出資源對象而已,若是想要查看對象的具體信息,須要用 「describe」
kubectl describe <resource_type> <object_name> --namespace=<namespace>
參數說明:
<resource_type> 跟上面同樣,能夠寫單複數形式、簡寫。<namespace> 也是同樣的,能夠寫成 「-n」,但有一點須要注意,不能寫成 「--all-namespaces」,由於若是不一樣 namespace 有兩個同名同類別的對象,那麼就出現歧義了,「--all-namespaces」 對 「kubectl describe」 是沒有意義的,因此不要這樣寫。
<object_name> 就是對象的名稱,也就是 「kubectl get」 命令顯示的結果。
示例:
kubectl describe pod kube-apiserver -n kube-system
kubectl describe node hello
小 Tips: 能夠用 「kubectl explain」 來查看某類資源的做用,如 「kubectl explain pod」,不過顯示的信息都是一兩句話帶過。。否則我也懶得寫這篇。。(;′⌒`)
更多資料:
接下來開始正式介紹 k8s 的各類資源。
Pod 是最小的可部署的 Kubernetes 對象模型。Pod 表示集羣上正在運行的進程。一個 Pod 由一個或多個容器組成,Pod 中容器共享存儲和網絡,在同一臺 Docker 主機上運行。在 kubernetes 中,若要運行一個容器,則必須先建立 pod,讓容器在 pod 中運行,能夠把 Pod 當作是容器的運行環境。
Docker 是 Kubernetes Pod 中最經常使用的容器運行時,但 Pod 也能支持其餘的容器運行時,如 rtk。
Kubernetes 集羣中的 Pod 可被用於如下兩個主要用途:
運行單個容器的 Pod。」每一個 Pod 一個容器」模型是最多見的 Kubernetes 用例;在這種狀況下,能夠將 Pod 看做單個容器的包裝器,而且 Kubernetes 直接管理 Pod,而不是容器。
運行多個協同工做的容器的 Pod。 Pod 可能封裝由多個緊密耦合且須要共享資源的共處容器組成的應用程序。 這些位於同一位置的容器可能造成單個內聚的服務單元——一個容器將文件從共享卷提供給公衆,而另外一個單獨的「掛斗」容器則刷新或更新這些文件。 Pod 將這些容器和存儲資源打包爲一個可管理的實體。
上面講對象的「規約」時已經說起 Pod 的模板文件,這裏再也不贅述。
Pod是容器的運行環境,而咱們的應用程序是部署在容器裏的,對於k8s的初學者,能夠先把Pod簡單地看做爲應用的運行容器,把Pod看做是應用在k8s上部署的最小單位。能夠簡單粗暴的說「Pod就是用來部署應用的,Pod就是用來裝應用的。」
Pod是不能被外網直接訪問的,因此不要想着只要把應用部署到Pod就能夠直接用,要想在外網訪問Pod須要用到service,下文會介紹。
更多資料:
當 Pod 被建立出來,Pod 會被調度到集羣中的節點上運行,Pod 會在該節點上一直保持運行狀態,直到進程終止、Pod 對象被刪除、Pod 因節點資源不足而被驅逐或者節點失效爲止。Pod 並不會自愈,當節點失效,或者調度 Pod 的這一操做失敗了,Pod 就該被刪除。如此,單單用 Pod 來部署應用,是不穩定不安全的。
Kubernetes 使用更高級的資源對象 「控制器」 來實現對Pod的管理。控制器能夠爲您建立和管理多個 Pod,管理副本和上線,並在集羣範圍內提供自修復能力。 例如,若是一個節點失敗,控制器能夠在不一樣的節點上調度同樣的替身來自動替換 Pod。
先引入「副本」的概念——一個Pod能夠被複製成多份,每一份可被稱之爲一個「副本」,這些「副本」除了一些描述性的信息(Pod的名字、uid等)不同之外,其它信息都是同樣的,譬如Pod內部的容器、容器數量、容器裏面運行的應用等的這些信息都是同樣的,這些副本提供一樣的功能。Pod 的「控制器」一般包含一個名爲 「replicas」 的屬性。「replicas」屬性則指定了特定Pod的副本的數量,噹噹前集羣中該Pod的數量與該屬性指定的值不一致時,k8s會採起一些策略去使得當前狀態知足配置的要求。
k8s的一些Pod「控制器」能夠提供Pod的「滾動更新」功能,若是你的應用升級了,譬如原來應用是v1版本,如今的版本是v2,那麼能夠經過僅僅一條命令或一份配置文件,讓k8s來自動地滾動更新應用。k8s會刪除一個v1的Pod,而後新建一個v2的Pod……這樣反覆交替操做,直至全部v1Pod被v2Pod代替,這樣就實現了不停機的應用滾動更新。k8s會保存應用的更新記錄,在須要「回滾降級」時,一樣能夠經過僅僅一條命令或者一個配置文件實現。
所以,雖然能夠直接使用 Pod,能夠直接建立Pod,但在 Kubernetes 中,更爲常見的是使用控制器建立和管理 Pod。在部署應用時,「控制器」 是比簡單的 Pod 更好的選擇。
下面開始介紹 Pod 的各類控制器,注意,這些控制器也是 k8s 中的資源,也能夠建立對象。
ReplicationController 簡寫 「RC」 或 「RCS」。譯做「副本控制器」,「Replication」 就是「複製」、「副本」的意思。ReplicationController 確保在任什麼時候候都有特定數量的 pod 副本處於運行狀態。 換句話說,ReplicationController 確保一個 pod 或一組同類的 pod 老是可用的。
當 pods 數量過多時,ReplicationController 會終止多餘的 pods。當 pods 數量太少時,ReplicationController 將會啓動新的 pods。 與手動建立的 pod 不一樣,由 ReplicationController 建立的 pods 在失敗、被刪除或被終止時會被自動替換。
下面給出一份生成 ReplicationController 對象的配置文件示例:
apiVersion: v1 kind: ReplicationController metadata: name: nginx spec: replicas: 3 selector: app: nginx template: metadata: name: nginx labels: app: nginx spec: containers: - name: nginx image: nginx ports: - containerPort: 80
來看下配置文件,該文件描述了一個資源對象,它有4個字段,分別是 「apiVersion」、「kind」、「metadata」、「spec」。上面講對象與「規約」時講過,建立一個 Pod 及 Pod控制器 對象時,這四個字段是必不可少的。kind 說明這是一個 「ReplicationController」 類型的對象,metadata 說明對象名稱是 「nginx」。spec 指定了這個對象的特徵,關注 spec 這個字段:
template
在 spec 中 template 這個字段是必需的,其實這就是一個 Pod 的模板,只不過這個模板是嵌套進來的,不須要 kind 和 apiVersion 字段。再來看下這是怎樣一個 Pod —— metadata 部分描述了 Pod 的名稱 「nginx」,還爲這個 Pod 分配了名爲 「app: nginx」 的標籤。spec 指定了該 Pod 由 「nginx」 鏡像構建而成,容器開啓了「80」端口。
replicas
replica就是「複製品」、「副本」的意思,「replicas: 3」就是開啓三個 Pod 副本,並維護這些副本,當 Pod 出錯了,就把 Pod 刪掉而後建立一個新的 Pod,使得 Pod 的數量始終維持在3個,這充分提升了部署的應用的高可用性。固然,在 k8s 運行過程當中某個瞬間,ReplicationController 管理的 Pod 因爲種種緣由,可能比設置的 replicas 的數量多,也可能少,但 ReplicationController 會採起合適的策略儘可能維持 Pod 的數量。
selector
經過指定 ReplicationController 的 selector 和 Pod 的 「app: nginx」 標籤,能夠實現 ReplicationController 和 Pod 的綁定關係,ReplicationController 就是僅僅管理這些附帶 「app: nginx」 標籤的 Pod 而不干涉其它的 Pod。不是由 ReplicationController 自己建立的,但包含 「app: nginx」 的 Pod,也由其管理。
更多資料:
ReplicaSet 簡寫 「RS」,是 「Replication Controller」 的升級版。和 「ReplicationController」 同樣用於確保任何給定時間指定的Pod副本數量,並提供聲明式更新等功能。
RC與RS惟一區別就是lable selectore支持不一樣,RS支持新的基於集合的標籤,RC僅支持基於等式的標籤。
Deployment是一個更高層次的API對象,他管理ReplicaSets和Pod,並提供聲明式更新等功能。
官方建議使用Deployment管理ReplicaSets,而不是直接使用ReplicaSets,這就意味着可能永遠不須要直接操做ReplicaSet對象。
StatefulSet適合持久性的應用程序,有惟一的網絡標識符(IP),持久存儲,有序的部署、擴展、刪除和滾動更新。
Daemon 一詞應該不陌生的,Daemon 進程(守護進程)、Demon 程序(守護程序)。顧名思義,DaemonSet 通常是用來部署一些特殊應用的,譬如日誌應用等有「守護」意義的應用。
DaemonSet確保全部(或一些)節點運行同一個Pod(固然這裏不是指「同一個」,而是和副本同樣的概念,固然不可能多個節點運行「同一個」Pod,它又不是量子態)。當節點加入kubernetes集羣中,Pod會被調度到該節點上運行,當節點從集羣中移除時,DaemonSet的Pod會被刪除。刪除DaemonSet會清理它全部建立的Pod。
一次性任務,運行完成後Pod銷燬,再也不從新啓動新容器。
CronJob 是在 Job 基礎上加上了定時功能。
更多資料:
------------------------以上都是 Pod 的 Controller---------------------
「Service」 簡寫 「svc」。如上文提到的,Pod不能直接提供給外網訪問,而是應該使用service。Service就是把Pod暴露出來提供服務,Service纔是真正的「服務」,它的中文名就叫「服務」。o( ̄︶ ̄)o
按照百度上找到的更專業的的說法,能夠說Service是一個應用服務的抽象,定義了Pod邏輯集合和訪問這個Pod集合的策略。Service代理Pod集合,對外表現爲一個訪問入口,訪問該入口的請求將通過負載均衡,轉發到後端Pod中的容器。
Pod只是運行應用的容器,只是簡單地提供某種「功能」,不能稱之爲「服務」。而service不同,service是對Pod訪問方式的抽象,service利用Pod的「功能」,利用「Pod」的能動性,經過路由轉發和負載均衡,對外提供真正意義上的「服務」。
k8s使用service還有一個緣由。通常而言,k8s每建立一個新的Pod,它的ip地址都是不同的(固然,你能夠設置固定ip,但這樣並不穩當,程序員都喜歡「解耦」,而這麼作顯然是與該理念背道而馳了),若是一個Pod由於某些問題掛了,k8s建立了一個新的Pod,這時ip地址不同了,那它還怎麼提供功能?這時,Service意義就出來了,一個Service與特定的一個或者一組Pod掛鉤,即便Pod掛掉了,k8s又建立了新的特定的Pod,Service仍然與這個新的Pod掛鉤,這樣,Pod的ip不同了,哪怕端口也不同了,仍然能經過Service來獲取Pod所提供的服務。
Service是如何保持這種與特定Pod綁定的關係的呢?那就是「Label」和「Label Selector」,能夠給Pod分配特定的Label,而後配置Service,經過「Lable Selector」選擇具備這些特定「Label」的Pod來接受請求、提供服務。
默認狀況下,在建立service對象的時候,若是不指定service的訪問方式,service被配置爲ClusterIp模式,在該模式下,只有集羣內部的網絡才能訪問到該service,要想真正的實現外網訪問service,須要把service訪問方式配置爲NodePort或其它。
更多資料:
如下內容待更…………
數據卷,共享Pod中容器使用的數據。用來放持久化的數據,好比數據庫數據。
用來存放一些隱祕的數據,見不得人的數據,好比證書、token、密碼等,能夠像 Volume 同樣被一個 Pod 引用(掛載)。
用來放配置,與 Secret 是相似的,只是ConfigMap放的是明文的數據,Secret 是密文存放。
Ingress 能夠提供外網訪問 Service 的能力。能夠把某個請求地址映射、路由到特定的 service。ingress 須要配合 ingress controller 一塊兒使用才能發揮做用,ingress只是至關於路由規則的集合而已,真正實現路由功能的,是 Ingress Controller,ingress controller 和其它 k8s 組件同樣,也是在Pod中運行。
更多資料:
訪問Service的Account