Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2262160
  • 博文数量: 168
  • 博客积分: 6641
  • 博客等级: 准将
  • 技术积分: 1996
  • 用 户 组: 普通用户
  • 注册时间: 2007-06-02 11:49
文章存档

2020年(4)

2019年(6)

2017年(1)

2016年(3)

2015年(3)

2014年(8)

2013年(2)

2012年(12)

2011年(19)

2010年(10)

2009年(3)

2008年(17)

2007年(80)

分类: LINUX

2019-12-08 17:51:41


ansible配置管理基础应用

2019.10.31 TsengYia 
---- http://tsengyia.blog.chinaunix.net/ 

系统环境: 
    RHEL 8.0 (Ootpa) [4.18.0-80.el8.x86_64] 
软件环境:
    ansible 2.8.0
###########################################

一、安装ansible
# yum  -y  install  ansible


配置调整及提权:
# vim  /etc/ansible/ansible.cfg
[defaults]
inventory = /etc/ansible/hosts    //主机清单的文件路径
remote_user = matthew  //用户playbook的用户身份(缺省为当前使用人)
roles_path = /etc/ansible/roles //角色文件的默认存放目录

[privilege_escalation]    //提权配置段(配合托管主机的visudo授权)
become=True 
become_method=sudo
become_user=root
become_ask_pass=False




二、设置托管主机清单(推荐通过SSH密钥管理所有主机)


# vim  /etc/ansible/hosts
192.168.0.1  //可以指定单个IP
192.168.0.2
192.168.0.[11:20]  //可以指定范围内的地址
[webservers]  //可以设分组
web1.example.com
web2.example.com  //可以指定单个域名
web3  ansible_ssh_host=192.168.1.3   ansible_ssh_port=2222    //可以设主机别名web3
web4  ansible_ssh_host=192.168.1.4   ansible_ssh_user="zhsan"  ansible_ssh_pass="1234567"
.. ..
[idc007]
172.25.0.11
172.25.0.12
[idc007:children]
webservers  //组内还可以嵌套其他组



三、远程执行少量命令(ad-hoc)
基本用法:
# ansible  <主机模式>  -m 模块名  -a  '参数 .. ..'  
# ansible  <主机模式>  -m 模块名  -a  '参数 .. ..'   -f  10  //并行处理10个主机(默认5)

!!!! 主机模式可以是 /etc/ansible/hosts 文件中指定的 IP地址、主机名、组名,用来限定去操作哪些主机
!!!! 可以使用通配符 * ,允许 : 或 , 分隔多个托管主机或组
!!!! 使用 'group1:group2' 表示在组1中或者在组2中
!!!! 使用 'group1:!group2' 表示在组1中但不在组2中的托管主机
!!!! 使用'group1:&group2' 表示既在组1中也在组2中的托管主机
!!!! 使用'group1[0]' 表示组1中的第1个主机(类似于属组下标的表示方式)
!!!! 使用'group1[0:4]' 表示组1中的第1~5个主机(类似于属组下标的表示方式)


1. 检查所有托管主机是否可以正常响应python指令
# ansible  all  -m  ping

2. 在 192.168开头的托管主机上执行命令
!!!! 缺省使用command模块执行远程命令,若要支持重定向、管道等功能,可以改用shell模块
# ansible  192.168*  -a  'useradd  zhsan'    //在远程主机上添加用户zhsan
# ansible  192.168* -m shell -a 'echo 1234567 | passwd --stdin zhsan'  //为该用户设置密码

3. 在远程主机 192.168.0.2 创建目录、文件、设置权限、删除、……
# ansible 192.168.0.2 -m file -a 'name=/repo/rh8dvd/ mode=755 state=directory'    //建目录
# ansible 192.168.0.2 -m file -a 'name=/repo/rh8dvd/a.txt state=touch'  //建普通文件
# ansible 192.168.0.2 -m file -a 'src=/etc/resolv.conf name=/etc/rs.conf state=link'    //建软链接文件
# ansible 192.168.0.2 -m file -a 'name=/repo/rh8dvd/a.txt owner=root mode=775 state=file'  //设置权限
# ansible 192.168.0.2 -m file -a 'name=/repo/rh8dvd/  state=absent'  //删除文档

