CentOS 7.6安装使用Ansible(三):Ansible Playbook和变量类型

四、Ansible Playbooks

1、PlaybookYAMLJinja2简介:

Playbook:包含Ansible指令的YAML格式的文件,#为注释,ansbile-playbook命令根据自上而下的顺序依次执行。

YAMLYAML Ain't a Markup LanguageYAML不是一种标记语言)的递归缩写。在开发这种语言时,YAML的意思其实是Yet Another Markup Language(仍是一种标记语言),但为了强调这种语言以数据为中心,而不是以标记语言为中心,采用反向缩略语重命名。YAML的语法和其它高级语言类似,并且可以简单表达清单、散列表、标量等数据形态。它使用空白符号缩进和大量依赖外观的特色,特别适合用来表达或编辑数据结构、各种配置文件、倾印除错内容、文件大纲。对于Ansible,每一个YAML文件都是从一个列表开始,列表中的每一项都是一个键值对,通常它们被称为一个“哈希”或“字典”。列表中的所有成员都开始于相同的缩进级别,并且使用一个“-”作为开头(一个横杠和一个空格)。一个字典是由一个简单的“键: 值”形式组成(冒号后必须是一个空格)。

Jinja2Python中被广泛应用的模版引擎,它的设计思想来源于Django的模板引擎,并扩展了其语法和一系列强大的功能,包括:

(1)字面量:

Ø  字符串:使用单引号或双引号

Ø  数字:整数、浮点数

Ø  列表:[item1, item2, ...]

Ø  元组:(item1, item2, ...)

Ø  字典:{key1:value1, key2:value2, ...}

Ø  布尔型:truefalse

(2)算术运算符:+-*///%**

(3)比较运算符:==!=>>=<<=

(4)逻辑运算符:andornot()

2、Playbook中的元素:

(1)hosts:执行指定任务的、定义在hosts文件中的被管控主机

192.168.1.144

[websrvs]

apache ansible_host=192.168.1.145

nginx ansible_host=192.168.1.220

备注:

Ø  如果定义了主机组名(websrvs)或主机别名(apachenginx),hosts可以使用组名或别名

Ø  如果只定义了IP地址(192.168.1.144),则hosts只能使用IP地址

(2)remote_user:在被管控主机上执行任务的用户

(3)tasks:定义要在被管控主机上执行的任务列表

(4)handlers:可以把handler理解成另一种形式的taskhandler中的任务会被task中的任务进行调用,但是被调用并不意味着一定会执行,只有当task中的任务真正执行以后(真正的进行实际操作,造成了实际的改变),handler中被调用的任务才会执行。如果task中的任务并没有做出任何实际的操作,那么handler中的任务即使被调用,也不会执行,另外handler执行的顺序与handlerplaybook中定义的顺序是相同的,与handlernotify的顺序无关。默认情况下,所有task执行完毕后,才会执行各个handler,并不是执行完某个task后,立即执行与其对应的handler

(5)vars:定义playbook运行时需要使用的变量

(6)templates:包含了模板语法的文件

(7)tags:用于让用户选择运行或略过playbook中的部分代码

3、ansible-playbook的使用格式:# ansible-playbook [options] playbook.yml [playbook2 ...]

[options]

Ø  -C:尝试预测可能发生的一些变化,并不真正执行

Ø  -e 'EXTRA_VARS':设置key=value的自定义变量

Ø  --syntax-check:对playbook执行语法检查,并不真正执行

Ø  --list-hosts:列出匹配的远程主机列表,并不执行任何其它操作

Ø  --list-tags:列出所有可用标签

Ø  --list-tasks:列出所有要执行的任务

Ø  -t TAGS:仅执行指定标签标记的任务

Ø  --skip-tags 'SKIP_TAGS':仅执行与指定标签不匹配的标记的任务

Ø  --start-at-task 'START_AT_TASK':从匹配指定标签标记的任务开始执行

Ø  -f FORKS:指定一次批量管控多少台主机,默认一批管控5台主机

