二进制方式部署K8S1.20高可用集群

 

 

 

 

 

 

作者

刘畅

时间

2021-08-27

 

 

 

 

 

 

 

 

目录

架构说明 4

1.1 生产环境可部署Kubernetes集群的两种方式 4

1.2 准备环境 4

1.3 操作系统初始化配置 6

2 部署Nginx+Keepalived高可用负载均衡器 8

2.1 安装软件包 9

2.2 Nginx配置文件 9

2.3 keepalived配置文件(NginxMaster) 11

2.4 keepalived配置文件(NginxBackup) 12

2.5 启动并设置开机启动 14

2.6 查看keepalived工作状态 14

2.7 Nginx+Keepalived高可用测试 15

3 部署Etcd集群 18

3.1 准备cfssl证书生成工具 18

3.2 生成Etcd证书 18

3.3 Github下载Etcd二进制文件 21

3.4 部署Etcd集群 22

4 部署Master1 Node 24

4.1 生成kube-apiserver证书 25

4.2 Github下载k8s二进制文件 29

4.3 解压二进制包 29

4.4 部署kube-apiserver 29

4.5 部署kube-controller-manager 32

4.6 部署kube-scheduler 36

4.7 部署kubectl 38

4.8 授权kubelet-bootstrap用户允许请求证书 39

4.10 授权apiserver访问kubelet 44

4.11 部署kube-proxy 45

5 部署网络组件 48

5.1 网络通信机制 48

5.2 calico简介 48

5.3 部署Calico 48

6 部署Master2 Node 51

6.1 创建etcd证书目录 51

6.2 拷贝文件 51

6.3 删除kubelet证书和kubeconfig文件 52

6.4 修改配置文件IP和主机名 52

6.5 启动设置开机启动 53

6.6 查看集群状态 53

6.7 批准kubelet证书申请 53

6.8 访问负载均衡器测试 54

7 部署Worker Node 55

7.1 创建工作目录 55

7.2 master1节点拷贝kubelet相关文件 55

7.3 master1节点拷贝kube-proxy相关文件 55

7.4 查看kubeletkube-proxy配置文件目录结构 56

7.5 启动并设置开机启动 57

7.6 批准kubelet证书申请并加入集群 57

8 部署CoreDNS 57

8.1 下载coredns 58

8.2 部署coredns 58

8.3 DNS解析测试 59

9 部署 Dashboard 59

9.1 说明 59

9.2 部署 60

9.3 token登录Dashboard 62

10 master节点打污点 63

10.1 taint语法 63

10.2 打污点 63

11 测试 64

11.1 部署一个服务 64

11.2 在浏览器进行访问 64

11.3 总结(个人理解) 65

12 知识拾遗 70

12.1 证书原理 70

12.2 清理docker磁盘 71

12.3 彻底卸载docker 72

12.4 镜像数据存放位置 73

12.5 容器数据存放位置 74

12.6 kubeconfig配置文件解析 75

12.7 kubernetes集群用于用户认证的默认ClusterRoleBinding 76


 

 

 

 

 

 

 

 

 

 

 

1.1 生产环境可部署Kubernetes集群的两种方式

1 kubeadm部署

(1) Kubeadm是一个K8s部署工具,提供kubeadm initkubeadm join,用于快速部署Kubernetes集群。

(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集群。
Kubeadm降低了k8s部署的门槛,但屏蔽了很多细节,遇到问题很难排查。如果想更容易
可控,推荐使用二进制包部署Kubernetes集群,虽然手动部署麻烦点,期间可以学习很多
工作原理,也利于后期维护。这里采用二进制搭建集群。

1.2 准备环境

1 服务器要求

建议最小硬件配置: 2CPU2G内存、30G硬盘
服务器最好可以访问外网,会有从网上拉取镜像需求,如果服务器不能上网,需要提前下载对应镜像并导入节点

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2 服务器规划

操作系统: CentOS7.5-x86-64

主机名

IP

软件

VIP

k8s-master1
(24
G)

主网卡eth1: 172.16.1.81
副网卡eth0:
10.0.0.81

etcd(etcd-1)
nginx + keepalived(master)
kubernetes1.20.0[docker-ce-19.03.9kube-apiserverkube-controller-managerkube-schedulerkubeletkube-proxy
]

 

 

 

 

 

172.16.1.80

 

 

 

 

 

k8s-master2
(24
G)

主网卡eth1: 172.16.1.82
副网卡eth0:
10.0.0.82

etcd(etcd-2)
nginx + keepalived(backup)
kubernetes1.20.0[docker-ce-19.03.9kube-apiserverkube-controller-managerkube-schedulerkubeletkube-proxy
]

k8s-node1
(48
G)

主网卡eth1: 172.16.1.83
副网卡eth0:
10.0.0.83

etcd(etcd-3)
kubernetes1.20.0[docker-ce-19.03.9kubeletkube-proxy
]

 

 

k8s-node2
(48G)

主网卡eth1: 172.16.1.84
副网卡eth0: 10.0.0.8
4

kubernetes1.20.0[docker-ce-19.03.9kubeletkube-proxy]

 

(1) 为了节省机器,etcd集群与K8s节点机器复用,也可以独立于k8s集群之外部署,只

apiserver能连接到就行。

 

(2) 为了节省机器,nginx+keepalivedK8s master节点机器复用,也可以独立于k8s

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

 

(3) master1节点和master2节点也部署node组件kubeletkube-proxy

使用kubectl管理master node,方便知道master节点的状态。

使用kube-proxy,方便通过master 节点的ip访问到svc后面的pod

kubelet # master节点apiserver的代理,收集node节点信息、管理pod

Kube-proxy # Service使用其将链接路由到Pod

 

(4) 集群网络

1) cluster-cidr # 172.27.0.0/16

