设为首页 收藏本站
查看: 862|回复: 0

[经验分享] Ansible 简单入门

[复制链接]
YunVN网友  发表于 2018-7-30 08:39:49 |阅读模式
  安装:
  先安装EPEL源
  yum install ansible -y
  Ansible配置和测试
  第一步是修改主机与配置组,文件位置 /etc/ansible/hosts, 格式是ini,添加两台主机IP 同时定义两个IP到webserver组 内容如下:
  【/etc/ansible/hosts】
  #web1.aa.com
  #web2.aa.com
  192.168.137.8
  192.168.137.9
  [webserver]
  192.168.137.8
  192.168.137.9
  通过PING魔窟测试主机的连通性,分别对单主机及组进行PING操作 初夏如下结果 表示安装测试成功
[root@localhost ansible]# ansible webserver -m ping -k  
SSH password:
  
192.168.137.8 | SUCCESS => {
  
    "changed": false,
  
    "ping": "pong"
  
}
  
192.168.137.9 | SUCCESS => {
  
    "changed": false,
  
    "ping": "pong"
  
}
  
[root@localhost ansible]#
  
#运行命令如下:
  
[root@localhost ansible]# ansible webserver -a "uptime"
  
192.168.137.8 | SUCCESS | rc=0 >>
  
16:43:39 up 26 min,  1 user,  load average: 0.03, 0.01, 0.00
  

  
127.168.137.9 | SUCCESS | rc=0 >>
  
16:43:40 up 49 min,  4 users,  load average: 0.14, 0.06, 0.01
  

  
[root@localhost ansible]#
  由于主控端与被控主机未配置SSH证书信任,需要在执行ansible命令时添加 -k 参数,要求提供root密码 即在提示 SSH password:时输入 很多人更倾向于使用Linux普通用户账户进行连接并使用sudo命令实现root权限,格式为:ansible webserver -m ping -u ansible -sudo.
  为了避免Ansible下发指令时输入目标主机密码,通过证书签名达到SSH无密码是一个方案,推荐使用ssk-keygen 与 ssh-copy-id来实现快速证书的生成及公钥下发,其中ssh-keygen生成一对秘钥,使用ssh-copy-id来下发生成的公钥。具体操作如下:

  在主控端主机创建秘钥 执行:ssk-keygen -t rsa, 有询问直接回车键即可 将在/root/.ssh目录下生成一对秘钥,其中>[root@localhost ansible]# ssh-keygen -t rsa -b 4096  
Generating public/private rsa key pair.
  
Enter file in which to save the key (/root/.ssh/id_rsa):
  
Created directory '/root/.ssh'.
  
Enter passphrase (empty for no passphrase):
  
Enter same passphrase again:
  
Your identification has been saved in /root/.ssh/id_rsa.
  
Your public key has been saved in /root/.ssh/id_rsa.pub.
  
The key fingerprint is:
  
36:ca:5e:14:6b:ef:ab:12:4d:82:be:33:d0:70:3c:f4 root@localhost
  
The key's randomart image is:
  
+--[ RSA 4096]----+
  
|                 |
  
|    .            |
  
|   o o  .        |
  
|  . = E .o       |
  
|   = . +S        |
  
|  . o..=.o       |
  
|   . .o.. .      |
  
|    +... .       |
  
|     o....o.     |
  
+-----------------+
  
[root@localhost ansible]#
  接下来同步公钥文件id_rsa.pub到目标主机,推荐使用ssh-copy-id公钥拷贝工具,命令格式:
  /usr/bin/ssh-copy-id [-i[identity_file]][user@]machine 本例中使用一下命令:
ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.137.8  
ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.137.9
  效验SSH无密码是否配置成功 ,运行 ssh root@192.168.137.8 如果直接进入目标root账号提示符,则署名配置成功。
  定义主机与组规则
  Ansible通过定义好的主机与组规则(Inventory)对匹配的目标主机进行远程操作,配置规则文件默认是/etc/ansible/hosts.
  定义主机与组
  所有定义的主机与组规则都在/etc/ansible/hosts文件中. 为ini文件格式 主机可以用域名、IP、别名进行标识,其中webserver、dbserver 为组名 紧跟着的主机为其成员 格式如下:
mail.example.com  
192.168.1.21:2135
  

  
[webserver]
  
foo.example.com
  
bar.example.com
  
192.168.1.22
  

  
[dbserver]
  
one.example.com
  
two.example.com
  
three.example.com
  
192.168.1.23
  其中 192.168.1.21:2135 的意思是定义一个SSH服务端口为2135的主机,当然我们也可以使用别名来描述一台主机。
  jumper ansible_ssh_port=22 ansible_ssh_host=192.168.1.50
  jumper为定义一个s别名,ansible_ssh_port为主机SSH服务端口,ansible_ssh_host为目标主机 更多保留主机变量如下:
  ansible_ssh_host  目标主机地址
  ansible_ssh_port   目标主机SSH端口 端口22无需指定
  ansible_ssh_user  目标主机用户名
  ansible_ssh_pass  目标主机密码
  ansible_connection 目标主机连接类型 可以视local、ssh 或者paramiko
  ansible_ssh_private_key_file 目标主机SSH私钥
  ansible_*_interpreter  指定采用非Python的其他脚本语言 如 Ruby Perl 或者其他
  组成员主机名称支持正则描述 示例如下:
