Playbook

Playbook是一个不同于使用Ansible命令行执行方式的模式,其功能更强大灵活,简单来说,Playbook是一个非常简单的配置管理和多主机部署系统,不同于任何已经存在的模式,可作为一个适合部署复杂应用程序的基础

模块执行是幂等性的,因此Playbook执行也是幂等性的,多次执行结果相同

值得注意的是Playbook是通过YAML格式来进行描述定义的

YAML标记语言

JSON和YAML互转网址

YAML是一种表达资料序列的格式,由于参考了其他多张语言,所以具有很高的可读性,其特性如下:

  • 具有很好的可读性,易于实现
  • 表达能力强,扩展性好
  • 和脚本语言的交互性好
  • 有一个一致的信息模型
  • 可以基于流来处理

基本语法规则

  1. 大小写敏感
  2. 使用缩进表示层级关系
  3. 缩进时不允许使用Tab键,只允许使用空格。
  4. 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
  5. ‘#’表示注释

支持的数据结构

YAML 支持以下几种数据类型:

  • 对象:键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary)
  • 数组:一组按次序排列的值,又称为序列(sequence) / 列表(list)
  • 纯量(scalars):单个的、不可再分的值

YAML对象

对象键值对使用冒号结构表示 key: value,冒号后面一定要加一个空格

也可以使用 key:{key1: value1, key2: value2, …}

用缩进表示层级关系

  1. yum:
  2. name: httpd
  3. state: latest

YAML数组

- 开头的行表示构成一个数组:

  1. - A
  2. - B
  3. - C
  4. # ["A","B","C"]

多维数组

  1. key: [value1, value2, ...]

子成员是数组

  1. -
  2. - A
  3. - B
  4. - C
  5. # [["A","B","C"]]

复合结构

例如:

  1. languages:
  2. - Ruby
  3. - Perl
  4. - Python
  5. websites:
  6. YAML: yaml.org
  7. Ruby: ruby-lang.org
  8. Python: python.org
  9. Perl: use.perl.org

转为JSON为

  1. {
  2. languages: [ 'Ruby', 'Perl', 'Python'],
  3. websites: {
  4. YAML: 'yaml.org',
  5. Ruby: 'ruby-lang.org',
  6. Python: 'python.org',
  7. Perl: 'use.perl.org'
  8. }
  9. }

核心字段

  • hosts:执行的远程主机列表
  • tasks:任务,由模块定义操作列表
  • variables:内置变量或者自定义变量
  • templates:模板,模板文件一般是由Jinja2语言编写的
  • handlers:和nogity结合使用,为条件触发操作,满足条件则执行
  • roles:角色

官方示例剧本

  1. - name: update web servers # 剧本名称
  2. hosts: webservers # 远程主机列表
  3. remote_user: root # 指定远程用户
  4. tasks:
  5. - name: ensure apache is at the latest version # 安装httpd
  6. yum:
  7. name: httpd
  8. state: latest
  9. - name: write the apache config file # 编写httpd配置文件
  10. template:
  11. src: /srv/httpd.j2
  12. dest: /etc/httpd.conf
  1. - name: update db servers # 剧本名称
  2. hosts: databases # 远程主机列表
  3. remote_user: root # 指定远程用户
  4. tasks:
  5. - name: ensure postgresql is at the latest version # 安装postgresql
  6. yum:
  7. name: postgresql
  8. state: latest
  9. - name: ensure that postgresql is started # 启动postgresql
  10. service:
  11. name: postgresql
  12. state: started

简单案例

