侧边栏壁纸
博主头像
汪洋

即使慢,驰而不息,纵会落后,纵会失败,但一定可以达到他所向的目标。 - 鲁迅

  • 累计撰写 192 篇文章
  • 累计创建 74 个标签
  • 累计收到 120 条评论

Kubernetes - 1.29.2+calico+RockyLinux9.2+高可用+Docker+cri-docker - 二进制部署

汪洋
2024-04-25 / 8 评论 / 6 点赞 / 631 阅读 / 77,741 字

一、环境初始化

1、镜像下载(所有节点)

# 官方下载地址
https://rockylinux.org/download

# 阿里云镜像下载地址
https://mirrors.aliyun.com/rockylinux/9/isos/x86_64/?spm=a2c6h.25603864.0.0.29696621VzJej5

2、环境配置(所有节点)

# 网卡配置
# cat /etc/NetworkManager/system-connections/ens160.nmconnection
[ipv4]
method=manual
address1=192.168.66.12/24,192.168.66.200
dns=114.114.114.114;8.8.8.8

# cat /etc/NetworkManager/system-connections/ens192.nmconnection
[connection]
autoconnect=false

# 调用 nmcli 重启设备和连接配置
nmcli d d ens192

nmcli d r ens160 
nmcli c r ens160

# 修改主机名和 /etc/hosts 解析文件
# Rocky 系统软件源更换
sed -e 's|^mirrorlist=|#mirrorlist=|g' \
    -e 's|^#baseurl=http://dl.rockylinux.org/$contentdir|baseurl=https://mirrors.aliyun.com/rockylinux|g' \
    -i.bak \
    /etc/yum.repos.d/[Rr]ocky*.repo
    
dnf makecache
# 防火墙修改 firewalld 为 iptables
systemctl stop firewalld
systemctl disable firewalld

yum -y install iptables-services
systemctl start iptables
iptables -F
systemctl enable iptables
# 禁用 Selinux
setenforce 0
sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config
grubby --update-kernel ALL --args selinux=0
# 查看是否禁用,grubby --info DEFAULT
# 回滚内核层禁用操作,grubby --update-kernel ALL --remove-args selinux
# 设置时区
timedatectl set-timezone Asia/Shanghai
# 关闭 swap 分区
swapoff -a
sed -i 's:/dev/mapper/rl-swap:#/dev/mapper/rl-swap:g' /etc/fstab
# 安装 ipvs
yum install -y ipvsadm
# 开启路由转发
echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.conf
sysctl -p
# 安装必备的工具包
yum update -y && yum -y install wget psmisc vim net-tools nfs-utils telnet yum-utils device-mapper-persistent-data lvm2 git network-scripts tar curl
# 排除 calico 网卡被 NetworkManager 所管理
cat > /etc/NetworkManager/conf.d/calico.conf << EOF 
[keyfile]
unmanaged-devices=interface-name:cali*;interface-name:tunl*
EOF

systemctl restart NetworkManager

这个参数用于指定不由 NetworkManager 管理的设备。它由以下两个部分组成

interface-name:cali*
表示以 "cali" 开头的接口名称被排除在 NetworkManager 管理之外。例如,"cali0", "cali1" 等接口不受 NetworkManager 管理

interface-name:tunl*
表示以 "tunl" 开头的接口名称被排除在 NetworkManager 管理之外。例如,"tunl0", "tunl1" 等接口不受 NetworkManager 管理

通过使用这个参数,可以将特定的接口排除在 NetworkManager 的管理范围之外,以便其他工具或进程可以独立地管理和配置这些接口

# 修改主机名和解析
192.168.10.11 k8s-master01 m1
192.168.10.12 k8s-master02 m2
192.168.10.13 k8s-master03 m3
192.168.10.14 k8s-node01 n1
192.168.10.15 k8s-node02 n2
# 时间同步配置
# 服务端
yum install chrony -y

cat > /etc/chrony.conf << EOF 
pool ntp.aliyun.com iburst
driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
allow 192.168.10.0/24
local stratum 10
keyfile /etc/chrony.keys
leapsectz right/UTC
logdir /var/log/chrony
EOF

systemctl restart chronyd ; systemctl enable chronyd

# 客户端
yum install chrony -y

cat > /etc/chrony.conf << EOF 
pool 192.168.10.11 iburst
pool 192.168.10.12 iburst
pool 192.168.10.13 iburst
driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
keyfile /etc/chrony.keys
leapsectz right/UTC
logdir /var/log/chrony
EOF

systemctl restart chronyd ; systemctl enable chronyd

#使用客户端进行验证
chronyc sources -v

pool ntp.aliyun.com iburst
指定使用ntp.aliyun.com作为时间服务器池,iburst选项表示在初始同步时会发送多个请求以加快同步速度。

driftfile /var/lib/chrony/drift
指定用于保存时钟漂移信息的文件路径。

makestep 1.0 3
设置当系统时间与服务器时间偏差大于1秒时,会以1秒的步长进行调整。如果偏差超过3秒,则立即进行时间调整。

rtcsync
启用硬件时钟同步功能,可以提高时钟的准确性。

allow 192.168.10.0/24
允许192.168.0.0/24网段范围内的主机与chrony进行时间同步。

local stratum 10
将本地时钟设为stratum 10,stratum值表示时钟的准确度,值越小表示准确度越高。

keyfile /etc/chrony.keys
指定使用的密钥文件路径,用于对时间同步进行身份验证。

leapsectz right/UTC
指定时区为UTC。

logdir /var/log/chrony
指定日志文件存放目录。

# 配置 ulimit
ulimit -SHn 65535

cat >> /etc/security/limits.conf <<EOF
* soft nofile 655360
* hard nofile 131072
* soft nproc 655350
* hard nproc 655350
* soft memlock unlimited
* hard memlock unlimitedd
EOF

soft nofile 655360
soft表示软限制,nofile表示一个进程可打开的最大文件数,默认值为1024。这里的软限制设置为655360,即一个进程可打开的最大文件数为655360。

hard nofile 131072
hard表示硬限制,即系统设置的最大值。nofile表示一个进程可打开的最大文件数,默认值为4096。这里的硬限制设置为131072,即系统设置的最大文件数为131072。

soft nproc 655350
soft表示软限制,nproc表示一个用户可创建的最大进程数,默认值为30720。这里的软限制设置为655350,即一个用户可创建的最大进程数为655350。

hard nproc 655350
hard表示硬限制,即系统设置的最大值。nproc表示一个用户可创建的最大进程数,默认值为4096。这里的硬限制设置为655350,即系统设置的最大进程数为655350。

soft memlock unlimited
seft表示软限制,memlock表示一个进程可锁定在RAM中的最大内存,默认值为64 KB。这里的软限制设置为unlimited,即一个进程可锁定的最大内存为无限制。

hard memlock unlimited
hard表示硬限制,即系统设置的最大值。memlock表示一个进程可锁定在RAM中的最大内存,默认值为64 KB。这里的硬限制设置为unlimited,即系统设置的最大内存锁定为无限制。

# 安装 ipvs
yum install ipvsadm ipset sysstat conntrack libseccomp -y

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

systemctl restart systemd-modules-load.service

lsmod | grep -e ip_vs -e nf_conntrack
# 修改内核参数
cat <<EOF > /etc/sysctl.d/k8s.conf
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-iptables = 1
fs.may_detach_mounts = 1
vm.overcommit_memory=1
vm.panic_on_oom=0
fs.inotify.max_user_watches=89100
fs.file-max=52706963
fs.nr_open=52706963
net.netfilter.nf_conntrack_max=2310720
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_keepalive_intvl =15
net.ipv4.tcp_max_tw_buckets = 36000
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_max_orphans = 327680
net.ipv4.tcp_orphan_retries = 3
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.ip_conntrack_max = 65536
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.tcp_timestamps = 0
net.core.somaxconn = 16384
net.ipv6.conf.all.disable_ipv6 = 0
net.ipv6.conf.default.disable_ipv6 = 0
net.ipv6.conf.lo.disable_ipv6 = 0
net.ipv6.conf.all.forwarding = 1
EOF

sysctl --system

这些是Linux系统的一些参数设置,用于配置和优化网络、文件系统和虚拟内存等方面的功能。以下是每个参数的详细解释:

  1. net.ipv4.ip_forward = 1
  • 这个参数启用了IPv4的IP转发功能,允许服务器作为网络路由器转发数据包。
  1. net.bridge.bridge-nf-call-iptables = 1
  • 当使用网络桥接技术时,将数据包传递到iptables进行处理。
  1. fs.may_detach_mounts = 1
  • 允许在挂载文件系统时,允许被其他进程使用。
  1. vm.overcommit_memory=1
  • 该设置允许原始的内存过量分配策略,当系统的内存已经被完全使用时,系统仍然会分配额外的内存。
  1. vm.panic_on_oom=0
  • 当系统内存不足(OOM)时,禁用系统崩溃和重启。
  1. fs.inotify.max_user_watches=89100
  • 设置系统允许一个用户的inotify实例可以监控的文件数目的上限。
  1. fs.file-max=52706963
  • 设置系统同时打开的文件数的上限。
  1. fs.nr_open=52706963
  • 设置系统同时打开的文件描述符数的上限。
  1. net.netfilter.nf_conntrack_max=2310720
  • 设置系统可以创建的网络连接跟踪表项的最大数量。
  1. net.ipv4.tcp_keepalive_time = 600
  • 设置TCP套接字的空闲超时时间(秒),超过该时间没有活动数据时,内核会发送心跳包。
  1. net.ipv4.tcp_keepalive_probes = 3
  • 设置未收到响应的TCP心跳探测次数。
  1. net.ipv4.tcp_keepalive_intvl = 15
  • 设置TCP心跳探测的时间间隔(秒)。
  1. net.ipv4.tcp_max_tw_buckets = 36000
  • 设置系统可以使用的TIME_WAIT套接字的最大数量。
  1. net.ipv4.tcp_tw_reuse = 1
  • 启用TIME_WAIT套接字的重新利用,允许新的套接字使用旧的TIME_WAIT套接字。
  1. net.ipv4.tcp_max_orphans = 327680
  • 设置系统可以同时存在的TCP套接字垃圾回收包裹数的最大数量。
  1. net.ipv4.tcp_orphan_retries = 3
  • 设置系统对于孤立的TCP套接字的重试次数。
  1. net.ipv4.tcp_syncookies = 1
  • 启用TCP SYN cookies保护,用于防止SYN洪泛攻击。
  1. net.ipv4.tcp_max_syn_backlog = 16384
  • 设置新的TCP连接的半连接数(半连接队列)的最大长度。
  1. net.ipv4.ip_conntrack_max = 65536
  • 设置系统可以创建的网络连接跟踪表项的最大数量。
  1. net.ipv4.tcp_timestamps = 0
  • 关闭TCP时间戳功能,用于提供更好的安全性。
  1. net.core.somaxconn = 16384
  • 设置系统核心层的连接队列的最大值。
  1. net.ipv6.conf.all.disable_ipv6 = 0
  • 启用IPv6协议。
  1. net.ipv6.conf.default.disable_ipv6 = 0
  • 启用IPv6协议。
  1. net.ipv6.conf.lo.disable_ipv6 = 0
  • 启用IPv6协议。
  1. net.ipv6.conf.all.forwarding = 1
  • 允许IPv6数据包转发。
