Loading

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

 

 

 

 

 

 

 

二进制方式部署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.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 架构图

wps1 

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

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,一个都不能少,为了方
便后期扩容可以多写几个预留的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
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=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

wps16

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

4 部署Master1 Node

172.16.1.81节点上操作

wps17 

wps18 

 

 

 

 

 

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
验证信息如下:
wps19

 

 

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
验证信息如下:

wps20 

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 工作流程:
wps21

 

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
wps22

# 查看错误日志,出现以下错误,正常,忽略即可
wps23

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
wps24
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

wps25
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
wps26

 

 

 

 

 

 

# 查看错误日志,出现如下报错是正常现象,这里不需要接入云供应商控制器
wps27

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
wps28

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
wps29

: 如上输出说明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
wps30

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

(3) 查看节点,节点处于未准备状态,因为没有安装网络插件
# kubectl get node
wps31

(4) 再次查看kubelet证书请求,CONDITION状态为Approved,Issued经核准,发布
# kubectl get csr
wps32

 

7 查看kubelet服务端口号

# netstat -tunlp | grep kubelet
wps33

 

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

# cat /opt/kubernetes/cfg/kubelet.kubeconfig
wps34
可以看到生成的证书文件存放位置如下:
client-certificate: /opt/kubernetes/ssl/kubelet-client-current.pem
client-key: /opt/kubernetes/ssl/kubelet-client-current.pem

wps35

 

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
配置保持一致。
wps36

 

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
wps37

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
wps38

(2) 修改etcd数据库地址及认证证书路径
wps39
(3) 修改集群网段
wps40

(4) 
添加calico环境变量的配置
wps41

- 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
wps42

 

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
wps43

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/
wps44

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动态生成的,每个节点都不一样。

wps45
# 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
wps46

6.7 批准kubelet证书申请

1 查看证书请求
# kubectl get csr
wps47

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

# 
查看授权请求状态
wps48

3 查看Node状态
(1) 查看网络插件Podmaster2上为running状态
# kubectl get pod -n kube-system -o wide
wps49

(2) master2 node变为准备状态
# kubectl get node
wps50

6.8 访问负载均衡器测试

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

这里在172.16.1.84节点上测试

[root@k8s-node2 ~]# curl -k https://172.16.1.80:16443/version
wps51

 

可以正确获取到K8s版本信息,说明负载均衡器搭建正常。

该请求数据流程为: curl->vip(nginx)->apiserver,通过查看Nginx日志也可以看到转

apiserver IP

通过"systemctl status keepalived"命令得知VIPmaster1(172.16.1.81)节点上。
[root@k8s-master1 ~]# cat
/var/log/nginx/k8s-access.log
wps52

7 部署Worker Node

172.16.1.8384节点上操作,部署kubeletkube-proxy两个服务

7.1 创建工作目录

# mkdir -p /opt/kubernetes/{bin,cfg,ssl,logs}

7.2 master1节点拷贝kubelet相关文件

1 拷贝ca证书文件
# scp -p -P 22 root@172.16.1.81:/opt/kubernetes/ssl/ca.pem /opt/kubernetes/ssl/

2 拷贝二进制文件
# scp -p -P 22 root@172.16.1.81:/opt/kubernetes/bin/kubelet /opt/kubernetes/bin/

3 拷贝配置文件
# scp -p -P 22 root@172.16.1.81:/opt/kubernetes/cfg/kubelet.conf /opt/kubernetes/cfg/
# scp -p -P 22 root@172.16.1.81:/opt/kubernetes/cfg/kubelet-config.yml /opt/kubernetes/cfg/
# scp -p -P 22 root@172.16.1.81:/opt/kubernetes/cfg/bootstrap.kubeconfig /opt/kubernetes/cfg/

4 修改配置文件
(
1) 检查bootstrap.kubeconfig连接apiserver地址为VIP: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-node1
……
: 172.16.1.8384节点主机名分别为k8s-node1k8s
-node2

5 拷贝systemd配置文件
# scp -p -P 22 root@172.16.1.81:/usr/lib/systemd/system/kubelet.service /usr/lib/systemd/system/

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

1 拷贝二进制文件
# scp -p -P 22 root@172.16.1.81:/opt/kubernetes/bin/kube-proxy /opt/kubernetes/bin/

