在Ubuntu24 上安装 Kubernetes 集群的详细过程,包括:节点安装调试、网络插件安装、Dashboard安装、Nginx 部署测试。

基础安装

系统环境设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 永久关闭防火墙:
sudo systemctl disable --now ufw
# 设置为亚洲的上海时区
sudo timedatectl set-timezone Asia/Shanghai
# 重启时间同步服务
sudo systemctl restart systemd-timesyncd.service
# 确保时间同步服务正常运行
timedatectl status

# 闭Swap分区
sudo swapoff -a
sudo sed -i '/swap/d' /etc/fstab

# 安装policycoreutils软件包
sudo apt install -y policycoreutils
# 检查selinux关闭状态
sestatus

系统参数配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# 添加主机名映射
sudo vi /etc/hosts
192.168.159.200 master200
192.168.159.201 slave201
192.168.159.202 slave202


# 配置内核参数:
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF

sudo sysctl --system

#
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

# 系统变量在你的 sysctl 配置中被设置为 1:
sysctl net.bridge.bridge-nf-call-iptables net.bridge.bridge-nf-call-ip6tables net.ipv4.ip_forward

# 指令确认 br_netfilter 和 overlay 模块被加载:
lsmod | grep br_netfilter
lsmod | grep overlay

安装containerd容器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# 安装Containerd:
sudo apt install -y containerd
# curl -LO https://github.com/containerd/containerd/releases/download/v1.7.13/cri-containerd-cni-1.7.13-linux-amd64.tar.gz
# sudo tar -zxvf cri-containerd-cni-1.7.13-linux-amd64.tar.gz -C /

# 查看版本
containerd -v

# 生成配置文件:
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml

# 修改配置文件: 将SystemdCgroup设置为true
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml

# 修改镜像
sudo vi /etc/containerd/config.toml
# 修改 sandbox_image 值为 registry.aliyuncs.com/google_containers/pause:3.9

# 重启
sudo systemctl enable --now containerd

# 启动
sudo systemctl restart containerd
sudo systemctl enable containerd
sudo systemctl status containerd

############################################## 使用(安装nginx)
# 拉取镜像
ctr image pull docker.io/library/nginx:latest
# 列出镜像
ctr image ls
# 删除镜像
ctr image rm docker.io/library/nginx:latest
# 导入镜像
ctr image import image.tar
# 导出镜像
ctr image export image.tar docker.io/library/nginx:latest

# 创建容器
ctr container create docker.io/library/nginx:latest my-nginx
# 启动容器任务
ctr task start my-nginx
# 停止容器任务
ctr task kill my-nginx
# 删除容器
ctr container rm my-nginx

# 查看任务列表
ctr task ls
# 进入容器
ctr task exec --tty --exec-id shell my-nginx /bin/sh
# 查看容器日志
ctr task logs my-nginx

安装Kubernetes组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 安装 必要组件
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl gpg

#Kubernetes 软件包仓库的公共签名密钥
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

# 添加 Kubernetes apt 仓库
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.28/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list

# 更新安装
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

kubeadm version

集群安装

初始化集群

在主节点上执行这行命令将主节点的镜像拉取下来:

1
2
3
4
5
# 通过 kubeadm version 确定版本号
sudo kubeadm config images pull \
--image-repository=registry.aliyuncs.com/google_containers \
--kubernetes-version=v1.28.15 \
--cri-socket=unix:///run/containerd/containerd.sock

执行集群初始化,注意IP和版本以及网络地址(network、service 可保持默认,需要与其他对应)

1
2
3
4
5
6
7
sudo kubeadm init \
--apiserver-advertise-address=192.168.159.200 \
--image-repository=registry.aliyuncs.com/google_containers \
--kubernetes-version=v1.28.15 \
--service-cidr=10.96.0.0/12 \
--pod-network-cidr=10.244.0.0/16 \
--cri-socket=unix:///run/containerd/containerd.sock

相关参数解释:

  • apiserver-advertise-address:集群广播地址,用 master 节点的内网 IP。

  • image-repository:由于默认拉取镜像地址 k8s.gcr.io 国内无法访问,这里指定阿里云镜像仓库地址。

  • kubernetes-version: K8s 版本,与上面安装的软件版本一致。

  • service-cidr:集群 Service 网段。

  • pod-network-cidr:集群 Pod 网段。

  • cri-socket:指定 cri-socket 接口,我们这里使用 unix:///var/run/cri-dockerd.sock。

初始化完成后如图所示:会出现两条命令,需要记录下来。

image-20250719175104305

在主节点上执行以下操作:

1
2
3
4
# 这个命令句是  kubeadm init 执行后打印的:看上图
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

节点安装

在所有工作节点上执行这行命令(注意修改为自己的token)