2) service-cluster-ip-range # 172.28.0.0/16

3) CLUSTER_KUBERNETES_SVC_IP # 172.28.0.1

4) clusterDNS # 172.28.0.2

 

 

 

 

 

 

 

 

 

 

 

 

 

3 架构图

第20章: 二进制方式部署K8S1.20高可用集群 

1.3 操作系统初始化配置

172.16.1.81-84节点上操作

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
: 因为kubectl访问apiserverexec pod需要用主机名进行访问
cat >> /etc/hosts << EOF
172.16.1.81 k8s-master1
172.16.1.82 k8s-master2
172.16.1.83 k8s-node1
172.16.1.84 k8s-node2
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) 下载二进制包并解压
下载地址:
 https://download.docker.com/linux/static/stable/x86_64/docker-19.03.9.tgz
# tar -xzf docker-19.03.9.tgz
# mv docker/* /usr/bin/

(2) 配置systemd管理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
TimeoutSec=0
RestartSec=2
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TasksMax=infinity
Delegate=yes
KillMode=process
[Install]
WantedBy=multi-user.target
EOF

(3) 添加阿里云的镜像仓库和配置容器运行时和kubelet使用systemd作为cgroup驱动
# mkdir -p /etc/docker
# cat > /etc/docker/daemon.json << EOF
{
  "registry-mirrors": ["https://b1cx9cn7.mirror.aliyuncs.com"],
  "exec-opts": ["native.cgroupdriver=systemd"]
}
EOF

(4) 启动Docker服务并设置开机启动,验证cgroup驱动类型
# systemctl daemon-reload
# systemctl start docker
# systemctl enable docker
# docker version  # 可以看到docker客户端和服务端都是同一个版本
# docker info
# docker info | grep Cgroup
Cgroup Driver: systemd

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高可用架构图:

第20章: 二进制方式部署K8S1.20高可用集群 

(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
第20章: 二进制方式部署K8S1.20高可用集群

[root@k8s-master1 ~]# ip addr
第20章: 二进制方式部署K8S1.20高可用集群

(2) 172.16.1.82(NginxBackup)节点
[root@k8s-master2 ~]# systemctl status keepalived.service
第20章: 二进制方式部署K8S1.20高可用集群

[root@k8s-master2 ~]# ip addr
第20章: 二进制方式部署K8S1.20高可用集群

(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
第20章: 二进制方式部署K8S1.20高可用集群
# keepalived释放vip

[root@k8s-master1 ~]#
ip addr
第20章: 二进制方式部署K8S1.20高可用集群

 

2 172.16.1.82(NginxBackup)上查看VIP已经成功绑定到eth1网卡

[root@k8s-master2 ~]# systemctl status keepalived.service
第20章: 二进制方式部署K8S1.20高可用集群
# eth1成功绑定vip

[root@k8s-master2 ~]# ip
addr
第20章: 二进制方式部署K8S1.20高可用集群

 

3 启动172.16.1.81(NginxMaster)节点上的nginx,发现keepalived变为BACKUP状态

[root@k8s-master1 ~]# systemctl start nginx
[root@k8s-master1 ~]# systemctl status keepalived.service
第20章: 二进制方式部署K8S1.20高可用集群

[root@k8s-master1 ~]# ip
addr
第20章: 二进制方式部署K8S1.20高可用集群

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
第20章: 二进制方式部署K8S1.20高可用集群
生成以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,一个都不能少,为了方
便后期扩容可以多写几个预留的IPhosts代表信任ip列表,在该列表的ip访问etcd
群可以不使用客户端证书。
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
第20章: 二进制方式部署K8S1.20高可用集群
生成以etcd开头的文件etcd.csretcd-key.pemetcd.pem

 

 

 

 

 

 

 

 

 

 

 

 

3 验证CA签发的Etcd HTTPS证书etcd.pem

验证网站: https://myssl.com/cert_decode.html
验证信息如下:
第20章: 二进制方式部署K8S1.20高可用集群

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=notify
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

Restart=on-failure
LimitNOFILE=65536
ExecReload=/bin/kill -HUP \$MAINPID
KillMode=control-group
RestartSec=2
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

第20章: 二进制方式部署K8S1.20高可用集群

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

4 部署Master1 Node

172.16.1.81节点上操作

第20章: 二进制方式部署K8S1.20高可用集群 

第20章: 二进制方式部署K8S1.20高可用集群 

 

 

 

 

 

4.1 生成kube-apiserver证书

1 自签证书颁发机构(CA)

# mkdir -p /root/k8s_tls/
# cd /root/k8s_tls/

生成CA默认配置文件和默认签名请求文件的方法(使用时根据需要修改默认配置)
# cfssl print-defaults config > ca-config.json
# cfssl print-defaults csr > ca-csr.json

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

:
1) ca-config.json# 可以定义多个profiles,分别指定不同的过期时间、使用场景等参数,后续在签名
证书时使用某个profile
2) signing # 表示该证书可用于签名其它证书,生成的ca.pem证书中CA=TRUE
3) server auth # 表示client可以用该CAserver提供的证书进行验证。
4) client auth # 
表示 server 可以用该CAclient提供的证书进行验证

