1.安装Ansible软件
yum -y install epel-release
yum -y install ansible
2. 配置ansible管理节点和主机节点的连接
其实就是配置从管理节点到远程主机之间基于密钥(无密码的方式)的SSH连接。
#生成ssh密钥
ssh-keygen
#复制SSH的公钥到远程主机,这样SSH的时候就不用输入密码了,实现免密连接
ssh-copy-id remoteuser@remoteserver
#SSH的时候不会提示是否保存密钥
ssh-keyscan remore_servers >> ~./ssh/known_hosts
验证SSH配置:
在管理节点执行下面的SSH命令,既不需要输入密码,也不会提醒你存储密钥,那就成功啦。
ssh remoteuser@remoteserver
二、Ansible管理哪些主机
Ansible需要知道自己可以管理的主机有哪些,以及一些连接参数,它由主机目录配置文件来管理。
1. 什么是主机目录
主机目录(Host Inventory, 又称主机清单)是配置文件,用来告诉Ansible需要管理哪些主机,并把这些主机按需分类。
例如,可以根据用途分类为数据库节点、服务节点等,也可以根据地点分类为中部机房、西部机房等。
2. 主机目录配置文件
默认的文件是 /etc/ansible/hosts
当然也可以修改为其他的文件。
最简单的hosts 示例:
代码语言:javascript复制192.168.93.110
aserver.example.org
bserver.example.org
带分组的Hosts文件示例:
代码语言:javascript复制[webserver]
foo.example.org
bar.example.org
[dbserver]
one.example.com
two.example.com
三、Ansible用命令管理主机-Ad-Hoc
Ansible 提供了一个命令行工具,在官方文档中给命令行起了一个名字叫 Ad-Hoc Commands。
1. Ansible命令行格式
代码语言:javascript复制ansible <host-pattern> [options]
- 检查ansible安装环境
检查所有的远程主机,是否以“yuki”用户创建了Ansible管理主机可以访问的环境:
代码语言:javascript复制ansible all -m ping -u bruce
- 执行命令
在所有远程主机上,默认以当前Bash的同名用户,在远程主机执行“echo hello”:
代码语言:javascript复制ansible all -a "/bin/echo hello"
- 复制文件
复制文件/etc/hosts到远程主机(组)“Web”,位置为/tmp/hosts:
代码语言:javascript复制ansible web -m copy -a "src=/etc/hosts dest=/tmp/hosts"
- 安装包
在远程主机(组)“Web”上安装yum包:
代码语言:javascript复制ansbile web -m yum -a "name=httpd state=present"
- 添加用户
ansible all -m user -a "name=yuki password=<crypted password here>"
- 下载git仓库
ansbile web -m git -a "repo=git://foo.example.org/repo.git dest=/srv/myapp version=HEAD"
- 启动服务
ansbile web -m service -a "name=httpd state=started"
- 并行执行
-f 10代表启动10台机器并行重启:
代码语言:javascript复制ansbile lb -a "/sbin/reboot" -f
- 查看远程主机的全部系统信息
ansbile all -m setup
四、Ansible用脚本管理主机-Playbook
代码语言:javascript复制为了避免重复的输入命令,Ansbile提供了脚本功能。Ansible脚本的名字叫Playbook,使用的是YAML格式,文件以yml或 yaml为后缀。
1. 执行playbook的方法
代码语言:javascript复制ansible-playbook deploy.yml
2. Playbook语法介绍
Playbook包含了几个关键字,每个关键字的含义如下:
- hosts : 某主机的IP,或者主机组的名字,或者关键字all
- remote_user : 以某个用户身份执行
- var : 变量
- tasks : Playbook 的核心,定义顺序执行的动作Action。每个Action调用一个Ansible模块。action的语法:
module: module_parameter=module_value
- handers : Playbook的event处理操作,有且仅有在被Action触发时才会执行。但多次触发只执行一次,并按照声明的顺序执行。
以下是一个为主机组Web部署Apache的deploy.yml文件,部署步骤如下:
- 安装apache包
- 复制配置文件httpd,并保证复制文件后,Apache服务会被重启
- 复制默认的网页文件index.html
- 启动Apache服务
---
- hosts: web
vars:
http_port:
max_clients:
remote_user: root
tasks:
- name: ensure apache is at the latest version
yum: pkg=httpd state=latest
- name : Write the configuration file
template: src=templates/httpd.comf.j2 dest=/etc/httpd/conf/httpd.conf
notify: #notify中调用handler中定义的操作
- restart apache
- name: Write the default index.html file
template: scr=templates/index.html.j2 dest=/var/www/html/index.html
- name: ensure apache is running
service: name=httpd state=started
handlers:
- name: restart apache
service: name=httpd state=restarted
五、Ansible模块
1. 什么是Ansible模块
bash无论是在命令行上执行,还是在bash脚本中,都需要调用cd,ls,yum,cp等命令。模块就是Ansible的“命令”。模块是Ansible-hocAd命令行和[Playbook脚本中都需要调用的。常用的Ansbile模块有yum、copy、template等。
bash在调用命令时可以跟不同的参数,每个命令的参数都是该命令自定义的。同样,Ansible中调用模块也可以跟不同的参数,每个模块的参数也都是由模块自定义的。
可以通过命令ansible-doc <module_name>查看具体某个模块的用法。
Ansible会提供一些常用的模块,同时Ansible也提供API,让用户可以自己写模块,使用的编程语言是Python。
2.在命令行里使用模块
在命令行中:
-m 后面接调用模块的名字
-a 后面接调用模块的参数
代码语言:javascript复制#使用模块copy复制文件/etc/hosts到远程主机(组)“Web”,位置为/tmp/hosts:
ansible web -m copy -a "src=/etc/hosts dest=/tmp/hosts"
#使用模块yum在远程主机(组)“Web”上安装yum包:
ansbile web -m yum -a "name=httpd state=present"
3. 在playbook脚本中使用模块
在playbook中,tasks中的每一个action都是对模块的一次调用。在每个action中:
冒号前面是模块的名字
冒号后面是调用模块的参数
代码语言:javascript复制---
tasks:
- name: ensure apache is at the latest version
yum: pkg=httpd state=latest
- name : Write the configuration file
template: src=templates/httpd.comf.j2 dest=/etc/httpd/conf/httpd.conf
- name: ensure apache is running
service: name=httpd state=started
4. Ansible常用模块
- ping 模块
测试远程节点的SSH连接是否就绪。但它并不像Linux命令那样简单地ping以下远程节点,而是先检查能否通过SSH登录远程节点,再检查其Python版本能否满足要求,如果都满足则返回pong , 表示成功。
ping无需任何参数
代码语言:javascript复制ansible all -m ping
- debug 模块
打印输出信息,类似于Linux上的echo命令
1)通过参数 msg定义打印的字符串
msg中可以嵌入变量,下面的例子中注入了系统变量,Ansible在执行playbook之前会收集一些比较常用的系统变量,这个在playbok中不需要定义直接使用就可以。
代码语言:javascript复制---
- hosts: all
remote_user: root
tasks:
- debug:
##打印字符串
msg: "System {{inventory_hostname}} has gateway {{ansible_default_ipv4.gateway}}."
2)通过参数var定义需要打印的变量
变量可以是系统变量,也可以是动态的执行结果,通过关键字register注入到变量中。
打印系统变量的值:
代码语言:javascript复制---
- hosts: all
remote_user: root
tasks:
- debug: #打印远程主机的网关
var: hostvars[inventory_hostname]["ansible_default_ipv4"]["gateway"]
打印动态注入的变量的值:
代码语言:javascript复制---
- hosts: all
remote_user: root
tasks:
- shell: /usr/bin/uptime
register: result
- debug:
var: result
- Copy 模块
从当前的机器上复制文件到远程主机节点上,并设置合理的文件权限。注意:copy模块在复制文件的时候,会先比较一下文件的checksum,如果相同则不会复制,返回状态为OK;如果不同才会复制,返回状态为changed。
1)可以利用mode设置copy过去的文件权限:
代码语言:javascript复制---
- hosts: all
remote_user: root
tasks:
- copy:
src: /tmp/testfile_Yuki
dest: /root/testfile_Yuki
owner: root
group: root
mode: 0644
2)备份原来节点上的文件
backup参数为yes的时候,如果发生了复制(copy)操作,那么会先复制目标节点上的源文件。当两个文件相同时,不再进行复制操作。
代码语言:javascript复制---
- hosts: all
remote_user: root
tasks:
- copy:
src: /tmp/testfile_Yuki
dest: /root/testfile_Yuki
backup: yes
3)复制后的验证操作
validate参数接需要验证的命令。一般需要验证复制后的文件,所以%s都可以指代复制后的文件。当copy模块加入了validate后,不仅需要成功复制文件,还需要validate命令返回成功的状态,整个模块的执行才算成功。
代码语言:javascript复制---
- hosts: all
remote_user: root
tasks:
- copy:
src: /tmp/testfile_Yuki
dest: /root/testfile_Yuki
validate: 'ls -ld %s'
- template 模块
如果复制的只是静态文件,那么用copy模块就够了。如果在复制的同时需要根据实际情况修改部分内容,那么就需要用到template模块了。
代码语言:javascript复制---
- hosts: all
remote_user: root
tasks:
- template:
src: /root/template
dest: /root/template
其中template文件的内容为:
代码语言:javascript复制[root@ansible ~]# cat template
The hostname: {{ ansible_hostname }}
The IP is: {{ ansible_default_ipv4.address }}
[root@ansible ~]#
执行结果:(在目标机上看到文件里面的变量被实际值替换)
template 也具体和copy一样的功能,如:设置文件权限、文件备份,以及验证功能。
代码语言:javascript复制---
- hosts: all
remote_user: root
tasks:
- template:
src: /root/template
dest: /root/template
owner: root
group: root
mode: '0755'
validate: 'ls -ld %s'
backup: yes
- file 模块
file模块可以用来设置远程主机上的文件、软连接和文件夹的权限,也可以用来创建和删除他们。
1)改变文件的权限
代码语言:javascript复制---
- hosts: all
remote_user: root
tasks:
- file:
path: /root/testfile_Yuki
owner: yuki
group: users
mode: '0644'
#mode: "u=rw,g=r,o=r"
2)创建文件的软链接
注意:这里src和dest参数的含义和copy模块中的不一样,file模块里面所操作的文件都是远程节点上的文件。
代码语言:javascript复制---
- hosts: all
remote_user: root
tasks:
- file:
src: /root/testfile_Yuki
dest: /root/testfile_Yuki.link
owner: root
group: root
mode: '0644'
state: link
运行结果:
3)创建一个新文件
和touch命令一样创建一个新文件
代码语言:javascript复制---
- hosts: all
remote_user: root
tasks:
- file:
path: /root/yuki
owner: root
group: root
mode: '0644'
state: touch
运行结果:
4)创建新的文件夹
代码语言:javascript复制---
- hosts: all
remote_user: root
tasks:
- file:
path: /root/yuki_dir
owner: root
group: root
mode: '0755'
state: directory
运行结果:
- User 模块
user模块可以增、删、改Linux远程节点的用户账户,并为其设置账户的属性。
1)增加用户
代码语言:javascript复制---
- hosts: all
remote_user: root
tasks:
- user:
name: yuki1
group: users
comment: "For Yuki use"
shell: /bib/bash
append: yes
运行结果:
2)删除用户
代码语言:javascript复制---
- hosts: all
remote_user: root
tasks:
- user:
name: yuki1
state: absent
remove: yes
运行结果:
3)修改用户的属性
为用户yuki1创建一个2048位的SSH密钥,放在家目录下的.ssh/id_rsa中
代码语言:javascript复制---
- hosts: all
remote_user: root
tasks:
- user:
name: yuki1
generate_ssh_key: yes
ssh_key_bits: 2048
ssh_key_file: .ssh/id_rsa
运行结果:
- yum 模块
yum模块是用来管理Redhat系的Linux上的安装包的。
1)从yum源上安装和删除包
安装最新版本的包,如果已经安装了老版本,那么会更新到最新的版本:
代码语言:javascript复制---
- hosts: all
remote_user: root
tasks:
- name: install the latest version of apache
yum:
name: httpd
state: latest
安装指定版本的包:
代码语言:javascript复制---
- hosts: all
remote_user: root
tasks:
- name: install the latest version of apache
yum:
name: httpd-2.2.29-1.4.amznl
state: present
删除httpd包:
代码语言:javascript复制---
- hosts: all
remote_user: root
tasks:
- name: remove the Apache package
yum:
name: httpd
state: absent
2)从yum源上安装一组包
代码语言:javascript复制---
- hosts: all
remote_user: root
tasks:
- name: install the "Development tools" packages group
yum:
name: "@Development tools"
state: present
- name: install the "Gnome desktop" packages group
yum:
name: "@gnome-desktop-environment"
state: present
3)安装本地rpm包
代码语言:javascript复制---
- hosts: all
remote_user: root
tasks:
- name: install the nginx package from the local file
yum:
name: /root/nginx****.rpm
state: present
4)从URL中安装包
---
代码语言:javascript复制- hosts: all
remote_user: root
tasks:
- name: install the nginx package from a remote repo
yum:
name: http://nginx.org/packages/****/nginx***.rpm
state: present
- service 服务管理模块
该模块用来管理远程节点上的服务,如:httpd、sshd、nfs、crond 等
1)开、关、重启、重载服务
开启服务:
---
- hosts: all
remote_user: root
tasks:
- name: Start mariadb service
service:
name: mariadb
state: started
运行结果:
关服务:
代码语言:javascript复制---
- hosts: all
remote_user: root
tasks:
- name: Stop mariadb service
service:
name: mariadb
state: stopped
重启服务:
代码语言:javascript复制---
- hosts: all
remote_user: root
tasks:
- name: Restart mariadb service
service:
name: mariadb
state: restarted
重载服务:
---
- hosts: all
remote_user: root
tasks:
- name: Reload mariadb service
service:
name: mariadb
state: reloaded
2)设置服务开机自启:
代码语言:javascript复制---
- hosts: all
remote_user: root
tasks:
- name: Enable mariadb service
service:
name: mariadb
enabled: yes
3)启动网络服务下的接口:
代码语言:javascript复制---
- hosts: all
remote_user: root
tasks:
- service:
name: network
state: restarted
args: eth0
代码语言:javascript复制firewalld模块
firewall模块为某服务和端口添加firewalled规则。firewalld中有正在运行的规则和永久的规则,firewalled规则都支持。
1)为服务添加firewalld规则:
代码语言:javascript复制---
- hosts: all
remote_user: root
tasks:
- firewalld:
service: https
permanent: true
state: enabled
代码语言:javascript复制---
- hosts: all
remote_user: root
tasks:
- firewalld:
zone: dmz
service: http
permanent: true
state: enabled
2)为端口号添加firewalld规则
代码语言:javascript复制---
- hosts: all
remote_user: root
tasks:
- firewalld:
port: 8081/tcp
permanent: true
state: disabled
代码语言:javascript复制shell模块
在远程节点上通过/bin/sh执行命令。如果一个操作可以通过yum、copy实现,那么建议不要使用shell或者command这样通用的命令模块。因为通用的命令模块不会根据具体操作的特点进行状态判断,所以当没有必要再重新执行的时候,它还是会重新执行一遍。
1)支持HOME、"<" 、">"、"|" 、";" 、">>" 、"&&"等
代码语言:javascript复制---
- hosts: all
remote_user: root
tasks:
- name: execute shell command
shell: echo $HOME > /tmp/result
运行结果:
2)执行脚本,在执行命令前改变工作目录,并且仅在somelog.txt不存在时执行命令。
代码语言:javascript复制---
- hosts: all
remote_user: root
tasks:
- name: execute shell command
shell: somescripts.sh >> somelog.txt
args:
chdir: somedir/
creates: somelog.txt
指定用bash执行命令:
代码语言:javascript复制---
- hosts: all
remote_user: root
tasks:
- name: execute shell command
shell: cat /home/yuki/testfile
args:
executable: /bin/bash
- command 模块
在远程节点上执行命令。和shell模块类似,但不支持HOME、"<" 、">"、"|" 、";" 、">>" 、"&&"等操作。
1)以shell模块相同之处
都可以调用单条命令
都可以在执行命令前改变目录,并仅在某个文件(如:somelog.txt)不存在时再执行。
代码语言:javascript复制---
- hosts: all
remote_user: root
tasks:
- command: ls -ld /home/yuki/testfile > somelog.txt
args:
chdir: somedir/
creates: somelog.txt
2)和shell命令不同之处
command模块多了一个传参方式
command模块不支持"&&"和">>"
代码语言:javascript复制- command: ls -ld /home/yuki/test.sh arg1 arg2
今天先介绍到这里,未完待续,敬请期待!
参考资料:
Ansible快速入门, 技术原理与实战。