Ansible

安装

1
2
yum install epel-release -y
yum install ansible –y

配置

目录在/etc/ansible下面,使用密码登录需要修改以下两个配置文件

  • host文件规定了管理的机器

    1
    [test]
    1
    172.20.10.4 ansible_user=sshin ansible_password=123
    1
    172.20.10.6 ansible_user=sshin ansible_password=123
    1
    172.20.10.7 ansible_user=sshin ansible_password=123
  • ansible.cfg是程序配置文件,用密码登录需要取消如下注释

    1
    # uncomment this to disable SSH key host checking
    1
    host_key_checking = False

配置公私钥登录

ssh-keygen -t rsa -b 4096

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
---
- name: Distribute SSH public key
hosts: test
become: yes
become_method: su
become_flags: "-"
become_user: root
vars:
ansible_become_password: root
tasks:
- name: Create authorized_keys directory
file:
path: /root/.ssh
state: directory
mode: '0700'

- name: Copy SSH public key
authorized_key:
user: root
key: "{{ lookup('file', '/root/.ssh/id_rsa.pub') }}"
state: present

1
2
3
4
5
6
7
8
9
10


传送ssh公钥:
ansible-playbook /etc/ansible/copy_ssh_public_keys.yaml

传完之后再次查看远程主机是否已经有了authorized_key文件:
ansible test -a "ls /root/.ssh/"
此时应该可以看到远程主机应该已经有了authorized_key这个文件。

ansible -i ./hosts test -v -m ping -u root --private-key=/.ssh/id_rsa

基础命令

帮助模块

查看帮助文档

1
2
3
4
5
6
[root@server ~]# ansible-doc -l |grep mysql
mysql_db Add or remove MySQL databases from a remote...
mysql_replication Manage MySQL replication
mysql_user Adds or removes a user from a MySQL databas...
mysql_variables Manage MySQL global variables
[root@server ~]# ansible-doc -s mysql_user

连通性测试

从本地ping远程机器

1
ansible -i ./hosts --connection=local test -m ping

测试是否可ssh到其他服务器

1
ansible web -m ping

command模块

1
ansible test -m command -a 'ls -l /'

命令模块接受命令名称,后面是空格分隔的列表参数。给定的命令将在所有选定的节点上执行。它不会通过shell进行处理,比如$HOME和操作如”<”,”>”,”|”,”;”,”&” 工作(需要使用(shell)模块实现这些功能)。注意,该命令不支持| 管道命令。  下面来看一看该模块下常用的几个命令:

chdir       # 在执行命令之前,先切换到该目录 executable # 切换shell来执行命令,需要使用命令的绝对路径 free_form   # 要执行的Linux指令,一般使用Ansible的-a参数代替。 creates  # 一个文件名,当这个文件存在,则该命令不执行,可以 用来做判断 removes # 一个文件名,这个文件不存在,则该命令不执行

1
[root@server ~]# ansible web -m command -a 'removes=/data/aaa.jpg cat /data/a'    #如果/data/aaa.jpg存在,则执行“cat /data/a”命令

shell模块

shell模块可以在远程主机上调用shell解释器运行命令,支持shell的各种功能,例如管道等。

1
2
3
4
5
6
[root@server ~]# ansible test -m shell -a 'cat /etc/passwd |grep "root"'
192.168.37.122 | SUCCESS | rc=0 >>
keer:x:10001:1000:keer:/home/keer:/bin/sh

192.168.37.133 | SUCCESS | rc=0 >>
keer:x:10001:10001::/home/keer:/bin/sh

  只要是我们的shell命令,都可以通过这个模块在远程主机上运行,这里就不一一举例了。

copy模块

这个模块用于将文件复制到远程主机,同时支持给定内容生成文件和修改权限等。  其相关选项如下:

src    #被复制到远程主机的本地文件。可以是绝对路径,也可以是相对路径。如果路径是一个目录,则会递归复制,用法类似于”rsync” content   #用于替换”src”,可以直接指定文件的值 dest    #必选项,将源文件复制到的远程主机的绝对路径 backup   #当文件内容发生改变后,在覆盖之前把源文件备份,备份文件包含时间信息 directory_mode    #递归设定目录的权限,默认为系统默认权限 force    #当目标主机包含该文件,但内容不同时,设为”yes”,表示强制覆盖;设为”no”,表示目标主机的目标位置不存在该文件才复制。默认为”yes” others    #所有的 file 模块中的选项可以在这里使用