Apache部署

  • 修改主机清单文件
  1. [root@server1 ~]# vim /etc/ansible/hosts
  2. [server2]
  3. 192.168.31.20
  • 创建剧本配置文件
  1. [root@server1 ~]# mkdir /playbook/file -p
  2. [root@server1 ~]# vim /playbook/apache-virtualhost-port.yaml
  3. - name: Update web servers
  4. hosts: server2
  5. remote_user: root
  6. tasks:
  7. - name: ensure apache is the latest version # 安装httpd
  8. yum:
  9. name: httpd
  10. state: latest
  11. - name: copy site1.conf to apache web server # 创建httpd虚拟主机配置文件
  12. copy:
  13. src: /playbook/file/site1.conf
  14. dest: /etc/httpd/conf.d/site1.conf
  15. - name: create directory1 for apache web server # 创建httpd网站根目录
  16. file:
  17. name: /data/site1/
  18. state: directory
  19. - name: create directory2 for apache web server # 创建httpd网站根目录
  20. file:
  21. name: /data/site2/
  22. state: directory
  23. - name: write index.html # 编写index.html文件
  24. shell: echo "site1" > /data/site1/index.html && echo "site2" > /data/site2/index.html
  25. - name: start apache web server # 启动httpd文件
  26. service:
  27. name: httpd
  28. state: restarted
  29. - name: test virtual hosts # 测试
  30. shell: curl 192.168.31.20:8080 && curl 192.168.31.20:8090
  • 创建虚拟主机配置文件
  1. [root@server1 ~]# vim /playbook/file/site1.conf
  2. Listen 8080
  3. Listen 8090
  4. <Directory "/data/">
  5. Require all granted
  6. </Directory>
  7. <VirtualHost *:8080>
  8. DocumentRoot "/data/site1/"
  9. </VirtualHost>
  10. <VirtualHost *:8090>
  11. DocumentRoot "/data/site2/"
  12. </VirtualHost>
  • 检查并启动剧本
  1. [root@server1 ~]# cd /playbook
  2. [root@server1 playbook]# ansible-playbook apache-virtualhost-port.yaml --syntax-check
  3. [root@server1 playbook]# ansible-playbook apache-virtualhost-port.yaml

Anisble剧本 - 图1

  • 测试网站
  1. [root@server1 ~]# curl 192.168.31.20:8080
  2. site1
  3. [root@server1 ~]# curl 192.168.31.20:8090
  4. site2

Nginx部署

  • 修改主机清单文件
  1. [root@server1 ~]# vim /etc/ansible/hosts
  2. [server3]
  3. 192.168.31.30
  • 创建剧本配置文件
  1. [root@server1 ~]# vim /playbook/nginx-virtualhost-port.yaml
  2. - name: Update web servers
  3. hosts: server3
  4. remote_user: root
  5. tasks:
  6. - name: install epel # 安装扩展源
  7. yum:
  8. name: epel-release.noarch
  9. state: latest
  10. - name: ensure nginx is the latest version # 安装Nginx
  11. yum:
  12. name: nginx
  13. state: latest
  14. - name: copy site1.conf to nginx web server # 创建Nginx虚拟主机配置文件
  15. copy:
  16. src: /playbook/file/site2.conf
  17. dest: /etc/nginx/conf.d/site2.conf
  18. - name: create directory for nginx web server # 创建网站根目录
  19. file:
  20. name: /data
  21. state: directory
  22. - name: write index.html # 编写index.html
  23. shell: echo "nginx server" > /data/index.html
  24. - name: start nginx web server # 启动服务
  25. service:
  26. name: nginx
  27. state: restarted
  • 创建虚拟主机配置文件
  1. [root@server1 ~]# vim playbook/file/site2.conf
  2. server {
  3. listen 8080;
  4. server_name 192.168.31.30:8080;
  5. location /{
  6. root /data;
  7. index index.html;
  8. }
  9. }
  • 检查并启动剧本
  1. [root@server1 ~]# cd /playbook
  2. [root@server1 playbook]# ansible-playbook nginx-virtualhost-port.yaml --syntax-check
  3. [root@server1 playbook]# ansible-playbook nginx-virtualhost-port.yaml

Anisble剧本 - 图2

  • 测试网站
  1. [root@server1 ~]# curl 192.168.31.30:8080
  2. nginx server

剧本变量

变量的来源:

  • 远程主机的所有变量都可以通过ansible -m setup nodes命令来获取
  • 自定义变量
  • 优先级

    1. 通过命令行指定变量优先级
    2. /etc/ansible/hosts定义的变量(针对单个主机定义,针对主机组进行定义)
    3. playbook中定义的变量

