第19章: kubeadm方式部署K8S1.20高可用集群



1  架構說明

1.1 生產環境可部署Kubernetes集群的兩種方式

1 kubeadm部署

(1) Kubeadm是一個K8s部署工具,提供kubeadm initkubeadm join,用於快速部署Kubernetes集群。這里采用kubeadm搭建集群。

(2) kubeadm工具功能
kubeadm init # 初始化一個Master節點
kubeadm join # 將工作節點加入集群
kubeadm upgrade # 升級K8s版本
kubeadm token # 管理 kubeadm join 使用的令牌
kubeadm reset # 清空 kubeadm init 或者 kubeadm join 對主機所做的任何更改
kubeadm version # 打印 kubeadm 版本
kubeadm alpha # 
預覽可用的新功能

 

2 二進制包部署

github下載發行版的二進制包,手動部署每個組件,組成Kubernetes集群。

1.2 准備環境

1 服務器要求

建議最小硬件配置: 2CPU2G內存、30G硬盤
服務器最好可以訪問外網,會有從網上拉取鏡像需求,如果服務器不能上網,需要提前下載對應鏡像並導入節點

 

2 服務器規划

操作系統: CentOS7.5

主機名

IP

軟件

VIP

k8s-master1

(24G)

主網卡: 172.16.1.81
副網卡:
10.0.0.81

docker-ce-19.03.9kubernetes-1.20etcd(etcd-1)nginx + keepalived(master)

 

 

172.16.1.80

 

 

k8s-master2

(24G)

主網卡: 172.16.1.82
副網卡:
10.0.0.82

docker-ce-19.03.9kubernetes-1.20etcd(etcd-2)nginx + keepalived(backup)

k8s-node1

(48G)

主網卡: 172.16.1.83
副網卡:
10.0.0.83

docker-ce-19.03.9kubernetes-1.20etcd(etcd-3)

 

 

(1) 為了節省機器,etcd集群與K8s節點機器復用,也可以獨立於k8s集群之外部署,只

apiserver能連接到就行。

(2) 為了節省機器,nginx+keepalivedK8s master節點機器復用,也可以獨立於k8s

群之外部署,只要nginxapiserver能通信就行。

 

 

 

3 架構圖

wps1 

1.3 操作系統初始化配置

172.16.1.81-83節點上操作

(1) 關閉防火牆
# systemctl stop firewalld
# systemctl disable firewalld

(2) 關閉selinux
# sed -i 's/enforcing/disabled/' /etc/selinux/config  # 永久
# setenforce 0  # 臨時

(3) 關閉swap
# swapoff -a  # 臨時
# sed -ri 's/.*swap.*/#&/' /etc/fstab    # 永久

(4) master添加hosts
cat >> /etc/hosts << EOF
172.16.1.81 k8s-master1
172.16.1.82 k8s-master2
172.16.1.83 k8s-node1
EOF

(5) 將橋接的IPv4流量傳遞到iptables的鏈
# cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
# sysctl --system  # 生效,手動加載所有的配置文件

(6) 時間同步
# yum install ntpdate -y
# ntpdate ntp.aliyun.com
# crontab -e
# crontab -l
*/5 * * * * /usr/sbin/ntpdate ntp.aliyun.com &>/dev/null

(7) 部署docker
這里使用Docker作為容器引擎,也可以換成別的,例如containerd
1) 安裝依賴包
# yum install -y yum-utils device-mapper-persistent-data lvm2
2) 添加Docker軟件包源
# yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo
3) 更新為阿里雲的源
# wget -O /etc/yum.repos.d/docker-ce.repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
4) 清理源緩存
# yum clean all
5) 安裝指定版本的Docker CE
# yum list docker-ce --showduplicates | sort -r
# yum list docker-ce-cli --showduplicates | sort -r
# yum install docker-ce-19.03.9-3.el7 docker-ce-cli-19.03.9-3.el7 -y
6) 啟動Docker服務並設置開機啟動
# systemctl start docker
# systemctl enable docker
# docker version  # 可以看到docker客戶端和服務端都是同一個版本
# docker info
7) 添加阿里雲的鏡像倉庫
# mkdir -p /etc/docker
# tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://b1cx9cn7.mirror.aliyuncs.com"]
}
EOF
8) 重啟docker
# systemctl daemon-reload
# systemctl restart docker