# 安装 Docker
# 二进制包下载地址:https://download.docker.com/linux/static/stable/x86_64/
# wget https://mirrors.ustc.edu.cn/docker-ce/linux/static/stable/x86_64/docker-25.0.3.tgz

tar xf docker-*.tgz 

cp docker/* /usr/bin/
# 创建 containerd 的 service 文件,并且启动
cat >/etc/systemd/system/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

systemctl enable --now containerd.service

[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:指定服务的类型,notify表示服务会在启动完成后向systemd发送通知。
  • Delegate=yes:允许服务代理其他服务的应答,例如收到关机命令后终止其他服务。
  • KillMode=process:指定服务终止时的行为,process表示终止服务进程。
  • Restart=always:指定服务终止后是否自动重启,always表示总是自动重启。
  • RestartSec=5:指定服务重启的时间间隔,单位为秒。
  • LimitNPROC=infinity:限制服务的最大进程数,infinity表示没有限制。
  • LimitCORE=infinity:限制服务的最大核心数,infinity表示没有限制。
  • LimitNOFILE=1048576:限制服务的最大文件数,指定为1048576。
  • TasksMax=infinity:限制服务的最大任务数,infinity表示没有限制。
  • OOMScoreAdjust=-999:指定服务的OOM(Out of Memory)得分,负数表示降低被终止的概率。

[Install]

  • WantedBy=multi-user.target:指定服务的安装方式,multi-user.target表示该服务在多用户模式下安装。
# 准备 docker 的 service 文件
cat > /etc/systemd/system/docker.service <<EOF
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service cri-docker.service docker.socket 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 $MAINPID
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

[Unit]

  • Description: 描述服务的作用,这里是Docker Application Container Engine,即Docker应用容器引擎。
  • Documentation: 提供关于此服务的文档链接,这里是Docker官方文档链接。
  • After: 说明该服务在哪些其他服务之后启动,这里是在网络在线、firewalld服务和containerd服务后启动。
  • Wants: 说明该服务想要的其他服务,这里是网络在线服务。
  • Requires: 说明该服务需要的其他服务,这里是docker.socket和containerd.service。

[Service]

  • Type: 服务类型,这里是notify,表示服务在启动完成时发送通知。
  • ExecStart: 命令,启动该服务时会执行的命令,这里是/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock,即启动dockerd并指定一些参数,其中-H指定dockerd的监听地址为fd://,--containerd指定containerd的sock文件位置。
  • ExecReload: 重载命令,当接收到HUP信号时执行的命令,这里是/bin/kill -s HUP $MAINPID,即发送HUP信号给主进程ID。
  • TimeoutSec: 服务超时时间,这里是0,表示没有超时限制。
  • RestartSec: 重启间隔时间,这里是2秒,表示重启失败后等待2秒再重启。
  • Restart: 重启策略,这里是always,表示总是重启。
  • StartLimitBurst: 启动限制次数,这里是3,表示在启动失败后最多重试3次。
  • StartLimitInterval: 启动限制时间间隔,这里是60秒,表示两次启动之间最少间隔60秒。
  • LimitNOFILE: 文件描述符限制,这里是infinity,表示没有限制。
  • LimitNPROC: 进程数限制,这里是infinity,表示没有限制。
  • LimitCORE: 核心转储限制,这里是infinity,表示没有限制。
  • TasksMax: 最大任务数,这里是infinity,表示没有限制。
  • Delegate: 修改权限,这里是yes,表示启用权限修改。
  • KillMode: 杀死模式,这里是process,表示杀死整个进程组。
  • OOMScoreAdjust: 用于调整进程在系统内存紧张时的优先级调整,这里是-500,表示将OOM分数降低500。

[Install]

  • WantedBy: 安装目标,这里是multi-user.target,表示在多用户模式下安装。
    在WantedBy参数中,我们可以使用以下参数:
  1. multi-user.target:指定该服务应该在多用户模式下启动。
  2. graphical.target:指定该服务应该在图形化界面模式下启动。
  3. default.target:指定该服务应该在系统的默认目标(runlevel)下启动。
  4. rescue.target:指定该服务应该在系统救援模式下启动。
  5. poweroff.target:指定该服务应该在关机时启动。
  6. reboot.target:指定该服务应该在重启时启动。
  7. halt.target:指定该服务应该在停止时启动。
  8. shutdown.target:指定该服务应该在系统关闭时启动。
    这些参数可以根据需要选择一个或多个,以告知系统在何时启动该服务。
#准备 docker 的 socket 文件
cat > /etc/systemd/system/docker.socket <<EOF
[Unit]
Description=Docker Socket for the API

[Socket]
ListenStream=/var/run/docker.sock
SocketMode=0660
SocketUser=root
SocketGroup=docker

[Install]
WantedBy=sockets.target
EOF

这是一个用于Docker API的socket配置文件,包含了以下参数:

[Unit]

  • Description:描述了该socket的作用,即为Docker API的socket。

[Socket]

  • ListenStream:指定了 socket 的监听地址,该 socket 会监听在 /var/run/docker.sock 上,即 Docker 守护程序使用的默认 sock 文件。
  • SocketMode:指定了socket文件的权限模式,此处为0660,即用户和用户组有读写权限,其他用户无权限。
  • SocketUser:指定了socket文件的所有者,此处为root用户。
  • SocketGroup:指定了socket文件的所属用户组,此处为docker用户组。

[Install]

  • WantedBy:指定了该socket被启用时的目标,此处为sockets.target,表示当sockets.target启动时启用该socket。

该配置文件的作用是为 Docker 提供 API 访问的通道,它监听在 /var/run/docker.sock 上,具有 root 用户权限,但只接受 docker 用户组的成员的连接,并且其他用户无法访问。这样,只有 docker 用户组的成员可以通过该 socket 与 Docker 守护进程进行通信。

# 配置加速器
mkdir /etc/docker/ -pv

cat >/etc/docker/daemon.json <<EOF
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "registry-mirrors": [
    "https://docker.mirrors.ustc.edu.cn"
  ],
  "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

该参数文件中包含以下参数:

  1. exec-opts: 用于设置Docker守护进程的选项,native.cgroupdriver=systemd表示使用systemd作为Cgroup驱动程序。
  2. registry-mirrors: 用于指定Docker镜像的镜像注册服务器。在这里有三个镜像注册服务器:https://docker.m.daocloud.io、https://docker.mirrors.ustc.edu.cn和http://hub-mirror.c.163.com。
  3. max-concurrent-downloads: 用于设置同时下载镜像的最大数量,默认值为3,这里设置为10。
  4. log-driver: 用于设置Docker守护进程的日志驱动程序,这里设置为json-file。
  5. log-level: 用于设置日志的级别,这里设置为warn。
  6. log-opts: 用于设置日志驱动程序的选项,这里有两个选项:max-size和max-file。max-size表示每个日志文件的最大大小,这里设置为10m,max-file表示保存的最大日志文件数量,这里设置为3。
  7. data-root: 用于设置Docker守护进程的数据存储根目录,默认为/var/lib/docker,这里设置为/var/lib/docker。
# 启动 Docker
groupadd docker

systemctl daemon-reload

systemctl enable --now docker.socket

systemctl enable --now docker.service

systemctl status docker.service

docker info
# 解压 cri-docker
# https://github.com/Mirantis/cri-dockerd/releases/
# wget  https://mirrors.chenby.cn/https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.10/cri-dockerd-0.3.10.amd64.tgz

tar xvf cri-dockerd-*.amd64.tgz 

cp -r cri-dockerd  /usr/bin/

chmod +x /usr/bin/cri-dockerd
# 写入启动  cri-docker 配置文件

cat >  /usr/lib/systemd/system/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=registry.aliyuncs.com/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

[Unit]

  • Description:该参数用于描述该单元的功能,这里描述的是CRI与Docker应用容器引擎的接口。
  • Documentation:该参数指定了相关文档的网址,供用户参考。
  • After:该参数指定了此单元应该在哪些其他单元之后启动,确保在网络在线、防火墙和Docker服务启动之后再启动此单元。
  • Wants:该参数指定了此单元希望也启动的所有单元,此处是希望在网络在线之后启动。
  • Requires:该参数指定了此单元需要依赖的单元,此处是cri-docker.socket单元。

[Service]

  • Type:该参数指定了服务的类型,这里是notify,表示当服务启动完成时向系统发送通知。
  • ExecStart:该参数指定了将要运行的命令和参数,此处是执行/usr/bin/cri-dockerd/cri-dockerd命令,并指定了网络插件为cni和Pod基础设施容器的镜像为registry.aliyuncs.com/google_containers/pause:3.7。
  • ExecReload:该参数指定在服务重载时运行的命令,此处是发送HUP信号给主进程。
  • TimeoutSec:该参数指定了服务启动的超时时间,此处为0,表示无限制。
  • RestartSec:该参数指定了自动重启服务的时间间隔,此处为2秒。
  • Restart:该参数指定了在服务发生错误时自动重启,此处是始终重启。
  • StartLimitBurst:该参数指定了在给定时间间隔内允许的启动失败次数,此处为3次。
  • StartLimitInterval:该参数指定启动失败的时间间隔,此处为60秒。
  • LimitNOFILE:该参数指定了允许打开文件的最大数量,此处为无限制。
  • LimitNPROC:该参数指定了允许同时运行的最大进程数,此处为无限制。
  • LimitCORE:该参数指定了允许生成的core文件的最大大小,此处为无限制。
  • TasksMax:该参数指定了此服务的最大任务数,此处为无限制。
  • Delegate:该参数指定了是否将控制权委托给指定服务,此处为是。
  • KillMode:该参数指定了在终止服务时如何处理进程,此处是通过终止进程来终止服务。

[Install]

  • WantedBy:该参数指定了希望这个单元启动的多用户目标。在这里,这个单元希望在multi-user.target启动。
# 写入 cri-docker 的 socket 配置文件

cat > /usr/lib/systemd/system/cri-docker.socket <<EOF
[Unit]
Description=CRI Docker Socket for the API
PartOf=cri-docker.service

[Socket]
ListenStream=%t/cri-dockerd.sock
SocketMode=0660
SocketUser=root
SocketGroup=docker

[Install]
WantedBy=sockets.target
EOF

该配置文件是用于systemd的单元配置文件(unit file),用于定义一个socket单元。

[Unit]

  • Description:表示该单元的描述信息。
  • PartOf:表示该单元是cri-docker.service的一部分。

[Socket]

  • ListenStream:指定了该socket要监听的地址和端口,这里使用了%t占位符,表示根据单元的类型来决定路径。%t/cri-dockerd.sock表示将监听Unix域套接字cri-dockerd.sock。Unix域套接字用于在同一台主机上的进程之间通信。
  • SocketMode:指定了socket文件的权限模式,此处为0660,即用户和用户组有读写权限,其他用户无权限。
  • SocketUser:指定了socket文件的所有者,此处为root用户。
  • SocketGroup:指定了socket文件的所属用户组,此处为docker用户组。

[Install]

  • WantedBy:部分定义了该单元的安装配置信息。WantedBy=sockets.target表示当sockets.target单元启动时,自动启动该socket单元。sockets.target是一个系统服务,用于管理所有的socket单元。
# 启动 cri-docker

systemctl daemon-reload

systemctl enable --now cri-docker.service

systemctl status docker.service

二、K8S 与 ETCD 下载及安装(在 master01 节点上操作)

1、安装 K8S 和 ETCD 二进制文件

# 下载安装包
wget https://mirrors.chenby.cn/https://github.com/etcd-io/etcd/releases/download/v3.5.12/etcd-v3.5.12-linux-amd64.tar.gz

wget https://dl.k8s.io/v1.29.2/kubernetes-server-linux-amd64.tar.gz

# 解压k8s安装文件
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安装文件
tar -xf etcd*.tar.gz && mv etcd-*/etcd /usr/local/bin/ && mv etcd-*/etcdctl /usr/local/bin/