1
2
3
4
5
# 这个命令句是  kubeadm init 执行后打印的:看上图,初始化完后的视图
kubeadm join 192.168.159.200:6443 \
--token kxzrga.d74axaspi1patvof \
--discovery-token-ca-cert-hash sha256:062b1ad988e637ae9cbeaacf0a89a35fbb5fe582ebb55768fe0ac7c7e6f2ee45 \
--cri-socket=unix:///run/containerd/containerd.sock

集群查看

1
2
3
4
5
6
7
8
# 在主节点上查看所有节点:
kubectl get nodes -o wide

# 节点
kubectl get nodes

# 集群和dns信息
kubectl cluster-info

image-20250720172436281

网络问题

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

1
2
3
4
5
 # kubectl 没有使用到证书与k8s api通信,在初始化集群的时候要想使用kubectl

# 解决方法
echo "export KUBECONFIG=/etc/kubernetes/kubelet.conf" >> /etc/profile
source /etc/profile

NotReady(pod)

某些关键的 pod 没有运行起来,可以用以下方式调查原因:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 查看pod运行状态
sudo kubectl get pods
sudo kubectl get pod --all-namespaces

#kube-system的 pod 状态
sudo kubectl get pod -n kube-system

# 查看pod节点详情 sudo kubectl describe pod <NAMESPACE_NAME> -n kube-system
sudo kubectl describe pod coredns-66f779496c-fjq22 -n kube-system

# 查看容器日志运行日志 sudo kubectl logs -f -n <NAMESPACE> <NAMESPACE_NAME>
sudo kubectl logs -f -n kube-system coredns-66f779496c-fjq22

# 检查资源限制:检查Pod的资源配置是否合理 sudo kubectl get pod <pod-name> -o yaml
# 查看resources字段,确认CPU和内存限制是否满足容器需求。
sudo kubectl get pod coredns-66f779496c-fjq22 -o yaml

资源查看:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 检查节点Taints配置
kubectl describe node slave201 |grep Taint
# 如果输出中包含类似 Taints: node-role.kubernetes.io/master:NoSchedule,则说明节点设置了Taints

# 验证CoreDNS Toleration设置
sudo kubectl edit deployment coredns -n kube-system
# 检查CoreDNS的Deployment或DaemonSet YAML文件,确保其包含正确的Toleration配置。以下是示例配置:
# tolerations:
# - key: CriticalAddonsOnly
# operator: Exists
# - effect: NoSchedule

# 确认资源充足
sudo kubectl describe pod coredns-66f779496c-rhnb9 -n kube-system
# 如果输出中包含Insufficient cpu,则说明节点资源不足

Pending(CoreDNS)

问题:coredns Pending

3 node(s) had untolerated taint {node.kubernetes.io/not-ready: }. preemption: 0/3 nodes are available: 3 Preemption is not helpful for scheduling.

image-20250719214020713

解决

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#########################################  查看 CoreDNS 状态
sudo kubectl get pod --all-namespaces
sudo kubectl get pod -n kube-system
sudo kubectl get pods -n kube-system | grep coredns

# 检查 CoreDNS 服务是否正常运行:
sudo kubectl get svc -n kube-system | grep kube-dns

# CoreDNS 配置
sudo kubectl edit configmap coredns -n kube-system
# 常见配置项说明
# kubernetes:解析 Kubernetes 内部域名。
# forward:将未匹配的域名请求转发到上游 DNS。
# cache:启用 DNS 缓存,提高查询效率。
# reload:自动加载配置变更。
sudo kubectl edit deployment coredns -n kube-system


######################################### 解决 DNS 功能
# 报错内容:3 node(s) had untolerated taint {env_role: }. preemption: 0/3 nodes are available: 3 Preemption is not helpful for scheduling..
sudo kubectl describe pod coredns-58fbbbd8c5-9f9hl -n kube-system

# 检查一下看看节点是否被打污点了: node节点变成了NoSchedule
kubectl describe node master200 |grep Taint

# 出错:去掉污点
sudo kubectl taint node master200 env_role:NoSchedule-
sudo kubectl taint node slave201 env_role:NoSchedule-
sudo kubectl taint node slave202 env_role:NoSchedule-

启动

1
2
sudo systemctl restart kubelet
sudo systemctl restart containerd

网络插件

除了coredns必选外,其他三个插件选其一即可。

检查 kubelet 是否正常

CNI 插件依赖 kubelet,如果 kubelet 没有正确指定 CNI 目录,则会失败:

1
2
3
4
5
6
7
8
9
10
11
journalctl -u kubelet -f | grep cni

# 如果看到如下报错: failed to read CNI config /etc/cni/net.d: no such file or directory
# 则说明 CNI 目录没有配置正确,需要重启 `kubelet`:
systemctl restart kubelet