(8) 增加 iptables conntrack 表大小,防止iptables
性能不佳
參考網站: https://docs.projectcalico.org/maintenance/troubleshoot/troubleshooting#configure-networkmanager
# sysctl -w net.netfilter.nf_conntrack_max=1000000
# echo "net.netfilter.nf_conntrack_max=1000000" >> /etc/sysctl.conf

2 部署Nginx+Keepalived高可用負載均衡器

172.16.1.81-82節點上操作

(1) Kubernetes作為容器集群系統,通過健康檢查+重啟策略實現了Pod故障自我修復能力,通過調度算法實現將Pod分布式部署,並保持預期副本數,根據Node失效狀態自動在其他Node拉起Pod,實現了應用層的高可用性。
(2) 針對Kubernetes集群,高可用性還應包含以下兩個層面的考慮:Etcd數據庫的高可用性和Kubernetes Master組件的高可用性。而kubeadm搭建的K8s集群Etcd只起了一個,存在單點,所以我們這里會獨立搭建一個Etcd集群。
(3) Master節點扮演着總控中心的角色,通過不斷與工作節點上的Kubeletkube-proxy進行通信來維護整個集群的健康工作狀態。如果Master節點故障,將無法使用kubectl工具或者API做任何集群管理。
(4) Master節點主要有三個服務kube-apiserverkube-controller-managerkube-scheduler,其中kube-controller-managerkube-scheduler組件自身通過選擇機制已經實現了高可用,所以Master高可用主要針對kube-apiserver組件,而該組件是以HTTP API提供服務,因此對他高可用與Web服務器類似,增加負載均衡器對其負載均衡即可,並且可水平擴容。
(5) kube-apiserver高可用架構圖:

wps2 

(6) Nginx是一個主流Web服務和反向代理服務器,這里用四層實現對apiserver實現負載均衡
Keepalived是一個主流高可用軟件,基於VIP綁定實現服務器雙機熱備,在上述拓撲中,Keepalived主要根據Nginx運行狀態判斷是否需要故障轉移(偏移VIP),例如當Nginx主節點掛掉,VIP會自動綁定在Nginx備節點,從而保證VIP一直可用,實現Nginx高可用

2.1 安裝軟件包

# yum install epel-release -y
# yum install nginx keepalived -y

2.2 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 172.16.1.81:6443;   # Master1 APISERVER IP:PORT
       server 172.16.1.82:6443;   # Master2 APISERVER IP:PORT
    }
   
    server {
       listen 16443;  # 由於nginxmaster節點復用,這個監聽端口不能是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

(1) 驗證 nginx配置文件是否正確
# nginx -t
nginx: [emerg] unknown directive "stream" in /etc/nginx/nginx.conf:13
nginx: configuration file /etc/nginx/nginx.conf test failed
# 報錯提示找不到stream這個模塊

(2) 解決辦法
# yum install nginx-mod-stream -y
# cat /usr/share/nginx/modules/mod-stream.conf
load_module "/usr/lib64/nginx/modules/ngx_stream_module.so";
# nginx 配置文件已經加載了stream模塊,nginx -t 驗證配置文件就不會報錯了。

2.3 keepalived配置文件(NginxMaster)

172.16.1.81節點上操作

# 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
    state BACKUP  # 指定實例初始狀態,實際的MASTERBACKUP是選舉決定的
    nopreempt       # 設置master恢復后為不搶占VIP資源
    interface eth1  # 修改為實際網卡名
    virtual_router_id 51 # VRRP 路由 ID實例,每個實例是唯一的
    priority 100    # 優先級,備服務器設置 90
    advert_int 1    # 指定VRRP 心跳包通告間隔時間,默認1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    # 虛擬IP
    virtual_ipaddress {
        172.16.1.80/24
    }
    track_script {
        check_nginx
    }
}
EOF

notification_email # 設置報警郵件地址即報警郵件接收者,可設置多個,每行一個;如果要開啟郵件報警功能,需要開啟本機的postfix或者sendmail服務;

notification_email_from # 用於設置郵件的發送地址,即報警郵件發送者;

smtp_server # 用於設置郵件的SMTP Server地址;

smtp_connect_timeout # 設置連接SMTP Server的超時時間;

router_id # 表示運行keepalived服務器的一個標識,是發郵件時顯示在郵件主題中的信息;

