特别鸣谢:https://github.com/cby-chen/Kubernetes
主机名称 | IP地址 | 说明 | 软件 |
---|---|---|---|
Master01 | 192.168.2.20 | master节点 | apiserver、controller-manager、scheduler、etcd、kubelet、kube-proxy、haproxy、keepalived、nginx |
Node01 | 192.168.2.23 | node节点 | kubelet、kube-proxy |
Node02 | 192.168.2.24 | node节点 | kubelet、kube-proxy |
检查操作系统的版本
# 此方式下安装kubernetes集群要求Centos版本要在7.5或之上
cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core)
主机名设置
hostnamectl set-hostname master
hostnamectl set-hostname worker01
hostnamectl set-hostname worker02
主机名本地解析
cat > /etc/hosts <<EOF
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.2.20 master
192.168.2.21 worker01
192.168.2.22 worker02
EOF
主机ssh免密
# 所有主机执行
yum install -y sshpass
rm -f /root/.ssh/id_rsa*
ssh-keygen -f /root/.ssh/id_rsa -P ''
export IP="192.168.2.20 192.168.2.21 192.168.2.22"
export SSHPASS=123
for HOST in $IP;do
sshpass -e ssh-copy-id -o StrictHostKeyChecking=no $HOST
done
禁用firewalld服务
systemctl stop firewalld
systemctl disable firewalld
禁用selinux
# 关闭selinux
setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=disabled/' /etc/selinux/config
禁用swap分区
启用swap设备会对系统的性能产生负面影响,kubernetes要求每个节点都要禁用swap设备
swapoff -a
sed -ri 's/.*swap.*/#&/' /etc/fstab
NetworkManager 禁用
# Ubuntu忽略,CentOS执行,CentOS9不支持方式一
# 方式一
# systemctl disable --now NetworkManager
# systemctl start network && systemctl enable network
# 方式二
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" 等
# interface-name:tunl* 表示以 "tunl" 开头的接口名称被排除在 NetworkManager 管理之外。例如,"tunl0", "tunl1" 等
时间同步
kubernetes要求集群中的节点时间必须精确一致,使用chronyd服务从网络同步时间
# apt install chrony -y
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.2.0/24
local stratum 10
keyfile /etc/chrony.keys
leapsectz right/UTC
logdir /var/log/chrony
EOF
systemctl restart chronyd ; systemctl enable chronyd
# 客户端
# apt install chrony -y
yum install chrony -y
cat > /etc/chrony.conf << EOF
pool 192.168.2.20 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 makestep
配置ulimit
ulimit -SHn 65535
cat >> /etc/security/limits.conf <<EOF
* soft nofile 655360
* hard nofile 131072
* soft nproc 655350
* hard nproc 655350
* seft memlock unlimited
* hard memlock unlimitedd
EOF
配置ipvs功能
在kubernetes中service有两种代理模型:iptables
和ipvs
。ipvs的性能要高一些,但是需要手动载入ipvs模块
kubernetes和docker在运行中会产生大量的iptables规则,为了不让系统规则跟它们混淆,直接关闭系统的规则. systemctl disable --now iptables
yum install -y ipvsadm ipset sysstat conntrack libseccomp
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
# ip_vs 内核模块,用于实现负载均衡和高可用性。它通过在前端代理服务器上分发传入请求到后端实际服务器上,提供了高性能和可扩展的网络服务。
# ip_vs_rr IPVS 的调度算法之一,使用轮询方式分发请求到后端服务器,每个请求按顺序依次分发。
# ip_vs_wrr IPVS 的调度算法之一,使用加权轮询方式分发请求到后端服务器,每个请求按照指定的权重比例分发。
# ip_vs_sh IPVS 的调度算法之一,使用哈希方式根据源 IP 地址和目标 IP 地址来分发请求。
# nf_conntrack 内核模块,用于跟踪和管理网络连接,包括 TCP、UDP 和 ICMP 等协议。它是实现防火墙状态跟踪的基础。
# ip_tables 内核模块,提供了对 Linux 系统 IP 数据包过滤和网络地址转换(NAT)功能的支持。
# ip_set 内核模块,扩展了 iptables 的功能,支持更高效的 IP 地址集合操作。
# xt_set 内核模块,扩展了 iptables 的功能,支持更高效的数据包匹配和操作。
# ipt_set 用户空间工具,用于配置和管理 xt_set 内核模块。
# ipt_rpfilter 内核模块,用于实现反向路径过滤,用于防止 IP 欺骗和 DDoS 攻击。
# ipt_REJECT iptables 目标,用于拒绝 IP 数据包,并向发送方发送响应,指示数据包被拒绝。
# ipip 内核模块,用于实现 IP 封装在 IP(IP-over-IP)的隧道功能。它可以在不同网络之间创建虚拟隧道来传输 IP 数据包。
修改linux的内核参数
修改linux的内核参数,添加网桥过滤和地址转发功能,将桥接的IPv4流量传递到iptables的链
cat > /etc/sysctl.d/kubernetes.conf << EOF
# sysctls for k8s node config
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
# 以上三条重要
kernel.softlockup_panic = 1
kernel.softlockup_all_cpu_backtrace = 1
fs.file-max = 2097152
fs.may_detach_mounts = 1
fs.inotify.max_user_watches = 524288
fs.inotify.max_user_instances = 8192
fs.inotify.max_queued_events = 16384
vm.swappiness = 0
vm.panic_on_oom = 0
vm.overcommit_memory = 1
vm.max_map_count = 262144
net.core.netdev_max_backlog = 16384
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.somaxconn = 32768
net.ipv4.tcp_max_syn_backlog = 8096
net.ipv4.tcp_slow_start_after_idle = 0
net.ipv4.tcp_rmem = 4096 12582912 16777216
net.ipv4.tcp_wmem = 4096 12582912 16777216
EOF
sysctl --system
# 这些是Linux系统的一些参数设置,用于配置和优化网络、文件系统和虚拟内存等方面的功能:
# net.ipv4.ip_forward 启用IPv4的IP转发功能,允许服务器作为网络路由器转发数据包
# net.bridge.bridge-nf-call-iptables 当使用网络桥接技术时,将数据包传递到iptables进行处理
# fs.may_detach_mounts 允许在挂载文件系统时,允许被其他进程使用
# vm.overcommit_memory 该设置允许原始的内存过量分配策略,当系统的内存已经被完全使用时,系统仍然会分配额外的内存
# vm.panic_on_oom 当系统内存不足(OOM)时,禁用系统崩溃和重启
# fs.inotify.max_user_watches 设置系统允许一个用户的inotify实例可以监控的文件数目的上限
# fs.file-max 设置系统同时打开的文件数的上限
# fs.nr_open 设置系统同时打开的文件描述符数的上限
# net.netfilter.nf_conntrack_max 设置系统可以创建的网络连接跟踪表项的最大数量
# net.ipv4.tcp_keepalive_time 设置TCP套接字的空闲超时时间(秒),超过该时间没有活动数据时,内核会发送心跳包
# net.ipv4.tcp_keepalive_probes 设置未收到响应的TCP心跳探测次数
# net.ipv4.tcp_keepalive_intvl 设置TCP心跳探测的时间间隔(秒)
# net.ipv4.tcp_max_tw_buckets 设置系统可以使用的TIME_WAIT套接字的最大数量
# net.ipv4.tcp_tw_reuse 启用TIME_WAIT套接字的重新利用,允许新的套接字使用旧的TIME_WAIT套接字
# net.ipv4.tcp_max_orphans 设置系统可以同时存在的TCP套接字垃圾回收包裹数的最大数量
# net.ipv4.tcp_orphan_retries 设置系统对于孤立的TCP套接字的重试次数
# net.ipv4.tcp_syncookies 启用TCP SYN cookies保护,用于防止SYN洪泛攻击
# net.ipv4.tcp_max_syn_backlog 设置新的TCP连接的半连接数(半连接队列)的最大长度
# net.ipv4.ip_conntrack_max 设置系统可以创建的网络连接跟踪表项的最大数量
# net.ipv4.tcp_timestamps 关闭TCP时间戳功能,用于提供更好的安全性
# net.core.somaxconn 设置系统核心层的连接队列的最大值
软件下载脚本
#!/bin/bash
# 查看版本地址:
# https://github.com/containernetworking/plugins/releases/
# https://github.com/containerd/containerd/releases/
# https://github.com/kubernetes-sigs/cri-tools/releases/
# https://github.com/Mirantis/cri-dockerd/releases/
# https://github.com/etcd-io/etcd/releases/
# https://github.com/cloudflare/cfssl/releases/
# https://github.com/kubernetes/kubernetes/tree/master/CHANGELOG
# https://download.docker.com/linux/static/stable/x86_64/
# https://github.com/opencontainers/runc/releases/
# https://mirrors.tuna.tsinghua.edu.cn/elrepo/kernel/el7/x86_64/RPMS/
# https://github.com/helm/helm/tags
# http://nginx.org/download/
# Version numbers
cni_plugins_version='v1.5.1'
cri_containerd_cni_version='1.7.18'
crictl_version='v1.30.0'
cri_dockerd_version='0.3.14'
etcd_version='v3.5.13'
cfssl_version='1.6.5'
kubernetes_server_version='1.30.2'
docker_version='26.1.4'
runc_version='1.1.13'
kernel_version='5.4.278'
helm_version='3.15.2'
nginx_version='1.27.0'
# URLs
base_url='https://github.com'
kernel_url="http://mirrors.tuna.tsinghua.edu.cn/elrepo/kernel/el7/x86_64/RPMS/kernel-lt-${kernel_version}-1.el7.elrepo.x86_64.rpm"
runc_url="${base_url}/opencontainers/runc/releases/download/v${runc_version}/runc.amd64"
docker_url="https://mirrors.ustc.edu.cn/docker-ce/linux/static/stable/x86_64/docker-${docker_version}.tgz"
cni_plugins_url="${base_url}/containernetworking/plugins/releases/download/${cni_plugins_version}/cni-plugins-linux-amd64-${cni_plugins_version}.tgz"
cri_containerd_cni_url="${base_url}/containerd/containerd/releases/download/v${cri_containerd_cni_version}/cri-containerd-cni-${cri_containerd_cni_version}-linux-amd64.tar.gz"
crictl_url="${base_url}/kubernetes-sigs/cri-tools/releases/download/${crictl_version}/crictl-${crictl_version}-linux-amd64.tar.gz"
cri_dockerd_url="${base_url}/Mirantis/cri-dockerd/releases/download/v${cri_dockerd_version}/cri-dockerd-${cri_dockerd_version}.amd64.tgz"
etcd_url="${base_url}/etcd-io/etcd/releases/download/${etcd_version}/etcd-${etcd_version}-linux-amd64.tar.gz"
cfssl_url="${base_url}/cloudflare/cfssl/releases/download/v${cfssl_version}/cfssl_${cfssl_version}_linux_amd64"
cfssljson_url="${base_url}/cloudflare/cfssl/releases/download/v${cfssl_version}/cfssljson_${cfssl_version}_linux_amd64"
helm_url="https://mirrors.huaweicloud.com/helm/v${helm_version}/helm-v${helm_version}-linux-amd64.tar.gz"
kubernetes_server_url="https://storage.googleapis.com/kubernetes-release/release/v${kubernetes_server_version}/kubernetes-server-linux-amd64.tar.gz"
nginx_url="http://nginx.org/download/nginx-${nginx_version}.tar.gz"
# Download packages
packages=(
# $kernel_url
$runc_url
$docker_url
$cni_plugins_url
$cri_containerd_cni_url
$crictl_url
$cri_dockerd_url
$etcd_url
$cfssl_url
$cfssljson_url
$helm_url
$kubernetes_server_url
$nginx_url
)
for package_url in "${packages[@]}"; do
filename=$(basename "$package_url")
if curl --parallel --parallel-immediate -k -L -C - -o "$filename" "$package_url"; then
echo "Downloaded $filename"
else
echo "Failed to download $filename"
exit 1
fi
done
升级内核
# 下载内核升级包
http://193.49.22.109/elrepo/kernel/el7/x86_64/RPMS/
# 安装内核,安装完成后检查 /boot/grub2/grub.cfg 中对应内核 menuentry 中是否包含 initrd16 配置,如果没有,再安装一次!
yum install -y kernel-lt-5.4.101-1.el7.elrepo.x86_64.rpm
# 查看当前操作系统所有的内核
awk -F\' '$1=="menuentry " {print i++ " : " $2}' /etc/grub2.cfg
# 设置默认启动内核为5.4.101
grub2-set-default 'CentOS Linux (5.4.101-1.el7.elrepo.x86_64) 7 (Core)'
# #################### 如果报错 ####################
awk: fatal: cannot open file `/etc/grub2.cfg' for reading (No such file or directory)
# 解决:
grub2-mkconfig -o /boot/grub2/grub.cfg
grub2-set-default 0
# 数字0为启动列表中第x项为启动项,x从0开始计数
# 如果命令不生效,则:
grubby --set-default /boot/vmlinuz-5.19.3-1.el7.elrepo.x86_64
重启服务器
containerd是一个容器运行时,用于管理和运行容器。它支持多种不同的参数配置来自定义容器运行时的行为和功能。
下载安装包
cd /zenglt
mkdir -p /etc/cni/net.d /opt/cni/bin
wget https://github.com/containernetworking/plugins/releases/download/v1.4.0/cni-plugins-linux-amd64-v1.4.0.tgz
tar -xf cni-plugins-linux-amd64-v1.4.0.tgz -C /opt/cni/bin/
wget https://github.com/containerd/containerd/releases/download/v1.7.13/cri-containerd-cni-1.7.13-linux-amd64.tar.gz
tar -xzf cri-containerd-cni-1.7.13-linux-amd64.tar.gz -C /
配置Containerd所需的模块
cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF
systemctl restart systemd-modules-load.service
配置Containerd所需的内核
net.bridge.bridge-nf-call-iptables
:控制网络桥接设备是否调用iptables规则处理网络数据包。设置为1时,网络数据包将被传递到iptables进行处理;设置为0时,网络数据包将绕过iptables直接传递。默认值是1。net.ipv4.ip_forward
:控制是否启用IP转发功能。IP转发使得操作系统可以将接收到的数据包从一个网络接口转发到另一个网络接口。默认的值是0cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
sysctl --system
创建Containerd的配置文件
# 创建默认配置文件
mkdir -p /etc/containerd
containerd config default | tee /etc/containerd/config.toml
# 修改Containerd的配置文件
sed -i "s#SystemdCgroup\ \=\ false#SystemdCgroup\ \=\ true#g" /etc/containerd/config.toml
# sed -i "s#registry.k8s.io#k8s.chenby.cn#g" /etc/containerd/config.toml
sed -i "s#config_path\ \=\ \"\"#config_path\ \=\ \"/etc/containerd/certs.d\"#g" /etc/containerd/config.toml
# 配置加速器
mkdir /etc/containerd/certs.d/docker.io -pv
cat > /etc/containerd/certs.d/docker.io/hosts.toml << EOF
server = "https://docker.io"
[host."https://docker.chenby.cn"]
capabilities = ["pull", "resolve"]
EOF
# Cgroup是Linux内核提供的一种资源隔离和管理机制,可以用于限制、分配和监控进程组的资源使用。
# 使用Cgroup,可以将容器的资源限制和隔离,以防止容器之间的资源争用和不公平的竞争。
注册 containerd 服务
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/local/bin/containerd
Type=notify
Delegate=yes
KillMode=process
Restart=always
RestartSec=5
LimitNPROC=infinity
LimitCORE=infinity
LimitNOFILE=infinity
TasksMax=infinity
OOMScoreAdjust=-999
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now containerd.service
systemctl status containerd.service
配置crictl客户端连接的运行时位置
crictl
是一个用于与容器运行时通信的命令行工具。它是容器运行时接口(CRI)工具的一个实现,可以对容器运行时进行管理和操作。
wget https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.29.0/crictl-v1.29.0-linux-amd64.tar.gz
tar xf crictl-v1.29.0-linux-amd64.tar.gz -C /usr/bin/
# 生成配置文件
cat > /etc/crictl.yaml <<EOF
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
EOF
# 测试
systemctl restart containerd
crictl info
# `runtime-endpoint` 指定容器运行时的终端套接字地址。
# `image-endpoint` 指定容器镜像服务的终端套接字地址。
# `timeout` 设置与容器运行时通信的超时时间,单位是秒。
# `debug` 指定是否开启调式模式。如果设置为`true`,则会输出更详细的调试信息。
kubernetes组件众多,这些组件之间通过HTTP/GRPC互相通信,来协同完成集群中的应用部署和管理工作。
cfssl证书生成工具是Cloudflare的一款把预先的证书机构、使用期等时间写在json文件里面会更加高效和自动化。cfssl采用go语言编写,是一个开源的证书管理工具,cfssljson用来从cfssl程序获取json输出,并将证书、密钥、csr和bundle写入文件中。
cfssl 文件下载
wget https://github.com/cloudflare/cfssl/releases/download/v1.6.4/cfssl_1.6.4_linux_amd64 -O /usr/local/bin/cfssl
wget 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*
根证书的配置信息,本次所有证书生成都依赖这个配置
根证书是CA认证中心与用户建立信任关系的基础,用户的数字证书必须有一个受信任的根证书,用户的数字证书才有效。证书包含三部分,用户信息、用户的公钥、证书签名。CA负责数字认证的批审、发放、归档、撤销等功能,CA颁发的数字证书拥有CA的数字签名,所以除了CA自身,其他机构无法不被察觉的改动。
{
"signing": {
"default": {
"expiry": "876000h"
},
"profiles": {
"kubernetes": {
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
],
"expiry": "876000h"
}
}
}
}
# 这段配置文件是用于配置加密和认证签名的一些参数。
# `signing`包含了默认签名配置和配置文件。默认签名配置`default`指定了证书的过期时间为`876000h`。
# `profiles`部分定义了不同的证书配置文件。这里,只有一个配置`kubernetes`。包含了`usages`和过期时间`expiry`
# 1. `signing`:用于对其他证书进行签名
# 2. `key encipherment`:用于加密和解密传输数据
# 3. `server auth`:表示client可以用该CA对server提供的证书进行校验
# 4. `client auth`:表示server可以用该CA对client提供的证书进行验证
csr.json
的解释
# - "CN": "" 指定了希望生成的证书的CN字段(Common Name),即证书的主题,通常是该证书标识的实体的名称。
# - "key": {} 指定了生成证书所使用的密钥的配置信息。"algo": "rsa" 指定了密钥的算法为RSA,"size": 2048 指定了密钥的长度为2048位。
# - "names": [] 包含了生成证书时所需的实体信息。在这个例子中,只包含了一个实体,其相关信息如下:
# - "C": "" 指定了实体的国家/地区代码,这里是中国
# - "ST": "" 指定了实体所在的省/州
# - "L": "" 指定了实体所在的城市
# - "O": "" 指定了实体的组织名称
# - "OU": "" 指定了实体所属的组织单位
# - "ca": {} 指定了生成证书时所需的CA(Certificate Authority)配置信息。
# - "expiry": "" 指定了证书的有效期,这里是876000小时。
# 生成证书签名请求时,可以使用这个JSON配置文件作为输入,根据配置文件中的信息生成相应的CSR文件。然后,可以将CSR文件发送给CA进行签名,以获得有效的证书。
initca 命令解释
cfssl gencert -initca etcd-ca-csr.json | cfssljson -bare /etc/etcd/ssl/etcd-ca
# -initca 表示初始化生成 ca
# etcd-ca-csr.json 表示ca的请求配置的json文件
# cfssljson 表示将生成的内容转化为json
# -bare 裸证书,表示仅生成证书和私钥
生成证书命令的解释
cfssl gencert \
-ca=/etc/etcd/ssl/etcd-ca.pem \
-ca-key=/etc/etcd/ssl/etcd-ca-key.pem \
-config=ca-config.json \
-profile=kubernetes \
etcd-csr.json | cfssljson -bare /etc/etcd/ssl/etcd
# 这条命令的作用是使用指定的CA证书和私钥,根据证书请求的JSON文件和配置文件生成etcd的证书文件。
# -ca 指定用于签名etcd证书的CA文件的路径。
# -ca-key 指定用于签名etcd证书的CA私钥文件的路径。
# -config 指定CA配置文件的路径,该文件定义了证书的有效期、加密算法等设置。
# -profile 指定使用的证书配置文件,该文件定义了证书的用途和扩展属性。
# etcd-csr.json 指定etcd证书请求的JSON文件的路径,该文件包含了证书请求的详细信息。
# cfssljson 通过管道将cfssl命令的输出传递给cfssljson命令,并使用-bare参数指定输出文件的前缀路径,这里将生成etcd证书的.pem和-key.pem文件。
# etcd 证书存放路径
mkdir -p /etc/etcd/ssl
# 生成 etcd 的 ca 的证书和私钥
mkdir -p /etc/etcd/ssl
# etcd ca 的证书和私钥的请求配置
cat > etcd-ca-csr.json << EOF
{
"CN": "etcd",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [{
"C": "CN",
"ST": "Guangdong",
"L": "Shenzhen",
"O": "etcd",
"OU": "Etcd Security"
}
],
"ca": {
"expiry": "876000h"
}
}
EOF
# 生成 etcd ca 的证书和私钥
cfssl gencert -initca etcd-ca-csr.json | cfssljson -bare /etc/etcd/ssl/etcd-ca
# etcd 的证书和私钥的请求配置
cat > etcd-csr.json << EOF
{
"CN": "etcd",
"hosts": [
"master01",
"worker01",
"worker02",
"127.0.0.1",
"192.168.2.20",
"192.168.2.21",
"192.168.2.22"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [{
"C": "CN",
"ST": "Guangdong",
"L": "Shenzhen",
"O": "etcd",
"OU": "Etcd Security"
}
]
}
EOF
# 生成 etcd 的证书和私钥
cfssl gencert \
-ca=/etc/etcd/ssl/etcd-ca.pem \
-ca-key=/etc/etcd/ssl/etcd-ca-key.pem \
-config=ca-config.json \
-profile=kubernetes \
etcd-csr.json | cfssljson -bare /etc/etcd/ssl/etcd
# 拷贝证书到其他 etcd 节点
scp -r /etc/etcd worker01:/etc/
scp -r /etc/etcd worker02:/etc/
CA (Certificate Authority) 证书
作为信任链的根,用于签署其他证书
# k8s 证书存放路径
mkdir -p /etc/kubernetes/pki
# 创建 k8s 的 ca 请求配置文件
cat > ca-csr.json << EOF
{
"CN": "kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [{
"C": "CN",
"ST": "Guangdong",
"L": "Shenzhen",
"O": "Kubernetes",
"OU": "Kubernetes-manual"
}
],
"ca": {
"expiry": "876000h"
}
}
EOF
# 使用这个 ca 给 k8s 所有组件的证书签名
cfssl gencert -initca ca-csr.json | cfssljson -bare /etc/kubernetes/pki/ca
创建 api-server 证书
用于 kube-apiserver 的身份验证和TLS连接
# api-server 证书的请求配置
# 同时还需要填写 service 网络的首个IP(一般是 kube-apiserver 指定的 service-cluster-ip-range 网段的第一个IP,如 10.96.0.1)
cat > apiserver-csr.json << EOF
{
"CN": "kube-apiserver",
"key": {
"algo": "rsa",
"size": 2048
},
"hosts": [
"kubernetes",
"kubernetes.default",
"kubernetes.default.svc",
"kubernetes.default.svc.cluster",
"kubernetes.default.svc.cluster.local",
"127.0.0.1",
"10.0.0.1",
"10.96.0.1",
"192.168.2.20",
"192.168.2.21",
"192.168.2.22",
"192.168.2.23",
"192.168.2.24",
"192.168.2.25"
],
"names": [{
"C": "CN",
"ST": "Guangdong",
"L": "Shenzhen",
"O": "Kubernetes",
"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 apiserver-csr.json | cfssljson -bare /etc/kubernetes/pki/apiserver
Front Proxy 证书
Front Proxy CA
用于签名 kubelet 和 kube-proxy 的客户端证书
# 生成 ca 的请求配置
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
Front Proxy Client 证书
用于 kube-proxy 与 kube-apiserver 之间的通信
# apiserver 聚合证书的请求配置
cat > front-proxy-client-csr.json << EOF
{
"CN": "front-proxy-client",
"key": {
"algo": "rsa",
"size": 2048
}
}
EOF
# 使用上一步创建的 ca 签名并生成证书
cfssl gencert \
-ca=/etc/kubernetes/pki/front-proxy-ca.pem \
-ca-key=/etc/kubernetes/pki/front-proxy-ca-key.pem \
-config=ca-config.json \
-profile=kubernetes front-proxy-client-csr.json | cfssljson -bare /etc/kubernetes/pki/front-proxy-client
controller-manager 证书
用于 kube-controller-manager 与 kube-apiserver 之间的通信
# controller-manager 证书的请求配置
cat > controller-manager-csr.json << EOF
{
"CN": "system:kube-controller-manager",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [{
"C": "CN",
"ST": "Guangdong",
"L": "Shenzhen",
"O": "system:kube-controller-manager",
"OU": "Kubernetes-manual"
}
]
}
EOF
# 生成 controller-manager 证书,并使用第一步创建的 ca 签名
cfssl gencert \
-ca=/etc/kubernetes/pki/ca.pem \
-ca-key=/etc/kubernetes/pki/ca-key.pem \
-config=ca-config.json \
-profile=kubernetes controller-manager-csr.json | \
cfssljson -bare /etc/kubernetes/pki/controller-manager
kube-scheduler 证书
用于 kube-scheduler 与 kube-apiserver 之间的通信
# kube-scheduler 证书的请求配置
cat > scheduler-csr.json << EOF
{
"CN": "system:kube-scheduler",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [{
"C": "CN",
"ST": "Guangdong",
"L": "Shenzhen",
"O": "system:kube-scheduler",
"OU": "Kubernetes-manual"
}
]
}
EOF
# 生成 kube-scheduler 证书,并使用第一步创建的 ca 签名
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
admin 证书
用于管理员访问 kube-apiserver
cat > admin-csr.json << EOF
{
"CN": "admin",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [{
"C": "CN",
"ST": "Guangdong",
"L": "Shenzhen",
"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
kube-proxy 证书
用于每个节点上的 kubelet 与 kube-apiserver 之间的通信
cat > kube-proxy-csr.json << EOF
{
"CN": "system:kube-proxy",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [{
"C": "CN",
"ST": "Guangdong",
"L": "Shenzhen",
"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
ServiceAccount Key
用于生成service account的token
openssl genrsa -out /etc/kubernetes/pki/sa.key 2048
openssl rsa -in /etc/kubernetes/pki/sa.key -pubout -out /etc/kubernetes/pki/sa.pub
所有etcd节点操作
下载 Etcd 安装文件
https://github.com/etcd-io/etcd/releases/download/v3.5.13/etcd-v3.5.13-linux-amd64.tar.gz
tar -zxf etcd-v3.5.13-linux-amd64.tar.gz
chmod +x etcd-v3.5.13-linux-amd64/etcd*
# 分发至所有 Etcd 节点
for host in master worker01 worker02
do
scp etcd-v3.5.13-linux-amd64/etcd* $host:/usr/local/bin/
done
写入 Etcd 配置文件 etcd.conf
[Member]
ETCD_NAME="master"
ETCD_DATA_DIR="/var/lib/etcd"
ETCD_LISTEN_PEER_URLS="https://192.168.2.20:2380"
ETCD_LISTEN_CLIENT_URLS="https://192.168.2.20:2379"
[Security]
ETCD_CLIENT_CERT_AUTH=true
ETCD_PEER_CLIENT_CERT_AUTH=true
ETCD_CERT_FILE=/etc/etcd/ssl/etcd.pem
ETCD_KEY_FILE=/etc/etcd/ssl/etcd-key.pem
ETCD_PEER_CERT_FILE=/etc/etcd/ssl/etcd.pem
ETCD_PEER_KEY_FILE=/etc/etcd/ssl/etcd-key.pem
ETCD_TRUSTED_CA_FILE=/etc/etcd/ssl/ca.pem
ETCD_PEER_TRUSTED_CA_FILE=/etc/etcd/ssl/ca.pem
ETCD_LOGGER=zap
[Clustering]
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-k8s"
ETCD_ADVERTISE_CLIENT_URLS="https://192.168.2.20:2379"
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.2.20:2380"
ETCD_INITIAL_CLUSTER="master=https://192.168.2.20:2380,worker01=https://192.168.2.21:2380,worker02=https://192.168.2.22:2380"
注册 Etcd 服务
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.conf
Restart=on-failure
RestartSec=10
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
Alias=etcd3.service
EOF
# 启动
systemctl daemon-reload
systemctl enable --now etcd.service
systemctl status etcd.service
验证
export ETCDCTL_API=3
etcdctl --endpoints="192.168.2.20:2379,192.168.2.21:2379,192.168.2.22:2379" \
--cacert=/etc/etcd/ssl/etcd-ca.pem \
--cert=/etc/etcd/ssl/etcd.pem \
--key=/etc/etcd/ssl/etcd-key.pem \
endpoint status --write-out=table
cd /zenglt
wget https://dl.k8s.io/v1.30.2/kubernetes-server-linux-amd64.tar.gz
tar -zxf kubernetes-server-linux-amd64.tar.gz
cp kubernetes/server/bin/kube{let,ctl,-apiserver,-controller-manager,-scheduler,-proxy} /usr/local/bin/
scp kubernetes/server/bin/kube{let,-proxy} worker01:/usr/local/bin/
scp kubernetes/server/bin/kube{let,-proxy} worker02:/usr/local/bin/
写入 kube-apiserver 启动配置文件
# 注意,当使用cat EOF命令直接写入文件时需要两个反斜杠,且反斜杠后不能有空格
cat > /etc/kubernetes/conf/kube-apiserver.conf <<EOF
KUBE_APISERVER_ARGS="--v=2 \\
--allow-privileged=true \\
--bind-address=0.0.0.0 \\
--secure-port=6443 \\
--advertise-address=192.168.2.20 \\
--service-cluster-ip-range=10.96.0.0/12 \\
--service-node-port-range=30000-32767 \\
--etcd-servers=https://192.168.2.20:2379,https://192.168.2.21:2379,https://192.168.2.22: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 \\
--audit-log-maxage=30 \\
--audit-log-maxbackup=3 \\
--audit-log-maxsize=100 \\
--audit-log-path=/var/log/kubernetes/kube-apiserver/apiserver-audit.log"
EOF
注册 kube-apiserver 服务
cat > /usr/lib/systemd/system/kube-apiserver.service << EOF
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/kubernetes/kubernetes
After=network.target
[Service]
Restart=on-failure
RestartSec=10s
LimitNOFILE=65535
EnvironmentFile=/etc/kubernetes/conf/kube-apiserver.conf
ExecStart=/usr/local/bin/kube-apiserver \$KUBE_APISERVER_ARGS
[Install]
WantedBy=multi-user.target
EOF
启动
systemctl daemon-reload
systemctl enable --now kube-apiserver.service
systemctl status kube-apiserver.service
配置 kube-controller-manager 的配置文件
配置 kube-controller-manager 组件的集群信息、上下文信息、身份验证信息,并设置默认使用的上下文
SERVER="https://192.168.2.20:6443"
KUBECONFIG="/etc/kubernetes/controller-manager.kubeconfig"
# 配置集群信息,包括证书颁发机构、证书、kube-apiserver地址等
kubectl config set-cluster kubernetes \
--embed-certs=true \
--certificate-authority=/etc/kubernetes/pki/ca.pem \
--server=$SERVER \
--kubeconfig=$KUBECONFIG
# 设置一个名为 kubernetes 的集群配置
# --embed-certs 将证书嵌入到生成的 kubeconfig 文件中,在使用 kubectl 时就不需要额外指定 CA 证书的路径。
# --certificate-authority 指定集群的证书颁发机构(CA)的路径,这个CA会验证kube-apiserver提供的证书是否合法。
# --server 指定kube-apiserver的地址,apiserver默认是6443端口,如果是多master则是代理的地址
# --kubeconfig 指定生成的kubeconfig文件的路径和名称
# 配置 Kubernetes 控制器管理器的上下文信息
kubectl config set-context \
system:kube-controller-manager@kubernetes \
--cluster=kubernetes \
--user=system:kube-controller-manager \
--kubeconfig=$KUBECONFIG
# system:kube-controller-manager@kubernetes: 上下文的名称,这是一个标识符,用于唯一标识该上下文
# --cluster 指定集群的名称为 `kubernetes`,这是一个现有集群的标识符。
# --user 指定使用的用户身份为 `system:kube-controller-manager`。这是一个特殊的用户身份,具有控制 Kubernetes 控制器管理器的权限。
# --kubeconfig: 指定生成的kubeconfig文件的路径和名称
# 设置 controller-manager 组件的客户端凭据,后续使用该文件进行身份验证和访问 Kubernetes API
kubectl config set-credentials \
system:kube-controller-manager \
--embed-certs=true \
--client-certificate=/etc/kubernetes/pki/controller-manager.pem \
--client-key=/etc/kubernetes/pki/controller-manager-key.pem \
--kubeconfig=$KUBECONFIG
# system:kube-controller-manager 设置用户凭据的名称,`system:`是 API Server 内置的身份验证器使用的用户标识符前缀,表示是一个系统用户
# --embed-certs 将证书嵌入到生成的 kubeconfig 文件中,在使用 kubectl 时就不需要额外指定 CA 证书的路径
# --client-certificate 指定 controller-manager 客户端证书的路径
# --client-key 指定 controller-manager 客户端私钥的路径
# --kubeconfig 指定生成的kubeconfig文件的路径和名称
# 设置默认环境,指定kubectl使用指定的上下文环境来部署和管理Kubernetes资源
kubectl config use-context system:kube-controller-manager@kubernetes --kubeconfig=$KUBECONFIG
# system:kube-controller-manager@kubernetes 指定的上下文名称,告诉kubectl要使用的Kubernetes集群和身份验证信息
# --kubeconfig:指定使用的kubeconfig文件的路径。kubeconfig文件存储了集群连接和身份验证信息
配置 kube-controller-manager 的启动配置文件
# 注意,当使用cat EOF命令直接写入文件时需要两个反斜杠,且反斜杠后不能有空格
cat > /etc/kubernetes/conf/kube-controller-manager.conf << EOF
KUBE_CONTROLLER_MANAGER_ARGS="--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 \\
--cluster-cidr=172.16.0.0/12 \\
--node-cidr-mask-size-ipv4=24 \\
--requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.pem"
EOF
# --v=2 设置日志的详细级别为 2。
# --bind-address 绑定的 IP 地址,用于监听 Kubernetes 控制平面的请求,设置为 0.0.0.0,表示监听所有网络接口上的请求。
# --root-ca-file 根证书文件的路径,用于验证集群其他组件的证书。
# --cluster-signing-cert-file 用于签名集群证书的证书文件路径。
# --cluster-signing-key-file 用于签名集群证书的私钥文件路径。
# --service-account-private-key-file 用于签名服务账户令牌的私钥文件路径,用于生成服务账户的 token
# --kubeconfigkubeconfig Kubeconfig 文件的路径,包含了与 Kubernetes API 服务器通信所需的配置信息。
# --leader-elect=true 启用 Leader 选举机制,确保只有一个控制器管理器作为 leader 在运行。
# --use-service-account-credentials 使用服务账户的凭据进行认证和授权。
# --node-monitor-grace-period=40s 节点监控的优雅退出时间,节点长时间不响应时会触发节点驱逐。
# --node-monitor-period=5s 节点状态检测周期,controller-manager 检查一次节点状态的时间周期
# --controllers 指定要运行的控制器,* 表示运行所有的控制器,bootstrapsigner 和 tokencleaner是额外启用的控制器
# --allocate-node-cidrs=true 启用自动分配节点 CIDR 功能,用于分配 Pod 的 IP 地址范围。
# --service-cluster-ip-range 定义 Service 的 IP 范围,用于分配服务的虚拟 IP 地址。
# --cluster-cidr 定义 cluster 的 CIDR 范围,用于分配 Pod 的 IP 地址。
# --node-cidr-mask-size-ipv4 分配给每个节点的 IPv4 子网掩码大小,默认是 24。
# --requestheader-client-ca-file 设置请求头中客户端 CA 的证书文件路径,用于认证请求头中的 CA 证书。
systemd 托管 kube-controller-manager
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]
Restart=always
RestartSec=10s
EnvironmentFile=/etc/kubernetes/conf/kube-controller-manager.conf
ExecStart=/usr/local/bin/kube-controller-manager \$KUBE_CONTROLLER_MANAGER_ARGS
[Install]
WantedBy=multi-user.target
EOF
# 启动
systemctl daemon-reload
systemctl enable --now kube-controller-manager.service
systemctl status kube-controller-manager.service
配置 kube-scheduler 的配置文件
配置 kube-scheduler 组件的集群信息、上下文信息、身份验证信息,并设置默认使用的上下文
KUBECONFIG="/etc/kubernetes/scheduler.kubeconfig"
# 配置集群信息,包括证书颁发机构、证书、kube-apiserver地址等
kubectl config set-cluster kubernetes \
--embed-certs=true \
--certificate-authority=/etc/kubernetes/pki/ca.pem \
--server=https://192.168.2.20:6443 \
--kubeconfig=$KUBECONFIG
# 设置一个名为 kubernetes 的集群配置
# --embed-certs 将证书嵌入到生成的 kubeconfig 文件中,在使用 kubectl 时就不需要额外指定 CA 证书的路径。
# --certificate-authority 指定集群的证书颁发机构(CA)的路径,这个CA会验证kube-apiserver提供的证书是否合法。
# --server 指定kube-apiserver的地址,apiserver默认是6443端口,如果是多master则是代理的地址
# --kubeconfig 指定生成的kubeconfig文件的路径和名称
# 配置 Kubernetes 控制器管理器的上下文信息
kubectl config set-context system:kube-scheduler@kubernetes \
--cluster=kubernetes \
--user=system:kube-scheduler \
--kubeconfig=$KUBECONFIG
# system:kube-controller-manager@kubernetes: 上下文的名称,这是一个标识符,用于唯一标识该上下文
# --cluster 指定集群的名称为 `kubernetes`,这是一个现有集群的标识符。
# --user 指定使用的用户身份为 `system:kube-scheduler`。用于认证和授权kube-scheduler组件访问Kubernetes集群的权限。
# --kubeconfig: 指定生成的kubeconfig文件的路径和名称
# 设置 kube-scheduler 组件的身份验证凭据
kubectl config set-credentials system:kube-scheduler \
--embed-certs=true \
--client-certificate=/etc/kubernetes/pki/scheduler.pem \
--client-key=/etc/kubernetes/pki/scheduler-key.pem \
--kubeconfig=$KUBECONFIG
# system:kube-scheduler 设置用户凭据的名称,`system:`是 API Server 内置的身份验证器使用的用户标识符前缀,表示是一个系统用户
# --embed-certs 将证书嵌入到生成的 kubeconfig 文件中,在使用 kubectl 时就不需要额外指定 CA 证书的路径。
# --client-certificate 指定 scheduler 客户端证书的路径。
# --client-key 指定 scheduler 客户端私钥的路径。
# --kubeconfig 指定生成的kubeconfig文件的路径和名称
# 设置默认环境,指定kubectl使用指定的上下文环境来部署和管理Kubernetes资源
kubectl config use-context system:kube-scheduler@kubernetes --kubeconfig=$KUBECONFIG
# system:kube-scheduler@kubernetes 指定的上下文名称,告诉kubectl要使用的Kubernetes集群和身份验证信息
# --kubeconfig 指定使用的kubeconfig文件的路径。kubeconfig文件存储了集群连接和身份验证信息
配置 kube-scheduler 的启动配置文件
cat > /etc/kubernetes/conf/kube-scheduler.conf << EOF
KUBE_SCHEDULER_ARGS="--v=2 \\
--bind-address=0.0.0.0 \\
--leader-elect=true \\
--kubeconfig=/etc/kubernetes/scheduler.kubeconfig"
EOF
注册 kube-scheduler 服务
cat > /usr/lib/systemd/system/kube-scheduler.service << EOF
[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/kubernetes/kubernetes
After=network.target
[Service]
Restart=always
RestartSec=10s
EnvironmentFile=/etc/kubernetes/conf/kube-scheduler.conf
ExecStart=/usr/local/bin/kube-scheduler \$KUBE_SCHEDULER_ARGS
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now kube-scheduler.service
systemctl status kube-scheduler.service
配置管理员 admin 的集群信息、上下文信息、身份验证信息,并设置默认使用的上下文
KUBECONFIG="/etc/kubernetes/admin.kubeconfig"
kubectl config set-cluster kubernetes \
--embed-certs=true \
--server=https://192.168.2.20:6443 \
--certificate-authority=/etc/kubernetes/pki/ca.pem \
--kubeconfig=$KUBECONFIG
kubectl config set-credentials kubernetes-admin \
--embed-certs=true \
--client-certificate=/etc/kubernetes/pki/admin.pem \
--client-key=/etc/kubernetes/pki/admin-key.pem \
--kubeconfig=$KUBECONFIG
kubectl config set-context kubernetes-admin@kubernetes \
--cluster=kubernetes \
--user=kubernetes-admin \
--kubeconfig=$KUBECONFIG
kubectl config use-context kubernetes-admin@kubernetes \
--kubeconfig=$KUBECONFIG
配置 Bootstrapping 的集群信息、上下文信息、身份验证信息,并设置默认使用的上下文
KUBECONFIG="/etc/kubernetes/bootstrap-kubelet.kubeconfig"
kubectl config set-cluster kubernetes \
--embed-certs=true \
--server=https://192.168.2.20:6443 \
--certificate-authority=/etc/kubernetes/pki/ca.pem \
--kubeconfig=$KUBECONFIG
echo "$(head -c 6 /dev/urandom | md5sum | head -c 6)"."$(head -c 16 /dev/urandom | md5sum | head -c 16)"
kubectl config set-credentials bootstrap-user \
--token=36b2ce.e1d273c8e15e5163 \
--kubeconfig=$KUBECONFIG
kubectl config set-context bootstrap-user@kubernetes \
--cluster=kubernetes \
--user=bootstrap-user \
--kubeconfig=$KUBECONFIG
kubectl config use-context bootstrap-user@kubernetes --kubeconfig=$KUBECONFIG
#
mkdir -p /root/.kube
cp /etc/kubernetes/admin.kubeconfig /root/.kube/config
# 修改 token 为上次命令的 token
cat > bootstrap.secret.yaml << EOF
apiVersion: v1
kind: Secret
metadata:
name: bootstrap-token-36b2ce
namespace: kube-system
type: bootstrap.kubernetes.io/token
stringData:
description: "The default bootstrap token generated by 'kubelet'"
token-id: abcdef
token-secret: 0123456789abcdef
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
所有节点执行
scp /etc/kubernetes/pki/{ca.pem,ca-key.pem,front-proxy-ca.pem} worker01:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/{ca.pem,ca-key.pem,front-proxy-ca.pem} worker02:/etc/kubernetes/pki/
scp /etc/kubernetes/bootstrap-kubelet.kubeconfig kube-proxy.kubeconfig worker01:/etc/kubernetes/
scp /etc/kubernetes/bootstrap-kubelet.kubeconfig kube-proxy.kubeconfig worker02:/etc/kubernetes/
mkdir -p /var/lib/kubelet \
/var/log/kubernetes \
/etc/systemd/system/kubelet.service.d \
/etc/kubernetes/manifests/
cat > /etc/kubernetes/kubelet-conf.yml <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
# - 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分钟。
cat > /etc/kubernetes/conf/kubelet.conf << EOF
KUBELET_ARGS="--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.kubeconfig \\
--kubeconfig=/etc/kubernetes/kubelet.kubeconfig \\
--config=/etc/kubernetes/kubelet-conf.yml \\
--container-runtime-endpoint=unix:///run/containerd/containerd.sock \\
--node-labels=node.kubernetes.io/node="
EOF
# 如果是使用 docker 作为容器运行时则
--container-runtime-endpoint=unix:///run/cri-dockerd.sock
cat > /usr/lib/systemd/system/kubelet.service << EOF
[Unit]
Description=Kubernetes Kubelet
Documentation=https://github.com/kubernetes/kubernetes
After=network-online.target firewalld.service containerd.service
Wants=network-online.target
Requires=containerd.service
[Service]
EnvironmentFile=/etc/kubernetes/conf/kubelet.conf
ExecStart=/usr/local/bin/kubelet \$KUBELET_ARGS
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now kubelet.service
systemctl status kubelet.service
配置 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
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
# apiVersion: - 指定该配置文件的API版本。
# bindAddress: - 指定kube-proxy使用的监听地址。0.0.0.0表示监听所有网络接口。
# clientConnection: - 客户端连接配置项。
# acceptContentTypes: - 指定接受的内容类型。
# burst: - 客户端请求超出qps设置时的最大突发请求数。
# contentType - 指定客户端请求的内容类型。
# kubeconfig - kube-proxy使用的kubeconfig文件路径。
# qps: - 每秒向API服务器发送的请求数量。
# clusterCIDR: - 指定集群使用的CIDR范围,用于自动分配Pod IP。
# configSyncPeriod: - 指定kube-proxy配置同步到节点的频率。
# conntrack: - 连接跟踪设置。
# max: - 指定连接跟踪的最大值。
# maxPerCore: - 指定每个核心的最大连接跟踪数。
# min: - 指定最小的连接跟踪数。
# tcpCloseWaitTimeout: - 指定处于CLOSE_WAIT状态的TCP连接的超时时间。
# tcpEstablishedTimeout: - 指定已建立的TCP连接的超时时间。
# enableProfiling: - 是否启用性能分析。
# healthzBindAddress: - 指定健康检查监听地址和端口。
# hostnameOverride: - 指定覆盖默认主机名的值。
# iptables: - iptables设置。
# masqueradeAll: - 是否对所有流量使用IP伪装。
# masqueradeBit: - 指定伪装的Bit标记。
# minSyncPeriod: - 指定同步iptables规则的最小间隔。
# syncPeriod: - 指定同步iptables规则的时间间隔。
# ipvs: - ipvs设置。
# masqueradeAll: - 是否对所有流量使用IP伪装。
# minSyncPeriod: - 指定同步ipvs规则的最小间隔。
# scheduler: - 指定ipvs默认使用的调度算法。
# syncPeriod: - 指定同步ipvs规则的时间间隔。
# kind: - 指定该配置文件的类型。
# metricsBindAddress: - 指定指标绑定的地址和端口。
# mode: - 指定kube-proxy的模式。这里指定为ipvs,使用IPVS代理模式。
# nodePortAddresses: - 指定可用于NodePort的网络地址。
# oomScoreAdj: - 指定kube-proxy的OOM优先级。
# portRange: - 指定可用于服务端口范围。
# udpIdleTimeout: - 指定UDP连接的空闲超时时间。
配置 kube-proxy 的启动配置文件
cat > /etc/kubernetes/conf/kube-proxy.conf <<EOF
KUBE_PROXY_ARGS="--v=2 --config=/etc/kubernetes/kube-proxy.yaml --cluster-cidr=172.16.0.0/12"
EOF
systemd 托管 kube-proxy
cat > /usr/lib/systemd/system/kube-proxy.service << EOF
[Unit]
Description=Kubernetes Kube Proxy
Documentation=https://github.com/kubernetes/kubernetes
After=network.target
[Service]
Restart=always
RestartSec=10s
EnvironmentFile=/etc/kubernetes/conf/kube-proxy.conf
ExecStart=/usr/local/bin/kube-proxy \$KUBE_PROXY_ARGS
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now kube-proxy.service
systemctl status kube-proxy.service
所有节点更新 runc
wget https://github.com/opencontainers/runc/releases/download/v1.1.13/runc.amd64
install -m 755 runc.amd64 /usr/local/sbin/runc
runc --version
runc version 1.1.13
commit: v1.1.13-0-g58aa9203-dirty
spec: 1.0.2-dev
go: go1.21.11
libseccomp: 2.5.5
安装calico-v3.26.5
wget https://raw.githubusercontent.com/projectcalico/calico/v3.26.5/manifests/tigera-operator.yaml
wget https://raw.githubusercontent.com/projectcalico/calico/v3.26.5/manifests/custom-resources.yaml
# 修改为 pods 的 CIDR
sed- i [email protected]\/[email protected]\/12@ custom-resources.yaml
kubectl create -f tigera-operator.yaml
kubectl get po -n tigera-operator
NAME READY STATUS RESTARTS AGE
tigera-operator-6d5758598f-jnkml 1/1 Running 0 11s
# 成功后执行下一步
kubectl create -f custom-resources.yaml
kubectl get po -n calico-system
NAME READY STATUS RESTARTS AGE
calico-kube-controllers-6c69b69876-h5j2f 1/1 Running 0 10m
calico-node-258zs 1/1 Running 0 10m
calico-node-9x4bg 1/1 Running 0 10m
calico-node-gppg2 1/1 Running 0 10m
calico-typha-66ccb8b69f-fx964 1/1 Running 0 10m
calico-typha-66ccb8b69f-nlw65 1/1 Running 0 10m
csi-node-driver-tw28f 2/2 Running 0 10m
csi-node-driver-xt4qv 2/2 Running 0 10m
csi-node-driver-zv8kc 2/2 Running 0 10m
helm repo add coredns https://coredns.github.io/helm
helm pull coredns/coredns
tar xvf coredns-*.tgz
cd coredns/
# 修改clusterIP 为集群中配置的,例如是 kube-apiserver 的配置文件中的 --cluster-ip
sed -i 's/# clusterIP: ""/ clusterIP: "10.96.0.10"/' values.yaml
helm install coredns . -n kube-system
kubectl get po -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-548c8c8646-sf8wg 1/1 Running 0 3m3s
# 标记控制平面
kubectl label node master node-role.kubernetes.io/control-plane=
# 标记 worker
kubectl label node worker01 node-role.kubernetes.io/worker=
# 控制平面打污点
kubectl taint node master node-role.kubernetes.io/master:NoSchedule