yum install ansible -y #安装,注意yum源问题
yum源:
yum install epel-release -y
mv /etc/yum.repos.d/epel.repo /etc/yum.repos.d/epel.repo.bak >> /dev/null
yum clean all
rpm -Uvh http://mirrors.ustc.edu.cn/epel/epel-release-latest-7.noarch.rpm
yum makecache
cd /etc/ansible/ 切换目录
cat ansible.cfg |grep -v "^#" |grep -v "^$" #检查生效的配置文件
vim hosts #编辑主机清单文件,在文件末尾添加如下:(这个是默认清单文件位置,也可以ansible -i或者ansible-playbook -i 指定)
[pxg]
192.168.137.155
192.168.137.162
以上意思为:主机组pxg包含这两个IP的主机
定义嵌套组
通过创建后缀为:children的主机组名称来实现,例子如下:
[web]
web1.example.com
web2.example.com
[db]
db1.example.com
db2.example.com
[all:children]
web
db
上述例子可以改成
[web]
web[1:2].example.com
[db]
db[1:2].example.com
[webdb:children]
web
db
ansible pxg --list ###清单验证:看看pxg清单有哪些主机
ansible all --list-hosts ##查看所有默认清单
ansible all -i /tmp/inventory --list-hosts ###含义自己猜
ansible localhost --list-hosts //清单中不用写,也可以列出本地机器
ansible配置文件
优先级从高到低:ANSIBLE_CONFIG环境变量指定的配置文件,运行ansible命令所在的目录的ansible.cfg文件,
用户主目录是否有.ansible.cfg,最后全局配置文件/etc/ansible/ansible.cfg
配置文件示例:
配置例子
[defaults]
inventory = ./inventory ######主机清单文件位置
remote_user = testuser ######指定登录受管主机的用户,不指定则为当前用户
受控主机上/etc/sudoers.d目录创建新文件testuser写入:testuser ALL=(ALL) NOPASSWD:ALL
注意:如果不写nopasswd,配置文件中become_ask_pass无论设置什么,都将提示你输入密码
ask_pass = false #######是否提示输入密码,如果使用ssh公钥验证则可以是false
deprecation_warnings=false #######拒绝警告
[privilege_escalation] #####privilege_escalation 配置ansible如何在受管主机上执行特权升级
become = true #######是否默认在受管主机上切换用户,通常切换为root
become_method = sudo #########如何切换,默认sudo提权,也可以是su直接切换用户
become_user = root #######切换成什么用户,默认root
become_ask_pass = false #####是否为切换提示输入密码,默认为false
注意:如果没有配置文件存在的话,那么将按照主控机的当前用户进行远程登录操作
#管理机需要免密登录被管理机器
ssh-keygen #生成key,不要设置密码
cd /root/.ssh
ssh-copy-id -i id_rsa.pub 192.168.137.155 #传输key,
ssh-copy-id -i id_rsa.pub 192.168.137.162 #传输key,
ansible all -m ping ###测试所有主机是否支持标准模块ping
ansible-doc -l #查询模块
ansible-doc 模块名字 //模块使用的相关介绍
例如:
ansible-doc shell ##查看shell模块
- chdir
Change into this directory before running the command.
[Default: (null)]
type: path
version_added: 0.6
- cmd
The command to run followed by optional arguments.
[Default: (null)]
type: str
- creates
A filename, when it already exists, this step will *not* be run.
[Default: (null)]
type: path
......
ansible pxg -m service -a 'enabled=true name=httpd state=started'
##调用service模块,对pxg主机清单执行,启动并设置随机启动httpd服务
ansible pxg -m yum -a 'name=vsftpd state=present' ###安装软件包vsftpd
如果是卸载的话,将present改成absent
#更改文件所属的用户、组、权限
#ansible pxg -m file -a 'owner=test group=test mode=644 path=/tmp/1.file'
ansible pxg -m command -a 'ifconfig' #查看两台被管理机器的网络信息
ansible pxg -m command -a 'systemctl status firewalld.service' #查看被管控机的防火墙状态
ansible pxg -m shell -a 'systemctl status firewalld.service && ifconfig' #查看被管控机的防火墙状态和网络信息
ansible pxg -m copy -a "src=/root/apache.sh dest=/root/apache.sh" #将管理机root下的脚本拷贝到被管理机的root下
ansible pxg -m copy -a "content='12121212' dest=/tmp/1 owner=root mode=660" ###自己猜
ansible pxg -m copy -a 'src=/tmp/1 dest=/tmp/2 remote_src=yes owner=root mode=660'
ansible pxg -m shell -a "sh /root/apache.sh chdir=/root/"#在被管理机器上运行拷贝的脚本
#创建新用户
ansible web -m user -a 'name="user1"'
ansible web -m command -a 'id user1'
可以通过状态state=present或absent来进行用户的创建和删除
例如:ansible pxg -m user -a 'name="user1" state=present'
ansible pxg -m user -a 'name="user1" state=absent'
#建立周期性任务
# ansible web -m cron -a 'minute="*/10" job="/bin/echo hello" name="test cron job"’
可以通过状态state=present或absent来进行对应任务的创建和删除,name要对应上:
ansible web -m cron -a 'name="test cron job" state=absent'
ansible web -m cron -a 'name="test cron job" minute="0" hour="12" weekday="3" job="/bin/echo hello"' #猜一下这个
##lineinfile模块
1)确保指定的”一行文本”存在于文件中,如果指定的文本本来就存在于文件中,则不做任何操作,如果不存在,默认在文件的末尾插入这行文本.
2)如果不止一行能够匹配正则,那么只有最后一个匹配正则的行才会被替换,被匹配行会被替换成 line 参数指定的内容。
受管机器上有个文件/tmp/1.file ,内容如下:
123
124
456
789
增加了一行内容
# ansible web -m lineinfile -a 'path=/tmp/1.file line="0000" '
按正则来匹配查找
# ansible web -m lineinfile -a 'path=/tmp/1.file regexp="^12" line="#12"’
提醒:backrefs=yes,那么当正则没有匹配到任何的行时,则不会对文件进行任何操作,相当于保持原文件不变
删除指定行
# ansible web -m lineinfile -a 'path=/tmp/1.file regexp="^000" state=absent '
############剧本###############3
新建剧本:
vim useradd.yml
--- ##开始符
- name: create user peng1
hosts:
- pxg
- web
become: yes
tasks:
- name: create user peng1
user:
name: peng1
state: present
... ###结束符
示例剧本2:
---
- name: httpd-install
hosts: pxg
remote_user: root
tasks:
- name: httpd-install
yum:
name: httpd
state: present
- name: httpd-start
service:
name: httpd
enabled: true
- name: mdb-start
hosts: pxg
remote_user: root
tasks:
- name: mdb-install
yum:
name: mariadb
state: present
- name: mdb-start
service:
name: mariadb
enabled: true
...
## 1、第一个name是对剧本的描述,hosts是要对哪些机器(主机组)进行任务的操作,tasks后面所跟的就是实际的执行操作
2、playbook会按照任务文件中的顺序进行执行
3、tasks后面的name是对任务的描述,可以不写,我们建议要写
4、service是该剧本中用到的模块
5、service后面的name和enabled是该模块的子项、参数。
##更复杂的剧本(创建用户)###
---
- name: 创建用户和设置属性示例
hosts: your_target_host
become: yes # 如果需要提升权限来创建用户,请确保使用sudo权限
tasks:
- name: 创建用户 "user1"
user:
name: user1
password: "$6$rounds=10000$saltstring$hashedpassword" # 设置密码,请使用密码哈希值,不要直接明文密码;方法:openssl passwd -1 "your_password"
state: present # 确保用户存在
- name: 设置用户 "user1" 的主组
user:
name: user1
group: users # 设置用户的主组
- name: 设置用户 "user1" 的UID
user:
name: user1
uid: 1001 # 设置用户的UID
####################################################################
ansible-playbook --syntax-check useradd.yml ###验证剧本语法
ansible-playbook -C useradd.yml ###空运行
ansible-playbook useradd.yml ####运行剧本
ansible pxg -m shell -a 'cat /etc/passwd |grep peng1' ######查询结果
###########ansible变量############
变量只能含有字母、数字和_
变量优先级:命令行>play范围>主机范围
命令行变量也称之为额外变量
ansible-playbook -C 06-vars-in-shell.yml -e service=httpd -e service2=httpd2 # 多个变量就多个-e即可,对应剧本如下:
- hosts: pxg
remote_user: root
tasks:
- name: 'task1: {{ service }}'
shell: echo {{ service }}
- name: task2 start {{ service2 }}
service: name={{ service2 }} state=started
# 执行任务时,输入:
# ansible-playbook 06-vars-in-shell.yml -e service=httpd -e service2=httpd2
两种方法定义剧本中的变量:
1)将变量放在playbook的vars块中
- hosts: all
vars:
user: peng
home: /home/peng
2)通过vars_files指定外部文件,在外部文件中指定变量
- hosts: all
vars_files:
- vars/users.yum
#######在users.yum文件中写入如下内容:
user: peng
home: /home/peng
声明过的变量可以在playbook中用双括号{{ }}进行引用,
在任务执行时,Ansible会将变量替换为变量对应的值。
示例:
---
- name:deploy and start apache service
hosts: pxg
vars:
web_pkg:httpd
firewalld_pkg:firewalld
web_service:httpd
firewalld_service:firewalld
rule:http
tasks:
- name: install vars package
yum:
name:
- "{{web_pkg}}"
- "{{firewalld_pkg}}"
state: latest
- name: start and enable firewall_service
service:
name: "{{firewalld_service}}"
enabled: true
state: started
- name: start and enable web_service
service:
name: "{{web_service}}"
enabled: true
state: started
...
####示例完毕####
###########数组变量#########
如有如下变量:
user1_frist_name: peng
user1_last_name: xiaogang
user1_home_dir: /users/peng
user2_frist_name: bin
user2_last_name: zhengyu
user2_home_dir: /users/bin
上面的变量可以改成users的数组
users :
peng:
frist_name: peng
last_name: xiaogang
home_dir: /users/peng
bin:
frist_name: bin
last_name: zhengyu
home_dir: /users/bim
数组回显:
users.peng.last_name 回显xiaogang
由于变量被定义为python字典,可用一下替代语法
users['bin']['last_name'] 回显zhengyu
#####变量的注册与使用######
示例:
---
- name: Installs a package and prints the result
hosts: web
tasks:
- name: Install the pachage
yum:
name: httpd
state: present
register: install_result
- debug: var=install_result
...
###
1、使用register注册变量install_result,来截获输出
2、通过debug模块,将变量install_result的值在终端屏幕输出
3、register经常和debug配合进行使用,用于调试等目的。
####事实变量######
每个剧本在运行每个play的第一个任务之前会先自动运行setup模块来收集事实。新的ansible版本中会被报告为
Gathering Facts任务,更早版本的ansible中报告为setup.
通过剧本打印出ansible_facts事实变量
---
- name: fact print
hosts: pxg
tasks:
- name: print facts
debug:
var: ansible_facts
...
#########
也可以通过ad-hoc命令使用setup模块打印出ansible_facts事实变量
ansible pxg -m setup
事实变量调用:
1、可以在playbook中用双括号{{ }}进行引用
2、ansible_facts['default_ipv4']['address'] 也可以写成
ansible_facts.default_ipv4.address
3、yml中的ens34的地址获取还可以
写成:
ansible_facts['ens34']['ipv4']['address']
或
ansible_ens34['ipv4']['address']
###新版本写法:{{ ansible_facts.ens34.ipv4.address }}
旧版本写法:{{ ansible_ens34.ipv4.address }}
旧版本是否支持,与配置文件中default段中的inject_facts_as_vars参数有关
值为false时,不支持旧版本写法,目前默认为true.
######事实收集的开和关#######
1、在剧本中的每个play都可以设置gather_facts: no进行收集关闭。
2、事实收集关闭,并不影响模块setup的运行。
3、如果剧本不涉及事实变量的引用,可以考虑关闭,
以提高运行速度和受管机的负载。
########自定义事实变量#########
默认情况下,自定义事实变量定义在后缀为.fact文件中,放在目录
/etc/ansible/facts.d下面
两种格式:
1)ini格式写法
[packages]
web_package = httpd
db_package = mariadb-server
[users]
user1 = joe
user2 = jane
2)json格式写法
{
"packages": {
"web_package": "httpd",
"db_package": "mariadb-server"
},
"users": {
"user1": "joe",
"user2": "jane"
}
}
########魔法变量#######
魔法变量不是事实变量,不能通过setup模块收集,但他们也都由ansible自动设置
常见的4个变量
ansible localhost -m debug -a 'var=hostvars["localhost"]'
ansible all -m debug -a 'var=groups["pxg"]'
############任务控制#############
#####循环编写
示例:
---
- name: 不循环的写法
hosts: pxg
tasks:
- name: 启动第一个模块vsftpd
service:
name: vsftpd
state: started
- name: 启动第二个模块httpd
service:
name: vsftpd
state: started
...
##########
---
- name: 变量提供列表loop方式循环启动两个模块
hosts: pxg
vars:
all_services:
- vsftpd
- httpd
tasks:
- name: 变量提列表方式循环启动两个模块
service:
name: "{{ item }}"
state: started
loop: "{{ all_services }}"
...
#######
---
- name: loop方式循环启动两个模块
hosts: pxg
tasks:
- name: 简单列表方式循环启动两个模块
service:
name: "{{ item }}"
state: started
loop:
- httpd
- vsftpd
...
###############
#loop列表中的项也可以是一个key: value的形式(字典方式)
---
- name: 散列或字典loop方式循环管理两个模块
hosts: pxg
tasks:
- name: 散列或字典loop方式循环管理两个模块
service:
name: "{{ item.name }}"
state: "{{ item.status }}"
loop:
- name: httpd
status: started
- name:vsftpd
status: stopped
...
############条件任务##############
略(见单独文档)
###########处理程序################
略
#########大项目相关###########
##主机模式例子:
例子1: 确定db1.example.com服务器是否在inventory1清单中
# ansible db1.example.com -i inventory1 --list-hosts
例子2: 使用all组列出inventory1清单中的所有主机
# ansible all -i inventory1 --list-hosts
例子3: 使用*号进行匹配(包括主机组的名字也参与匹配),匹配条件用单引号包起来
# ansible 'web*' -i inventory1 --list-hosts
例子4: 排除某个主机,通过!形式进行,前后条件通过逗号分隔,条件不分先后
# ansible 'web*,!jupiter.lab.example.com' -i inventory1 --list-hosts
例子5: 主机组和主机可以混合编队(并集)
#ansible 'prod,web*' -i inventory1 --list-hosts
例子6: 通过符号&交集方式选择主机
# ansible 'dev,&web*' -i inventory1 --list-hosts
例子7: 确定出不属于任何组的主机
# ansible ungrouped -i inventory1 --list-hosts
执行剧本指定清单文件
# ansible-playbook -i inventory2 inventory.yml ###注意剧本中hosts指定的必须在inventory2 清单文件中
#########动态清单########
当Ansible与AWS等云服务器结合使用时,维护清单文件将是一项繁重的任务。
由于云产品auto_scaling(自动缩放扩容)等功能的使用,我们的云服务器可
能经常性的进行新增或删除,也有可能进行ip地址的变更。有一个简单
的解决方案就是ansible动态清单。动态清单可以由任何语言编写生成,比较
常见的是用Python编写,但不管哪一种语言,返回的内容都是json格式输出。
查看当前静态清单文件json格式输出
#ansible-inventory --list
#ansible-inventory -i diyinventory --list
#ansible-inventory --graph
#####Python脚本清单例子####
#!/usr/bin/env python
import boto3
import json
# 配置 AWS 访问密钥和区域
aws_access_key = 'YOUR_AWS_ACCESS_KEY'
aws_secret_key = 'YOUR_AWS_SECRET_KEY'
aws_region = 'us-east-1'
# 创建 EC2 客户端
ec2 = boto3.client('ec2', aws_access_key_id=aws_access_key,
aws_secret_access_key=aws_secret_key, region_name=aws_region)
# 获取 EC2 实例信息
instances = ec2.describe_instances()
# 创建一个字典来存储动态清单信息
dynamic_inventory = {'all': {'hosts': []}, '_meta': {'hostvars': {}}}
# 遍历实例并添加到动态清单
for reservation in instances['Reservations']:
for instance in reservation['Instances']:
instance_id = instance['InstanceId']
private_ip = instance['PrivateIpAddress']
public_ip = instance['PublicIpAddress']
# 设置实例的属性
instance_info = {
'ansible_ssh_host': private_ip,
'ansible_ssh_user': 'ec2-user', # 或者其他 SSH 用户名
'ansible_ssh_private_key_file': '/path/to/your/private/key.pem'
}
# 添加到动态清单
dynamic_inventory['all']['hosts'].append(instance_id)
dynamic_inventory['_meta']['hostvars'][instance_id] = instance_info
# 将动态清单以 JSON 格式输出
print(json.dumps(dynamic_inventory))
注意:
YOUR_AWS_ACCESS_KEY
和 YOUR_AWS_SECRET_KEY
为你的 AWS 访问密钥。'/path/to/your/private/key.pem'
为你的 SSH 私钥文件路径。ec2.py
。然后,你可以使用 ansible-playbook
命令来运行 Ansible 剧本,例如:
ansible-playbook -i ec2.py your_playbook.yml
#########配置并行(分叉)###########
查看现在的并行数配置:默认为5
ansible-config dump |grep -i forks
ansible-config list |grep -i forks
####运行ansible和ansible-playbook时可以-f 或者 --forks选项指定并行数
###滚动更新###
serial: 主机数量或百分比
#####包含和导入####
剧本过长不容易维护和处理,可以将其分成小文件进行管理。也可采用模块化方式将多个
Playbook组合为一个主要的playbook,或者将文件中的任务列表插入play。这样可以更好的
在不同项目中重用play或任务序列。
如下剧本:import_playbook.yml 导入两个剧本web.yml\ftp.yml
import_playbook.yml>>>>>>>
---
- name:start web
import_playbook: web.yml
- name: start ftp
import_playbook: ftp.yml
...
##
web.yml>>>>>>
---
- name: 启动web
hosts: web
tasks:
- name: start httpd
service:
name:httpd
state:started
...
#####
ftp.yml>>>>
---
- name: 启动web
hosts: web
tasks:
- name: start vsftpd
service:
name:vsftpd
state:started
...
########################
##使用import_tasks静态导入任务文件
---
- name: 启动web
hosts: web
tasks:
- import_tasks: webserver_tasks.yml ###任务由静态文件webserver_tasks.yml导入
...
####
webserver_tasks.yml>>>>>
- name: start web server
service:
name: httpd
state:started ###这只是个任务
#############
##使用include_tasks动态导入任务文件
略
##################
##变量参数化,提高剧本复用率
略
##########角色###########
角色其实就是tasks的集合,是已经定义好的任务合集。
yum list rhel-system-roles ##确认角色是否已经安装好
yum install rhel-system-roles -y ###安装角色 默认角色在/usr/share/ansible/roles目录
ansible-galaxy init Mariadb ##创建角色Mariadb的目录结构
ansible-galaxy list ##列出本地找到的角色
ansible-galaxy remove Mariadb ###删除本地角色Mariadb
ansible-galaxy search mysql ###搜索mysql角色
ansible-galaxy install --force * ##更新所有角色
ansible-galaxy install 5KYDEV0P5.skydevops-mysql ###安装角色
可以写一个yml通过角色安装mysql
---
- hosts: pxg
remote_user: root
roles:
- 5KYDEV0P5.skydevops-mysql
...
##########