GCP Centos 9基于docker搭建k8s

134 阅读21分钟

一、安装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

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 默认使用 firewalldnftables,需显式放行 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-cmdfirewalld服务的命令行工具,停止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    

  1. CentOS 9 的特定差异  
    CentOS 9 默认使用 cgroups v2firewalld 的严格规则,可能与 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

验证步骤

  1. 检查配置文件生成  
    初始化成功后,确认以下文件存在:
    bash    ls -l /etc/kubernetes/admin.conf  # 集群管理员配置    ls -l /etc/kubernetes/kubelet.conf  # kubelet 配置    ls -l /etc/kubernetes/pki  # 证书目录    

  2. 测试 kubectl 连接  
    bash    kubectl get nodes    
    正常应返回当前节点状态为 Ready

  3. 查看 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  

关键预防措施

  1. 确保旧集群完全清理  
    每次初始化前执行:
    bash    kubeadm reset -f    sudo rm -rf /etc/kubernetes/pki /var/lib/etcd    

  2. 检查端口占用  
    初始化前运行:
    bash    sudo ss -tulnp | grep -E '2379|2380|6443'    

  3. 使用 --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 进程 在运行并占用端口。这通常是因为:

  1. 之前通过非容器化方式(如直接运行 etcd 二进制)启动了 etcd。
  2. 残留的 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  

关键预防措施

  1. 禁止非容器化启动 etcd  
    确保没有手动或通过脚本启动 etcd 二进制文件。

  2. 彻底清理旧集群  
    每次初始化前执行:
    bash    sudo kubeadm reset -f    sudo rm -rf /etc/kubernetes/pki /var/lib/etcd    

  3. 检查系统服务  
    如果系统安装了 etcd 包,卸载它:
    bash    sudo dnf remove etcd    


补充说明

  • 为什么容器外会有 etcd 进程?  
    可能因历史操作(如手动安装 etcd 或使用非 kubeadm 部署 Kubernetes)导致进程残留。

  • 如何避免未来冲突?  
    始终通过 kubeadm 管理集群,避免混合使用容器化和宿主机进程。



问题原因

出现 The connection to the server localhost:8080 was refused 错误,说明以下问题之一:

  1. Kubernetes API Server 未运行(控制平面未启动)。
  2. kubectl 未正确配置(未指定或加载正确的 kubeconfig 文件)。
  3. 证书或权限问题(如 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-apiserveretcd)应处于 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  

如果问题仍未解决,请提供以下信息:

  1. docker ps -a 的输出。
  2. journalctl -u kubelet 的日志片段。
  3. kubectl cluster-info 的完整错误信息。

2、kubectl get nodes 显示nodeready,怎么排查

1. 检查节点状态与详细信息

kubectl get nodes  # 确认节点状态   
kubectl describe node <节点名称>  # 查看详细状态与事件   
  • 关键观察点
    - Conditions 字段:检查 ReadyMemoryPressureDiskPressurePIDPressure 等状态是否异常 。
    - 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  # 检查内存剩余   
  • 异常处理
    - 若 DiskPressureTrue:清理磁盘或扩展存储 。
    - 若 MemoryPressureTrue:终止高内存进程或增加节点资源 。

5. 检查网络连通性

# 与 Master 节点通信  
ping <master-ip>  # 测试网络连通性   
nc -zv <master-ip> 6443  # 检查 API 端口 

# 节点间通信  
ping <其他节点-ip>  # 验证集群内部网络   
  • 网络问题
    - 若 NetworkUnavailableTrue:检查 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 组件证书有效期 。

总结步骤

  1. 执行 kubectl describe node 定位具体问题类型(资源、网络、组件等)。
  2. 根据问题类型排查对应方向(如重启 Kubelet、释放资源、修复网络)。
  3. 若问题持续,结合日志和检测器报告进一步分析 。

提示:若节点长期处于 NotReady,可考虑将其标记为不可调度(kubectl cordon <节点名称>)并迁移 Pod 。


验证步骤

  1. 检查 kubelet 状态
    bash    systemctl status kubelet    
    输出应为 Active: active (running)

  2. 查看集群节点
    bash    kubectl get nodes    
    节点状态应为 Ready

  3. 检查 Pod 状态
    bash    kubectl get pods -A    
    所有核心组件(如 kube-apiserverkube-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 (idu):(id -u):(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:

  kubernetes.io/docs/concep…

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.crtdashboard.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 路径可能是对的,但要根据实际情况来判断,以下为你分析不同场景:

可能正确的情况

  1. 手动创建证书并指定路径

如果在部署 Kubernetes Dashboard 之前,你手动创建了自签名证书,并将其放置在 /etc/kubernetes/pki/dashboard/ 目录下,同时在部署 Dashboard 时配置使用这些证书,那么这个路径就是正确的。例如,在使用 openssl 生成证书后,你将 dashboard.keydashboard.crt 复制到了该目录。

  1. 自动化部署脚本指定

某些自动化部署脚本(如 Ansible 或自定义的 shell 脚本)在部署 Kubernetes 集群和 Dashboard 时,可能会将生成的证书存储在 /etc/kubernetes/pki/dashboard/ 目录下。如果你的集群是通过此类脚本部署的,那么这两个文件位于该目录是合理的。

可能错误的情况

  1. 使用 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

  1. 默认自动生成

如果没有手动干预,Kubernetes Dashboard 可能会自动生成证书并将其存储在 Secret 中,而不是存储在节点的文件系统中。你可以通过以下命令查看 Dashboard 使用的 Secret:

kubectl get secrets -n kubernetes-dashboard | grep dashboard

验证方法

如果你想确定这两个文件是否为 Dashboard 使用的证书,可以通过以下步骤验证:

  1. 从 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

  1. 比较文件内容:

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.crtkubernetes-dashboard-certs 中存储的证书不一致,同时证书可能存在问题导致浏览器无法正确解析。以下是一些可以解决该问题的步骤:

1. 确认并更新 Dashboard 使用的证书

提取并更新 Secret 中的证书

如果要确保使用的是正确的证书,你可以使用本地的 dashboard.crtdashboard.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.crtdashboard.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 浏览器为例:

  1. 打开 Chrome 浏览器,点击右上角的三个点,选择“设置”。

  2. 在设置中搜索“管理证书”,点击“证书”选项。

  3. 在“受信任的根证书颁发机构”选项卡中,点击“导入”按钮,选择 dashboard.crt 文件,按照向导完成导入。

4. 网络和防火墙问题

防火墙规则

确保防火墙允许访问 Dashboard 的端口(通常是 443 或其他自定义端口)。你可以检查服务器上的防火墙规则,例如使用 firewalldiptables,确保相应端口开放:


# 对于 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,或者使用 pingtelnet 命令测试网络连通性:


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还有 StatefulSetDaemonSetJob 等 类型资源。我们都称为 工作负载

有状态应用使用 StatefulSet 部署,无状态应用使用 Deployment 部署

工作负载管理 | Kubernetes

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 - 博客园