ansible学习笔记
ad-hoc模式语法
ansibble 主机 -m 模块 -a “命令”
ansible -i win_hosts 主机 -m 模块 -a “命令”
默认使用/etc/ansible/hosts 文件 使用-i命令可以指定hosts文件
[root@master ansible]# ansible -i win_hosts node,nfs -m ping
1.ansible基础设置
1.1 host主机文件
vim /etc/ansible/hosts 主机清单文件
密码验证登陆
[node:vars] ##node组统一密码设置
ansible_user=root
ansible_password= "123456"
ansible_port= 22
[node]
192.168.100.102
192.168.100.103
192.168.100.104
[nfs] ##单独设置主机密码
192.168.100.105 ansible_user=root ansible_password=123456 ansible_port=22
指纹认证问题可以在/etc/ansible/ansible.conf record_host_keys=False 打开
公钥认证需提前下发公钥
第一步:在本地机器上使用ssh-keygen产生公钥私钥对
ssh-keygen
第二步:用ssh-copy-id将公钥复制到远程机器中
ssh-copy-id root@192.168.100.102
注意: ssh-copy-id 将key写到远程机器的 ~/ .ssh/authorized_key.文件中
不需要登录就去删掉
第三步: 登录到远程机器不用输入密码
ssh 用户名字@192.168.x.xxx
2.常用模块
ad-hoc模式语法
ansibble 主机 -m 模块 -a “命令”
https://docs.ansible.com/ansible/latest/collections/ansible/builtin/index.html#plugin-index
官方模块手册
查看shell模块参数
[root@localhost \~\]# ansible-doc shell -s
shell模块帮助
[root@localhost \~\]# ansible-doc shell
2.1 copy模块参数
下发的文件中带参数 需要用 template模块
参数 | 必填 | |
---|---|---|
src | 本地文件路径,需绝对值 | |
content | 覆盖写入目的文件内容 | |
dest | 1 | 远程文件夹或文件路径 |
backup | 可选,默认no ,拷贝文件会把目的文件备份 | |
follow | 拷贝文件夹中有link会一起拷过去 | |
force | 当远程主机的目标路径中已经存在同名文件,并且与ansible主机中的文件内容不同时,是否强制覆盖,默认值为yes,表示覆盖,如果设置为no,则不会执行覆盖拷贝操作,远程主机中的文件保持不变 | |
group | 组 | |
mode | chmod的意思 | |
owner | 所有者 |
文件拷过去并且修改所有者、用户组、权限
[root@localhost \~\]# ansible node -m copy -a "src=/uos.txt dest=/tmp/uos61.txt"
[root@localhost \~\]# ansible node -m copy -a"src=/uos.txt dest=/tmp/uos61.txt owner=www group=222 mode=777"
backup=yes 保存源文件并加个时间戳
ansible node -m copy -a "src=/uos.txt dest=/tmp/uos61.txt backup=yes"
content覆盖写入目的文件内容
ansible node -m copy -a "content="刺猹" dest=/tmp/uos61.txt backup=yes"
[root@localhost \~\]# ansible node -m shell -a "cat /tmp/uos61.txt"
192.168.100.102 \| CHANGED \| rc=0 \>\>
刺猹
192.168.100.103 \| CHANGED \| rc=0 \>\>
刺猹
192.168.100.104 \| CHANGED \| rc=0 \>\>
刺猹
拷贝无/ 把文件夹作为一个整体复制过去
[root@localhost hy\]# ansible node -m copy -a "src=/hy dest=/tmp"
有/拷贝 把目录下的所有文件拷进去
[root@localhost hy\]# ansible node -m copy -a "src=/hy/ dest=/tmp"
2.2 file模块
官方手册
https://docs.ansible.com/ansible/latest/collections/ansible/builtin/file_module.html#ansible-collections-ansible-builtin-file-module
剧本写法
<https://docs.ansible.com/ansible/latest/collections/ansible/builtin/file_module.html#examples>
state参数
新建文件夹 state=directory
[root@master ~]# ansible node -m file -a "path=/tmp/test_dir state=directory"
新建文件
[root@localhost \~\]# ansible node -m file -a "path=/tmp/test2 state=touch"
生成软连接
[root@localhost \~\]# ansible node -m file -a "src=/tmp/hy.txt dest=/hy.txt state=link"
生成文件并修改权限,所有者owner group mode
[root@localhost \~\]# ansible node -m file -a "path=/tmp/test4 state=touch owner=www group=www mode=667"
[root@localhost \~\]# ansible node -m file -a "path=/tmp/hy.txt owner=www group=www mode=000"
修改已存在文件的权限信息
2.3 script脚本模块
官方手册
[root@master ~]# ansible node -m script -a “/root/install.sh”
执行脚本
ansible node -vvvv -m script -a “/root/install.sh”
-vvvv 显示执行过程 v越多过程越详细
2.4 crontab模块参数
对应crontab * * * * * 分时日月周
默认值 | ||
---|---|---|
minute | * | 分, |
hour | * | |
day | * | |
month | * | |
weekday | * | |
special_time | 计划任务的时间设定格式为 @reboot 或者@hourly。@reboot 表示重启时执行,@hourly 表示每小时执行一次,相当于设置成”0 0 * * *”,这种@开头的时间设定格式则需要使用 special_time 参数进行设置,special_time 参数的可用值有reboot(重启后)、yearly(每年)、annually(每年,与yearly相同)、monthly(每月)、weekly(每周)、daily(每天)、hourly(每时)。 | |
当上述时间单位设定参数都未指定时,计划任务的时间设定默认会被设定为”* * * * *”,这样表示每秒都会执行一次计划任务,所以,在使用cron模块时,我们应该确定对应的时间参数设置正确。 | ||
user | 默认管理员 | |
job | 要执行的任务 | |
name | 定时任务名称 | |
state | absent 删除 | |
disabled | 当计划任务有名称时,我们可以根据名称使对应的任务”失效”(注释掉对应的任务)。注意,使用此参数时,除了需要指定任务的名称,还需要同时指定任务的job以及任务的时间设定,而且任务的时间设定必须和对应任务完全相同,否则在注释任务的同时,任务的时间设定会被修改,除非你确定这样做。 | |
backup | 如果此参数的值设置为 yes,那么当修改或者删除对应的计划任务时,会先对计划任务进行备份,然后再对计划任务进行修改或者删除,cron 模块会在远程主机的/tmp 目录下创建备份文件,以 crontab 开头并且随机加入一些字符,具体的备份文件名称会在返回信息的 backup_file字段中看到,推荐将此此参数设置为 yes。 |
ansible all -m cron -a “name=‘nep aliyun’ minute=*/5 job=‘ntpdate -u ntp.aliyun.com’”
定时5分钟同步一次时间
[root@master ~]# ansible all -m cron -a “name=‘nep aliyun’ state=absent”
删除任务
[root@master ~]# ansible all -m cron -a “name=‘work’ minute=30 hour=23 job=‘echo “date”>>/tmp/hy.log’”
修改原有任务
2.5 systemd
[root@master ~]# ansible all -m systemd -a “name=ntpd enabled=yes state=started”
服务开机启动
参数 | ||
---|---|---|
name | 服务名 | |
enabled | 开机启动 yes | |
state | reloaded restarted started stopped |
2.6 yum_repository 模块
[root@master \~\]# ansible all -m yum_repository -a 'name="nginx-stable" description="nginx repo" baseurl="<http://nginx.org/packages/centos/$releasever/$basearch/>" enabled=yes gpgcheck=no file="nginx"'
\[nginx-stable\]
name=nginx stable repo
baseurl=<http://nginx.org/packages/centos/$releasever/$basearch/>
gpgcheck=1
enabled=1
gpgkey=<https://nginx.org/keys/nginx_signing.key>
module_hotfixes=true
name | yum源名字 | |
---|---|---|
dirscription | yum源里的注释 | |
baseurl | baseurl地址 | |
enabled | yes 启用 | |
gpgcheck | yes/no | |
file | repo文件名 默认就是name.repo |
2.7 yum 模块 安装
[root@master \~\]# ansible all -m yum -a 'name=nginx state=installed'
state | absent 删 removed 删 installed 安 latest 安最新 present 安 |
---|
2.8 get_url
下载
ansible all -m get_url -a ‘url=“http://repo.zabbix.com/zabbix/6.0/rhel/9/x86_64/zabbix-agent2-6.0.9-release1.el9.x86_64.rpm” dest=/tmp/’
2.9 mount模块
[root@master \~\]# ansible node -m mount -a 'fstype=nfs src=192.168.100.105:/log path=/mnt state=mounted'
fstype 文件系统
src 源地址
path 挂载点
state absent 卸载并修改fstab
mounted 挂+修改fstab
present 仅修改 /etc/fstab 重启后才挂载
unmounted 卸载 不修改
remouunted 重新挂
fstype | 挂载设备的文件系统 iso9660(光驱) ext4、xfs、nfs cifs(samba的共享文件系统) ntfs( windows磁盘文件系统) | |
src | 挂接源设备地址 | |
path | 挂载点 | |
state | absent 永久卸载并修改fstab mounted 永久挂+修改fstab present 仅修改 /etc/fstab 重启后才挂载 unmounted 临时卸载 不修改fstab remouunted 重新挂 | |
3.ansible-playbook 剧本模式
剧本文件是yaml格式文件,后缀名为yml
同级任务对齐,下级缩进两格对齐
- hosts: node
tasks:
- name: touch file
shell: touch /node_playbook.log
执行剧本
先检查语法 参数 -C 大写c
ansible-playbook node.yml -C
没问题后执行
ansible-playbook node.yml
- hosts: all
tasks:
- name: groupadd
group: name=ngx gid=123123 state=present
- name: useradd
user: name=ngx uid=2223333 group=ngx shell=/sbin/nologin state=present
4.playbook变量设置
4.1剧本内定义变量
- hosts: node
vars:
file: /etc/hostname
tasks:
- name: test var
debug:
msg: 变量是{{file}}
- hosts: node
vars:
file: /etc/hostname
dir: hostname
tasks:
- name: test var
debug:
msg: " {{dir}} 变量是{{file}}"
##变量位于开头要加引号
4.2外置变量文件
[root@master \~\]# cat playbook-vars-file.yml vars-file.yml
- hosts: node
vars_files: ./vars-file.yml
tasks:
- name: test var
debug:
msg: " {{dir}} 变量是{{file}}"
cat vars-file.yml
file: /etc/hosts
dir: /opt/hy
4.4组变量文件
##组变量文件路径 /etc/ansible/group_vars/node/vars.yml
## 目录的路径要与hosts文件中的组名对应
##内部变量,外部变量文件,组变量可以混合设置使用,
##如果存在同名变量优先级如下
## all路径是指所有组的变量,但是如果node路径下与all路径下变量存在重名的,就近原则,采用node下的变量
## vars_files设置的外部变量文件优先级高于内部定义的变量
## vars_files设置的外部变量文件优先级高于组变量
[root@master group_vars]# pwd
/etc/ansible/group_vars
[root@master group_vars]# tree
.
├── all
│ └── vars.yml
├── nfs
│ └── vars.yml
└── node
└── vars.yml
3 directories, 3 files
[root@master ~]# cat playbook-group-vars.yml
- hosts: node
vars:
dir: 内部dir
vars_files: ./vars-file.yml
tasks:
- name: test var
debug:
msg: "变量是{{port}} all变量{{all_vars}} vars文件{{dir}} "
- hosts: nfs
vars:
file: /etc/file
port: 本地变量
tasks:
- name: test var nfs
debug:
msg: " 变量是{{port}} all变量{{all_vars}} 内部vars{{file}} "
4.5ansible 内置变量 facts
playbook每次执行都会收集主机facts信息,便于剧本直接引用数据
如果用不到内置变量可以设置 gather_facts: false 省去采集过程,提高剧本执行效率
查看所有变量
ansible node -m setup
可以在playbook中直接使用
带下级变量的用 . 连接
如: ansible_date_time.date =2022-11-26
"ansible_date_time": {
"date": "2022-11-26",
"day": "26",
"epoch": "1669427613",
"hour": "09",
"iso8601": "2022-11-26T01:53:33Z",
"iso8601_basic": "20221126T095333189512",
"iso8601_basic_short": "20221126T095333",
"iso8601_micro": "2022-11-26T01:53:33.189512Z",
"minute": "53",
"month": "11",
"second": "33",
"time": "09:53:33",
"tz": "CST",
"tz_offset": "+0800",
"weekday": "星期六",
"weekday_number": "6",
"weeknumber": "47",
"year": "2022"
}
常用变量
ansible_hostname 主机名
ansible_memtotal_mb 总内存(mb)
ansible_processor_vcpus cpu数
ansible_processor_cores cpu核心数
ansible_default_ivp4.address 默认网卡的ip
ansible_distribution 系统发行版本名字
4.6 register 注册变量
- hosts: node
tasks:
- name: get time
command: date +%F_%w
register: time
- name: print time
debug:
msg: '{{time.stdout}}'
##time.stdout 标准输出
##time.stderr 标准错误输出
##time.stdout执行结果
TASK [print time] ***********************************************************************************
ok: [192.168.100.102] => {
"msg": "2022-11-28_1"
}
ok: [192.168.100.103] => {
"msg": "2022-11-28_1"
}
ok: [192.168.100.104] => {
"msg": "2022-11-28_1"
}
##register注册time的变量
ok: [192.168.100.104] => {
"msg": {
"changed": true,
"cmd": [
"date",
"+%F_%w"
],
"delta": "0:00:00.003673",
"end": "2022-11-28 16:58:49.399794",
"failed": false,
"rc": 0,
"start": "2022-11-28 16:58:49.396121",
"stderr": "",
"stderr_lines": [],
"stdout": "2022-11-28_1",
"stdout_lines": [
"2022-11-28_1"
]
}
}
5.playbook流程控制
- handlers
- when 判断
- loop(with-items) 循环
5.1 handler
ansible会监控任务执行情况 如果change=1 说明状态发生变化
change=0 说明要么没执行,要么执行了没有任何影响
nitify命令会监控任务变化情况,如果change=1 就会触发notify定义的handler任务
handler在写法与功能与task一致,区别在于handler是触发后被动执行,task会按流程执行
- hosts: node
gather_facts: false ##用不到内置变量可以设置 gather_facts: false 省去采集过程,提高剧本执行效率
tasks:
- name: 分发 nginx
copy:
src: ./1.txt
dest: /root/1.txt
backup: yes
notify:
- reload nginx
handlers:
- name: reload nginx
systemd:
name: nginx
state: restarted
5.2 when 满足指定条件运行
-
```
- hosts: node
gather_facts: true
tasks:- name: nginx repo install
yum_repository:
name: “nginx-stable”
description: “nginx repo”
baseurl: “http://nginx.org/packages/centos/$releasever/$basearch/”
enabled: yes
gpgcheck: no
file: “nginx”
when: (ansible_hostname is match (“node|lb”) )
- name: nginx repo install
when:(ansile_hostname == (“node”) ) 如果hostname是node就执行
when:(ansile_hostname is match (“node|lb”) ) 如果hostname是node或lb就执行 is match支持正则
只有满足条件的主机执行了安装nginx repo的操作
[root@master ~]# ansible-playbook when-playbook.yml
PLAY [node] *****************************************************************************************
TASK [Gathering Facts] ******************************************************************************
ok: [192.168.100.104]
ok: [192.168.100.103]
ok: [192.168.100.102]TASK [nginx repo install] ***************************************************************************
skipping: [192.168.100.103]
skipping: [192.168.100.104]
changed: [192.168.100.102]PLAY RECAP ******************************************************************************************
192.168.100.102 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.100.103 : ok=1 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
192.168.100.104 : ok=1 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0 - hosts: node
5.3 loop(with-items) 循环
在要取的值中用 item变量代替
在下面写上with_items进行变量替换
- hosts: node
gather_facts: false
tasks:
- name: restart service
systemd:
name: "{{item}}"
state: stoped
with_items:
- nginx
- crond
[root@master ~]# ansible-playbook with-item.yml
PLAY [node] *****************************************************************************************
TASK [restart service] ******************************************************************************
changed: [192.168.100.103] => (item=nginx)
changed: [192.168.100.102] => (item=nginx)
changed: [192.168.100.104] => (item=nginx)
changed: [192.168.100.103] => (item=crond)
changed: [192.168.100.102] => (item=crond)
changed: [192.168.100.104] => (item=crond)
PLAY RECAP ******************************************************************************************
192.168.100.102 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.100.103 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.100.104 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
##可以将多个变量都写进item
- hosts: node
gather_facts: false
tasks:
- name: adduser
user:
name={{item.name}}
uid={{item.uid}}
with_items:
- {name: 'wangwu', uid: '1239' }
- {name: 'maliu', uid: '1238' }
5.4 tags 标签
用于指定运行那个任务或者跳过哪个任务
-t --tags 指定运行
–skip-tags 跳过某个
–list-tags 列出tag
- hosts: node
gather_facts: false
tasks:
- name: get hostname
shell: hostname
register: hostname
tags:
- get
- getname
- name: print name
debug:
msg: 主机名{{hostname.stdout}}
tags:
- print
- getname
ansible-playbook tag.yml -t get
只执行get
ansible-playbook tag.yml --skip-tags print
跳过 print
ansible-playbook tag.yml -t getname
执行getname这个tag的所有任务
5.5 忽略错误
ignore_errors: yes
在脚本编写调试时,出现错误忽略,继续执行
[root@master ~]# cat ignore_erroes.yml
- hosts: node
gather_facts: false
tasks:
- name: get hostname
shell: hostname
register: hostname
tags:
- get
- getname
- name: print name
debug:
msg: 主机名{{hostname.stdout}}
msg: 主机名{{hostname.st}}
tags:
- print
- getname
ignore_errors: yes
- name: msg
debug:
msg: 脚本执行完
5.6 include
将yml嵌进
[root@master ~]# cat playbook-include.yml include1.yml include2.yml
- hosts: all
tasks:
- include: include1.yml
- include: include2.yml
#include1.yml
- debug:
msg: "include1"
#include2.yml
- debug:
msg: "include2"
tags:
- print
- getname
ignore_errors: yes
- name: msg
debug:
msg: 脚本执行完
### 5.6 include
将yml嵌进
[root@master ~]# cat playbook-include.yml include1.yml include2.yml
- hosts: all
tasks:- include: include1.yml
- include: include2.yml
#include1.yml
- debug:
msg: “include1”
#include2.yml - debug:
msg: “include2”