2 拷贝配置文件
# scp -p -P 22 root@172.16.1.81:/opt/kubernetes/cfg/kube-proxy.conf /opt/kubernetes/cfg/
# scp -p -P 22 root@172.16.1.81:/opt/kubernetes/cfg/kube-proxy-config.yml /opt/kubernetes/cfg/
# scp -p -P 22 root@172.16.1.81:/opt/kubernetes/
cfg/kube-proxy.kubeconfig /opt/kubernetes/cfg/

3 修改配置文件
(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-node1
……
: 172.16.1.8384节点主机名分别为k8s-node1k8s-node2

4 拷贝systemd配置文件
# scp -p -P 22 root@172.16.1.81:/usr/lib/systemd/system/kube-proxy.service /usr/lib/systemd/system/

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

1 172.16.1.83(k8s-node1)节点
wps53

2 172.16.1.84(k8s-node2
)节点
wps54

7.5 启动并设置开机启动

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

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

172.16.1.82 master2节点上操作

1 查看kubelet证书请求
# kubectl get csr
wps55

2 批准申请
# kubectl certificate approve node-csr-nGTNITxQKkKhMVfQnpfzy_zvN9KtTG5PeMjZ8amr01k
# kubectl certificate approve node-csr-tK_mG7rzmSClO3DgsZmv8dIwz0_cMLuaYhXNuw1HES0

# 节点已经被接受
wps56

3 查看节点
(1) 查看网络插件podrunning状态
# kubectl get pod -n kube-system -o wide
wps57

(2) k8s-node1k8s-node2节点准备就绪
# kubectl get node -o wide
wps58

8 部署CoreDNS

172.16.1.81节点上操作

8.1 下载coredns

1 CoreDNS用于集群内部Service名称解析

2 github地址: https://github.com/coredns/deployment

3 "https://github.com/coredns/deployment/tree/coredns-1.14.0/kubernetes"下载下面两个文件
(1) deploy.sh
deploy.sh是一个方便的脚本,用于生成在当前运行标准 kube-dns 的集群上运行 CoreDNS 的清单。
安装脚本依赖:
yum -y install jq

(2) coredns.yaml.sed
使用该coredns.yaml.sed文件作为模板,它创建一个ConfigMap和一个CoreDNS部署,然后更新
Kube-DNS服务选择器以使用CoreDNS部署。通过重用现有服务,服务请求不会中断。

8.2 部署coredns

1 生成CoreDNS部署清单文件coredns.yaml

# chmod +x deploy.sh
# ./deploy.sh -i 172.28.0.2 > coredns.yaml

:
-i  # 表示指定集群的DNS IP地址,即Service服务的clusterIP。如果未指定,如果"kube dns"服务存在,
DNS IP地址使用"kube dns"服务的IP

 

2 执行部署

# kubectl apply -f coredns.yaml
wps59
:
默认coredns只部署一个pod副本,如果集群负载较高,需要设置多个副本,
修改coredns.yaml
文件下面的配置即可。
wps60

# kubectl get pods -n kube-system -o wide
wps61

# kubectl get svc -n kube-system
wps62

8.3 DNS解析测试

# kubectl run -it --rm dns-test --image=busybox:1.28.4 sh
wps63
解析没有任何的问题。

9 部署 Dashboard

master1master2节点上操作都可,我这里在172.16.1.81节点上操作

9.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
wps64

 

4 下载

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

9.2 部署

1 修改kubernetes-dashboard.yaml配置

由于默认kubernetes-dashboard只能集群内部访问,因此修改ServiceNodePort类型,暴露到k8s集群外部进行访问。
wps65

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
wps66

: 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
wps67

2) 获取kube-system命名空间中secrets/dashboard-admin-token-lx2wl登录k8s集群的token
# kubectl describe secrets dashboard-admin-token-lx2wl -n kube-system > dashboard-admin.token

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

9.3 token登录Dashboard

wps68 

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

wps69 

 

 

 

 

10 master节点打污点

10.1 taint语法

(1) 设置taint
kubectl taint node [node] key=value:[effect]
: 污点的键为key,值为 valuevalue可以省略(可以看做是一种描述)key:[effect]两者组合必须唯一。