# 查看/usr/local/bin下内容
ls /usr/local/bin/

这是一个 tar 命令,用于解压指定的 kubernetes-server-linux-amd64.tar.gz 文件,并将其中的特定文件提取到 /usr/local/bin 目录下。

命令的解释如下:

  • tar:用于处理 tar 压缩文件的命令。
  • -xf:表示解压操作。
  • kubernetes-server-linux-amd64.tar.gz:要解压的文件名。
  • --strip-components=3:表示解压时忽略压缩文件中的前3级目录结构,提取文件时直接放到目标目录中。
  • -C /usr/local/bin:指定提取文件的目标目录为 /usr/local/bin。
  • kubernetes/server/bin/kube{let,ctl,-apiserver,-controller-manager,-scheduler,-proxy}:要解压和提取的文件名模式,用花括号括起来表示模式中的多个可能的文件名。

总的来说,这个命令的作用是将 kubernetes-server-linux-amd64.tar.gz 文件中的 kubelet、kubectl、kube-apiserver、kube-controller-manager、kube-scheduler和kube-proxy 六个文件提取到 /usr/local/bin 目录下,同时忽略文件路径中的前三级目录结构。

# 查看版本
kubelet --version
	Kubernetes v1.29.2

etcdctl version
	etcdctl version: 3.5.12
	API version: 3.5
# 将组件发送至其它 k8s 节点
Master='k8s-master02 k8s-master03'

Work='k8s-node01 k8s-node02'

# 拷贝 master 组件
for NODE in $Master; do echo $NODE; scp /usr/local/bin/kube{let,ctl,-apiserver,-controller-manager,-scheduler,-proxy} $NODE:/usr/local/bin/; scp /usr/local/bin/etcd* $NODE:/usr/local/bin/; done

# 拷贝 work 组件
for NODE in $Work; do echo $NODE; scp /usr/local/bin/kube{let,-proxy} $NODE:/usr/local/bin/ ; done

# 所有节点执行
mkdir -p /opt/cni/bin

2、相关证书生成

a、安装证书工具

# master01 节点下载证书生成工具
wget "https://mirrors.chenby.cn/https://github.com/cloudflare/cfssl/releases/download/v1.6.4/cfssl_1.6.4_linux_amd64" -O /usr/local/bin/cfssl

wget "https://mirrors.chenby.cn/https://github.com/cloudflare/cfssl/releases/download/v1.6.4/cfssljson_1.6.4_linux_amd64" -O /usr/local/bin/cfssljson

chmod +x /usr/local/bin/cfssl /usr/local/bin/cfssljson

b、生成 ETCD 证书(以下操作在所有 master 节点操作)

mkdir /etc/etcd/ssl -p

# 写入生成证书所需的配置文件,master01 节点生成 etcd 证书
cat > ca-config.json << EOF 
{
  "signing": {
    "default": {
      "expiry": "876000h"
    },
    "profiles": {
      "kubernetes": {
        "usages": [
            "signing",
            "key encipherment",
            "server auth",
            "client auth"
        ],
        "expiry": "876000h"
      }
    }
  }
}
EOF

这段配置文件是用于配置加密和认证签名的一些参数。
在这里,有两个部分:signingprofiles

signing包含了默认签名配置和配置文件。
默认签名配置default指定了证书的过期时间为876000h876000h表示证书有效期为100年。

profiles部分定义了不同的证书配置文件。
在这里,只有一个配置文件kubernetes。它包含了以下usages和过期时间expiry

  1. signing:用于对其他证书进行签名
  2. key encipherment:用于加密和解密传输数据
  3. server auth:用于服务器身份验证
  4. client auth:用于客户端身份验证

对于kubernetes配置文件,证书的过期时间也是876000h,即100年。

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

这是一个用于生成证书签名请求(Certificate Signing Request,CSR)的 JSON 配置文件。JSON 配置文件指定了生成证书签名请求所需的数据。

  • "CN": "etcd" 指定了希望生成的证书的 CN 字段(Common Name),即证书的主题,通常是该证书标识的实体的名称。
  • "key": {} 指定了生成证书所使用的密钥的配置信息。"algo": "rsa" 指定了密钥的算法为 RSA,"size": 2048 指定了密钥的长度为 2048 位。
  • "names": [] 包含了生成证书时所需的实体信息。在这个例子中,只包含了一个实体,其相关信息如下:
    • "C": "CN" 指定了实体的国家/地区代码,这里是中国。
    • "ST": "Beijing" 指定了实体所在的省/州。
    • "L": "Beijing" 指定了实体所在的城市。
    • "O": "etcd" 指定了实体的组织名称。
    • "OU": "Etcd Security" 指定了实体所属的组织单位。
  • "ca": {} 指定了生成证书时所需的CA(Certificate Authority)配置信息。
    • "expiry": "876000h" 指定了证书的有效期,这里是876000小时。

生成证书签名请求时,可以使用这个 JSON 配置文件作为输入,根据配置文件中的信息生成相应的 CSR 文件。然后,可以将 CSR 文件发送给 CA 进行签名,以获得有效的证书。

生成 etcd 证书和 etcd 证书的 key(如果你觉得以后可能会扩容,可以在 ip 那多写几个预留出来)
若没有IPv6 可删除可保留

cfssl gencert -initca etcd-ca-csr.json | cfssljson -bare /etc/etcd/ssl/etcd-ca

具体的解释如下:

cfssl 是一个用于生成 TLS/SSL 证书的工具,它支持 PKI、JSON 格式配置文件以及与许多其他集成工具的配合使用。

gencert 参数表示生成证书的操作。-initca 参数表示初始化一个CA(证书颁发机构)。CA 是用于签发其他证书的根证书。etcd-ca-csr.json 是一个 JSON 格式的配置文件,其中包含了CA的详细信息,如私钥、公钥、有效期等。这个文件提供了生成 CA 证书所需的信息。

| 符号表示将上一个命令的输出作为下一个命令的输入。

cfssljson 是 cfssl 工具的一个子命令,用于格式化 cfssl 生成的 JSON 数据。 -bare 参数表示直接输出裸证书,即只生成证书文件,不包含其他格式的文件。/etc/etcd/ssl/etcd-ca 是指定生成的证书文件的路径和名称。

所以,这条命令的含义是使用 cfssl 工具根据配置文件 ca-csr.json 生成一个 CA 证书,并将证书文件保存在 /etc/etcd/ssl/etcd-ca 路径下。

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

这段代码是一个 JSON 格式的配置文件,用于生成一个证书签名请求(Certificate Signing Request,CSR)。

首先,"CN"字段指定了该证书的通用名称(Common Name),这里设为"etcd"。

接下来,"key"字段指定了密钥的算法("algo"字段)和长度("size"字段),此处使用的是RSA算法,密钥长度为2048位。

最后,"names"字段是一个数组,其中包含了一个名字对象,用于指定证书中的一些其他信息。这个名字对象包含了以下字段:

  • "C"字段指定了国家代码(Country),这里设置为"CN"。
  • "ST"字段指定了省份(State)或地区,这里设置为"Beijing"。
  • "L"字段指定了城市(Locality),这里设置为"Beijing"。
  • "O"字段指定了组织(Organization),这里设置为"etcd"。
  • "OU"字段指定了组织单元(Organizational Unit),这里设置为"Etcd Security"。

这些字段将作为证书的一部分,用于标识和验证证书的使用范围和颁发者等信息。

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.10.11,192.168.10.12,192.168.10.13,fc00:43f4:1eea:1::10,fc00:43f4:1eea:1::20,fc00:43f4:1eea:1::30,::1  -profile=kubernetes    etcd-csr.json | cfssljson -bare /etc/etcd/ssl/etcd

这是一条使用cfssl生成etcd证书的命令,下面是各个参数的解释:

-ca=/etc/etcd/ssl/etcd-ca.pem:指定用于签名etcd证书的CA文件的路径。
-ca-key=/etc/etcd/ssl/etcd-ca-key.pem:指定用于签名etcd证书的CA私钥文件的路径。
-config=ca-config.json:指定CA配置文件的路径,该文件定义了证书的有效期、加密算法等设置。
-hostname=xxxx:指定要为etcd生成证书的主机名和IP地址列表。
-profile=kubernetes:指定使用的证书配置文件,该文件定义了证书的用途和扩展属性。
etcd-csr.json:指定etcd证书请求的JSON文件的路径,该文件包含了证书请求的详细信息。
| cfssljson -bare /etc/etcd/ssl/etcd:通过管道将cfssl命令的输出传递给cfssljson命令,并使用-bare参数指定输出文件的前缀路径,这里将生成etcd证书的.pem和-key.pem文件。

这条命令的作用是使用指定的CA证书和私钥,根据证书请求的JSON文件和配置文件生成etcd的证书文件。

# 将证书复制到其他节点
Master='k8s-master02 k8s-master03'

for NODE in $Master; do ssh $NODE "mkdir -p /etc/etcd/ssl"; for FILE in etcd-ca-key.pem  etcd-ca.pem  etcd-key.pem  etcd.pem; do scp /etc/etcd/ssl/${FILE} $NODE:/etc/etcd/ssl/${FILE}; done; done

c、生成 K8S 相关证书(特别说明除外,以下操作在所有 master 节点操作)

mkdir -p /etc/kubernetes/pki
# master01 节点生成 k8s 证书, 写入生成证书所需的配置文件
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

这是一个用于生成 Kubernetes 相关证书的配置文件。该配置文件中包含以下信息:

  • CN:CommonName,即用于标识证书的通用名称。在此配置中,CN 设置为 "kubernetes",表示该证书是用于 Kubernetes。
  • key:用于生成证书的算法和大小。在此配置中,使用的算法是 RSA,大小是 2048 位。
  • names:用于证书中的名称字段的详细信息。在此配置中,有以下字段信息:
    • C:Country,即国家。在此配置中,设置为 "CN"。
    • ST:State,即省/州。在此配置中,设置为 "Beijing"。
    • L:Locality,即城市。在此配置中,设置为 "Beijing"。
    • O:Organization,即组织。在此配置中,设置为 "Kubernetes"。
    • OU:Organization Unit,即组织单位。在此配置中,设置为 "Kubernetes-manual"。
  • ca:用于证书签名的证书颁发机构(CA)的配置信息。在此配置中,设置了证书的有效期为 876000 小时。

这个配置文件可以用于生成 Kubernetes 相关的证书,以确保集群中的通信安全性。

