我正在做一个项目,需要在我的服务器上交换内存,以避免一些 python 长时间运行的进程内存不足,并且第一次意识到我的 ubuntu vagrant boxes 和 AWS ubuntu 实例还没有一个设置。
在https://github.com/ansible/ansible/issues/5241中讨论了一个可能的内置解决方案但从未实施,所以我猜这应该是一个非常常见的自动化任务。
您将如何以幂等方式使用 ansible 设置基于文件的交换内存? ansible 为这个设置提供了哪些模块或变量帮助(比如
ansible_swaptotal_mb
变量)?
这是我目前的解决方案:
- name: Create swap file
command: dd if=/dev/zero of={{ swap_file_path }} bs=1024 count={{ swap_file_size_mb }}k
creates="{{ swap_file_path }}"
tags:
- swap.file.create
- name: Change swap file permissions
file: path="{{ swap_file_path }}"
owner=root
group=root
mode=0600
tags:
- swap.file.permissions
- name: "Check swap file type"
command: file {{ swap_file_path }}
register: swapfile
tags:
- swap.file.mkswap
- name: Make swap file
command: "sudo mkswap {{ swap_file_path }}"
when: swapfile.stdout.find('swap file') == -1
tags:
- swap.file.mkswap
- name: Write swap entry in fstab
mount: name=none
src={{ swap_file_path }}
fstype=swap
opts=sw
passno=0
dump=0
state=present
tags:
- swap.fstab
- name: Mount swap
command: "swapon {{ swap_file_path }}"
when: ansible_swaptotal_mb < 1
tags:
- swap.file.swapon
我尝试了上面的答案,但
"Check swap file type"
总是以 changed
的形式返回,因此不是 idempotent,这是在编写 Ansible 任务时被鼓励作为最佳实践。
以下角色已经在 Ubuntu 14.04 Trusty 上进行了测试,不需要启用
gather_facts
。
- name: Set swap_file variable
set_fact:
swap_file: "{{swap_file_path}}"
tags:
- swap.set.file.path
- name: Check if swap file exists
stat:
path: "{{swap_file}}"
register: swap_file_check
tags:
- swap.file.check
- name: Create swap file
command: fallocate -l {{swap_file_size}} {{swap_file}}
when: not swap_file_check.stat.exists
tags:
- swap.file.create
- name: Change swap file permissions
file: path="{{swap_file}}"
owner=root
group=root
mode=0600
tags:
- swap.file.permissions
- name: Format swap file
sudo: yes
command: "mkswap {{swap_file}}"
when: not swap_file_check.stat.exists
tags:
- swap.file.mkswap
- name: Write swap entry in fstab
mount: name=none
src={{swap_file}}
fstype=swap
opts=sw
passno=0
dump=0
state=present
tags:
- swap.fstab
- name: Turn on swap
sudo: yes
command: swapon -a
when: not swap_file_check.stat.exists
tags:
- swap.turn.on
- name: Set swappiness
sudo: yes
sysctl:
name: vm.swappiness
value: "{{swappiness}}"
tags:
- swap.set.swappiness
从 Ansible 2.9 开始,
sudo
声明应该是 become
:
- name: Set swap_file variable
set_fact:
swap_file: "{{swap_file_path}}"
tags:
- swap.set.file.path
- name: Check if swap file exists
stat:
path: "{{swap_file}}"
register: swap_file_check
tags:
- swap.file.check
- name: Create swap file
command: fallocate -l {{swap_file_size}} {{swap_file}}
when: not swap_file_check.stat.exists
tags:
- swap.file.create
- name: Change swap file permissions
file: path="{{swap_file}}"
owner=root
group=root
mode=0600
tags:
- swap.file.permissions
- name: Format swap file
become: yes
command: "mkswap {{swap_file}}"
when: not swap_file_check.stat.exists
tags:
- swap.file.mkswap
- name: Write swap entry in fstab
mount: name=none
src={{swap_file}}
fstype=swap
opts=sw
passno=0
dump=0
state=present
tags:
- swap.fstab
- name: Turn on swap
become: yes
command: swapon -a
when: not swap_file_check.stat.exists
tags:
- swap.turn.on
- name: Set swappiness
become: yes
sysctl:
name: vm.swappiness
value: "{{swappiness}}"
tags:
- swap.set.swappiness
需要变量:
swap_file_path: /swapfile
# Use any of the following suffixes
# c=1
# w=2
# b=512
# kB=1000
# K=1024
# MB=1000*1000
# M=1024*1024
# xM=M
# GB=1000*1000*1000
# G=1024*1024*1024
swap_file_size: 4G
swappiness: 1
我的看法基于 Ashley 的回答(请投票!)并添加了以下额外功能:
...加上这些技术改进:
ok
和skipping
什么都没有改变,否则有些changed
),dd
而不是 fallocate
以与 XFS fs 兼容(有关更多信息,请参见 this answer),限制:
swap_file_path
.在带有 Ansible 2.9 的 Centos 7.7 和带有 Ansible 的 Rocky 8 上测试 4.8.0.
需要使用权限升级,因为许多命令需要以 root 身份运行。 (最简单的方法是将
--become
添加到 ansible-playbook
参数或 在您的 ansible.cfg
中设置适当的值)。
参数:
swap_configure: true # or false
swap_enable: true # or false
swap_file_path: /swapfile
swap_file_size_mb: 4096
swappiness: 1
代码:
- name: Configure swap
when: swap_configure | bool
block:
- name: Check if swap file exists
stat:
path: "{{swap_file_path}}"
get_checksum: false
get_md5: false
register: swap_file_check
changed_when: false
- name: Set variable for existing swap file size
set_fact:
swap_file_existing_size_mb: "{{ (swap_file_check.stat.size / 1024 / 1024) | int }}"
when: swap_file_check.stat.exists
- name: Check if swap is on
shell: swapon --show | grep {{swap_file_path}}
register: swap_is_enabled
changed_when: false
failed_when: false
- name: Disable swap
command: swapoff {{swap_file_path}}
register: swap_disabled
when: >
swap_file_check.stat.exists
and 'rc' in swap_is_enabled and swap_is_enabled.rc == 0
and (not swap_enable or (swap_enable and swap_file_existing_size_mb != swap_file_size_mb))
- name: Delete the swap file
file:
path: "{{swap_file_path}}"
state: absent
when: not swap_enable
- name: Remove swap entry from fstab
mount:
name: none
src: "{{swap_file_path}}"
fstype: swap
opts: sw
passno: '0'
dump: '0'
state: present
when: not swap_enable
- name: Configure swap
when: swap_enable | bool
block:
- name: Create or change the size of swap file
command: dd if=/dev/zero of={{swap_file_path}} count={{swap_file_size_mb}} bs=1MiB
register: swap_file_created
when: >
not swap_file_check.stat.exists
or swap_file_existing_size_mb != swap_file_size_mb
- name: Change swap file permissions
file:
path: "{{swap_file_path}}"
mode: 0600
- name: Check if swap is formatted
shell: file {{swap_file_path}} | grep 'swap file'
register: swap_file_is_formatted
changed_when: false
failed_when: false
- name: Format swap file if it's not formatted
command: mkswap {{swap_file_path}}
when: >
('rc' in swap_file_is_formatted and swap_file_is_formatted.rc > 0)
or swap_file_created.changed
- name: Add swap entry to fstab
mount:
name: none
src: "{{swap_file_path}}"
fstype: swap
opts: sw
passno: '0'
dump: '0'
state: present
- name: Turn on swap
shell: swapon -a
# if swap was disabled from the start
# or has been disabled to change its params
when: >
('rc' in swap_is_enabled and swap_is_enabled.rc != 0)
or swap_disabled.changed
- name: Configure swappiness
sysctl:
name: vm.swappiness
value: "{{ swappiness|string }}"
state: present
我无法回复 Greg Dubicki 的回答 所以我在这里加上我的 2 美分:
我认为在对
int
进行计算以将其转换为 swap_file_size_mb * 1024 * 1024
时将转换添加到 swap_file_size_mb | int * 1024 * 1024
将使代码更智能,以防您想使用事实根据 RAM 量提取最终交换大小安装如下:
swap_file_size_mb: "{{ ansible_memory_mb['real']['total'] * 2 }}"
否则它将始终调整交换文件的大小,即使大小相同。
这是我用来在新服务器上安装 4GB(或我为
group_vars
* dd_bs_size_mb
配置 swap_count
的任何内容)交换空间的 ansible-swap 剧本:
https://github.com/tribou/ansible-swap
我还在我的
~/.bash_profile
中添加了一个功能来帮助完成任务:
# Path to where you clone the repo
ANSIBLE_SWAP_PLAYBOOK=$HOME/dev/ansible-swap
install-swap ()
{
usage='Usage: install-swap HOST';
if [ $# -ne 1 ]; then
echo "$usage";
return 1;
fi;
ansible-playbook $ANSIBLE_SWAP_PLAYBOOK/ansible-swap/site.yml --extra-vars "target=$1"
}
只需确保先将您的
HOST
添加到您的 ansible 库存中。
那就只是
install-swap HOST
.
这是 Galaxy 上的一个预先存在的角色,它实现了同样的事情:https://galaxy.ansible.com/geerlingguy/swap
对我有用的是通过剧本添加 4Gib 交换。
检查这个:
.