一、安装docker
kubernetes-new-core-stable-v1.31-rpm-x86_64安装包下载_开源镜像站-阿里云
下载对应版本:
Index of linux/centos/7/x86_64/stable/Packages/
尝试使用 rpm 命令强制安装:
sudo rpm -ivh --nodeps ./docker-ce-20.10.7-3.el7.x86_64.rpm ./docker-ce-cli-20.10.7-3.el7.x86_64.rpm ./containerd.io-1.4.6-3.1.el7.x86_64.rpm
systemctl enable docker --now
docker --version
Docker version 20.10.7, build f0df350
可能踩坑:
1. 解决文件冲突问题
错误提示 file /usr/libexec/docker/cli-plugins/docker-buildx from install of docker-ce-cli conflicts with file from package docker-buildx-plugin 表明系统中已存在 docker-buildx-plugin 包,与当前安装的 docker-ce-cli 冲突。需先卸载该插件:
sudo yum remove docker-buildx-plugin
卸载后重新执行 RPM 安装命令:
sudo rpm -ivh --nodeps ./docker-ce-20.10.7-3.el7.x86_64.rpm \
./docker-ce-cli-20.10.7-3.el7.x86_64.rpm \
./containerd.io-1.4.6-3.1.el7.x86_64.rpm
二、安装Kubernetes
kubectl version --output=json v1.20.9
在centos9安装需要的前置操作
以下配置在 CentOS 7.9 中可能无需显式设置,但在 CentOS 9 中是必需的:
1、强制使用 cgroups v1
- 问题:CentOS 9 默认启用 cgroups v2,而 Kubernetes 1.20 对 cgroups v2 的支持不完善,导致 kubelet 无法正常启动。
- 解决方案:修改内核参数,回退到 cgroups v1:
# 修改 GRUB 配置
sudo grubby --update-kernel=ALL --args="systemd.unified_cgroup_hierarchy=0"
# 重启生效
sudo reboot
- **验证**:
stat -fc %T /sys/fs/cgroup/
输出应为 `tmpfs`(表示 cgroups v1),而非 `cgroup2fs`。
2、配置 Docker 使用 systemd cgroup driver
- 问题:Docker 默认的 cgroup driver 可能与 kubelet 不兼容。
- 解决方案:修改 Docker 配置:
sudo mkdir -p /etc/docker
cat <<EOF | sudo tee /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"]
}
EOF
重启 Docker
sudo systemctl restart docker
3、配置防火墙规则
问题:CentOS 9 默认使用 firewalld 和 nftables,需显式放行 Kubernetes 端口。
解决方案:
sudo firewall-cmd --permanent --add-port={6443,2379-2380,10250,10251,10252,30000-32767}/tcp
sudo firewall-cmd --permanent --add-port={8472}/udp # 如果使用 Flannel
sudo firewall-cmd --reload
或者直接停止firewalld服务
在CentOS系统中,停止firewall-cmd服务可以使用以下命令:
sudo systemctl stop firewalld
这个命令会立即停止firewalld服务,firewall-cmd是firewalld服务的命令行工具,停止firewalld服务后,firewall-cmd相关的功能也将无法使用。如果你希望禁止firewalld服务在系统启动时自动启动,可以使用以下命令:
sudo systemctl disable firewalld
如果后续想要重新启动firewalld服务,可以使用:
sudo systemctl start firewalld
要查看firewalld服务的状态,例如检查它是否正在运行,可以使用:
sudo systemctl status firewalld
4、初始化集群(必须执行 kubeadm init)
问题:即使 CentOS 7.9 未运行 kubeadm init 也能启动 kubelet,可能是因为旧版本 kubelet 对配置缺失的容忍度较高,但 Kubernetes 1.20 要求严格。
解决方案:必须执行 kubeadm init 生成配置文件:
sudo kubeadm init --apiserver-advertise-address=10.170.0.4 \
--control-plane-endpoint=cluster-endpoint \
--image-repository registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images \
--kubernetes-version v1.20.9 \
--service-cidr=10.96.0.0/16 \
--pod-network-cidr=192.168.0.0/16 \
--ignore-preflight-errors=SystemVerification
bash mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config
- CentOS 9 的特定差异
CentOS 9 默认使用 cgroups v2 和 firewalld 的严格规则,可能与 Kubernetes 1.20 的兼容性存在问题,导致kubeadm init失败。
为什么 CentOS 7.9 正常而 CentOS 9 失败?
CentOS 7.9 和 CentOS 9 在以下方面存在差异,可能导致相同步骤的结果不同:
| 差异点 | CentOS 7.9 | CentOS 9 |
|---|---|---|
| cgroups 版本 | 默认 cgroups v1 | 默认 cgroups v2 |
| 内核版本 | 3.10.x | 5.14.x |
| 防火墙管理 | iptables | firewalld + nftables |
| SELinux 策略 | 宽松模式 | 更严格的默认策略 |
| Kubernetes 软件源 | 可能使用旧版本仓库 | 可能缺少兼容性适配 |
重新初始化集群**
清理旧配置并重新初始化:
kubeadm reset -f
rm -rf /etc/kubernetes/ /var/lib/kubelet/
systemctl restart docker kubelet
sudo kubeadm init --apiserver-advertise-address=10.170.0.4 \
--control-plane-endpoint=cluster-endpoint \
--image-repository registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images \
--kubernetes-version v1.20.9 \
--service-cidr=10.96.0.0/16 \
--pod-network-cidr=192.168.0.0/16 \
--ignore-preflight-errors=SystemVerification
验证步骤
-
检查配置文件生成
初始化成功后,确认以下文件存在:
bash ls -l /etc/kubernetes/admin.conf # 集群管理员配置 ls -l /etc/kubernetes/kubelet.conf # kubelet 配置 ls -l /etc/kubernetes/pki # 证书目录 -
测试
kubectl连接
bash kubectl get nodes
正常应返回当前节点状态为Ready。 -
查看 kubelet 状态
bash systemctl status kubelet
状态应为Active: active (running)。
如果问题仍未解决,请提供完整的 kubeadm init 日志和 journalctl -u kubelet 输出,以便进一步诊断。
可能遇到问题
1、端口被占用(之前部署过k8s,但失败了)
查端口占用推荐命令
sudo lsof -i :10250
问题原因
从日志可见,etcd 启动失败的直接原因是 2380 端口已被占用:
2025-02-18 12:17:34.496128 C | etcdmain: listen tcp 10.170.0.4:2380: bind: address already in use
排查步骤
1. 查找占用 2380 端口的进程
sudo ss -tulnp | grep ':2380'
输出示例:
tcp LISTEN 0 128 10.170.0.4:2380 *:* users:(("etcd",pid=1234,fd=5))
2. 终止占用进程
根据上一步的 PID(例如 1234)终止进程:
sudo kill -9 1234
3. 检查残留的 etcd 容器
docker ps -a | grep etcd
- 如果发现旧的 etcd 容器,强制删除:
bash docker rm -f <CONTAINER_ID>
彻底清理 Kubernetes 残留
# 重置 kubeadm
sudo kubeadm reset -f
# 清理 etcd 数据目录
sudo rm -rf /var/lib/etcd/*
# 清理证书文件
sudo rm -rf /etc/kubernetes/pki/etcd
# 重启 Docker 和 kubelet
sudo systemctl restart docker kubelet
重新初始化集群
sudo kubeadm init \
--apiserver-advertise-address=10.170.0.4 \
--control-plane-endpoint=cluster-endpoint \
--image-repository registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images \
--kubernetes-version v1.20.9 \
--service-cidr=10.96.0.0/16 \
--pod-network-cidr=192.168.0.0/16 \
--ignore-preflight-errors=SystemVerification
关键预防措施
-
确保旧集群完全清理
每次初始化前执行:
bash kubeadm reset -f sudo rm -rf /etc/kubernetes/pki /var/lib/etcd -
检查端口占用
初始化前运行:
bash sudo ss -tulnp | grep -E '2379|2380|6443' -
使用
--ignore-preflight-errors=Port-2380(不推荐)
仅在确认端口占用是误报时使用:
bash kubeadm init ... --ignore-preflight-errors=Port-2380
补充说明
-
为什么 CentOS 7.9 正常而 CentOS 9 失败?
CentOS 9 默认使用 firewalld + nftables,可能未正确放行端口,而旧版本防火墙规则更宽松。 -
如何永久避免端口冲突?
如果 2380 端口被系统服务占用,可修改 etcd 监听端口:
bash # 在 kubeadm 配置文件中指定自定义端口 apiVersion: kubeadm.k8s.io/v1beta2 kind: ClusterConfiguration etcd: local: extraArgs: listen-peer-urls: "https://10.170.0.4:23800" # 改为其他端口
然后通过配置文件初始化:
bash kubeadm init --config=kubeadm-config.yaml
强制停止容器并禁止重启
要强制停止这两个容器并防止它们自动重启,需分两步操作:
1. 强制停止容器
# 停止 etcd 容器(替换为你的容器ID)
docker kill 157823d5b9d9
# 停止关联的 pause 容器(替换为你的容器ID)
docker kill 0892814b2d9e
2. 禁止 kubelet 自动重启 Pod
Kubernetes 控制平面组件(如 etcd)是通过 静态 Pod(Static Pod) 由 kubelet 直接管理的。只要 /etc/kubernetes/manifests/etcd.yaml 存在,kubelet 就会不断重启容器。要永久禁止重启,需删除该文件:
# 删除 etcd 的静态 Pod 定义文件
sudo rm /etc/kubernetes/manifests/etcd.yaml
# 重启 kubelet 使配置生效
sudo systemctl restart kubelet
彻底清理残留数据
# 重置 kubeadm
sudo kubeadm reset -f
# 清理 etcd 数据目录
sudo rm -rf /var/lib/etcd/*
# 清理 Docker 残留容器
docker ps -aq | xargs docker rm -f 2>/dev/null
验证端口占用
确保 2379 和 2380 端口未被占用:
sudo ss -tulnp | grep -E '2379|2380'
- 如果仍有进程占用,终止它们:
bash sudo kill -9 <PID>
重新初始化集群(可选)
如果需要重新部署集群,执行:
sudo kubeadm init \
--apiserver-advertise-address=10.170.0.4 \
--control-plane-endpoint=cluster-endpoint \
--image-repository registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images \
--kubernetes-version v1.20.9 \
--service-cidr=10.96.0.0/16 \
--pod-network-cidr=192.168.0.0/16 \
--ignore-preflight-errors=SystemVerification
关键说明
-
为什么 pause 容器需要停止?
pause 容器是 Kubernetes Pod 的基础容器,用于共享网络命名空间。停止 etcd Pod 时,其关联的 pause 容器也应一并停止。 -
如何防止未来自动重启?
删除/etc/kubernetes/manifests/etcd.yaml后,kubelet 不再监控该 Pod,因此不会自动重建。
彻底清除etcd
问题根源
即使你已经停止了容器,宿主机上仍有 独立的 etcd 进程 在运行并占用端口。这通常是因为:
- 之前通过非容器化方式(如直接运行
etcd二进制)启动了 etcd。 - 残留的 etcd 进程未彻底清理。
解决方案
1. 强制终止 etcd 进程
# 根据 PID 终止进程(替换为你的实际 PID)
sudo kill -9 27902
# 再次检查端口占用
sudo ss -tulnp | grep -E '2379|2380'
- 如果输出为空,说明端口已释放。
2. 检查是否有 systemd 管理的 etcd 服务
# 查看是否存在 etcd 服务
systemctl list-unit-files | grep etcd
# 如果存在,停止并禁用服务
sudo systemctl stop etcd
sudo systemctl disable etcd
3. 清理所有残留的 etcd 数据
# 清理数据目录
sudo rm -rf /var/lib/etcd/*
# 清理 Kubernetes 相关配置
sudo kubeadm reset -f
4. 重新初始化集群
sudo kubeadm init \
--apiserver-advertise-address=10.170.0.4 \
--control-plane-endpoint=cluster-endpoint \
--image-repository registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images \
--kubernetes-version v1.20.9 \
--service-cidr=10.96.0.0/16 \
--pod-network-cidr=192.168.0.0/16 \
--ignore-preflight-errors=SystemVerification
关键预防措施
-
禁止非容器化启动 etcd
确保没有手动或通过脚本启动etcd二进制文件。 -
彻底清理旧集群
每次初始化前执行:
bash sudo kubeadm reset -f sudo rm -rf /etc/kubernetes/pki /var/lib/etcd -
检查系统服务
如果系统安装了etcd包,卸载它:
bash sudo dnf remove etcd
补充说明
-
为什么容器外会有 etcd 进程?
可能因历史操作(如手动安装 etcd 或使用非 kubeadm 部署 Kubernetes)导致进程残留。 -
如何避免未来冲突?
始终通过kubeadm管理集群,避免混合使用容器化和宿主机进程。
问题原因
出现 The connection to the server localhost:8080 was refused 错误,说明以下问题之一:
- Kubernetes API Server 未运行(控制平面未启动)。
- kubectl 未正确配置(未指定或加载正确的
kubeconfig文件)。 - 证书或权限问题(如
admin.conf文件损坏或权限不足)。
逐步排查与解决方案
1. 检查 API Server 是否运行
API Server 是 Kubernetes 控制平面的核心组件,必须正常运行才能响应 kubectl 请求。
# 查看 kube-apiserver 容器状态
docker ps -a | grep kube-apiserver
# 如果容器处于 Exited 状态,查看日志
docker logs <kube-apiserver容器ID>
- 常见问题:
- 依赖组件未启动(如 etcd 崩溃)。
- 证书错误(如证书过期或配置错误)。
- 端口冲突(6443 端口被占用)。
2. 检查 kubectl 配置文件
默认情况下,kubectl 会尝试连接 localhost:8080,但正确配置应指向 API Server 的地址(如 https://<IP>:6443)。
# 确认是否已正确配置 kubeconfig
ls -l $HOME/.kube/config
# 如果文件不存在,手动复制 admin.conf
sudo mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
# 验证配置
kubectl cluster-info
3. 检查控制平面组件状态
如果 API Server 未运行,需确保所有依赖组件(如 etcd、kube-controller-manager)正常。
# 查看所有控制平面容器状态
docker ps -a | grep -E "etcd|kube-apiserver|kube-controller-manager|kube-scheduler"
# 重启 kubelet(触发组件重建)
sudo systemctl restart kubelet
4. 重新初始化集群
如果控制平面未正确初始化,需彻底清理后重试:
# 清理旧集群
sudo kubeadm reset -f
sudo rm -rf /etc/kubernetes/ /var/lib/etcd/* $HOME/.kube
# 重新初始化
sudo kubeadm init \
--apiserver-advertise-address=10.170.0.4 \
--control-plane-endpoint=cluster-endpoint \
--image-repository registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images \
--kubernetes-version v1.20.9 \
--service-cidr=10.96.0.0/16 \
--pod-network-cidr=192.168.0.0/16 \
--ignore-preflight-errors=SystemVerification
# 重新配置 kubectl
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
5. 检查防火墙和 SELinux
确保防火墙允许 API Server 端口(6443)通信:
# 放行 6443 端口
sudo firewall-cmd --permanent --add-port=6443/tcp
sudo firewall-cmd --reload
# 临时禁用 SELinux(仅用于测试)
sudo setenforce 0
验证集群状态
# 检查节点状态
kubectl get nodes
# 检查所有 Pod 状态
kubectl get pods -A
kubectl get pods -A -w 实时监控
- 预期输出:
- 节点状态应为Ready。
-kube-system命名空间下的核心组件(如kube-apiserver、etcd)应处于Running状态。
常见问题处理
场景 1:API Server 容器持续崩溃
- 检查日志:
bash docker logs <kube-apiserver容器ID> - 可能原因:
- etcd 连接失败:确保 etcd 容器正常运行。
- 证书错误:清理并重新生成证书:
bash sudo rm -rf /etc/kubernetes/pki sudo kubeadm init phase certs all
场景 2:kubeconfig 文件权限问题
- 修复权限:
bash sudo chmod 600 $HOME/.kube/config
场景 3:控制平面组件镜像拉取失败
- 手动拉取镜像:
bash docker pull registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/kube-apiserver:v1.20.9 docker pull registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/etcd:3.4.13-0
补充说明
-
control-plane-endpoint解析问题
如果使用自定义域名(如cluster-endpoint),需在/etc/hosts中添加解析:
bash echo "10.170.0.4 cluster-endpoint" | sudo tee -a /etc/hosts -
安装网络插件
初始化后必须安装网络插件(如 Calico):
bash kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml
如果问题仍未解决,请提供以下信息:
docker ps -a的输出。journalctl -u kubelet的日志片段。kubectl cluster-info的完整错误信息。
2、kubectl get nodes 显示nodeready,怎么排查
1. 检查节点状态与详细信息
kubectl get nodes # 确认节点状态
kubectl describe node <节点名称> # 查看详细状态与事件
- 关键观察点:
-Conditions字段:检查Ready、MemoryPressure、DiskPressure、PIDPressure等状态是否异常 。
-Events字段:查看是否有网络、存储或组件错误提示 。
2. 检查系统日志与 Kubelet 日志
# 操作系统日志(如 /var/log/syslog 或 /var/log/messages)
tail -f /var/log/syslog | grep -i error # 实时查看错误日志
# Kubelet 日志
journalctl -u kubelet -f # 查看 Kubelet 运行状态
- 常见错误:
-NetworkPluginNotReady:CNI 插件未初始化(需检查网络配置)。
-Failed to get system container stats:Docker/Containerd 服务异常 。
3. 验证 Kubelet 服务状态
systemctl status kubelet # 检查服务是否运行
systemctl restart kubelet # 尝试重启服务
- 配置检查:
- 确认/etc/kubernetes/kubelet.conf和/var/lib/kubelet/config.yaml配置正确(如 API 地址、证书路径)。
- 检查--cgroup-driver是否与 Docker/Containerd 一致(推荐systemd)。
4. 检查资源使用情况
# 资源压力诊断
kubectl top node <节点名称> # 查看 CPU/内存使用率
df -h # 检查磁盘空间
free -h # 检查内存剩余
- 异常处理:
- 若DiskPressure为True:清理磁盘或扩展存储 。
- 若MemoryPressure为True:终止高内存进程或增加节点资源 。
5. 检查网络连通性
# 与 Master 节点通信
ping <master-ip> # 测试网络连通性
nc -zv <master-ip> 6443 # 检查 API 端口
# 节点间通信
ping <其他节点-ip> # 验证集群内部网络
- 网络问题:
- 若NetworkUnavailable为True:检查 CNI 插件(如 Calico、Flannel)配置 。
- 检查防火墙规则是否阻止节点间通信 。
6. 检查 CNI 插件与容器运行时
# 检查 CNI 插件状态(如 Calico)
kubectl -n kube-system get pods -l k8s-app=calico-node -o wide
# 检查 Docker/Containerd 服务
systemctl status docker # 或 systemctl status containerd
- 常见问题:
- CNI 插件未正确初始化:需重新部署或修复配置 。
- 容器运行时异常:重启服务或检查日志 。
7. 使用节点问题检测器(Node Problem Detector)
kubectl get pods -n kube-system -l app=node-problem-detector # 检查检测器 Pod 状态
kubectl logs <node-problem-detector-pod> -n kube-system # 查看检测报告
- 作用:自动检测内核崩溃、文件系统错误等问题 。
8. 其他可能原因
- Swap 空间:确保节点关闭 Swap(
swapoff -a)。 - 内核参数:检查
/proc/sys/kernel/pid_max是否足够(PID 压力时需调整)。 - 证书过期:检查 etcd 和 Kubernetes 组件证书有效期 。
总结步骤
- 执行
kubectl describe node定位具体问题类型(资源、网络、组件等)。 - 根据问题类型排查对应方向(如重启 Kubelet、释放资源、修复网络)。
- 若问题持续,结合日志和检测器报告进一步分析 。
提示:若节点长期处于 NotReady,可考虑将其标记为不可调度(kubectl cordon <节点名称>)并迁移 Pod 。
验证步骤
-
检查 kubelet 状态:
bash systemctl status kubelet
输出应为Active: active (running)。 -
查看集群节点:
bash kubectl get nodes
节点状态应为Ready。 -
检查 Pod 状态:
bash kubectl get pods -A
所有核心组件(如kube-apiserver、kube-controller-manager)应处于Running状态。
故障排查
如果仍存在问题,检查以下日志:
# kubelet 日志
journalctl -xeu kubelet
# kubeadm init 日志
kubeadm init ... --v=5 # 添加详细日志级别
重点关注以下错误:
Failed to start ContainerManager: cgroups 配置问题。connection refused: API Server 未启动或防火墙阻止。certificate signed by unknown authority: 证书配置错误。
kubeadm快速初始化主节点
sudo kubeadm init --apiserver-advertise-address=10.170.0.4 \
--control-plane-endpoint=cluster-endpoint \
--image-repository registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images \
--kubernetes-version v1.20.9 \
--service-cidr=10.96.0.0/16 \
--pod-network-cidr=192.168.0.0/16 \
--ignore-preflight-errors=SystemVerification
最终成功
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/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown (id -g) $HOME/.kube/config
Alternatively, if you are the root user, you can run:
export KUBECONFIG=/etc/kubernetes/admin.conf
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
You can now join any number of control-plane nodes by copying certificate authorities
and service account keys on each node and then running the following as root:
kubeadm join cluster-endpoint:6443 --token b05gtp.g8y6f39dqj6a4n7a \
--discovery-token-ca-cert-hash sha256:12b2a04ff8837af389fd4263c20bc9aa7ff18d9c7a6cce888f1c2a3cef4d6604 \
--control-plane
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join cluster-endpoint:6443 --token b05gtp.g8y6f39dqj6a4n7a \
--discovery-token-ca-cert-hash sha256:12b2a04ff8837af389fd4263c20bc9aa7ff18d9c7a6cce888f1c2a3cef4d6604
过期后使用 新令牌
kubeadm token create --print-join-command
kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master-20250214 NotReady control-plane,master 2m58s v1.20.9
kubectl get pods -n kube-system | grep apiserver
kube-apiserver-k8s-master-20250214 1/1 Running 0 4m26s
docker ps -a | grep -E "kube-apiserver|kube-controller-manager|kube-scheduler|etcd"
9ccfa1663c60 eb07fd4ad3b4 "kube-controller-man…" 5 minutes ago Up 5 minutes k8s_kube-controller-manager_kube-controller-manager-k8s-master-20250214_kube-system_b1bffdcf877d2595795dcfce013a763f_0
e4495b3c2d03 0d0d57e4f64c "kube-apiserver --ad…" 5 minutes ago Up 5 minutes k8s_kube-apiserver_kube-apiserver-k8s-master-20250214_kube-system_e6ab64a4693463833225fb27f38fa605_0
eb6e29f66c1d 0369cf4303ff "etcd --advertise-cl…" 5 minutes ago Up 5 minutes k8s_etcd_etcd-k8s-master-20250214_kube-system_5fca6841db74b45a8119bd8f3ea09e0b_0
c75afce9c577 295014c114b3 "kube-scheduler --au…" 5 minutes ago Up 5 minutes k8s_kube-scheduler_kube-scheduler-k8s-master-20250214_kube-system_7feb7bfbba18944ee2b6bf81257c9648_0
9f76013fb3cc registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/pause:3.2 "/pause" 5 minutes ago Up 5 minutes k8s_POD_kube-controller-manager-k8s-master-20250214_kube-system_b1bffdcf877d2595795dcfce013a763f_0
2864a5a209d5 registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/pause:3.2 "/pause" 5 minutes ago Up 5 minutes k8s_POD_kube-apiserver-k8s-master-20250214_kube-system_e6ab64a4693463833225fb27f38fa605_0
f897fe9134f6 registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/pause:3.2 "/pause" 5 minutes ago Up 5 minutes k8s_POD_etcd-k8s-master-20250214_kube-system_5fca6841db74b45a8119bd8f3ea09e0b_0
5cdf81b57cbd registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/pause:3.2 "/pause" 5 minutes ago Up 5 minutes k8s_POD_kube-scheduler-k8s-master-20250214_kube-system_7feb7bfbba18944ee2b6bf81257c9648_0
三、安装网络插件让k8s集群所有机器网络串起来
Installing on on-premises deployments | Calico Documentation
curl docs.projectcalico.org/v3.20/manif… -O
kubectl apply -f calico.yaml
cat calico.yaml | grep 192.168 用默认的,不要改
四、K8s常用命令:
#查看集群所有节点
kubectl get nodes
#根据配置文件,给集群创建资源
kubectl apply -f xxxx.yaml
#查看集群部署了哪些应用?
kubectl get pods -A (等价于docker ps)
运行中的应用在docker里面叫容器,在k8s里面叫Pod
kubectl get pods -A
kubectl get pods 默认只看default namespace下的应用
kubectl get pods -n kubernetes-dashboard 指定namespace查看
NAME READY STATUS RESTARTS AGE
dashboard-metrics-scraper-79c5968bdc-tmmbv 1/1 Running 0 24h
kubernetes-dashboard-658485d5c7-t76d2 1/1 Running 0 23m
不指定,默认都部署到default 命名空间。
kind:Namespace、pod等
apiVersion: v1
kind: Namespace
metadata:
name: hello
资源文件方式部署
kubectl apply -f pod.yaml
kubectl delete -f pod.yaml
create直接启动
kubectl create ns hello
kubectl delete ns hello
kubectl run mynginx --image=nginx
查看default名称空间的Pod
kubectl get pod
描述
kubectl describe pod 你自己的Pod名字
删除
kubectl delete pod Pod名字
查看Pod的运行日志
kubectl logs Pod名字
每个Pod - k8s都会分配一个ip
kubectl get pod -owide
使用Pod的ip+pod里面运行容器的端口
curl 192.168.169.136
集群中的任意一个机器以及任意的应用都能通过Pod分配的ip来访问这个Pod
进入部署好的服务
kubectl exec -it mynginx -- /bin/bash
五、搭建自带监控平台
监控端口暴露到服务器上
kubectl edit svc kubernetes-dashboard -n kubernetes-dashboard
type: ClusterIP 改为 type: NodePort
kubectl get pods -n kubernetes-dashboard
访问: https://集群任意IP:端口 https://x.x.x.x:32759
发现浏览器访问报错dashborad证书问题
在 Kubernetes 中,Kubernetes Dashboard 默认使用的证书存储在其相关的 Secret 对象里。以下为你详细介绍查看 Dashboard 默认生成证书路径的具体步骤:
1. 确认 Secret 对象名称
通常,Kubernetes Dashboard 使用名为 kubernetes-dashboard-certs 的 Secret 对象来存储证书。你可以通过以下命令来确认:
kubectl get secrets -n kubernetes-dashboard
在输出结果里查找与证书相关的 Secret 对象,一般就是 kubernetes-dashboard-certs。
2. 查看 Secret 详情
找到 Secret 对象名称之后,使用下面的命令查看其详情:
kubectl describe secret kubernetes-dashboard-certs -n kubernetes-dashboard
输出结果会展示该 Secret 对象的详细信息,不过证书数据是以 Base64 编码形式存储的。
3. 获取证书数据
若你想获取证书的实际内容,可以使用以下命令将其解码并输出:
kubectl get secret kubernetes-dashboard-certs -n kubernetes-dashboard -o jsonpath='{.data.tls.crt}' | base64 -d > dashboard.crt kubectl get secret kubernetes-dashboard-certs -n kubernetes-dashboard -o jsonpath='{.data.tls.key}' | base64 -d > dashboard.key
上述命令会把证书和私钥分别解码并保存到 dashboard.crt 和 dashboard.key 文件中。
4. 证书在容器内的挂载路径
Kubernetes Dashboard Pod 在启动时会把这个 Secret 挂载到容器内的特定路径。你可以通过查看 Dashboard Deployment 的配置来确定挂载路径:
kubectl get deployment kubernetes-dashboard -n kubernetes-dashboard -o yaml
在输出的 YAML 文件里查找 volumeMounts 部分,通常证书会被挂载到 /certs 目录下,例如:
volumeMounts: - mountPath: /certs name: kubernetes-dashboard-certs
这就表明证书在 Dashboard 容器内的路径为 /certs/tls.crt 和 /certs/tls.key。
综上所述,你可以通过查看 Secret 对象获取证书数据,同时通过 Deployment 配置确定证书在容器内的挂载路径。
你通过 find 命令查找到的 /etc/kubernetes/pki/dashboard/dashboard.key 和 /etc/kubernetes/pki/dashboard/dashboard.crt 路径可能是对的,但要根据实际情况来判断,以下为你分析不同场景:
可能正确的情况
- 手动创建证书并指定路径
如果在部署 Kubernetes Dashboard 之前,你手动创建了自签名证书,并将其放置在 /etc/kubernetes/pki/dashboard/ 目录下,同时在部署 Dashboard 时配置使用这些证书,那么这个路径就是正确的。例如,在使用 openssl 生成证书后,你将 dashboard.key 和 dashboard.crt 复制到了该目录。
- 自动化部署脚本指定
某些自动化部署脚本(如 Ansible 或自定义的 shell 脚本)在部署 Kubernetes 集群和 Dashboard 时,可能会将生成的证书存储在 /etc/kubernetes/pki/dashboard/ 目录下。如果你的集群是通过此类脚本部署的,那么这两个文件位于该目录是合理的。
可能错误的情况
- 使用 Secret 挂载证书
在 Kubernetes 中,更常见的做法是使用 Secret 对象来管理证书,并将其挂载到 Dashboard Pod 中。这种情况下,证书不会直接存储在节点的 /etc/kubernetes/pki/dashboard/ 目录下,而是在 Pod 内部的挂载路径中,通常是 /certs 目录(具体取决于 Deployment 的配置)。你可以通过以下命令查看 Dashboard Pod 的挂载情况:
kubectl get deployment kubernetes-dashboard -n kubernetes-dashboard -o yaml | grep -A 5 volumeMounts
- 默认自动生成
如果没有手动干预,Kubernetes Dashboard 可能会自动生成证书并将其存储在 Secret 中,而不是存储在节点的文件系统中。你可以通过以下命令查看 Dashboard 使用的 Secret:
kubectl get secrets -n kubernetes-dashboard | grep dashboard
验证方法
如果你想确定这两个文件是否为 Dashboard 使用的证书,可以通过以下步骤验证:
- 从 Secret 中提取证书数据:
kubectl get secret kubernetes-dashboard-certs -n kubernetes-dashboard -o jsonpath='{.data.tls.crt}' | base64 -d > secret-dashboard.crt kubectl get secret kubernetes-dashboard-certs -n kubernetes-dashboard -o jsonpath='{.data.tls.key}' | base64 -d > secret-dashboard.key
- 比较文件内容:
diff /etc/kubernetes/pki/dashboard/dashboard.crt secret-dashboard.crt diff /etc/kubernetes/pki/dashboard/dashboard.key secret-dashboard.key
如果比较结果没有差异,说明这两个文件就是 Dashboard 使用的证书。
如果 diff 命令没有输出,就说明文件内容一致,即你找到的文件就是 Dashboard 使用的证书和私钥;若有输出,则表示文件内容不同,需要进一步排查。
当 diff 命令有输出,且 Chrome 浏览器访问时证书报错无法解码,这表明你找到的本地证书文件 /etc/kubernetes/pki/dashboard/dashboard.crt 和 kubernetes-dashboard-certs 中存储的证书不一致,同时证书可能存在问题导致浏览器无法正确解析。以下是一些可以解决该问题的步骤:
1. 确认并更新 Dashboard 使用的证书
提取并更新 Secret 中的证书
如果要确保使用的是正确的证书,你可以使用本地的 dashboard.crt 和 dashboard.key 来更新 kubernetes-dashboard-certs 这个 Secret 对象。执行以下命令:
kubectl create secret generic kubernetes-dashboard-certs --from-file=/etc/kubernetes/pki/dashboard/dashboard.crt --from-file=/etc/kubernetes/pki/dashboard/dashboard.key -n kubernetes-dashboard --dry-run=client -o yaml | kubectl apply -f -
上述命令会使用本地的证书文件更新 kubernetes-dashboard-certs Secret,--dry-run=client -o yaml 用于预览操作内容,然后通过 kubectl apply -f - 应用更改。
重启 Dashboard Pod
更新 Secret 后,需要重启 Kubernetes Dashboard 的 Pod 使新证书生效:
kubectl delete pods -n kubernetes-dashboard -l k8s-app=kubernetes-dashboard
这会删除当前运行的 Dashboard Pod,Kubernetes 会自动重新创建新的 Pod 并使用更新后的证书。
2. 检查证书的有效性
证书格式和内容
确保 dashboard.crt 和 dashboard.key 文件格式正确且内容完整。可以使用以下命令查看证书的基本信息:
openssl x509 -noout -text -in /etc/kubernetes/pki/dashboard/dashboard.crt
该命令会输出证书的详细信息,包括颁发者、有效期、域名等,检查这些信息是否正确。
证书有效期
确认证书是否在有效期内,如果证书已过期,需要重新生成证书。可以使用 openssl 生成自签名证书,示例命令如下:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/kubernetes/pki/dashboard/dashboard.key -out /etc/kubernetes/pki/dashboard/dashboard.crt -subj "/CN=35.241.123.85"
此命令会生成一个有效期为 365 天的自签名证书,/CN 指定了证书的通用名称,这里设置为你的 IP 地址 35.241.123.85。生成新证书后,按照前面的步骤更新 Secret 并重启 Dashboard Pod。
3. 浏览器信任问题
自签名证书
由于你使用的可能是自签名证书,浏览器默认不信任此类证书。你可以在浏览器中手动导入 dashboard.crt 证书来解决信任问题。以 Chrome 浏览器为例:
-
打开 Chrome 浏览器,点击右上角的三个点,选择“设置”。
-
在设置中搜索“管理证书”,点击“证书”选项。
-
在“受信任的根证书颁发机构”选项卡中,点击“导入”按钮,选择
dashboard.crt文件,按照向导完成导入。
4. 网络和防火墙问题
防火墙规则
确保防火墙允许访问 Dashboard 的端口(通常是 443 或其他自定义端口)。你可以检查服务器上的防火墙规则,例如使用 firewalld 或 iptables,确保相应端口开放:
# 对于 firewalld
sudo firewall-cmd --zone=public --add-port=443/tcp --permanent
sudo firewall-cmd --reload
# 对于 iptables
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
网络连接
检查网络连接是否正常,确保没有中间设备(如路由器、代理等)干扰了连接。你可以尝试在不同的网络环境下访问 Dashboard,或者使用 ping 和 telnet 命令测试网络连通性:
ping 35.241.123.85
telnet 35.241.123.85 443
通过以上步骤,你应该能够解决证书报错无法解码的问题,使 Chrome 浏览器可以正常访问 Kubernetes Dashboard。
终于成功!
六、K8s里的资源对象
1)Namespace
2)Pod
3)Deployment
控制Pod,使Pod拥有多副本,自愈,扩缩容等能力
清除所有Pod,比较下面两个命令有何不同效果?
kubectl run mynginx --image=nginx
kubectl create deployment mytomcat --image=tomcat:8.5.68
自愈能力
1、多副本
watch -n 1 kubectl get pod 实时监测
kubectl get pod -w 列表方式打印记录
2、扩缩容
3、自愈&故障转移
4、滚动更新
kubectl get deploy my-dep -oyaml
kubectl rollout history deploy/my-dep
deployment.apps/my-dep
REVISION CHANGE-CAUSE
1
2 kubectl set image deployment/my-dep nginx=nginx:1.16.1 --record=true
kubectl rollout undo deployment/my-dep --to-revision=1
kubectl set image deployment/my-dep nginx=nginx:1.16.1 --record
kubectl rollout status deployment/my-dep
5、版本回退
#历史记录
kubectl rollout history deployment/my-dep
#查看某个历史详情
kubectl rollout history deployment/my-dep --revision=2
#回滚(回到上次)
kubectl rollout undo deployment/my-dep
#回滚(回到指定版本)
kubectl rollout undo deployment/my-dep --to-revision=2
更多:
除了Deployment,k8s还有 StatefulSet 、DaemonSet 、Job 等 类型资源。我们都称为 工作负载。
有状态应用使用 StatefulSet 部署,无状态应用使用 Deployment 部署
4)Service
将一组 Pods 公开为网络服务的抽象方法。
暴露的既可以内部ip:port 也可以使用域名。域名规则:服务名.所在命名空间.svc:port
1、ClusterIP
等同于没有--type的,默认为ClusterIP
kubectl expose deployment my-dep --port=8000 --target-port=80 --type=ClusterIP
apiVersion: v1
kind: Service
metadata:
labels:
app: my-dep
name: my-dep
spec:
ports:
- port: 8000
protocol: TCP
targetPort: 80
selector:
app: my-dep
type: ClusterIP
2、NodePort
kubectl expose deployment my-dep --port=8000 --target-port=80 --type=NodePort
apiVersion: v1
kind: Service
metadata:
labels:
app: my-dep
name: my-dep
spec:
ports:
- port: 8000
protocol: TCP
targetPort: 80
selector:
app: my-dep
type: NodePort
NodePort范围在 30000-32767 之间
5)Ingress
Service的统一网关入口
6)存储抽象
1、所有节点
#所有机器安装
yum install -y nfs-utils
2、主节点
#nfs主节点
echo "/nfs/data/ *(insecure,rw,sync,no_root_squash)" > /etc/exports
mkdir -p /nfs/data
systemctl enable rpcbind --now
systemctl enable nfs-server --now
#配置生效
exportfs -r
3、从节点
showmount -e 172.31.0.4
#执行以下命令挂载 nfs 服务器上的共享目录到本机路径 /root/nfsmount
mkdir -p /nfs/data
mount -t nfs 172.31.0.4:/nfs/data /nfs/data
# 写入一个测试文件
echo "hello nfs server" > /nfs/data/test.txt
4、原生方式数据挂载
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx-pv-demo
name: nginx-pv-demo
spec:
replicas: 2
selector:
matchLabels:
app: nginx-pv-demo
template:
metadata:
labels:
app: nginx-pv-demo
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
nfs:
server: 172.31.0.4
path: /nfs/data/nginx-pv
①PV&PVC
PV:持久卷(Persistent Volume),将应用需要持久化的数据保存到指定位置
PVC:持久卷申明( Persistent Volume Claim ),申明需要使用的持久卷规格
a.创建pv池
静态供应
#nfs主节点
mkdir -p /nfs/data/01
mkdir -p /nfs/data/02
mkdir -p /nfs/data/03
创建PV
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv01-10m
spec:
capacity:
storage: 10M
accessModes:
- ReadWriteMany
storageClassName: nfs
nfs:
path: /nfs/data/01
server: 172.31.0.4
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv02-1gi
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteMany
storageClassName: nfs
nfs:
path: /nfs/data/02
server: 172.31.0.4
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv03-3gi
spec:
capacity:
storage: 3Gi
accessModes:
- ReadWriteMany
storageClassName: nfs
nfs:
path: /nfs/data/03
server: 172.31.0.4
b.PVC创建与绑定
创建PVC
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: nginx-pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 200Mi
storageClassName: nfs
创建Pod绑定PVC
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx-deploy-pvc
name: nginx-deploy-pvc
spec:
replicas: 2
selector:
matchLabels:
app: nginx-deploy-pvc
template:
metadata:
labels:
app: nginx-deploy-pvc
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
persistentVolumeClaim:
claimName: nginx-pvc
ConfigMap
抽取应用配置,并且可以自动更新
专门用于存储配置
挂载到redis的/redis-master目录下
内容是configMap为redis-conf中的内容
文件名是path,即redis.conf
六、总结
高版本搭建参考:
在centos stream 9上搭建k8s最新版本(当前:v1.26.1)集群环境 - zengql - 博客园