F/OSS gestionado y alojado de forma sostenible Almacenamiento de objetos, Redis, Prometheus en Hetzner, OVH y LeaseWeb **tl;dr - Explicación línea por línea de mi script de instalación de ZFS con tecnología ansible para usar en el hardware dedicado de Hetzner (Ubuntu 20.04 - âÂÂFocalâÂÂ) â  no es perfecto/mínimo, pero funciona para mí Hace un tiempo comencé a usar ZFS en todo mi hardware dedicado dedicado alojado en Hetzner para disputar los HDD y SSD adjuntos. Hay muchas opciones en el espacio (LVM estándar, mdraid btrfs, etc), pero elegí ZFS por su conjunto de características y ergonomía. No aburriré a nadie con el por qué, pero una de las cosas que necesitaba navegar era cómo instalar versiones más nuevas de ZFS en Ubuntu 20.04 (uno de los sistemas operativos compatibles con Hetzner). Encontré algunos problemas (particularmente después de la instalación) al configurar ZFS en mis sistemas, así que quería explicar cómo lo hice. Esta publicación es una explicación estrofa por estrofa de mis scripts de Ansible que instalan ZFS. Antes de saber si vale la pena cambiar a ZFS (o cualquier otro sistema de archivos), probablemente querrá usar RTFM. ZFS tiene muchos detalles y ciertamente no soy un experto en eso, pero es muy importante saber cómo y por qué, así como la terminología e incluso la historia del proyecto. Algunos enlaces para empezar: Junto con ZFS (que es probablemente la cantidad más desconocida aquí), probablemente desee estar familiarizado con Ubuntu y la administración general de sistemas. Esa es una gran área para cubrir, pero aquí hay algunos enlaces: Casi no hace falta decirlo, pero si no está muy familiarizado con la administración del sistema Linux en este momento, probablemente no debería intentarlo. Personalmente, elijo tener mis discos en una configuración algo personalizada â Tengo una configuración RAID1 (duplicación) a través de mdraid, junto con las particiones en cada disco que puedo darle a ZFS para que las administre. Idealmente, tendría discos completos para dar a ZFS, pero las particiones también funcionan. configuración del sistema operativo ( installimage) que incluye la configuración del disco se ejecuta desde el modo de rescate de Hetzner y se puede guiar con un archivo como el siguiente: # Declaraciones de unidades utilizadas por installimage DRIVE0 /dev/nvme0n1 DRIVE1 /dev/nvme1n1 # Habilitar software RAID (para el disco del sistema operativo) SWRAID 1 SWRAIDLEVEL 1 # Cargador de arranque (generalmente grub) BOOTLOADER grub # Machine hostname HOSTNAME machine01 # Partición configuración PART swap swap 32G PART /boot ext4 1G PART / ext4 128G # Esta última partición se realizará (borrada& recreado como ZFS más adelante) PARTE /root-disk-remaining ext4 all # Puede especificar las imágenes que utiliza Hetzner accediendo a su recurso compartido de red IMAGE /root/.oldroot/nfs/images/Ubuntu-2004-focal-64-minimal.tar. gz Obviamente, esto es bastante específico de Hetzner, pero haga lo que necesite hacer en sus propios sistemas para tener particiones/unidades disponibles para que las utilice ZFS. zfsutils-linuxand zfs-zed En Ansible YAML, el paso se ve así: - nombre: contiene todos los paquetes upstream relacionados con zfs ansible.builtin.shell: | apt-marca mantener zfsutils-linux apt-marca mantener zfs-zed A partir de la redacción de esta publicación, la versión de zfs-linux en Ubuntu Focal es 0.8.3. Dado que nuestro objetivo aquí es instalar y seguir usando una versión más nueva, queremos asegurarnos de que cualquier Las actualizaciones de apt no reemplazan nuestra versión instalada con una versión anterior. Mientras estamos aquí, purguemos los paquetes también. - nombre: Purgar paquetes ascendentes de ZFS (ubuntu) si están instalados ignore_errors: sí ansible.builtin.command: | apt purge --permitir-cambiar-paquetes retenidos zfsutils-linux zfs-zed Puede leer los documentos en apto para ver lo que purge hace â es similar a remove pero también elimina los archivos de configuración si están presentes. Puede instalar las dependencias para OpenZFS así: - nombre: Requisitos de instalación para compilar ZFS ansible.builtin.apt: nombre:packagesupdate_cache: sí estado: presente vars: paquetes: - build-essential - autoconf - automake - libtool - gawk - alien - fakeroot - dkms - libblkid-dev - uuid -dev - libudev-dev - libssl-dev - zlib1g-dev - libaio-dev - libattr1-dev - libelf-dev # La siguiente línea pide la salida de `uname -r`, por ejemplo "5.16.5-arch1- 1"para mi sistema arch # para que la línea se resuelva en algo así como "linux-headers-5.16.5-arch1-1"(no es válido en Ubuntu, por supuesto, pero es un ejemplo) - linux-headers uname_r.stdout }} - python3 - python3-dev - python3-setuptools - python3-cffi - libffi-dev - python3-packaging - git - libcurl4-openssl-dev Puede haber algunas dependencias que no son estrictamente necesarias, pero casi todas deberían ser obligatorias. /optar/zfs Aquí está ZFS: - nombre: Crear /opt/zfs ansible.builtin.file: ruta: /opt/zfs estado: directorio Si desea descargar ZFS: - nombre: Descargar zfs ansible.builtin.get_url: url: "httpsgithub.com/openzfs/zfs/releases/download/zfs _zfs_version zfs _zfs_version tar.gz"checksum:_zfs_tarball_sha256_checksummode: 0755 dest: "/opt/zfs/zfs _zfs_version tar .gz"Aquí la sustitución {{ _versión_zfs }} ( 2.1.1. También querrá hacer la descarga usted mismo y recopilar/generar una suma de comprobación para usar. ¡Nunca descargue cosas de Internet que se supone que no deben cambiar sin una suma de control! {{es la sintaxis de plantillas de Ansible) es Y si desea copiarlo desde la computadora donde se ejecuta Ansible (esto es lo que hago): - nombre: Copie el paquete zfs (evite el límite de velocidad) ansible.builtin.copy: src: files/zfs/zfs _zfs_version tar.gz"mode: 0755 dest: "/opt/zfs/zfs _zfs_version tar.gz"Independientemente de cómo elijas obtener la fuente, tendrás que descomprimirla, por supuesto: - nombre: Descomprima el código zfs ansible.builtin.unarchive: src: "/opt/zfs/zfs _zfs_version tar.gz"dest: "/opt/zfs"remote_src: sí Para iniciar el proceso de construcción: - nombre: Configuración y compilación de ZFS ansible.builtin.shell: | ./autogen../configure make clean make -j args: chdir: "/opt/zfs/zfs _zfs_version Si está familiarizado con la creación de cosas desde el origen, varios proyectos utilizan este conjunto de herramientas común (alguna variante de hacer, autogen y configurar scripts). Como es de esperar, esto puede llevar un tiempo, así que dale algo de tiempo. Después de compilar ZFS - nombre: Instalar ZFS ansible.builtin.shell: | hacer instalar argumentos: chdir: "/opt/zfs/zfs _zfs_version Normalmente pensarías que terminaríamos *aquí mismo*, ¡pero esta publicación existe porque hacer esto generalmente no es suficiente! Sigamos adelante. Primero fuerce la descarga de los módulos ZFS si se están ejecutando: - nombre: Forzar la descarga del módulo ZFS (ss) ansible.builtin.shell: | ./scripts/zfs.-u argumentos: chdir: "/opt/zfs/zfs _zfs_version Sería ideal *no* ejecutar ninguna carga de trabajo cuando esto suceda, como es de esperar. Mientras se descargan los módulos, podemos instalar algunos ayudantes: - nombre: Ayudantes posteriores a la instalación de ZFS ansible.builtin.shell: | ./scripts/zfs-helpers.-i argumentos: chdir: "/opt/zfs/zfs _zfs_version Después de instalar los ayudantes, forcemos la recarga del módulo ZFS: - nombre: Fuerza la recarga del módulo ZFS ansible.builtin.shell: | ./scripts/zfs.args: chdir: "/opt/zfs/zfs _zfs_versión He encontrado ese edificio y usando el El módulo deb (el formato utilizado por Debian para la instalación del paquete) también ayudó a que la instalación se mantuviera y no fuera reemplazada por los valores predeterminados del paquete de Ubuntu. Primero cree el paquete deb de ZFS a partir del código fuente: - nombre: Construya el paquete deb de ZFS ansible.builtin.shell: | hacer argumentos deb: chdir: "/opt/zfs/zfs _zfs_version Y luego instalarlo - nombre: Instalar paquetes deb de ZFS ansible.builtin.shell: | si | dpkg -i --force-overwrite deb apt install -f -y argumentos deb: chdir: "/opt/zfs/zfs _zfs_version En teoría, este paso *no debería* ser necesario (o debería usarse solo), ya que ya ejecutamos un proceso de instalación, pero descubrí que al hacer uno u otro  habría situaciones en las que los reinicios solicitarían el uso de una versión anterior de ZFS (a pesar de la apt purge) â particularmente a nivel del kernel. Modprobe Si desea habilitar el módulo ZFS que se instaló inmediatamente, use modprobe: - nombre: Modprobe zfs module block: - nombre: Instale el módulo kernel zfs community.general.modprobe: nombre: zfs state: presente Instalar ZFS significa instalar un módulo de kernel, pero dado que no lo hemos incorporado del todo a través de la compatibilidad con Dynamic Kernel Module, debemos habilitar el uso de módulos de kernel instalados localmente: - nombre: asegúrese de que extra esté al frente ansible.builtin.lineinfile: ruta: /etc/modules-load.d/modules.conf regexp: '^search'línea: "buscar actualizaciones adicionales ubuntu incorporadas"estado: presente Lo que esto hace es asegurarse de que el archivo que administra la ruta de búsqueda del módulo kernel /etc/modules-load.d/modules.conf tiene una línea que tiene buscar actualizaciones adicionales especificadas. Normalmente hay al menos una línea que comienza con buscar, y lo que queremos hacer es asegurarnos Las ubicaciones de módulos adicionales se buscan al principio del proceso. Querremos instalar a través del subsistema DKMS: - nombre: dkms install zfs ansible.builtin.shell: | dkms install zfs _zfs_version }} argumentos: chdir: "/opt/zfs/zfs _zfs_version En este punto, debería poder verificar la versión activa actual de ZFS, y debería mostrarle algo como esto: root@machine01 ~ # versión zfs zfs-2.1.1-1 zfs-kmod-2.1.1-1 Hay algunas unidades SystemD (como de costumbre, Digital Ocean tiene algunos documentos excelentes) que se crean pero deben habilitarse para que ZFS las use: - nombre: Asegúrese de que las unidades systemd relacionadas con zfs estén habilitadas bloque: - ansible.builtin.systemd: nombre:itemstate: iniciado habilitado: sí bucle: - zfs-import-cache.service - zfs-import.target - zfs-mount.service - zfs-share.service - zfs-zed.service - zfs-volume-wait.service - zfs.target Las variables que se repiten son similares a ejecutar systemd start and systemd enable . The security-minded reader at home is no doubt cringing into the atmosphere by now, but making sure my kernel upgrades are manual is the only way I’ve found to ensure that the installed version of ZFS was not disabled/unexpectedly altered/broken by kernel upgrades: - name: Hold all kernel upgrades to prevent custom built ZFS from doing fallback ansible.builtin.shell: | apt-mark hold linux-headers-generic apt-mark hold linux-image-generic apt-mark hold {{ uname_r.stdout }} # you'll need that `uname -r` output again here I personally prefer to hold back any kernel upgrades and instead perform them at machine setup rather than during operation. DKMS *should* ensure that with the building of any new kernel the ZFS code is rebuilt but it’s been flaky in the past so I find it hard to trust. Along with all the kernel changes we’ve made so far (good and questionable), one thing we’ll want to do is add the configuration necessary to ensure the kernel module is loaded: - name: Ensure zfs kernel module comes up with next restart tags: [ "zfs:post-install:config" ] block: - name: Add zfs module load file ansible.builtin.template: src: templates/kernel-modules/zfs.conf.j2 dest: /etc/modules-load.d/zfs.conf owner: root group: root mode: 0644 Now that we have ZFS installed (restart once to check I’m going to leave the rest of the cluster setup to you. There are a *lot* of ways to use ZFS and setup zpools (RAID0/1/5/Z Actually using ZFS properly is out of scope (I can only hope I’ve covered *installing* it properly, at least), but please refer to the usual manuals there to set up your ZFS pool and storage requirements. Trying to cover even the basics of how to setup ZFS for your drives once it’s been installed is certainly a lot of reading so we’ll leave it there for today. This is the part where you “draw the rest of the owl” (sorry). txg_timeout While experimenting with some write modes for Postgres on ZFS, I looked into an optimization modes that involved reducing the txg_timeout from it’s default of 5 seconds to 1 second. While I won’t get into the tradeoffs implied by that move (please read my post on Postgres + ZFS), here is the setup that I’ve used for modifying txg_timeout per-machine (some machines might use the optimization some might not): - name: Add systemd unit to support txg timeout customization tags: [ "zfs:post-install:config" ] block: - name: Set current ZFS txg_timeout (to 1) ansible.builtin.shell: | echo 1 > /sys/module/zfs/parameters/zfs_txg_timeout - name: install zfs-config-txg-timeout service ansible.builtin.template: src: templates/zfs-config-txg-timeout.service.j2 dest: /etc/systemd/system/zfs-config-txg-timeout.service owner: root group: root mode: 0644 - name: start & enable zfs-config-txg-timeout service ansible.builtin.systemd: name: zfs-config-txg-timeout.service state: started enabled: yes daemon_reload: yes The template that goes with that looks like this: [Unit] Description=Set ZFS txg_timeout After=zfs.target ConditionPathIsDirectory=/sys/module/zfs [Service] Type=oneshot RemainAfterExit=yes ExecStart=/usr/bin/bash -c 'echo {{ _zfs_txg_timeout_seconds | default(zfs_txg_timeout_seconds) }} > /sys/module/zfs/parameters/zfs_txg_timeout' # Not needed since we want it to always be whatever the setting is # ExecStop=/usr/bin/bash -c 'echo {{ _zfs_txg_timeout_seconds | default(zfs_txg_timeout_seconds) }} > /sys/module/zfs/parameters/zfs_txg_timeout' [Install] WantedBy=multi-user.target Obviously you’ll want to define {{ _zfs_txg_timeout_seconds }} and the zfs_txg_timeout_seconds. In general, this will make sure that the txg_timeout is set to what you want it to be upon startup after ZFS has started. Wasn’t that easy? If you’re answering no, it wasn’t easy for me to figure out either! I spent a lot of time wondering why DKMS wasn’t working properly (which is why the hack of preventing kernel upgrades is still included) and dealing with other issues. The OpenZFS documentation is pretty great but seems to be missing a guide somewhat like this, so hopefully this post will save people some time going forward when trying to experiment with new ZFS setups on Hetzner. Another thing I’m hoping for with this post is to be corrected – if you see something glaringly wrong in my setup, please reach out. The more people can use low cost infrastructure providers like Hetzner, the more cool software we get and the more interesting/innovative products can be built. To that end I’m working on NimbusWS (I’m behind on this but should launch by end of Q1 2022) – if you’re interested please sign up for the service and kick the tires (free tier usage will be available).