- 1、Kubernetes的重要概念
轉自:CloudMan老師公眾號《每天5分鍾玩轉Kubernetes》https://item.jd.com/26225745440.html
- Cluster
Cluster 是計算、存儲和網絡資源的集合,Kubernetes 利用這些資源運行各種基於容器的應用。
- Master
Master 是 Cluster 的大腦,它的主要職責是調度,即決定將應用放在哪里運行。Master 運行 Linux 操作系統,可以是物理機或者虛擬機。為了實現高可用,可以運行多個 Master。
- Node
Node 的職責是運行容器應用。Node 由 Master 管理,Node 負責監控並匯報容器的狀態,並根據 Master 的要求管理容器的生命周期。Node 運行在 Linux 操作系統,可以是物理機或者是虛擬機。
- Pod
Pod 是 Kubernetes 的最小工作單元。每個 Pod 包含一個或多個容器。Pod 中的容器會作為一個整體被 Master 調度到一個 Node 上運行。
Kubernetes 引入 Pod 主要基於下面兩個目的:
-
可管理性。
有些容器天生就是需要緊密聯系,一起工作。Pod 提供了比容器更高層次的抽象,將它們封裝到一個部署單元中。Kubernetes 以 Pod 為最小單位進行調度、擴展、共享資源、管理生命周期。 -
通信和資源共享。
Pod 中的所有容器使用同一個網絡 namespace,即相同的 IP 地址和 Port 空間。它們可以直接用 localhost 通信。同樣的,這些容器可以共享存儲,當 Kubernetes 掛載 volume 到 Pod,本質上是將 volume 掛載到 Pod 中的每一個容器。
Pods 有兩種使用方式:
-
運行單一容器。
one-container-per-Pod
是 Kubernetes 最常見的模型,這種情況下,只是將單個容器簡單封裝成 Pod。即便是只有一個容器,Kubernetes 管理的也是 Pod 而不是直接管理容器。 -
運行多個容器。
但問題在於:哪些容器應該放到一個 Pod 中?
答案是:這些容器聯系必須 非常緊密,而且需要 直接共享資源。
舉個例子。
下面這個 Pod 包含兩個容器:一個 File Puller,一個是 Web Server。
File Puller 會定期從外部的 Content Manager 中拉取最新的文件,將其存放在共享的 volume 中。Web Server 從 volume 讀取文件,響應 Consumer 的請求。
這兩個容器是緊密協作的,它們一起為 Consumer 提供最新的數據;同時它們也通過 volume 共享數據。所以放到一個 Pod 是合適的。
再來看一個反例:是否需要將 Tomcat 和 MySQL 放到一個 Pod 中?
Tomcat 從 MySQL 讀取數據,它們之間需要協作,但還不至於需要放到一個 Pod 中一起部署,一起啟動,一起停止。同時它們是之間通過 JDBC 交換數據,並不是直接共享存儲,所以放到各自的 Pod 中更合適。
- Controller
Kubernetes 通常不會直接創建 Pod,而是通過 Controller 來管理 Pod 的。Controller 中定義了 Pod 的部署特性,比如有幾個副本,在什么樣的 Node 上運行等。為了滿足不同的業務場景,Kubernetes 提供了多種 Controller,包括 Deployment、ReplicaSet、DaemonSet、StatefuleSet、Job 等,我們逐一討論。
Deployment 是最常用的 Controller,比如前面在線教程中就是通過創建 Deployment 來部署應用的。Deployment 可以管理 Pod 的多個副本,並確保 Pod 按照期望的狀態運行。
ReplicaSet 實現了 Pod 的多副本管理。使用 Deployment 時會自動創建 ReplicaSet,也就是說 Deployment 是通過 ReplicaSet 來管理 Pod 的多個副本,我們通常不需要直接使用 ReplicaSet。
DaemonSet 用於每個 Node 最多只運行一個 Pod 副本的場景。正如其名稱所揭示的,DaemonSet 通常用於運行 daemon。
StatefuleSet 能夠保證 Pod 的每個副本在整個生命周期中名稱是不變的。而其他 Controller 不提供這個功能,當某個 Pod 發生故障需要刪除並重新啟動時,Pod 的名稱會發生變化。同時 StatefuleSet 會保證副本按照固定的順序啟動、更新或者刪除。
Job 用於運行結束就刪除的應用。而其他 Controller 中的 Pod 通常是長期持續運行。
- Service
Deployment 可以部署多個副本,每個 Pod 都有自己的 IP,外界如何訪問這些副本呢?
通過 Pod 的 IP 嗎?
要知道 Pod 很可能會被頻繁地銷毀和重啟,它們的 IP 會發生變化,用 IP 來訪問不太現實。
答案是 Service。
Kubernetes Service 定義了外界訪問一組特定 Pod 的方式。Service 有自己的 IP 和端口,Service 為 Pod 提供了負載均衡。
Kubernetes 運行容器(Pod)與訪問容器(Pod)這兩項任務分別由 Controller 和 Service 執行。
- Namespace
如果有多個用戶或項目組使用同一個 Kubernetes Cluster,如何將他們創建的 Controller、Pod 等資源分開呢?
答案就是 Namespace。
Namespace 可以將一個物理的 Cluster 邏輯上划分成多個虛擬 Cluster,每個 Cluster 就是一個 Namespace。不同 Namespace 里的資源是完全隔離的。
Kubernetes 默認創建了兩個 Namespace。
[root@linux-node1 ~]# kubectl get namespace
NAME STATUS AGE
default Active 1d
kube-system Active 1d
default
-- 創建資源時如果不指定,將被放到這個 Namespace 中。
kube-system
-- Kubernetes 自己創建的系統資源將放到這個 Namespace 中。
-
2、Kubernetes架構和集群規划
-
(1)Kubernetes架構
-
(2)K8S架構拆解圖
K8S Master
節點
從上圖可以看到,Master是K8S集群的核心部分,主要運行着以下的服務:kube-apiserver、kube-scheduler、kube-controller-manager、etcd和Pod網絡(如:flannel)
API Server:K8S對外的唯一接口,提供HTTP/HTTPS RESTful API,即kubernetes API。所有的請求都需要經過這個接口進行通信。主要處理REST操作以及更新ETCD中的對象。是所有資源增刪改查的唯一入口。
Scheduler:資源調度,負責決定將Pod放到哪個Node上運行。Scheduler在調度時會對集群的結構進行分析,當前各個節點的負載,以及應用對高可用、性能等方面的需求。
Controller Manager:負責管理集群各種資源,保證資源處於預期的狀態。Controller Manager由多種controller組成,包括replication controller、endpoints controller、namespace controller、serviceaccounts controller等
ETCD:負責保存k8s 集群的配置信息和各種資源的狀態信息,當數據發生變化時,etcd會快速地通知k8s相關組件。
Pod網絡:Pod要能夠相互間通信,K8S集群必須部署Pod網絡,flannel是其中一種的可選方案。
K8S Node
節點
Node是Pod運行的地方,Kubernetes支持Docker、rkt等容器Runtime。Node上運行的K8S組件包括kubelet、kube-proxy和Pod網絡。
Kubelet:kubelet是node的agent,當Scheduler確定在某個Node上運行Pod后,會將Pod的具體配置信息(image、volume等)發送給該節點的kubelet,kubelet會根據這些信息創建和運行容器,並向master報告運行狀態。
Kube-proxy:service在邏輯上代表了后端的多個Pod,外借通過service訪問Pod。service接收到請求就需要kube-proxy完成轉發到Pod的。每個Node都會運行kube-proxy服務,負責將訪問的service的TCP/UDP數據流轉發到后端的容器,如果有多個副本,kube-proxy會實現負載均衡,有2種方式:LVS或者Iptables
Docker Engine:負責節點的容器的管理工作
Kubernetes中pod創建流程
Pod是Kubernetes中最基本的部署調度單元,可以包含container,邏輯上表示某種應用的一個實例。例如一個web站點應用由前端、后端及數據庫構建而成,這三個組件將運行在各自的容器中,那么我們可以創建包含三個container的pod。
具體的創建步驟包括:
(1)客戶端提交創建請求,可以通過API Server的Restful API,也可以使用kubectl命令行工具。支持的數據類型包括JSON和YAML。
(2)API Server處理用戶請求,存儲Pod數據到etcd。
(3)調度器通過API Server查看未綁定的Pod。嘗試為Pod分配主機。
(4)過濾主機 (調度預選):調度器用一組規則過濾掉不符合要求的主機。比如Pod指定了所需要的資源量,那么可用資源比Pod需要的資源量少的主機會被過濾掉。
(5)主機打分(調度優選):對第一步篩選出的符合要求的主機進行打分,在主機打分階段,調度器會考慮一些整體優化策略,比如把容一個Replication Controller的副本分布到不同的主機上,使用最低負載的主機等。
(6)選擇主機:選擇打分最高的主機,進行binding操作,結果存儲到etcd中。
(7)kubelet根據調度結果執行Pod創建操作: 綁定成功后,scheduler會調用APIServer的API在etcd中創建一個boundpod對象,描述在一個工作節點上綁定運行的所有pod信息。運行在每個工作節點上的kubelet也會定期與etcd同步boundpod信息,一旦發現應該在該工作節點上運行的boundpod對象沒有更新,則調用Docker API創建並啟動pod內的容器。
-
(3)實驗環境准備:
主機名 IP地址 描述 linux-node1.example.com eth0:192.168.56.110 K8S Master節點/ETCD節點 linux-node2.example.com eth0:192.168.56.120 K8S Node節點/ETCD節點 linux-node3.example.com eth0:192.168.56.130 K8S Node節點/ETCD節點
-
(4)系統環境初始化
1.安裝Docker
第一步:使用國內Docker源
[root@linux-node1 ~]# cd /etc/yum.repos.d/ [root@linux-node1 yum.repos.d]# wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo [root@linux-node2 ~]# cd /etc/yum.repos.d/ [root@linux-node2 yum.repos.d]# wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo [root@linux-node3 ~]# cd /etc/yum.repos.d/ [root@linux-node3 yum.repos.d]# wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
第二步:Docker安裝:
[root@linux-node1 ~]# yum install -y docker-ce [root@linux-node2 ~]# yum install -y docker-ce [root@linux-node3 ~]# yum install -y docker-ce
第三步:啟動后台進程:
[root@linux-node1 ~]# systemctl start docker [root@linux-node2 ~]# systemctl start docker [root@linux-node3 ~]# systemctl start docker
2.准備部署目錄
[root@linux-node1 ~]# mkdir -p /opt/kubernetes/{cfg,bin,ssl,log} [root@linux-node2 ~]# mkdir -p /opt/kubernetes/{cfg,bin,ssl,log} [root@linux-node3 ~]# mkdir -p /opt/kubernetes/{cfg,bin,ssl,log}
3.准備軟件包
百度網盤下載地址:
https://pan.baidu.com/s/1zs8sCouDeCQJ9lghH1BPiw
4.解壓軟件包
[root@linux-node1 src]# tar zxf kubernetes.tar.gz [root@linux-node1 src]# tar zxf kubernetes-server-linux-amd64.tar.gz [root@linux-node1 src]# tar zxf kubernetes-client-linux-amd64.tar.gz [root@linux-node1 src]# tar zxf kubernetes-node-linux-amd64.tar.gz
[root@linux-node1 src]# cd kubernetes #解壓的server、client、node都會解壓到kubernetes目錄下 [root@linux-node1 kubernetes]# ll total 29536 drwxr-xr-x 2 root root 6 Apr 12 23:16 addons drwxr-xr-x 3 root root 31 Apr 12 23:16 client drwxr-xr-x 13 root root 4096 Apr 12 23:24 cluster drwxr-xr-x 7 root root 131 Apr 12 23:25 docs drwxr-xr-x 34 root root 4096 Apr 12 23:25 examples drwxr-xr-x 3 root root 17 Apr 12 23:24 hack -rw-r--r-- 1 root root 24710771 Apr 12 23:16 kubernetes-src.tar.gz -rw-r--r-- 1 root root 5516760 Apr 12 23:16 LICENSES drwxr-xr-x 3 root root 17 Apr 12 23:16 node -rw-r--r-- 1 root root 3329 Apr 12 23:25 README.md drwxr-xr-x 3 root root 66 Apr 12 23:16 server drwxr-xr-x 3 root root 22 Apr 12 23:24 third_party -rw-r--r-- 1 root root 8 Apr 12 23:25 version
各個節點增加kubernetes的環境變量
[root@linux-node1 ~]# vim .bash_profile PATH=$PATH:$HOME/bin:/opt/kubernetes/bin [root@linux-node1 ~]# source .bash_profile
[root@linux-node2 ~]# vim .bash_profile PATH=$PATH:$HOME/bin:/opt/kubernetes/bin [root@linux-node2 ~]# source .bash_profile
[root@linux-node3 ~]# vim .bash_profile PATH=$PATH:$HOME/bin:/opt/kubernetes/bin [root@linux-node3 ~]# source .bash_profile
-
3、CA證書創建和分發
從k8s的1.8版本開始,K8S系統各組件需要使用TLS證書對通信進行加密。每一個K8S集群都需要獨立的CA證書體系。CA證書有以下三種:easyrsa、openssl、cfssl。這里使用cfssl證書,也是目前使用最多的,相對來說配置簡單一些,通過json的格式,把證書相關的東西配置進去即可。這里使用cfssl的版本為1.2版本。
(1)安裝 CFSSL
[root@linux-node1 ~]# cd /usr/local/src [root@linux-node1 src]# wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 [root@linux-node1 src]# wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 [root@linux-node1 src]# wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 [root@linux-node1 src]# chmod +x cfssl* #增加執行權限 [root@linux-node1 src]# mv cfssl-certinfo_linux-amd64 /opt/kubernetes/bin/cfssl-certinfo [root@linux-node1 src]# mv cfssljson_linux-amd64 /opt/kubernetes/bin/cfssljson [root@linux-node1 src]# mv cfssl_linux-amd64 /opt/kubernetes/bin/cfssl
復制cfssl命令文件到k8s-node1和k8s-node2節點。如果實際中多個節點,就都需要同步復制。 [root@linux-node1 ~]# ssh-copy-id linux-node1 [root@linux-node1 ~]# ssh-copy-id linux-node2 [root@linux-node1 ~]# ssh-copy-id linux-node3 [root@linux-node1 ~]# scp /opt/kubernetes/bin/cfssl* 192.168.56.120:/opt/kubernetes/bin cfssl 100% 10MB 18.1MB/s 00:00 cfssl-certinfo 100% 6441KB 21.3MB/s 00:00 cfssljson 100% 2224KB 13.3MB/s 00:00 [root@linux-node1 ~]# scp /opt/kubernetes/bin/cfssl* 192.168.56.130:/opt/kubernetes/bin cfssl 100% 10MB 22.5MB/s 00:00 cfssl-certinfo 100% 6441KB 40.7MB/s 00:00 cfssljson 100% 2224KB 43.1MB/s 00:00
(2)創建用來生成 CA 文件的 JSON 配置文件
[root@linux-node1 src]# mkdir ssl && cd ssl #創建臨時證書存放目錄 [root@linux-node1 ssl]# pwd /usr/local/src/ssl [root@linux-node1 ssl]# vim ca-config.json { "signing": { "default": { "expiry": "8760h" }, "profiles": { "kubernetes": { "usages": [ "signing", "key encipherment", "server auth", "client auth" ], "expiry": "8760h" } } } }
(3)創建用來生成 CA 證書簽名請求(CSR)的 JSON 配置文件
[root@linux-node1 ssl]# vim ca-csr.json { "CN": "kubernetes", "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "k8s", "OU": "System" } ] }
(4)生成CA證書(ca.pem)和密鑰(ca-key.pem)
[root@linux-node1 ssl]# cfssl gencert -initca ca-csr.json | cfssljson -bare ca #生成證書和密鑰 2018/05/30 14:11:02 [INFO] generating a new CA key and certificate from CSR 2018/05/30 14:11:02 [INFO] generate received request 2018/05/30 14:11:02 [INFO] received CSR 2018/05/30 14:11:02 [INFO] generating key: rsa-2048 2018/05/30 14:11:02 [INFO] encoded CSR 2018/05/30 14:11:02 [INFO] signed certificate with serial number 167714418220584190953978332616641264281080483250 [root@linux-node1 ssl]# ll total 20 -rw-r--r-- 1 root root 290 May 30 14:09 ca-config.json -rw-r--r-- 1 root root 1001 May 30 14:11 ca.csr -rw-r--r-- 1 root root 208 May 30 14:10 ca-csr.json -rw------- 1 root root 1675 May 30 14:11 ca-key.pem -rw-r--r-- 1 root root 1359 May 30 14:11 ca.pem
(5)分發證書
[root@linux-node1 ssl]# cp ca.csr ca.pem ca-key.pem ca-config.json /opt/kubernetes/ssl SCP證書到k8s-node1和k8s-node2節點,以后增加節點也是需要將這些證書進行分發 [root@linux-node1 ssl]# scp ca.csr ca.pem ca-key.pem ca-config.json 192.168.56.120:/opt/kubernetes/ssl ca.csr 100% 1001 350.2KB/s 00:00 ca.pem 100% 1359 891.4KB/s 00:00 ca-key.pem 100% 1675 1.0MB/s 00:00 ca-config.json 100% 290 180.7KB/s 00:00 [root@linux-node1 ssl]# scp ca.csr ca.pem ca-key.pem ca-config.json 192.168.56.130:/opt/kubernetes/ssl ca.csr 100% 1001 350.2KB/s 00:00 ca.pem 100% 1359 891.4KB/s 00:00 ca-key.pem 100% 1675 1.0MB/s 00:00 ca-config.json 100% 290 180.7KB/s 00:00