| Hostname | Role | IP Address | OS | 備註 |
|---|---|---|---|---|
| VIP | Load Balancer | 10.10.0.83 | HAProxy | API Server 統一入口 (Port 6444) |
doris-f01 |
Master | 10.10.0.85 |
Ubuntu 24.04 | 第一台初始節點 |
doris-f02 |
Master | 10.10.0.87 |
Ubuntu 24.04 | 後續加入的 Control Plane |
doris-f03 |
Master | 10.10.0.89 |
Ubuntu 24.04 | 後續加入的 Control Plane |
doris-b01 |
Worker | 10.10.0.93 |
Ubuntu 24.04 | 工作節點 |
doris-b02 |
Worker | 10.10.0.94 |
Ubuntu 24.04 | 工作節點 |
doris-b03 |
Worker | 10.10.0.95 |
Ubuntu 24.04 | 工作節點 |
doris-b04 |
Worker | 10.10.0.96 |
Ubuntu 24.04 | 工作節點 |
若已設定就跳過
hostnamectl set-hostname <hostname>
sudo swapoff -a
sudo sed -i '/swap/d' /etc/fstab
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables=1
net.ipv4.ip_forward=1
EOF
sudo sysctl --system
sudo apt update
sudo apt install -y containerd
sudo mkdir -p /etc/containerd
sudo containerd config default | sudo tee /etc/containerd/config.toml
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
sudo systemctl restart containerd
sudo systemctl enable containerd
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key | sudo apt-key add -
echo 'deb https://pkgs.k8s.io/core:/stable:/v1.30/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
apt-get upgrade 更新系統時,不小心自動升級了 K8s 元件。sudo apt-mark hold kubelet kubeadm kubectl
sudo systemctl enable kubelet
初始化整個cluster的第一台master
sudo vi /kubeadm-config.yaml
apiVersion: kubeadm.k8s.io/v1beta3
kind: ClusterConfiguration
# ==================== 1. 集群基本資訊 ====================
kubernetesVersion: v1.30.14 # 請確保與安裝的 kubeadm 版本一致
controlPlaneEndpoint: "10.10.0.83:6444" # VIP:HAProxy端口 (所有節點透過此溝通)
# ==================== 2. 網路設定 ====================
networking:
podSubnet: "10.244.0.0/16" # Pod 網段 (Flannel 預設)
serviceSubnet: "10.96.0.0/12" # Service 網段 (ClusterIP) default值
dnsDomain: cluster.local # default值
# ==================== 3. API Server 設定 ====================
apiServer:
certSANs: # 憑證需包含的所有 IP/域名
- "10.10.0.83" # VIP (最重要!)
- "10.10.0.85" # F01 IP
- "10.10.0.87" # F02 IP
- "10.10.0.89" # F03 IP
- "127.0.0.1"
extraArgs:
authorization-mode: "Node,RBAC" # default值
---
# ==================== 4. 本機初始化設定 ====================
apiVersion: kubeadm.k8s.io/v1beta3
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: "10.10.0.85" # **當前節點 (F01) 的 IP**
bindPort: 6443 # API Server 本機監聽 Port (default值)
nodeRegistration:
criSocket: unix:///var/run/containerd/containerd.sock # default值 建議保留
name: doris-f01 # 當前節點 Hostname 前面步驟已設定 保險起見這裡可以再設定一次
taints: # Master 污點 (不讓應用跑在 Master) default值
- effect: NoSchedule
key: node-role.kubernetes.io/control-plane
---
# ==================== 5. Kubelet 全域設定 ====================
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cgroupDriver: systemd # 關鍵!確保與 Containerd 一致 (default值 建議保留)
apiVersion: kubeadm.k8s.io/v1beta3
kind: ClusterConfiguration
# ==================== 基本信息 ====================
kubernetesVersion: v1.30.14 # K8s 版本,建議與 kubeadm 版本一致
# ==================== 控制平面 HA 配置 ====================
controlPlaneEndpoint: "10.10.0.83:6444" # VIP:HAProxy端口
# 所有節點將通過這個地址訪問 API Server
# 這是 HA 的關鍵配置
# ==================== 網路配置 ====================
networking:
podSubnet: "10.244.0.0/16" # Pod 網段,給 CNI 使用
# Calico/Flannel 會從這個範圍分配 Pod IP
# 不要與現有網路衝突!
serviceSubnet: "10.96.0.0/12" # Service 網段 (ClusterIP)
# K8s 內部服務的虛擬 IP 範圍
# 預設值,一般不需要改
# ==================== API Server 配置 ====================
apiServer:
certSANs: # 證書 Subject Alternative Names
- "10.10.0.83" # VIP - 必須加入!
- "10.10.0.85" # F01 IP
- "10.10.0.87" # F02 IP
- "10.10.0.89" # F03 IP
# - "k8s-api.yourdomain.com" # 如果有 DNS 也可以加
extraArgs: # API Server 額外參數
bind-address: "0.0.0.0" # 監聽所有 IP (預設是 0.0.0.0)
advertise-address: "10.10.0.85" # **重要**: 此節點對外宣告的 IP
# F01 用 .85, F02 用 .87, F03 用 .89
secure-port: "6443" # API Server 實際監聽端口
# 避免與 HAProxy 的 6443 衝突
# ==================== etcd 配置 ====================
#etcd:
# external: # 使用外部 etcd cluster
# endpoints: # etcd 節點列表
# - https://10.10.0.93:2379 # B01
# - https://10.10.0.94:2379 # B02
# - https://10.10.0.95:2379 # B03
#
# # etcd TLS 證書 - 需要預先準備
# caFile: /etc/kubernetes/pki/etcd/ca.crt # etcd CA 證書
# certFile: /etc/kubernetes/pki/etcd/client.crt # etcd 客戶端證書
# keyFile: /etc/kubernetes/pki/etcd/client.key # etcd 客戶端私鑰
---
# ==================== 初始化配置 (僅第一個 master 需要) ====================
apiVersion: kubeadm.k8s.io/v1beta3
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: "10.10.0.85" # **此節點的 IP** (F01)
bindPort: 6443 # API Server 監聽端口
nodeRegistration:
criSocket: unix:///var/run/containerd/containerd.sock # 容器運行時
name: doris-f01 # 節點名稱
taints: # 污點,防止 Pod 調度到 master
- effect: NoSchedule
key: node-role.kubernetes.io/control-plane
---
# ==================== Join 配置 (其他 master 加入時使用) ====================
apiVersion: kubeadm.k8s.io/v1beta3
kind: JoinConfiguration
discovery:
bootstrapToken:
apiServerEndpoint: "10.10.0.83:6444" # VIP 地址
token: <token> # 從 kubeadm init 輸出獲取
caCertHashes:
- "sha256:<hash>" # CA 證書 hash
controlPlane: # 標記為 control plane 節點
localAPIEndpoint:
advertiseAddress: "10.10.0.87" # **F02 的 IP** (F03 用 .89)
bindPort: 6443
certificateKey: <key> # 證書加密 key (kubeadm init 輸出)
nodeRegistration:
criSocket: unix:///var/run/containerd/containerd.sock
name: doris-f02 # 節點名稱
taints:
- effect: NoSchedule
key: node-role.kubernetes.io/control-plane
apiVersion: kubeadm.k8s.io/v1beta3
kind: ClusterConfiguration
# K8s 版本 (確保與 kubeadm 版本一致)
kubernetesVersion: v1.30.14
# 控制平面 HA 端點 (HAProxy VIP)
controlPlaneEndpoint: "10.10.0.83:6444"
# 網路配置
networking:
podSubnet: "10.244.0.0/16" # Pod 網段 (Calico 使用)
serviceSubnet: "10.96.0.0/12" # Service 網段
# API Server 配置
apiServer:
# 證書 SAN 列表 (所有可能訪問 API Server 的地址)
certSANs:
- "10.10.0.83" # VIP (必須!)
- "10.10.0.85" # F01
- "10.10.0.87" # F02
- "10.10.0.89" # F03
- "127.0.0.1" # localhost
- "kubernetes"
- "kubernetes.default"
- "kubernetes.default.svc"
- "kubernetes.default.svc.cluster.local"
extraArgs:
# API Server 監聽在所有網路介面
bind-address: "0.0.0.0"
# 此節點對外宣告的 IP (F01)
advertise-address: "10.10.0.85"
# API Server 實際監聽端口 (避免與 HAProxy 6443 衝突)
secure-port: "6443"
# 審計日誌 (可選,用於安全審計)
audit-log-path: /var/log/kubernetes/audit.log
audit-log-maxage: "30"
audit-log-maxbackup: "10"
audit-log-maxsize: "100"
# 使用外部 etcd cluster (B01-B03)
#etcd:
# external:
# endpoints:
# - https://10.10.0.93:2379 # B01
# - https://10.10.0.94:2379 # B02
# - https://10.10.0.95:2379 # B03
# # etcd TLS 證書路徑
# caFile: /etc/kubernetes/pki/etcd/ca.crt
# certFile: /etc/kubernetes/pki/etcd/client.crt
# keyFile: /etc/kubernetes/pki/etcd/client.key
# Controller Manager 配置
controllerManager:
extraArgs:
bind-address: "0.0.0.0"
# Node 心跳超時時間
node-monitor-grace-period: "40s"
# Pod 驅逐超時時間
pod-eviction-timeout: "5m0s"
# Scheduler 配置
scheduler:
extraArgs:
bind-address: "0.0.0.0"
# DNS 配置
dns:
imageRepository: registry.k8s.io/coredns
imageTag: v1.10.1
# 鏡像倉庫 (如果使用國內鏡像)
# imageRepository: registry.aliyuncs.com/google_containers
---
# 初始化配置 (僅第一個 master 需要)
apiVersion: kubeadm.k8s.io/v1beta3
kind: InitConfiguration
# 本地 API Server 端點配置
localAPIEndpoint:
advertiseAddress: "10.10.0.85" # F01 的 IP
bindPort: 6443 # 監聽端口
# 節點註冊配置
nodeRegistration:
criSocket: unix:///var/run/containerd/containerd.sock
name: doris-f01 # 節點名稱
# Master 節點污點 (防止普通 Pod 調度)
taints:
- effect: NoSchedule
key: node-role.kubernetes.io/control-plane
# 節點標籤
kubeletExtraArgs:
node-labels: "node-role.kubernetes.io/control-plane="
# Bootstrap Token 配置 (用於節點加入)
bootstrapTokens:
- groups:
- system:bootstrappers:kubeadm:default-node-token
ttl: 24h0m0s
usages:
- signing
- authentication
---
# Kubelet 配置
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
# 容器運行時
cgroupDriver: systemd
# 資源預留
systemReserved:
cpu: "500m"
memory: "1Gi"
ephemeral-storage: "1Gi"
kubeReserved:
cpu: "500m"
memory: "1Gi"
ephemeral-storage: "1Gi"
# 驅逐閾值
evictionHard:
memory.available: "200Mi"
nodefs.available: "10%"
imagefs.available: "15%"
# 日誌配置
logging:
format: json
# 序列化 image pulls (適合網路較慢的環境)
serializeImagePulls: false
maxParallelImagePulls: 3
# 建議先預拉映像檔,避免初始化超時
sudo kubeadm config images pull --config kubeadm-config.yaml
# 正式初始化
# --upload-certs:將憑證加密上傳,讓後續加入的 Master 節點能自動下載使用
sudo kubeadm init --config kubeadm-config.yaml --upload-certs
命令成功後會得到:
add master node 指令:
sudo kubeadm join 10.10.0.83:6444 --token <token> \
--discovery-token-ca-cert-hash sha256:<hash> \
--control-plane --certificate-key <key> \
--apiserver-advertise-address=<F02或F03的IP> \
--apiserver-bind-port=6443
add worker node:
sudo kubeadm join 10.10.0.83:6444 --token <token> \
--discovery-token-ca-cert-hash sha256:<hash>
目的: 將集群的管理員憑證 (admin.conf) 複製到使用者的預設目錄,讓 kubectl 能夠讀取並取得控制權限
kubectl 預設會去 ~/.kube/ 找設定檔kubeadm 產生的最高權限設定檔 (admin.conf) 複製過來kubaadmi init自動生成,裡面包含:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf ~/.kube/config
sudo chown $(id -u):$(id -g) ~/.kube/config
Kubernetes 本身不提供 Pod 之間的網路通訊功能,它只定義了介面 (CNI)。我們必須安裝網路插件來實現以下功能:
podSubnet (10.244.0.0/16),為每一個 Pod 分配唯一的 IP 地址。kubectl get nodes 會看到狀態為 NotReady。kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
檢查: 執行 kubectl get nodes,doris-f01 的狀態應該會從 NotReady 變成 Ready。
補充知識
同一台節點內: 其實不用 Flannel,Docker/Containerd 本身就能讓同一台節點上的容器互通(透過本機的 Bridge)。
跨節點: 這是困難點。當 Node A 的 Pod (IP 10.244.1.2) 想找 Node B 的 Pod (IP 10.244.2.3) 時,連線節點的路由器(無論是實體路由或 VM 的 vSwitch) 看不懂這些 10.244 的 Pod IP,它只認得 10.10 的節點 IP。
Flannel 的工作: 它負責把這些封包「包裝」起來(封裝),偽裝成節點對節點的流量,透過節點網路傳送到對面,再由對面的 Flannel「拆開」,交給目標 Pod。
在要加入 master 的機器執行 kubeadm 給的 kubeadm join:
sudo kubeadm join 10.10.0.83:6444 --token <token> \
--discovery-token-ca-cert-hash sha256:<hash> \
--control-plane --certificate-key <key> \
--apiserver-advertise-address=<F02或F03的IP> \
--apiserver-bind-port=6443
設定 Kubeconfig (讓 kubectl 可用) 加入成功後,必須配置憑證才能使用 kubectl 指令
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf ~/.kube/config # kubeadm join 會自動在 /etc/kubernetes/ 產生這份檔案
sudo chown $(id -u):$(id -g) ~/.kube/config
在每台 worker 機器執行 kubeadm 給的 kubeadm join:
sudo kubeadm join 10.10.0.83:6444 --token <TOKEN> --discovery-token-ca-cert-hash sha256:<HASH>
到master node上檢查節點:
kubectl get nodes -o wide