最近因项目需要使用ansible编写自动化部署的脚本,下面做一些小结,目前知涉及到项目中用到的一些东西

  • 环境:redhat7.2
  • 执行命令
ansible-playbook -i host xxx_init.yml
  • ansible的hosts文件
[MANAGE:children]#管理节点,分主备
MANAGE_PRIMARY
MANAGE_BACKUP

[MANAGE_PRIMARY]
10.100.100.100

[MANAGE_BACKUP]
10.100.100.101

[FRONT:children]#前台节点,分主备,主要负责一些负载均衡,消息转发
FRONT_PRIMARY
FRONT_BACKUP

[FRONT_PRIMARY]
10.100.100.102

[FRONT_BACKUP]
10.100.100.103

[BACK]#后台节点,处理北向请求
10.100.100.104
10.100.100.105
  • 脚本目录
callback_plugins目录存放的是ansible插件内容
group_vars目录存放变量文件
roles存放脚本
xxxx_init.yml脚本入口文件
  • xxx_init.yml脚本介绍
---

 - hosts: all#all表示上面hosts文件中所有的节点都会执行
  serial: 10#ansible默认是连接5台服务器,为从优化性能考虑,这里设置为10(同时也可以修改ansible的配置文件进行设置)
  roles:
 - role: common#指定需要执行的role
  vars_files:
 - group_vars/main_vars.yml#指定变量文件

 - hosts: MANAGE
  gather_facts: no#
  roles:
 - role: manage
  vars_files:
 - group_vars/main_vars.yml

 - hosts: FRONT
  gather_facts: no#为从优化性能考虑,关闭gather_facts(因为在执行脚本时,发现在切换脚本执行时,会执行setup模块,浪费时间,当上面的all尽量不要关闭gather_facts,因为脚本中会有获取相关信息的操作)
  roles:
 - role: front
  vars_files:
 - group_vars/main_vars.yml

 - hosts: BACK
  gather_facts: no
  roles:
 - role: back
  vars_files:
 - group_vars/main_vars.yml

 #注意事项:在hosts: all中,如果没有需要所有机器都要执行的这部操作的话,可以省略,但如果需要在hosts文件中的一个group组中想去获取其他group组的setup模块中的信息,可以只写下面的内容
 - hosts: all
  • ansible脚本使用yml语法格式,内容看起来清晰明了,同时格式有一定的要求,比如空格,初期会因为格式不正确,多出或者少了空格而报错,也是很莫名奇妙的。
  • common/main.yml脚本脚本内容
---

 - name: mode /root/.ssh/id_rsa permission to 600#这里相当于一个log
  command: chmod 600 /root/.ssh/id_rsa removes=/root/.ssh/id_rsa#执行command模块,直接执行命令,removes的意思是当该文件存在时才会执行这个赋予权限的操作,如果知道该文件是存在的话,执行文件付权限操作可以使用file模块

 - include: create_yum_source.yml#执行create_yum_source.yml脚本
 - include: jdk/install_jdk.yml
  • 在云化环境下,根据自己的产品创建对应的镜像,如果使用官方镜像,会比较大,上传镜像文件或者创建虚拟机相对来讲比较耗时,这里可以使用官方最小镜像进行安装,但一些自定义的rpm如何创建yum源呢?
  • 如何使用ansible创建自定义yum源呢?可以参考下面的内容(create_yum_source.yml)
#安装createrepo,这里是将createrepo及相关的依赖包找出来,然后使使用rpm方式进行安装
---

- name: install createrepo   #安装createrepo   
  shell: rpm -ivh {{ rpm_packages_path }}{{ item }} #rpm_packages_path变量为rpm包的路径
  ignore_errors: True
  with_items:
        - deltarpm-3.6-3.el7.x86_64.rpm
        - python-deltarpm-3.6-3.el7.x86_64.rpm
        - createrepo-0.9.9-23.el7.noarch.rpm

#创建yum源
- name: createrepo create packages  link
  command: createrepo {{ rpm_packages_path }}

#复制repo文件
- name: copy packages.repo files
  template: src={{ item }} dest=/etc/yum.repos.d/
  with_items:
     - packages.repo

##############################################
packages.repo文件内容:
[packages]
name=packages
baseurl=file://{{ rpm_packages_path }}
enabled=1
gpgcheck=0
#{{ rpm_packages_path }}是ansible引用变量的方式,该变量定义在group_vars/main_vars.yml文件中

##############################################
这里涉及到template模块,说一下temolate模块作用和用法
template模块主要是复制文件作用,同时file,copy,fatch模块也有复制文件作用
template模块中可以引用变量,写if判断,for循环等
参考下面template文件可以定义的小案例,案例为将keepalived的配置文件keepalived.conf
! Configuration File for keepalived

global_defs {
   router_id LVS_DEVEL
}

vrrp_script chk_haproxy {
    script "killall -0 haproxy"
    interval 2
    weight 2
}