[webserver]  
www[01:20].example.com
  

  
[dbserver]
  
db-[a:f].example.com
  定义主机变量
  主机可以指定变量,以便后面供Playbooks配置使用 比如定义主机hosts1 和 hosts2 上Apache参数http_port 及 maxRequestsPerChild,目的是让两台主机产生Apache配置文件httpd.conf差异化,定义格式如下:
[atlanta]  
host1 http_port=80 maxRequestsPerChild=808
  
host2 http_port=8080 maxRequestsPerChild=909
  定义组变量
  组变量的作用域是覆盖组所有成员,通过定义一个新块,块名由组名+":vars" 组成,定义格式如下:
[atlanta]  
host1
  
host2
  

  
[atlanta:vars]
  
ntp_server=ntp.atlanta.example.com
  
proxy=proxy.atlanta.example.com
  同时Ansible支持组嵌套组 ,通过定义一个新块,块名由组名+":children"组成,格式如下:
[atlanta]  
host1
  
host2
  

  
[raleigh]
  
host2
  
host3
  

  
[southeast:children]
  
atlanta
  
raleigh
  

  
[southeast:vars]
  
some_server=foo.southeast.example.com
  
halon_system_timeout=30
  
self_destruct_countdown=60
  
escape_pods=2
  

  
[usa:children]
  
southeast
  
northeast
  
southwest
  
southeast
  分离主机与组特定数据
  为了更好规范定义的主机与组变量,Ansible支持将/etc/ansible/hosts定义的主机名与组变量单独剥离出来存放到指定文件夹中.将采用YAML格式存放,存放位置规定: "/etc/ansible/group_vars/+组名" 和 "/etc/ansible/host_vars/+主机名" 分别存放指定组名或者主机名定义的变量。如下:
  /etc/ansible/group_vars/dbservers
  /etc/ansible/group_vars/webservers
  定义的dbserver变量格式为:
  [/etc/ansible/group_vars/dbservers]
  ---
  ntp_server:acme.example.org
  database_server:storage.example.org
  Ansible常用模块

  •   远程命令模块
   ansible webserver -m command -a "free -m"  #远程命令  
   ansible webserver -m script -a "/home/test.sh" #远程主机执行主控服务器脚本
  
   ansible webserver -m shell -a "/home/test.sh"   #执行远程主机脚本
  2. copy模块
  实现主控端想目标主机拷贝文件
  以下例子实现拷贝/home/test.sh文件到webserver组目标主机/tmp目录下 并更新文件属主和权限
ansible webserver -m copy -a "src=/home/test.sh dest=/tmp/ owner=root group=root mode=0755"  3.    stat模块
  获取远程文件状态信息,包括atime、ctime、mtime、MD5、uid、gid等信息
  例子:
ansible webserver -m stat -a "path=/etc/sysctl.conf"  4.    get_url模块
  实现在远程主机下载指定URL到本地 支持sha256sum文件效验
  实例:
ansible webserver -m get_url -a "url=http://www.baidu.com dest=/tmp/index.html mode=0440 force=yes "  5.    yum功能
  Linux平台软件包管理操作 常见的有yum apt 管理方式
  实例 :
   ansible webserver -m yum -a "name=curl state=latest"  
   ansible webserver -m apt -a "pkg=curl state=latest"
  6.    cron模块
  远程主机crontab配置
  实例:
ansible webserver -m cron -a "'name=check dirs' hour='5,2' job='ls -alh > /dev/null'"  结果:
#Ansible: test_check  
* 5,2 * * * ls -alh > /root/ll.txt
  7.   mount模块
  远程主机分区挂载
  实例:
ansible webserver -m mount -a "name=/mnt/data src=/dev/sd0 fstype=ext3 opts=ro state=present"  8.    service模块
  远程主机系统服务管理
  实例:
   ansible webserver -m service -a "name=nginx state=stopped"  
   ansible webserver -m service -a "name=nginx state=restarted"
  
   ansible webserver -m service -a "name=nginx state=reloaded"
  9.    sysctl包管理模块
  远程主机sysctl配置
  实例:
  ansible webserver -m sysctl -a "name=kernel.panic value=3 sysctl_file=/etc/sysctl.conf checks=before reload=yessalt '*' pkg.upgrade  10 .    user模块
  远程主机系统用户管理
  实例:
    ansible webserver -m user -a "name=johnd comment='John Doe'" #添加用户  
    ansible webserver -m user -a "name=johnd state=absent  remove=yes" #删除用户
  playbook介绍:
  playbook是一个不同于使用ansible命令行执行方式的模式,其功能更强大灵活。 简单来说 playbook是一个非常简单的配置管理和多主机部署系统,不同于任何已经存在的模式,可作为合适部署复杂应用程序的基础。playbook可以定制配置,可以按指定的操作步骤有序执行,支持同步和异步方式,官方有提供大量的例子参考。https://github.com/ansible/ansible-examples  。playbook是通过YAML格式来进行描述定义的,可以实现多台主机的应用部署,定在在webserver及dbserver组上执行特定指令步骤。下面介绍一个实例:
