Ansible

一、学习资源

https://www.jianshu.com/p/575ced3a08fa
http://www.ansible.com.cn/index.html
http://docs.ansible.com/

二、ansible命令的相关用法

指定test组使用shell模块执行uname -m命令
ansible -i /etc/ansible/hosts test -m shell -a 'uname -m'
本地执行date命令,默认模块command
ansible 127.0.0.1 -a 'date'
指定所有主机执行date 
ansible all -a 'date'
指定所有主机执行date,并输入密码 
ansible -i /etc/ansible/hosts  -a 'date' -k
查看所有的模块
ansible-doc -a
查看copy模块的用法
ansible-doc -s copy
ansible-doc -s docker
查看docker的模块
ansible-doc -l |grep docker
查看命令运行的详细信息,有助于排错
ansible -i /etc/ansible/hosts test -m shell -a 'uname -m' -vvv

  

使用命令行的方式放到后台运行

放到后台去运行,然后查询ID,查看有没有跑完
 [root@master ~]# ansible all -m ping -B 3600 -P 0
192.168.222.147 | SUCCESS => {
    "ansible_job_id": "678581125189.1288", 
    "changed": true, 
    "finished": 0, 
    "results_file": "/root/.ansible_async/678581125189.1288", 
    "started": 1
}
192.168.222.146 | SUCCESS => {
    "ansible_job_id": "36685447786.3154", 
    "changed": true, 
    "finished": 0, 
    "results_file": "/root/.ansible_async/36685447786.3154", 
    "started": 1
}
[root@master ~]# ansible all -m async_status -a 'jid=678581125189.1288'
192.168.222.147 | SUCCESS => {
    "ansible_job_id": "678581125189.1288", 
    "changed": false, 
    "finished": 1, 
    "ping": "pong"
}
192.168.222.146 | FAILED! => {
    "ansible_job_id": "678581125189.1288", 
    "changed": false, 
    "finished": 1, 
    "msg": "could not find job", 
    "started": 1
}

三、playbook

3.1)

如果你不需要获取被控机器的 fact 数据的话,你可以关闭获取 fact 数据功能。关闭之后,可以加快 ansible-playbook 的执行效率,尤其是你管理很大量的机器时,这非常明显。关闭获取 facts 很简单,只需要在 playbook 文件中加上“gather_facts: no”。

---
- hosts: webservers
  vars:
    http_port: 80
    max_clients: 200
  remote_user: root
  tasks:
  - name: ensure apache is at the latest version
    yum: pkg=httpd state=latest
  - name: write the apache config file
    template: src=/srv/httpd.j2 dest=/etc/httpd.conf
    notify:
    - restart apache
  - name: ensure apache is running
    service: name=httpd state=started
  handlers:
    - name: restart apache
      service: name=httpd state=restarted

3.2)几种变量的使用方式

1、在hosts里面自定义变量
在hosts里面的主机组里面,添加key
[test]
192.168.222.146
192.168.222.147
[test:vars]
key=nima
用debug输出
---
- hosts: all
  gather_facts: no
  tasks:
  - name: display var
    debug: msg="{{key}}"

2、在playbook中定义变量,这个高于上面的优先级
---
- hosts: all
  gather_facts: no
  vars:
    key: heihei
  tasks:
  - name: display var
    debug: msg="{{key}}"

	
	
---
- hosts: all
  gather_facts: no
  vars:
    key: heihei
    ji: hermes
  tasks:
  - name: display var
    debug: msg="{{key}}---{{ji}}"
	
3、通过文件定义变量var.yml
[root@master playbook]# cat var.yml 
---
key3: weiwei
[root@master playbook]# cat var.yml 
---
key3: weiwei


[root@master playbook]# cat test.yml 
---
- hosts: all
  gather_facts: no
  vars_files: 
    - /etc/ansible/playbook/var.yml
  tasks:
  - name: display var
    debug: msg="{{key3}}"


4、从命令行引入变量,内部需要先定义变量,这个优先级最高
ansible-playbook test.yml -e "key3=ni"

5、任务中传递的变量
[root@master playbook]# cat test.yml 
---
- hosts: all
  gather_facts: no
  tasks:
  - name: register var
    shell: hostname
    register: info     	//将处理的字典返回给info
  - name: display var
    debug: msg="{{info}}"		//因为是Python写的,所以可以根据键获得值debug: msg="{{info.stdout}}"

3.3)playbook几种循环方式

6、循环列表
---
- hosts: all
  gather_facts: no
  tasks:
  - name: debug loops
    debug: msg="{{item}}"
    with_items: 
    - one
    - two
    - three
    - four

