Ansible相关笔记2

Playbook
playbook 剧本是由一个或多个 "play" 组成的列表
play 的主要功能在于将预定义的一组主机,装扮成事先通过 ansible 中的 task 定义好的角色。 Task
际是调用 ansible 的一个 module ,将多个 play 组织在一个 playbook 中,即可以让它们联合起来,按
事先编排的机制执行预定义的动作
Playbook 文件是采用 YAML 语言编写的

一个 playbook 中由多个组件组成 , 其中所用到的常见组件类型如下 :
Hosts 执行的远程主机列表
Tasks 任务集 , 由多个 task 的元素组成的列表实现 , 每个 task 是一个字典 , 一个完整的代码块功能需最
少元素需包括 name task, 一个 name 只能包括一个 task
Variables 内置变量或自定义变量在 playbook 中调用
Templates 模板,可替换模板文件中的变量并实现一些简单逻辑的文件
Handlers notify 结合使用,由特定条件触发的操作,满足条件方才执行,否则不执行
tags 标签 指定某条任务执行,用于选择运行 playbook 中的部分代码。 ansible 具有幂等性,因此
会自动跳过没有变化的部分,即便如此,有些代码为测试其确实没有发生变化的时间依然会非常地
长。此时,如果确信其没有变化,就可以通过 tags 跳过此些代码片断
Hosts playbook 中的每一个 play 的目的都是为了让特定主机以某个指定的用户身份执行任务。 hosts
于指定要执行指定任务的主机,须事先定义在主机清单中
one.example.com
one.example.com:two.example.com
192.168.1.50
192.168.1.*
Websrvs:dbsrvs     #或者,两个组的并集
Websrvs:&dbsrvs   #与,两个组的交集
webservers:!dbsrvs  #在websrvs组,但不在dbsrvs组
remote_user 组件
remote_user: 可用于 Host task 中。也可以通过指定其通过 sudo 的方式在远程主机上执行任务,可 用于 play 全局或某任务;此外,甚至可以在 sudo 时使用 sudo_user 指定 sudo 时切换的用户
- hosts: websrvs
 remote_user: root
  
 tasks:
   - name: test connection
     ping:
     remote_user: test
     sudo: yes #默认sudo为root
     sudo_user:test2    #sudo为test2
task 列表和 action 组件
play 的主体部分是 task list task list 中有一个或多个 task, 各个 task 按次序逐个在 hosts 中指定的所有主
机上执行,即在所有主机上完成第一个 task 后,再开始第二个 task
task 的目的是使用指定的参数执行模块,而在模块参数中可以使用变量。模块执行是幂等的,这意味着多次执行是安全的,因为其结果均一致
每个 task 都应该有其 name ,用于 playbook 的执行结果输出,建议其内容能清晰地描述任务执行步骤。
如果未提供 name ,则 action 的结果将用于输出
task 两种格式:
action: module arguments  #示例: action: shell wall hello 
module: arguments   #建议使用 #示例: shell: wall hello
注意: shell command 模块后面跟命令,而非 key=value
[root@ansible ansible]#cat hello.yaml
---
# first yaml file 
- hosts: websrvs
 remote_user: root
 gather_facts: no   #不收集系统信息,提高执行效率,如果需要收集系统信息,可以不添加。
 tasks:
    - name: test network connection
      ping:
    - name: excute command
     command: wall "hello world!"
范例
---
- hosts: websrvs
 remote_user: root
 gather_facts: no
  
 tasks:
   - name: install httpd
     yum: name=httpd 
   - name: start httpd
     service: name=httpd state=started enabled=yes
其它组件说明
某任务的状态在运行后为 changed 时,可通过 "notify" 通知给相应的 handlers 任务
还可以通过 "tags" task 打标签,可在 ansible-playbook 命令上使用 -t 指定进行调用
ShellScripts VS Playbook 案例
#SHELL脚本实现
#!/bin/bash
# 安装Apache
yum install --quiet -y httpd 
# 复制配置文件
cp /tmp/httpd.conf /etc/httpd/conf/httpd.conf
cp/tmp/vhosts.conf /etc/httpd/conf.d/
# 启动Apache,并设置开机启动
systemctl enable --now httpd 
#Playbook实现
---
- hosts: websrvs
 remote_user: root
 gather_facts: no
  
 tasks:
   - name: "安装Apache"
     yum: name=httpd
   - name: "复制配置文件"
     copy: src=/tmp/httpd.conf dest=/etc/httpd/conf/
   - name: "复制配置文件"
     copy: src=/tmp/vhosts.conf dest=/etc/httpd/conf.d/
   - name: "启动Apache,并设置开机启动"
     service: name=httpd state=started enabled=yes
