news 2026/9/25 20:07:46

云原生监控与 CI/CD 基础实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
云原生监控与 CI/CD 基础实践

课程范围:19-云原生监控系统 Prometheus 告警和高级管理 | 20-代码私有仓库 Git 和 GitLab | 21-代码私有仓库 GitLab 管理和 Jenkins 基础

实验环境:Ubuntu2404(最小化安装),2 台虚拟机(可按课程要求扩展为 1 主 2 从)

国内源说明:本实验所有软件源、镜像源、插件源均使用国内源(阿里云 / 清华 / DaoCloud 等),无需科学上网。

角色主机名IP配置
Master(控制节点)k8s-master10.0.0.2002C/4G
Node1(工作节点)k8s-node110.0.0.812C/8G(GitLab 较吃内存)

第一部分:K8s 集群创建(第 19 课前置环境)

1.1 基础环境配置【所有节点执行】

1.设置主机名

2.配置hosts解析

3.关闭防火墙、swap

4.时间同步

5.加载内核模块、开启转发(Ubuntu用modules-load持久化)

6.安装ipvs依赖

7.修复 systemd-resolved(Ubuntu 24.04 的 /etc/resolv.conf 指向 127.0.0.53,
会导致 kubelet 解析异常,改为指向真实 DNS)

1.2 配置阿里云 apt 源【所有节点执行】

1.3 安装 containerd 容器运行时并配置国内镜像加速【所有节点执行】

K8s 1.24+ 已移除 dockershim,此处安装 containerd(来自阿里云 docker-ce 仓库),并配置 DaoCloud 国内镜像加速,后续 Prometheus / GitLab / Jenkins 官方镜像均可直接拉取,无需修改任何镜像名。

1.4 安装 kubeadm / kubelet / kubectl(阿里云 kubernetes-new 源,apt 版)【所有节点执行】

注意:阿里云 Kubernetes apt 仓库的密钥和包都在v1.30/deb/目录下(密钥为deb/Release.key),仓库地址以/结尾(flat 仓库格式),不要写成 stable/main 普通仓库格式。

1.5 初始化集群【Master 执行】

1.5.1 故障排查:API server is not healthy / kubelet 未运行【Master 执行】

若 init 报The API server is not healthy after 4m0s,按以下顺序定位:

# 1. 看控制面容器状态(哪个在 CrashLoopBackOff / Exited)
crictl --runtime-endpoint unix:///var/run/containerd/containerd.sock ps -a | grep -E 'kube|etcd|pause'

# 2. 看 kubelet 报错(最关键)
systemctl status kubelet --no-pager -l
journalctl -u kubelet --no-pager | tail -50

# 3. 看失败容器日志
crictl --runtime-endpoint unix:///var/run/containerd/containerd.sock logs <CONTAINERID>

常见原因 A:cgroup 驱动不一致(journalctl 出现cgroup driver字样):

grep -n "SystemdCgroup" /etc/containerd/config.toml # 必须为 true
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
systemctl restart containerd kubelet

常见原因 B:containerd 启动失败(mirrors 旧写法不兼容):改用官方certs.d目录方式配置镜像加速:

sed -i '/registry.mirrors/,$d' /etc/containerd/config.toml
sed -i 's#config_path = ""#config_path = "/etc/containerd/certs.d"#' /etc/containerd/config.toml
mkdir -p /etc/containerd/certs.d/{docker.io,registry.k8s.io,quay.io,ghcr.io,gcr.io}
cat > /etc/containerd/certs.d/docker.io/hosts.toml <<'EOF'
server = "https://registry-1.docker.io"
[host."https://docker.m.daocloud.io"]
capabilities = ["pull", "resolve"]
EOF
cat > /etc/containerd/certs.d/registry.k8s.io/hosts.toml <<'EOF'
server = "https://registry.k8s.io"
[host."https://k8s.m.daocloud.io"]
capabilities = ["pull", "resolve"]
EOF
cat > /etc/containerd/certs.d/quay.io/hosts.toml <<'EOF'
server = "https://quay.io"
[host."https://quay.m.daocloud.io"]
capabilities = ["pull", "resolve"]
EOF
cat > /etc/containerd/certs.d/ghcr.io/hosts.toml <<'EOF'
server = "https://ghcr.io"
[host."https://ghcr.m.daocloud.io"]
capabilities = ["pull", "resolve"]
EOF
cat > /etc/containerd/certs.d/gcr.io/hosts.toml <<'EOF'
server = "https://gcr.io"
[host."https://gcr.m.daocloud.io"]
capabilities = ["pull", "resolve"]
EOF
systemctl restart containerd kubelet