4. 在所有托管主机上建立新文件,
# ansible  all  -m  copy  -a  'src=/etc/fstab  dest=/tmp/fstab.txt mode=644'  //上传指定的文件
# ansible  all  -m  copy -a 'content="AAAA\nBBBB\nCCCC\n" dest=/tmp/content.txt'    //建立指定内容的新文件

5. 用户账号管理
# ansible all -m user -a 'name=zhsan uid=1234'  //添加新用户
# ansible all -m user -a "name=xiaoqi groups=users  password={{' 1234567'|password_hash('sha512') }} state=present"
   //添加新用户并设置密码、附属组
# ansible all -m user -a 'name=zhsan state=absent remove=yes'  //删除用户

6. 通过yum模块管理软件包
# ansible all -m yum -a 'pkg=httpd state=present'  //安装httpd软件包
# ansible all -m yum -a 'pkg=vsftpd state=absent'  //卸载vsftpd软件包

7. 通过service模块管理系统服务
# ansible webservers -m service -a "name=httpd state=restarted"  //确保重启httpd服务
# ansible webservers -m service -a "name=httpd enabled=yes"  //确保httpd服务开机后自动运行

8. 通过parted、lvg、lvol、filesystem模块管理磁盘及文件系统
# ansible pc180 -m parted -a "device=/dev/sdc  label=gpt  number=1 part_type=primary  part_start=0%  part_end=10GiB"
   //创建分区/dev/sdc1
# ansible pc180 -m lvg -a "vg=rhel pesize=16M pvs=/dev/sdc1"    //创建卷组rhel
# ansible pc180 -m lvol -a "lv=data size=1500M vg=rhel"  //创建逻辑卷data
# ansible pc180 -m filesystem -a "dev=/dev/rhel/data fstype=ext4"  //将逻辑卷格式化为ext4文件系统

9. 通过mysql_user模块添加数据库用户
!!!! 前提条件:托管机已安装并运行MySQL或MariaDB服务,且安装了python3-PyMySQL模块包
# ansible host1 -m mysql_user -a 'priv="*.*:ALL" name=jerry host=localhost password="123456" state=present'

10. 模块相关操作
# ansible-doc  -l  //列出支持的模块
# ansible-doc  copy  //查看copy模块的使用帮助


四、远程执行复杂任务(playbook)

1. 编写剧本 /root/zhsan.yml ,用来为远程主机添加用户 zhsan 并设置密码 1234567
# vim  /root/zhsan.yml
---  //建议的起始标记
- name:  Users Administration  //场景1开始
  hosts: 192.168.0.1 //演员表(作用于哪些主机)
  tasks:  //任务
  - name: add user zhsan  //任务1的描述文本
    user:  //使用user模块
      name: zhsan  //用户名zhsan
      state: present  //要求的状态为存在
      password: "{{' 1234567'|password_hash('sha512') }}"  //设置加密的密码字串
 ...  //建议的结束标记

# ansible-playbook  -C  /root/zhsan.yml  //检查剧本语法
# ansible-playbook  /root/zhsan.yml  //执行剧本

2. 编写剧本 /root/svr80.yml ,用来管理远程主机svr80的软件包
# vim  /root/svr80.yml
---
- name: Deploy LAMP platform
  hosts: pc180
  tasks:
    - name: Install package group
      yum: name="@RPM Development tools" state=installed  //安装一组软件
    - name: Update all packages 
      yum: name="*" state=latest  //升级所有软件包
...

3. 编写剧本 /root/nginx.yml ,用来为远程主机pc180安装并部署Nginx网站服务
# vim  /root/nginx.yml
---
- name: Deploy Nginx Web Server
  hosts: pc180
  tasks:
    - name: 1. Remove httpd package  //操作1,确保httpd被移除
      yum: pkg=httpd state=removed
    - name: 2. Install nginx package  //操作2,确保nginx被安装
      yum: pkg=nginx state=installed
    - name: 3. Enable and start nginx service  //操作3,确保nginx服务被启用
      service: name=nginx state=started enabled=yes
