Initial commit: LXC ZFS deployment with static MAC and VLAN

This commit is contained in:
bnolge
2026-03-17 10:47:36 +03:00
commit aaa94ecd58
3 changed files with 223 additions and 0 deletions
+78
View File
@@ -0,0 +1,78 @@
---
- name: Финальное развертывание Unprivileged LXC (ZFS + VLAN)
hosts: localhost
connection: local
become: yes
gather_facts: no
vars:
# Базовый конфиг (ID маппинг согласно вашему /etc/subuid)
base_lxc_conf: |
lxc.include = /usr/share/lxc/config/common.conf
lxc.include = /usr/share/lxc/config/debian.common.conf
lxc.arch = x86_64
# Маппинг для безопасного root (хост: 1,000,000 -> контейнер: 0)
lxc.idmap = u 0 1000000 65536
lxc.idmap = g 0 1000000 65536
# Сетевой интерфейс
lxc.net.0.type = veth
lxc.net.0.link = br0
lxc.net.0.flags = up
lxc.net.0.name = eth0
tasks:
- name: 1. Мгновенный клон из обновленного шаблона
shell: "zfs clone pool/lxc/template-debian12@snap0 pool/lxc/{{ item }}"
loop: [ 'bit-srv-prn', 'mail-bit-it-ru' ]
- name: 2. Настройка Legacy Mountpoint (важно для ZFS + LXC)
shell: "zfs set mountpoint=legacy pool/lxc/{{ item }}"
loop: [ 'bit-srv-prn', 'mail-bit-it-ru' ]
- name: 3. Подготовка директорий контейнеров
file:
path: "/var/lib/lxc/{{ item }}"
state: directory
loop: [ 'bit-srv-prn', 'mail-bit-it-ru' ]
- name: 4. Права на внешние данные почты (UID 1000000)
file:
path: /pool/bit-mail-data
owner: "1000000"
group: "1000000"
state: directory
recurse: yes
- name: 5. Запись конфига ПРИНТЕР (VLAN 30)
copy:
dest: /var/lib/lxc/bit-srv-prn/config
content: |
{{ base_lxc_conf }}
lxc.uts.name = bit-srv-prn
lxc.rootfs.path = zfs:pool/lxc/bit-srv-prn
lxc.net.0.veth.vlan.id = 30
- name: 6. Запись конфига ПОЧТА (VLAN 60 + Mount)
copy:
dest: /var/lib/lxc/mail-bit-it-ru/config
content: |
{{ base_lxc_conf }}
lxc.uts.name = mail-bit-it-ru
lxc.rootfs.path = zfs:pool/lxc/mail-bit-it-ru
lxc.net.0.veth.vlan.id = 60
lxc.mount.entry = /pool/bit-mail-data var/mail none bind,create=dir 0 0
- name: 7. Запуск контейнеров
shell: "lxc-start -n {{ item }} -d"
loop: [ 'bit-srv-prn', 'mail-bit-it-ru' ]
- name: 8. Проверка статуса (ждем загрузку)
pause:
seconds: 5
- name: 9. Итоговая таблица
shell: "lxc-ls -f"
register: lxc_final
- name: Результат
debug:
msg: "{{ lxc_final.stdout_lines }}"
+69
View File
@@ -0,0 +1,69 @@
---
- name: Развертывание Unprivileged LXC (Финал)
hosts: localhost
connection: local
become: yes
gather_facts: no
vars:
# Конфиг уже включает ID Mapping
base_conf: |
lxc.include = /usr/share/lxc/config/common.conf
lxc.include = /usr/share/lxc/config/debian.common.conf
lxc.arch = x86_64
lxc.idmap = u 0 100000 65536
lxc.idmap = g 0 100000 65536
lxc.net.0.type = veth
lxc.net.0.link = br0
lxc.net.0.flags = up
lxc.net.0.name = eth0
tasks:
- name: 1. Очистка старых контейнеров
shell: |
lxc-stop -n {{ item }} -k || true
lxc-destroy -n {{ item }} || true
zfs destroy -r pool/lxc/{{ item }} || true
loop: [ 'bit-srv-prn', 'mail-bit-it-ru' ]
failed_when: false
- name: 2. Мгновенный клон ZFS (уже с правами 100000)
shell: "zfs clone pool/lxc/template-debian12@snap0 pool/lxc/{{ item }}"
loop: [ 'bit-srv-prn', 'mail-bit-it-ru' ]
- name: 3. Установка legacy mountpoint
shell: "zfs set mountpoint=legacy pool/lxc/{{ item }}"
loop: [ 'bit-srv-prn', 'mail-bit-it-ru' ]
- name: 4. Подготовка папок LXC
file:
path: "/var/lib/lxc/{{ item }}"
state: directory
loop: [ 'bit-srv-prn', 'mail-bit-it-ru' ]
- name: 5. Права на внешние данные (для почты)
file:
path: /pool/bit-mail-data
owner: "100000"
group: "100000"
recurse: yes
- name: 6. Запись конфигов
copy:
dest: "/var/lib/lxc/{{ item.name }}/config"
content: |
{{ base_conf }}
lxc.net.0.veth.vlan.id = {{ item.vlan }}
lxc.rootfs.path = zfs:pool/lxc/{{ item.name }}
lxc.uts.name = {{ item.name }}
{% if item.mount is defined %}{{ item.mount }}{% endif %}
loop:
- { name: 'bit-srv-prn', vlan: '30' }
- { name: 'mail-bit-it-ru', vlan: '60', mount: 'lxc.mount.entry = /pool/bit-mail-data var/mail none bind,create=dir 0 0' }
- name: 7. Запуск
shell: "lxc-start -n {{ item.name }} -d"
loop:
- { name: 'bit-srv-prn' }
- { name: 'mail-bit-it-ru' }
+76
View File
@@ -0,0 +1,76 @@
---
- name: Деплой LXC с контролем уникальности MAC
hosts: localhost
become: yes
gather_facts: no
vars:
target_name: "default-container"
template_snap: "pool/lxc/template-debian12@snap0"
target_ds: "pool/lxc/{{ target_name }}"
base_lxc_path: "/var/lib/lxc/{{ target_name }}"
vlan_id: 30
tasks:
- name: 1. Валидация входных данных
fail:
msg: "Укажите имя: -e 'target_name=имя'"
when: target_name == "default-container"
- name: 2. Генерация детерминированного MAC-адреса
# Берем первые 6 символов sha256 от имени и разбиваем по 2 символа
set_fact:
generated_mac: "00:16:3e:{{ (target_name | checksum) | truncate(6, False, '') | batch(2) | map('join') | join(':') }}"
- name: 3. Сбор существующих MAC-адресов в системе
# Ищем строки lxc.net.0.hwaddr во всех конфигах /var/lib/lxc/*/config
shell: "grep -h 'lxc.net.0.hwaddr' /var/lib/lxc/*/config | awk '{print $3}' || true"
register: existing_macs
changed_when: false
- name: 4. Проверка на дубликат (если это новый контейнер)
fail:
msg: "Конфликт! MAC {{ generated_mac }} уже занят другим контейнером."
# Проверяем, есть ли сгенерированный мак в списке,
# НО игнорируем проверку, если мы просто пересобираем текущий контейнер
when:
- generated_mac in existing_macs.stdout_lines
- not (ansible_check_mode or (base_lxc_path + '/config') is file)
- name: 5. Создание ZFS клона
community.general.zfs:
name: "{{ target_ds }}"
origin: "{{ template_snap }}"
state: present
extra_zfs_properties:
mountpoint: legacy
- name: 6. Подготовка директории
file:
path: "{{ base_lxc_path }}"
state: directory
- name: 7. Запись конфига с фиксированным MAC
copy:
dest: "{{ base_lxc_path }}/config"
content: |
lxc.include = /usr/share/lxc/config/common.conf
lxc.arch = x86_64
lxc.idmap = u 0 1000000 65536
lxc.idmap = g 0 1000000 65536
lxc.net.0.type = veth
lxc.net.0.link = br0
lxc.net.0.flags = up
lxc.net.0.name = eth0
lxc.net.0.veth.vlan.id = {{ vlan_id }}
lxc.net.0.hwaddr = {{ generated_mac }}
lxc.uts.name = {{ target_name }}
lxc.rootfs.path = zfs:{{ target_ds }}
- name: 8. Запуск контейнера
community.general.lxc_container:
name: "{{ target_name }}"
state: started
- name: Итог
debug:
msg: "Контейнер {{ target_name }} запущен с MAC: {{ generated_mac }} в VLAN {{ vlan_id }}"