其中[effect]可取值: [ NoSchedule | PreferNoSchedule | NoExecute ]
NoSchedule # 一定不能被调度
PreferNoSchedule # 尽量不要调度
NoExecute # 不仅不会调度, 还会驱逐Node上已有的Pod

示例:
kubectl taint nodes node1 key1=value1:NoSchedule
kubectl taint nodes node1 key1=value1:NoExecute
kubectl taint nodes node1 key2=value2:NoSchedule

(2) 查看taint
kubectl describe node node1

(3) 删除taint(减号[-]表示删除)
1) key可以不用指定value
kubectl taint node node1 key1:NoSchedule-
kubectl taint node node1 key1:NoExecute-
2) 删除指定key所有的effect
kubectl taint node node1 key1-

10.2 打污点

172.16.1.81节点上操作

1 master1节点打污点
# kubectl taint node k8s-master1 node-role.kubernetes.io/master:NoSchedule

2 master2节点打污点
# kubectl taint node k8s-master2 node-role.kubernetes.io/master:NoSchedule

3 
查看master污点
wps70

11 测试

master1master2节点都可以操作,这里我在master2 172.16.1.82节点上操作

11.1 部署一个服务

# kubectl create deployment nginx --image=nginx --replicas=4
# kubectl expose deployment nginx --name=nginx --port=80 --target-port=80 --type=NodePort
[root@k8s-master2 ~]# kubectl get deployment,pod,svc -o wide -n default
wps71

# 每个节点上都会有一个nodePort
端口号
wps72

11.2 在浏览器进行访问

访问地址: http://NodeIP:nodePort
NodeIP # 172.16.1.81-84
nodePort # 30862
wps73
至此,一套完整的 Kubernetes 高可用集群就部署完成了。

 

 

 

 

 

11.3 总结(个人理解)

wps74 

1 架构说明

wps75

(1) kubernetesmaster组件和node(work)组件组成。

(2) master组件: etcdkube-apiserverkube-schedulerkube-controller-managerkubectl,共5
组件组成一个master节点。

(3) node组件: kubeletkube-proxy、符合CRI规范的容器运行时,共3大组件组成一个work节点。

(4) node组件运行在每一个节点上,包括 master 节点和 worker 节点。

(5) kube-apiserver组件作为k8s集群唯一暴露的访问入口,集中对外提供访问服务。

(6) kube-apiserver主动连接etcd组件存储k8s集群数据外,其它所有组件都是主动连接
kube-apiserver组件的,两者都是TLS双向认证。

(7) 对于主动连接kube-apiserver的组件,kube-apiserver根据客户端组件证书中的CN(用户名)O()
对组件进行默认内置RBAC鉴权(kubelet组件使用的是node鉴权)

(8) 在本套kubernetes集群高可用架构方案中,etcd集群单独使用一套ca用于签发证书,其它组件单独
使用另外一套ca用于签发证书。

(9) 主动连接kube-apiserver的组件,将客户端证书、客户端秘钥证书、ca证书以base64位编码的格
式都存在kubeconfig配置文件中,kubeconfig配置文件指定了连接kube-apiserverhttps地址。
kubeletkube-proxy组件部署到所有节点时,配置文件中的主机名需要集群中唯一,连接
kube-apiserverhttps地址指定的是VIP地址。

(10) 各组件绑定地址
1) master
kube-apiserver # master1-172.16.1.81master2-172.16.1.82
kube-controller-manager # 127.0.0.1
kube-scheduler # 127.0.0.1
2) worker
kubelet # 0.0.0.0
kube-proxy # 0.0.0.0

(11)  集群网络
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

 

2 master1节点

(1) 验证master1节点上etcdkube-apiserverkube-controller-managerkube-schedulerkubectl
组件工作正常
wps76

(2) master1节点上查看所有node节点状态(master2结果一致)
wps77

(3) master1节点上查看所有命名空间下的pod(master2结果一致
)
wps78

 

3 master2节点

(1) 验证master2节点上etcdkube-apiserverkube-controller-managerkube-schedulerkubectl
组件工作正常wps79

(2) master2节点上查看所有node节点状态(master1结果一致)
wps80

(3) master2节点上查看所有命名空间下的pod(master1
结果一致)
wps81

 

