主頁 > 軟體設計 > 2 二進制方式搭建K8S集群

2 二進制方式搭建K8S集群

2021-07-30 07:14:19 軟體設計

本文介紹單/多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-master1192.168.200.200kube-apiserver、kube-controller-manager、kube-scheduler、etcd
k8s-node1192.168.200.201kubelet、kube-proxy、docker、etcd
k8s-node2192.168.200.202kubelet、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-1192.168.200.200
etcd-2192.168.200.201
etcd-3192.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參考模型(思維導圖帶你一分鐘快速了解)

下一篇:計算機網路參考模型

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more