• 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
    

      

  • 相关阅读:
    系统结构实践——第一次作业
    个人作业——软件工程实践总结作业
    个人作业——软件评测
    软件工程第五次作业--结队编程
    软件工程第四次作业--结队作业
    第一次个人编程作业
    第一次软工作业
    java第五周上机练习
    Java作业5
    java4
  • 原文地址:https://www.cnblogs.com/bill2014/p/8993581.html
Copyright © 2020-2023  润新知