K8s v1.28.7 单Master节点纯二进制部署文档
文档说明
-
本文档适用于单机部署场景,部署前只需直接替换主机名(master01)和主机IP(192.168.133.140),替换完成后,跟随文档步骤复制粘贴命令即可完成部署。
-
本文档实现K8s v1.28.7 单Master节点纯二进制部署,kube-proxy提供二进制部署和DaemonSet守护进程部署两种方式,无语法错误、无多余依赖,所有命令可直接复制执行。
-
适配系统:CentOS 7(Linux x86_64)
核心说明
- 部署全程无kubeadm依赖,手动生成CA及所有组件证书,部署kube-apiserver后再生成admin.conf(确保api启动后可正常使用);各组件对应conf文件均在组件部署后生成,kube-proxy两种部署方式相互独立,可根据实际需求选择。同时保证kubelet能自动注册到集群。
- etcd 组件和kubernetes组件共用一套CA证书(front-proxy除外),且所有证书统一保存在/etc/kubernetes/pki目录下(kubelet和kube-proxy的除外)。
- kubelet和kube-proxy的相关文件分别保存在 /var/lib/kubelet 和 /var/lib/kube-proxy (当容器部署kube-proxy除外)。
一、环境准备
1.1 系统基础配置
首先安装必要依赖并升级内核,确保系统满足K8s部署基础要求:
bash
# 1. 必要的依赖 (libseccomp libseccomp-devel 是 runc 必要的依赖)
yum install -y ipvsadm ipset conntrack-tools socat ebtables libseccomp libseccomp-devel
# 内核升级
wget https://dl.lamp.sh/kernel/el7/kernel-ml-6.7.8-1.el7.elrepo.x86_64.rpm # 可直接复制到浏览器下载
rpm -ivh kernel-ml-6.7.8-1.el7.elrepo.x86_64.rpm
grub2-set-default 0 # 升级内核并设置内核启动顺序,重启生效
reboot
# 可选
yum install -y wget vim net-tools iftop telnet bash-completion.noarch
配置K8s基础内核参数,关闭防火墙、SELinux和swap,加载ipvs相关模块:
bash
# 2. 简单 k8s环境 内核参数版
systemctl stop firewalld && systemctl disable firewalld
setenforce 0 && sed -i 's/^SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
swapoff -a && sed -i '/swap/s/^/#/' /etc/fstab
cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
vm.swappiness = 0
EOF
sysctl --system
cat > /etc/sysconfig/modules/ipvs.modules << EOF
#!/bin/bash
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack
EOF
chmod 755 /etc/sysconfig/modules/ipvs.modules && bash /etc/sysconfig/modules/ipvs.modules
lsmod | grep -E "ip_vs|nf_conntrack"
生产环境优化版系统初始化脚本(推荐生产环境使用,包含更全面的内核、文件描述符等优化配置):
bash
# 3. 生产 优化 版
# cat initOS.sh
#!/usr/bin/env bash
swapoff -a
sed -i /^[^#]*swap*/s/^/\#/g /etc/fstab
# See https://github.com/kubernetes/website/issues/14457
if [ -f /etc/selinux/config ]; then
sed -ri 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
fi
# for ubuntu: sudo apt install selinux-utils
# for centos: yum install selinux-policy
if command -v setenforce &> /dev/null
then
setenforce 0
getenforce
fi
cat >> /etc/sysctl.conf <<-EOF
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-arptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_local_reserved_ports = 30000-32767
net.core.netdev_max_backlog = 65535
net.core.rmem_max = 33554432
net.core.wmem_max = 33554432
net.core.somaxconn = 32768
net.ipv4.tcp_max_syn_backlog = 1048576
net.ipv4.neigh.default.gc_thresh1 = 512
net.ipv4.neigh.default.gc_thresh2 = 2048
net.ipv4.neigh.default.gc_thresh3 = 4096
net.ipv4.tcp_retries2 = 15
net.ipv4.tcp_max_tw_buckets = 1048576
net.ipv4.tcp_max_orphans = 65535
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 10
net.ipv4.udp_rmem_min = 131072
net.ipv4.udp_wmem_min = 131072
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.rp_filter = 0
net.ipv4.conf.all.arp_accept = 1
net.ipv4.conf.default.arp_accept = 1
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.default.arp_ignore = 1
vm.max_map_count = 262144
vm.swappiness = 0
vm.overcommit_memory = 0
fs.inotify.max_user_instances = 524288
fs.inotify.max_user_watches = 524288
fs.pipe-max-size = 4194304
fs.aio-max-nr = 262144
kernel.pid_max = 65535
kernel.watchdog_thresh = 5
kernel.hung_task_timeout_secs = 5
EOF
#See https://help.aliyun.com/document_detail/118806.html#uicontrol-e50-ddj-w0y
sed -r -i "s@#{0,}?net.ipv4.tcp_tw_recycle ?= ?(0|1|2)@net.ipv4.tcp_tw_recycle = 0@g" /etc/sysctl.conf
sed -r -i "s@#{0,}?net.ipv4.tcp_tw_reuse ?= ?(0|1)@net.ipv4.tcp_tw_reuse = 0@g" /etc/sysctl.conf
sed -r -i "s@#{0,}?net.ipv4.conf.all.rp_filter ?= ?(0|1|2)@net.ipv4.conf.all.rp_filter = 0@g" /etc/sysctl.conf
sed -r -i "s@#{0,}?net.ipv4.conf.default.rp_filter ?= ?(0|1|2)@net.ipv4.conf.default.rp_filter = 0@g" /etc/sysctl.conf
sed -r -i "s@#{0,}?net.ipv4.ip_forward ?= ?(0|1)@net.ipv4.ip_forward = 1@g" /etc/sysctl.conf
sed -r -i "s@#{0,}?net.bridge.bridge-nf-call-arptables ?= ?(0|1)@net.bridge.bridge-nf-call-arptables = 1@g" /etc/sysctl.conf
sed -r -i "s@#{0,}?net.bridge.bridge-nf-call-ip6tables ?= ?(0|1)@net.bridge.bridge-nf-call-ip6tables = 1@g" /etc/sysctl.conf
sed -r -i "s@#{0,}?net.bridge.bridge-nf-call-iptables ?= ?(0|1)@net.bridge.bridge-nf-call-iptables = 1@g" /etc/sysctl.conf
sed -r -i "s@#{0,}?net.ipv4.ip_local_reserved_ports ?= ?([0-9]{1,}-{0,1},{0,1}){1,}@net.ipv4.ip_local_reserved_ports = 30000-32767@g" /etc/sysctl.conf
sed -r -i "s@#{0,}?vm.max_map_count ?= ?([0-9]{1,})@vm.max_map_count = 262144@g" /etc/sysctl.conf
sed -r -i "s@#{0,}?vm.swappiness ?= ?([0-9]{1,})@vm.swappiness = 0@g" /etc/sysctl.conf
sed -r -i "s@#{0,}?fs.inotify.max_user_instances ?= ?([0-9]{1,})@fs.inotify.max_user_instances = 524288@g" /etc/sysctl.conf
sed -r -i "s@#{0,}?kernel.pid_max ?= ?([0-9]{1,})@kernel.pid_max = 65535@g" /etc/sysctl.conf
sed -r -i "s@#{0,}?vm.overcommit_memory ?= ?(0|1|2)@vm.overcommit_memory = 0@g" /etc/sysctl.conf
sed -r -i "s@#{0,}?fs.inotify.max_user_watches ?= ?([0-9]{1,})@fs.inotify.max_user_watches = 524288@g" /etc/sysctl.conf
sed -r -i "s@#{0,}?fs.pipe-max-size ?= ?([0-9]{1,})@fs.pipe-max-size = 4194304@g" /etc/sysctl.conf
sed -r -i "s@#{0,}?net.core.netdev_max_backlog ?= ?([0-9]{1,})@net.core.netdev_max_backlog = 65535@g" /etc/sysctl.conf
sed -r -i "s@#{0,}?net.core.rmem_max ?= ?([0-9]{1,})@net.core.rmem_max = 33554432@g" /etc/sysctl.conf
sed -r -i "s@#{0,}?net.core.wmem_max ?= ?([0-9]{1,})@net.core.wmem_max = 33554432@g" /etc/sysctl.conf
sed -r -i "s@#{0,}?net.ipv4.tcp_max_syn_backlog ?= ?([0-9]{1,})@net.ipv4.tcp_max_syn_backlog = 1048576@g" /etc/sysctl.conf
sed -r -i "s@#{0,}?net.ipv4.neigh.default.gc_thresh1 ?= ?([0-9]{1,})@net.ipv4.neigh.default.gc_thresh1 = 512@g" /etc/sysctl.conf
sed -r -i "s@#{0,}?net.ipv4.neigh.default.gc_thresh2 ?= ?([0-9]{1,})@net.ipv4.neigh.default.gc_thresh2 = 2048@g" /etc/sysctl.conf
sed -r -i "s@#{0,}?net.ipv4.neigh.default.gc_thresh3 ?= ?([0-9]{1,})@net.ipv4.neigh.default.gc_thresh3 = 4096@g" /etc/sysctl.conf
sed -r -i "s@#{0,}?net.core.somaxconn ?= ?([0-9]{1,})@net.core.somaxconn = 32768@g" /etc/sysctl.conf
sed -r -i "s@#{0,}?net.ipv4.conf.eth0.arp_accept ?= ?(0|1)@net.ipv4.conf.eth0.arp_accept = 1@g" /etc/sysctl.conf
sed -r -i "s@#{0,}?fs.aio-max-nr ?= ?([0-9]{1,})@fs.aio-max-nr = 262144@g" /etc/sysctl.conf
sed -r -i "s@#{0,}?net.ipv4.tcp_retries2 ?= ?([0-9]{1,})@net.ipv4.tcp_retries2 = 15@g" /etc/sysctl.conf
sed -r -i "s@#{0,}?net.ipv4.tcp_max_tw_buckets ?= ?([0-9]{1,})@net.ipv4.tcp_max_tw_buckets = 1048576@g" /etc/sysctl.conf
sed -r -i "s@#{0,}?net.ipv4.tcp_max_orphans ?= ?([0-9]{1,})@net.ipv4.tcp_max_orphans = 65535@g" /etc/sysctl.conf
sed -r -i "s@#{0,}?net.ipv4.tcp_keepalive_time ?= ?([0-9]{1,})@net.ipv4.tcp_keepalive_time = 600@g" /etc/sysctl.conf
sed -r -i "s@#{0,}?net.ipv4.tcp_keepalive_intvl ?= ?([0-9]{1,})@net.ipv4.tcp_keepalive_intvl = 30@g" /etc/sysctl.conf
sed -r -i "s@#{0,}?net.ipv4.tcp_keepalive_probes ?= ?([0-9]{1,})@net.ipv4.tcp_keepalive_probes = 10@g" /etc/sysctl.conf
sed -r -i "s@#{0,}?net.ipv4.udp_rmem_min ?= ?([0-9]{1,})@net.ipv4.udp_rmem_min = 131072@g" /etc/sysctl.conf
sed -r -i "s@#{0,}?net.ipv4.udp_wmem_min ?= ?([0-9]{1,})@net.ipv4.udp_wmem_min = 131072@g" /etc/sysctl.conf
sed -r -i "s@#{0,}?net.ipv4.conf.all.arp_ignore ?= ??(0|1|2)@net.ipv4.conf.all.arp_ignore = 1@g" /etc/sysctl.conf
sed -r -i "s@#{0,}?net.ipv4.conf.default.arp_ignore ?= ??(0|1|2)@net.ipv4.conf.default.arp_ignore = 1@g" /etc/sysctl.conf
sed -r -i "s@#{0,}?kernel.watchdog_thresh ?= ?([0-9]{1,})@kernel.watchdog_thresh = 5@g" /etc/sysctl.conf
sed -r -i "s@#{0,}?kernel.hung_task_timeout_secs ?= ?([0-9]{1,})@kernel.hung_task_timeout_secs = 5@g" /etc/sysctl.conf
tmpfile="$$.tmp"
awk ' !x[$0]++{print > "'$tmpfile'"}' /etc/sysctl.conf
mv $tmpfile /etc/sysctl.conf
# ulimit
cat >> /etc/security/limits.conf <<-EOF
* soft nofile 1048576
* hard nofile 1048576
* soft nproc 65536
* hard nproc 65536
* soft memlock unlimited
* hard memlock unlimited
EOF
sed -r -i "s@#{0,}?\* soft nofile ?([0-9]{1,})@\* soft nofile 1048576@g" /etc/security/limits.conf
sed -r -i "s@#{0,}?\* hard nofile ?([0-9]{1,})@\* hard nofile 1048576@g" /etc/security/limits.conf
sed -r -i "s@#{0,}?\* soft nproc ?([0-9]{1,})@\* soft nproc 65536@g" /etc/security/limits.conf
sed -r -i "s@#{0,}?\* hard nproc ?([0-9]{1,})@\* hard nproc 65536@g" /etc/security/limits.conf
sed -r -i "s@#{0,}?\* soft memlock ?([0-9]{1,}([TGKM]B){0,1}|unlimited)@\* soft memlock unlimited@g" /etc/security/limits.conf
sed -r -i "s@#{0,}?\* hard memlock ?([0-9]{1,}([TGKM]B){0,1}|unlimited)@\* hard memlock unlimited@g" /etc/security/limits.conf
tmpfile="$$.tmp"
awk ' !x[$0]++{print > "'$tmpfile'"}' /etc/security/limits.conf
mv $tmpfile /etc/security/limits.conf
# Check if firewalld service exists and is running
systemctl status firewalld 1>/dev/null 2>/dev/null
if [ $? -eq 0 ]; then
# Firewall service exists and is running, stop and disable it
systemctl stop firewalld 1>/dev/null 2>/dev/null
systemctl disable firewalld 1>/dev/null 2>/dev/null
fi
# Check if ufw service exists and is running
systemctl status ufw 1>/dev/null 2>/dev/null
if [ $? -eq 0 ]; then
# ufw service exists and is running, stop and disable it
systemctl stop ufw 1>/dev/null 2>/dev/null
systemctl disable ufw 1>/dev/null 2>/dev/null
fi
modinfo br_netfilter > /dev/null 2>&1
if [ $? -eq 0 ]; then
modprobe br_netfilter
mkdir -p /etc/modules-load.d
echo 'br_netfilter' > /etc/modules-load.d/kubekey-br_netfilter.conf
fi
modinfo overlay > /dev/null 2>&1
if [ $? -eq 0 ]; then
modprobe overlay
echo 'overlay' >> /etc/modules-load.d/kubekey-br_netfilter.conf
fi
modprobe ip_vs
modprobe ip_vs_rr
modprobe ip_vs_wrr
modprobe ip_vs_sh
cat > /etc/modules-load.d/kube_proxy-ipvs.conf << EOF
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
EOF
modprobe nf_conntrack_ipv4 1>/dev/null 2>/dev/null
if [ $? -eq 0 ]; then
echo 'nf_conntrack_ipv4' > /etc/modules-load.d/kube_proxy-ipvs.conf
else
modprobe nf_conntrack
echo 'nf_conntrack' > /etc/modules-load.d/kube_proxy-ipvs.conf
fi
sysctl -p
sync
# echo 3 > /proc/sys/vm/drop_caches
# Make sure the iptables utility doesn't use the nftables backend.
update-alternatives --set iptables /usr/sbin/iptables-legacy >/dev/null 2>&1 || true
update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy >/dev/null 2>&1 || true
update-alternatives --set arptables /usr/sbin/arptables-legacy >/dev/null 2>&1 || true
update-alternatives --set ebtables /usr/sbin/ebtables-legacy >/dev/null 2>&1 || true
执行上述生产环境优化脚本,完成系统初始化:
bash
# 执行内核初始化
sh initOS.sh
1.2 安装cfssl证书生成工具
后续生成CA及各组件证书需依赖cfssl工具,执行以下命令安装并验证:
bash
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 /usr/local/bin/cfssljson
cfssl version
1.3 下载kubernetes软件
下载K8s v1.28.7版本二进制文件,并复制到系统可执行目录:
bash
K8S_VERSION=v1.28.7
wget https://dl.k8s.io/${K8S_VERSION}/kubernetes-server-linux-amd64.tar.gz
tar zxf kubernetes-server-linux-amd64.tar.gz
# 一次性复制所有K8s可执行文件到/usr/local/bin,无需单独复制单个组件
cp kubernetes/server/bin/* /usr/local/bin/
1.4 下载etcd软件
下载etcd v3.5.10版本(与K8s v1.28.7适配),并复制可执行文件到系统目录:
bash
wget https://github.com/etcd-io/etcd/releases/download/v3.5.10/etcd-v3.5.10-linux-amd64.tar.gz
tar zxf etcd-v3.5.10-linux-amd64.tar.gz
cp etcd-v3.5.10-linux-amd64/etcd* /usr/local/bin/
1.5 下载containerd软件
下载containerd v1.7.11版本(作为K8s容器运行时),并解压到指定目录:
bash
wget https://github.com/containerd/containerd/releases/download/v1.7.11/containerd-1.7.11-linux-amd64.tar.gz
tar zxf containerd-1.7.11-linux-amd64.tar.gz -C /usr/local/
二、生成CA证书及所有组件证书(除kubelet、kube-proxy)
创建证书存放目录,生成CA基础配置及各类组件证书,所有证书统一存放于/etc/kubernetes/pki目录:
bash
mkdir -p /etc/kubernetes/pki /opt/cert
cd /opt/cert
# 1. ETCD 和 k8s组件共用的CA
cat > ca-config.json << EOF
{
"signing": {
"default": {
"expiry": "876000h"
},
"profiles": {
"kubernetes": {
"usages": ["signing", "key encipherment", "server auth", "client auth"],
"expiry": "876000h"
}
}
}
}
EOF
cat > ca-csr.json << EOF
{
"CN": "kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "Beijing",
"L": "Beijing",
"O": "Kubernetes",
"OU": "CA"
}
]
}
EOF
cfssl gencert -initca ca-csr.json | cfssljson -bare /opt/cert/ca
mkdir -p /etc/kubernetes/pki/
mv /opt/cert/ca*.pem /etc/kubernetes/pki/
cat > /opt/cert/apiserver-csr.json << EOF
{
"CN": "kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "Beijing",
"L": "Beijing",
"O": "Kubernetes",
"OU": "API Server"
}
],
"hosts": [
"127.0.0.1",
"192.168.133.140",
"10.96.0.1",
"kubernetes",
"kubernetes.default",
"kubernetes.default.svc",
"kubernetes.default.svc.cluster",
"kubernetes.default.svc.cluster.local"
]
}
EOF
cfssl gencert -ca=/etc/kubernetes/pki/ca.pem \
-ca-key=/etc/kubernetes/pki/ca-key.pem \
-config=/opt/cert/ca-config.json \
-profile=kubernetes /opt/cert/apiserver-csr.json | cfssljson -bare /opt/cert/apiserver
mv /opt/cert/apiserver*.pem /etc/kubernetes/pki/
# 2. kube-apiserver 访问 kubelet用的证书
cat > /opt/cert/apiserver-kubelet-client-csr.json << EOF
{
"CN": "apiserver-kubelet-client",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "Beijing",
"L": "Beijing",
"O": "system:masters",
"OU": "Kubernetes"
}
]
}
EOF
cfssl gencert -ca=/etc/kubernetes/pki/ca.pem \
-ca-key=/etc/kubernetes/pki/ca-key.pem \
-config=/opt/cert/ca-config.json \
-profile=kubernetes /opt/cert/apiserver-kubelet-client-csr.json | cfssljson -bare /opt/cert/apiserver-kubelet-client
mv /opt/cert/apiserver-kubelet-client*.pem /etc/kubernetes/pki/
# 3. 生成front-proxy-ca证书(前端代理用,单独的ca)
cat > /opt/cert/front-proxy-ca-csr.json << EOF
{
"CN": "front-proxy-ca",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "Beijing",
"L": "Beijing",
"O": "Kubernetes",
"OU": "Front Proxy CA"
}
]
}
EOF
cfssl gencert -initca /opt/cert/front-proxy-ca-csr.json | cfssljson -bare /opt/cert/front-proxy-ca
mv /opt/cert/front-proxy-ca*.pem /etc/kubernetes/pki/
# 生成front-proxy-client证书(前端代理客户端用)
cat > /opt/cert/front-proxy-client-csr.json << EOF
{
"CN": "front-proxy-client",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "Beijing",
"L": "Beijing",
"O": "Kubernetes",
"OU": "Front Proxy Client"
}
]
}
EOF
cfssl gencert -ca=/etc/kubernetes/pki/front-proxy-ca.pem \
-ca-key=/etc/kubernetes/pki/front-proxy-ca-key.pem \
-config=/opt/cert/ca-config.json \
-profile=kubernetes /opt/cert/front-proxy-client-csr.json | cfssljson -bare /opt/cert/front-proxy-client
mv /opt/cert/front-proxy-client*.pem /etc/kubernetes/pki/
# 4. admin 证书(集群管理员用,如: kubectl 命令行)
cat > /opt/cert/admin-csr.json << EOF
{
"CN": "admin",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "Beijing",
"L": "Beijing",
"O": "system:masters",
"OU": "Kubernetes"
}
]
}
EOF
cfssl gencert -ca=/etc/kubernetes/pki/ca.pem \
-ca-key=/etc/kubernetes/pki/ca-key.pem \
-config=/opt/cert/ca-config.json \
-profile=kubernetes /opt/cert/admin-csr.json | cfssljson -bare /opt/cert/admin
mv /opt/cert/admin*.pem /etc/kubernetes/pki/
# 5. 生成service account密钥(sa相关)
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作为K8s集群的数据存储组件,需先生成其专属证书,再配置系统服务并启动,最后验证健康状态:
bash
mkdir -p /var/lib/etcd
# 1. etcd-member证书
cat > /opt/cert/etcd-member-csr.json << EOF
{
"CN": "etcd-member",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "Beijing",
"L": "Beijing",
"O": "Kubernetes",
"OU": "etcd"
}
],
"hosts": [
"127.0.0.1",
"192.168.133.140"
]
}
EOF
cfssl gencert -ca=/etc/kubernetes/pki/ca.pem \
-ca-key=/etc/kubernetes/pki/ca-key.pem \
-config=/opt/cert/ca-config.json \
-profile=kubernetes /opt/cert/etcd-member-csr.json | cfssljson -bare /opt/cert/etcd-member
mv /opt/cert/etcd-member*.pem /etc/kubernetes/pki/
# 2. etcd.env, etcd 配置参数
cat > /etc/etcd.env << EOF
# Environment file for etcd v3.5.13
ETCD_DATA_DIR=/var/lib/etcd
ETCD_ADVERTISE_CLIENT_URLS=https://192.168.133.140:2379
ETCD_INITIAL_ADVERTISE_PEER_URLS=https://192.168.133.140:2380
ETCD_INITIAL_CLUSTER_STATE=new
ETCD_METRICS=basic
ETCD_LISTEN_CLIENT_URLS=https://192.168.133.140:2379,https://127.0.0.1:2379
ETCD_INITIAL_CLUSTER_TOKEN=k8s_etcd
ETCD_LISTEN_PEER_URLS=https://192.168.133.140:2380
ETCD_NAME=etcd-master01
ETCD_PROXY=off
ETCD_ENABLE_V2=true
ETCD_INITIAL_CLUSTER=etcd-master01=https://192.168.133.140:2380
ETCD_ELECTION_TIMEOUT=5000
ETCD_HEARTBEAT_INTERVAL=250
ETCD_AUTO_COMPACTION_RETENTION=8
ETCD_SNAPSHOT_COUNT=10000
# TLS settings
ETCD_TRUSTED_CA_FILE=/etc/kubernetes/pki/ca.pem
ETCD_CERT_FILE=/etc/kubernetes/pki/etcd-member.pem
ETCD_KEY_FILE=/etc/kubernetes/pki/etcd-member-key.pem
ETCD_CLIENT_CERT_AUTH=true
ETCD_PEER_TRUSTED_CA_FILE=/etc/kubernetes/pki/ca.pem
ETCD_PEER_CERT_FILE=/etc/kubernetes/pki/etcd-member.pem
ETCD_PEER_KEY_FILE=/etc/kubernetes/pki/etcd-member-key.pem
ETCD_PEER_CLIENT_CERT_AUTH=true
# CLI settings
ETCDCTL_ENDPOINTS=https://127.0.0.1:2379
ETCDCTL_CACERT=/etc/kubernetes/pki/ca.pem
ETCDCTL_KEY=/etc/kubernetes/pki/etcd-member-key.pem
ETCDCTL_CERT=/etc/kubernetes/pki/etcd-member.pem
EOF
# 3. etcd 启动服务
cat > /etc/systemd/system/etcd.service << EOF
[Unit]
Description=etcd
After=network.target
[Service]
User=root
Type=notify
Nice=-20
OOMScoreAdjust=-1000
EnvironmentFile=-/etc/etcd.env
ExecStart=/usr/local/bin/etcd
NotifyAccess=all
RestartSec=10s
LimitNOFILE=40000
Restart=always
[Install]
WantedBy=multi-user.target
EOF
# 4. 启动 etcd 并验证
systemctl daemon-reload && systemctl enable etcd --now
systemctl status etcd
etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/ca.pem --cert=/etc/kubernetes/pki/etcd-member.pem --key=/etc/kubernetes/pki/etcd-member-key.pem endpoint health
四、部署容器运行时(containerd)
配置containerd系统服务,修改默认配置(适配systemd cgroup和国内镜像),启动并验证服务状态:
bash
# 1. 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
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNPROC=infinity
LimitCORE=infinity
LimitNOFILE=1048576
LimitMEMLOCK=infinity
# Comment TasksMax if your systemd version does not supports it.
# Only systemd 226 and above support this version.
TasksMax=infinity
OOMScoreAdjust=-999
[Install]
WantedBy=multi-user.target
EOF
# 2. containerd 配置文件
mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml
sed -i 's/SystemdCgroup \= false/SystemdCgroup \= true/' /etc/containerd/config.toml
sed -i '/sandbox_image/c\ sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.9"' /etc/containerd/config.toml
grep sandbox_image /etc/containerd/config.toml
# 3. 启动 containerd 服务
systemctl daemon-reload && systemctl enable containerd
systemctl restart containerd
systemctl status containerd
五、部署Master核心组件(kube-apiserver、kube-controller-manager、kube-scheduler)
说明:kube-controller-manager 和 kube-scheduler 组件需开启以下启动参数,确保Prometheus可无需认证获取监控指标:
bash
# kube-controller-manager 和 kube-scheduler 组件开启以下启动参数,Prometheus就不需要认证就可以获取监控指标
--authorization-always-allow-paths=/metrics
5.1 部署kube-apiserver
kube-apiserver是K8s集群的核心入口,配置系统服务、启动服务后,生成admin.conf配置文件,确保集群可正常访问:
bash
# 1. token.csv
cat > /etc/kubernetes/token.csv << EOF
ed0248a55cde31f039f9c9019c3a5440,kubelet-bootstrap,10001,"system:node-bootstrapper"
EOF
# 2. kube-apiserver
cat > /etc/systemd/system/kube-apiserver.service << EOF
[Unit]
Description=Kubernetes API Server
After=network.target etcd.service
[Service]
ExecStart=/usr/local/bin/kube-apiserver \
--advertise-address=192.168.133.140 \
--allow-privileged=true \
--authorization-mode=Node,RBAC \
--bind-address=0.0.0.0 \
--client-ca-file=/etc/kubernetes/pki/ca.pem \
--enable-admission-plugins=NamespaceLifecycle,NodeRestriction,LimitRanger,ServiceAccount,DefaultStorageClass,ResourceQuota \
--enable-bootstrap-token-auth=true \
--etcd-cafile=/etc/kubernetes/pki/ca.pem \
--etcd-certfile=/etc/kubernetes/pki/etcd-member.pem \
--etcd-keyfile=/etc/kubernetes/pki/etcd-member-key.pem \
--etcd-servers=https://192.168.133.140:2379 \
--feature-gates=RotateKubeletServerCertificate=true \
--kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.pem \
--kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client-key.pem \
--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname \
--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=front-proxy-client \
--requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.pem \
--requestheader-extra-headers-prefix=X-Remote-Extra- \
--requestheader-group-headers=X-Remote-Group \
--requestheader-username-headers=X-Remote-User \
--secure-port=6443 \
--service-account-issuer=https://kubernetes.default.svc.cluster.local \
--service-account-key-file=/etc/kubernetes/pki/sa.pub \
--service-account-signing-key-file=/etc/kubernetes/pki/sa.key \
--service-cluster-ip-range=10.96.0.0/16 \
--tls-cert-file=/etc/kubernetes/pki/apiserver.pem \
--tls-private-key-file=/etc/kubernetes/pki/apiserver-key.pem \
--token-auth-file=/etc/kubernetes/token.csv \
--v=2
Restart=always
RestartSec=5
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
EOF
# 3. 启动 kube-apiserver
systemctl daemon-reload && systemctl enable kube-apiserver --now
systemctl status kube-apiserver
# 4. admin.conf
MASTER_IP=192.168.133.140
kubectl config set-cluster kubernetes \
--certificate-authority=/etc/kubernetes/pki/ca.pem \
--embed-certs=true \
--server=https://${MASTER_IP}:6443 \
--kubeconfig=/etc/kubernetes/admin.conf
kubectl config set-credentials admin \
--client-certificate=/etc/kubernetes/pki/admin.pem \
--client-key=/etc/kubernetes/pki/admin-key.pem \
--embed-certs=true \
--kubeconfig=/etc/kubernetes/admin.conf
kubectl config set-context kubernetes \
--cluster=kubernetes \
--user=admin \
--kubeconfig=/etc/kubernetes/admin.conf
kubectl config use-context kubernetes --kubeconfig=/etc/kubernetes/admin.conf
mkdir -p ~/.kube
cp /etc/kubernetes/admin.conf ~/.kube/config
kubectl get cs,nodes
# echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> /etc/profile
# source /etc/profile
5.2 部署kube-controller-manager
生成kube-controller-manager证书及配置文件,配置系统服务并启动,验证组件状态:
bash
# 1. 生成kube-controller-manager证书
cat > /opt/cert/kube-controller-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"
}
]
}
EOF
cfssl gencert -ca=/etc/kubernetes/pki/ca.pem \
-ca-key=/etc/kubernetes/pki/ca-key.pem \
-config=/opt/cert/ca-config.json \
-profile=kubernetes /opt/cert/kube-controller-manager-csr.json | cfssljson -bare /opt/cert/kube-controller-manager
mv /opt/cert/kube-controller-manager*.pem /etc/kubernetes/pki/
# 2. kube-controller-manager.kubeconfig
cat > /etc/kubernetes/kube-controller-manager.kubeconfig << EOF
apiVersion: v1
kind: Config
clusters:
- cluster:
certificate-authority: /etc/kubernetes/pki/ca.pem
server: https://192.168.133.140:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: system:kube-controller-manager
name: system:kube-controller-manager@kubernetes
current-context: system:kube-controller-manager@kubernetes
users:
- name: system:kube-controller-manager
user:
client-certificate: /etc/kubernetes/pki/kube-controller-manager.pem
client-key: /etc/kubernetes/pki/kube-controller-manager-key.pem
EOF
# 3. kube-controller-manager.service
cat > /etc/systemd/system/kube-controller-manager.service << EOF
[Unit]
Description=Kubernetes Controller Manager
After=network.target kube-apiserver.service
[Service]
ExecStart=/usr/local/bin/kube-controller-manager \
--allocate-node-cidrs=true \
--authentication-kubeconfig=/etc/kubernetes/kube-controller-manager.kubeconfig \
--authorization-kubeconfig=/etc/kubernetes/kube-controller-manager.kubeconfig \
--bind-address=0.0.0.0 \
--client-ca-file=/etc/kubernetes/pki/ca.pem \
--cluster-cidr=10.244.0.0/16 \
--cluster-name=cluster.local \
--cluster-signing-cert-file=/etc/kubernetes/pki/ca.pem \
--cluster-signing-duration=876000h \
--cluster-signing-key-file=/etc/kubernetes/pki/ca-key.pem \
--controllers=*,bootstrapsigner,tokencleaner \
--feature-gates=RotateKubeletServerCertificate=true \
--kubeconfig=/etc/kubernetes/kube-controller-manager.kubeconfig \
--leader-elect=true \
--node-cidr-mask-size=24 \
--requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.pem \
--root-ca-file=/etc/kubernetes/pki/ca.pem \
--service-account-private-key-file=/etc/kubernetes/pki/sa.key \
--service-cluster-ip-range=10.96.0.0/16 \
--use-service-account-credentials=true \
--authorization-always-allow-paths=/metrics \
--v=2
Restart=always
RestartSec=5
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
EOF
# 4. 启动 kube-controller-manager
systemctl daemon-reload && systemctl enable kube-controller-manager --now
kubectl get cs
5.3 部署kube-scheduler
生成kube-scheduler证书及配置文件,配置系统服务并启动,验证组件状态:
bash
# 1. kube-scheduler 证书
cat > /opt/cert/kube-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"
}
]
}
EOF
cfssl gencert -ca=/etc/kubernetes/pki/ca.pem \
-ca-key=/etc/kubernetes/pki/ca-key.pem \
-config=/opt/cert/ca-config.json \
-profile=kubernetes /opt/cert/kube-scheduler-csr.json | cfssljson -bare /opt/cert/kube-scheduler
mv /opt/cert/kube-scheduler*.pem /etc/kubernetes/pki/
# 2. kube-scheduler.kubeconfig
cat > /etc/kubernetes/kube-scheduler.kubeconfig << EOF
apiVersion: v1
kind: Config
clusters:
- cluster:
certificate-authority: /etc/kubernetes/pki/ca.pem
server: https://192.168.133.140:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: system:kube-scheduler
name: system:kube-scheduler@kubernetes
current-context: system:kube-scheduler@kubernetes
users:
- name: system:kube-scheduler
user:
client-certificate: /etc/kubernetes/pki/kube-scheduler.pem
client-key: /etc/kubernetes/pki/kube-scheduler-key.pem
EOF
# 3. kube-scheduler.service
cat > /etc/systemd/system/kube-scheduler.service << EOF
[Unit]
Description=Kubernetes Scheduler
After=network.target kube-apiserver.service
[Service]
ExecStart=/usr/local/bin/kube-scheduler \
--authentication-kubeconfig=/etc/kubernetes/kube-scheduler.kubeconfig \
--authorization-kubeconfig=/etc/kubernetes/kube-scheduler.kubeconfig \
--bind-address=0.0.0.0 \
--feature-gates=RotateKubeletServerCertificate=true \
--kubeconfig=/etc/kubernetes/kube-scheduler.kubeconfig \
--leader-elect=true \
--authorization-always-allow-paths=/metrics \
--v=2
Restart=always
RestartSec=5
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
EOF
# 4. 启动 kube-scheduler
systemctl daemon-reload && systemctl enable kube-scheduler --now
systemctl status kube-scheduler
kubectl get cs
bash
[root@master01 ~]#
[root@master01 ~]# kubectl get cs
Warning: v1 ComponentStatus is deprecated in v1.19+
NAME STATUS MESSAGE ERROR
etcd-0 Healthy ok
controller-manager Healthy ok
scheduler Healthy ok
[root@master01 ~]#
六、部署kubelet(二进制方式,kubelet自动注册+生成证书+证书自动轮换)
6.1 kubelet自动注册集群(基于bootstrap token)
kubelet采用二进制部署,通过bootstrap token完成集群自动注册,结合证书自动轮换功能,无需手动干预证书更新,步骤如下:
bash
# 1. kubelet 工作目录和CA
mkdir -p /var/lib/kubelet/pki
cp /etc/kubernetes/pki/ca.pem /var/lib/kubelet/pki
# 2. 生成kubelet配置文件(指定bootstrap token、CA证书等,实现自动注册)
kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --user=kubelet-bootstrap
# 3. 授权kube-controller-manager自动批准kubelet证书签名请求(CSR,实现自动签名)
kubectl create clusterrolebinding node-autoapprove-bootstrap --clusterrole=system:certificates.k8s.io:certificatesigningrequests:nodeclient --user=kubelet-bootstrap
# 4. 授权nodes用户自动轮换证书(启用kubelet证书自动轮换的核心授权)
kubectl create clusterrolebinding node-autoapprove-certificate-rotation --clusterrole=system:certificates.k8s.io:certificatesigningrequests:selfnodeclient --user=system:nodes
# 5. 生成kubelet bootstrap-kubelet.kubeconfig(用于初始注册)
cat > /etc/kubernetes/bootstrap-kubelet.kubeconfig << EOF
apiVersion: v1
kind: Config
clusters:
- cluster:
certificate-authority: /etc/kubernetes/pki/ca.pem
server: https://192.168.133.140:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kubelet-bootstrap
name: default
current-context: default
users:
- name: kubelet-bootstrap
user:
token: ed0248a55cde31f039f9c9019c3a5440 # 与token.csv中的token一致
EOF
6.2 kubelet 配置文件和启动文件
开启证书自动轮换后,kubelet会定期更新证书(默认有效期1年),无需手动操作,可通过以下命令验证轮换配置生效:
bash
# 1. config.yaml 配置文件
cat > /var/lib/kubelet/config.yaml << EOF
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
address: 0.0.0.0
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.2
clusterDomain: cluster.local
configMapAndSecretChangeDetectionStrategy: Watch
containerLogMaxFiles: 3
containerLogMaxSize: 10Mi
enforceNodeAllocatable:
- pods
eventBurst: 10
eventRecordQPS: 5
evictionHard:
imagefs.available: 15%
memory.available: 300Mi
nodefs.available: 10%
nodefs.inodesFree: 5%
evictionPressureTransitionPeriod: 5m0s
failSwapOn: true
fileCheckFrequency: 40s
hairpinMode: hairpin-veth
healthzBindAddress: 0.0.0.0
healthzPort: 10248
httpCheckFrequency: 40s
imageGCHighThresholdPercent: 85
imageGCLowThresholdPercent: 80
imageMinimumGCAge: 2m0s
kubeAPIBurst: 100
kubeAPIQPS: 50
makeIPTablesUtilChains: true
maxOpenFiles: 1000000
maxParallelImagePulls: 5
maxPods: 110
nodeLeaseDurationSeconds: 40
nodeStatusReportFrequency: 1m0s
nodeStatusUpdateFrequency: 10s
oomScoreAdj: -999
podPidsLimit: -1
port: 10250
# disable readOnlyPort
readOnlyPort: 10255
resolvConf: /etc/resolv.conf
runtimeRequestTimeout: 2m0s
serializeImagePulls: false
streamingConnectionIdleTimeout: 4h0m0s
syncFrequency: 1m0s
rotateCertificates: true
certificateRotationGracePeriod: 30s
EOF
# 2. 创建kubelet系统服务文件
cat > /etc/systemd/system/kubelet.service << EOF
[Unit]
Description=Kubernetes Kubelet
After=network.target containerd.service
[Service]
WorkingDirectory=/var/lib/kubelet
ExecStartPre=/bin/mount -o remount,rw '/sys/fs/cgroup'
CPUAccounting=true
MemoryAccounting=true
ExecStart=/usr/local/bin/kubelet \
--config=/var/lib/kubelet/config.yaml \
--container-runtime-endpoint=unix:///run/containerd/containerd.sock \
--hostname-override=master01 \
--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.kubeconfig \
--kubeconfig=/var/lib/kubelet/kubelet.kubeconfig \
--root-dir=/var/lib/kubelet \
--v=2
Restart=always
StartLimitInterval=0
RestartSec=10
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
EOF
# 3. 启动kubelet服务(此时kubelet会通过bootstrap token向apiserver注册)
systemctl daemon-reload && systemctl enable kubelet --now
systemctl status kubelet
# 4. 查看节点是否已自动注册到集群(看到节点表示自动注册成功)
kubectl get no
七、部署kube-proxy(两种部署方式,二选一)
kube-proxy提供两种部署方式:二进制部署(适合单机场景,便于手动管理)、DaemonSet部署(适合集群扩展,自动调度),两种方式相互独立,选择一种即可。
7.1 方式一:二进制部署kube-proxy
生成kube-proxy证书及配置文件,配置系统服务,启动后验证服务状态:
bash
# 1. 生成kube-proxy证书
cat > /opt/cert/kube-proxy-csr.json << EOF
{
"CN": "system:kube-proxy",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "Beijing",
"L": "Beijing",
"O": "system:node-proxier",
"OU": "Kubernetes"
}
]
}
EOF
cfssl gencert -ca=/etc/kubernetes/pki/ca.pem \
-ca-key=/etc/kubernetes/pki/ca-key.pem \
-config=/opt/cert/ca-config.json \
-profile=kubernetes /opt/cert/kube-proxy-csr.json | cfssljson -bare /opt/cert/kube-proxy
mv /opt/cert/kube-proxy*.pem /etc/kubernetes/pki/
# 2. 生成kube-proxy kubeconfig配置文件
cat > /etc/kubernetes/kube-proxy.kubeconfig << EOF
apiVersion: v1
kind: Config
clusters:
- cluster:
certificate-authority: /etc/kubernetes/pki/ca.pem
server: https://192.168.133.140:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: system:kube-proxy
name: system:kube-proxy@kubernetes
current-context: system:kube-proxy@kubernetes
users:
- name: system:kube-proxy
user:
client-certificate: /etc/kubernetes/pki/kube-proxy.pem
client-key: /etc/kubernetes/pki/kube-proxy-key.pem
EOF
# 3. 生成kube-proxy配置文件(指定ipvs模式,适配前文ipvs模块)
mkdir -p /var/lib/kube-proxy
cat > /var/lib/kube-proxy/kube-proxy-config.yaml << EOF
kind: KubeProxyConfiguration
apiVersion: kubeproxy.config.k8s.io/v1alpha1
bindAddress: 0.0.0.0
clientConnection:
kubeconfig: "/etc/kubernetes/kube-proxy.kubeconfig"
clusterCIDR: "10.244.0.0/16"
conntrack:
maxPerCore: 32768
min: 131072
tcpCloseWaitTimeout: 1h0m0s
tcpEstablishedTimeout: 24h0m0s
healthzBindAddress: 0.0.0.0:10256
hostnameOverride: "master01" # 主机名
metricsBindAddress: 0.0.0.0:10249
mode: "ipvs"
ipvs:
scheduler: "rr"
EOF
# 4. 创建kube-proxy系统服务文件
cat > /etc/systemd/system/kube-proxy.service << EOF
[Unit]
Description=Kubernetes Kube-Proxy
After=network.target kube-apiserver.service
[Service]
ExecStart=/usr/local/bin/kube-proxy \
--config=/etc/kubernetes/kube-proxy-config.yaml \
--v=2
Restart=always
RestartSec=5
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
EOF
# 5. 启动kube-proxy并验证
systemctl daemon-reload && systemctl enable kube-proxy --now
systemctl status kube-proxy
# 验证ipvs规则(可看到kube-proxy生成的ipvs规则)
ipvsadm -Ln
7.2 方式二:DaemonSet部署kube-proxy(推荐集群扩展)
通过DaemonSet方式部署kube-proxy,会自动在所有节点(此处仅master节点)部署,无需手动配置系统服务,步骤如下:
bash
# 1. 生成kube-proxy配置文件(通过ConfigMap挂载)
cat > kube-proxy-configmap.yaml << EOF
apiVersion: v1
data:
config.conf: |-
apiVersion: kubeproxy.config.k8s.io/v1alpha1
bindAddress: 0.0.0.0
clientConnection:
kubeconfig: /var/lib/kube-proxy/kubeconfig.conf
clusterCIDR: 10.244.0.0/16
healthzBindAddress: ""
hostnameOverride: ""
ipvs:
scheduler: "rr"
kind: KubeProxyConfiguration
logging:
flushFrequency: 0
options:
json:
infoBufferSize: "0"
verbosity: 0
metricsBindAddress: ""
mode: ipvs
oomScoreAdj: -999
kubeconfig.conf: |-
apiVersion: v1
kind: Config
clusters:
- cluster:
certificate-authority: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
server: https://192.168.133.140:6443
name: default
contexts:
- context:
cluster: default
namespace: default
user: default
name: default
current-context: default
users:
- name: default
user:
tokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
kind: ConfigMap
metadata:
labels:
app: kube-proxy
name: kube-proxy
namespace: kube-system
EOF
# 2. 创建DaemonSet部署kube-proxy
cat > kube-proxy-daemonset.yaml << EOF
---
# kube-proxy ServiceAccount 配置
apiVersion: v1
kind: ServiceAccount
metadata:
name: kube-proxy
namespace: kube-system
labels:
k8s-app: kube-proxy
---
# kube-proxy 集群角色绑定配置
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: kube-proxy
labels:
k8s-app: kube-proxy
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:node-proxier # kube-proxy 必需的内置集群角色
subjects:
- kind: ServiceAccount
name: kube-proxy
namespace: kube-system # 与上面的 ServiceAccount 命名空间一致
---
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
labels:
k8s-app: kube-proxy
name: kube-proxy
namespace: kube-system
spec:
selector:
matchLabels:
k8s-app: kube-proxy
template:
metadata:
labels:
k8s-app: kube-proxy
spec:
containers:
- command:
- /usr/local/bin/kube-proxy
- --config=/var/lib/kube-proxy/config.conf
- --hostname-override=\$(NODE_NAME)
env:
- name: TZ
value: Asia/Shanghai
- name: NODE_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: spec.nodeName
#image: registry.aliyuncs.com/google_containers/kube-proxy:v1.28.7
image: registry.cn-hangzhou.aliyuncs.com/google_containers/kube-proxy:v1.28.7
imagePullPolicy: IfNotPresent
name: kube-proxy
resources: {}
securityContext:
privileged: true
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /var/lib/kube-proxy
name: kube-proxy
- mountPath: /run/xtables.lock
name: xtables-lock
- mountPath: /lib/modules
name: lib-modules
readOnly: true
dnsPolicy: ClusterFirst
hostNetwork: true
nodeSelector:
kubernetes.io/os: linux
priorityClassName: system-node-critical
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
serviceAccount: kube-proxy
serviceAccountName: kube-proxy
tolerations:
- operator: Exists
volumes:
- configMap:
defaultMode: 420
name: kube-proxy
name: kube-proxy
- hostPath:
path: /run/xtables.lock
type: FileOrCreate
name: xtables-lock
- hostPath:
path: /lib/modules
type: ""
name: lib-modules
---
EOF
# 3. 执行部署命令
kubectl apply -f kube-proxy-configmap.yaml
kubectl apply -f kube-proxy-daemonset.yaml
# 4. 验证部署结果(确保Pod处于Running状态)
kubectl get pods -n kube-system | grep kube-proxy
# 验证ipvs规则
ipvsadm -Ln
八、部署CNI网络插件(必部署)
CNI网络插件用于实现Pod之间的网络通信,此处选择calico,部署步骤如下:
bash
# 1. 下载calico部署文件(v3.31.4版本)
wget https://raw.githubusercontent.com/projectcalico/calico/v3.31.4/manifests/calico.yaml
# 2. 修改calico配置,指定集群CIDR(与kube-controller-manager中的cluster-cidr一致)
sed -i 's/192.168.0.0\/16/10.244.0.0\/16/g' calico.yaml
sed -i 's/docker.io/mirror.ccs.tencentyun.com/g' calico.yaml
# calico 用到的镜像可替换成以下的镜像
# docker pull registry.cn-shenzhen.aliyuncs.com/rmyyds/cni:v3.31.4
# docker pull registry.cn-shenzhen.aliyuncs.com/rmyyds/node:v3.31.4
# docker pull registry.cn-shenzhen.aliyuncs.com/rmyyds/kube-controllers:v3.31.4
# 3. 部署calico
kubectl apply -f calico.yaml
# 4. 验证calico部署(所有calico相关Pod均为Running状态即为正常)
kubectl get pods -n kube-system
# 5. 部署完成后,查看Node状态(变为Ready即为正常)
kubectl get nodes
九、部署coredns插件(必部署)
coredns用于k8s集群内部服务解析,部署步骤如下:
bash
# 1. 下载coredns部署文件
curl -O https://raw.githubusercontent.com/coredns/deployment/master/kubernetes/coredns.yaml.sed
curl -O https://raw.githubusercontent.com/coredns/deployment/master/kubernetes/deploy.sh
# 2. 修改coredns配置,生成部署文件(--dns-server 指定CoreDNS的ClusterIP为10.96.0.2)
chmod +x deploy.sh
./deploy.sh -i 10.96.0.2 > coredns.yaml
# 3. 替换成阿里云镜像
sed -i 's/coredns\/coredns/registry.aliyuncs.com\/google_containers\/coredns/g' coredns.yaml
# docker pull registry.aliyuncs.com/google_containers/coredns:1.9.4
# 4. 部署coredns(所有相关Pod均为Running状态即为正常)
kubectl apply -f coredns.yaml
# 5. 验证coredns部署(所有coredns相关Pod均为Running状态即为正常)
kubectl get pod -A
十、集群部署完成验证
所有组件部署完成后,执行以下命令验证集群整体状态,确保所有组件正常运行:
bash
# 1. 查看集群组件状态(etcd、controller-manager、scheduler均为Healthy)
kubectl get cs
# 2. 查看节点状态(node状态为Ready)
kubectl get nodes -o wide
# 3. 查看所有命名空间下的Pod状态(所有Pod均为Running,无Error、CrashLoopBackOff)
kubectl get pods --all-namespaces
# 4. 查看集群信息
kubectl cluster-info
# 5. 验证核心组件日志(可选,若有异常可查看日志排查)
systemctl status etcd containerd kube-apiserver kube-controller-manager kube-scheduler kubelet kube-proxy -l
# 6. 验证Pod网络通信(再次测试,确保跨Pod通信正常)
kubectl run test-pod1 --image=busybox:1.35 --command -- sleep 3600
kubectl run test-pod2 --image=busybox:1.35 --command -- sleep 3600
# 获取test-pod2的IP
POD2_IP=$(kubectl get pod test-pod2 -o jsonpath='{.status.podIP}')
# 在test-pod1中ping test-pod2的IP
kubectl exec -it test-pod1 -- ping $POD2_IP -c 3
# 删除测试Pod
kubectl delete pod test-pod1 test-pod2
十一、常见问题排查
11.1 组件启动失败
通过以下命令查看组件日志,定位失败原因:
bash
# 查看指定组件日志(以kubelet为例)
journalctl -u kubelet -f
# 查看容器日志(以calico为例)
kubectl logs -n kube-system <calico-pod-name> -f
11.2 kubelet注册失败
常见原因:bootstrap token不一致、CSR未批准、网络不通,排查步骤:
bash
# 1. 确认bootstrap token与token.csv一致
cat /etc/kubernetes/token.csv | awk -F ',' '{print $1}'
cat /etc/kubernetes/kubelet/bootstrap-kubeconfig | grep token
# 2. 确认CSR已批准
kubectl get csr
# 3. 确认kubelet与apiserver网络连通(6443端口可通)
telnet 192.168.133.140 6443
11.3 Pod网络不通
常见原因:calico未正常启动、ipvs模块未加载,排查步骤:
bash
# 1. 确认calico所有Pod正常运行
kubectl get pods -n kube-system
# 2. 确认ipvs模块已加载
lsmod | grep ip_vs
# 3. 查看calico节点状态
kubectl exec -n kube-system <calico-node-pod-name> -- calicoctl node status
11.4 单机部署k8s,要去除master节点的不可调度策略和去除污点
bash
kubectl taint nodes master01 node.kubernetes.io/not-ready-
kubectl taint nodes master01 node-role.kubernetes.io/control-plane:NoSchedule-
kubectl taint nodes master01 node-role.kubernetes.io/master:NoSchedule-
十二、总结
本文档完成了K8s v1.28.7 单Master节点纯二进制部署,涵盖环境准备、证书生成、核心组件部署、kubelet自动注册、kube-proxy两种部署方式及CNI网络插件部署,所有命令可直接复制执行。部署完成后,集群可正常运行,支持Pod创建、网络通信等核心功能,适合单机测试、小型生产环境使用。若需扩展为多节点集群,可参考本文档步骤,在新增节点上部署kubelet、kube-proxy及calico即可。