用法举例如下: ① 复制文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
[root@server ~]# ansible test -m copy -a 'src=~/hello dest=/data/hello' 
192.168.37.122 | SUCCESS => {
"changed": true,
"checksum": "22596363b3de40b06f981fb85d82312e8c0ed511",
"dest": "/data/hello",
"gid": 0,
"group": "root",
"md5sum": "6f5902ac237024bdd0c176cb93063dc4",
"mode": "0644",
"owner": "root",
"size": 12,
"src": "/root/.ansible/tmp/ansible-tmp-1512437093.55-228281064292921/source",
"state": "file",
"uid": 0
}
192.168.37.133 | SUCCESS => {
"changed": true,
"checksum": "22596363b3de40b06f981fb85d82312e8c0ed511",
"dest": "/data/hello",
"gid": 0,
"group": "root",
"md5sum": "6f5902ac237024bdd0c176cb93063dc4",
"mode": "0644",
"owner": "root",
"size": 12,
"src": "/root/.ansible/tmp/ansible-tmp-1512437093.74-44694985235189/source",
"state": "file",
"uid": 0
}

② 给定内容生成文件,并制定权限

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
[root@server ~]# ansible test -m copy -a 'content="I am keer\n" dest=/data/name mode=666'
192.168.37.122 | SUCCESS => {
"changed": true,
"checksum": "0421570938940ea784f9d8598dab87f07685b968",
"dest": "/data/name",
"gid": 0,
"group": "root",
"md5sum": "497fa8386590a5fc89090725b07f175c",
"mode": "0666",
"owner": "root",
"size": 10,
"src": "/root/.ansible/tmp/ansible-tmp-1512437327.37-199512601767687/source",
"state": "file",
"uid": 0
}
192.168.37.133 | SUCCESS => {
"changed": true,
"checksum": "0421570938940ea784f9d8598dab87f07685b968",
"dest": "/data/name",
"gid": 0,
"group": "root",
"md5sum": "497fa8386590a5fc89090725b07f175c",
"mode": "0666",
"owner": "root",
"size": 10,
"src": "/root/.ansible/tmp/ansible-tmp-1512437327.55-218104039503110/source",
"state": "file",
"uid": 0
}

  我们现在可以去查看一下我们生成的文件及其权限:

1
2
3
4
5
6
7
8
[root@server ~]# ansible web -m shell -a 'ls -l /data/'
192.168.37.122 | SUCCESS | rc=0 >>
total 28
-rw-rw-rw- 1 root root 12 Dec 6 09:45 name

192.168.37.133 | SUCCESS | rc=0 >>
total 40
-rw-rw-rw- 1 root root 12 Dec 5 09:45 name

  可以看出我们的name文件已经生成,并且权限为666。 ③ 关于覆盖  我们把文件的内容修改一下,然后选择覆盖备份:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
[root@server ~]# ansible test -m copy -a 'content="I am keerya\n" backup=yes dest=/data/name mode=666'
192.168.37.122 | SUCCESS => {
"backup_file": "/data/name.4394.2017-12-06@09:46:25~",
"changed": true,
"checksum": "064a68908ab9971ee85dbc08ea038387598e3778",
"dest": "/data/name",
"gid": 0,
"group": "root",
"md5sum": "8ca7c11385856155af52e560f608891c",
"mode": "0666",
"owner": "root",
"size": 12,
"src": "/root/.ansible/tmp/ansible-tmp-1512438383.78-228128616784888/source",
"state": "file",
"uid": 0
}
192.168.37.133 | SUCCESS => {
"backup_file": "/data/name.5962.2017-12-05@09:46:24~",
"changed": true,
"checksum": "064a68908ab9971ee85dbc08ea038387598e3778",
"dest": "/data/name",
"gid": 0,
"group": "root",
"md5sum": "8ca7c11385856155af52e560f608891c",
"mode": "0666",
"owner": "root",
"size": 12,
"src": "/root/.ansible/tmp/ansible-tmp-1512438384.0-170718946740009/source",
"state": "file",
"uid": 0
}

  现在我们可以去查看一下:

1
2
3
4
5
6
7
8
9
10
[root@server ~]# ansible web -m shell -a 'ls -l /data/'
192.168.37.122 | SUCCESS | rc=0 >>
total 28
-rw-rw-rw- 1 root root 12 Dec 6 09:46 name
-rw-rw-rw- 1 root root 10 Dec 6 09:45 name.4394.2017-12-06@09:46:25~

