Skip to content

** **

第16章 二进制安装多 master 节点的 k8s 高可用集群本章所讲内容:

16.1 初始化安装 k8s 的实验环境

16.2 搭建 etcd 集群

16.3 安装 kubernetes 组件

16.4 查看集群状态

16.5 测试 k8s 集群部署 tomcat 服务

16.6 验证 cordns 是否正常

16.7 安装 keepalived+nginx 实现 k8s apiserver 高可用

k8s 环境规划:

podSubnet(pod 网段) 10.244.0.0/16 serviceSubnet(service 网段): 10.96.0.0/12

实验环境规划:

操作系统:centos7.9

配置: 4Gib 内存/4vCPU/60G 硬盘

K8S 集群角色 IP 主机名 安装的组件
控制节点 192.168.40.60 xuegod60 apiserver、controller- manager、 schedule、etcd、kube-proxy、容器运行时、keepalived、 nginx
控制节点 192.168.40.61 xuegod61 apiserver、controller- manager、 schedule、etcd、kube-proxy、容器运行时、keepalived、 nginx
控制节点 192.168.40.62 xuegod62 apiserver、controller- manager、 schedule、etcd、kube-proxy、容器运行时、keepalived、 nginx
工作节点 192.168.40.63 xuegod63 Kube-proxy、 calico、coredns、容
器运行时、kubelet
VIP 192.168.40.199

16.1 初始化安装 k8s 集群的实验环境

16.1.1 配置静态 ip

vim /etc/sysconfig/network-scripts/ifcfg-ens33 文件

TYPE=Ethernet PROXY_METHOD=none BROWSER_ONLY=no

BOOTPROTO=static IPADDR=192.168.40.60 NETMASK=255.255.255.0 GATEWAY=192.168.40.2 DNS1=192.168.40.2 DEFROUTE=yes IPV4_FAILURE_FATAL=no IPV6INIT=yes IPV6_AUTOCONF=yes IPV6_DEFROUTE=yes IPV6_FAILURE_FATAL=no

IPV6_ADDR_GEN_MODE=stable-privacy NAME=ens33

DEVICE=ens33 ONBOOT=yes

修改配置文件之后需要重启网络服务才能使配置生效,重启网络服务命令如下: service network restart

注:/etc/sysconfig/network-scripts/ifcfg-ens33 文件里的配置说明:

NAME=ens33 #网卡名字,跟 DEVICE 名字保持一致即可

DEVICE=ens33 #网卡设备名,大家 ip addr 可看到自己的这个网卡设备名,每个人的机器可能这个名字不一样,需要写自己的

BOOTPROTO=static #static 表示静态 ip 地址

ONBOOT=yes #开机自启动网络,必须是 yes IPADDR=192.168.40.60 #ip 地址,需要跟自己电脑所在网段一致NETMASK=255.255.255.0 #子网掩码,需要跟自己电脑所在网段一致

GATEWAY=192.168.16.2 #网关,在自己电脑打开 cmd,输入 ipconfig /all 可看到

DNS1=192.168.16.2 #DNS,在自己电脑打开 cmd,输入 ipconfig /all 可看到

各个节点执行如下命令更新 yum 源和操作系统:

yum update -y

16.1.2 配置主机名

在 192.168.40.60 上执行如下:

hostnamectl set-hostname xuegod60 && bash

在 192.168.40.61 上执行如下:

hostnamectl set-hostname xuegod61 && bash

在 192.168.40.62 上执行如下:

hostnamectl set-hostname xuegod62 && bash

在 192.168.40.63 上执行如下:

hostnamectl set-hostname xuegod63 && bash

16.1.3 配置主机 hosts 文件

修改每台机器的/etc/hosts 文件,文件最后增加如下内容:

192.168.40.60 xuegod60

192.168.40.61 xuegod61

192.168.40.62 xuegod62

192.168.40.63 xuegod63

修改之后的文件如下:

127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4

::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 192.168.40.60 xuegod60

192.168.40.61 xuegod61

192.168.40.62 xuegod62

192.168.40.63 xuegod63

16.1.4 配置主机之间无密码登录

配置 xuegod60 到其他机器免密登录

[root@xuegod60 ~]# ssh-keygen #一路回车,不输入密码把本地生成的密钥文件和私钥文件拷贝到远程主机[root@xuegod60 ~]# ssh-copy-id xuegod60

img

img[root@xuegod60 ~]# ssh-copy-id xuegod61 [root@xuegod60 ~]# ssh-copy-id xuegod62

img

[root@xuegod60 ~]# ssh-copy-id xuegod63

配置 xuegod61 到其他机器免密登录

[root@xuegod61 ~]# ssh-keygen #一路回车,不输入密码把本地生成的密钥文件和私钥文件拷贝到远程主机[root@xuegod61 ~]# ssh-copy-id xuegod60

img

imgimg[root@xuegod61 ~]# ssh-copy-id xuegod61 [root@xuegod61 ~]# ssh-copy-id xuegod62 [root@xuegod61 ~]# ssh-copy-id xuegod63

配置 xuegod62 到其他机器免密登录

[root@xuegod62 ~]# ssh-keygen #一路回车,不输入密码把本地生成的密钥文件和私钥文件拷贝到远程主机[root@xuegod62 ~]# ssh-copy-id xuegod60

img

imgimg[root@xuegod62 ~]# ssh-copy-id xuegod61 [root@xuegod62~]# ssh-copy-id xuegod62 [root@xuegod62 ~]# ssh-copy-id xuegod63

配置 xuegod63 到其他机器免密登录

[root@xuegod63 ~]# ssh-keygen #一路回车,不输入密码把本地生成的密钥文件和私钥文件拷贝到远程主机[root@xuegod63 ~]# ssh-copy-id xuegod60

img

imgimg[root@xuegod63 ~]# ssh-copy-id xuegod61 [root@xuegod63 ~]# ssh-copy-id xuegod62 [root@xuegod63 ~]# ssh-copy-id xuegod63

16.1.5 关闭 firewalld 防火墙

[root@xuegod60 ~]# systemctl stop firewalld ; systemctl disable firewalld [root@xuegod61 ~]# systemctl stop firewalld ; systemctl disable firewalld [root@xuegod62 ~]# systemctl stop firewalld ; systemctl disable firewalld [root@xuegod63 ~]# systemctl stop firewalld ; systemctl disable firewalld

16.1.6 关闭 selinux,所有 k8s 机器均操作

sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config

#修改 selinux 配置文件之后,重启机器,selinux 配置才能永久生效,重启之后,登录到机器,执行如

下命令:

getenforce

#如果显示 Disabled 说明 selinux 已经关闭

16.1.7 关闭交换分区 swap,提升性能#临时关闭

[root@xuegod60 ~]# swapoff -a [root@xuegod61 ~]# swapoff -a [root@xuegod62 ~]# swapoff -a [root@xuegod63~]# swapoff -a

#永久关闭:注释 swap 挂载,给 swap 这行开头加一下注释

[root@xuegod60 ~]# vim /etc/fstab

#/dev/mapper/centos-swap swap swap defaults 0 0
[root@xuegod61 ~]# vim /etc/fstab
#/dev/mapper/centos-swap swap swap defaults 0 0
[root@xuegod62~]# vim /etc/fstab
#/dev/mapper/centos-swap swap swap defaults 0 0

[root@xuegod63 ~]# vim /etc/fstab #给 swap 这行开头加一下注释# #/dev/mapper/centos-swap swap swap defaults 0 0

问题 1:为什么要关闭 swap 交换分区?

Swap 是交换分区,如果机器内存不够,会使用 swap 分区,但是 swap 分区的性能较低,k8s 设计的时候为了能提升性能,默认是不允许使用交换分区的。Kubeadm 初始化的时候会检测 swap 是否关闭, 如果没关闭,那就初始化失败。如果不想要关闭交换分区,安装 k8s 的时候可以指定--ignore- preflight-errors=Swap 来解决。

16.1.8 修改机器内核参数

[root@xuegod60 ~]# modprobe br_netfilter [root@xuegod60 ~]# cat > /etc/sysctl.d/k8s.conf <<EOF net.bridge.bridge-nf-call-ip6tables = 1

net.bridge.bridge-nf-call-iptables = 1

net.ipv4.ip_forward = 1 EOF

[root@xuegod60 ~]# sysctl -p /etc/sysctl.d/k8s.conf [root@xuegod61 ~]# modprobe br_netfilter [root@xuegod61 ~]# cat > /etc/sysctl.d/k8s.conf <<EOF net.bridge.bridge-nf-call-ip6tables = 1

net.bridge.bridge-nf-call-iptables = 1

net.ipv4.ip_forward = 1 EOF

[root@xuegod61 ~]# sysctl -p /etc/sysctl.d/k8s.conf [root@xuegod62 ~]# modprobe br_netfilter [root@xuegod62 ~]# cat > /etc/sysctl.d/k8s.conf <<EOF

net.bridge.bridge-nf-call-ip6tables = 1

net.bridge.bridge-nf-call-iptables = 1

net.ipv4.ip_forward = 1 EOF

[root@xuegod62 ~]# sysctl -p /etc/sysctl.d/k8s.conf

[root@xuegod63 ~]# modprobe br_netfilter [root@xuegod63 ~]# cat > /etc/sysctl.d/k8s.conf <<EOF net.bridge.bridge-nf-call-ip6tables = 1

net.bridge.bridge-nf-call-iptables = 1

net.ipv4.ip_forward = 1 EOF

[root@xuegod63 ~]# sysctl -p /etc/sysctl.d/k8s.conf

问题 1:sysctl 是做什么的? 在运行时配置内核参数

-p 从指定的文件加载系统参数,如不指定即从/etc/sysctl.conf 中加载

问题 2:为什么要执行 modprobe br_netfilter?

修改/etc/sysctl.d/k8s.conf 文件,增加如下三行参数:

net.bridge.bridge-nf-call-ip6tables = 1

net.bridge.bridge-nf-call-iptables = 1

net.ipv4.ip_forward = 1

sysctl -p /etc/sysctl.d/k8s.conf 出现报错:

sysctl: cannot stat /proc/sys/net/bridge/bridge-nf-call-ip6tables: No such file or directory sysctl: cannot stat /proc/sys/net/bridge/bridge-nf-call-iptables: No such file or directory

解决方法:

modprobe br_netfilter

问题 3:为什么开启 net.bridge.bridge-nf-call-iptables 内核参数? 在 centos 下安装 docker,执行 docker info 出现如下警告: WARNING: bridge-nf-call-iptables is disabled

WARNING: bridge-nf-call-ip6tables is disabled

解决办法:

vim /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-ip6tables = 1

net.bridge.bridge-nf-call-iptables = 1

问题 4:为什么要开启 net.ipv4.ip_forward = 1 参数?

imgkubeadm 初始化 k8s 如果报错:

就表示没有开启 ip_forward,需要开启。net.ipv4.ip_forward 是数据包转发:

出于安全考虑,Linux 系统默认是禁止数据包转发的。所谓转发即当主机拥有多于一块的网卡时,其中一块收到数据包,根据数据包的目的 ip 地址将数据包发往本机另一块网卡,该网卡根据路由表继续发送数据包。这通常是路由器所要实现的功能。

要让 Linux 系统具有路由转发功能,需要配置一个 Linux 的内核参数 net.ipv4.ip_forward。这个参数指定了 Linux 系统当前对路由转发功能的支持情况;其值为 0 时表示禁止进行 IP 转发;如果是 1,则说明IP 转发功能已经打开。

16.1.9 配置阿里云的 repo 源:安装 docker 和 containerd #配置国内安装 docker 和 containerd 的阿里云的repo 源

[root@xuegod60 ~]#yum install yum-utils -y [root@xuegod61 ~]#yum install yum-utils -y [root@xuegod62 ~]#yum install yum-utils -y

[root@xuegod63 ~]#yum install yum-utils -y