常见系统变量:

  • 主机名: "{{ ansible_hostname }}"
  • inventory下面的所有主机和主机组信息:"{{ groups }}"
  • 操作系统版本: "{{ ansible_distribution }}" "{{ ansible_distribution_version }}"
  • 内核版本: "{{ ansible_kernel }}"
  • 系统位数: "{{ ansible_userspace_bits }}"
  • 网卡:"{{ ansible_eth0["device"] }}"
  • IP地址: "{{ ansible_eth0.ipv4.address}}"
  • 子网掩码: "{{ ansible_eth0.ipv4.netmask}}"

  • 总内存: "{{ ansible_memory_mb["real"]["total"] }}"

  • 内存空闲: "{{ ansible_memfree_mb }}"

Ansible handler

handler的作用

可以让某些任务不做一些不必要的重复工作,减少一些无谓的操作

比如说在某个剧本中的任务有:修改Nginx配置文件、重启Nginx服务、修改Nginx主页

那么就可以使用handler,在修改Nginx配置文件的下面加上一个notifynotify对应handlers下配置的任务(重启Nginx服务),然后只有当真的修改了Nginx配置文件后才会调用handler,即重启服务

否则假如只是修改了个主页文件,还要把所有任务执行一遍(包括重启服务),对于Nginx服务器来说岂不是很没必要

下面会举出这个例子

handler的特点

  • 在Ansible Playbook中,handler事实上也是个task,只不过这个task默认并不执行,只有在被触发时才执行
  • handler通过notify来监视某个或者某几个task,一旦task执行结果发生变化,则触发handler,执行相应操作
  • notify中定义内容一定要和handlers中定义的 - name 内容一样,这样才能达到触发的效果,否则会不生效
  • handler会在所有的play都执行完毕之后才会执行,并且handler下的任务只会执行一次
  • 任务表中的任务都是有状态的,也就是任务执行后的结果:changed或者ok,在Ansible中,只有在任务的执行状态为changed时,才会执行该任务调用的handler
  • handler是按照定义的顺序执行的(即在handlers下面写的顺序),而不是按照在任务中的调用顺序执行的
  1. - name: Update web servers
  2. hosts: server3
  3. remote_user: root
  4. - name: copy configuration file # 修改配置文件
  5. copy:
  6. src: /playbook/file/site2.conf
  7. dest: /etc/nginx/conf.d/site2.conf
  8. notify:
  9. - restart nginx web server
  10. - name: write index.html # 编写主页文件
  11. shell: echo "nginx server" > /data/index.html
  12. handlers:
  13. - name: restart nginx web server # 重启服务
  14. service:
  15. name: nginx
  16. state: restarted

剧本模板

Ansible模板介绍

  • 模板的本质是文本文件,内部嵌套有模板语言的脚本
  • 编写语言为Jinja2语法,由Python编写
  • 功能:将模板文件中的变量转换成对应的本地主机的确定值
  • 语法:

    • 字符串:使用单引号或者双引号代表字符串
    • 数字
    • 列表:使用中括号括起来表示的是列表[ ]
    • 元组:使用小括号表示元组( )
    • 字典:使用大括号表示字典{ }
    • 算数运算:+ - * / ………
    • 比较操作:== != > < ………
    • 逻辑运算:and or not

Jinja2语法

变量

  1. {{name}}

控制语句

  1. {% if A.safe %}
  2. A is safe.
  3. {% elif A.dead %}
  4. A is dead
  5. {% else %}
  6. A is okay
  7. {% endif %}

模板继承

父模板

  1. # base.html
  2. <html>
  3. <head>
  4. {% block head %}
  5. <title>
  6. {% block title %}
  7. {% end block %}
  8. </title>
  9. {% end block %}
  10. </head>
  11. <body>
  12. {% block body %}
  13. {% end block %}
  14. </body>
  15. </html>

继承模板

  1. {% extends 'base.html' %} # 继承base.html文件
  2. {% block head %}
  3. {{ super() }} # 用于获取原有的内容
  4. {% end block %}
  5. {% block title %}
  6. Index # 定制title部分的内容
  7. {% end block %}
  8. {% block body %}
  9. <h1>hello world</h1> # 定制body部分的内容
  10. {% end block %}