4 验证nginx负载均衡

(1) 找到keepalived VIP的地址
1) master1节点
wps82
# VIP 172.16.1.80master1节点上

2) master2节点
wps83

(2) master1节点上查看nginx日志
wps84
# 可以看到来自172.16.1.81-84节点上的kubeletkube-proxy组件访问负载均衡的VIP后,请求被负
# 载到后面的kube-apiserver组件上面,且状态码都为200

 

5 查看pod日志

wps85 

 

6 进入pod容器内

wps86 

 

7 使用coredns解析svc/nginx

wps87 

12 知识拾遗

12.1 证书原理

wps88

1 客户端向一个需要https访问的网站发起请求。

2 服务器将证书发送给客户端进行校验。证书里面包含了其公钥。这里要特别说一下客户
端到底如何来校验对方发过来的数字证书是否有效。
1) 首先在本地电脑寻找是否有这个服务器证书上的ca机构的根证书。如果有继续下一步
,如果没有弹出警告。
2) 使用ca机构根证书的公钥对服务器证书的指纹和指纹算法进行解密。
3) 得到指纹算法之后,拿着这个指纹算法对服务器证书的摘要进行计算得到指纹。
将计算出的指纹和从服务器证书中解密出的指纹对比看是否一样,如果一样则通过认证。

3 校验成功之后,客户端会生成一个随机串然后使用服务器证书的公钥进行加密之后发送
给服务器。

4 服务器通过使用自己的私钥解密得到这个随机值。

5 服务器从此开始使用这个随机值进行对称加密开始和客户端进行通信。

6 客户端拿到值用对称加密方式使用随机值进行解密。

7补充: 为什么不一直使用非对称进行加密,而是在类似握手之后开始使用对称加密算法
进行https通信,原因如下:
非对称加密的消耗和所需的计算以及时间远比对称加密消耗要大,所以在握手和认证之后,服务器和客户端就开始按照约定的随机串,对后续的数据传输进行加密。

12.2 清理docker磁盘

1 查看磁盘使用情况
# docker system df
wps89
# du -sh /var/lib/docker/

2 清理磁盘的命令
(1) 删除所有关闭的容器、所有没有被容器使用的网络、所有无dangling(tag)的镜像、
所有无dangling(tag)的构建缓存
# docker system prune
wps90

(2) 删除所有关闭的容器、所有没有被容器使用的网络、所有没有被容器使用的镜像、
所有的构建缓存
# docker system prune -a
wps91

(3) 注意: 这两个命令会把你暂时关闭的容器,以及暂时没有用到的Docker镜像都删掉,
所以使用之前一定要想清楚。

3 修改docker默认存储路径
(1) 停止docker服务
# systemctl stop docker.service

(2) 移动docker镜像及容器存储目录到指定目录
# mkdir -p /data/
# rsync -avz /var/lib/docker /data/

(3) 修改"/usr/lib/systemd/system/docker.service"配置文件
[Service]
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
# ExecStart最后面添加"--graph=/data/docker"参数,不加该参数时,docker默认存储路径为"/var/lib/docker"目录。

(4) 启动docker服务
# systemctl daemon-reload
# systemctl start docker.service

(5) 查看docker存储根目录变为了/data/docker
# docker info
wps92

(6) 再确认之前的镜像还在,确定容器没问题后删除/var/lib/docker/目录中。
# docker images
#
docker ps -a

12.3 彻底卸载docker

https://docs.docker.com/engine/install/centos/

https://developer.aliyun.com/mirror/docker-ce?spm=a2c6h.13651102.0.0.3e221b11NmqkeR

1 停止docker服务
# systemctl stop docker

2 卸载
(1) 旧版本卸载方式
# yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine

(2) ce版本卸载方式
# yum remove docker-ce docker-ce-cli containerd.io
-y
:
# rpm -qa | egrep "docker|containerd"
# 如果还有没卸载的使用yum remove <rpm 包名>
-y命令删除。

3 删除所有镜像、容器和卷
# rm -rf /var/lib/docker
: 只要不删除该目录,使用yum或二进制重新安装docker后容器和镜像


4 删除其它数据
# rm -rf /etc/docker/
# rm -rf /var/run/docker/
# rm -rf /var/lib/containerd/
# rm -rf /opt/containerd/