---  
- hosts: webserver
  
  vars:
  
    worker_processes: 4
  
    num_cpus: 4
  
    max_open_file: 65506
  
    root: /data
  
  remote_user: root
  
  tasks:
  
  - name ensure nginx is at the latest version
  
    yum: pkg=nginx state=latest
  
  - name: write the nginx config file
  
    template: src=/home/test/nginx2.conf dest=/etc/nginx/nginx.conf
  
    notify:
  
    - restart nginx
  
  - name: ensure nginx is running
  
    service: name=nginx start=started
  
  handlers:
  
  - name: restart nginx
  
    service: name=nginx state=restarted
  以上playbook定制了一个简单的Nginx软件包管理 内容包括安装 配置模板 状态管理等。下面进行说明。
  定义主机和用户:
  在playbook执行时,可以为主机或组定义变量,比如指定远程登录用户。一下为webserver组定义的相关变量,变量的作用域只限于webserver组下的主机。
- hosts: webserver  
  vars:
  
    worker_processes: 4
  
    num_cpus: 4
  
    max_open_file: 65506
  
  remote_user: root
  hosts参数的作用为定义的操作对象,可以视主机或组,本示例定义的为webserver组,同事通过vars定义了4个变量 配置模板用到,其中remote_user 为制动远程操作的用户名,默认为root账号,支持sudo方式运行,通过添加sudo:yes即可。注意 remote_user参数在Ansible1.4或更高版本才引入。
  任务列表:
  所有定义的任务列表tasks list ,playbook将按定义的配置文件自上而下的顺序执行,定义的主机都将得到相同的任务,但执行的返回结果不一定保持一致,取决于主机的环境及程序包状态。建议每个任务事件都定义一个name标签增强可读性,也便于观察输出结果了解运行的位置,默认使用action(具体的执行动作)来替换name作为输入。下列是一个简单的任务定义示例:
tasks:  
  - name: make sure nginx is running
  
  service: name=nginx state=started
  功能实际检测Nginx服务是否处于运行状态,如果没有则启动。其中name标签对下面的action进行描述,action部分可以视ansible的任意模块,本示例为service模块,参数使用key=value的格式,如 name=httpd 在定义任务时也可以引用变量 格式如下:
tasks:  
   - name: create a virtual host file for {{ vhost }}
  
   template: src=somefile.j2 dest=/etc/httpd/conf.d/{{ vhost }}
  在playbook可以通过template模块对本地配置模板文件进行渲染并同步到目标主机。已nginx配置文件为例,定义如下:
- name: write the nginx config file  
  template: src=/etc/ansible/nginx/nginx2.conf dest=/etc/nginx/nginx.conf
  
  notify:
  
  - restart nginx
  其中scr=/etc/ansible/nginx/nginx2.conf位管理端模板文件的存放位置 dest=/etc/nginx/nginx.conf为目标主机nginx配置的文件的存放位置,通过下面Nginx模板文件让大家对模板的定义有个基本的概念。
user nginx;  
worker_processes {{ worker_processes}};
  
{% if num_cpus == 2 %}
  
worker_cpu_affinity 01 10;
  
{% elif num_cpus == 4 %}
  
worker_cpu_affinity 1000 0100 0010 0001;
  
{% elif num_cpus >= 8 %}
  
worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;
  
{% else %}
  
worker_cpu_affinity 1000 0100 0010 0001;
  
{% endif %}
  
worker_rlimit_nofile {{ max_open file }};
  Ansible会根据定义好的模板渲染成真实的配置文件 ,模板使用YAML语法 最终生成的nginx.conf如下:
user nginx;  
worker_processes 4;
  
worker_cpu_affinity 1000 0100 0010 0001;
  
worker_rlimit_nofile 65506;
  档目标主机配置文件发生变化后,通知处理程序Handlers 来触发后面的动作,比如重启nginx服务。handlers中定义的处理程序没有通知触发时时不会执行的,触发后也只会运行一次。触发时通过Handlers定义的name标签来识别的,比如下面的notify中的 restart nginx 与handlers中的 name:restart nginx保持一致。
notify:  
      - restart nginx
  