playbook 命令
ansible-playbook <filename.yml> ... [options] 范例 :
--syntax-check      #语法检查,可缩写成--syntax, 相当于bash -n 
-C --check #模拟执行,只检测可能会发生的改变,但不真正执行操作,dry run 
--list-hosts    #列出运行任务的主机
--list-tags #列出tag
--list-tasks #列出task
--limit 主机列表 #只针对主机列表中的特定主机执行
-i INVENTORY        #指定主机清单文件,通常一个项对应一个主机清单文件
--start-at-task START_AT_TASK #从指定task开始执行,而非从头开始,START_AT_TASK为任务的
name
-v -vv  -vvv #显示过程

范例:
[root@ansible ansible]#cat hello.yml
---
- hosts: websrvs
 tasks:
    - name: hello
     command: echo "hello ansible"
[root@ansible ansible]#ansible-playbook hello.yml
[root@ansible ansible]#ansible-playbook -v hello.yml
ansible-playbook file.yml  --check #只检测
ansible-playbook file.yml  
ansible-playbook file.yml  --limit websrvs
利用 playbook 创建 mysql 用户
---
- hosts: dbsrvs
 remote_user: root
 gather_facts: no
 tasks:
   - {name: create group, group: name=mysql system=yes gid=306}
   - name: create user
     user: name=mysql shell=/sbin/nologin system=yes group=mysql uid=306 
home=/data/mysql create_home=no

 利用 playbook 安装 nginx

---
# install nginx 
- hosts: websrvs
 remote_user: root 
 gather_facts: no
 tasks:
    - name: add group nginx
     group: name=nginx state=present
    - name: add user nginx
     user: name=nginx state=present group=nginx
    - name: Install Nginx
     yum: name=nginx state=present
    - name: web page
     copy: src=files/index.html dest=/usr/share/nginx/html/index.html
    - name: Start Nginx
      service: name=nginx state=started enabled=yes

利用 playbook 安装和卸载 httpd

---
#install httpd
- hosts: websrvs
 remote_user: root
 gather_facts: no
 tasks:
    - name: Instal1 httpd
     yum: name=httpd
    - name: Modify config list port
     lineinfile: 
       path: /etc/httpd/conf/httpd.conf 
       regexp: '^Listen'
       line: 'Listen 8080'
    - name: Modify config data1
     lineinfile: 
       path: /etc/httpd/conf/httpd.conf 
       regexp: '^DocumentRoot "/var/www/html"'
       line: 'DocumentRoot "/data/html"'
    - name: Modify config data2
     lineinfile: 
       path: /etc/httpd/conf/httpd.conf 
       regexp: '^<Directory "/var/www/html">'
       line: '<Directory "/data/html">'
    - name: Mkdir website dir
     file: path=/data/html state=directory
    - name: Web html
     copy: src=files/index.html dest=/data/html/
    - name: Start service
      service: name=httpd state=started enabled=yes
# ansible-playbook   install_httpd.yml --limit 10.0.0.8

#remove_httpd.yml
---
- hosts: websrvs
 remote_user: root
 gather_facts: no 
 tasks:
   - name: remove httpd package
     yum: name=httpd state=absent
   - name: remove apache user 
     user: name=apache state=absent
   - name: remove config file
     file: name=/etc/httpd state=absent
   - name: remove web html
     file: name=/data/html/ state=absent

利用 playbook 安装 MySQL 5.6

[root@ansible ~]#ls -l /data/ansible/files/mysql-5.6.46-linux-glibc2.12-
x86_64.tar.gz 
-rw-r--r-- 1 root root 403177622 Dec  4 13:05 /data/ansible/files/mysql-5.6.46-
linux-glibc2.12-x86_64.tar.gz
[root@ansible ~]#cat /data/ansible/files/my.cnf 
[mysqld]
socket=/tmp/mysql.sock
user=mysql
symbolic-links=0
datadir=/data/mysql
innodb_file_per_table=1
log-bin
pid-file=/data/mysql/mysqld.pid
[client]
port=3306
socket=/tmp/mysql.sock
[mysqld_safe]
log-error=/var/log/mysqld.log
[root@ansible ~]#cat /data/ansible/files/secure_mysql.sh 
#!/bin/bash
/usr/local/mysql/bin/mysql_secure_installation <<EOF
y
test
test
yyyy
EOF
[root@ansible ~]#tree /data/ansible/files/
/data/ansible/files/
├── my.cnf
├── mysql-5.6.46-linux-glibc2.12-x86_64.tar.gz
└── secure_mysql.sh
0 directories, 3 files
[root@ansible ~]#cat /data/ansible/install_mysql.yml
---
# install mysql-5.6.46-linux-glibc2.12-x86_64.tar.gz
- hosts: dbsrvs
 remote_user: root
 gather_facts: no
 tasks:
    - name: install packages
     yum: name=libaio,perl-Data-Dumper,perl-Getopt-Long
    - name: create mysql group
     group: name=mysql gid=306
    - name: create mysql user
     user: name=mysql uid=306 group=mysql shell=/sbin/nologin system=yes