...

4. 编写剧本 /root/selinux.yml ,用来修改远程主机pc180上的SELinux配置
# vim  /root/selinux.yml
---
- name: Modify SELinux configuration
  hosts: pc180
  tasks:
  - lineinfile: path=/etc/selinux/config regexp='^SELINUX=' line='SELINUX=permissive'
...

5. 编写剧本 /root/webdev.yml, 用来向web服务器部署网页目录,并调整文档的SELinux安全属性
# vim  /root/webdev.yml
---
- name: Prepare Web Directory
  hosts: pc180
  tasks:
  - file:
      name: /webdev    //新文档的名称
      group: apache    //所属组
      mode: 02775  //权限(SetGID)
      setype: httpd_sys_content_t  //指定SELinux上下文的type类型
      state: directory  //文档类别为目录
  - file:
      name: /var/www/html/webdev  //链接文件的路径
      src: /webdev    //链接源
      state: link  //类型为符号链接
      force: yes  //强制创建(即使链接源还不存在)
  - copy:
      content: It's works!    //定义首页文件内容
      dest: /webdev/index.html  //上传为指定文件
      mode: 0644  //设置权限
      setype: httpd_sys_content_t  //指定SELinux上下文的type类型
  - service:
      name: httpd
      state: restarted  //重启httpd服务
      enabled: yes
...


五、使用变量优化配置

1. 在定义清单时,为主机 192.168.0.1 提供变量
# vim  /etc/ansible/hosts
192.168.0.1  datadir="/var/lib/mysql"  //定义名为datadir的变量

# ansible  192.168.0.1  -a  'echo {{datadir}}'    //测试变量调用
192.168.0.1 | CHANGED | rc=0 >>
/var/lib/mysql  //确认结果

2. 在定义清单时,为webservers组提供变量
# vim  /etc/ansible/hosts
[webservers]
web1.example.com
web2.example.com  
[webservers:vars]
webroot="/var/www/html"  //定义名为webroot的变量
index_file="index.html" //定义名为index_file的变量

# ansible websvrs  -m  file  -a  'dest={{webroot}}/{{index_file}}  state=touch'  //测试变量调用


3. 通过独立的文件为主机 192.168.0.2 、组 dbservers 提供变量
1)准备目录结构
# mkdir  -p  /etc/ansible/host_vars  //默认的主机变量目录位置
# mkdir  -p  /etc/ansible/group_vars  //默认的组变量目录位置

2)为主机 192.168.0.2 提供变量文件
# vim  /etc/ansible/host_vars/192.168.0.2  //文件名与清单中的主机地址要相对应
datadir: /var/lib/mysql  //注意冒号:后的空格不要省略
# ansible 192.168.0.2 -a 'echo {{ha}}'  //测试变量调用
192.168.0.2 | CHANGED | rc=0 >>
/var/lib/mysql  //确认结果

3)为组 webservers 提供变量文件
# vim  /etc/ansible/group_vars/webservers  //文件名与清单中的组名要相对应
http_user: apache    //注意冒号:后的空格不要省略
# ansible webservers -a 'echo {{http_user}}'    //测试变量调用
192.168.1.3 | CHANGED | rc=0 >>
apache    //确认结果

4. 编写剧本 /root/httpd81.yml ,用来修改远程主机pc180上的SELinux配置
# vim /etc/ansible/host_vars/pc180    //为主机定义变量
httpd_config: /etc/httpd/conf/httpd.conf  //定义变量httpd_config,存放配置文件路径
listen_port: 81  //定义变量listen_port,存放监听端口

# vim  /root/selinux.yml
---
- name: Configuraton Web Service
  hosts: pc180
  tasks:
  - name: Add Listen Port 81  //监听81端口(insertafter默认在最后一个匹配行后插入新行)
    lineinfile: path={{httpd_config}}  insertafter='^Listen '  line='Listen {{listen_port}}'
  - name: Remove Listen Port 8000    //删除指定内容的行
    lineinfile: path={{httpd_config}} regexp='^Listen *8000' state=absent