handlers:
  
      - name: restart nginx
  
      service: name=nginx state=restarted
  执行playbook
  执行playbook可以通过ansible-playbook命令实现,格式: ansible-playbook playbookfiel.yml [参数] 如启用10个并行进程数执行playbook:
  ansible-playbook /etc/ansible/nginx/nginx.yml -f 10
  其他参数:
  -u REMOTE_USER:手工指定远程执行playbook的系统用户
  --syntax-check 检查playbook语法
  --list-hosts playbooks 匹配到的主机列表
  -T TIMEOUT 定义playbook执行超时时间
  --setp 以单任务分步骤运行,方便做每一个不的确认工作。
  更多参数运行 ansible-playbook -help获取。
  以下是一个例子的执行结果  vsftpd.yml文件内容如下:
[root@localhost ansible]# cat vsftpd.yml  
---
  
- hosts: webserver
  
  remote_user: root
  
  tasks:
  
  - name: Install Vsftpd Server
  
    yum: pkg=vsftpd state=latest
  
    notify:
  
    - restart vsftpd
  
  - name: Check Vsftpd is Running
  
    service: name=vsftpd state=started
  
  handlers:
  
    - name: restart vsftpd
  
      service: name=vsftpd stated=restarted
  
[root@localhost ansible]#
  执行结果如下:
[root@localhost ansible]# ansible-playbook vsftpd.yml -f 10  

  
PLAY [webserver] ***************************************************************
  

  
TASK [setup] *******************************************************************
  
ok: [192.168.137.9]
  
ok: [192.168.137.8]
  

  
TASK [Install Vsftpd Server] ***************************************************
  
ok: [192.168.137.9]
  
ok: [192.168.137.8]
  

  
TASK [Check Vsftpd is Running] *************************************************
  
ok: [192.168.137.8]
  
ok: [192.168.137.9]
  

  
PLAY RECAP *********************************************************************
  
192.168.137.8              : ok=3    changed=0    unreachable=0    failed=0
  
192.168.137.9              : ok=3    changed=0    unreachable=0    failed=0
  

  
[root@localhost ansible]#
  角色定义
  已经了解了变量,任务和处理程序的定义 有什么方法更好的进行组织或抽象 让其复用性更强、功能根据模块化?答案就是角色,角色是Ansible定制好的一种标准规范,以不同级别目录层次及文件对角色、变量、任务、处理程序等拆分、为后续功能扩展、可维护性打下基础 一个定向的角色目录结构如下:
site.yml  
webserver.yml
  
fooserver.yml
  
roles/
  
   common/
  
       files/
  
       templates/
  
       tasks/
  
       handlers/
  
       vars/
  
       meta/
  
   webserver/
  
       files/
  
       templates/
  
       tasks/
  
       handlers/
  
       vars/
  
       meta/
  在playbook是这样引用的:
[site.yml]  
---
  
- hosts:webserver
  
  roles:
  
      -common
  
      -webserver
  角色定制已下规范,其中X为角色名
  如roles/x/tasks/main.yml 文件存在。其中列出的任务江北添加到执行队列
  如roles/x/handlers/main.yml 文件存在 其中所列出的处理程序将被添加到执行队列;
  如roles/x/vars/main.yml 文件存在 其中列出的变量将被添加到执行队列;
  如roles/x/meta/main.yml 文件存在 所列任何作用的依赖关系将被添加到角色的列表
  任何副本任务可以引用roles/x/files/无需写路径 默认相对或绝对医用;
  任何脚本任务可以引用roles/x/files/无需写路径 默认相对或绝对医用;
  任何模板任务可以引用文件中的roles/x/templates/无需写路径 默认相对或绝对医用;
  为了便于更好的理解 以下示例以角色的形式存在。同时添加了一个公共角色common 从角色全局作用域中抽取出公共的部分,一般为系统的基础服务,比如 ntp iptables、selinux、sysctl等。本示例是针对ntp服务的管理
  playbook目录结构
  playbook目录包括变量定义目录group_vars、主机组定义文件hotst、全局配置文件site.yml 角色功能目录,playbook目录如下:
[root@localhost playbook]# tree nginx/  
nginx/
  
├── group_Vars
  
├── hosts
  
├── roles
  
│   ├── common
  
│   │   ├── handlers
  
│   │   │   └── main.yml
  
│   │   ├── tasks
  
│   │   │   └── main.yml
  
│   │   ├── templates
  
│   │   │   └── ntp.conf.js
  
│   │   └── vars
  
│   │       └── main.yml
  
│   └── web
  
│       ├── handlers
  
│       │   └── main.yml
  
│       ├── tasks
  
│       │   └── main.yml
  
│       └── templates
  
│           └── nginx2.conf
  
└── site.yml
  

  
11 directories, 9 files
  