[root@xuegod60 ~]# yum-config-manager --add-repo http://mirrors.aliyun.com/docker- ce/linux/centos/docker-ce.repo

[root@xuegod61 ~]# yum-config-manager --add-repo http://mirrors.aliyun.com/docker- ce/linux/centos/docker-ce.repo

[root@xuegod62 ~]# yum-config-manager --add-repo http://mirrors.aliyun.com/docker- ce/linux/centos/docker-ce.repo

[root@xuegod63 ~]# yum-config-manager --add-repo http://mirrors.aliyun.com/docker- ce/linux/centos/docker-ce.repo

16.1.10 配置安装 k8s 组件需要的阿里云的 repo 源

[root@xuegod60 ~]#cat > /etc/yum.repos.d/kubernetes.repo <<EOF [kubernetes]

name=Kubernetes baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/ enabled=1

gpgcheck=0 EOF

[root@xuegod61 ~]#cat > /etc/yum.repos.d/kubernetes.repo <<EOF [kubernetes]

name=Kubernetes

baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/ enabled=1

gpgcheck=0 EOF

[root@xuegod62 ~]#cat > /etc/yum.repos.d/kubernetes.repo <<EOF [kubernetes]

name=Kubernetes baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/ enabled=1

gpgcheck=0 EOF

[root@xuegod63 ~]#cat > /etc/yum.repos.d/kubernetes.repo <<EOF [kubernetes]

name=Kubernetes baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/ enabled=1

gpgcheck=0 EOF

16.1.11 配置时间同步

#安装 ntpdate 命令

[root@xuegod60 ~]# yum install ntpdate -y #跟网络时间做同步

[root@xuegod60 ~]# ntpdate cn.pool.ntp.org #把时间同步做成计划任务

[root@xuegod60 ~]# crontab -e

* * * * * /usr/sbin/ntpdate cn.pool.ntp.org #重启 crond 服务

[root@xuegod60 ~]#service crond restart

在 xuegod61 上执行如下:

#安装 ntpdate 命令

[root@xuegod61 ~]# yum install ntpdate -y #跟网络时间做同步

[root@xuegod61 ~]#ntpdate cn.pool.ntp.org #把时间同步做成计划任务

[root@xuegod61 ~]#crontab -e

* * * * * /usr/sbin/ntpdate cn.pool.ntp.org #重启 crond 服务

[root@xuegod61 ~]#service crond restart

在 xuegod62 上执行如下:

#安装 ntpdate 命令

[root@xuegod62 ~]# yum install ntpdate -y #跟网络时间做同步

[root@xuegod62 ~]#ntpdate cn.pool.ntp.org #把时间同步做成计划任务

[root@xuegod62 ~]#crontab -e

* * * * * /usr/sbin/ntpdate cn.pool.ntp.org #重启 crond 服务[root@xuegod62~]#service crond restart

在 xuegod63 上执行如下:

#安装 ntpdate 命令

[root@xuegod63 ~]# yum install ntpdate -y #跟网络时间做同步

[root@xuegod63 ~]#ntpdate cn.pool.ntp.org #把时间同步做成计划任务

[root@xuegod63 ~]#crontab -e

* * * * * /usr/sbin/ntpdate cn.pool.ntp.org #重启 crond 服务

[root@xuegod63 ~]#service crond restart

16.2 、安装 containerd 服务

16.2.1 安装 containerd

在 k8s 集群每个节点都操作如下命令: yum install containerd.io-1.6.6 -y 接下来生成 containerd 的配置文件:

mkdir -p /etc/containerd

containerd config default > /etc/containerd/config.toml

修改配置文件:

打开/etc/containerd/config.toml

把 SystemdCgroup = false 修改成 SystemdCgroup = true

把 sandbox_image = "k8s.gcr.io/pause:3.6"修改成sandbox_image="registry.aliyuncs.com/google_containers/pause:3.7"

配置 containerd 开机启动,并启动 containerd systemctl enable containerd --now

16.2.2 安装 docker 服务

k8s 所有节点均按照以下配置:

yum install docker-ce -y systemctl enable docker --now

配置 docker 镜像加速器,k8s 所有节点均按照以下配置

vim /etc/docker/daemon.json

写入如下内容:

{

"registry-mirrors":["https://vh3bm52y.mirror.aliyuncs.com","https://registry.docker- cn.com","https://docker.mirrors.ustc.edu.cn","https://dockerhub.azk8s.cn","http://hub- mirror.c.163.com"]

}

重启 docker:

systemctl restart docker

16.3 搭建 etcd 集群

16.3.1 配置 etcd 工作目录

#创建配置文件和证书文件存放目录[root@xuegod60 ~]# mkdir -p /etc/etcd [root@xuegod60 ~]# mkdir -p /etc/etcd/ssl

[root@xuegod61 ~]# mkdir -p /etc/etcd [root@xuegod61 ~]# mkdir -p /etc/etcd/ssl

[root@xuegod62 ~]# mkdir -p /etc/etcd [root@xuegod62 ~]# mkdir -p /etc/etcd/ssl

16.3.2 安装签发证书工具 cfssl