Ø  -u REMOTE_USER:以哪个用户连接至被管控主机,默认为None

Ø  -T TIMEOUT:连接至被管控主机的超时时长,默认10

Ø  --version:查看ansible主配置文件、ansible配置的模块搜索路径、ansible python模块位置、可执行程序位置和python版本信息

Ø  -h:显示帮助信息

4、playbook示例:所有被管控主机安装memcached软件包,启动并实现开机自启

# mkdir -pv /playbooks

# vim /playbooks/memcached.yml

- hosts: all

remote_user: root

tasks:

- name: install memcached

yum: name=memcached state=latest

- name: start memcached service

service: name=memcached state=started enabled=yes

# ansible-playbook --syntax-check /playbooks/memcached.yml

# ansible-playbook -C /playbooks/memcached.yml

# ansible-playbook /playbooks/memcached.yml


五、Ansible Variables

1、内置变量:

(1)hostvars:获取被管控主机的主机变量信息

# ansible all -m debug -a 'msg={{hostvars}}'

(2)ansible_version:获取ansible的版本号

# ansible all -m debug -a 'msg={{ansible_version}}'

# ansible all -m debug -a 'msg={{ansible_version.full}}'

(3)group_names:获取当前被管控主机所在分组的组名

# ansible all -m debug -a 'msg={{group_names}}'

(4)groups:获取主机清单中所有主机及主机组的分组信息

# ansible all -m debug -a 'msg={{groups}}'

# ansible all -m debug -a 'msg={{groups.websrvs}}'

备注:所有主机默认被分成了组名为“all”的组,没有分组的主机分到了名为“ungrouped”的组,即组名为“未分组”的组

(5)inventory_file:获取主机清单文件存放的路径和名称

# ansible all -m debug -a 'msg={{inventory_file}}'

(6)inventory_hostname:获取被管控主机的主机名,此处的主机名并非系统的主机名,而是对应主机在主机清单中配置的名称

# ansible all -m debug -a 'msg={{inventory_hostname}}'

备注:如果使用IP配置主机,inventory_hostname返回的值就是IP,如果使用别名配置主机,返回的值就是别名

2、ansible_facts变量:

(1)ansible_distribution:获取被管控主机的系统类型

(2)ansible_distribution_major_version:获取被管控主机的系统主版本号

(3)ansible_hostname:获取被管控主机的主机名

(4)ansible_os_family:获取被管控主机的系统系列名称

(5)ansible_pkg_mgr:获取被管控主机的包管理器名称

# vim /playbooks/facts.yml

- hosts: all

remote_user: root

tasks:

- name: show distribution

debug: msg={{ansible_distribution}}

- name: show distribution major version

debug: msg={{ansible_distribution_major_version}}

- name: show hostname

debug: msg={{ansible_hostname}}

- name: show os family

debug: msg={{ansible_os_family}}

- name: show package manager

debug: msg={{ansible_pkg_mgr}}

# ansible-playbook --syntax-check /playbooks/facts.yml

# ansible-playbook -C /playbooks/facts.yml

# ansible-playbook /playbooks/facts.yml

备注:

Ø  使用命令# ansible all -m setup | less查看到的所有ansible_facts变量

Ø  所有ansible_facts变量只能在playbook中使用,不能在ad-hoc中直接使用,会提示没有定义

3、通过主机清单文件定义的主机及主机组变量:

# vim /etc/ansible/hosts

(1)主机变量:

192.168.1.144

[websrvs]

192.168.1.145 ansible_user=keyso ansible_ssh_pass=123456

192.168.1.220 ansible_user=keyso ansible_ssh_pass=123456

[dbsrvs]

146 ansible_host=192.168.1.146

[test:children]

websrvs

dbsrvs

备注:

Ø  定义了3个组,websrvsdbsrvstest组,且test组中包含了2个子组websrvsdbsrvs,当操作test组时就相当于操作了这2个子组中的所有主机

Ø  146 ansible_host=192.168.1.146146为主机别名,配置了主机别名,IP前需要增加参数ansible_host

