一、Ansible

前提环境:

主机名ip
hello (控制节点)192.168.10.125
zz-1 (被控节点)192.168.10.126
zz-2 (被控节点)192.168.10.127

1.安装Ansible

[root@hello ~]# yum install centos-release-ansible-29.noarch
[root@hello ~]# yum -y install ansible
[root@hello ~]# ansible --version       #查看ansible版本,可知是2.9.27,安装完成
ansible 2.9.27
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.6/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 3.6.8 (default, Sep 10 2021, 09:13:53) [GCC 8.5.0 20210514 (Red Hat 8.5.0-3)]

2.配置SSH免密登录

  • 生成一对密钥。ssh-keygen -t rsa
[root@hello ~]# ssh-keygen -t rsa      #对话询问可一直回车即可
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): 
Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:pnZSeog1UhY7B3ewSxBvRxtr909WaGLtq60Dko9fTBA root@hello.com
The key's randomart image is:
+---[RSA 3072]----+
|      =.o.E      |
|       B + = . . |
|      = * * + + .|
|     o = + + =  .|
|    . o S.  . o o|
|     + Bo .o   = |
|    . * o+ .o . .|
|     . +. ...o   |
|         .. oo.  |
+----[SHA256]-----+

该命令执行完以后会在/root/.ssh下生成一对密钥,id_rsa是私钥,id_rsa.pub是公钥,我们要把公钥发送到另外的两个虚拟机上。

  • 将公钥发送到远程主机
(第一个zz-1)    #对话输入yes,然后输入密码
[root@hello .ssh]# ssh-copy-id root@192.168.10.126    
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
The authenticity of host '192.168.10.126 (192.168.10.126)' can't be established.
ECDSA key fingerprint is SHA256:V/OqSbYJTqm3lFBN8OrPj821yYLsDQeGzWh6edwNhjY.
Are you sure you want to continue connecting (yes/no/[fingerprint])? y
Please type 'yes', 'no' or the fingerprint: yes
/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
root@192.168.10.126's password: 
Permission denied, please try again.
root@192.168.10.126's password: 

Number of key(s) added: 1
Now try logging into the machine, with:   "ssh 'root@192.168.10.126'"
and check to make sure that only the key(s) you wanted were added.

(第二个zz-2[root@hello ~]# ssh-copy-id root@192.168.10.127
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
The authenticity of host '192.168.10.127 (192.168.10.127)' can't be established.
ECDSA key fingerprint is SHA256:W9xVaoucrXdvXYsY1a+Dp1002kBoouiJL4bYJR+eeNc.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
/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
root@192.168.10.127's password: 

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'root@192.168.10.127'"
and check to make sure that only the key(s) you wanted were added.

然后我们就可以实现hello到其他两个虚拟机的免密登录啦。

验证:远程登陆zz-1(92.168.10.126)

[root@hello .ssh]# ssh 192.168.10.126
The authenticity of host '192.168.10.126 (192.168.10.126)' can't be established.
ECDSA key fingerprint is SHA256:0o3HC9/CmWEQt4RTR3Et0NMuf2ZG0DAhW2JKIACTmSQ.
Are you sure you want to continue connecting (yes/no/[fingerprint])? y
Please type 'yes', 'no' or the fingerprint: yes
Warning: Permanently added '192.168.10.126' (ECDSA) to the list of known hosts.
root@192.168.10.126's password: 
Last login: Wed Nov 22 06:56:34 2023 from 192.168.10.1
[root@zz-1 ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:0c:29:87:07:99 brd ff:ff:ff:ff:ff:ff
    inet 192.168.10.126/24 brd 192.168.10.255 scope global noprefixroute ens160
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe87:799/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

退出 exit

[root@zz-1 ~]# exit
注销
Connection to 192.168.10.126 closed.
[root@hello .ssh]# 

3.主机目录

主机目录默认的配置文件是/etc/ansible/hosts,将其清空,修改为如下

[root@hello ~]# vim /etc/ansible/hosts 
[root@hello ~]# cat /etc/ansible/hosts 
[/etc/Ansible/hosts]
192.168.10.126
192.168.10.127

[webservers]
192.168.10.126
192.168.10.127

修改完以后我们对节点进行ping操作,证明主机与两虚拟机联通,Ansible正常工作。

[root@hello ~]# ansible webservers -m ping
[WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see details
192.168.10.126 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}
192.168.10.127 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}

4.Ansible常用模块用法

  1. command模块shell模块

    command模块:在远程主机上执行指定得命令 如:cat ls ,不能使用特殊得符号 :| > >>

  	语法:
  		ansible  主机清单 -m  模块名 -a  '执行命令'
  		creates:当指定文件存在时,后一条命令不执行 / 指定文件不存在,后一条命令执行
  		removes:当指定文件存在时,后一条命令执行 / 指定文件不存在,后一条命令不执行
(查看所有节点/root下的文件)
[root@hello ~]# ansible all  -m command  -a 'ls /root'
[WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see details
192.168.10.127 | UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: ssh: connect to host 192.168.10.127 port 22: No route to host",
    "unreachable": true
}
192.168.10.126 | UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: ssh: connect to host 192.168.10.126 port 22: No route to host",
    "unreachable": true
}
(指定IP执行date)
[root@hello ~]# ansible 192.168.10.126 -m command -a "date" 
[WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see details
192.168.10.126 | UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: ssh: connect to host 192.168.10.126 port 22: No route to host",
    "unreachable": true
}

