day03

[toc]

playbook

模块

  1. # 在test组中的主机上,安装httpd、php、php-mysqlnd
  2. [root@control ansible]# vim pkg.yml
  3. ---
  4. - name: install pkgs
  5. hosts: test
  6. tasks:
  7. - name: install web pkgs # 此任务通过yum安装三个包
  8. yum:
  9. name: httpd,php,php-mysqlnd
  10. state: present
  11. # 安装多个软件包,还可以写为:
  12. ---
  13. - name: install pkgs
  14. hosts: test
  15. tasks:
  16. - name: install web pkgs
  17. yum:
  18. name: [httpd,php,php-mysqlnd]
  19. state: present
  20. # 安装多个软件包,还可以写为:
  21. ---
  22. - name: install pkgs
  23. hosts: test
  24. tasks:
  25. - name: install web pkgs
  26. yum:
  27. name:
  28. - httpd
  29. - php
  30. - php-mysqlnd
  31. state: present
  32. # 根据功能等,可以将一系列软件放到一个组中,安装软件包组,将会把很多软件一起安装上。比如gcc、java等都是开发工具,安装开发工具包组,将会把它们一起安装。
  33. [root@node1 ~]# yum grouplist # 列出所有的软件包组
  34. [root@node1 ~]# yum groupinstall "Development Tools"
  35. # 如果列出的组名为中文,可以这样进行:
  36. [root@node1 ~]# LANG=C yum grouplist
  37. # 继续编辑pkg.yml,在test组中的主机上安装Development tools组
  38. [root@control ansible]# vim pkg.yml
  39. ---
  40. - name: install pkgs
  41. hosts: test
  42. tasks:
  43. - name: install web pkgs # 此任务通过yum安装三个包
  44. yum:
  45. name:
  46. - httpd
  47. - php
  48. - php-mysqlnd
  49. state: present
  50. - name: install dev group # 此任务通过yum安装一组包
  51. yum:
  52. name: "@Development Tools" # @表示后面的名字是组名
  53. state: present
  54. [root@control ansible]# ansible-playbook pkg.yml
  55. # 系统升级命令
  56. [root@control ansible]# yum update
  57. # 继续编辑pkg.yml,在test组中的主机上升级所有的包到最新版本
  58. ---
  59. - name: install pkgs
  60. hosts: test
  61. tasks:
  62. - name: install web pkgs
  63. yum:
  64. name:
  65. - httpd
  66. - php
  67. - php-mysqlnd
  68. state: present
  69. - name: install dev group
  70. yum:
  71. name: "@Development Tools"
  72. state: present
  73. - name: update system # 相当于yum update命令
  74. yum:
  75. name: "*" # 表示系统已经安装的所有包
  76. state: latest
  77. [root@control ansible]# ansible-playbook pkg.yml

ansible变量

facts变量

  • facts翻译过来就是事实。
  • facts变量是ansible自带的预定义变量,用于描述被控端软硬件信息。
  • facts变量通过setup模块获得。
  1. # 通过setup模块查看所有facts变量
  2. [root@control ansible]# ansible test -m setup
  • facts变量是一个大的由{}构成的键值对字典。在{}中,有很多层级的嵌套。可以通过参数过滤出第一个层级的内容。
  1. # 查看所有的IPV4地址,filter是过滤的意思
  2. [root@control ansible]# ansible test -m setup -a "filter=ansible_all_ipv4_addresses"
  3. # 查看可用内存
  4. [root@control ansible]# ansible test -m setup -a "filter=ansible_memfree_mb"
  • 常用的facts变量

    • ansible_all_ipv4_addresses:所有的IPV4地址
    • ansible_bios_version:BIOS版本信息
    • ansible_memtotal_mb:总内存大小
    • ansible_hostname:主机名
  • 在playbook中使用变量
  1. # 显示远程主机的主机名和内存大小。在ansible中,变量使用{{}}表示
  2. # debug模块用于输出信息,常用的参数是msg,用于输出指定内容
  3. [root@control ansible]# vim debug.yml
  4. ---
  5. - name: display host info
  6. hosts: test
  7. tasks:
  8. - name: display hostname and memory
  9. debug: # debug是模块,它的选项msg可以输出指定信息
  10. msg: "hostname: {{ansible_hostname}}; mem: {{ansible_memtotal_mb}} MB"
  11. [root@control ansible]# ansible-playbook debug.yml