Ø  常用主机变量:

  ²  ansible_host:要远程连接的主机IP

    ²  ansible_portSSH使用的端口号

  ²  ansible_userSSH连接时默认使用的用户名

  ²  ansible_ssh_passSSH连接时的密码

  ²  ansbile_sudo_pass:使用sudo连接用户时的密码

(2)主机组变量:

192.168.1.144

[websrvs]

192.168.1.145

192.168.1.220

[dbsrvs]

146 ansible_host=192.168.1.146

[test:children]

websrvs

dbsrvs

[websrvs:vars]

ansible_user=keyso

ansible_ssh_pass=123456

备注:在配置密钥认证的情况下,无需配置ansible_useransible_ssh_pass两个参数

4、通过ansible-playbook命令传入变量:

# vim /playbooks/test.yml

- hosts: all

remote_user: root

tasks:

- name: command line variable

debug: msg={{cmdvar}}

# ansible-playbook --syntax-check -e cmdvar=hello /playbooks/test.yml

# ansible-playbook -C -e cmdvar=hello /playbooks/test.yml

# ansible-playbook -e cmdvar=hello /playbooks/test.yml

备注:命令行传入的变量优先级最高

5、循环中的固定变量item

(1)示例:如果被管控主机是RedHat系列的系统,则安装tomcatmemcachedvarnish三个软件包:

# vim /playbooks/pkgs.yml

- hosts: all

remote_user: root

tasks:

- name: install packages

yum: name={{item}} state=latest

loop:

- tomcat

- memcached

- varnish

when: ansible_os_family=="RedHat"

# ansible-playbook --syntax-check /playbooks/pkgs.yml

# ansible-playbook -C /playbooks/pkgs.yml

# ansible-playbook /playbooks/pkgs.yml

备注:

Ø  循环:迭代,需要重复执行的任务。对迭代项的引用,固定变量名为item,并在tasks中使用loop给定要迭代的元素列表。列表表示方式:字符串和字典。

Ø  when语句:在tasks中使用,表示条件判断,如果符合条件,则执行,jinja2的语法格式

(2)示例:所有被管控主机按如下要求创建用户组和用户,并设置用户系统登录密码

用户user1,基本组group1,密码111111

用户user2,基本组group2,密码222222

用户user3,基本组group3,密码333333

# vim /playbooks/addusers.yml

- hosts: all

remote_user: root

tasks:

- name: add groups

group: name={{item}} state=present

loop:

- group1

- group2

- group3

- name: add users

user: name={{item.user}} group={{item.group}} state=present

loop:

- {user: user1, group: group1}

- {user: user2, group: group2}

- {user: user3, group: group3}

- name: set password

shell: echo {{item.passwd}} | passwd --stdin {{item.user}}

loop:

- {passwd: 111111, user: user1}

- {passwd: 222222, user: user2}

- {passwd: 333333, user: user3}

# ansible-playbook --syntax-check /playbooks/addusers.yml

# ansible-playbook -C /playbooks/addusers.yml

# ansible-playbook /playbooks/addusers.yml

6、自定义变量:

(1)playbook中使用vars关键字定义变量

(2)playbook中使用set_fact模块定义变量

(3)vars_files:将文件中的变量引入playbook,以便在task中使用

(4)include_vars:将文件中的变量动态引入playbook,以便在task中使用

# vim /playbooks/uservar.yml

- hosts: all

remote_user: root

vars:

- var1: test1

vars_files:

- /tmp/uservar.txt

tasks:

- name: show var1

debug: msg={{var1}}

- name: show var2

debug: msg={{var2}}

- name: set var3

set_fact: var3=test3

- name: show var3

debug: msg={{var3}}

- name: modify uservar file

shell: sed -i 's/var2/var4/g' /tmp/uservar.txt

- name: set var4

include_vars: /tmp/uservar.txt

- name: show var4

debug: msg={{var4}}

# cat /tmp/uservar.txt

var2: test2

# ansible-playbook --syntax-check /playbooks/uservar.yml