(2) 自签CA 证书签名请求文件
# cat > ca-csr.json << EOF
{
    "CN": "kubernetes",
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "C": "CN",
            "L": "Beijing",
            "ST": "Beijing",
            "O": "k8s",
            "OU": "System"
        }
    ]
}
EOF

(3) 生成CA证书和私钥
# cfssl gencert -initca ca-csr.json | cfssljson -bare ca -
: 生成以ca开头证书颁发机构(CA)的文件有ca.csrca-key.pemca.pem

(4) 验证ca证书ca.pem
验证网站: https://myssl.com/cert_decode.html
验证信息如下:
第20章: 二进制方式部署K8S1.20高可用集群

 

 

2 使用自签CA签发kube-apiserver HTTPS证书

(1) 创建kube-apiserver证书签名请求文件(使用CN)
# cat > kube-apiserver-csr.json << EOF
{
    "CN": "kube-apiserver",
    "hosts": [
      "k8s-master1",
      "k8s-master2",
      "127.0.0.1",
      "172.16.1.81",
      "10.0.0.81",
      "172.16.1.82",
      "10.0.0.82",
      "172.16.1.80",
      "172.28.0.1",
      "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

:
CN # Common Namekube-apiserver从证书中提取该字段作为请求的用户名(User Name),浏览
器使用该字段验证网站是否合法。RBAC,用于client auth,放到客户端证书中。
O # Organizationkube-apiserver从证书中提取该字段作为请求用户所属的组(Group)RBAC
用于client auth,放到客户端证书中。

# 上述文件hosts字段中指定授权使用该证书的IP或者域名列表,为所有Master/LB/VIP IP/apiserver
集群内部cluster ip(指定的service-cluster-ip-range 网段的第一个IP "${CLUSTER_KUBERNETES_SVC_IP}")一个都不能少,为了方便后期扩容可以多写几个预留的IP
注意: 
hosts字段把可能部署kubelet的主机ip都写进去,只能写ip地址,不能写网段。后期如果在非hosts列表中ip主机上部署kubelet,需要重新签发证书,并更换证书,并重启服务

(2) 生成kube-apiserver证书和私钥
# cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes \
kube-apiserver-csr.json | cfssljson -bare kube-apiserver
# 生成以kube-apiserver开头的文件kube-apiserver.csrkube-apiserver-key.pemkube-apiserver.pem

(3) 验证kubernetes.pem证书
验证网站: https://myssl.com/cert_decode.html
验证信息如下:

第20章: 二进制方式部署K8S1.20高可用集群 

4.2 Github下载k8s二进制文件

地址:
https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.20.md
https://dl.k8s.io/v1.20.0/kubernetes-server-linux-amd64.tar.gz
: 打开链接你会发现里面有很多包,下载一个server包就够了,包含了MasterWorker Node二进制文件。

4.3 解压二进制包

# mkdir -p /opt/kubernetes/{bin,cfg,ssl,logs}
# tar -xzf kubernetes-server-linux-amd64.tar.gz
# cd kubernetes/server/bin/
# cp -a kube-apiserver kube-scheduler kube-controller-manager /opt/kubernetes/bin/
# cp -a kube-proxy kubelet /opt/kubernetes/bin/
# cp -a kubectl /usr/bin/

4.4 部署kube-apiserver

1 创建配置文件

# cat > /opt/kubernetes/cfg/kube-apiserver.conf << EOF
KUBE_APISERVER_OPTS="--logtostderr=false \\
--v=2 \\
--log-dir=/opt/kubernetes/logs \\
--etcd-servers=https://172.16.1.81:2379,https://172.16.1.82:2379,https://172.16.1.83:2379 \\
--bind-address=172.16.1.81 \\
--secure-port=6443 \\
--advertise-address=172.16.1.81 \\
--allow-privileged=true \\
--service-cluster-ip-range=172.28.0.0/16 \\
--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/kube-apiserver.pem \\
--kubelet-client-key=/opt/kubernetes/ssl/kube-apiserver-key.pem \\
--tls-cert-file=/opt/kubernetes/ssl/kube-apiserver.pem \\
--tls-private-key-file=/opt/kubernetes/ssl/kube-apiserver-key.pem \\
--client-ca-file=/opt/kubernetes/ssl/ca.pem \\
--service-account-key-file=/opt/kubernetes/ssl/ca-key.pem \\
--service-account-issuer=api \\
--service-account-signing-key-file=/opt/kubernetes/ssl/kube-apiserver-key.pem \\
--etcd-cafile=/usr/local/etcd/ssl/ca.pem \\
--etcd-certfile=/usr/local/etcd/ssl/etcd.pem \\
--etcd-keyfile=/usr/local/etcd/ssl/etcd-key.pem \\
--requestheader-client-ca-file=/opt/kubernetes/ssl/ca.pem \\
--proxy-client-cert-file=/opt/kubernetes/ssl/kube-apiserver.pem \\
--proxy-client-key-file=/opt/kubernetes/ssl/kube-apiserver-key.pem \\
--requestheader-allowed-names=kube-apiserver \\
--requestheader-extra-headers-prefix=X-Remote-Extra- \\
--requestheader-group-headers=X-Remote-Group \\
--requestheader-username-headers=X-Remote-User \\
--enable-aggregator-routing=true \\
--audit-log-maxage=30 \\
--audit-log-maxbackup=3 \\
--audit-log-maxsize=100 \\
--audit-log-path=/opt/kubernetes/logs/kube-apiserver-audit.log"
EOF

: 上面两个\\, 第一个是转义符,第二个是换行符,使用转义符是为了使用EOF保留换行符。
--logtostderr:启用日志
--v:日志等级
--log-dir:日志目录
--etcd-serversetcd集群地址
--bind-address:监听地址
--secure-porthttps安全端口
--advertise-address:集群通告地址
--allow-privileged:启用授权
--service-cluster-ip-rangeService虚拟IP地址段
--enable-admission-plugins:准入控制模块
--authorization-mode:认证授权,启用RBAC授权和节点自管理
--enable-bootstrap-token-auth:启用TLS bootstrap机制
--token-auth-filebootstrap token文件
--service-node-port-rangeService nodeport类型默认分配端口范围
--kubelet-client-xxxapiserver访问kubelet客户端证书
--tls-xxx-fileapiserver https证书
1.20版本必须加的参数:--service-account-issuer--service-account-signing-key-file
--etcd-xxxfile:连接Etcd集群证书
--audit-log-xxx:审计日志
启动聚合层相关配置:
--requestheader-client-ca-file
--proxy-client-cert-file
--proxy-client-key-file
--requestheader-allowed-names: 如果不为空的情况下,需要保证此设定值与证书中的CN一致
--requestheader-extra-headers-prefix
--requestheader-group-headers
--requestheader-username-headers
--enable-aggregator-routing

 

2 把刚才生成的证书拷贝到配置文件中的路径

# cp  -a /root/k8s_tls/ca*pem /root/k8s_tls/kube-apiserver*pem /opt/kubernetes/ssl/

 

3 启用TLS Bootstrapping机制

TLS Bootstraping: Master apiserver启用TLS认证后,Node节点kubeletkube-proxy
kube-apiserver进行通信,必须使用CA签发的有效客户端证书才可以,当Node节点很多时,这种客户端证书颁发需要大量工作,同样也会增加集群扩展复杂度。为了简化流程,Kubernetes引入了TLS bootstraping机制来自动颁发客户端证书,kubelet会以一个低权限用户自动向apiserver申请证书,kubelet的证书由apiserver动态签署。所以强烈建议在Node上使用这种方式,目前主要用于kubeletkube-proxy还是由我们统一颁发一个证书。
TLS bootstraping 工作流程:
第20章: 二进制方式部署K8S1.20高可用集群

 

4 创建上述配置文件中token文件

# cat > /opt/kubernetes/cfg/token.csv << EOF
362fccc729f416f6298bb4ac9b7aa705,kubelet-bootstrap,10001,"system:node-bootstrapper"
EOF

格式: token,用户名,UIDclusterrole
token也可自行生成替换: head -c 16 /dev/urandom | od -An -t x | tr -d ' '

 

5 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

 

6 启动并设置开机启动

# systemctl daemon-reload
# systemctl start kube-apiserver
# systemctl enable kube-apiserver
# netstat -tunlp | grep -w 6443
第20章: 二进制方式部署K8S1.20高可用集群

# 查看错误日志,出现以下错误,正常,忽略即可
第20章: 二进制方式部署K8S1.20高可用集群

4.5 部署kube-controller-manager

1 创建配置文件

# 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 \\
--kubeconfig=/opt/kubernetes/cfg/kube-controller-manager.kubeconfig \\
--bind-address=127.0.0.1 \\
--allocate-node-cidrs=true \\
--cluster-cidr=172.27.0.0/16 \\
--service-cluster-ip-range=172.28.0.0/16 \\
--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 \\
--cluster-signing-duration=87600h0m0s"
EOF

:
--kubeconfig:连接apiserver配置文件
--leader-elect:当该组件启动多个时,自动选举(HA)
自动为kubelet颁发证书的CA,与apiserver保持一致:
--cluster-signing-cert-file
--cluster-signing-key-file

 

2 生成kube-controller-manager证书

(1) 切换目录
# cd /root/k8s_tls/

(2) 创建证书请求文件(使用CN,O)
# 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

:
1) k8s各组件与kube-apiserver通信采用双向TLS认证。
2) kubernetes将证书中的CN字段作为UserO字段作为Group进行client auth
3) kube-apiserver预定义了一些RBAC使用的clusterrolebinding
4) clusterrolebinding - cluster-admin
# kubectl get clusterrolebinding cluster-admin -o yaml
第20章: 二进制方式部署K8S1.20高可用集群
ClusterRoleBinding cluster-adminGroup system:mastersClusterRole cluster-admin 绑定,ClusterRole cluster-admin
授予了调用kube-apiserver的所有API的权限。

