本文介紹單/多Master的K8S集群搭建全程序,
目錄
1 環境要求、節點規劃、配置
1.1 環境要求
1.2 節點規劃
1.3 作業系統初始化配置
2 ETCD集群部署
2.1 準備cfssl證書生成工具
2.2 生成ETCD證書
2.3 下載ETCD的二進制檔案
2.4 部署ETCD集群
3 安裝Docker
4 部署 Master-Node
4.1 生成kube-apiserver證書
4.2 下載并解壓二進制檔案
4.3 部署 kube-apiserver
4.4 部署 kube-controller-manager
4.5 部署 kube-scheduler
5 部署 Work-Node
5.1 創建作業目錄并拷貝二進制檔案
5.2 部署kubelet
5.3 批準 kubelet 證書申請并加入集群
5.4 部署 kube-proxy
5.5 部署網路組件
5.6 授權 apiserver 訪問 kubelet
5.7 新增加 Worker-Node
6 部署 DashBoard 和 CoreDNS
6.1 部署 DashBoard
6.2 部署 CoreDNS
7 擴容多 Master(高可用架構)
7.1 部署 Master2 Node
7.2 部署 Nginx+Keepalived 高可用負載均衡器
1 環境要求、節點規劃、配置
1.1 環境要求
- 作業系統:CentOS7.8_x64 (mini)
- 系統配置(每臺虛擬機):2G記憶體、2個CPU、每個CPU上1個核心、20G硬碟
- 網路要求:每臺虛擬機可訪問外網,機器之間可相互訪問
- Docker 版本:19-ce
- Kubernetes 版本:1.18
1.2 節點規劃
由于我只有一臺筆記本電腦(WIN10,16G記憶體),為了在VMWare中少開啟幾臺虛擬機,就把ETCD集群分別放到僅有的3個節點中,單Master節點的K8S集群部署架構及組件安裝如下圖:

因此,本次環境搭建,一共用到3臺虛擬機(單Master節點、雙Node節點,1+2=3臺)
單Master的K8S集群節點規劃如下 :
| 節點 | ip | 需要安裝的組件 |
| k8s-master1 | 192.168.200.200 | kube-apiserver、kube-controller-manager、kube-scheduler、etcd |
| k8s-node1 | 192.168.200.201 | kubelet、kube-proxy、docker、etcd |
| k8s-node2 | 192.168.200.202 | kubelet、kube-proxy、docker、etcd |
1.3 作業系統初始化配置
如下的8個步驟,需要在三臺主機上分別執行一遍:
# 1、關閉防火墻
systemctl stop firewalld && systemctl disable firewalld
# 2、關閉selinux(我選擇永久關閉,需要重啟機器)
永久關閉:sed -i 's/enforcing/disabled/' /etc/selinux/config
臨時關閉:setenforce 0
# 3、關閉swap(我選擇永久關閉)
永久關閉:sed -ri 's/.*swap.*/#&/' /etc/fstab
臨時關閉:swapoff -a
# 4、根據規劃設定主機名(更改后命令列輸入:bash 直接生效)
hostnamectl set-hostname k8s-master1
hostnamectl set-hostname k8s-node1
hostnamectl set-hostname k8s-node2
# 5、在master節點中添加集群中各個節點的主機名與ip的對應關系
#只有這個部分是只在Master中執行,其他的指令需要在3臺機器上都執行一遍
cat >> /etc/hosts << EOF
192.168.200.200 k8s-master
192.168.200.201 k8s-node1
192.168.200.202 k8s-node2
EOF
# 6、將橋接的IPv4流量傳遞到iptables的鏈
cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
# 7、配置生效
sysctl --system
# 8、時間同步
yum install ntpdate -y && ntpdate time.windows.com
2 ETCD集群部署
Etcd 是一個分布式鍵值存盤系統,Kubernetes使用Etcd進行資料存盤,所以先準備一個Etcd資料庫,為解決Etcd單點故障,應采用集群方式部署,這里使用3臺組建集群,可容忍1臺機器故障,為了節省機器,這里把3個ETCD實體分別部署在一個Matser節點和兩個Node節點上,
| ETCD實體 | IP |
| etcd-1 | 192.168.200.200 |
| etcd-2 | 192.168.200.201 |
| etcd-3 | 192.168.200.202 |
2.1 準備cfssl證書生成工具
#1、安裝cfssl證書生成工具(如果下載不了,可嘗試換成http協議)
wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
chmod +x cfssl_linux-amd64 cfssljson_linux-amd64 cfssl-certinfo_linux-amd64
mv cfssl_linux-amd64 /usr/local/bin/cfssl
mv cfssljson_linux-amd64 /usr/local/bin/cfssljson
mv cfssl-certinfo_linux-amd64 /usr/bin/cfssl-certinfo
2.2 生成ETCD證書
#2、生成自簽證書的根證書:創建檔案夾
mkdir -p ~/TLS/{etcd,k8s}
cd TLS/etcd
#3、生成自簽證書的根證書:檔案夾中寫入組態檔2個
#組態檔1
cat > ca-config.json << EOF
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"www": {
"expiry": "87600h",
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
]
}
}
}
}
EOF
#組態檔2
cat > ca-csr.json << EOF
{
"CN": "etcd CA",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "Beijing",
"ST": "Beijing"
}
]
}
EOF
#4、執行如下指令生成證書
cfssl gencert -initca ca-csr.json | cfssljson -bare ca -

接下來,使用自簽的根證書簽發ETCD HTTPS證書:
#5、創建證書申請檔案
cat > server-csr.json << EOF
{
"CN": "etcd",
"hosts": [
"192.168.200.200",
"192.168.200.201",
"192.168.200.202"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "BeiJing",
"ST": "BeiJing"
}
]
}
EOF
注意:上面組態檔中hosts欄位中的IP為所有etcd節點的集群內部通信IP,為了方便后期擴容可以多寫幾個預留IP(我沒有預留),
#6、生成證書
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=www server-csr.json | cfssljson -bare server
到目前為止,已經基于ETCD的根證書,生成了兩個域名證書如下,用于ETCD集群使用HTTPS進行通信 :