# Kubelet 需要在 /opt/cni/bin/ 目录找到 CNI 可执行文件:如果为空,则 CNI 没有正确安装,需要重新安装 CNI 插件。
ls -l /opt/cni/bin/

# 查看 /etc/cni/net.d/ 是否有 CNI 配置文件:正常情况下应有 CNI 配置文件,如果没有,请重新安装 CNI 插件。
ls -l /etc/cni/net.d/

coredns

DNS 是使用集群插件 管理器自动启动的内置的 Kubernetes 服务。

从 Kubernetes v1.12 开始,CoreDNS 是推荐的 DNS 服务器,取代了 kube-dns。 如果 你的集群原来使用 kube-dns,你可能部署的仍然是 kube-dns 而不是 CoreDNS。

重新安装 镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# 删除Deployment和ConfigMap
sudo kubectl delete deployment coredns -n kube-system \
sudo kubectl delete configmaps coredns -n kube-system
# 清理集群角色和绑定
sudo kubectl delete clusterrolebindings system:coredns \
sudo kubectl delete clusterroles system:coredns
# 删除ServiceAccount
sudo kubectl delete serviceaccounts coredns -n kube-system

# 更新CoreDNS配置并验证,Kubernetes会自动重新创建CoreDNS Pod
# sudo kubectl delete pod -l k8s-app=kube-dns -n kube-system


# 下载部署脚本文件:
wget https://raw.githubusercontent.com/coredns/deployment/master/kubernetes/deploy.sh
chmod +x deploy.sh
apt -y install jq
# 下载coredns.yaml.sed文件: -O coredns.yaml
wget https://raw.githubusercontent.com/coredns/deployment/master/kubernetes/coredns.yaml.sed

# 修改clusterIP(如果需要): 默认的clusterIP为10.96.0.10,如果需要修改,可以执行以下命令:
./deploy.sh -i 10.96.0.10 > coredns.yaml

# 更换源 image: coredns/coredns:1.9.4
# 为 image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/coredns/coredns:1.9.4
sudo kubectl apply -f coredns.yaml

sudo kubectl get pod --all-namespaces
sudo kubectl get pods -n kube-system -w
sudo kubectl get pods -n kube-system -l k8s-app=kube-dns

######################################### 验证 DNS 功能
vim busybox.yaml
# 输入 :set paste 解决编辑YML文件时,遇到自动缩进导致格式混乱的问题
apiVersion: v1
kind: Pod
metadata:
name: busybox
namespace: default
spec:
containers:
- name: busybox
image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/quay.io/prometheus/busybox
command:
- sleep
- "3600"
imagePullPolicy: IfNotPresent
restartPolicy: Always

sudo kubectl apply -f busybox.yaml
sudo watch kubectl get pods busybox

# 一旦该 pod 运行,您就可以在环境中执行 nslookup。如果您看到Server的内容,则 DNS 工作正常
sudo kubectl exec -ti busybox -- nslookup kubernetes.default

flannel

由 CoreOS 开发的项目 Flannel,可能是最直接和最受欢迎的 CNI 插件。

它是容器编排系统中最成熟的网络结构示例之一,旨在实现更好的容器间和主机间网络。随着 CNI 概念的兴起,Flannel CNI 插件算是早期的入门。

与其他方案相比,Flannel 相对容易安装和配置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
curl -LO https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
# 修改 kube-flannel.yml
# 将 image: quay.io/coreos/flannel:v0.13.1-rc2 修改为
# image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/quay.io/coreos/flannel:v0.13.1-rc2

sudo kubectl apply -f kube-flannel.yml

#监控安装过程
sudo watch kubectl get all -o wide -n kube-flannel

# 查看pod状态
sudo kubectl get pod -n kube-flannel
sudo kubectl get pod --all-namespaces

# 查看服务节点状态
kubectl get nodes
kubectl get nodes -o wide

calico

Calico 是 Kubernetes 生态系统中另一种流行的网络选择。

虽然 Flannel 被公认为是最简单的选择,但 Calico 以其性能、灵活性而闻名。Calico 的功能更为全面,不仅提供主机和 pod 之间的网络连接,还涉及网络安全和管理。Calico CNI 插件在 CNI 框架内封装了 Calico 的功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#安装Tigera Calico操作符和自定义资源
curl -LO https://raw.githubusercontent.com/projectcalico/calico/v3.30.2/manifests/tigera-operator.yaml
# 修改镜像quay.io/tigera/operator:v1.38.3 到国内 https://docker.aityp.com/
# image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/quay.io/tigera/operator:v1.38.3
sudo kubectl apply -f tigera-operator.yaml
sudo kubectl delete -f tigera-operator.yaml

# 下载客户端资源文件
curl -LO https://raw.githubusercontent.com/projectcalico/calico/v3.30.2/manifests/custom-resources.yaml
# 修改pod的网段地址
sed -i 's/cidr: 192.168.0.0/cidr: 10.244.0.0/g' custom-resources.yaml
sudo kubectl apply -f custom-resources.yaml
sudo kubectl delete -f custom-resources.yaml

