k8s 部署全程在超級用戶下進行
sudo su
本文請根據大綱順序閱讀!
一、配置基礎環境(在全部節點執行)
1、安裝docker 使用apt安裝containerd
新版k8s已經棄用docker轉為containerd,如果要將docker改為containerd詳見:將節點上的容器運行時從 Docker Engine 改為 containerd))
官網文檔 : Install Docker Engine on Ubuntu | Docker Documentation
- 卸載舊版本docker安裝包
for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg; done
- 更新
apt
包索引并安裝包以允許apt
通過 HTTPS 使用存儲庫:
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg
- 添加Docker官方GPG密鑰:
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
- 使用以下命令設置存儲庫(清華源):
echo \"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu \$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
- 更新
apt
包索引:
sudo apt-get update
- 安裝 Docker 引擎、containerd 和 Docker Compose。
舊版 k8s:
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
新版k8s:只需要安裝containerd即可,到這一步就可以結束了
sudo apt-get install containerd.io
- 通過運行鏡像來驗證Docker Engine安裝是否成功
hello-world
。
sudo docker run hello-world
- 配置docker 阿里云鏡像
加速器地址在阿里云控制臺申請:
sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://i848vj4w.mirror.aliyuncs.com"] } EOF sudo systemctl daemon-reload
sudo systemctl restart docker#查看是否配置成功
docker info
1、安裝容器運行時
- 安裝containerd
如果你已經執行了上面的教程安裝了最新版的docker,實際上containerd也已經被安裝,無需重新安裝。如果你想單獨安裝containerd,而不安裝docker,請按1、安裝docker 使用apt安裝containerd
步驟執行并在apt-get install時只執行containerd.io即可,或使用二進制安裝
- 配置 containerd
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
- 配置阿里云鏡像
[plugins."io.containerd.grpc.v1.cri".registry.mirrors][plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] endpoint = ["https://bqr1dr1n.mirror.aliyuncs.com"] [plugins."io.containerd.grpc.v1.cri".registry.mirrors."registry.aliyuncs.com/google_containers"] endpoint = ["https://registry.aliyuncs.com/k8sxio"]
- 重啟 containerd
sudo systemctl restart containerd
2、配置 systemd cgroup驅動
- 結合
runc
使用systemd
cgroup 驅動,在/etc/containerd/config.toml
中設置:
sudo vim config.toml
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]...[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]SystemdCgroup = true
- 重啟containerd:
sudo systemctl restart containerd
3、禁用Swap分區: Kubernetes不建議在節點上啟用Swap分區,因此需要禁用它。可以使用以下命令禁用Swap分區:
swapoff -a
sed -ri 's/.*swap.*/#&/' /etc/fstab
4、在各節點添加hosts配置
vim /etc/hosts192.168.16.200 k8s-master
192.168.16.201 k8s-node1
192.168.16.202 k8s-node2
5、轉發 IPv4 并讓 iptables 看到橋接流量
執行下述指令:
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
# 設置所需的 sysctl 參數,參數在重新啟動后保持不變
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
# 應用 sysctl 參數而不重新啟動
sudo sysctl --system
通過運行以下指令確認 br_netfilter
和 overlay
模塊被加載:
lsmod | grep br_netfilter
lsmod | grep overlay
通過運行以下指令確認 net.bridge.bridge-nf-call-iptables
、net.bridge.bridge-nf-call-ip6tables
和 net.ipv4.ip_forward
系統變量在你的 sysctl
配置中被設置為 1:
sysctl net.bridge.bridge-nf-call-iptables net.bridge.bridge-nf-call-ip6tables net.ipv4.ip_forward
6、關閉SELinux(ubuntu默認沒有安裝)
sudo setenforce 0
vim /etc/selinux/config
SELINUX=disabled
7、安裝 kubeadm、kubelet 和 kubectl
- 更新
apt
包索引并安裝使用 Kubernetesapt
倉庫所需要的包:
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl
- 下載 Google Cloud 公開簽名秘鑰(阿里云鏡像)
curl -fsSL https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-archive-keyring.gpg
- 添加 Kubernetes apt 倉庫(阿里云鏡像):
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
- 更新
apt
包索引,安裝 kubelet、kubeadm 和 kubectl,并鎖定其版本:
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
#鎖定版本
sudo apt-mark hold kubelet kubeadm kubectl
8、時間同步
# 安裝 NTP
sudo apt update
sudo apt install -y ntp
# 配置 NTP 服務器
sudo vim /etc/ntp.conf
#添加ntp服務器 中國開源免費NTP服務器
server cn.pool.ntp.org
#重新啟動 NTP 服務:
sudo systemctl restart ntp
#驗證時間同步狀態:
#查看 NTP 服務器狀態
ntpq -p
#查看系統時間
date
9、關閉防火墻
不建議直接關閉防火墻,而是放行要用的端口(但不關閉防火墻容易遇到很多問題)
ufw disable
systemctl disable firewalld #如果是已經啟動的pod被防火墻攔截了,有時候需要重啟服務器才生效
二、使用kubeadm部署工具安裝kubernetes
- k8s架構示意圖
1、初始化平面控制器 (control-plane node)
docker提前拉取初始化需要的鏡像(新版已不使用docker,請跳過… )
#查看鏡像版本
kubeadm config images list
命令返回值如下:
registry.k8s.io/kube-apiserver:v1.27.4
registry.k8s.io/kube-controller-manager:v1.27.4
registry.k8s.io/kube-scheduler:v1.27.4
registry.k8s.io/kube-proxy:v1.27.4
registry.k8s.io/pause:3.9
registry.k8s.io/etcd:3.5.7-0
registry.k8s.io/coredns/coredns:v1.10.1
這些鏡像是 Kubernetes 集群的核心組件,每個組件都扮演著不同的角色,負責集群的不同功能。以下是這些鏡像的作用簡介:
registry.k8s.io/kube-apiserver:v1.27.4
:
Kube API Server 是 Kubernetes 控制平面的核心組件之一,它提供了 Kubernetes API 的接入點,用于管理集群的操作和資源。它是集群中的主要入口,負責接收 API 請求、身份驗證和授權,以及將請求轉發到其他控制平面組件。
registry.k8s.io/kube-controller-manager:v1.27.4
:
Kube Controller Manager 是 Kubernetes 控制平面的組件之一,它負責管理控制循環,處理不同的控制器任務,例如 ReplicaSet、Deployment、NodeController 等。它持續監控集群狀態,并確保期望狀態與實際狀態一致。
registry.k8s.io/kube-scheduler:v1.27.4
:
Kube Scheduler 負責將新創建的 Pod 調度到集群中的節點上。它基于資源需求、親和性、反親和性等策略,選擇適合的節點來運行 Pod。
registry.k8s.io/kube-proxy:v1.27.4
:
Kube Proxy 是 Kubernetes 集群中的網絡代理,負責維護節點上的網絡規則,以便正確路由到相應的 Pod。它支持負載均衡和服務發現功能。
registry.k8s.io/pause:3.9
:
Pause 鏡像是一個微型容器,每個 Pod 都會運行一個 Pause 容器作為網絡命名空間的初始化進程。它充當了所有容器的父進程,幫助容器共享網絡命名空間和存儲卷。
registry.k8s.io/etcd:3.5.7-0
:
Etcd 是 Kubernetes 集群的分布式鍵值存儲,用于存儲集群狀態和配置信息。它支持高可用性和一致性,是集群的重要組成部分。
registry.k8s.io/coredns/coredns:v1.10.1
:
CoreDNS 是 Kubernetes 集群的默認 DNS 服務,用于處理 Pod 和服務名稱解析。它支持插件機制,可以擴展到不同的 DNS 后端和功能。
這些組件一起協同工作,構成了 Kubernetes 集群的核心基礎架構,支持容器編排和管理。
-
由于國內有墻,這里應該是拉不到的,得修改k8s.gcr.io/為國內的鏡像registry.aliyuncs.com/google_containers/
-
編寫拉取鏡像的腳本
vim kube-init-image-pull.sh
#!/bin/bash# Get the image list with versions from kubeadm
image_list=$(kubeadm config images list)# Loop through the images, pull them, rename them, and delete aliased images
for oldimage in $image_list; doecho "old image: $oldimage"#替換為國內鏡像名稱image=$(echo "$oldimage" | sed 's|registry.k8s.io/|registry.aliyuncs.com/google_containers/|')echo "Pulling image: $image"docker pull $image#拉取后要修改回原來的名稱docker tag $image $oldimagedocker rmi $image
done
chmod 777 kube-init-image-pull.sh
./kube-init-image-pull.sh
coredns如果拉不到 可能是因為名稱命名規則不太一樣
docker pull registry.aliyuncs.com/google_containers/coredns/coredns:v1.10.1 改為
docker pull registry.aliyuncs.com/google_containers/coredns:v1.10.1
手動拉一下并tag修改名稱
1)、使用配置文件初始化master
- 生成初始化配置文件到kube的目錄
kubeadm config print init-defaults > /home/kube/master/init-default.yaml
想了解更多配置 請參閱:kubeadm 配置 (v1beta3) | Kubernetes (p2hp.com)
sudo vim init-default.yaml
- 需要關注或修改的配置:
kubernetesVersion: 1.27.4
kubeadm version 命令查看控制面的目標版本。
advertiseAddress: 192.168.16.200
bindPort: 6443
表示控制面的穩定ip和端口,填當前節點的ip,端口可以默認6443,這兩個值可以使 controlPlaneEndpoint 代替。
imageRepository :registry.aliyuncs.com/google_containers (上面使用腳本提前拉鏡像的跳過,因為已經重命名過鏡像了,所以這里不需要改!!!改了反而報錯。)
設置用來拉取鏡像的容器倉庫。如果此字段為空,默認使用registry.k8s.io。 當 Kubernetes 用來執行 CI 構造時(Kubernetes 版本以 ci/ 開頭), 將默認使用gcr.io/k8s-staging-ci-images 來拉取控制面組件鏡像,而使用registry.k8s.io來拉取所有其他鏡像。
這里修改為阿里云的源,上面腳本的作用是跟這個配置修改的作用是一樣的。
imagePullPolicy:IfNotPresent
設定 "kubeadm init" 和 "kubeadm join" 操作期間的鏡像拉取策略。此字段的取值可以是 "Always"、"IfNotPresent" 或 "Never" 之一。 若此字段未設置,則 kubeadm 使用 "IfNotPresent" 作為其默認值,換言之, 當鏡像在主機上不存在時才執行拉取操作。
podSubnet:10.244.0.0/16
podSubnet 為 Pod 所使用的子網。 默認配置沒有該選項,在Network選項下給其增加該配置
配置驅動為systemd:
---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cgroupDriver: systemd
參考配置如下:
apiVersion: kubeadm.k8s.io/v1beta3
bootstrapTokens:
- groups:- system:bootstrappers:kubeadm:default-node-tokentoken: abcdef.0123456789abcdefttl: 24h0m0susages:- signing- authentication
kind: InitConfiguration
localAPIEndpoint:advertiseAddress: 192.168.16.200bindPort: 6443
nodeRegistration:criSocket: unix:///var/run/containerd/containerd.sockimagePullPolicy: IfNotPresentname: nodetaints: null
---
apiServer:timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta3
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns: {}
etcd:local:dataDir: /var/lib/etcd
imageRepository: registry.aliyuncs.com/google_containers
kind: ClusterConfiguration
kubernetesVersion: 1.27.4
networking:dnsDomain: cluster.localserviceSubnet: 10.96.0.0/12podSubnet: 10.244.0.0/16
scheduler: {}
---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cgroupDriver: systemd
- 初始化master
sudo kubeadm init --config=init-default.yaml --ignore-preflight-errors=all
可能會遇到此錯誤:
錯誤1:CRI插件被關閉
ERROR CRI]: container runtime is not running: output: time="2023-08-09T21:57:06+08:00" level=fatal msg="validate service connection: CRI v1 runtime API is not implemented for endpoint \"unix:///var/run/containerd/containerd.sock\": rpc error: code = Unimplemented desc = unknown service runtime.v1.RuntimeService"
, error: exit status 1
官網上的解釋是:配置 systemd
cgroup 驅動
說明:
如果你從軟件包(例如,RPM 或者 .deb
)中安裝 containerd,你可能會發現其中默認禁止了 CRI 集成插件。
你需要啟用 CRI 支持才能在 Kubernetes 集群中使用 containerd。 要確保 cri
沒有出現在 /etc/containerd/config.toml
文件中 disabled_plugins
列表內。如果你更改了這個文件,也請記得要重啟 containerd
。
如果你在初次安裝集群后或安裝 CNI 后遇到容器崩潰循環,則隨軟件包提供的 containerd 配置可能包含不兼容的配置參數。考慮按照 getting-started.md 中指定的 containerd config default > /etc/containerd/config.toml
重置 containerd 配置,然后相應地設置上述配置參數。
vim /etc/containerd/config.toml
#修改這行為[]
#disabled_plugins = ["cri"]
disabled_plugins = []
#重新啟動
sudo systemctl restart containerd
#重新初始化master
sudo kubeadm reset
sudo kubeadm init --config=init-default.yaml --ignore-preflight-errors=all
錯誤2:
[kubelet-check] Initial timeout of 40s passed.Unfortunately, an error has occurred:timed out waiting for the conditionThis error is likely caused by:- The kubelet is not running- The kubelet is unhealthy due to a misconfiguration of the node in some way (required cgroups disabled)If you are on a systemd-powered system, you can try to troubleshoot the error with the following commands:- 'systemctl status kubelet'- 'journalctl -xeu kubelet'Additionally, a control plane component may have crashed or exited when started by the container runtime.
To troubleshoot, list all containers using your preferred container runtimes CLI.
Here is one example how you may list all running Kubernetes containers by using crictl:- 'crictl --runtime-endpoint unix:///var/run/containerd/containerd.sock ps -a | grep kube | grep -v pause'Once you have found the failing container, you can inspect its logs with:- 'crictl --runtime-endpoint unix:///var/run/containerd/containerd.sock logs CONTAINERID'
error execution phase wait-control-plane: couldn't initialize a Kubernetes cluster
To see the stack trace of this error execute with --v=5 or higher
- 查看詳細報錯
journalctl -xeu kubelet
- 顯示的錯誤 (failed to get sandbox image “registry.k8s.io/pause:3.6”) 跟 pause鏡像版本對不上,我用的是3.9但是初始化的時候是3.6
#查看鏡像版本
kubeadm config images list
#查看containerd拉取的鏡像
crictl --runtime-endpoint unix:///var/run/containerd/containerd.sock images
在你的 containerd 配置中, 你可以通過設置以下選項重載沙箱鏡像:
[plugins."io.containerd.grpc.v1.cri"]sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.9"
systemctl restart containerd
Your Kubernetes control-plane has initialized successfully!
初始化完成后 會輸出這樣一段話:
To start using your cluster, you need to run the following as a regular user:mkdir -p $HOME/.kubesudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/configsudo chown $(id -u):$(id -g) $HOME/.kube/configAlternatively, if you are the root user, you can run:export KUBECONFIG=/etc/kubernetes/admin.confYou should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:https://kubernetes.io/docs/concepts/cluster-administration/addons/Then you can join any number of worker nodes by running the following on each as root:kubeadm join 192.168.16.200:6443 --token abcdef.0123456789abcdef \--discovery-token-ca-cert-hash sha256:438c87675185beeb9a495fc0b51d0993fb810340b5d793aa2b6b915cade42776
最后兩行記得拷貝記錄一下,后面初始化node的時候會用到
如果是root用戶,要運行
export KUBECONFIG=/etc/kubernetes/admin.conf
然后運行
mkdir -p $HOME/.kubesudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/configsudo chown $(id -u):$(id -g) $HOME/.kube/config
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:https://kubernetes.io/docs/concepts/cluster-administration/addons/
這段話提示我們需要部署一個pod network,在以下網址里面有很多種不同的插件,這里我們選擇flannel
wget https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml
kubectl apply -f kube-flannel.yml
使用以下命令查看鏡像拉取狀態,pending可能是還在下載鏡像
kubectl get pods -n kube-system -o wide
等全部鏡像變成RUNNING狀態后,master狀態也會變成Ready
kubectl get nodes
2)、使用配置文件初始化node
node的初始化和master的初始化步驟基本一致,除了初始化master
的步驟(但要包括那錯誤
例子中pause的配置)不需要做,其他的參考上面步驟重新做一遍即可,不同的是init命令換成了join命令
kubeadm join 192.168.16.200:6443 --token abcdef.0123456789abcdef \--discovery-token-ca-cert-hash sha256:438c87675185beeb9a495fc0b51d0993fb810340b5d793aa2b6b915cade42776
就是讓你們拷貝的那段,如果忘記了,可以使用以下命令重新獲取
kubeadm token create --print-join-command
查看nodes的狀態
kubectl get nodes
如果報以下錯誤
couldn't get current server API group list: Get "http://localhost:8080/api?timeout=32s": dial tcp 127.0.0.1:8080: connect: connection refused
查看/etc/kubernetes/kubelet.conf文件是否存在
不存在就先執行
kubeadm reset 后重新 kubeadm join
然后添加到環境變量中
echo "export KUBECONFIG=/etc/kubernetes/kubelet.conf" >> /etc/profile
source /etc/profile
再執行就正常了
kubectl get nodes
看到node和master的狀態都是Ready就沒問題了!
三、 部署Kuboard控制臺
1、搭建Kuboard
在正式安裝 kuboard v3 之前,需做好一個簡單的部署計劃的設計,在本例中,各組件之間的連接方式,如下圖所示:
- 假設用戶通過 http://外網IP:80 訪問 Kuboard v3;
- 安裝在 Kubernetes 中的 Kuboard Agent 通過
內網IP
訪問 Kuboard 的 Web 服務端口 80 和 Kuboard Agent Server 端口 10081。
- 拉取Kuboard鏡像
sudo docker pull eipwork/kuboard:v3
- 啟動kuboard容器
sudo docker run -d \--restart=unless-stopped \--name=kuboard \-p 8080:80/tcp \-p 10081:10081/tcp \-e KUBOARD_ENDPOINT="http://內網IP:80" \-e KUBOARD_AGENT_SERVER_TCP_PORT="10081" \-v ./kuboard-data:/data \eipwork/kuboard:v3# 也可以使用鏡像 swr.cn-east-2.myhuaweicloud.com/kuboard/kuboard:v3 ,可以更快地完成鏡像下載。# 請不要使用 127.0.0.1 或者 localhost 作為內網 IP \# Kuboard 不需要和 K8S 在同一個網段,Kuboard Agent 甚至可以通過代理訪問 Kuboard Server \
參數解釋
- 建議將此命令保存為一個 shell 腳本,例如
start-kuboard.sh
,后續升級 Kuboard 或恢復 Kuboard 時,需要通過此命令了解到最初安裝 Kuboard 時所使用的參數; - 第 4 行,將 Kuboard Web 端口 80 映射到宿主機的
8080
端口(您可以根據自己的情況選擇宿主機的其他端口); - 第 5 行,將 Kuboard Agent Server 的端口
10081/tcp
映射到宿主機的10081
端口(您可以根據自己的情況選擇宿主機的其他端口); - 第 6 行,指定 KUBOARD_ENDPOINT 為
http://內網IP
,如果后續修改此參數,需要將已導入的 Kubernetes 集群從 Kuboard 中刪除,再重新導入; - 第 7 行,指定 KUBOARD_AGENT_SERVER 的端口為
10081
,此參數與第 5 行中的宿主機端口應保持一致,修改此參數不會改變容器內監聽的端口10081
,例如,如果第 5 行為-p 30081:10081/tcp
則第 7 行應該修改為-e KUBOARD_AGENT_SERVER_TCP_PORT="30081"
; - 第 8 行,將持久化數據
/data
目錄映射到腳本文件夾下的kuboard-data` 路徑,請根據您自己的情況調整宿主機路徑;
其他參數
- 在啟動命令行中增加環境變量
KUBOARD_ADMIN_DERAULT_PASSWORD
,可以設置admin
用戶的初始默認密碼。
2、 訪問 Kuboard v3.x
在瀏覽器輸入 http://your-host-ip:8080
即可訪問 Kuboard v3.x 的界面,登錄方式:
- 用戶名:
admin
- 密 碼:
Kuboard123
3、添加K8s集群到Kuboard
-
選擇以agent方式添加k8s集群
-
選擇第二個Agent鏡像
-
拷貝命令并在master上執行
注意這里的80端口要更換成你映射到宿主機的端口,比如我設置的是8080
curl -k 'http://192.168.16.200:8080/kuboard-api/cluster/my-kubenetes/kind/KubernetesCluster/my-kubenetes/resource/installAgentToKubernetes?token=zNCekc0Os7YUpsceyJ1Fhcgt90ZmZ9J5' > kuboard-agent.yaml
- yaml里面的80端口也改成8080
vim kuboard-agent.yaml
- 啟動pods
kubectl apply -f ./kuboard-agent.yaml
- 查看日志,確保都是RUNNING狀態
kubectl get pods -n kuboard -o wide -l "k8s.kuboard.cn/name in (kuboard-agent-25i3sy, kuboard-agent-25i3sy-2)"
- 集群導入成功
- 選擇管理員角色登錄
- 至此整個k8s環境就部署好啦