ansible基础
ansible 安装
yum安装
yum -y install epel-release
sudo yum install ansible
ubuntu
$ sudo apt-get install software-properties-common
$ sudo apt-add-repository ppa:ansible/ansible
$ sudo apt-get update
$ sudo apt-get install ansible
未测试
pip 安装
sudo pip install ansible
在 /etc/ansible/hosts 中配置主机(此时需要对主机做免密访问)
192.168.1.50
aserver.example.org
bserver.example.org
测试,切换用户
ansible all -m ping #输出为直观方式
ansible all -m ping -o #输出为一行
# as bruce
$ ansible all -m ping -u bruce
# as bruce, sudoing to root
#以下新版已经改变
$ ansible all -m ping -u bruce --sudo
# as bruce, sudoing to batman
$ ansible all -m ping -u bruce --sudo --sudo-user batman
不使用公钥直接使用账号密码验证
##主机配置文件
192.168.21.119 ansible_ssh_user=root ansible_ssh_pass='123123'
192.168.21.118 ansible_ssh_user=root ansible_ssh_pass='123123'
##默认需要验证对方主机的指纹,否则执行失败,内网可以取消该设置
##
#报错:sing a SSH password instead of a key is not possible because Host Key checking is enabled and sshpass does not support this. Please add this host's fingerprint to your known_hosts file to manage this host.
#处理:
vi /etc/ansible/ansible.cfg
[defaults]
forks = 8 #执行时并发数
host_key_checking = False #不检测host key
Inventory
主机清单配置文件
主机与组
/etc/ansible/hosts
mail.example.com
[webservers] 组名
foo.example.com
bar.example.com
[dbservers]
one.example.com
two.example.com
three.example.com
badwolf.example.com:5309 #端口号不是默认
jumper ansible_ssh_port=5555 ansible_ssh_host=192.168.1.50 #通过 “jumper” 别名,会连接 192.168.1.50:5555.记住,这是通过 inventory 文件的特性功能设置的变量
[webservers]
www[01:50].example.com #一组相似的主机01:50 也可写为 1:50
[databases]
db-[a:f].example.com
[targets]
localhost ansible_connection=local
other1.example.com ansible_connection=ssh ansible_ssh_user=mpdehaan
other2.example.com ansible_connection=ssh ansible_ssh_user=mdehaan
主机变量
/etc/ansible/hosts
[atlanta]
host1 http_port=80 maxRequestsPerChild=808
host2 http_port=303 maxRequestsPerChild=909
组的变量
[atlanta]
host1
host2
[atlanta:vars]
ntp_server=ntp.atlanta.example.com
proxy=proxy.atlanta.example.com
把一个组作为另一个组的子成员
这些变量可以给 /usr/bin/ansible-playbook 使用,但不能给 /usr/bin/ansible 使用
[atlanta]
host1
host2
[raleigh]
host2
host3
[southeast:children]
atlanta
raleigh
[southeast:vars]
some_server=foo.southeast.example.com
halon_system_timeout=30
self_destruct_countdown=60
escape_pods=2
[usa:children]
southeast
northeast
southwest
northwest
分组定义Host 和Group 变量
/etc/ansible/hosts
#假设有一个主机名为 ‘foosball’, 主机同时属于两个组,一个是 ‘raleigh’, 另一个是 ‘webservers’. 那么以下配置文件(YAML 格式)中的变量可以为 ‘foosball’ 主机所用.依次为 ‘raleigh’ 的组变量,’webservers’ 的组变量,’foosball’ 的主机变量:
/etc/ansible/group_vars/raleigh
/etc/ansible/group_vars/webservers
/etc/ansible/host_vars/foosball
#/etc/ansible/group_vars/raleigh 变量的定义
---
ntp_server: acme.example.org
database_server: storage.example.org
#可以为一个主机,或一个组,创建一个目录,目录名就是主机名或组名.目录中的可以创建多个文件, 文件中的变量都会被读取为主机或组的变量.如下 ‘raleigh’ 组对应于 /etc/ansible/group_vars/raleigh/ 目录,其下有两个文件 db_settings 和 cluster_settings, 其中分别设置不同的变量
/etc/ansible/group_vars/raleigh/db_settings
/etc/ansible/group_vars/raleigh/cluster_settings
anslible-playbook变量的引用
通过inventosry 文件定义主机和主机组变量
[root@mini-install ~]# cat hosts
192.168.21.131 ansible_ssh_user=root ansible_ssh_pass='123123' key=131
192.168.21.134 ansible_ssh_user=root ansible_ssh_pass='123123' key=132
test ansible_ssh_user=root ansible_ssh_pass='123123' key=132
##playbook 文件
[root@mini-install ~]# cat variables.yml
---
- hosts: all
gather_facts: no
tasks:
- name: display hosts variables from variables
debug: msg="the {{ inventory_hostname }} Value is {{ key }}"
ansible-playbook -i hosts variables.yml
##每台主机引用了自己的变量
192.168.21.131 ansible_ssh_user=root ansible_ssh_pass='123123' key=131
192.168.21.134 ansible_ssh_user=root ansible_ssh_pass='123123' key=132
test ansible_ssh_user=root ansible_ssh_pass='123123' key=132
[nginx]
192.168.1.11[6:8]
[nginx:vars]
key=nginx
处于主机组内的主机,该组定义的变量针对所有主机,如果组内定义了变量,然后每台主机也定义了变量,如果key 不同,都可以直接引用,如果组内变量和主机变量的key一样,只用单台主机定义的变量会生效, 组内变量不会生效
通过在 /etc/ansible目录下的文件定义主机及主机组变量
/etc/ansible/
mkdir group_vars host_vars
vim host_vars/192.168.1.116 #主机名字, 和inventory 内的主机名保持一致
---
key: 1921.168.1.116
##删除主机变量,使用组变量
cat group_vars/nginx #inventory 内组的名称
---
key: NGINX
通过 命令行传入
ansible-playbook /root/variable.yaml -e "key=KEY"
支持指定文件的方式传入变量
cat var.yaml
---
key: KEY
cat var.json
{"key": "JSON"}
##
andible-playbook /root/variables.yml -e "@var.json"
andible-playbook /root/variables.yml -e "@var.yaml"
在play book 中使用vasrs
---
- hosts: all
remote_user: root
vasr:
key: ansible
在playbook中使用vars_file
---
- hosts: all
remote_user: root
vars_file:
- var.yaml
vars.yml 是变量存放的位置
使用register内的变量
ansilbe playbook 允许tasks 间传递变量
后一个task 是否执行需要判断第一个tasks 运行的后果
---
- hosts: all
remote_user: root
tasks:
- name: registes variables
shell hostname
register: info
- name: dispaly variables
debug: msg="This variables is {{ info}}"
---
- hosts: all
gather_facts: no
tasks:
- name: register
shell: hostname
register: info
- name: display hosts variables from variables
debug: msg="the variables is {{ info['stdout'] }}"
info 是一个字典类型的数据结构, 可以使用key value 的方式获取某一key 的value
变量使用vars_promt 传入
---
- hosts: all
gather_facts: no
vars_prompt:
- name: one
prompt: "plse input one value "
private: no ##交互输入可以显示出来
- name: two
prompt: "plse input two value "
default: "good" #未输入情况下默认值
private: yes #不如不显示
tasks:
- name: display one
debug: msg="the variables is {{ one }}"
- name: display two
debug: msg="the variables is {{ two }}"
playbook 循环
---
- hosts: all
gather_facts: no
tasks:
- name: display one
debug: msg="name ----->{{ item }}"
with_items:
- one
- two
- three
#with_items值是Python list 数据结构 循环读取list 内的值 key 的名称是item list里面也支持字典
---
- hosts: all
gather_facts: no
tasks:
- name: display one
debug: msg="name ----->{{ item.key1 }} value ---->{{ item.value1}}"
with_items:
- {key1: "one", value1: "value1"}
- {key1: "two", value1: "value2"}
- {key1: "three", value1: "value3"}
#key value 可以随意定义
##嵌套循环
---
- hosts: all
gather_facts: no
tasks:
- name: display one
debug: msg="name ----->{{ item[0] }} value ---->{{ item[1]}}"
with_nested:
- ['A']
- ['a','b','c']
散列loops
---
- hosts: all
gather_facts: False
vars:
user:
fengct:
name: fengct
shell: bash
test:
name: test
shell: sh
tasks:
- name: debug loops
debug: msg="name --------> {{ item.key }} keys -------> {{ item.value.name }} shell -------> {{ item.value.shell }}"
with_dict: "{{ user }}"
文件匹配循环
---
- hosts: all
gather_facts: False
tasks:
- name: debug loops
debug: msg="YAML files ---------> {{ item }}"
with_fileglob:
- /var/log/*.log
随机循环
---
- hosts: all
gather_facts: False
tasks:
- name: debug loops
debug: msg="name --------> {{ item }}"
with_random_choice:
- one
- two
- three
条件判断Loops(until:)
---
- hosts: all
gather_facts: True
tasks:
- name: debug loops
shell: cat /root/ansible
register: host
until: host.stdout.startswith("name")
retries: 5
delay: 5
文件优先匹配Loops(with_first_found:)
---
- hosts: all
gather_facts: True
tasks:
- name: debug loops
debug: msg="YAML files --------> {{ item }}"
with_first_found:
- "{{ ansible_distribution }}.yml"
- "loops.yml"
register loops (with_random_choice:)
---
- hosts: all
gather_facts: True
tasks:
- name: debug loops
shell: "{{ item }}"
with_items:
- date
- hostname
- uname
register: num
- name: SYSTEM INFO LOOPS----------->
debug: msg="{% for i in num.results %} {{ i.stdout }} {% endfor %}"
playbook默认内置变量
groups
group_names
hostvars
inventory_hotname
inventory_hostname_short
play_hosts
inventory_dir
Inventory 参数
ansible_ssh_host
将要连接的远程主机名.与你想要设定的主机的别名不同的话,可通过此变量设置.
ansible_ssh_port
ssh端口号.如果不是默认的端口号,通过此变量设置.
ansible_ssh_user
默认的 ssh 用户名
ansible_ssh_pass
ssh 密码(这种方式并不安全,我们强烈建议使用 --ask-pass 或 SSH 密钥)
ansible_sudo_pass
sudo 密码(这种方式并不安全,我们强烈建议使用 --ask-sudo-pass)
ansible_sudo_exe (new in version 1.8)
sudo 命令路径(适用于1.8及以上版本)
ansible_connection
与主机的连接类型.比如:local, ssh 或者 paramiko. Ansible 1.2 以前默认使用 paramiko.1.2 以后默认使用 'smart','smart' 方式会根据是否支持 ControlPersist, 来判断'ssh' 方式是否可行.
ansible_ssh_private_key_file
ssh 使用的私钥文件.适用于有多个密钥,而你不想使用 SSH 代理的情况.
ansible_shell_type
目标系统的shell类型.默认情况下,命令的执行使用 'sh' 语法,可设置为 'csh' 或 'fish'.
ansible_python_interpreter
目标主机的 python 路径.适用于的情况: 系统中有多个 Python, 或者命令路径不是"/usr/bin/python",比如 \*BSD, 或者 /usr/bin/python
不是 2.X 版本的 Python.我们不使用 "/usr/bin/env" 机制,因为这要求远程用户的路径设置正确,且要求 "python" 可执行程序名不可为 python以外的名字(实际有可能名为python26).
与 ansible_python_interpreter 的工作方式相同,可设定如 ruby 或 perl 的路径....
动态拉取主机
http://ansible.com.cn/docs/intro_dynamic_inventory.html
主机模式匹配
ansible <pattern_goes_here> -m <module_name> -a <arguments>
#示例
ansible webservers -m service -a "name=httpd state=restarted"
#一个pattern通常关联到一系列组(主机的集合) –如上示例中,所有的主机均在 “webservers” 组中
#patterns等同于目标为仓库(inventory)中的所有机器
all
*
#也可以写
one.example.com
one.example.com:two.example.com
192.168.1.50
192.168.1.*
#如下patterns分别表示一个或多个groups.多组之间以冒号分隔表示或的关系.这意味着一个主机可以同时存在多个组
webservers
webservers:dbservers
#所有执行命令的机器必须隶属 webservers 组但同时不在 phoenix组:
webservers:!phoenix
#执行命令有机器需要同时隶属于 webservers 和 staging 组
webservers:&staging
#“‘webservers’ 和 ‘dbservers’ 两个组中隶属于 ‘staging’ 组并且不属于 ‘phoenix’ 组的机器才执行命令”
webservers:dbservers:&staging:!phoenix
*.example.com
*.com
one*.com:dbservers #通配符和组
#group中选择对应编号的server:
webservers[0]
webservers[0-25]
#在patterns应用正则表达式,但你可以.只需要以 ‘~’ 开头即可
~(web|db).*\.example\.com
#通过 --limit 标记来添加排除条件,/usr/bin/ansible or /usr/bin/ansible-playbook都支持
ansible-playbook site.yml --limit datacenter2
#从文件读取hosts,文件名以@为前缀即可.从Ansible 1.2开始支持该功能
ansible-playbook site.yml --limit @retry_hosts.txt
ansible命令运行方式
Ad_Hoc command
如果我们敲入一些命令去比较快的完成一些事情,而不需要将这些执行的命令特别保存下来, 这样的命令就叫做 ad-hoc 命令.
Ansible提供两种方式去完成任务,一是 ad-hoc 命令,一是写 Ansible playbook.前者可以解决一些简单的任务, 后者解决较复杂的任务
Playbooks
playbook 由一个或多个 ‘plays’ 组成.它的内容是一个以 ‘plays’ 为元素的列表.
在 play 之中,一组机器被映射为定义好的角色.在 ansible 中,play 的内容,被称为 tasks,即任务.在基本层次的应用中,一个任务是一个对 ansible 模块的调用
---
- hosts: webservers
vars:
http_port: 80
max_clients: 200
remote_user: root
tasks:
- name: ensure apache is at the latest version
yum: pkg=httpd state=latest
- name: write the apache config file
template: src=/srv/httpd.j2 dest=/etc/httpd.conf
notify:
- restart apache
- name: ensure apache is running
service: name=httpd state=started
handlers:
- name: restart apache
service: name=httpd state=restarted
playbooks 基础
#hosts 行的内容是一个或多个组或主机的 patterns,以逗号为分隔符
---
- hosts: webservers
remote_user: root
#remote_user 就是账户名
#在每一个 task 中,可以定义自己的远程用户
---
- hosts: webservers
remote_user: root
tasks:
- name: test connection
ping:
remote_user: yourname
#支持从 sudo 执行命令
---
- hosts: webservers
remote_user: yourname
sudo: yes
#可以仅在一个 task 中,使用 sudo 执行命令,而不是在整个 play 中使用 sudo
---
- hosts: webservers
remote_user: yourname
tasks:
- service: name=nginx state=started
sudo: yes
#也可以登陆后,sudo 到不同的用户身份,而不是使用 root
---
- hosts: webservers
remote_user: yourname
sudo: yes
sudo_user: postgres
tasks 列表
每一个 play 包含了一个 task 列表(任务列表).一个 task 在其所对应的所有主机上(通过 host pattern 匹配的所有主机)执行完毕之后,下一个 task 才会执行.有一点需要明白的是(很重要),在一个 play 之中,所有 hosts 会获取相同的任务指令,这是 play 的一个目的所在,也就是将一组选出的 hosts 映射到 task.
在运行 playbook 时(从上到下执行),如果一个 host 执行 task 失败,这个 host 将会从整个 playbook 的 rotation 中移除. 如果发生执行失败的情况,请修正 playbook 中的错误,然后重新执行即可
每个 task 的目标在于执行一个 moudle, 通常是带有特定的参数来执行.在参数中可以使用变量(variables).
modules 具有”幂等”性,意思是如果你再一次地执行 moudle(译者注:比如遇到远端系统被意外改动,需要恢复原状),moudle 只会执行必要的改动,只会改变需要改变的地方.所以重复多次执行 playbook 也很安全.
对于 command module 和 shell module,重复执行 playbook,实际上是重复运行同样的命令.如果执行的命令类似于 ‘chmod’ 或者 ‘setsebool’ 这种命令,这没有任何问题.也可以使用一个叫做 ‘creates’ 的 flag 使得这两个 module 变得具有”幂等”特性 (不是必要的)
每一个 task 必须有一个名称 name,这样在运行 playbook 时,从其输出的任务执行信息中可以很好的辨别出是属于哪一个 task 的. 如果没有定义 name,‘action’ 的值将会用作输出信息中标记特定的 task
基本格式
tasks:
- name: make sure apache is running
service: name=httpd state=running
#两个 modudle 是 command 和 shell ,它们不使用 key=value 格式的参数
tasks:
- name: disable selinux
command: /sbin/setenforce 0
#使用 command module 和 shell module 时,我们需要关心返回码信息,如果有一条命令,它的成功执行的返回码不是0
tasks:
- name: run this command and ignore the result
shell: /usr/bin/somecommand || /bin/true
#或者
tasks:
- name: run this command and ignore the result
shell: /usr/bin/somecommand
ignore_errors: True
#如果 action 行看起来太长,你可以使用 space(空格) 或者 indent(缩进) 隔开连续的一行
tasks:
- name: Copy ansible inventory file to client
copy: src=/etc/ansible/hosts dest=/etc/ansible/hosts
owner=root group=root mode=0644
Handlers: 在发生改变时执行的操作
module 具有”幂等”性,所以当远端系统被人改动时,可以重放 playbooks 达到恢复的目的. playbooks 本身可以识别这种改动,并且有一个基本的 event system(事件系统),可以响应这种改动
当发生改动时)’notify’ actions 会在 playbook 的每一个 task 结束时被触发,而且即使有多个不同的 task 通知改动的发生, ‘notify’ actions 只会被触发一次.
#当一个文件的内容被改动时,重启两个 services
- name: template configuration file
template: src=template.j2 dest=/etc/foo.conf
notify:
- restart memcached
- restart apache
handlers:
- name: restart memcached
service: name=memcached state=restarted
- name: restart apache
service: name=apache state=restarted
#Handlers 最佳的应用场景是用来重启服务,或者触发系统重启操作
执行一个playbook
ansible-playbook playbook.yml -f 10
在执行一个 playbook 之前,想看看这个 playbook 的执行会影响到哪些 hosts
ansible-playbook playbook.yml --list-hosts
指定一个主机文件执行ansible-playbook
ansible-playbook -i hosts site.ymal
ansible roles
http://ansible.com.cn/docs/playbooks_roles.html
ansible架构模式
由控制机和被管机组成
ansible 是一个模型驱动的配置管理器,支持多节点发布,远程任务执行。默认使用ssh进行远程连接,无需在被管节点安装附加软件
ansible 默认基于推送方式
等幂性,如果系统已经处于期望的状态,则对系统什么也不做.
收敛性,指系统不需要变更或操作的特性
ansible puppet saltstack 技术特性比较
优缺点对比:
devops 是一组过程方法与系统的统称,用于促进软件开发(应用程序/软件工程), 技术运营和质量保障部门之间的沟通协助和整合
安装
ansible 配置环境
运行ansible命令时,命令将会按照预定的顺序查找配置文件,
1,ANSIBLE_CONFIG 环境变量指定的配置文件
2,./.ansible.cfg 当前目录下的配置
3,~/.ansible.cfg 当前用户下配置
4,/etc/ansible/ansible.cfg 自动产生的配置文件(安装时)
使用环境变量方式配置
1,大多数ansible 参数可以使用带有ANSIBLE_开头的环境变量进行配置,参数名必须都是大写字母
2,设置ansible.cfg
配置文件解析:
使用公钥认证
有台被管节点重新安装系统并在known_hosts 中有了与之前不同的密钥信息,就会提示一个密钥不匹配的错误
信息,
修改配置文件禁止出现:
在~/.ansible.cfg 或 /etc/ansible/ansible.cfg
[defaults]
host_key_checking = False
生成密钥配置访问
ssh-keygen
ssh-copy-id -f ~/.ssh/id_rsa.pub xxx@ip
主机配置文件
/etc/ansible/hosts
添加主机后测试,被测试的主机必须存在在该文件内
ansible 172.20.7.136 -m ping
注意:测试前必须为对方主机配置ssh 免密, 或配置文件中配置账号密码,否则会失败
ansible server -m ping
The authenticity of host '192.168.190.130 (192.168.190.130)' can't be established.
ECDSA key fingerprint is SHA256:cuGC6Brn/MfScy5YSA0M4F1WpWYHhkmyzvdhUzNz7y8.
ECDSA key fingerprint is MD5:f4:58:37:e4:03:bd:ab:9d:de:2d:e5:a4:57:9c:d5:2f.
Are you sure you want to continue connecting (yes/no)? The authenticity of host '192.168.190.129 (192.168.190.129)' can't be established.
ECDSA key fingerprint is SHA256:d9x3wF1f8FRnzlvIyGou+M83/YzPK0Dk8ZSvUQSUXEE.
ECDSA key fingerprint is MD5:57:f2:a4:18:4a:7d:a3:70:8b:1e:5c:b2:a5:9b:d1:9e.
Are you sure you want to continue connecting (yes/no)? yes
192.168.190.130 | UNREACHABLE! => {
"changed": false,
"msg": "Failed to connect to the host via ssh: Warning: Permanently added '192.168.190.130' (ECDSA) to the list of known hosts.\r\nPermission denied (publickey,password).",
"unreachable": true
}
192.168.190.129 | UNREACHABLE! => {
"changed": false,
"msg": "Failed to connect to the host via ssh: Host key verification failed.",
"unreachable": true
}
在当前目录下创建一个主机文件,执行时指定该文件
vim inventory.cfg
ansible server -m command -a '/bin/echo hello ansible!!' -i inventory.cfg
获取帮助信息
ansible-doc -l
ansible-doc -s command #查看该command模块的帮助
获取执行脚本时的详细执行信息
ansible server -m shell -a '/bin/echo hello' -vvv
ansible组件
inventory
机器的信息保存在inventory中, ansible 默认的inventory 是静态Ini 文件 /etc/ansible/hosts
可以通过ANSIBLE_HOSTS环境变量指定或者运行ansible 和ansible-playbook 时用-i 临时指定
1,定义主机和主机组
172.17.42.101 ansible_ssh_pass='123456' #内置变量定义密码
[docker] #组
172.17.42.10[1:3] #101-103
[docker:vars] #使用内置变量定义密码
ansible_ssh_pass='123456'
[ansible:children] #定义一个组叫ansible ,这个组下面包含docker 组
docker
invnetory 文件用来定义远端主机的的认证信息, ssh登录密码,用户名,及KEY ,添加完主机和主机组后可以使用命令针对主机进行操作和管理.
验证主机的联通性
ansible server -m ping -o
多个Inventory列表
需要修改ansible.cfg 中hosts 文件的定义, 或者使用ANSIBLE_HOSTS 环境变量定义,
准备一个目录,里面存放多个Inventory 文件
tree inventory/
inventory/
|____docker
|____hosts
#不同的文件存放不同的主机
cat inventory/docker
172.17.42.101 ansible_ssh_pass='123456'
172.17.42.101 ansible_ssh_pass='123456'
cat inventory/hosts
172.17.42.10[1:3]
[docker:vars]
ansible_ssh_pass='123456'
[ansible:children]
docker
##修改ansible.cfg 的配置文件 inventory 的值指向一个目录
inventory = /root/inventory/
##验证
ansible 172.17.41.101:172.17.41.102 --list-hosts
ansible docker --list-hosts
ansible ansible --list-hosts
ansible Ad_Hoc 命令
ansible-doc -l
ansible-doc "模块名"
ansible 命令都是并发执行的,默认并发数目由ansible.cfg 中的forks 设置 也可在运行中有 -f指定, 碰到执行任务时间很长的可以使用异步执行,
ansible server -m shell -a "hostname" -o
ansible server -m shell -a "uname -r" -f5 -o
异步执行示例:
ansible server -B 120 -P 0 -m shell -a "sleep 10;hostname" -f5 -o
#需要根据job_id 查询状态, -P 0
ansible 192.168.190.130 -m async_status -a "jid=742612762330.6634"
#当-P 不等于0
ansible server -B 120 -P 1 -m shell -a "sleep 10;hostname" -f5
自动根据job_id 去轮询查询执行结果
ansible 模块
复制文件
使用copy 模块批量下发文件,文件的变化是通过MD5值判断的
包和服务管理
-m yum
用户管理
-m user
#ansible user 的passwd 参数需要接受加密后的值
echo ansible | openssl passwd -1 -stdin
ansible docker -m user -a 'name=shencasn password="$1$vMJhzc8I$68DpG2Wz2nCjA51hVzLjf0"'
ansible facts
facts 组件是用于采集被管机器设备信息, 使用setup 模块查询所有facts 的信息,使用filter 查看指定信息,
ansible server -m setup -a 'filter=ansible_all_ipv4_addresses'

浙公网安备 33010602011771号