5) clusterrolebinding - system:kube-controller-manager
# kubectl get clusterrolebinding system:kube-controller-manager -o yaml

第20章: 二进制方式部署K8S1.20高可用集群
ClusterRoleBinding system:kube-controller-manager将用户system:kube-controller-manager
ClusterRole system:kube-controller-manager进行绑定。

(3) 生成证书
# 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

# 生成以kube-controller-manager开头的kube-controller-manager.csr
kube-controller-manager-key.pemkube-controller-manager.pem
的证书。

 

3 生成kubeconfig文件(以下是shell命令,直接在终端执行)

KUBE_CONFIG="/opt/kubernetes/cfg/kube-controller-manager.kubeconfig"
KUBE_APISERVER="https://172.16.1.81: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 kube-controller-manager@kubernetes \
  --cluster=kubernetes \
  --user=kube-controller-manager \
  --kubeconfig=${KUBE_CONFIG}

kubectl config use-context kube-controller-manager@kubernetes --kubeconfig=${KUBE_CONFIG}

 

4 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

 

5 启动并设置开机启动

# systemctl daemon-reload
# systemctl start kube-controller-manager
# systemctl enable kube-controller-manager
# netstat -tunlp | grep kube-controll
第20章: 二进制方式部署K8S1.20高可用集群

 

 

 

 

 

 

