martes, 18 de noviembre de 2014

Swap en servidores de integración

En los servidores de integración tengo el mínimo de RAM necesaria para que funcionen ya que no es importante el tiempo de respuesta ni que estén continuamente levantados.

Ahora mismo es bastante normal que me falle al desplegar una nueva versión si tiene que compilar alguna libreria, y tengo que parar todos los servicios para que tenga memoria suficiente.

Tambien me llegan de vez en cuando mails de Logcheck avisando de que se ha quedado la máquina sin memoria:

System Events
=-=-=-=-=-=-=
Nov  8 08:00:16 staging kernel: [338269.889408] ruby invoked oom-killer: gfp_mask=0x201da, order=0, oom_score_adj=0
Nov  8 08:00:16 staging kernel: [338269.889414] ruby cpuset=/ mems_allowed=0$ sudo apt-get install ntp

Hasta ahora he aceptado estos problemas sin darles mayor importancia ya que solo ocurren en integración. Esta mañana hablando con mi amigo David me ha comentado que estaba instalando un servidor y que le había añadido swap siguiendo las indicaciones de un artículo de la magnífica documentación de Digital Ocean.

Es una solución evidente que no se me había ocurrido hasta ahora. En producción nunca configuro swap por temas de rendimiento, pero en integración no hay ningún problema en añadirla y me soluciona los problemas comentados anteriormente.

Así que he creado una receta de ansible para añadir swap a un servidor basada en ese artículo.

# Based on https://www.digitalocean.com/community/tutorials/how-to-add-swap-on-ubuntu-14-04
- name: Create swap file
  command: fallocate -l 1G /swapfile creates=/swapfile

- name: Set swap file permissions
  file: dest=/swapfile owner=root group=root mode=600

- name: Check if swap already exists
  shell: "swapon -s | grep '/swapfile'"
  register: swapfile
  ignore_errors: True

- name: Set up the swap space
  command: mkswap /swapfile
  when: swapfile|failed

- name: Enable swap
  command: swapon /swapfile
  when: swapfile|failed

- name: Make the swap file permanent
  mount: name=none src=/swapfile fstype=swap opts=sw passno=0 dump=0 state=present

- name: Set swappiness
  sysctl: name=vm.swappiness value=10 state=present

- name: Set vfs_cache_pressure
  sysctl: name=vm.vfs_cache_pressure value=50 state=present

El playbook se podría hacer un poco más genérico con el tamaño y el nombre de la swap en ficheros de configuración, pero para mi caso no es necesario.

Por último, como en los comandos mkswap y swapon no hay ninguna opción para que no execute si ya existe, he añadido una condición chequeando previamente si ya está creada la swap en la máquina.