常见原因 C:sandbox 沙箱镜像拉取超时(containerd 日志出现failed to resolve "registry.k8s.io/pause:xxx" ... i/o timeout,kubelet 报CreatePodSandbox ... connection refused)

# 1. config_path 必须已指向 certs.d(否则加速不生效)
sed -i 's#config_path = ""#config_path = "/etc/containerd/certs.d"#g' /etc/containerd/config.toml

# 2. sandbox_image 只替换前缀、保留版本号(兼容不同 containerd 默认的 pause 版本)
sed -i 's#sandbox_image = "registry.k8s.io#sandbox_image = "registry.aliyuncs.com/google_containers#' /etc/containerd/config.toml

# 3. certs.d 目录和 hosts.toml 必须存在!config_path 指向的目录不存在会导致 containerd 直接起不来
ls /etc/containerd/certs.d/*/hosts.toml # 应列出 5 个文件,缺失就按 1.3 节第 4 步补建

# 4. 重启并实测拉取(成功输出镜像摘要才继续)
systemctl restart containerd
systemctl status containerd --no-pager # 必须 active (running)
crictl --runtime-endpoint unix:///var/run/containerd/containerd.sock pull registry.k8s.io/pause:3.10.2

常见原因 D:DNS 解析异常(拉取报dial tcp 10.255.x.x:443: connect: connection refused之类的内网地址错误,或时好时坏)

# 1. 检查解析结果(若返回 10.x/192.168.x 等内网地址,说明 DNS 被污染或配置错误)
getent hosts registry.aliyuncs.com
cat /etc/resolv.conf

# 2. 写死阿里公共 DNS(覆盖 systemd-resolved 符号链接)
rm -f /etc/resolv.conf
cat > /etc/resolv.conf <<'EOF'
nameserver 223.5.5.5
nameserver 223.6.6.6
EOF
getent hosts registry.aliyuncs.com # 确认已解析到公网 IP
常见原因 E:containerd 反复挂掉 / 预检报 CRI connection refused(kubeadm init预检直接报[ERROR CRI]: container runtime is not running ... dial unix /var/run/containerd/containerd.sock: connect: connection refused,说明 init 根本没开始跑):

# 1. 先看 containerd 为什么没起来
systemctl status containerd --no-pager
journalctl -u containerd --no-pager -n 30 # 若见 "failed to load TOML" 等,说明 config.toml 被多轮修改改坏了

# 2. 配置文件被反复 sed 改坏时,最干净的办法是重建(镜像已缓存、DNS 已修复,重建只需 2 分钟)
systemctl stop containerd
mv /etc/containerd/config.toml /etc/containerd/config.toml.bak.$(date +%s)
containerd config default > /etc/containerd/config.toml
sed -i 's#sandbox_image = "registry.k8s.io#sandbox_image = "registry.aliyuncs.com/google_containers#' /etc/containerd/config.toml
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
sed -i 's#config_path = ""#config_path = "/etc/containerd/certs.d"#' /etc/containerd/config.toml

# 3. certs.d 目录和 5 个 hosts.toml 按 1.3 节第 4 步重建(必须先建目录再启用 config_path!)
mkdir -p /etc/containerd/certs.d/{docker.io,registry.k8s.io,quay.io,ghcr.io,gcr.io}
# ...(写入各 hosts.toml,内容见 1.3 节)

# 4. 启动并验证
grep -nE "SystemdCgroup|config_path|sandbox_image" /etc/containerd/config.toml
systemctl restart containerd
systemctl status containerd --no-pager # 必须 active (running)
crictl --runtime-endpoint unix:///var/run/containerd/containerd.sock images | grep pause
# 确认沙箱镜像版本与本地缓存一致后,重新执行 1.5 的 kubeadm init

技巧:预拉控制面镜像,让 init 不依赖网络(还能顺带确认 pause 实际版本号)

kubeadm config images pull \
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version $(kubeadm version -o short)

# 预拉完成后把沙箱镜像版本改成与本地缓存一致(如 pause:3.10),避免沙箱去拉另一个版本
crictl --runtime-endpoint unix:///var/run/containerd/containerd.sock images | grep pause
sed -i 's#pause:3.10.2#pause:3.10#' /etc/containerd/config.toml
systemctl restart containerd
重置后重新初始化(失败的 init 必须清理,否则重跑会撞 6443 端口):

注意:若 init 报 API server not healthy 但 kubelet 已 healthy,先别急着重置——等 2~3 分钟后用cp -i /etc/kubernetes/admin.conf $HOME/.kube/config && kubectl get nodes试一次。慢速虚拟机上 etcd 初始化常超过 kubeadm 的 4 分钟超时,API Server 随后正常启动,集群实际可用。

kubeadm reset -f
rm -rf $HOME/.kube /etc/cni/net.d
systemctl restart containerd kubelet
# 重新执行 1.5 的 kubeadm init

1.6 工作节点加入集群【Node 执行】

join 报 "already exists / Port 10250 in use" 怎么办:说明该 Node 之前加入过(或有残留的 kubelet 占着 10250 端口)。清理后重新 join:

kubeadm reset -f

rm -rf /etc/cni/net.d /var/lib/kubelet/pki

systemctl restart containerd kubelet

然后重新执行 join 命令

token 过期(报 token invalid):token 有效期 24 小时,在 Master 上重新生成 join 命令即可:kubeadm token create --print-join-command

1.7 部署 Flannel 网络插件【Master 执行】

1.8 验证集群【Master 执行】

第二部分:实验一 —— 部署 Prometheus 完成对 K8s 集群的监控

任务目标:部署 Prometheus 并完成对 k8s 集群的监控,包括 node 监控、pod 监控,建立使用率大盘 node 和 pod,并配置告警。

2.1 创建监控命名空间【Master 执行】

2.2 部署 node-exporter(Node 监控数据采集)【Master 执行】

说明:node-exporter 以 DaemonSet 方式运行,Master 与 Node1 上各一个 Pod,采集主机指标(端口 9100)。

2.3 部署 kube-state-metrics(Pod/K8s 对象监控)【Master 执行】

2.4 部署 Prometheus 并配置告警规则【Master 执行】

2.5 部署 Alertmanager(接收告警)【Master 执行】

2.6 部署 Grafana 并建立使用率大盘【Master 执行】

2.7 建立 Node 和 Pod 使用率大盘【Master 执行后浏览器操作】

  1. 浏览器访问http://10.0.0.200:30300,账号admin,密码admin@123。
  2. 添加数据源:Connections → Data sources → Add data source → Prometheus,URL 填http://prometheus.monitoring.svc.cluster.local:9090,保存并测试。
  3. 导入 Node 使用率大盘:Dashboards → New → Import,输入社区大盘 ID1860(Node Exporter Full,含 CPU/内存/磁盘/网络使用率),数据源选 Prometheus,导入。 - 若 grafana.com 访问慢,可将大盘 JSON 从国内镜像站(如https://gitee.com搜索 node-exporter-full)下载后选择 "Upload JSON file" 本地导入。
  4. 导入 Pod 使用率大盘:同样方式导入大盘 ID6417(Kubernetes Pods,展示 Pod 的 CPU/内存使用率排行)。
  5. 截图保存:Node 大盘、Pod 大盘、http://10.0.0.200:30900(Prometheus)的 Targets 页面(应看到全部节点和 Pod 目标为 UP 状态)。

2.8 验证监控与告警【Master 执行】

第三部分:实验二 —— 部署 GitLab 并完成课程实验练习(第 20、21 课)

任务目标:在 K8s 上部署 GitLab,完成创建用户/群组/项目、配置 SSH 密钥、推送代码、分支与 Merge Request、Issue 管理等课程实验练习。

3.1 部署 GitLab(社区版)【Master 执行】

注意:PVC 声明在 default 命名空间但 PV 绑定的是 hostPath,GitLab 数据实际落在 k8s-node1 的/data/gitlab下。GitLab 启动需要 3~5 分钟,可用kubectl logs -f gitlab-xxxx观察。

3.2 获取初始 root 密码并登录【Master 执行】

浏览器访问http://10.0.0.81:30081,用户名root,粘贴上述密码登录。

3.3 GitLab 课程实验练习

(1)设置中文界面:头像 →Preferences → Language选简体中文,保存刷新。

(2)修改 root 密码:头像 →Edit profile → Password,设置新密码。

(3)创建用户并管理权限:管理中心(Admin Area)→ 用户 → 新建用户,创建dev1、dev2两个普通用户,为 dev1 设置密码,通过 dev1 登录验证。

(4)创建群组和项目:管理中心 → 新建群组,命名devops;在群组下新建项目demo-web(可见级别:私有)。

(5)配置 SSH 密钥并推送代码【本机或 Node 执行】:

将公钥粘贴到 GitLab:dev1 头像 → Preferences → SSH Keys → Add key

克隆并首次提交(端口 30081)

(6)分支与 Merge Request 练习:

在 GitLab 页面创建 Merge Request(feature/add-readme → main),指定 dev2 为审核人,审核合并。

(7)Issue 管理练习:项目计划(Plan)→ Issues → 新建 Issue,标题如"首页样式优化",指派给 dev1,并在 MR 中引用#1关联该 Issue,合并后观察 Issue 自动关闭。

(8)保护分支设置:项目设置 → 仓库 → 受保护分支,将main设为仅 Maintainer 可推送、所有人可合并,验证 dev1 无法直接向 main 推送。

dev1 换到功能分支再推:

第四部分:实验三 —— 部署 Jenkins 并完成课程实验练习(第 21 课)

任务目标:在 K8s 上部署 Jenkins,使用国内插件源完成插件安装,创建 Freestyle 任务和 Pipeline 任务,并打通 GitLab 拉取代码。

4.1 部署 Jenkins【Master 执行】

先在 node1 上准备数据目录(Node 执行)

4.2 获取初始管理员密码【Master 执行】

浏览器访问http://10.0.0.81:30080,粘贴密码解锁。

4.4 安装课程所需插件

在Manage Jenkins → Plugins → Available plugins中安装(国内源秒装):

  • Localization: Chinese (Simplified)(中文界面)
  • Git/GitLab(代码拉取与集成)
  • Pipeline(流水线,若初始未装)
  • Blue Ocean(可视化流水线,可选)

安装完成后重启:kubectl rollout restart deployment jenkins。

4.5 Jenkins 课程实验练习

(1)Freestyle 自由风格任务:

  1. 新建任务 → Freestyle project,命名demo-web-build。
  2. 源码管理选Git,仓库地址填 GitLab 项目 HTTP 地址:http://10.0.0.81:30081/devops/demo-web.git
  3. 凭据:添加 → Jenkins → 用户名/密码(填 GitLab 账号 dev1)。
  4. 构建步骤选执行 shell,内容:

echo "========== 构建开始 =========="
ls -l
cat index.html
echo "========== 构建完成 =========="

  1. 点击立即构建,查看Console Output,确认能成功从 GitLab 拉取代码并执行脚本。

(2)Pipeline 流水线任务:

  1. 新建任务 → Pipeline,命名demo-web-pipeline。
  2. Pipeline 脚本:

groovy pipeline { agent any stages { stage('拉取代码') { steps { git branch: 'main', credentialsId: 'gitlab-dev1', url: 'http://10.0.0.81:30081/devops/demo-web.git' } } stage('编译测试') { steps { sh 'echo "Pipeline 构建:$(date)"' sh 'ls -l' } } stage('部署模拟') { steps { sh 'echo "模拟部署到 K8s 集群"' } } } post { always { echo '流水线结束,无论成败都会执行' } success { echo '构建成功!' } failure { echo '构建失败,请检查日志' } } }

3.构建并查看 Stage View。

(3)定时构建(CI 触发方式练习):在 Freestyle 任务构建触发器中勾选Build periodically,填写H/5 * * * *(每 5 分钟一次),观察自动构建历史。


第五部分:作业总结

实验内容访问入口
K8s 集群kubeadm + containerd(阿里云源)-
Prometheus 监控node 监控 + pod 监控 + 告警 + Grafana 大盘http://10.0.0.200:30900/:30903/:30300
GitLab部署 + 用户/群组/项目/MR/Issue 练习http://10.0.0.81:30081
Jenkins部署 + 国内插件源 + Freestyle/Pipeline 练习http://10.0.0.81:30080

国内源汇总:

用途国内源地址
系统软件源mirrors.aliyun.com(Ubuntu apt,deb822 格式)
kubeadm/kubeletmirrors.aliyun.com/kubernetes-new/core/stable/v1.30/deb/(apt,密钥deb/Release.key)
K8s 控制面镜像registry.aliyuncs.com/google_containers
容器镜像加速docker.m.daocloud.io/k8s.m.daocloud.io/quay.m.daocloud.io/ghcr.m.daocloud.io
Flannel 清单下载ghfast.top(GitHub 加速)
NTP 时间同步ntp.aliyun.com
Jenkins 插件源mirrors.tuna.tsinghua.edu.cn/jenkins/updates/
Grafana 大盘备用大盘 JSON 国内镜像站本地导入
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/25 20:07:25

大唐杯备赛捷径:300道模拟题圈定5G核心考点

简介&#xff1a;《“大唐杯”全国大学生移动通信5G技术大赛模拟题库》面向该赛事的参赛学生与指导教师&#xff0c;覆盖第七届、第八届、第九届及历届考点&#xff0c;适合通信类专业备考与赛前强化。资源以判断题和选择题为主&#xff0c;内容涵盖eMBB、uRLLC、mMTC三大应用场…

作者头像 李华
网站建设 2026/9/25 20:03:58

Claude Code Skill 一句话生成 HTML 幻灯片:原理、实操与进阶技巧

1. 这个 Skill 到底解决了什么问题第一次看到"用一句话生成 PPT"这种说法&#xff0c;我的反应是怀疑。市面上打着 AI 生成 PPT 旗号的东西不少&#xff0c;实际用下来大多是套模板——你给它一段文字&#xff0c;它把文字塞进某个固定版式里&#xff0c;出来的东西千…

作者头像 李华
网站建设 2026/9/25 20:00:23

RS485总线时通时断丢包严重?从硬件到软件的全链路排查实战手册

前阵子在化工厂调试仪表采集系统,23台压力、温度传感器走RS485总线串联,白天空载调试一切正常,一到晚上车间电机、变频器全开,就开始频繁丢包,有时候连续十几帧收不到回复,历史数据断得稀碎。 一开始下意识觉得是轮询逻辑写得有问题,熬了半宿改了三版调度算法,问题反而…

作者头像 李华
网站建设 2026/9/25 19:49:42

论文提质最快的方式,是从 GPT-6 的这六步修改法开始

各位同仁好,我是七哥。一个在高校里从事人工智能 相关领域研究,钻研用大模型AI实操的学术人。可以和七哥交流学术写作或Gemini、GPT、Claude 等大模型 学术实操相关问题,多多交流,相互成就,共同进步。 论文修改时,经常一个问题刚处理好,另一个问题又冒出来。 比如,…

作者头像 李华
网站建设 2026/9/25 19:47:59

AI 编程工具内存泄露与卡顿治理:大型代码库下的 IDE 优化配置

AI 编程工具内存泄露与卡顿治理&#xff1a;大型代码库下的 IDE 优化配置随着 AI 编程助手&#xff08;Cursor、GitHub Copilot、Claude Code 等&#xff09;在工程团队中成为每日标配&#xff0c;一个几乎所有深度用户都会遭遇的工程痛点随之而来&#xff1a; 在打开包含数十万…

作者头像 李华