我想创建一个群集基础结构,每个节点都通过shh与其他节点通信。我想使用ansible创建一个idempotent剧本/角色,可以在初始化集群或将新节点添加到集群时执行。我能够想到两种实现此目的的方案。
task 1
从节点获取ssh密钥(可能将其分配给变量或写入文件)。task 2
的locally循环其他节点,并使用获取的密钥授权第一个节点。此业务情景支持free strategy。无需等待所有主机即可执行任务。但这也要求所有节点都具有相关的用户和公用密钥。因为如果您要在同一个剧本中创建用户(由于免费策略),task 2
开始运行时,可能会在集群中的其他节点上没有创建用户。
尽管我是自由策略的忠实拥护者,但出于效率考虑,我不实施这种方案。它使为节点群集。
task 1
从所有节点按顺序获取ssh密钥。然后将每个文件写入根据ansible_hostname
设置名称的文件。task 2
的locally循环遍历其他节点并授权所有密钥。此方案仅支持linear strategy。由于采用线性策略,您可以在同一个剧本中创建用户,所有用户将在task 1
开始运行之前创建。
我认为这是一种有效的方案。这使得仅的节点群集。我实现了它,然后放了我写的代码段。
---
- name: create node user
user:
name: "{{ node_user }}"
password: "{{ node_user_pass |password_hash('sha512') }}"
shell: /bin/bash
create_home: yes
generate_ssh_key: yes
- name: fetch all public keys from managed nodes to manager
fetch:
src: "/home/{{ node_user }}/.ssh/id_rsa.pub"
dest: "tmp/{{ ansible_hostname }}-id_rsa.pub"
flat: yes
- name: authorize public key for all nodes
authorized_key:
user: "{{ node_user }}"
key: "{{ lookup('file', 'tmp/{{ item }}-id_rsa.pub')}}"
state: present
with_items:
- "{{ groups['cluster_node'] }}"
- name: remove local public key copies
become: false
local_action: file dest='tmp/' state=absent
changed_when: false
run_once: true
也许我可以使用lineinfile代替fetch,但除此之外,我不知道这是否是正确的方法。群集大小变大时需要花费很长时间(由于线性策略)。有没有我可以使用的更有效的方法?
[当Ansible遍历authorized_key时,它将(大致)执行以下任务:
随着管理节点数的增加,这增加n 2;如果有1000箱,则每箱执行1000次此任务。
我在查找能够正确解释exactly幕后动态的特定文档时遇到麻烦,因此,我建议运行示例脚本以了解一下情况:
- hosts: all
tasks:
- name: do thing
shell: "echo \"hello this is {{item}}\""
with_items:
- alice
- brian
- charlie
应与三重详细标志(-vvv
)一起运行,并将输出通过管道传递到./ansible.log
(例如ansible-playbook example-loop.yml -i hosts.yml -vvv > example-loop-output.log
)。在这些日志中搜索command.py
和sftp
将有助于您了解随着"{{ groups['cluster_node'] }}"
检索到的列表的增加,脚本的扩展方式。
对于小型集群,这种低效率是完全可以接受的。但是,在大型群集上可能会出现问题。
现在,authorized_key
模块实质上只是生成一个aa_authorized_keys文件,其中a)已经存在于authorized_keys中的密钥,以及b)集群上每个节点的公共密钥。我们可以在控制节点上构造authorized_keys文件,然后将其部署到每个盒子,而不是在每个盒子上分别重复生成authorized_keys文件。
authorized_keys文件本身可以用assemble生成;这将采用所有收集的键并将它们连接到一个文件中。但是,如果仅将synchronize
或copy
这个文件结束,我们将清除添加到authorized_keys中的所有非集群键。为了避免这种情况,我们可以使用blockinfile。 blockinfile
可以管理Ansible添加的群集密钥。我们将能够在删除过时的密钥的同时添加新密钥。
- hosts: cluster
name: create node user and generate keys
tasks:
- name: create node user
user:
name: "{{ node_user }}"
password: "{{ node_user_pass |password_hash('sha512') }}"
shell: /bin/bash
create_home: yes
generate_ssh_key: yes
- name: fetch all public keys from managed nodes to manager
fetch:
src: "/home/{{ node_user }}/.ssh/id_rsa.pub"
dest: "/tmp/keys/{{ ansible_host }}-id_rsa.pub"
flat: yes
become: yes
- hosts: localhost
name: generate authorized_keys file
tasks:
- name: Assemble authorized_keys from a directory
assemble:
src: "/tmp/keys"
dest: "/tmp/authorized_keys"
- hosts: cluster
name: update authorized_keys file
tasks:
- name: insert/update configuration using a local file
blockinfile:
block: "{{ lookup('file', '/tmp/authorized_keys') }}"
dest: "/home/{{ node_user }}/.ssh/authorized_keys"
backup: yes
create: yes
owner: "{{ node_user }}"
group: "{{ node_group }}"
mode: 0600
become: yes
原样,此解决方案不容易与角色兼容;角色被设计为仅处理主机(主机,组,组的集合等)的单个值,并且以上解决方案要求在组和本地主机之间切换。
我们可以用delegate_to
对此进行补救,尽管在大型集群中它可能效率不高,因为集群中的每个节点都将尝试组装authorized_keys。根据ansible项目的总体结构(以及团队的规模),这可能是理想的,也可能不是理想的;当用delegate_to
浏览大脚本时,很容易会漏掉某些正在本地执行的脚本。
- hosts: cluster
name: create node user and generate keys
tasks:
- name: create node user
user:
name: "{{ node_user }}"
password: "{{ node_user_pass |password_hash('sha512') }}"
shell: /bin/bash
create_home: yes
generate_ssh_key: yes
- name: fetch all public keys from managed nodes to manager
fetch:
src: "/home/{{ node_user }}/.ssh/id_rsa.pub"
dest: "/tmp/keys/{{ ansible_host }}-id_rsa.pub"
flat: yes
- name: Assemble authorized_keys from a directory
assemble:
src: "/tmp/keys"
dest: "/tmp/authorized_keys"
delegate_to: localhost
- name: insert/update configuration using a local file
blockinfile:
block: "{{ lookup('file', '/tmp/authorized_keys') }}"
dest: "/home/{{ node_user }}/.ssh/authorized_keys"
backup: yes
create: yes
owner: "{{ node_user }}"
group: "{{ node_group }}"
mode: 0600
become: yes