CFSSL(CloudFlare's SSL)是由 CloudFlare 开发的工具集,用于创建和管理 PKI(Public Key Infrastructure,公钥基础设施)。PKI 是一种广泛使用的安全框架,用于确保网络通信的机密性、完整性和身份验证。

CFSSL 包含以下主要组件:

1、cfssl: 这是命令行工具,用于生成证书、密钥和其他安全资产。它支持多种证书配置选项,使用户能够轻松地生成自签名证书、服务器证书、客户端证书等。

2、cfssljson: 该工具用于将 JSON 格式的证书请求(CSR)转换为其他格式,如 PEM 格式。PEM 是一种常用的证书格式,适用于许多应用程序和服务器。

3、cfssl-bundle: 用于将证书绑定到其相应的中间证书和根证书,创建一个完整的证书链。

4、cfssl-certinfo: 用于解码和打印证书的信息,方便用户查看证书的详细信息。

5、cfssl-newkey: 用于生成新的私钥。

[root@xuegod60 ~]# mkdir /data/work -p

[root@xuegod60 ~]# cd /data/work/

把 cfssl-certinfo_linux-amd64 、cfssljson_linux-amd64 、cfssl_linux-amd64 上传到

/data/work/目录下[root@xuegod60 work]# ls

cfssl-certinfo_linux-amd64 cfssljson_linux-amd64 cfssl_linux-amd64 #把文件变成可执行权限

[root@xuegod60 work]# chmod +x *

[root@xuegod60 work]# mv cfssl_linux-amd64 /usr/local/bin/cfssl [root@xuegod60 work]# mv cfssljson_linux-amd64 /usr/local/bin/cfssljson [root@xuegod60 work]# mv cfssl-certinfo_linux-amd64 /usr/local/bin/cfssl-certinfo

16.3.3 配置 ca 证书

#生成 ca 证书请求文件

[root@xuegod60 work]# vim ca-csr.json

{

"CN": "kubernetes", "key": {

"algo": "rsa", "size": 2048

},

"names": [

{

"C": "CN",

"ST": "Hubei",

"L": "Wuhan",

"O": "k8s",

"OU": "system"

}

],

"ca": {

}

}

"expiry": "87600h"

img

[root@xuegod60 work]# cfssl gencert -initca ca-csr.json | cfssljson -bare ca

备注:

上述 ca-csr.json 配置文件是用于生成 Kubernetes 集群中的CA 证书签名请求(CSR)的配置,解释如

imgimgimgimg下:

1. CN (Common Name) : 这是证书的通用名称,通常用于标识证书持有者的名称。在这个示例
中,CN 被设置为"kubernetes",意味着生成的 CA 证书将用于 Kubernetes 集群。 2.key: 这个字段用于指定生成密钥的配置。在这里,使用 RSA 算法生成密钥,其大小为 2048 位。 3. names: 这是一个包含有关证书主题(Subject)的信息的数组。主题信息描述了证书持有者的身份。在这个示例中,证书的主题包含以下字段: · C (Country): 国家,设置为"CN"表示中国。 · ST (State): 省份或州,设置为"Hubei"表示湖北省。 · L (Locality): 城市或地区,设置为"Wuhan"表示武汉市。 · O (Organization): 组织名称,设置为"k8s"表示 Kubernetes。 · OU (Organizational Unit): 组织单元,设置为"system"表示系统级别。 4. ca: 这个字段用于设置 CA 证书的相关配置。 · expiry: 它指定了 CA 证书的有效期。在这个示例中,设置为"87600h",表示 CA 证书的有效期为 87600 小时(约合 10 年)。

imgimgimgimgimg#生成 ca 证书的配置文件

[root@xuegod60 work]# vim ca-config.json

{

"signing": {

"default": {

"expiry": "87600h"

},

"profiles": {

"kubernetes": { "usages": [

"signing",

"key encipherment", "server auth", "client auth"

],

"expiry": "87600h"

}

}

}

}

备注:

上述 ca-config.json 文件是用于 CFSSL 工具集创建和管理 CA(Certificate Authority,证书颁发机

构)的配置文件。让我们逐个解释每个字段的含义:

signing : 这个字段定义了 CA 的签名配置。

· img: 在这个部分,定义了一个名为"default"的签名配置。它用于设置默认的签名配置,如

果没有明确指定其他配置,则使用这个默认配置。

· expiry: 它指定了默认签名配置中生成的证书的有效期。在这个示例中,设置为

"87600h",表示默认签名的证书有效期为 87600 小时(约合 10 年)。

· profiles: 这个部分用于定义不同的证书配置文件(profile),以供后续使用。

·

它包含以下字段:

·

种用途:

·

·

·

·

·

kubernetes: 在这个示例中,定义了名为"kubernetes"的证书配置文件(profile)。

usages: 这个字段指定了该配置文件所生成证书的用途。在这里,设置了四

"signing": 表示生成的证书可用于签名其他证书,即作为 CA 证书。

"key encipherment": 表示生成的证书可用于密钥加密。"server auth": 表示生成的证书可用于服务器身份验证。"client auth": 表示生成的证书可用于客户端身份验证。

expiry: 它指定了该配置文件所生成证书的有效期。在这个示例中,设置为

"87600h",表示使用该配置文件生成的证书的有效期为 87600 小时(约合 10 年)。

16.3.4 生成 etcd 证书

#配置 etcd 证书请求,hosts 的 ip 变成自己 etcd 所在节点的 ip [root@xuegod60 work]# vim etcd-csr.json

{

"CN": "etcd", "hosts": [

"127.0.0.1",

"192.168.40.60",

"192.168.40.61",

"192.168.40.62",

"192.168.40.199"

imgimgimgimgimgimgimg],

"key": {

"algo": "rsa", "size": 2048

},

"names": [{

"C": "CN",

"ST": "Hubei",

"L": "Wuhan",

"O": "k8s",

"OU": "system"

}]

}

img备注:

文本框: 上述内容是一个用于生成 etcd 集群证书签名请求(CSR)的配置文件。让我们逐个解释每个字段的含义:

1. CN (Common Name) : 这是证书的通用名称,用于标识证书持有者的名称。在这个示例中,
CN 被设置为"etcd",意味着生成的证书将用于 etcd 集群。 2.hosts: 这是一个包含 etcd 节点的主机列表。生成的证书将允许这些主机使用该证书进行身份验 证和安全通信。在这个示例中,列出了五个主机: · "127.0.0.1": 本地回环地址,可能是用于单节点测试。 · "192.168.40.60": etcd 节点 1 的 IP 地址。 · "192.168.40.61": etcd 节点 2 的 IP 地址。 · "192.168.40.62": etcd 节点 3 的 IP 地址。 · "192.168.40.199": etcd 代理节点的 IP 地址。 3. key: 这个字段用于指定生成密钥的配置。在这里,使用 RSA 算法生成密钥,其大小为 2048 位。 4. names: 这是一个包含有关证书主题(Subject)的信息的数组。主题信息描述了证书持有者的身份。在这个示例中,证书的主题包含以下字段: · C (Country): 国家,设置为"CN"表示中国。 · ST (State): 省份或州,设置为"Hubei"表示湖北省。 · L (Locality): 城市或地区,设置为"Wuhan"表示武汉市。 · O (Organization): 组织名称,设置为"k8s"表示 Kubernetes。 · OU (Organizational Unit): 组织单元,设置为"system"表示系统级别。

文本框: 综上所述,该配置文件指定了生成用于 etcd 集群的证书签名请求。这些证书将用于对 etcd 节点进行身份验证和安全通信,确保 etcd 集群的安全运行。主机列表中列出的 IP 地址将获得使用这些证书的权限。证书的主题信息包含有关 etcd 集群所属组织和位置的信息。

[root@xuegod60 work]# cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca- config.json -profile=kubernetes etcd-csr.json | cfssljson -bare etcd

创建 etcd 的 CA 证书:这里需要 4 个文件

1、etcd-csr.json:etcd 的证书配置

2、ca.pem:基础公钥

3、ca-key.pem:基础私钥

4、ca-config.json:配置文件,如过期时间

[root@xuegod60 work]# ls etcd*.pem etcd-key.pem etcd.pem

执行后会生成三个文件:

1、etcd.csr 2、etcd.pem

3、etcd-key.pem

在一台机器上做证书生成,生成后将这三个文件拷贝到其他几台机器。

16.3.5 部署 etcd 集群

把 etcd-v3.4.13-linux-amd64.tar.gz 上传到/data/work 目录下

[root@xuegod60 work]# pwd

/data/work

[root@xuegod60 work]# tar -xf etcd-v3.4.13-linux-amd64.tar.gz [root@xuegod60 work]# cp -ar etcd-v3.4.13-linux-amd64/etcd /usr/local/bin/ [root@xuegod60 work]# chmod +x /usr/local/bin/etcd

[root@xuegod60 work]# scp -r etcd-v3.4.13-linux-amd64/etcd xuegod61:/usr/local/bin/ [root@xuegod61]# chmod +x /usr/local/bin/etcd

[root@xuegod60 work]# scp -r etcd-v3.4.13-linux-amd64/etcd xuegod62:/usr/local/bin/ [root@xuegod62]# chmod +x /usr/local/bin/etcd

#创建配置文件

[root@xuegod60 work]# vim etcd.conf #[Member]

ETCD_NAME="etcd1"

ETCD_DATA_DIR="/var/lib/etcd/default.etcd" ETCD_LISTEN_PEER_URLS="https://192.168.40.60:2380" ETCD_LISTEN_CLIENT_URLS="https://192.168.40.60:2379,http://127.0.0.1:2379"

#[Clustering] ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.40.60:2380" ETCD_ADVERTISE_CLIENT_URLS="https://192.168.40.60:2379"

ETCD_INITIAL_CLUSTER="etcd1=https://192.168.40.60:2380,etcd2=https://192.168.40.61:2 380,etcd3=https://192.168.40.62:2380"

ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster" ETCD_INITIAL_CLUSTER_STATE="new"

#备注,上述配置解释说明:

1. imgETCD_NAME: 这是 etcd 节点的名称。在这个示例中,节点名称被设置为"etcd1"

2. ETCD_DATA_DIR: 这是 etcd 节点数据的存储目录路径。在这个示例中,etcd 数据将存储在

"/var/lib/etcd/default.etcd"目录中。

3. ETCD_LISTEN_PEER_URLS: 这是 etcd 节点监听对等节点连接的 URL 地址。在这个示例中,

etcd 节点将使用"https://192.168.40.60:2380"作为对等节点监听地址。

4. ETCD_LISTEN_CLIENT_URLS: 这是 etcd 节点监听客户端连接的 URL 地址。在这个示例中,

etcd 节点将使用"https://192.168.40.60:2379"和"http://127.0.0.1:2379"作为客户端监听地址。

5. ETCD_INITIAL_ADVERTISE_PEER_URLS: 这是 etcd 节点在集群初始化时用于通告自己的对等

节点监听地址。在这个示例中,etcd 节点将使用"https://192.168.40.60:2380"作为初始对等节点通

告地址。

6. ETCD_ADVERTISE_CLIENT_URLS: 这是 etcd 节点在集群初始化时用于通告自己的客户端监听

地址。在这个示例中,etcd 节点将使用"https://192.168.40.60:2379"作为初始客户端通告地址。

7. ETCD_INITIAL_CLUSTER: 这是 etcd 集群初始化时指定的所有成员节点和对应的对等节点监听

地址。每个成员节点的格式为"名称=对等节点监听地址",多个成员节点之间用逗号分隔。在这个示例 中,etcd 集群有 3 个成员节点,分别是"etcd1"、"etcd2"和"etcd3",对应的对等节点监听地址分别是

"https://192.168.40.60:2380"、"https://192.168.40.61:2380"和

"https://192.168.40.62:2380"。

8. ETCD_INITIAL_CLUSTER_TOKEN: 这是 etcd 集群初始化时使用的令牌,用于确保只有相同令

牌的节点才能组成一个集群。在这个示例中,集群初始化令牌被设置为"etcd-cluster"。

9. ETCD_INITIAL_CLUSTER_STATE: 这是 etcd 集群初始化时的状态。在这个示例中,集群初始化状态被设置为"new",表示一个新的集群。
综上所述,该配置文件包含了 etcd 集群的相关设置,包括节点名称、数据目录、监听地址、成员节点信息以及集群初始化相关的配置。这些设置将确保 etcd 集群能够正常运行和通信,形成一个安全可靠的分 布式存储系统。

img#创建启动服务文件

[root@xuegod60 work]# vim etcd.service [Unit]

Description=Etcd Server After=network.target After=network-online.target Wants=network-online.target

[Service] Type=notify

EnvironmentFile=-/etc/etcd/etcd.conf WorkingDirectory=/var/lib/etcd/ ExecStart=/usr/local/bin/etcd \

--cert-file=/etc/etcd/ssl/etcd.pem \

--key-file=/etc/etcd/ssl/etcd-key.pem \

--trusted-ca-file=/etc/etcd/ssl/ca.pem \

--peer-cert-file=/etc/etcd/ssl/etcd.pem \

--peer-key-file=/etc/etcd/ssl/etcd-key.pem \

--peer-trusted-ca-file=/etc/etcd/ssl/ca.pem \

--peer-client-cert-auth \

--client-cert-auth Restart=on-failure RestartSec=5 LimitNOFILE=65536

[Install]

WantedBy=multi-user.target

[root@xuegod60]#yum install rsync -y [root@xuegod61]#yum install rsync -y [root@xuegod62]#yum install rsync -y [root@xuegod63]#yum install rsync -y

[root@xuegod60 work]# cp ca.pem /etc/etcd/ssl/ [root@xuegod60 work]# cp etcd.pem /etc/etcd/ssl/ [root@xuegod60 work]# cp etcd.conf /etc/etcd/

[root@xuegod60 work]# cp etcd.service /usr/lib/systemd/system/

[root@xuegod60 work]# for i in xuegod61 ;do rsync -vaz etcd.conf $i:/etc/etcd/;done [root@xuegod60 work]# for i in xuegod61 ;do rsync -vaz etcd.pem ca.pem

$i:/etc/etcd/ssl/;done

[root@xuegod60 work]# for i in xuegod61;do rsync -vaz etcd.service

$i:/usr/lib/systemd/system/;done

[root@xuegod60 work]# for i in xuegod62 ;do rsync -vaz etcd.conf $i:/etc/etcd/;done [root@xuegod60 work]# for i in xuegod62 ;do rsync -vaz etcd.pem ca.pem

$i:/etc/etcd/ssl/;done

[root@xuegod60 work]# for i in xuegod62;do rsync -vaz etcd.service

$i:/usr/lib/systemd/system/;done

#启动 etcd 集群

[root@xuegod60 work]# mkdir -p /var/lib/etcd/default.etcd [root@xuegod61 work]# mkdir -p /var/lib/etcd/default.etcd [root@xuegod62work]# mkdir -p /var/lib/etcd/default.etcd

[root@xuegod61 ~]# vim /etc/etcd/etcd.conf #[Member]

ETCD_NAME="etcd2"

ETCD_DATA_DIR="/var/lib/etcd/default.etcd" ETCD_LISTEN_PEER_URLS="https://192.168.40.61:2380" ETCD_LISTEN_CLIENT_URLS="https://192.168.40.61:2379,http://127.0.0.1:2379"

#[Clustering] ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.40.61:2380" ETCD_ADVERTISE_CLIENT_URLS="https://192.168.40.61:2379"

ETCD_INITIAL_CLUSTER="etcd1=https://192.168.40.60:2380,etcd2=https://192.168.40.61:2 380,etcd3=https://192.168.40.62:2380"

ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster" ETCD_INITIAL_CLUSTER_STATE="new"

[root@xuegod62 ~]# vim /etc/etcd/etcd.conf #[Member]

ETCD_NAME="etcd3"

ETCD_DATA_DIR="/var/lib/etcd/default.etcd" ETCD_LISTEN_PEER_URLS="https://192.168.40.62:2380" ETCD_LISTEN_CLIENT_URLS="https://192.168.40.62:2379,http://127.0.0.1:2379"

#[Clustering] ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.40.62:2380" ETCD_ADVERTISE_CLIENT_URLS="https://192.168.40.62:2379"

ETCD_INITIAL_CLUSTER="etcd1=https://192.168.40.60:2380,etcd2=https://192.168.40.61:2 380,etcd3=https://192.168.40.62:2380"

ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster" ETCD_INITIAL_CLUSTER_STATE="new"

[root@xuegod60 work]# systemctl daemon-reload [root@xuegod60 work]# systemctl enable etcd.service [root@xuegod60 work]# systemctl start etcd.service

[root@xuegod61 work]# systemctl daemon-reload [root@xuegod61 work]# systemctl enable etcd.service [root@xuegod61 work]# systemctl start etcd.service

[root@xuegod62 work]# systemctl daemon-reload [root@xuegod62 work]# systemctl enable etcd.service [root@xuegod62 work]# systemctl start etcd.service

启动 etcd 的时候,先启动 xuegod60 的 etcd 服务,会一直卡住在启动的状态,然后接着再启动

xuegod61 和 xuegod62 的etcd,这样 xuegod60 这个节点 etcd 才会正常起来

[root@xuegod60]# systemctl status etcd [root@xuegod61]# systemctl status etcd [root@xuegod62]# systemctl status etcd

img

#查看 etcd 集群状态

[root@xuegod60 work]# /usr/local/bin/etcdctl --write-out=table -- cacert=/etc/etcd/ssl/ca.pem --cert=/etc/etcd/ssl/etcd.pem --key=/etc/etcd/ssl/etcd- key.pem -- endpoints=https://192.168.40.60:2379,https://192.168.40.61:2379,https://192.168.40.62:23 79 endpoint status --cluster

img

显示如下:

16.4 安装 kubernetes 组件

16.4.1 下载安装包

二进制包所在的 github 地址如下:

https://github.com/kubernetes/kubernetes

#把 kubernetes-server-linux-amd64.tar.gz 上传到 xuegod60 上的/data/work 目录下: [root@xuegod60 work]# tar zxvf kubernetes-server-linux-amd64.tar.gz [root@xuegod60 work]# cd kubernetes/server/bin/

[root@xuegod60 bin]# cp kube-apiserver kube-controller-manager kube-scheduler kubectl

/usr/local/bin/

[root@xuegod60 bin]# rsync -vaz kube-apiserver kube-controller-manager kube-scheduler kubectl xuegod61:/usr/local/bin/

[root@xuegod60 bin]# rsync -vaz kube-apiserver kube-controller-manager kube-scheduler kubectl xuegod62:/usr/local/bin/

[root@xuegod60 bin]# scp kubelet kube-proxy xuegod63:/usr/local/bin/ [root@xuegod60 bin]# cd /data/work/

[root@xuegod60 work]# mkdir -p /etc/kubernetes/ [root@xuegod60 work]# mkdir -p /etc/kubernetes/ssl [root@xuegod60 work]# mkdir /var/log/kubernetes

16.4.2 部署 apiserver 组件

#创建 token.csv 文件

[root@xuegod60 ~]# cd /data/work/ [root@xuegod60 work]# cat > token.csv << EOF

$(head -c 16 /dev/urandom | od -An -t x | tr -d ' '),kubelet- bootstrap,10001,"system:kubelet-bootstrap"

EOF

备注:

img

img

#创建 csr 请求文件,替换为自己机器的 IP [root@xuegod60 work]# vim kube-apiserver-csr.json

{

"CN": "kubernetes", "hosts": [

"127.0.0.1",

"192.168.40.60",

"192.168.40.61",

"192.168.40.62",

"192.168.40.63",

"192.168.40.199",

"10.96.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",

"ST": "Hubei",

"L": "Wuhan",

"O": "k8s",

"OU": "system"

}

]

}

