目录

Kubernetes 二进制部署:从零搭建单 Master 集群

使用 kubeadm 部署 Kubernetes 集群很方便,但它隐藏了底层细节。通过二进制方式手动部署,可以深入理解每个组件的作用和协作方式。

本文在 etcd 集群 已部署的基础上,搭建单 Master 节点的 Kubernetes 集群。

架构概览

单 Master 架构中,Master 节点运行控制平面组件,Worker 节点运行工作负载:

https://blog-img-1259526442.cos.ap-nanjing.myqcloud.com/20250523101735908.png

核心组件

组件 运行位置 作用
kube-apiserver Master 集群入口,所有操作的统一接口
etcd Master 分布式键值存储,保存集群状态
kube-controller-manager Master 控制循环,确保实际状态匹配期望状态
kube-scheduler Master 将 Pod 调度到合适的 Node
kubelet Worker 管理 Pod 生命周期,汇报节点状态
kube-proxy Worker 实现 Service 网络代理和负载均衡

组件协作流程

kubectl create deployment nginx --image=nginx
  kube-apiserver ──→ etcd(存储期望状态)
  controller-manager(创建 ReplicaSet → 创建 Pod)
  scheduler(选定 Node,写入 Pod.Spec.NodeName)
  kubelet(watch 到分配给自己的 Pod,拉起容器)
  kube-proxy(配置 iptables/IPVS 规则,实现 Service 访问)

前置条件

条件 说明
etcd 集群 已部署,参考 etcd 集群部署
操作系统 Linux(本文以 Ubuntu 为例)
容器运行时 containerd 或 Docker 已安装,参考 Docker 入门
网络 节点间互通,关闭 swap

关闭 swap

Kubernetes 默认要求关闭 swap:

sudo swapoff -a
# 永久关闭:注释 /etc/fstab 中的 swap 行
sudo sed -i '/ swap / s/^/#/' /etc/fstab

下载二进制文件

从 Kubernetes GitHub Releases 下载:

# 设置版本
KUBE_VERSION="v1.33.0"
ARCH="amd64"

# 下载 Server 二进制(Master 节点需要)
wget "https://dl.k8s.io/${KUBE_VERSION}/kubernetes-server-linux-${ARCH}.tar.gz"
tar -xf kubernetes-server-linux-${ARCH}.tar.gz

# 复制到系统路径
sudo cp kubernetes/server/bin/kube-apiserver /usr/local/bin/
sudo cp kubernetes/server/bin/kube-controller-manager /usr/local/bin/
sudo cp kubernetes/server/bin/kube-scheduler /usr/local/bin/
sudo cp kubernetes/server/bin/kubectl /usr/local/bin/

# Worker 节点需要的二进制
sudo cp kubernetes/server/bin/kubelet /usr/local/bin/
sudo cp kubernetes/server/bin/kube-proxy /usr/local/bin/

也可以单独下载 Node 二进制:

https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.33.md#node-binaries

部署 Master 组件

生成集群证书

Kubernetes 各组件之间通过 TLS 加密通信,需要生成证书:

# 安装 cfssl 工具
wget https://github.com/cloudflare/cfssl/releases/download/v1.6.5/cfssl_1.6.5_linux_amd64
wget https://github.com/cloudflare/cfssl/releases/download/v1.6.5/cfssljson_1.6.5_linux_amd64
chmod +x cfssl_* && sudo mv cfssl_* /usr/local/bin/

# 创建 CA 证书
mkdir -p /etc/kubernetes/pki && cd /etc/kubernetes/pki

cat > ca-config.json <<EOF
{
  "signing": {
    "default": { "expiry": "87600h" },
    "profiles": {
      "kubernetes": {
        "usages": ["signing", "key encipherment", "server auth", "client auth"],
        "expiry": "87600h"
      }
    }
  }
}
EOF

cat > ca-csr.json <<EOF
{
  "CN": "kubernetes-ca",
  "key": { "algo": "rsa", "size": 2048 },
  "names": [{ "C": "CN", "ST": "Beijing", "L": "Beijing", "O": "k8s", "OU": "system" }]
}
EOF

cfssl gencert -initca ca-csr.json | cfssljson -bare ca

生成 apiserver 证书:

cat > apiserver-csr.json <<EOF
{
  "CN": "kube-apiserver",
  "key": { "algo": "rsa", "size": 2048 },
  "names": [{ "C": "CN", "ST": "Beijing", "L": "Beijing", "O": "k8s", "OU": "system" }],
  "hosts": [
    "127.0.0.1",
    "10.96.0.1",
    "kubernetes",
    "kubernetes.default",
    "kubernetes.default.svc",
    "kubernetes.default.svc.cluster.local",
    "MASTER_IP",
    "MASTER_PUBLIC_IP"
  ]
}
EOF

cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json \
  -profile=kubernetes apiserver-csr.json | cfssljson -bare apiserver

MASTER_IPMASTER_PUBLIC_IP 替换为实际的内网和公网 IP。

部署 kube-apiserver

创建 systemd 服务文件:

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=MASTER_IP \\
  --bind-address=0.0.0.0 \\
  --secure-port=6443 \\
  --etcd-servers=https://ETCD_IP1:2379,https://ETCD_IP2:2379,https://ETCD_IP3:2379 \\
  --etcd-cafile=/etc/kubernetes/pki/ca.pem \\
  --etcd-certfile=/etc/kubernetes/pki/apiserver.pem \\
  --etcd-keyfile=/etc/kubernetes/pki/apiserver-key.pem \\
  --tls-cert-file=/etc/kubernetes/pki/apiserver.pem \\
  --tls-private-key-file=/etc/kubernetes/pki/apiserver-key.pem \\
  --client-ca-file=/etc/kubernetes/pki/ca.pem \\
  --service-cluster-ip-range=10.96.0.0/12 \\
  --service-node-port-range=30000-32767 \\
  --allow-privileged=true \\
  --enable-bootstrap-token-auth \\
  --authorization-mode=Node,RBAC \\
  --v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

关键参数说明:

参数 作用
--etcd-servers etcd 集群地址
--service-cluster-ip-range Service ClusterIP 地址范围
--authorization-mode 授权模式,RBAC 是标准选择
--enable-bootstrap-token-auth 启用 Bootstrap Token 认证(用于节点自动注册)

启动并验证:

sudo systemctl daemon-reload
sudo systemctl enable --now kube-apiserver

# 验证
curl -k https://127.0.0.1:6443/healthz

部署 kube-controller-manager

cat > /etc/systemd/system/kube-controller-manager.service <<EOF
[Unit]
Description=Kubernetes Controller Manager
After=kube-apiserver.service

[Service]
ExecStart=/usr/local/bin/kube-controller-manager \\
  --master=https://127.0.0.1:6443 \\
  --kubeconfig=/etc/kubernetes/controller-manager.kubeconfig \\
  --cluster-cidr=10.244.0.0/16 \\
  --service-cluster-ip-range=10.96.0.0/12 \\
  --cluster-signing-cert-file=/etc/kubernetes/pki/ca.pem \\
  --cluster-signing-key-file=/etc/kubernetes/pki/ca-key.pem \\
  --root-ca-file=/etc/kubernetes/pki/ca.pem \\
  --service-account-private-key-file=/etc/kubernetes/pki/ca-key.pem \\
  --allocate-node-cidrs=true \\
  --v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now kube-controller-manager

部署 kube-scheduler

cat > /etc/systemd/system/kube-scheduler.service <<EOF
[Unit]
Description=Kubernetes Scheduler
After=kube-apiserver.service

[Service]
ExecStart=/usr/local/bin/kube-scheduler \\
  --master=https://127.0.0.1:6443 \\
  --kubeconfig=/etc/kubernetes/scheduler.kubeconfig \\
  --v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now kube-scheduler

验证 Master 组件

# 查看组件状态
kubectl --kubeconfig=/etc/kubernetes/admin.kubeconfig get cs

# 预期输出
# NAME                 STATUS    MESSAGE   ERROR
# controller-manager   Healthy   ok
# scheduler            Healthy   ok
# etcd-0               Healthy   ok

部署 Worker 组件

以下步骤在每个 Worker 节点上执行。

部署 kubelet

# 创建 kubelet 配置
cat > /etc/kubernetes/kubelet-config.yaml <<EOF
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
authentication:
  anonymous:
    enabled: false
  webhook:
    enabled: true
  x509:
    clientCAFile: /etc/kubernetes/pki/ca.pem
authorization:
  mode: Webhook
clusterDomain: cluster.local
clusterDNS:
  - 10.96.0.10
