😘作者简介:一名运维工作人员。
👊宣言:人生就是B(birth)和D(death)之间的C(choise),做好每一个选择。
🙏创作不易,动动小手给个点赞加关注吧,有什么意见评论区告诉我。
目录
[2) 编写剧本](#2) 编写剧本)
9)查看web2的配置文件,并用web浏览器访问web2的8090端口
一、剧本(playbook)
1、介绍
playbook是ansible用于配置,部署,和管理被控节点的剧本。通过playbook的详细描述,执行其中的tasks,可以让远端主机达到预期的状态。playbook是由一个或多个"play"组成的列表。 当对一台机器做环境初始化的时候往往需要不止做一件事情,这时使用playbook会更加适合。通过playbook你可以一次在多台机器执行多个指令。通过这种预先设计的配置保持了机器的配置统一,并很简单的执行日常任务。
ansible通过不同的模块实现相应的管理,管理的方式通过定义的清单文件(hosts)所管理的主机包括认证的方式连接的端口等。所有的功能都是通过调用不同的模块(modules)来完成不同的功能的。不管是执行单条命令还是play-book都是基于清单文件。
playbook格式:playbook由YMAL语言编写。YMAL格式是类似于JSON的文件格式,便于人理解和阅读,同时便于书写。
2、剧本组成
剧本的角色(play), 定义的是主机信息
剧本的任务(task), 定义的是具体任务
playbook组成部分:
1) 一个playbook有多个play组成
2) 一个play可以包含多个task任务
3) 简单理解为使用多个模块功能完成一件事
task:
Variables:变量
Templates:模板
Handlers:触发器,当 changed 状态条件满足时,(notify)触发执行的操作。
3、剧本编写规范
编写规范遵循yaml语法规范
缩进规范 两个空格表示一个缩进 不平级标题之间一定要开头相隔两个空格
注意: 缩进只能以空格表示 tab会报错。
字典规范 冒号后面必须要有空格
注意: 冒号结尾时不需要有空格 注释信息中冒号也不需要。
列表规范: 横线后面要有一个空格
4、实战(编写搭建nginx的剧本)
1)本机安装nginx准备配置文件
bash
#安装nginx这里我之前安装好的
[root@localhost ~]# yum install -y nginx
上次元数据过期检查:0:40:12 前,执行于 2023年07月26日 星期三 08时23分53秒。
软件包 nginx-1:1.22.1-2.el9.x86_64 已安装。
依赖关系解决。
无需任何处理。
完毕!
#创建一个存放nginx配置文件的目录,用作copy到远程服务器使用
[root@localhost ~]# mkdir /nginx
[root@localhost ~]# cp /etc/nginx/nginx.conf /nginx/
#更改nginx的默认端口,用作检测推送
[root@localhost ~]# sed -i '/listen/s/80/8090/g' /nginx/nginx.conf
2) 编写剧本
bash
[root@localhost ~]# vim nginx.yml
[root@localhost ~]# cat nginx.yml
- hosts: nginx
tasks:
- name: install nginx
yum: name=nginx state=present
- name: copy nginx conf
copy: src=/nginx/nginx.conf dest=/etc/nginx/nginx.conf
- name: start service
service: name=nginx state=started enabled=yes
剧本解释:
- hosts:指定需要执行剧本的主机
tasks:任务列表
- name:类似于注释
ansible模块相关命令
3)测试并执行剧本
ansible-playbook nginx.yml --syntax-check 检验语法
ansible-playbook nginx.yml --list-tasks 列出任务
ansible-playbook nginx.yml --list-hosts 列出主机
ansible-playbook nginx.yml 执行
测试剧本
bash
#测试剧本语法,无报错即可,报错根据报错提示去修改剧本
[root@localhost ~]# ansible-playbook nginx.yml --syntax-check
playbook: nginx.yml
#列出任务列表,展示有哪些任务需要执行
[root@localhost ~]# ansible-playbook nginx.yml --list-tasks
playbook: nginx.yml
play #1 (nginx): nginx TAGS: []
tasks:
install nginx TAGS: []
copy nginx conf TAGS: []
start service TAGS: []
#列出需要执行剧本的主机
[root@localhost ~]# ansible-playbook nginx.yml --list-hosts
playbook: nginx.yml
play #1 (nginx): nginx TAGS: []
pattern: ['nginx']
hosts (1):
web2
执行剧本
bash
[root@localhost ~]# ansible-playbook nginx.yml
PLAY [nginx] ************************************************************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************************************************
ok: [web2] #web2可以执行
TASK [install nginx] ****************************************************************************************************************************************************
changed: [web2] #web2安装了nginx
TASK [copy nginx conf] **************************************************************************************************************************************************
changed: [web2] #拷贝配置文件到web2成功
TASK [start service] ****************************************************************************************************************************************************
changed: [web2] #启动nginx成功
PLAY RECAP **************************************************************************************************************************************************************
web2 : ok=4 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
测试web2的nginx
用浏览器分别访问web2的80端口和8090端口。
80端口访问失败。
8090端口访问成功,说明剧本执行成功,web2的nginx配置文件是刚刚在ansible主机修改的配置文件。
5、使用剧本的变量(部署httpd)
在剧本中定义变量并使用变量,比如部署软件的时候,将软件的名字和配置文件的路径设置为变量,这样一个剧本只需要更改变量即可完成剧本的复用。
下面在web1使用剧本部署httpd,并且使用变量来测试。
1)本机安装httpd,准备配置文件
思路:准备一个httpd文件夹,将httpd配置文件拷贝到httpd文件夹备用,并且更改配置文件的端口为9090,以便检测远程主机的配置文件是否是推送过去的。
bash
[root@localhost ~]# mkdir /httpd
[root@localhost ~]# cp /etc/httpd/conf/httpd.conf /httpd/
[root@localhost ~]# sed -i '/^Listen/s/80/9090/g' /httpd/httpd.conf
2)编写剧本
定义变量:
vars:
- key:values
引用变量{{key}}
bash
[root@localhost ~]# vim http.yml
[root@localhost ~]# cat http.yml
- hosts: http
vars: #定义变量
- pkg: httpd #包名
- svc: httpd #服务名
tasks:
- name: install httpd
yum: name={{pkg}} state=present #引用包名变量
- name: cpoy http conf
copy: src=/httpd/httpd.conf dest=/etc/httpd/conf/httpd.conf
- name: start httpd service
service: name={{svc}} state=started enabled=yes #引用服务名变量
3)检测脚本
bash
[root@localhost ~]# ansible-playbook http.yml --syntax-check
[DEPRECATION WARNING]: Specifying a list of dictionaries for vars is deprecated in favor of specifying a dictionary. This feature will be removed in version 2.18.
Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
playbook: http.yml
4)执行剧本
bash
[root@localhost ~]# ansible-playbook http.yml
[DEPRECATION WARNING]: Specifying a list of dictionaries for vars is deprecated in favor of specifying a dictionary. This feature will be removed in version 2.18.
Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
PLAY [http] *************************************************************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************************************************
ok: [web1]
TASK [install httpd] ****************************************************************************************************************************************************
changed: [web1]
TASK [copy http conf] ***************************************************************************************************************************************************
changed: [web1]
TASK [start httpd service] **********************************************************************************************************************************************
changed: [web1]
PLAY RECAP **************************************************************************************************************************************************************
web1 : ok=4 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
5)使用web浏览器访问web1的9090端口
6、handlers
触发器,当 changed 状态条件满足时,(notify)触发执行的操作。
在需要执行触发器的位置设置
notify:标记
然后在定义触发器
handlers:
- name:标记
触发执行命令
注意:notify的标记要和handlers的标记要一致,这里是一一对应的。
在配置文件发生改变的时候,需要重启服务才能生效,所以一般在拷贝配置文件任务那里添加一个notify,在触发器位置执行重启服务器。
这里使用刚刚nginx的剧本来进行测试。
1)更改nginx的配置文件
bash
[root@localhost ~]# sed -i '/listen/s/8090/8888/g' /nginx/nginx.conf
将默认端口改为8888
2)编写剧本
bash
[root@localhost ~]# vim nginx.yml
[root@localhost ~]# cat nginx.yml
- hosts: nginx
tasks:
- name: install nginx
yum: name=nginx state=present
- name: copy nginx conf
copy: src=/nginx/nginx.conf dest=/etc/nginx/nginx.conf
notify: restart nginx service
- name: update index.html
shell: echo 'i am sure' > /usr/share/nginx/html/index.html
- name: start service
service: name=nginx state=started enabled=yes
handlers:
- name: restart nginx service
service: name=nginx state=restarted
3)测试剧本
bash
[root@localhost ~]# ansible-playbook nginx.yml --syntax-check
playbook: nginx.yml
4)运行剧本
5)使用web浏览器访问web2的8888端口
成功!!!
7、template
可以看作是一个编译过的模板文件,用来产生目标文本,传递Python的变量给模板去替换模板中的标记。
1)准备模板
将原本的配置文件重命名改成.j2文件作为配置文件模板。
然后更改模板内容。
在主机清单定义一个变量
bash
[root@localhost ~]# mv /nginx/nginx.conf /nginx/nginx.conf.j2
这里将模板文件的listen处改为使用变量ansible_http_port。
2)修改nginx剧本
bash
- hosts: nginx
tasks:
- name: install nginx
yum: name=nginx state=present
- name: nginx conf
template: src=/nginx/nginx.conf.j2 dest=/etc/nginx/nginx.conf
notify: restart nginx service
- name: update index.html
shell: echo 'i am sure' > /usr/share/nginx/html/index.html
- name: start service
service: name=nginx state=started enabled=yes
handlers:
- name: restart nginx service
service: name=nginx state=restarted
将原来的copy改为使用模板来推送配置文件
3)运行剧本并用查看web2的nginx的配置文件
8、tags模块
可以在一个playbook中为某个或某些任务定义"标签",在执行此playbook时通过ansible-playbook命令使用--tags选项能实现仅运行指定的tasks。
playbook还提供了一个特殊的tags为always。作用就是当使用always当tags的task时,无论执行哪一个tags时,定义有always的tags都会执行。
1)编写剧本(以创建目录为例)
bash
[root@localhost ~]# cat tags.yml
- hosts: nginx
tasks:
- name: mkdir dir1
file: name=/test/dir1 state=directory
tags:
- first
- name: mkdir dir2
file: name=/test/dir2 state=directory
- name: nkdir dir3
file: name=/test/dir3 state=directory
tags:
- always
这里给dir1任务打了first的标签 ,给dir2任务没有打标签,给dir3打了always的标签
2)运行剧本
看到运行提示,只有dir1和dir3被创建。
3)查看web2主机的/test目录
bash
[root@localhost ~]# ansible nginx -m shell -a 'ls /test'
web2 | CHANGED | rc=0 >>
dir1
dir3
发现只有dir1和dir3,因为在运行剧本的时候加了tags="first"所以剧本中只有打first标签的任务和打always的任务被执行,其余任务不会被执行。
二、roles角色扮演
1、介绍
roles则是在ansible中,playbooks的目录组织结构。
将代码或文件进行模块化,成为roles的文件目录组织结构,
易读,代码可重用,层次清晰。
2、实战(远程配置nginx)
1)目录结构
结构介绍:
- nginx 角色名
- files 普通文件,用来存放由 copy 模块或 script 模块调用的文件。
- handlers 触发器程序,此目录应当包含一个 main.yml 文件,用于定义此角色中触发条件时执行的动作。
- tasks 主任务,此目录应当包含一个 main.yml 文件,用于定义此角色的任务列表,此文件可以使用 include 包含其它的位于此目录的 task 文件。
- templates 金甲模板(有变量的文件),用来存放 j2 模板,template 模块会自动在此目录中寻找 j2 模板文件。
- vars 自定义变量,此目录应当包含一个 main.yml 文件,用于定义此角色用到的变量。
- f除开files目录和templates目录不需要创建main.yml文件,其余都要各个目录下都要创建
2)准备目录
bash
mkdir roles/nginx/{files,handlers,tasks,templates,vars} -p
touch roles/site.yaml roles/nginx/{handlers,tasks,vars}/main.yaml
[root@localhost ~]# tree roles/
roles/
├── nginx
│ ├── files
│ ├── handlers
│ │ └── main.yaml
│ ├── tasks
│ │ └── main.yaml
│ ├── templates
│ └── vars
│ └── main.yaml
└── site.yaml
6 directories, 4 files
3)准备file、template文件
制作nginx主页,以及金甲模板,并修改模板。
bash
[root@localhost ~]# cp /nginx/nginx.conf.j2 roles/nginx/templates/
[root@localhost ~]# echo "<h1>I am Sure Nginx<h1/>" > roles/nginx/files/index.html
[root@localhost ~]# tree roles/
roles/
├── nginx
│ ├── files
│ │ └── index.html
│ ├── handlers
│ │ └── main.yaml
│ ├── tasks
│ │ └── main.yaml
│ ├── templates
│ │ └── nginx.conf.j2
│ └── vars
│ └── main.yaml
└── site.yaml
4)编写任务
在tasks目录下的main.yaml写
bash
[root@localhost ~]# cat roles/nginx/tasks/main.yaml
tasks:
- name: install nginx
yum: name={{pkg}} state=present
- name: set nginx conf
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
notify: restart nginx service
- name: copy nginx index
copy: src=index.html dest=/usr/share/nginx/html/index.html
- name: start nginx service
service: name={{svc}} state=started enabled=yes
5)定义变量
在vars目录下的main.yaml编写。
bash
[root@localhost ~]# cat roles/nginx/vars/main.yaml
port: 8090
work_connection: 1024
pkg: nginx
svc: nginx
6)定义handlers
在handlers目录下的main.yaml编写。
bash
[root@localhost ~]# cat roles/nginx/handlers/main.yaml
- name: restart nginx service
service: name={{svc}} state=restarted
7)编写剧本
在site.yaml编写
剧本中的角色可以是多个,这里是以一个nginx为例。
bash
[root@localhost ~]# cat roles/site.yaml
- hosts: nginx
roles:
- nginx
8)测试并运行剧本
bash
[root@localhost ~]# ansible-playbook roles/site.yaml --syntax-check
playbook: roles/site.yaml
[root@localhost ~]# ansible-playbook roles/site.yaml
[WARNING]: Found variable using reserved name: port
PLAY [nginx] ************************************************************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************************************************
ok: [web2]
TASK [nginx : install nginx] ********************************************************************************************************************************************
ok: [web2]
TASK [nginx : set nginx conf] *******************************************************************************************************************************************
changed: [web2]
TASK [nginx : copy nginx index] *****************************************************************************************************************************************
changed: [web2]
TASK [nginx : start nginx service] **************************************************************************************************************************************
ok: [web2]
RUNNING HANDLER [nginx : restart nginx service] *************************************************************************************************************************
changed: [web2]
PLAY RECAP **************************************************************************************************************************************************************
web2 : ok=6 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
9)查看web2的配置文件,并用web浏览器访问web2的8090端口
bash
[root@localhost ~]# ansible nginx -m shell -a 'cat /etc/nginx/nginx.conf | grep listen'
web2 | CHANGED | rc=0 >>
listen 8090;
listen [::]:8090;
# listen 443 ssl http2;
# listen [::]:443 ssl http2;
[root@localhost ~]# ansible nginx -m shell -a 'cat /etc/nginx/nginx.conf | grep worker_connection'
web2 | CHANGED | rc=0 >>
worker_connections 1024;
web2的nginx的配置文件中发现端口为8090,worker_connections是1024,和刚刚设置的变量一致。
访问web2的8090端口展示的页面正是刚刚自己自定义的网络首页。