安装单节点的k8s集群
目标:安装单节点的k8s集群。
预算:20
预计安装时长:一天(是这样的,很恶心)
参考链接:https://gitee.com/cookeem/kubeadm-ha/blob/master/README-standalone.md
不懂为啥不能一键部署,而且有的资源下载不了,大部分时间都在等安装,然后解决安装不了的问题。
kubectl
是 Kubernetes 的命令行工具,用于与 Kubernetes 集群进行交互。它允许用户部署、管理和排查 Kubernetes 应用。
kubeadm
是 Kubernetes 的一个工具,用于快速启动和管理 Kubernetes 集群。它简化了集群的部署过程,并提供了初始化集群、加入节点和升级集群等功能。
1. 创建云主机
华为云创建云服务器ECS
选择按需计费
实例选择2核CPU,4G内存(需要>2G)
操作系统选择Debian 12
公网带宽选择按流量计费,带宽大小5Mbit/s.
设置密码
购买成功。
Nxshell连接到服务器
2. 安装docker
https://gitee.com/cookeem/kubeadm-ha/blob/master/README-standalone.md
# 安装基础软件
apt-get -y update #更新本地APT软件包索引,从配置的源服务器获取最新软件包信息
apt-get install -y sudo wget ca-certificates curl gnupg htop git jq tree #安装系统管理工具集
apt-get -y install apt-transport-https ca-certificates curl software-properties-common
#仓库支持组件,支持HTTPS协议源,提供add-apt-repository命令
# 安装docker-ce,整块命令复制过去执行
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/debian/gpg | sudo apt-key add -
add-apt-repository "deb [arch=amd64] https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/debian $(lsb_release -cs) stable"
apt-get -y update
apt-get -y install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-compose
#创建权限为755的密钥存储目录
#通过清华镜像站获取Docker官方GPG密钥并添加到APT信任链
#添加清华镜像的Docker仓库,$(lsb_release -cs)自动获取系统代号(如bookworm)
#安装完整Docker套件
# 检查docker版本
docker version
# 设置docker参数,整块命令复制
# 支持国内dockerhub镜像 文档参见: https://github.com/DaoCloud/public-image-mirror
# 这里使用daocloud的dockerhub的镜像代理
cat << EOF > /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2",
"registry-mirrors": [
"https://docker.m.daocloud.io"
]
}
EOF
#"exec-opts": ["native.cgroupdriver=systemd"]:设置 Docker 守护进程的 exec-opts 选项,指定 cgroup 驱动为 systemd。这对于使用 systemd 作为 init 系统的 Linux 发行版很有用。
#"log-driver": "json-file":设置 Docker 容器的日志驱动为 json-file。这是 Docker 的默认日志驱动,它会将日志以 JSON 格式写入文件。
#"log-opts": {"max-size": "100m"}:为日志驱动设置选项,这里指定每个日志文件的最大大小为 100MB。当达到这个大小时,Docker 会创建新的日志文件。
#"storage-driver": "overlay2":设置 Docker 的存储驱动为 overlay2。overlay2 是 Docker 的默认存储驱动,它提供了对联合文件系统的支持,优化了性能和空间利用率。
#"registry-mirrors": ["https://docker.m.daocloud.io"]:设置 Docker 镜像仓库的镜像源。这里指定了一个镜像加速器(如 DaoCloud 提供的),可以加速 Docker 镜像的拉取速度。
# 重启docker服务
systemctl restart docker
systemctl status docker
# 验证docker服务是否正常
docker images
# 拉取测试镜像
docker pull busybox
# 运行测试镜像
docker run --rm busybox uname -m
3. 安装k8s
华为云入站设置放行31000端口
# 安装kubernetes相关组件,整块复制
curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add -
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF
apt-get -y update
apt-get install -y kubelet kubeadm kubectl
kubeadm version
#kubelet是k8s守护进程,kubeadm是k8s的安装工具,kubectl是k8s命令行工具
# 获取kubernetes所需要的镜像,整块命令复制
# kubeadm config images list命令会列出当前Kubernetes版本所需的全部核心组件镜像,导出为环境变量PAUSE_IMAGE
kubeadm config images list --image-repository registry.cn-hangzhou.aliyuncs.com/google_containers
export PAUSE_IMAGE=$(kubeadm config images list --image-repository registry.cn-hangzhou.aliyuncs.com/google_containers | grep pause)
# 注意pause镜像用于配置cri-dockerd的启动参数
# 应该是输出 registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.9
echo $PAUSE_IMAGE
k8s从v1.24版本开始移除了docker-shim组件(用来连接k8s和docker),需要安装cri-dockerd
来替代该组件
# 安装cri-dockerd,用于连接kubernetes和docker,命令分开敲
# 可主机下完ftp传上去
wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.15/cri-dockerd-0.3.15.amd64.tgz
tar zxvf cri-dockerd-0.3.15.amd64.tgz
cd cri-dockerd/
mkdir -p /usr/local/bin
# 将文件的所有者(owner)和所属组(group)均设置为root用户,权限0755,安装cri-dockerd至/usr/local/bin/目录下
install -o root -g root -m 0755 cri-dockerd /usr/local/bin/cri-dockerd
# 创建cri-docker.socket启动文件
# Description描述服务用途,PartOf表明隶属关系(需与cri-docker.service联动)
# ListenStream=%t/cri-dockerd.sock指定运行时目录下的套接字文件(%t即/run)
# SocketMode=0660设置权限(root用户和docker组可读写)
# SocketUser/Group明确运行身份
# [Install]段的WantedBy=sockets.target确保系统启动时自动激活该套接字
# sockets.target 是一个特殊的systemd目标,它代表了所有监听套接字的集合
cat << EOF > /etc/systemd/system/cri-docker.socket
[Unit]
Description=CRI Docker Socket for the API
PartOf=cri-docker.service
[Socket]
ListenStream=%t/cri-dockerd.sock
SocketMode=0660
SocketUser=root
SocketGroup=docker
[Install]
WantedBy=sockets.target
EOF
# 创建cri-docker.service启动文件
# 注意设置pause容器镜像信息 --pod-infra-container-image=$PAUSE_IMAGE
#Documentation:提供服务的文档链接,这里是Mirantis的文档地址。
#After:定义服务启动顺序,确保network-online.target、firewalld.service和docker.service在该服务之前启动。
#Wants:声明服务的弱依赖,这里是network-online.target。
#Requires:声明服务的强依赖,这里是cri-docker.socket,确保套接字服务先于本服务启动。
#Type:服务类型,这里是notify,表示服务启动后会发送通知信号。
#ExecStart:服务启动命令,指定cri-dockerd的执行路径和参数,包括容器运行时端点和pause容器镜像信息($PAUSE_IMAGE)。
#fd:// 表示使用文件描述符传递套接字,CRI-Docker 守护进程不会自己创建套接字,而是从 systemd 接收一个已经打开的套接字文件描述符
#--pod-infra-container-image指定了用于基础设施(pause)容器的镜像。基础设施容器是每个 Pod 中的第一个容器,它负责为 Pod 中的其他容器提供网络命名空间。
#ExecReload:服务重载命令,用于发送HUP信号给主进程。
#TimeoutSec:服务启动超时时间,设置为0表示不超时。
#RestartSec:服务重启间隔,这里是2秒。
#Restart:服务重启策略,这里是always,表示服务退出后总是重启。
#StartLimitBurst和StartLimitInterval:控制服务在指定时间内的启动次数,以防止服务频繁启动失败。
#LimitNOFILE、LimitNPROC、LimitCORE:设置服务进程的文件描述符、进程数和核心转储文件大小限制为无限制。
#TasksMax:设置服务进程可以创建的最大任务数(线程数)为无限制。
#Delegate:允许服务在其cgroup中启动子进程。
#KillMode:定义杀死服务进程的方式,这里是process,表示仅杀死主进程。
#WantedBy:指定服务安装时的默认启用级别,这里是multi-user.target,表示在系统多用户模式下启用服务。
cat << EOF > /etc/systemd/system/cri-docker.service
[Unit]
Description=CRI Interface for Docker Application Container Engine
Documentation=https://docs.mirantis.com
After=network-online.target firewalld.service docker.service
Wants=network-online.target
Requires=cri-docker.socket
[Service]
Type=notify
ExecStart=/usr/local/bin/cri-dockerd --container-runtime-endpoint fd:// --pod-infra-container-image=$PAUSE_IMAGE
ExecReload=/bin/kill -s HUP \$MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
# Note that StartLimit* options were moved from "Service" to "Unit" in systemd 229.
# Both the old, and new location are accepted by systemd 229 and up, so using the old location
# to make them work for either version of systemd.
StartLimitBurst=3
# Note that StartLimitInterval was renamed to StartLimitIntervalSec in systemd 230.
# Both the old, and new name are accepted by systemd 230 and up, so using the old name to make
# this option work for either version of systemd.
StartLimitInterval=60s
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
# Comment TasksMax if your systemd version does not support it.
# Only systemd 226 and above support this option.
TasksMax=infinity
Delegate=yes
KillMode=process
[Install]
WantedBy=multi-user.target
EOF
# 启动cri-dockerd
systemctl daemon-reload
systemctl enable --now cri-docker.socket
systemctl restart cri-docker
systemctl status cri-docker
# 通过kubeadm预先拉取所需的容器镜像
# --cri-socket 指定CRI-Dockerd的套接字路径
kubeadm config images pull --image-repository registry.cn-hangzhou.aliyuncs.com/google_containers --cri-socket unix:///var/run/cri-dockerd.sock
# 查看拉取的镜像
docker images
# 部署前清理旧的安装配置
kubeadm reset -f --cri-socket unix:///var/run/cri-dockerd.sock
#在/etc/sysctl.conf添加配置
vim /etc/sysctl.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
#刷新一下,发现报错,因为之前配置的br_netfilter没有启动
#sysctl:cannot stat /proc/sys/net/bridge/bridge-nf-call-ip6tables:No such file or directory
#sysctl:cannot stat /proc/sys/net/bridge/bridge-nf-call-iptables:No such file or directory
sysctl -p
#驱动加载
modprobe br_netfilter
bridge
sysctl -p
# 使用kubeadm初始化kubernetes集群
kubeadm init --image-repository registry.cn-hangzhou.aliyuncs.com/google_containers --cri-socket unix:///var/run/cri-dockerd.sock
超时报错
#检查日志
journalctl -xeu kubelet | grep error
cd /etc/containerd
ls
rm config.toml
#生成默认的配置文件
containerd config default > /etc/containerd/config.toml
vim /etc/containerd/config.toml
#将sandbox image "registry.k8s.io/pause:3.8"
#改成sanbox_image = "registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.9"
#将 SystemdCgroup = false 改为 SystemdCgroup = true
#保存退出,重启Containerd
sudo systemctl restart containerd
#清除初始化失败的残存文件
sudo rm -rf /etc/kubernetes/manifests/*.yaml # 删除残留清单文件
sudo kubeadm reset --force --cri-socket unix:///var/run/cri-dockerd.sock # 重置集群状态
#解除端口占用
sudo ss -tulnp | grep 10250 # 查看占用进程,发现被kubelet占用
#关闭服务
sudo systemctl daemon-reload
systemctl stop kubelet
#手动拉取镜像并改名
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.9
docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.9 registry.k8s.io/pause:3.9
#再次尝试
kubeadm init --image-repository registry.cn-hangzhou.aliyuncs.com/google_containers --cri-socket unix:///var/run/cri-dockerd.sock --v=5
k8s的控制平面成功初始化
# 在所有master节点上设置kubectl访问kubernetes集群
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
# 在所有master节点上设置kubectl的自动完成,可以通过键盘TAB键自动补全子命令和参数
kubectl completion -h
kubectl completion bash > ~/.kube/completion.bash.inc
printf "
# Kubectl shell completion
source '$HOME/.kube/completion.bash.inc'
" >> $HOME/.bash_profile
source $HOME/.bash_profile
# 检查节点就绪状态,未安装网路网络组件,节点状态为 NOT READY
kubectl get nodes
# 检查pod状态,coredns状态为Pending
kubectl -n kube-system get pods
# 在k8s-demo节点上安装cilium网络组件
# 建议主机下载下来在文件上传到服务器
wget https://github.com/cilium/cilium-cli/releases/download/v0.16.16/cilium-linux-amd64.tar.gz
tar zxvf cilium-linux-amd64.tar.gz
mv cilium /usr/local/bin/
cilium install --set cni.chainingMode=portmap
# 检查cilium部署情况,多次敲命令直到全为running,再敲下一个命令
kubectl -n kube-system get pods
# 检查节点就绪状态
kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-demo Ready control-plane 3m15s v1.28.2
# 设置所有master允许调度pod
kubectl taint nodes --all node-role.kubernetes.io/control-plane-
# 测试部署应用到kubernetes集群
# 部署一个nginx应用,并暴露到node Port 31000
kubectl run nginx --image=nginx --image-pull-policy=IfNotPresent --port=80 -l=app=nginx
kubectl create service nodeport nginx --tcp=80:80 --node-port=31000
# 检查pod状态,等到running状态执行下条命令
kubectl get pods,svc
# 检查服务是否可以访问
#curl ip:31000
curl ecs-dd27-5400:31000
等一会
4. 在k8s中部署应用
1. kubernetes-dashboard
首先在华为云设置入站放行30000端口
#查看k8s版本,发现是1.28.2
kubectl version
再翻阅https://github.com/kubernetes/dashboard/releases
,可以得知我们的dashboard版本应当为7.5.0
安装kubernetes-dashboard
# 安装helm
wget https://get.helm.sh/helm-v3.15.4-linux-amd64.tar.gz
tar zxvf helm-v3.15.4-linux-amd64.tar.gz
mv linux-amd64/helm /usr/bin/
rm -rf linux-amd64/
# 测试helm
helm --help
# 添加 kubernetes-dashboard helm chart 仓库
helm repo add kubernetes-dashboard https://kubernetes.github.io/dashboard/
helm repo add stable https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
helm repo list
helm repo update
# 把helm chart 下载到本地,可以本机访问下载失败的报错链接进行下载然后传到服务器上
#helm fetch stable/kubernetes-dashboard --untar
helm fetch kubernetes-dashboard/kubernetes-dashboard --untar
# 获取镜像,分开敲
docker pull kubernetesui/dashboard-auth:1.1.3
docker pull kubernetesui/dashboard-api:1.7.0
docker pull kubernetesui/dashboard-web:1.4.0
docker pull kubernetesui/dashboard-metrics-scraper:1.1.1
docker pull kong:3.6
# 设置 kubernetes-dashboard 的部署配置
cat << EOF > kubernetes-dashboard.yaml
auth:
image:
repository: kubernetesui/dashboard-auth
tag: 1.1.3
api:
image:
repository: kubernetesui/dashboard-api
tag: 1.7.0
web:
image:
repository: kubernetesui/dashboard-web
tag: 1.4.0
metricsScraper:
image:
repository: kubernetesui/dashboard-metrics-scraper
tag: 1.1.1
EOF
# 部署 kubernetes-dashboard,k8s 1.28.2对应dashboard版本7.5.0
#helm uninstall kubernetes-dashboard -n kubernetes-dashboard
kubectl create namespace kubernetes-dashboard --dry-run=client -o yaml | kubectl apply -f -
helm install -n kubernetes-dashboard kubernetes-dashboard kubernetes-dashboard/ --version 7.5.0 -f kubernetes-dashboard.yaml
# # 如果需要删除kubernetes-dashboard可以执行以下命令
# helm uninstall kubernetes-dashboard
# helm uninstall -n kubernetes-dashboard kubernetes-dashboard
# 把kubernetes-dashboard暴露到30000端口
# 指定命名空间,使用 JSON Patch 格式局部修改(patch)服务(svc,service):kubernetes-dashboard-kong-proxy
# 将服务类型从默认的 ClusterIP 改为 NodePort
kubectl -n kubernetes-dashboard patch svc kubernetes-dashboard-kong-proxy --type json --patch '
[
{
"op": "replace",
"path": "/spec/type",
"value": "NodePort"
}
]'
# 将 NodePort 端口显式设置为 30000
# path: /spec/ports/0/nodePort:修改第一个端口的 nodePort 值
kubectl -n kubernetes-dashboard patch svc kubernetes-dashboard-kong-proxy --type json --patch '
[
{
"op": "replace",
"path": "/spec/ports/0/nodePort",
"value": 30000
}
]'
# 检查部署的pods
kubectl -n kubernetes-dashboard get pods
# 检查部署的services
kubectl -n kubernetes-dashboard get services
# 创建管理员serviceaccount
# kube-system 命名空间创建一个名为 admin-user 的服务账号
# -dry-run=client:模拟执行命令,仅生成资源配置文件而不实际创建。
# -o yaml:输出 YAML 格式的资源配置,便于通过管道传递给 kubectl apply。
# | kubectl apply -f -:将生成的 YAML 配置应用到集群,实现声明式创建。
kubectl create serviceaccount -n kube-system admin-user --dry-run=client -o yaml | kubectl apply -f -
# 创建管理员clusterrolebinding
# 将 admin-user 服务账号绑定到 cluster-admin 集群角色,授予其集群最高权限
# --clusterrole=cluster-admin:引用预定义的集群管理员角色(cluster-admin),拥有所有资源的完全控制权。
# --serviceaccount=kube-system:admin-user:指定绑定的服务账号(格式为 命名空间:服务账号名)
kubectl create clusterrolebinding admin-user --clusterrole=cluster-admin --serviceaccount=kube-system:admin-user --dry-run=client -o yaml | kubectl apply -f -
# 手动创建serviceaccount的secret
# 创建一个类型为 service-account-token 的 Secret,自动生成令牌用于 admin-user 服务账号的认证
cat << EOF | kubectl apply -f -
apiVersion: v1
kind: Secret
metadata:
name: admin-user-secret
namespace: kube-system
annotations:
kubernetes.io/service-account.name: admin-user
type: kubernetes.io/service-account-token
EOF
# 获取kubernetes管理token
# 使用 JSONPath 提取 Secret 中 data.token 字段的值
kubectl -n kube-system get secret admin-user-secret -o jsonpath='{ .data.token }' | base64 -d
#eyJhbGciOiJSUzI1NiIsImtpZCI6IjFIckdvbVh6cDNMUkpyUkVlcmkzUFNYMVpRUHNlVG8ySUZ0cnA4WHJRTzQifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbi11c2VyLXNlY3JldCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJhZG1pbi11c2VyIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiY2I0YTFlNzctNWQ3Yy00YzEyLWI4YTQtMjc3NjRjZmEyNWZkIiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmUtc3lzdGVtOmFkbWluLXVzZXIifQ.w6-oEKwPYkuc_SwUbKBDNxuR_3yH-4YAo4iuT108EhI2GVY0MNSoXlXr95CKKJVrwTPDHmx1E-EDrTJot3ehJGdrCTVvhdtmjzSHnct06I2cCgfe8-_1GiDD7pedUI3IczymrG92MJXI8gf-kXJ7GB_Vv49W0_9OiJfQpbJls3AxXVxw6xKCv3btfi6Z71UBypaxpRTaviK2RCKshEngFkc_h3Oo8KXIt5dB2aE0nZCWVQ4RUdu4-SeCEVxq_Dp3TEKOTzwnF3Ro6mm__YD7i5qc2veEzHkFoC6XKBsx3X9ZC3zCbTCpexdCOCBrddXK0T8nPP8q8pobxTiCP_RBiQ
# 使用浏览器访问kubernetes-dashboard: https://服务器公网IP:30000
# 使用kubernetes管理token登录kubernetes-dashboard
输入token登录
2. metrics-server
性能监测组件
# 拉取镜像
docker pull k8s.m.daocloud.io/metrics-server/metrics-server:v0.7.1
docker tag k8s.m.daocloud.io/metrics-server/metrics-server:v0.7.1 registry.k8s.io/metrics-server/metrics-server:v0.7.1
# 获取metrics-server安装yaml
curl -O -L https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.7.1/components.yaml
# 添加--kubelet-insecure-tls参数
sed -i 's/- args:/- args:\n - --kubelet-insecure-tls/g' components.yaml
# 安装metrics-server
kubectl apply -f components.yaml
# # 删除metrics-server
# kubectl delete -f components.yaml
# 等待metrics-server正常
kubectl -n kube-system get pods -l=k8s-app=metrics-server
# 查看节点的性能指标
kubectl top nodes
# 查看所有pods的性能指标
kubectl top pods -A
dashboard pods界面出现性能监测功能
本科出路确实比较一般,大家都推荐读研说我年轻该拼一拼,但我感觉没有以前的锐气了(被称作不思进取)。学历贬值跟得上行业发展的速度吗?读研出来就没有35岁危机了?每次想到读研这个话题就会感到沮丧继而心烦意乱。我想当下还是把实习的工作做好再说吧。
各位不要被我影响自己的想法。
2025-7-7