生成hosts解析文件

  • 创建模板文件/playbook/hosts.j2
  1. 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
  2. ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
  3. {% for host in groups.all %}
  4. {{hostvars[host].ansible_ens33.ipv4.address}} {{hostvars[host].ansible_hostname}}
  5. {% endfor %}
  • 创建剧本配置文件/playbook/hosts.yaml
  1. - name: Config hosts file
  2. hosts: all
  3. remote_user: root
  4. tasks:
  5. - name: copy hosts.j2 to group servers
  6. template:
  7. src: hosts.j2
  8. dest: /etc/hosts
  • 检查并运行剧本
  1. [root@server1 playbook]# ansible-playbook hosts.yaml --syntax-check
  2. [root@server1 playbook]# ansible-playbook hosts.yaml

Anisble剧本 - 图3

  • 查看hosts文件(server1/server2/server3)
  1. [root@server1 ~]# cat /etc/hosts
  2. 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
  3. ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
  4. 192.168.31.10 server1
  5. 192.168.31.20 server2
  6. 192.168.31.30 server3
  • 进行互ping测试
  1. [root@server1 ~]# ping server1
  2. [root@server1 ~]# ping server2
  3. [root@server1 ~]# ping server3

PS:

如果出现这种情况,是因为没有给这个主机设置免密登录导致的,给这台主机设置一下免密登录就可以了Anisble剧本 - 图4

生成Nginx配置文件

  • 创建模板文件/playbook/nginx.j2
  1. {% for vhost in nginx_vhosts %}
  2. server {
  3. listen {{ vhost.listen }}
  4. {% if vhost.server_name is defined %}
  5. server_name {{ vhost.server_name }}
  6. {% endif %}
  7. root {{ vhost.root }}
  8. }
  9. {% endfor %}
  • 创建剧本配置文件/playbook/nginx.yml
  1. - hosts: all
  2. remote_user: root
  3. vars:
  4. nginx_vhosts:
  5. - web1:
  6. listen: 8080
  7. root: "/data/web1/"
  8. - web2:
  9. listen: 8080
  10. server_name: "www.web2.com"
  11. root: "/data/web2/"
  12. - web3:
  13. listen: 8080
  14. server_name: "www.web3.com"
  15. root: "/data/web3/"
  16. tasks:
  17. - name: template config to
  18. template:
  19. src: nginx.j2
  20. dest: /etc/nginx/conf.d/nginx3.conf
  • 检查并运行剧本
  1. [root@server1 playbook]# ansible-playbook nginx.yaml --syntax-check
  2. [root@server1 playbook]# ansible-playbook nginx.yaml

Anisble剧本 - 图5

  • 查看由剧本创建的Nginx虚拟主机配置文件(server1/server2/server3)
  1. [root@server2 ~]# cat /etc/nginx/conf.d/nginx3.conf
  2. server {
  3. listen 8080
  4. root /data/web1/
  5. }
  6. server {
  7. listen 8080
  8. server_name www.web2.com
  9. root /data/web2/
  10. }
  11. server {
  12. listen 8080
  13. server_name www.web3.com
  14. root /data/web3/
  15. }

循环迭代

with_items(简单循环)

with_items是Playbook标准循环,可以用于迭代一个列表或字典,通过{{ item }}获取每次迭代的值

基于字符串列表

  1. - hosts: all
  2. remote_user: root
  3. tasks:
  4. - name: create rsyncd file
  5. copy: src={{ item }} dest=/tmp/{{ item }}
  6. with_items:
  7. - a
  8. - b
  9. - c
  10. - d

基于字典列表

  1. - hosts: all
  2. remote_user: root
  3. tasks:
  4. - name: add several users
  5. user: name={{ item.name }} state=present groups={{ item.groups }}
  6. with_items:
  7. - { name: 'testuser1' , groups: 'wheel'}
  8. - { name: 'testuser2' , groups: 'root' }

with_list(嵌套循环)

