- 一、环境初始化
- 二、K8S 与 ETCD 下载及安装(在 master01 节点上操作)
- 三、K8S 系统组件配置
- 四、TLS Bootstrapping 配置
- 五、Node 配置
- 六、安装网络插件
- 七、安装 CoreDNS(只在 master01 操作)
- 八、安装 Metrics Server
- 九、安装命令补全
- 十、高可用验证
一、环境初始化
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系统的一些参数设置,用于配置和优化网络、文件系统和虚拟内存等方面的功能。以下是每个参数的详细解释:
- net.ipv4.ip_forward = 1
- 这个参数启用了IPv4的IP转发功能,允许服务器作为网络路由器转发数据包。
- net.bridge.bridge-nf-call-iptables = 1
- 当使用网络桥接技术时,将数据包传递到iptables进行处理。
- fs.may_detach_mounts = 1
- 允许在挂载文件系统时,允许被其他进程使用。
- vm.overcommit_memory=1
- 该设置允许原始的内存过量分配策略,当系统的内存已经被完全使用时,系统仍然会分配额外的内存。
- vm.panic_on_oom=0
- 当系统内存不足(OOM)时,禁用系统崩溃和重启。
- fs.inotify.max_user_watches=89100
- 设置系统允许一个用户的inotify实例可以监控的文件数目的上限。
- fs.file-max=52706963
- 设置系统同时打开的文件数的上限。
- fs.nr_open=52706963
- 设置系统同时打开的文件描述符数的上限。
- net.netfilter.nf_conntrack_max=2310720
- 设置系统可以创建的网络连接跟踪表项的最大数量。
- net.ipv4.tcp_keepalive_time = 600
- 设置TCP套接字的空闲超时时间(秒),超过该时间没有活动数据时,内核会发送心跳包。
- net.ipv4.tcp_keepalive_probes = 3
- 设置未收到响应的TCP心跳探测次数。
- net.ipv4.tcp_keepalive_intvl = 15
- 设置TCP心跳探测的时间间隔(秒)。
- net.ipv4.tcp_max_tw_buckets = 36000
- 设置系统可以使用的TIME_WAIT套接字的最大数量。
- net.ipv4.tcp_tw_reuse = 1
- 启用TIME_WAIT套接字的重新利用,允许新的套接字使用旧的TIME_WAIT套接字。
- net.ipv4.tcp_max_orphans = 327680
- 设置系统可以同时存在的TCP套接字垃圾回收包裹数的最大数量。
- net.ipv4.tcp_orphan_retries = 3
- 设置系统对于孤立的TCP套接字的重试次数。
- net.ipv4.tcp_syncookies = 1
- 启用TCP SYN cookies保护,用于防止SYN洪泛攻击。
- net.ipv4.tcp_max_syn_backlog = 16384
- 设置新的TCP连接的半连接数(半连接队列)的最大长度。
- net.ipv4.ip_conntrack_max = 65536
- 设置系统可以创建的网络连接跟踪表项的最大数量。
- net.ipv4.tcp_timestamps = 0
- 关闭TCP时间戳功能,用于提供更好的安全性。
- net.core.somaxconn = 16384
- 设置系统核心层的连接队列的最大值。
- net.ipv6.conf.all.disable_ipv6 = 0
- 启用IPv6协议。
- net.ipv6.conf.default.disable_ipv6 = 0
- 启用IPv6协议。
- net.ipv6.conf.lo.disable_ipv6 = 0
- 启用IPv6协议。
- 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参数中,我们可以使用以下参数:
- multi-user.target:指定该服务应该在多用户模式下启动。
- graphical.target:指定该服务应该在图形化界面模式下启动。
- default.target:指定该服务应该在系统的默认目标(runlevel)下启动。
- rescue.target:指定该服务应该在系统救援模式下启动。
- poweroff.target:指定该服务应该在关机时启动。
- reboot.target:指定该服务应该在重启时启动。
- halt.target:指定该服务应该在停止时启动。
- 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
该参数文件中包含以下参数:
- exec-opts: 用于设置Docker守护进程的选项,native.cgroupdriver=systemd表示使用systemd作为Cgroup驱动程序。
- registry-mirrors: 用于指定Docker镜像的镜像注册服务器。在这里有三个镜像注册服务器:https://docker.m.daocloud.io、https://docker.mirrors.ustc.edu.cn和http://hub-mirror.c.163.com。
- max-concurrent-downloads: 用于设置同时下载镜像的最大数量,默认值为3,这里设置为10。
- log-driver: 用于设置Docker守护进程的日志驱动程序,这里设置为json-file。
- log-level: 用于设置日志的级别,这里设置为warn。
- log-opts: 用于设置日志驱动程序的选项,这里有两个选项:max-size和max-file。max-size表示每个日志文件的最大大小,这里设置为10m,max-file表示保存的最大日志文件数量,这里设置为3。
- 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
这段配置文件是用于配置加密和认证签名的一些参数。
在这里,有两个部分:signing
和profiles
。
signing
包含了默认签名配置和配置文件。
默认签名配置default
指定了证书的过期时间为876000h
。876000h
表示证书有效期为100年。
profiles
部分定义了不同的证书配置文件。
在这里,只有一个配置文件kubernetes
。它包含了以下usages
和过期时间expiry
:
signing
:用于对其他证书进行签名key encipherment
:用于加密和解密传输数据server auth
:用于服务器身份验证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 组件配置文件示例。以下是每个配置项的详细解释:
- apiVersion: kubeproxy.config.k8s.io/v1alpha1
- 指定该配置文件的 API 版本。
- bindAddress: 0.0.0.0
- 指定 kube-proxy 使用的监听地址。0.0.0.0 表示监听所有网络接口。
- 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服务器发送的请求数量。
- clusterCIDR: 172.16.0.0/12,fc00:2222::/112
- 指定集群使用的CIDR范围,用于自动分配Pod IP。
- configSyncPeriod: 15m0s
- 指定kube-proxy配置同步到节点的频率。
- conntrack:
- 连接跟踪设置。
a. max: null
- 指定连接跟踪的最大值。
b. maxPerCore: 32768
- 指定每个核心的最大连接跟踪数。
c. min: 131072
- 指定最小的连接跟踪数。
d. tcpCloseWaitTimeout: 1h0m0s
- 指定处于CLOSE_WAIT状态的TCP连接的超时时间。
e. tcpEstablishedTimeout: 24h0m0s
- 指定已建立的TCP连接的超时时间。
- enableProfiling: false
- 是否启用性能分析。
- healthzBindAddress: 0.0.0.0:10256
- 指定健康检查监听地址和端口。
- hostnameOverride: ""
- 指定覆盖默认主机名的值。
- iptables:
- iptables设置。
a. masqueradeAll: false
- 是否对所有流量使用IP伪装。
b. masqueradeBit: 14
- 指定伪装的Bit标记。
c. minSyncPeriod: 0s
- 指定同步iptables规则的最小间隔。
d. syncPeriod: 30s
- 指定同步iptables规则的时间间隔。
- ipvs:
- ipvs设置。
a. masqueradeAll: true
- 是否对所有流量使用IP伪装。
b. minSyncPeriod: 5s
- 指定同步ipvs规则的最小间隔。
c. scheduler: "rr"
- 指定ipvs默认使用的调度算法。
d. syncPeriod: 30s
- 指定同步ipvs规则的时间间隔。
- kind: KubeProxyConfiguration
- 指定该配置文件的类型。
- metricsBindAddress: 127.0.0.1:10249
- 指定指标绑定的地址和端口。
- mode: "ipvs"
- 指定kube-proxy的模式。这里指定为ipvs,使用IPVS代理模式。
- nodePortAddresses: null
- 指定可用于NodePort的网络地址。
- oomScoreAdj: -999
- 指定kube-proxy的OOM优先级。
- portRange: ""
- 指定可用于服务端口范围。
- 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
评论区