# ansible-playbook -C /playbooks/uservar.yml

# ansible-playbook /playbooks/uservar.yml

备注:

Ø  set_fact模块定义的变量在其它playbook中也能被正常引用,但vars关键字定义的变量不行

Ø  在变量文件/tmp/uservar.txt中通过sed命令将var2替换成了变量var4include_vars模块能够重新加载变量文件,并动态的以任务的方式引用变量var4

Ø  变量文件/tmp/uservar.txt位于Ansible主机,与被管控主机无关

7、 综合示例:

(1)如果被管控主机是CentOS 7.x系列的系统,则根据提供的模板文件redis.conf.j2安装、配置并启动redis

# vim /playbooks/redis.yml

- hosts: all

remote_user: root

tasks:

- name: install redis

yum: name=redis state=latest

- name: install configuration file

template: src=/playbooks/redis.conf.j2 dest=/etc/redis.conf owner=redis group=root mode=0640 backup=yes

when: ansible_distribution=="CentOS" and ansible_distribution_major_version=="7"

notify: restart redis service

tags: redis configuration file

- name: start redis service

service: name=redis state=started enabled=yes

handlers:

- name: restart redis service

service: name=redis state=restarted

# cat /playbooks/redis.conf.j2

bind {{ansible_host}}

requirepass keyso0728

# ansible-playbook --syntax-check /playbooks/redis.yml

# ansible-playbook -C /playbooks/redis.yml

# ansible-playbook /playbooks/redis.yml

备注:

Ø  Ansible节点中先安装redis,提取redis.conf,并修改为模板文件

Ø  CentOS 7.6CentOS 6.10redis.conf原始配置文件内容一致

Ø  redis启动后监听的端口为6379

Ø  修改模板文件redis.conf.j2中的内容,然后将模板文件复制至被管控节点,重启redis生效,可以执行命令:# ansible-playbook -t 'redis configuration file' /playbooks/redis.yml

(2)安全加固后的被管控主机不允许直接以root用户身份登录,需要通过普通用户testuser连接至被管控主机,然后suroot用户,执行那些需要root用户权限才能执行的命令

# vim /etc/ansible/hosts

192.168.1.144

[websrvs]

192.168.1.145

192.168.1.220

[dbsrvs]

146 ansible_host=192.168.1.146

[test:children]

websrvs

dbsrvs

# ansible all -a 'whoami' --> root用户

# ansible all -m user -a 'name=testuser state=present'

# ansible all -m shell -a 'echo 123456 | passwd --stdin testuser'

禁止root用户直接登录远程被管控主机:

# ansible all -m lineinfile -a 'path=/etc/ssh/sshd_config regexp="^#PermitRootLogin yes" line="PermitRootLogin no" state=present backup=yes'

# ansible all -m service -a 'name=sshd state=restarted'

再使用root用户连接至被管控节点会报错

# vim /etc/ansible/hosts

192.168.1.144

[websrvs]

192.168.1.145

192.168.1.220

[dbsrvs]

146 ansible_host=192.168.1.146

[test:children]

websrvs

dbsrvs

[websrvs:vars]

ansible_user=testuser

ansible_ssh_pass=123456

ansible_become_pass=hellolinux

备注:

Ø  ansible_user:定义普通用户名称

Ø  ansible_ssh_pass:定义普通用户密码

Ø  ansible_become_pass:定义切换root用户时需要的登录密码

# ansible all -a 'whoami' --> testuser用户

尝试以testuser用户身份在每台被管控主机的/root目录下创建a.txt文件,结果Permission denied

# ansible all -m file -a 'content= path=/root/a.txt state=touch'

# ansible all --become-method su -b -a 'whoami' --> root用户

备注:

Ø  --become-method:将权限提升的方式设置为su,默认为sudo

Ø  -b:使用become执行操作(不提示密码输入)

# ansible all --become-method su -b -m file -a 'content= path=/root/a.txt state=touch'


猜你喜欢

转载自blog.51cto.com/qiuyue/2384878