内网环境下手动部署kubernetes(v1.26.3)高可用集群

这篇博客主要是记录了手动部署一个高可用的Kubernetes集群的过程。旨在帮助自己及初学者学习kubernetes,并记录下具体的操作过程和总结的知识点。文中可能存在一些问题或不足之处,仅供参考。

文章目录

  • 一、环境准备
    • 1.1 集群规划与配置
    • 1.2 部署前准备
    • 1.3 升级内核至4.19版本
    • 1.4 关闭swap交换分区
    • 1.5 网络配置
    • 1.6 时间同步
    • 1.7 配置ulimit
    • 1.8 安装ipvsadm
    • 1.9 修改内核参数
    • 1.10 设置主机名和hosts本地解析
  • 二、K8S基本组件安装
    • 2.1 安装docker
    • 2.2 安装镜像仓库
    • 2.3 安装cri-docker
    • 2.4 安装k8s与etcd组件
  • 三、相关证书生成
    • 3.1 生成etcd证书
    • 3.2 生成apiserver证书
    • 3.3 生成front-proxy-client证书
    • 3.4 生成controller-manage的证书
    • 3.5 生成scheduler的证书
    • 3.6 生成admin的证书
    • 3.7 生成kube-proxy证书
    • 3.8 创建ServiceAccount Key
  • 四、ETCD集群配置
  • 五、Keepalibed高可用配置
    • 5.1 安装keepalived
    • 5.2 主节点测试高可用
  • 六、K8S组件配置
    • 6.1 配置apiserver、controller manager和scheduler
    • 6.2 配置TLS Bootstrapping
  • 七、Node节点配置
    • 7.1 kubelet配置
    • 7.2 kube-proxy配置
    • 7.3 查看k8s集群
  • 八、安装Calico、CoreDNS和Metrics Server
    • 8.1 安装Calico
    • 8.2 安装CoreDNS
    • 8.3 安装Metrics Server
  • 九、安装dashboard
  • 十、集群可用性验证


一、环境准备

(1)保证机器之间是互相联通的。这里部署环境为三台4核4G的centos 7.9虚拟机,用于学习环境勉强够用,最终部署一个三个master节点的高可用集群。
(2)内网环境需要提前下载好软件包复制到离线机器上;联网环境直接install下载安装即可。
(3)k8s集群版本为1.26.3,这里的运行环境下发现cri-docker必须是0.3.0版本及以上,其他软件版本不是太旧即可。

1.1 集群规划与配置

1.集群规划

IP地址 说明 组件
192.168.79.100 高可用节点(vip)
192.168.79.101 k8s-master01、k8s-node01 apiserver;controller manager; scheduler;etcd;kube-proxy, kubelet;keepalived;kubectl
192.168.79.102 k8s-master01、k8s-node01 apiserver;controller manager; scheduler;etcd;kube-proxy, kubelet;keepalived;kubectl
192.168.79.103 k8s-master01、k8s-node01 apiserver;controller manager; scheduler;etcd;kube-proxy, kubelet;keepalived;kubectl

2.网段规划

主机网段 192.168.79.0/24
service网段 10.96.0.0/16
pod网段 172.16.0.0/12

3.软件配置信息说明

配置信息 说明 配置信息 说明
系统版本 CentOS 7.9 etcd 版本:3.5.6
系统内核 kernel-ml-4.19.12 keepalived 版本:2.1.5
K8S组件 版本:1.26.3 coredns 版本:1.9.4
docker 版本:20.10.21 metrics-server 版本:0.5.2
cri-docker 版本:0.3.0 dashboard 版本:2.7.0

4.软件包/镜像包下载

这里主要是模拟工作中在内网的离线环境下,所以需要提前在一台联网机器上下载好相关软件包、镜像包、依赖包等等。可参考此篇博客1.6节下载所需软件包、镜像包:二进制安装Kubernetes(k8s) v1.26.0 IPv4/IPv6双栈 。联网环境下直接install安装即可,可跳过此步。这里大概说明一下:

#主要组件下载如kubernetes、etcd、docker、cri-docker:
wget https://dl.k8s.io/v1.26.3/kubernetes-server-linux-amd64.tar.gz
wget https://ghproxy.com/https://github.com/etcd-io/etcd/releases/download/v3.5.6/etcd-v3.5.6-linux-amd64.tar.gz
wget https://download.docker.com/linux/static/stable/x86_64/docker-20.10.21.tgz
wget https://ghproxy.com/https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.0/cri-dockerd-0.3.0.amd64.tgz

#相关软件包去官网提前下载好
(1)kubernetes1.26.+二进制包下载地址:https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.26.md2)etcd二进制包下载地址:https://github.com/etcd-io/etcd/releases3)docker二进制包下载二进制包下载地址:https://download.docker.com/linux/static/stable/x86_64/4)cri-docker二进制包下载地址:https://github.com/Mirantis/cri-dockerd/releases/5)cfssl二进制包下载地址:https://github.com/cloudflare/cfssl/releases/6)keepalived二进制源码包:http://www.keepalived.org/download.html7)其他:......

这里已经将相关软件包,依赖包提前下载好并拷贝到一台服务器的/root/kubernetes-v1.26.3/目录下,说明如下:
(1)/root/kubernetes-v1.26.3/config/ 一些软件的配置文件
(2)/root/kubernetes-v1.26.3/images/ 相关镜像包
(3)/root/kubernetes-v1.26.3/packages/ 软件安装包
(4)/root/kubernetes-v1.26.3/RPMpackages/ 软件RPM包

5.学习拓展:

1.只下载不安装软件
yum install --downloadonly --downloaddir=下载目录 下载软件名

2.yum install xxx.rpm和rpm -ivh xxx.rpm 命令安装本地RPM包区别:
(1)yum install xxx.rpm命令会先检查本地yum仓库,如果能找到该RPM包及其依赖项,则会自动安装。如果在本地yum仓库中找不到该RPM包及其依赖项,它会给出错误提示并停止安装。这个命令比较适合在离线环境下使用,因为可以通过本地yum仓库来解决RPM包的依赖关系。
(2)rpm -ivh xxx.rpm命令则是直接安装该RPM包,不会检查是否有依赖关系。如果该RPM包依赖其他包,则需要手动安装这些依赖项。这个命令比较适合在在线环境下使用,因为可以通过yum来解决依赖关系,并自动安装所需的依赖包。

3.安装RPM包时强制覆盖现有文件并忽略依赖关系使用参数--force --nodeps
(1)举例:rpm -ivh xxx.rpm --force --nodeps
(2)安装本地软件包:yum localinstall -y xxx.rpm

4.安装时缺少依赖的rpm包,下载网址(centos7 x86_64):
(1)https://rpmfind.net/linux/RPM/
(2)https://centos.pkgs.org/7/centos-x86_64/
(3)http://mirror.centos.org/centos/7/os/x86_64/Packages/
(4)http://www.rpmfind.net/linux/rpm2html/search.php

1.2 部署前准备

1.关闭防火墙和SELinux

在实际生产环境中,通常会采用防火墙和SELinux来增强系统的安全性,但在学习和测试环境中,这些安全措施可能会造成麻烦。因此,只用于学习环境建议关闭所有节点的防火墙和SELinux,以方便学习和测试。三台机器(所有节点)均需要在部署前配置好环境。

#关闭防火墙,关闭SELinux(设置为disabled)
systemctl stop firewalld && systemctl disable firewalld 
setenforce 0
sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/selinux/config

#确保防火墙和SElinux是关闭状态
systemctl status firewalld
cat /etc/selinux/config

内网环境下手动部署kubernetes(v1.26.3)高可用集群_第1张图片

#拓展总结:
##常用的和防火墙相关的命令及其具体的例子:
1.iptables:这是一个基于内核的防火墙工具,可以用来设置和管理IPv4和IPv6防火墙规则。
(1)添加规则:iptables -A INPUT -p tcp --dport 22 -j ACCEPT,表示允许TCP协议、目标端口为22的流量通过INPUT链。
(2)删除规则:iptables -D INPUT -p tcp --dport 22 -j ACCEPT,表示删除INPUT链中允许TCP协议、目标端口为22的规则。
(3)查看规则:iptables -L,可以查看当前所有的iptables规则。

2.ufw:这是Ubuntu系统中的一种简单的防火墙工具,它可以用来管理iptables规则。
(1)启动防火墙:sudo ufw enable,表示启动防火墙,并应用默认规则。
(2)允许端口:sudo ufw allow 22/tcp,表示允许TCP协议的22端口通过防火墙。
(3)禁止端口:sudo ufw deny 80/tcp,表示禁止TCP协议的80端口通过防火墙。

3.firewalld:这是一个动态的防火墙管理工具,它可以在运行时添加、删除和修改防火墙规则。
(1)启动防火墙:systemctl start firewalld,表示启动firewalld服务。
(2)关闭防火墙:systemctl stop firewalld,表示停止firewalld服务。
允许端口:firewall-cmd --add-port=80/tcp --permanent,表示允许TCP协议的80端口通过防火墙,并将规则永久化。

4.tcpdump:这是一个网络分析工具,可以用来捕获网络数据包并分析它们。
(1)捕获数据包:sudo tcpdump -i eth0,表示在eth0接口上捕获所有的数据包。
(2)过滤数据包:sudo tcpdump -i eth0 tcp port 22,表示在eth0接口上只捕获TCP协议、目标端口为22的数据包。

5.nmap:这是一个网络扫描工具,可以用来扫描网络中的主机和端口。
(1)扫描主机:nmap 192.168.1.1,表示扫描IP地址为192.168.1.1的主机。
(2)扫描端口:nmap -p 80 192.168.1.1,表示扫描IP地址为192.168.1.1的主机上的80端口是否开放。

6.ping:这是一个用来测试网络连接的基本工具,可以用来测试主机之间的连通性。
测试连通性:ping www.baidu.com,表示测试与百度服务器的连通性。

7.traceroute:这是一个网络诊断工具,可以用来追踪网络数据包在互联网中的路由路径。
追踪路由路径:traceroute www.baidu.com,表示追踪连接到百度服务器的路由路径。

8.netstat:这是一个网络工具,可以用来显示网络连接、路由表和网络接口等信息。
(1)查看连接状态:netstat -an,可以查看当前所有的网络连接状态。
(2)查看端口占用:netstat -anp | grep 80,可以查看所有占用80端口的进程。

2.各节点配置免密登录

在Kubernetes集群中,各节点之间需要频繁地进行通信和交互,例如节点之间的API调用和控制平面和数据平面之间的通信等。这需要在各节点之间建立起可信的、安全的连接

配置免密登录这一步是非必要的,在学习环境中,为了方便节点之间的通信和交互,并保障连接的安全性,通常会在各节点之间配置免密登录。这样管理员可以在任意一个节点上进行操作,而不需要在不同节点之间频繁地输入密码。这里在master01节点上安装sshpass,设置三台机器之间互相免密。

#下载其rpm包后安装sshpass
cd /root/kubernetes-v1.26.3/RPMpackages/
rpm -ivh sshpass-1.06-2.el7.x86_64.rpm

#所有master节点之间配置免密,这里三个master节点密码都是root
ssh-keygen -f /root/.ssh/id_rsa -P ''
export IP="192.168.79.101 192.168.79.102 192.168.79.103"
export SSHPASS=root
for HOST in $IP;do
     sshpass -e ssh-copy-id -o StrictHostKeyChecking=no $HOST
done

内网环境下手动部署kubernetes(v1.26.3)高可用集群_第2张图片

#拓展总结:
#如果master节点机器的密码不一样,脚本修改如下:
IP_LIST="192.168.79.101 192.168.79.102 192.168.79.103"
#定义每个主机对应的密码
declare -A PASS_LIST=(
    ["192.168.79.101"]="password1"
    ["192.168.79.102"]="password2"
    ["192.168.79.103"]="password3"
)
# 生成SSH密钥对
ssh-keygen -f /root/.ssh/id_rsa -P ''
# 遍历远程主机列表,将公钥复制到远程主机上
for HOST in $IP_LIST; do
    PASSWORD=${PASS_LIST[$HOST]}
    sshpass -p "$PASSWORD" ssh-copy-id -o StrictHostKeyChecking=no $HOST
done

#SCP命令是用于在不同计算机之间安全地复制文件和目录的命令。它使用SSH协议进行加密传输,因此非常适合用于安全文件传输。
#常用的SCP命令语法如下:scp [选项] [源文件或目录] [目标文件或目录];
其中[选项]常用的有:-r(传输目录)、-v(详细信息)

(1)将本地文件 /home/user/file.txt 复制到远程主机 192.168.0.100/var/www/html/ 目录下:
   scp /home/user/file.txt root@192.168.0.100:/var/www/html/
(2)将本地目录 /home/user/docs 及其所有内容复制到远程主机 192.168.0.100/var/www/ 目录中:
   scp -r /home/user/docs root@192.168.0.100:/var/www/
(3)在传输过程中显示进度(将本地目录复制到远程主机目录中,并显示传输进度和详细信息):
   scp -r -v /home/user/images root@192.168.0.100:/var/www/html/

1.3 升级内核至4.19版本

部署k8s集群建议 Linux 内核使用3.10 以上的版本。提前下载好kernel-ml的rpm包。

#这里系统内核选择的是4.19稳定版kernel-ml,所有节点升级系统内核到4.19
cd /root/kubernetes-v1.26.3/RPMpackages/kernel/
yum install -y kernel-ml-devel-4.19.12-1.el7.elrepo.x86_64.rpm
yum install -y kernel-ml-4.19.12-1.el7.elrepo.x86_64.rpm

#更改内核启动顺序
grub2-set-default 0 && grub2-mkconfig -o /etc/grub2.cfg

#查看默认内核(输出/boot/vmlinuz-4.19.12-1.el7.elrepo.x86_64则升级内核成功)
grubby --default-kernel

#若不是最新的,使用以下命令设置,reboot重启生效。
grubby --set-default $(ls /boot/vmlinuz-* | grep elrepo)

在这里插入图片描述

拓展总结:
#1.查看当前系统版本:cat /etc/redhat-release
#2.查看当前系统的内核:uname -sr
#3.查看系统架构:uname -m
#4.查看cpu详细信息:lscpu
#5.查看当前系统的磁盘空间使用情况:df -h
#6.查看当前系统的内存使用情况:free -m
#7.查看当前系统的IP地址:ip addr show 或者 ip a
#8.查看当前系统的DNS配置:cat /etc/resolv.conf
#9.查看当前系统的路由表:ip route list
#10.查看当前系统的网络连接状态:netstat -an
#11.查看当前系统的进程信息:ps aux
#12.查看当前系统的日志信息:tail -f /var/log/messages

1.4 关闭swap交换分区

在Kubernetes集群中,关闭 swap 分区是一个比较常见的配置项。原因如下:
(1)减少内存压力:关闭 swap 分区可以避免因为系统内存不足而将内存中的数据写入磁盘,从而减少磁盘 I/O 的负载,提高系统性能。
(2)避免OOM Killer:如果系统内存不足,操作系统会使用OOM Killer机制杀掉一些进程来释放内存,这可能会导致Kubernetes容器被异常终止,影响应用程序的稳定性和可用性。
(3)安全考虑:在Kubernetes集群中,容器中运行的应用程序只能看到自己的文件系统,不能直接访问宿主机上的文件系统。如果开启了swap分区,容器中的进程可以访问到宿主机上的swap分区,这可能会带来一些安全隐患。

为了保证Kubernetes集群的性能、稳定性和安全性,建议在部署 Kubernetes集群时关闭swap分区。

#所有节点关闭swap交换分区
sed -ri 's/.*swap.*/#&/' /etc/fstab
swapoff -a && sysctl -w vm.swappiness=0

#查看是否关闭(swap 0 0 0则成功关闭)
free -m

内网环境下手动部署kubernetes(v1.26.3)高可用集群_第3张图片

1.5 网络配置

由于容器是被隔离的虚拟化技术,容器内部的IP地址和端口是隔离的,因此需要配置一些网络规则来实现容器之间的通信和访问。这里使用 calico 作为网络插件,其目的是为 Kubernetes 集群提供高性能、高可靠性的网络基础设施,并且支持复杂的网络拓扑结构。