shell模块 :在远程主机上执行复杂的命令,比较好用得模块

语法:ansible 主机清单 -m 模块名 -a ‘执行命令’

(查看所有节点/root下的文件)
[root@hello ~]# ansible all  -m shell  -a 'ls /root'
[WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see details
192.168.10.126 | UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: ssh: connect to host 192.168.10.126 port 22: No route to host",
    "unreachable": true
}
192.168.10.127 | UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: ssh: connect to host 192.168.10.127 port 22: No route to host",
    "unreachable": true
}
  1. setup模块:查看目录节点的各种信息
[root@hello ~]# ansible webservers -m setup
[WARNING]: Invalid characters were found in group names but not replaced, use
-vvvv to see details
192.168.10.127 | UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: ssh: connect to host 192.168.10.127 port 22: No route to host",
    "unreachable": true
}
192.168.10.126 | UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: ssh: connect to host 192.168.10.126 port 22: No route to host",
    "unreachable": true
}
  1. copy模块:将主控端的文件复制到远程主机,只针对文件

       src  源文件路径
       dest   目标文件路径
       content  将指定内容覆盖写入到目标主机文件中
       force=no 	当主控端拷贝的文件名和目标名一致,但是内容不一致,放弃拷贝
       force=yes   当主控端拷贝的文件名和目标名一致,但是内容不一致,则进行覆盖
       backup=yes	 当主控端拷贝的文件名和目标名一致,但是内容不一致,则进行备份
    
(例子: 将主控端/root/test文件,复制到所有节点的/root目录下)
[root@hello ~]# ansible all -m copy -a 'dest=/root src=/root/test'
[WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see
details
192.168.10.126 | CHANGED => {
    "changed": true,
    "dest": "/root/",
    "src": "/root/test"
}
192.168.10.127 | CHANGED => {
    "changed": true,
    "dest": "/root/",
    "src": "/root/test"
}
  1. file模块:创建或者和删除远程主机上的文件或者目录

    path 指定文件 	如果远程主机上没有该文件,则进行创建
    state 创建类型   touch 文件  directory 目录 
    state=absent  删除文件或者目录
    
    link 软连接	src=源文件名  path=目标链接文件名
    hard 硬链接	src=源文件名  path=目标链接文件名
    
    以下三个参数,既可以修改,也可以自动添加
    mod:权限	可以在添加时设置特殊权限,前提要有执行权限( set 粘滞位)
    owner:属主
    group:属组
    
(删除刚才复制的文件)
[root@hello ~]#  ansible all -m file -a 'path=/root/test state=absent'
[WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see
details
192.168.10.126 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "path": "/root/test",
    "state": "absent"
}
192.168.10.127 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "path": "/root/test",
    "state": "absent"
}