create_home=no home=/data/mysql
    - name: copy tar to remote host and file mode 
     unarchive: src=/data/ansible/files/mysql-5.6.46-linux-glibc2.12-
x86_64.tar.gz dest=/usr/local/ owner=root group=root 
    - name: create linkfile /usr/local/mysql 
     file: src=/usr/local/mysql-5.6.46-linux-glibc2.12-x86_64 
dest=/usr/local/mysql state=link
    - name: data dir
     shell: chdir=/usr/local/mysql/ ./scripts/mysql_install_db --
datadir=/data/mysql --user=mysql
     tags: data
    - name: config my.cnf
     copy: src=/data/ansible/files/my.cnf  dest=/etc/my.cnf 
    - name: service script
     shell: /bin/cp /usr/local/mysql/support-files/mysql.server 
/etc/init.d/mysqld
    - name: enable service
     shell: /etc/init.d/mysqld start;chkconfig --add mysqld;chkconfig mysqld on 
     tags: service
    - name: PATH variable
     copy: content='PATH=/usr/local/mysql/bin:$PATH'
dest=/etc/profile.d/mysql.sh
    - name: secure script
     script: /data/ansible/files/secure_mysql.sh
     tags: script

 Playbook中使用handlers和notify

Handlers本质是task list ,类似于MySQL中的触发器触发的行为,其中的task与前述的task并没有本质上的不同,主要用于当关注的资源发生变化时,才会采取一定的操作。而Notify对应的action可用于在每个play的最后被触发,这样可避免多次有改变发生时每次都执行指定的操作,仅在所有的变化发生完成后一次性地执行指定操作。在notify中列出的操作称为handler,也即notify中调用handler中定义的操作
注意:
如果多个task通知了相同的handlers, 此handlers仅会在所有tasks结束后运行一 次。
只有notify对应的task发生改变了才会通知handlers, 没有改变则不会触发handlers
handlers 是在所有前面的tasks都成功执行才会执行,如果前面任何一个task失败,会导致handler跳
过执行,可以使用force_handlers: yes 强制执行handler

案例1:
---
- hosts: websrvs
 remote_user: root
 gather_facts: no
 tasks:
    - name: Install httpd
      yum: name=httpd state=present
    - name: Install configure file
      copy: src=files/httpd.conf dest=/etc/httpd/conf/
      notify: 
        - restart httpd 
        - wall
    - name: ensure apache is running
      service: name=httpd state=started enabled=yes
   
 handlers:
    - name: restart httpd
      service: name=httpd state=restarted
    - name: wall
      command: wall "The config file is changed"
案例2:
---
- hosts: websrvs
 remote_user: root
 gather_facts: no
 tasks:
    - name: add group nginx
     user: name=nginx state=present
    - name: add user nginx
     user: name=nginx state=present group=nginx
    - name: Install Nginx
     yum: name=nginx state=present
    - name: config 
     copy: src=/root/config.txt dest=/etc/nginx/nginx.conf
     notify: ["Restart Nginx","Check Nginx Process"] #或者下面格式
        - Restart Nginx
        - Check Nginx Process
   
   handlers:
     - name: Restart Nginx
       service: name=nginx state=restarted enabled=yes
     - name: Check Nginx process
       shell: killall -0 nginx &> /tmp/nginx.log
案例3:强制调用handlers
- hosts: websrvs
 force_handlers: yes #无论task中的任何一个task失败,仍强制调用handlers
 tasks:
    - name: config file
     copy: src=nginx.conf  dest=/etc/nginx/nginx.conf
     notify: restart nginx
    - name: install package
     yum: name=no_exist_package
 handlers:
    - name: restart nginx
      service: name=nginx state=restarted

Playbook中使用tags组件

在playbook文件中,可以利用tags组件,为特定 task 指定标签,当在执行playbook时,可以只执行特定tags的task,而非整个playbook文件。

可以一个task对应多个tag,也可以多个task对应一个tag。

还有另外3个特殊关键字用于标签, tagged, untagged 和 all,它们分别是仅运行已标记,只有未标记和所有任务。

vim httpd.yml
---
# tags example
- hosts: websrvs
  remote_user: root
  gather_facts: no
  
 tasks:
    - name: Install httpd
      yum: name=httpd state=present
    - name: Install configure file
      copy: src=files/httpd.conf dest=/etc/httpd/conf/
      tags: [ conf,file ] #写在一行
        - conf    #写成多行
        - file
    - name: start httpd service
      tags: service
      service: name=httpd state=started enabled=yes
  