...



六、 搜集托管主机信息/系统变量
!!!! 托管主机的各种环境指标信息,可以通过 setup 模块获得
# ansible host1 -m setup    //列出所有信息
# ansible host1 -m setup -a 'filter=*_os_*'  //过滤出包含 _os_ 的指标
# ansible host1 -m setup -a 'filter=ansible_memtotal_mb'    //过滤出总内存大小的指标
$ ansible pc180 -m setup -a 'filter=ansible_bios_version'    //过滤出BIOS版本
# ansible host1 -m debug -a 'var=hostvars["pc180"]'  //通过魔法变量hostvars列出托管主机pc180上的变量
# ansible pc180 -m debug -a 'var=group_names'    //通过魔法变量group_names列出托管主机所在组名

1. 在剧本中阻止搜集信息
---
- name: xxxx
- hosts: pc180
  gather_facts: no    //如果用不到,可以不搜集信息(缺省会自动搜集)
  tasks: 
  .. ..
...

2. 编写剧本获取远程主机的主机名、IP地址、网络接口列表、分区大小等信息
# vim  /root/getinfo.yml
---
- hosts: pc180
  tasks:
  - name: Show IP infomation
    debug:
      msg: >
        Hostname is {{ansible_facts.hostname}}
        IP address of ens3 is {{ansible_ens3.ipv4.address}}
        Size of partition sdb2 is {{ansible_facts.devices.sdb.partitions.sdb2.size}}
        Network interfaces is {{ansible_facts.interfaces}}
...

3. 编写剧本向远程主机部署指定文件 /tmp/newfile.txt,包含的内容来自于content提供
# vim  /root/putfile.yml
---
- hosts: pc180
  tasks:
  - copy:
      content: |
            Hello everyone,
           Ansible is such a good tool,
           You can try it.
      dest: /tmp/newfile.txt
...

4. 编写剧本向远程主机部署指定文件 /etc/myhosts,包含的内容来自于控制机上的模板文件hosts.j2

# vim  /etc/ansible/hosts.j2
{% for id in groups.all %}
{{hostvars[id].ansible_facts.ens3.ipv4.address}}  {{hostvars[id].ansible_facts.fqdn}}  {{hostvars[id].ansible_facts.hostname}}
{% endfor %}

# vim  /root/myhosts.yml
---
- name: gather facts
  hosts: all

- hosts: pc180
  tasks:
  - template: 
      src: hosts.j2
      dest: /etc/myhosts
...


5. 编写剧本为托管主机生成硬件报告文件 /root/hwinfo.txt
# vim  /root/hw.temp    //硬件信息报告模板文件
InverntoryHostname=AAAA
MemTotal=BBBB
BiosVersion=CCCC
Sizeof_sda=DDDD
Sizeof_sdb=EEEE

# vim  /root/hwinfo.yml  //生成硬件报告剧本
- name: hardware report
  hosts: all
  ignore_errors: yes //忽略个别错误
  vars: //提取硬件检测结果
    - sfile: /root/hwinfo.txt //硬件报告文件路径
    - host: "{{inventory_hostname}}" //提取清单主机名
    - mem: "{{ansible_facts.memtotal_mb}}" //提取总内存大小(MB)
    - bios: "{{ansible_facts.bios_version}}" //提取BIOS版本
    - vdasize: "{{ansible_facts.devices.sda.size}}" //提取磁盘vda大小
    - vdbsize: "{{ansible_facts.devices.sdb.size if ansible_facts.devices.sdb.size is defined else 'NONE' }}"  //提取磁盘vdb大小,或NONE
  tasks: //修改报告(根据模板内容查找替换)
    - get_url: url= dest={{sfile}} force=yes
    - replace: name={{sfile}} regexp=AAAA replace={{host}}  
    - replace: name={{sfile}} regexp=BBBB replace={{mem}}
    - replace: name={{sfile}} regexp=CCCC replace={{bios}}
    - replace: name={{sfile}} regexp=DDDD replace={{vdasize}}
    - replace: name={{sfile}} regexp=EEEE replace={{vdbsize}}
