Ansible und AWS: NVMe-Volumes automatisch einbinden

Für unser SaaS-Angebot nutzen wir die Cloud-Dienste von AWS. Diese richten wir mittels Ansible-Skripten ein. Dabei sind wir auf ein interessantes Problem beim Einbinden zusätzlicher EBS-Volumes auf einer Instanz gestoßen:

Wir binden die Volumes mit dem ec2_vol Plugin ein:

				
					- name: Create EC2 volume
  amazon.aws.ec2_vol:
    volume_size: "16G"
    volume_type: "gp2"
    instance: "{{ instance_id }}"
    device_name: sdf
    name: "some-data"
    tags:
      purpose: "{{ purpose }}"
    state: present
  register: ec2_volume
				
			

Laut Dokumentation sollte das Volume nun unter dem device_name, in diesem Fall also /dev/sdf, erreichbar sein. Allerdings klappt das nicht wie gedacht. Zum einen werden diese Namen vom Kernel vergeben und sind nicht vorhersagbar. Zum anderen werden NVMe-SSDs mit dem Namensschema /dev/nvmeXnY versehen. Die Dokumentation von AWS zum Thema EBS/NVMe weist darauf hin und klärt auf, dass der device_name eigentlich in ein Feld des NVMe-Controllers geschrieben wird.

Wie bindet man ein Volume ein, das soeben erst dynamisch erzeugt wurde?

Der Device Name wird zufällig zugewiesen, und Eigenschaften wie die UUID sind bei neuen Volumes noch unbekannt: wie können wir zuverlässig das richtige Volume einbinden? Dazu gibt es einige Lösungen, die jedoch recht viele Shellskripte erfordern. Ich möchte einen einfacheren Weg mit den Bordmitteln von Ansible aufzeigen:

Dabei können wir ausnutzen, dass unser Volume von AWS eine ID der Form vol-abcdef0123456 erhält. Diese wird dem Volume als Seriennummer zugewiesen, aber ohne den Bindestrich, volabcdef0123456.

Fragen wir von AWS die Volumeinformationen ab…

				
					- name: Get EC2 volume details
  delegate_to: localhost
  amazon.aws.ec2_vol_info:
    filters:
      "tag:Name": "some-data"
  register: ec2_vol_info
				
			

… und extrahieren die Volume-ID:

				
					- name: Store volume serial number
  ansible.builtin.set_fact:
    ebs_volume_id: "{{ ec2_vol_info.volumes[0].id | replace('-', '') }}"
				
			

Nun können wir mit lsblk den Pfad zu dem Volume mit dieser „Seriennummer“ ermitteln:

				
					- name: List Linux block devices
  ansible.builtin.shell:
    cmd: "lsblk -o PATH,SERIAL | grep {{ ebs_volume_id }} | cut -d' ' -f1"
  register: lsblk

- name: Store EBS volume device name
  ansible.builtin.set_fact:
    ebs_volume_device_name: "{{ lsblk.stdout }}"
				
			

Und voilà, in ebs_volume_device_name ist nun der volle Pfad zu unseren Volume gespeichert. Diesen kann man nun nutzen um das Volume zu formatieren und zu mounten:

				
					- name: Format EC2 volume
  community.general.filesystem:
    fstype: ext4
    dev: "{{ ebs_volume_device_name }}"
    force: no

- name: Mount EC2 volume
  ansible.posix.mount:
    path: /mnt/ebs
    src: "{{ ebs_volume_device_name }}"
    fstype: ext4
    boot: yes
    state: mounted
				
			

Abgesehen von dem Shell-Einzeiler um lsblk kamen übersichtliche, gut lesbare und wartbare Ansible-Plugins zum Einsatz.

Dieser Ansatz funktioniert auch über Neustarts der Instanz hinweg, so wie es Ansibles idempotentes Design vorsieht.

© 2022 flowciety GmbH

Gluon

In der Teilchenphysik sind die Gluonen (engl. to glue = kleben) Elementarteilchen, die für die Anziehung von Protonen und Neutronen in einem Atomkern verantwortlich sind.

Wie die Teilchen auf subatomarer Ebene, hilft Glu:on Unternehmen eine starke Verbindung mit ihren Partnern aufzubauen.