ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Ansible+Shell+CI/CD:自动化运维入门主线全解析

Ansible+Shell+CI/CD:自动化运维入门主线全解析 这是最近后台被问得最多的一个问题想转运维但不知道怎么下手。看了不少教程一会儿让学 Shell一会儿让学 Ansible一会儿又说要懂 CI/CD网上资料越刷越乱。如果你也卡在这个阶段这篇文章就是给你准备的。这篇文章只做一件事把 Ansible Shell CI/CD 这条自动化运维主线讲清楚告诉你每个工具解决什么问题、怎么安装、怎么写第一段自动化脚本、怎么把这三样串成一条完整的部署流水线。全程会用一套可复现的操作示例你可以在自己的 Linux 机器或虚拟机上照着跑。先给结论这不是某个需要高配显卡的 AI 项目而是纯软件工具链只要有一台 Linux 机器虚拟机也行2GB 内存就足够入门。不需要买服务器不需要花钱唯一的门槛是你要愿意动手敲命令。值得关注的点有三个第一Ansible 是配置管理和批量操作的核心写一次就能在几十台机器上重复执行第二Shell 是操作系统的“胶水语言”批量任务、文件处理、定时脚本都离不开第三CI/CD 是把自动化打包成流水线的工程化方法决定了你写的脚本能不能稳定地在团队里跑起来。文章会按照“概念 - 环境 - 操作 - 串联 - 实战 - 排查”的顺序来写。你可以把它当成一份 90 分钟的上手笔记屏幕开两个窗口左边看文章右边开终端看到命令就敲一遍。1. 技术栈全景Ansible、Shell、CI/CD 分别解决什么问题很多新手容易犯一个错误就是把 Ansible、Shell、CI/CD 当成三套并列的技术去学。实际上它们是三个不同层级的东西解决的是完全不同的三类问题。Shell 是最底层的一环。Shell 脚本本质上是把多条 Linux 命令组合成一个可执行的文件适合做单机上的自动化批量改文件名、循环备份日志、定时清理临时文件、检测端口存活等。只要你在 Linux 上敲过的命令都可以写进 Shell 脚本里反复执行。Ansible 是更上面的一层解决的是“多台机器如何保持一致”的问题。你不需要登录到每一台服务器上手动执行命令而是在一台控制机上面定义好目标机器列表和要执行的任务Ansible 会通过 SSH 连接所有目标机器把任务批量下发并执行。如果你管理的是十几台甚至上百台服务器这一步可以省下非常多的时间。CI/CD 则是工程化的一层它解决的是“自动化流程怎么稳定地持续运行”的问题。CI持续集成指的是代码提交后自动完成构建、测试CD持续交付/持续部署指的是通过测试后自动把产物部署到目标环境。一个完整的 CI/CD 流水线本质上就是由很多个脚本和 Ansible 任务组合成的可重复、可追踪、可回滚的流程。三者之间的关系可以这样理解Shell 是操作系统的“手”Ansible 是批量操作的“调度员”CI/CD 是约束调度员按规范流程工作的“管理平台”。学习顺序建议是Linux 基础命令 - Shell 脚本 - Ansible - CI/CD。这也是大多数运维岗招聘 JD 里出现频率最高的技能组合。从招聘需求来看Shell 脚本编程、Linux 常用命令、Ansible 安装部署、CI/CD 流水线是出现频率最高的关键词。把这四个点覆盖住投日常运维、DevOps 工程师、自动化运维岗位才有底气。2. 环境准备一台 Linux 控制机和一个测试节点就够了学习这套工具链不需要一开始就买一堆云服务器。最推荐的方案是用虚拟机或者本机 Linux 环境准备两台主机即可控制节点用来安装 Ansible执行自动化任务。可以直接用自己的电脑VMware/VirtualBox 里的 Ubuntu/CentOS 虚拟机都可以。被管节点用来被 Ansible 控制的目标机器。如果没有第二台机器也可以在同一台机器上用第二个虚拟机甚至用 Docker 容器代替。在开始之前先把基础命令摸熟。至少需要熟悉文件和目录操作cd、ls、mkdir、cp、mv、rm、find、查看系统状态ps、top、free、df、文本处理grep、awk、sed、sort、uniq和网络相关命令curl、ping、ssh、scp。这些命令不需要背熟但看到要能明白意思。以 Ubuntu/Debian 系为例安装 Ansible 只需要两条命令sudo apt update sudo apt install ansible -y如果是 CentOS/RHEL/Fedora 系列用 yum 或 dnf 代替sudo yum install epel-release -y sudo yum install ansible -y安装完成后验证版本ansible --version能看到版本号就说明安装成功。Ansible 还有 Windows 安装方式通过 WSL 或 MSYS2 环境但初学者建议直接用 Linux 虚拟机少踩环境坑。SSH 免密登录配置是关键一步。Ansible 通过 SSH 连接目标机器因此控制节点需要能免密登录到被管节点。用命令行生成密钥ssh-keygen -t rsa -b 4096生成后一路回车即可。然后把公钥推送到被管节点ssh-copy-id user目标IP输入一次密码后后续连接就不需要再输入密码了。验证一下ssh user目标IP hostname能正常返回主机名说明免密登录配置成功。磁盘和内存方面入门学习控制在 10GB 磁盘、2GB 内存左右就非常充裕。Ansible 本身非常轻量它不要求在目标机器上安装任何代理服务只要求目标机器有 Python 环境这一点和 SaltStack 等工具的设计思路不同。3. Ansible 核心概念Inventory、模块、Playbook 一次讲清Ansible 有四个核心概念搞明白这四个东西整个 Ansible 就学会了一半。3.1 Inventory告诉 Ansible 管理哪些机器Inventory主机清单是一个配置文件默认位置在/etc/ansible/hosts你也可以在项目目录里创建自己的 inventory 文件。它的格式很简单[web] 192.168.1.10 192.168.1.11 [db] 192.168.1.20 [web:vars] ansible_userubuntu ansible_ssh_private_key_file/home/user/.ssh/id_rsa[web]、[db]是组名下面写目标机器的 IP 或域名。:vars用来配置该组机器的连接变量。在执行的机器上写好这个文件后后续所有操作都是围绕这个清单展开。3.2 模块Ansible 的功能原子Ansible 的核心是一个个模块每个模块负责一种操作。常用的模块包括ping测试控制节点和被管节点之间的连接是否正常。copy把本地文件复制到目标机器。file管理文件属性和权限。command/shell在目标机器上执行命令。service管理系统服务启停。cron管理定时任务。apt/yum安装软件包。lineinfile修改配置文件中的某一行。用 ad-hoc临时命令的方式直接调用模块可以快速验证功能。例如测试连接ansible web -m ping -i inventory.ini复制一个文件到目标节点ansible web -m copy -a src./index.html dest/tmp/index.html -i inventory.ini看到目标机器上出现了对应文件就说明模块执行成功。3.3 Playbook把操作写成可复用的剧本ad-hoc 适合单条命令生产环境里配置一个 web 服务可能需要执行十几步操作这时候就要用 Playbook。Playbook 是 YAML 格式的文本文件描述一组任务的执行步骤。一个最简单的 Playbook 示例--- - name: 测试 Playbook hosts: web tasks: - name: 创建目录 file: path: /opt/mydata state: directory - name: 复制配置文件 copy: src: ./config/nginx.conf dest: /etc/nginx/nginx.conf - name: 启动 nginx 服务 service: name: nginx state: started enabled: yes执行 Playbook 的命令ansible-playbook -i inventory.ini site.yml执行后Ansible 会依次在每个目标机器上完成目录创建、配置文件复制、服务启动三步操作。全程不需要登录到目标机器不需要手动执行命令而且同一份 Playbook 可以在任意多台机器上重复执行。3.4 幂等性Ansible 最重要的特性学习 Ansible 必须理解“幂等”这个概念。简单说同一份 Playbook 执行一次和执行一百次最终结果是一致的。如果目录已经存在创建目录的任务不会报错也不会重复创建如果配置文件内容一样复制任务不会反复覆盖。这保证了自动化任务可以安全地反复执行这也是 Ansible 比普通 Shell 脚本更适合做生产配置管理的原因。写 Shell 脚本时如果脚本没有做判断执行两次很容易产生问题而 Ansible 模块内置了幂等逻辑降低了写自动化脚本的心智负担。4. Shell 脚本自动化运维的底层能力Shell 脚本虽然看起来不如 Ansible 高级但它是所有自动化操作的底层承载。Ansible 中的很多任务最终也要调用 Shell 命令来完成。如果你的 Shell 基础不扎实写 Playbook 时会在命令拼接、变量传递、结果判断上卡壳。4.1 Shell 脚本基本结构一个标准的 Shell 脚本以 shebang 开头指定解释器#!/bin/bash # 定义变量 BACKUP_DIR/data/backup LOG_FILE/var/log/backup.log # 创建目录 mkdir -p $BACKUP_DIR # 循环处理多个目录 for dir in /data/logs /data/uploads; do if [ -d $dir ]; then cp -r $dir $BACKUP_DIR/$(basename $dir)_$(date %Y%m%d) else echo 目录不存在: $dir $LOG_FILE fi done # 执行结果检查 if [ $? -eq 0 ]; then echo 备份完成: $(date) $LOG_FILE else echo 备份失败: $(date) $LOG_FILE exit 1 fi这个脚本里覆盖了大部分基础语法变量定义、for 循环、if 条件判断、命令执行结果捕获、日期格式化、日志输出。4.2 变量与参数传递Shell 脚本最常见的运行方式就是带参执行。以下两个位置参数是必须掌握的$1、$2是脚本接收的参数$#表示参数个数$?表示上一条命令的返回值0 表示成功$表示所有参数的列表写一个带参的脚本示例#!/bin/bash # usage: ./deploy.sh app_name version APP_NAME${1:?请传入应用名} VERSION${2:?请传入版本号} echo 开始部署: $APP_NAME echo 版本号: $VERSION这里用了${1:?}做参数强制校验如果调用脚本时没有传参会自动报错退出避免后续执行产生莫名其妙的问题。4.3 循环与条件判断是批量任务的核心批量任务场景里循环处理是最常用的技巧。例如批量处理多个文件#!/bin/bash # 查找目录下所有 .log 结尾的文件 find /var/log -name *.log -type f | while read file; do echo 清理文件: $file $file # 清空但不删除 done条件判断则用来做分支处理比如根据环境变量选择不同的部署模式#!/bin/bash ENV$1 if [ $ENV prod ]; then echo 生产环境执行完整检查 # 健康检查、备份、灰度等步骤 elif [ $ENV test ]; then echo 测试环境跳过部分检查 else echo 未知环境退出 exit 1 fi4.4 调试技巧Shell 脚本一旦出错如果没有调试思路会非常痛苦。这里给出两个最实用的启动参数# 进入调试模式执行每条命令前先把命令打印出来 bash -x your_script.sh # 错误立即退出避免中间状态继续往下执行 bash -e your_script.sh写脚本的时候建议开头加上set -e # 出错即退出 set -u # 使用未定义变量时报错 set -o pipefail # 管道命令中任一命令失败则整体失败这套组合能让脚本行为更稳定不至于在执行到一半的时候悄悄失败。4.5 一个完整场景批量重命名文件并获取文件所在目录有时候需要在脚本里获取脚本自身所在目录这在自动化部署里很常见。方案是SCRIPT_DIR$(cd $(dirname $0) pwd) echo 脚本所在目录: $SCRIPT_DIR批量重命名文件#!/bin/bash # 把所有 .txt 后缀改为 .log for file in *.txt; do mv $file ${file%.txt}.log done这类场景是 Shell 的强项也是面试题里出现频率最高的部分。写熟之后你会发现 Ansible 里的 command/shell 模块只是把本地 Shell 的能力迁移到远程机器上执行而已。5. CI/CD 基础从“手动部署”到“流水线自动部署”CI/CD 不是某款具体软件的专属功能而是一套工程化方法。CI持续集成强调代码合并到主干后自动进行构建和测试尽早发现问题CD持续交付/持续部署强调每次代码变更都具备自动发布到环境的能力。5.1 CI/CD 流水线的核心概念一条标准的流水线由阶段Stage和任务Job组成常见阶段划分如下阶段作用示例命令build构建应用产物npm run build/mvn clean packagetest运行自动化测试pytest/go testpackage打包镜像或安装包docker build/tar -czfdeploy部署到目标环境ansible-playbook/scp只要提交代码流水线就会按照这几个阶段依次执行任何一步失败都会中断整个流程并通过邮件或 IM 消息通知负责人。5.2 常见 CI/CD 工具选型现在常见的 CI/CD 工具包括 GitLab CI、Jenkins、GitHub Actions。它们的核心思路类似区别主要在配置格式和托管方式上。GitLab CI 的配置文件是.gitlab-ci.yml写在项目根目录示例stages: - build - deploy build_app: stage: build script: - echo 开始构建 - npm install - npm run build deploy_to_server: stage: deploy script: - echo 开始部署 - ansible-playbook -i inventory.ini deploy.yml only: - main当代码 push 到 main 分支后GitLab 会自动运行上述步骤。这个过程中构建环节使用 Shell 脚本完成部署环节调用 Ansible 完成非常好的体现了三者如何协作。Jenkins 则更偏向传统的自建服务器模式通过 Web UI 配置任务同时支持使用Jenkinsfile把流水线沉淀成项目内的代码文件。GitHub Actions 的配置语法是 YAML存放在.github/workflows/目录下适用于 GitHub 托管的项目。5.3 CI/CD 不是必需马上学完的工具如果你刚接触运维不要一上来就研究 Kubernetes、Helm 等发布平台。当前阶段最需要掌握的是流水线的基本概念以及怎么把已经写好的 Shell 和 Ansible 任务放进流水线。这一步能真正把“本地手动执行”升级成“提交代码后自动完成全部部署”。6. Ansible Shell CI/CD 协同搭建一条最简单的自动部署流水线现在把三个技术点串成一条完整的部署链路。假设场景是开发者在测试环境更新一个静态网站页面希望提交代码后自动完成页面部署。完整链路如下代码推送 - GitLab CI 触发 - 构建页面 - Ansible 将页面分发到 Web 服务器 - 验证访问 - 完成整个流程里三个角色的分工是Shell负责构建时的页面处理比如压缩资源、拼接文件、生成版本号。Ansible负责将构建产物复制到远程服务器并执行 nginx reload。CI/CD负责串联上述步骤确保每次代码变更都触发相同的流程。下面给出一个可复用的 GitLab CI Ansible 组合示例。项目结构project/ ├── .gitlab-ci.yml ├── deploy.yml ├── inventory.ini └── index.html.gitlab-ci.yml内容stages: - build - deploy build_job: stage: build script: - bash ./build.sh artifacts: paths: - dist/ deploy_job: stage: deploy script: - ansible-playbook -i inventory.ini deploy.yml only: - maindeploy.yml内容--- - name: 部署静态页面 hosts: web tasks: - name: 创建目标目录 file: path: /var/www/html state: directory owner: www-data group: www-data mode: 0755 - name: 复制页面文件 copy: src: ./dist/ dest: /var/www/html/ owner: www-data group: www-data mode: 0644 - name: 重载 nginx service: name: nginx state: reloaded从代码提交到最终部署完成整个过程不需要任何人登录服务器。这就是自动化运维的标准姿势把重复的事交给机器把人的精力留在解决新问题上。7. 实战场景Ansible 复制文件到所有节点并授权权限这是一个在实际运维里非常高频的操作也是后台经常被问到的问题。需求通常是需要把同一个配置包或二进制文件分发到所有机器并设置统一的执行权限。7.1 准备 inventory 文件[all_nodes] 192.168.1.10 192.168.1.11 192.168.1.12 [all_nodes:vars] ansible_userubuntu ansible_becomeyes ansible_become_methodsudo这里启用了become表示执行任务时切换到 root 权限。分发文件到所有节点并设置权限最常见的方式是用copy模块配合mode参数--- - name: 分发脚本文件到所有节点 hosts: all_nodes tasks: - name: 复制脚本文件 copy: src: ./tools/deploy_helper.sh dest: /usr/local/bin/deploy_helper.sh owner: root group: root mode: 0777执行ansible-playbook -i inventory.ini distribute.yml执行完成后三台目标机器的/usr/local/bin/deploy_helper.sh都会有777权限。7.2 关于 777 权限的提醒这里必须多说一句777权限意味着所有用户都可以读、写、执行该文件在测试环境没问题但在生产环境非常危险。生产建议先按职责划分可执行程序建议0755即属主可读写执行属组和其他人可读执行。配置文件建议0644即属主可读写属组和其他人只读。私钥等敏感文件建议0600只有属主可读写。如果公司内部安全规范严格尽量避免大规模使用 777。需要批量授权但又想控制风险时可以这样做- name: 设置权限 file: path: /usr/local/bin/deploy_helper.sh owner: root group: ops mode: 0750这样只有 root 和 ops 组内用户才有执行权限其他人无法碰这个文件。7.3 分发目录而非单个文件如果希望把整个目录复制到所有节点可以这样写- name: 复制配置目录 copy: src: ./config/ dest: /etc/myapp/ owner: root group: root mode: 0644注意src路径后面带斜杠会复制目录内部所有文件而不是目录本身。如果不确定效果建议先执行一次 ad-hoc 查看结果ansible all_nodes -m copy -a src./test.conf dest/tmp/test.conf -i inventory.ini先单节点验证再批量执行可以大幅度减少误操作。8. 资源占用与性能观察很多人会担心自动化工具吃资源。实际上 Ansible 和 Shell 相对轻量通过 SSH 执行任务本身运行在控制节点上目标机器不需要安装 agent。但学习过程中也可以形成资源观察的习惯这对后续做生产环境优化很有帮助。8.1 控制节点资源观察执行大规模 Ansible 操作时控制节点 CPU 和内存会短暂升高。可以用系统命令观察top -u 当前用户Ansible 控制进程会以ansible或 Python 进程的形式出现。如果管理几千台机器还可以开启forks参数调节并行度[defaults] forks 10默认 forks 是 5即同时执行 5 个节点的任务。服务器性能允许时调高可以加快执行速度但不要调到远超控制机核数。8.2 目标节点资源观察被管节点上执行任务时主要关注负载和磁盘uptime free -h df -h使用 Playbook 批量查看时可以用 command 模块ansible all_nodes -m shell -a uptime free -h df -h -i inventory.ini8.3 降低资源占用的思路如果批量执行时目标机器负载很高可以从几个方向调整减少 playbook 中任务的重复执行次数。把大文件传输改为控制节点上的压缩包传输目标节点再解压。使用throttle参数限制同一批机器的并发数或直接在 inventory 中分组控制。使用 Ansible 的serial参数分批滚动执行例如每批 5 台- hosts: all_nodes serial: 5 tasks: - name: 执行任务 command: echo batch这样能避免同一时间所有目标机器同时抢资源。9. 常见问题与排查方法按照下面的表格可以解决学习过程中 90% 的报错问题。问题现象可能原因排查方式解决方案ansible 命令找不到未安装 Ansible 或 PATH 未配置执行which ansible按 2 节安装 Ansible连接被拒绝SSH 服务未启动或端口错误ssh userip -p 端口启动 sshd 服务或用-p指定端口权限被拒绝当前用户没有 sudo 权限执行sudo whoami将被管节点用户加入 sudoers主机清单不生效inventory 文件路径错误ansible-inventory --list -i 文件指定正确路径执行脚本报错shell 语法错误或权限不足bash -x script.sh按 4.4 节调试CI 流水线一直卡住部署任务没有设置超时或者依赖服务挂起查看 Runner/Jenkins 日志给流水线配置超时时间批量任务部分节点失败节点网络不稳定或配置不同查看失败节点的完整输出使用--limit单独执行失败节点排查目标机器时区不一致脚本使用时间戳导致结果不一致执行date对比时间在 playbook 中统一用date模块时区777 权限带来的安全告警权限设置过于宽松检查敏感文件权限改用 0750 或 0644Playbook 执行结果与预期不符变量定义或引用错误增加debug模块打印变量明确变量作用域避免全局覆盖其中最关键的一个排查思路是将复杂问题拆到最小可复现步骤。比如 Playbook 批量失败先用 ad-hoc 单节点执行再逐步增加节点找到出问题的具体那个环节。10. 学习路线与实践建议最后给出一条适合零基础的学习路径建议按这个顺序执行不要跳用一周时间熟悉 Linux 常用命令重点练文件操作、权限管理、文本处理、进程管理。用一周时间写 10 个 Shell 脚本覆盖循环、条件判断、函数、定时任务。用一周时间完成 Ansible 安装、免密登录、Inventory 配置、Playbook 编写并在两台虚拟机上做实验。用一周时间跑通一个最小的 CI/CD 流程可以选择 GitLab CI 或 Jenkins内部用 Shell 和 Ansible 完成任务。最后一到两周把一套完整的部署流程做成自己的项目比如写一个自动化部署静态网站或 Node.js/Python 服务的流水线并把代码放到 Gitlab/GitHub 上。实践过程中建议建立一套自己的实验目录ops-lab/ ├── ansible/ │ ├── inventory.ini │ ├── playbooks/ │ └── roles/ ├── scripts/ │ ├── deploy.sh │ └── backup.sh ├── ci/ │ └── .gitlab-ci.yml └── logs/目录分离的意义在于Ansible 的 Inventory 和 Playbook 是一部分Shell 脚本是一部分CI 流水线配置是一部分。分门别类管理后后续扩展和维护都能节省大量时间。另一个建议是“坚持最小案例先行”。不要一开始就设计一个覆盖几十台机器、包含 Docker/K8s/监控的完整架构。先用两台虚拟机和 3 条 Ansible 任务跑通再逐步添加复杂度。运维自动化最怕的不是工具学不会而是一上来就陷入各种联动问题。从招聘角度看能写出规范的 Shell 脚本、会写 Ansible Playbook、能描述清楚 CI/CD 流水线里的阶段和任务这三个能力已经可以构成一份不错的初级运维简历。相比那些堆砌名词的简历面试官更愿意看到“我把一套测试环境部署自动化了从代码提交到服务上线需要 10 分钟”这样具体的产出。第一次跑通第一条自动化部署任务时你会明白运维自动化的核心不是多高深的算法而是把那些重复了几十遍的操作交给机器。
返回列表