#备注:

文本框: 上述配置文件是一个用于生成 Kubernetes 相关证书签名请求(CSR)的示例配置。让我们逐个解释每个字段的含义:

imgimgimgimgimgimg

1. CN (Common Name) : 这是证书的通用名称,用于标识证书持有者的名称。在这个示例中,
CN 被设置为"kubernetes",意味着生成的证书将与 Kubernetes 相关。 2.hosts: 这是一个包含证书主题中"Subject Alternative Name"字段的列表。这个字段用于指定证书可以用于验证的主机或域名。在这个示例中,列出了多个主机或 IP 地址,包括: · "127.0.0.1": 本地回环地址,可能是用于单节点测试。 · "192.168.40.60": Kubernetes 节点 1 的 IP 地址。 · "192.168.40.61": Kubernetes 节点 2 的 IP 地址。 · "192.168.40.62": Kubernetes 节点 3 的 IP 地址。 · "192.168.40.63": Kubernetes 节点 4 的 IP 地址。 · "192.168.40.199": Kubernetes 代理节点的 IP 地址。 · "10.96.0.1": Kubernetes Service Cluster IP 地址,通常是 kube-apiserver 的 Cluster IP。 · "kubernetes": Kubernetes 集群的域名。 · "kubernetes.default": Kubernetes 默认命名空间的域名。 · "kubernetes.default.svc": Kubernetes 默认命名空间的 Service 的域名。 · "kubernetes.default.svc.cluster": Kubernetes 默认命名空间的 Service Cluster 域名。 · "kubernetes.default.svc.cluster.local": Kubernetes 默认命名空间的 Service Cluster Local 域名。 3. key: 这个字段用于指定生成密钥的配置。在这里,使用 RSA 算法生成密钥,其大小为 2048 位。 4. names: 这是一个包含有关证书主题(Subject)的信息的数组。主题信息描述了证书持有者的身份。在这个示例中,证书的主题包含以下字段: · C (Country): 国家,设置为"CN"表示中国。 · ST (State): 省份或州,设置为"Hubei"表示湖北省。 · L (Locality): 城市或地区,设置为"Wuhan"表示武汉市。 · O (Organization): 组织名称,设置为"k8s"表示 Kubernetes。 · OU (Organizational Unit): 组织单元,设置为"system"表示系统级别。

imgimg#生成证书

[root@xuegod60 work]# cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca- config.json -profile=kubernetes kube-apiserver-csr.json | cfssljson -bare kube-apiserver

#创建 api-server 的配置文件,替换成自己的 ip [root@xuegod60 work]# vim kube-apiserver.conf KUBE_APISERVER_OPTS="--enable-admission-

plugins=NamespaceLifecycle,NodeRestriction,LimitRanger,ServiceAccount,DefaultStorageC lass,ResourceQuota \

--anonymous-auth=false \

--bind-address=192.168.40.60 \

--secure-port=6443 \

--advertise-address=192.168.40.60 \

--authorization-mode=Node,RBAC \

--runtime-config=api/all=true \

--enable-bootstrap-token-auth \

--service-cluster-ip-range=10.96.0.0/12 \

--token-auth-file=/etc/kubernetes/token.csv \

--service-node-port-range=30000-50000 \

--tls-cert-file=/etc/kubernetes/ssl/kube-apiserver.pem \

--tls-private-key-file=/etc/kubernetes/ssl/kube-apiserver-key.pem \

--client-ca-file=/etc/kubernetes/ssl/ca.pem \

--kubelet-client-certificate=/etc/kubernetes/ssl/kube-apiserver.pem \

--kubelet-client-key=/etc/kubernetes/ssl/kube-apiserver-key.pem \

--service-account-key-file=/etc/kubernetes/ssl/ca-key.pem \

--service-account-signing-key-file=/etc/kubernetes/ssl/ca-key.pem \

--service-account-issuer=https://kubernetes.default.svc.cluster.local \

--etcd-cafile=/etc/etcd/ssl/ca.pem \

--etcd-certfile=/etc/etcd/ssl/etcd.pem \

--etcd-keyfile=/etc/etcd/ssl/etcd-key.pem \

--etcd- servers=https://192.168.40.60:2379,https://192.168.40.61:2379,https://192.168.40.62:2379

\

--allow-privileged=true \

--apiserver-count=3 \

--audit-log-maxage=30 \

--audit-log-maxbackup=3 \

--audit-log-maxsize=100 \

--audit-log-path=/var/log/kube-apiserver-audit.log \

--event-ttl=1h \

--alsologtostderr=true \

--logtostderr=false \

--log-dir=/var/log/kubernetes \

--v=4"

#注:

文本框: 上述配置是用于配置 Kubernetes API Server(kube-apiserver)的选项。这些选项设置了 kube- apiserver 的各种参数,让我们逐个解释每个选项的含义:

img

\1. --enable-admission-plugins: 这个选项用于启用一系列准入控制插件,用于对 API 请求进行

验证和修改。在这里,启用了多个准入控制插件,包括:NamespaceLifecycle、NodeRestriction、

LimitRanger、ServiceAccount、DefaultStorageClass 和 ResourceQuota。

\2. --anonymous-auth: 这个选项用于控制是否允许匿名用户访问 API Server。在这里,将匿名

认证禁用,设置为 false,即不允许匿名用户访问。

\3. --bind-address: 这个选项用于指定 API Server 监听的 IP 地址。在这里,设置为

192.168.40.60,即 API Server 将绑定在该 IP 地址上。

\4. --secure-port: 这个选项用于指定 API Server 监听的安全端口。在这里,设置为 6443,即

API Server 将监听在 6443 端口上。

\5. --advertise-address: 这个选项用于指定 API Server 广告自己的 IP 地址。在这里,设置为

192.168.40.60,即 API Server 将使用该地址作为自己的广告地址。

\6. --authorization-mode: 这个选项用于指定 API Server 的授权模式。在这里,启用了 Node

和 RBAC(Role-Based Access Control)两种授权模式。

\7. --runtime-config: 这个选项用于配置 API Server 的运行时配置。在这里,启用了所有的 API

组。

\8. --enable-bootstrap-token-auth: 这个选项用于启用 Bootstrap Token 认证机制,用于节点加入集群时的身份验证。

\9. --service-cluster-ip-range: 这个选项用于指定 Service Cluster IP 地址范围。在这里,设置

为 10.96.0.0/12。

\10. --token-auth-file: 这个选项用于指定 Token 认证文件的路径。在这里,设置为

/etc/kubernetes/token.csv,即 Token 认证的文件路径。

\11. --service-node-port-range: 这个选项用于指定 Service NodePort 端口范围。在这里,设置

30000-50000

\12. --tls-cert-file: 这个选项用于指定 kube-apiserver 的 TLS 证书文件路径。

\13. --tls-private-key-file: 这个选项用于指定 kube-apiserver 的 TLS 私钥文件路径。

img

#创建服务启动文件

[root@xuegod60 work]# vim kube-apiserver.service [Unit]

Description=Kubernetes API Server Documentation=https://github.com/kubernetes/kubernetes After=etcd.service

Wants=etcd.service

[Service]

EnvironmentFile=-/etc/kubernetes/kube-apiserver.conf ExecStart=/usr/local/bin/kube-apiserver $KUBE_APISERVER_OPTS Restart=on-failure

RestartSec=5 Type=notify LimitNOFILE=65536

[Install]

WantedBy=multi-user.target

[root@xuegod60 work]# cp ca.pem /etc/kubernetes/ssl [root@xuegod60 work]# cp kube-apiserver.pem /etc/kubernetes/ssl/ [root@xuegod60 work]# cp token.csv /etc/kubernetes/ [root@xuegod60 work]# cp kube-apiserver.conf /etc/kubernetes/

[root@xuegod60 work]# cp kube-apiserver.service /usr/lib/systemd/system/ [root@xuegod60 work]# rsync -vaz token.csv xuegod61:/etc/kubernetes/ [root@xuegod60 work]# rsync -vaz kube-apiserver.pem xuegod61:/etc/kubernetes/ssl/ [root@xuegod60 work]# rsync -vaz ca.pem xuegod61:/etc/kubernetes/ssl/ [root@xuegod60 work]# rsync -vaz kube-apiserver.conf xuegod61:/etc/kubernetes/ [root@xuegod60 work]# rsync -vaz kube-apiserver.service xuegod61:/usr/lib/systemd/system/

[root@xuegod60 work]# rsync -vaz token.csv xuegod62:/etc/kubernetes/ [root@xuegod60 work]# rsync -vaz kube-apiserver.pem xuegod62:/etc/kubernetes/ssl/ [root@xuegod60 work]# rsync -vaz ca.pem xuegod62:/etc/kubernetes/ssl/ [root@xuegod60 work]# rsync -vaz kube-apiserver.conf xuegod62:/etc/kubernetes/ [root@xuegod60 work]# rsync -vaz kube-apiserver.service xuegod62:/usr/lib/systemd/system/

注:xuegod61 配置文件 kube-apiserver.conf 的 IP 地址修改为实际的本机 IP [root@xuegod61 ~]# cat /etc/kubernetes/kube-apiserver.conf KUBE_APISERVER_OPTS="--enable-admission-

plugins=NamespaceLifecycle,NodeRestriction,LimitRanger,ServiceAccount,DefaultStorageC lass,ResourceQuota \

--anonymous-auth=false \

--bind-address=192.168.40.61 \

--secure-port=6443 \

--advertise-address=192.168.40.61 \

--authorization-mode=Node,RBAC \

--runtime-config=api/all=true \

--enable-bootstrap-token-auth \

--service-cluster-ip-range=10.96.0.0/12 \

--token-auth-file=/etc/kubernetes/token.csv \

--service-node-port-range=30000-50000 \

--tls-cert-file=/etc/kubernetes/ssl/kube-apiserver.pem \

--tls-private-key-file=/etc/kubernetes/ssl/kube-apiserver-key.pem \

--client-ca-file=/etc/kubernetes/ssl/ca.pem \

--kubelet-client-certificate=/etc/kubernetes/ssl/kube-apiserver.pem \

--kubelet-client-key=/etc/kubernetes/ssl/kube-apiserver-key.pem \

--service-account-key-file=/etc/kubernetes/ssl/ca-key.pem \

--service-account-signing-key-file=/etc/kubernetes/ssl/ca-key.pem \

--service-account-issuer=https://kubernetes.default.svc.cluster.local \

--etcd-cafile=/etc/etcd/ssl/ca.pem \

--etcd-certfile=/etc/etcd/ssl/etcd.pem \

--etcd-keyfile=/etc/etcd/ssl/etcd-key.pem \

--etcd- servers=https://192.168.40.60:2379,https://192.168.40.61:2379,https://192.168.40.62:2379

\

--allow-privileged=true \

--apiserver-count=3 \

--audit-log-maxage=30 \

--audit-log-maxbackup=3 \

