主题
单Master节点部署Kubernetes
环境信息
- 🐧 操作系统:Ubuntu 22.04.3 LTS
- ☸️ Kubernetes:v1.35.4
- 📦 容器运行时:containerd 2.2.3
- 🌐 网络插件:Calico v3.25.0
- 🔍 DNS:CoreDNS 1.11.3
- 🔐 证书工具:cfssl 1.6.5
- 🗄️ KV存储:etcd v3.6.10
- 🌐 IP 地址:192.168.60.128(Master)
安装执行
注意:执行前请将脚本中的 IP 地址修改为实际 Master 节点 IP
bash
# 1.下载
curl -OL "https://cnb.cool/zhucuiding/docs/-/releases/download/k8s/k8s-1.35.4.tar.gz"
# 2.解压
tar -zxvf k8s-1.35.4.tar.gz && cd k8s-1.35.4
# 3.初始化环境
bash init-k8s.sh
# 4.安装containerd
cd containerd && bash install.sh
# 5. 安装cfssl
cd cfssl && bash install.sh
# 6.安装etcd
cd etcd && bash install.sh
# 7.安装k8s
cd k8s && bash install.sh
# 8.安装calico
kubectl apply -f calico.yaml
# 9.安装coredns
cd coredns && bash install.sh说明:
- 初始化执行包含关闭swap,关闭防火墙和修改内核参数
- 使用containerd,脚本内已包含crictl命令
- 安装cfssl是为后续的etcd和k8s相关组件生成证书
脚本详情
脚本文件位于
scripts/目录下,可直接下载使用
环境初始化
scripts/init-k8s.sh
bash
#! /bin/bash
function get_ip() {
ip=$(hostname -I | awk '{print $1}')
}
function set_hostname() {
hostnamectl set-hostname master
}
function set_swap() {
swapoff -a
sed -i '/^[^#]*swap/ s/^/#/' /etc/fstab
}
function set_ufw() {
systemctl disable --now ufw
}
function set_hosts() {
HOSTS_ENTRY="$ip master"
if grep -q "^$HOSTS_ENTRY" /etc/hosts; then
echo "Hosts entry already exists, skipping..."
else
echo "$HOSTS_ENTRY" | sudo tee -a /etc/hosts
echo "Hosts entry added successfully"
fi
}
function configure_kernel_params() {
cat >/etc/modules-load.d/containerd.conf <<EOF
overlay
br_netfilter
EOF
modprobe overlay && modprobe br_netfilter
cat >/etc/sysctl.d/99-kubernetes-cri.conf <<EOF
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
sysctl --system >/dev/null 2>&1
sysctl net.bridge.bridge-nf-call-iptables
sysctl net.ipv4.ip_forward
}
function main() {
get_ip
set_hostname
set_swap
set_ufw
set_hosts
configure_kernel_params
}
main "$@"Containerd
scripts/containerd/install.sh
bash
#! /bin/bash
#
# curl -LO https://github.com/containerd/containerd/releases/download/v2.2.3/containerd-2.2.3-linux-amd64.tar.gz
# curl -LO https://github.com/opencontainers/runc/releases/download/v1.4.2/runc.amd64
# curl -LO https://github.com/containernetworking/plugins/releases/download/v1.9.1/cni-plugins-linux-amd64-v1.9.1.tgz
# curl -LO https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.35.0/crictl-v1.35.0-linux-amd64.tar.gz
containerd_file=containerd-2.2.3-linux-amd64.tar.gz
runc_file=runc.amd64
cni_file=cni-plugins-linux-amd64-v1.9.1.tgz
crictl_file=crictl-v1.35.0-linux-amd64.tar.gz
function cni_install() {
mkdir -p /opt/cni/bin
tar Cxzvf /opt/cni/bin $cni_file
}
function containerd_install() {
if command -v containerd &>/dev/null; then
"containerd已存在,安装失败"
exit 1
fi
echo "开始安装containerd"
tar -zxvf $containerd_file
cp bin/* /usr/local/bin/
rm -rf bin
install -m 755 $runc_file /usr/local/sbin/runc
cat >/usr/lib/systemd/system/containerd.service <<EOF
[Unit]
Description=containerd container runtime
Documentation=https://containerd.io
After=network.target dbus.service
[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
# 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
# 配置 containerd(此处放containerd.toml文件会覆盖config.toml中的内容)
mkdir -p /etc/containerd/conf.d
/usr/local/bin/containerd config default >/etc/containerd/config.toml
cat >/etc/containerd/conf.d/containerd.toml <<EOF
[plugins.'io.containerd.cri.v1.images'.registry]
config_path = ''
[plugins.'io.containerd.cri.v1.runtime'.containerd.runtimes.runc.options]
SystemdCgroup = true
EOF
# 配置代理拉取镜像
mkdir -p /etc/systemd/system/containerd.service.d
cat >/etc/systemd/system/containerd.service.d/http-proxy.conf <<EOF
[Service]
Environment="HTTP_PROXY=http://192.168.60.1:12450"
Environment="HTTPS_PROXY=http://192.168.60.1:12450"
Environment="NO_PROXY=localhost,127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,.svc,.cluster.local,.ewhisper.cn"
EOF
# 启动服务
systemctl daemon-reload
systemctl enable --now containerd
if systemctl is-active --quiet containerd; then
echo "containerd 安装成功"
return 0
else
echo "containerd 启动失败"
journalctl -u containerd -n 10
return 1
fi
}
function crictl_install() {
tar Czxvf /usr/local/bin $crictl_file
# 消除警告在使用crictl时
cat >/etc/crictl.yaml <<EOF
runtime-endpoint: "unix:///var/run/containerd/containerd.sock"
image-endpoint: "unix:///var/run/containerd/containerd.sock"
timeout: 30
debug: false
EOF
}
function main() {
cni_install
containerd_install
crictl_install
}
main "$@"scripts/containerd/uninstall.sh
bash
#! /bin/bash
function containerd_uninstall() {
if ! command -v containerd &>/dev/null; then
echo "containerd 未安装"
return 0
fi
echo "开始卸载 containerd..."
# 停止服务
systemctl stop containerd 2>/dev/null || true
systemctl disable containerd 2>/dev/null || true
# 删除文件
rm -f /etc/systemd/system/containerd.service
rm -f /usr/local/bin/containerd*
rm -f /usr/local/bin/ctr
rm -rf /etc/systemd/system/containerd.service.d
rm -rf /etc/containerd
rm -rf /etc/crictl.yaml
rm -rf /var/lib/containerd
rm -rf /run/containerd
rm -rf /usr/local/sbin/runc
rm -rf /usr/local/bin/crictl
# 删除自动生成的目录
rm -rf /run/containerd
rm -rf /var/log/containerd
# 重新加载
systemctl daemon-reload
echo "containerd 卸载完成"
return 0
}
function cni_uninstall() {
rm -rf /opt/cni
rm -rf /etc/cni
rm -rf /var/lib/cni
}
function main() {
containerd_uninstall
cni_uninstall
}
main "$@"CFSSL
scripts/cfssl/install.sh
bash
#! /bin/bash
# curl -x http://192.168.60.1:12450 -LO https://github.com/cloudflare/cfssl/releases/download/v1.6.5/cfssl_1.6.5_linux_amd64
# curl -x http://192.168.60.1:12450 -LO https://github.com/cloudflare/cfssl/releases/download/v1.6.5/cfssljson_1.6.5_linux_amd64
cfssl_file=cfssl_1.6.5_linux_amd64
cfssljson_file=cfssljson_1.6.5_linux_amd64
function cfssl_install() {
echo "开始安装cfssl"
install -m 755 $cfssl_file /usr/local/bin/cfssl
install -m 755 $cfssljson_file /usr/local/bin/cfssljson
echo "cfssl安装完成"
}
function main() {
cfssl_install
}
main "$@"scripts/cfssl/uninstall.sh
bash
#! /bin/bash
function cfssl_uninstall() {
echo "开始卸载cfssl"
rm -rf /usr/local/bin/cfssl
rm -rf /usr/local/bin/cfssljson
echo "卸载cfssl完成"
}
function main() {
cfssl_uninstall
}
main "$@"ETCD
scripts/etcd/install.sh
bash
#! /bin/bash
# curl -x http://192.168.60.1:12450 -LO https://github.com/etcd-io/etcd/releases/download/v3.6.10/etcd-v3.6.10-linux-amd64.tar.gz
#root@master:~/master/etcd# etcdctl \
# --endpoints=https://192.168.60.128:2379 \
# --cacert=/etc/etcd/ssl/etcd-ca.pem \
# --cert=/etc/etcd/ssl/client.pem \
# --key=/etc/etcd/ssl/client-key.pem \
# endpoint health
# etcd-ca.pem CA 根证书(所有节点共用)
# server.pem / server-key.pem 服务端证书(etcd 对外服务)
# client.pem / client-key.pem 客户端证书(kube-apiserver 访问 etcd)
# peer-master.pem / peer-master-key.pem Peer 证书(etcd 节点间通信)
etcd_file=etcd-v3.6.10-linux-amd64
etcd_ip="192.168.60.128"
etcd_host="master"
cert_dir="/etc/etcd/ssl"
function etcd_install() {
echo "开始安装etcd"
tar -zxvf $etcd_file.tar.gz
cp -a $etcd_file/etcd* /usr/local/bin
rm -rf $etcd_file
}
function etcd_ca_gencert() {
mkdir -p $cert_dir
cd $cert_dir
# 创建 CA 配置文件
cat >ca-config.json <<EOF
{
"signing": {
"default": {
"expiry": "43800h"
},
"profiles": {
"server": {
"expiry": "43800h",
"usages": ["signing", "key encipherment", "server auth"]
},
"client": {
"expiry": "43800h",
"usages": ["signing", "key encipherment", "client auth"]
},
"peer": {
"expiry": "43800h",
"usages": ["signing", "key encipherment", "server auth", "client auth"]
}
}
}
}
EOF
echo "创建CA配置文件完成"
# 创建 CA 证书签名请求
cat >ca-csr.json <<EOF
{
"CN": "etcd-ca",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "Beijing",
"L": "Beijing",
"O": "etcd",
"OU": "CA"
}
]
}
EOF
# 生成 CA 根证书
cfssl gencert -initca ca-csr.json | cfssljson -bare ca
mv ca.pem etcd-ca.pem
mv ca-key.pem etcd-ca-key.pem
echo "生成CA根证书完成"
# 创建服务端证书请求
cat >server-csr.json <<EOF
{
"CN": "etcd-server",
"hosts": ["127.0.0.1", "localhost", "$etcd_ip", "$etcd_host", "::1"],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "Beijing",
"L": "Beijing",
"O": "etcd",
"OU": "Server"
}
]
}
EOF
echo "创建服务端证书请求完成"
# 生成服务端证书
cfssl gencert \
-ca=etcd-ca.pem \
-ca-key=etcd-ca-key.pem \
-config=ca-config.json \
-profile=server \
server-csr.json | cfssljson -bare server
echo "生成服务端证书完成"
# 创建客户端证书请求
cat >client-csr.json <<EOF
{
"CN": "etcd-client",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "Beijing",
"L": "Beijing",
"O": "etcd",
"OU": "Client"
}
]
}
EOF
echo "创建客户端证书请求完成"
# 生成客户端证书
cfssl gencert \
-ca=etcd-ca.pem \
-ca-key=etcd-ca-key.pem \
-config=ca-config.json \
-profile=client \
client-csr.json | cfssljson -bare client
echo "客户端证书生成完成"
# 生成 Peer 证书
cat >peer-csr.json <<EOF
{
"CN": "etcd-peer-${etcd_host}",
"hosts": ["127.0.0.1", "localhost", "$etcd_ip", "$etcd_host", "::1"],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "Beijing",
"L": "Beijing",
"O": "etcd",
"OU": "Peer"
}
]
}
EOF
echo "生成 Peer 证书完成"
# 生成 Peer 证书
cfssl gencert \
-ca=etcd-ca.pem \
-ca-key=etcd-ca-key.pem \
-config=ca-config.json \
-profile=peer \
peer-csr.json | cfssljson -bare "peer-${etcd_host}"
echo "peer证书生成完成"
}
function etct_service_config() {
echo "创建etcd服务配置"
cat >/etc/systemd/system/etcd.service <<EOF
[Unit]
Description=etcd key-value store
Documentation=https://github.com/etcd-io/etcd
After=network.target
[Service]
Type=notify
ExecStart=/usr/local/bin/etcd \\
--name=${etcd_host} \\
--data-dir=/var/lib/etcd \\
--listen-client-urls=https://${etcd_ip}:2379,https://127.0.0.1:2379 \\
--advertise-client-urls=https://${etcd_ip}:2379 \\
--listen-peer-urls=https://${etcd_ip}:2380 \\
--initial-advertise-peer-urls=https://${etcd_ip}:2380 \\
--initial-cluster=${etcd_host}=https://${etcd_ip}:2380 \\
--initial-cluster-state=new \\
--initial-cluster-token=etcd-cluster-0 \\
--client-cert-auth \\
--trusted-ca-file=/etc/etcd/ssl/etcd-ca.pem \\
--cert-file=/etc/etcd/ssl/server.pem \\
--key-file=/etc/etcd/ssl/server-key.pem \\
--peer-client-cert-auth \\
--peer-trusted-ca-file=/etc/etcd/ssl/etcd-ca.pem \\
--peer-cert-file=/etc/etcd/ssl/peer-${etcd_host}.pem \\
--peer-key-file=/etc/etcd/ssl/peer-${etcd_host}-key.pem
Restart=always
RestartSec=10
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload && systemctl enable --now etcd
echo "etcd 服务配置完成"
}
function main() {
etcd_install
etcd_ca_gencert
etct_service_config
}
main "$@"scripts/etcd/uninstall.sh
bash
#! /bin/bash
function etcd_uninstall() {
echo "开始卸载etcd"
echo "关闭etcd服务"
systemctl disable --now etcd
echo "删除etcd存储目录"
rm -rf /var/lib/etcd
echo "删除证书目录"
rm -rf /etc/etcd/ssl
echo "删除etcd二进制文件"
rm -rf /usr/local/bin/etcd*
echo "卸载etcd完成"
}
function main() {
etcd_uninstall
}
main "$@"Kubernetes
scripts/k8s/k8s-download.sh
bash
#! /bin/bash
k8s_version=v1.35.4
base_url=https://dl.k8s.io/$k8s_version/bin/linux/amd64
mkdir -p k8s-binaries
components=(
kube-apiserver
kube-controller-manager
kube-proxy
kube-scheduler
kubectl
kubelet
)
function k8s_download() {
for component in "${components[@]}"; do
url="$base_url/$component"
echo "开始下载: $component"
curl -x http://192.168.60.1:12450 \
--tlsv1.2 \
--connect-timeout 30 \
--retry 5 \
--retry-delay 2 \
-LO "$url"
mv $component k8s-binaries/
done
}
function main() {
k8s_download
}
main "$@"scripts/k8s/install.sh
bash
#! /bin/bash
# kubernetes-ca.pem Kubernetes CA 根证书
# apiserver.pem API Server 服务端证书
# apiserver-kubelet-client.pem API Server 访问 kubelet
# scheduler.pem 调度器客户端证书
# controller-manager.pem 控制器管理器客户端证书
# admin.pem 管理员 kubectl 证书
# kube-proxy.pem kube-proxy 客户端证书
master_ip="192.168.60.128"
master_host="master"
function install_k8s_binaries() {
install -m 755 k8s-binaries/kube* /usr/local/bin/
}
function gencert_k8s_certs() {
mkdir -p /etc/kubernetes/pki
cd /etc/kubernetes/pki
# 创建ca配置文件
cat >ca-config.json <<'EOF'
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"kubernetes": {
"expiry": "87600h",
"usages": ["signing", "key encipherment", "server auth", "client auth"]
}
}
}
}
EOF
echo "ca配置文件创建完成"
cat >ca-csr.json <<'EOF'
{
"CN": "kubernetes-ca",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "Beijing",
"L": "Beijing",
"O": "Kubernetes",
"OU": "CA"
}
]
}
EOF
echo "ca证书请求文件创建完成"
cfssl gencert -initca ca-csr.json | cfssljson -bare kubernetes-ca
echo "ca根证书生成完成"
cat >apiserver-csr.json <<EOF
{
"CN": "kube-apiserver",
"hosts": [
"127.0.0.1",
"localhost",
"${master_ip}",
"10.96.0.1",
"${master_host}",
"kubernetes",
"kubernetes.default",
"kubernetes.default.svc",
"kubernetes.default.svc.cluster.local"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "Beijing",
"L": "Beijing",
"O": "Kubernetes",
"OU": "apiserver"
}
]
}
EOF
cfssl gencert \
-ca=kubernetes-ca.pem \
-ca-key=kubernetes-ca-key.pem \
-config=ca-config.json \
-profile=kubernetes \
apiserver-csr.json | cfssljson -bare apiserver
echo "apiserver证书生成完成"
cat >apiserver-kubelet-client-csr.json <<'EOF'
{
"CN": "kube-apiserver-kubelet-client",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "Beijing",
"L": "Beijing",
"O": "system:masters",
"OU": "Kubernetes"
}
]
}
EOF
cfssl gencert \
-ca=kubernetes-ca.pem \
-ca-key=kubernetes-ca-key.pem \
-config=ca-config.json \
-profile=kubernetes \
apiserver-kubelet-client-csr.json | cfssljson -bare apiserver-kubelet-client
echo "apiserver-kubelet-client 证书生成完成"
cat >scheduler-csr.json <<'EOF'
{
"CN": "system:kube-scheduler",
"key": { "algo": "rsa", "size": 2048 },
"names": [{ "O": "system:kube-scheduler", "OU": "Kubernetes" }]
}
EOF
cfssl gencert \
-ca=kubernetes-ca.pem \
-ca-key=kubernetes-ca-key.pem \
-config=ca-config.json \
-profile=kubernetes \
scheduler-csr.json | cfssljson -bare scheduler
echo "scheduler 证书生成完成"
cat >controller-manager-csr.json <<'EOF'
{
"CN": "system:kube-controller-manager",
"key": { "algo": "rsa", "size": 2048 },
"names": [{ "O": "system:kube-controller-manager", "OU": "Kubernetes" }]
}
EOF
cfssl gencert \
-ca=kubernetes-ca.pem \
-ca-key=kubernetes-ca-key.pem \
-config=ca-config.json \
-profile=kubernetes \
controller-manager-csr.json | cfssljson -bare controller-manager
echo "controller-manager 证书生成完成"
cat >kubelet-csr.json <<EOF
{
"CN": "system:node:master",
"hosts": ["127.0.0.1", "localhost", "${master_ip}", "${master_host}"],
"key": { "algo": "rsa", "size": 2048 },
"names": [{ "O": "system:nodes", "OU": "Kubernetes" }]
}
EOF
cfssl gencert \
-ca=kubernetes-ca.pem \
-ca-key=kubernetes-ca-key.pem \
-config=ca-config.json \
-profile=kubernetes \
kubelet-csr.json | cfssljson -bare kubelet
echo "kubelet 证书生成完成"
cat >admin-csr.json <<'EOF'
{
"CN": "admin",
"key": { "algo": "rsa", "size": 2048 },
"names": [{ "O": "system:masters", "OU": "Kubernetes" }]
}
EOF
cfssl gencert \
-ca=kubernetes-ca.pem \
-ca-key=kubernetes-ca-key.pem \
-config=ca-config.json \
-profile=kubernetes \
admin-csr.json | cfssljson -bare admin
echo "admin 证书生成完成"
cat >kube-proxy-csr.json <<'EOF'
{
"CN": "system:kube-proxy",
"key": { "algo": "rsa", "size": 2048 },
"names": [{ "O": "system:node-proxier", "OU": "Kubernetes" }]
}
EOF
cfssl gencert \
-ca=kubernetes-ca.pem \
-ca-key=kubernetes-ca-key.pem \
-config=ca-config.json \
-profile=kubernetes \
kube-proxy-csr.json | cfssljson -bare kube-proxy
echo "kube-proxy 证书生成完成"
chmod 600 *-key.pem
chmod 644 *.pem
echo "所有证书生成完成"
}
function start_apiserver() {
cat >/etc/systemd/system/kube-apiserver.service <<EOF
[Unit]
Description=Kubernetes API Server
Documentation=https://kubernetes.io/docs/home/
After=network.target
After=etcd.service
[Service]
ExecStart=/usr/local/bin/kube-apiserver \\
--advertise-address=${master_ip} \\
--allow-privileged=true \\
--authorization-mode=Node,RBAC \\
--client-ca-file=/etc/kubernetes/pki/kubernetes-ca.pem \\
--enable-admission-plugins=NodeRestriction \\
--enable-bootstrap-token-auth=true \\
--etcd-cafile=/etc/etcd/ssl/etcd-ca.pem \\
--etcd-certfile=/etc/etcd/ssl/client.pem \\
--etcd-keyfile=/etc/etcd/ssl/client-key.pem \\
--etcd-servers=https://${master_ip}:2379 \\
--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 \\
--secure-port=6443 \\
--service-account-issuer=https://kubernetes.default.svc.cluster.local \\
--service-account-key-file=/etc/kubernetes/pki/apiserver-key.pem \\
--service-account-signing-key-file=/etc/kubernetes/pki/apiserver-key.pem \\
--service-cluster-ip-range=10.96.0.0/12 \\
--tls-cert-file=/etc/kubernetes/pki/apiserver.pem \\
--tls-private-key-file=/etc/kubernetes/pki/apiserver-key.pem \\
--v=2
Restart=always
RestartSec=10
Type=notify
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now kube-apiserver
}
function start_scheduler() {
cat >/etc/systemd/system/kube-scheduler.service <<'EOF'
[Unit]
Description=Kubernetes Scheduler
Documentation=https://kubernetes.io/docs/home/
After=network.target
After=kube-apiserver.service
[Service]
ExecStart=/usr/local/bin/kube-scheduler \
--leader-elect=true \
--kubeconfig=/etc/kubernetes/scheduler.conf \
--v=2
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
cat >/etc/kubernetes/scheduler.conf <<EOF
apiVersion: v1
kind: Config
clusters:
- cluster:
certificate-authority: /etc/kubernetes/pki/kubernetes-ca.pem
server: https://$master_ip:6443
name: kubernetes
users:
- name: system:kube-scheduler
user:
client-certificate: /etc/kubernetes/pki/scheduler.pem
client-key: /etc/kubernetes/pki/scheduler-key.pem
contexts:
- context:
cluster: kubernetes
user: system:kube-scheduler
name: system:kube-scheduler
current-context: system:kube-scheduler
EOF
systemctl daemon-reload
systemctl enable --now kube-scheduler
}
function start_controller_manager() {
cat >/etc/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/kubernetes-ca.pem \
--cluster-signing-cert-file=/etc/kubernetes/pki/kubernetes-ca.pem \
--cluster-signing-key-file=/etc/kubernetes/pki/kubernetes-ca-key.pem \
--service-account-private-key-file=/etc/kubernetes/pki/apiserver-key.pem \
--kubeconfig=/etc/kubernetes/controller-manager.conf \
--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=10.244.0.0/16 \
--node-cidr-mask-size-ipv4=24
Restart=always
RestartSec=10s
[Install]
WantedBy=multi-user.target
EOF
cat >/etc/kubernetes/controller-manager.conf <<EOF
apiVersion: v1
kind: Config
clusters:
- cluster:
certificate-authority: /etc/kubernetes/pki/kubernetes-ca.pem
server: https://$master_ip:6443
name: kubernetes
users:
- name: system:kube-controller-manager
user:
client-certificate: /etc/kubernetes/pki/controller-manager.pem
client-key: /etc/kubernetes/pki/controller-manager-key.pem
contexts:
- context:
cluster: kubernetes
user: system:kube-controller-manager
name: system:kube-controller-manager
current-context: system:kube-controller-manager
EOF
systemctl daemon-reload
systemctl enable --now kube-controller-manager
}
function start_kubelet() {
mkdir -p /var/lib/kubelet
cat >/var/lib/kubelet/config.yaml <<'EOF'
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cgroupDriver: systemd
clusterDNS:
- 10.96.0.10
clusterDomain: cluster.local
containerRuntimeEndpoint: unix:///var/run/containerd/containerd.sock
authentication:
anonymous:
enabled: false
webhook:
enabled: true
cacheTTL: 2m
x509:
clientCAFile: /etc/kubernetes/pki/kubernetes-ca.pem
authorization:
mode: Webhook
webhook:
cacheAuthorizedTTL: 5m
cacheUnauthorizedTTL: 30s
EOF
cat >/etc/kubernetes/kubelet.conf <<EOF
apiVersion: v1
kind: Config
clusters:
- cluster:
certificate-authority: /etc/kubernetes/pki/kubernetes-ca.pem
server: https://$master_ip:6443
name: kubernetes
users:
- name: system:node:master
user:
client-certificate: /etc/kubernetes/pki/kubelet.pem
client-key: /etc/kubernetes/pki/kubelet-key.pem
contexts:
- context:
cluster: kubernetes
user: system:node:master
name: default
current-context: default
EOF
cat >/etc/systemd/system/kubelet.service <<'EOF'
[Unit]
Description=Kubernetes Kubelet
Documentation=https://kubernetes.io/docs/home/
After=containerd.service
[Service]
ExecStart=/usr/local/bin/kubelet \
--config=/var/lib/kubelet/config.yaml \
--kubeconfig=/etc/kubernetes/kubelet.conf \
--hostname-override=master \
--v=2
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now kubelet
}
function start_kube_proxy() {
cat >/etc/kubernetes/kube-proxy.conf <<EOF
apiVersion: v1
kind: Config
clusters:
- cluster:
certificate-authority: /etc/kubernetes/pki/kubernetes-ca.pem
server: https://$master_ip:6443
name: kubernetes
users:
- name: system:kube-proxy
user:
client-certificate: /etc/kubernetes/pki/kube-proxy.pem
client-key: /etc/kubernetes/pki/kube-proxy-key.pem
contexts:
- context:
cluster: kubernetes
user: system:kube-proxy
name: default
current-context: default
EOF
cat >/etc/systemd/system/kube-proxy.service <<'EOF'
[Unit]
Description=Kubernetes Kube Proxy
Documentation=https://kubernetes.io/docs/home/
After=network.target
[Service]
ExecStart=/usr/local/bin/kube-proxy \
--kubeconfig=/etc/kubernetes/kube-proxy.conf \
--v=2
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now kube-proxy
}
function config_kubectl() {
mkdir -p $HOME/.kube
cat >$HOME/.kube/config <<EOF
apiVersion: v1
kind: Config
clusters:
- cluster:
certificate-authority: /etc/kubernetes/pki/kubernetes-ca.pem
server: https://192.168.60.128:6443
name: kubernetes
users:
- name: admin
user:
client-certificate: /etc/kubernetes/pki/admin.pem
client-key: /etc/kubernetes/pki/admin-key.pem
contexts:
- context:
cluster: kubernetes
user: admin
name: kubernetes-admin
current-context: kubernetes-admin
EOF
}
function delete_taint() {
until kubectl get node master &>/dev/null; do sleep 2; done
kubectl taint nodes master node.kubernetes.io/not-ready:NoSchedule-
}
function main() {
install_k8s_binaries
gencert_k8s_certs
start_apiserver
start_scheduler
start_controller_manager
start_kubelet
start_kube_proxy
config_kubectl
delete_taint
echo "k8s安装完成"
}
main "$@"scripts/k8s/uninstall.sh
bash
#! /bin/bash
services=(
"kube-apiserver"
"kube-controller-manager"
"kube-scheduler"
"kubelet"
"kube-proxy"
)
function stop_services() {
for svc in "${services[@]}"; do
systemctl disable --now "$svc" 2>/dev/null
done
}
function remove_k8s_config() {
# kubectl 配置
rm -rf $HOME/.kube
# kube-proxy
rm -rf /etc/systemd/system/kube-proxy.service
rm -rf /etc/kubernetes/kube-proxy.conf
# kubelet
rm -rf /etc/systemd/system/kubelet.service
rm -rf /etc/kubernetes/kubelet.conf
rm -rf /var/lib/kubelet
# controller-manager
rm -rf /etc/kubernetes/controller-manager.conf
rm -rf /etc/systemd/system/kube-controller-manager.service
# scheduler
rm -rf /etc/kubernetes/scheduler.conf
rm -rf /etc/systemd/system/kube-scheduler.service
# apiserver
rm -rf /etc/systemd/system/kube-apiserver.service
# pki 证书
rm -rf /etc/kubernetes/pki
# 删除自动生成的目录
rm -rf /var/log/kubernetes
rm -rf /run/kubernetes
systemctl daemon-reload
}
function remove_k8s_binaries() {
rm -rf /usr/local/bin/kube*
}
function main() {
stop_services
remove_k8s_config
remove_k8s_binaries
echo "Kubernetes 卸载完成"
}
main "$@"Calico
scripts/calico/calico.yaml
bash
kubectl apply -f calico.yamlCalico 网络插件清单文件位于 scripts/calico/calico.yaml,可直接应用部署。
CoreDNS
scripts/coredns/install.sh
bash
#!/bin/bash
set -e
function coredns_install() {
cat >coredns.yaml <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
name: coredns
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
kubernetes.io/bootstrapping: rbac-defaults
name: system:coredns
rules:
- apiGroups:
- ""
resources:
- endpoints
- services
- pods
- namespaces
verbs:
- list
- watch
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
- list
- watch
- apiGroups:
- "discovery.k8s.io"
resources:
- endpointslices
verbs:
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
annotations:
rbac.authorization.k8s.io/autoupdate: "true"
labels:
kubernetes.io/bootstrapping: rbac-defaults
name: system:coredns
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:coredns
subjects:
- kind: ServiceAccount
name: coredns
namespace: kube-system
---
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
data:
Corefile: |
.:53 {
errors
health {
lameduck 5s
}
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
}
prometheus :9153
forward . 8.8.8.8 8.8.4.4
cache 30
loop
reload
loadbalance
}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: coredns
namespace: kube-system
labels:
k8s-app: kube-dns
spec:
replicas: 1
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
selector:
matchLabels:
k8s-app: kube-dns
template:
metadata:
labels:
k8s-app: kube-dns
spec:
priorityClassName: system-cluster-critical
serviceAccountName: coredns
tolerations:
- key: "CriticalAddonsOnly"
operator: "Exists"
nodeSelector:
kubernetes.io/os: linux
containers:
- name: coredns
image: coredns/coredns:1.11.3
imagePullPolicy: IfNotPresent
resources:
limits:
memory: 170Mi
requests:
cpu: 100m
memory: 70Mi
args: [ "-conf", "/etc/coredns/Corefile" ]
volumeMounts:
- name: config-volume
mountPath: /etc/coredns
readOnly: true
ports:
- containerPort: 53
name: dns
protocol: UDP
- containerPort: 53
name: dns-tcp
protocol: TCP
- containerPort: 9153
name: metrics
protocol: TCP
livenessProbe:
httpGet:
path: /health
port: 8080
scheme: HTTP
initialDelaySeconds: 60
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 5
readinessProbe:
httpGet:
path: /ready
port: 8181
scheme: HTTP
initialDelaySeconds: 10
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 3
securityContext:
allowPrivilegeEscalation: false
capabilities:
add:
- NET_BIND_SERVICE
drop:
- ALL
readOnlyRootFilesystem: true
dnsPolicy: Default
volumes:
- name: config-volume
configMap:
name: coredns
---
apiVersion: v1
kind: Service
metadata:
name: kube-dns
namespace: kube-system
annotations:
prometheus.io/port: "9153"
prometheus.io/scrape: "true"
labels:
k8s-app: kube-dns
kubernetes.io/cluster-service: "true"
kubernetes.io/name: "CoreDNS"
spec:
selector:
k8s-app: kube-dns
clusterIP: 10.96.0.10
ports:
- name: dns
port: 53
protocol: UDP
- name: dns-tcp
port: 53
protocol: TCP
- name: metrics
port: 9153
protocol: TCP
EOF
kubectl apply -f coredns.yaml
echo "CoreDNS 部署完成,等待 Pod 就绪..."
kubectl rollout status deployment/coredns -n kube-system --timeout=120s
echo "CoreDNS 已就绪"
}
function main() {
coredns_install
}
main "$@"scripts/coredns/uninstall.sh
bash
#! /bin/bash
# curl -x http://192.168.60.1:12450 -o coredns.yaml -L https://raw.githubusercontent.com/coredns/deployment/refs/heads/master/kubernetes/coredns.yaml.sed
function coredns_uninstall() {
kubectl delete -f coredns.yaml --ignore-not-found=true
rm -rf coredns.yaml
}
function main() {
coredns_uninstall
}
main "$@"