alex-rhel8.2 虚拟机
Anisble-练习环境说明
hostname:server1
ip:172.25.254.250/24
kiosk:redhat
root:Asimov
RHCE-RH294-172.25.254.250
control、node1-5
alice:alice
root:redhat
[kiosk@server1 ~]$ ip addr show
privbr0:
inet 172.25.250.254/24
inet 172.25.0.254/24
inet 172.25.254.254/24
inet 172.25.254.250/24 (xshell)
[root@server1 ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
172.25.0.254 server1.net0.example.com
172.25.0.25 alex01.net0.examle.com alex01
172.25.0.26 alex02.net0.examle.com alex02
172.25.254.254 classroom content classroom.example.com content.example.com
172.25.254.250 foundation0 foundation0.example.com study.lab0.example.com
172.25.254.100 control.lab0.example.com control con
172.25.254.101 node1.lab0.example.com node1 n1
172.25.254.102 node2.lab0.example.com node2 n2
172.25.254.103 node3.lab0.example.com node3 n3
172.25.254.104 node4.lab0.example.com node4 n4
172.25.254.105 node5.lab0.example.com node5 n5
172.25.0.220 registry.lab.example.com utility
[kiosk@server1 ~]$ rht-vmctl status all
Usage: rht-vmctl 子命令 虚拟机名称
子命令可以是:
start: 启动虚拟机
stop : 关闭虚拟机
reset: 重置虚拟机
虚拟机名称可以是:
red
blue
control
node1
node2
node3
node4
node5
[root@server1 ~]# virsh list --all
Id Name State
1 control running
2 node1 running
3 node2 running
4 node3 running
5 node4 running
6 node5 running
-
alex01 shut off
-
alex02 shut off
-
utility shut off
[root@server1 ~]# virsh start control
[root@server1 ~]# virsh shutdown control
切换用户
[kiosk@server1 ~]$ su - root
Password:Asimov
启动control 和 node1、node2、node3、node4、node5 六台服务器
[root@server1 ~]# rht-vmctl start control
Start control OK.
[root@server1 ~]# rht-vmctl start node1
Start node1 OK.
[root@server1 ~]# rht-vmctl start node2
Start node2 OK.
[root@server1 ~]# rht-vmctl start node3
Start node3 OK.
[root@server1 ~]# rht-vmctl start node4
Start node4 OK.
[root@server1 ~]# rht-vmctl start node5
Start node5 OK
[root@server1 ~]# ping control
[root@server1 ~]# ssh alice@control
alice@control’s password:alice
安装ansible
[alice@control ~]$ sudo dnf install -y ansible
查看 ansible 版本
[alice@control ~]$ ansible --version
ansible 2.8.5
测试验证 ansible 是否在工作(add-hoc临时命令)
测试 ansible ,表示ansible运行成功,参数 -m 表示 module 的意思
[alice@control ~]$ ansible -m ping localhost
localhost | SUCCESS => {
“changed”: false,
“ping”: “pong”
}
测试 control 到 node[1-5] 之间是否 SSH 免密
[alice@control ~]$ ssh alice@node1
[alice@node1 ~]$ exit
[alice@control ~]$ ssh alice@node2
[alice@node2 ~]$ exit
[alice@control ~]$ ssh alice@node3
[alice@node3 ~]$ exit
[alice@control ~]$ ssh alice@node4
[alice@node4 ~]$ exit
[alice@control ~]$ ssh alice@node5
[alice@node5 ~]$ exit
[alice@control ~]$
安装 ansible 后自动生成的文件
[alice@control ~]$ ls -l /etc/ansible/
-rw-r–r--. 1 root root 19980 Oct 11 2019 ansible.cfg
-rw-r–r--. 1 root root 1016 Oct 11 2019 hosts
drwxr-xr-x. 2 root root 6 Oct 11 2019 roles
参数解析
ansible.cfg -> 表示配置文件
hosts -> 表示资产清单文件
roles -> 表示角色
一般情况下,我们不使用默认的 hosts 作为清单文件,而是自定义一个清单,比如"alex-hosts"
在家目录创建 ansible 目录,并复制文件到家目录的 ansible
[alice@control ~]$ mkdir -p ~/ansible
[alice@control ~]$ cp -rfv /etc/ansible/ansible.cfg ansible/
[alice@control ~]$ cp -rfv /etc/ansible/hosts ansible/
当我们通过普通用户,进行远程连接的时候,需要做如下配置
[alice@control ~]$ vim ansible/ansible.cfg
15 inventory = /home/alice/ansible/alice-inventory
25 ask_pass = False
73 host_key_checking = False
107 remote_user = alice
341 [privilege_escalation]
342 become=True
343 become_method=sudo
344 become_user=root
345 become_ask_pass=False
/home/alice/ansible 目录创建 alice-inventory 文件
[alice@control ~]$ touch ansible/alice-inventory
编辑 alice-inventory 资产清单文件
[alice@control ~]$ vim ansible/alice-inventory
[network]
node1.lab0.example.com
[linux]
node[2:3].lab0.example.com
[os:children]
linux
[prod]
node[4:5].lab0.example.com
查看
[alice@control ~]$ ansible-inventory -i /home/alice/ansible/alice-inventory --list
ansible ping
[alice@control ~]$ ansible -m ping os -i ansible/alice-inventory
node2.lab0.example.com | SUCCESS => {
“ansible_facts”: {
“discovered_interpreter_python”: “/usr/libexec/platform-python”
},
“changed”: false,
“ping”: “pong”
}
node3.lab0.example.com | SUCCESS => {
“ansible_facts”: {
“discovered_interpreter_python”: “/usr/libexec/platform-python”
},
“changed”: false,
“ping”: “pong”
}
ansible 加载当前路径下的 ansible.cfg 配置文件
[alice@control ~]$ cd ansible/
[alice@control ansible]$ pwd
/home/alice/ansible
[alice@control ansible]$ ansible -m ping os
node2.lab0.example.com | SUCCESS => {
“ansible_facts”: {
“discovered_interpreter_python”: “/usr/libexec/platform-python”
},
“changed”: false,
“ping”: “pong”
}
node3.lab0.example.com | SUCCESS => {
“ansible_facts”: {
“discovered_interpreter_python”: “/usr/libexec/platform-python”
},
“changed”: false,
“ping”: “pong”
}
[alice@control ansible]$ pwd
/home/alice/ansible
[alice@control ansible]$ ansible -m ping network
yum 模块安装受管理节点的软件包
语法: ansible -m <主机或者主机组> -a “选项”
[alice@control ansible]$ ansible -m yum prod -a “name=httpd state=latest”
[alice@control ansible]$ ansible -m yum prod -a “name=httpd state=present”
[alice@control ansible]$ ansible -m yum prod -a “name=httpd state=absent”
参数解析
latest -> 更新为最新的版本
present -> 安装
absent -> remove 卸载
[alice@control ansible]$ ansible -m dnf prod -a “name=httpd state=latest”
[alice@control ansible]$ ansible -m dnf prod -a “name=httpd state=present”
[alice@control ansible]$ ansible -m dnf prod -a “name=httpd state=absent”
升级所有的包
[alice@control ansible]$ ansible -m dnf prod -a “name=’*’ state=latest”
组安装 yum groupinstall -y , 这个组内的所有包都会安装
name=’@Development tools’
[alice@control ansible]$ ansible -m dnf prod -a “name=’@Development tools’ state=latest”
shell 模块平时执行系统命令一样对主机组的节点进行命令的执行
[alice@control ansible]$ ansible -m shell prod -a “yum repolist -y all”
列出 ansible 已经支持的模块
[alice@control ansible]$ ansible-doc -l
[alice@control ansible]$ ansible-doc -l | grep -i yum
[alice@control ansible]$ ansible-doc -l | grep -i azure
查看有多少模块
[alice@control ansible]$ ansible-doc -l | wc -l
2834
查看模块的名称和内容
[alice@control ansible]$ ansible-doc -l | grep -i lvol
查看某一个模块的具体参数
[alice@control ansible]$ ansible-doc -s yum
##安装BaseOS软件仓库
[alice@control ansible]$ ansible -m yum_repository prod -a “baseurl=http://study.lab0.example.com/rhel8.2/BaseOS enabled=true file=‘BaseOS’ name=‘BaseOS’ gpgcheck=false description=‘This is BaseOS repofile’”
##安装AppStream软件仓库
[alice@control ansible]$ ansible -m yum_repository prod -a “baseurl=http://study.lab0.example.com/rhel8.2/AppStream enabled=true file=‘AppStream’ name=‘AppStream’ gpgcheck=false description=‘This is AppStream repofile’”
查看 /etc/yum.repos.d/ 目录内容
[alice@control ansible]$ ansible -m shell prod -a “ls -l /etc/yum.repos.d/”
ansible 方式通过 yum 模块,安装 httpd 服务
[alice@control ansible]$ ansible -m yum prod -a “name=httpd state=present”
ansible 方式通过 shell 模块,查看 httpd 信息
[alice@control ansible]$ ansible -m shell prod -a “yum -y info httpd”
安装BaseOS软件仓库,放在同一个 repo 文件中,通过 file 属性指定
[alice@control ansible]$ ansible -m yum_repository prod -a “baseurl=http://study.lab0.example.com/rhel8.2/BaseOS enabled=true file=‘alex’ name=‘BaseOS’ gpgcheck=false description=‘This is BaseOS repofile’”
[alice@control ansible]$ ansible -m yum_repository prod -a “baseurl=http://study.lab0.example.com/rhel8.2/AppStream enabled=true file=‘alex’ name=‘AppStream’ gpgcheck=false description=‘This is AppStream repofile’”
发现 BaseOS 和 AppStream 都在同一个文件
[alice@control ansible]$ ansible -m shell prod -a “cat /etc/yum.repos.d/alex.repo”
查看 ansible 文档模块
[alice@control ansible]$ ansible-doc -l | grep -i copy
查看 ansible copy 模块的具体参数
[alice@control ansible]$ ansible-doc -s copy
查看管理节点(control)的文件,ansible.repo
[alice@control ansible]$ ls -l /etc/yum.repos.d/
-rw-r–r--. 1 root root 81 Oct 30 2020 ansible.repo
-rw-r–r--. 1 root root 358 Oct 30 2020 redhat.repo
-rw-r–r--. 1 root root 179 Oct 30 2020 rhel8.repo
把管理节点的文件拷贝到被管理节点
control 拷贝到 node4 和 node5 节点
[alice@control ansible]$ ansible -m copy prod -a “src=/etc/yum.repos.d/ansible.repo dest=/etc/yum.repos.d/”
查看 node4 和 node5 被管理节点的 yum 状态
[alice@control ansible]$ ansible -m shell prod -a “yum repolist -y all”
copy 模块不一定非得是 src属性,可以没有源文件,content 属性表示内容,放到目标文件,\n表示换行
这是一种覆盖的方式,类似于重定向的 > 是覆盖的方式
[alice@control ansible]$ ansible -m copy prod -a “content=‘I Love \nLinux’ dest=/opt/alex.txt”
[alice@control ansible]$ ansible -m copy prod -a “content=‘I Love \nSpark’ dest=/opt/alex.txt”
[alice@control ansible]$ ansible -m copy prod -a “content=‘I Love \nScala\n’ dest=’/opt/alex.txt’ owner=‘alex’ group=‘alex’ mode=‘0550’ setype=‘httpd_sys_content_t’”
参数解析
owner: 属主
group: 属组
mode: 权限
通过 shell 模块查看
[alice@control ansible]$ ansible -m shell prod -a “cat /opt/alex.txt”
拷贝内容到目标文件,并设置文件类型
[alice@control ansible]$ ansible -m copy prod -a “content=‘hello,alex\nSpark\n’ dest=’/var/www/html/index.html’ mode=‘0550’ setype=‘httpd_sys_content_t’”
查看文件类型
[alice@control ansible]$ ansible -m shell prod -a “ls -lZ /var/www/html/index.html”
node4.lab0.example.com | CHANGED | rc=0 >>
-r-xr-x—. 1 root root system_u:object_r:httpd_sys_content_t:s0 17 Nov 27 16:22 /var/www/html/index.html
node5.lab0.example.com | CHANGED | rc=0 >>
-r-xr-x—. 1 root root system_u:object_r:httpd_sys_content_t:s0 17 Nov 27 16:22 /var/www/html/index.html
启动 httpd 服务,并设置开机自动启动
[alice@control ansible]$ ansible -m service prod -a “name=‘httpd’ enabled=‘yes’ state=‘started’”
state 状态有 started、stoped、restarted、reloaded
重启 httpd 服务
[alice@control ansible]$ ansible -m service prod -a “name=‘httpd’ state=‘restarted’”
赋予权限
[alice@control ansible]$ ansible -m shell prod -a "chmod -R 755 /var/www/html/index.html
访问
[alice@control ansible]$ ansible -m shell prod -a “curl -l http://127.0.0.1/”
设置 SELinux 安全性上下文
[alice@control ansible]$ ansible -m copy prod -a “content=‘hello,world\n’ dest=’/opt/a.txt’ owner=‘alex’ group=‘alice’ mode=‘755’ setype=‘httpd_sys_content_t’”
参数解析
owner:属主
group:属组
mode:权限
查看
[alice@control ansible]$ ansible -m shell prod -a “ls -lZ /opt/”
创建一个连接文件,测试未看到效果
[alice@control ansible]$ ansible -m copy prod -a “src=’/opt/module/control.file’ dest=’/mnt/test1’ follow=‘yes’”
file
[alice@control ansible]$ ansible -m file prod -a “path=’/opt/a.txt’ owner=‘alice’ group=‘alice’ mode=‘666’ setype=‘samba_share_t’”
参数解析
path:目标文件
owner:属主
group:属组
mode:权限
setype:修改 SELinux 的安全性上下文
查看
[alice@control ansible]$ ansible -m shell prod -a “ls -lZ /opt/”
state=‘touch’ 表示创建文件
[alice@control ansible]$ ansible -m file prod -a “path=’/opt/software’ owner=‘alice’ group=‘alice’ mode=‘666’ setype=‘samba_share_t’ state=‘touch’”
state=‘directory’ 表示创建目录
[alice@control ansible]$ ansible -m file prod -a “path=’/opt/soft/ware’ owner=‘alice’ group=‘alice’ mode=‘666’ setype=‘samba_share_t’ state=‘directory’”
[alice@control ansible]$ ansible -m file prod -a " src=’/mnt/test1’ path=’/opt/soft/test1’ owner=‘alice’ group=‘alice’ mode=‘666’ setype=‘samba_share_t’ state=‘link’"
state=‘link’ 表示软连接
state=‘hard’ 表示硬连接
当 state 表示为 link 或者 hard 的时候,需要指定 src属性
这里的 src 和 path 都表示 prod 组中的,不是 control 服务器
fetch -> 从被管理节点上拷贝文件到控制节点上
[alice@control ansible]$ ansible -m fetch prod -a “src=’/mnt/test1’ dest=’/home/alice/’”
[alice@control ansible]$ ansible -m fetch prod -a “src=’/mnt/test1’ dest=’/home/alice/’ flat=‘yes’”
参数解析
flat=‘yes’ 不拷贝被管理节点的目录结构
src=拷贝那个文件,这时候代表被管理节点
dest=目标路径,放到那个目录下面,这时候代表管理节点
lineinfile -> 最主要的功能在于替换
[alice@control ansible]$ ansible -m lineinfile prod -a “path=’/etc/sysconfig/selinux’ regexp=’^SELINUX=’ line=‘SELINUX=disabled’”
参数解析
path=’/etc/sysconfig/selinux’ 表示你要修改那个文件
regexp=’^SELINUX=’ 使用正则表达式的方式来匹配你要修改哪一行
line= 你要替换的内容
查看
[alice@control ansible]$ ansible -m shell prod -a “cat /etc/sysconfig/selinux”
参数 state=‘absent’ 的时候,表示删除,删除匹配的行
[alice@control ansible]$ ansible -m lineinfile prod -a “path=’/etc/sysconfig/selinux’ regexp=’^SELINUX=’ state=‘absent’”
insertbefore/insertafter=’^SELINUX=’ 使用正则表达式,来匹配行
insertbefore 在匹配的行之前插入内容
[alice@control ansible]$ ansible -m lineinfile prod -a “path=’/etc/sysconfig/selinux’ state=‘present’ insertbefore=’^SELINUX=’ line=‘I think i am right’”
insertafter 在匹配的行之后插入内容
[alice@control ansible]$ ansible -m lineinfile prod -a “path=’/etc/sysconfig/selinux’ state=‘present’ insertafter=’^SELINUX=’ line=‘I think i am after’”
查看
[alice@control ansible]$ ansible -m shell prod -a “cat /etc/sysconfig/selinux”
I think i am right
SELINUX=disabled
I think i am after
create=‘yes’ 在文件的末尾添加内容
[alice@control ansible]$ ansible -m lineinfile prod -a “path=’/etc/sysconfig/selinux’ line=‘qwe\nasd’ create=‘yes’”
查看
[alice@control ansible]$ ansible -m shell prod -a “cat /etc/sysconfig/selinux”
group 模块 -> 创建组
[alice@control ansible]$ ansible -m group prod -a “name=‘alexmk’ state=‘present’”
查看
[alice@control ansible]$ ansible -m shell prod -a “cat /etc/group”
group 模块 -> 删除组
[alice@control ansible]$ ansible -m group prod -a “name=‘alexmk’ state=‘absent’”
查看
[alice@control ansible]$ ansible -m shell prod -a “cat /etc/group”
user 模块 添加用户
[alice@control ansible]$ ansible -m user prod -a “name=‘testk’ state=‘present’”
参数解析
name -> 用户名
state=‘present’ 表示添加用户
查看
[alice@control ansible]$ ansible -m shell prod -a “cat /etc/passwd”
[alice@control ansible]$ ansible -m shell prod -a “ls -l /home/”
user 模块 删除用户
[alice@control ansible]$ ansible -m user prod -a “name=‘testk’ state=‘absent’ remove=‘yes’”
参数解析
state=‘absent’ 表示删除用户
remove=‘yes’ 表示删除用户的家目录
user 模块指定更多属性
[alice@control ansible]$ ansible -m user prod -a “name=‘testa’ state=‘present’ uid=‘1009’ group=‘alex’ comment=‘create a user’ shell=’/sbin/nologin’”
参数解析
name=‘testa’ 指定添加用户的用户名
state=‘present’ present表示添加 ,absent表示删除
uid=‘1009’ 指定uid
group=‘alex’ 指定所属组
groups=‘alice’ 指定的是附加组
comment=‘create a user’ 添加描述
shell=’/sbin/nologin’ 添加shell类型,此时这个用户的shell类型是不能登陆的
查看
[alice@control ansible]$ ansible -m shell prod -a “id testa”
node5.lab0.example.com | CHANGED | rc=0 >>
uid=1009(testa) gid=1001(alex) groups=1001(alex)
node4.lab0.example.com | CHANGED | rc=0 >>
uid=1009(testa) gid=1001(alex) groups=1001(alex)
groups=‘alice’ 指定的是附加组
[alice@control ansible]$ ansible -m user prod -a “name=‘testa’ state=‘present’ groups=‘alice’”
查看
[alice@control ansible]$ ansible -m shell prod -a “id testa”
node5.lab0.example.com | CHANGED | rc=0 >>
uid=1009(testa) gid=1001(alex) groups=1001(alex),1000(alice)
node4.lab0.example.com | CHANGED | rc=0 >>
uid=1009(testa) gid=1001(alex) groups=1001(alex),1000(alice)
与防火墙有关的模块
[alice@control ansible]$ ansible -m firewalld prod -a “zone=‘home’ source=‘172.25.250.0/24’ state=‘enabled’ permanent=‘yes’ immediate=‘yes’”
参数解析
zone=‘home’ 要关联的 zone 名
source=‘172.25.250.0/24’ 那个源关联 zone 名
state=‘enabled’ 启动这个规则
permanent=‘yes’ 永久生效
immediate=‘yes’ 立即生效
防火墙->配置基本规则
[alice@control ansible]$ ansible -m firewalld prod -a “service=‘http’ state=‘enabled’ permanent=‘yes’ immediate=‘yes’”
[alice@control ansible]$ ansible -m firewalld prod -a “service=‘http’ state=‘disabled’ permanent=‘yes’ immediate=‘yes’ zone=‘home’”
参数解析
state=‘disabled’ 表示不启动这个规则
与系统命令有关的模块
[alice@control ansible]$ ansible -m shell prod -a “df -TH”
与网络工具有关的模块
[alice@control ~]$ ansible -m get_url prod -a “url=‘http://content.example.com/ks/rh294-serverarc.local’ dest=’/mnt’ mode=‘0644’”
参数解析
url:资源路径
dest:存放路径
mode:权限
[alice@control ansible]$ ansible -m uri prod -a “url=‘http://content.example.com’”
uri:用户 和 web http 进行交互
[alice@control ansible]$ ansible -m shell prod -a “ip addr show”
day09 ============================================================================================================================ day09
Playbook
查看资产清单
[alice@control ansible]$ ansible-inventory --list
[alice@control ansible]$ ansible --list all
[alice@control ansible]$ cat alice-inventory
[network]
node1.lab0.example.com
[linux]
node[2:3].lab0.example.com
[os:children]
linux
[prod]
node[4:5].lab0.example.com
查看模块
[alice@control ansible]$ ansible-doc -l | grep -i yum
查看某一个模块的具体参数
[alice@control ansible]$ ansible-doc -s yum_repository
打开浏览器
[root@server1 ~]# firefox
查看主机名称
[alice@control ~]$ hostnamectl
查看yum repo文件
[alice@control ~]$ cat /etc/yum.repos.d/rhel8.repo
[appstream]
name=appstream
baseurl=http://study.lab0.example.com/rhel8.2/AppStream
gpgcheck=0
[baseos]
name=baseos
baseurl=http://study.lab0.example.com/rhel8.2/BaseOS
gpgcheck=0
[alice@control ansible]$ pwd
/home/alice/ansible
[alice@control ansible]$ touch yum.sh
[alice@control ansible]$ chmod 755 yum.sh
[alice@control ansible]$ vim yum.sh
:set paste 进入粘贴模式
i
#!/bin/bash
ansible -m yum_repository all -a “name=‘EX294_BASE’ file=‘EX294_BASE’ description=‘EX294 base software’ baseurl=‘http://content.example.com/rhel8.2/BaseOS’ gpgcheck=‘yes’ gpgkey=‘http://content.example.com/rhel8.2/RPM-GPG-KEY-redhat-release’ enabled=‘yes’”
ansible -m yum_repository all -a “name=‘EX294_STREAM’ file=‘EX294_STREAM’ description=‘EX294 stream software’ baseurl=‘http://content.example.com/rhel8.2/AppStream’ gpgcheck=‘yes’ gpgkey=‘http://content.example.com/rhel8.2/RPM-GPG-KEY-redhat-release’ enabled=‘yes’”
ansible -m shell all -a “rpm --import http://content.example.com/rhel8.2/RPM-GPG-KEY-redhat-release”
查看并验证
[alice@control ansible]$ ansible -m shell all -a “ls -l /etc/yum.repos.d/”
[alice@control ansible]$ ansible -m shell all -a “yum repolist --all”
[alice@control ansible]$ ansible -m shell all -a “cat /etc/yum.repos.d/EX294*”
创建 yml 文件
[alice@control ansible]$ touch test.yml
编辑 yml 文件
[alice@control ansible]$ vim test.yml
- name: this is a test yml file
hosts: network,os,prod
tasks:- name: test install vsftpd package
yum:
name: vsftpd
state: latest
- name: test install vsftpd package
查看 ansible-playbook 帮助文档
[alice@control ansible]$ ansible-playbook --help
通过 --syntax-check 参数,检查 yml 文件语法是否有问题
[alice@control ansible]$ ansible-playbook --syntax-check test.yml
playbook: test.yml
通过 -C 参数,进行预执行测试,不是真的执行
#空运行,确认模块的参数、执行的效果是否达到我们的预期
[alice@control ansible]$ ansible-playbook -C test.yml
检查是否有安装上
[alice@control ansible]$ ansible -m shell network -a “yum info -y vsftpd”
#真正的执行playbook
[alice@control ansible]$ ansible-playbook test.yml
再次检查是否有安装上
[alice@control ansible]$ ansible -m shell network -a “yum info -y vsftpd”
#设置vim支持对yaml格式的识别以及格式上的自动对齐。
[alice@control ansible]$ vim ~/.vimrc
autocmd FileType yaml setlocal ai ts=2 sw=2 et
编写一个简单的playbook
[alice@control ansible]$ touch adduser.yml
[alice@control ansible]$ vim adduser.yml
检查语法
[alice@control ansible]$ ansible-playbook --syntax-check adduser.yml
假执行
[alice@control ansible]$ ansible-playbook -C adduser.yml
真执行
[alice@control ansible]$ ansible-playbook -C adduser.yml
查看验证
[alice@control ansible]$ ansible -m shell prod -a “id alex123”
编写一个较为复杂的 playbook
在 node[1:5] 主机组中,安装 httpd 服务,并且配置防火墙等等操作
1)任务安装包
2)给一个页面文件
3)8080 端口访问,修改配置文件
4)防火墙
[alice@control ansible]$ touch http.yml
[alice@control ansible]$ vim http.yml
- name: httpd
hosts: network,os,prod
tasks:-
name: install httpd package
yum:
name: httpd
state: latest -
name: web content
copy:
content: “Test first playbook\n”
dest: /var/www/html/index.html
setype: httpd_sys_content_t
mode: 0666 -
name: modify httpd configurations
lineinfile:
path: /etc/httpd/conf/httpd.conf
regexp: ^Listen
line: “Listen 8080”
state: present -
name: start firewalld service
service:
name: firewalld
enabled: true
state: started -
name: modify firewalld rule
firewalld:
port: 8080/tcp
immediate: yes
permanent: yes
state: enabled -
name: start httpd service
service:
name: httpd
enabled: true
state: started
-
检查语法
[alice@control ansible]$ ansible-playbook --syntax-check http.yml
playbook: http.yml
空执行,假执行,做检查使用
[alice@control ansible]$ ansible-playbook -C http.yml
真执行
[alice@control ansible]$ ansible-playbook http.yml
查看并验证
[alice@control ansible]$ ansible -m shell network -a “systemctl status httpd”
[alice@control ansible]$ ansible -m shell network -a “firewall-cmd --list-all”
[alice@control ansible]$ touch install.yml
[alice@control ansible]$ vim install.yml
- name: this is a test yml file
hosts: network,os,prod
tasks:-
name: test install vsftpd package
yum:
name: vsftpd
state: latest -
name: start vsftpd service
service:
name: vsftpd
state: started
enabled: yes -
name: start firewalld service
service:
name: firewalld
state: started
enabled: yes -
name: modify firewalld port
firewalld:
port: 21/tcp
permanent: yes
immediate: yes
state: enabled
-
检查语法
[alice@control ansible]$ ansible-playbook --syntax-check install.yml
空执行,假执行
[alice@control ansible]$ ansible-playbook -C install.yml
真执行
[alice@control ansible]$ ansible-playbook install.yml
验证
[alice@control ansible]$ ansible -m shell network -a “systemctl status vsftpd”
[alice@control ansible]$ ansible -m shell network -a “firewall-cmd --list-all”
变量1 -> 在 playbook 中定义变量
[alice@control ansible]$ cp install.yml install-vars.yml
[alice@control ansible]$ vim install-vars.yml
- name: this is a test yml file
hosts: network,os,prod
vars:
package_name: httpd
service_name: httpd
service_port: 80
tasks:-
name: install httpd package
yum:
name: “{{ package_name }}”
state: latest -
name: start httpd service
service:
name: “{{ service_name }}”
state: started
enabled: yes -
name: start firewalld service
service:
name: firewalld
state: started
enabled: yes -
name: modify firewalld port
firewalld:
port: “{{ service_port }}/tcp”
permanent: yes
immediate: yes
state: enabled
-
检查语法
[alice@control ansible]$ ansible-playbook --syntax-check install-vars.yml
空执行,假执行
[alice@control ansible]$ ansible-playbook -C install-vars.yml
真执行
[alice@control ansible]$ ansible-playbook install-vars.yml
查看并验证
[alice@control ansible]$ ansible -m shell network -a “systemctl status httpd”
[alice@control ansible]$ ansible -m shell network -a “firewall-cmd --list-all”
变量2 -> 在 Playbook 外部中加载变量文件
[alice@control ansible]$ touch packages.yml
[alice@control ansible]$ vim packages.yml
- package_name: httpd
service_name: httpd
service_port: 80
[alice@control ansible]$ cp install-vars.yml install-vars2.yml
[alice@control ansible]$ vim install-vars2.yml
- name: this is a test yml file
hosts: network,os,prod
vars_files:-
/home/alice/ansible/packages.yml
tasks: -
name: install httpd package
yum:
name: “{{ package_name }}”
state: latest -
name: start httpd service
service:
name: “{{ service_name }}”
state: started
enabled: yes -
name: start firewalld service
service:
name: firewalld
state: started
enabled: yes -
name: modify firewalld port
firewalld:
port: “{{ service_port }}/tcp”
permanent: yes
immediate: yes
state: enabled
-
检查语法
[alice@control ansible]$ ansible-playbook --syntax-check install-vars2.yml
空执行,假执行
[alice@control ansible]$ ansible-playbook -C install-vars2.yml
真执行
[alice@control ansible]$ ansible-playbook install-vars2.yml
查看并验证
[alice@control ansible]$ ansible -m shell network -a “systemctl status httpd”
[alice@control ansible]$ ansible -m shell network -a “firewall-cmd --list-all”
变量3 -> 在执行剧本的时候,定义变量
[alice@control ansible]$ cp install-vars2.yml install-vars3.yml
[alice@control ansible]$ vim install-vars3.yml
- name: this is a test yml file
hosts: network,os,prod
tasks:-
name: install httpd package
yum:
name: “{{ package_name }}”
state: latest -
name: start httpd service
service:
name: “{{ service_name }}”
state: started
enabled: yes -
name: start firewalld service
service:
name: firewalld
state: started
enabled: yes -
name: modify firewalld port
firewalld:
port: “{{ service_port }}/tcp”
permanent: yes
immediate: yes
state: enabled
-
检查语法
[alice@control ansible]$ ansible-playbook --syntax-check install-vars3.yml
空执行,假执行
[alice@control ansible]$ ansible-playbook -e package_name=httpd -e service_name=httpd -e service_port=83 -C install-vars3.yml
真执行
[alice@control ansible]$ ansible-playbook -e package_name=httpd -e service_name=httpd -e service_port=82 install-vars3.yml
查看并验证
[alice@control ansible]$ ansible -m shell network -a “systemctl status httpd”
[alice@control ansible]$ ansible -m shell network -a “firewall-cmd --list-all”
变量3 -> 在执行剧本的时候,定义变量 -> 安装 mariadb
[alice@control ansible]$ vim install-vars3.yml
- name: this is a test yml file
hosts: network,os,prod
tasks:-
name: install {{ package_name }} package
yum:
name: “{{ package_name }}”
state: latest -
name: start {{ service_name }} service
service:
name: “{{ service_name }}”
state: started
enabled: yes -
name: start firewalld service
service:
name: firewalld
state: started
enabled: yes -
name: modify firewalld port
firewalld:
port: “{{ service_port }}/tcp”
permanent: yes
immediate: yes
state: enabled
-
检查语法
[alice@control ansible]$ ansible-playbook --syntax-check install-vars3.yml
空执行,假执行
[alice@control ansible]$ ansible-playbook -e package_name=mariadb-server -e service_name=mariadb -e service_port=3306 -C install-vars3.yml
真执行
[alice@control ansible]$ ansible-playbook -e package_name=mariadb-server -e service_name=mariadb -e service_port=3306 install-vars3.yml
查看并验证
[alice@control ansible]$ ansible -m shell network -a “systemctl status mariadb”
[alice@control ansible]$ ansible -m shell network -a “firewall-cmd --list-all”
[alice@control ansible]$ ansible -m shell network -a “ss -tunpa | grep 3306”
变量4 -> 在 inventory 资产清单文件内定义变量
[alice@control ansible]$ vim alice-inventory
[network]
node1.lab0.example.com
[linux]
node[2:3].lab0.example.com
[os:children]
linux
[prod]
node[4:5].lab0.example.com
[network:vars]
package_name=httpd
service_name=httpd
service_port=80
[alice@control ansible]$ cp install-vars3.yml install-vars4.yml
[alice@control ansible]$ vim install-vars4.yml
- name: this is a test yml file
hosts: network,os,prod
tasks:-
name: install {{ package_name }} package
yum:
name: “{{ package_name }}”
state: latest
when: inventory_hostname in groups[‘network’] -
name: start {{ service_name }} service
service:
name: “{{ service_name }}”
state: started
enabled: yes
when: inventory_hostname in groups.network -
name: start firewalld service
service:
name: firewalld
state: started
enabled: yes
when: inventory_hostname in groups[‘network’] -
name: modify firewalld port
firewalld:
port: “{{ service_port }}/tcp”
permanent: yes
immediate: yes
state: enabled
when: inventory_hostname in groups[‘network’]
-
检查语法
[alice@control ansible]$ ansible-playbook --syntax-check install-vars4.yml
空执行,假执行
[alice@control ansible]$ ansible-playbook -C install-vars4.yml
真执行
[alice@control ansible]$ ansible-playbook install-vars4.yml
查看并验证
[alice@control ansible]$ ansible -m shell network -a “systemctl status httpd”
[alice@control ansible]$ ansible -m shell network -a “firewall-cmd --list-all”
#when条件 -> 筛选主机组
when: inventory_hostname in groups.network
when: inventory_hostname in groups[‘network’]
管理机密文件 -> ansible-vault
[alice@control ansible]$ ansible-vault -h
[alice@control ansible]$ ansible-vault --help
Usage: ansible-vault [create|decrypt|edit|encrypt|encrypt_string|rekey|view] [options] [vaultfile.yml]
encryption/decryption utility for Ansible data files
Options:
–ask-vault-pass ask for vault password
-h, --help show this help message and exit
–new-vault-id=NEW_VAULT_ID
the new vault identity to use for rekey
–new-vault-password-file=NEW_VAULT_PASSWORD_FILE
new vault password file for rekey
–vault-id=VAULT_IDS the vault identity to use
–vault-password-file=VAULT_PASSWORD_FILES
vault password file
-v, --verbose verbose mode (-vvv for more, -vvvv to enable
connection debugging)
–version show program’s version number, config file location,
configured module search path, module location,
executable location and exit
See ‘ansible-vault --help’ for more information on a specific
command.
1)新建一个具有加密的yml文件
[alice@control ansible]$ ansible-vault create vault1.yml
New Vault password: 123
Confirm New Vault password: 123
- name: user
hosts: all
tasks:- name: delete alex user
user:
name: alex
state: absent
- name: delete alex user
vim 和 cat 查看都是加密文件
[alice@control ansible]$ vim vault1.yml
[alice@control ansible]$ cat vault1.yml
$ANSIBLE_VAULT;1.1;AES256
36313435326662643038623736303635636434376235336334343337343966383562343935366335
6164613266306630633837653133663565643264323736300a396137626664383430386636626131
65326461393665663864653936653136376161316265666463636533313232363030336337613138
3738393564386533650a633131626265643839626233613062316435653664373662396230316636
61323564333961386639633230313733666536343165326131333834646637666664656366313861
30353537646264336434313037303064366333353861643132313833613739306234643833316335
39353039633262303662383237326431653530343738303361653532616639356131326430666364
31353334323266313131396636663230333335323961316531323535373039326364353439653961
61363865646131316236663765346635346664323162303031346166373139316331303138373231
34636665396136383963363432363031323032393161353836613233353563636633396638353038
386262356337646361323965303364366131
查看加密文件
[alice@control ansible]$ ansible-vault view vault1.yml
Vault password: 123
- name: user
hosts: all
tasks:- name: delete alex user
user:
name: alex
state: absent
- name: delete alex user
编辑加密文件
[alice@control ansible]$ ansible-vault edit vault1.yml
Vault password: 123
加密文件必须输入密码,使用 --ask-vault-pass 参数
[alice@control ansible]$ ansible-playbook --syntax-check vault1.yml
ERROR! Attempting to decrypt but no vault secrets found
检查语法
[alice@control ansible]$ ansible-playbook --ask-vault-pass --syntax-check vault1.yml
Vault password: 123
playbook: vault1.yml
空执行,假执行
[alice@control ansible]$ ansible-playbook --ask-vault-pass -C vault1.yml
真执行
[alice@control ansible]$ ansible-playbook --ask-vault-pass vault1.yml
2)现有的 yml 文件,进行 vault 加密
对 test.yml 文件进行加密
[alice@control ansible]$ ansible-vault encrypt test.yml
New Vault password:
Confirm New Vault password:
Encryption successful
vim 和 cat 看到的都是加密文件
[alice@control ansible]$ vim test.yml
[alice@control ansible]$ cat test.yml
$ANSIBLE_VAULT;1.1;AES256
34363462376631623162356132643334313938656635376232363430323862383035356362343939
3036306337333636346161313535653766363238383833610a333635373632323132363530633437
61383566656436666132616161346334613131346135373934396137373161303538343335643830
6536633964633032310a383761333631653265323663383533333234643335306637646530663131
62666135343061386235313632633063626134346164663434393161316334306362386537376238
34343937333263383133316166633635343562663865386531653538313438653431646333376666
63366239326134346536343137616231373264373135316661396137313866646234376534333933
31363334343833623865343562326432393733386238626634626366633339323365356237356533
34386139656339383966643935353231353937323435373964663162306338616666326265363264
31633063623136376338313634303334303032633162353532396162336335356164376363363436
36303633666337653931646236393931346438636439303365383332313666343933656133623630
61343533613131363862336363653434656538323730363531303566643030343363363736376264
63653933643430303832373831303962613830626165356536353464313536653132
编辑加密文件
[alice@control ansible]$ ansible-vault edit test.yml
Vault password: 123
- name: this is a test yml file
hosts: network,os,prod
tasks:- name: test install vsftpd package
yum:
name: vsftpd
state: latest
- name: test install vsftpd package
3)指定 vault 密码文件的方式
[alice@control ansible]$ echo ‘123’ > password
[alice@control ansible]$ ansible-vault encrypt --vault-password-file=password test1.yml
Encryption successful
编辑
[alice@control ansible]$ ansible-vault edit --vault-password-file=password test1.yml
查看
[alice@control ansible]$ ansible-vault view --vault-password-file=password test1.yml
- name: this is a test yml file
hosts: network,os,prod
tasks:- name: test install vsftpd package
yum:
name: vsftpd
state: latest
- name: test install vsftpd package
检查语法
[alice@control ansible]$ ansible-playbook --vault-password-file=password --syntax-check test1.yml
playbook: test1.yml
空执行,假执行
[alice@control ansible]$ ansible-playbook --vault-password-file=password -C test1.yml
真执行
[alice@control ansible]$ ansible-playbook --vault-password-file=password test1.yml
4)更新现有的key
[alice@control ansible]$ ansible-vault rekey vault1.yml
Vault password: 123
New Vault password: qwe
Confirm New Vault password: qwe
Rekey successful
5)解密key,解密加密文件
[alice@control ansible]$ ansible-vault decrypt vault1.yml
Vault password: qwe
Decryption successful
解密后的文件,cat 和 vim 编辑都可以看到明文了
[alice@control ansible]$ vim vault1.yml
[alice@control ansible]$ cat vault1.yml
- name: user
hosts: all
tasks:- name: delete alex user
user:
name: alex
state: absent
- name: delete alex user
管理事实
管理事实 -> 设置内置变量
gather_facts: no|yes
默认为yes,如果设置为no,则在此playbook中是不能调用内置变量
编写创建用户 createuser.yml
[alice@control ansible]$ touch createuser.yml
[alice@control ansible]$ vim createuser.yml
- name: users
hosts: all
tasks:- name: create users
user:
name: “{{ item.user_name }}”
comment: “{{ item.user_comment }}”
shell: “{{ item.user_shell }}”
state: present
loop:- { user_name: “alex666”,user_comment: “IT”,user_shell: “/bin/bash” }
- { user_name: “alex777”,user_comment: “dev”,user_shell: “/sbin/nologin” }
- { user_name: “alex888”,user_comment: “prod”,user_shell: “/bin/bash” }
when: inventory_hostname in groups.linux
- name: create users
loop 是遍历的意思
检查语法
[alice@control ansible]$ ansible-playbook --syntax-check createuser.yml
空执行,假执行
[alice@control ansible]$ ansible-playbook -C createuser.yml
设置 gather_facts: no
[alice@control ansible]$ cp createuser.yml gather_facts.yml
[alice@control ansible]$ vim gather_facts.yml
- name: users
hosts: all
gather_facts: no
tasks:- name: create users
user:
name: “{{ item.user_name }}”
comment: “{{ item.user_comment }}”
shell: “{{ item.user_shell }}”
state: present
loop:- { user_name: “alex666”,user_comment: “IT”,user_shell: “/bin/bash” }
- { user_name: “alex777”,user_comment: “dev”,user_shell: “/sbin/nologin” }
- { user_name: “alex888”,user_comment: “prod”,user_shell: “/bin/bash” }
when: inventory_hostname in groups.linux
- name: create users
loop 是遍历的意思
检查语法
[alice@control ansible]$ ansible-playbook --syntax-check gather_facts.yml
playbook: gather_facts.yml
空执行,假执行,发现不收集内置变量了
[alice@control ansible]$ ansible-playbook -C gather_facts.yml
查看 debug 模块的参数信息
[alice@control ansible]$ ansible-doc -s debug
gather_facts 设置为 yes,添加debug模块
[alice@control ansible]$ cp gather_facts.yml gather_facts2.yml
[alice@control ansible]$ vim gather_facts2.yml
- name: users
hosts: all
gather_facts: yes
tasks:-
name: create users
user:
name: “{{ item.user_name }}”
comment: “{{ item.user_comment }}”
shell: “{{ item.user_shell }}”
state: present
loop:- { user_name: “alex666”,user_comment: “IT”,user_shell: “/bin/bash” }
- { user_name: “alex777”,user_comment: “dev”,user_shell: “/sbin/nologin” }
- { user_name: “alex888”,user_comment: “prod”,user_shell: “/bin/bash” }
when: inventory_hostname in groups.linux
-
name: debug
debug:
var: ansible_facts
-
loop 是遍历的意思
检查语法
[alice@control ansible]$ ansible-playbook --syntax-check gather_facts2.yml
playbook: gather_facts2.yml
空执行,假执行
[alice@control ansible]$ ansible-playbook -C gather_facts2.yml
setup 模块进行查看
[alice@control ansible]$ ansible -m setup network > a.txt
[alice@control ansible]$ vim a.txt
[alice@control ansible]$ grep ‘hostname’ a.txt
“ansible_hostname”: “node1”,
[alice@control ansible]$ cat a.txt | grep -i hostname
“ansible_hostname”: “node1”,
ansible_hostname
ansible_eth0 ipv4 address = IP地址
##获取主机名(基于简单的变量)
[alice@control ansible]$ cp gather_facts2.yml gather_facts3.yml
[alice@control ansible]$ vim gather_facts3.yml
- name: users
hosts: all
gather_facts: yes
tasks:- name: debug
debug:
var: ansible_facts[‘hostname’]
- name: debug
检查语法
[alice@control ansible]$ ansible-playbook --syntax-check gather_facts3.yml
playbook: gather_facts3.yml
空执行,假执行 -> 获取hostname变量
[alice@control ansible]$ ansible-playbook -C gather_facts3.yml
##获取IP地址:(基于带有层级结构的变量)
[alice@control ansible]$ cp gather_facts3.yml gather_facts4.yml
[alice@control ansible]$ vim gather_facts4.yml
- name: users
hosts: all
gather_facts: yes
tasks:- name: debug
debug:
var: ansible_facts[‘eth0’][‘ipv4’][‘address’]
- name: debug
检查语法
[alice@control ansible]$ ansible-playbook --syntax-check gather_facts4.yml
playbook: gather_facts4.yml
空执行,假执行 -> 获取 IP 地址变量值
[alice@control ansible]$ ansible-playbook -C gather_facts4.yml
#循环:
循环1 -> 简单循环
[alice@control ansible]$ touch useradd.yml
[alice@control ansible]$ vim useradd.yml
- name: users
hosts: all
tasks:- name: create users
user:
name: “{{ item }}”
state: present
loop:- alex123
- alex456
when: inventory_hostname in groups.linux
- name: create users
loop 是遍历的意思
检查语法
[alice@control ansible]$ ansible-playbook --syntax-check useradd.yml
playbook: useradd.yml
空执行,假执行
[alice@control ansible]$ ansible-playbook -C useradd.yml
真执行
[alice@control ansible]$ ansible-playbook useradd.yml
查看验证
[alice@control ansible]$ ansible -m shell linux -a “tail -2 /etc/passwd”
循环2 -> 数组方式循环
[alice@control ansible]$ cp useradd.yml useradd2.yml
[alice@control ansible]$ vim useradd2.yml
- name: users
hosts: all
vars:
user_name:
- mk111
- mk222
tasks:- name: create users
user:
name: “{{ item }}”
state: present
loop: “{{ user_name }}”
when: inventory_hostname in groups.linux
- name: create users
loop 是遍历的意思
检查语法
[alice@control ansible]$ ansible-playbook --syntax-check useradd2.yml
playbook: useradd2.yml
空执行,假执行
[alice@control ansible]$ ansible-playbook -C useradd2.yml
真执行
[alice@control ansible]$ ansible-playbook useradd2.yml
查看验证
[alice@control ansible]$ ansible -m shell linux -a “tail -2 /etc/passwd”
循环3 -> 字典方式循环
[alice@control ansible]$ cp useradd2.yml useradd3.yml
[alice@control ansible]$ vim useradd3.yml
- name: users
hosts: all
tasks:- name: create users
user:
name: “{{ item.user_name }}”
comment: “{{ item.user_comment }}”
shell: “{{ item.user_shell }}”
state: present
loop:- { user_name: “alex666”,user_comment: “IT”,user_shell: “/bin/bash” }
- { user_name: “alex777”,user_comment: “dev”,user_shell: “/sbin/nologin” }
- { user_name: “alex888”,user_comment: “prod”,user_shell: “/bin/bash” }
when: inventory_hostname in groups.linux
- name: create users
loop 是遍历的意思
检查语法
[alice@control ansible]$ ansible-playbook --syntax-check useradd3.yml
playbook: useradd3.yml
空执行,假执行
[alice@control ansible]$ ansible-playbook -C useradd3.yml
真执行
[alice@control ansible]$ ansible-playbook useradd3.yml
查看验证
[alice@control ansible]$ ansible -m shell linux -a “tail -2 /etc/passwd”
playbook 卸载安装包
[alice@control ansible]$ touch remove.yml
[alice@control ansible]$ vim remove.yml
- name: remove httpd
hosts: all
tasks:- name: remove httpd packages
yum:
name: httpd
state: absent
- name: remove httpd packages
检查语法
[alice@control ansible]$ ansible-playbook --syntax-check remove.yml
playbook: remove.yml
空执行,假执行
[alice@control ansible]$ ansible-playbook -C remove.yml
真执行
[alice@control ansible]$ ansible-playbook remove.yml
查看验证
[alice@control ansible]$ ansible -m shell all -a “rpm -qa | grep -i httpd”
when -> 通过查找变量 rc 的值来进行判断
[alice@control ansible]$ touch when-httpd.yml
[alice@control ansible]$ vim when-httpd.yml
- name: when httpd
hosts: all
tasks:-
name: test if installed httpd
shell: rpm -qa | grep -i httpd
register: package_name -
name: install httpd packages
yum:
name: httpd
state: latest
when: “package_name.rc == 0” -
name: debug
debug:
var: package_name
-
检查语法
[alice@control ansible]$ ansible-playbook --syntax-check when-httpd.yml
playbook: when-httpd.yml
执行
[alice@control ansible]$ ansible-playbook when-httpd.yml
查看并验证
[alice@control ansible]$ ansible -m shell all -a “rpm -qa | grep -i httpd”
when: “package_name.rc == 0” 表示安装
when: “not package_name.rc != 0” 表示安装
when -> 通过判断 卸载 httpd 服务
[alice@control ansible]$ cp when-httpd.yml when-httpd2.yml
[alice@control ansible]$ vim when-httpd2.yml
- name: when httpd
hosts: all
tasks:-
name: test if installed httpd
shell: rpm -qa | grep -i httpd
register: package_name -
name: uninstall httpd packages
yum:
name: httpd
state: absent
when: “not package_name.rc” -
name: debug
debug:
var: package_name
-
检查语法
[alice@control ansible]$ ansible-playbook --syntax-check when-httpd2.yml
playbook: when-httpd2.yml
查看并验证
[alice@control ansible]$ ansible -m shell all -a “rpm -qa | grep -i httpd”
day10 =============================================================================================================================================================================== day10
程序处理
程序处理 -> lineinfile 进行内容替换
查看 lineinfile 模块的详细参数
[alice@control ansible]$ ansible-doc -s lineinfile
当查看到参数有(required)的参数时,表示这个参数是必须的
lineinfile 模块 ansible 实现方式,初体验
lineinfile -> 最主要的功能在于替换
[alice@control ansible]$ ansible -m lineinfile all -a “path=’/etc/sysconfig/selinux’ regexp=’^SELINUX=’ line=‘SELINUX=disabled’”
参数解析
path=’/etc/sysconfig/selinux’ 表示你要修改那个文件
regexp=’^SELINUX=’ 使用正则表达式的方式来匹配你要修改哪一行
line= 你要替换的内容
查看
[alice@control ansible]$ ansible -m shell all -a “cat /etc/sysconfig/selinux”
insertbefore/insertafter=’^SELINUX=’ 使用正则表达式,来匹配行
insertbefore 在匹配的行之前插入内容
[alice@control ansible]$ ansible -m lineinfile all -a “path=’/etc/sysconfig/selinux’ state=‘present’ insertbefore=’^SELINUX=’ line=‘I think i am right’”
insertafter 在匹配的行之后插入内容
[alice@control ansible]$ ansible -m lineinfile all -a “path=’/etc/sysconfig/selinux’ state=‘present’ insertafter=’^SELINUX=’ line=‘I think i am after’”
查看
[alice@control ansible]$ ansible -m shell all -a “cat /etc/sysconfig/selinux”
I think i am right
SELINUX=disabled
I think i am after
参数 state=‘absent’ 的时候,表示删除,删除匹配的行
[alice@control ansible]$ ansible -m lineinfile all -a “path=’/etc/sysconfig/selinux’ regexp=’^I think’ state=‘absent’”
create=‘yes’ 在文件的末尾添加内容
[alice@control ansible]$ ansible -m lineinfile all -a “path=’/etc/sysconfig/selinux’ line=‘qweasd’ create=‘yes’”
查看
[alice@control ansible]$ ansible -m shell all -a “cat /etc/sysconfig/selinux”
参数 state=‘absent’ 的时候,表示删除,删除匹配的行
[alice@control ansible]$ ansible -m lineinfile all -a “path=’/etc/sysconfig/selinux’ regexp=’^qweasd’ state=‘absent’”
查看
[alice@control ansible]$ ansible -m shell all -a “cat /etc/sysconfig/selinux”
lineinfile 模块 ansible-playbook 实现方式
获取 SELinux
[alice@control ansible]$ ansible -m shell linux -a “getenforce”
临时修改
[alice@control ansible]$ ansible -m shell linux -a “setenforce 0”
[alice@control ansible]$ touch lineinfile.yml
[alice@control ansible]$ vim lineinfile.yml
- name: Linux SELinux
hosts: all
tasks:- name: disable selinux
lineinfile:
path: /etc/selinux/config
regexp: ‘^SELINUX=’
line: ‘SELINUX=disabled’
- name: disable selinux
检查语法
[alice@control ansible]$ ansible-playbook --syntax-check lineinfile.yml
playbook: lineinfile.yml
空执行,假执行
[alice@control ansible]$ ansible-playbook -C lineinfile.yml
真执行
[alice@control ansible]$ ansible-playbook lineinfile.yml
查看验证
[alice@control ansible]$ ansible -m shell all -a “getenforce”
临时修改
[alice@control ansible]$ ansible -m shell linux -a “setenforce 0”
[alice@control ansible]$ touch lineinfile-httpd.yml
[alice@control ansible]$ vim lineinfile-httpd.yml
- name: lineinfile httpd
hosts: all
tasks:-
name: install httpd
yum:
name: httpd
state: present -
name: modify httpd’s website
copy:
content: “hello,alex”
dest: /var/www/html/index.html -
name: modify httpd’s main configuration file
lineinfile:
path: /etc/httpd/conf/httpd.conf
regexp: “^Listen 80”
line: “Listen 8080” -
name: start httpd service
service:
name: httpd
state: started
enabled: true
-
检查语法
[alice@control ansible]$ ansible-playbook --syntax-check lineinfile-httpd.yml
playbook: lineinfile-httpd.yml
空执行,假执行
[alice@control ansible]$ ansible-playbook -C lineinfile-httpd.yml
真执行
[alice@control ansible]$ ansible-playbook lineinfile-httpd.yml
查看验证
[alice@control ansible]$ ansible -m shell all -a “dnf info -y httpd”
[alice@control ansible]$ ansible -m shell all -a “rpm -qa | grep -i httpd”
[alice@control ansible]$ ansible -m shell all -a “ss -tunpla | grep 8080”
[alice@control ansible]$ ansible -m shell all -a “lsof -i:80”
handlers 进行程序处理
[alice@control ansible]$ touch handlers.yml
[alice@control ansible]$ vim handlers.yml
-
name: handlers
hosts: all
tasks:-
name: install httpd
yum:
name: httpd
state: present -
name: modify httpd’s website
copy:
content: “hello,alex”
dest: /var/www/html/index.html
setype: httpd_sys_content_t -
name: modify httpd’s main configuration file
lineinfile:
path: /etc/httpd/conf/httpd.conf
regexp: “^Listen 80”
line: “Listen 8080”
notify:- restart httpd
-
name: firewalld add http services
firewalld:
state: enabled
service: http
permanent: yes
immediate: yes -
name: install vsftpd services
dnf:
name: vsftpd
state: latest
notify:- restart vsftpd
handlers:
-
name: restart httpd
service:
name: httpd
state: restarted -
name: restart vsftpd
service:
name: vsftpd
state: restarted
-
检查语法
[alice@control ansible]$ ansible-playbook --syntax-check handlers.yml
playbook: handlers.yml
空执行,假执行
[alice@control ansible]$ ansible-playbook -C handlers.yml
真执行,通过 -vv 参数 验证
[alice@control ansible]$ ansible-playbook handlers.yml -v
[alice@control ansible]$ ansible-playbook handlers.yml -vv
[alice@control ansible]$ ansible-playbook handlers.yml -vvv
任务控制
ignore_errors -> 处理任务失败
添加
ignore_errors: yes
尖叫提示: 不是所有的问题,都可以进行忽略,当任务的执行成功或者失败对后面的任务没有直接关联的时候是可以忽略的。
[alice@control ansible]$ cp handlers.yml ignore.yml
[alice@control ansible]$ vim ignore.yml
-
name: handlers
hosts: all
tasks:-
name: install httpd
yum:
name: http
state: present
ignore_errors: yes -
name: modify httpd’s website
copy:
content: “hello,alex”
dest: /var/www/html/index.html
setype: httpd_sys_content_t -
name: modify httpd’s main configuration file
lineinfile:
path: /etc/httpd/conf/httpd.conf
regexp: “^Listen 80”
line: “Listen 8080”
notify:- restart httpd
-
name: firewalld add http services
firewalld:
state: enabled
service: http
permanent: yes
immediate: yes -
name: install vsftpd services
dnf:
name: vsftpd
state: latest
notify:- restart vsftpd
handlers:
-
name: restart httpd
service:
name: httpd
state: restarted -
name: restart vsftpd
service:
name: vsftpd
state: restarted
-
语法检查
[alice@control ansible]$ ansible-playbook --syntax-check ignore.yml
playbook: ignore.yml
空执行,假执行
[alice@control ansible]$ ansible-playbook -C ignore.yml
##验证:错误的task,会出现…ignoring
[alice@control ansible]$ ansible-playbook ignore.yml
force_handlers: yes -> 强制执行失败的任务
添加
force_handlers: yes
虽然有excute错误的任务,handlers中的任务会根据已经发生changed的任务中的notify进行触发。
[alice@control ansible]$ cp ignore.yml force_handlers.yml
[alice@control ansible]$ vim force_handlers.yml
-
name: handlers
hosts: all
force_handlers: yes
tasks:-
name: install httpd
yum:
name: httpd
state: present -
name: modify httpd’s website
copy:
content: “hello,alex”
dest: /var/www/html/index.html
setype: httpd_sys_content_t -
name: modify httpd’s main configuration file
lineinfile:
path: /etc/httpd/conf/httpd.conf
regexp: “^Listen 80”
line: “Listen 8080”
notify:- restart httpd
-
name: firewalld add http services
firewalld:
state: enabled
service: http
permanent: yes
immediate: yes -
name: install vsftpd services
dnf:
name: vsftpd
state: latest
notify:- restart vsftpd
-
name: excute /bin/false
command: /bin/false
handlers:
-
name: restart httpd
service:
name: httpd
state: restarted -
name: restart vsftpd
service:
name: vsftpd
state: restarted
-
语法检查
[alice@control ansible]$ ansible-playbook --syntax-check force_handlers.yml
playbook: force_handlers.yml
空执行,假执行
[alice@control ansible]$ ansible-playbook -C force_handlers.yml
真执行
[alice@control ansible]$ ansible-playbook force_handlers.yml
验证
[alice@control ansible]$ ansible-playbook force_handlers.yml -vv
[alice@control ansible]$ ansible -m shell all -a “cat /var/www/html/index.html”
[alice@control ansible]$ ansible -m shell all -a “systemctl status httpd”
failed_when -> 指定任务失败的条件
failed_when 来指定任务失败的条件,某些任务默认永远不可能报告失败,但是我们可以人为的指定报告,指定任务失败的条件
添加
register: command_result
failed_when: command_result.rc == 0
[alice@control ansible]$ touch failed_when.yml
[alice@control ansible]$ vim failed_when.yml
- name: failed_when
hosts: all
tasks:-
name: failed
command: /bin/false -
name: add web content
copy:
content: “hello alex”
dest: /opt/testfile.txt
-
语法检查
[alice@control ansible]$ ansible-playbook --syntax-check failed_when.yml
playbook: failed_when.yml
空执行,假执行
[alice@control ansible]$ ansible-playbook -C failed_when.yml
真执行,报错 rc:1
[alice@control ansible]$ ansible-playbook failed_when.yml
failed_when 使用策略
(1)在 shell | command 中定义一个 register 变量
(2)在后续的任务中,通过 register 变量中的值,决定该任务以及后续任务是否需要执行
[alice@control ansible]$ vim failed_when.yml
- name: failed_when
hosts: all
tasks:-
name: failed
command: /bin/false
register: command_result
failed_when: command_result.rc == 0 -
name: add web content
copy:
content: “hello alex”
dest: /opt/testfile.txt
-
语法检查
[alice@control ansible]$ ansible-playbook --syntax-check failed_when.yml
playbook: failed_when.yml
空执行,假执行
[alice@control ansible]$ ansible-playbook -C failed_when.yml
[alice@control ansible]$ ansible-playbook -C failed_when.yml -vv
真执行
[alice@control ansible]$ ansible-playbook failed_when.yml -vv
Ansible 块和错误处理(block、rescue、always)
block 与 when、rescue、always 是同一级别,位于 tasks 之下
block 包含 when 关键字
block 中的子任务失败后,会执行 rescue 模块,always 模块是无论如何都会执行的
[alice@control ansible]$ touch block.yml
[alice@control ansible]$ vim block.yml
[alice@control ansible]$ cat block.yml
- name: block rescue always
hosts: all
tasks:-
name: install and configure httpd
block:-
name: install
yum:
name: httpd
state: latest -
name: configure
copy:
content: “hello,alex”
dest: /var/www/html/index.html -
name : start servie
service:
name: httpd
state: started
enabled: true
when: ansible_distribution == “RedHat”
rescue:
- name: shell command failure
shell: echo “hello,failure”
always:
- name: shell command failure or success
shell: echo “hello,always”
-
-
语法检查
[alice@control ansible]$ ansible-playbook --syntax-check block.yml
playbook: block.yml
空执行,假执行
[alice@control ansible]$ ansible-playbook -C block.yml
真执行
[alice@control ansible]$ ansible-playbook block.yml -vv
jinjia2
在被管理节点上创建文件或者目录
如果要使用 template 模块,需要使用具体语法
src: 指定来源 jinjia2 模块
dest: 指定要在目标主机上创建文件
{% EXPR %} -> 用于表达式或者逻辑式
{{ EXPR }} -> 用于向最终用户输出表达式或者变量的结果
##简单的facts变量
1、ansible_distribution
2、ansible_facts[‘distribution’]
ansible_facts[‘hostname’]
##复杂一点的facts变量
通过ansible_facts变量获取IP地址:
1、ansible_eth0.ipv4.address =IP地址
2、ansible_facts[‘eth0’][‘ipv4’][‘address’]
实操实验
[alice@control ansible]$ vim hosts.j2
Welcome {{ ansible_fqdn }} to {{ ansible_facts[‘hostname’] }} on {{ ansible_facts[‘eth0’][‘ipv4’][‘address’] }}
[alice@control ansible]$ touch template.yml
[alice@control ansible]$ vim template.yml
- name: jinjia2
hosts: all
tasks:-
name: install httpd
yum:
name: httpd
state: latest -
name: get information
template:
src: /home/alice/ansible/hosts.j2
dest: /var/www/html/index.html
mode: 0666
setype: httpd_sys_content_t
owner: apache
group: apache -
name: start httpd
service:
name: httpd
state: started
enabled: true
-
语法检查
[alice@control ansible]$ ansible-playbook --syntax-check template.yml
playbook: template.yml
空执行,假执行
[alice@control ansible]$ ansible-playbook -C template.yml
真执行
[alice@control ansible]$ ansible-playbook template.yml
验证
[alice@control ansible]$ curl -l http://node1/
Welcome node1.lab0.example.com to node1 on 172.25.254.101
[alice@control ansible]$ curl -l http://node2/
Welcome node2.lab0.example.com to node2 on 172.25.254.102
[alice@control ansible]$ curl -l http://node3/
Welcome node3.lab0.example.com to node3 on 172.25.254.103
[alice@control ansible]$ curl -l http://node4/
Welcome node4.lab0.example.com to node4 on 172.25.254.104
jinjia2 模板还可以如下定义,还有如下语法使用
[alice@control ansible]$ vim alex_hosts.j2
{% for host in groups[‘var’] %}
{{ ansible_facts[‘hostname’] }}
{% endfor %}
{% if ansible_facts[‘hostname’] != “s1” %}
{{ ansible_facts[‘hostname’] }}
{% endif %}
防火墙开放端口
[alice@control ansible]$ vim firewall.yml
- name: firewall
hosts: all
tasks:-
name: modify firewalld rule 81
firewalld:
port: 81/tcp
immediate: yes
permanent: yes
state: enabled -
name: modify firewalld rule 82
firewalld:
port: 82/tcp
immediate: yes
permanent: yes
state: enabled -
name: modify firewalld rule 8080
firewalld:
port: 8080/tcp
immediate: yes
permanent: yes
state: enabled
-
语法检查
[alice@control ansible]$ ansible-playbook --syntax-check firewall.yml
playbook: firewall.yml
空执行,假执行
[alice@control ansible]$ ansible-playbook -C firewall.yml
真执行
[alice@control ansible]$ ansible-playbook firewall.yml
[alice@control ansible]$ ansible -m shell all -a “systemctl status httpd”
[alice@control ansible]$ ansible -m shell all -a “firewall-cmd --list-all”
一、管理大项目
1、定义主机列表(资产清单 inventory)
1)静态资产清单
[var]
node1.lab.example.com
172.25.250.10
yml 中单一主机域名,单一IP
- hosts: 10.60.100.111
- hosts: node1.lab.example.com
资产清单中所有的主机
- hosts: ‘*’
- hosts: all
资产清单中多个主机
- hosts: ‘10.60.100.*’
列表的形式
- hosts: 10.60.100.110,10.60.100.111
2)动态资产清单
[alice@control ansible]$ touch inventry2.py
[alice@control ansible]$ vim inventry2.py
#!/usr/bin/env python3
#coding:utf8
import json
import sys
def all():
info_dict = {
“all”: [
“172.25.254.102”,
“172.25.254.103”
]
}
print(json.dumps(info_dict,indent=4))
def group():
host1 = [‘172.25.254.102’]
host2 = [‘172.25.254.102’,‘172.25.254.103’]
group1 = ‘alex-g1’
group2 = ‘alex-g2’
hostdata = {
group1: {“hosts”:host1},
group2: {“hosts”:host2}
}
print(json.dumps(hostdata,indent=4))
def host(ip):
info_dict = {
“172.25.254.102”: {
“ansible_ssh_host”: “172.25.254.102”,
“ansible_ssh_port”: 22,
“ansible_ssh_user”: “root”,
“ansible_ssh_pass”: “redhat”,
},
“172.25.254.103”: {
“ansible_ssh_host”: “172.25.254.103”,
“ansible_ssh_port”: 22,
“ansible_ssh_user”: “root”,
“ansible_ssh_pass”: “redhat”,
}
}
print(json.dumps(info_dict,indent=4))
if len(sys.argv) == 2 and (sys.argv[1] == ‘–list’):
group()
elif len(sys.argv) == 3 and (sys.argv[1] == ‘–host’):
host(sys.argv[2])
else:
print("Usage: %s --list or --host " % sys.argv[0])
sys.exit(1)
赋予权限
[alice@control ansible]$ chmod 755 inventry2.py
安装python3环境
[alice@control ansible]$ dnf info -y python*
[alice@control ansible]$ sudo dnf install -y python36
[alice@control ansible]$ python3 --version
Python 3.6.8
[alice@control ansible]$ python3 -V
Python 3.6.8
[alice@control ansible]$ dnf list -y installed | grep -i python
查看资产清单 通过-i 参数指定资产清单文件
[alice@control ansible]$ ansible-inventory --list
[alice@control ansible]$ ansible-inventory -i inventry2.py --list
ansible 中 ping 模块可以使用,其它模块也可以使用,其它模块就不再演示了
[alice@control ansible]$ ansible -m ping alex-g1 -i inventry2.py
管理多个资产清单文件(通过目录的方式)
[alice@control ansible]$ mkdir inven
[alice@control ansible]$ cp -rfvp alice-inventory inven/
[alice@control ansible]$ cp -rfvp inventry2.py inven/
查看(静态+动态)资产清单文件
[alice@control ansible]$ ansible all -i inven/ --list
[alice@control ansible]$ ansible all -i inven/ --list-host
[alice@control ansible]$ ansible all -i inven/ --list-hosts
ansible 配置并行,默认是5
[alice@control ansible]$ cat ansible.cfg | grep -i forks
#forks = 5
[alice@control ansible]$ grep ‘forks’ ansible.cfg
#forks = 5
包含和导入剧本(include 与 import)
import 静态操作,解析剧本时,对所有 import * 语句进行处理。
include 动态操作,所有include * 语句均在执行playbook 时候进行处理。
[alice@control ansible]$ touch install-tasks.yml
[alice@control ansible]$ vim install-tasks.yml
- hosts: all
tasks:- name: install httpd packages
yum:
name: httpd
state: latest
- name: install httpd packages
[alice@control ansible]$ touch service-tasks.yml
[alice@control ansible]$ vim service-tasks.yml
- hosts: all
tasks:- name: start httpd service
service:
name: httpd
state: started
enabled: true
- name: start httpd service
[alice@control ansible]$ touch install-packages.yml
[alice@control ansible]$ vim install-packages.yml
- name: install packages
hosts: all
tasks:-
name: import tasks
import_tasks: install-tasks.yml -
name: include
include_tasks: service-tasks.yml
-
语法检查
[alice@control ansible]$ ansible-playbook --syntax-check install-tasks.yml
playbook: install-tasks.yml
[alice@control ansible]$ ansible-playbook --syntax-check service-tasks.yml
playbook: service-tasks.yml
[alice@control ansible]$ ansible-playbook install-packages.yml
通过角色简化 playbook
角色定义
配置 roles 目录
[alice@control ansible]$ mkdir roles
ansible.cfg 指定默认的角色路径
[alice@control ansible]$ vim ansible.cfg
68 roles_path = /home/alice/ansible/roles
[alice@control ansible]$ grep roles_path ansible.cfg
roles_path = /home/alice/ansible/roles
查看帮助
[alice@control ansible]$ ansible-galaxy --help
查看版本
[alice@control ansible]$ ansible-galaxy --version
ansible-galaxy 2.8.5
创建 apache 角色
创建角色的的时候,一定要切换到默认的角色路径目录下进行初始化的创建
[alice@control roles]$ ansible-galaxy init apache
- apache was created successfully
[alice@control roles]$ pwd
/home/alice/ansible/roles
[alice@control roles]$ ll
drwxrwxr-x. 10 alice alice 135 Dec 1 11:50 apache
安装 tree 服务
[alice@control roles]$ sudo dnf install -y tree
[alice@control roles]$ tree -d -L 2
.
└── apache
├── defaults
├── files
├── handlers
├── meta
├── tasks
├── templates
├── tests
└── vars
[alice@control roles]$ tree
.
└── apache
├── defaults
│ └── main.yml
├── files
├── handlers
│ └── main.yml
├── meta
│ └── main.yml
├── README.md
├── tasks
│ └── main.yml
├── templates
├── tests
│ ├── inventory
│ └── test.yml
└── vars
└── main.yml
并非每个角色都拥有所有这些目录
defaults -> 此目录中的main.yml 文件包含角色变量的默认值,使用角色时可以覆盖这些默认值,这些变量的优先级较低,应该在play中更改和自定义。
files -> 次目录包含由角色任务引用的静态文件。
handlers 此目录中的 main.yml 文件包含角色的处理程序定义。
meta -> 此目录中 main.yml 文件包含与角色相关的信息,如作者、许可证、平台和可先的角色依赖项。
tasks -> 此目录中的 main.yml 文件包含角色的任务定义。
templates -> 此目录包含由角色任务引用的 jinjia2 模板。
tests -> 此目录可以包含清单和 test.yml playbook,k可用于测试角色。
vars -> 此目录中的 main.yml 文件,定义角色的变量值。这些变量通常用于角色内部用途,这些变量的优先级较高,在 playbook 中 使用时不应更改
配置角色
[alice@control roles]$ cp …/hosts.j2 apache/templates/
[alice@control roles]$ vim apache/tasks/main.yml
-
name: install web packages
dnf:
name: httpd
state: latest -
name: start httpd service
service:
name: httpd
state: started
enabled: true -
name: copy website index.html
template:
src: templates/hosts.j2
dest: /var/www/html/index.html
mode: 0644
owner: apache
group: apache
setype: httpd_sys_content_t -
name: modify httpd.conf listener
lineinfile:
path: /etc/httpd/conf/httpd.conf
regexp: “^Listen 80”
line: “Listen 8080”
notify:- restart httpd service
-
name: firewalld policy
firewalld:
state: enabled
port: 8080/tcp
permanent: yes
immediate: yes
[alice@control roles]$ vim apache/handlers/main.yml
- name: restart httpd service
service:
name: httpd
state: restarted
列出可以使用的角色
[alice@control ansible]$ ansible-galaxy list
/home/alice/ansible/roles
- apache, (unknown version)
使用角色
来到roles目录之外的目录比如/home/alice/ansible,创建一个roles.yml
[alice@control ansible]$ touch roles.yml
[alice@control ansible]$ vim roles.yml
- hosts: all
roles:- apache
语法检查
[alice@control ansible]$ ansible-playbook --syntax-check roles.yml
playbook: roles.yml
空执行,假执行,验证执行
[alice@control ansible]$ ansible-playbook -C roles.yml
真执行
[alice@control ansible]$ ansible-playbook roles.yml
查看并验证
[alice@control ansible]$ ansible -m shell all -a “curl -l http://localhost:8080/”
使用系统角色
安装系统角色
[alice@control ~]$ sudo dnf install -y rhel-system-roles
查看系统角色
[alice@control ~]$ ls -l /usr/share/ansible/
[alice@control ~]$ ls -l /usr/share/ansible/roles/
复制系统角色到自定义目录
[alice@control ansible]$ cp -arfvp /usr/share/ansible/roles/rhel-system-roles.timesync/ ~/ansible/roles/
修改名称,只因名称太长
[alice@control ansible]$ mv roles/rhel-system-roles.timesync roles/timesync
查看角色
[alice@control ansible]$ ansible-galaxy list
/home/alice/ansible/roles
- apache, (unknown version)
- timesync, (unknown version)
查看 readme 文件
[alice@control ansible]$ less roles/timesync/README.md
模板
yaml
- hosts: targets
vars:
timesync_ntp_servers:
- hostname: foo.example.com
iburst: yes
- hostname: bar.example.com
iburst: yes
- hostname: baz.example.com
iburst: yes
roles:- rhel-system-roles.timesync
[alice@control ansible]$ touch timesync.yml
[alice@control ansible]$ vim timesync.yml
- hosts: network,linux,prod
vars:
timesync_ntp_servers:
- hostname: classromm
iburst: yes
roles:- timesync
语法检查
[alice@control ansible]$ ansible-playbook --syntax-check timesync.yml
playbook: timesync.yml
安装 chronyd 服务
[alice@control ansible]$ ansible -m shell all -a “dnf install -y chrony”
空执行,假执行,验证执行
[alice@control ansible]$ ansible-playbook -C timesync.yml
真执行
[alice@control ansible]$ ansible-playbook timesync.yml
查看验证
[alice@control ansible]$ ansible -m shell all -a “chronyc sources -v”
[alice@control ansible]$ ansible -m shell all -a “timedatectl”
自定义 role 角色,部署 httpd 服务
创建角色的的时候,一定要切换到默认的角色路径目录下进行初始化的创建
[alice@control ansible]$ cd roles/
[alice@control roles]$ ansible-galaxy init httpd
- httpd was created successfully
列出可以使用的角色
[alice@control ansible]$ ansible-galaxy list
/home/alice/ansible/roles
- apache, (unknown version)
- timesync, (unknown version)
- httpd, (unknown version)
安装 httpd 的软件包
[alice@control ansible]$ vim roles/httpd/tasks/main.yml
- name: install httpd
yum:
name: httpd
state: latest
通过 fetch 配置 httpd 服务
fetch -> 从被管理节点上拷贝文件到控制节点上
[alice@control ansible]$ ansible -m fetch all -a “src=’/usr/share/doc/httpd/httpd-vhosts.conf’ dest=’/home/alice/ansible/roles/httpd/files/’ flat=‘yes’”
flat=‘yes’ 不拷贝被管理节点的目录结构
修改文件名
[alice@control ansible]$ mv roles/httpd/files/httpd-vhosts.conf roles/httpd/files/server.conf
编辑 httpd_configuration.yml 文件
[alice@control ansible]$ vim roles/httpd/tasks/httpd_configuration.yml
- name: copy httpd configuration file
copy:
src: files/server.conf
dest: /etc/httpd/conf.d/server.conf
上传代码
[alice@control ansible]$ echo “hello,alex” > roles/httpd/files/index.html
编辑 httpd_webcontent.yml 文件
[alice@control ansible]$ vim roles/httpd/tasks/httpd_webcontent.yml
- name: copy source code
copy:
src: files/index.html
dest: /var/www/html/index.html
setype: httpd_sys_content_t
启动 httpd 服务
[alice@control ansible]$ vim roles/httpd/tasks/httpd_service.yml
- name: start httpd service
service:
name: httpd
state: started
enabled: true
配置 firewalld
[alice@control ansible]$ vim roles/httpd/tasks/firewalld_service.yml
- name: start firewalld service
service:
name: firewalld
state: started
enabled: true
[alice@control ansible]$ vim roles/httpd/tasks/firewalld_rules.yml
- name: modify firewalld rules
firewalld:
zone: public
state: enabled
permanent: yes
rich_rule: rule family=ipv4 source address=“172.25.254.101/24” port port=“80” protocol=“tcp” accept
添加 notify 模块
[alice@control ansible]$ vim roles/httpd/tasks/httpd_configuration.yml
- name: copy httpd configuration file
copy:
src: files/server.conf
dest: /etc/httpd/conf.d/server.conf
notify: restart httpd
[alice@control ansible]$ vim roles/httpd/handlers/httpd_install.yml
- name: restart httpd
service:
name: httpd
state: restarted
[alice@control ansible]$ vim roles/httpd/tasks/main.yml
-
name: import httpd playbook
import_tasks: tasks/httpd_install.yml -
name: import configuration httpd playbook
import_tasks: tasks/httpd_configuration.yml -
name: import webcontent httpd playbook
import_tasks: tasks/httpd_webcontent.yml -
name: import start httpd service playbook
import_tasks: tasks/httpd_service.yml -
name: import start firewalld service playbook
import_tasks: tasks/firewalld_service.yml -
name: import configuration firewalld rules playbook
import_tasks: tasks/firewalld_rules.yml
[alice@control ansible]$ ls -l roles/httpd/tasks/
-rw-rw-r–. 1 alice alice 219 Dec 1 15:11 firewalld_rules.yml
-rw-rw-r–. 1 alice alice 114 Dec 1 15:07 firewalld_service.yml
-rw-rw-r–. 1 alice alice 151 Dec 1 15:12 httpd_configuration.yml
-rw-rw-r–. 1 alice alice 75 Dec 1 15:15 httpd_install.yml
-rw-rw-r–. 1 alice alice 106 Dec 1 15:05 httpd_service.yml
-rw-rw-r–. 1 alice alice 140 Dec 1 15:03 httpd_webcontent.yml
-rw-rw-r–. 1 alice alice 549 Dec 1 15:21 main.yml
定义访问入口
[alice@control ansible]$ touch site.yml
[alice@control ansible]$ vim site.yml
- hosts: all
roles:- httpd
检查语法
[alice@control ansible]$ ansible-playbook --syntax-check site.yml
playbook: site.yml
空执行,假执行,验证执行
[alice@control ansible]$ ansible-playbook -C site.yml
真执行
[alice@control ansible]$ ansible-playbook site.yml
[alice@control ansible]$ tree roles/httpd/
roles/httpd/
├── defaults
│ └── main.yml
├── files
│ ├── index.html
│ └── server.conf
├── handlers
│ └── main.yml
├── meta
│ └── main.yml
├── README.md
├── tasks
│ ├── firewalld_rules.yml
│ ├── firewalld_service.yml
│ ├── httpd_configuration.yml
│ ├── httpd_install.yml
│ ├── httpd_service.yml
│ ├── httpd_webcontent.yml
│ └── main.yml
├── templates
├── tests
│ ├── inventory
│ └── test.yml
└── vars
└── main.yml
通过模板方式进行定义变量
[alice@control ansible]$ mv roles/httpd/files/server.conf roles/httpd/templates/
[alice@control ansible]$ vim roles/httpd/templates/server.conf
{% if PORT != 8080 %}
Listen 80
{% endif %}
<VirtualHost *:{{ PORT }}>
ServerAdmin webmaster@dummy-host.example.com
DocumentRoot “/var/www/dummy-host.example.com”
ServerName dummy-host.example.com
ServerAlias www.dummy-host.example.com
ErrorLog “/var/log/httpd/dummy-host.example.com-error_log”
CustomLog “/var/log/httpd/dummy-host.example.com-access_log” common
[alice@control ansible]$ vim roles/httpd/tasks/httpd_configuration.yml
- name: copy httpd configuration file
template:
src: templates/server.conf
dest: /etc/httpd/conf.d/server.conf
notify: restart httpd
[alice@control ansible]$ vim roles/httpd/vars/main.yml
PORT: 80
[alice@control ansible]$ vim roles/httpd/tasks/firewalld_rules.yml
- name: modify firewalld rules
firewalld:
zone: public
state: enabled
permanent: yes
rich_rule: rule family=ipv4 source address=“172.25.254.101/24” port port={{ PORT }} protocol=“tcp” accept
空执行,假执行,验证执行
[alice@control ansible]$ ansible-playbook -C site.yml
真执行
[alice@control ansible]$ ansible-playbook site.yml
使用 Ansible galaxy 部署角色
Ansible 内容公共资源库: https://galaxy.ansible.com
[alice@control ansible]$ touch requirements.yml
[alice@control ansible]$ vim requirements.yml
- src: http://content.example.com/roles/haproxy.tar
name: balancer
[alice@control ansible]$ ansible-galaxy install -r requirements.yml -p roles/
- downloading role from http://content.example.com/roles/haproxy.tar
- extracting balancer to /home/alice/ansible/roles/balancer
- balancer was installed successfully
[alice@control ansible]$ ansible-galaxy list
/home/alice/ansible/roles
- apache, (unknown version)
- timesync, (unknown version)
- httpd, (unknown version)
- balancer, (unknown version)
[alice@control ansible]$ touch roles_balancer.yml
[alice@control ansible]$ vim roles_balancer.yml
- name: use balancer roles
hosts: linux
roles:- balancer
[alice@control ansible]$ ansible-playbook --syntax-check roles_balancer.yml
playbook: roles_balancer.yml
空执行,假执行,验证执行
[alice@control ansible]$ ansible-playbook -C roles_balancer.yml
Ansible 故障排除
1)配置 Ansible 日志
[alice@control ansible]$ vim +/log_path ansible.cfg
[alice@control ansible]$ grep log_path ansible.cfg
log_path = /var/log/ansible.log
2)使用 Ansible debug 模块显示输出
[alice@control ansible]$ ansible-doc debug
[alice@control ansible]$ ansible-doc -s debug
[alice@control ansible]$ touch debug_test.yml
[alice@control ansible]$ vim debug_test.yml
- name: test debug yml
hosts: network
tasks:- name: debug
debug:
msg: “This is a test yml”
- name: debug
语法检查
[alice@control ansible]$ ansible-playbook --syntax-check debug_test.yml
[WARNING]: log file at /var/log/ansible.log is not writeable and we cannot create it, aborting
playbook: debug_test.yml
[alice@control ansible]$ ansible-playbook debug_test.yml -vvv
setup 模块进行查看
[alice@control ansible]$ ansible -m setup network > a.txt
自动执行 Linux 管理任务
1、软件包管理模块
1)yum
2)yum_repository
[alice@control ansible]$ ansible -m shell network -a “dnf grouplist -y”
[alice@control ansible]$ touch groupinstall.yml
基于软件包组的安装
[alice@control ansible]$ vim groupinstall.yml
- name: group install
hosts: network
tasks:- name: install
yum:
name: “@RPM Development Tools”
state: present
- name: install
语法检查
[alice@control ansible]$ ansible-playbook --syntax-check groupinstall.yml
playbook: groupinstall.yml
空执行,假执行,验证执行
[alice@control ansible]$ ansible-playbook -C groupinstall.yml
真执行
[alice@control ansible]$ ansible-playbook groupinstall.yml
查看并验证
[alice@control ansible]$ ansible -m shell network -a “dnf grouplist -y”
2、用户管理模块
1)user
2)group
[alice@control ansible]$ ansible-doc -s user
[alice@control ansible]$ ansible-doc -s group
[alice@control ansible]$ ansible-doc -s user | grep -i group
[alice@control ansible]$ useradd test1 -g alex -G mk
-g 私有组
-G 附加组
[alice@control ansible]$ touch user.yml
[alice@control ansible]$ vim user.yml
- name: user
hosts: network
vars:- user_name: alex
- user_passwd: redhat
tasks: - name: create user
user:
name: “{{ user_name }}”
password: “{{user_passwd | password_hash(‘sha512’)}}”
语法检查
[alice@control ansible]$ ansible-playbook --syntax-check user.yml
playbook: user.yml
空执行,假执行,验证执行
[alice@control ansible]$ ansible-playbook -C user.yml
真执行
[alice@control ansible]$ ansible-playbook user.yml
存储管理模块
lvg
lvol
filesystem
mount
[alice@control ansible]$ ansible -m shell network -a “lsblk -fp”
node1.lab0.example.com | CHANGED | rc=0 >>
NAME FSTYPE LABEL UUID MOUNTPOINT
/dev/sr0
/dev/vda
├─/dev/vda1 xfs 32810515-85c4-4919-b519-fc340bc07086 /boot
└─/dev/vda2 LVM2_member vvxScI-37RQ-oaX3-TyHa-Gz1k-iknv-abLH4D
├─/dev/mapper/rhel-root xfs bd4d478b-e2fb-4cad-8ec0-8a265a82ebd1 /
└─/dev/mapper/rhel-swap swap 3573749e-344d-401f-aa2a-d3946dbb51da [SWAP]
[root@server1 ~]# systemctl start cockpit
[root@server1 ~]# lsof -i:9090
https://172.25.254.250:9090/system
username:root
password:Asimov
在 node1 上添加磁盘,然后重启 node1 服务器
再次查看,发现 node1 多了一块磁盘 /dev/vdb
[alice@control ansible]$ ansible -m shell network -a “lsblk -fp”
node1.lab0.example.com | CHANGED | rc=0 >>
NAME FSTYPE LABEL UUID MOUNTPOINT
/dev/sr0
/dev/vda
├─/dev/vda1 xfs 32810515-85c4-4919-b519-fc340bc07086 /boot
└─/dev/vda2 LVM2_member vvxScI-37RQ-oaX3-TyHa-Gz1k-iknv-abLH4D
├─/dev/mapper/rhel-root xfs bd4d478b-e2fb-4cad-8ec0-8a265a82ebd1 /
└─/dev/mapper/rhel-swap swap 3573749e-344d-401f-aa2a-d3946dbb51da [SWAP]
/dev/vdb
[alice@control ansible]$ ansible-doc -l | grep -i vg
[alice@control ansible]$ ansible-doc -s lvg
[alice@control ansible]$ ansible-doc -l | grep -i lv
[alice@control ansible]$ ansible-doc -s lvol
[alice@control ansible]$ ansible-doc -s filesystem
[alice@control ansible]$ ansible-doc -s mount
[alice@control ansible]$ touch disk_lv.yml
[alice@control ansible]$ vim disk_lv.yml
- name: disk pe pv vg lv filesystem
hosts: network
tasks:-
name: create vg
lvg:
vg: alexvg
pesize: 64m
pvs: /dev/vdb -
name: create lv
lvol:
vg: alexvg
lv: alexlv001
size: 500m -
name: create filesystem
filesystem:
fstype: xfs
dev: /dev/alexvg/alexlv001 -
name: mount
mount:
src: /dev/alexvg/alexlv001
path: /opt/alexdir
fstype: xfs
state: mounted
-
语法检查
[alice@control ansible]$ ansible-playbook --syntax-check disk_lv.yml
playbook: disk_lv.yml
空执行,假执行,验证执行
[alice@control ansible]$ ansible-playbook -C disk_lv.yml
真执行 -vv查看详细信息
[alice@control ansible]$ ansible-playbook disk_lv.yml -vv
查看并验证
[alice@control ansible]$ ansible network -m shell -a “tail -1 /etc/fstab”
node1.lab0.example.com | CHANGED | rc=0 >>
/dev/alexvg/alexlv001 /opt/alexdir xfs defaults 0 0
查看并验证
[alice@control ansible]$ ansible network -m shell -a “df -Th”
node1.lab0.example.com | CHANGED | rc=0 >>
Filesystem Type Size Used Avail Use% Mounted on
devtmpfs devtmpfs 473M 0 473M 0% /dev
tmpfs tmpfs 490M 0 490M 0% /dev/shm
tmpfs tmpfs 490M 6.7M 484M 2% /run
tmpfs tmpfs 490M 0 490M 0% /sys/fs/cgroup
/dev/mapper/rhel-root xfs 47G 1.9G 45G 4% /
/dev/vda1 xfs 1014M 160M 855M 16% /boot
tmpfs tmpfs 98M 0 98M 0% /run/user/1000
/dev/mapper/alexvg-alexlv001 xfs 507M 30M 478M 6% /opt/alexdir