一.Ansible简介
1.什么是Ansible
- Ansible是一个开源部署工具
- 开发语言:Python
- 特点:SSH协议通讯,全平台,无需编译,模块化部署管理
2.Ansible与Chef,Saltstack的不同
- Chef:Ruby语言编写,C/S架构,配置需要Git依赖,Recipe脚本编写规范需要编程经验
- Saltstack:Python语言编写,C/S架构,模块化配置管理,YAML脚本编写规范,适合大规模集群部署
- Ansible:Python语言编写,无Client,模块化配置管理,Playbook脚本编写规范,易于上手,适合中小规模快速部署
二.Ansible的优势和应用场景
1.Ansible的优势
- 轻量级无客户端Agentless
- 开源免费,学习成本低,快速上手
- 使用Playbook作为核心配置架构,统一的脚本格式批量化部署
- 完善的模块化扩展,支持目前主流的开发场景
- 强大的稳定性和兼容性
- 活跃的官方社区问题讨论,方便Trubleshooting与DEBUG问题
三.Ansible安装配置
1.安装配置
- Python3.7.0+Ansible2.7.1
brew install ansible
- 查看Ansible是否安装完成
ansible --version
四.Ansible playbooks入门和编码规范
1.Playbooks框架与格式
- TestPlaybooks
- Inventory/ 目录下存放一个或多个Server详细清单目录,用来保存目标部署主机的相关域名或ip地址,及该主机的变量参数。通常我们会采用具体清单与变量声明文件,如dev/qc/prod
- testenv意味着在testenv的主机部署到testenv环境中
- roles/ 用于保存我们要部署的详细任务列表,下方可以存放一个或多个role,通常会命名为具体部署的app或项目名称
- testbox/作为项目名称【详细任务】
- tasks/用于存放任务内容文件
- main.yml主任务文件
- tasks/用于存放任务内容文件
- testbox/作为项目名称【详细任务】
- deploy.yml作为Playbook任务入口文件,将调度roles下需要部署的项目,以及该项目下的所有任务,最后将该项目部署到Inventory下定义的目标主机中
- Inventory/ 目录下存放一个或多个Server详细清单目录,用来保存目标部署主机的相关域名或ip地址,及该主机的变量参数。通常我们会采用具体清单与变量声明文件,如dev/qc/prod
2.Playbooks编写规范
-
详细目录testenv【testenv环境下的server清单】
[testservers] -> Server组列表 test.example.com -> 目标部署服务器主机名 [testserver:vars] -> Server组列表参数,用来定义目标主机所用到的所有key/value参数对,作为Server的变量声明 server_name=test.example.com user=root output=/root/test.txt
-
主任务文件main.yml【特定role下面具体执行的任务乐章,保存一个或多个task作为音符】
-name: Print server name and user to remote testbox -> 任务名称,表示task是做什么的 shell: "echo 'Currently {{user}} is logining {{server_name}}' > {{output}}" -> 执行的任务,使用shell模块(调用Ansible内嵌模块)执行命令,其中的变量使用的是inventory/testenv文件中的变量声明值 以上代码的含义是执行上述的task,通过Ansible的shell模块在目标主机下打印一句话并重定向到目标主机下对应output文件中
-
任务入口文件deploy.yml【作为核心文件直接与Ansible Playbook命令直接对话,将Playbook下所有编排命令全部展示给Ansible进行最终的play演奏,执行到最终的主机中】
- hosts: "testservers" -> Server列表对应inventory下的文件中的server主标签,声明要部署的目标主机为test.example.com的主机 gather_facts: true -> 获取Server基本信息 remote_user: root -> 目标服务器系统用户指定 roles: - testbox -> 进入roles/testbox任务目录执行里面的所有tasks
-
在使用Ansible执行命令之前,由于Ansible是使用SSH作为通信协议,为了保证Ansible服务器可以操作目标服务器,我们需要配置Ansible主机与目标主机的密钥认证,保证Ansible主机与目标主机可以实现部署操作
- 在Ansible主机配置DNS记录,将对应test.example.com域名解析到对应目标主机的ip地址。【配置hosts文件,添加DNS记录如
106.54.32.234 test.example.com
】 - 配置SSH免密码密钥认证
- Ansible服务器端创建SSH本地密钥认证对
ssh-keygen -t rsa
,一路回车创建对应的私钥[id_rsa]和公钥[id_rsa.pub] - Ansible服务器端建立与目标部署机器的密钥认证(将Ansible中的密钥传递到目标机器中)
ssh-copy-id -i /home/deploy/.ssh/id_rsa.pub [email protected]
,其中[email protected]
表示目标主机用户名@目标主机域名
。执行命令后需要输入yes确认连接,且输入目标主机root用户名的密码,输入完密码后就可以将本地的ssh公钥传递到目标主机中,从而建立了Ansible服务器端与目标主机间的密钥认证,实现免密登录
- Ansible服务器端创建SSH本地密钥认证对
- 执行Playbooks
- 部署到testenv环境
ansible-playbook -i inventory/testenv ./deploy.yml
- 确认是否执行成功
- 命令执行后输出ok个数和changed个数
- 使用
ssh [email protected]
并查看/root/test.txt
文件有对应的输出内容
- 在Ansible主机配置DNS记录,将对应test.example.com域名解析到对应目标主机的ip地址。【配置hosts文件,添加DNS记录如
五.Ansible playbooks常用模块介绍
1.File模块
-
在目标主机创建文件或目录,并赋予其系统权限
-
实例:使用file模块执行Ansible Task任务
- name: create a file file: 'path=/root/foo.txt state=touch mode=0755 owner=foo group=foo'
- name定义任务名称
- file声明任务语句调用file模块
- path定义文本文件在目标主机上的位置
- state定义要去创建一个文件
- mode定义要给文件0755的权限
- owner定义文件的所属用户
- group定义文件的所属组
2.Copy模块
-
实现Ansible服务端到目标主机的文件传送
-
实例:使用copy模块执行Ansible Task任务
- name: copy a file copy: 'remote_src=no src=roles/testbox/files/foo.sh dest=/root/foo.sh mode=0644 force=yes'
- name定义任务名称
- copy声明任务语句调用copy模块
- remote_src=no表示要从Ansible主机中的文件传递到目标主机中
- src声明源文件的路径(Ansible服务器)
- dest声明目标文件的路径(目标服务器)
- mode声明目标文件的权限
- force=yes定义当前的Copy任务强制执行
3.Stat模块
-
获取远程文件状态信息,并将信息保存到环境变量下供随后使用
-
实例
- name: check if foo.sh exists stat: 'path=/root/foo.sh' register: script_stat
stat: 'path=/root/foo.sh'
表示要获取文件状态信息的路径register: script_stat
将stat获取的文件信息传递给script_stat变量
4.Debug模块
-
打印语句到Ansible执行输出
-
实例
- debug: msg="foo.sh exists" -> 定义使用debug模块输出的语句内容为foo.sh exists when: script_stat.stat.exists -> when是Ansible内嵌的条件语句,script_stat.stat.exists判断变量中的值是否存在,若存在则打印上述信息
5.Command/Shell模块
-
用来执行Linux目标主机命令行,Shell模块可以调用Linux系统下的/bin/bash,可以使用系统环境变量、重定向符和管道符等
-
实例
- name: run the script command: "sh /root/foo.sh" - name: run the script shell: "echo 'test' > /root/test.txt" -> 推荐使用shell模块
6.Template模块
-
实现Ansible服务端到目标主机的jinja2模板传送
-
实例
- name: write the nginx config file template: src=roles/testbox/templates/nginx.conf.j2 dest=/etc/nginx/nginx.conf -> src指定模板文件,dest指定目标文件路径,其中传递过程中会替换对应的变量信息
7.Packaging模块
-
调用目标主机系统包管理工具(yum,apt)进行安装,常用这个模块去安装对应发行版下的app安装包
-
实例
- name: ensure nginx is at the latest version yum: pkg=nginx state=latest -> 使用yum安装,安装包是nginx包,版本是最新[此方式适用于CentOS/Rethat系统] - name: ensure nginx is at the latest version apt: pkg=nginx state=latest -> 使用apt安装,安装包是nginx包,版本是最新[此方式适用于Debian/Ubuntu系统]
8.Service模块
-
管理目标主机系统服务
-
实例
- name: start nginx service service: name=nginx state=started -> 启动nginx服务
六.Ansible playbooks常用模块案例操作
1.案例操作
-
到目标服务器上执行如下命令进行预配置工作
useradd foo useradd deploy #添加两个系统用户 mkdir /etc/nginx #创建目录 rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm #给yum源添加nginx安装包
-
修改roles/testbox/tasks/main.yml
- name: create a file file: 'path=/root/foo.txt state=touch mode=0755 owner=foo group=foo'
-
执行ansible-playbook执行上述任务创建foo文件
ansible-playbook -i inventory/testenv ./deploy.yml
-
在role/testbox下添加test目录,并创建foo.sh文件添加文件内容
mkdir roles/testbox/files vi roles/testbox/files/foo.sh # 添加文件内容如下 # echo "This is a test script"
-
在main.yml中添加新的Copy任务
- name: Create a file file: 'path=/root/foo.txt state=touch mode=0755 owner=foo group=foo' - name: Copy a file copy: 'remote_src=no src=roles/testbox/files/foo.sh dest=/root/foo.sh mode=0644 force=yes'
-
执行ansible-playbook执行上述任务拷贝文件
ansible-playbook -i inventory/testenv ./deploy.yml
-
在main.yml中添加获取文件状态和判断文件是否存在并打印输出信息任务
- name: Create a file file: 'path=/root/foo.txt state=touch mode=0755 owner=foo group=foo' - name: Copy a file copy: 'remote_src=no src=roles/testbox/files/foo.sh dest=/root/foo.sh mode=0644 force=yes' - name: Check if foo.sh exists stat: 'path=/root/foo.sh' register: script_stat - debug: msg="foo.sh exists" when: script_stat.stat.exists
-
执行ansible-playbook执行上述任务进行文件是否存在的判断
ansible-playbook -i inventory/testenv ./deploy.yml
-
在main.yml中添加执行脚本文件的任务
- name: Create a file file: 'path=/root/foo.txt state=touch mode=0755 owner=foo group=foo' - name: Copy a file copy: 'remote_src=no src=roles/testbox/files/foo.sh dest=/root/foo.sh mode=0644 force=yes' - name: Check if foo.sh exists stat: 'path=/root/foo.sh' register: script_stat - debug: msg="foo.sh exists" when: script_stat.stat.exists - name: Run the script command: "sh /root/foo.sh"
-
执行ansible-playbook运行上述任务执行shell脚本
ansible-playbook -i inventory/testenv ./deploy.yml
-
添加变量参数到testenv中
[testservers] test.example.com [testservers:vars] server_name=test.example.com user=root output=/root/test.txt port=80 user=deploy worker_processes=4 max_open_file=65505 root=/www
-
在roles/testbox下创建templates目录
mkdir roles/testbox/templates
-
在templates文件创建nginx.conf.j2模板文件,使用nginx.conf文件并修改对应字段为
{{变量}}
# For more information on configuration, see: user {{ user }}; worker_processes {{ worker_processes }}; error_log /var/log/nginx/error.log; pid /var/run/nginx.pid; events { worker_connections {{ max_open_file }}; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; #gzip on; # Load config files from the /etc/nginx/conf.d directory # The default server is in conf.d/default.conf #include /etc/nginx/conf.d/*.conf; server { listen {{ port }} default_server; server_name {{ server_name }}; #charset koi8-r; #access_log logs/host.access.log main; location / { root {{ root }}; index index.html index.htm; } error_page 404 /404.html; location = /404.html { root /usr/share/nginx/html; } # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } } }
-
在main.yml中添加传送替换后的nginx.conf文件模板任务、yum安装nginx任务和启动远程nginx服务任务
- name: Create a file file: 'path=/root/foo.txt state=touch mode=0755 owner=foo group=foo' - name: Copy a file copy: 'remote_src=no src=roles/testbox/files/foo.sh dest=/root/foo.sh mode=0644 force=yes' - name: Check if foo.sh exists stat: 'path=/root/foo.sh' register: script_stat - debug: msg="foo.sh exists" when: script_stat.stat.exists - name: Run the script command: "sh /root/foo.sh" - name: Write the nginx config file template: src=roles/testbox/templates/nginx.conf.j2 dest=/etc/nginx/nginx.conf - name: Ensure nginx is at the latest version yum: pkg=nginx state=latest - name: Start nginx service service: name=nginx state=started
-
执行ansible-playbook运行上述模块任务
ansible-playbook -i inventory/testenv ./deploy.yml
-
进入目标主机查看nginx.conf文件是否成功替换模板,且通过
ps -ef | grep nginx
命令查看是否启动nginx服务