前言
在本地虛擬機環境中使用 kubeadm 搭建 Kubernetes 集羣是學習和實驗的理想選擇。考慮到實際應用場景中可能存在的網絡限制以及鏡像構建需求,本文詳細記錄了在完全離線環境下部署單節點 Kubernetes 集羣的完整過程。通過集成 Harbor 私有鏡像倉庫,所有 Kubernetes 組件鏡像均從本地 Harbor 實例拉取,確保部署過程的可靠性和可重複性。
本指南適用於希望在受限網絡環境中快速搭建 Kubernetes 實驗環境的技術人員,涵蓋了從系統初始化到 Cilium 網絡插件配置的全流程。
環境和版本信息
基礎環境配置
- 操作系統:Debian 13 (代號 "Trixie")
- 硬件規格:4 核 CPU / 4GB 內存 / 40GB 存儲空間
- 網絡拓撲:單節點部署(Control Plane + Worker 合一)
軟件版本清單
| 組件 | 版本 | 説明 |
|---|---|---|
| Kubernetes | v1.33.7 | 容器編排平台 |
| containerd | 2.2.1 | 容器運行時 |
| runc | 1.4.0 | OCI 運行時規範實現 |
| CNI Plugins | 1.9.0 | 容器網絡接口插件 |
| Harbor | v2.14.2 | 企業級容器鏡像倉庫 |
| Cilium | v1.18.6 | eBPF 驅動的網絡和安全解決方案 |
| Helm | 3.19.5 | Kubernetes 包管理器 |
網絡規劃
| IP 地址 | 主機名 | 角色 |
|---|---|---|
| 192.168.0.22 | deb13-k8s-node1 | Kubernetes 節點 |
| 192.168.0.42 | deb13-harbor | Harbor 鏡像倉庫 |
注意:本文檔假設兩台主機位於同一內網環境中,且網絡連通性已驗證。
系統初始化
在開始 Kubernetes 組件安裝之前,需要對系統進行必要的初始化配置,以滿足 Kubernetes 的運行要求。
1. 安裝 IPVS 相關工具包
IPVS(IP Virtual Server)是 Linux 內核的負載均衡實現,Kubernetes 在 IPVS 模式下運行 kube-proxy 時需要相關工具支持。
# 僅在 Kubernetes 節點執行
sudo apt update
sudo apt install -y ipvsadm ipset
2. 配置主機名
為便於管理和識別,建議為每台主機設置有意義的主機名。
# Harbor 服務器
hostnamectl set-hostname deb13-harbor
# Kubernetes 節點
hostnamectl set-hostname deb13-k8s-node1
3. 配置本地 DNS 解析
編輯 /etc/hosts 文件,添加主機名與 IP 地址的映射關係:
cat >> /etc/hosts << EOF
192.168.0.22 deb13-k8s-node1
192.168.0.42 deb13-harbor
EOF
4. 加載必要的內核模塊
Kubernetes 依賴特定的內核模塊來支持容器網絡功能。創建模塊加載配置並立即生效:
# 創建模塊加載配置文件
cat << EOF > /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF
# 立即加載模塊
sudo modprobe overlay
sudo modprobe br_netfilter
# 驗證模塊加載狀態
lsmod | grep -E "(overlay|br_netfilter)"
5. 配置系統內核參數
調整內核參數以優化容器運行環境:
cat > /etc/sysctl.d/k8s.conf << EOF
net.ipv4.ip_forward=1
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
vm.swappiness = 0
EOF
# 應用配置
sudo sysctl --system
重要提示:如果系統啓用了 swap 分區,必須在 Kubernetes 啓動前將其關閉,否則 kubelet 將無法正常啓動。可通過以下命令臨時關閉:
sudo swapoff -a
# 永久關閉需註釋 /etc/fstab 中的 swap 相關行
Harbor 私有鏡像倉庫部署
Harbor 作為企業級容器鏡像倉庫,為離線環境下的 Kubernetes 部署提供了可靠的鏡像分發能力。
1. 準備 Harbor 安裝包
從 Harbor GitHub Releases 頁面下載離線安裝包(約 600MB)。安裝 Harbor 前需確保 Docker 和 Docker Compose 已正確安裝。
2. 生成自簽名 TLS 證書
由於 Harbor 強制要求 HTTPS 連接,我們需要為 Harbor 服務器生成自簽名證書。創建證書生成腳本:
# 創建證書目錄
mkdir -p ~/apps/harbor/certs
cd ~/apps/harbor/certs
# 創建證書生成腳本
cat > gen-harbor-crt.sh << 'EOF'
#!/bin/bash
# --- 配置參數 ---
DOMAIN="deb13-harbor" # Harbor 域名
IP="192.168.0.42" # Harbor 服務器內網 IP
DAYS=3650 # 有效期 10 年
# 1. 生成私鑰 (無密碼)
openssl genrsa -out harbor.key 2048
# 2. 創建 OpenSSL 配置文件以包含 SAN
cat > harbor.conf << CONF_EOF
[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no
[req_distinguished_name]
CN = ${DOMAIN}
[v3_req]
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = ${DOMAIN}
IP.1 = ${IP}
CONF_EOF
# 3. 生成自簽名證書
openssl req -x509 -nodes -days ${DAYS} -key harbor.key -out harbor.crt -config harbor.conf -extensions v3_req
# 4. 驗證證書(查看是否有 Subject Alternative Name 字段)
echo "--------------------------------------------------"
echo "證書信息驗證:"
openssl x509 -in harbor.crt -text -noout | grep -A 1 "Subject Alternative Name"
echo "--------------------------------------------------"
echo "生成成功!"
echo "服務端使用: harbor.crt, harbor.key"
echo "客户端 (K8s 節點) 使用: harbor.crt"
EOF
# 執行證書生成
chmod +x gen-harbor-crt.sh
./gen-harbor-crt.sh
3. 配置 Harbor
從模板文件複製並修改 Harbor 配置:
# 複製配置模板
cp harbor.yml.tmpl harbor.yml
# 修改關鍵配置項
主要配置項如下:
# Harbor 訪問地址
hostname: 192.168.0.42
# HTTPS 配置
https:
port: 443
certificate: /home/rainux/apps/harbor/certs/harbor.crt
private_key: /home/rainux/apps/harbor/certs/harbor.key
# 管理員密碼(請設置強密碼)
harbor_admin_password: your-harbor-password
# 數據庫密碼
database:
password: your-db-password
# 數據存儲路徑
data_volume: /home/rainux/apps/harbor/data
# 日誌配置
log:
location: /home/rainux/apps/harbor/logs
# 啓用指標監控
metric:
enabled: true
port: 9090
path: /metrics
4. 啓動 Harbor 服務
cd ~/apps/harbor
sudo ./install.sh
5. 初始化 Harbor 項目
通過 Web 界面訪問 Harbor(https://192.168.0.42),使用配置的管理員密碼登錄後,創建以下兩個公開項目:
google_containers:用於存儲 Kubernetes 核心組件鏡像cilium:用於存儲 Cilium 網絡插件相關鏡像
配置更新説明:如需修改 Harbor 配置,可執行以下命令使配置生效:
sudo ./prepare docker-compose down -v sudo docker-compose up -d
Containerd 容器運行時配置
Containerd 作為輕量級容器運行時,是 Kubernetes 推薦的運行時選項之一。
1. 下載必要組件
從官方 GitHub 倉庫下載以下組件:
- containerd
- runc
- CNI Plugins
2. 安裝 runc
# 注意:原文中的文件名可能存在筆誤,應為 runc.amd64
chmod +x runc.amd64
sudo mv runc.amd64 /usr/local/bin/runc
3. 安裝 CNI 插件
sudo mkdir -p /opt/cni/bin/
sudo tar xf cni-plugins-linux-amd64-v1.9.0.tgz -C /opt/cni/bin/
4. 安裝 containerd
sudo tar xf containerd-2.2.1-linux-amd64.tar.gz
sudo mv bin/* /usr/local/bin/
5. 配置 containerd
生成默認配置並進行必要的修改:
# 創建 Harbor 證書目錄
sudo mkdir -p /etc/containerd/certs.d/192.168.0.42/
# 生成默認配置
sudo containerd config default > /etc/containerd/config.toml
# 複製 Harbor 證書
sudo cp ~/apps/harbor/certs/harbor.crt /etc/containerd/certs.d/192.168.0.42/ca.crt
關鍵配置修改:
# 設置 Pod 沙箱鏡像源
[plugins.'io.containerd.cri.v1.images'.pinned_images]
sandbox = '192.168.0.42/google_containers/pause:3.10'
# 配置私有鏡像倉庫
[plugins.'io.containerd.cri.v1.images'.registry]
config_path = '/etc/containerd/certs.d'
# 啓用 systemd cgroup 驅動
[plugins.'io.containerd.cri.v1.runtime'.containerd.runtimes.runc.options]
SystemdCgroup = true
6. 配置 systemd 服務
從 官方倉庫 獲取 service 文件:
sudo curl -o /usr/lib/systemd/system/containerd.service https://raw.githubusercontent.com/containerd/containerd/main/containerd.service
7. 啓動 containerd 服務
sudo systemctl daemon-reload
sudo systemctl enable --now containerd
Kubernetes 組件部署
1. 安裝 Kubernetes 二進制文件
從 Kubernetes GitHub Releases 下載 kubernetes-server-linux-amd64.tar.gz,提取核心組件:
# 解壓並安裝核心組件
tar xf kubernetes-server-linux-amd64.tar.gz
sudo cp kubernetes/server/bin/{kubeadm,kubelet,kubectl} /usr/local/bin/
# 驗證所需鏡像列表
kubeadm config images list --kubernetes-version v1.33.7
將列出的所有鏡像(包括 pause、coredns、etcd 等)從官方源拉取後重新打標籤並推送到 Harbor 的 google_containers 項目中。
2. 配置 kubelet systemd 服務
創建主服務文件 /usr/lib/systemd/system/kubelet.service:
[Unit]
Description=kubelet: The Kubernetes Node Agent
Documentation=https://kubernetes.io/docs/
Wants=network-online.target
After=network-online.target
[Service]
ExecStart=/usr/local/bin/kubelet
Restart=always
StartLimitInterval=0
RestartSec=10
[Install]
WantedBy=multi-user.target
3. 創建 kubeadm 配置目錄
sudo mkdir -p /usr/lib/systemd/system/kubelet.service.d/
4. 配置 kubeadm drop-in 文件
創建 /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf:
# Note: This dropin only works with kubeadm and kubelet v1.11+
[Service]
Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf"
Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml"
# This is a file that "kubeadm init" and "kubeadm join" generates at runtime, populating the KUBELET_KUBEADM_ARGS variable dynamically
EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env
# This is a file that the user can use for overrides of the kubelet args as a last resort. Preferably, the user should use
# the .NodeRegistration.KubeletExtraArgs object in the configuration files instead. KUBELET_EXTRA_ARGS should be sourced from this file.
EnvironmentFile=-/etc/sysconfig/kubelet
ExecStart=
ExecStart=/usr/local/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS
5. 啓動 kubelet 服務
sudo systemctl daemon-reload
sudo systemctl enable --now kubelet
集羣初始化
1. 創建 kubeadm 配置文件
創建 kubeadm-config.yaml 配置文件:
apiVersion: kubeadm.k8s.io/v1beta4
kind: ClusterConfiguration
kubernetesVersion: v1.33.7
imageRepository: 192.168.0.42/google_containers # 指向本地 Harbor 倉庫
networking:
podSubnet: "10.10.0.0/16" # Cilium 默認 Pod 網段
serviceSubnet: "10.96.0.0/12"
---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cgroupDriver: systemd
imageGCHighThresholdPercent: 70 # 磁盤使用率超過 70% 時開始清理鏡像
imageGCLowThresholdPercent: 60 # 清理至磁盤使用率 60% 時停止
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs" # 雖然後續會使用 Cilium 替代 kube-proxy,但初始化階段仍需配置
2. 執行集羣初始化
sudo kubeadm init --config kubeadm-config.yaml --ignore-preflight-errors=ImagePull
3. 清理 kube-proxy(使用 Cilium 替代)
由於我們將使用 Cilium 作為網絡解決方案,可以移除 kube-proxy:
# 刪除 kube-proxy DaemonSet
kubectl delete ds kube-proxy -n kube-system
# 在所有節點清理 iptables 規則殘留
sudo kube-proxy --cleanup
4. 驗證初始化狀態
初始化完成後,配置 kubectl 並檢查集羣狀態:
# 配置 kubectl
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
# 檢查節點狀態(此時應顯示 NotReady,因為 CNI 尚未安裝)
kubectl get nodes
kubectl get namespaces
Cilium 網絡插件部署
Cilium 基於 eBPF 技術提供高性能的網絡、安全和可觀測性功能。
1. 安裝 cilium-cli
從 Cilium CLI Releases 下載並安裝命令行工具。
2. 準備 Cilium 鏡像
將 Cilium 所需的鏡像推送到 Harbor 倉庫:
#!/bin/bash
set -euo pipefail
images=(
cilium/cilium:v1.18.6
cilium/hubble-relay:v1.18.6
cilium/hubble-ui-backend:v0.13.3
cilium/hubble-ui:v0.13.3
cilium/cilium-envoy:v1.35.9-1767794330-db497dd19e346b39d81d7b5c0dedf6c812bcc5c9
cilium/certgen:v0.3.1
cilium/startup-script:1755531540-60ee83e
)
src_registry="quay.io"
target_registry="192.168.0.42"
for image in "${images[@]}"; do
echo "Processing image: ${image}"
docker pull "${src_registry}/${image}"
docker tag "${src_registry}/${image}" "${target_registry}/${image}"
docker push "${target_registry}/${image}"
done
3. 獲取 Helm Chart
helm repo add cilium https://helm.cilium.io/
helm pull cilium/cilium --version 1.18.6
tar xf cilium-1.18.6.tgz
mv cilium cilium-chart
4. 配置 Chart Values
首先替換所有鏡像源地址:
sed -i 's#quay.io#192.168.0.42#g' ./cilium-chart/values.yaml
關鍵配置項調整:
# 啓用 kube-proxy 替代模式
kubeProxyReplacement: true
# 指定 Kubernetes API 服務器地址
k8sServiceHost: "192.168.0.22"
k8sServicePort: 6443
# 單節點部署,operator 副本數設為 1
operator:
replicas: 1
# 啓用 Hubble 可觀測性組件
hubble:
enabled: true
relay:
enabled: true
ui:
enabled: true
# 配置 IPAM CIDR 範圍
ipam:
operator:
clusterPoolIPv4PodCIDRList:
- "10.10.0.0/16"
鏡像 Digest 注意事項:通過 docker pull 再 push 的方式可能導致鏡像 digest 發生變化。如遇鏡像拉取失敗,可將
values.yaml中的useDigest設置為false。
5. 安裝 Cilium
# 執行安裝
cilium install --chart-directory ./cilium-chart
# 檢查安裝狀態
cilium status
# 移除 control-plane 污點以允許 Pod 調度
kubectl taint nodes --all node-role.kubernetes.io/control-plane-
6. 驗證集羣狀態
等待所有 Pod 正常運行後,驗證集羣就緒狀態:
# 檢查所有命名空間的 Pod 狀態
kubectl get pods -A
# 驗證節點狀態(應顯示 Ready)
kubectl get nodes
# 檢查 Cilium 組件狀態
cilium status --verbose
添加工作節點(擴展部署)
完成單節點集羣部署後,如需擴展為多節點集羣,可在新節點上執行以下步驟:
在新節點上需要先完成上面的系統初始化、Containerd配置、kube組件配置
1. 生成節點加入令牌
在 Control Plane 節點上生成 24 小時有效的加入令牌:
kubeadm token create --print-join-command
該命令將輸出類似以下格式的加入命令:
kubeadm join 192.168.0.22:6443 --token <token> --discovery-token-ca-cert-hash sha256:<hash>
2. 在新節點執行加入命令
在新節點上執行上述命令,並忽略鏡像預檢錯誤:
sudo kubeadm join 192.168.0.22:6443 \
--token <token> \
--discovery-token-ca-cert-hash sha256:<hash> \
--ignore-preflight-errors=ImagePull
3. 驗證節點加入狀態
# 檢查節點列表
kubectl get nodes
# 驗證 Cilium 狀態
cilium status
# 清理 iptables 規則(如已禁用 kube-proxy)
sudo iptables -F
Cilium 會自動在新節點上部署代理 Pod,確保網絡連通性。
私有鏡像倉庫認證配置
對於 Harbor 中非公開項目的鏡像拉取,需要配置相應的認證機制。
方式一:Pod 級別 imagePullSecrets(推薦)
適用於需要精細化控制鏡像拉取權限的場景。
1. 創建 Docker Registry Secret
kubectl create secret docker-registry harbor-pull-secret \
--docker-server=192.168.0.42 \
--docker-username=<your-username> \
--docker-password=<your-password> \
--docker-email=<your-email>
2. 在 Pod 定義中引用 Secret
apiVersion: v1
kind: Pod
spec:
containers:
- name: my-app
image: 192.168.0.42/private-project/my-image:v1
imagePullSecrets:
- name: harbor-pull-secret
方式二:ServiceAccount 綁定(便捷方案)
適用於命名空間內所有 Pod 都需要訪問私有鏡像倉庫的場景。
# 將 Secret 綁定到 default ServiceAccount
kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "harbor-pull-secret"}]}'
此配置將使該命名空間下所有新建的 Pod 自動繼承鏡像拉取權限。
方式三:Containerd 全局認證(實驗環境適用)
在 Containerd 層面配置全局認證,適用於個人實驗環境。
編輯 /etc/containerd/config.toml:
[plugins."io.containerd.grpc.v1.cri".registry.configs."192.168.0.42".auth]
username = "your-username"
password = "your-password"
# 或使用 base64 編碼的憑證:auth = "base64(username:password)"
安全提醒:方式三將憑據明文存儲在配置文件中,不建議在生產環境中使用。
補充
相較於使用二進制方式部署,用kubeadm起碼省去了手動維護證書的操作,後續添加節點也更簡單些。有空整個ansible讓添加節點更方便。