with_itemswith_list都可以用作简单循环,但是with_items不能用在嵌套循环,它会将列表展开拉平然后将元素一个一个输出,with_list则不会将嵌套列表拉平

  1. - hosts: all
  2. tasks:
  3. - name: print msg
  4. debug:
  5. msg: '{{ item }}'
  6. with_list:
  7. - [1,2,3]
  8. - [a,b]
  9. # 最后输出[1,2,3],[a,b]
  10. # 如果是with_items则是 1,2,3,a,b
  • 还有一个关键字with_flattened也是和with_items一样的,会将嵌套列表拉平
  • with_list只会处理最外层的列表,将最外层的列表中的每一项循环处理

with_together(合并对齐)

with_together会将每个小列表中的值对齐合并

  1. - hosts: all
  2. tasks:
  3. - name: print msg
  4. debug:
  5. msg: '{{ item }}'
  6. with_together:
  7. - [1,2,3]
  8. - [a,b,c]
  9. # 最后输出[1,a],[2,b],[3,c]
  10. # 如果没有写c,那么最后一个会是[3,null]

loop

Ansible 支持使用 loop 关键字对一组项目迭代任务,可以配置循环以利用列表中的各个项目、列表中的各个文件的内容、生成的数字序列或更为复杂任务

基于字符串列表

  1. - hosts: all
  2. tasks:
  3. - name: print users name
  4. debug:
  5. msg: '{{ item }}'
  6. loop:
  7. - tom
  8. - bob
  9. - alice
  10. # 或者
  11. - hosts: all
  12. vars:
  13. users:
  14. - tom
  15. - bob
  16. - alice
  17. tasks:
  18. - name: print users name
  19. debug:
  20. msg: '{{ item }}'
  21. loop: "{{ users }}"

基于字典列表

  1. - hosts: all
  2. tasks:
  3. - name: create users
  4. user:
  5. name: "{{ item.name }}"
  6. state: present
  7. groups: "{{ item.group }}"
  8. loop:
  9. - name: jane
  10. group: whell
  11. - name: joe
  12. group: root
  13. # 或者
  14. - hosts: all
  15. vars:
  16. users:
  17. - name: jane
  18. groups: teacher
  19. - name: joe
  20. groups: student
  21. tasks:
  22. - name: create users
  23. user:
  24. name: "{{ item.name }}"
  25. groups: "{{ item.groups }}"
  26. state: present
  27. loop: "{{ users }}"

剧本角色

介绍

角色(roles)是ansible自1.2版本开始引入的新特性,用于层次性,结构化地组织Playbook,分别将变量、文件、任务、模板及处理器放置于单独的目录中,并可以便捷地调用它们

角色的使用,让代码复用度提高,可以解决一些运维复杂的场景问题

当有多个角色时,可以将他们分别放于roles目录下的独立子目录中

初始化一个角色:ansible-galaxy init 角色名

目录说明

tasks目录:角色需要执行的主任务文件放置在此目录中,默认的主任务文件名为main.yml,当调用角色时,默认会执行main.yml文件中的任务;可以将其他需要执行的任务文件通过include的方式包含在tasks/main.yml文件中

handlers目录:当角色需要调用handlers时,默认会在此目录中的main.yml文件中查找对应的handlers

defaults目录:角色会使用的变量可以写入到此目录中的main.yml文件中,通常,defaults/main.yml文件中的变量都用于设置默认值

vars目录:角色会使用的变量可以写入到此目录中的main.yml文件中,看到这里你肯定会有疑问

PS:vars/main.yml文件和defaults/main.yml的区别:

defaults/main.yml文件中的变量的优先级是最低的,而vars/main.yml文件中的变量的优先级非常高

如果只是想提供一个默认的配置,那么可以把对应的变量定义在defaults/main.yml中,如果想要确保在调用角色时,使用的值就是指定的值,则可以将变量定义在vars/main.yml中,因为定义在vars/main.yml文件中的变量的优先级非常高,所以其值比较难以覆盖

meta目录:如果你想要赋予这个角色一些元数据,则可以将元数据写入到meta/main.yml文件中,这些元数据用于描述角色的相关属性,比如作者信息、角色主要作用等等,你也可以在meta/main.yml文件中定义这个角色依赖于哪些其他角色,或者改变角色的默认调用设定

templates目录: 角色相关的模板文件可以放置在此目录中,当使用角色相关的模板时,如果没有指定路径,会默认从此目录中查找对应名称的模板文件