...

6. 编写剧本为受管主机创建逻辑卷
!!!! 当卷组rhel不存在时,提示信息“VG not found”
!!!! 当创建逻辑卷空间不足时,“insufficient free space”

# vim  /root/lv.yml
- name: manager volume
  hosts: all
  tasks:
    - name: 1. failed when VG not found
      debug: msg="VG not found"
      when: "'vgxxx' not in ansible_facts.lvm.vgs"  //目标VG不存在时报错
      failed_when: "'vgxxx' not in ansible_facts.lvm.vgs"  //停止后续任务
    - name: 2. lvcreate
      block:    //配置指令块
        - lvol: lv=data size=1500M vg=vgxxx
          notify: mkfs    //lv建成功后通知mkfs
      rescue:  //若块操作失败,则执行补救
        - debug: msg="insufficient free space"
        - lvol: lv=data size=800M vg=vgxxx
          notify: mkfs    //lv建成功后通知mkfs
  handlers:  //收到通知后执行
    - name: mkfs  //定义通知接口名mkfs
      filesystem: dev=/dev/vgxxx/data fstype=ext4 force=yes
...



七、在playbook中使用循环、条件

1. 编写剧本 lamp.yml,用来确保在托管主机上安装并启用LAMP平台
# vim  lamp.yml
---
- name: Deploy LAMP Platform
  hosts: host1
  # import_tasks: /etc/ansible/startup.yml
  tasks:
  - name: install LAMP packages
    yum: name:={{item}}  state=present  //调用循环变量(固定名称item)
    loop:  //配置列表循环项
        - httpd
        - mariadb
        - mariadb-server
        - php
        - php-mysqlnd
  - name: enable LAMP services
    service: name={{item}}  state=started  enabled=yes
    loop:
        - httpd
        - mariadb
...

2. 编写剧本 when.yml,当托管主机的硬件平台为x86_64时,创建标记文件 /tmp/x86_64.mark

# vim  /root/when.yml
---
- name: test match
  hosts: 192.168.0.1
  gather_facts: yes  //搜集客户端环境信息(缺省)
  tasks:
  - name: if x86_64 then create a file
    file:
            name: /tmp/x86_64.mark
            state: touch
    when: ansible_machine == "x86_64"  //通过 when 设置执行条件
...

3. 编写剧本 users.yml ,根据托管主机所属的清单组不同分别添加不同的用户
!!!! 如果属于dev或test组,添加用户harry,隶属于附加组 adm,密码为1234
!!!! 如果属于prod组,则添加用户natasha,密码来自于文件 locker.yml 中的变量 pw_of_product

# vim  /root/users.yml
---
- name: Add different users according to different conditions
  hosts: pc180
  vars_files: locker.yml    //为用户提供密码的变量列表文件,比如pw_of_product变量
  vars:
    - grp1: dev
    - grp2: test
    - grp3: prod
  tasks:
    - user: name=harry  groups=adm  state=present password='{{'1234'|password_hash('sha512')}}'
      when: (grp1 in group_names) or (grp2 in group_names)
    - user: name=natasha state=present password='{{  {{pw_of_product}} |password_hash('sha512')}}'
      when: grp3 in group_names
...

!!!! 注意:若密码文件 locker.yml 已经加密,则通过ansible-playbook执行剧本时需指定密码
# vim  secret.txt
your_password

# ansible-playbook  --vault-password-file=secret.txt  users.yml

4. 编写剧本 issue.yml ,为受管主机设置 /etc/myissue 文件内容
!!!! 如果属于dev组,则内容为Development
!!!! 如果属于test组,则内容为Test
!!!! 如果属于prod组,则内容为Production

[matthew@svr8 ansible]$ cat issue.yml 
---
- name: modify issue file
  hosts: all
  tasks:
  - name: aaa
    copy:
      content: | 
        {% if "dev" in group_names %}
        Development
        {% elif "test" in group_names %}
        Test
        {% elif "prod" in group_names %}
        Production
        {% endif %}
      dest: /etc/myissue