vrrp_script # 指定檢查nginx工作狀態腳本(根據nginx狀態判斷是否故障轉移)

virtual_ipaddress # 虛擬IP(VIP)

nopreempt # 通常如果master服務死掉后backup會變成master,但是當master服務又好了的時候master此時會搶占VIP,這樣就會發生兩次切換對業務繁忙的網站來說是不好的。所以我們要在Master節點配置文件加入nopreempt非搶占,但是這個參數只能用於statebackup,故我們在用HA的時候最好masterbackupstate都設置成backup讓其通過priority(優先級)來競爭。

 

檢查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

: 
keepalived根據腳本返回狀態碼(0為工作正常,非0不正常)判斷是否故障轉移。

2.4 keepalived配置文件(NginxBackup)

172.16.1.82節點上操作

# 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 eth1
    virtual_router_id 51 # VRRP 路由 ID實例,每個實例是唯一的
    priority 90
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        172.16.1.80/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

2.5 啟動並設置開機啟動

# systemctl start nginx
# systemctl start keepalived
# systemctl enable nginx
# systemctl enable keepalived

: 
因為nginx為無狀態應用,keepalived可以做開機自啟動。如果做的是有狀態應用的高可用,

keepalived不要設置開機自啟動,防止主從切換問題。

2.6 查看keepalived工作狀態

(1) 172.16.1.81 (NginxMaster)節點
[root@k8s-master1 ~]# systemctl status keepalived.service
wps3

[root@k8s-master1 ~]# ip addr
wps4

(2) 172.16.1.82(NginxBackup)節點
[root@k8s-master2 ~]# systemctl status keepalived.service
wps5

[root@k8s-master2 ~]# ip addr
wps6

(3) 通過keepalived狀態可以看到,172.16.1.81節點的eth1網卡綁定了虛擬IP 172.16.1.80172.16.1.82節點的狀態為BACKUP。說明Keepalived+N
ginx高可用配置正常。

2.7 Nginx+Keepalived高可用測試

1 殺掉172.16.1.81(NginxMaster)節點上的nginx進程

[root@k8s-master1 ~]# systemctl stop nginx
[root@k8s-master1 ~]# systemctl status keepalived.service
wps7
# keepalived釋放vip

[root@k8s-master1 ~]#
ip addr
wps8

 

2 172.16.1.82(NginxBackup)上查看VIP已經成功綁定到eth1網卡

[root@k8s-master2 ~]# systemctl status keepalived.service
wps9
# eth1成功綁定vip

[root@k8s-master2 ~]# ip
addr
wps10

 

3 啟動172.16.1.81(NginxMaster)節點上的nginx,發現keepalived變為BACKUP狀態

[root@k8s-master1 ~]# systemctl start nginx
[root@k8s-master1 ~]# systemctl status keepalived.service
wps11

[root@k8s-master1 ~]# ip
addr
wps12

 

4 同理,當172.16.1.82(NginxBackup)節點nginx進程停止后會釋放VIP資源,同時172.16.1.81(NginxMaster)節點會重新接管VIP資源。當172.16.1.82(NginxBackup)節點nginx啟動后其keepalived狀態會變為BACKUP狀態。

3 部署Etcd集群

172.16.1.81-83節點上操作

 

Etcd是一個分布式鍵值存儲系統,Kubernetes使用Etcd進行數據存儲,kubeadm搭建默認情況下只啟動一個Etcd Pod,存在單點故障,生產環境強烈不建議,所以我們這里使用3台服務器組建集群,可容忍1台機器故障,當然,你也可以使用5台組建集群,可容忍2台機器故障。

3.1 准備cfssl證書生成工具

172.16.1.81節點上操作

cfssl是一個開源的證書管理工具,使用json文件生成證書,相比openssl更方便使用。

# 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

3.2 生成Etcd證書

172.16.1.81節點上操做

1 創建工作目錄

# mkdir -p /root/etcd_tls/
# cd /root/etcd_tls/

 

2 自簽證書頒發機構(CA)

(1) 自簽CA屬性配置文件
# cat > ca-config.json << EOF
{
  "signing": {
    "default": {
      "expiry": "876000h"
    },
    "profiles": {
      "server": {
         "expiry": "876000h",
         "usages": [
            "signing",
            "key encipherment",
            "server auth",
            "client auth"
        ]
      }
    }
  }
}
EOF