# 查看错误日志,出现如下报错是正常现象,这里不需要接入云供应商控制器
第20章: 二进制方式部署K8S1.20高可用集群

4.6 部署kube-scheduler

1 创建配置文件

cat > /opt/kubernetes/cfg/kube-scheduler.conf << EOF
KUBE_SCHEDULER_OPTS="--logtostderr=false \\
--v=2 \\
--log-dir=/opt/kubernetes/logs \\
--leader-elect=true \\
--kubeconfig=/opt/kubernetes/cfg/kube-scheduler.kubeconfig \\
--bind-address=127.0.0.1"
EOF

:
--kubeconfig:连接apiserver配置文件
--leader-elect:当该组件启动多个时,自动选举(HA
)

 

2 生成kube-scheduler证书

(1) 切换工作目录
# cd /root/k8s_tls/

(2) 创建证书请求文件(使用CN, O)
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

(3) 生成证书
# cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes \
kube-scheduler-csr.json | cfssljson -bare kube-scheduler

生成以kube-scheduler开头的kube-scheduler.csrkube-scheduler-key.pemkube-scheduler.pem证书。

 

3 生成kubeconfig文件(以下是shell命令,直接在终端执行)

KUBE_CONFIG="/opt/kubernetes/cfg/kube-scheduler.kubeconfig"
KUBE_APISERVER="https://172.16.1.81: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 kube-scheduler@kubernetes \
  --cluster=kubernetes \
  --user=kube-scheduler \
  --kubeconfig=${KUBE_CONFIG}