192.168.37.133 | SUCCESS | rc=0 >>
total 40
-rw-rw-rw- 1 root root 12 Dec 5 09:46 name
-rw-rw-rw- 1 root root 10 Dec 5 09:45 name.5962.2017-12-05@09:46:24~

  可以看出,我们的源文件已经被备份,我们还可以查看一下name文件的内容:

1
2
3
4
5
6
[root@server ~]# ansible web -m shell -a 'cat /data/name'
192.168.37.122 | SUCCESS | rc=0 >>
I am keerya

192.168.37.133 | SUCCESS | rc=0 >>
I am keerya

  证明,这正是我们新导入的文件的内容。

对凝思系统的支持

配置网卡

  • /etc/network中修改interfaces

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # This file describes the network interfaces available on your system
    # and how to activate them. For more information, see interfaces(5).
    # The loopback network interface
    auto lo
    iface lo inet loopback
    auto eth3
    iface eth3 inet static
    address 172.20.10.7
    netmask 255.255.255.0
    gateway 172.20.10.1
  • 使用命令使其生效

    • Ifdown eth3
    • ifup eth3

对ansible源代码进行修改

对文件/usr/lib/python2.7/site-packages/ansible/plugins/become/su.py进行如下修改

添加bool(b_su_prompt_localizations_re.match(b_output.decode('gbk').encode('utf-8')))使得gbk编码得以被支持

1
2
3
4
5
6
7
8
9
10
11
def check_password_prompt(self, b_output):
''' checks if the expected password prompt exists in b_output '''

prompts = self.get_option('prompt_l10n') or self.SU_PROMPT_LOCALIZATIONS
b_password_string = b"|".join((br'(\w+\'s )?' + to_bytes(p)) for p in prompts)
# Colon or unicode fullwidth colon
b_password_string = b_password_string + to_bytes(u' ?(:|:) ?')
b_su_prompt_localizations_re = re.compile(b_password_string, flags=re.IGNORECASE)
# print(b_output.decode('gbk'))
# print(bool(b_su_prompt_localizations_re.match(b_output.decode('gbk').encode('utf-8'))))
return bool(b_su_prompt_localizations_re.match(b_output)) or bool(b_su_prompt_localizations_re.match(b_output.decode('gbk').encode('utf-8')))
  1. 首先需要进行配置

    目录在/etc/ansible下面,使用密码登录需要修改以下两个配置文件

    • host文件规定了管理的机器

      1
      2
      3
      4
      [test]
      172.20.10.4 ansible_user=sshin ansible_password=123
      172.20.10.6 ansible_user=sshin ansible_password=123
      172.20.10.7 ansible_user=sshin ansible_password=123
    • ansible.cfg是程序配置文件,用密码登录需要取消如下注释

      1
      2
      # uncomment this to disable SSH key host checking
      host_key_checking = False
  2. 使用ansible test -m ping,该命令使用test组群对本机进行ping操作,查看是否配置可用

  3. 编写playword

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
---
- name: Distribute SSH public key
hosts: test
become: yes
become_method: su
become_flags: "-"
become_user: root
vars:
ansible_become_password: root
tasks:
- name: Create authorized_keys directory
file:
path: /root/.ssh
state: directory
mode: '0700'

- name: Copy SSH public key
authorized_key:
user: root
key: "{{ lookup('file', '/root/.ssh/id_rsa.pub') }}"
state: present

- name: Change PubkeyAuthentication to yes
replace:
path: /etc/ssh/sshd_config
regexp: 'PubkeyAuthentication\s+no'
replace: 'PubkeyAuthentication yes'

- name: Restart SSH service using Ansible
command: systemctl restart sshd

- name: Restart SSH service 4 凝思
command: /etc/init.d/ssh restart

命名为copy_ssh_without_root.yaml即使用非root账号进行登录,并提权root然后进行相关操作。

其中凝思的重启ssh为:sudo /etc/init.d/ssh restart

保存完输入ansible-playbook copy_ssh_without_root.yaml

  1. 修改host文件,删除账号密码相关的内容。
1
2
3
4
[test]
172.20.10.4
172.20.10.6
172.20.10.7
  1. 使用ansible test -m ping命令再进行ping测试,通过即完成了批量添加ssh证书的工作。

reference

参考来源