(2) 自簽CA生成配置文件
# cat > ca-csr.json << EOF
{
    "CN": "etcd CA",
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "C": "CN",
            "L": "Beijing",
            "ST": "Beijing"
        }
    ]
}
EOF

: "CN": "etcd CA" 表示證書頒發機構(CA)的名稱。

(3) 生成CA
# cfssl gencert -initca ca-csr.json | cfssljson -bare ca
wps13
生成以ca開頭證書頒發機構(CA)的文件有ca.csrca-key.pem
ca.pem

 

2 使用自簽CA簽發Etcd HTTPS證書

(1) 創建證書申請文件(CSR)
cat > etcd-csr.json << EOF
{
    "CN": "etcd",
    "hosts": [
    "172.16.1.81",
    "172.16.1.82",
    "172.16.1.83"
    ],
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "C": "CN",
            "L": "BeiJing",
            "ST": "BeiJing"
        }
    ]
}
EOF

:
1) 上述文件hosts字段中IP為所有etcd節點的集群內部通信IP,一個都不能少,為了方便后
期擴容可以多寫幾個預留的IP
2) "CN": "etcd" 表示CA簽發Etcd HTTPS證書的域名。

(2) 生成證書
# cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=server etcd-csr.json | cfssljson -bare etcd
wps14
生成以etcd開頭的文件etcd.csretcd-key.pemetcd.pem

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

3 驗證CA簽發的Etcd HTTPS證書etcd.pem

驗證網站: https://myssl.com/cert_decode.html
驗證信息如下:
wps15

3.3 Github下載Etcd二進制文件

# 下載地址
https://github.com/etcd-io/etcd/releases/download/v3.5.0/etcd-v3.5.0-linux-amd64.tar.gz

3.4 部署Etcd集群

1 創建工作目錄並解壓二進制包

# mkdir -p /usr/local/etcd/{bin,cfg,ssl,default.etcd}
# tar -xzf etcd-v3.5.0-linux-amd64.tar.gz
# cp -a etcd-v3.5.0-linux-amd64/{etcd,etcdctl} /usr/local/etcd/bin/
# useradd -M -s /sbin/nologin etcd
# id etcd
uid=1000(etcd) gid=1000(etcd) groups=1000(etcd)
#
chown -R etcd.etcd /usr/local/etcd/

 

2 創建etcd配置文件

cat > /usr/local/etcd/cfg/etcd.conf << EOF
#[Member]
ETCD_NAME="etcd-1"
# 節點名稱,集群中唯一,172.16.1.81-83節點名分別為etcd-1etcd-2etcd-3
ETCD_DATA_DIR="/usr/local/etcd/default.etcd"
# 數據目錄
ETCD_LISTEN_PEER_URLS="https://172.16.1.81:2380"
# 集群通信監聽地址,172.16.1.81-83節點分別為各自的IP
ETCD_LISTEN_CLIENT_URLS="https://172.16.1.81:2379"
# 客戶端訪問監聽地址,172.16.1.81-83節點分別為各自的IP

#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://172.16.1.81:2380"
# 集群通告地址,172.16.1.81-83節點分別為各自的IP
ETCD_ADVERTISE_CLIENT_URLS="https://172.16.1.81:2379"
# 客戶端通告地址,172.16.1.81-83節點分別為各自的IP
ETCD_INITIAL_CLUSTER="etcd-1=https://172.16.1.81:2380,etcd-2=https://172.16.1.82:2380,etcd-3=https://172.16.1.83:2380"
# 集群節點地址,172.16.1.81-83節點的IP
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
# 集群Token
ETCD_INITIAL_CLUSTER_STATE="new"
# 
加入集群的當前狀態,new是新集群,existing表示加入已有集群
EOF

 

3 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=simple
EnvironmentFile=/usr/local/etcd/cfg/etcd.conf
ExecStart=/usr/local/etcd/bin/etcd \
--cert-file=/usr/local/etcd/ssl/etcd.pem \
--key-file=/usr/local/etcd/ssl/etcd-key.pem \
--peer-cert-file=/usr/local/etcd/ssl/etcd.pem \
--peer-key-file=/usr/local/etcd/ssl/etcd-key.pem \
--trusted-ca-file=/usr/local/etcd/ssl/ca.pem \
--peer-trusted-ca-file=/usr/local/etcd/ssl/ca.pem \
--logger=zap