[root@localhost playbook]#
  1.新建目录nginx
  2.定义主机组
  以下定义了一个业务组webserver 成员时两台主机
  【nginx/hosts】
  [webserver]  
  192.168.137.8
  
  192.168.137.9
  注意:这个非必选配置,默认将引用/etc/ansible/hosts的参数 角色中自定义组与主机文件将通过 -i file 命令行参数调用。如 ansible-playbook -i hosts 来调用
  3.定义主机组或变量
  group_vars为定义变量目录,目录当中的文件名要与组名保持一致,组变量文件定义的变量作为域值受限于该组,all代表所有主机
  【nginx/group_vars/all】
---  
nptserver:ntp.sjtu.edu.cn
  【nginx/group_vars/webserver】
---  
worker_processes:4
  
num_cpus:4
  
max_open_file:65536
  
root:/data
  4. 全局配置文件site.yml
  全局配置文件引用了两个角色块,角色应用方位及实现的功能功都不一样:
  【nginx/site.yml】
---  
- name:apply common configuration to all nodes
  
  hosts:all
  
  roles:
  
    - common
  
- name:configure and deploy the webserver and application code
  
  hosts:webserver
  
  roles:
  
    - we
  全局配置文件site.yml引用了两个角色,一个为公共类的common,另一个为web类,分别对应nginx/common 、nginx/web目录 以此类推,可以引用更多的角色,如dbserver、nosql、Hadoop等,前提是我们要先进行定义。通常情况下一个角色对应着一个特定功能服务。通过hosts参数来绑定角色对应的主机或组。
  5.    角色common的定义
  角色common定义了 handlers   tasks   templates   vars 4个功能类,分别存放处理程序、任务列表、模板、变量的配置文件main.yml。需要注意的是 vars/main.yml中定义的变量优先级高于/nginx/group_vars/all定义的 可以从ansible-playbook的执行结果中得到验证。各功能模块配置文件如下:
  [handlers/main.yml]
- name:restart ntp  
  service:name=ntpd state=restarted
  [tasks/main.yml]
- name:Install ntp  
  yum:name=ntp state=present
  

  
- name:Configure ntp file
  
  template:src=ntp.conf.js dest/etc/ntp.conf
  
  notify:restart ntp
  

  
- name:Start the ntp service
  
  service: name=ntpd state=started enabled=true
  

  
- name: test to see if selinux is running
  
  command:getenforce
  
  register:sestatus
  
  changed_when:false
  其中template:src=ntp.conf.js引用是唔需要写路径。默认在上级的templates目录中查找。
  [templates/ntp.conf.j2]
driftfile /var/lib/ntp/drift  
restrict 127.0.0.1
  
restrict -6 ::1
  
server {{ ntpserver }}
  
includefile /etc/ntp/crypto/pw
  
keys /etc/ntp/keys
  此处` ntpserver `将引用vars/main.yml定义的ntpserver变量。
  [vars/main.yml]
---  
ntpserver:210.72.145.44
  6. 角色WEB的定义
  角色web定义了handlers tasks templates三个功能类  具体如下:
【handlers/main.yml】  
- name: restart nginx
  
   service: name=nginx state=restarted
  
【tasks/main.yml】
  
- name: Install nginx
  
   yum: pkg=nginx state=latest
  
- name: write the nginx config file
  
   template: src=nginx2.conf dest=/etc/nginx/nginx.conf
  
   notify:
  
   - restart nginx
  
- name: check nginx is running
  
   service:name=nginx state=started
  
【template/nginx2.conf】
  
user    nginx;
  
worker_processes {{ worker_processes }};
  
{% if num_cpus == 2 %}
  
worker_cpu_affinity 01 10;
  
{% if num_cpus == 4 %}
  
worker_cpu_affinity 1000 0100 0010 0001;
  
{% if num_cpus >= 8 %}
  
worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;
  
{% else %}
  
worker_cpu_affinity 1000 0100 0010 0001;
  
{% endif %}
  
worker_rlimit_nofile {{ max_open_file }};
  
....
  7 运行角色
  cd /etc/ansible/playbook/nginx
  ansible-playbook -i hosts site.yml -f 10
  我自己的测试执行结果如下:
[root@localhost nginx]# ansible-playbook -i hosts site.yml -f 10  

  
PLAY [comment settings] ********************************************************
  

  
TASK [setup] *******************************************************************
  
ok: [192.168.137.8]
  
ok: [192.168.137.9]
  

  
TASK [common : Install ntp] ****************************************************
  
ok: [192.168.137.9]
  
ok: [192.168.137.8]
  

  
TASK [common : write ntp config file] ******************************************
  
ok: [192.168.137.9]
  
ok: [192.168.137.8]
  

  
TASK [common : start ntp server] ***********************************************
  
ok: [192.168.137.8]
  
ok: [192.168.137.9]
  

  
TASK [common : check selinux diabled] ******************************************
  
ok: [192.168.137.9]
  
ok: [192.168.137.8]
  

  
PLAY [Deploy webserver] ********************************************************
  

  
TASK [setup] *******************************************************************
  
ok: [192.168.137.9]
  
ok: [192.168.137.8]
  

  
TASK [web : Copy nginx yum repo file] ******************************************
  