--audit-log-maxsize=100 \

--audit-log-path=/var/log/kube-apiserver-audit.log \

--event-ttl=1h \

--alsologtostderr=true \

--logtostderr=false \

--log-dir=/var/log/kubernetes \

--v=4"

注:xuegod62 配置文件 kube-apiserver.conf 的 IP 地址修改为实际的本机 IP [root@xuegod62~]# cat /etc/kubernetes/kube-apiserver.conf KUBE_APISERVER_OPTS="--enable-admission-

plugins=NamespaceLifecycle,NodeRestriction,LimitRanger,ServiceAccount,DefaultStorageC lass,ResourceQuota \

--anonymous-auth=false \

--bind-address=192.168.40.62 \

--secure-port=6443 \

--advertise-address=192.168.40.62 \

--authorization-mode=Node,RBAC \

--runtime-config=api/all=true \

--enable-bootstrap-token-auth \

--service-cluster-ip-range=10.96.0.0/12 \

--token-auth-file=/etc/kubernetes/token.csv \

--service-node-port-range=30000-50000 \

--tls-cert-file=/etc/kubernetes/ssl/kube-apiserver.pem \

--tls-private-key-file=/etc/kubernetes/ssl/kube-apiserver-key.pem \

--client-ca-file=/etc/kubernetes/ssl/ca.pem \

--kubelet-client-certificate=/etc/kubernetes/ssl/kube-apiserver.pem \

--kubelet-client-key=/etc/kubernetes/ssl/kube-apiserver-key.pem \

--service-account-key-file=/etc/kubernetes/ssl/ca-key.pem \

--service-account-signing-key-file=/etc/kubernetes/ssl/ca-key.pem \

--service-account-issuer=https://kubernetes.default.svc.cluster.local \

--etcd-cafile=/etc/etcd/ssl/ca.pem \

--etcd-certfile=/etc/etcd/ssl/etcd.pem \

--etcd-keyfile=/etc/etcd/ssl/etcd-key.pem \

--etcd- servers=https://192.168.40.60:2379,https://192.168.40.61:2379,https://192.168.40.62:2379

\

--allow-privileged=true \

--apiserver-count=3 \

--audit-log-maxage=30 \

--audit-log-maxbackup=3 \

--audit-log-maxsize=100 \

--audit-log-path=/var/log/kube-apiserver-audit.log \

--event-ttl=1h \

--alsologtostderr=true \

--logtostderr=false \

--log-dir=/var/log/kubernetes \

--v=4"

[root@xuegod60 work]# systemctl daemon-reload [root@xuegod61]# systemctl daemon-reload [root@xuegod62]# systemctl daemon-reload

[root@xuegod60 work]# systemctl enable kube-apiserver [root@xuegod61]# systemctl enable kube-apiserver [root@xuegod62]# systemctl enable kube-apiserver

[root@xuegod60 work]# systemctl start kube-apiserver [root@xuegod61]# systemctl start kube-apiserver [root@xuegod62]# systemctl start kube-apiserver

[root@xuegod60 work]# systemctl status kube-apiserver Active: active (running) since Wed

[root@xuegod61]# systemctl status kube-apiserver Active: active (running) since Wed

[root@xuegod62]# systemctl status kube-apiserver

Active: active (running) since Wed

16.4.3 部署 kubectl 组件

Kubectl 是客户端工具,操作k8s 资源的,如增删改查等。

#创建 csr 请求文件

[root@xuegod60 work]# vim admin-csr.json

{

"CN": "admin",

"hosts": [], "key": {

"algo": "rsa", "size": 2048

},

"names": [

{

"C": "CN",

"ST": "Hubei",

"L": "Wuhan",

"O": "system:masters",

"OU": "system"

}

]

}

#说明:

img

#生成证书

[root@xuegod60 work]# cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca- config.json -profile=kubernetes admin-csr.json | cfssljson -bare admin [root@xuegod60 work]# cp admin*.pem /etc/kubernetes/ssl/

配置安全上下文

1. 设置集群参数

[root@xuegod60 work]# kubectl config set-cluster kubernetes --certificate- authority=ca.pem --embed-certs=true --server=https://192.168.40.60:6443 -- kubeconfig=kube.config

#查看 kube.config 内容

[root@xuegod60 work]# cat kube.config apiVersion: v1

clusters:

- cluster:

certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUR0akNDQXA2Z0F3SUJBZ0lVYnVjNUswe

VhVWmxDTzJMVjZhY3N2QlNFSjdvd0RRWUpLb1pJaHZjTkFRRUwKQlFBd1lURUxNQWtHQT FVRUJoTUNRMDR4RGpBTUJnTlZCQWdUQlVoMVltVnBNUTR3REFZRFZRUUhFd1ZYZFdoaAp iakVNTUFvR0ExVUVDaE1EYXpoek1ROHdEUVlEVlFRTEV3WnplWE4wWlcweEV6QVJCZ05WQ kFNVENtdDFZbVZ5CmJtVjBaWE13SGhjTk1qSXdPVEF6TVRFME5UQXdXaGNOTXpJd09ETXh NVEUwTlRBd1dqQmhNUXN3Q1FZRFZRUUcKRXdKRFRqRU9NQXdHQTFVRUNCTUZTSFZpW ldreERqQU1CZ05WQkFjVEJWZDFhR0Z1TVF3d0NnWURWUVFLRXdOcgpPSE14RHpBTkJnTl ZCQXNUQm5ONWMzUmxiVEVUTUJFR0ExVUVBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEU VlKCktvWklodmNOQVFFQkJRQURnZ0VQQURDQ0FRb0NnZ0VCQUx5TGJiSEJFWENsbUhwK 3A0UTREV053VjlFQTRHNDgKZGlUenJRZjdOaC9nTUl4ekZhcHVLYUlHRGxGNGVEV25MbXV

MZXJveGlNZGg1andaK0FUQmd2eXplRnQwZVRuTQphdWhNNGZrRE1aNmdkb2U5STVQUit wb0lMVmdodkxEd2tTOHlFZEtNcGpXcnl5cWpJMkNLNEVvM2F6MC9qVEN4Ck9aRGc2Qk1W Y3lVbDk1MkhrUnNaYmVGemdiTVA2c1plenBRa1MyRk5KWWpJVWtjUFN5THdGQmMxQkV pODhiQTcKbjkwOTdUQ1VISk9zdFVEcHd3VUMxNkZUV2EwZFNsbFJKYW8rUGN4L0lhcGw0V GVPZnYzUzBqVm5CbXVidlFzeApleGl1dEFLTC9sZm1YalVNb3pTYXMrdmpGcXZXd0tkVXh6Yl gvQ25TUzFGSUhTanZSUWpMVEc4Q0F3RUFBYU5tCk1HUXdEZ1lEVlIwUEFRSC9CQVFEQWdF R01CSUdBMVVkRXdFQi93UUlNQVlCQWY4Q0FRSXdIUVlEVlIwT0JCWUUKRkFPdXBRdmRw QWZxb0JNMkhKY3FlWU9mZ2xLRE1COEdBMVVkSXdRWU1CYUFGQU91cFF2ZHBBZnFvQk0 ySEpjcQplWU9mZ2xLRE1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQk9aL3BKY25qVzJEQ

VVuMFVWZ2VoekFyanhmLzVRCkJJNi9wdkl4ekNTeXlzeWVWL2d6QnV0MmsrL25lVEh3bnhX bzJCMzF2cTdWbFMyeklSSng0S2l3M3dzbFVrR08KRkR0SmZBRlF1OW5KZGZKOFJyRWk4Z2d EZVVIRGtsY3JwZEhXYmM1Y3BLUy81K1pHbFFPc0JCK21XSGdQQkJHYwpQai95VDQ0NmE3

OHlYU1IrRzVXWjQ5dG5kMDNqczEvbm1EcmZNUU1xUVhhUVpiUDB1Z3V3WmlJK2NFN3lR YUhGCkgwWGd6WXpDZDlzZVdrMEFYdHlLc09Ga3RjZ3NvN2lkWXZFSDNQa3llbC8vWjFndG hUS1NNSzRoa3BFYWVzVnAKN3ZnNmk0dE82MzJ1NGpBVDU3M21HYzgwcmdZMlJpaWhiR

lQzaXl3SlFNNVIzZGpCS2NueVlGNGUKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=

server: https://192.168.40.60:6443 name: kubernetes

contexts: null current-context: "" kind: Config preferences: {} users: null

2. 设置客户端认证参数

[root@xuegod60 work]# kubectl config set-credentials admin --client- certificate=admin.pem --client-key=admin-key.pem --embed-certs=true -- kubeconfig=kube.config

3. 设置上下文参数

[root@xuegod60 work]# kubectl config set-context kubernetes --cluster=kubernetes -- user=admin --kubeconfig=kube.config

4. 设置当前上下文

[root@xuegod60 work]# kubectl config use-context kubernetes --kubeconfig=kube.config [root@xuegod60 work]# mkdir ~/.kube -p

[root@xuegod60 work]# cp kube.config ~/.kube/config 5.授权 kubernetes 证书访问kubelet api 权限

[root@xuegod60 work]# kubectl create clusterrolebinding kube-apiserver:kubelet-apis -- clusterrole=system:kubelet-api-admin --user kubernetes

[root@xuegod60 work]# kubectl create clusterrolebinding aa --clusterrole=cluster-admin -

-user admin

#查看集群组件状态

[root@xuegod60 work]# kubectl cluster-info

Kubernetes control plane is running at https://192.168.40.60:6443

#同步 kubectl 文件到其他节点[root@xuegod61 ~]# mkdir /root/.kube/ [root@xuegod62 ~]# mkdir /root/.kube/

[root@xuegod60 work]# rsync -vaz /root/.kube/config xuegod61:/root/.kube/ [root@xuegod60 work]# rsync -vaz /root/.kube/config xuegod62:/root/.kube/

16.4.4 部署 kube-controller-manager 组件

#创建 csr 请求文件

[root@xuegod60 work]# vim kube-controller-manager-csr.json

{

"CN": "system:kube-controller-manager", "key": {

"algo": "rsa", "size": 2048

},

"hosts": [ "127.0.0.1",

"192.168.40.60",

"192.168.40.61",

"192.168.40.62",

"192.168.40.199"

],

"names": [

{

"C": "CN",

"ST": "Hubei",

"L": "Wuhan",

"O": "system:kube-controller-manager", "OU": "system"

}

]

}

注:

img

img

#生成证书

[root@xuegod60 work]# 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 的 kubeconfig 1.设置集群参数

[root@xuegod60 work]# kubectl config set-cluster kubernetes --certificate- authority=ca.pem --embed-certs=true --server=https://192.168.40.60:6443 -- kubeconfig=kube-controller-manager.kubeconfig

2. 设置客户端认证参数

[root@xuegod60 work]# kubectl config set-credentials system:kube-controller-manager -- client-certificate=kube-controller-manager.pem --client-key=kube-controller-manager- key.pem --embed-certs=true --kubeconfig=kube-controller-manager.kubeconfig

3. 设置上下文参数

[root@xuegod60 work]# kubectl config set-context system:kube-controller-manager -- cluster=kubernetes --user=system:kube-controller-manager --kubeconfig=kube- controller-manager.kubeconfig

4. 设置当前上下文

[root@xuegod60 work]# kubectl config use-context system:kube-controller-manager -- kubeconfig=kube-controller-manager.kubeconfig

#创建配置文件 kube-controller-manager.conf [root@xuegod60 work]# vim kube-controller-manager.conf KUBE_CONTROLLER_MANAGER_OPTS=" \

--secure-port=10257 \

--bind-address=127.0.0.1 \

--kubeconfig=/etc/kubernetes/kube-controller-manager.kubeconfig \

--service-cluster-ip-range=10.96.0.0/12 \

--cluster-name=kubernetes \

--cluster-signing-cert-file=/etc/kubernetes/ssl/ca.pem \