resolvConf: /run/systemd/resolve/resolv.conf
runtimeRequestTimeout: "15m"
EOF

# 创建 systemd 服务
cat > /etc/systemd/system/kubelet.service <<EOF
[Unit]
Description=Kubernetes Kubelet
After=containerd.service
Requires=containerd.service

[Service]
ExecStart=/usr/local/bin/kubelet \\
  --config=/etc/kubernetes/kubelet-config.yaml \\
  --kubeconfig=/etc/kubernetes/kubelet.kubeconfig \\
  --bootstrap-kubeconfig=/etc/kubernetes/bootstrap.kubeconfig \\
  --container-runtime-endpoint=unix:///run/containerd/containerd.sock \\
  --pod-infra-container-image=registry.k8s.io/pause:3.10 \\
  --v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now kubelet

部署 kube-proxy

# 创建 kube-proxy 配置
cat > /etc/kubernetes/kube-proxy-config.yaml <<EOF
kind: KubeProxyConfiguration
apiVersion: kubeproxy.config.k8s.io/v1alpha1
clientConnection:
  kubeconfig: /etc/kubernetes/kube-proxy.kubeconfig
mode: ipvs
clusterCIDR: 10.244.0.0/16
EOF

# 创建 systemd 服务
cat > /etc/systemd/system/kube-proxy.service <<EOF
[Unit]
Description=Kubernetes Kube Proxy
After=network.target

[Service]
ExecStart=/usr/local/bin/kube-proxy \\
  --config=/etc/kubernetes/kube-proxy-config.yaml \\
  --v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now kube-proxy

验证集群

检查节点状态

kubectl get nodes

# 预期输出(节点需几分钟变为 Ready)
# NAME         STATUS   ROLES           AGE   VERSION
# master-01    Ready    control-plane   5m    v1.33.0
# worker-01    Ready    <none>          3m    v1.33.0
# worker-02    Ready    <none>          3m    v1.33.0

部署 CNI 网络插件

节点处于 NotReady 状态通常是因为没有安装 CNI。以 Calico 为例:

kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.29.3/manifests/calico.yaml

部署 CoreDNS

CoreDNS 提供集群内 DNS 解析:

# 下载 CoreDNS 部署清单
wget https://raw.githubusercontent.com/kubernetes/kubernetes/v1.33.0/cluster/addons/dns/coredns/coredns.yaml.sed
mv coredns.yaml.sed coredns.yaml

# 替换变量
sed -i 's/__DNS__DOMAIN__/cluster.local/g' coredns.yaml
sed -i 's/__DNS__SERVER__IP__/10.96.0.10/g' coredns.yaml

kubectl apply -f coredns.yaml

验证集群功能

# 创建测试 Pod
kubectl run nginx --image=nginx --port=80

# 检查 Pod 状态
kubectl get pods -o wide

# 创建 Service
kubectl expose pod nginx --port=80 --type=NodePort

# 访问测试
curl $(kubectl get svc nginx -o jsonpath='{.spec.ports[0].nodePort}')

证书与配置文件汇总

文件 用途
ca.pem / ca-key.pem CA 根证书和私钥
apiserver.pem / apiserver-key.pem API Server TLS 证书
admin.kubeconfig 管理员 kubectl 配置
controller-manager.kubeconfig Controller Manager 连接 API Server
scheduler.kubeconfig Scheduler 连接 API Server
kubelet.kubeconfig Kubelet 连接 API Server
kube-proxy.kubeconfig Kube Proxy 连接 API Server
bootstrap.kubeconfig 节点自动注册 Bootstrap Token

排错指南

现象 排查方向
kubectl 连接超时 检查 apiserver 端口 6443 是否监听,防火墙是否放通
节点 NotReady journalctl -u kubelet 查看日志,检查 CNI 插件是否安装
Pod Pending kubectl describe pod <name> 查看调度失败原因
Service 无法访问 检查 kube-proxy 是否运行,ipvsadm -Ln 查看规则
证书错误 检查证书 hosts 是否包含实际 IP,证书是否过期

生产环境建议

二进制部署适合学习和理解架构,生产环境建议:

  • kubeadm:官方推荐的集群部署工具
  • 托管服务:阿里云 ACK、腾讯云 TKE、AWS EKS 等
  • 高可用:多 Master + 外部 etcd + 负载均衡器