文章目录
ansible上手指南
ansible可以用于批量化地配置管理系统,远程执行命令
ansible是一个同时管理多个主机的软件,必须是任意可以通过ssh登录的机器,基于python编写
- 远程虚拟机
- 物理机
- 本机机器
ansible最大的特点是无需在被管理端安装客户端,仅仅使用ssh服务即可(不额外占用端口),不使用root也可以执行,并且可以使用yaml配置文件语法
此处有三台虚拟机,此处机器操作系统为CentOS8
node1 192.168.84.5 安装了ansible的机器
node2 192.168.84.6
node3 192.168.84.7
配置yum、epel源
此处机器操作系统为 CentOS8
请务必检查:(这里CentOS8与CentOS7是相同的)
本机 /etc/sysconfig/network-scripts/ifcfg-ens33 文件配置正确
DNS服务器正常,文件位置:/etc/resolv.conf
检查防火墙与SELinux服务
否则可能出现以下问题
[root@node2 yum.repos.d]# ping www.baidu.com ping: www.baidu.com: 未知的名称或服务
导致 /etc/yum.repos.d/CentOS-Base.repo 文件
一、配置阿里云yum源
1.备份原有yum源配置文件
sudo mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak
2.下载阿里云CentOS 8 yum源配置文件
sudo curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-8.repo
3.清理与生成缓存
#清理缓存
sudo yum clean all
#生成缓存
sudo yum makecache
二、配置EPEL源
1.安装EPEL源的GPG密钥
sudo rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
2.安装EPEL源的yum配置文件
sudo yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm
3.替换EPEL源的yum配置文件为阿里云镜像
sudo sed -i 's|^#baseurl=https://download.fedoraproject.org/pub|baseurl=https://mirrors.aliyun.com|' /etc/yum.repos.d/epel*
sudo sed -i 's|^metalink|#metalink|' /etc/yum.repos.d/epel*
4.清理与生成缓存
#清理缓存
sudo yum clean all
#生成缓存
sudo yum makecache
三、检查可用的yum仓库
yum repolist
管理端安装ansible
#因为ansible无需额外配置,所以此处使用yum直接安装
#需提前配置好阿里云yum、epel源
yum install -y epel-release
yum install ansible libselinux-python -y
检查ansible的安装情况
#查询ansible软件安装情况,查询配置文件和可执行命令
[root@node1 ~]# rpm -ql ansible | grep -E '^/etc|^/usr/bin'
/etc/ansible
/etc/ansible/ansible.cfg
/etc/ansible/hosts
/etc/ansible/roles
/usr/bin/ansible
/usr/bin/ansible-2
/usr/bin/ansible-2.7
/usr/bin/ansible-config
/usr/bin/ansible-connection
/usr/bin/ansible-console
/usr/bin/ansible-console-2
/usr/bin/ansible-console-2.7
/usr/bin/ansible-doc
/usr/bin/ansible-doc-2
/usr/bin/ansible-doc-2.7
/usr/bin/ansible-galaxy
/usr/bin/ansible-galaxy-2
/usr/bin/ansible-galaxy-2.7
/usr/bin/ansible-inventory
/usr/bin/ansible-playbook
/usr/bin/ansible-playbook-2
/usr/bin/ansible-playbook-2.7
/usr/bin/ansible-pull
/usr/bin/ansible-pull-2
/usr/bin/ansible-pull-2.7
/usr/bin/ansible-vault
/usr/bin/ansible-vault-2
/usr/bin/ansible-vault-2.7
检查ansible版本
[root@node1 ~]# ansible --version
ansible 2.9.27
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python2.7/site-packages/ansible
executable location = /usr/bin/ansible
#本机的python解释器版本为2.7.5
python version = 2.7.5 (default, Oct 14 2020, 14:45:30) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)]
被管理端安装ansible模块
yum install epel-release libselinux-python -y
ansible使用
ansible配置文件
- 位置: /etc/ansible/ansible.cfg
配置hosts文件(需要管理的主机)
-
vim /etc/ansible/hosts
添加如下信息
[fishpie] #分组名字,可以 [] 内自定义
192.168.84.6 #node2
192.168.84.7 #node3
ssh密码验证
直接利用ssh服务来管理需要操控的对象
-m 指定功能模块,默认就是command
-a 告诉模块需要执行的参数
-k 使用密码验证
-u 指定登录用户
#此处的fishpie就是hosts文件中的分组
ansible fishpie -m command -a 'hostname' -k -u root
可能会出现一下问题
[root@node1 ansible]# ansible fishpie -m command -a 'hostname' -k -u root
SSH password:
192.168.84.6 | FAILED | rc=-1 >>
Using 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.
192.168.84.7 | FAILED | rc=-1 >>
Using 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.
解决方法:
- 将目标主机的指纹添加到SSH的known_hosts文件中
ssh root@192.168.84.6 ssh root@192.168.84.7 …(手动全部连接一遍) - 在Ansible的ansible.cfg配置文件中,禁用主机密钥检查
在 /etc/ansible/ansible.cfg 文件中添加或放行 host_key_checking = False
第一种方法较为麻烦,但是稍微安全一些,在可信环境下,可以使用第二种
连接成功后
[root@node1 ansible]# ansible fishpie -m command -a 'hostname' -k -u root
SSH password:
192.168.84.7 | CHANGED | rc=0 >>
node3
192.168.84.6 | CHANGED | rc=0 >>
node2
配置免密登录
方式一:直接在hosts文件添加ssh用户与密码(不是很安全)
-
vim /etc/ansible/hosts
改动以下内容
[fishpie]
192.168.84.6 ansible_user=root ansible_ssh_pass=123456 #指定ssh连接用户名与密码
192.168.84.7 ansible_user=root ansible_ssh_pass=123456 #指定ssh连接用户名与密码
此时执行命令可直接跳过指定用户与密码
[root@node1 ansible]# ansible fishpie -a 'hostname'
192.168.84.7 | CHANGED | rc=0 >>
node3
192.168.84.6 | CHANGED | rc=0 >>
node2
方式二:在管理机上创建被管理机的密钥对(更安全)
#在node1上创建ssh密钥对
#-f 指定生成的密钥文件的路径和文件名
#-P 参数用于指定密钥的密码(passphrase) ''标识不为密钥设置密码
ssh-keygen -f ~/.ssh/id_rsa -P '' > /dev/null 2>&1
编写公钥分发脚本 ssh_key_send.sh
#!/bin/bash
rm -rf ~/.ssh/id_rsa*
ssh-keygen -f ~/.ssh/id_rsa -P '' > /dev/null 2>&1
SSH_Pass=123456
Key_Path=~/.ssh/id_rsa.pub
for ip in 6 7
do
sshpass -p$SSH_Pass ssh-copy-id -i $Key_Path "-o StrictHostKeyChecking=no" 192.168.84.$ip
done
执行情况
[root@node1 mysh]# chmod -x ssh_key_send.sh
[root@node1 mysh]# sh ssh_key_send.sh
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
Number of key(s) added: 1
Now try logging into the machine, with: "ssh -o ' StrictHostKeyChecking=no' '192.168.84.6'"
and check to make sure that only the key(s) you wanted were added.
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
Number of key(s) added: 1
Now try logging into the machine, with: "ssh -o ' StrictHostKeyChecking=no' '192.168.84.7'"
and check to make sure that only the key(s) you wanted were added.
此时也可以进行无密码连接(此时host文件仅仅配置了被管理机的ip地址)
[root@node1 ansible]# ansible fishpie -a 'hostname'
192.168.84.7 | CHANGED | rc=0 >>
node3
192.168.84.6 | CHANGED | rc=0 >>
node2
ansible模式(重点)
ad-hoc模式
- -m command 命令(默认)
- -m shell shell特性操作
- -m copy 复制
- -m yum 安装
- -m user 用户操作
- -m service 系统服务
关于cmmand模式与shell模式的区别:
- 命令执行方式:
command
模块直接在远程主机上执行指定的命令,不会通过shell进行处理。这意味着shell的特性,如变量替换、通配符展开等,不会生效shell
模块通过shell(/bin/sh)来执行命令,因此shell的特性可以生效。这允许你使用环境变量、管道、重定向等shell功能- 参数处理:
command
模块将给定的命令作为一个字符串,不会对其进行任何处理。你需要自己处理任何引号或转义字符shell
模块会将给定的命令通过shell进行处理,因此你可以使用shell的语法,如管道、重定向等- 安全性:
command
模块相对更安全,因为它不会解释shell的元字符,减少了注入攻击的风险shell
模块使用shell来执行命令,如果命令来自不可信的源(如用户输入),可能存在安全风险- 幂等性:
command
模块默认是幂等的,意味着重复执行相同的命令不会改变结果shell
模块默认是非幂等的,因为shell命令可能会有副作用,重复执行可能导致不同的结果例如:
使用command模块
ansible all -m command -a "ls /tmp"
使用shell模块
ansible all -m shell -a "ls /tmp | grep file"
用于处理临时、简单的任务
- cpu负载情况,网络情况
- 临时分发配置文件
示例:
在fishpie组显示系统运行时间
[root@node1 ansible]# ansible fishpie -m command -a 'uptime'
192.168.84.7 | CHANGED | rc=0 >>
20:49:41 up 3:44, 2 users, load average: 0.00, 0.03, 0.06
192.168.84.6 | CHANGED | rc=0 >>
20:49:41 up 3:44, 2 users, load average: 0.00, 0.01, 0.05
在fishpie组执行特定命令
[root@node1 ansible]# ansible fishpie -m shell -a "ls -l /home"
192.168.84.7 | CHANGED | rc=0 >>
总用量 0
drwx------. 4 fishpie fishpie 123 4月 8 14:30 fishpie
192.168.84.6 | CHANGED | rc=0 >>
总用量 0
drwx------. 4 fishpie fishpie 123 11月 2 16:34 fishpie
drwx------. 2 fishpie123 sfishpie123 62 10月 14 2023 fishpie123
在fishpie组每台系统内文件传输
ansible fishpie -m copy -a "src=/etc/hosts dest=/tmp/hosts"
在fishpie组安装安装Apache httpd软件包
ansible fishpie -m yum -a "name=httpd state=present"
在fishpie组所有主机上创建 名为apple,密码为123456 的用户
ansible fishpie -m user -a "name=apple password=123456"
在fishpie组所有主机上启动Apache httpd服务
ansible fishpie -m service -a "name=httpd state=started"
playbook模式
用于处理具体且大量操作的任务
- 一键部署rsync备份服务器
- 一键部署lnmp环境
指定管理主机组的文件,然后创建 YAML 文件
示例:
一键部署LNMP环境(Linux、Nginx、MySQL、PHP)
创建名为lnmp的YAML文件,
---
- hosts: fishpie #指定主机组
become: yes #在执行以下任务时权限升级(sudo)
tasks:
- name: Install nginx #安装nginx
yum:
name: nginx
state: present
- name: Start nginx service #启动nginx
service:
name: nginx
state: started
- name: Install MySQL #安装MySQL
yum:
name: mariadb-server
state: present
- name: Start MySQL service #启动MySQL
service:
name: mariadb
state: started
- name: Set MySQL root password #设置MySQL的root密码
mysql_user:
name: root
password: secret
login_unix_socket: /var/lib/mysql/mysql.sock
- name: Install PHP and related packages #安装PHP和相关的包
yum:
name:
- php
- php-fpm
- php-mysql
state: present
- name: Start PHP-FPM service #启动PHP-FPM服务
service:
name: php-fpm
state: started
- name: Configure nginx for PHP #配置Nginx以支持PHP
template:
src: default.conf.j2
dest: /etc/nginx/conf.d/default.conf
notify: Restart nginx
#当'Configure nginx for PHP'任务发出通知时,它会重启Nginx服务
handlers:
- name: Restart nginx #重启nginx
service:
name: nginx
state: restarted
在这个hosts文件目录下运行
ansible-playbook -i hosts lnmp.yml
ansible模块
command模块
查看模块支持的参数
- ansible-doc -s <模块种类>
比如查看command模块支持的参数
[root@node1 ansible]# ansible-doc -s command
- name: Execute commands on targets
command:
argv: # Passes the command as a list rather than a string. Use `argv' to avoid quoting values that
would otherwise be interpreted incorrectly (for example "user
name"). Only the string or the list form can be provided, not
both. One or the other must be provided.
chdir: # Change into this directory before running the command.
cmd: # The command to run.
creates: # A filename or (since 2.0) glob pattern. If it already exists, this step *won't* be run.
free_form: # The command module takes a free form command to run. There is no actual parameter named 'free
form'.
removes: # A filename or (since 2.0) glob pattern. If it already exists, this step *will* be run.
stdin: # Set the stdin of the command directly to the specified value.
stdin_add_newline: # If set to `yes', append a newline to stdin data.
strip_empty_ends: # Strip empty lines from the end of stdout/stderr in result.
warn: # Enable or disable task warnings.
可知command模块支持参数
chdir #执行命令前,先cd进入该参数指定的目录
cmd #直接执行命令
creates #创建文件前先判断该文件是否存在,文件不存在才执行动作
free_form #可以输入任何系统命令
removes #删除文件前先判断该文件是否存在,文件不存在才执行动作
详细示例:
-
chdir
-
作用:在执行命令之前,先进入指定的目录。
-
示例:
- name: Run command in specific directory command: cmd: ls chdir: /var/www/html
-
在远程主机的
/var/www/html
目录下执行ls
命令。
-
-
cmd
-
作用:指定要执行的命令。
-
示例:
- name: Run a command command: /usr/bin/hostname
-
在远程主机上执行
/usr/bin/hostname
命令。
-
-
creates
-
作用:指定一个文件名或(从Ansible 2.0开始)一个glob模式。如果指定的文件或模式已经存在,则该任务将不会运行。
-
示例:
- name: Install nginx command: yum install -y nginx creates: /usr/sbin/nginx
-
如果
/usr/sbin/nginx
已经存在,则不会执行yum install -y nginx
命令。
-
-
free_form
-
作用:这不是一个真正的参数,而是表示
command
模块接受一个自由格式的命令。你可以直接写命令而不用cmd
参数。 -
示例:
- name: Run a command command: /usr/bin/hostname
-
等同于使用
cmd
参数。
-
-
removes
-
作用:指定一个文件名或(从Ansible 2.0开始)一个glob模式。如果指定的文件或模式已经存在,则该任务将会运行。
-
示例:
- name: Remove file command: rm /tmp/file removes: /tmp/file
-
如果
/tmp/file
存在,则会执行rm /tmp/file
命令。
-
-
stdin
-
作用:将命令的标准输入直接设置为指定的值。
-
示例:
- name: Run command with stdin command: python stdin: print('Hello, World!')
-
运行
python
命令,并将print('Hello, World!')
作为标准输入传递给它。
-
-
stdin_add_newline
-
作用:如果设置为
yes
,则在标准输入数据的末尾添加一个新行。 -
示例:
- name: Run command with stdin command: python stdin: print('Hello, World!') stdin_add_newline: yes
-
确保在标准输入的末尾有一个新行。
-
-
strip_empty_ends
-
作用:从结果的stdout/stderr中去除末尾的空行。
-
示例:
- name: Run command and strip empty lines command: /usr/bin/some_command strip_empty_ends: yes
-
从命令的输出中删除末尾的空行。
-
-
warn
-
作用:启用或禁用任务警告。
-
示例:
- name: Run command without warnings command: /usr/bin/some_command warn: no
-
禁用该任务的警告。
-
script模块
可以批量让所有被管理的机器执行脚本,且该脚本不需要在客户端上存在
模块参数
[root@node1 ansible]# ansible-doc -s script
- name: Runs a local script on a remote node after transferring it
script:
chdir: # Change into this directory on the remote node before running the script.
cmd: # Path to the local script to run followed by optional arguments.
creates: # A filename on the remote node, when it already exists, this step will *not* be run.
decrypt: # This option controls the autodecryption of source files using vault.
executable: # Name or path of a executable to invoke the script with.
free_form: # Path to the local script file followed by optional arguments.
removes: # A filename on the remote node, when it does not exist, this step will *not* be run.
示例:
在/myscript目录下创建一个名为localhostname.sh的脚本,内容如下
pwd
hostname
添加执行权限
chmod -x localhostname.sh
使用该脚本
[root@node1 myscript]# ansible fishpie -m script -a "/myscript/localhostname.sh"
192.168.84.7 | CHANGED => {
"changed": true,
"rc": 0,
"stderr": "Shared connection to 192.168.84.7 closed.\r\n",
"stderr_lines": [
"Shared connection to 192.168.84.7 closed."
],
"stdout": "/root\r\nnode3\r\n",
"stdout_lines": [
"/root", #返回的内容
"node3" #返回的内容
]
}
192.168.84.6 | CHANGED => {
"changed": true,
"rc": 0,
"stderr": "Shared connection to 192.168.84.6 closed.\r\n",
"stderr_lines": [
"Shared connection to 192.168.84.6 closed."
],
"stdout": "/root\r\nnode2\r\n",
"stdout_lines": [
"/root",
"node2"
]
}