第20章: 二进制方式部署K8S1.20高可用集群
二进制方式部署K8S1.20高可用集群
作者 |
刘畅 |
时间 |
2021-08-27 |
目录
1.1 生产环境可部署Kubernetes集群的两种方式 4
2 部署Nginx+Keepalived高可用负载均衡器 8
2.3 keepalived配置文件(NginxMaster) 11
2.4 keepalived配置文件(NginxBackup) 12
4.5 部署kube-controller-manager 32
4.8 授权kubelet-bootstrap用户允许请求证书 39
6.3 删除kubelet证书和kubeconfig文件 52
7.2 从master1节点拷贝kubelet相关文件 55
7.3 从master1节点拷贝kube-proxy相关文件 55
1 架构说明
1.1 生产环境可部署Kubernetes集群的两种方式
1 kubeadm部署
(1) Kubeadm是一个K8s部署工具,提供kubeadm init和kubeadm 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 服务器要求
建议最小硬件配置: 2核CPU、2G内存、30G硬盘
服务器最好可以访问外网,会有从网上拉取镜像需求,如果服务器不能上网,需要提前下载对应镜像并导入节点。
2 服务器规划
操作系统: CentOS7.5-x86-64
主机名 |
IP |
软件 |
VIP |
k8s-master1 |
主网卡eth1: 172.16.1.81 |
etcd(etcd-1) |
172.16.1.80
|
k8s-master2 |
主网卡eth1: 172.16.1.82 |
etcd(etcd-2) | |
k8s-node1 |
主网卡eth1: 172.16.1.83 |
etcd(etcd-3) |
|
k8s-node2 |
主网卡eth1:
172.16.1.84 |
kubernetes1.20.0[docker-ce-19.03.9、kubelet、kube-proxy] |
|
(1) 为了节省机器,etcd集群与K8s节点机器复用,也可以独立于k8s集群之外部署,只
要apiserver能连接到就行。
(2) 为了节省机器,nginx+keepalived与K8s master节点机器复用,也可以独立于k8s集
群之外部署,只要nginx与apiserver能通信就行。
(3) master1节点和master2节点也部署node组件kubelet、kube-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 架构图
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访问apiserver、exec
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节点扮演着总控中心的角色,通过不断与工作节点上的Kubelet和kube-proxy进行通信来维护整个集群的健康工作状态。如果Master节点故障,将无法使用kubectl工具或者API做任何集群管理。
(4)
Master节点主要有三个服务kube-apiserver、kube-controller-manager和kube-scheduler,其中kube-controller-manager和kube-scheduler组件自身通过选择机制已经实现了高可用,所以Master高可用主要针对kube-apiserver组件,而该组件是以HTTP API提供服务,因此对他高可用与Web服务器类似,增加负载均衡器对其负载均衡即可,并且可水平扩容。
(5) kube-apiserver高可用架构图:
(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; #
由于nginx与master节点复用,这个监听端口不能是6443,否则会冲突
proxy_pass
k8s-apiserver;
}
}
http
{
log_format main '$remote_addr - $remote_user [$time_local] "$request"
'
'$status
$body_bytes_sent "$http_referer" '
'"$http_user_agent"
"$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size
2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
server
{
listen 80 default_server;
server_name _;
location
/ {
}
}
}
EOF
(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 #
指定实例初始状态,实际的MASTER和BACKUP是选举决定的
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非抢占,但是这个参数只能用于state为backup,故我们在用HA的时候最好master和backup的state都设置成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
[root@k8s-master1
~]# ip addr
(2)
172.16.1.82(NginxBackup)节点
[root@k8s-master2
~]# systemctl status keepalived.service
[root@k8s-master2
~]# ip
addr
(3)
通过keepalived状态可以看到,172.16.1.81节点的eth1网卡绑定了虚拟IP 172.16.1.80,172.16.1.82节点的状态为BACKUP。说明Keepalived+Nginx高可用配置正常。
2.7 Nginx+Keepalived高可用测试
1 杀掉172.16.1.81(NginxMaster)节点上的nginx进程
[root@k8s-master1 ~]# systemctl stop
nginx
[root@k8s-master1
~]# systemctl status keepalived.service
# keepalived释放vip
[root@k8s-master1
~]# ip addr
2 在172.16.1.82(NginxBackup)上查看VIP已经成功绑定到eth1网卡
[root@k8s-master2 ~]# systemctl status
keepalived.service
# eth1成功绑定vip
[root@k8s-master2
~]# ip addr
3 启动172.16.1.81(NginxMaster)节点上的nginx,发现keepalived变为BACKUP状态
[root@k8s-master1 ~]# systemctl start
nginx
[root@k8s-master1
~]# systemctl status keepalived.service
[root@k8s-master1
~]# ip addr
4 同理,当172.16.1.82(NginxBackup)节点nginx进程停止后会释放VIP资源,同时172.16.1.81(NginxMaster)节点会重新接管VIP资源。当172.16.1.82(NginxBackup)节点nginx启动后其keepalived状态会变为BACKUP状态。
3 部署Etcd集群
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 –
生成以ca开头证书颁发机构(CA)的文件有ca.csr、ca-key.pem、ca.pem
2 使用自签CA签发Etcd HTTPS证书
(1)
创建证书申请文件(CSR)
cat
> etcd-csr.json <<
EOF
{
"CN":
"etcd",
"hosts":
[
"172.16.1.81",
"172.16.1.82",
"172.16.1.83"
],
"key":
{
"algo":
"rsa",
"size":
2048
},
"names":
[
{
"C":
"CN",
"L":
"BeiJing",
"ST":
"BeiJing"
}
]
}
EOF
注:
1) 上述文件hosts字段中IP为所有etcd节点的集群内部通信IP,一个都不能少,为了方
便后期扩容可以多写几个预留的IP。hosts代表信任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
生成以etcd开头的文件etcd.csr、etcd-key.pem、etcd.pem。
3 验证CA签发的Etcd HTTPS证书etcd.pem
验证网站:
https://myssl.com/cert_decode.html
验证信息如下:
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-1、etcd-2、etcd-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
注: 如果输出上面信息,就说明集群部署成功。如果有问题第一步先看日志:"/var/log/message"或
"journalctl -u
etcd"
4 部署Master1 Node
在172.16.1.81节点上操作
4.1 生成kube-apiserver证书
# 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可以用该CA对server提供的证书进行验证。
4)
client
auth # 表示 server 可以用该CA对client提供的证书进行验证。
(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.csr、ca-key.pem、ca.pem
(4)
验证ca证书ca.pem
验证网站: https://myssl.com/cert_decode.html
验证信息如下:
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 Name,kube-apiserver从证书中提取该字段作为请求的用户名(User Name),浏览
器使用该字段验证网站是否合法。RBAC,用于client
auth,放到客户端证书中。
O #
Organization,kube-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.csr、kube-apiserver-key.pem、kube-apiserver.pem
(3)
验证kubernetes.pem证书
验证网站: https://myssl.com/cert_decode.html
验证信息如下:
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包就够了,包含了Master和Worker
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
# 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-servers:etcd集群地址
--bind-address:监听地址
--secure-port:https安全端口
--advertise-address:集群通告地址
--allow-privileged:启用授权
--service-cluster-ip-range:Service虚拟IP地址段
--enable-admission-plugins:准入控制模块
--authorization-mode:认证授权,启用RBAC授权和节点自管理
--enable-bootstrap-token-auth:启用TLS bootstrap机制
--token-auth-file:bootstrap token文件
--service-node-port-range:Service nodeport类型默认分配端口范围
--kubelet-client-xxx:apiserver访问kubelet客户端证书
--tls-xxx-file:apiserver https证书
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节点kubelet和kube-proxy要
与kube-apiserver进行通信,必须使用CA签发的有效客户端证书才可以,当Node节点很多时,这种客户端证书颁发需要大量工作,同样也会增加集群扩展复杂度。为了简化流程,Kubernetes引入了TLS bootstraping机制来自动颁发客户端证书,kubelet会以一个低权限用户自动向apiserver申请证书,kubelet的证书由apiserver动态签署。所以强烈建议在Node上使用这种方式,目前主要用于kubelet,kube-proxy还是由我们统一颁发一个证书。
TLS bootstraping 工作流程:
4 创建上述配置文件中token文件
# cat > /opt/kubernetes/cfg/token.csv <<
EOF
362fccc729f416f6298bb4ac9b7aa705,kubelet-bootstrap,10001,"system:node-bootstrapper"
EOF
格式: token,用户名,UID,clusterrole
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
# 查看错误日志,出现以下错误,正常,忽略即可
4.5 部署kube-controller-manager
# 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字段作为User,O字段作为Group进行client auth。
3) kube-apiserver预定义了一些RBAC使用的clusterrolebinding。
4) clusterrolebinding
- cluster-admin
# kubectl get clusterrolebinding cluster-admin -o
yaml
ClusterRoleBinding
cluster-admin将Group
system:masters与ClusterRole
cluster-admin 绑定,ClusterRole
cluster-admin
授予了调用kube-apiserver的所有API的权限。
5) clusterrolebinding
- system:kube-controller-manager
# kubectl get clusterrolebinding
system:kube-controller-manager -o yaml
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.pem、kube-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
# 查看错误日志,出现如下报错是正常现象,这里不需要接入云供应商控制器
4.6 部署kube-scheduler
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.csr、kube-scheduler-key.pem、kube-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
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.csr、kubernetes-admin.pem、kubernetes-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
注: 如上输出说明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-dir:kubelet证书生成目录
--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
(2)
批准k8s-master1节点kubelet的证书申请
# kubectl certificate approve
node-csr-dSmKmmNtYygtqirJdYbVF0uhPGOJpnhEGASiN2bWH10
(3)
查看节点,节点处于未准备状态,因为没有安装网络插件
#
kubectl get node
(4)
再次查看kubelet证书请求,CONDITION状态为Approved,Issued经核准,发布
# kubectl get csr
7 查看kubelet服务端口号
# netstat -tunlp | grep kubelet
8 查看自动生成的kubelet.kubeconfig上下文文件
# cat /opt/kubernetes/cfg/kubelet.kubeconfig
可以看到生成的证书文件存放位置如下:
client-certificate:
/opt/kubernetes/ssl/kubelet-client-current.pem
client-key:
/opt/kubernetes/ssl/kubelet-client-current.pem
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
配置保持一致。
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
注:
授权中的user和apiserver证书中的CN保持一致,因为apiserver要访问kubelet也
要经过apiserver服务的验证。
kind:
User
name: kube-apiserver
4.11 部署kube-proxy
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.csr、kube-proxy.pem、kube-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
5 部署网络组件
5.1 网络通信机制
k8s中的网络主要涉及到pod的各种访问需求,如同一pod的内部(单容器或者多容器)通
信、pod A与pod
B的通信、从外部网络访问pod以及从pod访问外部网络。k8s的网络
基于第三方插件实现,该规范有CoreOS和Google联合定制,叫做CNI(Container
Network
Interface)。目前常用的的CNI网络插件有calico和flannel。
5.2 calico简介
1 calico是一个纯三层的网络解决方案,为容器提供多node间的访问通信,calico将每一个
node节点都当做为一个路由器(router),各节点通过BGP(Border Gateway Protocol)
边界
网关协议学习并在node节点生成路由规则,从而将不同node节点上的pod连接起来进
行通信,是目前Kubernetes主流的网络方案。
2
BGP是一个去中心化的协议,它通过自动学习和维护路由表实现网络的可用性,但是并不
是所有的网络都支持BGP,另外为了跨网络实现更大规模的网络管理,calico 还支持IP-in-IP
的叠加模型,简称IPIP,IPIP可以实现跨不同网段建立路由通信,但是会存在安全性问题,其在内核内置,可以通过Calico的配置文件设置是否启用IPIP,在公司内部如果k8s的node节点没有跨越网段建议关闭IPIP,默认IPIP为启用。
5.3 部署Calico
1 由于我采用了https来安装etcd,所以要下载支持https的yaml文件
(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
(2) 修改etcd数据库地址及认证证书路径
(3) 修改集群网段
(4) 添加calico环境变量的配置
- 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
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
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/
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动态生成的,每个节点都不一样。
# 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地址为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-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 查看集群状态
6.7 批准kubelet证书申请
1 查看证书请求
#
kubectl get csr
2
接受授权请求
# kubectl certificate approve
node-csr-PF5HycY6pM7_nw4FYlryozBqgfZQQYY5AQwpVToHVbg
# 查看授权请求状态
3 查看Node状态
(1)
查看网络插件Pod在master2上为running状态
#
kubectl get pod -n kube-system -o wide
(2)
master2 node变为准备状态
# kubectl get node
找K8s集群中任意一个节点,使用curl查看K8s版本测试,使用VIP访问。
这里在172.16.1.84节点上测试
[root@k8s-node2 ~]# curl -k
https://172.16.1.80:16443/version
可以正确获取到K8s版本信息,说明负载均衡器搭建正常。
该请求数据流程为: curl->vip(nginx)->apiserver,通过查看Nginx日志也可以看到转
发apiserver IP。
通过"systemctl status
keepalived"命令得知VIP在master1(172.16.1.81)节点上。
[root@k8s-master1
~]# cat /var/log/nginx/k8s-access.log
7 部署Worker Node
在172.16.1.83、84节点上操作,部署kubelet、kube-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.83、84节点主机名分别为k8s-node1、k8s-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.83、84节点主机名分别为k8s-node1、k8s-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 查看kubelet、kube-proxy配置文件目录结构
1 172.16.1.83(k8s-node1)节点
2 172.16.1.84(k8s-node2)节点
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
2 批准申请
# kubectl certificate approve
node-csr-nGTNITxQKkKhMVfQnpfzy_zvN9KtTG5PeMjZ8amr01k
# kubectl certificate approve
node-csr-tK_mG7rzmSClO3DgsZmv8dIwz0_cMLuaYhXNuw1HES0
# 节点已经被接受
3
查看节点
(1)
查看网络插件pod为running状态
#
kubectl get pod -n kube-system -o wide
(2)
k8s-node1、k8s-node2节点准备就绪
# kubectl get node -o wide
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
注:
默认coredns只部署一个pod副本,如果集群负载较高,需要设置多个副本,
修改coredns.yaml文件下面的配置即可。
# kubectl get pods -n kube-system -o
wide
# kubectl get svc -n kube-system
8.3 DNS解析测试
# kubectl
run -it --rm dns-test --image=busybox:1.28.4 sh
解析没有任何的问题。
9 部署 Dashboard
在master1或master2节点上操作都可,我这里在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
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只能集群内部访问,因此修改Service为NodePort类型,暴露到k8s集群外部进行访问。
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
注: 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-admin的secrets名称
#
kubectl describe serviceaccount dashboard-admin -n kube-system
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
https://kubernetes.io/docs/reference/access-authn-authz/authentication/
10 为master节点打污点
10.1 taint语法
(1)
设置taint
kubectl taint node [node]
key=value:[effect]
注:
污点的键为key,值为
value,value可以省略(可以看做是一种描述),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污点
11 测试
在master1、master2节点都可以操作,这里我在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
# 每个节点上都会有一个nodePort端口号
11.2 在浏览器进行访问
访问地址: http://NodeIP:nodePort
NodeIP #
172.16.1.81-84
nodePort #
30862
至此,一套完整的 Kubernetes 高可用集群就部署完成了。
11.3 总结(个人理解)
1 架构说明
(1) kubernetes有master组件和node(work)组件组成。
(2) master组件: etcd、kube-apiserver、kube-scheduler、kube-controller-manager、kubectl,共5大
组件组成一个master节点。
(3) node组件: kubelet、kube-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-apiserver的https地址。
kubelet、kube-proxy组件部署到所有节点时,配置文件中的主机名需要集群中唯一,连接
kube-apiserver的https地址指定的是VIP地址。
(10)
各组件绑定地址
1) master
kube-apiserver #
master1-172.16.1.81、master2-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节点上etcd、kube-apiserver、kube-controller-manager、kube-scheduler、kubectl
组件工作正常
(2)
在master1节点上查看所有node节点状态(与master2结果一致)
(3)
在master1节点上查看所有命名空间下的pod(与master2结果一致)
3 master2节点
(1) 验证master2节点上etcd、kube-apiserver、kube-controller-manager、kube-scheduler、kubectl
组件工作正常
(2)
在master2节点上查看所有node节点状态(与master1结果一致)
(3)
在master2节点上查看所有命名空间下的pod(与master1结果一致)
4 验证nginx负载均衡
(1) 找到keepalived VIP的地址
1) master1节点
#
VIP 172.16.1.80在master1节点上
2) master2节点
(2)
在master1节点上查看nginx日志
# 可以看到来自172.16.1.81-84节点上的kubelet、kube-proxy组件访问负载均衡的VIP后,请求被负
# 载到后面的kube-apiserver组件上面,且状态码都为200。
5 查看pod日志
6 进入pod容器内
7 使用coredns解析svc/nginx
12 知识拾遗
12.1 证书原理
1 客户端向一个需要https访问的网站发起请求。
2 服务器将证书发送给客户端进行校验。证书里面包含了其公钥。这里要特别说一下客户
端到底如何来校验对方发过来的数字证书是否有效。
1) 首先在本地电脑寻找是否有这个服务器证书上的ca机构的根证书。如果有继续下一步
,如果没有弹出警告。
2) 使用ca机构根证书的公钥对服务器证书的指纹和指纹算法进行解密。
3) 得到指纹算法之后,拿着这个指纹算法对服务器证书的摘要进行计算得到指纹。
将计算出的指纹和从服务器证书中解密出的指纹对比看是否一样,如果一样则通过认证。
3
校验成功之后,客户端会生成一个随机串然后使用服务器证书的公钥进行加密之后发送
给服务器。
4 服务器通过使用自己的私钥解密得到这个随机值。
5 服务器从此开始使用这个随机值进行对称加密开始和客户端进行通信。
6 客户端拿到值用对称加密方式使用随机值进行解密。
7补充: 为什么不一直使用非对称进行加密,而是在类似握手之后开始使用对称加密算法
进行https通信,原因如下:
非对称加密的消耗和所需的计算以及时间远比对称加密消耗要大,所以在握手和认证之后,服务器和客户端就开始按照约定的随机串,对后续的数据传输进行加密。
12.2 清理docker磁盘
1 查看磁盘使用情况
#
docker system df
# du -sh
/var/lib/docker/
2 清理磁盘的命令
(1)
删除所有关闭的容器、所有没有被容器使用的网络、所有无dangling(tag)的镜像、
所有无dangling(tag)的构建缓存
#
docker system prune
(2)
删除所有关闭的容器、所有没有被容器使用的网络、所有没有被容器使用的镜像、
所有的构建缓存
#
docker system prune -a
(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
(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
id:
dd34e67e3371
2 查找image元数据
cat /var/lib/docker/image/overlay2/imagedb/content/sha256/<镜像id>
diff_ids就是镜像层了,而且排列顺序也有讲究,从上到下依次依赖构建。
取其中一条为例:
sha256:8f736d52032f7a4b7d828c0e119571cc3c047514c568f30ad52b6a503d050d85
3 找到对应的layer元数据
#
cd /var/lib/docker/image/overlay2/layerdb/sha256/
#
ls -l
4 镜像层的数据文件
# grep -ri "8f736d52032f7"
文件中包含上面取值diff_ids
文件所在的目录为:
2a3d94c7adfe6e94ef038a9b3ea3631168e979f8ddb49a38b203e364627af2d9
/var/lib/docker/overlay2/<cache-id内容>/目录就是镜像分层存放的目录。
12.5 容器数据存放位置
容器数据文件都存放在/var/lib/docker/overlay2目录下。
1 获取容器id
#
docker ps
容器id: 236c84698420
2 根据容器id找到容器目录
# ls -l
/var/lib/docker/containers/236c846984200c81ee4cbb0ac44dbc6bed60de6d78cb40d02e27e1cc5c561959/
3 在镜像层下找到容器的挂载信息
# cd /var/lib/docker/image/overlay2/layerdb/mounts/
#
ls -l
# ls -l
236c846984200c81ee4cbb0ac44dbc6bed60de6d78cb40d02e27e1cc5c561959
# cat mount-id
be467eefc18186e758692fe088f067dc73b422882ebf56a3d774956f2f81e444
4 容器数据存储位置
container的数据文件存放位置在"/var/lib/docker/overlay2/<mount-id的内容>"目录下,目录内容如下
12.6 kubeconfig配置文件解析
# kubectl get config
# cat
/opt/kubernetes/cfg/bootstrap.kubeconfig
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
kind和apiVersion都是固定值,用户不需要关心
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
比如第一行表示ClusterRoleBinding
system:basic-user将system:authenticated
组绑定到ClusterRole system:basic-user上
# kubectl get ClusterRoleBinding system:basic-user -o
yaml
2 user
3 其它组件角色