ok: [192.168.137.8]
  
ok: [192.168.137.9]
  

  
TASK [web : Install Nginx Web Server] ******************************************
  
ok: [192.168.137.9]
  
ok: [192.168.137.8]
  

  
TASK [web : write nginx config] ************************************************
  
ok: [192.168.137.8]
  
ok: [192.168.137.9]
  

  
TASK [web : check nginx running] ***********************************************
  
ok: [192.168.137.9]
  
ok: [192.168.137.8]
  

  
PLAY RECAP *********************************************************************
  
192.168.137.8              : ok=10   changed=0    unreachable=0    failed=0
  
192.168.137.9              : ok=10   changed=0    unreachable=0    failed=0
  

  
[root@localhost nginx]#
  目录结构和文件内容如下:
├── group_vars  
│   └── webserver
  
├── hosts
  
├── roles
  
│   ├── common
  
│   │   ├── handlers
  
│   │   │   └── main.yml
  
│   │   ├── tasks
  
│   │   │   └── main.yml
  
│   │   ├── templates
  
│   │   │   └── ntp.conf.j2
  
│   │   └── vars
  
│   │       └── main.yml
  
│   └── web
  
│       ├── files
  
│       │   └── nginx.repo
  
│       ├── handlers
  
│       │   └── main.yml
  
│       ├── tasks
  
│       │   └── main.yml
  
│       └── templates
  
│           └── nginx2.conf
  
└── site.yml
  文件内容如下:
[root@localhost playbook]# cat nginx/group_vars/webserver  
---
  
worker_processes: auto
  
num_cpus: 2
  
max_open_file: 65536
  
root: /data
  
[root@localhost playbook]# cat nginx/hosts
  
[webserver]
  
192.168.137.8
  
192.168.137.9
  
[root@localhost playbook]# cat nginx/roles/common/handlers/main.yml
  
- name: restart ntp
  
  service: name=ntpd state=restarted
  
[root@localhost playbook]# cat nginx/roles/common/tasks/main.yml
  
- name: Install ntp
  
  yum: name=ntp state=present
  
- name: write ntp config file
  
  template: src=ntp.conf.j2 dest=/etc/ntp.conf
  
  notify: restart ntp
  
- name: start ntp server
  
  service: name=ntpd state=started enabled=true
  
- name: check selinux diabled
  
  command: getenforce
  
  register: sestatus
  
  changed_when: false
  
[root@localhost playbook]# cat nginx/roles/common/templates/ntp.conf.j2
  
driftfile /var/lib/ntp/drift
  
restrict 127.0.0.1
  
restrict -6 ::1
  

  
server {{ ntpserver }}
  

  
includefile /etc/ntp/crypto/pw
  
keys /etc/ntp/keys
  
[root@localhost playbook]# cat nginx/roles/common/vars/main.yml
  
---
  
ntpserver: ntp.sjtu.edu.cn
  
[root@localhost playbook]# cat nginx/roles/web/handlers/main.yml
  
- name: restart nginx
  
  service: name=nginx state=restarted
  
[root@localhost playbook]# cat nginx/roles/web/tasks/main.yml
  
- name: Copy nginx yum repo file
  
  copy: src=/root/playbook/nginx/roles/web/files/nginx.repo dest=/etc/yum.repos.d/ owner=root group=root mode=0755
  
- name: Install Nginx Web Server
  
  yum: name=nginx state=latest
  
- name: write nginx config
  
  template: src=nginx2.conf dest=/etc/nginx/nginx.conf
  
  notify:
  
  - restart nginx
  
- name: check nginx running
  
  service: name=nginx state=started
  
[root@localhost playbook]# cat nginx/roles/web/templates/nginx2.conf
  
user  nginx;
  
worker_processes {{ worker_processes }};
  
{% if num_cpus == 2 %}
  
worker_cpu_affinity 01 10;
  
{% elif num_cpus == 4 %}
  
worker_cpu_affinity 1000 0100 0010 0001;
  
{% elif num_cpus >= 8 %}
  
worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;
  
{% else %}
  
worker_cpu_affinity 1000 0100 0010 0001;
  
{% endif %}
  
worker_rlimit_nofile {{ max_open_file }};
  

  

  
error_log  /var/log/nginx/error.log warn;
  