12.4 镜像数据存放位置

镜像层的数据文件都存放在/var/lib/docker/overlay2目录下/var/lib/docker目录下占用空间最大的
就是/var/lib/docker/overlay2这个目录。
1 查看镜像id
# docker images
wps93
id: dd34e67e3371

2 查找image元数据
cat /var/lib/docker/image/overlay2/imagedb/content/sha256/<镜像id
>
wps94
diff_ids就是镜像层了,而且排列顺序也有讲究,从上到下依次依赖构建。
取其中一条为例:
sha256:8f736d52032f7a4b7d828c0e119571cc3c047514c568f30ad52b6a503d050d85

3 找到对应的layer元数据
# cd /var/lib/docker/image/overlay2/layerdb/sha256/
# ls -l
wps95

4 镜像层的数据文件
# grep -ri "8f736d52032f7"
wps96
文件中包含上面取值diff_ids 文件所在的目录为:
2a3d94c7adfe6e94ef038a9b3ea3631168e979f8ddb49a38b203e364627af2d9

wps97

/var/lib/docker/overlay2/<cache-id内容>/目录就是镜像分层存放的目录。

12.5 容器数据存放位置

容器数据文件都存放在/var/lib/docker/overlay2目录下。
1 获取容器id
# docker ps
wps98
容器id: 236c84698420

2 
根据容器id找到容器目录
# ls -l /var/lib/docker/containers/236c846984200c81ee4cbb0ac44dbc6bed60de6d78cb40d02e27e1cc5c561959/
wps99

3 在镜像层下找到容器的挂载信息
# cd /var/lib/docker/image/overlay2/layerdb/mounts/
# ls -l
wps100

# ls -l 236c846984200c81ee4cbb0ac44dbc6bed60de6d78cb40d02e27e1cc5c561959
wps101

# cat mount-id
be467eefc18186e758692fe088f067dc73b422882ebf56a3d774956f2f81e444

4 容器数据存储位置
container的数据文件存放位置在"/var/lib/docker/overlay2/<mount-id的内容>"目录下,目录内容如下
wps102

12.6 kubeconfig配置文件解析

# kubectl get config
wps103

# cat /opt/kubernetes/cfg/bootstrap.kubeconfig
wps104

1 集群: clusters记录了clusters(一个或多个 K8S 集群)信息
(1) name 是这个cluster(K8S 集群)的名称代号
(2) server 是这个cluster(K8S 集群)的访问方式,一般为 IP+PORT
(3) certificate-authority-data 是证书数据,只有当cluster(K8S 集群)的连接方式是 https 时,为了安
全起见需要证书数据,服务端ca证书。

2 上下文: contexts是上下文信息,包括了cluster(K8S 集群)和访问cluster(K8S 集群)的用户账号等信息
(1) name 是这个上下文的名称代号
(2) cluster cluster(K8S 集群)的名称代号
(3) user 是访问cluster(K8S 集群)的用户账号代号

3 当前上下文: current-context记录当前 kubectl 默认使用的上下文信息

4 kindapiVersion都是固定值,用户不需要关心

5 preferences则是配置文件的其他设置信息,没有使用过

6 客户端认证: users记录了访问cluster(K8S 集群)的账号信息
(1) name 是用户账号的名称代号(实际取值由创建证书时的用户名[CN]和组[O]来决定,RBAC授权)
(2) user  是用户的认证方式,认证的方式不止一种,常用的如下:
1) token
user:
  token: 362fccc729f416f6298bb4ac9b7aa705
2) 公钥+私钥
user:
  client-certificate-data: REDACTED
  client-key-data: REDACTED

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

官方文档: https://v1-20.docs.kubernetes.io/zh/docs/reference/access-authn-authz/rbac/

 

1 group

wps105

wps106

比如第一行表示ClusterRoleBinding system:basic-usersystem:authenticated 组绑定到ClusterRole system:basic-user

# kubectl get ClusterRoleBinding system:basic-user -o yaml
wps107

 

 

 

 

2 user

wps108 

 

3 其它组件角色

wps109 

posted @ 2021-09-03 14:32  云起时。  阅读(536)  评论(0编辑  收藏  举报