10-算力中心运维三剑客:Ansible + Jenkins + K8s 高效实战
在算力中心运维工作中,我们经常需要处理降内核版本、安装网卡驱动、GPU驱动等任务。如果手动一台台操作,效率极低且容易出错。Ansible、Jenkins、K8s 这三个工具结合使用,可以构建一个高效的自动化运维体系。
1. 三剑客的角色定位
场景类比:
想象一个现代化的工厂生产线:
- Ansible 是 自动化装配线工人 - 负责具体的安装、配置操作
- Jenkins 是 生产调度中心 - 负责协调、触发、监控整个流程
- K8s 是 智能仓储系统 - 负责管理容器化应用的部署和调度
1.1 Ansible - 配置管理专家
核心职责:
- 批量操作服务器(降内核、装驱动)
- 配置管理(统一配置、版本控制)
- 任务自动化(定时任务、批量更新)
适用场景:
- ✅ 降内核版本(需要重启服务器)
- ✅ 安装网卡驱动(操作系统层面)
- ✅ 安装GPU驱动(操作系统层面)
- ✅ 批量配置系统参数
- ✅ 批量部署软件包
1.2 Jenkins - CI/CD 流水线
核心职责:
- 自动化流程编排
- 任务调度和触发
- 构建和部署自动化
- 通知和监控
适用场景:
- ✅ 定时执行运维任务
- ✅ 代码提交触发自动化流程
- ✅ 多阶段任务编排(先降内核,再装驱动,最后部署应用)
- ✅ 团队协作和权限管理
1.3 K8s - 容器编排平台
核心职责:
- 容器化应用管理
- 资源调度和分配
- 服务发现和负载均衡
- 自动扩缩容
适用场景:
- ✅ 部署和管理AI训练任务
- ✅ 部署Web服务、API服务
- ✅ 管理有状态服务(数据库、Redis)
- ✅ 资源配额和调度优化
2. 实战场景:降内核版本 + 安装GPU驱动
2.1 传统方式 vs 自动化方式
传统方式(痛苦):
bash
# 1. 手动登录每台服务器
ssh server1
# 2. 检查当前内核版本
uname -r
# 3. 降内核版本
yum install kernel-4.18.0-348.el8.x86_64
# 4. 重启服务器
reboot
# 5. 等待重启完成
# 6. 重新登录
ssh server1
# 7. 安装GPU驱动
./NVIDIA-Linux-x86_64-535.129.03.run
# 8. 验证驱动
nvidia-smi
# 9. 重复以上步骤对server2、server3...server100
问题: 耗时长、容易出错、无法并行、难以回滚
自动化方式(高效):
bash
# 1. 在Jenkins点击"降内核+装驱动"按钮
# 2. Jenkins触发Ansible Playbook
# 3. Ansible并行操作100台服务器
# 4. 自动验证结果
# 5. 发送通知
2.2 完整自动化流程
流程图:
用户触发
↓
Jenkins Pipeline
↓
阶段1: 备份当前配置
↓
阶段2: 降内核版本(Ansible)
↓
阶段3: 重启服务器(Ansible)
↓
阶段4: 等待服务器恢复(Jenkins)
↓
阶段5: 安装GPU驱动(Ansible)
↓
阶段6: 验证驱动(Ansible)
↓
阶段7: 部署应用到K8s(Jenkins + K8s)
↓
完成通知
3. Ansible实战:降内核版本
3.1 Ansible Playbook示例
文件结构:
ansible-playbooks/
├── inventory/
│ └── hosts # 服务器清单
├── roles/
│ ├── downgrade-kernel/
│ │ ├── tasks/
│ │ │ └── main.yml # 降内核任务
│ │ └── handlers/
│ │ └── main.yml # 处理器
│ └── install-gpu-driver/
│ ├── tasks/
│ │ └── main.yml # 安装GPU驱动任务
│ └── files/
│ └── NVIDIA-Linux-x86_64-535.129.03.run
└── playbooks/
├── downgrade-kernel.yml # 降内核playbook
└── install-gpu-driver.yml # 安装GPU驱动playbook
降内核Playbook:
yaml
# 以下代码为示例,实际操作前请在测试环境验证
---
- name: 降内核版本
hosts: gpu_servers
become: yes
serial: 10 # 每次同时操作10台服务器,避免全部重启
tasks:
- name: 检查当前内核版本
command: uname -r
register: current_kernel
changed_when: false
- name: 显示当前内核版本
debug:
msg: "当前内核版本: {{ current_kernel.stdout }}"
- name: 备份当前内核配置
copy:
src: /etc/grub2.cfg
dest: /etc/grub2.cfg.backup
remote_src: yes
backup: yes
- name: 安装指定版本的内核
yum:
name: kernel-4.18.0-348.el8.x86_64
state: present
disable_gpg_check: yes
- name: 设置默认启动内核
command: grub2-set-default 0
changed_when: false
- name: 显示默认启动内核
command: grub2-editenv list
register: default_kernel
changed_when: false
- name: 通知需要重启
debug:
msg: "内核已降级,默认启动内核: {{ default_kernel.stdout }},需要重启服务器"
handlers:
- name: 重启服务器
reboot:
reboot_timeout: 600
connect_timeout: 15
test_command: whoami
async: 1
poll: 0
3.2 安装GPU驱动Playbook
yaml
# 以下代码为示例,实际操作前请在测试环境验证
---
- name: 安装GPU驱动
hosts: gpu_servers
become: yes
serial: 10
tasks:
- name: 检查GPU驱动版本
command: nvidia-smi --query-gpu=driver_version --format=csv,noheader
register: current_driver
changed_when: false
ignore_errors: yes
- name: 显示当前GPU驱动版本
debug:
msg: "当前GPU驱动版本: {{ current_driver.stdout | default('未安装') }}"
- name: 检查内核版本
command: uname -r
register: kernel_version
changed_when: false
- name: 检查内核头文件
yum:
name: kernel-devel-{{ kernel_version.stdout }}
state: present
- name: 安装依赖包
yum:
name:
- gcc
- make
- dkms
- kernel-headers
state: present
- name: 复制GPU驱动安装包
copy:
src: files/NVIDIA-Linux-x86_64-535.129.03.run
dest: /tmp/NVIDIA-Linux-x86_64-535.129.03.run
mode: '0755'
- name: 安装GPU驱动
command: /tmp/NVIDIA-Linux-x86_64-535.129.03.run --silent
register: install_result
async: 1800 # 最长等待30分钟
poll: 10
- name: 验证GPU驱动安装
command: nvidia-smi
register: nvidia_smi
changed_when: false
- name: 显示GPU信息
debug:
msg: "{{ nvidia_smi.stdout }}"
- name: 检查GPU驱动版本
command: nvidia-smi --query-gpu=driver_version --format=csv,noheader
register: new_driver
changed_when: false
- name: 显示新安装的GPU驱动版本
debug:
msg: "新安装的GPU驱动版本: {{ new_driver.stdout }}"
4. Jenkins Pipeline实战
4.1 Jenkinsfile示例
groovy
// 以下代码为示例,实际操作前请在测试环境验证
pipeline {
agent any
parameters {
choice(
name: 'OPERATION',
choices: ['downgrade_kernel', 'install_gpu_driver', 'all'],
description: '选择要执行的操作'
)
string(
name: 'KERNEL_VERSION',
defaultValue: '4.18.0-348.el8.x86_64',
description: '目标内核版本'
)
string(
name: 'GPU_DRIVER_VERSION',
defaultValue: '535.129.03',
description: 'GPU驱动版本'
)
}
environment {
ANSIBLE_HOST_KEY_CHECKING = 'False'
ANSIBLE_INVENTORY = '/etc/ansible/hosts'
}
stages {
stage('前置检查') {
steps {
script {
echo "开始执行运维任务"
echo "操作类型: ${params.OPERATION}"
echo "目标内核版本: ${params.KERNEL_VERSION}"
echo "GPU驱动版本: ${params.GPU_DRIVER_VERSION}"
}
}
}
stage('备份配置') {
when {
expression { params.OPERATION in ['downgrade_kernel', 'all'] }
}
steps {
script {
echo "备份当前配置..."
sh """
ansible-playbook \
-i ${ANSIBLE_INVENTORY} \
ansible-playbooks/playbooks/backup-config.yml
"""
}
}
}
stage('降内核版本') {
when {
expression { params.OPERATION in ['downgrade_kernel', 'all'] }
}
steps {
script {
echo "开始降内核版本..."
sh """
ansible-playbook \
-i ${ANSIBLE_INVENTORY} \
-e "kernel_version=${params.KERNEL_VERSION}" \
ansible-playbooks/playbooks/downgrade-kernel.yml
"""
}
}
}
stage('等待服务器重启') {
when {
expression { params.OPERATION in ['downgrade_kernel', 'all'] }
}
steps {
script {
echo "等待服务器重启..."
sleep(time: 10, unit: 'MINUTES')
sh """
ansible-playbook \
-i ${ANSIBLE_INVENTORY} \
ansible-playbooks/playbooks/wait-for-servers.yml
"""
}
}
}
stage('安装GPU驱动') {
when {
expression { params.OPERATION in ['install_gpu_driver', 'all'] }
}
steps {
script {
echo "开始安装GPU驱动..."
sh """
ansible-playbook \
-i ${ANSIBLE_INVENTORY} \
-e "gpu_driver_version=${params.GPU_DRIVER_VERSION}" \
ansible-playbooks/playbooks/install-gpu-driver.yml
"""
}
}
}
stage('验证结果') {
steps {
script {
echo "验证操作结果..."
sh """
ansible-playbook \
-i ${ANSIBLE_INVENTORY} \
ansible-playbooks/playbooks/verify.yml
"""
}
}
}
stage('部署应用到K8s') {
steps {
script {
echo "部署应用到K8s集群..."
sh """
kubectl apply -f k8s-manifests/
kubectl rollout status deployment/ai-training
"""
}
}
}
}
post {
success {
echo "运维任务执行成功!"
emailext (
subject: "✅ 运维任务成功: ${params.OPERATION}",
body: "运维任务执行成功,详细信息请查看Jenkins日志。",
to: 'ops-team@example.com'
)
}
failure {
echo "运维任务执行失败!"
emailext (
subject: "❌ 运维任务失败: ${params.OPERATION}",
body: "运维任务执行失败,请立即检查Jenkins日志。",
to: 'ops-team@example.com'
)
}
}
}
5. K8s集成:部署AI训练任务
5.1 K8s Deployment示例
yaml
# 以下代码为示例,实际操作前请在测试环境验证
apiVersion: apps/v1
kind: Deployment
metadata:
name: ai-training
namespace: ai-workspace
spec:
replicas: 3
selector:
matchLabels:
app: ai-training
template:
metadata:
labels:
app: ai-training
spec:
nodeSelector:
gpu: "true" # 只调度到有GPU的节点
containers:
- name: ai-training
image: registry.example.com/ai-training:latest
resources:
limits:
nvidia.com/gpu: 4 # 使用4块GPU
memory: "32Gi"
cpu: "8"
requests:
nvidia.com/gpu: 4
memory: "16Gi"
cpu: "4"
volumeMounts:
- name: data
mountPath: /data
- name: models
mountPath: /models
volumes:
- name: data
persistentVolumeClaim:
claimName: data-pvc
- name: models
persistentVolumeClaim:
claimName: models-pvc
5.2 K8s Job示例(一次性任务)
yaml
# 以下代码为示例,实际操作前请在测试环境验证
apiVersion: batch/v1
kind: Job
metadata:
name: model-training-job
namespace: ai-workspace
spec:
backoffLimit: 3
parallelism: 2
completions: 10
template:
spec:
nodeSelector:
gpu: "true"
containers:
- name: training
image: registry.example.com/model-training:latest
command: ["python", "train.py"]
args:
- "--epochs=100"
- "--batch-size=32"
resources:
limits:
nvidia.com/gpu: 8
memory: "64Gi"
cpu: "16"
restartPolicy: OnFailure
6. 完整工作流程示例
6.1 场景:批量更新GPU驱动并重新部署AI训练任务
步骤1:在Jenkins创建任务
- 登录Jenkins
- 创建新的Pipeline任务
- 配置参数选择(驱动版本、目标服务器组等)
步骤2:执行任务
- 点击"Build with Parameters"
- 选择操作类型:all(降内核+装驱动)
- 填写GPU驱动版本:535.129.03
- 点击"开始构建"
步骤3:自动化执行
Jenkins自动执行:
├── 前置检查(验证参数、检查服务器状态)
├── 备份配置(备份grub配置、驱动配置)
├── 降内核版本(Ansible并行操作100台服务器)
├── 等待服务器重启(分批重启,每批10台)
├── 安装GPU驱动(Ansible并行安装)
├── 验证结果(检查内核版本、GPU驱动版本)
├── 部署应用到K8s(更新Deployment、启动训练任务)
└── 发送通知(邮件、Slack、钉钉)
步骤4:监控和验证
- 在Jenkins查看执行日志
- 在Grafana查看服务器状态
- 在K8s Dashboard查看Pod状态
- 验证AI训练任务正常运行
7. 最佳实践
7.1 Ansible最佳实践
1. 使用Inventory分组管理服务器
ini
# 以下代码为示例,实际操作前请在测试环境验证
[gpu_servers]
server[01:50].example.com
[network_servers]
server[51:70].example.com
[storage_servers]
server[71:80].example.com
[all_servers:children]
gpu_servers
network_servers
storage_servers
2. 使用Role组织Playbook
roles/
├── common/ # 通用配置
├── kernel/ # 内核管理
├── gpu-driver/ # GPU驱动
├── network-driver/ # 网卡驱动
└── monitoring/ # 监控配置
3. 使用变量管理不同环境
yaml
# vars/production.yml
kernel_version: 4.18.0-348.el8.x86_64
gpu_driver_version: 535.129.03
network_driver_version: 1.2.3
# vars/staging.yml
kernel_version: 4.18.0-348.el8.x86_64
gpu_driver_version: 535.129.03
network_driver_version: 1.2.3
7.2 Jenkins最佳实践
1. 使用多阶段Pipeline
groovy
// 以下代码为示例,实际操作前请在测试环境验证
stages {
stage('测试环境') {
when { branch 'staging' }
steps {
// 在测试环境先执行
}
}
stage('生产环境') {
when { branch 'main' }
input {
message "确认在生产环境执行?"
}
steps {
// 在生产环境执行
}
}
}
2. 使用参数化构建
groovy
// 以下代码为示例,实际操作前请在测试环境验证
parameters {
choice(name: 'ENVIRONMENT', choices: ['staging', 'production'])
string(name: 'SERVER_GROUP')
booleanParam(name: 'DRY_RUN', defaultValue: true)
}
3. 使用通知集成
groovy
// 以下代码为示例,实际操作前请在测试环境验证
post {
success {
slackSend(
color: 'good',
message: "✅ 任务成功: ${env.JOB_NAME} #${env.BUILD_NUMBER}"
)
}
failure {
slackSend(
color: 'danger',
message: "❌ 任务失败: ${env.JOB_NAME} #${env.BUILD_NUMBER}"
)
}
}
7.3 K8s最佳实践
1. 使用Namespace隔离环境
bash
# 以下代码为示例,实际操作前请在测试环境验证
kubectl create namespace staging
kubectl create namespace production
kubectl config set-context --current --namespace=staging
2. 使用ResourceQuota限制资源
yaml
# 以下代码为示例,实际操作前请在测试环境验证
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-resources
namespace: ai-workspace
spec:
hard:
requests.cpu: "100"
requests.memory: 200Gi
limits.cpu: "200"
limits.memory: 400Gi
requests.nvidia.com/gpu: 50
3. 使用HPA自动扩缩容
yaml
# 以下代码为示例,实际操作前请在测试环境验证
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: ai-training-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: ai-training
minReplicas: 3
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 80
8. 常见问题解决
8.1 Ansible常见问题
问题1:SSH连接失败
yaml
# 解决方案:配置SSH密钥认证
# 以下代码为示例,实际操作前请在测试环境验证
[defaults]
host_key_checking = False
private_key_file = ~/.ssh/ansible_key
问题2:任务执行超时
yaml
# 解决方案:增加超时时间
# 以下代码为示例,实际操作前请在测试环境验证
- name: 安装GPU驱动
command: /tmp/NVIDIA-Linux-x86_64-535.129.03.run --silent
async: 3600 # 1小时超时
poll: 10
8.2 Jenkins常见问题
问题1:Pipeline执行失败
groovy
// 解决方案:添加错误处理
// 以下代码为示例,实际操作前请在测试环境验证
stage('执行任务') {
steps {
script {
try {
sh 'ansible-playbook playbook.yml'
} catch (Exception e) {
echo "任务执行失败: ${e}"
currentBuild.result = 'FAILURE'
throw e
}
}
}
}
问题2:并发执行冲突
groovy
// 解决方案:使用锁机制
// 以下代码为示例,实际操作前请在测试环境验证
lock(resource: 'gpu-servers') {
stage('降内核') {
steps {
sh 'ansible-playbook downgrade-kernel.yml'
}
}
}
8.3 K8s常见问题
问题1:Pod无法调度
bash
# 解决方案:检查节点资源
# 以下命令为示例,实际操作前请在测试环境验证
kubectl describe pod <pod-name>
kubectl top nodes
kubectl get nodes -o wide
问题2:GPU资源不足
yaml
# 解决方案:使用NodeSelector和Taints
# 以下代码为示例,实际操作前请在测试环境验证
apiVersion: v1
kind: Node
metadata:
name: gpu-node-01
spec:
taints:
- key: nvidia.com/gpu
value: "true"
effect: NoSchedule
9. 总结
通过Ansible + Jenkins + K8s的组合,我们可以构建一个高效的算力中心运维体系:
核心优势:
- 自动化程度高:从手动操作到一键执行
- 可追溯性强:所有操作都有日志记录
- 可重复性好:相同操作可以重复执行
- 可扩展性强:轻松扩展到更多服务器
- 风险可控:分批操作、灰度发布、快速回滚
工作流程:
Jenkins(调度中心)
↓ 触发任务
Ansible(执行引擎)
↓ 批量操作
K8s(应用管理)
↓ 部署应用
监控告警
↓ 实时监控
通知反馈
关键要点:
- Ansible负责"做什么":降内核、装驱动、配置系统
- Jenkins负责"什么时候做":定时触发、条件触发、手动触发
- K8s负责"应用怎么跑":容器编排、资源调度、自动扩缩容
- 三者结合:构建完整的自动化运维体系
通过合理使用这三个工具,算力中心运维效率可以提升10倍以上,同时大大降低人为错误的风险。