pid        /var/run/nginx.pid;
  

  

  
events {
  
    worker_connections  204800;
  
    use epoll;
  
    multi_accept on;
  
}
  

  

  
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;
  
    server_tokens off;
  
    tcp_nopush on;
  
    keepalive_timeout 10;
  
    client_header_timeout 10;
  
    client_body_timeout 10;
  
    reset_timedout_connection on;
  
    send_timeout 10;
  
    #limit_conn_zone $binary_remote_addr zone=addr:10m;
  
    #limit_conn addr 100;
  
    gzip on;
  
    gzip_min_length 1000;
  
    gzip_comp_level 4;
  
    include /etc/nginx/conf.d/*.conf;
  
}
  
[root@localhost playbook]# cat nginx/site.yml
  
---
  
- name: comment settings
  
  hosts: all
  
  roles:
  
     - common
  

  
- name: Deploy webserver
  
  hosts: webserver
  
  roles:
  
    - web
  

  
[root@localhost playbook]#
  获取远程主机系统信息:Facts
  facts是一个非常有用的组件,类似于Saltstack的Grains功能,实现获取远程主机的系统信息,包括主机名,IP地址,操作系统,分区信息,硬件信息等。可以配合playbook实现更加个性化和灵活的要求。比如在httpd.conf模板中引用Facts的主机名信息作为ServerName参数的值。通过运行  ansible-playbook -m setup 可获取Facts信息 例如 获取192.168.137.8 的Facts信息需要运行
  ansible-playbook 192.168.137.8 -m setup  结果如下:
[root@localhost ~]# ansible 192.168.137.8 -m setup  
192.168.137.8 | SUCCESS => {
  
    "ansible_facts": {
  
        "ansible_all_ipv4_addresses": [
  
            "192.168.137.8"
  
        ],
  
        "ansible_all_ipv6_addresses": [
  
            "fe80::20c:29ff:fe7a:596d"
  
        ],
  
        "ansible_architecture": "x86_64",
  
        "ansible_bios_date": "05/20/2014",
  
        "ansible_bios_version": "6.00",
  
        "ansible_cmdline": {
  
            "KEYBOARDTYPE": "pc",
  
            "KEYTABLE": "us",
  
            "LANG": "en_US.UTF-8",
  
            "SYSFONT": "latarcyrheb-sun16",
  
            "crashkernel": "auto",
  
            "quiet": true,
  
            "rd_LVM_LV": "vg_serv/lv_root",
  
            "rd_NO_DM": true,
  
            "rd_NO_LUKS": true,
  
            "rd_NO_MD": true,
  
            "rhgb": true,
  
            "ro": true,
  
            "root": "/dev/mapper/vg_serv-lv_root"
  
        },
  
        "ansible_date_time": {
  
            "date": "2016-07-26",
  
            "day": "26",
  
            "epoch": "1469546980",
  
            "hour": "23",
  
            "iso8601": "2016-07-26T15:29:40Z",
  
            "iso8601_basic": "20160726T232940834874",
  
            "iso8601_basic_short": "20160726T232940",
  
            "iso8601_micro": "2016-07-26T15:29:40.835071Z",
  
            "minute": "29",
  
            "month": "07",
  
            "second": "40",
  
            "time": "23:29:40",
  
            "tz": "CST",
  
            "tz_offset": "+0800",
  
            "weekday": "Tuesday",
  
            "weekday_number": "2",
  
            "weeknumber": "30",
  
            "year": "2016"
  
        },
  
        "ansible_default_ipv4": {
  
            "address": "192.168.137.8",
  
            "alias": "eth1",
  
            "broadcast": "192.168.137.255",
  
            "gateway": "192.168.137.1",
  
            "interface": "eth1",
  
            "macaddress": "00:0c:29:7a:59:6d",
  
            "mtu": 1500,
  
            "netmask": "255.255.255.0",
  
            "network": "192.168.137.0",
  
            "type": "ether"
  
        },
  

  
.......................省略
  在模板文件中这样引用Facts信息
  ` ansible_device`.`sda`.`model `
  ` ansible_hostname `
  Jinja2过滤器
  jinja2是Python下一个广泛应用的模板引擎,他的设计类似于Django的模板引擎,并扩展了其语法和一系列强大的功能,官网地址 http://jinja.pocoo.org/  简要说明Ansible 使用Jinja2强大的过滤器Filters功能
  使用格式:{{ 变量名 | 过滤方法 }}
  示例:获取一个文件路径变量过滤出文件名
  {{ path | basename }}
  获取文件所处的目录名:
  {{ path | dirname }}
  下面为一个完整的示例,实现从/etc/profile 中过滤出文件名 profile  并输出重定向到/tmp/testshell文件中
---  
- hosts: 192.168.1.21
  
  vars:
  
      filename: /etc/profile
  
  tasks:
  
     - name: "shell"
  
       shell: echo {{ filename | basename }} >> /tmp/testshell
  本地Facts
  我们可以通过Facts来获取目标主机的系统信息,当这些信息不能满足我们功能需求时,可以通过编写自定义的facts模块来实现。当然 还有一个更简单的办法 就是通过本地facts来实现。 只需要在目标设备/etc/ansible/facts.d目录定义JSON、INI或可执行文件的JSON输出 文件扩展名使用“.fact” 这些文件都可以作为Ansible本地Facts 例如 在目标设备 192.168.137.9 定义三个变量  供以后playbook使用
  【/etc/ansible/facts.d/preferences.fact】
  [general]
  max_memory_size=32
  max_user_processes=3730
  open_files=65535
  在主控端运行ansible 192.168.1.21 -m setup -a "filter=ansible_local" 可以看到定义的结果 返回结果如下:
[root@localhost ~]# ansible 192.168.137.9 -m setup -a "filter=ansible_local"  
192.168.137.9 | SUCCESS => {
  
    "ansible_facts": {
  
        "ansible_local": {
  
            "preferences": {
  
                "general": {
  
                    "max_memory_size": "32",
  
                    "max_user_processes": "3730",
  
                    "open_files": "65535"
  
                }
  
            }
  
        }
  
    },
  
    "changed": false
  
}
  
[root@localhost ~]#
  注册变量:
  变量的另一个用途是将一条命令的运行结果保存到变量中,供后面的playbook使用 下面是一个简单的示例
- hosts: webserver  
  tasks:
  
    - shell: /usr/bin/foo
  
      register: foo_result
  
      ignore_errors:True
  
    - shell: /usr/bin/bar
  
      when: foo_result.rc == 5
  上述例子注册了一个foo_result的变量 值为shell:/usr/bin/foo的运行结果。ingore_error为忽略错误。变量注册完成后。就可以在后面的playbook中使用了。当条件语句when:foo_result.rc == 5成立时 shell:/usr/bin/bar命令才会运行,其中foo_result.rc为返回/usr/bin/foo的resultcode 返回码  例如 返回rc=0的返回码
[root@localhost ~]# ansible 192.168.137.9 -a "free -m"  
192.168.137.9 | SUCCESS | rc=0 >>
  
             total       used       free     shared    buffers     cached
  
Mem:          1989        601       1387          0         63        252
  
-/+ buffers/cache:        285       1704
  
Swap:         2015          0       2015
  

  
[root@localhost ~]#
  条件语句:
  有时候一个playbook的结果取决于一个变量  或者取决于上一个任务的执行结果.在某些情况下 一个变量的值可以依赖于其他变量的值 当然也会影响Ansible的执行过程。
  下面主要介绍when声明:
  有时候我们想跳过某些主机的执行步骤 比如符合特定版本的操作系统将不安装某个软件。在Ansible中很容易做到这一点 通过when 子句实现  其中将引用jinja2表达式 如下示例:
tasks:  
  - name: "shutdown Debian flavored systems"
  
    command: /sbin/shutdown -t now
  
    when: ansible_os_family == "Debian"
  通过定义任务的facts本地变量 ansible_os_family 操作系统版本名称是否为Debian 结果将返回BOOL类型值,为True时将执行上一条语句 command:/sbin/shutdown -t now 为False时该条语句都不会触发 。看另一个示例 通过判断一条命令执行结果做不同的处理。
tasks:  
   - command: /bin/false
  
     register: result
  
     ingore_error: True
  
   - command: /bin/someting
  
     when: result|failed
  
   - command: /bin/someting_else
  
     when: result|success
  
   - command: /bin/still/someting
  
     when: result|skipped
  when:result|success的意思当变量result的执行结果为成功状态时 将执行/bin/someting_else命令 其他同理。其中success为ansible内部过滤器方法 返回True代表运行成功。
  循环:
  通常一个任务会做很多事情,例如创建大量的用户,安装很多包 或者重复特定步骤 直到某种结果条件为止.ansible为我们提供了此支持。示例如下:
- name: add several users  
  user: name={{ item }} state=present groups=wheel
  
  with_items:
  
    - testuser1
  
    - testuser2
  这个示例实现了一个批量创建用户的功能 with_items会自动循环执行上面的语句 user: name=` item ` state=present groups=wheel 循环次数为with_items的元素个数。这里有两个元素 分别是testuser1 和 testuser2  会分别替换 ` item `项 这个示例与下面的语句是等价的:
- name: add user testuser1  
  user: name=testuser1 state=present groups=wheel
  
- name: add user testuser2
  
  user: name=testuser2 state=present groups=wheel
  当然 元素也支持字典的形式 如下:
- name: add several users  
  user: name={{ item.name }} state=present groups={{ item.groups }}
  
  with_items:
  
     - { name: 'testuser1',groups:'wheel'}
  
     - { name: 'testuser2',groups:'root'}
  循环也支持list形式 不过是通过with_flattened语句实现 如下示例:
---  
packages_base:
  
    - [ 'foo-packages','bar-packages']
  
packages_apps:
  
    - [ ['one-packages','two-packages'] ]
  
    - [ ['red-packages'],['blue-packages'] ]
  以上定义了两个列表变量,分别是需要安装的软件包名 以便后面如下引用:
- name: flattened loop demo  
  yum: name={{ item }} state=installed
  
  with_flattened:
  
      - packages_base
  
      - packages_apps

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-543323-1-1.html 上篇帖子: ansible 的简单介绍 下篇帖子: ansible 部署ssh 偶尔巨慢的解决方法
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表