kubectl config use-context kube-scheduler@kubernetes --kubeconfig=${KUBE_CONFIG}

 

4 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

 

5 启动并设置开机启动

# systemctl daemon-reload
# systemctl start kube-scheduler
# systemctl enable kube-scheduler
# netstat -tunlp | grep schedule
第20章: 二进制方式部署K8S1.20高可用集群

4.7 部署kubectl

1 生成kubectl连接集群的证书

(1) 切换工作目录
# cd /root/k8s_tls/

(2) 创建证书请求文件(使用O)
# cat > kubernetes-admin-csr.json <<EOF
{
  "CN": "kubernetes-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 \
kubernetes-admin-csr.json | cfssljson -bare kubernetes-admin

生成以kubernetes-admin开头的kubernetes-admin.csrkubernetes-admin.pemkubernetes-admin-key.pem
证书。

 

2 生成kubeconfig文件(以下是shell命令,直接在终端执行)

mkdir -p /root/.kube/

KUBE_CONFIG="/root/.kube/config"
KUBE_APISERVER="https://172.16.1.81: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 kubernetes-admin \
  --client-certificate=./kubernetes-admin.pem \
  --client-key=./kubernetes-admin-key.pem \
  --embed-certs=true \
  --kubeconfig=${KUBE_CONFIG}

kubectl config set-context kubernetes-admin@kubernetes \
  --cluster=kubernetes \
  --user=kubernetes-admin \
  --kubeconfig=${KUBE_CONFIG}

kubectl config use-context kubernetes-admin@kubernetes --kubeconfig=${KUBE_CONFIG}

 

3 通过kubectl工具查看当前集群组件状态

# kubectl get cs
第20章: 二进制方式部署K8S1.20高可用集群

: 如上输出说明Master1节点组件运行正常

4.8 授权kubelet-bootstrap用户允许请求证书

# kubectl create clusterrolebinding kubelet-bootstrap \
--clusterrole=system:node-bootstrapper \
--user=kubelet-bootstrap
4.9 部署kubelet
1创建配置文件
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=registry.aliyuncs.com/google_containers/pause-amd64:3.0"
EOF

:
--hostname-override:显示名称,集群中唯一
--network-plugin:启用CNI
--kubeconfig:空路径,会自动生成,后面用于连接apiserver
--bootstrap-kubeconfig:首次启动向apiserver申请证书
--config:配置参数文件
--cert-dirkubelet证书生成目录
--pod-infra-container-image:管理Pod网络容器的镜像

 

2 配置参数文件

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: systemd
clusterDNS:
- 172.28.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

 

3 生成kubelet初次加入集群引导kubeconfig文件

生成 kubelet bootstrap kubeconfig 配置文件(以下是shell命令,可以在终端直接运行)

KUBE_CONFIG="/opt/kubernetes/cfg/bootstrap.kubeconfig"
KUBE_APISERVER="https://172.16.1.80:16443"
TOKEN="362fccc729f416f6298bb4ac9b7aa705"

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 kubelet-bootstrap@kubernetes \
  --cluster=kubernetes \
  --user=kubelet-bootstrap \
  --kubeconfig=${KUBE_CONFIG}

kubectl config use-context kubelet-bootstrap@kubernetes --kubeconfig=${KUBE_CONFIG}

:
KUBE_APISERVER # apiserver IP:PORT,这里写VIP:PORT
TOKEN #
token.csv里保持一致

 

4 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

 

5 启动并设置开机启动

# systemctl daemon-reload
# systemctl start kubelet
# systemctl enable kubelet

 

6 批准kubelet证书申请并加入集群

(1) 查看kubelet证书请求CONDITION状态为Pending待定
# kubectl get csr
第20章: 二进制方式部署K8S1.20高可用集群

(2) 批准k8s-master1
节点kubelet的证书申请
# kubectl certificate approve node-csr-dSmKmmNtYygtqirJdYbVF0uhPGOJpnhEGASiN2bWH10

(3) 查看节点,节点处于未准备状态,因为没有安装网络插件
# kubectl get node
第20章: 二进制方式部署K8S1.20高可用集群

(4) 再次查看kubelet证书请求,CONDITION状态为Approved,Issued经核准,发布
# kubectl get csr
第20章: 二进制方式部署K8S1.20高可用集群

 

7 查看kubelet服务端口号

# netstat -tunlp | grep kubelet
第20章: 二进制方式部署K8S1.20高可用集群

 

8 查看自动生成的kubelet.kubeconfig上下文文件

# cat /opt/kubernetes/cfg/kubelet.kubeconfig
第20章: 二进制方式部署K8S1.20高可用集群
可以看到生成的证书文件存放位置如下:
client-certificate: /opt/kubernetes/ssl/kubelet-client-current.pem
client-key: /opt/kubernetes/ssl/kubelet-client-current.pem

第20章: 二进制方式部署K8S1.20高可用集群

 

9 验证证书kubelet-client-current.pem

(1) 说明
特别注意,kubelet连接apiserver服务端,apiserver服务端需要对kubelet的客户端证
书进行client auth验证,使用的是node鉴权,而不是rbac鉴权。
官方文档: https://kubernetes.io/zh/docs/reference/access-authn-authz/node/
1) 节点鉴权是一种特殊用途的鉴权模式,专门对 kubelet 发出的 API 请求进行鉴权。
2) 为了获得节点鉴权器的授权,kubelet 必须使用一个凭证以表示它在 system:nodes 组中,用户名为 system:node:<nodeName>