具体来说,需要将 calico 网络相关的设备(interface)标记为 NetworkManager 不管理的设备。这样可以避免 NetworkManager 对 calico 网络设备的干扰,确保 calico 插件能够正常地进行网络配置和管理。

#所有节点进行网络配置,使用calico
cat > /etc/NetworkManager/conf.d/calico.conf << EOF 
[keyfile]
unmanaged-devices=interface-name:cali*;interface-name:tunl*
EOF

#重启NetworkManager
systemctl restart NetworkManager

1.6 时间同步

由于容器是被隔离的虚拟化技术,容器内部的时间可能和宿主机不一致,容器之间的时间也可能存在差异。如果容器之间的时间不一致,就会导致如SSL证书验证失败、网络连接超时等问题。

常见的时间同步方案有NTP和Chrony两种。NTP是一种网络时间协议,可以通过互联网进行时间同步,但是受网络条件和时延的影响比较大。Chrony可以通过本地网络进行时间同步,具有较低的时延和较高的精度。

这里由于工作需要使用ntp时间同步即可,建议使用chrony。相关rpm包均放在/root/kubernetes-v1.26.3/RPMpackages目录下,将ntp.conf文件里的IP改为实际部署IP即可。

#查看123端口是否被占用,防止端口占用导致ntpq无法实现开机启动
netstat -apn | grep 123

#在所有节点上安装net-tools和ntp
yum install -y /root/kubernetes-v1.26.3/RPMpackages/net-tools-2.0-0.25.20131004git.el7.x86_64.rpm
yum install -y /root/kubernetes-v1.26.3/RPMpackages/ntp/*.rpm

##使用master01节点作为ntp的服务器,规划如下:
192.168.79.101  ----ntp服务端
192.168.79.102  ----ntp客户端
192.168.79.103  ----ntp客户端
##服务端配置(192.168.79.101)
mv /etc/ntp.conf /etc/ntp.conf.bak
#每隔5分钟自动同步服务器时间,可修改同步间隔时间
cat > /etc/ntp.conf << EOF
driftfile /var/lib/ntp/drift
restrict default nomodify notrap nopeer noquery  #默认限制,禁止修改、trap、peer和query
restrict 127.0.0.1                               #限制只允许本地回环地址进行操作
restrict ::1 

server 127.127.1.1                               #表示指定当前服务器作为NTP服务器
*/5 * * * * /usr/sbin/ntpdate 192.168.79.101     #每隔5分钟自动同步101机器的时间

includefile /etc/ntp/crypto/pw                   #包含认证密钥的文件路径
keys /etc/ntp/keys                               #NTP使用的认证密钥文件路径
disable monitor                                  #禁用监视端口
EOF

#123端口可能被chronyd服务占用,如果chronyd是启动状态,需要将其disabled。否则ntpd服务无法开机自动启动
systemctl stop chronyd && systemctl disable chronyd
systemctl status chronyd

#重启并设置ntp开机自启,查看ntp服务状态
systemctl restart ntpd && systemctl enable ntpd
service ntpd status

内网环境下手动部署kubernetes(v1.26.3)高可用集群_第4张图片

##客户端配置(192.168.79.102192.168.79.103)
mv /etc/ntp.conf /etc/ntp.conf.bak
cat > /etc/ntp.conf << EOF
driftfile /var/lib/ntp/drift
restrict default nomodify notrap nopeer noquery
restrict 127.0.0.1
restrict ::1

server 192.168.79.101  #指向时间同步服务器IP
Fudge 192.168.79.101 stratum 10

includefile /etc/ntp/crypto/pw
keys /etc/ntp/keys
disable monitor
EOF

#同步时间时,只需要服务器ntp服务打开,客户端服务必须关闭(inactive) 
systemctl restart ntpd && systemctl stop ntpd
systemctl is-active ntpd

#开启时间同步(服务端已配置每5分钟自动同步时间)
#客户端手动方式验证时间同步:
ntpdate 192.168.79.101 

内网环境下手动部署kubernetes(v1.26.3)高可用集群_第5张图片

#拓展总结:
##常用的与时间相关的命令:
(1)date:显示当前系统日期和时间。
(2)cal:显示当前月份的日历。
(3)clock:显示硬件时钟时间。
(4)timedatectl:用于管理系统时钟和时区。
(5)hwclock:用于读取和设置硬件时钟。

##内网环境中手动设置时间步骤:
1.使用 date 命令查看当前时间和日期。
2.关闭 NTP 服务,以防止它在后台同步时间。
systemctl stop ntpd       # CentOS/RHEL 7
systemctl stop chronyd    # CentOS/RHEL 8

3.使用 date 命令手动设置正确的时间和日期。例如,要将系统时间设置为 20235613:30:00:
date -s "2023-05-06 13:30:00"

4.修改硬件时钟,以便下次重启时系统时间不会回到原来的不准确时间:
hwclock --systohc

5.启动 NTP 服务,以便在未来保持时间同步:
systemctl start ntpd      # CentOS/RHEL 7
systemctl start chronyd   # CentOS/RHEL 8

1.7 配置ulimit

在部署 Kubernetes 集群时,需要配置 ulimit(用户限制)参数。ulimit 是一个系统级别的参数,用于控制每个用户进程能够使用的资源(如文件句柄、内存、CPU 时间等)的数量。在 Kubernetes 集群中,各个组件和服务需要同时运行大量的进程,因此需要适当调整 ulimit 参数,以确保系统能够正常运行,并能够满足 Kubernetes 的性能要求。需要注意的是,在修改 ulimit 参数时,应该根据系统的实际情况进行调整,以充分利用系统资源,并避免资源浪费。

#所有节点配置ulimit 
ulimit -SHn 65535
cat >> /etc/security/limits.conf <<EOF
* soft nofile 655360
* hard nofile 131072
* soft nproc 655350
* hard nproc 655350
* seft memlock unlimited
* hard memlock unlimitedd
EOF

1.8 安装ipvsadm

在 Kubernetes 集群中,使用 IPVS 作为负载均衡器,可以提高集群的性能和可靠性。IPVS(IP Virtual Server)是 Linux 内核中的一个负载均衡器,它能够将网络流量分发到不同的后端服务器上,以实现负载均衡和高可用性。

为了在 Kubernetes 集群中使用 IPVS,需要先安装 ipvsadm 工具。ipvsadm 是一个命令行工具,用于配置和管理 IPVS。在 Kubernetes 集群中,使用 ipvsadm 可以轻松地配置 IPVS,并监视其运行状态。

#所有节点安装ipvsadm后修改配置文件:
#yum install -y ipvsadm ipset sysstat conntrack libseccomp
#yum install -y ipset-*.el7.x86_64.rpm lm_sensors-libs-*.el7.x86_64.rpm ipset-libs-*.el7.x86_64.rpm sysstat-*.el7_9.x86_64.rpm  ipvsadm-*.el7.x86_64.rpm  

cat >> /etc/modules-load.d/ipvs.conf <<EOF 
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack
ip_tables
ip_set
xt_set
ipt_set
ipt_rpfilter
ipt_REJECT
ipip
EOF

#重启并查看ipvsadm
systemctl restart systemd-modules-load.service 
lsmod | grep -e ip_vs -e nf_conntrack

内网环境下手动部署kubernetes(v1.26.3)高可用集群_第6张图片

1.9 修改内核参数

在部署 Kubernetes 集群时,需要修改一些内核参数,以便优化集群的性能和稳定性。这些参数包括网络参数、文件系统参数、内存管理参数等。

其中,net.ipv4.ip_forward、net.bridge.bridge-nf-call-iptables 和 net.ipv4.tcp_syncookies 等参数对于 Kubernetes 集群的正常运行非常重要。

#所有节点修改内核参数:
cat <<EOF > /etc/sysctl.d/k8s.conf
net.ipv4.ip_forward = 1                 #开启ipv4转发功能
net.bridge.bridge-nf-call-iptables = 1  #设置bridge netfilter模块允许IPTABLES处理桥接数据包
fs.may_detach_mounts = 1                #允许卸载挂载点失效的文件系统
vm.overcommit_memory=1                  #内存过度分配策略,允许虚拟机使用所有可用的空闲内存,避免oom killer杀掉进程
vm.panic_on_oom=0                       #禁用oom killer

fs.inotify.max_user_watches=89100       #设置可以同时监视的watch数目
fs.file-max=52706963                    #最大允许打开的文件句柄数
fs.nr_open=52706963                     #最大打开文件描述符个数
net.netfilter.nf_conntrack_max=2310720  #最大连接跟踪表项数目

net.ipv4.tcp_keepalive_time = 600       #设置TCP连接在没有数据传输时TCP维持连接的状态最大时间
net.ipv4.tcp_keepalive_probes = 3       #尝试发送几次心跳包才能断开空闲连接
net.ipv4.tcp_keepalive_intvl =15        #两次TCP Keepalive之间的时间间隔
net.ipv4.tcp_max_tw_buckets = 36000     #系统中允许保存的time_wait套接字最大数量
net.ipv4.tcp_tw_reuse = 1               #开启TCP连接复用功能
net.ipv4.tcp_max_orphans = 327680       #系统同时保持TIME_WAIT套接字与CLOSE状态套接字的最大值
net.ipv4.tcp_orphan_retries = 3         #系统清理孤立套接字的最大次数
net.ipv4.tcp_syncookies = 1             #启动SYN Cookies,防止SYN Flood攻击
net.ipv4.tcp_max_syn_backlog = 16384    #TCP半连接队列长度,即允许多少个请求同时进入待处理状态
net.ipv4.ip_conntrack_max = 65536       #最大连接跟踪表项数目
net.ipv4.tcp_max_syn_backlog = 16384    #TCP半连接队列长度,即允许多少个请求同时进入待处理状态
net.ipv4.tcp_timestamps = 0             #禁用时间戳记录
net.core.somaxconn = 16384              #最大并发连接数
net.ipv6.conf.all.disable_ipv6 = 0      #将disable_ipv6设置为0,表示开启IPv6协议。
net.ipv6.conf.default.disable_ipv6 = 0
net.ipv6.conf.lo.disable_ipv6 = 0
net.ipv6.conf.all.forwarding = 1        #开启ipv6转发功能
EOF

#重新加载内核参数配置,并将其应用于当前系统的内核中
sysctl --system

1.10 设置主机名和hosts本地解析

#根据集群规划,各节点设置对应的主机名
hostnamectl set-hostname k8s-master01    #192.168.79.101
hostnamectl set-hostname k8s-master02    #192.168.79.102
hostnamectl set-hostname k8s-master03    #192.168.79.103

#所有节点编辑/etc/hosts文件,添加:
192.168.79.101 k8s-master01
192.168.79.102 k8s-master02
192.168.79.103 k8s-master03
192.168.79.100 vip

#重启或新开窗口验证是否生效:reboot

内网环境下手动部署kubernetes(v1.26.3)高可用集群_第7张图片

总结:本节所有操作如无特别说明,所有k8s节点都应配置好环境(配置免密只需要在一台机器安装sshpass即可,注意ntp区分服务端和客户端)。

二、K8S基本组件安装

(1)所有节点(这里是三台机器)都需要安装容器运行时,即docker和cri-docker,镜像仓库只需要安装在其中一个节点(这里是master01节点:192.168.79.101机器上)即可。
(2)在离线环境中,已经提前下载好相关软件包(本节需要包括docke、cri-docker、k8s、etcd四个软件包)放在master01机器目录下,这里已经存放在/root/kubernetes-v1.26.3/packages/目录下。
(3)联网环境中直接install安装相关软件即可。

在这里插入图片描述

2.1 安装docker

Docker是一种开源的容器化平台,可以将应用程序及其依赖项封装在一个轻量级、可移植的容器中,并在任何支持Docker的环境中运行。每个Docker容器具有自己的文件系统、网络和进程空间,相互隔离,可保证应用程序的稳定性和安全性。

Kubernetes(简称K8s)是一种流行的容器编排平台,可以自动化管理、部署和扩展容器化应用程序。Kubernetes可以管理数千个Docker容器,并确保这些容器在集群中按照需求水平扩展。而Docker则提供了一种轻量级的容器化技术,使得应用程序更易于封装、交付和部署。

在Kubernetes集群中,Docker充当容器引擎的角色,负责创建和运行容器。Kubernetes则通过调度器和控制器等组件来管理这些容器,并根据需要自动扩展或缩小容器数量,以满足应用程序的需求。因此,Docker在Kubernetes集群中起到了关键的作用,为应用程序的部署和管理提供了基础设施支持。

不过,从Kubernetes 1.20版本开始,官方推荐使用CRI-O或containerd等其他容器运行时接口(CRI)兼容的容器引擎,而不是直接使用Docker。

(1)在离线环境下,创建了一个config目录存放相关配置文件,这里是在/root/kubernetes-v1.26.3/config/目录下
(2)在/root/kubernetes-v1.26.3/config/目录下创建containerd.service、docker.service、docker.socket、daemon.json这四个文件

1.containerd.service文件内容如下:

cat > /root/kubernetes-v1.26.3/config/containerd.service << EOF
[Unit]
Description=containerd container runtime
Documentation=https://containerd.io
After=network.target local-fs.target

[Service]
ExecStartPre=-/sbin/modprobe overlay
ExecStart=/usr/bin/containerd
Type=notify
Delegate=yes
KillMode=process
Restart=always
RestartSec=5
LimitNPROC=infinity
LimitCORE=infinity
LimitNOFILE=1048576
TasksMax=infinity
OOMScoreAdjust=-999

[Install]
WantedBy=multi-user.target
EOF

2.docker.service文件内容如下:

cat > /root/kubernetes-v1.26.3/config/docker.service << EOF
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service containerd.service
Wants=network-online.target
Requires=docker.socket containerd.service

[Service]
Type=notify
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
ExecReload=/bin/kill -s HUP 
TimeoutSec=0
RestartSec=2
Restart=always
StartLimitBurst=3
StartLimitInterval=60s
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TasksMax=infinity
Delegate=yes
KillMode=process
OOMScoreAdjust=-500

[Install]
WantedBy=multi-user.target
EOF

3.docker.socket文件内容如下:

cat > /root/kubernetes-v1.26.3/config/docker.socket << EOF
[Unit]
Description=Docker Socket for the API

[Socket]
ListenStream=/var/run/docker.sock
#如果需要开启docker组可放开以下三个命令
#SocketMode=0660
#SocketUser=root
#SocketGroup=docker

[Install]
WantedBy=sockets.target

EOF

4.daemon.json文件内容如下:

cat > /root/kubernetes-v1.26.3/config/daemon.json << EOF
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "insecure-registries":["0.0.0.0/0"],
  "max-concurrent-downloads": 10,
  "log-driver": "json-file",
  "log-level": "warn",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
    },
  "data-root": "/var/lib/docker"
}
EOF
#daemon.json文件说明:
{
  "exec-opts": ["native.cgroupdriver=systemd"],   // 使用systemd作为cgroup driver
  "insecure-registries":["0.0.0.0/0"],            // 允许拉取任意仓库的镜像
  "max-concurrent-downloads": 10,                 // 最大并发下载镜像数设置为10
  "log-driver": "json-file",                      // 日志驱动
  "log-level": "warn",                            // 日志级别
  "log-opts": {
    "max-size": "10m",                            // 单个日志文件大小上限
    "max-file": "3"                               // 最多保留日志文件数
  },
  "data-root": "/var/lib/docker"                  // docker存储数据的根目录
}
#进入软件包目录,解压docker压缩包
cd /root/kubernetes-v1.26.3/packages/
tar xf docker-*.tgz 

