8.A 创建和使用分区(NEW)
创建和使用分区
创建一个名为 /home/greg/ansible/partition.yml 的 playbook ,它将在所有受管节点上创建分区:
在vdb创建一个1500M主分区,分区号1,并格式化ext4
prod组将分区永久挂载到/data
如果磁盘空间不够,
给出提示信息Could not create partition of that size
创建800MiB分区
如果 vdb不存在,则给出提示信息this disk is not exist
Hint - 提示
Docs » User Guide » Working With Playbooks » Blocks
Docs » User Guide » Working With Playbooks » Conditionals
Docs » Special Variables
```bash $ /home/greg/ansible/partition.yml ```
--- - name: 创建和使用分区 hosts: all tasks: - name: Handle the error block: - name: Create a new primary partition parted: device: /dev/vdb number: 1 state: present part_end: 1500MiB - name: Create a ext4 filesystem filesystem: fstype: ext4 dev: /dev/vdb1 - name: Mount mount: path: /data src: /dev/vdb1 fstype: ext4 state: mounted when: inventory_hostname in groups.prod rescue: - debug: msg: Could not create partition of that size - name: Create a new primary partition parted: device: /dev/vdb number: 1 state: present part_end: 800MiB when: ansible_devices.vdb is defined - debug: msg: this disk is not exist when: ansible_devices.vdb is undefined
$ ansible-playbook /home/greg/ansible/partition.yml PLAY [创建和使用分区] *********************************************************************** TASK [Gathering Facts] *************************************************************** ok: [node5] ok: [node2] ok: [node1] ok: [node4] ok: [node3] TASK [Create a new primary partition] ************************************************ skipping: [node1] fatal: [node3]: FAILED! => {"changed": false, "err": "Error: The location 1500MiB is outside of the device /dev/vdb.\n", "msg": "Error while running parted script: /usr/sbin/parted -s -m -a optimal /dev/vdb -- unit KiB mklabel msdos mkpart primary 0% 1500MiB", "out": "", "rc": 1} changed: [node5] changed: [node4] changed: [node2] TASK [Create a ext4 filesystem] ****************************************************** skipping: [node1] changed: [node5] changed: [node2] changed: [node4] TASK [Mount] ************************************************************************* skipping: [node1] skipping: [node2] skipping: [node5] changed: [node4] TASK [debug] ************************************************************************* ok: [node3] => { "msg": "Could not create partition of that size" } TASK [Create a new primary partition] ************************************************ changed: [node3] TASK [debug] ************************************************************************* ok: [node1] => { "msg": "this disk is not exist" } skipping: [node2] skipping: [node5] skipping: [node3] skipping: [node4] PLAY RECAP *************************************************************************** node1 : ok=2 changed=0 unreachable=0 failed=0 skipped=3 rescued=0 ignored=0 node2 : ok=3 changed=2 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0 node3 : ok=3 changed=1 unreachable=0 failed=0 skipped=1 rescued=1 ignored=0 node4 : ok=4 changed=3 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0 node5 : ok=3 changed=2 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0
$ ansible all -a 'lsblk' node2 | CHANGED | rc=0 >> NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT vda 252:0 0 12G 0 disk ├─vda1 252:1 0 1M 0 part ├─vda2 252:2 0 100M 0 part /boot/efi ├─vda3 252:3 0 9.9G 0 part / └─vda4 252:4 0 2G 0 part vdb 252:16 0 2G 0 disk └─`vdb1 252:17 0 1.5G 0 part` node3 | CHANGED | rc=0 >> NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT vda 252:0 0 11G 0 disk ├─vda1 252:1 0 1M 0 part ├─vda2 252:2 0 100M 0 part /boot/efi ├─vda3 252:3 0 9.9G 0 part / └─vda4 252:4 0 1024M 0 part vdb 252:16 0 1G 0 disk └─`vdb1 252:17 0 799M 0 part` node5 | CHANGED | rc=0 >> NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT vda 252:0 0 12G 0 disk ├─vda1 252:1 0 1M 0 part ├─vda2 252:2 0 100M 0 part /boot/efi ├─vda3 252:3 0 9.9G 0 part / └─vda4 252:4 0 2G 0 part vdb 252:16 0 2G 0 disk └─`vdb1 252:17 0 1.5G 0 part` node4 | CHANGED | rc=0 >> NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT vda 252:0 0 12G 0 disk ├─vda1 252:1 0 1M 0 part ├─vda2 252:2 0 100M 0 part /boot/efi ├─vda3 252:3 0 9.9G 0 part / └─vda4 252:4 0 2G 0 part vdb 252:16 0 2G 0 disk └─`vdb1 252:17 0 1.5G 0 part /data` node1 | CHANGED | rc=0 >> NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT vda 252:0 0 20G 0 disk ├─vda1 252:1 0 1M 0 part ├─vda2 252:2 0 100M 0 part /boot/efi └─vda3 252:3 0 9.9G 0 part / $ ansible all -a 'lsblk -f /dev/vdb1' node4 | CHANGED | rc=0 >> NAME FSTYPE LABEL UUID MOUNTPOINT vdb1 `ext4` 00075f7d-69d4-4993-a5ed-fab33dc3f32b /data node5 | CHANGED | rc=0 >> NAME FSTYPE LABEL UUID MOUNTPOINT vdb1 `ext4` 666af262-3f7c-4938-8517-f01af44d2b4d node3 | CHANGED | rc=0 >> NAME FSTYPE LABEL UUID MOUNTPOINT vdb1 node2 | CHANGED | rc=0 >> NAME FSTYPE LABEL UUID MOUNTPOINT vdb1 `ext4` 63bf6c38-37b0-4663-b10e-bca22b8c9645 node1 | FAILED | rc=32 >> lsblk: /dev/vdb1: not a block devicenon-zero return code $ ansible prod -a 'grep data /etc/fstab' node4 | CHANGED | rc=0 >> `/dev/vdb1 /data ext4 defaults 0 0` node3 | FAILED | rc=1 >> non-zero return code
8.B 创建和使用逻辑卷(OLD)
创建和使用逻辑卷
创建一个名为 /home/greg/ansible/lv.yml 的 playbook ,它将在所有受管节点上运行以执行下列任务:
创建符合以下要求的逻辑卷:
逻辑卷创建在 research 卷组中
逻辑卷名称为 data
逻辑卷大小为 1500 MiB
使用 ext4 文件系统格式化逻辑卷
如果无法创建请求的逻辑卷大小,应显示错误信息
Could not create logical volume of that size
,并且应改为使用大小 800 MiB。
如果卷组 research 不存在,应显示错误信息
Volume group done not exist
不要以任何方式挂载逻辑卷
Hint - 提示 Docs » User Guide » Working With Playbooks » Blocks
```bash $ ansible-doc lvol $ ansible-doc filesystem $ ansible-doc debug
$ ansible-doc stat
$ ansible all -m setup -a ‘filter=lvm’
$ vim /home/greg/ansible/lv.yml
```yaml --- - name: 创建和使用逻辑卷 hosts: all tasks: - block: - name: Create a logical volume lvol: vg: research lv: data size: 1500 - name: Create a ext4 filesystem filesystem: fstype: ext4 dev: /dev/research/data rescue: - debug: msg: Could not create logical volume of that size - name: Create a logical volume lvol: vg: research lv: data size: 800 when: ansible_lvm.vgs.research is defined - debug: msg: Volume group done not exist when: ansible_lvm.vgs.research is not defined
$ ansible-playbook /home/greg/ansible/lv.yml PLAY [创建和使用逻辑卷] ************************************************************************* TASK [Gathering Facts] ****************************************************************** ok: [node2] ok: [node5] ok: [node4] ok: [node3] ok: [node1] TASK [Create a logical volume] ********************************************************** skipping: [node1] [WARNING]: The value 1500 (type int) in a string field was converted to '1500' (type string). If this does not look like what you expect, quote the entire value to ensure it does not change. fatal: [node3]: FAILED! => {"changed": false, "err": " Volume group \"research\" has insufficient free space (255 extents): 375 required.\n", "msg": "Creating logical volume 'data' failed", "rc": 5} changed: [node2] changed: [node4] changed: [node5] TASK [Create a ext4 filesystem] ********************************************************* skipping: [node1] changed: [node2] changed: [node4] changed: [node5] TASK [debug] **************************************************************************** ok: [node3] => { "msg": "Could not create logical volume of that size" } TASK [Create a logical volume] ********************************************************** [WARNING]: The value 800 (type int) in a string field was converted to '800' (type string). If this does not look like what you expect, quote the entire value to ensure it does not change. changed: [node3] TASK [debug] **************************************************************************** ok: [node1] => { "msg": "Volume group done not exist" } skipping: [node2] skipping: [node5] skipping: [node3] skipping: [node4] PLAY RECAP ****************************************************************************** node1 : ok=2 changed=0 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0 node2 : ok=3 changed=2 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0 node3 : ok=3 changed=1 unreachable=0 failed=0 skipped=1 rescued=1 ignored=0 node4 : ok=3 changed=2 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0 node5 : ok=3 changed=2 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
$ ansible all -m shell -a 'lvs' $ ansible all -m shell -a 'blkid /dev/research/data'
9. 生成主机文件
生成主机文件
将一个初始模板文件从 http://materials/hosts.j2 下载到 /home/greg/ansible
完成该模板,以便用它生成以下文件:针对每个清单主机包含一行内容,其格式与 /etc/hosts 相同
创建名为 /home/greg/ansible/hosts.yml 的 playbook ,它将使用此模板在 dev 主机组中的主机上生成文件 /etc/myhosts 。
该 playbook 运行后, dev 主机组中主机上的文件 /etc/myhosts 应针对每个受管主机包含一行内容:
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 172.25.250.9 node1.lab.example.com node1 172.25.250.10 node2.lab.example.com node2 172.25.250.11 node3.lab.example.com node3 172.25.250.12 node4.lab.example.com node4 172.25.250.13 node5.lab.example.com node5
注:清单主机名称的显示顺序不重要。
Hint - 提示
endfor
Docs » User Guide » Working With Playbooks » Using Variables
to_nice_yaml
Docs » User Guide » Working With Playbooks » Templating (Jinja2) » Filters
when
Docs » User Guide » Working With Playbooks » Conditionals
$ ansible dev -m debug -a 'var=groups' $ ansible dev -m debug -a "var=groups['all']" $ wget http://materials/hosts.j2 $ vim hosts.j2
- 第一次
{% for host in groups['all'] %} {{ hostvars[host]['ansible_facts'] | to_nice_yaml }} {% endfor %}
$ vim hosts.yml
--- - name: 生成主机文件 hosts: all tasks: - name: Template a file to /etc/myhosts template: src: /home/greg/ansible/hosts.j2 dest: /etc/myhosts when: inventory_hostname in groups.dev # when: '"dev" in group_names'
$ ansible-playbook hosts.yml
# vim /etc/myhosts /172.25.250.9 /node1.lab.example.com /node1
$ vim host.j2
10. 修改文件内容
修改文件内容
按照下方所述,创建一个名为 /home/greg/ansible/issue.yml 的 playbook :
该 playbook 将在所有清单主机上运行
该 playbook 会将 /etc/issue 的内容替换为下方所示的一行文本:
在 dev 主机组中的主机上,这行文本显示 为:Development
在 test 主机组中的主机上,这行文本显示 为:Test
在 prod 主机组中的主机上,这行文本显示 为:Production
Hint - 提示 Docs » User Guide » Working With Playbooks » Conditionals
Docs » Special Variables
$ ansible dev -m debug -a 'var=inventory_hostname' $ ansible dev -m debug -a 'var=groups' $ ansible dev -m debug -a 'var=groups.dev' $ ansible-doc copy $ ansible-doc stat $ vim /home/greg/ansible/issue.yml
--- - name: 修改文件内容 hosts: all tasks: - name: Copy using inline content 1 copy: content: 'Development' dest: /etc/issue when: inventory_hostname in groups.dev - name: Copy using inline content 2 copy: content: 'Test' dest: /etc/issue when: inventory_hostname in groups.test - name: Copy using inline content 3 copy: content: 'Production' dest: /etc/issue when: inventory_hostname in groups.prod
$ ansible-playbook /home/greg/ansible/issue.yml
$ ansible dev -a 'cat /etc/issue' $ ansible test -a 'cat /etc/issue' $ ansible prod -a 'cat /etc/issue'
11. 创建 Web 内容目录
创建 Web 内容目录
按照下方所述,创建一个名为 /home/greg/ansible/webcontent.yml 的 playbook :
该 playbook 在 dev 主机组中的受管节点上运行
创建符合下列要求的目录/webdev:
所有者为 webdev 组
具有常规权限:owner=read+write+execute, group=read+write+execute,other=read+execute
具有特殊权限:设置组 ID
用符号链接将 /var/www/html/webdev 链接到 /webdev
创建文件 /webdev/index.html ,其中包含如下所示的单行文件: Development
在 dev 主机组中主机上浏览此目录(例如 http://172.25.250.9/webdev/ )将生成以下输出
Development
Hint - 提示
- 隐藏考点setype,文件的上下文关系
- 需完成第3题
- 需完成第7题
$ ansible-doc file $ ansible-doc copy $ ansible dev -a 'ls -ldZ /var/www/html' -rw-r--r--. 1 root root system_u:object_r:`httpd_sys_content_t`:s0 11 Apr 14 07:11 /var/www/html
$ vim /home/greg/ansible/webcontent.yml
--- - name: 创建 Web 内容目录 hosts: dev # 完成第 7 题,可以使用『角色』启动服务 # roles: # - apache tasks: - name: Create a directory if it does not exist file: path: /webdev state: directory group: webdev mode: u=rwx,g=rwxs,o=rx # mode: '2775' - name: Create a symbolic link file: src: /webdev dest: /var/www/html/webdev state: link - name: Copy using inline content copy: content: 'Development' dest: /webdev/index.html setype: httpd_sys_content_t # 未完成第 7 题,可以使用『模块』启动服务 - name: Start service httpd, if not started service: name: httpd state: started enabled: yes
$ ansible-playbook /home/greg/ansible/webcontent.yml
$ curl http://node1/webdev/ Development
12. 生成硬件报告
生成硬件报告
创建一个名为 /home/greg/ansible/hwreport.yml 的 playbook ,它将在所有受管节点上生成含有以下信息的输出文件 /root/hwreport.txt :
清单主机名称
以 MB 表示的总内存大小
BIOS 版本
磁盘设备 vda 的大小
磁盘设备 vdb 的大小
输出文件中的每一行含有一个 key=value 对
您的 playbook 应当:
从 http://materials/hwreport.empty 下载文件,并将它保存为 /root/hwreport.txt
使用正确的值改为 /root/hwreport.txt
如果硬件项不存在,相关的值应设为 NONE
Hint - 提示
- inventory_hostname
- Docs » Special Variables
- default
- Docs » User Guide » Working With Playbooks » Templating (Jinja2) » Filters
$ ansible all -m setup | grep mem $ ansible all -m setup | grep bios $ ansible all -m setup -a 'filter=*device*' $ ansible-doc -l | grep -i download $ ansible-doc get_url $ ansible-doc lineinfile $ curl http://materials/hwreport.empty $ vim /home/greg/ansible/hwreport.yml
- 方法一
--- - name: 生成硬件报告 hosts: all tasks: - name: Download foo.conf get_url: url: http://materials/hwreport.empty dest: /root/hwreport.txt - name: Ensure 1 lineinfile: path: /root/hwreport.txt regexp: '^HOST=' line: HOST={{ inventory_hostname }} - name: Ensure 2 lineinfile: path: /root/hwreport.txt regexp: '^MEMORY=' line: MEMORY={{ ansible_memtotal_mb }} - name: Ensure 3 lineinfile: path: /root/hwreport.txt regexp: '^BIOS=' line: BIOS={{ ansible_bios_version }} - name: Ensure 4 lineinfile: path: /root/hwreport.txt regexp: '^DISK_SIZE_VDA=' line: DISK_SIZE_VDA={{ ansible_devices.vda.size }} - name: Ensure 5 lineinfile: path: /root/hwreport.txt regexp: '^DISK_SIZE_VDB=' line: DISK_SIZE_VDB={{ ansible_devices.vdb.size | default('NONE', true) }}
- 方法二
$ ansible-playbook /home/greg/ansible/hwreport.yml
$ ansible all -a 'cat /root/hwreport.txt'
13. 创建密码库
创建密码库
按照下方所述,创建一个 Ansible 库来存储用户密码:
库名称为 /home/greg/ansible/locker.yml
库中含有两个变量,名称如下:
pw_developer,值为 Imadev
pw_manager,值为 Imamgr
用于加密和解密该库的密码为 whenyouwishuponastar
密码存储在文件 /home/greg/ansible/secret.txt 中
Hint - 提示
- 做完最后一题,再做这个题
$ vim ansible.cfg
... vault_password_file = /home/greg/ansible/secret.txt
$ echo whenyouwishuponastar > /home/greg/ansible/secret.txt $ ansible-vault create /home/greg/ansible/locker.yml
--- pw_developer: Imadev pw_manager: Imamgr
$ ansible-vault view /home/greg/ansible/locker.yml --- pw_developer: Imadev pw_manager: Imamgr $ cat /home/greg/ansible/locker.yml ...
14. 创建用户帐户
创建用户帐户
从 http://materials/user_list.yml 下载要创建的用户的列表,并将它保存到 /home/greg/ansible
在本次练习中使用在其他位置创建的密码库 /home/greg/ansible/locker.yml 。创建名为 /home/greg/ansible/users.yml 的 playbook ,从而按以下所述创建用户帐户:
职位描述为 developer 的用户应当:
在 dev 和 test 主机组中的受管节点上创建
从 pw_developer 变量分配密码
是补充组 devops 的成员
职位描述为 manager 的用户应当:
在 prod 主机组中的受管节点上创建
从 pw_manager 变量分配密码
是补充组 opsmgr 的成员
密码采用 sha512 哈希格式。
您的 playbook 应能够在本次练习中使用在其他位置创建的库密码文件 /home/greg/ansible/secret.txt 正常运行。
Hint - 提示 Docs » User Guide » Working With Playbooks » Advanced Playbooks Features » Playbook Keywords
Docs » User Guide » Working With Playbooks » Loops
Docs » User Guide » Working With Playbooks » Conditionals
Docs » User Guide » Working With Playbooks » Templating (Jinja2) » Filters
$ wget http://materials/user_list.yml $ vim /home/greg/ansible/users.yml
- 方法一
--- - name: 创建用户帐户 1 hosts: dev,test vars_files: - /home/greg/ansible/locker.yml - /home/greg/ansible/user_list.yml tasks: - name: Ensure group 1 group: name: devops state: present - name: Add the user 1 user: name: "{{ item.name }}" groups: devops password: "{{ pw_developer | password_hash('sha512') }}" append: yes loop: "{{ users }}" when: item.job == 'developer' - name: 创建用户帐户 2 hosts: prod vars_files: - /home/greg/ansible/locker.yml - /home/greg/ansible/user_list.yml tasks: - name: Ensure group 2 group: name: opsmgr state: present - name: Add the user 2 user: name: "{{ item.name }}" groups: opsmgr password: "{{ pw_manager | password_hash('sha512') }}" append: yes loop: "{{ users }}" when: item.job == 'manager'
- 方法二
--- - name: 创建用户帐户 hosts: all vars_files: - /home/greg/ansible/locker.yml - /home/greg/ansible/user_list.yml tasks: - name: Ensure group1 group: name: devops loop: "{{ users }}" when: inventory_hostname in groups.dev or inventory_hostname in groups.test - name: Add the user1 user: name: "{{ item.name }}" password: "{{ pw_developer | password_hash('sha512', 'mysecretsalt') }}" groups: devops loop: "{{ users }}" when: item.job == 'developer' and (inventory_hostname in groups.dev or inventory_hostname in groups.test) - name: Ensure group2 group: name: opsmgr loop: "{{ users }}" when: inventory_hostname in groups.prod - name: Add the user2 user: name: "{{ item.name }}" password: "{{ pw_manager | password_hash('sha512', 'mysecretsalt') }}" groups: opsmgr loop: "{{ users }}" when: item.job == 'manager' and inventory_hostname in groups.prod
$ ansible-playbook /home/greg/ansible/users.yml
$ ansible dev,test -m shell -a 'id bob; id sally; id fred' $ ssh bob@172.25.250.9 bob@172.25.250.9\'s password: `Imadev` <Ctrl-D> $ ansible prod -m shell -a 'id fred; id bob; id sally' $ ssh sally@172.25.250.12 sally@172.25.250.12\'s password: `Imamgr` <Ctrl-D>
15. 更新 Ansible 库的密钥
更新 Ansible 库的密钥
按照下方所述,更新现有 Ansible 库的密钥:
- 从
http://materials/salaries.yml
下载 Ansible 库到/home/greg/ansible
- 当前的库密码为
insecure8sure
- 新的库密码为
bbs2you9527
- 库使用
新密码
保持加密状态
Hint - 提示 Docs » User Guide » Ansible Vault
$ wget http://materials/salaries.yml $ ansible-vault rekey salaries.yml Vault password: `insecure8sure` New Vault password: `bbs2you9527` Confirm New Vault password: `bbs2you9527` Rekey successful
$ ansible-vault view salaries.yml Vault password: `bbs2you9527` haha $ ansible-vault view --ask-vault-pass salaries.yml Vault password: `bbs2you9527` haha
Important - 重要
- vault 实验,先做最后一题,再做倒数第三题`创建密码库
- 如果已经修改了配置文件,验证时需使用--ask-vault-pass
16. 配置 cron 作业(增加)
配置 cron 作业
创建一个名为 /home/greg/ansible/cron.yml 的 playbook :
该 playbook 在 test 主机组中的受管节点上运行
配置 cron 作业,该作业每隔 2 分钟运行并执行以下命令:
logger "EX200 in progress",以用户 bob 身份运行
Hint - 提示 完成第 14 题
$ ansible-doc -l | grep cron $ ansible-doc cron $ vim /home/greg/ansible/cron.yml
--- - name: cron hosts: test tasks: - name: Ensure a job cron: name: "check dirs" minute: "*/2" job: 'logger "EX200 in progress"' user: bob
$ ansible-playbook /home/greg/ansible/cron.yml
$ ansible test -a 'crontab -l -u bob' node2 | CHANGED | rc=0 >> #Ansible: check dirs */2 * * * * logger "EX200 in progress" $ sleep 4m; \ ansible test -a 'grep EX200 /var/log/messages' node2 | CHANGED | rc=0 >> ... Aug 27 20:26:02 node2 `bob`[3626]: `EX200 in progress` Aug 27 20:28:01 node2 `bob`[3867]: `EX200 in progress`