还有很多模块,这里就不一一列举了

最后推荐大家看一下Ansible的中文文档,Ansible「2.9」 中文官方文档

5.playbook

playbook格式(语法格式非常关键)

playbook由YMAL语言编写,YMAL格式是类似于JSON的文件格式,便于理解和阅读,同时便于书写

一个剧本里面可以有多个play,每个play只能有一个tasks,每个tasks可以有多个name

playbook的基础组件:
name:定义任务模块名称
hosts:定义执行任务的主机
user:用于指定远程主机上执行任务的用户
task:指定一个任务
vars:定义变量
vars_files:调用定义变量文件
notify:任务执行结果如果是发生更改了的则触发定义在handler的任务执行
handlers:用于当前关注的资源发生变化时采取一定指定的操作
yaml语言格式要求
1.在单一档案中,可以用连续三个连字号(—)区分多个档案,另外,还有选择性的连续三个点号_(…)来表示档案的结尾
2.此行开始正常写playbook的内容,一般建议写明该playbook的功能
3.使用#注释代码
4.缩进必须统一的,不能空格和tab混用
5.缩进的级别也必须是一致的,同样的缩进代表同样的级别,程序判别配置的级别是通过缩进结合换行来实现的
6.YAML文件内容是区分大小写的,k/v的值均需大小写敏感
7.多个k/v可以同行写也可以换行写,同行使用,分割
8.v可以是个字符串,也可以是另一个列表
9.一个完整的代码块功能需最少元素包括name和task
10.一个name只能包括一个task
11.YAML文件扩展名通常为yaml或yml

安装Ansible和所需的python环境,手动关闭firewalld和SELINUX

[root@hello ~]# systemctl stop firewalld
[root@hello ~]# systemctl disable firewalld
[root@hello ~]# vim /etc/selinux/config


# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=disabled
# SELINUXTYPE= can take one of these three values:
#     targeted - Targeted processes are protected,
#     minimum - Modification of targeted policy. Only selected processes are protected. 
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted

//保存并退出,然后重启机器即可

编写一个playbook,实现Apache的安装与启动

[root@hello ~]# mkdir /etc/ansible/playbook
[root@hello ~]# cd /etc/ansible/playbook
[root@hello playbook]# vim apache.yml
[root@hello playbook]# cat apache.yml
---
- name: 下载yum源
  hosts: 192.168.10.126
  tasks:
    - name: 传输yum
      copy:
        src: /etc/yum.repos.d/CentOS-Base.repo  (这个文件,记得在自己主机中查看一下是否是这个)
        dest: /etc/yum.repos.d/CentOS-Base.repo 


- name: 修改yum源的配置文件
  hosts: 192.168.10.126
  tasks:
    - name: 修改
      command: sed -i 's/8/7/g' /etc/yum.repos.d/CentOS-Base.repo 


- name: 安装httpd服务
  hosts: 192.168.10.126
  tasks:
    - name: 安装
      yum:
        name: httpd
        state: present


- name: 修改httpd的配置文件
  hosts: 192.168.10.126
  tasks:
    - name: 修改
      command: sed -i 's/#ServerName www.example.com:80/ServerName www.example.com:80/' /etc/httpd/conf/httpd.conf 


- name: 启动httpd服务
  hosts: 192.168.10.126
  tasks:
    - name: 启动
      service:
        name: httpd
        state: started
        enabled: yes
    - name: 关闭
      service:
        name: firewalld
        state: stopped
        enabled: no
    - name: 重启
      service:
        name: httpd
        state: restarted
~  
~
~
~
"apache.yml" [] 52L, 1251C 已写入 
[root@ghello playbook]# ansible-playbook /etc/ansible/playbook/apache.yml                         

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