#拷贝相关文件到对应目录下
mkdir -p /etc/docker
cp docker/* /usr/bin/
cp /root/kubernetes-v1.26.3/config/daemon.json /etc/docker/
cp /root/kubernetes-v1.26.3/config/{containerd.service,docker.service,docker.socket} /etc/systemd/system/
#启动docker并设置开机自启
#如果socker文件里开启了docker组则需创建docker组
#groupadd docker
systemctl daemon-reload
systemctl start containerd docker.socket docker
systemctl enable containerd docker.socket docker
systemctl status docker
#在其他k8s节点执行相同的操作安装docker

内网环境下手动部署kubernetes(v1.26.3)高可用集群_第8张图片

2.2 安装镜像仓库

说明:
(1)如果是联网环境直接跳过此步,使用官方镜像仓库即可。
(2)在内网环境下,需要安装镜像仓库来存储相关镜像。提前在联网机器下载好相关镜像并拷贝到内网环境中。
(3)需要注意的是,后续相关配置文件、yaml文件使用到镜像时,务必注意镜像名(仓库)是否正确。

1.联网环境拉取相关镜像:
#calico.yaml需要镜像:
docker pull registry.cn-hangzhou.aliyuncs.com/chenby/cni:master
docker pull registry.cn-hangzhou.aliyuncs.com/chenby/node:master
docker pull registry.cn-hangzhou.aliyuncs.com/chenby/kube-controllers:master
docker pull registry.cn-hangzhou.aliyuncs.com/chenby/typha:master

#coredns.yaml、metric.yaml、dashboard.yaml需要镜像:
docker pull registry.cn-hangzhou.aliyuncs.com/chenby/coredns:v1.10.0
docker pull registry.cn-hangzhou.aliyuncs.com/chenby/metrics-server:v0.5.2
docker pull kubernetesui/dashboard:v2.7.0
docker pull kubernetesui/metrics-scraper:v1.0.8

#cri-docker.service文件需要镜像:
docker pull registry.aliyuncs.com/google_containers/pause:3.7

#镜像仓库镜像以及其他相关镜像:
docker pull registry
docker pull busybox:1.28
docker pull registry.cn-hangzhou.aliyuncs.com/chenby/pause:3.6 
docker pull quay.io/coreos/etcd:v3.5.4


2.镜像打包保存到本地:
docker save 镜像名:版本号 -o 镜像包名,示例如下:
docker save registry.cn-hangzhou.aliyuncs.com/chenby/cni:master -o cni.tar 

3.其它镜像打包同理不再赘述,打包后拷贝到内网环境中解压到本地即可:
docker load < file.tar

4.拓展学习--总结常用的一些与Docker镜像相关的命令:
(1)docker images:列出本地所有的Docker镜像。
(2)docker pull <image>:从Docker Hub或其他指定的镜像仓库中下载一个镜像。
(3)docker push <image>:将本地的Docker镜像推送到Docker Hub或其他指定的镜像仓库中。
(4)docker build -t <tag> <path> . :使用指定标签(tag)和路径(path)构建Docker镜像。
(5)docker run <image>:启动一个基于指定镜像的容器。
(6)docker tag <old_image> <new_image>:为一个已有的镜像打上新的标签(tag)。
(7)docker rmi <image>:删除一个本地的Docker镜像。
(8)docker inspect <image>:显示一个Docker镜像的详细信息。
(9)docker save <image> > <file.tar>:将一个Docker镜像保存成一个tar文件,以便在另一台机器上加载。
(10)docker load < <file.tar>:从一个tar文件中加载一个Docker镜像。

内网环境下手动部署kubernetes(v1.26.3)高可用集群_第9张图片

#安装镜像仓库操作只需在master01执行
#解压镜像仓库镜像,解压/images目录下的所有镜像包
cd /root/kubernetes-v1.26.3/images
for file in *.tar; do docker load < "$file"; done

#批量给镜像重新打tag后查看镜像(改为实际的仓库地址):
for image in $(docker images --format "{{.Repository}}:{{.Tag}}")
do
    docker tag $image 192.168.79.101:5000/${image#*/}
done
docker images | grep 192.168.79.101:5000
#创建本地镜像映射地址
mkdir -p /data/docker/dockerImages

#配置 Docker 镜像仓库的参数,包括存储方式、网络配置、健康检查等。重点是配置了仓库镜像的可删除属性
cat > /data/docker/config.yml << EOF
version: 0.1
log:
  fields:
    service: registry             # 日志服务名
storage:
  delete:
    enabled: true                 # 允许删除镜像
  cache:
    blobdescriptor: inmemory      # blob描述符采用内存缓存
  filesystem:
    rootdirectory: /var/lib/registry    # 镜像存储目录
http:
  addr: :5000                           # 监听端口
  headers:
    X-Content-Type-Options: [nosniff]   # 设置HTTP响应头
health:
  storagedriver:
    enabled: true                 # 开启健康检查
    interval: 10s                 # 每次检查间隔时间
    threshold: 3                  # 最大故障次数
EOF
#启动镜像仓库容器,-d 表示以后台方式运行容器,-p 表示把主机的 5000 端口映射到容器的 5000 端口;
#把宿主机上的 /data/docker/dockerImages 目录挂载到容器内的 /var/lib/registry 目录;
#把宿主机上的 /data/docker/config.yml 文件挂载到容器内的 /etc/docker/registry/config.yml 文件;
#设置当容器异常退出时,自动重启容器:
docker run -d \
    -p 5000:5000 \
    -v /data/docker/dockerImages:/var/lib/registry \
    -v /data/docker/config.yml:/etc/docker/registry/config.yml \
    --restart=always \
    --name registry \
    registry:latest

#使用 awk 工具对所有镜像进行筛选,只保留镜像名称为 "192.168.79.101:5000/" 开头的镜像;
#循环处理每个镜像,将筛选出来的镜像进行打标签,即 docker tag 命令;
#将打好标签的镜像推送至远程 Docker 镜像仓库,即 docker push 命令:
images=$(docker images | awk '$1 ~ /^192.168.79.101:5000\// {print $1 ":" $2}')
for image in $images
do
  docker tag $image 192.168.79.101:5000/$(echo $image | cut -d '/' -f 2-)
  docker push 192.168.79.101:5000/$(echo $image | cut -d '/' -f 2-)
done

#验证:在安装了docker的所有节点查看能否访问到192.168.79.101:5000仓库
curl http://192.168.79.101:5000/v2/_catalog

内网环境下手动部署kubernetes(v1.26.3)高可用集群_第10张图片

#拓展总结
##常用 Docker 命令的具体用法如下:
1.docker run:启动一个容器并运行一个镜像。常见选项包括:
  -d:以后台守护进程方式运行容器。
  -p:将容器端口映射到主机端口。
  -v:将容器内的目录或文件挂载到主机上。
  --name:指定容器名称。
  -e:设置环境变量。
  --rm:当容器退出时自动删除该容器。

2.docker ps:列出运行中的容器。常见选项包括:
  -a:列出所有的容器(包括已停止的)。
  -q:只显示容器 ID。

3.docker build:使用 Dockerfile 构建一个新的 Docker 镜像。常见选项包括:
  -t:为新构建的镜像指定名称和标签。
  -f:指定要使用的 Dockerfile 文件路径。
 
4.docker stop:停止运行中的容器。常见选项包括:
  -t:指定超时时间,单位为秒。

5.docker rm:删除一个或多个容器。常见选项包括: 
  -f:强制删除正在运行的容器。
  -v:同时删除与容器关联的数据卷。
  -l:同时删除容器的链接。

6.docker logs:查看容器的日志输出。常见选项包括:
  -f:跟踪容器的日志输出。
  --tail:只显示最后几行日志。
  --since 和 --until:根据时间范围过滤日志输出。
  
7.docker exec:在正在运行的容器中执行命令。常见选项包括:
  -it:以交互式终端方式进入容器。
  -e:指定环境变量。

2.3 安装cri-docker

说明:
(1)从Kubernetes 1.20版本开始,官方不再推荐使用Docker作为容器运行时,建议使用CRI作为统一的容器接口。因为CRI提供了更加灵活的接口,可以与多种容器运行时进行交互。
(2)cri-docker是一个基于Docker的CRI适配器,用于在Kubernetes集群中使用Docker作为容器运行时。使用cri-docker,可以在Kubernetes集群中轻松使用Docker镜像来构建和运行应用程序。同时,cri-docker还能提供Docker API兼容性,这样就可以通过Docker命令行工具来操作Kubernetes集群中的容器,这样既方便又熟悉。需要注意的是,cri-docker并不是默认的容器运行时,需要手动安装和配置cri-docker,才能在Kubernetes集群中使用Docker作为容器运行时。
(3)在/root/kubernetes-v1.26.3/config/目录下创建cri-docker.service、cri-docker.socket两个文件。

1.cri-docker.service文件内容如下:

#注意将ExecStart=/usr/bin/cri-dockerd...里的镜像修改为自己镜像仓库对应的镜像。
cat > /root/kubernetes-v1.26.3/config/cri-docker.service << EOF
[Unit]
Description=CRI Interface for Docker Application Container Engine
Documentation=https://docs.mirantis.com
After=network-online.target firewalld.service docker.service
Wants=network-online.target
Requires=cri-docker.socket

[Service]
Type=notify
ExecStart=/usr/bin/cri-dockerd --network-plugin=cni --pod-infra-container-image=192.168.79.101:5000/google_containers/pause:3.7
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
StartLimitBurst=3
StartLimitInterval=60s

LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity

TasksMax=infinity
Delegate=yes
KillMode=process

[Install]
WantedBy=multi-user.target
EOF

2.cri-docker.socket文件内容如下:

cat > /root/kubernetes-v1.26.3/config/cri-docker.socket << EOF
[Unit]
Description=CRI Docker Socket for the API
PartOf=cri-docker.service

[Socket]
ListenStream=%t/cri-dockerd.sock
#如果需要开启docker组可放开以下三个命令
#SocketMode=0660
#SocketUser=root
#SocketGroup=docker

[Install]
WantedBy=sockets.target
EOF
#解压cri-docker安装包后拷贝到/usr/bin/目录下
cd /root/kubernetes-v1.26.3/packages
tar xf cri-dockerd-0.3.0.amd64.tgz

#拷贝相关文件到对应目录下
cp cri-dockerd/cri-dockerd /usr/bin/
chmod +x /usr/bin/cri-dockerd
cp /root/kubernetes-v1.26.3/config/cri-docker.service /usr/lib/systemd/system/
cp /root/kubernetes-v1.26.3/config/cri-docker.socket /usr/lib/systemd/system/

#启动cri-docker并查看运行状态及版本
systemctl daemon-reload
systemctl enable cri-docker && systemctl start cri-docker
systemctl status cri-docker
cri-dockerd --version
#在其他master节点执行相同的操作安装cri-docker

内网环境下手动部署kubernetes(v1.26.3)高可用集群_第11张图片

2.4 安装k8s与etcd组件

#解压并安装 Kubernetes 的二进制文件,指定要提取的文件列表将文件提取到 /usr/local/bin 目录中
cd /root/kubernetes-v1.26.3/packages/
tar -xf kubernetes-server-linux-amd64.tar.gz  --strip-components=3 -C /usr/local/bin kubernetes/server/bin/kube{let,ctl,-apiserver,-controller-manager,-scheduler,-proxy}

#解压etcd安装文件,将 etcd 二进制文件移动到 /usr/local/bin目录中
tar -xf etcd*.tar.gz && mv etcd-*/etcd /usr/local/bin/ && mv etcd-*/etcdctl /usr/local/bin/

#其他k8s节点执行相同操作安装相关etcd和k8s组件
#所有节点上验证docker和cri-docker是否成功启动
#注意master节点有2个etcd组件、6个k8s组件,worker节点可只有kubectl和kube-proxy组件
systemctl is-active docker cri-docker
ls /usr/local/bin/
kubelet --version && etcdctl version

内网环境下手动部署kubernetes(v1.26.3)高可用集群_第12张图片

总结:本节所有操作如无特别说明,所有k8s节点都应安装docker和cri-docker,以及/usr/local/bin/目录下查看是否有相关文件,镜像仓库只需要安装在其中一台机器上。

三、相关证书生成

以下 JSON 文件定义了一个证书签名请求(Certificate Signing Request,CSR)。其中,一些常见的字段含义如下:

(1)CN (Common Name):这是证书中的“公用名称”字段,etcd/kube-apiserver 在证书签发时会将该字段作为请求用户名(User Name)。在 TLS 证书中,通常会将该字段设置为服务的域名或 IP 地址以验证其身份的合法性。
(2)O (Organization):这个字段通常表示证书使用者属于的组 (Group),在后续启用 RBAC 等需要授权管理的场景中非常重要,可以作为权限控制的依据。
(3)C (Country):国家名称缩写
(4)ST (State):州、省
(5)L (Locality):地区、城市
(6)OU (Organization Unit Name):组织单位名称、部门
(7)此外,JSON 文件还需要定义证书相关的其他信息,例如证书的密钥算法、大小、有效期等。这里证书年限被设置为100年("expiry": "876000h")。

注意以下JSON 文件是用来生成 CA 证书签名请求的,而不是普通的 TLS 证书签名请求。因此,其中的各个字段有些许不同
#在所有节点上创建存放证书相关的json文件的目录
mkdir -p /root/pki 

#证书相关的所有json文件是通用的,在所有节点上一次性生成即可
cd /root/pki
cat > admin-csr.json << EOF 
{
  "CN": "admin",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "Beijing",
      "L": "Beijing",
      "O": "system:masters",
      "OU": "Kubernetes-manual"
    }
  ]
}
EOF

cat > ca-config.json << EOF 
{
  "signing": {
    "default": {
      "expiry": "876000h"
    },
    "profiles": {
      "kubernetes": {
        "usages": [
            "signing",
            "key encipherment",
            "server auth",
            "client auth"
        ],
        "expiry": "876000h"
      }
    }
  }
}
EOF

cat > etcd-ca-csr.json  << EOF 
{
  "CN": "etcd",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "Beijing",
      "L": "Beijing",
      "O": "etcd",
      "OU": "Etcd Security"
    }
  ],
  "ca": {
    "expiry": "876000h"
  }
}
EOF

cat > front-proxy-ca-csr.json  << EOF 
{
  "CN": "kubernetes",
  "key": {
     "algo": "rsa",
     "size": 2048
  },
  "ca": {
    "expiry": "876000h"
  }
}
EOF

cat > kubelet-csr.json  << EOF 
{
  "CN": "system:node:\$NODE",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "L": "Beijing",
      "ST": "Beijing",
      "O": "system:nodes",
      "OU": "Kubernetes-manual"
    }
  ]
}
EOF

cat > manager-csr.json << EOF 
{
  "CN": "system:kube-controller-manager",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "Beijing",
      "L": "Beijing",
      "O": "system:kube-controller-manager",
      "OU": "Kubernetes-manual"
    }
  ]
}
EOF

cat > apiserver-csr.json << EOF 
{
  "CN": "kube-apiserver",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "Beijing",
      "L": "Beijing",
      "O": "Kubernetes",
      "OU": "Kubernetes-manual"
    }
  ]
}
EOF

cat > ca-csr.json   << EOF 
{
  "CN": "kubernetes",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "Beijing",
      "L": "Beijing",
      "O": "Kubernetes",
      "OU": "Kubernetes-manual"
    }
  ],
  "ca": {
    "expiry": "876000h"
  }
}
EOF

cat > etcd-csr.json << EOF 
{
  "CN": "etcd",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "Beijing",
      "L": "Beijing",
      "O": "etcd",
      "OU": "Etcd Security"
    }
  ]
}
EOF

cat > front-proxy-client-csr.json  << EOF 
{
  "CN": "front-proxy-client",
  "key": {
     "algo": "rsa",
     "size": 2048
  }
}
EOF

cat > kube-proxy-csr.json  << EOF 
{
  "CN": "system:kube-proxy",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "Beijing",
      "L": "Beijing",
      "O": "system:kube-proxy",
      "OU": "Kubernetes-manual"
    }
  ]
}
EOF

cat > scheduler-csr.json << EOF 
{
  "CN": "system:kube-scheduler",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "Beijing",
      "L": "Beijing",
      "O": "system:kube-scheduler",
      "OU": "Kubernetes-manual"
    }
  ]
}
EOF
#注意!以下证书生成操作在master01节点生成etcd和k8s证书相关文件即可,然后复制相关文件到其他节点
#首先在master01上将证书生成工具cfssl解压并拷贝到相关目录并赋权
#wget "https://github.com/cloudflare/cfssl/releases/download/v1.6.1/cfssl_1.6.2_linux_amd64" -O /usr/local/bin/cfssl
#wget "https://github.com/cloudflare/cfssl/releases/download/v1.6.1/cfssljson_1.6.2_linux_amd64" -O /usr/local/bin/cfssljson

