2.1 安装
#!/bin/bash ################################################################################ # 远程主机 ################################################################################ # 远程主机无需做过多的配置,只需启动SSH服务,并且具有Python 2.4以上的环境。 ################################################################################ # 管理节点 ################################################################################ # 安装Ansible yum install -y epel-release.noarch yum install -y ansible # 配置「管理节点」到「远程主机」的连接 # 即SSH连接(这里配置的是密钥连接,而不是密码连接。在Ansible中,这两种都是可以的。) ssh-keygen ssh-copy-id username@hostname ssh-keyscan hostname >> ~/.ssh/known_hosts # 测试SSH连接 ssh username@hostname
2.2 设置要管理的主机
接下来,需要指定要被Ansible管理的主机:“主机目录(Host Inventory)”,一个配置文件,/etc/ansible/hosts,指定了被管理的主机,内容如下:
# 被管理的主机列表 a.example.com b.example.com c.example.com # “[dbserver]”,定义名为dbserver的主机组,指定“dbserver”等价于指定了dbserver部分下的所有主机 [dbserver] db0.example.com db1.example.com db2.example.com # 同“[dbserver]”,定义主机组。 [webserver] web0.example.com web1.example.com web2.example.com
2.3 使用命令管理主机
Ansible提供了命令行工具,称为“Ad-Hoc Commands”。
命令通常是ansible <host-pattern> [options]格式。下面是几个命令示例:
# 检查所有的远程主机,是否存在可以访问远程主机的bruce用户 ansible all -m ping -u bruce # 以管理节点的当前登录用户名,在远程主机上执行命令 ansible all -a "/bin/echo hello" # 复制文件 ansible web -m copy -a "src=/etc/hosts dest=/tmp/hosts" # 安装软件包 ansible web -m yum -a "name=acme state=present" # 添加用户 ansible all -m user -a "name=foo password=<crypted password>" # 从仓库检出代码 ansible web -m git -a "repo=git://src.exammple.com/project.git dest=/srv/http/project version=HEAD" # 启动服务 ansible web -m service -a "name=httpd state=started" # 并行执行任务,启动10个进程执行任务。 ansible lb -a "/sbin/reboot" -f 10 # 查看远程主机的信息 ansible all -m setup
2.5 模块
什么是模块?
在Shell中,我们会执行cp、ls、mv、rm、yum等命令,进行复制、查看、用户管理、权限管理、服务管理等日常操作。
在Ansible中,既然是批量管理主机,那肯定也会进行复制、查看、服务管理等等操作。在Ansible中,完成这些操作的不是“命令”,而是称为“模块”的东西。例如,文件复制使用copy模块;软件安装使用yum模块;用户管理使用user模块;服务管理使用service模块等等。
如何使用模块?
每个模块都有自己的选项,如同Shell命令一样。
使用ansible-doc <module_name>进行查看模块手册,或者查看官方「Module Index」手册。
使用ansible-doc -l列出当前所有可用模块,并显示一句话描述模块的作用。
下面是「在命令行中」使用模块的示例:
#!/bin/bash # 使用模块copy,复制管理节点文件/etc/hosts到所有远程主机/tmp/hosts ansible all -m copy -a "src=/etc/hosts dest=/trnp/hosts" # 使用模块yum,在远程主机 Web 上安装 httpd 包 ansible web -rn yum -a "narne=httpd state=present"
上述两个命令中,参数all与web是主机组,在/etc/ansible/hosts中进行配置;选项-m指定要使用的模块;选项-a指定要传递给模块的参数;
下面是「在Playbook中」使用模块的示例:
--- tasks: - name: ensure apache is at the latest version yum: pkg=httpd state=latest - name: write the apache config file template: src=ternplates/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf - name: ensure apache is running service: name=httpd state=started
在Playbook中,指令tasks中的每一个“动作(Action)”都是对模块的一次调用。在每个动作中:
- 参数name指定了动作的描述;
- 每个动作的第二行则是要执行的动作。冒号前面是模块的名字。冒号后面是调用模块的参数。
模块的总结:
- 模块既可以在命令行中指定,也可以在Playbook中指定;
- 模块作用与参数与所使用的模块有关,使用之前参阅文档;
- 使用ansible-doc <module_name>进行查看模块手册,或者查看官方「Module Index」手册;
- Ansible提供了一些常用的模块,用户也可以更具自己的需要开发自己的模块。
常用模块示例
debug:用于调试的模块,只是简单打印 些消息 , 有点像 Linux 的 echo 命令。
template:从本地复制文件到远程节点 , 并进行变量的替换。
file:设置文件属性。
yum:RedHat系列的发行版上的包管理。
service:管理服务。
firewalld:管理防火墙中的服务和端口。
command:在远程节点上执行命令 ,不支持“$HOME” 、“<”、 “>“
模块:ping
测试能否通过SSH连接远程主机,并且远程主机的Python版本是否满足要求。如果成功则返回“pong”。
#!/bin/bash ansible all -m ping
模块:debug
打印信息,类似于Linux中的echo命令。
- hosts: all remote_user: root tasks: - name: "debug module" debug: msg: "System {{ inventory_hostname }} has gateway {{ ansible_default_ipv4.gateway }}"
{{ inventory_hostname }}与{{ ansible_default_ipv4.gateway }}会被自动替换成变量,这些变量是由Ansible在执行Playbook之前注入的,不需要定义即可使用。
变量可以是系统变量 ,也可以是动态的执行结果。如下示例,通过regester关键字将执行结果注入result变量中,然后使用debug模块打印:
- hosts: all remote_user: root tasks: - name: "debug module register" shell: /usr/bin/uptime register: result - name: "debug module var" debug: var: result
模块:copy
复制「本地」文件到「远程」主机。该模块会比较文件校验和,如果相同则不会复制,并返回OK,如果不同则进行复制,并返回changed。
- hosts: all remote_user: root tasks: - name: "module copy" template: src: /etc/sudoers dest: /tmp/sudoers.backup backup: yes owner: root group: root mode: 0600 validate: 'visudo - cf %s'
与之前的例子类似,name为动作的描述;src是本地文件位置;dest为远程主机文件保存位置;backup表示文件存在则进行备份,文件名追加时间形式的后缀;owner指定所有者;group指定所属组;mode指定权限;validate对文件进行校验,参数为命令,并且只有命令以“0”退出,则表示复制成功,%s代表文件。
模块:template
复制静态文件很简单。但有时复制文件的时,我们需要根据远程主机的当前配置调整文件的内容(比如需要在配置文件中设置当前主机的IP地址)。这时候就可以使用template模块。该模块使用Jinja2模板引擎,使用{{ var_name }}来表示变量。文件/tmp/index.html.j2的内容如下:
<h1>PORT: {{ http_port }}<h1/> <p>Served by {{ ansible_hostname }} ({{ ansible_default_ipv4.address }}) . </p>
下面是Playbook的内容:
- hosts: all vars: http_port: 80 remote_user: root tasks: - name: "module copy" template: src: /tmp/index.html.j2 dest: /tmp/index.html backup: yes owner: root group: root mode: 0600
如上示例,/tmp/index.html.j2为模板文件,使用的两个变量ansible_hostname和ansible_default_ipv4.address都是远程主机的系统变量,可以直接使用,http_port是环境变量,使用var关键字进行定义,并且template模块具有和copy模块类似的备份、所有权、模式设定等等功能。
模块:file
设置远程主机上的文件、目录、软链接的权限,也可以创建和删除它们。
- hosts: all remote_user: root tasks: - name: "创建文件夹" file: state: directory path: /tmp/module-file mode: 0755 - name: "创建文件" file: state: touch path: /tmp/module-file/foo.txt - name: "创建到文件的软链接" file: state: link src: /tmp/module-file/foo.txt dest: /tmp/module-file/link-to-foo.txt owner: root group: root - name: "修改文件权限" file: path: /tmp/module-file/foo.txt owner: root group: root # mode: "u=rw,g=r,o=r" # mode: "u+w,a-x" mode: 0600
模块:user
用于管理系统的用户账户,并且设置相关的属性。
- hosts: all remote_user: root tasks: - name: "创建用户" user: name: zheng comment: "Mr. Zheng" # 设置UID uid: 1040 # 设置默认的Shell shell: /bin/bash # 设置组 group: root # 追加两个附属组,而不是覆盖原由附属组 groups: bin, daemon append: yes # 为用户添加过期时间。使用date --date '2019-01-10' +%s命令生成 expires: 1547049600 # 为账户 jsmith 创建一个 2048 位的 SSH 密钥 , 放 在~jsmith/.ssh/id_rsa 中 。 generate_ssh_key: yes ssh_key_bits: 2048 ssh_key_file: .ssh/id_rsa - name: "删除用户" user: name: zheng state: absent remove: yes
模块:yum
用于在RHEL、CentOS、Fedora21等系统发行版中管理软件包。
- hosts: all remote_user: root tasks: - name: "使用URL安装软件包" yum: name: http://nginx.org/packages/centos/7/x86_64/RPMS/nginx-1.14.2-1.el7_4.ngx.x86_64.rpm state: present - name: "安装本地包" yum: name: /tmp/nginx-1.14.2-1.el7_4.ngx.x86_64.rpm state: present - name: "安装软件包组" yum: name: "@gnome-desktop-environment" state: present - name: "安装指定仓库中的包" yum: name: httpd enablerepo: testing state: present - name: "安装最后一个版本的Apache服务" yum: name: httpd state: latest - name: "安装指定版本的Apache服务" yum: name: httpd-2.2.29-1.4.amznl state: present - name: "删除软件包" yum: name: httpd state: absent
模块:service
用于管理服务器中的服务,进行启动、重启、开机启动等操作。
- hosts: all remote_user: root tasks: - name: "启动" service: name: httpd state: started - name: "停止" service: name: httpd state: stopped - name: "重新启动" service: name: restarted state: - name: "开机启动" service: name: httpd enabled: yes - name: "重新启动网络服务" service: name: network state: restarted args: eth0
模块:firewalld
用于添加防火墙规则,这要求远程远程主机的firewalld的版本在0.2.11以上。
- hosts: all remote_user: root tasks: - name: "允许HTTPS请求" firewalld: service: https permanent: true state: enable - name: "允许HTTP请求" firewalld: zone: dmz service: https permanent: true state: enable - name: "禁用TCP端口" firewalld: port: 8081/tcp permanent: true state: disable - name: "启用UDP端口" firewalld: port: 162-189/udp permanent: true state: enable
模块:shell
使用/bin/sh执行命令,如果一个命令能通过其他模块完成,则不建议使用shell模块。因为shell模块的状态判断能力比较弱。
- hosts: all remote_user: root tasks: - name: "支持 $HOME 、<、>、|、;、& 操作符号" shell: service jboss start && chkconfig jboss on - name: "支持脚本调用" shell: somescript.sh > somelog.txt - name: "执行命令前改变工作目录" shell: somescript.sh > somelog.txt args: chdir: somedir/ - name: "执行命令前改变工作目录,并且仅在文件 some_log.txt 不存在时执行命令" shell: somescript.sh > somelog.txt args: chdir: somedir/ creates: somelog.txt - name: "使用Bash运行命令" shell: cat < /tmp/\*txt args: executable: /bin/bash
模块:command
该模块与shell模块类似,但是不支持 $HOME 、<、>、|、;、& 操作符号。
- hosts: all remote_user: root tasks: - name: "调用单条命令" command: /sbin/shutdown -t now - name: "执行命令前改变工作目录,并且仅在文件不存在时执行命令" command : /usr/bin/make_database.sh argl arg2 args: chdir: somedir/ creates: /path/to/database - name: "另外一种传参方式" command: /sbin/shutdown -t now creates=/path/to/database