[root@ansible ~]#ansible-playbook --list-tags httpd.yml
[root@ansible ~]#ansible-playbook -t conf,service httpd.yml
[root@ansible ~]#ansible-playbook --skip-tags conf httpd.yml
[root@ansible ~]#ansible-playbook   httpd.yml --skip-tags untagged

 使用 setup 模块中变量

本模块自动在playbook调用,不要用ansible命令调用,生成的系统状态信息, 并存放在facts变量中
facts 包括的信息很多,如: 主机名,IP,CPU,内存,网卡等
facts 变量的实际使用场景案例
通过facts变量获取被控端CPU的个数信息,从而生成不同的Nginx配置文件
通过facts变量获取被控端内存大小信息,从而生成不同的memcached的配置文件
通过facts变量获取被控端主机名称信息,从而生成不同的Zabbix配置文件

变量的优先级从高到低如下:
-e 选项定义变量(ansible命令传入变量) -->playbook中vars_files --> playbook中vars变量定义 -->host_vars/主机名
文件 -->主机清单中主机变量--> group_vars/主机组名文件-->group_vars/all文件--> 主机清单组
变量
ansible 10.0.0.101 -m setup -a 'filter="ansible_default_ipv4"'
10.0.0.101 | SUCCESS => {
    "ansible_facts": {
        "ansible_default_ipv4": {
            "address": "10.0.0.101", 
            "alias": "eth0", 
            "broadcast": "10.0.0.255", 
            "gateway": "10.0.0.2", 
            "interface": "eth0", 
            "macaddress": "00:0c:29:e8:c7:9b", 
            "mtu": 1500, 
            "netmask": "255.255.255.0", 
            "network": "10.0.0.0", 
            "type": "ether"
       }
   }, 
    "changed": false
}
[root@centos8 ~]#ansible 10.0.0.8 -m setup -a "filter=ansible_nodename"
10.0.0.8 | SUCCESS => {
    "ansible_facts": {
        "ansible_nodename": "centos8",
        "discovered_interpreter_python": "/usr/libexec/platform-python"
   },
    "changed": false
}


---
#var1.yml
- hosts: all
 remote_user: root
 gather_facts: yes
 tasks:
    - name: create log file
     file: name=/data/{{ ansible_nodename }}.log state=touch owner=test 
mode=600
  
[root@ansible ~]#ansible-playbook var.yml

[root@ansible ansible]#cat show_ip.yml 
- hosts: websrvs
  
 tasks:
    - name: show eth0 ip address {{ ansible_facts["eth0"]["ipv4"]["address"] }} 
     debug:  
       msg: IP address {{ ansible_eth0.ipv4.address }}
        #msg: IP address {{ ansible_facts["eth0"]["ipv4"]["address"] }}
        #msg: IP address {{ ansible_facts.eth0.ipv4.address }}
范例: 
4.9.2 在playbook 命令行中定义变量
范例:
范例: 
        #msg: IP address {{ ansible_default_ipv4.address }}
        #msg: IP address {{ ansible_eth0.ipv4.address }}
        #msg: IP address {{ ansible_eth0.ipv4.address.split('.')[-1] }} #取IP中的
最后一个数字
[root@ansible ansible]#ansible-playbook -v show_ip.yml

[root@centos8 ~]#cat test.yml 
---
- hosts: websrvs
  
 tasks:
    - name: test var
     file: path=/data/{{ ansible_facts["eth0"]["ipv4"]["address"] }}.log 
state=touch
      #file: path=/data/{{ ansible_eth0.ipv4.address }}.log state=touch #和上面效
果一样
[root@centos8 ~]#ansible-playbook test.yml 
[root@centos8 ~]#ll /data/10.0.0.8.log 
-rw-r--r-- 1 root root 0 Oct 16 18:22 /data/10.0.0.8.log

在playbook命令行中定义变量。
vim var2.yml
---
- hosts: websrvs
  remote_user: root
  tasks:
    - name: install package
      yum: name={{ pkname }} state=present
[root@ansible ~]#ansible-playbook -e pkname=httpd var2.yml
在文件中定义变量:
#也可以将多个变量放在一个文件中
[root@ansible ~]#cat vars
pkname1: memcached
pkname2: vsftpd 
[root@ansible ~]#vim var2.yml
---
- hosts: websrvs
 remote_user: root
 tasks:
    - name: install package {{ pkname1 }
      yum: name={{ pkname1 }} state=present
    - name: install package {{ pkname2 }
      yum: name={{ pkname2 }} state=present
[root@ansible ~]#ansible-playbook -e '@vars' var2.yml

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值