cd /root/kubernetes-v1.26.3/packages/
cp cfssl_*_linux_amd64 /usr/local/bin/cfssl
cp cfssljson_*_linux_amd64 /usr/local/bin/cfssljson
chmod +x /usr/local/bin/cfssl /usr/local/bin/cfssljson

3.1 生成etcd证书

在 Kubernetes 中,etcd 是一个可靠、高性能和分布式的键值存储系统,用于存储 Kubernetes 集群的状态和配置信息。etcd 作为 Kubernetes 的数据后端,是整个集群的核心组件之一。因此,需要生成 etcd 集群的证书,用于加密和验证 etcd 集群中各个节点之间的通信,并确保只有经过授权的实体才能访问 etcd 数据库。

#创建etcd证书存放目录
mkdir /etc/etcd/ssl -p

#生成etcd证书和密钥,修改-hostname为签发证书的主机名和 IP 地址列表
cd /root/pki
#生成etcd集群的根证书
cd /root/pki
cfssl gencert -initca etcd-ca-csr.json | cfssljson -bare /etc/etcd/ssl/etcd-ca
cfssl gencert \
   -ca=/etc/etcd/ssl/etcd-ca.pem \
   -ca-key=/etc/etcd/ssl/etcd-ca-key.pem \
   -config=ca-config.json \
   -hostname=127.0.0.1,k8s-master01,k8s-master02,k8s-master03,192.168.79.101,192.168.79.102,192.168.79.103 \
   -profile=kubernetes \
   etcd-csr.json | cfssljson -bare /etc/etcd/ssl/etcd
#说明:以上命令使用CloudFlare 的 SSL 工具(CFSSL)来生成 Kubernetes API Server的证书和密钥文件。使用以下参数:
-ca:指定 CA 根证书文件路径。
-ca-key:指定 CA 根证书对应的私钥文件路径。
-config:指定证书配置文件路径。
-hostname:指定 API Server 可接受的主机名或 IP 地址列表。
-profile:指定证书配置文件中定义的 profile 名称。
apiserver-csr.json:指定 CSR 文件路径,描述了要生成的证书的详细信息。
cfssljson -bare /etc/kubernetes/pki/apiserver:将生成的证书和密钥文件输出到指定路径下。

内网环境下手动部署kubernetes(v1.26.3)高可用集群_第13张图片

3.2 生成apiserver证书

Kubernetes API Server 是 Kubernetes 的核心组件之一,它作为整个集群的控制平面,负责处理用户请求、管理容器状态等操作。使用证书来加密和验证 Kubernetes API Server 和其他组件之间的通信可以确保数据传输的安全性和可靠性,避免未经授权的访问或数据泄露。

#创建k8s证书存放目录
mkdir -p /etc/kubernetes/pki

#签发根证书json文件,以下所有证书生成操作在json文件目录下执行
cd /root/pki
cfssl gencert -initca ca-csr.json | cfssljson -bare /etc/kubernetes/pki/ca

#注意:10.96.0.1是service网段的第一个地址;192.168.79.100为高可用节点ip地址
cfssl gencert   \
-ca=/etc/kubernetes/pki/ca.pem   \
-ca-key=/etc/kubernetes/pki/ca-key.pem   \
-config=ca-config.json   \
-hostname=10.96.0.1,192.168.79.100,127.0.0.1,kubernetes,kubernetes.default,kubernetes.default.svc,kubernetes.default.svc.cluster,kubernetes.default.svc.cluster.local \
-profile=kubernetes   apiserver-csr.json | cfssljson -bare /etc/kubernetes/pki/apiserver

3.3 生成front-proxy-client证书

Kubernetes 的前置代理(Front Proxy)是一种访问控制机制,它允许仅限于特定受信任的客户端访问 Kubernetes API Server。前置代理作为 API Server 和客户端之间的中介,用于处理请求和响应,并验证客户端的身份和权限。前置代理可以确保只有经过授权的客户端才能访问 Kubernetes 的 API Server。前置代理在 Kubernetes 中有多个作用,包括:

(1)认证和授权:前置代理可以对客户端进行身份验证和授权,并确保只有经过授权的客户端才能访问 Kubernetes API Server。
(2)加密通信:前置代理可以使用 HTTPS 等协议对客户端和 API Server 之间的通信进行加密,以保护集群的安全性。
(3)负载均衡:前置代理可以作为负载均衡器,将客户端请求分配给多个 API Server 实例,以提高集群的可用性和性能。
(4)请求转发:前置代理可以将某些请求转发到其他服务或端点,例如认证服务、监控服务等。

总之,前置代理是 Kubernetes 安全和可靠性的重要组成部分,它能够帮助集群管理员管理和保护 Kubernetes 集群中的资源和信息。

#签发证书,警告忽略
cfssl gencert -initca front-proxy-ca-csr.json | cfssljson -bare /etc/kubernetes/pki/front-proxy-ca 

cfssl gencert  \
-ca=/etc/kubernetes/pki/front-proxy-ca.pem   \
-ca-key=/etc/kubernetes/pki/front-proxy-ca-key.pem   \
-config=ca-config.json   \
-profile=kubernetes   front-proxy-client-csr.json | cfssljson -bare /etc/kubernetes/pki/front-proxy-client

3.4 生成controller-manage的证书

Kubernetes Controller Manager 是 Kubernetes 的核心组件之一,它负责监控集群状态、自动修复故障、调度 Pod 等操作。使用证书来加密和验证 Controller Manager 和 API Server 之间的通信可以确保数据传输的安全性和可靠性,避免未经授权的访问或数据泄露。

#签发证书,警告忽略
cfssl gencert \
   -ca=/etc/kubernetes/pki/ca.pem \
   -ca-key=/etc/kubernetes/pki/ca-key.pem \
   -config=ca-config.json \
   -profile=kubernetes \
   manager-csr.json | cfssljson -bare /etc/kubernetes/pki/controller-manager
   
#这里--server=https://192.168.79.100:6443(高可用节点ip:端口6443)
#设置集群参数
kubectl config set-cluster kubernetes \
     --certificate-authority=/etc/kubernetes/pki/ca.pem \
     --embed-certs=true \
     --server=https://192.168.79.100:6443 \
     --kubeconfig=/etc/kubernetes/controller-manager.kubeconfig
	 
#设置上下文参数
kubectl config set-context system:kube-controller-manager@kubernetes \
    --cluster=kubernetes \
    --user=system:kube-controller-manager \
    --kubeconfig=/etc/kubernetes/controller-manager.kubeconfig
	
#设置客户端认证参数
kubectl config set-credentials system:kube-controller-manager \
     --client-certificate=/etc/kubernetes/pki/controller-manager.pem \
     --client-key=/etc/kubernetes/pki/controller-manager-key.pem \
     --embed-certs=true \
     --kubeconfig=/etc/kubernetes/controller-manager.kubeconfig
	 
#设置默认上下文
kubectl config use-context system:kube-controller-manager@kubernetes \
     --kubeconfig=/etc/kubernetes/controller-manager.kubeconfig
#说明:以上命令是用来配置 Kubernetes 集群的 kubeconfig文件,包括设置集群参数、上下文参数和客户端认证参数,并将它们嵌入到 kubeconfig 文件中。
#其中set-cluster 命令用于设置集群参数,set-context 命令用于设置上下文参数,set-credentials 命令用于设置客户端认证参数,use-context 命令用于设置默认上下文。这些命令都需要指定 kubeconfig 文件的路径。
#设置集群参数
kubectl config set-cluster kubernetes \
--certificate-authority=/etc/kubernetes/pki/ca.pem \                #指定集群CA证书
--embed-certs=true \                                                #将证书嵌入到 kubeconfig 文件中
--server=https://192.168.79.100:6443 \                              #指定 API Server 的地址和端口
--kubeconfig=/etc/kubernetes/controller-manager.kubeconfig          #kubeconfig 文件路径

#设置上下文参数
kubectl config set-context system:kube-controller-manager@kubernetes \
--cluster=kubernetes \                                               #指定使用的集群
--user=system:kube-controller-manager \                              #指定使用的用户
--kubeconfig=/etc/kubernetes/controller-manager.kubeconfig           #kubeconfig 文件路径

#设置客户端认证参数
kubectl config set-credentials system:kube-controller-manager \
--client-certificate=/etc/kubernetes/pki/controller-manager.pem \    #指定客户端证书
--client-key=/etc/kubernetes/pki/controller-manager-key.pem \        #指定客户端证书私钥
--embed-certs=true \                                                 #将证书嵌入到 kubeconfig 文件中
--kubeconfig=/etc/kubernetes/controller-manager.kubeconfig           #kubeconfig 文件路径

#设置默认上下文
kubectl config use-context system:kube-controller-manager@kubernetes \
--kubeconfig=/etc/kubernetes/controller-manager.kubeconfig           #指定 kubeconfig 文件路径,切换当前上下文为指定上下文

内网环境下手动部署kubernetes(v1.26.3)高可用集群_第14张图片

3.5 生成scheduler的证书

Kubernetes Scheduler 是 Kubernetes 的核心组件之一,它负责监视集群中新创建的 Pod,并为其选择一个合适的节点进行调度。为了保证通信的安全性,Kubernetes 要求所有的组件间通信都必须使用 TLS 加密。

#方法同上,签发证书,警告忽略
cfssl gencert \
   -ca=/etc/kubernetes/pki/ca.pem \
   -ca-key=/etc/kubernetes/pki/ca-key.pem \
   -config=ca-config.json \
   -profile=kubernetes \
   scheduler-csr.json | cfssljson -bare /etc/kubernetes/pki/scheduler

#这里--server=https://192.168.79.100:6443(高可用节点ip:端口6443)
#设置kubeconfig文件中的kubernetes集群信息,包括CA证书、API Server地址和端口等参数。
kubectl config set-cluster kubernetes \
     --certificate-authority=/etc/kubernetes/pki/ca.pem \
     --embed-certs=true \
     --server=https://192.168.79.100:6443 \
     --kubeconfig=/etc/kubernetes/scheduler.kubeconfig

#设置kubeconfig文件中的system:kube-scheduler用户信息,包括客户端证书和私钥等参数。
kubectl config set-credentials system:kube-scheduler \
     --client-certificate=/etc/kubernetes/pki/scheduler.pem \
     --client-key=/etc/kubernetes/pki/scheduler-key.pem \
     --embed-certs=true \
     --kubeconfig=/etc/kubernetes/scheduler.kubeconfig

#设置kubeconfig文件中的context信息,包括使用的集群和用户信息。
kubectl config set-context system:kube-scheduler@kubernetes \
     --cluster=kubernetes \
     --user=system:kube-scheduler \
     --kubeconfig=/etc/kubernetes/scheduler.kubeconfig

#设置kubeconfig文件中使用的上下文为system:kube-scheduler@kubernetes
kubectl config use-context system:kube-scheduler@kubernetes \
     --kubeconfig=/etc/kubernetes/scheduler.kubeconfig

3.6 生成admin的证书

Kubernetes 的管理员证书用于管理 Kubernetes 集群,例如通过 kubectl 命令行工具对集群进行管理、监控和调试。管理员证书授予用户或组织访问 Kubernetes API Server 的权限,并允许其执行敏感操作,如创建、删除 Pod、查看集群状态等操作。管理员证书的安全非常重要,因为 admin 证书代表了对 Kubernetes 集群的完全控制权。只有授权的用户才能持有该证书,以确保 Kubernetes 集群的安全性和可靠性。

#方法同上,签发证书,警告忽略
cfssl gencert \
   -ca=/etc/kubernetes/pki/ca.pem \
   -ca-key=/etc/kubernetes/pki/ca-key.pem \
   -config=ca-config.json \
   -profile=kubernetes \
   admin-csr.json | cfssljson -bare /etc/kubernetes/pki/admin

#这里--server=https://192.168.79.100:6443(高可用节点ip:端口6443)
kubectl config set-cluster kubernetes     \
  --certificate-authority=/etc/kubernetes/pki/ca.pem     \
  --embed-certs=true     \
  --server=https://192.168.79.100:6443     \
  --kubeconfig=/etc/kubernetes/admin.kubeconfig

kubectl config set-credentials kubernetes-admin  \
  --client-certificate=/etc/kubernetes/pki/admin.pem     \
  --client-key=/etc/kubernetes/pki/admin-key.pem     \
  --embed-certs=true     \
  --kubeconfig=/etc/kubernetes/admin.kubeconfig

kubectl config set-context kubernetes-admin@kubernetes    \
  --cluster=kubernetes     \
  --user=kubernetes-admin     \
  --kubeconfig=/etc/kubernetes/admin.kubeconfig

kubectl config use-context kubernetes-admin@kubernetes  \
  --kubeconfig=/etc/kubernetes/admin.kubeconfig

3.7 生成kube-proxy证书

Kubernetes kube-proxy 是一个负责服务发现和负载均衡的组件,它会监视 Kubernetes Service 的变化,并自动更新负载均衡规则。使用证书来加密和验证 kube-proxy 和 API Server 之间的通信可以确保数据传输的安全性和可靠性,避免未经授权的访问或数据泄露。

#方法同上,签发证书,警告忽略
cfssl gencert \
   -ca=/etc/kubernetes/pki/ca.pem \
   -ca-key=/etc/kubernetes/pki/ca-key.pem \
   -config=ca-config.json \
   -profile=kubernetes \
   kube-proxy-csr.json | cfssljson -bare /etc/kubernetes/pki/kube-proxy

#相关环境配置,修改--server为集群的高可用节点+端口号
kubectl config set-cluster kubernetes     \
  --certificate-authority=/etc/kubernetes/pki/ca.pem     \
  --embed-certs=true     \
  --server=https://192.168.79.100:6443     \
  --kubeconfig=/etc/kubernetes/kube-proxy.kubeconfig

kubectl config set-credentials kube-proxy  \
  --client-certificate=/etc/kubernetes/pki/kube-proxy.pem     \
  --client-key=/etc/kubernetes/pki/kube-proxy-key.pem     \
  --embed-certs=true     \
  --kubeconfig=/etc/kubernetes/kube-proxy.kubeconfig

kubectl config set-context kube-proxy@kubernetes    \
  --cluster=kubernetes     \
  --user=kube-proxy     \
  --kubeconfig=/etc/kubernetes/kube-proxy.kubeconfig

kubectl config use-context kube-proxy@kubernetes  \
  --kubeconfig=/etc/kubernetes/kube-proxy.kubeconfig

学习总结:以上有些命令需要在 kubeconfig 文件中设置集群、上下文和认证参数。具体来说,它们的作用如下:
(1)kubectl config set-cluster 命令用于设置集群参数,包括集群的名称、API Server 的地址和端口、CA 证书等。这些参数可以在 kubeconfig 文件中使用,并由 Kubernetes 命令使用以连接到正确的集群。

(2)kubectl config set-context 命令用于设置上下文参数,包括上下文的名称、关联的集群和用户等。上下文定义了用户与集群之间的联系,使用户能够轻松地在不同的集群和用户之间切换。

(3)kubectl config set-credentials 命令用于设置客户端认证参数,包括客户端证书、私钥等。这些参数通常与用户相关联,用于验证用户身份并授予其访问权限。

(4)kubectl config use-context 命令用于设置默认上下文,使用户可以通过简单的命令行选项或环境变量来更改当前的上下文。默认情况下,Kubernetes 将使用名为 default 的上下文,但使用此命令可以更改为其他上下文,从而使用户可以轻松地在不同的集群和用户之间切换。

对于 controller-manager、scheduler、kube-proxy 等 Kubernetes 组件,它们需要使用 kubeconfig 文件中的参数来与 API Server 进行通信并执行其任务。因此,在配置 Kubernetes 组件时,也需要设置正确的集群、上下文和认证参数。这些命令可以帮助管理员轻松地在 kubeconfig 文件中设置这些参数,以确保组件能够正确连接到 Kubernetes 集群。