# 监控
sudo watch kubectl get all -o wide -n calico-system

sudo kubectl describe pod csi-node-driver-ks4k9 -n calico-system
sudo kubectl get pod -n calico-system
sudo kubectl get pod --all-namespaces

cilium

1
kubectl apply -f https://raw.githubusercontent.com/cilium/cilium/v1.12/install/kubernetes/quick-install.yaml

Dashboard

一定要与k8s版本对应,在官网查看支持的版本。

image-20250720163701810

安装插件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 查看k8s 版本	Version: v1.28.15
kubectl version

wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml
# 把recommended.yaml里访问方式调整为nodeport,是集群外部能否访问
# 添加 type 和 nodePort 节点
spec:
type: NodePort
ports:
- port: 443
targetPort: 8443
nodePort: 30012

# 修改镜像
# image 前加 swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/, 如下:
# image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/kubernetesui/dashboard:v2.7.0
# image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/kubernetesui/metrics-scraper:v1.0.8

sudo kubectl apply -f recommended.yaml
# 查看状态
sudo kubectl get all -n kubernetes-dashboard
# 端口信息
sudo kubectl get pod,svc -n kubernetes-dashboard

# 访问: https://192.168.159.200:30012/

获取token:方式一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# 输入 :set paste	解决编辑YML文件时,遇到自动缩进导致格式混乱的问题
vim admin-token.yaml
# 粘贴以下内容
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin
namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: admin
namespace: kubernetes-dashboard

---
apiVersion: v1
kind: Secret
metadata:
name: kubernetes-dashboard-token
namespace: kubernetes-dashboard
annotations:
kubernetes.io/service-account.name: "admin"
type: kubernetes.io/service-account-token


sudo kubectl apply -f admin-token.yaml

# 查看kubernetes-dashboard下面的secret
sudo kubectl get secret -n kubernetes-dashboard

# 查看登录token(获取令牌)
sudo kubectl describe secret kubernetes-dashboard-token -n kubernetes-dashboard
sudo kubectl -n kubernetes-dashboard describe secret $(kubectl -n kubernetes-dashboard get secret | grep admin-user | awk '{print $1}')

获取token:方式二

1
2
3
4
5
6
7
8
9
# 创建Service Account
kubectl create serviceaccount dashboard-admin-sa -n kubernetes-dashboard
# 绑定ClusterRole
kubectl create clusterrolebinding dashboard-admin-sa-binding \
--clusterrole=cluster-admin \
--serviceaccount=kubernetes-dashboard:dashboard-admin-sa

# 获取Token信息
kubectl -n kubernetes-dashboard get secret $(kubectl -n kubernetes-dashboard get sa dashboard-admin-sa -o jsonpath="{.secrets[0].name}") -o jsonpath="{.data.token}" | base64 --decode

常见问题及解答

问题 答案
1. 创建Service Account时提示权限不足 确保你有足够的权限在集群中创建Service Account。如果你是集群管理员,可以尝试使用cluster-admin权限。
2. 获取Token信息时提示找不到Secret 确认Service Account名称是否正确,且是否已经成功创建。可以通过kubectl get sa命令查看Service Account列表。
3. 登录时提示Token无效 确认Token信息是否正确复制,且Token是否已经过期。Token的有效期通常是24小时,过期后需要重新创建。
4. 无法打开Kubernetes Dashboard 确认Kubernetes Dashboard是否已经正确安装并启动。可以通过kubectl get pods -n kubernetes-dashboard命令查看Dashboard的运行状态。
5. 登录后无法看到集群资源 确认Service Account是否已经绑定到正确的ClusterRole,且ClusterRole是否拥有足够的权限。

效果展示

image-20250720172611409

image-20250720172701262

部署nginx

vim nginx-deploy.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx-deploy
name: nginx-deploy
spec:
replicas: 1
selector:
matchLabels:
app: nginx-deploy
template:
metadata:
labels:
app: nginx-deploy
spec:
containers:
- image: registry.cn-shenzhen.aliyuncs.com/xiaohh-docker/nginx:1.25.4
name: nginx
ports:
- containerPort: 80

---

apiVersion: v1
kind: Service
metadata:
labels:
app: nginx-deploy
name: nginx-svc
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
nodePort: 30080
selector:
app: nginx-deploy
type: NodePort

部署并查看

1
2
3
4
5
6
7
8
9
sudo kubectl apply -f nginx-deploy.yaml
sudo kubectl get all -o wide

# 访问
kubectl get svc
kubectl describe service nginx-svc
kubectl get nodes

# 页面 http://192.168.159.200:30080/
image-20250720161241610