2.3 下載ETCD的二進制檔案
瀏覽器輸入地址直接下載,下載之后把壓縮包拖動到root目錄下,
https://github.com/etcd-io/etcd/releases/download/v3.4.9/etcd-v3.4.9-linux-amd64.tar.gz
2.4 部署ETCD集群
以下操作只在節點1(Master)上進行一遍,至于節點2、3,直接從節點1中把結果拷貝過去即可,
- step1:創建作業目錄并解壓二進制包
mkdir /opt/etcd/{bin,cfg,ssl} -p
tar zxvf etcd-v3.4.9-linux-amd64.tar.gz
mv etcd-v3.4.9-linux-amd64/{etcd,etcdctl} /opt/etcd/bin/
- step2:創建ETCD組態檔
cat > /opt/etcd/cfg/etcd.conf << EOF
#[Member]
ETCD_NAME="etcd-1"
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="https://192.168.200.200:2380"
ETCD_LISTEN_CLIENT_URLS="https://192.168.200.200:2379"
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.200.200:2380"
ETCD_ADVERTISE_CLIENT_URLS="https://192.168.200.200:2379"
ETCD_INITIAL_CLUSTER="etcd-1=https://192.168.200.200:2380,etcd-2=https://192.168.200.201:2380,etcd-3=https://192.168.200.202:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"
EOF
組態檔中各個引數含義如下:
#ETCD_NAME:節點名稱,集群中唯一
#ETCD_DATA_DIR:資料目錄
#ETCD_LISTEN_PEER_URLS:集群通信監聽地址
#ETCD_LISTEN_CLIENT_URLS:客戶端訪問監聽地址
#ETCD_INITIAL_ADVERTISE_PEER_URLS:集群通告地址
#ETCD_ADVERTISE_CLIENT_URLS:客戶端通告地址
#ETCD_INITIAL_CLUSTER:集群節點地址
#ETCD_INITIAL_CLUSTER_TOKEN:集群Token
#ETCD_INITIAL_CLUSTER_STATE:加入集群的當前狀態,new是新集群,existing表示加入已有集群
- step3:systemd管理etcd
cat > /usr/lib/systemd/system/etcd.service << EOF
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
[Service]
Type=notify
EnvironmentFile=/opt/etcd/cfg/etcd.conf
ExecStart=/opt/etcd/bin/etcd \
--cert-file=/opt/etcd/ssl/server.pem \
--key-file=/opt/etcd/ssl/server-key.pem \
--peer-cert-file=/opt/etcd/ssl/server.pem \
--peer-key-file=/opt/etcd/ssl/server-key.pem \
--trusted-ca-file=/opt/etcd/ssl/ca.pem \
--peer-trusted-ca-file=/opt/etcd/ssl/ca.pem \
--logger=zap
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
- step4:拷貝證書到組態檔路徑下
cp ~/TLS/etcd/ca*pem ~/TLS/etcd/server*pem /opt/etcd/ssl/
- step5:啟動,并設定開機啟動
systemctl daemon-reload
systemctl enable etcd
systemctl start etcd
注意:systemctl start etcd 指令執行之后會“卡住”因為其他的ETCD節點還沒部署呢,輸入以下的指令可以查看日志:
#把和etcd有關的日志保存到a檔案中,再從a中檢索和ip相關的內容,下圖截取了其中的一部分
#注意:本步驟不是必須要執行的
journalctl -u etcd > a
cat a grep|192.168.200

- step6:將上述節點1所有生成的檔案拷貝到節點2和節點3
#分別拷貝etcd的作業目錄、管理服務的組態檔到另外兩臺主機
scp -r /opt/etcd/ root@192.168.200.201:/opt/
scp /usr/lib/systemd/system/etcd.service root@192.168.200.201:/usr/lib/systemd/system/
scp -r /opt/etcd/ root@192.168.200.202:/opt/
scp /usr/lib/systemd/system/etcd.service root@192.168.200.202:/usr/lib/systemd/system/
注意:需要修改ETCD組態檔引數(共5處修改點),分別修改另外2個ETCD的引數
vi /opt/etcd/cfg/etcd.conf
#[Member]
ETCD_NAME="etcd-1" # 修改1,節點2改為etcd-2,節點3改為etcd-3
ETCD_LISTEN_PEER_URLS="https://192.168.200.201:2380" # 修改2 當前服務器IP
ETCD_LISTEN_CLIENT_URLS="https://192.168.200.201:2379" # 修改3 當前服務器IP
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.200.201:2380" # 修改4 當前服務器IP
ETCD_ADVERTISE_CLIENT_URLS="https://192.168.200.201:2379" # 修改5 當前服務器IP
啟動并設定開機啟動(同上):
systemctl daemon-reload
systemctl enable etcd
systemctl start etcd
- step7:查看集群狀態
在任意一個ETCD節點上輸入如下指令,可以查看集群狀態情況true表示健康(保證IP正確)
ETCDCTL_API=3 /opt/etcd/bin/etcdctl --cacert=/opt/etcd/ssl/ca.pem --cert=/opt/etcd/ssl/server.pem --key=/opt/etcd/ssl/server-key.pem --endpoints="https://192.168.200.200:2379,https://192.168.200.201:2379,https://192.168.200.202:2379" endpoint health --write-out=table