files目录:角色可能会用到的其他文件可以放置在此目录中,比如,当你定义nginx角色时,需要配置https,那么相关的证书文件即可放置在此目录中

安装Httpd

  • 准备角色
  1. [root@server1 roles]# ansible-galaxy init apache
  2. - Role apache was created successfully
  • 编写角色主配置文件
  1. [root@server1 roles]# vim site.yml
  2. - name: Install Apache web server
  3. hosts: server3
  4. remote_user: root
  5. roles:
  6. - apache
  • 编写角色tasks里的main.yaml文件
  1. [root@server1 roles]# vim apache/tasks/main.yml
  2. ---
  3. # tasks file for apache
  4. - name: Install httpd # 安装httpd服务
  5. yum:
  6. name: httpd
  7. state: present
  8. - name: start httpd # 启动httpd服务
  9. service:
  10. name: httpd
  11. state: restarted
  12. - name: write conf file # 编写index.html
  13. copy:
  14. content: "hello apache\n"
  15. dest: "/var/www/html/index.html"
  • 检查并运行剧本
  1. [root@eagle roles]# ansible-playbook site.yaml --syntax-check
  2. [root@eagle tasks]# ansible-playbook site.yaml

Anisble剧本 - 图6

  • 验证结果
  1. [root@server1 roles]# curl 192.168.31.30
  2. hello apache

安装Halo博客

Halo是一个博客系统,官方网址https://halo.run/

使用Ansible去自动部署Halo博客系统需要准备的有:Java Nginx Halo

  • 准备角色
  1. [root@server1 ~]# cd /etc/ansible/roles/
  2. [root@server1 roles]# ansible-galaxy init halo
  3. - Role halo was created successfully
  4. [root@server1 roles]# ansible-galaxy init java
  5. - Role java was created successfully
  6. [root@server1 roles]# ansible-galaxy init nginx
  7. - Role nginx was created successfully
  • 编写剧本主配置文件site.yaml
  1. [root@server1 roles]# vim site.yml
  2. - name: Install Halo Blog
  3. hosts: server2
  4. remote_user: root
  5. strategy: free
  6. pre_tasks:
  7. - name: config nginx repo for centos7
  8. yum_repository:
  9. name: nginx
  10. description: nginx
  11. baseurl: http://nginx.org/packages/centos/$releasever/$basearch/
  12. gpgcheck: no
  13. roles:
  14. - nginx
  • 查看目录结构
  1. [root@server1 roles]# tree
  2. .
  3. ├── halo
  4. ├── defaults
  5. └── main.yml
  6. ├── files
  7. ├── handlers
  8. └── main.yml
  9. ├── meta
  10. └── main.yml
  11. ├── README.md
  12. ├── tasks
  13. └── main.yml
  14. ├── templates
  15. ├── tests
  16. ├── inventory
  17. └── test.yml
  18. └── vars
  19. └── main.yml
  20. ├── java
  21. ├── defaults
  22. └── main.yml
  23. ├── files
  24. ├── handlers
  25. └── main.yml
  26. ├── meta
  27. └── main.yml
  28. ├── README.md
  29. ├── tasks
  30. └── main.yml
  31. ├── templates
  32. ├── tests
  33. ├── inventory
  34. └── test.yml
  35. └── vars
  36. └── main.yml
  37. ├── nginx
  38. ├── defaults
  39. └── main.yml
  40. ├── files
  41. ├── handlers
  42. └── main.yml
  43. ├── meta
  44. └── main.yml
  45. ├── README.md
  46. ├── tasks
  47. └── main.yml
  48. ├── templates
  49. ├── tests
  50. ├── inventory
  51. └── test.yml
  52. └── vars
  53. └── main.yml
  54. └── site.yml