cfssl gencert -initca ca-csr.json | cfssljson -bare /etc/kubernetes/pki/ca

具体的解释如下:

cfssl是一个用于生成TLS/SSL证书的工具,它支持PKI、JSON格式配置文件以及与许多其他集成工具的配合使用。

gencert参数表示生成证书的操作。-initca参数表示初始化一个CA(证书颁发机构)。CA是用于签发其他证书的根证书。ca-csr.json是一个JSON格式的配置文件,其中包含了CA的详细信息,如私钥、公钥、有效期等。这个文件提供了生成CA证书所需的信息。

| 符号表示将上一个命令的输出作为下一个命令的输入。

cfssljson是cfssl工具的一个子命令,用于格式化cfssl生成的JSON数据。 -bare参数表示直接输出裸证书,即只生成证书文件,不包含其他格式的文件。/etc/kubernetes/pki/ca是指定生成的证书文件的路径和名称。

所以,这条命令的含义是使用cfssl工具根据配置文件ca-csr.json生成一个CA证书,并将证书文件保存在/etc/kubernetes/pki/ca路径下。

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-config.json << EOF 
{
  "signing": {
    "default": {
      "expiry": "876000h"
    },
    "profiles": {
      "kubernetes": {
        "usages": [
            "signing",
            "key encipherment",
            "server auth",
            "client auth"
        ],
        "expiry": "876000h"
      }
    }
  }
}
EOF
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.10.16,127.0.0.1,kubernetes,kubernetes.default,kubernetes.default.svc,kubernetes.default.svc.cluster,kubernetes.default.svc.cluster.local,xinxianghf.com,xinxianghf.cn,192.168.10.11,192.168.10.12,192.168.10.13,192.168.10.14,192.168.10.15,192.168.10.16,192.168.10.17,192.168.10.18,192.168.10.19,192.168.10.20,fc00:43f4:1eea:1::10,fc00:43f4:1eea:1::20,fc00:43f4:1eea:1::30,fc00:43f4:1eea:1::40,fc00:43f4:1eea:1::50,fc00:43f4:1eea:1::60,fc00:43f4:1eea:1::70,fc00:43f4:1eea:1::80,fc00:43f4:1eea:1::90,fc00:43f4:1eea:1::100,::1   -profile=kubernetes   apiserver-csr.json | cfssljson -bare /etc/kubernetes/pki/apiserver
# 生成 apiserver 聚合证书
cat > front-proxy-ca-csr.json  << EOF 
{
  "CN": "kubernetes",
  "key": {
     "algo": "rsa",
     "size": 2048
  },
  "ca": {
    "expiry": "876000h"
  }
}
EOF

cfssl gencert   -initca front-proxy-ca-csr.json | cfssljson -bare /etc/kubernetes/pki/front-proxy-ca 

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

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
# 生成 controller-manage 的证书
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

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
   
kubectl config set-cluster kubernetes \
     --certificate-authority=/etc/kubernetes/pki/ca.pem \
     --embed-certs=true \
     --server=https://127.0.0.1:8443 \
     --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
# 生成 kube-scheduler 的证书
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

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
   
kubectl config set-cluster kubernetes \
     --certificate-authority=/etc/kubernetes/pki/ca.pem \
     --embed-certs=true \
     --server=https://127.0.0.1:8443 \
     --kubeconfig=/etc/kubernetes/scheduler.kubeconfig
     
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
     
kubectl config set-context system:kube-scheduler@kubernetes \
     --cluster=kubernetes \
     --user=system:kube-scheduler \
     --kubeconfig=/etc/kubernetes/scheduler.kubeconfig
     
kubectl config use-context system:kube-scheduler@kubernetes \
     --kubeconfig=/etc/kubernetes/scheduler.kubeconfig
# 生成 admin 的证书配置
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

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
   
kubectl config set-cluster kubernetes     \
  --certificate-authority=/etc/kubernetes/pki/ca.pem     \
  --embed-certs=true     \
  --server=https://127.0.0.1:8443     \
  --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
# 创建 kube-proxy 证书
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

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
   
   
kubectl config set-cluster kubernetes     \
  --certificate-authority=/etc/kubernetes/pki/ca.pem     \
  --embed-certs=true     \
  --server=https://127.0.0.1:8443     \
  --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
# 创建 ServiceAccount Key ——secret
openssl genrsa -out /etc/kubernetes/pki/sa.key 2048
openssl rsa -in /etc/kubernetes/pki/sa.key -pubout -out /etc/kubernetes/pki/sa.pub
# 将证书发送到其他 master 节点
# 其他节点创建目录
mkdir  /etc/kubernetes/pki/ -p

for NODE in k8s-master02 k8s-master03; do  for FILE in $(ls /etc/kubernetes/pki | grep -v etcd); do  scp /etc/kubernetes/pki/${FILE} $NODE:/etc/kubernetes/pki/${FILE}; done;  for FILE in admin.kubeconfig controller-manager.kubeconfig scheduler.kubeconfig; do  scp /etc/kubernetes/${FILE} $NODE:/etc/kubernetes/${FILE}; done; done
# 查看证书
ls /etc/kubernetes/pki/

[root@k8s-master01 ~]# ls /etc/kubernetes/pki/ | wc -l
26

三、K8S 系统组件配置

1、ETCD 配置

这个配置文件是用于 etcd 集群的配置,其中包含了一些重要的参数和选项:

  • name:指定了当前节点的名称,用于集群中区分不同的节点。
  • data-dir:指定了 etcd 数据的存储目录。
  • wal-dir:指定了 etcd 数据写入磁盘的目录。
  • snapshot-count:指定了触发快照的事务数量。
  • heartbeat-interval:指定了 etcd 集群中节点之间的心跳间隔。
  • election-timeout:指定了选举超时时间。
  • quota-backend-bytes:指定了存储的限额,0 表示无限制。
  • listen-peer-urls:指定了节点之间通信的 URL,使用 HTTPS 协议。
  • listen-client-urls:指定了客户端访问 etcd 集群的 URL,同时提供了本地访问的 URL。
  • max-snapshots:指定了快照保留的数量。
  • max-wals:指定了日志保留的数量。
  • initial-advertise-peer-urls:指定了节点之间通信的初始 URL。
  • advertise-client-urls:指定了客户端访问 etcd 集群的初始 URL。
  • discovery:定义了 etcd 集群发现相关的选项。
  • initial-cluster:指定了 etcd 集群的初始成员。
  • initial-cluster-token:指定了集群的 token。
  • initial-cluster-state:指定了集群的初始状态。
  • strict-reconfig-check:指定了严格的重新配置检查选项。
  • enable-v2:启用了 v2 API。
  • enable-pprof:启用了性能分析。
  • proxy:设置了代理模式。
  • client-transport-security:客户端的传输安全配置。
  • peer-transport-security:节点之间的传输安全配置。
  • debug:是否启用调试模式。
  • log-package-levels:日志的输出级别。
  • log-outputs:指定了日志的输出类型。
  • force-new-cluster:是否强制创建一个新的集群。

这些参数和选项可以根据实际需求进行调整和配置。

# 如果要用IPv6那么把IPv4地址修改为IPv6即可
cat > /etc/etcd/etcd.config.yml << EOF 
name: 'k8s-master01'
data-dir: /var/lib/etcd
wal-dir: /var/lib/etcd/wal
snapshot-count: 5000
heartbeat-interval: 100
election-timeout: 1000
quota-backend-bytes: 0
listen-peer-urls: 'https://192.168.10.11:2380'
listen-client-urls: 'https://192.168.10.11:2379,http://127.0.0.1:2379'
max-snapshots: 3
max-wals: 5
cors:
initial-advertise-peer-urls: 'https://192.168.10.11:2380'
advertise-client-urls: 'https://192.168.10.11:2379'
discovery:
discovery-fallback: 'proxy'
discovery-proxy:
discovery-srv:
initial-cluster: 'k8s-master01=https://192.168.10.11:2380,k8s-master02=https://192.168.10.12:2380,k8s-master03=https://192.168.10.13:2380'
initial-cluster-token: 'etcd-k8s-cluster'
initial-cluster-state: 'new'
strict-reconfig-check: false
enable-v2: true
enable-pprof: true
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'
  auto-tls: true
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'
  auto-tls: true
debug: false
log-package-levels:
log-outputs: [default]
force-new-cluster: false
EOF
# 如果要用IPv6那么把IPv4地址修改为IPv6即可
cat > /etc/etcd/etcd.config.yml << EOF 
name: 'k8s-master02'
data-dir: /var/lib/etcd
wal-dir: /var/lib/etcd/wal
snapshot-count: 5000
heartbeat-interval: 100
election-timeout: 1000
quota-backend-bytes: 0
listen-peer-urls: 'https://192.168.10.12:2380'
listen-client-urls: 'https://192.168.10.12:2379,http://127.0.0.1:2379'
max-snapshots: 3
max-wals: 5
cors:
initial-advertise-peer-urls: 'https://192.168.10.12:2380'
advertise-client-urls: 'https://192.168.10.12:2379'
discovery:
discovery-fallback: 'proxy'
discovery-proxy:
discovery-srv:
initial-cluster: 'k8s-master01=https://192.168.10.11:2380,k8s-master02=https://192.168.10.12:2380,k8s-master03=https://192.168.10.13:2380'
initial-cluster-token: 'etcd-k8s-cluster'
initial-cluster-state: 'new'
strict-reconfig-check: false
enable-v2: true
enable-pprof: true
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'
  auto-tls: true
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'
  auto-tls: true
debug: false
log-package-levels:
log-outputs: [default]
force-new-cluster: false
EOF
# 如果要用IPv6那么把IPv4地址修改为IPv6即可
cat > /etc/etcd/etcd.config.yml << EOF 
name: 'k8s-master03'
data-dir: /var/lib/etcd
wal-dir: /var/lib/etcd/wal
snapshot-count: 5000
heartbeat-interval: 100
election-timeout: 1000
quota-backend-bytes: 0
listen-peer-urls: 'https://192.168.10.13:2380'
listen-client-urls: 'https://192.168.10.13:2379,http://127.0.0.1:2379'
max-snapshots: 3
max-wals: 5
cors:
initial-advertise-peer-urls: 'https://192.168.10.13:2380'
advertise-client-urls: 'https://192.168.10.13:2379'
discovery:
discovery-fallback: 'proxy'
discovery-proxy:
discovery-srv:
initial-cluster: 'k8s-master01=https://192.168.10.11:2380,k8s-master02=https://192.168.10.12:2380,k8s-master03=https://192.168.10.13:2380'
initial-cluster-token: 'etcd-k8s-cluster'
initial-cluster-state: 'new'
strict-reconfig-check: false
enable-v2: true
enable-pprof: true
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'
  auto-tls: true
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'
  auto-tls: true
debug: false
log-package-levels:
log-outputs: [default]
force-new-cluster: false
EOF
# 创建 service( 所有 master 节点操作)
cat > /usr/lib/systemd/system/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
# 创建 etcd 证书目录
mkdir /etc/kubernetes/pki/etcd