自定义变量

  • 引入变量,可以方便Playbook重用。比如装包的playbook,包名使用变量。多次执行playbook,只要改变变量名即可,不用编写新的playbook。
  • ansible支持10种以上的变量定义方式。常用的变量来源如下:

    • inventory变量。变量来自于主机清单文件
    • facts变量。
    • playbook变量。变量在playbook中定义。
    • 变量文件。专门创建用于保存变量的文件。推荐变量写入单独的文件。
  1. # 使用inventory变量。
  2. [root@control ansible]# vim hosts
  3. [test]
  4. node1 iname="nb" # 主机变量定义的方法。iname是自定义名称
  5. [proxy]
  6. node2
  7. [webservers]
  8. node[3:4]
  9. [database]
  10. node5
  11. [cluster:children]
  12. webservers
  13. database
  14. [webservers:vars] # 组变量定义方法。:vars是固定格式
  15. iname="dachui"
  16. # 通过变量创建用户
  17. [root@control ansible]# vim var1.yml
  18. ---
  19. - name: test create user
  20. hosts: test
  21. tasks:
  22. - name: create user
  23. user:
  24. name: "{{iname}}"
  25. state: present
  26. - name: create user in webservers
  27. hosts: webservers
  28. tasks:
  29. - name: create some users
  30. user:
  31. name: "{{iname}}"
  32. state: present
  33. [root@control ansible]# ansible-playbook var1.yml
  34. # 上述两个play也可以合并为一个,如下:
  35. [root@control ansible]# vim var1.yml
  36. ---
  37. - name: test create user
  38. hosts: test,webservers # 指定执行的目标是test组和webservers组
  39. tasks:
  40. - name: create user
  41. user:
  42. name: "{{iname}}"
  43. state: present
  44. # 在playbook中定义变量
  45. # 在test组中的主机上创建用户jack,他的密码是123456
  46. [root@control ansible]# vim user_jack.yml
  47. ---
  48. - name: create user
  49. hosts: test
  50. vars: # 固定格式,用于声明变量
  51. username: "jack" # 此处引号可有可无
  52. mima: "123456" # 此处引号是需要的,表示数字字符
  53. tasks:
  54. - name: create some users
  55. user:
  56. name: "{{username}}" # {}出现在开头,必须有引号
  57. state: present
  58. password: "{{mima|password_hash('sha512')}}"
  59. [root@control ansible]# ansible-playbook user_jack.yml
  60. # 将变量定义在文件中
  61. [root@control ansible]# vim vars.yml # 文件名自定义
  62. ---
  63. yonghu: rose
  64. mima: abcd
  65. [root@control ansible]# vim user_rose.yml
  66. ---
  67. - name: create user
  68. hosts: test
  69. vars_files: vars.yml # vars_files用于声明变量文件
  70. tasks:
  71. - name: create some users
  72. user:
  73. name: "{{yonghu}}" # 这里的变量来自于vars.yml
  74. state: present
  75. password: "{{mima|password_hash('sha512')}}"
  76. [root@control ansible]# ansible-playbook user_rose.yml

补充模块

