Kubernetes 深入學習
目錄
- 一、簡介
- 二、叢集架構與元件
- 三、核心概念
- 四、叢集搭建 —— 平臺規劃
- 五、叢集搭建 —— 部署Etcd叢集
- 六、叢集搭建 —— 部署Master元件
- 七、叢集搭建 —— 部署Node元件
- 八、叢集搭建 —— 部署 Dashboard
- 九、叢集搭建 —— 多 Master 部署
回到頂部
一、簡介
1、Kubernetes 是什麼
Kubernetes 是一個全新的基於容器技術的分散式架構解決方案,是 Google 開源的一個容器叢集管理系統,Kubernetes 簡稱 K8S。
Kubernetes 是一個一站式的完備的分散式系統開發和支撐平臺,更是一個開放平臺,對現有的程式語言、程式設計框架、中介軟體沒有任何侵入性。
Kubernetes 提供了完善的管理工具,這些工具涵蓋了開發、部署測試、運維監控在內的各個環節。
Kubernetes 具有完備的叢集管理能力,包括多層次的安全防護和准入機制、多租戶應用支撐能力、透明的服務註冊和服務發現機制、內建智慧負載均衡器、強大的故障發現和自我修復能力、服務滾動升級和線上擴容能力、可擴充套件的資源自動排程機制、多粒度的資源配額管理能力。
Kubernetes 官方文件:https://kubernetes.io/zh/
2、Kubernetes 特性
① 自我修復
在節點故障時,重新啟動失敗的容器,替換和重新部署,保證預期的副本數量;殺死健康檢查失敗的容器,並且在未準備好之前不會處理使用者的請求,確保線上服務不中斷。
② 彈性伸縮
使用命令、UI或者基於CPU使用情況自動快速擴容和縮容應用程式例項,保證應用業務高峰併發時的高可用性;業務低峰時回收資源,以最小成本執行服務。
③ 自動部署和回滾
K8S採用滾動更新策略更新應用,一次更新一個Pod,而不是同時刪除所有Pod,如果更新過程中出現問題,將回滾更改,確保升級不影響業務。
④ 服務發現和負載均衡
K8S為多個容器提供一個統一訪問入口(內部IP地址和一個DNS名稱),並且負載均衡關聯的所有容器,使得使用者無需考慮容器IP問題。
⑤ 機密和配置管理
管理機密資料和應用程式配置,而不需要把敏感資料暴露在映象裡,提高敏感資料安全性。並可以將一些常用的配置儲存在K8S中,方便應用程式使用。
⑥ 儲存編排
掛載外部儲存系統,無論是來自本地儲存,公有云,還是網路儲存,都作為叢集資源的一部分使用,極大提高儲存使用靈活性。
⑦ 批處理
提供一次性任務,定時任務;滿足批量資料處理和分析的場景。
回到頂部二、叢集架構與元件
Kubernetes 叢集架構以及相關的核心元件如下圖所示:一個 Kubernetes 叢集一般包含一個 Master 節點和多個 Node 節點,一個節點可以看成是一臺物理機或虛擬機器。
1、Master
Master 是 K8S 的叢集控制節點,每個 K8S 叢集裡需要有一個 Master 節點來負責整個叢集的管理和控制,基本上 K8S 所有的控制命令都是發給它,它來負責具體的執行過程。Master 節點通常會佔據一個獨立的伺服器,因為它太重要了,如果它不可用,那麼所有的控制命令都將失效。
Master 節點上執行著以下關鍵元件:
① kube-apiserver
是叢集的統一入口,各元件協調者,以 HTTP Rest 提供介面服務,所有物件資源的增、刪、改、查和監聽操作都交給 apiserver 處理後再提交給 Etcd 儲存。
② kube-controller-manager
是 K8S 裡所有資源物件的自動化控制中心,處理叢集中常規後臺任務,一個資源對應一個控制器,而 controller-manager 就是負責管理這些控制器的。
③ kube-scheduler
根據排程演算法為新建立的 Pod 選擇一個 Node 節點,可以任意部署,可以部署在同一個節點上,也可以部署在不同的節點上。
④ etcd
是一個分散式的,一致的 key-value 儲存,主要用途是共享配置和服務發現,儲存叢集狀態資料,比如 Pod、Service 等物件資訊。
2、Node
除了 Master,K8S 叢集中的其它機器被稱為 Node 節點,Node 節點是 K8S 叢集中的工作負載節點,每個 Node 都會被 Master 分配一些工作負載,當某個 Node 宕機時,其上的工作負載會被 Master 自動轉移到其它節點上去。
每個 Node 節點上都執行著以下關鍵元件:
① kubelet
kubelet 是 Master 在 Node 節點上的 Agent(代理),與 Master 密切協作,管理本機執行容器的生命週期,負責 Pod 對應的容器的建立、啟停等任務,實現叢集管理的基本功能。
② kube-proxy
在 Node 節點上實現 Pod 網路代理,實現 Kubernetes Service 的通訊,維護網路規則和四層負載均衡工作。
③ docker engine
Docker 引擎,負責本機的容器建立和管理工作。
Node 節點可以在執行期間動態增加到 K8S 叢集中,前提是這個節點上已經正確安裝、配置和啟動了上述關鍵元件。在預設情況下 kubelet 會向 Master 註冊自己,一旦 Node 被納入叢集管理範圍,kubelet 就會定時向 Master 節點彙報自身的情況,例如作業系統、Docker 版本、機器的 CPU 和記憶體情況,以及之前有哪些 Pod 在執行等,這樣 Master 可以獲知每個 Node 的資源使用情況,並實現高效均衡的資源排程策略。而某個 Node 超過指定時間不上報資訊時,會被 Master 判定為“失聯”,Node 的狀態被標記為不可用(Not Ready),隨後 Master 會觸發“工作負載大轉移”的自動流程。
回到頂部三、核心概念
1、Pod
Pod 是 K8S 中最重要也是最基本的概念,Pod 是最小的部署單元,是一組容器的集合。每個 Pod 都由一個特殊的根容器 Pause 容器,以及一個或多個緊密相關的使用者業務容器組成。
Pause 容器作為 Pod 的根容器,以它的狀態代表整個容器組的狀態。K8S 為每個 Pod 都分配了唯一的 IP 地址,稱之為 Pod IP。Pod 裡的多個業務容器共享 Pause 容器的IP,共享 Pause 容器掛載的 Volume。
2、Label
標籤,附加到某個資源上,用於關聯物件、查詢和篩選。一個 Label 是一個 key=value 的鍵值對,key 與 value 由使用者自己指定。Label 可以附加到各種資源上,一個資源物件可以定義任意數量的 Label,同一個 Label 也可以被新增到任意數量的資源上。
我們可以通過給指定的資源物件捆綁一個或多個不同的 Label 來實現多維度的資源分組管理功能,以便於靈活、方便地進行資源分配、排程、配置、部署等工作。
K8S 通過 Label Selector(標籤選擇器)來查詢和篩選擁有某些 Label 的資源物件。Label Selector 有基於等式( name=label1 )和基於集合( name in (label1, label2) )的兩種方式。
3、ReplicaSet(RC)
ReplicaSet 用來確保預期的 Pod 副本數量,如果有過多的 Pod 副本在執行,系統就會停掉一些 Pod,否則系統就會再自動建立一些 Pod。
我們很少單獨使用 ReplicaSet,它主要被 Deployment 這個更高層的資源物件使用,從而形成一整套 Pod 建立、刪除、更新的編排機制。
4、Deployment
Deployment 用於部署無狀態應用,Deployment 為 Pod 和 ReplicaSet 提供宣告式更新,只需要在 Deployment 描述想要的目標狀態,Deployment 就會將 Pod 和 ReplicaSet 的實際狀態改變到目標狀態。5、Horizontal Pod Autoscaler(HPA)
HPA 為 Pod 橫向自動擴容,也是 K8S 的一種資源物件。HPA 通過追蹤分析 RC 的所有目標 Pod 的負載變化情況,來確定是否需要針對性調整目標 Pod 的副本數量。
6、Service
Service 定義了一個服務的訪問入口,通過 Label Selector 與 Pod 副本叢集之間“無縫對接”,定義了一組 Pod 的訪問策略,防止 Pod 失聯。
建立 Service 時,K8S會自動為它分配一個全域性唯一的虛擬 IP 地址,即 Cluster IP。服務發現就是通過 Service 的 Name 和 Service 的 ClusterIP 地址做一個 DNS 域名對映來解決的。
7、Namespace
名稱空間,Namespace 多用於實現多租戶的資源隔離。Namespace 通過將叢集內部的資源物件“分配”到不同的Namespace中,形成邏輯上分組的不同專案、小組或使用者組。
K8S 叢集在啟動後,會建立一個名為 default 的 Namespace,如果不特別指明 Namespace,建立的 Pod、RC、Service 都將被建立到 default 下。
當我們給每個租戶建立一個 Namespace 來實現多租戶的資源隔離時,還可以結合 K8S 的資源配額管理,限定不同租戶能佔用的資源,例如 CPU 使用量、記憶體使用量等。
回到頂部四、叢集搭建 —— 平臺規劃
1、生產環境 K8S 平臺規劃
K8S 環境有兩種架構方式,單 Master 叢集和多 Master 叢集,將先搭建起單 Master 叢集,再擴充套件為多 Master 叢集。開發、測試環境可以部署單 Master 叢集,生產環境為了保證高可用需部署多 Master 叢集。
① 單 Master 叢集架構
單 Master 叢集架構相比於多 Master 叢集架構無法保證叢集的高可用,因為 master 節點一旦宕機就無法進行叢集的管理工作了。單 master 叢集主要包含一臺 Master 節點,及多個 Node 工作節點、多個 Etcd 資料庫節點。
Etcd 是 K8S 叢集的資料庫,可以安裝在任何地方,也可以與 Master 節點在同一臺機器上,只要 K8S 能連通 Etcd。
② 多 Master 叢集架構
多 Master 叢集能保證叢集的高可用,相比單 Master 架構,需要一個額外的負載均衡器來負載多個 Master 節點,Node 節點從連線 Master 改成連線 LB 負載均衡器。
③ 叢集規劃
為了測試,我在本地使用 VMware 建立了幾個虛擬機器(可通過克隆快速建立虛擬機器),一個虛擬機器代表一臺獨立的伺服器。
K8S 叢集規劃如下:
生產環境建議至少兩臺 Master 節點,LB 主備各一個節點;至少兩臺以上 Node 節點,根據實際執行的容器數量調整;Etcd 資料庫可直接部署在 Master 和 Node 的節點,機器比較充足的話,可以部署在單獨的節點上。
④ 伺服器硬體配置推薦
測試環境與生產環境伺服器配置推薦如下,本地虛擬機器的配置將按照本地測試環境的配置來建立虛擬機器。
2、作業系統初始化
接下來將基於二進位制包的方式,手動部署每個元件,來組成 K8S 高可用叢集。通過手動部署每個元件,一步步熟悉每個元件的配置、元件之間的通訊等,深層次的理解和掌握 K8S。
首先做的是每臺伺服器的配置初始化,依次按如下步驟初始化。
① 關閉防火牆
# systemctl stop firewalld # systemctl disable firewalld
② 關閉 selinux
# #臨時生效 # setenforce 0
# #永久生效 # sed -i 's/enforcing/disabled/' /etc/selinux/config
③ 關閉 swap
# #臨時關閉 # swapoff -a
# # 永久生效 # vim /etc/fstab
# #將 [UUID=5b59fd54-eaad-41d6-90b2-ce28ac65dd81 swap swap defaults 0 0] 這一行註釋掉
④ 新增 hosts
# vim /etc/hosts 192.168.31.24 k8s-master-1 192.168.31.26 k8s-master-2 192.168.31.35 k8s-node-1 192.168.31.71 k8s-node-2 192.168.31.178 k8s-lb-master 192.168.31.224 k8s-lb-backup
⑤ 同步系統時間
各個節點之間需保持時間一致,因為自簽證書是根據時間校驗證書有效性,如果時間不一致,將校驗不通過。
# #聯網情況可使用如下命令回到頂部
# ntpdate time.windows.com
# #如果不能聯外網可使用 date 命令設定時間
五、叢集搭建 —— 部署Etcd叢集
1、自簽證書
K8S 叢集安裝配置過程中,會使用各種證書,目的是為了加強叢集安全性。K8S 提供了基於 CA 簽名的雙向數字證書認證方式和簡單的基於 http base 或 token 的認證方式,其中 CA 證書方式的安全性最高。每個K8S叢集都有一個叢集根證書頒發機構(CA),叢集中的元件通常使用CA來驗證API server的證書,由API伺服器驗證kubelet客戶端證書等。
證書生成操作可以在master節點上執行,證書只需要建立一次,以後在向叢集中新增新節點時只要將證書拷貝到新節點上,並做一定的配置即可。下面就在 k8s-master-1 節點上來建立證書,詳細的介紹也可以參考官方文件:分發自簽名-CA-證書
① K8S 證書
如下是 K8S 各個元件需要使用的證書
② 準備 cfssl 工具
我是使用 cfssl 工具來生成證書,首先下載 cfssl 工具。依次執行如下命令:
# curl -L https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 -o /usr/local/bin/cfssl # curl -L https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 -o /usr/local/bin/cfssljson # curl -L https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 -o /usr/local/bin/cfssl-certinfo # chmod +x /usr/local/bin/cfssl*
2、自籤 Etcd SSL 證書
我們首先為 etcd 簽發一套SSL證書,通過如下命令建立幾個目錄,/k8s/etcd/ssl 用於存放 etcd 自簽證書,/k8s/etcd/cfg 用於存放 etcd 配置檔案,/k8s/etcd/bin 用於存放 etcd 執行程式。
# cd / # mkdir -p /k8s/etcd/{ssl,cfg,bin}
進入 etcd 目錄:
# cd /k8s/etcd/ssl
① 建立 CA 配置檔案:ca-config.json
執行如下命令建立 ca-config.json
cat > ca-config.json <<EOF { "signing": { "default": { "expiry": "87600h" }, "profiles": { "etcd": { "usages": [ "signing", "key encipherment", "server auth", "client auth" ], "expiry": "87600h" } } } } EOF
說明:
- signing:表示該證書可用於簽名其它證書;生成的 ca.pem 證書中 CA=TRUE;
- profiles:可以定義多個 profiles,分別指定不同的過期時間、使用場景等引數;後續在簽名證書時使用某個 profile;
- expiry:證書過期時間
- server auth:表示client可以用該 CA 對server提供的證書進行驗證;
- client auth:表示server可以用該CA對client提供的證書進行驗證;
② 建立 CA 證書籤名請求檔案:ca-csr.json
執行如下命令建立 ca-csr.json:
cat > ca-csr.json <<EOF { "CN": "etcd", "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "Shanghai", "L": "Shanghai", "O": "etcd", "OU": "System" } ], "ca": { "expiry": "87600h" } } EOF
說明:
- CN:Common Name,kube-apiserver 從證書中提取該欄位作為請求的使用者名稱 (User Name);瀏覽器使用該欄位驗證網站是否合法;
- key:加密演算法
- C:國家
- ST:地區
- L:城市
- O:組織,kube-apiserver 從證書中提取該欄位作為請求使用者所屬的組 (Group);
- OU:組織單位
③ 生成 CA 證書和私鑰
# cfssl gencert -initca ca-csr.json | cfssljson -bare ca
說明:
- ca-key.pem:CA 私鑰
- ca.pem:CA 數字證書
④ 建立證書籤名請求檔案:etcd-csr.json
執行如下命令建立 etcd-csr.json:
cat > etcd-csr.json <<EOF { "CN": "etcd", "hosts": [ "192.168.31.24", "192.168.31.35", "192.168.31.71" ], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "etcd", "OU": "System" } ] } EOF
說明:
- hosts:需要指定授權使用該證書的 IP 或域名列表,這裡配置所有 etcd 的IP地址。
- key:加密演算法及長度
⑤ 為 etcd 生成證書和私鑰
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=etcd etcd-csr.json | cfssljson -bare etcd
說明:
- -ca:指定 CA 數字證書
- -ca-key:指定 CA 私鑰
- -config:CA 配置檔案
- -profile:指定環境
- -bare:指定證書名字首
說明:
- ca-key.pem:etcd 私鑰
- ca.pem:etcd 數字證書
證書生成完成,後面部署 Etcd 時主要會用到如下幾個證書:
3、Etcd 資料庫叢集部署
etcd 叢集採用主從架構模式(一主多從)部署,叢集通過選舉產生 leader,因此需要部署奇數個節點(3/5/7)才能正常工作。etcd使用raft一致性演算法保證每個節點的一致性。
① 下載 etcd
從 github 上下載合適版本的 etcd
# cd /k8s/etcd # wget https://github.com/etcd-io/etcd/releases/download/v3.2.28/etcd-v3.2.28-linux-amd64.tar.gz
解壓:
# tar zxf etcd-v3.2.28-linux-amd64.tar.gz
將 etcd 複製到 /usr/local/bin 下:
# cp etcd-v3.2.28-linux-amd64/{etcd,etcdctl} /k8s/etcd/bin # rm -rf etcd-v3.2.28-linux-amd64*
② 建立 etcd 配置檔案:etcd.conf
cat > /k8s/etcd/cfg/etcd.conf <<EOF # [member] ETCD_NAME=etcd-1 ETCD_DATA_DIR=/k8s/data/default.etcd ETCD_LISTEN_PEER_URLS=https://192.168.31.24:2380 ETCD_LISTEN_CLIENT_URLS=https://192.168.31.24:2379 # [cluster] ETCD_INITIAL_ADVERTISE_PEER_URLS=https://192.168.31.24:2380 ETCD_ADVERTISE_CLIENT_URLS=https://192.168.31.24:2379 ETCD_INITIAL_CLUSTER=etcd-1=https://192.168.31.24:2380,etcd-2=https://192.168.31.35:2380,etcd-3=https://192.168.31.71:2380 ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster ETCD_INITIAL_CLUSTER_STATE=new # [security] ETCD_CERT_FILE=/k8s/etcd/ssl/etcd.pem ETCD_KEY_FILE=/k8s/etcd/ssl/etcd-key.pem ETCD_TRUSTED_CA_FILE=/k8s/etcd/ssl/ca.pem ETCD_PEER_CERT_FILE=/k8s/etcd/ssl/etcd.pem ETCD_PEER_KEY_FILE=/k8s/etcd/ssl/etcd-key.pem ETCD_PEER_TRUSTED_CA_FILE=/k8s/etcd/ssl/ca.pem EOF
說明:
- ETCD_NAME:etcd在叢集中的唯一名稱
- ETCD_DATA_DIR:etcd資料存放目錄
- ETCD_LISTEN_PEER_URLS:etcd叢集間通訊的地址,設定為本機IP
- ETCD_LISTEN_CLIENT_URLS:客戶端訪問的地址,設定為本機IP
- ETCD_INITIAL_ADVERTISE_PEER_URLS:初始叢集通告地址,叢集內部通訊地址,設定為本機IP
- ETCD_ADVERTISE_CLIENT_URLS:客戶端通告地址,設定為本機IP
- ETCD_INITIAL_CLUSTER:叢集節點地址,以 key=value 的形式新增各個 etcd 的地址
- ETCD_INITIAL_CLUSTER_TOKEN:叢集令牌,用於叢集間做簡單的認證
- ETCD_INITIAL_CLUSTER_STATE:叢集狀態
- ETCD_CERT_FILE:客戶端 etcd 數字證書路徑
- ETCD_KEY_FILE:客戶端 etcd 私鑰路徑
- ETCD_TRUSTED_CA_FILE:客戶端 CA 證書路徑
- ETCD_PEER_CERT_FILE:叢集間通訊etcd數字證書路徑
- ETCD_PEER_KEY_FILE:叢集間通訊etcd私鑰路徑
- ETCD_PEER_TRUSTED_CA_FILE:叢集間通訊CA證書路徑
③ 建立 etcd 服務:etcd.service
通過EnvironmentFile指定 etcd.conf 作為環境配置檔案
cat > /k8s/etcd/etcd.service <<'EOF' [Unit] Description=Etcd Server After=network.target After=network-online.target Wants=network-online.target [Service] Type=notify EnvironmentFile=/k8s/etcd/cfg/etcd.conf WorkingDirectory=${ETCD_DATA_DIR} ExecStart=/k8s/etcd/bin/etcd \ --name=${ETCD_NAME} \ --data-dir=${ETCD_DATA_DIR} \ --listen-peer-urls=${ETCD_LISTEN_PEER_URLS} \ --listen-client-urls=${ETCD_LISTEN_CLIENT_URLS},http://127.0.0.1:2379 \ --initial-advertise-peer-urls=${ETCD_INITIAL_ADVERTISE_PEER_URLS} \ --advertise-client-urls=${ETCD_ADVERTISE_CLIENT_URLS} \ --initial-cluster=${ETCD_INITIAL_CLUSTER} \ --initial-cluster-token=${ETCD_INITIAL_CLUSTER_TOKEN} \ --initial-cluster-state=${ETCD_INITIAL_CLUSTER_STATE} \ --cert-file=${ETCD_CERT_FILE} \ --key-file=${ETCD_KEY_FILE} \ --trusted-ca-file=${ETCD_TRUSTED_CA_FILE} \ --peer-cert-file=${ETCD_PEER_CERT_FILE} \ --peer-key-file=${ETCD_PEER_KEY_FILE} \ --peer-trusted-ca-file=${ETCD_PEER_TRUSTED_CA_FILE} Restart=on-failure LimitNOFILE=65536 [Install] WantedBy=multi-user.target EOF
etcd.service 更多的配置以及說明可以通過如下命令檢視:
# /k8s/etcd/bin/etcd --help
④ 將 etcd 目錄拷貝到另外兩個節點
# scp -r /k8s root@k8s-node-1:/k8s # scp -r /k8s root@k8s-node-2:/k8s
⑤ 修改兩個節點配置檔案
修改 k8s-node-1 節點的 /k8s/etcd/cfg/etcd.conf:
# [member] ETCD_NAME=etcd-2 ETCD_LISTEN_PEER_URLS=https://192.168.31.35:2380 ETCD_LISTEN_CLIENT_URLS=https://192.168.31.35:2379 # [cluster] ETCD_INITIAL_ADVERTISE_PEER_URLS=https://192.168.31.35:2380 ETCD_ADVERTISE_CLIENT_URLS=https://192.168.31.35:2379
修改 k8s-node-2 節點的 /k8s/etcd/cfg/etcd.conf:
# [member] ETCD_NAME=etcd-2 ETCD_LISTEN_PEER_URLS=https://192.168.31.71:2380 ETCD_LISTEN_CLIENT_URLS=https://192.168.31.71:2379 # [cluster] ETCD_INITIAL_ADVERTISE_PEER_URLS=https://192.168.31.71:2380 ETCD_ADVERTISE_CLIENT_URLS=https://192.168.31.71:2379
⑥ 啟動 etcd 服務
首先在三個節點將 etcd.service 拷貝到 /usr/lib/systemd/system/ 下
# cp /k8s/etcd/etcd.service /usr/lib/systemd/system/ # systemctl daemon-reload
在三個節點啟動 etcd 服務
# systemctl start etcd
設定開機啟動
# systemctl enable etcd
檢視 etcd 的日誌
# tail -f /var/log/messages
注意:如果日誌中出現連線異常資訊,請確認所有節點防火牆是否開放2379,2380埠,或者直接關閉防火牆。
檢視 etcd 叢集狀態
/k8s/etcd/bin/etcdctl \ --ca-file=/k8s/etcd/ssl/ca.pem \ --cert-file=/k8s/etcd/ssl/etcd.pem \ --key-file=/k8s/etcd/ssl/etcd-key.pem \ --endpoints=https://192.168.31.24:2379,https://192.168.31.35:2379,https://192.168.31.71:2379 \ cluster-health回到頂部
六、叢集搭建 —— 部署Master元件
1、自籤 ApiServer SSL 證書
K8S 叢集中所有資源的訪問和變更都是通過 kube-apiserver 的 REST API 來實現的,首先在 master 節點上部署 kube-apiserver 元件。
我們首先為 apiserver 簽發一套SSL證書,過程與 etcd 自籤SSL證書類似。通過如下命令建立幾個目錄,ssl 用於存放自簽證書,cfg 用於存放配置檔案,bin 用於存放執行程式,logs 存放日誌檔案。
# cd / # mkdir -p /k8s/kubernetes/{ssl,cfg,bin,logs}
進入 kubernetes 目錄:
# cd /k8s/kubernetes/ssl
① 建立 CA 配置檔案:ca-config.json
執行如下命令建立 ca-config.json
cat > ca-config.json <<EOF { "signing": { "default": { "expiry": "87600h" }, "profiles": { "kubernetes": { "usages": [ "signing", "key encipherment", "server auth", "client auth" ], "expiry": "87600h" } } } } EOF
② 建立 CA 證書籤名請求檔案:ca-csr.json
執行如下命令建立 ca-csr.json:
cat > ca-csr.json <<EOF { "CN": "kubernetes", "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "Shanghai", "L": "Shanghai", "O": "kubernetes", "OU": "System" } ], "ca": { "expiry": "87600h" } } EOF
③ 生成 CA 證書和私鑰
# cfssl gencert -initca ca-csr.json | cfssljson -bare ca
④ 建立證書籤名請求檔案:kubernetes-csr.json
執行如下命令建立 kubernetes-csr.json:
cat > kubernetes-csr.json <<EOF { "CN": "kubernetes", "hosts": [ "127.0.0.1", "10.0.0.1", "192.168.31.24", "192.168.31.26", "192.168.31.35", "192.168.31.71", "192.168.31.26", "192.168.31.26", "kubernetes", "kubernetes.default", "kubernetes.default.svc", "kubernetes.default.svc.cluster", "kubernetes.default.svc.cluster.local" ], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "kubernetes", "OU": "System" } ] } EOF
說明:
- hosts:指定會直接訪問 apiserver 的IP列表,一般需指定 etcd 叢集、kubernetes master 叢集的主機 IP 和 kubernetes 服務的服務 IP,Node 的IP一般不需要加入。
⑤ 為 kubernetes 生成證書和私鑰
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kubernetes-csr.json | cfssljson -bare kubernetes
2、部署 kube-apiserver 元件
① 下載二進位制包
通過 kubernetes Github 下載安裝用的二進位制包,我這裡使用 v1.16.2 版本,server 二進位制包已經包含了 master、node 上的各個元件,下載 server 二進位制包即可。
考慮到網路問題,可以從百度網盤下載已經準備好的二進位制包:連結: 下載離線安裝包。
將下載好的 kubernetes-v1.16.2-server-linux-amd64.tar.gz 上傳到 /usr/local/src下,並解壓:
# tar -zxf kubernetes-v1.16.2-server-linux-amd64.tar.gz
先將 master 節點上部署的元件拷貝到 /k8s/kubernetes/bin 目錄下:
# cp -p /usr/local/src/kubernetes/server/bin/{kube-apiserver,kube-controller-manager,kube-scheduler} /k8s/kubernetes/bin/ # cp -p /usr/local/src/kubernetes/server/bin/kubectl /usr/local/bin/
② 建立 Node 令牌檔案:token.csv
Master apiserver 啟用 TLS 認證後,Node節點 kubelet 元件想要加入叢集,必須使用CA簽發的有效證書才能與apiserver通訊,當Node節點很多時,簽署證書是一件很繁瑣的事情,因此有了 TLS Bootstrap 機制,kubelet 會以一個低許可權使用者自動向 apiserver 申請證書,kubelet 的證書由 apiserver 動態簽署。因此先為 apiserver 生成一個令牌檔案,令牌之後會在 Node 中用到。
生成 token,一個隨機字串,可使用如下命令生成 token:apiserver 配置的 token 必須與 Node 節點 bootstrap.kubeconfig 配置保持一致。
# head -c 16 /dev/urandom | od -An -t x | tr -d ' '
建立 token.csv,格式:token,使用者,UID,使用者組
cat > /k8s/kubernetes/cfg/token.csv <<'EOF' bfa3cb7f6f21f87e5c0e5f25e6cfedad,kubelet-bootstrap,10001,"system:node-bootstrapper" EOF
③ 建立 kube-apiserver 配置檔案:kube-apiserver.conf
kube-apiserver 有很多配置項,可以參考官方文件檢視每個配置項的用途:kube-apiserver
注意:踩的一個坑,“\” 後面不要有空格,不要有多餘的換行,否則啟動失敗。
cat > /k8s/kubernetes/cfg/kube-apiserver.conf <<'EOF' KUBE_APISERVER_OPTS="--etcd-servers=https://192.168.31.24:2379,https://192.168.31.35:2379,https://192.168.31.71:2379 \ --bind-address=192.168.31.24 \ --secure-port=6443 \ --advertise-address=192.168.31.24 \ --allow-privileged=true \ --service-cluster-ip-range=10.0.0.0/24 \ --service-node-port-range=30000-32767 \ --enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota,NodeRestriction \ --authorization-mode=RBAC,Node \ --enable-bootstrap-token-auth=true \ --token-auth-file=/k8s/kubernetes/cfg/token.csv \ --kubelet-client-certificate=/k8s/kubernetes/ssl/kubernetes.pem \ --kubelet-client-key=/k8s/kubernetes/ssl/kubernetes-key.pem \ --tls-cert-file=/k8s/kubernetes/ssl/kubernetes.pem \ --tls-private-key-file=/k8s/kubernetes/ssl/kubernetes-key.pem \ --client-ca-file=/k8s/kubernetes/ssl/ca.pem \ --service-account-key-file=/k8s/kubernetes/ssl/ca-key.pem \ --etcd-cafile=/k8s/etcd/ssl/ca.pem \ --etcd-certfile=/k8s/etcd/ssl/etcd.pem \ --etcd-keyfile=/k8s/etcd/ssl/etcd-key.pem \ --v=2 \ --logtostderr=false \ --log-dir=/k8s/kubernetes/logs \ --audit-log-maxage=30 \ --audit-log-maxbackup=3 \ --audit-log-maxsize=100 \ --audit-log-path=/k8s/kubernetes/logs/k8s-audit.log" EOF
重點配置說明:
- --etcd-servers:etcd 叢集地址
- --bind-address:apiserver 監聽的地址,一般配主機IP
- --secure-port:監聽的埠
- --advertise-address:叢集通告地址,其它Node節點通過這個地址連線 apiserver,不配置則使用 --bind-address
- --service-cluster-ip-range:Service 的 虛擬IP範圍,以CIDR格式標識,該IP範圍不能與物理機的真實IP段有重合。
- --service-node-port-range:Service 可對映的物理機埠範圍,預設30000-32767
- --admission-control:叢集的准入控制設定,各控制模組以外掛的形式依次生效,啟用RBAC授權和節點自管理
- --authorization-mode:授權模式,包括:AlwaysAllow,AlwaysDeny,ABAC(基於屬性的訪問控制),Webhook,RBAC(基於角色的訪問控制),Node(專門授權由 kubelet 發出的API請求)。(預設值"AlwaysAllow")。
- --enable-bootstrap-token-auth:啟用TLS bootstrap功能
- --token-auth-file:這個檔案將被用於通過令牌認證來保護API服務的安全埠。
- --v:指定日誌級別,0~8,越大日誌越詳細
④ 建立 apiserver 服務:kube-apiserver.service
cat > /usr/lib/systemd/system/kube-apiserver.service <<'EOF' [Unit] Description=Kubernetes API Server Documentation=https://github.com/GoogleCloudPlatform/kubernetes After=network.target [Service] EnvironmentFile=-/k8s/kubernetes/cfg/kube-apiserver.conf ExecStart=/k8s/kubernetes/bin/kube-apiserver $KUBE_APISERVER_OPTS
Restart=on-failure LimitNOFILE=65536 [Install] WantedBy=multi-user.target EOF
⑤ 啟動 kube-apiserver 元件
啟動元件
# systemctl daemon-reload # systemctl start kube-apiserver # systemctl enable kube-apiserver
檢查啟動狀態
# systemctl status kube-apiserver.service
檢視啟動日誌
# less /k8s/kubernetes/logs/kube-apiserver.INFO
⑥ 將 kubelet-bootstrap 使用者繫結到系統叢集角色,之後便於 Node 使用token請求證書
kubectl create clusterrolebinding kubelet-bootstrap \ --clusterrole=system:node-bootstrapper \ --user=kubelet-bootstrap
3、部署 kube-controller-manager 元件
① 建立 kube-controller-manager 配置檔案:kube-controller-manager.conf
詳細的配置可參考官方文件:kube-controller-manager
cat > /k8s/kubernetes/cfg/kube-controller-manager.conf <<'EOF' KUBE_CONTROLLER_MANAGER_OPTS="--leader-elect=true \ --master=127.0.0.1:8080 \ --address=127.0.0.1 \ --allocate-node-cidrs=true \ --cluster-cidr=10.244.0.0/16 \ --service-cluster-ip-range=10.0.0.0/24 \ --cluster-signing-cert-file=/k8s/kubernetes/ssl/ca.pem \ --cluster-signing-key-file=/k8s/kubernetes/ssl/ca-key.pem \ --root-ca-file=/k8s/kubernetes/ssl/ca.pem \ --service-account-private-key-file=/k8s/kubernetes/ssl/ca-key.pem \ --experimental-cluster-signing-duration=87600h0m0s \ --v=2 \ --logtostderr=false \ --log-dir=/k8s/kubernetes/logs" EOF
重點配置說明:
- --leader-elect:當該元件啟動多個時,自動選舉,預設true
- --master:連線本地apiserver,apiserver 預設會監聽本地8080埠
- --allocate-node-cidrs:是否分配和設定Pod的CDIR
- --service-cluster-ip-range:Service 叢集IP段
② 建立 kube-controller-manager 服務:kube-controller-manager.service
cat > /usr/lib/systemd/system/kube-controller-manager.service <<'EOF' [Unit] Description=Kubernetes Controller Manager Documentation=https://github.com/GoogleCloudPlatform/kubernetes After=network.target [Service] EnvironmentFile=/k8s/kubernetes/cfg/kube-controller-manager.conf ExecStart=/k8s/kubernetes/bin/kube-controller-manager $KUBE_CONTROLLER_MANAGER_OPTS
Restart=on-failure LimitNOFILE=65536 [Install] WantedBy=multi-user.target EOF
③ 啟動 kube-controller-manager 元件
啟動元件
# systemctl daemon-reload # systemctl start kube-controller-manager # systemctl enable kube-controller-manager
檢查啟動狀態
# systemctl status kube-controller-manager.service
檢視啟動日誌
# less /k8s/kubernetes/logs/kube-controller-manager.INFO
4、部署 kube-scheduler 元件
① 建立 kube-scheduler 配置檔案:kube-scheduler.conf
cat > /k8s/kubernetes/cfg/kube-scheduler.conf <<'EOF' KUBE_SCHEDULER_OPTS="--leader-elect=true \ --master=127.0.0.1:8080 \ --address=127.0.0.1 \ --v=2 \ --logtostderr=false \ --log-dir=/k8s/kubernetes/logs" EOF
② 建立 kube-scheduler 服務:kube-scheduler.service
cat > /usr/lib/systemd/system/kube-scheduler.service <<'EOF' [Unit] Description=Kubernetes Scheduler Documentation=https://github.com/GoogleCloudPlatform/kubernetes After=network.target [Service] EnvironmentFile=/k8s/kubernetes/cfg/kube-scheduler.conf ExecStart=/k8s/kubernetes/bin/kube-scheduler $KUBE_SCHEDULER_OPTS
Restart=on-failure LimitNOFILE=65536 [Install] WantedBy=multi-user.target EOF
③ 啟動 kube-scheduler 元件
啟動元件
# systemctl daemon-reload # systemctl start kube-scheduler # systemctl enable kube-scheduler
檢視啟動狀態
# systemctl status kube-scheduler.service
檢視啟動日誌
# less /k8s/kubernetes/logs/kube-scheduler.INFO
less /k8s/kubernetes/logs/kube-scheduler.INFO
5、檢視叢集狀態
① 檢視元件狀態
# kubectl get cs回到頂部
七、叢集搭建 —— 部署Node元件
1、安裝 Docker
CentOS 安裝參考官方文件:https://docs.docker.com/install/linux/docker-ce/centos/
① 解除安裝舊版本
# yum remove docker docker-common docker-selinux
② 安裝依賴包
# yum install -y yum-utils device-mapper-persistent-data lvm2
③ 安裝 Docker 軟體包源
# yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
④ 安裝 Docker CE
# yum install docker-ce
⑤ 啟動 Docker 服務
# systemctl start docker
⑥ 設定開機啟動
# systemctl enable docker
⑦ 驗證安裝是否成功
# docker -v
# docker info
2、Node 節點證書
① 建立 Node 節點的證書籤名請求檔案:kube-proxy-csr.json
首先在 k8s-master-1 節點上,通過頒發的 CA 證書先建立好 Node 節點要使用的證書,先建立證書籤名請求檔案:kube-proxy-csr.json:
cat > kube-proxy-csr.json <<EOF { "CN": "system:kube-proxy", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "kubernetes", "OU": "System" } ] } EOF
② 為 kube-proxy 生成證書和私鑰
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy
③ node 節點建立工作目錄
在 k8s-node-1 節點上建立 k8s 目錄
# mkdir -p /k8s/kubernetes/{bin,cfg,logs,ssl}
④ 將 k8s-master-1 節點的檔案拷貝到 node 節點
將 kubelet、kube-proxy 拷貝到 node 節點上:
# scp -r /usr/local/src/kubernetes/server/bin/{kubelet,kube-proxy} root@k8s-node-1:/k8s/kubernetes/bin/
將證書拷貝到 k8s-node-1 節點上:
# scp -r /k8s/kubernetes/ssl/{ca.pem,kube-proxy.pem,kube-proxy-key.pem} root@k8s-node-1:/k8s/kubernetes/ssl/
3、安裝 kubelet
① 建立請求證書的配置檔案:bootstrap.kubeconfig
bootstrap.kubeconfig 將用於向 apiserver 請求證書,apiserver 會驗證 token、證書 是否有效,驗證通過則自動頒發證書。
cat > /k8s/kubernetes/cfg/bootstrap.kubeconfig <<'EOF' apiVersion: v1 clusters: - cluster: certificate-authority: /k8s/kubernetes/ssl/ca.pem server: https://192.168.31.24:6443 name: kubernetes contexts: - context: cluster: kubernetes user: kubelet-bootstrap name: default current-context: default kind: Config preferences: {} users: - name: kubelet-bootstrap user: token: bfa3cb7f6f21f87e5c0e5f25e6cfedad EOF
說明:
- certificate-authority:CA 證書
- server:master 地址
- token:master 上 token.csv 中配置的 token
② 建立 kubelet 配置檔案:kubelet-config.yml
為了安全性,kubelet 禁止匿名訪問,必須授權才可以,通過 kubelet-config.yml 授權 apiserver 訪問 kubelet。
cat > /k8s/kubernetes/cfg/kubelet-config.yml <<'EOF' kind: KubeletConfiguration apiVersion: kubelet.config.k8s.io/v1beta1 address: 0.0.0.0 port: 10250 readOnlyPort: 10255 cgroupDriver: cgroupfs clusterDNS: - 10.0.0.2 clusterDomain: cluster.local failSwapOn: false authentication: anonymous: enabled: false webhook: cacheTTL: 2m0s enabled: true x509: clientCAFile: /k8s/kubernetes/ssl/ca.pem authorization: mode: Webhook webhook: cacheAuthroizedTTL: 5m0s cacheUnauthorizedTTL: 30s evictionHard: imagefs.available: 15% memory.available: 100Mi nodefs.available: 10% nodefs.inodesFree: 5% maxOpenFiles: 100000 maxPods: 110 EOF
說明:
- address:kubelet 監聽地址
- port:kubelet 的埠
- cgroupDriver:cgroup 驅動,與 docker 的 cgroup 驅動一致
- authentication:訪問 kubelet 的授權資訊
- authorization:認證相關資訊
- evictionHard:垃圾回收策略
- maxPods:最大pod數
③ 建立 kubelet 服務配置檔案:kubelet.conf
cat > /k8s/kubernetes/cfg/kubelet.conf <<'EOF' KUBELET_OPTS="--hostname-override=k8s-node-1 \ --network-plugin=cni \ --cni-bin-dir=/opt/cni/bin \ --cni-conf-dir=/etc/cni/net.d \ --cgroups-per-qos=false \ --enforce-node-allocatable="" \ --kubeconfig=/k8s/kubernetes/cfg/kubelet.kubeconfig \ --bootstrap-kubeconfig=/k8s/kubernetes/cfg/bootstrap.kubeconfig \ --config=/k8s/kubernetes/cfg/kubelet-config.yml \ --cert-dir=/k8s/kubernetes/ssl \ --pod-infra-container-image=kubernetes/pause:latest \ --v=2 \ --logtostderr=false \ --log-dir=/k8s/kubernetes/logs" EOF
說明:
- --hostname-override:當前節點註冊到K8S中顯示的名稱,預設為主機 hostname
- --network-plugin:啟用 CNI 網路外掛
- --cni-bin-dir:CNI 外掛可執行檔案位置,預設在 /opt/cni/bin 下
- --cni-conf-dir:CNI 外掛配置檔案位置,預設在 /etc/cni/net.d 下
- --cgroups-per-qos:必須加上這個引數和--enforce-node-allocatable,否則報錯 [Failed to start ContainerManager failed to initialize top level QOS containers.......]
- --kubeconfig:會自動生成 kubelet.kubeconfig,用於連線 apiserver
- --bootstrap-kubeconfig:指定 bootstrap.kubeconfig 檔案
- --config:kubelet 配置檔案
- --cert-dir:證書目錄
- --pod-infra-container-image:管理Pod網路的映象,基礎的 Pause 容器,預設是 k8s.gcr.io/pause:3.1
④ 建立 kubelet 服務:kubelet.service
cat > /usr/lib/systemd/system/kubelet.service <<'EOF' [Unit] Description=Kubernetes Kubelet After=docker.service Before=docker.service [Service] EnvironmentFile=/k8s/kubernetes/cfg/kubelet.conf ExecStart=/k8s/kubernetes/bin/kubelet $KUBELET_OPTS Restart=on-failure LimitNOFILE=65536 [Install] WantedBy=multi-user.target EOF
⑤ 啟動 kubelet
# systemctl daemon-reload
# systemctl start kubelet
開機啟動:
# systemctl enable kubelet
檢視啟動日誌:
# tail -f /k8s/kubernetes/logs/kubelet.INFO
⑥ master 給 node 授權
kubelet 啟動後,還沒加入到叢集中,會向 apiserver 請求證書,需手動在 k8s-master-1 上對 node 授權。
通過如下命令檢視是否有新的客戶端請求頒發證書:
# kubectl get csr
給客戶端頒發證書,允許客戶端加入叢集:
# kubectl certificate approve node-csr-FoPLmv3Sr2XcYvNAineE6RpdARf2eKQzJsQyfhk-xf8
⑦ 授權成功
檢視 node 是否加入叢集(此時的 node 還處於未就緒的狀態,因為還沒有安裝 CNI 元件):
# kubectl get node
頒發證書後,可以在 /k8s/kubenetes/ssl 下看到 master 為 kubelet 頒發的證書:
在 /k8s/kubenetes/cfg 下可以看到自動生成的 kubelet.kubeconfig 配置檔案:
4、安裝 kube-proxy
① 建立 kube-proxy 連線 apiserver 的配置檔案:kube-proxy.kubeconfig
cat > /k8s/kubernetes/cfg/kube-proxy.kubeconfig <<'EOF' apiVersion: v1 clusters: - cluster: certificate-authority: /k8s/kubernetes/ssl/ca.pem server: https://192.168.31.24:6443 name: kubernetes contexts: - context: cluster: kubernetes user: kube-proxy name: default current-context: default kind: Config preferences: {} users: - name: kube-proxy user: client-certificate: /k8s/kubernetes/ssl/kube-proxy.pem client-key: /k8s/kubernetes/ssl/kube-proxy-key.pem EOF
② 建立 kube-proxy 配置檔案:kube-proxy-config.yml
cat > /k8s/kubernetes/cfg/kube-proxy-config.yml <<'EOF' kind: KubeProxyConfiguration apiVersion: kubeproxy.config.k8s.io/v1alpha1 address: 0.0.0.0 metrisBindAddress: 0.0.0.0:10249 clientConnection: kubeconfig: /k8s/kubernetes/cfg/kube-proxy.kubeconfig hostnameOverride: k8s-node-1 clusterCIDR: 10.0.0.0/24 mode: ipvs ipvs: scheduler: "rr" iptables: masqueradeAll: true EOF
說明:
- metrisBindAddress:採集指標暴露的地址埠,便於監控系統,採集資料
- clusterCIDR:叢集 Service 網段
③ 建立 kube-proxy 配置檔案:kube-proxy.conf
cat > /k8s/kubernetes/cfg/kube-proxy.conf <<'EOF' KUBE_PROXY_OPTS="--config=/k8s/kubernetes/cfg/kube-proxy-config.yml \ --v=2 \ --logtostderr=false \ --log-dir=/k8s/kubernetes/logs" EOF
④ 建立 kube-proxy 服務:kube-proxy.service
cat > /usr/lib/systemd/system/kube-proxy.service <<'EOF' [Unit] Description=Kubernetes Proxy After=network.target [Service] EnvironmentFile=/k8s/kubernetes/cfg/kube-proxy.conf ExecStart=/k8s/kubernetes/bin/kube-proxy $KUBE_PROXY_OPTS Restart=on-failure LimitNOFILE=65536 [Install] WantedBy=multi-user.target EOF
⑤ 啟動 kube-proxy
啟動服務:
# systemctl daemon-reload
# systemctl start kube-proxy
開機啟動:
# systemctl enable kube-proxy
檢視啟動日誌:
# tail -f /k8s/kubernetes/logs/kube-proxy.INFO
5、部署其它Node節點
部署其它 Node 節點基於與上述流程一致,只需將配置檔案中 k8s-node-1 改為 k8s-node-2 即可。
# kubectl get node -o wide
6、部署K8S容器叢集網路(Flannel)
① K8S 叢集網路
Kubernetes 專案並沒有使用 Docker 的網路模型,kubernetes 是通過一個 CNI 介面維護一個單獨的網橋來代替 docker0,這個網橋預設叫 cni0。
CNI(Container Network Interface)是CNCF旗下的一個專案,由一組用於配置 Linux 容器的網路介面的規範和庫組成,同時還包含了一些外掛。CNI僅關心容器建立時的網路分配,和當容器被刪除時釋放網路資源。
Flannel 是 CNI 的一個外掛,可以看做是 CNI 介面的一種實現。Flannel 是針對 Kubernetes 設計的一個網路規劃服務,它的功能是讓叢集中的不同節點主機建立的Docker容器都具有全叢集唯一的虛擬IP地址,並讓屬於不同節點上的容器能夠直接通過內網IP通訊。
Flannel 網路架構請參考:flannel 網路架構
② 建立 CNI 工作目錄
通過給 kubelet 傳遞 --network-plugin=cni 命令列選項來啟用 CNI 外掛。 kubelet 從 --cni-conf-dir (預設是 /etc/cni/net.d)讀取配置檔案並使用該檔案中的 CNI 配置來設定每個 pod 的網路。CNI 配置檔案必須與 CNI 規約匹配,並且配置引用的任何所需的 CNI 外掛都必須存在於 --cni-bin-dir(預設是 /opt/cni/bin)指定的目錄。
由於前面部署 kubelet 服務時,指定了 --cni-conf-dir=/etc/cni/net.d,--cni-bin-dir=/opt/cni/bin,因此首先在node節點上建立這兩個目錄:
# mkdir -p /opt/cni/bin /etc/cni/net.d
③ 裝 CNI 外掛
可以從 github 上下載 CNI 外掛:下載 CNI 外掛 。
解壓到 /opt/cni/bin:
# tar zxf cni-plugins-linux-amd64-v0.8.2.tgz -C /opt/cni/bin/
④ 部署 Flannel
可通過此地址下載 flannel 配置檔案:下載 kube-flannel.yml
注意如下配置:Network 的地址需與 kube-controller-manager.conf 中的 --cluster-cidr=10.244.0.0/16 保持一致。
在 k8s-master-1 節點上部署 Flannel:
# kubectl apply -f kube-flannel.yml
⑤ 檢查部署狀態
Flannel 會在 Node 上起一個 Flannel 的 Pod,可以檢視 pod 的狀態看 flannel 是否啟動成功:
# kubectl get pods -n kube-system -o wide
Flannel 部署成功後,就可以看 Node 是否就緒:
# kubectl get nodes -o wide
在 Node 上檢視網路配置,可以看到多了一個 flannel.1 的虛擬網絡卡,這塊網絡卡用於接收 Pod 的流量並轉發出去。
⑥ 測試建立 Pod
例如建立一個 Nginx 服務:
# kubectl create deployment web --image=nginx
檢視 Pod 狀態:
在對應的節點上可以看到部署的容器:
容器建立成功後,再在 Node 上檢視網路配置,又多了一塊 cni0 的虛擬網絡卡,cni0 用於 pod 本地通訊使用。
暴露埠並訪問 Nginx:
# kubectl expose deployment web --port=80 --type=NodePort
7、部署內部 DNS 服務
在Kubernetes叢集推薦使用Service Name作為服務的訪問地址,因此需要一個Kubernetes叢集範圍的DNS服務實現從Service Name到Cluster IP的解析,這就是Kubernetes基於DNS的服務發現功能。
① 部署 CoreDNS
下載CoreDNS配置檔案:coredns.yaml
注意如下 clusterIP 一定要與 kube-config.yaml 中的 clusterDNS 保持一致
部署 CoreDNS:
$ kubectl apply -f coredns.yaml
② 驗證 CoreDNS
建立 busybox 服務:
# cat > busybox.yaml <<'EOF' apiVersion: v1 kind: Pod metadata: name: busybox namespace: default spec: dnsPolicy: ClusterFirst containers: - name: busybox image: busybox:1.28.4 command: - sleep - "3600" imagePullPolicy: IfNotPresent restartPolicy: Always EOF
# kubectl apply -f busybox.yaml
驗證是否安裝成功:
回到頂部八、叢集搭建 —— 部署 Dashboard
K8S 提供了一個 Web 版 Dashboard,使用者可以用 dashboard 部署容器化的應用、監控應用的狀態,能夠建立和修改各種 K8S 資源,比如 Deployment、Job、DaemonSet 等。使用者可以 Scale Up/Down Deployment、執行 Rolling Update、重啟某個 Pod 或者通過嚮導部署新的應用。Dashboard 能顯示叢集中各種資源的狀態以及日誌資訊。Kubernetes Dashboard 提供了 kubectl 的絕大部分功能。
1、部署 K8S Dashboard
通過此地址下載 dashboard yaml檔案:kubernetes-dashboard.yaml
下載下來之後,需更新如下內容:通過 Node 暴露埠訪問 dashboard
部署 dashboard:
# kubectl apply -f kubernetes-dashboard.yaml
檢視是否部署成功:
通過 https 訪問 dashboard:
2、登入授權
Dashboard 支援 Kubeconfig 和 Token 兩種認證方式,為了簡化配置,我們通過配置檔案為 Dashboard 預設使用者賦予 admin 許可權。
cat > kubernetes-adminuser.yaml <<'EOF' apiVersion: v1 kind: ServiceAccount metadata: name: admin-user namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: name: admin-user roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: admin-user namespace: kube-system EOF
授權:
# kubectl apply -f kubernetes-adminuser.yaml
獲取登入的 token:
# kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk ' {print $1}')
通過token登入進 dashboard,就可以檢視叢集的資訊:
回到頂部九、叢集搭建 —— 多 Master 部署
1、部署Master2元件
① 將 k8s-master-1 上相關檔案拷貝到 k8s-master-2 上
建立k8s工作目錄:
# mkdir -p /k8s/kubernetes # mkdir -p /k8s/etcd
拷貝 k8s 配置檔案、執行檔案、證書:
# scp -r /k8s/kubernetes/{cfg,ssl,bin} root@k8s-master-2:/k8s/kubernetes # cp /k8s/kubernetes/bin/kubectl /usr/local/bin/
拷貝 etcd 證書:
# scp -r /k8s/etcd/ssl root@k8s-master-2:/k8s/etcd
拷貝 k8s 服務的service檔案:
# scp /usr/lib/systemd/system/kube-* root@k8s-master-2:/usr/lib/systemd/system
② 修改 k8s-master-2 上的配置檔案
修改 kube-apiserver.conf,修改IP為本機IP
③ 啟動 k8s-master-2 元件
重新載入配置:
# systemctl daemon-reload
啟動 kube-apiserver:
# systemctl start kube-apiserver # systemctl enable kube-apiserver
啟動 kube-controller-manager:
# systemctl start kube-controller-manager # systemctl enable kube-controller-manager
部署 kube-scheduler:
# systemctl start kube-scheduler # systemctl enable kube-scheduler
④ 驗證
2、部署 Nginx 負載均衡
為了保證 k8s master 的高可用,將使用 k8s-lb-master 和 k8s-lb-backup 這兩臺機器來部署負載均衡。這裡使用 nginx 做負載均衡器,下面分別在 k8s-lb-master 和 k8s-lb-backup 這兩臺機器上部署 nginx。
① gcc等環境安裝,後續有些軟體安裝需要這些基礎環境
# gcc安裝: # yum install gcc-c++ # PCRE pcre-devel 安裝: # yum install -y pcre pcre-devel # zlib 安裝: # yum install -y zlib zlib-devel #OpenSSL 安裝: # yum install -y openssl openssl-devel
② 安裝nginx
# rpm -ivh https://nginx.org/packages/rhel/7/x86_64/RPMS/nginx-1.16.1-1.el7.ngx.x86_64.rpm
③ apiserver 負載配置
# vim /etc/nginx/nginx.conf
增加如下配置:
stream { log_format main '$remote_addr $upstream_addr - [$time_local] $status $upstream_bytes_sent'; access_log /var/log/nginx/k8s-access.log main; upstream k8s-apiserver { server 192.168.31.24:6443; server 192.168.31.26:6443; } server { listen 6443; proxy_pass k8s-apiserver; } }
④ 啟動 nginx
# systemctl start nginx # systemctl enable nginx
3、部署 KeepAlive
為了保證 nginx 的高可用,還需要部署 keepalive,keepalive 主要負責 nginx 的健康檢查和故障轉移。
① 分別在 k8s-lb-master 和 k8s-lb-backup 這兩臺機器上安裝 keepalive
# yum install keepalived -y
② master 啟動 keepalived
修改 k8s-lb-master keepalived 配置檔案
cat > /etc/keepalived/keepalived.conf <<'EOF' global_defs { notification_email { [email protected] [email protected] [email protected] } notification_email_from [email protected] smtp_server 127.0.0.1 smtp_connect_timeout 30 router_id NGINX_MASTER } vrrp_script check_nginx { script "/etc/keepalived/check_nginx.sh" } # vrrp例項 vrrp_instance VI_1 { state MASTER interface ens33 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.31.100/24 } track_script { check_nginx } } EOF
配置說明:
- vrrp_script:用於健康檢查nginx狀態,如果nginx沒有正常工作,就會進行故障漂移,使備節點接管VIP,這裡通過 shell 指令碼來檢查nginx狀態
- state:keepalived 角色,主節點為 MASTER,備節點為 BACKUP
- interface:介面,配置本地網絡卡名,keepalived 會將虛擬IP繫結到這個網絡卡上
- virtual_router_id:#VRRP 路由ID例項,每個例項是唯一的
- priority:優先順序,備伺服器設定90
- advert_int:指定VRRP心跳包通告間隔時間,預設1秒
- virtual_ipaddress:VIP,要與當前機器在同一網段,keepalived 會在網絡卡上附加這個IP,之後通過這個IP來訪問Nginx,當nginx不可用時,會將此虛擬IP漂移到備節點上。
增加 check_nginx.sh 指令碼,通過此指令碼判斷 nginx 是否正常:
cat > /etc/keepalived/check_nginx.sh <<'EOF' #!/bin/bash count=$(ps -ef | grep nginx | egrep -cv "grep|$$") if [ "$count" -eq 0 ];then exit 1; else exit 0; fi EOF
增加可執行許可權:
# chmod +x /etc/keepalived/check_nginx.sh
啟動 keepalived:
# systemctl start keepalived # systemctl enable keepalived
③ backup 啟動 keepalived
修改 k8s-lb-backup keepalived 配置檔案
cat > /etc/keepalived/keepalived.conf <<'EOF' global_defs { notification_email { [email protected] [email protected] [email protected] } notification_email_from [email protected] smtp_server 127.0.0.1 smtp_connect_timeout 30 router_id NGINX_BACKUP } vrrp_script check_nginx { script "/etc/keepalived/check_nginx.sh" } # vrrp例項 vrrp_instance VI_1 { state BACKUP interface eno16777736 virtual_router_id 51 priority 90 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.31.100/24 } track_script { check_nginx } } EOF
增加 check_nginx.sh 指令碼:
cat > /etc/keepalived/check_nginx.sh <<'EOF' #!/bin/bash count=$(ps -ef | grep nginx | egrep -cv "grep|$$") if [ "$count" -eq 0 ];then exit 1; else exit 0; fi EOF
增加可執行許可權:
# chmod +x /etc/keepalived/check_nginx.sh
啟動 keepalived:
# systemctl start keepalived # systemctl enable keepalived
④ 驗證負載均衡
keepalived 已經將VIP附加到MASTER所在的網絡卡上
BACKUP節點上並沒有
關閉 k8s-lb-master 上的nginx,可看到VIP已經不在了
可以看到已經漂移到備節點上了,如果再重啟 MASTER 上的 Ngnix,VIP又會漂移到主節點上。
訪問虛擬IP還是可以訪問的
4、Node節點連線VIP
① 修改 node 節點的配置檔案中連線 k8s-master 的IP為VIP
② 重啟 kubelet 和 kube-proxy
# systemctl restart kubelet # systemctl restart kube-proxy
③ 在 node 節點上訪問VIP呼叫 apiserver 驗證
Authorization 的token 是前面生成 token.csv 中的令牌。
至此,通過二進位制方式安裝 K8S 叢集就算完成了!!