cloud-init
cloud-init
- クラウド環境のサーバー (cloud instance) の初期化処理を容易にするためのツールである。
起動ステージ (Boot Stages)
- 起動は 5 つのステージに分けられる。
- Detect
- Local
- Network
- Config
- Final
Detect
-
ds-identify
ツールを実行して、cloud instance が実行されている環境 (データソース) を検出する。 - データソースの一覧はこちらを参照。
Local
- systemd サービス:
cloud-init-local.service
Network
- systemd サービス:
cloud-init.service
- モジュール:
/etc/cloud/cloud.cfg
のcloud_init_modules
Config
- systemd サービス:
cloud-config.service
- モジュール:
/etc/cloud/cloud.cfg
のcloud_config_modules
Final
- systemd サービス:
cloud-final.service
- モジュール:
/etc/cloud/cloud.cfg
のcloud_final_modules
初回起動検出 (First Boot Determination)
- https://docs.cloud-init.io/en/latest/explanation/boot.html#first-boot-determination
- cloud-init は、対象の cloud instance が初回起動か (イメージから作成されたか) 、既存のものを再起動したものかで、異なる処理を実行する。
- 初回起動の場合は "per-instance" の設定を行い、以降の起動では "per-boot" の設定を行う。
- cloud-init は、内部の状態をキャッシュに保存しており、キャッシュ内のインスタンス ID が現在のものと一致しているかどうかで、初回起動かどうかの判定を行う。この挙動を "check" モードという。
- 上記の挙動がうまく動作しない場合のために、"trust" モードが存在しており、無条件にキャッシュのインスタンス ID 情報を信用させることもできる。ただし、インスタンス ID を再検出させたい場合はキャッシュディレクトリを手動で削除しなければいけない。
- "check" モードと "trust" モードのどっちを利用するかは、設定ファイルで
manual_cache_clean
を設定することでできる。これは、デフォルトで false に設定されていて、"check" モードが選択される。true にした場合に "trust" モードになる。
キャッシュディレクトリのレイアウト (Cache Directory Layout)
- ドキュメント: https://github.com/canonical/cloud-init/blob/main/doc/var-lib-cloud.txt
-
/var/lib/cloud/
-
data/
: インスタンス ID、ホスト名、データソース等の情報-
instance-id
: cloud instance の識別子 -
result.json
: データソースとエラーが発生したかどうか -
status.json
: データソース、各ステージの情報 (エラーが発生したか、開始時間、終了時間)
-
handlers/
-
instance/
:instances/<instance-id>/
へのシンボリックリンク -
instances/
<instance-id>/
-
scripts/
: cloud-init 経由で実行したいスクリプト-
per-boot/
: 起動ごと -
per-instance/
: インスタンスごと -
per-once/
: 1 度だけ -
vendor/
: ベンダーごと (?)
-
-
seed/
: 特定のデータソースに対して、ユーザーデータなどを注入できる (基本的に気にしないで良い) -
sem/
: 1回限りのスクリプトが実行されたかどうかを示すセマフォ (基本的に気にしないで良い)
-
-
cloud-init clean
コマンドでクリーンアップできる。
設定ファイル (Configuration Files)
- https://cloudinit.readthedocs.io/en/latest/explanation/configuration.html#base-configuration
/etc/cloud/cloud.cfg
/etc/cloud/cloud.cfg.d/*.cfg
ログ (Logs)
- https://cloudinit.readthedocs.io/en/latest/howto/debugging.html#cloud-init-ran-but-didn-t-do-what-i-want-it-to
/var/log/cloud-init.log
/var/log/cloud-init-output.log
-
cloud-init collect-logs
コマンドを使うと、トラブルシューティングに使える諸々のファイルを tar で固めてくれる。
ユーザーデータのフォーマット
cloud-config
- https://cloudinit.readthedocs.io/en/latest/reference/examples.html#yaml-examples
- YAML 形式で記述する cloud-init 固有の設定ができる。
-
#cloud-config
(MIME アーカイブの場合はContent-Type: text/cloud-config
) から始まる必要がある。
ユーザーデータスクリプト
- シェルスクリプトを実行するのに利用できるため、cloud-init で用意されていない任意の処理が実行できる。
-
#!
(MIME アーカイブの場合はContent-Type: text/x-shellscript
) から始まる必要がある。
MIME マルチパートアーカイブ
Content-Type: multipart/mixed; boundary="boundary_str"
This is the preamble. It is to be ignored.
--boundary_str
Content-Type: text/cloud-config
...
--boundary_str
Content-Type: text/x-shellscript
...
--boundary_str--
This is the epilogue. It is also to be ignored.
参考リンク (References)
Hands-On
Amazon Linux 2023 AMI を使って、色々確認していく。
ちゃんとインストールされてる。
$ rpm -qa | grep cloud-init
cloud-init-cfg-ec2-22.2.2-1.amzn2023.1.12.noarch
cloud-init-22.2.2-1.amzn2023.1.12.noarch
RPM パッケージには、依存関係を含めると、かなり色んなファイルが入ってるが、重要そうなものだけここでは抜粋。cloud-init
, cloud-id
, cloud-init-per
などの実行ファイルの他に、systemd 用のファイルや設定ファイルが入っている。
$ rpm -ql cloud-init
# snipped
/etc/cloud/cloud.cfg
/etc/cloud/cloud.cfg.d
/etc/cloud/cloud.cfg.d/05_logging.cfg
/etc/cloud/cloud.cfg.d/40_selinux-reboot.cfg
/etc/cloud/cloud.cfg.d/README
# snipped
/usr/bin/cloud-id
/usr/bin/cloud-init
/usr/bin/cloud-init-per
# snipped
/usr/lib/systemd/system-generators/cloud-init-generator
/usr/lib/systemd/system/cloud-config.service
/usr/lib/systemd/system/cloud-config.target
/usr/lib/systemd/system/cloud-final.service
/usr/lib/systemd/system/cloud-init-hotplugd.service
/usr/lib/systemd/system/cloud-init-hotplugd.socket
/usr/lib/systemd/system/cloud-init-local.service
/usr/lib/systemd/system/cloud-init.service
/usr/lib/systemd/system/cloud-init.target
# snipped
/usr/libexec/cloud-init
/usr/libexec/cloud-init/ds-identify
/usr/libexec/cloud-init/hook-hotplug
/usr/libexec/cloud-init/uncloud-init
/usr/libexec/cloud-init/write-ssh-key-fingerprints
# snipped
/var/lib/cloud
cloud-init
本体には、パスが通ってる。
$ which cloud-init
/usr/bin/cloud-init
systemd における依存関係を確認する。cloud-init.target
が最終的なターゲットになる模様。
$ sudo systemctl list-dependencies
default.target
# snipped
● └─multi-user.target
# snipped
● ├─cloud-init.target
● │ ├─cloud-config.service
● │ ├─cloud-final.service
● │ ├─cloud-init-local.service
● │ └─cloud-init.service
# snipped
systemd における順序関係を確認する。
$ sudo systemctl list-dependencies --after cloud-init.target
cloud-init.target
● ├─cloud-config.service
● ├─cloud-final.service
● ├─cloud-init-local.service
● └─multi-user.target
# snipped
$ sudo systemctl list-dependencies --after cloud-final.service
cloud-final.service
● ├─cloud-config.service
# snipped
● ├─network-online.target
● │ ├─cloud-init.service
● │ ├─systemd-networkd-wait-online.service
● │ └─network.target
● │ ├─systemd-networkd.service
● │ ├─systemd-resolved.service
● │ └─network-pre.target
● │ ├─cloud-init-local.service
● │ └─systemd-network-generator.service
# snipped
$ sudo systemctl list-dependencies --after cloud-config.service
cloud-config.service
# snipped
● ├─cloud-config.target
● │ ├─cloud-init-local.service
● │ └─cloud-init.service
● ├─network-online.target
● │ ├─cloud-init.service
● │ ├─systemd-networkd-wait-online.service
● │ └─network.target
● │ ├─systemd-networkd.service
● │ ├─systemd-resolved.service
● │ └─network-pre.target
● │ ├─cloud-init-local.service
● │ └─systemd-network-generator.service
# snipped
$ sudo systemctl list-dependencies --after cloud-config.target
cloud-config.target
● ├─cloud-init-local.service
● └─cloud-init.service
$ sudo systemctl list-dependencies --after cloud-init.service
cloud-init.service
● ├─cloud-init-local.service
● ├─system.slice
● ├─systemd-journald.socket
● └─systemd-networkd-wait-online.service
まとめると、順序的には、以下の通り。
cloud-init-local.service
は、ネットワークの設定を始める前に実行し、cloud-final.service
は逆にネットワークがオンラインになってから実行する。
cloud-init-local.service
|
V
network-pre.target
|
V
network.service
|
V
cloud-init.service
|
V
cloud-config.target network-online.target
| |
+---------------------+
V
cloud-config.service
|
V
cloud-final.service
|
V
cloud-init.target
中で何が実行されているか見る。
Amazon Linux 2023 では、EC2 上だとファイルの削除だけで、cloud-init init --local
は実行しないらしい。
$ sudo systemctl cat cloud-init-local | grep -B 2 ExecStart
[Service]
Type=oneshot
ExecStart=/usr/bin/cloud-init init --local
--
# Skip cloud-init-local if we're running in Amazon EC2
[Service]
ExecStart=
ExecStart=/bin/rm -vf /var/lib/cloud/instance/boot-finished /var/lib/cloud/data/no-net /var/lib/cloud/instance
$ sudo systemctl cat cloud-init.service | grep ExecStart
ExecStart=/usr/bin/cloud-init init
$ sudo systemctl cat cloud-config.service | grep ExecStart
ExecStart=/usr/bin/cloud-init modules --mode=config
$ sudo systemctl cat cloud-final.service | grep ExecStart
ExecStart=/usr/bin/cloud-init modules --mode=final
ヘルプメッセージを見てみる。
$ cloud-init --help
usage: /usr/bin/cloud-init [-h] [--version] [--file FILES] [--debug] [--force]
{init,modules,single,query,dhclient-hook,features,analyze,devel,collect-logs,clean,status,schema} ...
optional arguments:
-h, --help show this help message and exit
--version, -v Show program's version number and exit.
--file FILES, -f FILES
Use additional yaml configuration files.
--debug, -d Show additional pre-action logging (default: False).
--force Force running even if no datasource is found (use at your own risk).
Subcommands:
{init,modules,single,query,dhclient-hook,features,analyze,devel,collect-logs,clean,status,schema}
init Initialize cloud-init and perform initial modules.
modules Activate modules using a given configuration key.
single Run a single module.
query Query standardized instance metadata from the command line.
dhclient-hook Run the dhclient hook to record network info.
features List defined features.
analyze Devel tool: Analyze cloud-init logs and data.
devel Run development tools.
collect-logs Collect and tar all cloud-init debug info.
clean Remove logs and artifacts so cloud-init can re-run.
status Report cloud-init status or wait on completion.
schema Validate cloud-config files using jsonschema.
$ cloud-init init --help
usage: /usr/bin/cloud-init init [-h] [--local]
optional arguments:
-h, --help show this help message and exit
--local, -l Start in local mode (default: False).
$ cloud-init modules --help
usage: /usr/bin/cloud-init modules [-h] [--mode {init,config,final}]
optional arguments:
-h, --help show this help message and exit
--mode {init,config,final}, -m {init,config,final}
Module configuration name to use (default: config).
journal ログを見てみる。
$ journalctl -u cloud-init-local.service
Feb 09 09:57:45 localhost systemd[1]: Starting cloud-init-local.service - Initial cloud-init job (pre-networking)...
Feb 09 09:57:45 localhost systemd[1]: Finished cloud-init-local.service - Initial cloud-init job (pre-networking).
$ journalctl -u cloud-init-local.service
Feb 09 09:57:45 localhost systemd[1]: Starting cloud-init-local.service - Initial cloud-init job (pre-networking)...
Feb 09 09:57:45 localhost systemd[1]: Finished cloud-init-local.service - Initial cloud-init job (pre-networking).
[ec2-user@ip-172-31-73-4 ~]$ journalctl -u cloud-init.service
Feb 09 09:57:46 localhost systemd[1]: Starting cloud-init.service - Initial cloud-init job (metadata service crawler)...
Feb 09 09:57:47 localhost cloud-init[9594]: Cloud-init v. 22.2.2 running 'init' at Fri, 09 Feb 2024 09:57:47 +0000. Up 8.61 seconds.
Feb 09 09:57:47 localhost cloud-init[9594]: ci-info: +++++++++++++++++++++++++++++++++++++++Net device info+++++++++++++++++++++++++++++++++++++++
Feb 09 09:57:47 localhost cloud-init[9594]: ci-info: +--------+------+------------------------------+---------------+--------+-------------------+
Feb 09 09:57:47 localhost cloud-init[9594]: ci-info: | Device | Up | Address | Mask | Scope | Hw-Address |
Feb 09 09:57:47 localhost cloud-init[9594]: ci-info: +--------+------+------------------------------+---------------+--------+-------------------+
# snipped
Feb 09 09:57:47 localhost cloud-init[9594]: ci-info: +--------+------+------------------------------+---------------+--------+-------------------+
Feb 09 09:57:47 localhost cloud-init[9594]: ci-info: ++++++++++++++++++++++++++++++Route IPv4 info++++++++++++++++++++++++++++++
Feb 09 09:57:47 localhost cloud-init[9594]: ci-info: +-------+-------------+-------------+-----------------+-----------+-------+
Feb 09 09:57:47 localhost cloud-init[9594]: ci-info: | Route | Destination | Gateway | Genmask | Interface | Flags |
Feb 09 09:57:47 localhost cloud-init[9594]: ci-info: +-------+-------------+-------------+-----------------+-----------+-------+
# snipped
Feb 09 09:57:47 localhost cloud-init[9594]: ci-info: +-------+-------------+-------------+-----------------+-----------+-------+
Feb 09 09:57:47 localhost cloud-init[9594]: ci-info: +++++++++++++++++++Route IPv6 info+++++++++++++++++++
Feb 09 09:57:47 localhost cloud-init[9594]: ci-info: +-------+-------------+---------+-----------+-------+
Feb 09 09:57:47 localhost cloud-init[9594]: ci-info: | Route | Destination | Gateway | Interface | Flags |
Feb 09 09:57:47 localhost cloud-init[9594]: ci-info: +-------+-------------+---------+-----------+-------+
# snipped
Feb 09 09:57:47 localhost cloud-init[9594]: ci-info: +-------+-------------+---------+-----------+-------+
Feb 09 09:57:48 ip-172-31-73-4.ec2.internal useradd[9672]: new group: name=ec2-user, GID=1000
Feb 09 09:57:48 ip-172-31-73-4.ec2.internal useradd[9672]: new user: name=ec2-user, UID=1000, GID=1000, home=/home/ec2-user, shell=/bin/bash, from=none
Feb 09 09:57:48 ip-172-31-73-4.ec2.internal useradd[9672]: add 'ec2-user' to group 'adm'
Feb 09 09:57:48 ip-172-31-73-4.ec2.internal useradd[9672]: add 'ec2-user' to group 'wheel'
Feb 09 09:57:48 ip-172-31-73-4.ec2.internal useradd[9672]: add 'ec2-user' to group 'systemd-journal'
Feb 09 09:57:48 ip-172-31-73-4.ec2.internal useradd[9672]: add 'ec2-user' to shadow group 'adm'
Feb 09 09:57:48 ip-172-31-73-4.ec2.internal useradd[9672]: add 'ec2-user' to shadow group 'wheel'
Feb 09 09:57:48 ip-172-31-73-4.ec2.internal useradd[9672]: add 'ec2-user' to shadow group 'systemd-journal'
Feb 09 09:57:49 ip-172-31-73-4.ec2.internal cloud-init[9594]: Generating public/private ed25519 key pair.
Feb 09 09:57:49 ip-172-31-73-4.ec2.internal cloud-init[9594]: Your identification has been saved in /etc/ssh/ssh_host_ed25519_key
Feb 09 09:57:49 ip-172-31-73-4.ec2.internal cloud-init[9594]: Your public key has been saved in /etc/ssh/ssh_host_ed25519_key.pub
Feb 09 09:57:49 ip-172-31-73-4.ec2.internal cloud-init[9594]: The key fingerprint is:
Feb 09 09:57:49 ip-172-31-73-4.ec2.internal cloud-init[9594]: SHA256:isDkkiBPlB1KF2bxgJ3eA59MryM3yQNG61fvtsOPYDA root@ip-172-31-73-4.ec2.internal
Feb 09 09:57:49 ip-172-31-73-4.ec2.internal cloud-init[9594]: The key's randomart image is:
Feb 09 09:57:49 ip-172-31-73-4.ec2.internal cloud-init[9594]: +--[ED25519 256]--+
# snipped
Feb 09 09:57:49 ip-172-31-73-4.ec2.internal cloud-init[9594]: +----[SHA256]-----+
Feb 09 09:57:49 ip-172-31-73-4.ec2.internal cloud-init[9594]: Generating public/private ecdsa key pair.
Feb 09 09:57:49 ip-172-31-73-4.ec2.internal cloud-init[9594]: Your identification has been saved in /etc/ssh/ssh_host_ecdsa_key
Feb 09 09:57:49 ip-172-31-73-4.ec2.internal cloud-init[9594]: Your public key has been saved in /etc/ssh/ssh_host_ecdsa_key.pub
Feb 09 09:57:49 ip-172-31-73-4.ec2.internal cloud-init[9594]: The key fingerprint is:
Feb 09 09:57:49 ip-172-31-73-4.ec2.internal cloud-init[9594]: SHA256:eXNPlizwki4+6nShA7H8LGFnpfeV6IsMAP+yCP0MKwQ root@ip-172-31-73-4.ec2.internal
Feb 09 09:57:49 ip-172-31-73-4.ec2.internal cloud-init[9594]: The key's randomart image is:
Feb 09 09:57:49 ip-172-31-73-4.ec2.internal cloud-init[9594]: +---[ECDSA 256]---+
# snipped
Feb 09 09:57:49 ip-172-31-73-4.ec2.internal cloud-init[9594]: +----[SHA256]-----+
Feb 09 09:57:49 ip-172-31-73-4.ec2.internal systemd[1]: Finished cloud-init.service - Initial cloud-init job (metadata service crawler).
$ journalctl -u cloud-config.service
Feb 09 09:57:49 ip-172-31-73-4.ec2.internal systemd[1]: Starting cloud-config.service - Apply the settings specified in cloud-config...
Feb 09 09:57:49 ip-172-31-73-4.ec2.internal cloud-init[9728]: Cloud-init v. 22.2.2 running 'modules:config' at Fri, 09 Feb 2024 09:57:49 +0000. Up 10.54 seconds.
Feb 09 09:57:49 ip-172-31-73-4.ec2.internal systemd[1]: Finished cloud-config.service - Apply the settings specified in cloud-config.
$ journalctl -u cloud-final.service
Feb 09 09:57:49 ip-172-31-73-4.ec2.internal systemd[1]: Starting cloud-final.service - Execute cloud user/final scripts...
Feb 09 09:57:49 ip-172-31-73-4.ec2.internal cloud-init[9747]: Cloud-init v. 22.2.2 running 'modules:final' at Fri, 09 Feb 2024 09:57:49 +0000. Up 10.78 seconds.
Feb 09 09:57:49 ip-172-31-73-4.ec2.internal cloud-init[9750]: -----BEGIN SSH HOST KEY FINGERPRINTS-----
# snipped
Feb 09 09:57:49 ip-172-31-73-4.ec2.internal cloud-init[9755]: -----END SSH HOST KEY FINGERPRINTS-----
Feb 09 09:57:49 ip-172-31-73-4.ec2.internal cloud-init[9756]: #############################################################
Feb 09 09:57:49 ip-172-31-73-4.ec2.internal cloud-init[9747]: Cloud-init v. 22.2.2 finished at Fri, 09 Feb 2024 09:57:49 +0000. Datasource DataSourceEc2. Up 10.90 seconds
Feb 09 09:57:49 ip-172-31-73-4.ec2.internal systemd[1]: Finished cloud-final.service - Execute cloud user/final scripts.
/var/lib/cloud
の階層構造を見ておく。
$ tree /var/lib/cloud
/var/lib/cloud
├── data
│ ├── instance-id
│ ├── previous-datasource
│ ├── previous-hostname
│ ├── previous-instance-id
│ ├── python-version
│ ├── result.json
│ ├── set-hostname
│ └── status.json
├── handlers
├── instance -> /var/lib/cloud/instances/i-XXXXXXXX
├── instances
│ └── i-XXXXXXXX
│ ├── boot-finished
│ ├── cloud-config.txt
│ ├── datasource
│ ├── handlers
│ ├── obj.pkl
│ ├── scripts
│ ├── sem
│ │ ├── config_ca_certs
│ │ ├── config_disk_setup
│ │ ├── config_install_hotplug
│ │ ├── config_keyboard
│ │ ├── config_keys_to_console
│ │ ├── config_locale
│ │ ├── config_mcollective
│ │ ├── config_mounts
│ │ ├── config_ntp
│ │ ├── config_package_update_upgrade_install
│ │ ├── config_phone_home
│ │ ├── config_power_state_change
│ │ ├── config_puppet
│ │ ├── config_reset_rmc
│ │ ├── config_rightscale_userdata
│ │ ├── config_rsyslog
│ │ ├── config_runcmd
│ │ ├── config_salt_minion
│ │ ├── config_scripts_per_instance
│ │ ├── config_scripts_user
│ │ ├── config_scripts_vendor
│ │ ├── config_seed_random
│ │ ├── config_selinux
│ │ ├── config_set_passwords
│ │ ├── config_ssh
│ │ ├── config_ssh_authkey_fingerprints
│ │ ├── config_timezone
│ │ ├── config_users_groups
│ │ ├── config_write_files
│ │ ├── config_write_files_deferred
│ │ ├── config_write_metadata
│ │ ├── config_yum_add_repo
│ │ ├── config_yum_variables
│ │ └── consume_data
│ ├── user-data.txt
│ ├── user-data.txt.i
│ ├── vendor-data.txt
│ ├── vendor-data.txt.i
│ ├── vendor-data2.txt
│ └── vendor-data2.txt.i
├── scripts
│ ├── per-boot
│ ├── per-instance
│ ├── per-once
│ └── vendor
├── seed
└── sem
└── config_scripts_per_once.once
$ cat /var/lib/cloud/instance/datasource
DataSourceEc2: DataSourceEc2
デフォルトの /etc/cloud/cloud.cfg
を見ておく。
$ cat /etc/cloud/cloud.cfg
# The top level settings are used as module
# and system configuration.
# A set of users which may be applied and/or used by various modules
# when a 'default' entry is found it will reference the 'default_user'
# from the distro configuration specified below
users:
- default
# If this is set, 'root' will not be able to ssh in and they
# will get a message to login instead as the default $user
disable_root: true
mount_default_fields: [~, ~, 'auto', 'defaults,nofail', '0', '2']
resize_rootfs: noblock
resize_rootfs_tmp: /dev
ssh_pwauth: false
# This will cause the set+update hostname module to not operate (if true)
preserve_hostname: false
# If you use datasource_list array, keep array items in a single line.
# If you use multi line array, ds-identify script won't read array items.
# Example datasource config
# datasource:
# Ec2:
# metadata_urls: [ 'blah.com' ]
# timeout: 5 # (defaults to 50 seconds)
# max_wait: 10 # (defaults to 120 seconds)
# The modules that run in the 'init' stage
cloud_init_modules:
- migrator
- seed_random
- bootcmd
- write-files
- write-metadata
- growpart
- resizefs
- disk_setup
- mounts
- set_hostname
- update_hostname
- update_etc_hosts
- ca-certs
- rsyslog
- selinux
- users-groups
- ssh
# The modules that run in the 'config' stage
cloud_config_modules:
- ssh-import-id
- keyboard
- locale
- set-passwords
- yum-variables
- yum-add-repo
- ntp
- timezone
- disable-ec2-metadata
- runcmd
# The modules that run in the 'final' stage
cloud_final_modules:
- package-update-upgrade-install
- write-files-deferred
- puppet
- chef
- mcollective
- salt-minion
- reset_rmc
- refresh_rmc_and_interface
- rightscale_userdata
- scripts-vendor
- scripts-per-once
- scripts-per-boot
- scripts-per-instance
- scripts-user
- ssh-authkey-fingerprints
- keys-to-console
- install-hotplug
- phone-home
- final-message
- power-state-change
# System and/or distro specific settings
# (not accessible to handlers/transforms)
system_info:
# This will affect which distro class gets used
distro: amazon
# Default user name + that default users groups (if added/used)
default_user:
name: ec2-user
lock_passwd: True
gecos: EC2 Default User
groups: [wheel, adm, systemd-journal]
sudo: ["ALL=(ALL) NOPASSWD:ALL"]
shell: /bin/bash
# Other config here will be given to the distro class and/or path classes
paths:
cloud_dir: /var/lib/cloud/
templates_dir: /etc/cloud/templates/
ssh_svcname: sshd
Hands-On (Cont.)
ブートレコードを確認しておく。
$ cloud-init analyze show
-- Boot Record 01 --
The total time elapsed since completing an event is printed after the "@" character.
The time the event takes is printed after the "+" character.
Starting stage: init-network
|`->no cache found @00.04600s +00.00000s
|`->found network data from DataSourceEc2 @00.06900s +00.14000s
|`->setting up datasource @00.24400s +00.00000s
|`->reading and applying user-data @00.39400s +00.00200s
|`->reading and applying vendor-data @00.39600s +00.00000s
|`->reading and applying vendor-data2 @00.39600s +00.00000s
|`->activating datasource @00.56600s +00.00200s
|`->config-migrator ran successfully @00.61700s +00.00000s
|`->config-seed_random ran successfully @00.61700s +00.00100s
|`->config-bootcmd ran successfully @00.61800s +00.00000s
|`->config-write-files ran successfully @00.61800s +00.00100s
|`->config-write-metadata ran successfully @00.62000s +00.00300s
|`->config-growpart ran successfully @00.62300s +00.52100s
|`->config-resizefs ran successfully @01.14400s +00.00200s
|`->config-disk_setup ran successfully @01.14600s +00.00200s
|`->config-mounts ran successfully @01.14800s +00.00200s
|`->config-set_hostname ran successfully @01.15000s +00.00000s
|`->config-update_hostname ran successfully @01.15000s +00.00300s
|`->config-update_etc_hosts ran successfully @01.15300s +00.00000s
|`->config-ca-certs ran successfully @01.15400s +00.00100s
|`->config-rsyslog ran successfully @01.15500s +00.00100s
|`->config-selinux ran successfully @01.15600s +00.01800s
|`->config-users-groups ran successfully @01.17500s +00.40000s
|`->config-ssh ran successfully @01.57500s +00.05600s
Finished stage: (init-network) 01.63100 seconds
Starting stage: modules-config
|`->config-keyboard ran successfully @01.93300s +00.00300s
|`->config-locale ran successfully @01.93600s +00.00400s
|`->config-set-passwords ran successfully @01.94000s +00.01300s
|`->config-yum-variables ran successfully @01.95300s +00.00200s
|`->config-yum-add-repo ran successfully @01.95500s +00.00100s
|`->config-ntp ran successfully @01.95600s +00.00100s
|`->config-timezone ran successfully @01.95800s +00.00100s
|`->config-disable-ec2-metadata ran successfully @01.95900s +00.00000s
|`->config-runcmd ran successfully @01.95900s +00.00100s
Finished stage: (modules-config) 00.04500 seconds
Starting stage: modules-final
|`->config-package-update-upgrade-install ran successfully @02.19600s +00.00300s
|`->config-write-files-deferred ran successfully @02.19900s +00.00100s
|`->config-puppet ran successfully @02.20000s +00.00100s
|`->config-chef ran successfully @02.20100s +00.00000s
|`->config-mcollective ran successfully @02.20100s +00.00100s
|`->config-salt-minion ran successfully @02.20300s +00.00100s
|`->config-reset_rmc ran successfully @02.20400s +00.00100s
|`->config-refresh_rmc_and_interface ran successfully @02.20500s +00.00000s
|`->config-rightscale_userdata ran successfully @02.20500s +00.00100s
|`->config-scripts-vendor ran successfully @02.20600s +00.00100s
|`->config-scripts-per-once ran successfully @02.20700s +00.00100s
|`->config-scripts-per-boot ran successfully @02.20900s +00.00000s
|`->config-scripts-per-instance ran successfully @02.20900s +00.00100s
|`->config-scripts-user ran successfully @02.21000s +00.00100s
|`->config-ssh-authkey-fingerprints ran successfully @02.21100s +00.01100s
|`->config-keys-to-console ran successfully @02.22200s +00.01800s
|`->config-install-hotplug ran successfully @02.24100s +00.00100s
|`->config-phone-home ran successfully @02.24200s +00.00100s
|`->config-final-message ran successfully @02.24400s +00.00400s
|`->config-power-state-change ran successfully @02.24800s +00.00200s
Finished stage: (modules-final) 00.09200 seconds
Total Time: 1.76800 seconds
1 boot records analyzed
$ grep 'Running module' /var/log/cloud-init.log
2024-02-09 09:57:48,094 - modules.py[DEBUG]: Running module migrator (<module 'cloudinit.config.cc_migrator' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_migrator.py'>) with frequency always
2024-02-09 09:57:48,095 - modules.py[DEBUG]: Running module seed_random (<module 'cloudinit.config.cc_seed_random' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_seed_random.py'>) with frequency once-per-instance
2024-02-09 09:57:48,096 - modules.py[DEBUG]: Running module bootcmd (<module 'cloudinit.config.cc_bootcmd' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_bootcmd.py'>) with frequency always
2024-02-09 09:57:48,096 - modules.py[DEBUG]: Running module write-files (<module 'cloudinit.config.cc_write_files' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_write_files.py'>) with frequency once-per-instance
2024-02-09 09:57:48,097 - modules.py[DEBUG]: Running module write-metadata (<module 'cloudinit.config.cc_write_metadata' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_write_metadata.py'>) with frequency once-per-instance
2024-02-09 09:57:48,101 - modules.py[DEBUG]: Running module growpart (<module 'cloudinit.config.cc_growpart' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_growpart.py'>) with frequency always
2024-02-09 09:57:48,622 - modules.py[DEBUG]: Running module resizefs (<module 'cloudinit.config.cc_resizefs' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_resizefs.py'>) with frequency always
2024-02-09 09:57:48,624 - modules.py[DEBUG]: Running module disk_setup (<module 'cloudinit.config.cc_disk_setup' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_disk_setup.py'>) with frequency once-per-instance
2024-02-09 09:57:48,626 - modules.py[DEBUG]: Running module mounts (<module 'cloudinit.config.cc_mounts' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_mounts.py'>) with frequency once-per-instance
2024-02-09 09:57:48,628 - modules.py[DEBUG]: Running module set_hostname (<module 'cloudinit.config.cc_set_hostname' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_set_hostname.py'>) with frequency always
2024-02-09 09:57:48,628 - modules.py[DEBUG]: Running module update_hostname (<module 'cloudinit.config.cc_update_hostname' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_update_hostname.py'>) with frequency always
2024-02-09 09:57:48,631 - modules.py[DEBUG]: Running module update_etc_hosts (<module 'cloudinit.config.cc_update_etc_hosts' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_update_etc_hosts.py'>) with frequency always
2024-02-09 09:57:48,631 - modules.py[DEBUG]: Running module ca-certs (<module 'cloudinit.config.cc_ca_certs' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_ca_certs.py'>) with frequency once-per-instance
2024-02-09 09:57:48,633 - modules.py[DEBUG]: Running module rsyslog (<module 'cloudinit.config.cc_rsyslog' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_rsyslog.py'>) with frequency once-per-instance
2024-02-09 09:57:48,634 - modules.py[DEBUG]: Running module selinux (<module 'cloudinit.config.cc_selinux' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_selinux.py'>) with frequency once-per-instance
2024-02-09 09:57:48,652 - modules.py[DEBUG]: Running module users-groups (<module 'cloudinit.config.cc_users_groups' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_users_groups.py'>) with frequency once-per-instance
2024-02-09 09:57:49,053 - modules.py[DEBUG]: Running module ssh (<module 'cloudinit.config.cc_ssh' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_ssh.py'>) with frequency once-per-instance
2024-02-09 09:57:49,411 - modules.py[DEBUG]: Running module keyboard (<module 'cloudinit.config.cc_keyboard' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_keyboard.py'>) with frequency once-per-instance
2024-02-09 09:57:49,414 - modules.py[DEBUG]: Running module locale (<module 'cloudinit.config.cc_locale' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_locale.py'>) with frequency once-per-instance
2024-02-09 09:57:49,418 - modules.py[DEBUG]: Running module set-passwords (<module 'cloudinit.config.cc_set_passwords' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_set_passwords.py'>) with frequency once-per-instance
2024-02-09 09:57:49,431 - modules.py[DEBUG]: Running module yum-variables (<module 'cloudinit.config.cc_yum_variables' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_yum_variables.py'>) with frequency once-per-instance
2024-02-09 09:57:49,433 - modules.py[DEBUG]: Running module yum-add-repo (<module 'cloudinit.config.cc_yum_add_repo' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_yum_add_repo.py'>) with frequency once-per-instance
2024-02-09 09:57:49,434 - modules.py[DEBUG]: Running module ntp (<module 'cloudinit.config.cc_ntp' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_ntp.py'>) with frequency once-per-instance
2024-02-09 09:57:49,435 - modules.py[DEBUG]: Running module timezone (<module 'cloudinit.config.cc_timezone' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_timezone.py'>) with frequency once-per-instance
2024-02-09 09:57:49,437 - modules.py[DEBUG]: Running module disable-ec2-metadata (<module 'cloudinit.config.cc_disable_ec2_metadata' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_disable_ec2_metadata.py'>) with frequency always
2024-02-09 09:57:49,437 - modules.py[DEBUG]: Running module runcmd (<module 'cloudinit.config.cc_runcmd' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_runcmd.py'>) with frequency once-per-instance
2024-02-09 09:57:49,674 - modules.py[DEBUG]: Running module package-update-upgrade-install (<module 'cloudinit.config.cc_package_update_upgrade_install' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_package_update_upgrade_install.py'>) with frequency once-per-instance
2024-02-09 09:57:49,677 - modules.py[DEBUG]: Running module write-files-deferred (<module 'cloudinit.config.cc_write_files_deferred' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_write_files_deferred.py'>) with frequency once-per-instance
2024-02-09 09:57:49,678 - modules.py[DEBUG]: Running module puppet (<module 'cloudinit.config.cc_puppet' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_puppet.py'>) with frequency once-per-instance
2024-02-09 09:57:49,679 - modules.py[DEBUG]: Running module chef (<module 'cloudinit.config.cc_chef' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_chef.py'>) with frequency always
2024-02-09 09:57:49,679 - modules.py[DEBUG]: Running module mcollective (<module 'cloudinit.config.cc_mcollective' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_mcollective.py'>) with frequency once-per-instance
2024-02-09 09:57:49,680 - modules.py[DEBUG]: Running module salt-minion (<module 'cloudinit.config.cc_salt_minion' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_salt_minion.py'>) with frequency once-per-instance
2024-02-09 09:57:49,682 - modules.py[DEBUG]: Running module reset_rmc (<module 'cloudinit.config.cc_reset_rmc' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_reset_rmc.py'>) with frequency once-per-instance
2024-02-09 09:57:49,683 - modules.py[DEBUG]: Running module refresh_rmc_and_interface (<module 'cloudinit.config.cc_refresh_rmc_and_interface' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_refresh_rmc_and_interface.py'>) with frequency always
2024-02-09 09:57:49,683 - modules.py[DEBUG]: Running module rightscale_userdata (<module 'cloudinit.config.cc_rightscale_userdata' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_rightscale_userdata.py'>) with frequency once-per-instance
2024-02-09 09:57:49,684 - modules.py[DEBUG]: Running module scripts-vendor (<module 'cloudinit.config.cc_scripts_vendor' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_scripts_vendor.py'>) with frequency once-per-instance
2024-02-09 09:57:49,685 - modules.py[DEBUG]: Running module scripts-per-once (<module 'cloudinit.config.cc_scripts_per_once' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_scripts_per_once.py'>) with frequency once
2024-02-09 09:57:49,686 - modules.py[DEBUG]: Running module scripts-per-boot (<module 'cloudinit.config.cc_scripts_per_boot' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_scripts_per_boot.py'>) with frequency always
2024-02-09 09:57:49,687 - modules.py[DEBUG]: Running module scripts-per-instance (<module 'cloudinit.config.cc_scripts_per_instance' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_scripts_per_instance.py'>) with frequency once-per-instance
2024-02-09 09:57:49,688 - modules.py[DEBUG]: Running module scripts-user (<module 'cloudinit.config.cc_scripts_user' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_scripts_user.py'>) with frequency once-per-instance
2024-02-09 09:57:49,689 - modules.py[DEBUG]: Running module ssh-authkey-fingerprints (<module 'cloudinit.config.cc_ssh_authkey_fingerprints' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_ssh_authkey_fingerprints.py'>) with frequency once-per-instance
2024-02-09 09:57:49,700 - modules.py[DEBUG]: Running module keys-to-console (<module 'cloudinit.config.cc_keys_to_console' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_keys_to_console.py'>) with frequency once-per-instance
2024-02-09 09:57:49,719 - modules.py[DEBUG]: Running module install-hotplug (<module 'cloudinit.config.cc_install_hotplug' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_install_hotplug.py'>) with frequency once-per-instance
2024-02-09 09:57:49,720 - modules.py[DEBUG]: Running module phone-home (<module 'cloudinit.config.cc_phone_home' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_phone_home.py'>) with frequency once-per-instance
2024-02-09 09:57:49,721 - modules.py[DEBUG]: Running module final-message (<module 'cloudinit.config.cc_final_message' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_final_message.py'>) with frequency always
2024-02-09 09:57:49,726 - modules.py[DEBUG]: Running module power-state-change (<module 'cloudinit.config.cc_power_state_change' from '/usr/lib/python3.9/site-packages/cloudinit/config/cc_power_state_change.py'>) with frequency once-per-instance
Source Code Reading
setup.py
cloud-init
のエントリポイントは cloudinit.cmd.main:main
.
setuptools.setup(
# snipped
entry_points={
"console_scripts": [
"cloud-init = cloudinit.cmd.main:main",
# snipped
],
},
)
cloudinit/cmd/main.py
複数のサブコマンドが用意されており、各種 main 関数に分岐していく。
-
init
:main_init()
-
modules
:main_modules()
-
single
:main_single()
-
features
:main_features()
- etc...
def main(sysv_args=None):
# snipped
parser = argparse.ArgumentParser(prog=sysv_args.pop(0))
# snipped
subparsers = parser.add_subparsers(title="Subcommands", dest="subcommand")
# snipped
parser_init = subparsers.add_parser(
"init", help="Initialize cloud-init and perform initial modules."
)
# snipped
parser_init.set_defaults(action=("init", main_init))
# snipped
parser_mod = subparsers.add_parser(
"modules", help="Activate modules using a given configuration key."
)
# snipped
parser_mod.set_defaults(action=("modules", main_modules))
# snipped
parser_single = subparsers.add_parser(
"single", help="Run a single module."
)
# snipped
parser_single.set_defaults(action=("single", main_single))
# snipped
parser_query = subparsers.add_parser(
"query",
help="Query standardized instance metadata from the command line.",
)
parser_features = subparsers.add_parser(
"features", help="List defined features."
)
parser_features.set_defaults(action=("features", main_features))
parser_analyze = subparsers.add_parser(
"analyze", help="Devel tool: Analyze cloud-init logs and data."
)
parser_devel = subparsers.add_parser(
"devel", help="Run development tools."
)
parser_collect_logs = subparsers.add_parser(
"collect-logs", help="Collect and tar all cloud-init debug info."
)
parser_clean = subparsers.add_parser(
"clean", help="Remove logs and artifacts so cloud-init can re-run."
)
parser_status = subparsers.add_parser(
"status", help="Report cloud-init status or wait on completion."
)
parser_schema = subparsers.add_parser(
"schema", help="Validate cloud-config files using jsonschema."
)
# snipped
args = parser.parse_args(args=sysv_args)
# Subparsers.required = True and each subparser sets action=(name, functor)
(name, functor) = args.action
# snipped
with args.reporter:
retval = util.log_time(
logfunc=LOG.debug,
msg="cloud-init mode '%s'" % name,
get_uptime=True,
func=functor,
args=(name, args),
)
Source Code Reading (Cont.)
cloud-init.service
cloud-init init
のコードパスを辿る。
コード中に、どんな処理をしてるのか書いてくれてる (ありがたい...) 。
def main_init(name, args):
# snipped
# Cloud-init 'init' stage is broken up into the following sub-stages
# 1. Ensure that the init object fetches its config without errors
# 2. Setup logging/output redirections with resultant config (if any)
# 3. Initialize the cloud-init filesystem
# 4. Check if we can stop early by looking for various files
# 5. Fetch the datasource
# 6. Connect to the current instance location + update the cache
# 7. Consume the userdata (handlers get activated here)
# 8. Construct the modules object
# 9. Adjust any subsequent logging/output redirections using the modules
# objects config as it may be different from init object
# 10. Run the modules for the 'init' stage
# snipped
init = stages.Init(ds_deps=deps, reporter=args.reporter)
Init
クラスの実体が作成されている。
https://github.com/canonical/cloud-init/blob/main/cloudinit/stages.py
class Init:
# snipped
self._cfg: Dict = {}
Stage 1
設定ファイル (/etc/cloud/cloud.cfg
や /etc/cloud/cloud.cfg.d/*
など) を読み込む。
# Stage 1
init.read_cfg(extract_fns(args))
https://github.com/canonical/cloud-init/blob/main/cloudinit/stages.py
def read_cfg(self, extra_fns=None):
if not self._cfg:
self._cfg = self._read_cfg(extra_fns)
def _read_cfg(self, extra_fns):
# snipped
merger = helpers.ConfigMerger(
# snipped
base_cfg=fetch_base_config(instance_data_file=instance_data_file),
)
return merger.cfg
https://github.com/canonical/cloud-init/blob/main/cloudinit/stages.py
def fetch_base_config(*, instance_data_file=None) -> dict:
return util.mergemanydict(
[
# builtin config, hardcoded in settings.py.
util.get_builtin_cfg(),
# Anything in your conf.d or 'default' cloud.cfg location.
util.read_conf_with_confd(
CLOUD_CONFIG, instance_data_file=instance_data_file
),
# runtime config. I.e., /run/cloud-init/cloud.cfg
read_runtime_config(),
# Kernel/cmdline parameters override system config
util.read_conf_from_cmdline(),
],
reverse=True,
)
https://github.com/canonical/cloud-init/blob/main/cloudinit/settings.py
# This is expected to be a yaml formatted file
CLOUD_CONFIG = "/etc/cloud/cloud.cfg"
Stage 4
--local
が指定されない場合は、DSMODE_NETWORK
(ネットワークデータソースモード) になり、初回起動確認の "trust" モードが使用される。
# Stage 4
path_helper = init.paths
purge_cache_on_python_version_change(init)
mode = sources.DSMODE_LOCAL if args.local else sources.DSMODE_NETWORK
if mode == sources.DSMODE_NETWORK:
existing = "trust"
sys.stderr.write("%s\n" % (netinfo.debug_info()))
else:
# snipped
Stage 5
データソースを取得する。
# Stage 5
# snipped
try:
init.fetch(existing=existing)
# snipped
except sources.DataSourceNotFoundException:
# snipped
Stage 6
/var/lib/cloud/instance/
周りを更新してから、ネットワークの構成を適用して、ユーザーデータを保存する。
# Stage 6
iid = init.instancify()
# snipped
init.apply_network_config(bring_up=bring_up_interfaces)
# snipped
# update fully realizes user-data (pulling in #include if necessary)
init.update()
_maybe_set_hostname(init, stage="init-net", retry_stage="modules:config")
https://github.com/canonical/cloud-init/blob/main/cloudinit/stages.py
def update(self):
self._store_rawdata(self.datasource.get_userdata_raw(), "userdata")
self._store_processeddata(self.datasource.get_userdata(), "userdata")
self._store_raw_vendordata(
self.datasource.get_vendordata_raw(), "vendordata"
)
self._store_processeddata(
self.datasource.get_vendordata(), "vendordata"
)
self._store_raw_vendordata(
self.datasource.get_vendordata2_raw(), "vendordata2"
)
self._store_processeddata(
self.datasource.get_vendordata2(), "vendordata2"
)
Stage 7
# Stage 7
try:
# Attempt to consume the data per instance.
# This may run user-data handlers and/or perform
# url downloads and such as needed.
(ran, _results) = init.cloudify().run(
"consume_data",
init.consume_data,
args=[PER_INSTANCE],
freq=PER_INSTANCE,
)
if not ran:
# Just consume anything that is set to run per-always
# if nothing ran in the per-instance code
#
# See: https://bugs.launchpad.net/bugs/819507 for a little
# reason behind this...
init.consume_data(PER_ALWAYS)
.cloudify()
によって Cloud
クラスの実体に変換される。
https://github.com/canonical/cloud-init/blob/main/cloudinit/stages.py
def cloudify(self):
# Form the needed options to cloudify our members
return cloud.Cloud(
self.datasource,
self.paths,
self.cfg,
self.distro,
helpers.Runners(self.paths),
reporter=self.reporter,
)
https://github.com/canonical/cloud-init/blob/main/cloudinit/cloud.py
class Cloud:
def __init__(
self,
datasource: DataSource,
paths: Paths,
cfg: dict,
distro: Distro,
runners: Runners,
reporter: Optional[events.ReportEventStack] = None,
):
# snipped
def run(self, name, functor, args, freq=None, clear_on_fail=False):
return self._runners.run(name, functor, args, freq, clear_on_fail)
https://github.com/canonical/cloud-init/blob/main/cloudinit/helpers.py
class Runners:
def __init__(self, paths):
self.paths = paths
self.sems = {}
# snipped
def run(self, name, functor, args, freq=None, clear_on_fail=False):
sem = self._get_sem(freq)
if not sem:
sem = DummySemaphores()
if not args:
args = []
if sem.has_run(name, freq):
LOG.debug("%s already ran (freq=%s)", name, freq)
return (False, None)
with sem.lock(name, freq, clear_on_fail) as lk:
if not lk:
raise LockFailure("Failed to acquire lock for %s" % name)
else:
LOG.debug("Running %s using lock (%s)", name, lk)
if isinstance(args, (dict)):
results = functor(**args)
else:
results = functor(*args)
return (True, results)
https://github.com/canonical/cloud-init/blob/main/cloudinit/stages.py
def consume_data(self, frequency=PER_INSTANCE):
# Consume the userdata first, because we need want to let the part
# handlers run first (for merging stuff)
# snipped
Stage 8
Modules
クラスの実体を作成する。
# Stage 8 - re-read and apply relevant cloud-config to include user-data
mods = Modules(init, extract_fns(args), reporter=args.reporter)
https://github.com/canonical/cloud-init/blob/main/cloudinit/config/modules.py
class Modules:
def __init__(self, init: Init, cfg_files=None, reporter=None):
# snipped
Stage 10
# Stage 10
return (init.datasource, run_module_section(mods, name, name))
def run_module_section(mods: Modules, action_name, section):
full_section_name = MOD_SECTION_TPL % (section)
(which_ran, failures) = mods.run_section(full_section_name)
# snipped
https://github.com/canonical/cloud-init/blob/main/cloudinit/config/modules.py
def run_section(self, section_name):
"""Runs all modules in the given section.
section_name - One of the modules lists as defined in
/etc/cloud/cloud.cfg. One of:
- cloud_init_modules
- cloud_config_modules
- cloud_final_modules
"""
# snipped