ExecReload=/bin/kill -HUP "\$MAINPID"
KillMode=process
Restart=on-failure
LimitNOFILE=65536
User=etcd
Group=etcd

[Install]
WantedBy=multi-user.target
EOF

 

4 拷貝生成的證書

172.16.1.81節點上操作

# cp -a /root/etcd_tls/ca.pem /root/etcd_tls/etcd*pem /usr/local/etcd/ssl/
# scp -p -P 22 /root/etcd_tls/ca.pem /root/etcd_tls/etcd*pem root@172.16.1.82:/usr/local/etcd/ssl/
# scp -p -P 22 /root/etcd_tls/ca.pem /root/etcd_tls/etcd*pem root@172.16.1.83:
/usr/local/etcd/ssl/

 

5 啟動並設置開機啟動

# systemctl daemon-reload
# systemctl start etcd
# systemctl enable etcd

 

6 查看集群狀態

172.16.1.81-83上任意一個節點上都可以查看

# ETCDCTL_API=3 /usr/local/etcd/bin/etcdctl --cacert=/usr/local/etcd/ssl/ca.pem \
--cert=/usr/local/etcd/ssl/etcd.pem \
--key=/usr/local/etcd/ssl/etcd-key.pem \
--endpoints="https://172.16.1.81:2379,https://172.16.1.82:2379,https://172.16.1.83:2379" \
endpoint health --write-out=table

wps16

: 
如果輸出上面信息,就說明集群部署成功。如果有問題第一步先看日志:"/var/log/message""journalctl -u etcd"

4 安裝kubeadm/kubelet/kubectl

172.16.1.81-83節點上操作

4.1 添加阿里雲YUM軟件源

# cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF

# yum clean all
#
yum makecache

4.2 安裝

由於版本更新頻繁,這里指定版本號部署

# yum install kubelet-1.20.0 kubeadm-1.20.0 kubectl-1.20.0 -y
# systemctl enable kubelet.service

5 部署Kubernetes Master

172.16.1.81-82節點上操作

5.1 初始化Master1

172.16.1.81節點上操作

1 生成初始化配置文件

[root@k8s-master1 ~]# cat > kubeadm-config.yaml << EOF
apiVersion: kubeadm.k8s.io/v1beta2
bootstrapTokens:
- groups:
  - system:bootstrappers:kubeadm:default-node-token
  token: 9037x2.tcaqnpaqkra9vsbw
  ttl: 24h0m0s
  usages:
  - signing
  - authentication
kind: InitConfiguration
localAPIEndpoint:
  advertiseAddress: 172.16.1.81
  bindPort: 6443
nodeRegistration:
  criSocket: /var/run/dockershim.sock
  name: k8s-master1
  taints:
  - effect: NoSchedule
    key: node-role.kubernetes.io/master
---
apiServer:
  certSANs:  # 包含所有Master/LB/VIP IP,一個都不能少為了方便后期擴容可以多寫幾個預留的IP
  - k8s-master1
  - k8s-master2
  - 172.16.1.81
  - 10.0.0.81
  - 172.16.1.82
  - 10.0.0.82
  - 172.16.1.80
  - 127.0.0.1
  extraArgs:
    authorization-mode: Node,RBAC
  timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta2
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controlPlaneEndpoint: 172.16.1.80:16443 # 負載均衡虛擬IPVIP)和端口
controllerManager: {}
dns:
  type: CoreDNS
etcd:
  external:  # 使用外部etcd
    endpoints:
    - https://172.16.1.81:2379 # etcd集群3個節點
    - https://172.16.1.82:2379
    - https://172.16.1.83:2379
    caFile: /usr/local/etcd/ssl/ca.pem # 連接etcd所需證書
    certFile: /usr/local/etcd/ssl/etcd.pem
    keyFile: /usr/local/etcd/ssl/etcd-key.pem
imageRepository: registry.aliyuncs.com/google_containers # 由於默認拉取鏡像地址k8s.gcr.io國內無法訪問,這里指定阿里雲鏡像倉庫地址
kind: ClusterConfiguration
kubernetesVersion: v1.20.0 # K8s版本,與上面安裝的一致
networking:
  dnsDomain: cluster.local
  podSubnet: 10.244.0.0/16  # Pod網絡,與下面部署的CNI網絡組件yaml中保持一致
  serviceSubnet: 10.96.0.0/12  # 集群內部虛擬網絡,Pod統一訪問入口