firewalld模块

  • 用于配置防火墙的模块

  • 常用选项:

    • port:声明端口
    • permanent:永久生效,但不会立即生效
    • immediate:立即生效,临时生效
    • state:enabled,放行;disabled拒绝
  • 防火墙一般默认拒绝,明确写入允许的服务。

  • 有一些服务有名字,有些服务没有名字。但是最终都是基于TCP或UDP的某些端口。比如http服务基于TCP80端口。服务名和端口号对应关系的说明文件是:/etc/services

  • 配置服务器的防火墙,一般来说只要配置开放哪些服务或端口即可。没有明确开放的,都默认拒绝。

  • 应用

    • 在test组中的主机上安装并启动httpd
    • 客户端访问服务器的http服务
    • 在test组中的主机上安装并启动firewalld
    • 客户端访问服务器的http服务
    • 在test组中的主机上开放http服务
  1. # 配置httpd服务
  2. [root@control ansible]# vim firewall.yml
  3. ---
  4. - name: configure test
  5. hosts: test
  6. tasks:
  7. - name: install httpd pkg # 这里通过yum模块装httpd
  8. yum:
  9. name: httpd
  10. state: present
  11. - name: start httpd service # 这里通过service模块启httpd服务
  12. service:
  13. name: httpd
  14. state: started
  15. enabled: yes
  16. [root@control ansible]# ansible-playbook firewall.yml
  17. [root@control ansible]# curl http://192.168.88.11/ # 可访问
  18. # 安装并启动firewalld
  19. [root@control ansible]# vim firewall.yml
  20. ---
  21. - name: configure test
  22. hosts: test
  23. tasks:
  24. - name: install httpd pkg # 这里通过yum模块装httpd
  25. yum:
  26. name: httpd
  27. state: present
  28. - name: start httpd service # 这里通过service模块启httpd服务
  29. service:
  30. name: httpd
  31. state: started
  32. enabled: yes
  33. - name: install firewalld pkg # 这里通过yum模块装firewalld
  34. yum:
  35. name: firewalld
  36. state: present
  37. - name: start firewalld service # 这里通过service模块启firewalld服务
  38. service:
  39. name: firewalld
  40. state: started
  41. enabled: yes
  42. [root@control ansible]# ansible-playbook firewall.yml
  43. [root@control ansible]# curl http://192.168.88.11/ # 被拒绝
  44. curl: (7) Failed to connect to 192.168.88.11 port 80: 没有到主机的路由
  45. # 配置防火墙规则,放行http协议
  46. [root@control ansible]# vim firewall.yml
  47. ---
  48. - name: configure test
  49. hosts: test
  50. tasks:
  51. - name: install httpd pkg # 这里通过yum模块装httpd
  52. yum:
  53. name: httpd
  54. state: present
  55. - name: start httpd service # 这里通过service模块启httpd服务
  56. service:
  57. name: httpd
  58. state: started
  59. enabled: yes
  60. - name: install firewalld pkg # 这里通过yum模块安装firewalld
  61. yum:
  62. name: firewalld
  63. state: present
  64. - name: start firewalld service # 这里通过service模块启service服务
  65. service:
  66. name: firewalld
  67. state: started
  68. enabled: yes
  69. - name: set firewalld rules # 通过firewalld模块开放80端口
  70. firewalld:
  71. port: 80/tcp
  72. permanent: yes
  73. immediate: yes
  74. state: enabled
  75. [root@control ansible]# ansible-playbook firewall.yml
  76. [root@control ansible]# curl http://192.168.88.11/ # 可访问

template模块

  • copy模块可以上传文件,但是文件内容固定
  • template模块可以上传具有特定格式的文件(如文件中包含变量)
  • 当远程主机接收到文件之后,文件中的变量将会变成具体的值
  • template模块上传的文件,使用的语法叫Jinja2。
  • 常用选项:

    • src:要上传的文件
    • dest:目标文件路径
  1. # 使用template模块将含有变量的文件上传到test组中的主机
  2. [root@control ansible]# vim index.j2
  3. Welcome to {{ansible_hostname}} on {{ansible_eth0.ipv4.address}}
  4. [root@control ansible]# vim templ.yml
  5. ---
  6. - name: upload index
  7. hosts: test
  8. tasks:
  9. - name: create web index
  10. template:
  11. src: index.j2
  12. dest: /var/www/html/index.html
  13. [root@control ansible]# ansible-playbook templ.yml
  14. [root@control ansible]# curl http://192.168.88.11/
  15. Welcome to node1 on 192.168.88.11
  16. [root@node1 ~]# cat /var/www/html/index.html
  17. Welcome to node1 on 192.168.88.11