例如
---
- hosts: all
  gather_facts: no
  tasks:
  - name: install
    yum: name="{{item}}" state=present
    with_items:
    - nginx
    - mysql
    - php
    - zabbix

7、循环字典
---
- hosts: all
  tasks:
  - name: dict
    debug: msg="name--->{{item.key}}value--->{{item.value}}"
    with_items:
    - {key: "one",value: "va1"}
    - {key: "two",value: "va2"}

8、嵌套循环
[root@master playbook]# cat qiantao.yml 
---
- hosts: all
  tasks:
  - name: debug loops
    debug: msg="name--->{{item[0]}} value--->{{item[1]}}"
    with_nested:
    - ['a','b']
    - ['c','d','e']

9、散列循环,对于自定义的变量循环
---
- hosts: all
  gather_facts: no
  vars:
    user:
      shan:
        name: shan
        shell: bash
      heihei:
        name: heihei
        shell: jjj
  tasks: 
   - name: loop
     debug: msg="{{item.key}}"
     with_dict: "{{user}}"

10、文件循环
---
- hosts: all

  tasks:

    # first ensure our target directory exists
    - file: dest=/etc/fooapp state=directory

    # copy each file over that matches the given pattern
    - copy: src={{ item }} dest=/etc/fooapp/ owner=root mode=600
      with_fileglob:
        - /playbooks/files/fooapp/*
		

11、达到某条件终止循环
- shell: /usr/bin/foo
  register: result
  until: result.stdout.find("all systems go") != -1
  retries: 5
  delay: 10
  
 [root@master playbook]# cat heihei.yml 
---
- hosts: all
  gather_facts: no
  tasks: 
  - name: os
    shell: /bin/uname -m
    register: result
    until: result.stdout == "i686"
    retries: 3
    delay: 5

3.4)条件判断when,when result|skipped这种方式是jinjia2的方式,result是执行命令的返回字典,当skipped为true的时候,当前task执行。

12、条件判断 when
tasks:
  - command: /bin/false
    register: result
    ignore_errors: True
  - command: /bin/something
    when: result|failed
  - command: /bin/something_else
    when: result|success
  - command: /bin/still/something_else
    when: result|skipped
	
---
- hosts: all
  tasks:
   - name: redhat install nginx
     yum: name=nginx.i686 state=present
     when: ansible_os_family == "RedHat"
   - name: restart nginx
     shell: /etc/init.d/nginx reload
     when: ansible_os_family == "RedHat" 

  

3.5)jinjia2过滤器

---
- hosts: all
  gather_facts: no
  vars:
    list: [1,2,3,4]
    one: "1"
    str: "string"
    ansible: "hermes"
  tasks: 
  - name: print str
    debug: msg="{{str}}"
  - name: run commands
    shell: df -h
    register: info
  - name: pprint info
    debug: msg="{{info.stdout|pprint}}"
  - name: info
    debug: msg="{{info}}"
  - name: debug conditionals filter
    debug: msg="the run commands status is changed"
    when: info|changed  
  - name: debug int caplitailize filter
    debug: msg="the int value is===>{{one|int}} the lower value is===>{{str|capitalize}}"
  - name: debug default filter
    debug: msg="the variable value is===>{{ansible|default('ansible is not define')}}"
  - name: debug list max and min filter
    debug: msg="the list max value is==={{list|max}} and list min value is===>{{list|min}}"
  - name: debug random filter
    debug: msg="the list random value is {{list|random}} {{1000|random(1,10)}}"
  - name: debug join
    debug: msg="the top filter value is {{list|join("+")}}"
  - name: debug replace
    debug: msg="the replace value is {{str|replace("t","T")}}"
  - name: debug regex_replace
    debug: msg="the regex_replace value is {{str|regex_replace('.*tr(.*)$','weiwei')}}"

  

3.6)jinjia2语法逻辑控制,,需要使用template模块。

[root@master playbook]# cat f2.j2 
{% set list=['one','two','three'] %}
{% for i in list %}
   {{i}}
{% endfor%}


{% set list1=['one','two','three'] %}
{% for i in list1 %}
   {% if i == 'one' %}
      ===>{{i}}
   {% elif loop.index ==2 %}
      ===>{{i}}
   {% else %}
      ===>{{i}}
   {% endif %}
{% endfor %}

{% set dict={'key':'value'}%}
{% for key,value in dict.iteritems()%}
   {{key}}===>{{value}}
{% endfor %}

{% set dict1={'key1':{'key2':'vlan'}}%}
{{dict1['key1']['key2']}}


[root@master playbook]# cat jinjia2.yml 
---
- hosts: all
  gather_facts: no 
  tasks:
  - name: template
    template: src=/etc/ansible/playbook/f2.j2 dest=/tmp/f2 

  

四、Playbook的标准目录结构,标准很重要。

production                # inventory file for production servers 关于生产环境服务器的清单文件
stage                     # inventory file for stage environment 关于 stage 环境的清单文件

group_vars/
   group1                 # here we assign variables to particular groups 这里我们给特定的组赋值
   group2                 # ""
host_vars/
   hostname1              # if systems need specific variables, put them here 如果系统需要特定的变量,把它们放置在这里.
   hostname2              # ""

library/                  # if any custom modules, put them here (optional) 如果有自定义的模块,放在这里(可选)
filter_plugins/           # if any custom filter plugins, put them here (optional) 如果有自定义的过滤插件,放在这里(可选)

site.yml                  # master playbook 主 playbook
webservers.yml            # playbook for webserver tier Web 服务器的 playbook
dbservers.yml             # playbook for dbserver tier 数据库服务器的 playbook

roles/
    common/               # this hierarchy represents a "role" 这里的结构代表了一个 "role"
        tasks/            #
            main.yml      #  <-- tasks file can include smaller files if warranted
        handlers/         #
            main.yml      #  <-- handlers file
        templates/        #  <-- files for use with the template resource
            ntp.conf.j2   #  <------- templates end in .j2
        files/            #
            bar.txt       #  <-- files for use with the copy resource
            foo.sh        #  <-- script files for use with the script resource
        vars/             #
            main.yml      #  <-- variables associated with this role
        defaults/         #
            main.yml      #  <-- default lower priority variables for this role
        meta/             #
            main.yml      #  <-- role dependencies

    webtier/              # same kind of structure as "common" was above, done for the webtier role
    monitoring/           # ""
    fooapp/               # ""

  

五、接着是一个haproxy+lnmp的案例Playbook,通过角色来配置,内容很糙,学习阶段使用挺好。

5.1)目录结构

[root@master ansible]# tree .
.
├── all
├── ansible.cfg
├── group_vars
│   ├── haproxy
│   ├── mysql
│   └── nginx
├── hosts
├── roles
│   ├── base
│   │   ├── files
│   │   │   └── CentOS-Base.repo
│   │   └── tasks
│   │       └── main.yml
│   ├── haproxy
│   │   ├── tasks
│   │   │   └── main.yml
│   │   └── templates
│   │       └── haproxy.cfg.j2
│   ├── mysql
│   │   └── tasks
│   │       └── main.yml
│   └── nginx
│       ├── tasks
│       │   └── main.yml
│       └── templates
│           └── index.htm.j2
└── site.yml

  

5.2)主机配置

[nginx]
192.168.222.147
[haproxy]
192.168.222.146

5.3)所有的变量配置跟入口文件site.yml在同一个层级

[root@master ansible]# for i in `ls group_vars`;do echo $i;cat group_vars/$i;done
haproxy
---
mode: http
balance: roundrobin
mysql
---
user: ansible
password: ansible
database: ansible
nginx
---
nginx: nginx-1.12.2.tar.gz
php: php-7.1.12.tar.gz

5.4)入口文件site.yml

[root@master ansible]# cat site.yml 
---
- name: replace yum
  hosts: all
  roles:
  - base
- name: install nginx
  hosts: nginx
  roles:
  - nginx
- name: install mysql
  hosts: nginx
  roles: 
  - mysql
- name: install haproxy
  hosts: haproxy
  roles:
  - haproxy

5.5)base角色,用来同步被控制机的yum源于控制机一致。

[root@master base]# tree .
.
├── files
│   └── CentOS-Base.repo
└── tasks
    └── main.yml

[root@master tasks]# cat main.yml 
---
- copy: src=CentOS-Base.repo dest=/etc/yum.repos.d/CentOS-Base.repo

5.6)nginx角色

[root@master nginx]# tree .
.
├── tasks
│   └── main.yml
└── templates
    └── index.htm.j2

[root@master tasks]# cat main.yml 
---
- yum: name=libtool-libs state=present
- shell: mkdir -p /usr/local/services
- shell: mkdir /data/soft -p
- copy: src=/data/{{nginx}}.rpm dest=/data/soft/{{nginx}}.rpm
- copy: src=/data/{{php}}.rpm dest=/data/soft/{{php}}.rpm
- shell: rpm -qa|grep {{nginx}} || rpm -ivh /data/soft/{{nginx}}
- shell: rpm -qa|grep {{php}} || rpm -ivh /data/soft/{{php}}
- shell: chdir=/usr/local/servers/ test -d nginx
- shell: chdir=/usr/local/servers/ test -d php
- shell: netstat -tnlp|grep nginx || /sbin/service nginx start
- template: src=index.htm.j2 dest=/data/htdocs/www/index.htm

[root@master templates]# cat index.htm.j2 
{{ ansible_default_ipv4.address}}

5.7)mysql角色

[root@master tasks]# cat main.yml 
---
- name: install mysql-server
  yum: name={{item}} state=installed
  with_items: 
  - mysql-server
  - mysql-python
- name: start msyql
  service: name=mysqld state=started enabled=yes
- name: create database
  mysql_db: name={{database}} state=present
- name: create user
  mysql_user: name={{user}} password={{password}} priv={{database}}.*:ALL host='%' state=present

  

5.8)haproxy角色

[root@master haproxy]# tree .
.
├── tasks
│   └── main.yml
└── templates
    └── haproxy.cfg.j2

[root@master tasks]# cat main.yml 
---
- name: install haproxy
  yum: name={{item}} state=present
  with_items:
  - haproxy
- name: copyhaproxy.conf
  template: src=haproxy.cfg.j2 dest=/etc/haproxy/haproxy.cfg owner=root group=root mode=644
- name: start haproxy
  service: name=haproxy state=started enabled=yes

[root@master templates]# cat haproxy.cfg.j2 
global
    log 127.0.0.1   local0 info
    log 127.0.0.1   local1 warning
    maxconn 4096
    chroot /usr/local/haproxy  #改变当前的工作目录
    pidfile /usr/local/haproxy/conf/haproxy.pid
    user	root
    group	root
    daemon
    stats socket /var/run/haproxy.sock mode 600 level admin
    stats timeout 2m
 
defaults
    log global
    mode    {{mode}}
    option  http-keep-alive
    option httplog
    option dontlognull
    retries    3
    maxconn 2000
    timeout connect 5000ms  #??server???5s
    timeout client 50000ms  #???????50s
    timeout server 50000ms  #server?????50s
 
 
frontend ansible
    bind {{ansible_default_ipv4.address}}:80
    mode {{mode}}
    #option httplog
    log    global
    default_backend nginx
 
backend nginx
    option forwardfor header X-REAL-IP
    option httpchk HEAD / HTTP/1.0
    balance {{balance}}
    #server web-node1 192.168.222.147:8080 check source 192.168.222.140:1025-65000 inter 2000 rise 30 fall 15
    {% for host in groups['nginx'] %}  #循环的NGINX组
    server {{hostvars[host].get('ansible_hostname')}} {{hostvars[host].get('inventory_hostname')}}:80 check inter 3000 rise 3 fall 2
    {% endfor %}

六、ansible优化执行速度,标准化,可以参考如下链接,我写的也很糙,时间不多。

https://blog.csdn.net/felix_yujing/article/details/76796522

1、开启ssh长连接
在openssh5.6以后的版本就可以支持multiplexing,,,不用管被管理端,只要改管理端
[root@master ansible]# ssh -v
vim ansible.cfg
ssh_args = -C -o ControlMaster=auto -o ControlPersist=5d

2、开启pipelining
将操作变成命令给远端去执行,而不是变成文件到远端去执行。,,但是这个需要在被管理端进行一些配置修改
# Enabling pipelining reduces the number of SSH operations required to
# execute a module on the remote server. This can result in a significant
# performance improvement when enabled, however when using "sudo:" you must
# first disable 'requiretty' in /etc/sudoers
#
# By default, this option is disabled to preserve compatibility with
# sudoers configurations that have requiretty (the default on many distros).
#
#pipelining = False

pipelining = True

3、开启accelerate模式,依赖ansible中的长连接,开启这个需要在管理端和被管理端安装python-keyczar
[accelerate]
accelerate_port = 5099
accelerate_timeout = 30
accelerate_connect_timeout = 5.0

4、设置facts缓存
gathering = smart
fact_caching_timeout = 86400
fact_caching_connection = /dev/shm/ansible_fact_cache
ansible还支持把数据放到redis里面,读取速度更快
gathering = smart
fact_caching_timeout = 86400
fact_caching = reids

  

原文地址:https://www.cnblogs.com/bill2014/p/8993581.html