scheduler: {}
EOF

 

2 使用配置文件進行初始化

(1) 進行初始化
[root@k8s-master1 ~]# kubeadm init --config kubeadm-config.yaml

(2) 初始化出現警告
1)
警告內容
[WARNING IsDockerSystemdCheck]: detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd". Please follow the guide at https://kubernetes.io/docs/setup/cri/
2) 原因
表示,更改設置,令容器運行時和kubelet使用systemd作為cgroup驅動,以此使系統更為穩定。 請注意在docker下設置native.cgroupdriver=systemd選項。
3) 解決辦法
方法1:
編輯"/etc/docker/daemon.json"文件,追加"exec-opts"配置。
{
  "exec-opts": ["native.cgroupdriver=systemd"]
}
方法2:
編輯"/usr/lib/systemd/system/docker.service"文件,在ExecStart后追加
"--exec-opt native.cgroupdriver=systemd"
配置。
4) 使配置生效
# systemctl daemon-reload.service
# systemctl restart docker.service
5) 驗證
# docker info | grep Cgroup
Cgroup Driver: systemd
: 驗證成功,不要忘記在docker各個節點上都要做配置

(3) 清空kubeadm init 所做的更改
[root@k8s-master1 ~]# kubeadm reset

(4) 重新進行初始化
[root@k8s-master1 ~]#  kubeadm init --config kubeadm-config.yaml

……(省略的日志
)
Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

You can now join any number of control-plane nodes by copying certificate authorities
and service account keys on each node and then running the following as root:

  kubeadm join 172.16.1.80:16443 --token 9037x2.tcaqnpaqkra9vsbw \
    --discovery-token-ca-cert-hash sha256:a5669a292020ec7facec1584461ffe6c18791e721c4e1d135a11970897fbcfc7 \
    --control-plane 

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 172.16.1.80:16443 --token 9037x2.tcaqnpaqkra9vsbw \
--discovery-token-ca-cert-hash sha256:a5669a292020ec7facec1584461ffe6c18791e721c4e1d135a11970897fbcfc7


: 初始化完成后,會有兩個join的命令,帶有"--control-plane"是用於加入組建多master
群的,不帶的是加入節點的。

 

3 拷貝kubectl使用的連接k8s認證文件到默認路徑

[root@k8s-master1 ~]# mkdir -p $HOME/.kube
[root@k8s-master1 ~]# cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
[root@k8s-master1 ~]# chown $(id -u):$(id -g) $HOME/.kube/config
[root@k8s-master1 ~]# kubectl get node
NAME          STATUS     ROLES                  AGE   VERSION
k8s-master1   NotReady   control-plane,master   45m   v1.20.0

5.2 初始化Master2

172.16.1.82節點上操作

1 Master1節點生成的證書拷貝到Master2

[root@k8s-master2 ~]# scp -rp -P 22 root@172.16.1.81:/etc/kubernetes/pki /etc/kubernetes/

 

2 復制加入master1初始化時輸出的join命令在master2執行

[root@k8s-master2 ~]# kubeadm join 172.16.1.80:16443 --token 9037x2.tcaqnpaqkra9vsbw \
--discovery-token-ca-cert-hash sha256:a5669a292020ec7facec1584461ffe6c18791e721c4e1d135a11970897fbcfc7 \
--control-plane

……(省略的日志)
This node has joined the cluster and a new control plane instance was created:

* Certificate signing request was sent to apiserver and approval was received.
* The Kubelet was informed of the new secure connection details.
* Control plane (master) label and taint were applied to the new node.
* The Kubernetes control plane instances scaled up.


To start administering your cluster from this node, you need to run the following as a regular user:

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

Run 'kubectl get nodes' to see this node join the cluster.

 

3 拷貝kubectl使用的連接k8s認證文件到默認路徑

[root@k8s-master2 ~]# mkdir -p $HOME/.kube
[root@k8s-master2 ~]# cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
[root@k8s-master2 ~]# chown $(id -u):$(id -g) $HOME/.kube/config
[root@k8s-master2 ~]#
kubectl get node
NAME          STATUS     ROLES                  AGE    VERSION
k8s-master1   NotReady   control-plane,master   105m   v1.20.0
k8s-master2   NotReady   control-plane,master   101m   v1.20.0