...

5. Jinja2模板文件语法
1)if选择,生成端口配置
{% if PORT %}
bind-address=0.0.0.0:{{port}}
{% else %}
bind-address=0.0.0.0:3306
{% endif %}

2)for循环,生成主机映射列表
{% for id in range(6,10) %}
172.24.0.{{id}}  node{{id}}.example.com  node{{id}}
{% endfor %}

3)for循环生成虚拟web主机配置文件
# vim  /etc/ansible/vhosts.conf.j2 
{% for id in vhosts %}

    ServerName  {{ id.servername }}
    DocumentRoot  {{ id.documentroot   }}

{% endfor %}

# vim  /root/httpd_vhosts.yml 
---
- name: Configure web vhosts
  hosts: pc180
  vars:
    vhosts:
      - { servername: 'node1.example.com', documentroot: '/var/www/node1' }
      - { servername: 'node2.example.com', documentroot: '/var/www/node2' }
      - { servername: 'node3.example.com', documentroot: '/var/www/node3' }
  tasks: 
  - template: src=/etc/ansible/vhosts.conf.j2 dest=/etc/httpd/conf.d/vhosts.conf 
...



八、ansible-vault加密管理

!!!! 针对包含敏感数据的清单、剧本、变量等文件,都可以进行加密,以提高安全性

1. 加密文件的基本管理操作
# ansible-vault  create  secret.yml    //新建加密文件,根据提示设置口令
# ansible-vault  encrypt  secret.yml  //加密已有文件,根据提示设置口令
# ansible-vault  view  secret.yml    //查看加密文件,根据提示验证口令
# ansible-vault rekey secret2.yml    //修改加密口令,需验证旧口令
# ansible-vault  decrypt  secret.yml    //解除加密保护,需验证旧口令

2. 加密文件的应用
1)使用ansible、ansible-playbook时,添加 --ask-vault-pass 以提示从键盘输入口令(缺省不提示)
# ansible-playbook  secret.yml  --vault-password-file=/root/ansible.pass

2)使用ansible、ansible-playbook时,通过 --vault-password-file 免除交互
# echo redhat > /root/ansible.pass    //创建口令文件
# chmod 600 /root/ansible.pass  //控制访问权限
# ansible-playbook  secret.yml  --vault-password-file=/root/ansible.pass  //调用口令文件自动验证

3)加密、解密、查看加密的文件时,通过 --vault-password-file 免除交互
# ansible-vault  view secret.yml  --vault-password-file=/root/ansible.pass

4)修改加密口令时,新口令可以通过 --new-vault-password-file 免除交互
# echo 1234567 > /root/ansible.newpass  //创建新口令文件
# chmod  600  /root/ansible.newpass  //控制访问权限
# ansible-vault rekey secret.yml --vault-password-file=/root/ansible.pass  --new-vault-password-file=/root/ansible.newpass 


九、创建及使用角色
# cd  /etc/ansible/roles/
# ansible-galaxy  init  httpd    //初始化指定名称为httpd的角色目录
#  vim  http/tasks/main.yml    //编写此角色的主任务剧本
---
# tasks file for http
- name: 1. install httpd
  yum: pkg=httpd state=installed
- name: 2. restart httpd and firewalld
  service: name={{item}} state=restarted enabled=yes
  loop:
    - httpd
    - firewalld
- name: 3. deploy index.html    //参照模板为受管web主机建立首页文件
  template: src=index.html.j2 dest=/var/www/html/index.html
- name: 4. configure firewall rule
  firewalld: service=http permanent=yes state=enabled
...

# vim roles/http/templates/index.html.j2  //编写模板文件(需要的话)
Welcome to {{ ansible_facts.fqdn }} on {{ ansible_facts.ens3.ipv4.address }}

# vim  /root/httprole.yml    //编写调用http角色的应用剧本
---
- name: use role http
  hosts: pc180
  roles: 
    - http
...

# ansible-playbook  /root/httprole.yml    //使用剧本

#############################################################################

阅读(8854) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~