进阶语法

错误处理

  • 当Playbook中包含很多任务时,当某一个任务遇到错误,它将崩溃,终止执行
  1. # 在test组中的主机上启动mysqld服务,然后创建/tmp/service.txt
  2. # 因为目标主机上没有mysqld服务,所以它将崩溃,终止执行。即,不会创建/tmp/service.txt文件
  3. [root@control ansible]# vim myerr.yml
  4. ---
  5. - name: my errors
  6. hosts: test
  7. tasks:
  8. - name: start mysqld service # 通过service模块启动mysqld服务
  9. service:
  10. name: mysqld
  11. state: started
  12. enabled: yes
  13. - name: touch a file # 通过file模块创建文件
  14. file:
  15. path: /tmp/service.txt
  16. state: touch
  17. # 执行playbook,第1个任务就会失败
  18. [root@control ansible]# ansible-playbook myerr.yml
  19. # 到node1上查看,因为第2个任务没有执行,所以文件不会创建
  20. [root@node1 ~]# ls /tmp/service.txt
  21. ls: cannot access '/tmp/service.txt': No such file or directory
  • 可以指定某一个任务如果出现错误,则忽略它
  1. # 编辑myerr.yml,如果myslqd服务无法启动,则忽略它
  2. [root@control ansible]# vim myerr.yml
  3. ---
  4. - name: my errors
  5. hosts: test
  6. tasks:
  7. - name: start mysqld service
  8. service:
  9. name: mysqld
  10. state: started
  11. enabled: yes
  12. ignore_errors: yes # 即使这个任务失败了,也要继续执行下去
  13. - name: touch a file
  14. file:
  15. path: /tmp/service.txt
  16. state: touch
  17. [root@control ansible]# ansible-playbook myerr.yml
  18. [root@node1 ~]# ls /tmp/service.txt # 第2个任务已执行
  19. /tmp/service.txt
  • 通过全局设置,无论哪个任务出现问题,都要忽略
  1. [root@control ansible]# vim myerr.yml
  2. ---
  3. - name: my errors
  4. hosts: test
  5. ignore_errors: yes
  6. tasks:
  7. - name: start mysqld service
  8. service:
  9. name: mysqld
  10. state: started
  11. enabled: yes
  12. - name: touch a file
  13. file:
  14. path: /tmp/mysql.txt
  15. state: touch
  16. [root@control ansible]# ansible-playbook myerr.yml
  17. [root@node1 ~]# ls /tmp/mysql.txt
  18. /tmp/mysql.txt

