本次实验环境是在之前编写playbook时配置过的实验环境,在普通用户devops家目录下的ansible目录中进行实验。已经提前配置好ansible及两台hosts主机的免密及用户授权,三台机子均拥有普通用户devops。具体方法详情见前篇《云计算自动化运维——Ansible详解及inventory文件配置》
附链接:https://blog.csdn.net/CapejasmineY/article/details/103113503
之前学习了playbook,将所有任务、解释器等都定义在一个文件中,内容过于复杂繁琐,不利于后期的维护,因此需要解耦、拆解!
把某个服务特定功能配置定义成模块,当使用时直接调用这个模块,简单明了,在ansible中它有一个特有的名称,即角色。
存放由copy或script模块等调用的文件。Ansible roles是为了层次化、结构化地组织Playbook。根据playbook的功能,如tasks,handlers,templates,files等要实现的工作进行拆分,将各自的功能块放在相应目录中。在roles目录下,分别创建不同的目录,每个目录就是不同的角色,roles目录下是角色的集合。
除此外,每个角色根据其要实现的不同功能,在该角色目录下创建相应的子目录来存放被模块化分解的剧本文件,然后根据各个模块要实现的工作在相应的子目录中编写剧本,大致如下:
角色子目录结构及相应功能拆解:
templates:
template模块查找所需要模板文件的目录。Ansible 里用的文件模板使用的是 Jinja2 ,基本上就是你可以在文本文件里使用变量,做条件判断等。
tasks:
用于定义任务,至少应该包含一个名为main.yml的文件(类似于java和go等编译性语言,用于指定程序的入口),其他的文件需要在此文件中通过include进行包含。
handlers:
定义解释器,至少应该包含一个名为main.yml的文件,其他的文件需要在此文件中通过include进行包含。
vars:
定义变量,至少应该包含一个名为main.yml的文件,其他的文件需要在此文件中通过include进行包含。
meta:
定义元数据,至少应该包含一个名为main.yml的文件,定义当前角色的特殊设定及其依赖关系,其他的文件需要在此文件中通过include进行包含。
default:
设定模式变量时使用此目录中的main.yml文件。
常用命令:
ansible-galaxy list #列出已安装角色
ansible-galaxy init apache #使用init命令初始化新角色的基本结构,节省创建各种目录和main.yml文件的时间
实验环境:
虚拟机名称 | ip | 版本 | 角色 |
---|---|---|---|
server1 | 172.25.1.1 | 7.5 | ansible |
server2 | 172.25.1.2 | 7.5 | 远程主机hosts |
server3 | 172.25.1.3 | 7.5 | 远程主机hosts |
注:保证ansible虚拟机能上网
实验:
1、角色安装部署
步骤一:编写ansible.cfg文件,将角色目录文件路径写入
vim ansible.cfg
[defaults]
#(1)资源清单的路径
inventory = ./hosts
remote_user = devops #登陆到hosts主机上后用的身份
roles_path = ./roles
#安全的角度-->开放普通用户的身份
[privilege_escalation]
#(1)是否可以sudo
become=True
#(2)采用sudo的身份
become_method=sudo
#(3)sudo后的用户身份
become_user=root
#(4)sudo是否需要验证密码
become_ask_pass=False
步骤二:创建角色目录并初始化新角色
cd /home/devops/ansible
mkdir roles #创建角色目录
cd roles #进入角色目录
ansible-galaxy init apache #使用init命令初始化新角色apache的基本结构
cd /home/devops/ansible #进入ansible目录
ansible-galaxy list #列出已安装角色
2、编写apache自动安装角色
列出apache目录结构:
步骤一:在apache目录下编写tasks/main.yml文件
---
# tasks file for apache
- name: install apache
yum:
name: httpd
state: present
- name: config apache
template:
src: httpd.conf.j2
dest: /etc/httpd/conf/httpd.conf
notify: restart httpd
- name: start apache
service:
name httpd
state: started
- name: copy index.html
copy:
src: index.html
dest: /var/www/html/index.html
步骤二:编写触发器handlers/main.yml文件
---
# handlers file for apache
- name: restart httpd #此处的name与playbook中一致
service:
name: httpd
state: restarted
步骤三:在tasks目录下(此路径是tasks/main.yml文件中指出的路径,可修改)编写要拷贝的目标主机的默认发布页面文件
vim index.html
www.westos.org
步骤四:提前安装好httpd服务,将生成的配置文件httpd.conf拷贝到templates目录下,并做相应修改
修改文件所有人和所有组为devops
修改文件类型:
修改配置文件httpd.conf中的监听主机及监听端口,用变量代替
步骤五:编写vars/main.xml文件,定义变量
步骤六:关闭hosts主机防火墙
ansible all调用hosts文件中定义的所有主机:
步骤七:编写apache.yml文件,调用执行角色
---
- hosts: db
roles:
- apache
查看hosts文件,db组内主机是server3:
步骤八:执行apache.yml文件
ansible-playbook apache.yml
3、判断hosts文件中的变量及apache.yml文件变量及角色中vars/main.xml文件变量的优先级
思路:上一步是在vars/main.xml文件中定义的监听端口变量http_port: 80,角色调用时直接读取到了。此时我们在hosts文件中的db主机对应组内变量中添加监听端口变量http_port=8080,赋于不同的值,然后运行脚本,看哪个变量会被读取到。判断出优先级后,在apache.yml文件中添加变量http_port: 8989,测试哪个会被读取。
步骤一:在hosts文件中定义http_port变量
步骤二:运行playbook并测试
ansible-playbook apache.yml
测试:
结果分析:角色执行时,如果hosts文件及vars/main.yml文件中有相同变量,会优先读取vars/main.yml文件中的变量。
步骤三:在apache.yml文件中添加变量http_port
步骤四:运行playbook并测试
测试:
结果分析:角色执行时,如果hosts文件及vars/main.yml文件及playbook中有相同变量,会优先读取vars/main.yml文件中的变量。
步骤五:注释掉vars/main.yml文件中的变量
步骤六:运行playbook并测试
测试:
结果分析:角色执行时,如果hosts文件及playbook中有相同变量,会优先读取playbook文件中的变量。
步骤七:注释掉playbook中的变量
步骤八:运行playbook并测试
结论:playbook执行角色调用时,读取变量优先级
roles/vars/main.yml>playbook > hosts
4、查看主机信息及对应变量名
ansible db -m setup | less #列出db组的主机信息
此种方式会查询到很多字典键值对,选取其中一种正确的变量名即可。这种对应方式与python语法类似,在playbook中定义时也使用层级对应关系定义,字典里边不同类型的key值,需要选取不同的截取方式。
(1)修改上一步apache检测主机名变量定义名称,对应特定主机
为修改方便,我将主机名变量写到playbook中,注释掉vars/main.xml文件中的变量
(官方推荐)
方式一:
ansible db -m setup | less #查看db组内主机信息
参照查到的内容定义主机名:
运行:
测试:
server3主机上:
查看/etc/httpd/conf/httpd.conf 文件
方式二:
ansible db -m setup | less #查看db组内主机信息
(1)编写playbook,展示hosts主机信息
使用ansible db -m setup | less 查询各变量名,将其写到playbook中
步骤一:编辑info.j2文件
主机名: "{{ ansible_facts['hostname'] }}"
主机ip: "{{ ansible_facts['default_ipv4']['address'] }}"
主机网关: "{{ ansible_facts['default_ipv4']['gateway' ]}}"
主机dns: "{{ ansible_facts['dns']['nameservers'][-1] }}"
系统空闲内存: "{{ ansible_facts['memfree_mb'] }}"MB
系统磁盘空间: "{{ ansible_facts['devices']['dm-0']['size']}}"
系统内核: "{{ ansible_facts['kernel'] }}"
系统版本: "{{ ansible_facts['distribution'] }}" "{{ ansible_facts['distribution_version'] }}"
步骤二:编辑playbook文件,将文件的执行内容发往目标主机
运行:
测试:
6、when用法
Ansible提供when语句,可以控制任务的执行流程。
例:
---
- hosts: webserver
vars:
- http_port: 8080
- http_host: "{{ ansible_eth0['ipv4']['address'] }}"
roles:
- role: apache
when: ansible_hostname == "server3" #只有当ansible对server3主机执行时,调用角色apache
loop循环中存放的字典型数据,用 item.key值 调用value值
【1】创建多用户,并为每个用户设置密码
例:
---
- hosts: localhost
tasks:
- name: create users
user:
name: "{{ item.user }}"
state: present
password: "{{ item.pass | password_hash('sha512') }}"
loop:
- { user: user1, pass: westos }
- { user: user2, pass: redhat }
- { user: user3, pass: linux }
可以看出这种方式下,密码暴露在外不安全
【2】创建用户时用户密码加密
ansible-vault #查看加密用法
ansible-vault encrypt userlist.yml #加密
ansible-vault view userlist.yml #查看密文对应的明文
ansible-vault decrypt userlist.yml #解密
步骤二:文件加密
步骤三:修改users.yml文件,将变量文件写入playbook
步骤四:运行
8、更新/etc/hosts主机解析文件
步骤一:编写模板文件
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
{% for host in groups['localhost'] %} #对localhost组内主机
{{ hostvars[host]['ansible_facts']['eth0']['ipv4']['address']}} {{ hostvars[host]['ansible_facts']['hostname']}}
{% endfor %}