Nginx角色配置

  • 编写Nginx角色主配置剧本文件
  1. [root@server1 roles]# vim nginx/tasks/main.yml
  2. ---
  3. # tasks file for nginx
  4. - name: make sure nginx state is installed # 安装Nginx
  5. yum:
  6. name: nginx
  7. state: present
  8. - name: copy halo to nginx config file # 虚拟主机反向代理配置文件
  9. template:
  10. src: halo.conf
  11. dest: "/etc/nginx/conf.d/halo.conf"
  12. - name: make sure nginx service is running # 启动Nginx
  13. service:
  14. name: nginx
  15. state: restarted
  16. - name: make sure port is open # 等待端口启用
  17. wait_for:
  18. port: "{{ nginx_port }}"
  • 修改Nginx角色的设定及其依赖关系
  1. [root@server1 roles]# vim nginx/meta/main.yml
  2. dependencies:
  3. # List your role dependencies here, one per line. Be sure to remove the'[]' above,
  4. # if you add dependencies to this list.
  5. - role: java
  6. - role: halo
  • 编写Nginx角色的反向代理配置
  1. [root@server1 roles]# vim nginx/templates/halo.conf
  2. upstream halo{
  3. server 127.0.0.1:8090;
  4. }
  5. server {
  6. listen 80;
  7. listen [::]:80;
  8. server_name {{ halo_domain }};
  9. client_max_body_size 1024m;
  10. location / {
  11. proxy_pass http://halo;
  12. proxy_set_header HOST $host;
  13. proxy_set_header X-Forwarded-Proto $scheme;
  14. proxy_set_header X-Real-IP $remote_addr;
  15. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  16. }
  17. }

Java角色配置

  • 编写Java角色主配置剧本文件
  1. [root@server1 roles]# vim java/tasks/main.yml
  2. ---
  3. # tasks file for java
  4. - name: install java # 安装Java环境
  5. yum: name=java-11-openjdk state=installed

Halo角色配置

  • 编写Halo角色主配置剧本文件
  1. [root@server1 roles]# vim halo/tasks/main.yml
  2. ---
  3. # tasks file for halo
  4. - name: get halo # 下载halo源码包
  5. get_url:
  6. url: https://dl.halo.run/release/halo-1.4.11.jar
  7. dest: "{{ halopath }}"
  8. - name: add halo service file # 添加halo服务文件
  9. template:
  10. src: halo.service
  11. dest: "/etc/systemd/system/halo.service"
  12. - name: touch ~/.halo directory # 创建.halo文件夹
  13. file:
  14. path: ~/.halo
  15. state: directory
  16. - name: copy halo config file # 拷贝application.yaml文件
  17. template:
  18. src: application.yaml
  19. dest: "~/.halo/application.yaml"
  20. - name: start halo # 启动halo服务
  21. systemd:
  22. daemon_reload: yes
  23. name: halo
  24. state: started
  25. enabled: yes
  • 编写Halo角色变量配置文件
  1. [root@server1 roles]# cat halo/vars/main.yml
  2. ---
  3. # vars file for halo
  4. memory: 512m
  5. halo_port: 8090
  6. halopath: /root/halo.jar
  7. halo_domain: 192.168.31.20
  8. nginx_port: 80
  • 下载Halo的service文件并配置,下载保存位置需要和halo的tasks中的main.yml编写的位置对应
  1. [root@server1 roles]# wget https://dl.halo.run/config/halo.service -O halo/templates/halo.service
  2. [root@server1 roles]# vim halo/templates/halo.service
  3. [Unit]
  4. Description=Halo Service
  5. Documentation=https://docs.halo.run
  6. After=network-online.target
  7. Wants=network-online.target
  8. [Service]
  9. Type=simple
  10. User=root
  11. ExecStart=/usr/bin/java -server -Xms256m -Xmx256m -jar /root/halo.jar
  12. ExecStop=/bin/kill -s QUIT $MAINPID
  13. Restart=always
  14. StandOutput=syslog
  15. StandError=inherit
  16. [Install]
  17. WantedBy=multi-user.target
  • 下载Halo的application.yaml文件,下载保存位置需要和halo的tasks中的main.yml编写的位置对应
  1. [root@server1 roles]# wget https://dl.halo.run/config/application-template.yaml -O halo/templates/application.yaml

运行与测试

检查并运行site.yaml剧本

  1. [root@server1 roles]# ansible-playbook site.yaml --syntax-check
  2. [root@server1 roles]# ansible-playbook site.yaml

Anisble剧本 - 图7

  • 进入浏览器查看结果192.168.31.20

Anisble剧本 - 图8