--cluster-signing-key-file=/etc/kubernetes/ssl/ca-key.pem \

--allocate-node-cidrs=true \

--cluster-cidr=10.244.0.0/16 \

--root-ca-file=/etc/kubernetes/ssl/ca.pem \

--service-account-private-key-file=/etc/kubernetes/ssl/ca-key.pem \

--leader-elect=true \

--feature-gates=RotateKubeletServerCertificate=true \

--controllers=*,bootstrapsigner,tokencleaner \

--horizontal-pod-autoscaler-sync-period=10s \

--tls-cert-file=/etc/kubernetes/ssl/kube-controller-manager.pem \

--tls-private-key-file=/etc/kubernetes/ssl/kube-controller-manager-key.pem \

--use-service-account-credentials=true \

--alsologtostderr=true \

--logtostderr=false \

--v=2"

备注:

文本框: 该配置文件是用于配置 Kubernetes 中 kube-controller-manager 组件的启动参数。kube- controller-manager 是 Kubernetes 控制平面中的一个核心组件,负责运行多个控制器,以确保集群的自愈性和自动化功能。 以下是对这些配置参数的解释说明:

· --secure-port=10257 : 指定 kube-controller-manager 组件监听的安全端口号,用于与其
他组件通信的安全端口。 ·--bind-address=127.0.0.1: 指定 kube-controller-manager 组件绑定的 IP 地址,这里是绑定到本地回环地址,即只能在本地访问。 · --kubeconfig=/etc/kubernetes/kube-controller-manager.kubeconfig: 指定 kube- controller-manager 使用的 kubeconfig 文件路径,用于配置认证和访问控制。 · --service-cluster-ip-range=10.96.0.0/12: 指定服务的 ClusterIP 范围,这些 IP 地址用于集群内部服务之间的通信。 · --cluster-name=kubernetes: 指定集群的名称。 · --cluster-signing-cert-file=/etc/kubernetes/ssl/ca.pem: 指定集群签名证书的路径,用于签署其他证书。 · --cluster-signing-key-file=/etc/kubernetes/ssl/ca-key.pem: 指定集群签名证书的私钥路径。 · --allocate-node-cidrs=true: 允许 kube-controller-manager 为节点分配 CIDR 网段。 · --cluster-cidr=10.244.0.0/16: 指定集群使用的 Pod 网络的 CIDR 网段。

img

#创建启动文件

[root@xuegod60 work]# vim kube-controller-manager.service [Unit]

Description=Kubernetes Controller Manager Documentation=https://github.com/kubernetes/kubernetes [Service]

EnvironmentFile=-/etc/kubernetes/kube-controller-manager.conf ExecStart=/usr/local/bin/kube-controller-manager $KUBE_CONTROLLER_MANAGER_OPTS Restart=on-failure

RestartSec=5 [Install]

WantedBy=multi-user.target

#启动服务

[root@xuegod60 work]# cp kube-controller-manager.pem /etc/kubernetes/ssl/ [root@xuegod60 work]# cp kube-controller-manager.kubeconfig /etc/kubernetes/ [root@xuegod60 work]# cp kube-controller-manager.conf /etc/kubernetes/ [root@xuegod60 work]# cp kube-controller-manager.service /usr/lib/systemd/system/ [root@xuegod60 work]# rsync -vaz kube-controller-manager.pem xuegod61:/etc/kubernetes/ssl/

[root@xuegod60 work]# rsync -vaz kube-controller-manager.kubeconfig kube-controller- manager.conf xuegod61:/etc/kubernetes/

[root@xuegod60 work]# rsync -vaz kube-controller-manager.service xuegod61:/usr/lib/systemd/system/

[root@xuegod60 work]# rsync -vaz kube-controller-manager*.pem xuegod62:/etc/kubernetes/ssl/

[root@xuegod60 work]# rsync -vaz kube-controller-manager.kubeconfig kube-controller- manager.conf xuegod62:/etc/kubernetes/

[root@xuegod60 work]# rsync -vaz kube-controller-manager.service xuegod62:/usr/lib/systemd/system/

[root@xuegod60 work]# systemctl daemon-reload [root@xuegod60 work]# systemctl enable kube-controller-manager [root@xuegod60 work]# systemctl start kube-controller-manager [root@xuegod60 work]# systemctl status kube-controller-manager

Active: active (running) since

[root@xuegod61]# systemctl daemon-reload [root@xuegod61]# systemctl enable kube-controller-manager [root@xuegod61]# systemctl start kube-controller-manager [root@xuegod61]# systemctl status kube-controller-manager

Active: active (running) since

[root@xuegod62]# systemctl daemon-reload [root@xuegod62]# systemctl enable kube-controller-manager [root@xuegod62]# systemctl start kube-controller-manager [root@xuegod62]# systemctl status kube-controller-manager

Active: active (running) since

16.4.5 部署 kube-scheduler 组件

#创建 csr 请求

[root@xuegod60 work]# vim kube-scheduler-csr.json

{

"CN": "system:kube-scheduler",

"hosts": [ "127.0.0.1",

"192.168.40.60",

"192.168.40.61",

"192.168.40.62",

"192.168.40.199"

],

"key": {

"algo": "rsa", "size": 2048

},

"names": [

{

"C": "CN",

"ST": "Hubei",

"L": "Wuhan",

"O": "system:kube-scheduler", "OU": "system"

}

]

}

注: hosts 列表包含所有 kube-scheduler 节点 IP; CN 为 system:kube-scheduler、O 为system:kube-scheduler,kubernetes 内置的 ClusterRoleBindings system:kube-scheduler 将赋予 kube-scheduler 工作所需的权限。

#生成证书

[root@xuegod60 work]# 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 的 kubeconfig 1.设置集群参数

[root@xuegod60 work]# kubectl config set-cluster kubernetes --certificate- authority=ca.pem --embed-certs=true --server=https://192.168.40.60:6443 -- kubeconfig=kube-scheduler.kubeconfig

2. 设置客户端认证参数

[root@xuegod60 work]# kubectl config set-credentials system:kube-scheduler --client- certificate=kube-scheduler.pem --client-key=kube-scheduler-key.pem --embed-certs=true

--kubeconfig=kube-scheduler.kubeconfig

3. 设置上下文参数

[root@xuegod60 work]# kubectl config set-context system:kube-scheduler -- cluster=kubernetes --user=system:kube-scheduler --kubeconfig=kube-

scheduler.kubeconfig

4. 设置当前上下文

[root@xuegod60 work]# kubectl config use-context system:kube-scheduler -- kubeconfig=kube-scheduler.kubeconfig

#创建配置文件 kube-scheduler.conf [root@xuegod60 work]# vim kube-scheduler.conf

KUBE_SCHEDULER_OPTS="--bind-address=127.0.0.1 \

--kubeconfig=/etc/kubernetes/kube-scheduler.kubeconfig \

--leader-elect=true \

--alsologtostderr=true \

--logtostderr=false \

--log-dir=/var/log/kubernetes \

--v=2"

#创建服务启动文件

[root@xuegod60 work]# vim kube-scheduler.service [Unit]

Description=Kubernetes Scheduler Documentation=https://github.com/kubernetes/kubernetes

[Service]

EnvironmentFile=-/etc/kubernetes/kube-scheduler.conf ExecStart=/usr/local/bin/kube-scheduler $KUBE_SCHEDULER_OPTS Restart=on-failure

RestartSec=5

[Install]

WantedBy=multi-user.target

#启动服务

[root@xuegod60 work]# cp kube-scheduler*.pem /etc/kubernetes/ssl/ [root@xuegod60 work]# cp kube-scheduler.kubeconfig /etc/kubernetes/ [root@xuegod60 work]# cp kube-scheduler.conf /etc/kubernetes/ [root@xuegod60 work]# cp kube-scheduler.service /usr/lib/systemd/system/

[root@xuegod60 work]# rsync -vaz kube-scheduler*.pem xuegod61:/etc/kubernetes/ssl/ [root@xuegod60 work]# rsync -vaz kube-scheduler.kubeconfig kube-scheduler.conf xuegod61:/etc/kubernetes/

[root@xuegod60 work]# rsync -vaz kube-scheduler.service xuegod61:/usr/lib/systemd/system/

[root@xuegod60 work]# rsync -vaz kube-scheduler*.pem xuegod62:/etc/kubernetes/ssl/ [root@xuegod60 work]# rsync -vaz kube-scheduler.kubeconfig kube-scheduler.conf

xuegod62:/etc/kubernetes/

[root@xuegod60 work]# rsync -vaz kube-scheduler.service xuegod62:/usr/lib/systemd/system/

[root@xuegod60 work]# systemctl daemon-reload [root@xuegod60 work]# systemctl enable kube-scheduler [root@xuegod60 work]# systemctl start kube-scheduler [root@xuegod60 work]# systemctl status kube-scheduler

kube-scheduler.service - Kubernetes Scheduler Active: active (running) since Wed

[root@xuegod61]# systemctl daemon-reload [root@xuegod61]# systemctl enable kube-scheduler [root@xuegod61]# systemctl start kube-scheduler [root@xuegod61]# systemctl status kube-scheduler

kube-scheduler.service - Kubernetes Scheduler Active: active (running) since Wed

[root@xuegod62]# systemctl daemon-reload [root@xuegod62]# systemctl enable kube-scheduler [root@xuegod62]# systemctl start kube-scheduler [root@xuegod62]# systemctl status kube-scheduler

kube-scheduler.service - Kubernetes Scheduler Active: active (running) since Wed

16.4.6 导入离线镜像压缩包

#把 pause-cordns.tar.gz 上传到 xuegod63 节点,手动解压[root@xuegod63 ~]# docker load -i pause-cordns.tar.gz [root@xuegod63 ~]# ctr -n=k8s.io images import pause-cordns.tar.gz

16.4.7 部署 kubelet 组件

#启动 TLS Bootstrapping 机制

Master apiserver 启用 TLS 认证后,每个节点的 kubelet 组件都要使用由 apiserver 使用的 CA 签发的有效证书才能与 apiserver 通讯,当 Node 节点很多时,这种客户端证书颁发需要大量工作,同样也会增加集群扩展复杂度。

为了简化流程,Kubernetes 引入了 TLS bootstraping 机制来自动颁发客户端证书,kubelet 会以一个低权限用户自动向 apiserver 申请证书,kubelet 的证书由 apiserver 动态签署。

Bootstrap 是很多系统中都存在的程序,比如 Linux 的 bootstrap,bootstrap 一般都是作为预先配

置在开启或者系统启动的时候加载,这可以用来生成一个指定环境。Kubernetes 的 kubelet 在启动时同样可以加载一个这样的配置文件,这个文件的内容类似如下形式:

apiVersion: v1 clusters: null contexts:

- context:

cluster: kubernetes user: kubelet-bootstrap

name: default

current-context: default kind: Config preferences: {}

users:

- name: kubelet-bootstrap user: {}

#TLS bootstrapping 具体引导过程

1. TLS 作用

TLS 的作用就是对通讯加密,防止中间人窃听;同时如果证书不信任的话根本就无法与 apiserver 建立连接,更不用提有没有权限向 apiserver 请求指定内容。

2. RBAC 作用

当 TLS 解决了通讯问题后,那么权限问题就应由 RBAC 解决(可以使用其他权限模型,如 ABAC); RBAC 中规定了一个用户或者用户组(subject)具有请求哪些 api 的权限;在配合 TLS 加密的时候,实际上 apiserver 读取客户端证书的 CN 字段作为用户名,读取 O 字段作为用户组.

以上说明:第一,想要与 apiserver 通讯就必须采用由 apiserver CA 签发的证书,这样才能形成信任关系,建立 TLS 连接;第二,可以通过证书的 CN、O 字段来提供 RBAC 所需的用户与用户组。

#kubelet 首次启动流程

TLS bootstrapping 功能是让 kubelet 组件去 apiserver 申请证书,然后用于连接 apiserver;那么第一次启动时没有证书如何连接 apiserver ?