vrrp_instance VI_1 {
    state MASTER
    interface {{ front_vrrp_instance_interface }}#前面定义的变量
    virtual_router_id 40
    priority 101
    advert_int 2
    garp_master_delay 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
     track_interface {
{# 这里是想将该FRONT组中所有的网卡写入这里,除了lo网口,front_master_name为前面定义好的变量 #}
{% for host in groups['FRONT'] %}
{% if hostvars[host]['ansible_nodename'] == front_master_name %}
{% for interface in hostvars[host]['ansible_interfaces'] %}
{% if interface != 'lo' %}
         {{ interface }}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
    }

    virtual_ipaddress {
      {{ vnf_context_data.vnf_attributes.extensions.front_vip }}/32
    }

     track_script {
        chk_haproxy
    }     
}

template模块中,如何获取hosts中其他组信息,如其他group组的setup模块信息,参考下面的代码

{% for host in groups['FRONT'] %}
{% if hostvars[host]['ansible_nodename'] == front_master_name %}
{% for interface in hostvars[host]['ansible_interfaces'] %}
{% if interface != 'lo' %}
         {{ interface }}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
#########################
说明:
groups['FRONT']为hosts文件中[FRONT]组下面的机器(注意格式)
上面代码表示为遍历hosts文件中[FRONT]组中所有机器,当机器的hostname为front_master_name(定义的变量)时,则将该机器所有的网卡获取出来,除了lo网口
注意:在xxx_init.yml入口文件中要有
 - hosts: all
类似一个全局变量
  • ansible脚本如何像java一样使用 try catch finally?
tasks:
 - name: Attempt and gracefull roll back demo
     block:          #like java try
       - debug: msg='I execute normally'
       - command: /bin/false
       - debug: msg='I never execute, due to the above task failing'
     rescue:            #like java catch
       - debug: msg='I caught an error'
       - command: /bin/false
       - debug: msg='I also never execute :-('
     always:          #like java finally
       - debug: msg="this always executes"
  • ansible安装jdk,配置环境变量(ansible安装远程机器,配置环境变量,使用source /etc/profile 不生效?,参考下面的代码)
    除了在/etc/profile文件添加环境变量,并source;还要在/root/.bashrc 文件中添加环境变量,并source
- name: check jdk variable 
  shell: cat /etc/profile
  register: result

- name: jdk variable configuration /etc/profile file
  shell: /bin/echo {{ item }} >> /etc/profile; source /etc/profile
  when: result.stdout.find('JAVA_HOME') == -1
  with_items:
     - export JAVA_HOME=/usr/java/jdk{{ jdk_version }}
     - export JAVA_BIN=/usr/java/jdk{{ jdk_version }}/bin
     - export PATH=$PATH:/usr/java/jdk{{ jdk_version }}/bin
     - export JRE_HOME=/usr/java/jdk{{ jdk_version }}/jre
     - export CLASSPATH=.:/usr/java/jdk{{ jdk_version }}/lib:/usr/java/jdk{{ jdk_version }}/jre/lib
     - export JAVA_HOME JAVA_BIN PATH JRE_HOME CLASSPATH

- name: check jdk variable 
  shell: cat /root/.bashrc
  register: bashrc_result

- name: jdk variable configuration /root/.bashrc file
  shell: /bin/echo {{ item }} >> /root/.bashrc; source /root/.bashrc
  when: bashrc_result.stdout.find('JAVA_HOME') == -1
  with_items:
     - export JAVA_HOME=/usr/java/jdk{{ jdk_version }}

如果修改了上面2个文件后,执行source指令还没有生效?
原因:请把被控制机的远程登录界面关掉的情况下执行ansible脚本即可生效

  • ansible如何判定hosts文件中某个组下面机器的个数?
    场景:当hosts文件中某个组下面没有机器时,执行缩容操作,如果有机器,执行扩容操作
如 hosts,文件中new组下面的机器个数为0个,执行缩容
[new]
如果new组下面机器多个,执行扩容操作
[new]
172.10.10.1
###########################
判定语句:
when: (groups['new']|length > 0)
  • ansible 如何判定一个文件夹是否存在,如果存在则执行相应的操作?
- name: judge templates directory if exit
  shell: ls /home/templates/
  connection: local
  register: result
  ignore_errors: True

#- debug: var=result verbosity=0
- include: syn_templates.yml
  when: result.rc == 0
  • ansible如何将多个文件传到被控制上?(仅跟上一步)
    先进行压缩,然后使用unarchive模块传到被控制机上,多个文件速度比copy要快
syn_templates.yml 如下:

---

- name: gzip templates
  command: tar -zcvf /tmp/templates.tar.gz /home/templates
  connection: local

- name: syn templates to dest server
  unarchive: src=/tmp/templates.tar.gz dest=/ group=sfy owner=sfy-adm