1. 程式人生 > 其它 >Kubernetes 深入學習

Kubernetes 深入學習

目錄

 


回到頂部

一、簡介

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 叢集就算完成了!!