3 安裝Docker
其實,我這三臺虛擬機上本來就安裝好了Docker,如果沒有安裝Docker,可以參考該教程,當然,如果虛擬機本來就安裝了Docker,我也會把修改點指出來,
如果虛擬機上本來就沒安裝Docker,安裝步驟分為如下5步:
- step1:下載Docker的安裝包(二級制安裝,yum也可以)瀏覽器輸入如下指令就能下載:
https://download.docker.com/linux/static/stable/x86_64/docker-19.03.9.tgz
- step2:解壓,移動
tar zxvf docker-19.03.9.tgz
mv docker/* /usr/bin
- step3:設定systemd管理docker的組態檔(指定了docker守護行程啟動的命令)
cat > /usr/lib/systemd/system/docker.service << EOF
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
[Service]
Type=notify
ExecStart=/usr/bin/dockerd
ExecReload=/bin/kill -s HUP $MAINPID
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TimeoutStartSec=0
Delegate=yes
KillMode=process
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
[Install]
WantedBy=multi-user.target
EOF
- step4:設定鏡像加速
mkdir /etc/docker
cat > /etc/docker/daemon.json << EOF
{
"registry-mirrors": ["https://b9pmyelo.mirror.aliyuncs.com"]
}
EOF
- step5:啟動并設定開機啟動
systemctl daemon-reload
systemctl start docker
systemctl enable docker
如果虛擬機上本來就安裝了Docker,只需要把修改2個組態檔即可:
- step1:修改systemd管理docker的組態檔
執行上面的step3,
- step2:設定鏡像加速
執行上面的step4(去掉第一行創建檔案夾的操作),
- step3:啟動并設定開機啟動
執行上面的step5,最后,命令列輸入:docker info 查看docker是否成功啟動,上面所有的操作在3臺機器上分別執行,
4 部署 Master-Node
到目前為止,前期準備作業已經完成了(環境準備、部署ETCD集群、安裝Docker),接下來基于K8S中的各種組件的二進制檔案,進行組件的配置與安裝,不過,在進行配置安裝操作之前先了解一下K8S的證書機制:
- K8S所有組件均采用HTTPS通信,基于兩套根證書(apiserver、etcd)
- 證書分為管理節點和作業節點:
- 管理節點:controller-manager和scheduler連接apiserver時所需要的客戶端證書
- 作業節點:kubelet、kube-proxy連接apiserver時所需要的客戶端證書,一般采用BootStrap TLS機制,所以kubelet的證書初次啟動會向apiserver申請頒發證書,由controller-manager組件自動頒發,如下圖:

4.1 生成kube-apiserver證書
- step1:切換到目錄:
cd TLS/k8s
- step2:自簽證書頒發機構(CA)
cat > ca-config.json << EOF
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"kubernetes": {
"expiry": "87600h",
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
]
}
}
}
}
EOF
cat > ca-csr.json << EOF
{
"CN": "kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "Beijing",
"ST": "Beijing",
"O": "k8s",
"OU": "System"
}
]
}
EOF
- step3:生成證書
cfssl gencert -initca ca-csr.json | cfssljson -bare ca -

- step4:使用自簽CA簽發kube-apiserver HTTPS證書
注:上述檔案hosts欄位中IP為所有Master節點ip、負載均衡器LB的ip、負載均衡器的VIP,一個都不能少!為了方便后期擴容可以多寫幾個預留的IP(203是第二個Mstser、88是VIP),
cat > server-csr.json << EOF
{
"CN": "kubernetes",
"hosts": [
"10.0.0.1",
"127.0.0.1",
"192.168.200.200",
"192.168.200.201",
"192.168.200.202",
"192.168.200.203",
"192.168.200.88",
"kubernetes",
"kubernetes.default",
"kubernetes.default.svc",
"kubernetes.default.svc.cluster",
"kubernetes.default.svc.cluster.local"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "BeiJing",
"ST": "BeiJing",
"O": "k8s",
"OU": "System"
}
]
}
EOF
- step5:生成證書
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes server-csr.json | cfssljson -bare server

4.2 下載并解壓二進制檔案
下載
https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.18.md#v1183
下載如下這個二進制壓縮包即可,

解壓
mkdir -p /opt/kubernetes/{bin,cfg,ssl,logs}
tar zxvf kubernetes-server-linux-amd64.tar.gz
cd kubernetes/server/bin
cp kube-apiserver kube-scheduler kube-controller-manager /opt/kubernetes/bin
cp kubectl /usr/bin/
4.3 部署 kube-apiserver
- step1:創建組態檔
etcd-servers:分別填寫3臺機器的ip,bind-address、advertise-address填寫Master節點ip
cat > /opt/kubernetes/cfg/kube-apiserver.conf << EOF
KUBE_APISERVER_OPTS="--logtostderr=false \\
--v=2 \\
--log-dir=/opt/kubernetes/logs \\
--etcd-servers=https://192.168.200.200:2379,https://192.168.200.201:2379,https://192.168.200.202:2379 \\
--bind-address=192.168.200.200 \\
--secure-port=6443 \\
--advertise-address=192.168.200.200 \\
--allow-privileged=true \\
--service-cluster-ip-range=10.0.0.0/24 \\
--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota,NodeRestriction \\
--authorization-mode=RBAC,Node \\
--enable-bootstrap-token-auth=true \\
--token-auth-file=/opt/kubernetes/cfg/token.csv \\
--service-node-port-range=30000-32767 \\
--kubelet-client-certificate=/opt/kubernetes/ssl/server.pem \\
--kubelet-client-key=/opt/kubernetes/ssl/server-key.pem \\
--tls-cert-file=/opt/kubernetes/ssl/server.pem \\
--tls-private-key-file=/opt/kubernetes/ssl/server-key.pem \\
--client-ca-file=/opt/kubernetes/ssl/ca.pem \\
--service-account-key-file=/opt/kubernetes/ssl/ca-key.pem \\
--etcd-cafile=/opt/etcd/ssl/ca.pem \\
--etcd-certfile=/opt/etcd/ssl/server.pem \\
--etcd-keyfile=/opt/etcd/ssl/server-key.pem \\
--audit-log-maxage=30 \\
--audit-log-maxbackup=3 \\
--audit-log-maxsize=100 \\
--audit-log-path=/opt/kubernetes/logs/k8s-audit.log"
EOF
組態檔中引數解釋如下:
logtostderr:啟用日志
v:日志等級
log-dir:日志目錄
etcd-servers:etcd集群地址
bind-address:監聽地址
secure-port:https安全埠
advertise-address:集群通告地址
allow-privileged:啟用授權
service-cluster-ip-range:Service虛擬IP地址段
enable-admission-plugins:準入控制模塊
authorization-mode:認證授權,啟用RBAC授權和節點自管理
enable-bootstrap-token-auth:啟用TLS bootstrap機制
token-auth-file:bootstrap token檔案
service-node-port-range:Service nodeport型別默認分配埠范圍
kubelet-client-xxx:apiserver訪問kubelet客戶端證書
tls-xxx-file:apiserver https證書
etcd-xxxfile:連接Etcd集群證書
audit-log-xxx:審計日志
- step2:拷貝證書
把剛才生成的證書拷貝到組態檔中的路徑:
cp ~/TLS/k8s/ca*pem ~/TLS/k8s/server*pem /opt/kubernetes/ssl/
- step3:啟用 TLS Bootstrapping 機制
生成token:
head -c 16 /dev/urandom | od -An -t x | tr -d ' '
創建上述組態檔中token檔案(把生成的token替換,格式:token,用戶名,UID,用戶組)
cat > /opt/kubernetes/cfg/token.csv << EOF
4ec49cd2f31388108e1c8958a805c8d4,kubelet-bootstrap,10001,"system:node-bootstrapper"
EOF
- step4:systemd管理apiserver
cat > /usr/lib/systemd/system/kube-apiserver.service << EOF
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/kubernetes/kubernetes
[Service]
EnvironmentFile=/opt/kubernetes/cfg/kube-apiserver.conf
ExecStart=/opt/kubernetes/bin/kube-apiserver \$KUBE_APISERVER_OPTS
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
- step5:啟動并設定開機啟動
systemctl daemon-reload
systemctl start kube-apiserver
systemctl enable kube-apiserver
- step6:授權kubelet-bootstrap用戶允許請求證書(給token中的用戶最小權限)
kubectl create clusterrolebinding kubelet-bootstrap \
--clusterrole=system:node-bootstrapper \
--user=kubelet-bootstrap
4.4 部署 kube-controller-manager
- step1:創建組態檔
cat > /opt/kubernetes/cfg/kube-controller-manager.conf << EOF
KUBE_CONTROLLER_MANAGER_OPTS="--logtostderr=false \\
--v=2 \\
--log-dir=/opt/kubernetes/logs \\
--leader-elect=true \\
--master=127.0.0.1:8080 \\
--bind-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=/opt/kubernetes/ssl/ca.pem \\
--cluster-signing-key-file=/opt/kubernetes/ssl/ca-key.pem \\
--root-ca-file=/opt/kubernetes/ssl/ca.pem \\
--service-account-private-key-file=/opt/kubernetes/ssl/ca-key.pem \\
--experimental-cluster-signing-duration=87600h0m0s"
EOF
組態檔中引數介紹如下:
#引數介紹
master:通過本地非安全本地埠8080連接apiserver,
leader-elect:當該組件啟動多個時,自動選舉(HA)
cluster-signing-cert-file/–cluster-signing-key-file:自動為kubelet頒發證書的CA,與apiserver保持一致
- step2: 生成kubeconfig檔案(這一步似乎不用執行)
除了為該組件創建 .conf 主組態檔之外,還需要生成一個該組件專屬的 .kubeconfig 組態檔用于連接apiserver
先生成kube-controller-manager證書
#切換作業目錄
cd ~/TLS/k8s
#創建證書請求檔案
cat > kube-controller-manager-csr.json << EOF
{
"CN": "system:kube-controller-manager",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "BeiJing",
"ST": "BeiJing",
"O": "system:masters",
"OU": "System"
}
]
}
EOF
#生成controller-manager 證書
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-controller-manager-csr.json | cfssljson -bare kube-controller-manager
再生成kubeconfig組態檔
KUBE_CONFIG="/opt/kubernetes/cfg/kube-controller-manager.kubeconfig"
KUBE_APISERVER="https://192.168.200.200:6443"
kubectl config set-cluster kubernetes \
--certificate-authority=/opt/kubernetes/ssl/ca.pem \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=${KUBE_CONFIG}
kubectl config set-credentials kube-controller-manager \
--client-certificate=./kube-controller-manager.pem \
--client-key=./kube-controller-manager-key.pem \
--embed-certs=true \
--kubeconfig=${KUBE_CONFIG}
kubectl config set-context default \
--cluster=kubernetes \
--user=kube-controller-manager \
--kubeconfig=${KUBE_CONFIG}
kubectl config use-context default --kubeconfig=${KUBE_CONFIG}
kubeconfig組態檔生成之后,可以用以下指令查看:
cat /opt/kubernetes/cfg/kube-controller-manager.kubeconfig
- step3:systemd管理controller-manager
cat > /usr/lib/systemd/system/kube-controller-manager.service << EOF
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/kubernetes/kubernetes
[Service]
EnvironmentFile=/opt/kubernetes/cfg/kube-controller-manager.conf
ExecStart=/opt/kubernetes/bin/kube-controller-manager \$KUBE_CONTROLLER_MANAGER_OPTS
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
- step4:啟動并設定開機啟動
systemctl daemon-reload
systemctl start kube-controller-manager
systemctl enable kube-controller-manager
4.5 部署 kube-scheduler
- step1:創建組態檔
cat > /opt/kubernetes/cfg/kube-scheduler.conf << EOF
KUBE_SCHEDULER_OPTS="--logtostderr=false \
--v=2 \
--log-dir=/opt/kubernetes/logs \
--leader-elect \
--master=127.0.0.1:8080 \
--bind-address=127.0.0.1"
EOF
組態檔中引數介紹如下:
#引數介紹
master:通過本地非安全本地埠8080連接apiserver,
leader-elect:當該組件啟動多個時,自動選舉(HA)
- step2:生成 kubeconfig 檔案(這一步似乎不用執行)
除了為該組件創建 .conf 主組態檔之外,還需要生成一個該組件專屬的 .kubeconfig 組態檔用于連接apiserver
先生成 kube-scheduler證書
#切換作業目錄
cd ~/TLS/k8s
#創建證書請求檔案
cat > kube-scheduler-csr.json << EOF
{
"CN": "system:kube-scheduler",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "BeiJing",
"ST": "BeiJing",
"O": "system:masters",
"OU": "System"
}
]
}
EOF
#生成 kube-scheduler 證書
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-scheduler-csr.json | cfssljson -bare kube-scheduler
再生成kubeconfig組態檔
KUBE_CONFIG="/opt/kubernetes/cfg/kube-scheduler.kubeconfig"
KUBE_APISERVER="https://192.168.200.200:6443"
kubectl config set-cluster kubernetes \
--certificate-authority=/opt/kubernetes/ssl/ca.pem \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=${KUBE_CONFIG}
kubectl config set-credentials kube-scheduler \
--client-certificate=./kube-scheduler.pem \
--client-key=./kube-scheduler-key.pem \
--embed-certs=true \
--kubeconfig=${KUBE_CONFIG}
kubectl config set-context default \
--cluster=kubernetes \
--user=kube-scheduler \
--kubeconfig=${KUBE_CONFIG}
kubectl config use-context default --kubeconfig=${KUBE_CONFIG}
kubeconfig組態檔生成之后,可以用以下指令查看:
cat /opt/kubernetes/cfg/kube-scheduler.kubeconfig
- step3:systemd管理scheduler
cat > /usr/lib/systemd/system/kube-scheduler.service << EOF
[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/kubernetes/kubernetes
[Service]
EnvironmentFile=/opt/kubernetes/cfg/kube-scheduler.conf
ExecStart=/opt/kubernetes/bin/kube-scheduler \$KUBE_SCHEDULER_OPTS
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
- step4:啟動并設定開機啟動
systemctl daemon-reload
systemctl start kube-scheduler
systemctl enable kube-scheduler
- step5:查看集群狀態
查看集群狀態用到kubectl工具,kubectl連接集群前進行配置(生成證書+生成連接用組態檔,但是,這一步似乎不用執行)
#1、切換作業目錄
cd ~/TLS/k8s
#2、生成kubectl連接K8S集群的證書
cat > admin-csr.json << EOF
{
"CN": "admin",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "BeiJing",
"ST": "BeiJing",
"O": "system:masters",
"OU": "System"
}
]
}
EOF
#3、生成證書
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes admin-csr.json | cfssljson -bare admin
#4、生成kubeconfig組態檔(放到kubectl默認的組態檔夾/root/.kube/config下)
mkdir /root/.kube
KUBE_CONFIG="/root/.kube/config"
KUBE_APISERVER="https://192.168.200.200:6443"
kubectl config set-cluster kubernetes \
--certificate-authority=/opt/kubernetes/ssl/ca.pem \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=${KUBE_CONFIG}
kubectl config set-credentials cluster-admin \
--client-certificate=./admin.pem \
--client-key=./admin-key.pem \
--embed-certs=true \
--kubeconfig=${KUBE_CONFIG}
kubectl config set-context default \
--cluster=kubernetes \
--user=cluster-admin \
--kubeconfig=${KUBE_CONFIG}
kubectl config use-context default --kubeconfig=${KUBE_CONFIG}
到目前為止,Matser節點上的所有組件都已經啟動成功(scheduler、controller-manager、etcd-0),通過kubectl工具查看當前集群組件狀態:
kubectl get cs

5 部署 Work-Node
- 注意:Node節點所需要配置和安裝的所有操作,都會在Matser節點機器上執行一遍,即Master既作為Master節點,同時又作為作業節點(只不過不使用作業節點的功能而已),
- 注意:在Matser節點上還是要部署Node組件的,一方面,如果要在Master上運行Pod容器就需要部署Node組件,另一方面,如果只是想讓Matser節點單純的作為容器管理的節點,那么可以給Matser打上污點即可,這樣Pod就不會部署到Matser節點上了,此外,如果不在Matser上部署Node組件,“kubectl get node” 指令中就沒法找到Master組件了,
- 配置完成后,會把在Master節點上生成的所有檔案拷貝到各個Node節點中,并修改必要的配置引數資訊,
5.1 創建作業目錄并拷貝二進制檔案
在所有worker node創建作業目錄,并從master節點上把二進制檔案拷貝到Node節點作業目錄
mkdir -p /opt/kubernetes/{bin,cfg,ssl,logs}
cd kubernetes/server/bin
cp kubelet kube-proxy /opt/kubernetes/bin # 本地拷貝
5.2 部署kubelet
- step1:創建主組態檔
cat > /opt/kubernetes/cfg/kubelet.conf << EOF
KUBELET_OPTS="--logtostderr=false \\
--v=2 \\
--log-dir=/opt/kubernetes/logs \\
--hostname-override=k8s-master1 \\
--network-plugin=cni \\
--kubeconfig=/opt/kubernetes/cfg/kubelet.kubeconfig \\
--bootstrap-kubeconfig=/opt/kubernetes/cfg/bootstrap.kubeconfig \\
--config=/opt/kubernetes/cfg/kubelet-config.yml \\
--cert-dir=/opt/kubernetes/ssl \\
--pod-infra-container-image=lizhenliang/pause-amd64:3.0"
EOF
#組態檔引數解釋
hostname-override:顯示名稱,集群中唯一
network-plugin:啟用CNI
kubeconfig:空路徑,會自動生成,后面用于連接apiserver
bootstrap-kubeconfig:首次啟動向apiserver申請證書
config:配置引數檔案
cert-dir:kubelet證書生成目錄
pod-infra-container-image:管理Pod網路容器的鏡像
- step2:配置引數檔案
cat > /opt/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: /opt/kubernetes/ssl/ca.pem
authorization:
mode: Webhook
webhook:
cacheAuthorizedTTL: 5m0s
cacheUnauthorizedTTL: 30s
evictionHard:
imagefs.available: 15%
memory.available: 100Mi
nodefs.available: 10%
nodefs.inodesFree: 5%
maxOpenFiles: 1000000
maxPods: 110
EOF
- step3:生成kubelet初次加入集群引導kubeconfig檔案
KUBE_CONFIG="/opt/kubernetes/cfg/bootstrap.kubeconfig"
KUBE_APISERVER="https://192.168.200.200:6443" # apiserver IP:PORT
TOKEN="4ec49cd2f31388108e1c8958a805c8d4" # 與token.csv里保持一致
# 生成 kubelet bootstrap kubeconfig 組態檔
kubectl config set-cluster kubernetes \
--certificate-authority=/opt/kubernetes/ssl/ca.pem \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=${KUBE_CONFIG}
kubectl config set-credentials "kubelet-bootstrap" \
--token=${TOKEN} \
--kubeconfig=${KUBE_CONFIG}
kubectl config set-context default \
--cluster=kubernetes \
--user="kubelet-bootstrap" \
--kubeconfig=${KUBE_CONFIG}
kubectl config use-context default --kubeconfig=${KUBE_CONFIG}
- step4:systemd管理kubelet
cat > /usr/lib/systemd/system/kubelet.service << EOF
[Unit]
Description=Kubernetes Kubelet
After=docker.service
[Service]
EnvironmentFile=/opt/kubernetes/cfg/kubelet.conf
ExecStart=/opt/kubernetes/bin/kubelet \$KUBELET_OPTS
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
- step5:啟動并設定開機啟動
systemctl daemon-reload
systemctl start kubelet
systemctl enable kubelet
5.3 批準 kubelet 證書申請并加入集群
查看kubelet證書請求,批準請求(請求name按實際填寫)
kubectl get csr
kubectl certificate approve node-csr-BWueBGbAmxsFfA8nydpgvg0wEX592ppsxXVChZZGapU

查看節點
kubectl get node
查看節點時,由于 網路插件還沒有部署,所以顯示NotReady狀態:

5.4 部署 kube-proxy
- step1:創建主組態檔
cat > /opt/kubernetes/cfg/kube-proxy.conf << EOF
KUBE_PROXY_OPTS="--logtostderr=false \\
--v=2 \\
--log-dir=/opt/kubernetes/logs \\
--config=/opt/kubernetes/cfg/kube-proxy-config.yml"
EOF
- step2:配置引數檔案
cat > /opt/kubernetes/cfg/kube-proxy-config.yml << EOF
kind: KubeProxyConfiguration
apiVersion: kubeproxy.config.k8s.io/v1alpha1
bindAddress: 0.0.0.0
metricsBindAddress: 0.0.0.0:10249
clientConnection:
kubeconfig: /opt/kubernetes/cfg/kube-proxy.kubeconfig
hostnameOverride: k8s-master1
clusterCIDR: 10.244.0.0/16
EOF
- step3:生成kube-proxy.kubeconfig檔案
# 1、切換作業目錄
cd ~/TLS/k8s
# 2、創建證書請求檔案
cat > kube-proxy-csr.json << EOF
{
"CN": "system:kube-proxy",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "BeiJing",
"ST": "BeiJing",
"O": "k8s",
"OU": "System"
}
]
}
EOF
# 3、生成證書
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy
# 4、生成kubeconfig檔案:
KUBE_CONFIG="/opt/kubernetes/cfg/kube-proxy.kubeconfig"
KUBE_APISERVER="https://192.168.200.200:6443"
kubectl config set-cluster kubernetes \
--certificate-authority=/opt/kubernetes/ssl/ca.pem \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=${KUBE_CONFIG}
kubectl config set-credentials kube-proxy \
--client-certificate=./kube-proxy.pem \
--client-key=./kube-proxy-key.pem \
--embed-certs=true \
--kubeconfig=${KUBE_CONFIG}
kubectl config set-context default \
--cluster=kubernetes \
--user=kube-proxy \
--kubeconfig=${KUBE_CONFIG}
kubectl config use-context default --kubeconfig=${KUBE_CONFIG}
- step4:systemd 管理kube-proxy
cat > /usr/lib/systemd/system/kube-proxy.service << EOF
[Unit]
Description=Kubernetes Proxy
After=network.target
[Service]
EnvironmentFile=/opt/kubernetes/cfg/kube-proxy.conf
ExecStart=/opt/kubernetes/bin/kube-proxy \$KUBE_PROXY_OPTS
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
- step5:啟動并設定開機啟動
systemctl daemon-reload
systemctl start kube-proxy
systemctl enable kube-proxy
5.5 部署網路組件
Calico是一個純三層的資料中心網路方案,是目前Kubernetes主流的網路方案
首先把Calico的組態檔 calico.yaml 拖動到:/root/ 目錄下,并cd回到root下:cd,然后執行如下兩條指令:
#安裝calico
kubectl apply -f calico.yaml
#列出“kube-system”命名空間下的所有pod
kubectl get pods -n kube-system
當Calico Pod都Running起來后,節點網路也會準備就緒,此時查看集群中的節點資訊:
kubectl get node

5.6 授權 apiserver 訪問 kubelet
應用場景:kubectl logs
cat > apiserver-to-kubelet-rbac.yaml << EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
labels:
kubernetes.io/bootstrapping: rbac-defaults
name: system:kube-apiserver-to-kubelet
rules:
- apiGroups:
- ""
resources:
- nodes/proxy
- nodes/stats
- nodes/log
- nodes/spec
- nodes/metrics
- pods/log
verbs:
- "*"
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: system:kube-apiserver
namespace: ""
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:kube-apiserver-to-kubelet
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: kubernetes
EOF
kubectl apply -f apiserver-to-kubelet-rbac.yaml
到目前為止,在Matser節點中要部署的所有組件都已經安裝配置到Matser節點中了
(1)Matser組件:apiserver、controller-manager、scheduler
(2)Node組件:kubelet、kube-proxy
當然,Node作業節點中的組件可以不部署在Matser節點中,但是本案例還是這樣做了,無傷大雅,接下來就把在Master節點中所部署的Node組件直接拷貝到各個Node節點上來,并修改必要的配置資訊,Node節點的部署就輕松很多了,
5.7 新增加 Worker-Node
- step1:拷貝已部署好的Node相關檔案到新節點
在Master節點中,將Worker Node涉及檔案拷貝到另外2個新節點192.168.200.201/202
#拷貝作業目錄(連帶Master的內容一起拷貝了,沒關系,反正也用不到)
scp -r /opt/kubernetes root@192.168.200.201:/opt/
#拷貝組態檔
scp -r /usr/lib/systemd/system/{kubelet,kube-proxy}.service root@192.168.200.201:/usr/lib/systemd/system
#拷貝證書檔案
scp /opt/kubernetes/ssl/ca.pem root@192.168.200.201:/opt/kubernetes/ssl
#對202機器同樣執行一遍
scp -r /opt/kubernetes root@192.168.200.202:/opt/
scp -r /usr/lib/systemd/system/{kubelet,kube-proxy}.service root@192.168.200.202:/usr/lib/systemd/system
scp /opt/kubernetes/ssl/ca.pem root@192.168.200.202:/opt/kubernetes/ssl
- step2:洗掉 kubelet 證書和 kubeconfig 檔案
由于這幾個檔案是證書申請審批后自動生成的,每個Node不同,因此必須洗掉
#在node1、node2兩個節點上分別執行如下命令
rm -f /opt/kubernetes/cfg/kubelet.kubeconfig
rm -f /opt/kubernetes/ssl/kubelet*
- step3:修改主機名
在兩臺機器上分別打開2個組態檔,并修改主機名
#修改kubelet組態檔
vi /opt/kubernetes/cfg/kubelet.conf
--hostname-override=k8s-node1
#修改kube-proxy組態檔
vi /opt/kubernetes/cfg/kube-proxy-config.yml
hostnameOverride: k8s-node1
#名稱換成:k8s-node2再執行一遍
- step4:啟動并設定開機啟動
systemctl daemon-reload
systemctl start kubelet kube-proxy
systemctl enable kubelet kube-proxy
- step5:在Master上批準新的Node kubelet證書申請
注意:該操作在Master節點上完成!
先查看證書請求:
kubectl get csr
在兩臺node機器上分別執行完前4步操作之后(node節點中啟動kubelet后就會有請求資訊),查看證書請求會看到2條資訊:

根據證書請求name進行授權
#授權ndoe1
kubectl certificate approve node-csr-MYWfZXy8o2n8Gb6dZ-fVKw1qVFkmgEkSFdg7m1VL56w
#授權node2
kubectl certificate approve node-csr-XAp5v8JU6qlAkDwzXPiN0DkJ9xlqsq4KbMekUFqBwKM
- step6:查看Node狀態
kubectl get node

6 部署 DashBoard 和 CoreDNS
- dashboard是k8s官方的UI工具,可以通過可視化界面的方式查看、操作k8s集群,但是功能較弱,
- CoreDNS用于集群內部Service名稱決議
6.1 部署 DashBoard
- step1:把 DashBoard 的yaml檔案拷貝到Master節點的 /root/路徑下

- step2: 安裝 DashBoard
kubectl apply -f kubernetes-dashboard.yaml
- step3:查看 DashBoard 部署情況
kubectl get pods,svc -n kubernetes-dashboard

- step4: 訪問地址 https://192.168.200.200:30001

此時需要一個token,生成token步驟如下(Master主機下操作):
#創建service account
kubectl create serviceaccount dashboard-admin -n kube-system
#將service account系結到集群角色,具備管理員權限
kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin
#獲取token
kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk '/dashboard-admin/{print $1}')
輸入token后進入DashBoard界面:

6.2 部署 CoreDNS
- step1:把 CoreDNS 的yaml檔案拷貝到Master節點的 /root/路徑下
- step2:安裝
kubectl apply -f coredns.yaml
- step3:查看部署情況
kubectl get pods -n kube-system

到目前為止,一個單Master集群就搭建完成了,接下來進行多Master集群擴容,
如果你的機器配置不夠用,到這里就已經可以進行后續的K8S學習了,
但是如果追求K8S集群的高可用的話,就再搞一臺虛擬機作為第二個Matser-Node,操作如下,
7 擴容多 Master(高可用架構)
- Kubernetes作為容器集群系統,通過健康檢查+重啟策略實作了Pod故障自我修復能力,通過調度演算法實作將Pod分布式部署,并保持預期副本數,根據Node失效狀態自動在其他Node拉起Pod,實作了應用層的高可用性,
- 針對Kubernetes集群,高可用性還應包含以下兩個層面的考慮:Etcd資料庫的高可用性和Kubernetes Master組件的高可用性, 而Etcd我們已經采用3個節點組建集群實作高可用,本節將對Master節點高可用進行說明和實施,
- Master節點扮演著總控中心的角色,通過不斷與作業節點上的Kubelet和kube-proxy進行通信來維護整個集群的健康作業狀態,如果Master節點故障,將無法使用kubectl工具或者API做任何集群管理,
- Master節點主要有三個服務kube-apiserver、kube-controller-manager和kube-scheduler,其中kube-controller-manager和kube-scheduler組件自身通過選擇機制已經實作了高可用,所以Master高可用主要針對kube-apiserver組件,而該組件是以HTTP API提供服務,因此對他高可用與Web服務器類似,增加負載均衡器對其負載均衡即可,并且可水平擴容,
7.1 部署 Master2 Node
現在需要再增加一臺新服務器(虛擬機),作為Master2 Node,IP是192.168.200.203,
Master2 與已部署的Master1所有操作一致,只需將Master1所有K8s檔案拷貝過來,再修改下服務器IP和主機名啟動即可,
- step1:安裝Docker
##在Matser1節點上進行如下拷貝操作,拷貝到Master2節點
scp /usr/bin/docker* root@192.168.200.203:/usr/bin
scp /usr/bin/runc root@192.168.200.203:/usr/bin
scp /usr/bin/containerd* root@192.168.200.203:/usr/bin
scp /usr/lib/systemd/system/docker.service root@192.168.200.203:/usr/lib/systemd/system
scp -r /etc/docker root@192.168.200.203:/etc
# 在Master2中啟動Docker
systemctl daemon-reload
systemctl start docker
systemctl enable docker
- step2:在Matser2中創建ETCD證書目錄
mkdir -p /opt/etcd/ssl
- step3:拷貝Master1上所有K8s檔案和etcd證書到Master2
scp -r /opt/kubernetes root@192.168.200.203:/opt
scp -r /opt/etcd/ssl root@192.168.200.203:/opt/etcd
scp /usr/lib/systemd/system/kube* root@192.168.200.203:/usr/lib/systemd/system
scp /usr/bin/kubectl root@192.168.200.203:/usr/bin
scp -r ~/.kube root@192.168.200.203:~
- step4:洗掉kubelet證書和kubeconfig檔案
rm -f /opt/kubernetes/cfg/kubelet.kubeconfig
rm -f /opt/kubernetes/ssl/kubelet*
- step5:修改組態檔ip與主機名
修改apiserver、kubelet和kube-proxy組態檔為本地IP及主機名:
vi /opt/kubernetes/cfg/kube-apiserver.conf
...
--bind-address=192.168.200.203 \
--advertise-address=192.168.200.203 \
...
vi /opt/kubernetes/cfg/kube-controller-manager.kubeconfig
server: https://192.168.200.203:6443
vi /opt/kubernetes/cfg/kube-scheduler.kubeconfig
server: https://192.168.200.203:6443
vi /opt/kubernetes/cfg/kubelet.conf
--hostname-override=k8s-master2
vi /opt/kubernetes/cfg/kube-proxy-config.yml
hostnameOverride: k8s-master2
vi ~/.kube/config
...
server: https://192.168.200.203:6443
- step6:設定開機啟動
systemctl daemon-reload
systemctl start kube-apiserver kube-controller-manager kube-scheduler kubelet kube-proxy
systemctl enable kube-apiserver kube-controller-manager kube-scheduler kubelet kube-proxy
- step7:查看集群狀態
kubectl get cs

- step8:批準kubelet證書申請
查看證書請求:
kubectl get csr
授權請求:
kubectl certificate approve node-csr-pt7afV7SOLIx5F-CMdAhzoes2hbVL7E-NmipvtcEEy8
查看node(如果狀態沒變成 Ready 就多等幾分鐘):
kubectl get node

7.2 部署 Nginx+Keepalived 高可用負載均衡器
kube-apiserver高可用架構圖如下:

- Nginx是一個主流Web服務和反向代理服務器,這里用四層實作對apiserver的負載均衡,
- Keepalived是一個主流高可用軟體,基于VIP系結實作服務器雙機熱備,基于上圖,Keepalived主要根據Nginx運行狀態判斷是否需要故障轉移(漂移VIP),例如當Nginx主節點掛掉,VIP會自動系結在Nginx備節點,從而保證VIP一直可用,實作Nginx高可用,
- 為了節省機器,這里與K8s Master節點機器復用,也可以獨立于k8s集群之外部署,只要nginx與apiserver能通信就行,
- 如果你是在公有云上,一般都不支持keepalived,那么你可以直接用它們的負載均衡器產品,直接負載均衡多臺Master kube-apiserver,架構同上,

在兩臺Master節點上分別進行如下操作:
- step1: 安裝軟體包(主備一樣)
yum install epel-release -y
yum install nginx keepalived -y
- step2:修改Nginx組態檔(主備一樣)
cat > /etc/nginx/nginx.conf << "EOF"
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
# 四層負載均衡,為兩臺Master apiserver組件提供負載均衡
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.200.200:6443; # Master1 APISERVER IP:PORT
server 192.168.200.203:6443; # Master2 APISERVER IP:PORT
}
server {
listen 16443; # 由于nginx與master節點復用,這個監聽埠不能是6443,否則會沖突
proxy_pass k8s-apiserver;
}
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
server {
listen 80 default_server;
server_name _;
location / {
}
}
}
EOF

- step3: 修改keepalived組態檔(Nginx Master)
cat > /etc/keepalived/keepalived.conf << EOF
global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
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_instance VI_1 {
state MASTER
interface ens33 # 修改為實際網卡名
virtual_router_id 51 # VRRP 路由 ID實體,每個實體是唯一的
priority 100 # 優先級,備服務器設定 90
advert_int 1 # 指定VRRP 心跳包通告間隔時間,默認1秒
authentication {
auth_type PASS
auth_pass 1111
}
# 虛擬IP
virtual_ipaddress {
192.168.200.88/24
}
track_script {
check_nginx
}
}
EOF
此外,需要準備上述組態檔中檢查nginx運行狀態的腳本:
cat > /etc/keepalived/check_nginx.sh << "EOF"
#!/bin/bash
count=$(ss -antp |grep 16443 |egrep -cv "grep|$$")
if [ "$count" -eq 0 ];then
exit 1
else
exit 0
fi
EOF
chmod +x /etc/keepalived/check_nginx.sh
- step4: 修改keepalived組態檔(Nginx Backup)
cat > /etc/keepalived/keepalived.conf << EOF
global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
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_instance VI_1 {
state BACKUP
interface ens33
virtual_router_id 51 # VRRP 路由 ID實體,每個實體是唯一的
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.200.88/24
}
track_script {
check_nginx
}
}
EOF
此外,需要準備上述組態檔中檢查nginx運行狀態的腳本:
cat > /etc/keepalived/check_nginx.sh << "EOF"
#!/bin/bash
count=$(ss -antp |grep 16443 |egrep -cv "grep|$$")
if [ "$count" -eq 0 ];then
exit 1
else
exit 0
fi
EOF
chmod +x /etc/keepalived/check_nginx.sh
- step5:修改,讓所有Worker Node連接LB VIP(Matser也是Worker-Node)
#左邊的ip是Nginx-Master的ip(200),右邊的ip是VIP(88)
sed -i 's#192.168.200.200:6443#192.168.200.88:16443#' /opt/kubernetes/cfg/*
systemctl restart kubelet kube-proxy
之前我們是讓Matser1節點和其他各個Node節點進行直連,而現在,斷開了這個連接(而是讓node連接VIP),由于目前Nginx還沒有啟動,所以執行kubectl get node 指令時會出現如下無法連接的情況:

- step6:啟動并設定開機啟動
systemctl daemon-reload
systemctl start nginx keepalived
systemctl enable nginx keepalived
注意:如果在任何環節出現作業系統軟死鎖的問題,如下:
這個bug沒有讓系統徹底死機,但是會讓Nginx被鎖死在了某個狀態,而造成死鎖的原因我估計是因為虛擬機的CPU太忙了或者CPU電壓不穩定, 請輸入如下幾行指令解決:
#查看引數 watchdog_thresh(結果應該是10)
tail -1 /proc/sys/kernel/watchdog_thresh
#把這個引數改為30
echo 30 > /proc/sys/kernel/watchdog_thresh
#臨時生效
sysctl -w kernel.watchdog_thresh=30
- step7:查看keepalived作業狀態(Master1)
此時,在ens33網卡系結了192.168.200.88 虛擬IP,說明Nginx-Master作業正常,
現在訪問192.168.200.88這個虛擬ip實際上就是在訪問K8S-Matser集群中某個實體的apiserver,
(vip->Nginx-Master->K8S-Matser-apiserver,vip是Nginx的虛擬ip,與K8S-Matser節點無關)

- step8:測驗
(1) Nginx代理測驗
在K8s集群中選擇任意節點,使用curl查看K8s版本測驗,此時使用VIP進行訪問:
curl -k https://192.168.200.88:16443/version
如果能夠獲得k8s資訊,說明Nginx搭建正常,且curl->vip(nginx)->apiserver(k8s-matser) 的鏈路被打通了,

當然,通過Nginx日志也可以看到轉發apiserver Ip:
tail /var/log/nginx/k8s-access.log -f
(2)K8S創建容器后訪問測驗
在Matser節點上創建一個容器,然后訪問該容器,測驗是否能成功訪問:
#創建容器,訪問該容器的ip就是node1或者node2的ip,因為node1和node2完全一樣,用來部署容器應用,實作高可用
kubectl create deployment web --image=nginx
#暴露埠80
kubectl expose deployment web --port=80 --target-port=80 --type=NodePort
#查看service(獲取埠號)
kubectl get svc

到這里就算結束了,實際上還有個測驗沒做,就是:Nginx+Keepalived的高可用測驗,
為什么沒做這個測驗呢?是因為我的電腦在一次系統內核軟死鎖之后,Nginx的啟動總是失敗,網路上的方法不能很好的解決我的問題,然而當我使用了step6中的方法之后,在matser1中部署的ngxin可以正常啟動了,然而master2中的nginx仍不能正常啟動,很奇怪,哭唧唧,后續針對這個問題再研究一下吧,這篇文章寫得蠻長,mark一下,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/290838.html
標籤:其他
上一篇:計算機網路OSI與TCP/IP參考模型(思維導圖帶你一分鐘快速了解)
下一篇:計算機網路參考模型