触发执行任务

  • 通过handlers定义触发执行的任务
  • handlers中定义的任务,不是一定会执行的
  • 在tasks中定义的任务,通过notify关键通知handlers中的哪个任务要执行
  • 只有tasks中的任务状态是changed才会进行通知。
  1. # 下载node1上的/etc/httpd/conf/httpd.conf
  2. [root@control ansible]# vim get_conf.yml
  3. ---
  4. - name: download httpd.conf
  5. hosts: test
  6. tasks:
  7. - name: get httpd.conf
  8. fetch:
  9. src: /etc/httpd/conf/httpd.conf
  10. dest: ./
  11. flat: yes # 直接下载文件,不要目录
  12. [root@control ansible]# ansible-playbook get_conf.yml
  13. # 修改httpd.conf的端口为变量
  14. [root@control ansible]# vim +45 httpd.conf
  15. ... ...
  16. Listen {{http_port}}
  17. ... ...
  18. # 修改httpd服务的端口为8000,重启httpd
  19. [root@control ansible]# vim trigger.yml
  20. ---
  21. - name: configure httpd
  22. hosts: test
  23. vars:
  24. http_port: "8000" # 定义httpd.conf中的变量和值
  25. tasks:
  26. - name: upload httpd.conf # 上传httpd.conf
  27. template:
  28. src: ./httpd.conf
  29. dest: /etc/httpd/conf/httpd.conf
  30. - name: restart httpd # 重启服务
  31. service:
  32. name: httpd
  33. state: restarted
  34. # 第一次执行trigger.yml,上传文件和重启服务两个任务的状态都是黄色changed
  35. [root@control ansible]# ansible-playbook trigger.yml
  36. # 第二次执行trigger.yml,上传文件的任务状态是绿色的ok,重启服务任务的状态是黄色changed
  37. [root@control ansible]# ansible-playbook trigger.yml
  38. # 既然配置文件没有改变,那么服务就不应该重启
  39. # 修改Playbook,只有配置文件变化了,才重启服务
  40. [root@control ansible]# vim trigger.yml
  41. ---
  42. - name: configure httpd
  43. hosts: test
  44. vars:
  45. http_port: "80"
  46. tasks:
  47. - name: upload httpd.conf
  48. template:
  49. src: ./httpd.conf
  50. dest: /etc/httpd/conf/httpd.conf
  51. notify: restart httpd # 通知restart httpd需要执行
  52. handlers:
  53. - name: restart httpd
  54. service:
  55. name: httpd
  56. state: restarted
  57. # 第一次运行Playbook,因为第1个任务是黄色的changed,所以handlers中的任务也被触发执行
  58. [root@control ansible]# ansible-playbook trigger.yml
  59. # 第二次运行Playbook,因为第1个任务是绿色的OK,也就不会再触发执行其他任务了
  60. [root@control ansible]# ansible-playbook trigger.yml

when条件

  • 只有满足某一条件时,才执行任务

  • 常用的操作符:

    • ==:相等
    • !=:不等
    • >:大于
    • <:小于
    • <=:小于等于
    • >=:大于等于
  • 多个条件或以使用and或or进行连接

  • when表达式中的变量,可以不使用{{}}

  1. # 当test组中的主机内存大于2G的时候,才安装mariadb-server
  2. [root@control ansible]# vim when1.yml
  3. ---
  4. - name: install mariadb
  5. hosts: test
  6. tasks:
  7. - name: install mariadb pkg
  8. yum:
  9. name: mariadb-server
  10. state: present
  11. when: ansible_memtotal_mb>2048
  12. # 如果目标主机没有2GB内存,则不会安装mariadb-server
  13. [root@control ansible]# ansible-playbook when1.yml
  14. # 多条件。系统发行版是RedHat8才执行任务
  15. # /etc/motd中的内容,将会在用户登陆时显示在屏幕上
  16. [root@control ansible]# vim motd
  17. _____________
  18. < hello world >
  19. -------------
  20. \ ^__^
  21. \ (oo)\_______
  22. (__)\ )\/\
  23. ||----w |
  24. || ||
  25. [root@control ansible]# vim when2.yml
  26. ---
  27. - name: when condition
  28. hosts: test
  29. tasks:
  30. - name: modify /etc/motd
  31. copy:
  32. dest: /etc/motd
  33. src: motd
  34. when: > # 以下三行合并成一行
  35. ansible_distribution == "RedHat"
  36. and
  37. ansible_distribution_major_version == "8"
  38. [root@control ansible]# ansible-playbook when2.yml

cowsay:

```shell [root@node1 ~]# yum install -y cowsay-3.04-4.el7.noarch.rpm [root@node1 ~]# cowsay hello world # 默认是奶牛形象 [root@node1 ~]# cowsay -l # 查看可用形象 [root@node1 ~]# cowsay -f sheep hello world

[root@node1 ~]# cowsay -l > ss.txt [root@node1 ~]# vim ss.txt # 删除第1行的说明 [root@node1 ~]# for i in $(cat ss.txt)

do echo “———————$i————————“ cowsay -f $i hello sleep 3 echo “————————————————“ done ```