3.8 创建ServiceAccount Key

#创建用于 Service Account 的私钥和公钥
openssl genrsa -out /etc/kubernetes/pki/sa.key 2048
openssl rsa -in /etc/kubernetes/pki/sa.key -pubout -out /etc/kubernetes/pki/sa.pub

上面的命令是用 OpenSSL 工具生成 Kubernetes ServiceAccount Key,包括私钥和公钥两部分。具体来说:
(1)第一行命令使用 OpenSSL 生成一个 2048 位的 RSA 私钥,保存在 /etc/kubernetes/pki/sa.key 文件中。
(2)第二行命令使用 OpenSSL 提取 sa.key 文件中的公钥,并将其保存在 /etc/kubernetes/pki/sa.pub 文件中。

说明: Kubernetes 的 ServiceAccount 是用于身份验证和授权的一种机制,它允许 Pod 和其他 Kubernetes 对象通过 API Server 访问 Kubernetes 集群中的资源。ServiceAccount 包含了一个唯一的名称和一个与之对应的 Secret,其中Secret就是上述命令生成的sa.key。

sa.key用于对与 ServiceAccount 相关联的 Pod 进行身份认证和授权,以便它们可以访问 Kubernetes 集群中的资源。例如,当一个 Pod 向 API Server 发起请求时,API Server 会验证该请求是否来自于具有相应权限的 ServiceAccount。如果是,则请求被接受并处理;否则,请求将被拒绝。