ln -s /etc/etcd/ssl/* /etc/kubernetes/pki/etcd/

systemctl daemon-reload

systemctl enable --now etcd.service

systemctl status etcd.service
# 查看 etcd 状态
# 如果要用 IPv6 那么把 IPv4 地址修改为 IPv6 即可
export ETCDCTL_API=3
etcdctl --endpoints="192.168.10.13:2379,192.168.10.12:2379,192.168.10.11: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

2、Nginx 配置

# 安装编译环境
yum install gcc -y

# 下载解压 nginx 二进制文件
# wget http://nginx.org/download/nginx-1.25.3.tar.gz
tar xvf nginx-*.tar.gz
cd nginx-*

# 进行编译
./configure --with-stream --without-http --without-http_uwsgi_module --without-http_scgi_module --without-http_fastcgi_module
make && make install 

# 拷贝编译好的 nginx
node='k8s-master02 k8s-master03 k8s-node01 k8s-node02'
for NODE in $node; do scp -r /usr/local/nginx/ $NODE:/usr/local/nginx/; done
# 写入配置文件(在所有主机上执行)
cat > /usr/local/nginx/conf/kube-nginx.conf <<EOF
worker_processes 1;
events {
    worker_connections  1024;
}
stream {
    upstream backend {
    	least_conn;
        hash $remote_addr consistent;
        server 192.168.10.11:6443        max_fails=3 fail_timeout=30s;
        server 192.168.10.12:6443        max_fails=3 fail_timeout=30s;
        server 192.168.10.13:6443        max_fails=3 fail_timeout=30s;
    }
    server {
        listen 127.0.0.1:8443;
        proxy_connect_timeout 1s;
        proxy_pass backend;
    }
}
EOF
cat > /etc/systemd/system/kube-nginx.service <<EOF
[Unit]
Description=kube-apiserver nginx proxy
After=network.target
After=network-online.target
Wants=network-online.target

[Service]
Type=forking
ExecStartPre=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/kube-nginx.conf -p /usr/local/nginx -t
ExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/kube-nginx.conf -p /usr/local/nginx
ExecReload=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/kube-nginx.conf -p /usr/local/nginx -s reload
PrivateTmp=true
Restart=always
RestartSec=5
StartLimitInterval=0
LimitNOFILE=65536
 
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload

systemctl enable --now kube-nginx.service

systemctl status kube-nginx.service

3、其它组件配置

# 所有 k8s 节点创建以下目录
mkdir -p /etc/kubernetes/manifests/ /etc/systemd/system/kubelet.service.d /var/lib/kubelet /var/log/kubernetes
# 创建 apiserver(所有 master 节点)
# master01 节点配置
cat > /usr/lib/systemd/system/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.10.11 \\
      --service-cluster-ip-range=10.96.0.0/12,fd00:1111::/112  \\
      --service-node-port-range=30000-32767  \\
      --etcd-servers=https://192.168.10.11:2379,https://192.168.10.12:2379,https://192.168.10.13: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
Restart=on-failure
RestartSec=10s
LimitNOFILE=65535

[Install]
WantedBy=multi-user.target

EOF



# master02 节点配置
cat > /usr/lib/systemd/system/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.10.12 \\
      --service-cluster-ip-range=10.96.0.0/12,fd00:1111::/112  \\
      --service-node-port-range=30000-32767  \\
      --etcd-servers=https://192.168.10.11:2379,https://192.168.10.12:2379,https://192.168.10.13: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

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

[Install]
WantedBy=multi-user.target

EOF




# master03 配置
cat > /usr/lib/systemd/system/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.10.13 \\
      --service-cluster-ip-range=10.96.0.0/12,fd00:1111::/112  \\
      --service-node-port-range=30000-32767  \\
      --etcd-servers=https://192.168.10.11:2379,https://192.168.10.12:2379,https://192.168.10.13: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

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

[Install]
WantedBy=multi-user.target

EOF


# 启动 apiServer
systemctl daemon-reload

systemctl enable --now kube-apiserver.service

systemctl status kube-apiserver.service

该配置文件是用于定义Kubernetes API Server的systemd服务的配置。systemd是一个用于启动和管理Linux系统服务的守护进程。

[Unit]

  • Description: 服务的描述信息,用于显示在日志和系统管理工具中。
  • Documentation: 提供关于服务的文档链接。
  • After: 规定服务依赖于哪些其他服务或单元。在这个例子中,API Server服务在网络目标启动之后启动。

[Service]

  • ExecStart: 定义服务的命令行参数和命令。这里指定了API Server的启动命令,包括各种参数选项。
  • Restart: 指定当服务退出时应该如何重新启动。在这个例子中,服务在失败时将被重新启动。
  • RestartSec: 指定两次重新启动之间的等待时间。
  • LimitNOFILE: 指定进程可以打开的文件描述符的最大数量。

[Install]

  • WantedBy: 指定服务应该安装到哪个系统目标。在这个例子中,服务将被安装到multi-user.target目标,以便在多用户模式下启动。

上述配置文件中定义的kube-apiserver服务将以指定的参数运行,这些参数包括:

  • --v=2 指定日志级别为2,打印详细的API Server日志。
  • --allow-privileged=true 允许特权容器运行。
  • --bind-address=0.0.0.0 绑定API Server监听的IP地址。
  • --secure-port=6443 指定API Server监听的安全端口。
  • --advertise-address=192.168.1.31 广告API Server的地址。
  • --service-cluster-ip-range=10.96.0.0/12,fd00:1111::/112 指定服务CIDR范围。
  • --service-node-port-range=30000-32767 指定NodePort的范围。
  • --etcd-servers=https://192.168.1.31:2379,https://192.168.1.32:2379,https://192.168.1.33:2379 指定etcd服务器的地址。
  • --etcd-cafile 指定etcd服务器的CA证书。
  • --etcd-certfile 指定etcd服务器的证书。
  • --etcd-keyfile 指定etcd服务器的私钥。
  • --client-ca-file 指定客户端CA证书。
  • --tls-cert-file 指定服务的证书。
  • --tls-private-key-file 指定服务的私钥。
  • --kubelet-client-certificate--kubelet-client-key 指定与kubelet通信的客户端证书和私钥。
  • --service-account-key-file 指定服务账户公钥文件。
  • --service-account-signing-key-file 指定服务账户签名密钥文件。
  • --service-account-issuer 指定服务账户的发布者。
  • --kubelet-preferred-address-types 指定kubelet通信时的首选地址类型。
  • --enable-admission-plugins 启用一系列准入插件。
  • --authorization-mode 指定授权模式。
  • --enable-bootstrap-token-auth 启用引导令牌认证。
  • --requestheader-client-ca-file 指定请求头中的客户端CA证书。
  • --proxy-client-cert-file--proxy-client-key-file 指定代理客户端的证书和私钥。
  • --requestheader-allowed-names 指定请求头中允许的名字。
  • --requestheader-group-headers 指定请求头中的组头。
  • --requestheader-extra-headers-prefix 指定请求头中的额外头前缀。
  • --requestheader-username-headers 指定请求头中的用户名头。
  • --enable-aggregator-routing 启用聚合路由。

整个配置文件为Kubernetes API Server提供了必要的参数,以便正确地启动和运行。

# 配置 kube-controller-manager service
# 所有master节点配置,且配置相同
# 172.16.0.0/12为pod网段,按需求设置你自己的网段

cat > /usr/lib/systemd/system/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=0.0.0.0 \\
      --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 \\
      --controllers=*,bootstrapsigner,tokencleaner \\
      --allocate-node-cidrs=true \\
      --service-cluster-ip-range=10.96.0.0/12,fd00:1111::/112 \\
      --cluster-cidr=172.16.0.0/12,fc00:2222::/112 \\
      --node-cidr-mask-size-ipv4=24 \\
      --node-cidr-mask-size-ipv6=120 \\
      --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.pem

Restart=always
RestartSec=10s

[Install]
WantedBy=multi-user.target

EOF


# 启动 kube-controller-manager
systemctl daemon-reload

systemctl enable --now kube-controller-manager.service

systemctl status kube-controller-manager.service

这是一个用于启动 Kubernetes 控制器管理器的 systemd 服务单元文件。下面是对每个部分的详细解释:

[Unit]:单元的基本信息部分,用于描述和标识这个服务单元。
Description:服务单元的描述信息,说明了该服务单元的作用,这里是 Kubernetes 控制器管理器。
Documentation:可选项,提供了关于该服务单元的文档链接。
After:定义了该服务单元在哪些其他单元之后启动,这里是 network.target,即在网络服务启动之后启动。

[Service]:定义了服务的运行参数和行为。
ExecStart:指定服务启动时执行的命令,这里是 /usr/local/bin/kube-controller-manager,并通过后续的行继续传递了一系列的参数设置。
Restart:定义了服务在退出后的重新启动策略,这里设置为 always,表示总是重新启动服务。
RestartSec:定义了重新启动服务的时间间隔,这里设置为 10 秒。

[Install]:定义了如何安装和启用服务单元。
WantedBy:指定了服务单元所属的 target,这里是 multi-user.target,表示启动多用户模式下的服务。
在 ExecStart 中传递的参数说明如下:

  • --v=2:设置日志的详细级别为 2。
  • --bind-address=0.0.0.0:绑定的 IP 地址,用于监听 Kubernetes 控制平面的请求,这里设置为 0.0.0.0,表示监听所有网络接口上的请求。
  • --root-ca-file:根证书文件的路径,用于验证其他组件的证书。
  • --cluster-signing-cert-file:用于签名集群证书的证书文件路径。
  • --cluster-signing-key-file:用于签名集群证书的私钥文件路径。
  • --service-account-private-key-file:用于签名服务账户令牌的私钥文件路径。
  • --kubeconfig:kubeconfig 文件的路径,包含了与 Kubernetes API 服务器通信所需的配置信息。
  • --leader-elect=true:启用 Leader 选举机制,确保只有一个控制器管理器作为 leader 在运行。
  • --use-service-account-credentials=true:使用服务账户的凭据进行认证和授权。
  • --node-monitor-grace-period=40s:节点监控的优雅退出时间,节点长时间不响应时会触发节点驱逐。
  • --node-monitor-period=5s:节点监控的检测周期,用于检测节点是否正常运行。
  • --controllers:指定要运行的控制器类型,在这里使用了通配符 *,表示运行所有的控制器,同时还包括了 bootstrapsigner 和 tokencleaner 控制器。
  • --allocate-node-cidrs=true:为节点分配 CIDR 子网,用于分配 Pod 网络地址。
  • --service-cluster-ip-range:定义 Service 的 IP 范围,这里设置为 10.96.0.0/12 和 fd00::/108。
  • --cluster-cidr:定义集群的 CIDR 范围,这里设置为 172.16.0.0/12 和 fc00::/48。
  • --node-cidr-mask-size-ipv4:分配给每个节点的 IPv4 子网掩码大小,默认是 24。
  • --node-cidr-mask-size-ipv6:分配给每个节点的 IPv6 子网掩码大小,默认是 120。
  • --requestheader-client-ca-file:设置请求头中客户端 CA 的证书文件路径,用于认证请求头中的 CA 证书。

这个服务单元文件描述了 Kubernetes 控制器管理器的启动参数和行为,并且定义了服务的依赖关系和重新启动策略。通过 systemd 启动该服务单元,即可启动 Kubernetes 控制器管理器组件。

# 配置 kube-scheduler service
# 所有 master 节点配置,且配置相同
cat > /usr/lib/systemd/system/kube-scheduler.service << EOF

[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/kubernetes/kubernetes
After=network.target

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

Restart=always
RestartSec=10s

[Install]
WantedBy=multi-user.target

EOF



# 启动 kube-scheduler
systemctl daemon-reload

systemctl enable --now kube-scheduler.service

systemctl status kube-scheduler.service

这是一个用于启动 Kubernetes 调度器的 systemd 服务单元文件。下面是对每个部分的详细解释:

[Unit]:单元的基本信息部分,用于描述和标识这个服务单元。
Description:服务单元的描述信息,说明了该服务单元的作用,这里是 Kubernetes 调度器。
Documentation:可选项,提供了关于该服务单元的文档链接。
After:定义了该服务单元在哪些其他单元之后启动,这里是 network.target,即在网络服务启动之后启动。

[Service]:定义了服务的运行参数和行为。
ExecStart:指定服务启动时执行的命令,这里是 /usr/local/bin/kube-scheduler,并通过后续的行继续传递了一系列的参数设置。
Restart:定义了服务在退出后的重新启动策略,这里设置为 always,表示总是重新启动服务。
RestartSec:定义了重新启动服务的时间间隔,这里设置为 10 秒。

[Install]:定义了如何安装和启用服务单元。
WantedBy:指定了服务单元所属的 target,这里是 multi-user.target,表示启动多用户模式下的服务。

在 ExecStart 中传递的参数说明如下:

  • --v=2:设置日志的详细级别为 2。
  • --bind-address=0.0.0.0:绑定的 IP 地址,用于监听 Kubernetes 控制平面的请求,这里设置为 0.0.0.0,表示监听所有网络接口上的请求。
  • --leader-elect=true:启用 Leader 选举机制,确保只有一个调度器作为 leader 在运行。
  • --kubeconfig=/etc/kubernetes/scheduler.kubeconfig:kubeconfig 文件的路径,包含了与 Kubernetes API 服务器通信所需的配置信息。

这个服务单元文件描述了 Kubernetes 调度器的启动参数和行为,并且定义了服务的依赖关系和重新启动策略。通过 systemd 启动该服务单元,即可启动 Kubernetes 调度器组件。

四、TLS Bootstrapping 配置

# 在 master01 上配置
kubectl config set-cluster kubernetes     \
--certificate-authority=/etc/kubernetes/pki/ca.pem     \
--embed-certs=true     --server=https://127.0.0.1:8443     \
--kubeconfig=/etc/kubernetes/bootstrap-kubelet.kubeconfig

kubectl config set-credentials tls-bootstrap-token-user     \
--token=c8ad9c.2e4d610cf3e7426e \
--kubeconfig=/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

kubectl config use-context tls-bootstrap-token-user@kubernetes     \
--kubeconfig=/etc/kubernetes/bootstrap-kubelet.kubeconfig

mkdir -p /root/.kube ; cp /etc/kubernetes/admin.kubeconfig /root/.kube/config
# 查看集群状态
kubectl get cs
cat > 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
    
    
kubectl create -f bootstrap.secret.yaml

五、Node 配置

1、复制相关证书至 node

# 在 master01 上将证书复制到 node 节点
cd /etc/kubernetes/
 
for NODE in k8s-master02 k8s-master03 k8s-node01 k8s-node02; do ssh $NODE mkdir -p /etc/kubernetes/pki; for FILE in pki/ca.pem pki/ca-key.pem pki/front-proxy-ca.pem bootstrap-kubelet.kubeconfig kube-proxy.kubeconfig; do scp /etc/kubernetes/$FILE $NODE:/etc/kubernetes/${FILE}; done; done

2、配置 kubelet(所有节点)

# kubelet 配置
# 当使用 docker 作为 Runtime
cat > /usr/lib/systemd/system/kubelet.service << EOF

[Unit]
Description=Kubernetes Kubelet
Documentation=https://github.com/kubernetes/kubernetes
After=network-online.target firewalld.service cri-docker.service docker.socket containerd.service
Wants=network-online.target
Requires=docker.socket containerd.service

[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

# IPv6示例
# 若不使用IPv6那么忽略此项即可
# 下方 --node-ip 更换为每个节点的IP即可
# cat > /usr/lib/systemd/system/kubelet.service << EOF
# [Unit]
# Description=Kubernetes Kubelet
# Documentation=https://github.com/kubernetes/kubernetes
# After=network-online.target firewalld.service cri-docker.service docker.socket # containerd.service
# Wants=network-online.target
# Requires=docker.socket containerd.service

# [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=   \\
#     --node-ip=192.168.1.31,2408:822a:245:8c01::fab
# [Install]
# WantedBy=multi-user.target
# EOF

cat > /etc/kubernetes/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

systemctl daemon-reload

systemctl enable --now kubelet.service

systemctl status kubelet.service

这是一个Kubelet的配置文件,用于配置Kubelet的各项参数。

  • apiVersion: kubelet.config.k8s.io/v1beta1:指定了配置文件的API版本为kubelet.config.k8s.io/v1beta1。
  • kind: KubeletConfiguration:指定了配置类别为KubeletConfiguration。
  • address: 0.0.0.0:指定了Kubelet监听的地址为0.0.0.0。
  • port: 10250:指定了Kubelet监听的端口为10250。
  • readOnlyPort: 10255:指定了只读端口为10255,用于提供只读的状态信息。
  • authentication:指定了认证相关的配置信息。
    • anonymous.enabled: false:禁用了匿名认证。
    • webhook.enabled: true:启用了Webhook认证。
    • x509.clientCAFile: /etc/kubernetes/pki/ca.pem:指定了X509证书的客户端CA文件路径。
  • authorization:指定了授权相关的配置信息。
    • mode: Webhook:指定了授权模式为Webhook。
    • webhook.cacheAuthorizedTTL: 5m0s:指定了授权缓存时间段为5分钟。
    • webhook.cacheUnauthorizedTTL: 30s:指定了未授权缓存时间段为30秒。
  • cgroupDriver: systemd:指定了Cgroup驱动为systemd。
  • cgroupsPerQOS: true:启用了每个QoS类别一个Cgroup的设置。
  • clusterDNS: 指定了集群的DNS服务器地址列表。
    • 10.96.0.10:指定了DNS服务器地址为10.96.0.10。
  • clusterDomain: cluster.local:指定了集群的域名后缀为cluster.local。
  • containerLogMaxFiles: 5:指定了容器日志文件保留的最大数量为5个。
  • containerLogMaxSize: 10Mi:指定了容器日志文件的最大大小为10Mi。
  • contentType: application/vnd.kubernetes.protobuf:指定了内容类型为protobuf。
  • cpuCFSQuota: true:启用了CPU CFS Quota。
  • cpuManagerPolicy: none:禁用了CPU Manager。
  • cpuManagerReconcilePeriod: 10s:指定了CPU管理器的调整周期为10秒。
  • enableControllerAttachDetach: true:启用了控制器的挂载和拆卸。
  • enableDebuggingHandlers: true:启用了调试处理程序。
  • enforceNodeAllocatable: 指定了强制节点可分配资源的列表。
    • pods:强制节点可分配pods资源。
  • eventBurst: 10:指定了事件突发的最大数量为10。
  • eventRecordQPS: 5:指定了事件记录的最大请求量为5。
  • evictionHard: 指定了驱逐硬性限制参数的配置信息。
    • imagefs.available: 15%:指定了镜像文件系统可用空间的限制为15%。
    • memory.available: 100Mi:指定了可用内存的限制为100Mi。
    • nodefs.available: 10%:指定了节点文件系统可用空间的限制为10%。
    • nodefs.inodesFree: 5%:指定了节点文件系统可用inode的限制为5%。
  • evictionPressureTransitionPeriod: 5m0s:指定了驱逐压力转换的时间段为5分钟。
  • failSwapOn: true:指定了在发生OOM时禁用交换分区。
  • fileCheckFrequency: 20s:指定了文件检查频率为20秒。
  • hairpinMode: promiscuous-bridge:设置了Hairpin Mode为"promiscuous-bridge"。
  • healthzBindAddress: 127.0.0.1:指定了健康检查的绑定地址为127.0.0.1。
  • healthzPort: 10248:指定了健康检查的端口为10248。
  • httpCheckFrequency: 20s:指定了HTTP检查的频率为20秒。
  • imageGCHighThresholdPercent: 85:指定了镜像垃圾回收的上阈值为85%。
  • imageGCLowThresholdPercent: 80:指定了镜像垃圾回收的下阈值为80%。
  • imageMinimumGCAge: 2m0s:指定了镜像垃圾回收的最小时间为2分钟。
  • iptablesDropBit: 15:指定了iptables的Drop Bit为15。
  • iptablesMasqueradeBit: 14:指定了iptables的Masquerade Bit为14。
  • kubeAPIBurst: 10:指定了KubeAPI的突发请求数量为10个。
  • kubeAPIQPS: 5:指定了KubeAPI的每秒请求频率为5个。
  • makeIPTablesUtilChains: true:指定了是否使用iptables工具链。
  • maxOpenFiles: 1000000:指定了最大打开文件数为1000000。
  • maxPods: 110:指定了最大的Pod数量为110。
  • nodeStatusUpdateFrequency: 10s:指定了节点状态更新的频率为10秒。
  • oomScoreAdj: -999:指定了OOM Score Adjustment为-999。
  • podPidsLimit: -1:指定了Pod的PID限制为-1,表示无限制。
  • registryBurst: 10:指定了Registry的突发请求数量为10个。
  • registryPullQPS: 5:指定了Registry的每秒拉取请求数量为5个。
  • resolvConf: /etc/resolv.conf:指定了resolv.conf的文件路径。
  • rotateCertificates: true:指定了是否轮转证书。
  • runtimeRequestTimeout: 2m0s:指定了运行时请求的超时时间为2分钟。
  • serializeImagePulls: true:指定了是否序列化镜像拉取。
  • staticPodPath: /etc/kubernetes/manifests:指定了静态Pod的路径。
  • streamingConnectionIdleTimeout: 4h0m0s:指定了流式连接的空闲超时时间为4小时。
  • syncFrequency: 1m0s:指定了同步频率为1分钟。
  • volumeStatsAggPeriod: 1m0s:指定了卷统计聚合周期为1分钟。

3、kube-proxy 配置(所有节点)

# 将 kubeconfig 发送至其他节点
# master-1 执行
for NODE in k8s-master02 k8s-master03 k8s-node01 k8s-node02; do scp /etc/kubernetes/kube-proxy.kubeconfig $NODE:/etc/kubernetes/kube-proxy.kubeconfig; done
# 所有 k8s 节点添加 kube-proxy 的 service 文件
cat >  /usr/lib/systemd/system/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 \\
  --cluster-cidr=172.16.0.0/12,fc00:2222::/112 \\
  --v=2
Restart=always
RestartSec=10s

[Install]
WantedBy=multi-user.target

EOF


# 所有 k8s节点添加 kube-proxy 的配置
cat > /etc/kubernetes/kube-proxy.yaml << 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,fc00:2222::/112
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



systemctl daemon-reload

systemctl enable --now kube-proxy.service

systemctl status kube-proxy.service

这是一个 Kubernetes 的 kube-proxy 组件配置文件示例。以下是每个配置项的详细解释:

  1. apiVersion: kubeproxy.config.k8s.io/v1alpha1
  • 指定该配置文件的 API 版本。
  1. bindAddress: 0.0.0.0
  • 指定 kube-proxy 使用的监听地址。0.0.0.0 表示监听所有网络接口。
  1. clientConnection:
  • 客户端连接配置项。

a. acceptContentTypes: ""

  • 指定接受的内容类型。

b. burst: 10

  • 客户端请求超出qps设置时的最大突发请求数。

c. contentType: application/vnd.kubernetes.protobuf

  • 指定客户端请求的内容类型。

d. kubeconfig: /etc/kubernetes/kube-proxy.kubeconfig

  • kube-proxy使用的kubeconfig文件路径。

e. qps: 5

  • 每秒向API服务器发送的请求数量。
  1. clusterCIDR: 172.16.0.0/12,fc00:2222::/112
  • 指定集群使用的CIDR范围,用于自动分配Pod IP。
  1. configSyncPeriod: 15m0s
  • 指定kube-proxy配置同步到节点的频率。
  1. conntrack:
  • 连接跟踪设置。

a. max: null

  • 指定连接跟踪的最大值。

b. maxPerCore: 32768

  • 指定每个核心的最大连接跟踪数。

c. min: 131072

  • 指定最小的连接跟踪数。

d. tcpCloseWaitTimeout: 1h0m0s

  • 指定处于CLOSE_WAIT状态的TCP连接的超时时间。

e. tcpEstablishedTimeout: 24h0m0s

  • 指定已建立的TCP连接的超时时间。
  1. enableProfiling: false
  • 是否启用性能分析。
  1. healthzBindAddress: 0.0.0.0:10256
  • 指定健康检查监听地址和端口。
  1. hostnameOverride: ""
  • 指定覆盖默认主机名的值。
  1. iptables:
  • iptables设置。

a. masqueradeAll: false

  • 是否对所有流量使用IP伪装。

b. masqueradeBit: 14

  • 指定伪装的Bit标记。

c. minSyncPeriod: 0s

  • 指定同步iptables规则的最小间隔。

d. syncPeriod: 30s

  • 指定同步iptables规则的时间间隔。
  1. ipvs:
  • ipvs设置。

a. masqueradeAll: true

  • 是否对所有流量使用IP伪装。

b. minSyncPeriod: 5s

  • 指定同步ipvs规则的最小间隔。

c. scheduler: "rr"

  • 指定ipvs默认使用的调度算法。

d. syncPeriod: 30s

  • 指定同步ipvs规则的时间间隔。
  1. kind: KubeProxyConfiguration
  • 指定该配置文件的类型。
  1. metricsBindAddress: 127.0.0.1:10249
  • 指定指标绑定的地址和端口。
  1. mode: "ipvs"
  • 指定kube-proxy的模式。这里指定为ipvs,使用IPVS代理模式。
  1. nodePortAddresses: null
  • 指定可用于NodePort的网络地址。
  1. oomScoreAdj: -999
  • 指定kube-proxy的OOM优先级。
  1. portRange: ""
  • 指定可用于服务端口范围。
  1. udpIdleTimeout: 250ms
  • 指定UDP连接的空闲超时时间。

六、安装网络插件

wget https://mirrors.chenby.cn/https://github.com/projectcalico/calico/blob/master/manifests/calico-typha.yaml

cp calico-typha.yaml calico.yaml

vim calico.yaml
# calico-config ConfigMap处
    "ipam": {
        "type": "calico-ipam",
    },
    - name: IP
      value: "autodetect"

    - name: CALICO_IPV4POOL_CIDR
      value: "172.16.0.0/12"

# vim calico-ipv6.yaml
# calico-config ConfigMap处
#     "ipam": {
#         "type": "calico-ipam",
#         "assign_ipv4": "true",
#         "assign_ipv6": "true"
#     },
#     - name: IP
#       value: "autodetect"
# 
#     - name: IP6
#       value: "autodetect"
# 
#     - name: CALICO_IPV4POOL_CIDR
#       value: "172.16.0.0/12"
# 
#     - name: CALICO_IPV6POOL_CIDR
#       value: "fc00:2222::/112"
# 
#     - name: FELIX_IPV6SUPPORT
#       value: "true"


# 若docker镜像拉不下来,可以使用国内的仓库
sed -i "s#docker.io/calico/#m.daocloud.io/docker.io/calico/#g" calico.yaml 
sed -i "s#docker.io/calico/#m.daocloud.io/docker.io/calico/#g" calico-ipv6.yaml

sed -i "s#m.daocloud.io/docker.io/calico/#docker.io/calico/#g" calico.yaml 
sed -i "s#m.daocloud.io/docker.io/calico/#docker.io/calico/#g" calico-ipv6.yaml

# 本地没有公网 IPv6 使用 calico.yaml
kubectl apply -f calico.yaml

七、安装 CoreDNS(只在 master01 操作)

# 安装 helm,官方脚本,保存执行
#!/usr/bin/env bash

# Copyright The Helm Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# The install script is based off of the MIT-licensed script from glide,
# the package manager for Go: https://github.com/Masterminds/glide.sh/blob/master/get

: ${BINARY_NAME:="helm"}
: ${USE_SUDO:="true"}
: ${DEBUG:="false"}
: ${VERIFY_CHECKSUM:="true"}
: ${VERIFY_SIGNATURES:="false"}
: ${HELM_INSTALL_DIR:="/usr/local/bin"}
: ${GPG_PUBRING:="pubring.kbx"}

HAS_CURL="$(type "curl" &> /dev/null && echo true || echo false)"
HAS_WGET="$(type "wget" &> /dev/null && echo true || echo false)"
HAS_OPENSSL="$(type "openssl" &> /dev/null && echo true || echo false)"
HAS_GPG="$(type "gpg" &> /dev/null && echo true || echo false)"
HAS_GIT="$(type "git" &> /dev/null && echo true || echo false)"

# initArch discovers the architecture for this system.
initArch() {
  ARCH=$(uname -m)
  case $ARCH in
    armv5*) ARCH="armv5";;
    armv6*) ARCH="armv6";;
    armv7*) ARCH="arm";;
    aarch64) ARCH="arm64";;
    x86) ARCH="386";;
    x86_64) ARCH="amd64";;
    i686) ARCH="386";;
    i386) ARCH="386";;
  esac
}

# initOS discovers the operating system for this system.
initOS() {
  OS=$(echo `uname`|tr '[:upper:]' '[:lower:]')

  case "$OS" in
    # Minimalist GNU for Windows
    mingw*|cygwin*) OS='windows';;
  esac
}

# runs the given command as root (detects if we are root already)
runAsRoot() {
  if [ $EUID -ne 0 -a "$USE_SUDO" = "true" ]; then
    sudo "${@}"
  else
    "${@}"
  fi
}

# verifySupported checks that the os/arch combination is supported for
# binary builds, as well whether or not necessary tools are present.
verifySupported() {
  local supported="darwin-amd64\ndarwin-arm64\nlinux-386\nlinux-amd64\nlinux-arm\nlinux-arm64\nlinux-ppc64le\nlinux-s390x\nlinux-riscv64\nwindows-amd64"
  if ! echo "${supported}" | grep -q "${OS}-${ARCH}"; then
    echo "No prebuilt binary for ${OS}-${ARCH}."
    echo "To build from source, go to https://github.com/helm/helm"
    exit 1
  fi

  if [ "${HAS_CURL}" != "true" ] && [ "${HAS_WGET}" != "true" ]; then
    echo "Either curl or wget is required"
    exit 1
  fi

  if [ "${VERIFY_CHECKSUM}" == "true" ] && [ "${HAS_OPENSSL}" != "true" ]; then
    echo "In order to verify checksum, openssl must first be installed."
    echo "Please install openssl or set VERIFY_CHECKSUM=false in your environment."
    exit 1
  fi

  if [ "${VERIFY_SIGNATURES}" == "true" ]; then
    if [ "${HAS_GPG}" != "true" ]; then
      echo "In order to verify signatures, gpg must first be installed."
      echo "Please install gpg or set VERIFY_SIGNATURES=false in your environment."
      exit 1
    fi
    if [ "${OS}" != "linux" ]; then
      echo "Signature verification is currently only supported on Linux."
      echo "Please set VERIFY_SIGNATURES=false or verify the signatures manually."
      exit 1
    fi
  fi

  if [ "${HAS_GIT}" != "true" ]; then
    echo "[WARNING] Could not find git. It is required for plugin installation."
  fi
}

# checkDesiredVersion checks if the desired version is available.
checkDesiredVersion() {
  if [ "x$DESIRED_VERSION" == "x" ]; then
    # Get tag from release URL
    local latest_release_url="https://get.helm.sh/helm-latest-version"
    local latest_release_response=""
    if [ "${HAS_CURL}" == "true" ]; then
      latest_release_response=$( curl -L --silent --show-error --fail "$latest_release_url" 2>&1 || true )
    elif [ "${HAS_WGET}" == "true" ]; then
      latest_release_response=$( wget "$latest_release_url" -q -O - 2>&1 || true )
    fi
    TAG=$( echo "$latest_release_response" | grep '^v[0-9]' )
    if [ "x$TAG" == "x" ]; then
      printf "Could not retrieve the latest release tag information from %s: %s\n" "${latest_release_url}" "${latest_release_response}"
      exit 1
    fi
  else
    TAG=$DESIRED_VERSION
  fi
}

# checkHelmInstalledVersion checks which version of helm is installed and
# if it needs to be changed.
checkHelmInstalledVersion() {
  if [[ -f "${HELM_INSTALL_DIR}/${BINARY_NAME}" ]]; then
    local version=$("${HELM_INSTALL_DIR}/${BINARY_NAME}" version --template="{{ .Version }}")
    if [[ "$version" == "$TAG" ]]; then
      echo "Helm ${version} is already ${DESIRED_VERSION:-latest}"
      return 0
    else
      echo "Helm ${TAG} is available. Changing from version ${version}."
      return 1
    fi
  else
    return 1
  fi
}

# downloadFile downloads the latest binary package and also the checksum
# for that binary.
downloadFile() {
  HELM_DIST="helm-$TAG-$OS-$ARCH.tar.gz"
  DOWNLOAD_URL="https://get.helm.sh/$HELM_DIST"
  CHECKSUM_URL="$DOWNLOAD_URL.sha256"
  HELM_TMP_ROOT="$(mktemp -dt helm-installer-XXXXXX)"
  HELM_TMP_FILE="$HELM_TMP_ROOT/$HELM_DIST"
  HELM_SUM_FILE="$HELM_TMP_ROOT/$HELM_DIST.sha256"
  echo "Downloading $DOWNLOAD_URL"
  if [ "${HAS_CURL}" == "true" ]; then
    curl -SsL "$CHECKSUM_URL" -o "$HELM_SUM_FILE"
    curl -SsL "$DOWNLOAD_URL" -o "$HELM_TMP_FILE"
  elif [ "${HAS_WGET}" == "true" ]; then
    wget -q -O "$HELM_SUM_FILE" "$CHECKSUM_URL"
    wget -q -O "$HELM_TMP_FILE" "$DOWNLOAD_URL"
  fi
}

# verifyFile verifies the SHA256 checksum of the binary package
# and the GPG signatures for both the package and checksum file
# (depending on settings in environment).
verifyFile() {
  if [ "${VERIFY_CHECKSUM}" == "true" ]; then
    verifyChecksum
  fi
  if [ "${VERIFY_SIGNATURES}" == "true" ]; then
    verifySignatures
  fi
}

# installFile installs the Helm binary.
installFile() {
  HELM_TMP="$HELM_TMP_ROOT/$BINARY_NAME"
  mkdir -p "$HELM_TMP"
  tar xf "$HELM_TMP_FILE" -C "$HELM_TMP"
  HELM_TMP_BIN="$HELM_TMP/$OS-$ARCH/helm"
  echo "Preparing to install $BINARY_NAME into ${HELM_INSTALL_DIR}"
  runAsRoot cp "$HELM_TMP_BIN" "$HELM_INSTALL_DIR/$BINARY_NAME"
  echo "$BINARY_NAME installed into $HELM_INSTALL_DIR/$BINARY_NAME"
}

# verifyChecksum verifies the SHA256 checksum of the binary package.
verifyChecksum() {
  printf "Verifying checksum... "
  local sum=$(openssl sha1 -sha256 ${HELM_TMP_FILE} | awk '{print $2}')
  local expected_sum=$(cat ${HELM_SUM_FILE})
  if [ "$sum" != "$expected_sum" ]; then
    echo "SHA sum of ${HELM_TMP_FILE} does not match. Aborting."
    exit 1
  fi
  echo "Done."
}

# verifySignatures obtains the latest KEYS file from GitHub main branch
# as well as the signature .asc files from the specific GitHub release,
# then verifies that the release artifacts were signed by a maintainer's key.
verifySignatures() {
  printf "Verifying signatures... "
  local keys_filename="KEYS"
  local github_keys_url="https://raw.githubusercontent.com/helm/helm/main/${keys_filename}"
  if [ "${HAS_CURL}" == "true" ]; then
    curl -SsL "${github_keys_url}" -o "${HELM_TMP_ROOT}/${keys_filename}"
  elif [ "${HAS_WGET}" == "true" ]; then
    wget -q -O "${HELM_TMP_ROOT}/${keys_filename}" "${github_keys_url}"
  fi
  local gpg_keyring="${HELM_TMP_ROOT}/keyring.gpg"
  local gpg_homedir="${HELM_TMP_ROOT}/gnupg"
  mkdir -p -m 0700 "${gpg_homedir}"
  local gpg_stderr_device="/dev/null"
  if [ "${DEBUG}" == "true" ]; then
    gpg_stderr_device="/dev/stderr"
  fi
  gpg --batch --quiet --homedir="${gpg_homedir}" --import "${HELM_TMP_ROOT}/${keys_filename}" 2> "${gpg_stderr_device}"
  gpg --batch --no-default-keyring --keyring "${gpg_homedir}/${GPG_PUBRING}" --export > "${gpg_keyring}"
  local github_release_url="https://github.com/helm/helm/releases/download/${TAG}"
  if [ "${HAS_CURL}" == "true" ]; then
    curl -SsL "${github_release_url}/helm-${TAG}-${OS}-${ARCH}.tar.gz.sha256.asc" -o "${HELM_TMP_ROOT}/helm-${TAG}-${OS}-${ARCH}.tar.gz.sha256.asc"
    curl -SsL "${github_release_url}/helm-${TAG}-${OS}-${ARCH}.tar.gz.asc" -o "${HELM_TMP_ROOT}/helm-${TAG}-${OS}-${ARCH}.tar.gz.asc"
  elif [ "${HAS_WGET}" == "true" ]; then
    wget -q -O "${HELM_TMP_ROOT}/helm-${TAG}-${OS}-${ARCH}.tar.gz.sha256.asc" "${github_release_url}/helm-${TAG}-${OS}-${ARCH}.tar.gz.sha256.asc"
    wget -q -O "${HELM_TMP_ROOT}/helm-${TAG}-${OS}-${ARCH}.tar.gz.asc" "${github_release_url}/helm-${TAG}-${OS}-${ARCH}.tar.gz.asc"
  fi
  local error_text="If you think this might be a potential security issue,"
  error_text="${error_text}\nplease see here: https://github.com/helm/community/blob/master/SECURITY.md"
  local num_goodlines_sha=$(gpg --verify --keyring="${gpg_keyring}" --status-fd=1 "${HELM_TMP_ROOT}/helm-${TAG}-${OS}-${ARCH}.tar.gz.sha256.asc" 2> "${gpg_stderr_device}" | grep -c -E '^\[GNUPG:\] (GOODSIG|VALIDSIG)')
  if [[ ${num_goodlines_sha} -lt 2 ]]; then
    echo "Unable to verify the signature of helm-${TAG}-${OS}-${ARCH}.tar.gz.sha256!"
    echo -e "${error_text}"
    exit 1
  fi
  local num_goodlines_tar=$(gpg --verify --keyring="${gpg_keyring}" --status-fd=1 "${HELM_TMP_ROOT}/helm-${TAG}-${OS}-${ARCH}.tar.gz.asc" 2> "${gpg_stderr_device}" | grep -c -E '^\[GNUPG:\] (GOODSIG|VALIDSIG)')
  if [[ ${num_goodlines_tar} -lt 2 ]]; then
    echo "Unable to verify the signature of helm-${TAG}-${OS}-${ARCH}.tar.gz!"
    echo -e "${error_text}"
    exit 1
  fi
  echo "Done."
}

# fail_trap is executed if an error occurs.
fail_trap() {
  result=$?
  if [ "$result" != "0" ]; then
    if [[ -n "$INPUT_ARGUMENTS" ]]; then
      echo "Failed to install $BINARY_NAME with the arguments provided: $INPUT_ARGUMENTS"
      help
    else
      echo "Failed to install $BINARY_NAME"
    fi
    echo -e "\tFor support, go to https://github.com/helm/helm."
  fi
  cleanup
  exit $result
}

# testVersion tests the installed client to make sure it is working.
testVersion() {
  set +e
  HELM="$(command -v $BINARY_NAME)"
  if [ "$?" = "1" ]; then
    echo "$BINARY_NAME not found. Is $HELM_INSTALL_DIR on your "'$PATH?'
    exit 1
  fi
  set -e
}

# help provides possible cli installation arguments
help () {
  echo "Accepted cli arguments are:"
  echo -e "\t[--help|-h ] ->> prints this help"
  echo -e "\t[--version|-v <desired_version>] . When not defined it fetches the latest release from GitHub"
  echo -e "\te.g. --version v3.0.0 or -v canary"
  echo -e "\t[--no-sudo]  ->> install without sudo"
}

# cleanup temporary files to avoid https://github.com/helm/helm/issues/2977
cleanup() {
  if [[ -d "${HELM_TMP_ROOT:-}" ]]; then
    rm -rf "$HELM_TMP_ROOT"
  fi
}

# Execution

#Stop execution on any error
trap "fail_trap" EXIT
set -e

# Set debug if desired
if [ "${DEBUG}" == "true" ]; then
  set -x
fi

# Parsing input arguments (if any)
export INPUT_ARGUMENTS="${@}"
set -u
while [[ $# -gt 0 ]]; do
  case $1 in
    '--version'|-v)
       shift
       if [[ $# -ne 0 ]]; then
           export DESIRED_VERSION="${1}"
           if [[ "$1" != "v"* ]]; then
               echo "Expected version arg ('${DESIRED_VERSION}') to begin with 'v', fixing..."
               export DESIRED_VERSION="v${1}"
           fi
       else
           echo -e "Please provide the desired version. e.g. --version v3.0.0 or -v canary"
           exit 0
       fi
       ;;
    '--no-sudo')
       USE_SUDO="false"
       ;;
    '--help'|-h)
       help
       exit 0
       ;;
    *) exit 1
       ;;
  esac
  shift
done
set +u

initArch
initOS
verifySupported
checkDesiredVersion
if ! checkHelmInstalledVersion; then
  downloadFile
  verifyFile
  installFile
fi
testVersion
cleanup
# 下载tgz包
helm repo add coredns https://coredns.github.io/helm
helm pull coredns/coredns
tar xvf coredns-*.tgz
cd coredns/

# 修改IP地址
vim values.yaml
cat values.yaml | grep clusterIP:
clusterIP: "10.96.0.10"

# 示例
---
service:
# clusterIP: ""
# clusterIPs: []
# loadBalancerIP: ""
# externalIPs: []
# externalTrafficPolicy: ""
# ipFamilyPolicy: ""
  # The name of the Service
  # If not set, a name is generated using the fullname template
  clusterIP: "10.96.0.10"
  name: ""
  annotations: {}
---

# 修改为国内源 docker源可选
sed -i "s#coredns/#m.daocloud.io/docker.io/coredns/#g" values.yaml
sed -i "s#registry.k8s.io/#m.daocloud.io/registry.k8s.io/#g" values.yaml

# 默认参数安装
helm install  coredns ./coredns/ -n kube-system

八、安装 Metrics Server

# 下载 
wget https://mirrors.chenby.cn/https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

# 修改配置
vim components.yaml

---
# 1
			- args:
        - --cert-dir=/tmp
        - --secure-port=10250
        - --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
        - --requestheader-username-headers=X-Remote-User
        - --requestheader-group-headers=X-Remote-Group
        - --requestheader-extra-headers-prefix=X-Remote-Extra-


# 2
        volumeMounts:
        - mountPath: /tmp
          name: tmp-dir
        - name: ca-ssl
          mountPath: /etc/kubernetes/pki

# 3
      volumes:
      - emptyDir: {}
        name: tmp-dir
      - name: ca-ssl
        hostPath:
          path: /etc/kubernetes/pki
---


# 修改为国内源 docker源可选
sed -i "s#registry.k8s.io/#m.daocloud.io/registry.k8s.io/#g" *.yaml

# 执行部署
kubectl apply -f components.yaml

九、安装命令补全

yum install bash-completion -y
source /usr/share/bash-completion/bash_completion
source <(kubectl completion bash)
echo "source <(kubectl completion bash)" >> ~/.bashrc

十、高可用验证

# 确认 etcd 高可用
export ETCDCTL_API=3
etcdctl --endpoints="192.168.10.13:2379,192.168.10.12:2379,192.168.10.11: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
# cat /root/.bashrc
alias ectl='etcdhelper -endpoint "https://192.168.10.12:2379" -key /etc/etcd/ssl/etcd-key.pem  -cert /etc/etcd/ssl/etcd.pem -cacert /etc/etcd/ssl/etcd-ca.pem'

# 查看当前的 schedule 主节点
ectl get /registry/leases/kube-system/kube-scheduler

# 查看当前的 controllermanager 主节点
ectl get /registry/leases/kube-system/kube-controller-manager

读取 etcd 的方式:https://github.com/openshift/origin/tree/master/tools/etcdhelper

官方解释:https://github.com/kubernetes/kubernetes/issues/44670 , protobuf

0

评论区