(2) 验证网站: https://myssl.com/cert_decode.html
验证信息见下图:
从证书的验证信息可以看到kubelet客户端证书中配置的CN(用户名)system:node:k8s-master1
O(用户组)system:nodes,符合Node鉴权的要求。
注意: system:node:<nodeName>配置中的<nodeName>需要和上面kubelet.conf配置文件中的
hostname-override
配置保持一致。
第20章: 二进制方式部署K8S1.20高可用集群

 

10 小结

同理在其它节点上部署kubelet也是相同的方法,如果不使用TLS bootstraping方式实现kubelet
apiserver自动申请颁发客户端证书,也可以向部署kube-controller-manager
证书那样做。

4.10 授权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: kube-apiserver
EOF

kubectl apply -f apiserver-to-kubelet-rbac.yaml

:
授权中的userapiserver证书中的CN保持一致,因为apiserver要访问kubelet
要经过apiserver服务的验证。
kind: User
name: kube-apiserver

4.11 部署kube-proxy

1 创建配置文件

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

 

2 配置参数文件

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: 172.27.0.0/16
EOF

 

3 生成kube-proxy证书

(1) 切换工作目录
# cd /root/k8s_tls/

(2) 创建证书请求文件(使用CN)
# 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

生成以kube-proxy开头的kube-proxy.csrkube-proxy.pemkube-proxy-key.pem证书文件。

4 生成kubeconfig文件

KUBE_CONFIG="/opt/kubernetes/cfg/kube-proxy.kubeconfig"
KUBE_APISERVER="https://172.16.1.80:16443"

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 kube-proxy@kubernetes \
  --cluster=kubernetes \
  --user=kube-proxy \
  --kubeconfig=${KUBE_CONFIG}

kubectl config use-context kube-proxy@kubernetes --kubeconfig=${KUBE_CONFIG}

: KUBE_APISERVER # aipserver地址写VIP:
PORT

 

5 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

 

6 启动并设置开机启动

# systemctl daemon-reload
# systemctl start kube-proxy
# systemctl enable kube-proxy
# netstat -tunlp | grep kube-proxy
第20章: 二进制方式部署K8S1.20高可用集群

5 部署网络组件

master1 172.16.1.81节点上操作

5.1 网络通信机制

k8s中的网络主要涉及到pod的各种访问需求,如同一pod的内部(单容器或者多容器)
信、pod Apod B的通信、从外部网络访问pod以及从pod访问外部网络。k8s的网络
基于第三方插件实现,该规范有CoreOSGoogle联合定制,叫做CNI(Container Network
Interface)。目前常用的的CNI网络插件有calicoflannel

5.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
为启用。

5.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
第20章: 二进制方式部署K8S1.20高可用集群

(2) 修改etcd数据库地址及认证证书路径
第20章: 二进制方式部署K8S1.20高可用集群
(3) 修改集群网段
第20章: 二进制方式部署K8S1.20高可用集群

(4) 
添加calico环境变量的配置
第20章: 二进制方式部署K8S1.20高可用集群

- 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-etcd.yaml
[root@k8s-master1 ~]#
kubectl get pods -n kube-system

 

4 查看Calico Pod都为Running

[root@k8s-master1 ~]# kubectl get pod -n kube-system -o wide
第20章: 二进制方式部署K8S1.20高可用集群

 

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
第20章: 二进制方式部署K8S1.20高可用集群