#将证书发送到其他k8s节点(注意只能在一个master节点生成证书再复制到其他节点)
Master='192.168.79.102 192.168.79.103'  
for NODE in $Master;   
    do echo "copy file to $NODE";   
    ssh $NODE "mkdir -p /etc/kubernetes/pki /etc/etcd/ssl";
    scp /etc/etcd/ssl/* $NODE:/etc/etcd/ssl/;   
    scp -r /etc/kubernetes/* $NODE:/etc/kubernetes/; 
done 

#验证:所有k8s节点中etcd证书相关文件6个,k8s证书相关文件应有26个
ls /etc/etcd/ssl/ | wc -l
ls /etc/kubernetes/pki/ | wc -l

在这里插入图片描述

总结:本节所有操作只需在一个master节点上生成所有证书相关文件,然后分发给其他节点。

四、ETCD集群配置

etcd是一个分布式、可靠的键值存储系统,它用于存储Kubernetes集群中所有节点和组件之间共享的配置数据和状态信息。etcd集群的作用如下:
(1)存储Kubernetes集群的元数据:包括服务、部署、节点等资源对象的元数据。
(2)保持集群状态一致性:etcd通过Raft协议实现强一致性复制,确保了分布式系统中的数据一致性。
(3)故障恢复:etcd支持快照备份和数据恢复,有助于在发生故障时恢复集群状态。
(4)高可用:通过部署多个etcd节点组成的集群,可以实现自动故障转移,提高整个Kubernetes集群的可用性。

总之,在Kubernetes高可用集群中,为了确保etcd的高可用性,通常需要运行一个由多个节点组成的etcd集群。在这个集群中,每个节点都运行一个etcd实例,并通过Raft协议进行通信和同步。这样,即使其中一个节点失效,整个集群仍然可以正常工作,因为其他节点可以接替失效节点的功能,确保Kubernetes集群的可用性和稳定性。

这里在/root/kubernetes-v1.26.3/config/目录下创建etcd.config.yml、etcd.service两个文件。

1.etcd.config.yml文件内容如下:

cat > /root/kubernetes-v1.26.3/config/etcd.config.yml << EOF
name: 'k8s-master01'                           # etcd集群中当前节点的名称
data-dir: /var/lib/etcd                        # 存储数据的目录
wal-dir: /var/lib/etcd/wal                     # 存储WAL数据的目录
snapshot-count: 5000                           # 自动触发快照的阈值
heartbeat-interval: 100                        # 心跳间隔时间
election-timeout: 1000                         # 选举超时时间
quota-backend-bytes: 0                         # 数据库大小限制(0表示不限制)
listen-peer-urls: 'https://192.168.79.101:2380' # 集群内部通信地址
listen-client-urls: 'https://192.168.79.101:2379,http://127.0.0.1:2379' # 外部客户端访问地址
max-snapshots: 3                               # 最多保存的快照文件数
max-wals: 5                                    # 最多保存的WAL文件数

# 跨域资源共享配置
cors:                                          
initial-advertise-peer-urls: 'https://192.168.79.101:2380'  # 初始集群的内部通信地址
advertise-client-urls: 'https://192.168.79.101:2379'        # 初始集群的外部访问地址

# 发现服务配置
discovery:                                      
discovery-fallback: 'proxy'                     # 当DNS解析失败时使用的代理模式
discovery-proxy:                                # 使用代理发现服务时的代理地址
discovery-srv:                                  # 使用SRV记录发现服务时的域名

# 初始集群配置信息
initial-cluster: 'k8s-master01=https://192.168.79.101:2380,k8s-master02=https://192.168.79.102:2380,k8s-master03=https://192.168.79.103:2380' 
initial-cluster-token: 'etcd-k8s-cluster'       # 集群令牌,用于区分不同的集群
initial-cluster-state: 'new'                    # 集群初始状态
strict-reconfig-check: false                    # 是否开启严格重构检查
enable-v2: true                                 # 是否启用v2 API
enable-pprof: true                              # 是否启用pprof调试工具
proxy: 'off'                                    # 是否使用代理
proxy-failure-wait: 5000                        # 代理失败等待时间
proxy-refresh-interval: 30000                   # 代理刷新间隔时间
proxy-dial-timeout: 1000                        # 代理拨号超时时间
proxy-write-timeout: 5000                       # 代理写超时时间
proxy-read-timeout: 0                           # 代理读超时时间

# 客户端传输安全配置
client-transport-security:                      
  cert-file: '/etc/kubernetes/pki/etcd/etcd.pem'           # 客户端证书文件路径
  key-file: '/etc/kubernetes/pki/etcd/etcd-key.pem'        # 客户端密钥文件路径
  client-cert-auth: true                                   # 是否开启客户端证书验证
  trusted-ca-file: '/etc/kubernetes/pki/etcd/etcd-ca.pem'  # 受信任的CA证书文件路径
  auto-tls: true                                           # 是否自动生成TLS证书和密钥

# 对等节点传输安全配置
peer-transport-security:                                 
  cert-file: '/etc/kubernetes/pki/etcd/etcd.pem'           # 对等节点证书文件路径
  key-file: '/etc/kubernetes/pki/etcd/etcd-key.pem'        # 对等节点密钥文件路径
  peer-client-cert-auth: true                              # 是否开启对等节点客户端证书验证
  trusted-ca-file: '/etc/kubernetes/pki/etcd/etcd-ca.pem'  # 受信任的CA证书文件路径
  auto-tls: true                                           # 是否自动生成TLS证书和密钥
debug: false                             # 是否开启调试模式
log-package-levels:                      # 日志级别设置
log-package-levels:                      # 指定不同包的日志级别
log-outputs: [default]                   # 日志输出方式,默认为标准输出
force-new-cluster: false                 # 是否强制创建一个新的集群
EOF

2.etcd.service文件内容如下:

cat > /root/kubernetes-v1.26.3/config/etcd.service << EOF
[Unit]
Description=Etcd Service
Documentation=https://coreos.com/etcd/docs/latest/
After=network.target

[Service]
Type=notify
ExecStart=/usr/local/bin/etcd --config-file=/etc/etcd/etcd.config.yml
Restart=on-failure
RestartSec=10
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
Alias=etcd3.service
EOF
#复制相关文件到对应目录下
cp /root/kubernetes-v1.26.3/yaml/etcd.config.yml /etc/etcd/
cp /root/kubernetes-v1.26.3/config/etcd.service /usr/lib/systemd/system/

#编辑etcd.config.yml文件,在不同节点上修改为当前节点所对应的名称或IP:
vi /etc/etcd/etcd.config.yml
---------------------------------------------------------------------------
1.name:'k8s-master01'  ----修改名称(如这里三个节点分别是是k8s-master01/02/032.listen-peer-urls  ----修改为当前节点IP
3.listen-client-urls  ----修改为当前节点IP
4.initial-advertise-peer-urls  ----修改为当前节点IP
5.advertise-client-urls   ----修改为当前节点IP
6.initial-cluster:    ----修改为实际集群节点IP
---------------------------------------------------------------------------

#创建一个符号链接指向证书目录
mkdir /etc/kubernetes/pki/etcd
ln -s /etc/etcd/ssl/* /etc/kubernetes/pki/etcd/
#所有节点都要启动etcd,查看运行状态
systemctl daemon-reload
systemctl enable etcd && systemctl start etcd && systemctl status etcd

#验证:保证三个节点etcd都处于运行状态,查看etcd集群状态信息
export ETCDCTL_API=3
etcdctl --endpoints="192.168.79.101:2379,192.168.79.102:2379,192.168.79.103:2379" \
  --cacert=/etc/kubernetes/pki/etcd/etcd-ca.pem \
  --cert=/etc/kubernetes/pki/etcd/etcd.pem \
  --key=/etc/kubernetes/pki/etcd/etcd-key.pem \
  endpoint status --write-out=table

内网环境下手动部署kubernetes(v1.26.3)高可用集群_第15张图片

总结:本节每个节点都需要安装etcd组成etcd集群,每个节点的etcd配置文件里注意修改为对应ip即可。

五、Keepalibed高可用配置

(1)Keepalived是一种可以提供基于VRRP协议的高可用性解决方案。它可以将多个服务器(这里是三个,一台为主服务器(MASTER),另外两台是备份服务器(BACKUP))组成一个虚拟IP(VIP)地址,然后将该地址指向其中一台服务器。如果该服务器出现故障,其他服务器可以接管VIP,从而确保服务的高可用性。
(2)在Kubernetes集群中,通过在每个Master节点上安装Keepalived,可以实现对API Server的高可用性。如果有服务器出现问题,Keepalived 会将其从系统中移除,并且同时使用备份服务器代替该服务器的工作,当这台服务器可以正常工作后,Keepalived 再将其放入服务器群中,这个过程是 Keepalived 自动完成的,不需要人工干涉,我们只需要修复出现问题的服务器即可。因此通过keepalived来确保整个Kubernetes集群的正常运行。
(3)Keepalived是用于实现高可用性的虚拟主机控制器,它可以与不同的负载均衡器 (如 Nginx 和 HAProxy) 一起使用,以提高集群的可靠性和可用性。使用 Keepalived 和负载均衡器可以帮助确保集群中的服务器始终保持高可用性,因为它们可以自动检测服务器的健康状况,并在服务器失效时自动纠正。

参考:Keepalived 原理与实战

#首先创建keepalived配置文件
cat > /root/kubernetes-v1.26.3/config/keepalived.conf << EOF
! Configuration File for keepalived

global_defs {
    router_id LVS_DEVEL     # 全局定义
    script_user root        # 脚本运行用户为root用户
    enable_script_security  # 启用脚本安全性检查
}

#这里只使用keepalived,如需使用keepalived + haproxy可放开
#vrrp_script chk_apiserver {                       #用于检测haproxy是否正常
#    script "/etc/keepalived/check_apiserver.sh"   #健康检查脚本
#    interval 5                                    # 每5秒执行一次检测
#    weight -5                                     # 权重变化
#    fall 2                                        #失败计数器阈值
#    rise 1                                        #成功计数器阈值
#}

# VRRP实例
vrrp_instance VI_1 {
    state MASTER                  # 实例状态(MASTER或BACKUP,主=MASTER,从=BACKUP)
    interface ens33               # 注意网卡名是否为ens33
    mcast_src_ip 192.168.79.101   # 当前节点ip
    virtual_router_id 51          # 虚拟路由ID实例,同一集群下所有节点相同
    priority 100                  # 实例优先级越大越优先,这里主=100,从<100
    nopreempt                   # 是否允许抢占
	advert_int 2                # 广告发送间隔
	authentication {            # 身份验证信息
	auth_type PASS              # 认证类型
	auth_pass K8SHA_KA_AUTH     # 认证密码
	}
  
    virtual_ipaddress {
        192.168.79.100            # VIP节点IP
    }
}
EOF    

5.1 安装keepalived

#离线环境下编译过程可能会报各种错误,基本都是缺少编译环境问题,提前准备好zlib、openssl等相关依赖组件(这里依赖包已放在/root/kubernetes-v1.26.3/RPMpackages/keepalived/目录下)
#安装依赖包,解压keepavlived安装包
tar -zxvf /root/kubernetes-v1.26.3/packages/keepalived-2.1.5.tar.gz -C /root/kubernetes-v1.26.3/packages/ 
rpm -Uvh /root/kubernetes-v1.26.3/RPMpackages/keepalived/*.rpm --force --nodeps

#进入解压后目录编译并安装,忽略相关警告
cd /root/kubernetes-v1.26.3/packages/keepalived-2.1.5
./configure --prefix=/usr/local/keepalived
make && make install

内网环境下手动部署kubernetes(v1.26.3)高可用集群_第16张图片

# keepalived默认读取/etc/keepalived/下的keepalived.conf文件
mkdir /etc/keepalived/
cp /root/kubernetes-v1.26.3/config/keepalived.conf /etc/keepalived/
cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/

#这里keepalived规划为:
192.168.79.101  keepalived master(keepalived主节点)
192.168.79.102  keepalived backup(keepalived备份节点1192.168.79.103  keepalived backup(keepalived备份节点2)

#修改keepalived.conf文件:
vi /etc/keepalived/keepalived.conf

#在每个节点上注意修改keepalived配置文件:
-------------------------------------------------------------------
1.state:  ----MASTER(101)或者BACKUP(102103),注意大写
2.Interface  ----当前机器使用的网卡,这里是ens33
3.mcast_src_ip  ----当前机器的ip
4.priority  ----注意备份keepalived节点priority值要小于keepalived主节点(这里是10070505.virtual_ipaddress  ----高可用虚拟ip
--------------------------------------------------------------------

#启动服务,查看状态
systemctl daemon-reload  
systemctl enable keepalived && systemctl start keepalived 
systemctl status keepalived 

内网环境下手动部署kubernetes(v1.26.3)高可用集群_第17张图片

5.2 主节点测试高可用

#安装telnet客户端
rpm -ivh /root/kubernetes-v1.26.3/RPMpackages/telnet/telnet-0.17-66.el7.x86_64.rpm

1.所有master节点都能ping通高可用节点:
ping 192.168.79.100
2.关闭keepalived主节点,高可用节点是否漂移到keepalived备份节点1
ip a | grep inet
-------------------------------------------------------------------------
测试方法:1)在master01机器上查看是否绑定了虚拟IP192.168.79.1002)关闭master01,此时虚拟IP被master02绑定
(3)再次开启master01,虚拟IP重新被master01绑定。
-------------------------------------------------------------------------
3. telnet能访问到虚拟ip端口(安装完apiserver后测试)
telnet 192.168.79.100 6443

内网环境下手动部署kubernetes(v1.26.3)高可用集群_第18张图片

总结:本节需要在两个或多个节点安装keepalived。其中,一个节点作为主服务器,其余节点作为备份服务器。当主服务器出错时,keepalived能够自动切换到其他备份服务器上。需要注意的是,主备服务器的配置文件略有不同。

六、K8S组件配置

在 Kubernetes 集群中,apiserver、controller manager 和 scheduler 是三个核心控制平面组件,它们共同负责集群的管理和协调。
(1)apiserver:Kubernetes API server是集群中的中心控制器,负责提供 Kubernetes API 服务。它是集群内各个组件(如 kubelet、controller manager、scheduler 等)以及外部用户与集群进行交互的主要接口。apiserver 负责处理 API 请求,验证请求的合法性,以及将集群的状态信息存储在 etcd 数据库中。此外,apiserver 还负责集群内部的认证、授权和准入控制。
(2)controller manager:Kubernetes controller manager是一个包含多个控制器的组件,这些控制器负责管理集群中的各种资源。例如,节点控制器负责管理节点的生命周期,复制控制器负责确保 Pod 的副本数量与预期一致,服务控制器负责管理服务的负载均衡等。controller manager 通过不断地检查集群的当前状态,并与期望状态进行比较,来确保集群的稳定运行。
(3)scheduler:Kubernetes scheduler负责将新创建的 Pod 分配到合适的节点上运行。当用户创建一个新的 Pod 时,scheduler 会根据集群中节点的资源使用情况、Pod 的资源需求、亲和性和反亲和性规则等因素,为 Pod 选择一个最佳的节点。然后,scheduler 将 Pod 的信息发送给被选中的节点上的 kubelet,由 kubelet 负责启动和运行 Pod。

在Kubernetes集群中,这三个组件互相配合,相互依赖,以确保集群内部的资源和组件以期望的状态运行。API Server提供API接口,Controller Manager监控集群状态并进行调整,Scheduler进行Pod的调度。这些组件通过API Server进行通信和协作,以保证集群运行的稳定性和可靠性。如果其中任何一个组件出现问题,可能会导致集群无法正常工作,因此在部署Kubernetes集群的过程中,要确保这些组件都处于运行状态。

在/root/kubernetes-v1.26.3/config/目录下创建kube-apiserver.service、kube-controller-manager.service、kube-scheduler.servic三个文件

1.kube-apiserver.service文件内容如下:

cat > /root/kubernetes-v1.26.3/config/kube-apiserver.service << EOF
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/kubernetes/kubernetes
After=network.target

[Service]
ExecStart=/usr/local/bin/kube-apiserver \
      --v=2  \
      --allow-privileged=true  \
      --bind-address=0.0.0.0  \
      --secure-port=6443  \
      --advertise-address=192.168.79.101 \
      --service-cluster-ip-range=10.96.0.0/12  \
      --service-node-port-range=30000-32767  \
      --etcd-servers=https://192.168.79.101:2379,https://192.168.79.102:2379,https://192.168.79.103:2379 \
      --etcd-cafile=/etc/etcd/ssl/etcd-ca.pem  \
      --etcd-certfile=/etc/etcd/ssl/etcd.pem  \
      --etcd-keyfile=/etc/etcd/ssl/etcd-key.pem  \
      --client-ca-file=/etc/kubernetes/pki/ca.pem  \
      --tls-cert-file=/etc/kubernetes/pki/apiserver.pem  \
      --tls-private-key-file=/etc/kubernetes/pki/apiserver-key.pem  \
      --kubelet-client-certificate=/etc/kubernetes/pki/apiserver.pem  \
      --kubelet-client-key=/etc/kubernetes/pki/apiserver-key.pem  \
      --service-account-key-file=/etc/kubernetes/pki/sa.pub  \
      --service-account-signing-key-file=/etc/kubernetes/pki/sa.key  \
      --service-account-issuer=https://kubernetes.default.svc.cluster.local \
      --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname  \
      --enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,ResourceQuota \
	  --authorization-mode=Node,RBAC  \
      --enable-bootstrap-token-auth=true  \
      --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.pem  \
      --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.pem  \
      --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client-key.pem  \
      --requestheader-allowed-names=aggregator  \
      --requestheader-group-headers=X-Remote-Group  \
      --requestheader-extra-headers-prefix=X-Remote-Extra-  \
      --requestheader-username-headers=X-Remote-User \
      --enable-aggregator-routing=true
      # --feature-gates=IPv6DualStack=true
      # --token-auth-file=/etc/kubernetes/token.csv

Restart=on-failure
RestartSec=10s
LimitNOFILE=65535

[Install]
WantedBy=multi-user.target
EOF

2.kube-controller-manager.service文件内容如下:

cat > /root/kubernetes-v1.26.3/config/kube-controller-manager.service << EOF
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/kubernetes/kubernetes
After=network.target

[Service]
ExecStart=/usr/local/bin/kube-controller-manager \
      --v=2 \
      --bind-address=127.0.0.1 \
      --root-ca-file=/etc/kubernetes/pki/ca.pem \
      --cluster-signing-cert-file=/etc/kubernetes/pki/ca.pem \
      --cluster-signing-key-file=/etc/kubernetes/pki/ca-key.pem \
      --service-account-private-key-file=/etc/kubernetes/pki/sa.key \
      --kubeconfig=/etc/kubernetes/controller-manager.kubeconfig \
      --leader-elect=true \
      --use-service-account-credentials=true \
      --node-monitor-grace-period=40s \
      --node-monitor-period=5s \
      --pod-eviction-timeout=2m0s \
      --controllers=*,bootstrapsigner,tokencleaner \
      --allocate-node-cidrs=true \
      --service-cluster-ip-range=10.96.0.0/12 \
      --cluster-cidr=172.16.0.0/12 \
      --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.pem 
      --node-cidr-mask-size-ipv4=24

Restart=always
RestartSec=10s

[Install]
WantedBy=multi-user.target
EOF

3.kube-scheduler.servic文件内容如下:

cat > /root/kubernetes-v1.26.3/config/kube-scheduler.servic << EOF
[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/kubernetes/kubernetes
After=network.target

[Service]
ExecStart=/usr/local/bin/kube-scheduler \
      --v=2 \
      --leader-elect=true \
      --authentication-kubeconfig=/etc/kubernetes/scheduler.kubeconfig \
      --authorization-kubeconfig=/etc/kubernetes/scheduler.kubeconfig \
      --kubeconfig=/etc/kubernetes/scheduler.kubeconfig

Restart=always
RestartSec=10s

[Install]
WantedBy=multi-user.target
EOF

6.1 配置apiserver、controller manager和scheduler

#所有master节点执行相同操作,配置三个组件(工作节点无需配置)
#创建以下目录:
mkdir -p /etc/kubernetes/manifests/ /etc/systemd/system/kubelet.service.d /var/lib/kubelet /var/log/kubernetes
----------------------------------------------------------------------------------------------------------
(1)/etc/kubernetes/manifests/:这个目录用于存放 Kubernetes 静态 Pod 的 YAML 配置文件。
(2)/etc/systemd/system/kubelet.service.d:这个目录用于存放 kubelet 服务的 Systemd 配置文件。
(3)/var/lib/kubelet:这个目录用于存放 kubelet 运行时的数据,例如 Pod 的数据、容器运行时的数据等。
(4)/var/log/kubernetes:这个目录用于存放 Kubernetes 组件的日志文件,例如 kubelet、kube-proxy 等组件的日志。
----------------------------------------------------------------------------------------------------------

#拷贝相关文件到对应目录下
#cp /root/kubernetes-v1.26.3/config/token.csv /etc/kubernetes/pki/
cp /root/kubernetes-v1.26.3/config/kube-apiserver.service /usr/lib/systemd/system/
cp /root/kubernetes-v1.26.3/config/kube-controller-manager.service /usr/lib/systemd/system/
cp /root/kubernetes-v1.26.3/config/kube-scheduler.service /usr/lib/systemd/system/

#kube-scheduler.servic、kube-controller-manager.service注意相关ip网段是否正确
#编辑kube-apiserver.service文件
vi /usr/lib/systemd/system/kube-apiserver.service
---------------------------------------------------
1.--advertise-address  ----当前节点IP地址
2.--etcd-servers   ----etcd集群所有节点
3.--service-cluster-ip-range  ----service网段
---------------------------------------------------

#验证:启动三个组件并查看运行状态
systemctl daemon-reload 
systemctl start kube-apiserver kube-controller-manager kube-scheduler 
systemctl enable kube-apiserver kube-controller-manager kube-scheduler
systemctl is-active kube-apiserver kube-controller-manager kube-scheduler

#测试telnet能访问到虚拟ip端口
telnet 192.168.79.100 6443

内网环境下手动部署kubernetes(v1.26.3)高可用集群_第19张图片

6.2 配置TLS Bootstrapping

在 Kubernetes 中,TLS Bootstrapping 是一种自动为 kubelet 生成和管理 TLS 证书的机制。它的主要目的是确保集群内部通信的安全性。在 Kubernetes 集群中,各个组件(如 API server、kubelet、kube-proxy 等)之间的通信需要加密,以防止数据泄露和中间人攻击。为了实现这一目标,Kubernetes 使用了 TLS 证书来对通信进行加密。

在没有 TLS Bootstrapping 的情况下,需要手动为每个 kubelet 生成 TLS 证书,并将证书分发到各个节点。这个过程既繁琐又容易出错。而通过启用 TLS Bootstrapping,可以简化这个过程,让 Kubernetes 自动为 kubelet 生成和管理 TLS 证书。

TLS Bootstrapping 的工作原理如下:
(1)当 kubelet 首次启动时,它会生成一个私钥和一个证书签名请求(CSR)。
(2)kubelet 将 CSR 发送给 Kubernetes API server。
(3)API server 根据预先定义的角色和权限,对 CSR 进行审批。
(4)一旦 CSR 获得批准,API server 会使用集群的根证书为 kubelet 签发一个 TLS 证书。
(5)kubelet 使用这个 TLS 证书与 API server 进行安全通信。
(6)通过使用 TLS Bootstrapping,您可以确保集群内部通信的安全性,同时简化了证书管理的过程。

#创建bootstrap.secret.yaml文件
mkdir /root/bootstrap
cat > /root/bootstrap/bootstrap.secret.yaml << EOF
apiVersion: v1
kind: Secret
metadata:
  name: bootstrap-token-c8ad9c
  namespace: kube-system
type: bootstrap.kubernetes.io/token
stringData:
  description: "The default bootstrap token generated by 'kubelet '."
  token-id: c8ad9c
  token-secret: 2e4d610cf3e7426e
  usage-bootstrap-authentication: "true"
  usage-bootstrap-signing: "true"
  auth-extra-groups:  system:bootstrappers:default-node-token,system:bootstrappers:worker,system:bootstrappers:ingress
 
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: kubelet-bootstrap
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:node-bootstrapper
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: system:bootstrappers:default-node-token
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: node-autoapprove-bootstrap
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:certificates.k8s.io:certificatesigningrequests:nodeclient
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: system:bootstrappers:default-node-token
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: node-autoapprove-certificate-rotation
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:certificates.k8s.io:certificatesigningrequests:selfnodeclient
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: system:nodes
---
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
    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
#所有k8s节点执行相同操作,配置TLS Bootstrapping
#环境配置:--server是高可用节点:端口号6443
#该命令用于配置名为"kubernetes"的集群,并将证书授权、服务器地址等信息写入到 "/etc/kubernetes/bootstrap-kubelet.kubeconfig" 文件中。
kubectl config set-cluster kubernetes \
  --certificate-authority=/etc/kubernetes/pki/ca.pem \
  --embed-certs=true \
  --server=https://192.168.79.100:6443 \
  --kubeconfig=/etc/kubernetes/bootstrap-kubelet.kubeconfig

#该命令用于设置一个名为"tls-bootstrap-token-user"的凭证,使用指定的令牌并将其写入 "/etc/kubernetes/bootstrap-kubelet.kubeconfig" 文件中。
kubectl config set-credentials tls-bootstrap-token-user \
  --token=c8ad9c.2e4d610cf3e7426e \
  --kubeconfig=/etc/kubernetes/bootstrap-kubelet.kubeconfig

#该命令用于创建名为"tls-bootstrap-token-user@kubernetes"的上下文,该上下文包含与"kubernetes"集群相关联的用户和凭据,并将其写入 "/etc/kubernetes/bootstrap-kubelet.kubeconfig" 文件中。
kubectl config set-context tls-bootstrap-token-user@kubernetes \
  --cluster=kubernetes \
  --user=tls-bootstrap-token-user \
  --kubeconfig=/etc/kubernetes/bootstrap-kubelet.kubeconfig

#该命令用于将当前上下文设置为"tls-bootstrap-token-user@kubernetes",并使用 "/etc/kubernetes/bootstrap-kubelet.kubeconfig" 文件作为 kubeconfig 文件
kubectl config use-context tls-bootstrap-token-user@kubernetes \
  --kubeconfig=/etc/kubernetes/bootstrap-kubelet.kubeconfig
  
#查看相关组件是否处于运行状态
systemctl is-active docker cri-docker keepalived kube-apiserver kube-controller-manager kube-scheduler

#配置kubeconfig管理节点上使用kubectl命令
mkdir -p /root/.kube ; cp /etc/kubernetes/admin.kubeconfig /root/.kube/config

#验证:所有k8s节点查看能否获取组件的状态信息
kubectl get cs

#注意!在Master01节点创建bootstrap.secret即可
kubectl create -f /root/bootstrap/bootstrap.secret.yaml

内网环境下手动部署kubernetes(v1.26.3)高可用集群_第20张图片

七、Node节点配置

在 Kubernetes 集群中,kubelet 和 kube-proxy 是两个关键的节点级别组件,它们分别负责节点上的容器运行和网络通信。
(1)kubelet:kubelet 是 Kubernetes 集群中每个节点上运行的一个代理,负责管理该节点上的容器。kubelet 根据从 API server 接收到的 PodSpec(包含在 Pod 的 YAML 配置文件中)来确保容器的运行状态。它会周期性地从 API server 获取分配给该节点的 Pod 信息,并根据这些信息启动、停止或重启容器。此外,kubelet 还负责向 API server 报告节点的状态信息,如节点的资源使用情况、容器的运行状态等。
(2)kube-proxy:kube-proxy 是 Kubernetes 集群中每个节点上运行的一个网络代理,负责实现 Kubernetes 服务的负载均衡和网络通信。当用户创建一个 Kubernetes 服务时,kube-proxy 会自动为该服务创建一个虚拟 IP 地址,并将该地址映射到后端 Pod 的 IP 地址。kube-proxy 通过监听 API server 中的服务和端点信息,动态更新这些映射关系。此外,kube-proxy 还负责实现跨节点的 Pod 通信,以及从外部访问集群内部服务的网络转发。

在/root/kubernetes-v1.26.3/config/目录下创建kubelet.service、kubelet-conf.yml、kube-proxy.service、kube-proxy.yaml四个文件

1.kubelet.service文件内容如下:

cat > /root/kubernetes-v1.26.3/config/kubelet.service << EOF
[Unit]
Description=Kubernetes Kubelet
Documentation=https://github.com/kubernetes/kubernetes

[Service]
ExecStart=/usr/local/bin/kubelet \
    --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.kubeconfig  \
    --kubeconfig=/etc/kubernetes/kubelet.kubeconfig \
    --config=/etc/kubernetes/kubelet-conf.yml \
    --container-runtime-endpoint=unix:///run/cri-dockerd.sock  \
    --node-labels=node.kubernetes.io/node=

[Install]
WantedBy=multi-user.target
EOF

2.kubelet-conf.yml文件内容如下:

cat > /root/kubernetes-v1.26.3/config/kubelet-conf.yml << EOF
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
address: 0.0.0.0
port: 10250
readOnlyPort: 10255
authentication:
  anonymous:
    enabled: false
  webhook:
    cacheTTL: 2m0s
    enabled: true
  x509:
    clientCAFile: /etc/kubernetes/pki/ca.pem
authorization:
  mode: Webhook
  webhook:
    cacheAuthorizedTTL: 5m0s
    cacheUnauthorizedTTL: 30s
cgroupDriver: systemd
cgroupsPerQOS: true
clusterDNS:
- 10.96.0.10
clusterDomain: cluster.local
containerLogMaxFiles: 5
containerLogMaxSize: 10Mi
contentType: application/vnd.kubernetes.protobuf
cpuCFSQuota: true
cpuManagerPolicy: none
cpuManagerReconcilePeriod: 10s
enableControllerAttachDetach: true
enableDebuggingHandlers: true
enforceNodeAllocatable:
- pods
eventBurst: 10
eventRecordQPS: 5
evictionHard:
  imagefs.available: 15%
  memory.available: 100Mi
  nodefs.available: 10%
  nodefs.inodesFree: 5%
evictionPressureTransitionPeriod: 5m0s
failSwapOn: true
fileCheckFrequency: 20s
hairpinMode: promiscuous-bridge
healthzBindAddress: 127.0.0.1
healthzPort: 10248
httpCheckFrequency: 20s
imageGCHighThresholdPercent: 85
imageGCLowThresholdPercent: 80
imageMinimumGCAge: 2m0s
iptablesDropBit: 15
iptablesMasqueradeBit: 14
kubeAPIBurst: 10
kubeAPIQPS: 5
makeIPTablesUtilChains: true
maxOpenFiles: 1000000
maxPods: 110
nodeStatusUpdateFrequency: 10s
oomScoreAdj: -999
podPidsLimit: -1
registryBurst: 10
registryPullQPS: 5
resolvConf: /etc/resolv.conf
rotateCertificates: true
runtimeRequestTimeout: 2m0s
serializeImagePulls: true
staticPodPath: /etc/kubernetes/manifests
streamingConnectionIdleTimeout: 4h0m0s
syncFrequency: 1m0s
volumeStatsAggPeriod: 1m0s
EOF

3.kube-proxy.service文件内容如下:

cat > /root/kubernetes-v1.26.3/config/kube-proxy.service << EOF
[Unit]
Description=Kubernetes Kube Proxy
Documentation=https://github.com/kubernetes/kubernetes
After=network.target

[Service]
ExecStart=/usr/local/bin/kube-proxy \
  --config=/etc/kubernetes/kube-proxy.yaml \
  --v=2

Restart=always
RestartSec=10s

[Install]
WantedBy=multi-user.target
EOF

4.kube-proxy.yml文件内容如下:

cat > /root/kubernetes-v1.26.3/config/kube-proxy.yml << EOF
apiVersion: kubeproxy.config.k8s.io/v1alpha1
bindAddress: 0.0.0.0
clientConnection:
  acceptContentTypes: ""
  burst: 10
  contentType: application/vnd.kubernetes.protobuf
  kubeconfig: /etc/kubernetes/kube-proxy.kubeconfig
  qps: 5
clusterCIDR: 172.16.0.0/12
configSyncPeriod: 15m0s
conntrack:
  max: null
  maxPerCore: 32768
  min: 131072
  tcpCloseWaitTimeout: 1h0m0s
  tcpEstablishedTimeout: 24h0m0s
enableProfiling: false
healthzBindAddress: 0.0.0.0:10256
hostnameOverride: ""
iptables:
  masqueradeAll: false
  masqueradeBit: 14
  minSyncPeriod: 0s
  syncPeriod: 30s
ipvs:
  masqueradeAll: true
  minSyncPeriod: 5s
  scheduler: "rr"
  syncPeriod: 30s
kind: KubeProxyConfiguration
metricsBindAddress: 127.0.0.1:10249
mode: "ipvs"
nodePortAddresses: null
oomScoreAdj: -999
portRange: ""
udpIdleTimeout: 250ms
EOF

7.1 kubelet配置

#所有k8s节点执行相同操作,配置kubelet
#复制相关文件到对应目录下,根据实际集群实际情况更改相关ip网段
cp /root/kubernetes-v1.26.3/config/kubelet.service /usr/lib/systemd/system/
cp /root/kubernetes-v1.26.3/yaml/kubelet-conf.yml /etc/kubernetes/

#所有节点检查相关组件是否全部启动(worker节点无需检查后三个组件)
systemctl is-active keepalived kube-apiserver kube-controller-manager kube-scheduler

#所有节点启动kubelet并查看状态
systemctl daemon-reload
systemctl start kubelet && systemctl enable kubelet
systemctl status kubelet

7.2 kube-proxy配置

#所有k8s节点执行相同操作,配置kube-proxy
#复制相关文件到对应目录下,根据实际集群实际情况更改相关ip网段
cp /root/kubernetes-v1.26.3/config/kube-proxy.service /usr/lib/systemd/system/
cp /root/kubernetes-v1.26.3/yaml/kube-proxy.yaml /etc/kubernetes/

#所有节点启动kube-proxy并查看状态
systemctl daemon-reload
systemctl restart kube-proxy && systemctl enable kube-proxy
systemctl status kube-proxy

7.3 查看k8s集群

#首先所有k8s节点安装kubectl命令行自动补全功能
rpm -ivh /root/kubernetes-v1.26.3/RPMpackages/bash-completion-2.1-8.el7.noarch.rpm
source /usr/share/bash-completion/bash_completion && source <(kubectl completion bash)
echo "source <(kubectl completion bash)" >> ~/.bashrc

#k8s组件基本安装配置完毕,查看运行状态(工作节点4个unknown是正常的)
systemctl is-active docker cri-docker etcd keepalived kube-apiserver kube-controller-manager kube-scheduler kubelet kube-proxy
kubectl get cs

#验证:查看能否获取k8s集群信息(此时为NotReady状态)
kubectl get node

内网环境下手动部署kubernetes(v1.26.3)高可用集群_第21张图片

总结:
1.Kubernetes的Master节点是Kubernetes集群的控制节点,用来管理整个集群。Master节点上运行了以下组件:
(1)API Server:处理所有来自用户和Node节点的请求,并返回相应的结果。
(2)etcd:分布式键值存储,用于存储集群的状态和元数据。
(3)Controller Manager:负责集群控制器的管理,包括Replication Controller,Endpoint Controller等。
(4)Scheduler:负责Pod的调度,将Pod调度到Node节点上。

2.Node节点是Kubernetes集群中运行应用程序的节点,也称为工作节点。Node节点上运行了以下组件:
(1)Kubelet:负责与Master节点通信,管理Pod的生命周期,并确保Pod处于健康状态。
(2)Container Runtime:用于运行容器,包括Docker,CRI-O等。
(3)kube-proxy:负责维护网络规则,负责Pod的服务发现和负载均衡等。

总的来说,Master节点主要负责集群的管理和控制,Node节点主要负责运行容器和提供服务。在Kubernetes集群中,Master节点和Node节点各自承担不同的角色和任务,相互协作,共同构建一个高效、可靠的容器化平台。

八、安装Calico、CoreDNS和Metrics Server

k8s集群已经基本部署完毕,Calico、CoreDNS和Metrics Server以及后续的dashboard只需要在其中一个节点部署即可。

8.1 安装Calico

Calico是一种开源的网络和安全解决方案,它可以为Kubernetes集群提供高效的网络和安全管理。在Kubernetes集群中,Calico通常作为网络插件来使用,用于管理Kubernetes集群内的容器网络和安全。具体来说,Calico在Kubernetes集群中的作用包括:
(1)实现容器网络:Calico使用BGP协议和Linux内核路由表来创建一个扁平的、高性能的容器网络,可以为Kubernetes集群中的每个容器分配一个独立的IP地址,并且容器之间的通信可以通过直接路由而不需要NAT。
(2)提供网络策略:Calico可以为Kubernetes集群提供网络策略,用于控制容器之间的通信。这些策略可以基于标签或命名空间来定义,并且可以包括允许或拒绝容器之间的特定流量。
(3)实现安全防护:Calico可以提供一些安全功能,如入侵检测、流量监控和日志记录等,以保护Kubernetes集群中的容器免受恶意攻击和数据泄露。

#参考:https://zhuanlan.zhihu.com/p/494374026
#提前下载好calico的yaml模板:
wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.5.0/aio/deploy/recommended.yaml

#也可以通过官方部署方式:https://docs.tigera.io/calico/latest/getting-started/kubernetes/self-managed-onprem/onpremises
#注意修改,通过vi编辑yaml文件,"/+搜索词+enter键""n"搜索下一个,搜索词如下:
(1"CALICO_IPV4POOL_CIDR":指定Calico网络插件所使用的IP地址段的。注意网段需和规划一致,这里是:value: "172.16.0.0/16"2"CALICO_IPV4POOL_IPIP":如果需要使用IPIP模式,需要将该参数设置为"Always"。
(3"image":注意所有镜像是否正确,确保是本地仓库镜像(如这里:image: 192.168.79.101:5000/chenby/cni:master)

#只在master01节点安装calico,这里部署在kubernetes-dashboard命名空间下
kubectl apply -f /root/calico/calico.yaml
kubectl get pod -A

#删除Calico:kubectl delete -f /root/calico/calico.yaml
#查看Calico的日志:kubectl logs <pod-name> -n kube-system

内网环境下手动部署kubernetes(v1.26.3)高可用集群_第22张图片

8.2 安装CoreDNS

CoreDNS是 Kubernetes 集群中默认的 DNS 服务器。在 Kubernetes 集群中,所有的 Pod 都会被分配一个 DNS 名称,这个名称可以用来在集群内部进行服务发现和通信。而 CoreDNS 就是负责解析这些 DNS 名称的服务器。具体来说,CoreDNS在 Kubernetes 集群中主要有以下作用:
(1)服务发现:当我们在 Kubernetes 中创建 Service 对象时,Kubernetes 会自动为该 Service 创建一个 DNS 记录,这个 DNS 记录将指向该 Service 对应的所有 Pod 的 IP 地址。当其他 Pod 需要访问该 Service 时,可以通过该 DNS 记录进行访问。
(2)DNS 转发:CoreDNS 还可以配置为将某些 DNS 请求转发到外部 DNS 服务器,比如 Google DNS 或者阿里云 DNS。
(3)插件扩展:CoreDNS 支持插件扩展,可以通过插件来实现更多的功能,比如使用 etcd 存储 DNS 记录、实现 DNS 缓存等。

#在coredns目录下创建coredns.yaml文件
mkdir /root/coredns
cat > /root/coredns/coredns.yaml << EOF
apiVersion: v1
kind: ServiceAccount
metadata:
  name: coredns
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: system:coredns
rules:
  - apiGroups:
    - ""
    resources:
    - endpoints
    - services
    - pods
    - namespaces
    verbs:
    - list
    - watch
  - apiGroups:
    - discovery.k8s.io
    resources:
    - endpointslices
    verbs:
    - list
    - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: system:coredns
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:coredns
subjects:
- kind: ServiceAccount
  name: coredns
  namespace: kube-system
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: coredns
  namespace: kube-system
data:
  Corefile: |
    .:53 {
        errors
        health {
          lameduck 5s
        }
        ready
        kubernetes cluster.local in-addr.arpa ip6.arpa {
          fallthrough in-addr.arpa ip6.arpa
        }
        prometheus :9153
        forward . /etc/resolv.conf {
          max_concurrent 1000
        }
        cache 30
        loop
        reload
        loadbalance
    }
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: coredns
  namespace: kube-system
  labels:
    k8s-app: kube-dns
    kubernetes.io/name: "CoreDNS"
spec:
  # replicas: not specified here:
  # 1. Default is 1.
  # 2. Will be tuned in real time if DNS horizontal auto-scaling is turned on.
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
  selector:
    matchLabels:
      k8s-app: kube-dns
  template:
    metadata:
      labels:
        k8s-app: kube-dns
    spec:
      priorityClassName: system-cluster-critical
      serviceAccountName: coredns
      tolerations:
        - key: "CriticalAddonsOnly"
          operator: "Exists"
      nodeSelector:
        kubernetes.io/os: linux
      affinity:
         podAntiAffinity:
           preferredDuringSchedulingIgnoredDuringExecution:
           - weight: 100
             podAffinityTerm:
               labelSelector:
                 matchExpressions:
                   - key: k8s-app
                     operator: In
                     values: ["kube-dns"]
               topologyKey: kubernetes.io/hostname
      containers:
      - name: coredns
        image: 192.168.79.101:5000/chenby/coredns:v1.10.0
        imagePullPolicy: IfNotPresent
        resources:
          limits:
            memory: 170Mi
          requests:
            cpu: 100m
            memory: 70Mi
        args: [ "-conf", "/etc/coredns/Corefile" ]
        volumeMounts:
        - name: config-volume
          mountPath: /etc/coredns
          readOnly: true
        ports:
        - containerPort: 53
          name: dns
          protocol: UDP
        - containerPort: 53
          name: dns-tcp
          protocol: TCP
        - containerPort: 9153
          name: metrics
          protocol: TCP
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            add:
            - NET_BIND_SERVICE
            drop:
            - all
          readOnlyRootFilesystem: true
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 60
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 5
        readinessProbe:
          httpGet:
            path: /ready
            port: 8181
            scheme: HTTP
      dnsPolicy: Default
      volumes:
        - name: config-volume
          configMap:
            name: coredns
            items:
            - key: Corefile
              path: Corefile
---
apiVersion: v1
kind: Service
metadata:
  name: kube-dns
  namespace: kube-system
  annotations:
    prometheus.io/port: "9153"
    prometheus.io/scrape: "true"
  labels:
    k8s-app: kube-dns
    kubernetes.io/cluster-service: "true"
    kubernetes.io/name: "CoreDNS"
spec:
  selector:
    k8s-app: kube-dns
  clusterIP: 10.96.0.10 
  ports:
  - name: dns
    port: 53
    protocol: UDP
  - name: dns-tcp
    port: 53
    protocol: TCP
  - name: metrics
    port: 9153
    protocol: TCP
EOF
#也可以直接去下载官方最新yaml:https://github.com/coredns/deployment
#注意修改,通过vi编辑yaml文件,"/+搜索词+enter键""n"搜索下一个,搜索词如下:
(1)clusterIP: 指定 CoreDNS 服务的 ClusterIP 地址,用于服务发现和负载均衡。这里是clusterIP: 10.96.0.10。
(2)image: 指定要使用的 CoreDNS 镜像,确保镜像名正确。如这里:image: 192.168.79.101:5000/chenby/coredns:v1.10.0

#只在master01节点安装coredns,安装后查看pod部署状态
kubectl apply -f /root/coredns/coredns.yaml
kubectl get pod -A

#删除CoreDNS:kubectl delete -f /root/coredns/coredns.yaml
#查看CoreDNS Pod 的日志:kubectl logs <pod-name> -n kube-system

内网环境下手动部署kubernetes(v1.26.3)高可用集群_第23张图片

8.3 安装Metrics Server

Metrics Server 是一个 Kubernetes 组件,它是 Kubernetes 中的一个聚合器,可以收集和存储 Pod、Node、Service 等资源的各种性能指标,例如 CPU 使用率、内存使用率、网络流量等。Metrics Server 会定期从 Kubernetes API Server 中获取这些资源的指标数据,并将这些数据存储在其自身的内存中,供其他组件或工具调用。Metrics Server在 Kubernetes 集群中主要有以下作用:
(1)提供集群性能指标:Metrics Server 可以提供 Kubernetes 集群的各种性能指标,帮助管理员更好地监测集群的状态,发现并解决潜在的问题。
(2)支持自动扩容:当 Pod 需要更多资源时,Kubernetes 可以根据 Metrics Server 收集到的性能指标信息自动扩容 Pod 的数量。
(3)支持 HPA:HPA(Horizontal Pod Autoscaler)是 Kubernetes 中的一个组件,可以根据 Metrics Server 收集到的性能指标信息自动调整 Pod 的数量,从而保证集群的稳定性和可靠性。

#在metrics-server目录下创建metrics-server.yaml文件
mkdir /root/metrics-server
cat > /root/metrics-server/metrics-server.yaml << EOF
apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    k8s-app: metrics-server
  name: metrics-server
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  labels:
    k8s-app: metrics-server
    rbac.authorization.k8s.io/aggregate-to-admin: "true"
    rbac.authorization.k8s.io/aggregate-to-edit: "true"
    rbac.authorization.k8s.io/aggregate-to-view: "true"
  name: system:aggregated-metrics-reader
rules:
- apiGroups:
  - metrics.k8s.io
  resources:
  - pods
  - nodes
  verbs:
  - get
  - list
  - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  labels:
    k8s-app: metrics-server
  name: system:metrics-server
rules:
- apiGroups:
  - ""
  resources:
  - pods
  - nodes
  - nodes/stats
  - namespaces
  - configmaps
  verbs:
  - get
  - list
  - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  labels:
    k8s-app: metrics-server
  name: metrics-server-auth-reader
  namespace: kube-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: extension-apiserver-authentication-reader
subjects:
- kind: ServiceAccount
  name: metrics-server
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  labels:
    k8s-app: metrics-server
  name: metrics-server:system:auth-delegator
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:auth-delegator
subjects:
- kind: ServiceAccount
  name: metrics-server
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  labels:
    k8s-app: metrics-server
  name: system:metrics-server
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:metrics-server
subjects:
- kind: ServiceAccount
  name: metrics-server
  namespace: kube-system
---
apiVersion: v1
kind: Service
metadata:
  labels:
    k8s-app: metrics-server
  name: metrics-server
  namespace: kube-system
spec:
  ports:
  - name: https
    port: 443
    protocol: TCP
    targetPort: https
  selector:
    k8s-app: metrics-server
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    k8s-app: metrics-server
  name: metrics-server
  namespace: kube-system
spec:
  selector:
    matchLabels:
      k8s-app: metrics-server
  strategy:
    rollingUpdate:
      maxUnavailable: 0
  template:
    metadata:
      labels:
        k8s-app: metrics-server
    spec:
      containers:
      - args:
        - --cert-dir=/tmp
        - --secure-port=4443
        - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
        - --kubelet-use-node-status-port
        - --metric-resolution=15s
        - --kubelet-insecure-tls
        - --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.pem # change to front-proxy-ca.crt for kubeadm
        - --requestheader-username-headers=X-Remote-User
        - --requestheader-group-headers=X-Remote-Group
        - --requestheader-extra-headers-prefix=X-Remote-Extra-
        image: 192.168.79.101:5000/chenby/metrics-server:v0.5.2
        imagePullPolicy: IfNotPresent
        livenessProbe:
          failureThreshold: 3
          httpGet:
            path: /livez
            port: https
            scheme: HTTPS
          periodSeconds: 10
        name: metrics-server
        ports:
        - containerPort: 4443
          name: https
          protocol: TCP
        readinessProbe:
          failureThreshold: 3
          httpGet:
            path: /readyz
            port: https
            scheme: HTTPS
          initialDelaySeconds: 20
          periodSeconds: 10
        resources:
          requests:
            cpu: 100m
            memory: 200Mi
        securityContext:
          readOnlyRootFilesystem: true
          runAsNonRoot: true
          runAsUser: 1000
        volumeMounts:
        - mountPath: /tmp
          name: tmp-dir
        - name: ca-ssl
          mountPath: /etc/kubernetes/pki
      nodeSelector:
        kubernetes.io/os: linux
      priorityClassName: system-cluster-critical
      serviceAccountName: metrics-server
      volumes:
      - emptyDir: {}
        name: tmp-dir
      - name: ca-ssl
        hostPath:
          path: /etc/kubernetes/pki

---
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
  labels:
    k8s-app: metrics-server
  name: v1beta1.metrics.k8s.io
spec:
  group: metrics.k8s.io
  groupPriorityMinimum: 100
  insecureSkipTLSVerify: true
  service:
    name: metrics-server
    namespace: kube-system
  version: v1beta1
  versionPriority: 100
EOF
#也可以直接去下载官方最新yaml:https://gitcode.net/mirrors/kubernetes-sigs/metrics-server?utm_source=csdn_github_accelerator
#注意修改,通过vi编辑yaml文件,"/+搜索词+enter键""n"搜索下一个,搜索词如下:
(1)args:metrics-server 启动时的参数配置,可以根据需要进行修改,常见的参数包括 kubelet-insecure-tls、kubelet-preferred-address-types 等。
(2)image: 指定要使用的 CoreDNS 镜像,确保镜像名正确。如这里:image: 192.168.79.101:5000/chenby/metrics-server:v0.5.2。
(3)resources:metrics-server 使用的 CPU 和内存资源配置,可以根据实际情况进行修改。如这里:cpu: 100m  memory: 200Mi。

#只在master01节点安装metrics-server,安装后查看pod部署状态
kubectl apply -f /root/metrics-server/metrics-server.yaml
kubectl get pods -n kube-system

#验证 metrics-server 是否生效,可以通过以下命令查看节点的 CPU 和内存使用情况:
kubectl top nodes

#查看 metrics-server 的日志:
kubectl logs -n kube-system metrics-server-xxxxx

#查看 metrics-server 的 API 对象:
kubectl get --raw /apis/metrics.k8s.io/

#查看 pod 的 CPU 和内存使用情况:
kubectl top pods -n <namespace>

#删除metrics-server
kubectl delete -f /root/metrics-server/metrics-server.yaml

内网环境下手动部署kubernetes(v1.26.3)高可用集群_第24张图片

九、安装dashboard

Kubernetes Dashboard 是一个基于 Web 的用户界面,允许 Kubernetes 集群管理员和开发者对 Kubernetes 集群进行可视化操作和监控。它提供了一个方便的方式来查看和管理 Kubernetes 集群中的资源,包括 Pods、Deployments、Services、Nodes 等,还可以对集群进行扩容、缩容和升级等操作。在 Kubernetes 集群中,Dashboard 的作用具体有以下几个方面:
(1)提供可视化操作界面:Dashboard 提供了一个 Web 界面,管理员和开发人员可以通过它方便地查看 Kubernetes 集群中的资源状态,以及进行资源的创建、删除、扩容、缩容等操作,而无需使用命令行工具,这对于不熟悉命令行的用户来说非常方便。
(2)监控 Kubernetes 集群:Dashboard 提供了一个监控面板,可以展示集群中的各种运行状态和指标,如 CPU、内存、网络等,同时 Dashboard 也支持自定义查询和展现,方便管理员和开发者了解 Kubernetes 集群的运行状态。
(3)显示集群事件和日志:Dashboard 还可以展示 Kubernetes 集群中的事件和日志,管理员可以通过它快速了解集群中发生的事件和异常情况,方便及时处理和调整。
(4)提供安全认证和授权:Dashboard 支持多种身份验证方式,如 Token、用户名和密码等,同时还可以进行授权管理,对不同用户和角色进行权限控制,保障 Kubernetes 集群的安全性。

在/root/dashboard/目录下创建dashboard.yaml、dashboard-user.yaml两个文件

1.dashboard.yaml文件内容如下:

#创建dashboard目录
mkdir /root/dashboard
cat > /root/dashboard/dashboard.yaml << EOF
apiVersion: v1
kind: Namespace
metadata:
  name: kubernetes-dashboard

---

apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard

---

kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
spec:
  type: NodePort
  ports:
    - port: 443
      targetPort: 8443
      nodePort: 30090
  selector:
    k8s-app: kubernetes-dashboard

---

apiVersion: v1
kind: Secret
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard-certs
  namespace: kubernetes-dashboard
type: Opaque

---

apiVersion: v1
kind: Secret
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard-csrf
  namespace: kubernetes-dashboard
type: Opaque
data:
  csrf: ""

---

apiVersion: v1
kind: Secret
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard-key-holder
  namespace: kubernetes-dashboard
type: Opaque

---

kind: ConfigMap
apiVersion: v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard-settings
  namespace: kubernetes-dashboard

---

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
rules:
  # Allow Dashboard to get, update and delete Dashboard exclusive secrets.
  - apiGroups: [""]
    resources: ["secrets"]
    resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs", "kubernetes-dashboard-csrf"]
    verbs: ["get", "update", "delete"]
    # Allow Dashboard to get and update 'kubernetes-dashboard-settings' config map.
  - apiGroups: [""]
    resources: ["configmaps"]
    resourceNames: ["kubernetes-dashboard-settings"]
    verbs: ["get", "update"]
    # Allow Dashboard to get metrics.
  - apiGroups: [""]
    resources: ["services"]
    resourceNames: ["heapster", "dashboard-metrics-scraper"]
    verbs: ["proxy"]
  - apiGroups: [""]
    resources: ["services/proxy"]
    resourceNames: ["heapster", "http:heapster:", "https:heapster:", "dashboard-metrics-scraper", "http:dashboard-metrics-scraper"]
    verbs: ["get"]

---

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
rules:
  # Allow Metrics Scraper to get metrics from the Metrics server
  - apiGroups: ["metrics.k8s.io"]
    resources: ["pods", "nodes"]
    verbs: ["get", "list", "watch"]

---

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: kubernetes-dashboard
subjects:
  - kind: ServiceAccount
    name: kubernetes-dashboard
    namespace: kubernetes-dashboard

---

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: kubernetes-dashboard
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: kubernetes-dashboard
subjects:
  - kind: ServiceAccount
    name: kubernetes-dashboard
    namespace: kubernetes-dashboard

---

kind: Deployment
apiVersion: apps/v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
spec:
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      k8s-app: kubernetes-dashboard
  template:
    metadata:
      labels:
        k8s-app: kubernetes-dashboard
    spec:
      securityContext:
        seccompProfile:
          type: RuntimeDefault
      containers:
        - name: kubernetes-dashboard
          image: 192.168.79.101:5000/google_containers/dashboard:v2.7.0
          imagePullPolicy: Always
          ports:
            - containerPort: 8443
              protocol: TCP
          args:
            - --auto-generate-certificates
            - --namespace=kubernetes-dashboard
            # Uncomment the following line to manually specify Kubernetes API server Host
            # If not specified, Dashboard will attempt to auto discover the API server and connect
            # to it. Uncomment only if the default does not work.
            # - --apiserver-host=http://my-address:port
          volumeMounts:
            - name: kubernetes-dashboard-certs
              mountPath: /certs
              # Create on-disk volume to store exec logs
            - mountPath: /tmp
              name: tmp-volume
          livenessProbe:
            httpGet:
              scheme: HTTPS
              path: /
              port: 8443
            initialDelaySeconds: 30
            timeoutSeconds: 30
          securityContext:
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            runAsUser: 1001
            runAsGroup: 2001
      volumes:
        - name: kubernetes-dashboard-certs
          secret:
            secretName: kubernetes-dashboard-certs
        - name: tmp-volume
          emptyDir: {}
      serviceAccountName: kubernetes-dashboard
      nodeSelector:
        "kubernetes.io/os": linux
      # Comment the following tolerations if Dashboard must not be deployed on master
      tolerations:
        - key: node-role.kubernetes.io/master
          effect: NoSchedule

---

kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: dashboard-metrics-scraper
  name: dashboard-metrics-scraper
  namespace: kubernetes-dashboard
spec:
  ports:
    - port: 8000
      targetPort: 8000
  selector:
    k8s-app: dashboard-metrics-scraper

---

kind: Deployment
apiVersion: apps/v1
metadata:
  labels:
    k8s-app: dashboard-metrics-scraper
  name: dashboard-metrics-scraper
  namespace: kubernetes-dashboard
spec:
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      k8s-app: dashboard-metrics-scraper
  template:
    metadata:
      labels:
        k8s-app: dashboard-metrics-scraper
    spec:
      securityContext:
        seccompProfile:
          type: RuntimeDefault
      containers:
        - name: dashboard-metrics-scraper
          image: 192.168.79.101:5000/google_containers/metrics-scraper:v1.0.8
          ports:
            - containerPort: 8000
              protocol: TCP
          volumeMounts:
          - mountPath: /tmp
            name: tmp-volume
          securityContext:
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            runAsUser: 1001
            runAsGroup: 2001
      serviceAccountName: kubernetes-dashboard
      nodeSelector:
        "kubernetes.io/os": linux
      # Comment the following tolerations if Dashboard must not be deployed on master
      tolerations:
        - key: node-role.kubernetes.io/master
          effect: NoSchedule
      volumes:
        - name: tmp-volume
          emptyDir: {}
EOF

2.dashboard-user.yaml文件内容如下:

#创建dashboard用户
cat > /root/dashboard/dashboard-user.yaml << EOF
apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin-user
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: admin-user
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: admin-user
  namespace: kube-system
EOF
#也可以直接去下载官方最新部署模板:https://gitcode.net/mirrors/kubernetes/dashboard?utm_source=csdn_github_accelerator
#注意修改,通过vi编辑dashboard.yaml文件,"/+搜索词+enter键""n"搜索下一个,搜索词如下:
(1)nodePort:设置dashboard的service服务为通过nodeport暴露端口,这里自定义端口为:300902)image: 指定要使用的 dashboard 镜像,确保镜像名正确。如这里:image: 192.168.79.101:5000/google_containers/dashboard:v2.7.0。

#部署dashboard:
kubectl apply -f /root/dashboard/dashboard.yaml

#该服务部署在kubernetes-dashboard,查看详细信息
kubectl get svc kubernetes-dashboard -n kubernetes-dashboard
kubectl get pod -n kubernetes-dashboard

内网环境下手动部署kubernetes(v1.26.3)高可用集群_第25张图片

#创建一个ServiceAccount(dashboard用户),创建一个新的token,命名为admin-user用于登录到Kubernetes Dashboard。
kubectl apply -f /root/dashboard/dashboard-user.yaml
kubectl create token admin-user -n kube-system

#执行完以上命令会生成token,以此token登录dashboard
https://192.168.79.101:30090

内网环境下手动部署kubernetes(v1.26.3)高可用集群_第26张图片
内网环境下手动部署kubernetes(v1.26.3)高可用集群_第27张图片

十、集群可用性验证

busybox是一个轻量级的Linux发行版,它只包含了一些最常用的基本工具和命令,如sh、ls、cp、cat等。由于其体积小且功能完善,因此经常被用作验证镜像或调试容器的工具。

#创建busybox.yaml,验证部署pod资源
mkdir /root/test
cat >/root/test/busybox.yaml << EOF
apiVersion: v1
kind: Pod
metadata:
  name: busybox
  namespace: default
spec:
  containers:
  - name: busybox
    image: 192.168.79.101:5000/busybox:1.28
    command:
      - sleep
      - "3600"
    imagePullPolicy: IfNotPresent
  restartPolicy: Always
EOF
#部署busybox到default命名空间:
kubectl apply -f /root/test/busybox.yaml
#Pod解析默认命名空间中的kubernetes
kubectl get svc
kubectl exec busybox -n default -- nslookup kubernetes

#Pod能解析跨namespace的Service
kubectl exec busybox -n default -- nslookup kube-dns.kube-system

#每个节点必须能访问到kubernetes svc 443和kube-dns的service 53端口
telnet 10.96.0.1 443
telnet 10.96.0.10 53
curl 10.96.0.10:53

#Pod和Pod之间跨namespace跨机器都能通信
#进入busybox的pod内ping其他节点其他命名空间上的pod
kubectl get pod -A -owide
kubectl exec -ti busybox -- sh
ping 192.168.79.101

#可以连通证明此pod是可以跨命名空间跨主机通信的,删除busybox,验证完毕
kubectl delete -f /root/kubernetes-v1.26.3/yaml/busybox.yaml

内网环境下手动部署kubernetes(v1.26.3)高可用集群_第28张图片

总结(参考:https://cloud.tencent.com/developer/beta/article/1638810)
#常用的kubectl基础命令:
1.create:创建资源(如 Pod、Service、Deployment 等)。
kubectl create -f my-deployment.yaml

2.apply:将更改应用到资源。
kubectl apply -f my-deployment.yaml

3.delete:删除资源。
(1)根据yaml文件删除对应的资源:kubectl delete -f demo-service.yaml
(2)删除具体的资源:kubectl delete 资源类型 资源名称 -n 命名空间
(3)强制删除pod举例:kubectl delete pod kafka-0 -n default --force --grace-period=0

4.get:获取资源的信息。
(1)获取当前namespace下的所有Pod对象:kubectl get pods -n namespace
(2)获取所有namespace下的Pod对象:kubectl get po -A
(3)获取所有namespace下的Pod对象及其详细信息:kubectl get pod -A -owide

5.describe:获取资源的详细描述。
kubectl describe pod my-pod -n namespace

6.logs:获取 Pod 中容器的日志。
kubectl logs my-pod

7.run:快速创建并运行一个新的 Pod。
kubectl run my-pod --image=my-image

8.top:显示资源的资源使用情况。
kubectl top node

9.expose:将 Pod 暴露为 Service,使其可以被外部访问。
kubectl expose pod my-pod --port=80 --target-port=8080

10.set:更新资源的属性。
kubectl set image deployment/my-deployment my-container=my-image:v2

11.edit:编辑资源的配置。
kubectl edit deployment my-deployment

12.exec:在指定的容器中执行命令。
kubectl exec my-pod – ls /app

13.scale:调整资源的副本数量。
kubectl scale deployment my-deployment --replicas=3

14.cp:在本地文件系统和 Pod 之间复制文件。
kubectl cp my-pod:/app/file.txt ./file.txt

你可能感兴趣的:(kubernetes,docker,容器)