在 apiserver 配置中指定了一个 token.csv 文件,该文件中是一个预设的用户配置;同时该用户的Token 和 由 apiserver 的 CA 签发的用户被写入了 kubelet 所使用的 bootstrap.kubeconfig 配置文件中;这样在首次请求时,kubelet 使用 bootstrap.kubeconfig 中被 apiserver CA 签发证书时信任的用户来与 apiserver 建立 TLS 通讯,使用 bootstrap.kubeconfig 中的用户 Token 来向apiserver 声明自己的 RBAC 授权身份.

token.csv 格式:

3940fd7fbb391d1b4d861ad17a1f0613,kubelet-bootstrap,10001,"system:kubelet- bootstrap"

首次启动时,可能与遇到 kubelet 报 401 无权访问 apiserver 的错误;这是因为在默认情况下,

kubelet 通过 bootstrap.kubeconfig 中的预设用户 Token 声明了自己的身份,然后创建 CSR 请

求;但是不要忘记这个用户在我们不处理的情况下他没任何权限的,包括创建 CSR 请求;所以需要创建一个 ClusterRoleBinding,将预设用户 kubelet-bootstrap 与内置的 ClusterRole system:node- bootstrapper 绑定到一起,使其能够发起 CSR 请求。稍后安装 kubelet 的时候演示。

kubelet: 每个 Node 节点上的 kubelet 定期就会调用 API Server 的 REST 接口报告自身状态,API Server 接收这些信息后,将节点状态信息更新到 etcd 中。kubelet 也通过 API Server 监听 Pod 信息,从而对 Node 机器上的 POD 进行管理,如创建、删除、更新 Pod

kubelet 启动时实际需要指定两个配置⽂件

--kubeconfig 指定的是 kube-config ⽂件,其中内置了集群根 CA 公钥以及⾃⼰作为客户端的公钥和私钥

--config 指定的是 kubelet 的配置

kubelet 组件在⼯作时,采⽤主动的查询机制,即定期请求 apiserver 获取⾃⼰所应当处理的任务,如哪些 pod 分配到了⾃⼰⾝上,从⽽去处理这些任务;同时 kubelet ⾃⼰还会暴露出两个本⾝api 的端

⼝,⽤于将⾃⼰本⾝的私有 api 暴露出去,这两个端⼝分别是该配置⽂件中指定的 10250 与 10255。对于 10250 端⼝,kubelet 会在其上采⽤TLS 加密以提供适当的鉴权功能;对于 10255 端⼝, kubelet 会以只读形式暴露组件本⾝的私有 api ,并且不做鉴权处理。

因此,kubelet 上实际上有两个地⽅⽤到证书,⼀个是⽤于与 API server 通讯所⽤到的证书,另⼀个是该配置⽂件中设置的 kubelet 的 10250 私有 api 端⼝需要⽤到的证书。

(3)签发⽤户的证书

①⾸先开发⼈员需⽤通过 OpenSSL 等证书⼯具⽣成私钥

②创建对应的 x509 csr 请求⽂件(需要在 subj 字段中指定 user 和 group )

③Kubernetes 集群本⾝就提供了证书签发的 API certificates.k8s.io/v1beta1。调⽤后,api-server

会根据请求,以 csr 资源对象的形式创建对应的签发请求。

安装和配置 kubelet,步骤如下: 以下操作在 xuegod60 上操作

创建 kubelet-bootstrap.kubeconfig [root@xuegod60 work]# cd /data/work/

[root@xuegod60 work]# BOOTSTRAP_TOKEN=$(awk -F "," '{print $1}'

/etc/kubernetes/token.csv)

[root@xuegod60 work]# kubectl config set-cluster kubernetes --certificate- authority=ca.pem --embed-certs=true --server=https://192.168.40.60:6443 -- kubeconfig=kubelet-bootstrap.kubeconfig

[root@xuegod60 work]# kubectl config set-credentials kubelet-bootstrap -- token=${BOOTSTRAP_TOKEN} --kubeconfig=kubelet-bootstrap.kubeconfig

[root@xuegod60 work]# kubectl config set-context default --cluster=kubernetes -- user=kubelet-bootstrap --kubeconfig=kubelet-bootstrap.kubeconfig

[root@xuegod60 work]# kubectl config use-context default --kubeconfig=kubelet- bootstrap.kubeconfig

[root@xuegod60 work]# kubectl create clusterrolebinding kubelet-bootstrap -- clusterrole=system:node-bootstrapper --user=kubelet-bootstrap

#创建配置文件 kubelet.json

"cgroupDriver": "systemd"要和 docker 的驱动一致。

address 替换为自己 xuegod63 的 IP 地址。

[root@xuegod60 work]# vim kubelet.json

{

"kind": "KubeletConfiguration",

"apiVersion": "kubelet.config.k8s.io/v1beta1", "authentication": {

"x509": {

"clientCAFile": "/etc/kubernetes/ssl/ca.pem"

},

"webhook": { "enabled": true, "cacheTTL": "2m0s"

},

"anonymous": { "enabled": false

}

},

"authorization": { "mode": "Webhook", "webhook": {

"cacheAuthorizedTTL": "5m0s", "cacheUnauthorizedTTL": "30s"

}

},

"address": "192.168.40.63",

"port": 10250,

"readOnlyPort": 10255, "cgroupDriver": "systemd", "hairpinMode": "promiscuous-bridge", "serializeImagePulls": false, "featureGates": {

"RotateKubeletClientCertificate": true, "RotateKubeletServerCertificate": true

},

"clusterDomain": "cluster.local.", "clusterDNS": ["10.96.0.2"]

}

[root@xuegod60 work]# vim kubelet.service [Unit]

Description=Kubernetes Kubelet Documentation=https://github.com/kubernetes/kubernetes After=docker.service

Requires=docker.service [Service]

WorkingDirectory=/var/lib/kubelet ExecStart=/usr/local/bin/kubelet \

--bootstrap-kubeconfig=/etc/kubernetes/kubelet-bootstrap.kubeconfig \

--cert-dir=/etc/kubernetes/ssl \

--kubeconfig=/etc/kubernetes/kubelet.kubeconfig \

--config=/etc/kubernetes/kubelet.json \

--container-runtime-endpoint=unix:///run/containerd/containerd.sock \

--pod-infra-container-image=k8s.gcr.io/pause:3.2 \

--alsologtostderr=true \

--logtostderr=false \

--log-dir=/var/log/kubernetes \

--v=2

Restart=on-failure RestartSec=5

[Install]

WantedBy=multi-user.target

#注: –hostname-override:显示名称,集群中唯一

–kubeconfig:空路径,会自动生成,后面用于连接 apiserver

–bootstrap-kubeconfig:首次启动向 apiserver 申请证书

–config:配置参数文件

–cert-dir:kubelet 证书生成目录

–pod-infra-container-image:管理 Pod 网络容器的镜像

#注:kubelete.json 配置文件 address 改为各个节点的 ip 地址,在各个 work 节点上启动服务

[root@xuegod63 ~]# mkdir /etc/kubernetes/ssl -p

[root@xuegod60 work]# scp kubelet-bootstrap.kubeconfig kubelet.json xuegod63:/etc/kubernetes/

[root@xuegod60 work]# scp ca.pem xuegod63:/etc/kubernetes/ssl/ [root@xuegod60 work]# scp kubelet.service xuegod63:/usr/lib/systemd/system/

#启动 kubelet 服务

[root@xuegod63 ~]# mkdir /var/lib/kubelet [root@xuegod63 ~]# mkdir /var/log/kubernetes [root@xuegod63 ~]# systemctl daemon-reload [root@xuegod63 ~]# systemctl enable kubelet [root@xuegod63 ~]# systemctl start kubelet [root@xuegod63 ~]# systemctl status kubelet

Active: active (running) since

确认 kubelet 服务启动成功后,接着到 xuegod60 节点上 Approve 一下 bootstrap 请求。

[əˈpruːv]:批准

执行如下命令可以看到一个 worker 节点发送了一个 CSR 请求:

[root@xuegod60 work]# kubectl get csr

NAME AGE SIGNERNAME

REQUESTOR CONDITION

node-csr-SY6gROGEmH0qVZhMVhJKKWN3UaWkKKQzV8dopoIO9Uc 87s kubernetes.io/kube-apiserver-client-kubelet kubelet-bootstrap Pending

[root@xuegod60 work]# kubectl certificate approve node-csr- SY6gROGEmH0qVZhMVhJKKWN3UaWkKKQzV8dopoIO9Uc [root@xuegod60 work]# kubectl get csr

NAME AGE SIGNERNAME

REQUESTOR CONDITION

node-csr-SY6gROGEmH0qVZhMVhJKKWN3UaWkKKQzV8dopoIO9Uc 2m25s kubernetes.io/kube-apiserver-client-kubelet kubelet-bootstrap Approved,Issued

[root@xuegod60 work]# kubectl get nodes

NAME STATUS ROLES AGE VERSION

xuegod63 NotReady <none> 30s v16.25.0 #注意:STATUS 是 NotReady 表示还没有安装网络插件

16.4.8 部署 kube-proxy 组件

#创建 csr 请求

[root@xuegod60 work]# vim kube-proxy-csr.json

{

"CN": "system:kube-proxy",

"key": {

"algo": "rsa", "size": 2048

},

"names": [

{

"C": "CN",

"ST": "Hubei",

"L": "Wuhan",

"O": "k8s",

"OU": "system"

}

]

}

生成证书

[root@xuegod60 work]# cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca- config.json -profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy

#创建 kubeconfig 文件

[root@xuegod60 work]# kubectl config set-cluster kubernetes --certificate- authority=ca.pem --embed-certs=true --server=https://192.168.40.60:6443 -- kubeconfig=kube-proxy.kubeconfig

[root@xuegod60 work]# kubectl config set-credentials kube-proxy --client- certificate=kube-proxy.pem --client-key=kube-proxy-key.pem --embed-certs=true -- kubeconfig=kube-proxy.kubeconfig

[root@xuegod60 work]# kubectl config set-context default --cluster=kubernetes -- user=kube-proxy --kubeconfig=kube-proxy.kubeconfig

[root@xuegod60 work]# kubectl config use-context default --kubeconfig=kube- proxy.kubeconfig

#创建 kube-proxy 配置文件

[root@xuegod60 work]# vim kube-proxy.yaml apiVersion: kubeproxy.config.k8s.io/v1alpha1 bindAddress: 192.168.40.63

clientConnection:

kubeconfig: /etc/kubernetes/kube-proxy.kubeconfig clusterCIDR: 192.168.40.0/24

healthzBindAddress: 192.168.40.63:10256 kind: KubeProxyConfiguration metricsBindAddress: 192.168.40.63:10249 mode: "ipvs"

#创建服务启动文件

[root@xuegod60 work]# vim kube-proxy.service [Unit]

Description=Kubernetes Kube-Proxy Server Documentation=https://github.com/kubernetes/kubernetes

After=network.target

[Service] WorkingDirectory=/var/lib/kube-proxy ExecStart=/usr/local/bin/kube-proxy \

--config=/etc/kubernetes/kube-proxy.yaml \

--alsologtostderr=true \

--logtostderr=false \

--log-dir=/var/log/kubernetes \

--v=2

Restart=on-failure RestartSec=5 LimitNOFILE=65536

[Install]

WantedBy=multi-user.target

[root@xuegod60 work]# scp kube-proxy.kubeconfig kube-proxy.yaml xuegod63:/etc/kubernetes/

[root@xuegod60 work]#scp kube-proxy.service xuegod63:/usr/lib/systemd/system/

#启动服务

[root@xuegod63 ~]# mkdir -p /var/lib/kube-proxy [root@xuegod63 ~]# systemctl daemon-reload [root@xuegod63 ~]# systemctl enable kube-proxy [root@xuegod63 ~]# systemctl start kube-proxy [root@xuegod63 ~]# systemctl status kube-proxy

