cloud-init
Cloud-init - это индустриальный кросс-платформенный мульти-дистрибутивный стандарт для инициализации инстансов
Он поддерживается во всех крупных cloud-провайдерах, в системах провижининга для приватных инфраструктур и на bare-metal
При загрузке инстанса cloud-init понимает в каком облаке он запущен, читает предоставленную метадату и инициализирует систему соответствующим образом
Он может сетапить сеть, девайсы, ssh-ключи и много всего другого
Getting Started
Tutorial
Для обучения и тестирования cloud-init скриптов удобно использовать lxd (там из коробки хорошая поддержка cloud-init)
Вот такой терраформ манифест создает подходящую виртуалку
terraform {
required_providers {
yandex = {
source = "yandex-cloud/yandex"
}
}
}
provider "yandex" {
token = "AQAAAAAayaoeuWVmM00"
cloud_id = "b1gaeounndt"
folder_id = "b1gaaoeuobf5v"
zone = "ru-central1-c"
}
data "yandex_compute_image" "compute_image_search" {
family = "ubuntu-2004-lts"
}
resource "yandex_compute_instance" "test" {
platform_id = "standard-v1"
zone = "ru-central1-a"
resources {
cores = 4
core_fraction = 20
memory = 4
}
boot_disk {
initialize_params {
image_id = "${data.yandex_compute_image.compute_image_search.image_id}"
size = 30
}
}
network_interface {
subnet_id = "${yandex_vpc_subnet.test_network_subnet.id}"
nat = true
}
metadata = {
ssh-keys = "ubuntu:${file("~/.ssh/id_rsa.pub")}"
}
}
resource "yandex_vpc_network" "test_network" {}
resource "yandex_vpc_subnet" "test_network_subnet" {
zone = "ru-central1-a"
network_id = "${yandex_vpc_network.test_network.id}"
v4_cidr_blocks = ["10.2.0.0/16"]
}
Далее заходим на нее, и налаживаем lxd
root@fhmkp99o5k8l3iultpf3:~# apt install snapd
root@fhmkp99o5k8l3iultpf3:~# snap install lxd
root@fhmkp99o5k8l3iultpf3:~# lxd init --minimal
Далее подготавливаем cloud-init конфиг
root@fhmkp99o5k8l3iultpf3:~# cat <<EOF > /tmp/user-data
> #cloud-config
> runcmd:
> - echo 'Hello, World!' > /var/tmp/hello-world.txt
> EOF
Запускаем контейнер с этим конфигом
root@fhmkp99o5k8l3iultpf3:~# lxc launch ubuntu:focal my-test --config=user.user-data="$(cat /tmp/user-data)"
Идем внутрь и проверяем как оно там отработало
root@fhmkp99o5k8l3iultpf3:~# lxc shell my-test
root@my-test:~# cloud-init status -l
status: done
time: Wed, 10 Aug 2022 11:11:58 +0000
detail:
DataSourceNoCloud [seed=/var/lib/cloud/seed/nocloud-net][dsmode=net]
root@my-test:~# cloud-init query userdata
#cloud-config
runcmd:
- echo 'Hello, World!' > /var/tmp/hello-world.txt
root@my-test:~# cloud-init schema --system --annotate
Valid cloud-config: system userdata
root@my-test:~# cat /var/tmp/hello-world.txt
Hello, World!
Сносим этот контейнер
root@fhmkp99o5k8l3iultpf3:~# lxc stop my-test
root@fhmkp99o5k8l3iultpf3:~# lxc rm my-test
Boot Stages
При загрузке из под systemd у cloud-init есть пять стадий:
- Generator - systemd generator (так и не понял что это за зверь) включает в автозагрузку
cloud-init.target
. Cloud-init можно выключить если создать файл/etc/cloud/cloud-init.disabled
или если передать аргумент при загрузке ядраcloud-init=disabled
- Local - сервис
cloud-init-local.service
. Цель локальной стадии - найти локальные источники данных и настроить сеть - Network -
cloud-init.service
, запускается после local stage и настроенной сети, запускаетdisk_setup
иmounts
модули - Config -
cloud-config.service
, запускает конфигурационные модули - Final -
cloud-final.service
, эта стадия запускается в последнюю очередь. Занимается установкой пакетов, применением configuration management плагинов (ansible, puppet, etc), и запуском пользовательских скриптов
Cloud-init понимает запускается он впервые на новом инстансе или нет, в зависимости от этого применяется соответсвующая конфигурация
При первой загрузке применяется вся per-instance
конфигурация, а при повторной загрузке применяются per-boot
конфиги
При запуске cloud-init оставляет кэш который хранит внутреннее состояние и используется между загрузками
Соответственно если кэш присутствует, значит cloud-init уже запускался на этой системе
Это могло случится если система была перезагружена или если файловая система была приаттачена к новому инстансу и фактически это первая загрузка системы но кэш в файловой системе уже присутствует (такое бывает когда инстанс запускается из образа созданного из уже запровижененной машины)
По умолчанию cloud-init пытается понять что за кейс у него сейчас, для этого он проверяет instance id из кэша и сравнивает с id который определяется окружением, если разные то это первая загрузка. Внутри это поведение называется check
Instance ID находится в /var/lib/cloud
:
root@fhmkp99o5k8l3iultpf3:~# cat /var/lib/cloud/data/instance-id
fhmkp99o5k8l3iultpf3
Возможны ситуации когда это поведение нужно изменить, это измененное поведение называется trust
и заставляет cloud-init безусловно доверять найденной в кеше инфе
Управлять этим можно через опцию manual_cache_clean
:
- false -> check
- true -> trust
Можно вручную снести кэш через cloud-init clean
Эта команда сносит все из /var/lib/cloud
root@fhmkp99o5k8l3iultpf3:~# tree /var/lib/cloud/ | wc -l
78
root@fhmkp99o5k8l3iultpf3:~# cloud-init clean
root@fhmkp99o5k8l3iultpf3:~# tree /var/lib/cloud/ | wc -l
4
CLI Interface
Актуальный список подкомманд доступен в хелпе cloud-init --help
- analyze - анализ длительности загрузки (связано с
systemd-analyze
) - clean - чистит артифакты из
/var/lib/cloud
, так же с соответствующими ключами может почистить логи, удалить instance id файл и ребутнуть машину после удаления артифактов - collect-logs - собирает логи и всякую инфу и закладывает это в tar-архив
root@fhmkp99o5k8l3iultpf3:~# cloud-init collect-logs Wrote /root/cloud-init.tar.gz root@fhmkp99o5k8l3iultpf3:~# tar --list -f cloud-init.tar.gz cloud-init-logs-2022-08-11/ cloud-init-logs-2022-08-11/cloud-init.log cloud-init-logs-2022-08-11/dmesg.txt cloud-init-logs-2022-08-11/journal.txt cloud-init-logs-2022-08-11/dpkg-version cloud-init-logs-2022-08-11/run/ cloud-init-logs-2022-08-11/run/cloud-init/ cloud-init-logs-2022-08-11/run/cloud-init/cloud.cfg cloud-init-logs-2022-08-11/run/cloud-init/instance-data-sensitive.json cloud-init-logs-2022-08-11/run/cloud-init/instance-data.json cloud-init-logs-2022-08-11/run/cloud-init/.instance-id cloud-init-logs-2022-08-11/run/cloud-init/.ds-identify.result cloud-init-logs-2022-08-11/run/cloud-init/ds-identify.log cloud-init-logs-2022-08-11/run/cloud-init/enabled cloud-init-logs-2022-08-11/run/cloud-init/cloud-init-generator.log cloud-init-logs-2022-08-11/run/cloud-init/sem/ cloud-init-logs-2022-08-11/run/cloud-init/sem/apply_network_config.once cloud-init-logs-2022-08-11/run/cloud-init/result.json cloud-init-logs-2022-08-11/run/cloud-init/cloud-id cloud-init-logs-2022-08-11/run/cloud-init/cloud-id-ec2 cloud-init-logs-2022-08-11/run/cloud-init/status.json cloud-init-logs-2022-08-11/cloud-init-output.log cloud-init-logs-2022-08-11/version
- devel - набор подкоманд которые сейчас находятся в разбработке, они будут вынесены в top-level когда станут стабильными
- features - принтит фичи (хз что это)
- init - налаживает стадии загрузки
- modules - запускает модули, по умолчанию при запуске от ОС запускет только config и final стадии
- query - инструмент для доступа к закешированной информации собранной при загрузке системы (
/run/cloud-init/instance-data.json
) - schema - валидирует cloud-config файлы
- single - запускает один указанный модуль (а не стейдж как обычно)
- status - статус выполнения
No Comments