注:由於網絡插件還沒有部署,還沒有准備就緒 NotReady

5.3 訪問負載均衡器測試

K8s集群中任意一個節點,使用curl查看K8s版本測試,使用VIP訪問

這里在172.16.1.83節點上測試

[root@k8s-node1 ~]# curl -k https://172.16.1.80:16443/version
{
  "major": "1",
  "minor": "20",
  "gitVersion": "v1.20.0",
  "gitCommit": "af46c47ce925f4c4ad5cc8d1fca46c7b77d13b38",
  "gitTreeState": "clean",
  "buildDate": "2020-12-08T17:51:19Z",
  "goVersion": "go1.15.5",
  "compiler": "gc",
  "platform": "linux/amd64"
}

 

可以正確獲取到K8s版本信息,說明負載均衡器搭建正常。

該請求數據流程為: curl->vip(nginx)->apiserver,通過

查看Nginx日志也可以看到轉發apiserver IP

通過"systemctl status keepalived"命令得知VIPmaster1(172.16.1.81)節點上。
[root@k8s-master1 ~]# tail /var/log/nginx/k8s-access.log -f
172.16.1.83 172.16.1.81:6443 - [21/Aug/2021:16:48:49 +0800] 200 419
172.16.1.83 172.16.1.82:6443 - [21/Aug/2021:16:48:50 +0800] 200 419
172.16.1.83 172.16.1.81:6443 - [21/Aug/2021:16:48:50 +0800] 200 419

6 加入Kubernetes Node

172.16.1.83(k8s-node1)節點上操作

向集群添加新節點,執行在kubeadm init輸出的kubeadm join命令

[root@k8s-node1 ~]# kubeadm join 172.16.1.80:16443 --token 9037x2.tcaqnpaqkra9vsbw \
--discovery-token-ca-cert-hash sha256:a5669a292020ec7facec1584461ffe6c18791e721c4e1d135a11970897fbcfc7

……(省略的日志)
This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

后續其他節點也是這樣加入。默認token有效期為24小時,當過期之后,該token就不可用了。

這時就需要重新創建token,可以直接使用命令快捷生成: kubeadm token create --print-join-command

7 部署網絡組件

master1master2節點上操作都可,我這里在172.16.1.81節點上操作

7.1 網絡通信機制

k8s中的網絡主要涉及到pod的各種訪問需求,如同一pod的內部(單容器或者多容器)
信、pod Apod B的通信、從外部網絡訪問pod以及從pod訪問外部網絡。k8s的網絡
基於第三方插件實現,該規范有CoreOSGoogle聯合定制,叫做CNI(Container Network
Interface)。目前常用的的CNI網絡插件有calicoflannel

7.2 calico簡介

1 calico是一個純三層的網絡解決方案,為容器提供多node間的訪問通信,calico將每一個
node節點都當做為一個路由器(router),各節點通過BGP(Border Gateway Protocol) 邊界
網關協議學習並在node節點生成路由規則,從而將不同node節點上的pod連接起來進
行通信,是目前Kubernetes主流的網絡方案。

2 BGP是一個去中心化的協議,它通過自動學習和維護路由表實現網絡的可用性,但是並不
是所有的網絡都支持BGP,另外為了跨網絡實現更大規模的網絡管理,calico 還支持IP-in-IP
的疊加模型,簡稱IPIPIPIP可以實現跨不同網段建立路由通信,但是會存在安全性問題,其
在內核內置,可以通過Calico的配置文件設置是否啟用IPIP,在公司內部如果k8snode
點沒有跨越網段建議關閉IPIP,默認IPIP
為啟用。

7.3 部署Calico

1 由於我采用了https來安裝etcd,所以要下載支持httpsyaml文件

(1) 官方文檔
https://docs.projectcalico.org/getting-started/kubernetes/self-managed-onprem/onpremises

(2) 下載
# wget https://docs.projectcalico.org/manifests/calico-etcd.yaml
# 我這里使用的版本為3
.20.0

 

2修改calico-etcd.yaml文件

(1) 修改secret
wps17

(2) 修改etcd數據庫地址及認證證書路徑
wps18

(3) 修改集群網段
wps19