Active: active (running) since Wed

16.4.9 部署 calico 组件

把安装 calico 需要的镜像 calico.tar.gz 传到 xuegod63 节点,手动解压:

[root@xuegod63 ~]# ctr -n=k8s.io images import calico.tar.gz

上传 calico.yaml 到 xuegod60 上,使用 yaml 文件安装 calico 网络插件 。

**NAME**                  **READY**                  **STATUS**                  **RESTARTS**                  **AGE**                            **calico-kube-controllers-6949477b58-qvn5b**                  **1/1**                  **Running**                  **0**                  **2m17s**                            **calico-node-lv6w4**             **[root@xuegod60 ~]#      kubectl get nodes**                  **1/1**                  **Running**                  **0**                  **2m18s**

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

NAME STATUS ROLES AGE VERSION

xuegod63 Ready <none> 73m v16.25.0

16.4.10 部署 coredns 组件

[root@xuegod60 ~]# kubectl apply -f coredns.yaml [root@xuegod60 ~]# kubectl get pods -n kube-system

NAME READY STATUS RESTARTS AGE

calico-node-xk7n4 1/1 Running 0 6m6s coredns-7bf4bd64bd-dt8dq 1/1 Running 0 51s [root@xuegod60 ~]# kubectl get svc -n kube-system

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.255.0.2 <none> 53/UDP,53/TCP,9153/TCP 12m

16.5 查看集群状态

[root@xuegod60 ~]# kubectl get nodes

NAME STATUS ROLES AGE VERSION

xuegod63 Ready <none> 38m v16.23.1

16.6 对系统用户 kubernetes 做授权

[root@xuegod60 ~]# kubectl create clusterrolebinding kubernetes-kubectl -- clusterrole=cluster-admin --user=kubernetes

16.7 验证 k8s 网络和 cordns 是否正常

[root@xuegod63 ~]# ctr -n=k8s.io images import busybox-1-28.tar.gz [root@xuegod60 ~]# kubectl run busybox --image busybox:1.28 --restart=Never --rm -it busybox -- sh

/ # ping www.baidu.com

PING www.baidu.com (39.156.66.18): 56 data bytes

64 bytes from 39.156.66.18: seq=0 ttl=127 time=39.3 ms #通过上面可以看到能访问网络

/ # nslookup kubernetes Server: 10.96.0.2

Address 1: 10.96.0.2 kube-dns.kube-system.svc.cluster.local

Name: kubernetes

Address 1: 10.96.0.1 kubernetes.default.svc.cluster.local

#注意:

busybox 要用指定的 16.28 版本,不能用最新版本,最新版本,nslookup 会解析不到dns 和 ip,

16.8 安装 keepalived+nginx 实现 k8s apiserver 高可用

1、安装 nginx 主备:

在 xuegod60 和 xuegod61 上做 nginx 主备安装[root@xuegod60 ~]# yum install epel-release -y [root@xuegod61 ~]# yum install epel-release -y

[root@xuegod60 ~]# yum install nginx keepalived nginx-mod-stream -y [root@xuegod61 ~]# yum install nginx keepalived nginx-mod-stream -y

2、修改 nginx 配置文件。主备一样[root@xuegod60 ~]# vim /etc/nginx/nginx.conf user nginx;

worker_processes auto;

error_log /var/log/nginx/error.log; pid /run/nginx.pid;

include /usr/share/nginx/modules/*.conf; events {

worker_connections 1024;

}

# 四层负载均衡,为两台 Master apiserver 组件提供负载均衡

stream {

log_format main '$remote_addr $upstream_addr - [$time_local] $status

$upstream_bytes_sent';

access_log /var/log/nginx/k8s-access.log main; upstream k8s-apiserver {

server 192.168.40.60:6443 weight=5 max_fails=3 fail_timeout=30s; server 192.168.40.61:6443 weight=5 max_fails=3 fail_timeout=30s; server 192.168.40.62:6443 weight=5 max_fails=3 fail_timeout=30s;

}

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

}

}

}

#配置文件说明:

weight 是权重,默认是 1.权重越大接受的请求越多。

max_falis 允许请求失败的次数,默认是 1,当超过最大次数时,返回 proxy_next_upstream 模块定义的错误。0 表示禁止失败尝试,企业场景:2-3.京东 1 次,蓝汛 10 次,根据业务需求去配置。

fail timeout 在经历了 max_fails 次失败后,暂停服务的时间。京东是 3s,蓝汛是 3s,根据业务需求配置。常规业务 2-3 秒合理。

例:如果 max_fails 是 3,他就检测 3 次,如果 3 次都是 502.那么,他就会根据 fail_timeout 的值, 等待 30 秒,再去检测。

[root@xuegod61 ~]# vim /etc/nginx/nginx.conf user nginx;

worker_processes auto;

error_log /var/log/nginx/error.log; pid /run/nginx.pid;

include /usr/share/nginx/modules/*.conf; events {

worker_connections 1024;

}

# 四层负载均衡,为两台 Master apiserver 组件提供负载均衡

stream {

log_format main '$remote_addr $upstream_addr - [$time_local] $status

$upstream_bytes_sent';

access_log /var/log/nginx/k8s-access.log main; upstream k8s-apiserver {

server 192.168.40.60:6443 weight=5 max_fails=3 fail_timeout=30s; server 192.168.40.61:6443 weight=5 max_fails=3 fail_timeout=30s; server 192.168.40.62:6443 weight=5 max_fails=3 fail_timeout=30s;

}

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

}

}

}

3、keepalive 配置主 keepalived

[root@xuegod60 ~]# vim /etc/keepalived/keepalived.conf global_defs {

notification_email { acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc

}

notification_email_from Alexandre.Cassen@firewall.loc smtp_server 127.0.0.1

smtp_connect_timeout 30 router_id NGINX_MASTER

}

vrrp_script check_nginx {

script "/etc/keepalived/check_nginx.sh"

}

vrrp_instance VI_1 { state MASTER

interface ens33 # 修改为实际网卡名

virtual_router_id 51 # VRRP 路由 ID 实例,每个实例是唯一的

priority 100 # 优先级,备服务器设置 90

advert_int 1 # 指定 VRRP 心跳包通告间隔时间,默认 1 秒

authentication { auth_type PASS auth_pass 1111

}

# 虚拟 IP virtual_ipaddress {

192.168.40.199/24

}

track_script {

check_nginx

}

}

#vrrp_script:指定检查 nginx 工作状态脚本(根据 nginx 状态判断是否故障转移)

#virtual_ipaddress:虚拟 IP(VIP)

[root@xuegod60 ~]# vim /etc/keepalived/check_nginx.sh

#!/bin/bash

#1、判断 Nginx 是否存活

counter=$(ps -ef |grep nginx | grep sbin | egrep -cv "grep|$$" ) if [ $counter -eq 0 ]; then

#2、如果不存活则尝试启动 Nginx service nginx start

sleep 2

#3、等待 2 秒后再次获取一次 Nginx 状态

counter=$(ps -ef |grep nginx | grep sbin | egrep -cv "grep|$$" )

#4、再次进行判断,如 Nginx 还不存活则停止 Keepalived,让地址进行漂移if [ $counter -eq 0 ]; then

service keepalived stop

fi

fi

[root@xuegod60 ~]# chmod +x /etc/keepalived/check_nginx.sh

备 keepalive

[root@xuegod61 ~]# vim /etc/keepalived/keepalived.conf global_defs {

notification_email { acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc

}

notification_email_from Alexandre.Cassen@firewall.loc smtp_server 127.0.0.1

smtp_connect_timeout 30 router_id NGINX_BACKUP

}

vrrp_script check_nginx {

script "/etc/keepalived/check_nginx.sh"

}

vrrp_instance VI_1 { state BACKUP interface ens33

virtual_router_id 51 # VRRP 路由 ID 实例,每个实例是唯一的

priority 90

advert_int 1 authentication {

auth_type PASS auth_pass 1111

}

virtual_ipaddress { 192.168.40.199/24

}

track_script {

check_nginx

}

}

[root@xuegod61 ~]# vim /etc/keepalived/check_nginx.sh #!/bin/bash

#1、判断 Nginx 是否存活

counter=$(ps -ef |grep nginx | grep sbin | egrep -cv "grep|$$" ) if [ $counter -eq 0 ]; then

#2、如果不存活则尝试启动 Nginx service nginx start

sleep 2

#3、等待 2 秒后再次获取一次 Nginx 状态

counter=$(ps -ef |grep nginx | grep sbin | egrep -cv "grep|$$" )

#4、再次进行判断,如 Nginx 还不存活则停止 Keepalived,让地址进行漂移if [ $counter -eq 0 ]; then

service keepalived stop

fi

fi

[root@xuegod61 ~]# chmod +x /etc/keepalived/check_nginx.sh

#注:keepalived 根据脚本返回状态码(0 为工作正常,非 0 不正常)判断是否故障转移。

4、启动服务:

[root@xuegod60 ~]# systemctl daemon-reload [root@xuegod60 ~]# systemctl start nginx [root@xuegod60 ~]# systemctl start keepalived [root@xuegod60 ~]# systemctl enable nginx keepalived [root@xuegod60]# systemctl status keepalived

img

[root@xuegod61 ~]# systemctl daemon-reload [root@xuegod61 ~]# systemctl start nginx [root@xuegod61 ~]# systemctl start keepalived [root@xuegod61 ~]# systemctl enable nginx keepalived [root@xuegod61]# systemctl status keepalived

img

5、测试 vip 是否绑定成功

[root@xuegod60 ~]# ip addr

1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000

link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo

valid_lft forever preferred_lft forever inet6 ::1/128 scope host

valid_lft forever preferred_lft forever

2: ens33: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000

link/ether 00:0c:29:79:9e:36 brd ff:ff:ff:ff:ff:ff

inet 192.168.40.60/24 brd 192.168.40.255 scope global noprefixroute ens33 valid_lft forever preferred_lft forever

inet 192.168.40.199/24 scope global secondary ens33 valid_lft forever preferred_lft forever

inet6 fe80::b6ef:8646:1cfc:3e0c/64 scope link noprefixroute valid_lft forever preferred_lft forever

6、测试 keepalived:

img

停掉 xuegod60 上的keepalived,Vip 会漂移到 xuegod61 [root@xuegod60 ~]# service keepalived stop [root@xuegod61]# ip addr

#启动 xuegod60 上的 nginx 和 keepalived,vip 又会漂移回来[root@xuegod60 ~]# systemctl daemon-reload [root@xuegod60 ~]# systemctl start nginx [root@xuegod60 ~]# systemctl start keepalived [root@xuegod60]# ip addr

img

目前所有的 Worker Node 组件连接都还是 xuegod60 Node,如果不改为连接 VIP 走负载均衡器,那么 Master 还是单点故障。

因此接下来就是要改所有 Worker Node(kubectl get node 命令查看到的节点)组件配置文件,由原来 192.168.40.60 修改为 192.168.40.199(VIP)。

在所有 Worker Node 执行:

[root@xuegod63 ~]# sed -i 's#192.168.40.60:6443#192.168.40.199:16443#'

/etc/kubernetes/kubelet-bootstrap.kubeconfig

[root@xuegod63 ~]# sed -i 's#192.168.40.60:6443#192.168.40.199:16443#'

/etc/kubernetes/kubelet.json

[root@xuegod63 ~]# sed -i 's#192.168.40.60:6443#192.168.40.199:16443#'

/etc/kubernetes/kubelet.kubeconfig

[root@xuegod63 ~]# sed -i 's#192.168.40.60:6443#192.168.40.199:16443#'

/etc/kubernetes/kube-proxy.yaml

[root@xuegod63 ~]# sed -i 's#192.168.40.60:6443#192.168.40.199:16443#'

/etc/kubernetes/kube-proxy.kubeconfig

[root@xuegod63 ~]# systemctl restart kubelet kube-proxy

这样高可用集群就安装好了