6 部署Master2 Node

172.16.1.82节点上操作

Master2与已部署的Master1所有操作一致。所以我们只需将Master1所有K8s文件拷贝过来,再修改下服务器IP和主机名启动即可。

6.1 创建etcd证书目录

# mkdir -p /usr/local/etcd/ssl/
:
我这里master2已经部署了etcd服务,且ssl存放目录为/usr/local/etcd/ssl/,就不从
 master1节点上复制etcd证书了,如果没有需要复制且和master1
路径保持一致。

6.2 拷贝文件

1 拷贝Master1上所有K8s文件和证书到Master2
# scp -rp -P 22 root@172.16.1.81:/opt/kubernetes /opt/
# rm -rf /opt/kubernetes/logs/*

2 拷贝systemd管理服务的文件
# scp -p -P 22 root@172.16.1.81:/usr/lib/systemd/system/kube* /usr/lib/systemd/system/
第20章: 二进制方式部署K8S1.20高可用集群

3 拷贝kubectl执行文件和config文件
# scp -p -P 22 root@172.16.1.81:/usr/bin/kubectl /usr/bin/
# scp -rp -P 22 root@172.16.1.81:/root/.kube /root/
# rm -rf /root/.kube/cache/

6.3 删除kubelet证书和kubeconfig文件

因为kubelet证书和kubelet.kubeconfig是通过申请apiserver动态生成的,每个节点都不一样。

第20章: 二进制方式部署K8S1.20高可用集群
# rm -f /opt/kubernetes/ssl/kubelet*

# rm -f /opt/kubernetes/cfg/kubelet.kubeconfig

6.4 修改配置文件IP和主机名

1 修改kube-apiserver.conf绑定的ip地址
# vim /opt/kubernetes/cfg/kube-apiserver.conf
......
--bind-address=172.16.1.82 \
--advertise-address=172.16.1.82 \
......

2 修改kube-controller-manager.kubeconfig连接apiserver的地址
# vim /opt/kubernetes/cfg/kube-controller-manager.kubeconfig
……
server: https://172.16.1.82:6443
……

3 修改kube-scheduler.kubeconfig连接apiserver的地址
# vim /opt/kubernetes/cfg/kube-scheduler.kubeconfig
……
server: https://172.16.1.82:6443
……

4 修改kubectl config文件连接apiserver的地址
# vim /root/.kube/config
......
server: https://172.16.1.82:6443
……

5 修改kubelet配置
(1) 检查bootstrap.kubeconfig连接apiserver地址为V
IP:PORT
# cat /opt/kubernetes/cfg/bootstrap.kubeconfig
……
server: https://172.16.1.80:16443
……

(2) 修改kubelet.conf中的主机名
# vim /opt/kubernetes/cfg/kubelet.conf
……
--hostname-override=k8s-master2
……

6 修改kube-proxy配置
(1) 检查kube-proxy.kubeconfig
连接apiserver地址为VIP:PORT
# cat /opt/kubernetes/cfg/kube-proxy.kubeconfig
……
server: https://172.16.1.80:16443
……

(2) 修改kube-proxy-config.yml中的主机名
# vim /opt/kubernetes/cfg/kube-proxy-config.yml
……
hostnameOverride: k8s-master2
……

6.5 启动设置开机启动

# 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

# 一定要查看相关服务是否有错误日志journalctl -u <服务
>

6.6 查看集群状态

# kubectl get cs
第20章: 二进制方式部署K8S1.20高可用集群

6.7 批准kubelet证书申请

1 查看证书请求
# kubectl get csr
第20章: 二进制方式部署K8S1.20高可用集群

2 接受
授权请求
# kubectl certificate approve node-csr-PF5HycY6pM7_nw4FYlryozBqgfZQQYY5AQwpVToHVbg

# 
查看授权请求状态
第20章: 二进制方式部署K8S1.20高可用集群

3 查看Node状态
(1) 查看网络插件Podmaster2上为running状态
# kubectl get pod -n kube-system -o wide
第20章: 二进制方式部署K8S1.20高可用集群

(2) master2 node变为准备状态
# kubectl get node
第20章: 二进制方式部署K8S1.20高可用集群

6.8 访问负载均衡器测试

K8s集群中任意一个节点,使用curl查看K8s版本测试,使用VIP访问

这里在172.16.1.84

相关文章:

  • 2022-12-23
  • 2021-12-29
  • 2021-07-27
  • 2022-02-09
  • 2022-02-10
  • 2021-09-22
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2021-10-27
  • 2021-10-05
  • 2021-06-28
  • 2021-12-15
  • 2022-12-23
  • 2022-12-23
  • 2021-09-05
相关资源
相似解决方案