Ansible systemd 挂载依赖
Ansible systemd mount dependency
我使用 Ansible 将 systemd 单元文件部署到一个庄园中的所有服务器,并使其在启动时启动。在其中一些服务器上,单元文件中定义的二进制文件位于不同的文件系统上。这要求单元文件依赖于正在挂载的文件系统。例如:
[Unit]
Description = Start the widget
After = network.target usr.mount
[Service]
Type = simple
ExecStart = /usr/bin/widget
[Install]
WantedBy = multi-user.target
目前单元文件由Ansible部署为静态文件,使用ansible.builtin.copy
模块。如果 /usr
是挂载点,有没有办法将其转换为模板并将挂载点附加到 After =
?
只需使用 template 任务,在 src 模板任务中有一个条件,可以根据条件打印所需的块。您可以将变量传递给 template 任务并根据它做出决定,即。您首先检查任务中是否需要该文件系统,然后根据模板任务生成文件。
Ansible fact ansible_mounts 保留挂载点列表。让我们使用以下变量进行测试
widgets:
- /usr/local/apps/widget
- /usr/share/apps/widget
- /scratch/apps/widget
my_ansible_mounts:
- mount: /
- mount: /boot/efi
- mount: /usr
- mount: /usr/local
root:
- /
创建小部件和相关挂载点的字典,例如
- set_fact:
_mlist: []
- set_fact:
_mlist: "{{ _mlist + [{'dict': item.0, 'mount': item.1}] }}"
with_nested:
- "{{ widgets }}"
- "{{ my_ansible_mounts|map(attribute='mount')|difference(root) }}"
when: item.0|regex_search('^' ~ item.1) != None
- set_fact:
_mdict: {}
- set_fact:
_mdict: "{{ _mdict|combine({item.0: item.1|
map(attribute='mount')|
map('regex_replace', '/', '-')|
list}) }}"
loop: "{{ _mlist|groupby('dict') }}"
给予
_mdict:
/usr/local/apps/widget:
- -usr
- -usr-local
/usr/share/apps/widget:
- -usr
那么流程应该是微不足道的,例如
- debug:
msg: |-
{% if _mdict[item]|default([])|length > 0 %}
[Unit]
Description = Start the widget
After = network.target{% for i in _mdict[item] %} {{ i[1:] }}.mount{% endfor %}
{% endif %}
[Service]
Type = simple
ExecStart = {{ item }}
loop: "{{ widgets }}"
给予
ok: [localhost] => (item=/usr/local/apps/widget) =>
msg: |-
[Unit]
Description = Start the widget
After = network.target usr.mount usr-local.mount
[Service]
Type = simple
ExecStart = /usr/local/apps/widget
ok: [localhost] => (item=/usr/share/apps/widget) =>
msg: |-
[Unit]
Description = Start the widget
After = network.target usr.mount
[Service]
Type = simple
ExecStart = /usr/share/apps/widget
ok: [localhost] => (item=/scratch/apps/widget) =>
msg: |-
[Service]
Type = simple
ExecStart = /scratch/apps/widget
为了测试真实的东西,在代码中,将 my_ansible_mounts 替换为 ansible_mounts 并适合widgets 和 hosts 满足您的需求。
我使用 Ansible 将 systemd 单元文件部署到一个庄园中的所有服务器,并使其在启动时启动。在其中一些服务器上,单元文件中定义的二进制文件位于不同的文件系统上。这要求单元文件依赖于正在挂载的文件系统。例如:
[Unit]
Description = Start the widget
After = network.target usr.mount
[Service]
Type = simple
ExecStart = /usr/bin/widget
[Install]
WantedBy = multi-user.target
目前单元文件由Ansible部署为静态文件,使用ansible.builtin.copy
模块。如果 /usr
是挂载点,有没有办法将其转换为模板并将挂载点附加到 After =
?
只需使用 template 任务,在 src 模板任务中有一个条件,可以根据条件打印所需的块。您可以将变量传递给 template 任务并根据它做出决定,即。您首先检查任务中是否需要该文件系统,然后根据模板任务生成文件。
Ansible fact ansible_mounts 保留挂载点列表。让我们使用以下变量进行测试
widgets:
- /usr/local/apps/widget
- /usr/share/apps/widget
- /scratch/apps/widget
my_ansible_mounts:
- mount: /
- mount: /boot/efi
- mount: /usr
- mount: /usr/local
root:
- /
创建小部件和相关挂载点的字典,例如
- set_fact:
_mlist: []
- set_fact:
_mlist: "{{ _mlist + [{'dict': item.0, 'mount': item.1}] }}"
with_nested:
- "{{ widgets }}"
- "{{ my_ansible_mounts|map(attribute='mount')|difference(root) }}"
when: item.0|regex_search('^' ~ item.1) != None
- set_fact:
_mdict: {}
- set_fact:
_mdict: "{{ _mdict|combine({item.0: item.1|
map(attribute='mount')|
map('regex_replace', '/', '-')|
list}) }}"
loop: "{{ _mlist|groupby('dict') }}"
给予
_mdict:
/usr/local/apps/widget:
- -usr
- -usr-local
/usr/share/apps/widget:
- -usr
那么流程应该是微不足道的,例如
- debug:
msg: |-
{% if _mdict[item]|default([])|length > 0 %}
[Unit]
Description = Start the widget
After = network.target{% for i in _mdict[item] %} {{ i[1:] }}.mount{% endfor %}
{% endif %}
[Service]
Type = simple
ExecStart = {{ item }}
loop: "{{ widgets }}"
给予
ok: [localhost] => (item=/usr/local/apps/widget) =>
msg: |-
[Unit]
Description = Start the widget
After = network.target usr.mount usr-local.mount
[Service]
Type = simple
ExecStart = /usr/local/apps/widget
ok: [localhost] => (item=/usr/share/apps/widget) =>
msg: |-
[Unit]
Description = Start the widget
After = network.target usr.mount
[Service]
Type = simple
ExecStart = /usr/share/apps/widget
ok: [localhost] => (item=/scratch/apps/widget) =>
msg: |-
[Service]
Type = simple
ExecStart = /scratch/apps/widget
为了测试真实的东西,在代码中,将 my_ansible_mounts 替换为 ansible_mounts 并适合widgets 和 hosts 满足您的需求。