(4) 
添加calico環境變量的配置
wps20


- name: KUBERNETES_SERVICE_HOST
  value: "172.16.1.80"
- name: KUBERNETES_SERVICE_PORT
  value: "16443"
- name: KUBERNETES_SERVICE_PORT_HTTPS
  value: "16443"

 

3 部署

[root@k8s-master1 ~]# kubectl apply -f calico.yaml
[root@k8s-master1 ~]#
kubectl get pods -n kube-system

 

4 查看Calico Pod都為Running

[root@k8s-master1 ~]# kubectl get pod -A -o wide
wps21

 

5 補充

(1) 后續如果發生異常時,可以用到的命令
1) 查看pod產生的日志
# kubectl logs -f <PodName> -n kube-system
2) 查看pod的具體描述
# kubectl describe pod  <PodName> -n kube-system
3) 查看集群環境輸出
# kubectl get ev -n kube-system

(2) coredns pod起不來
1)
查看pod描述信息,報錯如下
network for pod "coredns-7f89b7bc75-bspm8": networkPlugin cni failed to set up pod "coredns-7f89b7bc75-bspm8_kube-system" network: stat /var/lib/calico/nodename: no such file or directory: check that the calico/node container is running and has mounted /var/lib/calico/
2) 報錯原因
calico pod正常運行時會在宿主機上生成路徑為"/var/lib/calico/nodename"的文件,如果
calico pod沒有正常運行,會導致coredns pod無法掛載宿主機上的"/var/lib/calico/"卷。
3) 解決辦法
calico pod 運行正常的情況下刪除coredns pod,讓coredns 
pod自動創建新的。

 

6 節點准備就緒

[root@k8s-master1 ~]# kubectl get node
wps22

8 部署 Dashboard

master1master2節點上操作都可,我這里在172.16.1.81節點上操作

8.1 說明

Dashboard是官方提供的一個UI,可用於基本管理K8s資源。

 

1 官方文檔

https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/

 

2 gitlab項目地址

https://github.com/kubernetes/dashboard

 

3 版本兼容

https://github.com/kubernetes/dashboard/releases/tag/v2.3.1
wps23

4 下載

# wget -O kubernetes-dashboard.yaml \
https://raw.githubusercontent.com/kubernetes/dashboard/v2.3.1/aio/deploy/recommended.yaml

8.2 部署

1 修改kubernetes-dashboard.yaml配置

由於默認kubernetes-dashboard只能集群內部訪問,因此修改ServiceNodePort類型,暴露
k8s集群外部進行訪問。
wps24

 

2 應用kubernetes-dashboard.yaml

[root@k8s-master1 ~]# kubectl apply -f kubernetes-dashboard.yaml
# 查看pod狀態
[root@k8s-master1 ~]# kubectl get pod -n kubernetes-dashboard -o wide
wps25

: kubernetes dashboard pod運行正常,訪問地址: 
https://NodeIP:30001

 

3 創建訪問dashboard的token

(1) 創建serviceaccount並賦權
1) kube-system命名空間中創建serviceaccount/dashboard-admin
# kubectl create serviceaccount dashboard-admin -n kube-system
2) 綁定kube-system命名空間中serviceaccount/dashboard-admin到集群角色cluster-admin
# kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin \
--serviceaccount=kube-system:dashboard-admin

(2) 獲取訪問token
1) 獲取kube-system命名空間中serviceaccount/dashboard-adminsecrets名稱
# kubectl describe serviceaccount dashboard-admin -n kube-system



wps26

2) 獲取kube-system命名空間中secrets/dashboard-admin-token-ld7hk登錄k8s集群的token
# kubectl describe secrets dashboard-admin-token-ld7hk -n kube-system

3) 補充: 一條命令獲取token
# kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk '/dashboard-admin/{print $1}')

8.3 token登錄Dashboard

wps27 

https://kubernetes.io/docs/reference/access-authn-authz/authentication/

wps28 

9 補充

自此使用kubeadm方式部署K8S1.20高可用集群就完成了。

9.1 master1節點查看k8s集群中所有的pod

172.16.1.81節點

[root@k8s-master1 ~]# kubectl get pod -A -o wide

wps29 

9.2 master2節點查看k8s集群中所有的pod

172.16.1.82節點

[root@k8s-master2 ~]# kubectl get pod -A -o wide

wps30 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM