Diferencia entre revisiones de «Cloud-init»

De MediaWiki
Ir a la navegación Ir a la búsqueda
 
(No se muestran 10 ediciones intermedias del mismo usuario)
Línea 275: Línea 275:
 
   - systemctl restart apache2
 
   - systemctl restart apache2
  
−
== Zona horaria ==
+
=== Configuración da zona horaria ===
 +
 
 
Para rematar indicamos zona horaria e locale:
 
Para rematar indicamos zona horaria e locale:
  
Línea 332: Línea 333:
 
locale: es_ES.UTF-8
 
locale: es_ES.UTF-8
  
−
== Verificando a sintaxe ==
+
=== Verificando a sintaxe ===
  
−
Unha vez creado o arquivo imos a http://www.yamllint.com/ ou https://codebeautify.org/yaml-validator para validar a sintaxe; xa que non é a primeira vez que por culpa dunha mala sintaxe, non funciona a inicialización do contedor. Copiamos&pegamos o contido do noso config.yml e prememos en Go.
+
Unha vez creado o arquivo imos a http://www.yamllint.com/ ou https://codebeautify.org/yaml-validator para validar a sintaxe; xa que non é a primeira vez que por culpa dunha mala sintaxe, non funciona a inicialización do contedor.
 +
 
 +
Copiamos&pegamos o contido do noso config.yml e prememos en Go.
  
 
Validación do YAML
 
Validación do YAML
Línea 342: Línea 345:
 
== Lanzando o contedor ==
 
== Lanzando o contedor ==
 
Unha vez verificada a sintaxe podemos proseguir e preparnos para lanzar o contedor. É moi importante ter en conta que as imaxes cloud Ubuntu que empregamos veñen con cloud-init configurado para esperar que o contedor reciba unha configuración rede inicial por dhcp. No caso de non ter un servidor dhcp temos que indicalo cun parámetro de configuración:
 
Unha vez verificada a sintaxe podemos proseguir e preparnos para lanzar o contedor. É moi importante ter en conta que as imaxes cloud Ubuntu que empregamos veñen con cloud-init configurado para esperar que o contedor reciba unha configuración rede inicial por dhcp. No caso de non ter un servidor dhcp temos que indicalo cun parámetro de configuración:
−
 
+
* Se hai servidor dhcp (o normal cando creamos redes lxd e é o noso caso) podemos lanzar o contedor executando:
−
Si hai servidor dhcp (o normal cando creamos redes lxd e é o noso caso) podemos lanzar o contedor executando:
+
$ incus launch images:ubuntu/22.04/cloud asir06 -c user.user-data="$(cat config.yml)" -p WAN
−
asir@incus:~$ incus launch images:ubuntu/22.04/cloud asir06 -c user.user-data="$(cat config.yml)" -p WAN
+
* Si non hai servidor dhcp: hai que facer dúas cousas:
−
Si non hai servidor dhcp: hai que facer dúas cousas:
+
A) Engadir un bloque bootcmd no config.yml para configurar a rede do equipo nada máis arrincar o contedor.
−
Engadir un bloque bootcmd no config.yml para configurar a rede do equipo nada máis arrincar o contedor.
+
<pre>
 
# executar comandos ó iniciar o contedor
 
# executar comandos ó iniciar o contedor
 
bootcmd:
 
bootcmd:
Línea 353: Línea 356:
 
  - [sh, -c, "echo 'nameserver 8.8.8.8' > /etc/resolv.conf"]
 
  - [sh, -c, "echo 'nameserver 8.8.8.8' > /etc/resolv.conf"]
 
  - [sh, -c, "echo 'nameserver 8.8.4.4' >> /etc/resolv.conf"]  
 
  - [sh, -c, "echo 'nameserver 8.8.4.4' >> /etc/resolv.conf"]  
−
Indicar a cloud-init coa propiedade user.network_mode=link-local que a configuración rede farase a man e non por dhcp.
+
</pre>
−
magasix@lxd:~$ incus launch images:ubuntu/22.04/cloud asir06 -c user.user-data="$(cat config.yml)" -c user.network_mode=link-local -p WAN
+
 
 +
B) Indicar a cloud-init coa propiedade user.network_mode=link-local que a configuración rede farase a man e non por dhcp.
 +
$ incus launch images:ubuntu/22.04/cloud asir06 -c user.user-data="$(cat config.yml)" -c user.network_mode=link-local -p WAN
 +
 
 
Hai diferenzas entre bootcmd e runcmd:
 
Hai diferenzas entre bootcmd e runcmd:
 +
* bootcmd execútase moi pronto no inicio do contedor e sempre se executa en cada inicio.
 +
* runmcd execútase máis tarde e únicamente no primeiro inicio do contedor.
  
−
bootcmd execútase moi pronto no inicio do contedor e sempre se executa en cada inicio.
 
−
runmcd execútase máis tarde e únicamente no primeiro inicio do contedor.
 
 
Podemos facer comprobacións de que todo foi ben unha vez rematado o aprovisionamento:
 
Podemos facer comprobacións de que todo foi ben unha vez rematado o aprovisionamento:
−
 
+
$  incus exec asir06 -- cloud-init status
−
asir@incus:~$  incus exec asir06 -- cloud-init status
+
status: done
−
status: done
+
$ incus exec asir06 bash
−
asir@incus:~$ incus exec asir06 bash
+
# cat /etc/hostname  
−
root@asir06:~# cat /etc/hostname  
+
asir06
−
asir06
+
# cat /etc/hosts
−
root@asir06:~# cat /etc/hosts
+
<pre>
 
# Your system has configured 'manage_etc_hosts' as True.
 
# Your system has configured 'manage_etc_hosts' as True.
 
# As a result, if you wish for changes to this file to persist
 
# As a result, if you wish for changes to this file to persist
Línea 381: Línea 387:
 
ff02::1 ip6-allnodes
 
ff02::1 ip6-allnodes
 
ff02::2 ip6-allrouters
 
ff02::2 ip6-allrouters
−
root@asir06:~# cat /etc/apt/apt.conf.d/01apt-cacher-ng
+
</pre>
−
Acquire::http { Proxy "http://192.0.2.20:3142"; }
+
 
−
root@asir06:~# ss -ltn
+
# cat /etc/apt/apt.conf.d/01apt-cacher-ng
 +
Acquire::http { Proxy "http://192.0.2.20:3142"; }
 +
 
 +
# ss -ltn
 +
<pre>
 
State          Recv-Q          Send-Q          Local Address:Port          Peer Address:Port          Process                                 
 
State          Recv-Q          Send-Q          Local Address:Port          Peer Address:Port          Process                                 
 
LISTEN        0                4096            127.0.0.53%lo:53                0.0.0.0:*                                                                                       
 
LISTEN        0                4096            127.0.0.53%lo:53                0.0.0.0:*                                                                                       
Línea 390: Línea 400:
 
LISTEN        0                511                        *:80                      *:*                                                                                       
 
LISTEN        0                511                        *:80                      *:*                                                                                       
 
LISTEN        0                128                      [::]:22                    [::]:*
 
LISTEN        0                128                      [::]:22                    [::]:*
−
root@asir06:~# dpkg -l | grep -i php
+
</pre>
 +
 
 +
# dpkg -l | grep -i php
 +
<pre>
 
ii  libapache2-mod-php              2:8.3+94+ubuntu22.04.1+deb.sury.org+2      all          server-side, HTML-embedded scripting language (Apache 2 module) (default)
 
ii  libapache2-mod-php              2:8.3+94+ubuntu22.04.1+deb.sury.org+2      all          server-side, HTML-embedded scripting language (Apache 2 module) (default)
 
ii  libapache2-mod-php8.3          8.3.7-2+ubuntu22.04.1+deb.sury.org+1      amd64        server-side, HTML-embedded scripting language (Apache 2 module)
 
ii  libapache2-mod-php8.3          8.3.7-2+ubuntu22.04.1+deb.sury.org+1      amd64        server-side, HTML-embedded scripting language (Apache 2 module)
Línea 397: Línea 410:
 
ii  php-common                      2:94+ubuntu22.04.1+deb.sury.org+2          all          Common files for PHP packages
 
ii  php-common                      2:94+ubuntu22.04.1+deb.sury.org+2          all          Common files for PHP packages
 
...
 
...
−
root@asir06:~#
+
</pre>
−
 
 
 
Tamén podemos verificar que é posible conectarse por ssh usando a identidade dixital autorizada accedendo pola IP asignada por DHCP ó contedor asir06, no meu caso a 135:
 
Tamén podemos verificar que é posible conectarse por ssh usando a identidade dixital autorizada accedendo pola IP asignada por DHCP ó contedor asir06, no meu caso a 135:
 
  $ incus ls
 
  $ incus ls
Línea 449: Línea 461:
 
</pre>
 
</pre>
  
−
== Cloud-init e power_state ==
+
=== Cloud-init e power_state ===
−
Pode ser interesante reiniciar o contedor ó remate do proceso para ver o comportamento do contedor fronte ós reinicios. É posible reiniciar o contedor a través de scripts ou runcmd pero facelo con power_state asegura que todas as accións de cloud-init remataron antes de reiniciar. Para configurar o reinicio automático engadiriamos as seguintes liñas no config.yml:
+
Pode ser interesante reiniciar o contedor ó remate do proceso para ver o comportamento do contedor fronte ós reinicios.  
  
 +
É posible reiniciar o contedor a través de scripts ou runcmd pero facelo con power_state asegura que todas as accións de cloud-init remataron antes de reiniciar. Para configurar o reinicio automático engadiriamos as seguintes liñas no config.yml:
 +
 +
<pre>
 
# reinicio ó rematar
 
# reinicio ó rematar
 
power_state:
 
power_state:
 
   mode: reboot
 
   mode: reboot
 +
</pre>
 +
 
Desta forma poderiamos esquecernos dalgúns comandos do bloque runcmd xa que co reinicio do contedor os cambios indicados xa se aplicarían:
 
Desta forma poderiamos esquecernos dalgúns comandos do bloque runcmd xa que co reinicio do contedor os cambios indicados xa se aplicarían:
  
 +
<pre>
 
# Executar comandos no primeiro inicio
 
# Executar comandos no primeiro inicio
 
runcmd:
 
runcmd:
Línea 467: Línea 485:
 
#  - systemctl restart sshd
 
#  - systemctl restart sshd
 
#  - systemctl restart apache2
 
#  - systemctl restart apache2
 +
</pre>
 +
 
Ademais do reinicio pódese configurar o apagado e un tempo de retardo.
 
Ademais do reinicio pódese configurar o apagado e un tempo de retardo.
  
Línea 623: Línea 643:
 
* como é posible lanzar un contedor e personalizar a súa configuración de xeito automático no primeiro inicio.  
 
* como é posible lanzar un contedor e personalizar a súa configuración de xeito automático no primeiro inicio.  
 
* no último exemplo, con cloud-init, user.user-data, user.network-config e grazas a apt-cacher-ng, en aproximadamente un minuto un servidor Apache con php correndo.
 
* no último exemplo, con cloud-init, user.user-data, user.network-config e grazas a apt-cacher-ng, en aproximadamente un minuto un servidor Apache con php correndo.
 +
 +
== Cloud-init: orde de execución e logs ==
 +
 +
A orde de prioridade á hora de executar as accións indicados no arquivo config.yml nun contedor LXD pode verse no arquivo
 +
# less /etc/cloud/cloud.cfg
 +
<pre>
 +
...
 +
# The modules that run in the 'init' stage
 +
cloud_init_modules:
 +
  - seed_random
 +
  - bootcmd
 +
  - write_files
 +
  - growpart
 +
  - resizefs
 +
  - disk_setup
 +
  - mounts
 +
  - set_hostname
 +
  - update_hostname
 +
  - update_etc_hosts
 +
  - ca_certs
 +
  - rsyslog
 +
  - users_groups
 +
  - ssh
 +
 +
# The modules that run in the 'config' stage
 +
cloud_config_modules:
 +
  - wireguard
 +
  - snap
 +
  - ubuntu_autoinstall
 +
  - ssh_import_id
 +
  - keyboard
 +
  - locale
 +
  - set_passwords
 +
  - grub_dpkg
 +
  - apt_pipelining
 +
  - apt_configure
 +
  - ubuntu_pro
 +
  - ntp
 +
  - timezone
 +
  - disable_ec2_metadata
 +
  - runcmd
 +
  - byobu
 +
 +
# The modules that run in the 'final' stage
 +
cloud_final_modules:
 +
  - package_update_upgrade_install
 +
  - fan
 +
  - landscape
 +
  - lxd
 +
  - ubuntu_drivers
 +
  - write_files_deferred
 +
  - puppet
 +
  - chef
 +
  - ansible
 +
  - mcollective
 +
  - salt_minion
 +
  - reset_rmc
 +
  - 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
 +
...
 +
</pre>
 +
 +
Aínda que ás veces non é de moita axuda, existe un arquivo de log en /var/log/cloud-init-output.log coas accións feitas por cloud-init ó arrincar o contedor:
 +
# less /var/log/cloud-init-output.log
 +
<pre>
 +
Cloud-init v. 24.1.3-0ubuntu1~22.04.1 running 'init-local' at Fri, 31 May 2024 08:38:28 +0000. Up 1.25 seconds.
 +
2024-05-31 08:38:29,018 - schema.py[WARNING]: Invalid network-config provided: Please run 'sudo cloud-init schema --system' to see the schema errors.
 +
Cloud-init v. 24.1.3-0ubuntu1~22.04.1 running 'init' at Fri, 31 May 2024 08:38:41 +0000. Up 14.17 seconds.
 +
ci-info: ++++++++++++++++++++++++++++++++++++++Net device info+++++++++++++++++++++++++++++++++++++++
 +
ci-info: +--------+------+-----------------------------+---------------+--------+-------------------+
 +
ci-info: | Device |  Up  |          Address          |      Mask    | Scope  |    Hw-Address    |
 +
ci-info: +--------+------+-----------------------------+---------------+--------+-------------------+
 +
ci-info: |  eth0  | True |          192.0.2.26        | 255.255.255.0 | global | 00:16:3e:4e:a4:c5 |
 +
ci-info: |  eth0  | True | fe80::216:3eff:fe4e:a4c5/64 |      .      |  link  | 00:16:3e:4e:a4:c5 |
 +
ci-info: |  lo  | True |          127.0.0.1          |  255.0.0.0  |  host  |        .        |
 +
ci-info: |  lo  | True |          ::1/128          |      .      |  host  |        .        |
 +
ci-info: +--------+------+-----------------------------+---------------+--------+-------------------+
 +
ci-info: ++++++++++++++++++++++++++++Route IPv4 info++++++++++++++++++++++++++++
 +
ci-info: +-------+-------------+-----------+---------------+-----------+-------+
 +
ci-info: | Route | Destination |  Gateway  |    Genmask    | Interface | Flags |
 +
ci-info: +-------+-------------+-----------+---------------+-----------+-------+
 +
ci-info: |  0  |  0.0.0.0  | 192.0.2.1 |    0.0.0.0    |    eth0  |  UG  |
 +
ci-info: |  1  |  192.0.2.0  |  0.0.0.0  | 255.255.255.0 |    eth0  |  U  |
 +
ci-info: +-------+-------------+-----------+---------------+-----------+-------+
 +
ci-info: +++++++++++++++++++Route IPv6 info+++++++++++++++++++
 +
ci-info: +-------+-------------+---------+-----------+-------+
 +
ci-info: | Route | Destination | Gateway | Interface | Flags |
 +
ci-info: +-------+-------------+---------+-----------+-------+
 +
ci-info: |  0  |  fe80::/64  |    ::  |    eth0  |  U  |
 +
ci-info: |  2  |    local    |    ::  |    eth0  |  U  |
 +
ci-info: |  3  |  multicast  |    ::  |    eth0  |  U  |
 +
ci-info: +-------+-------------+---------+-----------+-------+
 +
...
 +
Cloud-init v. 24.1.3-0ubuntu1~22.04.1 running 'modules:config' at Fri, 31 May 2024 08:38:47 +0000. Up 19.41 seconds.
 +
Generating locales (this might take a while)...
 +
  es_ES.UTF-8... done
 +
Generation complete.
 +
Hit:1 http://archive.ubuntu.com/ubuntu jammy InRelease
 +
Get:2 http://security.ubuntu.com/ubuntu jammy-security InRelease [129 kB]
 +
Get:3 https://ppa.launchpadcontent.net/ondrej/php/ubuntu jammy InRelease [24.6 kB]
 +
Get:4 http://security.ubuntu.com/ubuntu jammy-security/main amd64 Packages [1475 kB]
 +
Get:5 http://security.ubuntu.com/ubuntu jammy-security/main Translation-en [254 kB]
 +
Get:6 http://security.ubuntu.com/ubuntu jammy-security/restricted amd64 Packages [1876 kB]
 +
Get:7 http://security.ubuntu.com/ubuntu jammy-security/restricted Translation-en [318 kB]
 +
Get:8 http://security.ubuntu.com/ubuntu jammy-security/universe amd64 Packages [854 kB]
 +
Get:9 http://security.ubuntu.com/ubuntu jammy-security/universe Translation-en [165 kB]
 +
Get:10 http://security.ubuntu.com/ubuntu jammy-security/universe amd64 c-n-f Metadata [16.8 kB]
 +
Get:11 http://security.ubuntu.com/ubuntu jammy-security/multiverse amd64 Packages [37.2 kB]
 +
Get:12 http://security.ubuntu.com/ubuntu jammy-security/multiverse Translation-en [7588 B]
 +
Get:13 http://security.ubuntu.com/ubuntu jammy-security/multiverse amd64 c-n-f Metadata [260 B]
 +
...
 +
Cloud-init v. 24.1.3-0ubuntu1~22.04.1 running 'modules:final' at Fri, 31 May 2024 08:39:03 +0000. Up 35.97 seconds.
 +
Reading package lists...
 +
Building dependency tree...
 +
Reading state information...
 +
bash-completion is already the newest version (1:2.11-5ubuntu1).
 +
bash-completion set to manually installed.
 +
The following additional packages will be installed:
 +
  apache2-bin apache2-data apache2-utils bzip2 fontconfig-config
 +
  fonts-dejavu-core libabsl20210324 libaom3 libapache2-mod-php8.3 libapr1
 +
  libaprutil1 libaprutil1-dbd-sqlite3 libaprutil1-ldap libavif13 libdav1d5
 +
  libde265-0 libdeflate0 libfontconfig1 libfreetype6 libgav1-0 libgd3 libheif1
 +
  libjbig0 libjpeg-turbo8 libjpeg8 liblua5.3-0 libonig5 libtiff5 libwebp7
 +
  libx265-199 libxmlrpc-epi0 libxpm4 libyuv0 libzip4 mailcap mime-support
 +
  mysql-client-8.0 mysql-client-core-8.0 mysql-common php8.3 php8.3-cli
 +
  php8.3-common php8.3-curl php8.3-gd php8.3-intl php8.3-mbstring php8.3-mysql
 +
  php8.3-opcache php8.3-readline php8.3-soap php8.3-xml php8.3-xmlrpc
 +
  php8.3-zip ssl-cert
 +
Suggested packages:
 +
  apache2-doc apache2-suexec-pristine | apache2-suexec-custom www-browser
 +
  bzip2-doc php-pear libgd-tools
 +
The following NEW packages will be installed:
 +
  apache2 apache2-bin apache2-data apache2-utils bzip2 fontconfig-config
 +
  fonts-dejavu-core libabsl20210324 libaom3 libapache2-mod-php
 +
  libapache2-mod-php8.3 libapr1 libaprutil1 libaprutil1-dbd-sqlite3
 +
  libaprutil1-ldap libavif13 libdav1d5 libde265-0 libdeflate0 libfontconfig1
 +
  libfreetype6 libgav1-0 libgd3 libheif1 libjbig0 libjpeg-turbo8 libjpeg8
 +
  liblua5.3-0 libonig5 libtiff5 libwebp7 libx265-199 libxmlrpc-epi0 libxpm4
 +
  libyuv0 libzip4 mailcap mime-support mysql-client mysql-client-8.0
 +
  mysql-client-core-8.0 mysql-common net-tools php php-cli php-common php-curl
 +
  php-gd php-intl php-mbstring php-mysql php-soap php-xml php-xmlrpc php-zip
 +
  php8.3 php8.3-cli php8.3-common php8.3-curl php8.3-gd php8.3-intl
 +
  php8.3-mbstring php8.3-mysql php8.3-opcache php8.3-readline php8.3-soap
 +
  php8.3-xml php8.3-xmlrpc php8.3-zip ssl-cert
 +
0 upgraded, 70 newly installed, 0 to remove and 25 not upgraded.
 +
...
 +
Creating config file /etc/php/8.3/mods-available/calendar.ini with new version
 +
 +
Creating config file /etc/php/8.3/mods-available/ctype.ini with new version
 +
 +
Creating config file /etc/php/8.3/mods-available/exif.ini with new version
 +
 +
Creating config file /etc/php/8.3/mods-available/fileinfo.ini with new version
 +
 +
Creating config file /etc/php/8.3/mods-available/ffi.ini with new version
 +
 +
Creating config file /etc/php/8.3/mods-available/ftp.ini with new version
 +
 +
Creating config file /etc/php/8.3/mods-available/gettext.ini with new version
 +
 +
Creating config file /etc/php/8.3/mods-available/iconv.ini with new version
 +
 +
Creating config file /etc/php/8.3/mods-available/pdo.ini with new version
 +
...
 +
Creating config file /etc/php/8.3/mods-available/gd.ini with new version
 +
Setting up php (2:8.3+94+ubuntu22.04.1+deb.sury.org+2) ...
 +
Setting up php-gd (2:8.3+94+ubuntu22.04.1+deb.sury.org+2) ...
 +
Processing triggers for ufw (0.36.1-4ubuntu0.1) ...
 +
Processing triggers for man-db (2.10.2-1) ...
 +
Processing triggers for libc-bin (2.35-0ubuntu3.7) ...
 +
Processing triggers for php8.3-cli (8.3.7-2+ubuntu22.04.1+deb.sury.org+1) ...
 +
Processing triggers for libapache2-mod-php8.3 (8.3.7-2+ubuntu22.04.1+deb.sury.org+1) ...
 +
NEEDRESTART-VER: 3.5
 +
Considering dependency setenvif for ssl:
 +
Module setenvif already enabled
 +
Considering dependency mime for ssl:
 +
Module mime already enabled
 +
Considering dependency socache_shmcb for ssl:
 +
Enabling module socache_shmcb.
 +
Enabling module ssl.
 +
See /usr/share/doc/apache2/README.Debian.gz on how to configure SSL and create self-signed certificates.
 +
To activate the new configuration, you need to run:
 +
  systemctl restart apache2
 +
Enabling site default-ssl.
 +
To activate the new configuration, you need to run:
 +
  systemctl reload apache2
 +
Cloud-init v. 24.1.3-0ubuntu1~22.04.1 finished at Fri, 31 May 2024 08:39:35 +0000. Datasource DataSourceLXD.  Up 67.52 seconds
 +
</pre>
 +
 +
Tamén no log /var/log/cloud-init.log podemos atopar informacións sobre as actuacións feitas por cloud-init:
 +
 +
# less /var/log/cloud-init.log
 +
<pre>
 +
...
 +
2024-05-31 08:38:42,058 - distros[DEBUG]: Adding user magasix
 +
2024-05-31 08:38:42,059 - subp.py[DEBUG]: Running hidden command to protect sensitive input/output logstring: ['useradd', 'magasix', '--groups', 'sudo', '--password', 'REDACTED',
 +
'--shell', '/bin/bash', '-m']
 +
2024-05-31 08:38:42,143 - util.py[DEBUG]: Reading from /etc/sudoers (quiet=False)
 +
2024-05-31 08:38:42,144 - util.py[DEBUG]: Read 1671 bytes from /etc/sudoers
 +
2024-05-31 08:38:42,145 - util.py[DEBUG]: Writing to /etc/sudoers.d/90-cloud-init-users - wb: [440] 143 bytes
 +
2024-05-31 08:38:42,146 - util.py[DEBUG]: Reading from /etc/ssh/sshd_config (quiet=False)
 +
2024-05-31 08:38:42,147 - util.py[DEBUG]: Read 3254 bytes from /etc/ssh/sshd_config
 +
2024-05-31 08:38:42,148 - util.py[DEBUG]: Changing the ownership of /home/magasix/.ssh to 1000:1000
 +
2024-05-31 08:38:42,148 - util.py[DEBUG]: Writing to /home/magasix/.ssh/authorized_keys - wb: [600] 0 bytes
 +
2024-05-31 08:38:42,149 - util.py[DEBUG]: Changing the ownership of /home/magasix/.ssh/authorized_keys to 1000:1000
 +
2024-05-31 08:38:42,149 - util.py[DEBUG]: Reading from /home/magasix/.ssh/authorized_keys (quiet=False)
 +
2024-05-31 08:38:42,149 - util.py[DEBUG]: Read 0 bytes from /home/magasix/.ssh/authorized_keys
 +
2024-05-31 08:38:42,149 - util.py[DEBUG]: Writing to /home/magasix/.ssh/authorized_keys - wb: [600] 759 bytes
 +
2024-05-31 08:38:42,150 - handlers.py[DEBUG]: finish: init-network/config-users_groups: SUCCESS: config-users_groups ran successfully
 +
...
 +
</pre>
 +
 +
Cloud-init proporciona un resumo da execución:
 +
 +
# cloud-init status
 +
status: done
 +
 +
# cloud-init status --long
 +
<pre>
 +
status: done
 +
extended_status: degraded done
 +
boot_status_code: enabled-by-generator
 +
last_update: Thu, 01 Jan 1970 00:01:11 +0000
 +
detail: DataSourceNoCloud [seed=/var/lib/cloud/seed/nocloud-net]
 +
errors: []
 +
recoverable_errors:
 +
DEPRECATED:
 +
    - Deprecated cloud-config provided: users.0.ssh-authorized-keys:  Deprecated in version 18.3. Use **ssh_authorized_keys** instead.
 +
</pre>
  
 
= Escenario 2: cloud-config para despregue masivo de contedores cun script de xestión =
 
= Escenario 2: cloud-config para despregue masivo de contedores cun script de xestión =
 +
 +
O obxectivo deste é ver como xuntando ó visto ata o de agora podemos crear un script de xestión dun escenario con varios contedores (crear, arrincar, parar e borrar).
 +
 +
O noso obxectivo será montar un sistema con tres servidores coas seguintes características:
 +
* Nos servidores hai un usuario administrador.
 +
* Está habilitado o acceso por ssh mediante contrasinal.
 +
* Os servidores están configurados correctamente para poder saír a Internet.
 +
* Os servidores están configurados para usar o servidor apt-cacher-ng.
 +
* Os servidores corren Apache+php.
 +
 +
== Preparación dos equipos do escenario ==
 +
 +
Tómase como punto de partida o estado do equipo apt-cacher-ng ó remate do escenario anterior. Non hai que crear ningún contedor xa que o obxectivo do escenario é a súa creación e configuración.
 +
 +
'''NOTA'''. Esta práctica hai que facela usando contedores xa que non funciona nas imaxes Ubuntu usadas en Virtualbox.
 +
 +
== Script xestión escenario ==
 +
 +
NOTAS: o script básico e as plantillas poden descargarse:
 +
* [https://PENDIENTE script básico PENDIENTE]
 +
* config_PLANTILLA.yml
 +
* network_PLANTILLA.yml
 +
 +
Abordaremos o problema centrándonos en primeiro lugar na creación e configuración automática dos contedores server01, server02 e server03 xa que constitúe a parte fundamental do problema; para despois, ampliar as funcionalidades do script.
 +
 +
Cun editor de texto creamos o noso script e comezamos definindo unhas variables que permitirán adaptar o script rápidamente a outras redes:
 +
<pre>
 +
#!/bin/bash
 +
REDE=192.0.2.3
 +
MS=255.255.255.0
 +
GW=192.0.2.1
 +
<(pre>
 +
 +
A continuación temos que crear un contedor para server01, asignarlle os arquivos config.yml e network.yml personalizados e arrincalo. Cun bucle for repetimos estas accións tantas veces como servidores desexemos. Pero, cómo podemos facer para ter un config.yml personalizado para cada server?.
 +
 +
A forma de poder asignar un config.yml personalizado é crear unha plantilla sobre a que sacar unha copia para personalizada.
 +
 +
A modo de exemplo a miña plantilla chámase config_PLANTILLA.yml e o seu contido é:
 +
 +
<pre>
 +
#cloud-config
 +
# Configurar /etc/hostname e /etc/hosts
 +
hostname: NOMBRE
 +
fqdn: NOMBRE.platega.example
 +
manage_etc_hosts: true
 +
# Usuario
 +
users:
 +
  - default
 +
  - name: magasix
 +
    lock_passwd: false
 +
    passwd: $y$j9T$ww80Jq/hcuhChau8w3Poe0$AuTOsqM0BL5Q3ltgrBaSGqLANZofUcOJuAMw3rdXNn6
 +
#    ssh-authorized-keys:
 +
#      - clave pública asociada a la clave privada para acceder por SSH
 +
    sudo: ['ALL=(ALL) NOPASSWD:ALL']
 +
    groups: sudo
 +
    shell: /bin/bash
 +
system_info:
 +
  default_user:
 +
    name: ubuntu
 +
    gecos: Usuario por defecto
 +
    plain_text_passwd: abc123.
 +
    lock_passwd: false
 +
# Habilitar PasswordAuthentication
 +
#ssh_pwauth: True
 +
# Configurar caché de paquetes para acelerar instalación
 +
write_files:
 +
  - path: /etc/apt/apt.conf.d/01apt-cacher-ng
 +
    content: |
 +
      Acquire::http { Proxy "http://192.0.2.20:3142"; }
 +
# Conservar repositorios e instalar paquetes
 +
apt:
 +
  preserve_sources_list: true
 +
# Actualizar sistema
 +
package_upgrade: true
 +
packages:
 +
  - net-tools
 +
  - apache2
 +
  - php
 +
  - php-cli
 +
  - php-common
 +
  - libapache2-mod-php
 +
  - php-gd
 +
  - php-curl
 +
  - php-mbstring
 +
  - php-xmlrpc
 +
  - php-soap
 +
  - php-xml
 +
  - php-intl
 +
  - php-mysql
 +
  - php-zip
 +
  - mysql-client
 +
  - bash-completion
 +
  - openssh-server
 +
  - sudo
 +
  - bash
 +
# Ejecutar comandos en el primer arranque
 +
runcmd:
 +
  - sed -i "s%#PermitRootLogin prohibit-password%PermitRootLogin no%g" /etc/ssh/sshd_config
 +
- sed -i "s%#PasswordAuthentication yes%PasswordAuthentication yes%g" /etc/ssh/sshd_config
 +
  - sed -i "3iUseDNS no" /etc/ssh/sshd_config
 +
  - a2enmod ssl
 +
  - a2ensite default-ssl.conf
 +
  - echo '<?php phpinfo(); ?>' > /var/www/html/info.php
 +
  - echo '<?php echo "<html><head><title>Sitio web en ${_SERVER["SERVER_ADDR"]}</title></head><body><h1>Mi Sitio Web</h1>Est&aacute;s en ${_SERVER["SERVER_ADDR"]}</body></html>";?>'  > /var/www/html/index.php
 +
  - rm /var/www/html/index.html
 +
  - systemctl restart sshd
 +
  - systemctl restart apache2
 +
# Zona horaria y locale
 +
timezone: Europe/Madrid
 +
locale: es_ES.UTF-8
 +
# reinicio al acabar
 +
#power_state:
 +
#  mode: reboot
 +
</pre>
 +
 +
Coa configuración de rede faise o mesmo: unha plantilla de nome network_PLANTILLA.yml:
 +
 +
<pre>
 +
#cloud-config
 +
version: 1
 +
config:
 +
  - type: physical
 +
    name: eth0
 +
    subnets:
 +
      - type: static
 +
        ipv4: true
 +
        address: XXXX
 +
        netmask: YYYY
 +
        gateway: ZZZZ
 +
        control: auto
 +
  - type: nameserver
 +
    address:
 +
      - 8.8.8.8
 +
      - 8.8.4.4
 +
</pre>
 +
 +
Fixarse en que o que está en amarelo usarémolo para facer sustitucións e o que está en negriña correspóndese á configuración desexada (usuario, apt-cacher-ng, acceso ssh por contrasinal).
 +
 +
Voltamos ó noso script e engadimos:
 +
 +
<pre>
 +
#!/bin/bash
 +
REDE=192.0.2.3
 +
MS=255.255.255.0
 +
GW=192.0.2.1
 +
for j in {1..3}
 +
do
 +
    # creamos contedor sen arricar
 +
    incus init images:ubuntu/22.04/cloud server0$j --profile WAN
 +
    # personalizar a configuración do contedor
 +
    cp config_PLANTILLA.yml config.yml
 +
    cp network_PLANTILLA.yml network.yml
 +
    sed -i "s/NOMBRE/server0$j/g" config.yml
 +
    sed -i "s/XXXX/$REDE$j/g" network.yml
 +
    sed -i "s/YYYY/$MS/g" network.yml
 +
    sed -i "s/ZZZZ/$GW/g" network.yml
 +
    incus config set server0$j user.user-data -< config.yml
 +
    incus config set server0$j user.network-config -< network.yml
 +
    incus start server0$j
 +
    rm config.yml network.yml
 +
done
 +
</pre>
 +
 +
Fixarse que na primeira execución do bucle:
 +
* Usamos un Ubuntu Jammy Jellyfish (22.04) para crear un contedor de nome server01 e profile WAN sen arrincalo (incus init). Indicar o alias ou imaxe que queirades usar.
 +
* Creamos un arquivo config.yml a partir da plantilla e procedemos a facer sustitucións:
 +
:* hostname: NOMBRE --> hostname: server01
 +
:* fqdn: NOMBRE.platega.example --> fqdn: server01.platega.example
 +
* Creamos un arquivo network.yml a partir da plantilla e procedemos a facer sustitucións:
 +
:* XXXX --> 192.0.2.31
 +
:* YYYY --> 255.255.255.0
 +
:* ZZZZ --> 192.0.2.1
 +
* Asignamos o config.yml como user.user-data do contedor.
 +
* Asignamos o netwok.yml como user.network-config do contedor.
 +
* Arrincamos o contedor.
 +
 +
Grazas ó bucle repetimos as accións e temos así os tres servidores personalizados. Ollo co explicado no punto 4.2 Cloud-config en relación ó servidor dhcp; xa que no caso de non habelo, habería que poñer a propiedade user.network_mode=link-local do contedor para indicar que a configuración rede farase a man e non por dhcp e ademais engadir a sección bootcmd en config.yml
 +
 +
Procedemos a asignarlle permisos de execución ó script e a lanzalo:
 +
$ chmod 755 escenario_8C.sh
 +
$ ./escenario_8C.sh
 +
$ incus ls -c n,4,s,l,P,m
 +
<pre>
 +
+---------------+-------------------+---------+----------------------+----------+--------------+
 +
|    NAME      |      IPV4        |  STATE  |    LAST USED AT    | PROFILES | MEMORY USAGE |
 +
+---------------+-------------------+---------+----------------------+----------+--------------+
 +
| apt-cacher-ng | 192.0.2.20 (eth0) | RUNNING | 2026/03/01 12:01 CET | WAN      | 79.78MiB    |
 +
+---------------+-------------------+---------+----------------------+----------+--------------+
 +
| server01      | 192.0.2.31 (eth0) | RUNNING | 2026/03/01 13:30 CET | WAN      | 72.16MiB    |
 +
+---------------+-------------------+---------+----------------------+----------+--------------+
 +
| server02      | 192.0.2.32 (eth0) | RUNNING | 2026/03/01 13:30 CET | WAN      | 72.41MiB    |
 +
+---------------+-------------------+---------+----------------------+----------+--------------+
 +
| server03      | 192.0.2.33 (eth0) | RUNNING | 2026/03/01 13:30 CET | WAN      | 72.36MiB    |
 +
+---------------+-------------------+---------+----------------------+----------+--------------+
 +
</pre>
 +
Vemos como están arrincados e totalmete configurados os tres servidores ó cabo duns minutos.
 +
$ incus exec server01 -- cloud-init status
 +
status: done
 +
$ incus exec server02 -- cloud-init status
 +
status: done
 +
$ incus exec server03 -- cloud-init status
 +
status: done
 +
 +
== Script de xestión mellorado ==
 +
NOTAS: o script mellorado pode descargarse:
 +
* [http:// PENDIENTE script mellorado PENDIENTE]
 +
 +
Xa temos o núcleo do script creado e podemos proceder a melloralo creando un menú con opcións de creación, inicio, parada e destrucción dos contedores:
 +
 +
<pre>
 +
#!/bin/bash
 +
REDE=192.0.2.3
 +
MS=255.255.255.0
 +
GW=192.0.2.1
 +
#incus project switch APT-CACHER
 +
clear
 +
echo "----- Escenario 8C -----"
 +
echo "Seleccionar a operación:"
 +
echo "1. Crear escenario"
 +
echo "2. Parar contedores escenario"
 +
echo "3. Arrincar contedores escenario"
 +
echo "4. Borrar escenario"
 +
echo "------"
 +
read opcion
 +
case $opcion in
 +
1) echo "Crear escenario"
 +
  for j in {1..3}
 +
  do
 +
    # creamos contedor sen arricar
 +
    incus init images:ubuntu/22.04/cloud server0$j --profile WAN
 +
    # personalizar a configuración do contedor
 +
    cp config_PLANTILLA.yml config.yml
 +
    cp network_PLANTILLA.yml network.yml
 +
    sed -i "s/HOSTNAME/server0$j/g" config.yml
 +
    sed -i "s/FQDN/server0$j.platega.example/g" config.yml
 +
    sed -i "s/XXXX/$REDE$j/g" network.yml
 +
    sed -i "s/YYYY/$MS/g" network.yml
 +
    sed -i "s/ZZZZ/$GW/g" network.yml
 +
    incus config set server0$j user.user-data -< config.yml
 +
    incus config set server0$j user.network-config -< network.yml
 +
    incus start server0$j
 +
  done
 +
  sleep 3
 +
  incus ls -c n,4,s,l,P,m
 +
  ;;
 +
2) echo "Parar contedores escenario"
 +
  for j in {1..3}
 +
  do
 +
    incus stop -f server0$j
 +
  done
 +
  echo " "
 +
    ;;
 +
3) echo "Arrincar containers escenario"
 +
  for j in {1..3}
 +
  do
 +
    incus start server0$j
 +
  done
 +
  echo " "
 +
  ;;
 +
4) echo "Borrar escenario"
 +
  for j in {1..3}
 +
  do
 +
    incus delete -f server0$j
 +
  done
 +
  echo " "
 +
  ;;
 +
*) echo "opción incorrecta"
 +
  ;;
 +
esac
 +
</pre>
 +
 +
Executamos o script e aparece o menú para xestionalo:
 +
$ ./escenario_8C_con_menu.sh
 +
<pre>
 +
----- Escenario 8C -----
 +
Seleccionar a operación:
 +
1. Crear escenario
 +
2. Parar contedores escenario
 +
3. Arrincar contedores escenario
 +
4. Borrar escenario
 +
------
 +
1
 +
Crear escenario
 +
Creando server01
 +
Creando server02
 +
Creando server03
 +
+---------------+-------------------+---------+----------------------+----------+--------------+
 +
|    NAME      |      IPV4        |  STATE  |    LAST USED AT    | PROFILES | MEMORY USAGE |
 +
+---------------+-------------------+---------+----------------------+----------+--------------+
 +
| apt-cacher-ng | 192.0.2.20 (eth0) | RUNNING | 2026/03/01 12:01 CET | WAN      | 79.78MiB    |
 +
+---------------+-------------------+---------+----------------------+----------+--------------+
 +
| server01      | 192.0.2.31 (eth0) | RUNNING | 2026/03/01 13:41 CET | WAN      | 41.63MiB    |
 +
+---------------+-------------------+---------+----------------------+----------+--------------+
 +
| server02      | 192.0.2.32 (eth0) | RUNNING | 2026/03/01 13:41 CET | WAN      | 41.69MiB    |
 +
+---------------+-------------------+---------+----------------------+----------+--------------+
 +
| server03      | 192.0.2.33 (eth0) | RUNNING | 2026/03/01 13:41 CET | WAN      | 42.69MiB    |
 +
+---------------+-------------------+---------+----------------------+----------+--------------+
 +
</pre>
  
 
= Referencias =
 
= Referencias =
 
* [https://docs.cloud-init.io/en/latest/index.html Documentación oficial de cloud-init]
 
* [https://docs.cloud-init.io/en/latest/index.html Documentación oficial de cloud-init]

Revisión actual del 19:45 4 mar 2026

Cloud-init

O termo cloud computing foi definido como un modelo para facer posible o acceso a rede axeitado e baixo demanda a un conxunto de recursos de computación configurables e compartidos (por exemplo, redes, servidores, almacenamento, aplicacións e servizos...) onde o seu aprovisionamento e liberación pode realizarse con rapidez e cun mínimo esforzo de xestión e interacción por parte do proveedor do cloud. A orixe do térmo está no gráfico de uso común para representar Internet como se fose unha nube (cloud). Os recursos de computación (hardware e software) destos modelos están dispoñibles a través de Internet.

Cloud computing

Fig. Cloud computing. Fonte: Wikipedia . Licenza CC

Unha característica do cloud computing especialmente interesante para a nosa docencia é a súa capacidade de creación, inicio e configuración de máquinas virtuais (instancias) dun xeito moi rápido e automatizado. Nos sistemas cloud empréganse 'cloud images' que veñen sendo plantillas de sistemas operativos preconfigurados que permiten iniciar novas instancias. A modo de exemplo, Canonical proporciona imaxes cloud de Ubuntu a través de https://cloud-images.ubuntu.com.

Ubuntu Cloud Images

Fig. Imaxes cloud de Ubuntu - https://cloud-images.ubuntu.com/

Ubuntu Cloud Images

Fig. Imaxes cloud de Ubuntu Focal Fossa - https://cloud-images.ubuntu.com/focal/current/

Cada instancia ó crearse é un clon idéntico de calquera outra instancia xa que son creadas a partir da mesma imaxe; sendo normal que desexemos configurar as nosas instancias despois de arrincar para instalar algúns paquetes, crear usuarios e/ou grupos, iniciar servizos, ... Aquí é onde entran dúas tecnoloxías:

User data
permite a un usuario pasar información contida nun arquivo local a unha instancia no momento do lanzamento.
Cloud-init
para facer algo útil cos user-data, a imaxe da máquina virtual debe estar preparada para correr un servizo ó arrincar que recolla esa información e execute as accións pertinentes en base ó seu contido. Cloud-init é unha ferramenta deseñada para facer isto; xa que ó arrincar a instancia, aplicará os user-data que se lle pasen. Cloud-init soporta varios formatos para recibir os user-data, sendo os shell scripts e os arquivos cloud-config os máis usados.

Despois de traballar con contedores LXC podemos deducir que moito do falado neste punto élle de aplicación:

  • Arrincamos contedores a partir de imaxes cloud dispoñibles en repositorios.
  • Ó crearse un contedor temos unha nova instancia semellante á imaxe de partida e semellante a todos os contedores creados a partir da mesma plantilla.
  • A creación e inicio das instancias é moi rápida, sendo posible facer lanzamentos masivos de contedores en pouco tempo. O mesmo acontece coa destrucción dos contedores.

O que queda por ver é como facer os despregues conseguindo instancias personalizadas en base ás nosas necesidades; e como unha tecnoloxía orientada á nube como é LXC/Incus, está preparada para aproveitarse de user-data e cloud-init.

No seguinte vídeo pode verse como en minuto e medio creamos unha máquina Ubuntu Server e grazas a cloud-init entre outras cousas:

  • Creamos un usuario administrador chamado magasix.
  • Autorizamos unha identidade dixital para acceder por ssh como magasix.
  • Configuramos a rede.
  • Instalamos apache+php+mysql.
  • Configuramos os repositorios desexados e indicamos que se empregue un servidor apt-cacher-ng.
  • Configuramos a zona horaria a Europa/Madrid.

No vídeo, executamos o comando:

tail -f /var/log/cloud-init-output.log 

Así veremos as accións que está a desenvolver cloud-init:

Escenario 1: cloud-config para crear un contedor LXC que no momento do seu primeiro inicio se configure automáticamente

Nesta práctica usaremos user-data e cloud-init para crear un contedor LXC que no momento do seu primeiro inicio se configure automáticamente de xeito que:

  • Teña o nome do equipo nos arquivos hostname e hosts.
  • Configure o servizo ssh para non permitir o acceso a root, permitir únicamente acceso mediante claves dixitais e non facer resolucións dns inversas para acelerar o proceso de login.
  • Teña un usuario administrador cunha identidade dixital autorizada para acceder por ssh.
  • Teña a configuración de rede correcta.
  • Teña os repositorios desexados.
  • Teña configurado o uso dun servidor apt-cacher-ng.
  • Teña instalado Apache con soporte php.

Preparación do escenario

Tómase como punto de partida o estado do equipo apt-cacher-ng ó remate do escenario anterior. Non hai que crear o contedor asir06 xa que o obxectivo do escenario é a súa creación e configuración.

Para aqueles que se animaron a probar o uso de projects e co gallo de ter algo organizados os contedores, pódese crear o contedor asir06 no project APT-CACHER creado no escenario 8A. Podemos verificar o project no que estamos con:

$ incus project list
+----------------------+--------+----------+---------+
|         NAME         | IMAGES | PROFILES | USED BY |
+----------------------+--------+----------+---------+
| APT-CACHER (current) | NO     | YES      | 8       |
+----------------------+--------+----------+---------+
| default              | YES    | YES      | 33      |
+----------------------+--------+----------+---------+

E no caso de non estar nel, podemos ir a él facendo:

$ incus project switch APT-CACHER
IMPORTANTE- Esta práctica hai que facela usando contedores xa que non funciona nas imaxes Ubuntu usadas en Virtualbox.

Cloud-config

Como sinala a documentación de cloud-init, cloud-config é a forma máis sinxela de proporcionar user-data á instancia, xa que o usuario pode especificar o que quere nun arquivo de texto cun formato fácilmente entendible polos humanos. O que si é obrigatario é que o arquivo respecte a sintaxe YAML; polo que é moi boa idea verificar a sintaxe, cousa que nos faremos antes de utilizalo para lanzar unha instancia.

NOTA: o arquivo config.yml pode descargarse dende a seguinte ligazón: config.yml

Comezamos creando no equipo anfitrión dos contedores un arquivo de nome config.yml cun editor de texto e escribindo a primeira liña:

#cloud-config

Unha vez posta a primeira liña obrigatoria, imos indicar o nome que terá o noso contedor:

  1. cloud-config
  2. Configurar /etc/hostname e /etc/hosts

hostname: asir06 fqdn: asir06.platega.example manage_etc_hosts: true

A continuación imos crear un usuario administrador cun contrasinal e cunha identidade dixital autorizada para acceder vía ssh. Para facelo precisamos coñecer:

O contrasinal cifrado: podemos xerar o contrasinal cifrado usando a utilidade mkpasswd presente na maioría das distribucións Linux. No caso de non tela instalada procedemos á súa instalación:

$ sudo apt install whois
$ mkpasswd --method=sha-512
Contraseña: 
$6$HjlvGV7JIzh$fsf2cYeU39dGnK3h45NL9Xgg1R6mzBPMUn.e5KuFaraYAsevr/msF/F8/.ZdZPLJtYxbsvb3HCJ3bRKgzrRfq0

A clave pública da identidade dixital a autorizar: lembrando o aprendido no apartado de Autenticación por claves do módulo de Seguridade por escuridade fronte a securización do servizo, unha identidade dixital tiña dúas claves, a privada e a pública. O que precisamos agora é o contido da clave pública que no meu caso chámase id_rsa.pub:

$ ls -lahF .ssh/
total 36K
drwx------  2 magasix magasix 4,0K nov  7 01:44 ./
drwxr-xr-x 40 magasix magasix 4,0K nov 10 19:37 ../
-rw-rw-r--  1 magasix magasix  524 oct 29 02:12 config
-rw-------  1 magasix magasix 3,3K oct 29 01:45 id_rsa
-rw-------  1 magasix magasix 3,2K oct 29 02:03 id_rsa_asir01
-rw-r--r--  1 magasix magasix  756 oct 29 02:03 id_rsa_asir01.pub
-rw-r--r--  1 magasix magasix  759 oct 29 01:45 id_rsa.pub
-rw-------  1 magasix magasix 1,1K nov 10 13:31 known_hosts
...
$ cat .ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC3uNp/L2xHX/XJgf9jHe9MSAs/TN2njwhDlXZh9Fv6JJaVQN74OK5lSfZeF7ToHNN3KP7V/EuVHseDE1Ct8HApdRXke1zUX6UDR/KAq2DPvrHT3KPLgM6iJZEPG5Ww8rI9DU8oU95o7hQUkmIsvbJsc0QmnjJ+Fv/+EVfnuSQ7IRybPrR5DnlxTKjR3cNtaFQ3aAfIzxFAVq+GSLvn38kkoL2gyInYEkb/5M2e9D2mcxmS4qbQbvJU8t0wuo1uOIECCSnqlobCxxueAP9eejGYxtugmgg3Gwxsz7nCCafbJDYx1NGgq4ZwenxBKhPzqJvVCfyVm7kr58OZh2DHwcZVS8RKELFnniVWXB21W541EvhiI07gqQXbySZzCOizmu46VxkscoCAaoclL9/QGfGuI6du5VvGgo/qEkPBYKWFp3PSEks56AtT1JesSbYvo62r6heI8volpZrag9CgzaVTB8M89InzzQxZyliaa0u7D5Uj6gOp51aivWRMXoESO/IUVc1cc9Sc/oECGBZ/qsPkk+2PLbwb5W5k+Oi2YBT6UOnywtI12E5ise+iJ8NqzeacVT8Hs/P8QxfXmFCn/Q49Z5DmObZmfDVqOk7wmO1OZSdGXtbUbwhqS4LnWnXNmd6MlkPM11VS1Tc7R6MkZVCvQ5UtmGJ5nLet2ucZwKWPyQ== Identidade manuel - curso platega

Unha vez obtidos os datos, engadimos ó arquivo config.yml os datos para crear un usuario (no meu caso chamareino magasix) e que reempraza o usuario ubuntu que por defecto ten a imaxe cloud. Dúas cousas importantes:

As tabulacións son espazos en branco e non tabulacións. Fixarse que a clave pública autorizada é unha única liña aínda que por espazo nos apuntamentos poida parecer que son varias liñas:#cloud-config

  1. Configurar /etc/hostname e /etc/hosts

hostname: asir06 fqdn: asir06.platega.example manage_etc_hosts: true

  1. Usuario

users:

 - name: magasix
   lock_passwd: false
   passwd: $6$571sUrFFS2MTd$FFpgMgYcwl4TkMTWP0M8Qe.0UcAw.gUpqbgGsNQTpMWNN5harLSUKTAHOpPxoKARZRreDJAqY1EfQEUORDpHF1
   ssh-authorized-keys:
     - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC3uNp/L2xHX/XJgf9jHe9MSAs/TN2njwhDlXZh9Fv6JJaVQN74OK5lSfZeF7ToHNN3KP7V/EuVHseDE1Ct8HApdRXke1zUX6UDR/KAq2DPvrHT3KPLgM6iJZEPG5Ww8rI9DU8oU95o7hQUkmIsvbJsc0QmnjJ+Fv/+EVfnuSQ7IRybPrR5DnlxTKjR3cNtaFQ3aAfIzxFAVq+GSLvn38kkoL2gyInYEkb/5M2e9D2mcxmS4qbQbvJU8t0wuo1uOIECCSnqlobCxxueAP9eejGYxtugmgg3Gwxsz7nCCafbJDYx1NGgq4ZwenxBKhPzqJvVCfyVm7kr58OZh2DHwcZVS8RKELFnniVWXB21W541EvhiI07gqQXbySZzCOizmu46VxkscoCAaoclL9/QGfGuI6du5VvGgo/qEkPBYKWFp3PSEks56AtT1JesSbYvo62r6heI8volpZrag9CgzaVTB8M89InzzQxZyliaa0u7D5Uj6gOp51aivWRMXoESO/IUVc1cc9Sc/oECGBZ/qsPkk+2PLbwb5W5k+Oi2YBT6UOnywtI12E5ise+iJ8NqzeacVT8Hs/P8QxfXmFCn/Q49Z5DmObZmfDVqOk7wmO1OZSdGXtbUbwhqS4LnWnXNmd6MlkPM11VS1Tc7R6MkZVCvQ5UtmGJ5nLet2ucZwKWPyQ== Identidade manuel - curso platega
   sudo: ['ALL=(ALL) NOPASSWD:ALL']
   groups: sudo
   shell: /bin/bash

A continuación imos indicar o contido do arquivo de configuración para usar ó apt-cacher-ng usando write_files:

  1. cloud-config
  2. Configurar /etc/hostname e /etc/hosts

hostname: asir06 fqdn: asir06.platega.example manage_etc_hosts: true

  1. Usuario

users:

- name: magasix
  lock_passwd: false
  passwd: $6$571sUrFFS2MTd$FFpgMgYcwl4TkMTWP0M8Qe.0UcAw.gUpqbgGsNQTpMWNN5harLSUKTAHOpPxoKARZRreDJAqY1EfQEUORDpHF1
  ssh-authorized-keys:
    - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQD033pPV59uD6U2DxkMvtKTv+xXL/YuZr62HoKK9NC0eQa+EgiRt94ZC7k4WFNbf9AtmDHPO1y5C/LI5V0lqXGoAkwHFO2CzNrdnGNxBSCeNgk92gdtWpJ8GPSwqci6Vmk7TSJ6JscRMI5Dwg8Q9JbvRsncwkNzHQ1jV4dnmK3KAc3Wusg3xBeeKIZALgHswWv18VGCMvaTt6QLMLMqjW6sw4MCarygBK30o33BvZUbO9zq6yy4TVjw6ws3789TyI38lLOQ/wyfSapFzryK/1yi6XJzpk2LbCv5NgcmtrjsitxEgT8yrLfPunoIzhjdWZRVIPyLCrg4r0e3d/eTip3D1Uuycl1ud8WeWw7b9fe9rPbBUA5C21fsUQiTB+bMTN/vXzMdEXr2Wjup830d0x8Ia4a8koE9SP+v8Bo/lANmlN1lxOnDCuWLQR3O/FGoVlEiX0RGYLuVrzY216PMP7juEqM1dLZvJ3mwzT9xonTx+boMcPeVT4cNFiaJuCBTwnZDKfnZiQ8BdAVNkMjaDjf/qjWSZOltXYP0azOQhK/i15iol4cMKLfmYA1dj36vnkUa1k9jBeUgKRNaqxNiZByzy7tpR7nb+UYiGgnF28jKzlLsYuD+YlqRn7ipHmzdLfHMURO35CwwMQhon6VVKwKOA1m0pHp6+++n9OnoP9eRuw== Identidade manuel - curso platega
  sudo: ['ALL=(ALL) NOPASSWD:ALL']
  groups: sudo
  shell: /bin/bash

write_files:

 - path: /etc/apt/apt.conf.d/01apt-cacher-ng
   content: |
     Acquire::http { Proxy "http://192.0.2.20:3142"; }

A continuación imos indicar que se conserve o contido do /etc/apt/sources.list,

  1. cloud-config
  2. Configurar /etc/hostname e /etc/hosts

hostname: asir06 fqdn: asir06.platega.example manage_etc_hosts: true

  1. Usuario

users:

- name: magasix
  lock_passwd: false
  passwd: $6$571sUrFFS2MTd$FFpgMgYcwl4TkMTWP0M8Qe.0UcAw.gUpqbgGsNQTpMWNN5harLSUKTAHOpPxoKARZRreDJAqY1EfQEUORDpHF1
  ssh-authorized-keys:
    - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQD033pPV59uD6U2DxkMvtKTv+xXL/YuZr62HoKK9NC0eQa+EgiRt94ZC7k4WFNbf9AtmDHPO1y5C/LI5V0lqXGoAkwHFO2CzNrdnGNxBSCeNgk92gdtWpJ8GPSwqci6Vmk7TSJ6JscRMI5Dwg8Q9JbvRsncwkNzHQ1jV4dnmK3KAc3Wusg3xBeeKIZALgHswWv18VGCMvaTt6QLMLMqjW6sw4MCarygBK30o33BvZUbO9zq6yy4TVjw6ws3789TyI38lLOQ/wyfSapFzryK/1yi6XJzpk2LbCv5NgcmtrjsitxEgT8yrLfPunoIzhjdWZRVIPyLCrg4r0e3d/eTip3D1Uuycl1ud8WeWw7b9fe9rPbBUA5C21fsUQiTB+bMTN/vXzMdEXr2Wjup830d0x8Ia4a8koE9SP+v8Bo/lANmlN1lxOnDCuWLQR3O/FGoVlEiX0RGYLuVrzY216PMP7juEqM1dLZvJ3mwzT9xonTx+boMcPeVT4cNFiaJuCBTwnZDKfnZiQ8BdAVNkMjaDjf/qjWSZOltXYP0azOQhK/i15iol4cMKLfmYA1dj36vnkUa1k9jBeUgKRNaqxNiZByzy7tpR7nb+UYiGgnF28jKzlLsYuD+YlqRn7ipHmzdLfHMURO35CwwMQhon6VVKwKOA1m0pHp6+++n9OnoP9eRuw== Identidade manuel - curso platega
  sudo: ['ALL=(ALL) NOPASSWD:ALL']
  groups: sudo
  shell: /bin/bash

write_files:

 - path: /etc/apt/apt.conf.d/01apt-cacher-ng
   content: |
     Acquire::http { Proxy "http://192.0.2.20:3142"; }
  1. Conservar repositorios e instalar paquetes

apt:

 preserve_sources_list: true

packages:

 - net-tools
 - apache2
 - php
 - php-cli
 - php-common
 - libapache2-mod-php
 - php-gd
 - php-curl
 - php-mbstring
 - php-xmlrpc
 - php-soap 
 - php-xml
 - php-intl
 - php-mysql
 - php-zip
 - mysql-client
 - openssh-server
 - sudo
 - bash
 - bash-completion

Configuración de ssh e apache

A continuación indicamos na seccion runcmd comandos a executar no primeiro inicio da máquina e que no noso exemplo servirán para:

Configurar o servizo ssh: Bloqueamos o acceso a root. Habilitamos o acceso por contrasinal Configurar que non se fagan resolucións inversas para acelerar o proceso de autenticación. Habilitar o servizo https en Apache Crear un arquivo info.php no DocumentRoot do sitio web activo no servidor web. Reiniciar o servizo ssh e Apache para aplicar a nova configuración.

  1. cloud-config
  2. Configurar /etc/hostname e /etc/hosts

hostname: asir06 fqdn: asir06.platega.example manage_etc_hosts: true

  1. Usuario

users:

- name: magasix
  lock_passwd: false
  passwd: $6$571sUrFFS2MTd$FFpgMgYcwl4TkMTWP0M8Qe.0UcAw.gUpqbgGsNQTpMWNN5harLSUKTAHOpPxoKARZRreDJAqY1EfQEUORDpHF1
  ssh-authorized-keys:
    - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQD033pPV59uD6U2DxkMvtKTv+xXL/YuZr62HoKK9NC0eQa+EgiRt94ZC7k4WFNbf9AtmDHPO1y5C/LI5V0lqXGoAkwHFO2CzNrdnGNxBSCeNgk92gdtWpJ8GPSwqci6Vmk7TSJ6JscRMI5Dwg8Q9JbvRsncwkNzHQ1jV4dnmK3KAc3Wusg3xBeeKIZALgHswWv18VGCMvaTt6QLMLMqjW6sw4MCarygBK30o33BvZUbO9zq6yy4TVjw6ws3789TyI38lLOQ/wyfSapFzryK/1yi6XJzpk2LbCv5NgcmtrjsitxEgT8yrLfPunoIzhjdWZRVIPyLCrg4r0e3d/eTip3D1Uuycl1ud8WeWw7b9fe9rPbBUA5C21fsUQiTB+bMTN/vXzMdEXr2Wjup830d0x8Ia4a8koE9SP+v8Bo/lANmlN1lxOnDCuWLQR3O/FGoVlEiX0RGYLuVrzY216PMP7juEqM1dLZvJ3mwzT9xonTx+boMcPeVT4cNFiaJuCBTwnZDKfnZiQ8BdAVNkMjaDjf/qjWSZOltXYP0azOQhK/i15iol4cMKLfmYA1dj36vnkUa1k9jBeUgKRNaqxNiZByzy7tpR7nb+UYiGgnF28jKzlLsYuD+YlqRn7ipHmzdLfHMURO35CwwMQhon6VVKwKOA1m0pHp6+++n9OnoP9eRuw== Identidade manuel - curso platega
  sudo: ['ALL=(ALL) NOPASSWD:ALL']
  groups: sudo
  shell: /bin/bash

write_files:

 - path: /etc/apt/apt.conf.d/01apt-cacher-ng
   content: |
     Acquire::http { Proxy "http://192.0.2.20:3142"; }
  1. Conservar repositorios e instalar paquetes

apt:

 preserve_sources_list: true

packages:

 - net-tools
 - apache2
 - php
 - php-cli
 - php-common
 - libapache2-mod-php
 - php-gd
 - php-curl
 - php-mbstring
 - php-xmlrpc
 - php-soap 
 - php-xml
 - php-intl
 - php-mysql
 - php-zip
 - mysql-client
 - openssh-server
 - sudo
 - bash
 - bash-completion
  1. Executar comandos no primeiro inicio

runcmd:

 - sed -i "s%#PermitRootLogin prohibit-password%PermitRootLogin no%g" /etc/ssh/sshd_config
 - sed -i "s%PasswordAuthentication yes%PasswordAuthentication yes%g" /etc/ssh/sshd_config
 - sed -i "3iUseDNS no" /etc/ssh/sshd_config
 - a2enmod ssl
 - a2ensite default-ssl.conf
 - echo '<?php phpinfo(); ?>' > /var/www/html/info.php
 - systemctl restart sshd
 - systemctl restart apache2

Configuración da zona horaria

Para rematar indicamos zona horaria e locale:

  1. cloud-config
  2. Configurar /etc/hostname e /etc/hosts

hostname: asir06 fqdn: asir06.platega.example manage_etc_hosts: true

  1. Usuario

users:

- name: magasix
  lock_passwd: false
  passwd: $6$571sUrFFS2MTd$FFpgMgYcwl4TkMTWP0M8Qe.0UcAw.gUpqbgGsNQTpMWNN5harLSUKTAHOpPxoKARZRreDJAqY1EfQEUORDpHF1
  ssh-authorized-keys:
    - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQD033pPV59uD6U2DxkMvtKTv+xXL/YuZr62HoKK9NC0eQa+EgiRt94ZC7k4WFNbf9AtmDHPO1y5C/LI5V0lqXGoAkwHFO2CzNrdnGNxBSCeNgk92gdtWpJ8GPSwqci6Vmk7TSJ6JscRMI5Dwg8Q9JbvRsncwkNzHQ1jV4dnmK3KAc3Wusg3xBeeKIZALgHswWv18VGCMvaTt6QLMLMqjW6sw4MCarygBK30o33BvZUbO9zq6yy4TVjw6ws3789TyI38lLOQ/wyfSapFzryK/1yi6XJzpk2LbCv5NgcmtrjsitxEgT8yrLfPunoIzhjdWZRVIPyLCrg4r0e3d/eTip3D1Uuycl1ud8WeWw7b9fe9rPbBUA5C21fsUQiTB+bMTN/vXzMdEXr2Wjup830d0x8Ia4a8koE9SP+v8Bo/lANmlN1lxOnDCuWLQR3O/FGoVlEiX0RGYLuVrzY216PMP7juEqM1dLZvJ3mwzT9xonTx+boMcPeVT4cNFiaJuCBTwnZDKfnZiQ8BdAVNkMjaDjf/qjWSZOltXYP0azOQhK/i15iol4cMKLfmYA1dj36vnkUa1k9jBeUgKRNaqxNiZByzy7tpR7nb+UYiGgnF28jKzlLsYuD+YlqRn7ipHmzdLfHMURO35CwwMQhon6VVKwKOA1m0pHp6+++n9OnoP9eRuw== Identidade manuel - curso platega
  sudo: ['ALL=(ALL) NOPASSWD:ALL']
  groups: sudo
  shell: /bin/bash

write_files:

 - path: /etc/apt/apt.conf.d/01apt-cacher-ng
   content: |
     Acquire::http { Proxy "http://192.0.2.20:3142"; }
  1. Conservar repositorios e instalar paquetes

apt:

 preserve_sources_list: true

packages:

 - net-tools
 - apache2
 - php
 - php-cli
 - php-common
 - libapache2-mod-php
 - php-gd
 - php-curl
 - php-mbstring
 - php-xmlrpc
 - php-soap 
 - php-xml
 - php-intl
 - php-mysql
 - php-zip
 - mysql-client
 - bash-completion
  1. Executar comandos no primeiro inicio

runcmd:

 - sed -i "s%#PermitRootLogin prohibit-password%PermitRootLogin no%g" /etc/ssh/sshd_config
 - sed -i "s%PasswordAuthentication yes%PasswordAuthentication no%g" /etc/ssh/sshd_config
 - sed -i "3iUseDNS no" /etc/ssh/sshd_config
 - a2enmod ssl
 - a2ensite default-ssl.conf
 - echo '<?php phpinfo(); ?>' > /var/www/html/info.php
 - systemctl restart sshd
 - systemctl restart apache2
  1. Zona horaria e locale

timezone: Europe/Madrid locale: es_ES.UTF-8

Verificando a sintaxe

Unha vez creado o arquivo imos a http://www.yamllint.com/ ou https://codebeautify.org/yaml-validator para validar a sintaxe; xa que non é a primeira vez que por culpa dunha mala sintaxe, non funciona a inicialización do contedor.

Copiamos&pegamos o contido do noso config.yml e prememos en Go.

Validación do YAML

Fig. Verificando a sintaxe YAML.

Lanzando o contedor

Unha vez verificada a sintaxe podemos proseguir e preparnos para lanzar o contedor. É moi importante ter en conta que as imaxes cloud Ubuntu que empregamos veñen con cloud-init configurado para esperar que o contedor reciba unha configuración rede inicial por dhcp. No caso de non ter un servidor dhcp temos que indicalo cun parámetro de configuración:

  • Se hai servidor dhcp (o normal cando creamos redes lxd e é o noso caso) podemos lanzar o contedor executando:
$ incus launch images:ubuntu/22.04/cloud asir06 -c user.user-data="$(cat config.yml)" -p WAN
  • Si non hai servidor dhcp: hai que facer dúas cousas:

A) Engadir un bloque bootcmd no config.yml para configurar a rede do equipo nada máis arrincar o contedor.

# executar comandos ó iniciar o contedor
bootcmd:
 - ip addr add dev eth0 192.0.2.26/24
 - ip route add default via 192.0.2.1
 - [sh, -c, "echo 'nameserver 8.8.8.8' > /etc/resolv.conf"]
 - [sh, -c, "echo 'nameserver 8.8.4.4' >> /etc/resolv.conf"] 

B) Indicar a cloud-init coa propiedade user.network_mode=link-local que a configuración rede farase a man e non por dhcp.

$ incus launch images:ubuntu/22.04/cloud asir06 -c user.user-data="$(cat config.yml)" -c user.network_mode=link-local -p WAN

Hai diferenzas entre bootcmd e runcmd:

  • bootcmd execútase moi pronto no inicio do contedor e sempre se executa en cada inicio.
  • runmcd execútase máis tarde e únicamente no primeiro inicio do contedor.

Podemos facer comprobacións de que todo foi ben unha vez rematado o aprovisionamento:

$  incus exec asir06 -- cloud-init status
status: done
$ incus exec asir06 bash
# cat /etc/hostname 
asir06
# cat /etc/hosts
# Your system has configured 'manage_etc_hosts' as True.
# As a result, if you wish for changes to this file to persist
# then you will need to either
# a.) make changes to the master file in /etc/cloud/templates/hosts.debian.tmpl
# b.) change or remove the value of 'manage_etc_hosts' in
#     /etc/cloud/cloud.cfg or cloud-config from user-data
#
127.0.1.1 asir06.platega.example asir06
127.0.0.1 localhost

# The following lines are desirable for IPv6 capable hosts
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
# cat /etc/apt/apt.conf.d/01apt-cacher-ng
Acquire::http { Proxy "http://192.0.2.20:3142"; }
# ss -ltn
State          Recv-Q          Send-Q          Local Address:Port          Peer Address:Port          Process                                 
LISTEN        0                4096            127.0.0.53%lo:53                 0.0.0.0:*                                                                                      
LISTEN        0                128                   0.0.0.0:22                 0.0.0.0:*                                                                                      
LISTEN        0                511                         *:44                       *:*                                                                                      
LISTEN        0                511                         *:80                       *:*                                                                                      
LISTEN        0                128                      [::]:22                    [::]:*
# dpkg -l | grep -i php
ii  libapache2-mod-php              2:8.3+94+ubuntu22.04.1+deb.sury.org+2      all          server-side, HTML-embedded scripting language (Apache 2 module) (default)
ii  libapache2-mod-php8.3           8.3.7-2+ubuntu22.04.1+deb.sury.org+1       amd64        server-side, HTML-embedded scripting language (Apache 2 module)
ii  php                             2:8.3+94+ubuntu22.04.1+deb.sury.org+2      all          server-side, HTML-embedded scripting language (default)
ii  php-cli                         2:8.3+94+ubuntu22.04.1+deb.sury.org+2      all          command-line interpreter for the PHP scripting language (default)
ii  php-common                      2:94+ubuntu22.04.1+deb.sury.org+2          all          Common files for PHP packages
...

Tamén podemos verificar que é posible conectarse por ssh usando a identidade dixital autorizada accedendo pola IP asignada por DHCP ó contedor asir06, no meu caso a 135:

$ incus ls
+---------------+---------+--------------------+------+-----------+-----------+
|     NAME      |  STATE  |        IPV4        | IPV6 |   TYPE    | SNAPSHOTS |
+---------------+---------+--------------------+------+-----------+-----------+
| apt-cacher-ng | RUNNING | 192.0.2.20 (eth0)  |      | CONTAINER | 0         |
+---------------+---------+--------------------+------+-----------+-----------+
...
+---------------+---------+--------------------+------+-----------+-----------+
| asir06        | RUNNING | 192.0.2.144 (eth0) |      | CONTAINER | 0         |
+---------------+---------+--------------------+------+-----------+-----------+
$ ssh -i ~/.ssh/id_rsa magasix@192.0.2.26
The authenticity of host '192.0.2.144 (192.0.2.144)' can't be established.
ED25519 key fingerprint is SHA256:vympcjMRG0K4man1csRAsg0KNT47pT3gj9iP7OXJfjc.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.0.2.144' (ED25519) to the list of known hosts.
Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 6.5.0-35-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/pro

 System information disabled due to load higher than 1.0

Expanded Security Maintenance for Applications is not enabled.

16 updates can be applied immediately.
8 of these updates are standard security updates.
To see these additional updates run: apt list --upgradable

Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status



The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

Cloud-init e power_state

Pode ser interesante reiniciar o contedor ó remate do proceso para ver o comportamento do contedor fronte ós reinicios.

É posible reiniciar o contedor a través de scripts ou runcmd pero facelo con power_state asegura que todas as accións de cloud-init remataron antes de reiniciar. Para configurar o reinicio automático engadiriamos as seguintes liñas no config.yml:

# reinicio ó rematar
power_state:
  mode: reboot

Desta forma poderiamos esquecernos dalgúns comandos do bloque runcmd xa que co reinicio do contedor os cambios indicados xa se aplicarían:

# Executar comandos no primeiro inicio
runcmd:
  - sed -i "s%#PermitRootLogin prohibit-password%PermitRootLogin no%g" /etc/ssh/sshd_config
  - sed -i "s%PasswordAuthentication yes%PasswordAuthentication yes%g" /etc/ssh/sshd_config
  - sed -i "3iUseDNS no" /etc/ssh/sshd_config
  - a2enmod ssl
  - a2ensite default-ssl.conf
  - echo '<?php phpinfo(); ?>' > /var/www/html/info.php
#  - systemctl restart sshd
#  - systemctl restart apache2

Ademais do reinicio pódese configurar o apagado e un tempo de retardo.

Configuración de rede

Por defecto o contedor recibe a configuración de rede por dhcp, pero podemos personalizala usando calquera das seguintes opcións:

Con user.network-config

Usando user.network-config podemos pasarlle información a cloud-init para que configure a rede do contedor. Facemos dous arquivos:

En primeiro lugar temos o config.yml feito en apartados anteriores

En segundo lugar temos un novo arquivo network.yml onde definimos a configuración de rede:

#cloud-config
version: 1
config:
  - type: physical
    name: eth0
    subnets:
      - type: static
        ipv4: true
        address: 192.0.2.26
        netmask: 255.255.255.0
        gateway: 192.0.2.1
        control: auto
  - type: nameserver
    address:
      - 8.8.8.8
      - 8.8.4.4

Procedemos á creación do contedo pasándolle o config.yml e o network.yml:

$ incus launch images:ubuntu/22.04/cloud asir06 -c user.user-data="$(cat config.yml)" -c user.network-config="$(cat network.yml)" -p WAN

O resultado é un contedor coa configuración de rede esperada e gardada en /etc/network/interfaces.d/50-cloud-init.cfg

# cat /etc/netplan/50-cloud-init.yaml 
# This file is generated from information provided by the datasource.  Changes
# to it will not persist across an instance reboot.  To disable cloud-init's
# network configuration capabilities, write a file
# /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg with the following:
# network: {config: disabled}
network:
    version: 2
    ethernets:
        eth0:
            addresses:
            - 192.0.2.26/24
            nameservers:
                addresses:
                - 8.8.8.8
                - 8.8.4.4
                search: []
            routes:
            -   to: default
                via: 192.0.2.1
# resolvectl status
Global
       Protocols: -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
resolv.conf mode: stub

Link 13 (eth0)
    Current Scopes: DNS
         Protocols: +DefaultRoute +LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
Current DNS Server: 8.8.8.8
       DNS Servers: 8.8.8.8 8.8.4

Sen user.network-config

Outra forma é modificar o config.yml para escribir a configuración de rede nun arquivo de configuración, e aplicar os cambios para que teña efecto sen necesidade de reiniciar o contedor:

NOTA. o arquivo config.yml coa parte de rede pode descargarse dende a seguinte ligazón: config_con_rede.yml
#cloud-config
# Configurar /etc/hostname e /etc/hosts
hostname: asir06
fqdn: asir06.platega.example
manage_etc_hosts: true
# Usuario
users:
 - name: magasix
   lock_passwd: false
   passwd: $6$571sUrFFS2MTd$FFpgMgYcwl4TkMTWP0M8Qe.0UcAw.gUpqbgGsNQTpMWNN5harLSUKTAHOpPxoKARZRreDJAqY1EfQEUORDpHF1
   ssh-authorized-keys:
     - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQD033pPV59uD6U2DxkMvtKTv+xXL/YuZr62HoKK9NC0eQa+EgiRt94ZC7k4WFNbf9AtmDHPO1y5C/LI5V0lqXGoAkwHFO2CzNrdnGNxBSCeNgk92gdtWpJ8GPSwqci6Vmk7TSJ6JscRMI5Dwg8Q9JbvRsncwkNzHQ1jV4dnmK3KAc3Wusg3xBeeKIZALgHswWv18VGCMvaTt6QLMLMqjW6sw4MCarygBK30o33BvZUbO9zq6yy4TVjw6ws3789TyI38lLOQ/wyfSapFzryK/1yi6XJzpk2LbCv5NgcmtrjsitxEgT8yrLfPunoIzhjdWZRVIPyLCrg4r0e3d/eTip3D1Uuycl1ud8WeWw7b9fe9rPbBUA5C21fsUQiTB+bMTN/vXzMdEXr2Wjup830d0x8Ia4a8koE9SP+v8Bo/lANmlN1lxOnDCuWLQR3O/FGoVlEiX0RGYLuVrzY216PMP7juEqM1dLZvJ3mwzT9xonTx+boMcPeVT4cNFiaJuCBTwnZDKfnZiQ8BdAVNkMjaDjf/qjWSZOltXYP0azOQhK/i15iol4cMKLfmYA1dj36vnkUa1k9jBeUgKRNaqxNiZByzy7tpR7nb+UYiGgnF28jKzlLsYuD+YlqRn7ipHmzdLfHMURO35CwwMQhon6VVKwKOA1m0pHp6+++n9OnoP9eRuw== Identidade manuel - curso platega
   sudo: ['ALL=(ALL) NOPASSWD:ALL']
   groups: sudo
   shell: /bin/bash
write_files:
  - path: /etc/netplan/50-cloud-init.yaml
    content: |
      network:
        version: 2
        ethernets:
          eth0:
            addresses: [192.0.2.26/24]
            nameservers:
              addresses: [8.8.8.8,8.8.4.4]
            routes:
              - to: default
                via: 192.0.2.1
  - path: /etc/apt/apt.conf.d/01apt-cacher-ng
    content: |
      Acquire::http { Proxy "http://192.0.2.20:3142"; }
# Conservar repositorios e instalar paquetes
apt:
  preserve_sources_list: true
packages:
  - net-tools
  - apache2
  - php
  - php-cli
  - php-common
  - libapache2-mod-php
  - php-gd
  - php-curl
  - php-mbstring
  - php-xmlrpc
  - php-soap 
  - php-xml
  - php-intl
  - php-mysql
  - php-zip
  - mysql-client
  - openssh-server
  - sudo
  - bash
  - bash-completion
# Executar comandos no primeiro inicio
runcmd:
  - sed -i "s%#PermitRootLogin prohibit-password%PermitRootLogin no%g" /etc/ssh/sshd_config
  - sed -i "s%PasswordAuthentication yes%PasswordAuthentication yes%g" /etc/ssh/sshd_config
  - sed -i "3iUseDNS no" /etc/ssh/sshd_config
  - a2enmod ssl
  - a2ensite default-ssl.conf
  - echo '<?php phpinfo(); ?>' > /var/www/html/info.php
  - systemctl restart sshd
  - systemctl restart apache2
  - netplan apply
# Zona horaria e locale
timezone: Europe/Madrid
locale: es_ES.UTF-8

E procedemos á creación do contedor:

incus launch images:ubuntu/22.04/cloud asir06 -c user.user-data="$(cat config_con_rede.yml)"

Para rematar este apartado, indicar que hai diferentes maneiras de facer algunhas das cousas que configuramos (p.e. o que comentamos sobre a rede), pero podemos ver

  • como é posible lanzar un contedor e personalizar a súa configuración de xeito automático no primeiro inicio.
  • no último exemplo, con cloud-init, user.user-data, user.network-config e grazas a apt-cacher-ng, en aproximadamente un minuto un servidor Apache con php correndo.

Cloud-init: orde de execución e logs

A orde de prioridade á hora de executar as accións indicados no arquivo config.yml nun contedor LXD pode verse no arquivo

# less /etc/cloud/cloud.cfg
...
# The modules that run in the 'init' stage
cloud_init_modules:
  - seed_random
  - bootcmd
  - write_files
  - growpart
  - resizefs
  - disk_setup
  - mounts
  - set_hostname
  - update_hostname
  - update_etc_hosts
  - ca_certs
  - rsyslog
  - users_groups
  - ssh

# The modules that run in the 'config' stage
cloud_config_modules:
  - wireguard
  - snap
  - ubuntu_autoinstall
  - ssh_import_id
  - keyboard
  - locale
  - set_passwords
  - grub_dpkg
  - apt_pipelining
  - apt_configure
  - ubuntu_pro
  - ntp
  - timezone
  - disable_ec2_metadata
  - runcmd
  - byobu

# The modules that run in the 'final' stage
cloud_final_modules:
  - package_update_upgrade_install
  - fan
  - landscape
  - lxd
  - ubuntu_drivers
  - write_files_deferred
  - puppet
  - chef
  - ansible
  - mcollective
  - salt_minion
  - reset_rmc
  - 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
...

Aínda que ás veces non é de moita axuda, existe un arquivo de log en /var/log/cloud-init-output.log coas accións feitas por cloud-init ó arrincar o contedor:

# less /var/log/cloud-init-output.log 
Cloud-init v. 24.1.3-0ubuntu1~22.04.1 running 'init-local' at Fri, 31 May 2024 08:38:28 +0000. Up 1.25 seconds.
2024-05-31 08:38:29,018 - schema.py[WARNING]: Invalid network-config provided: Please run 'sudo cloud-init schema --system' to see the schema errors.
Cloud-init v. 24.1.3-0ubuntu1~22.04.1 running 'init' at Fri, 31 May 2024 08:38:41 +0000. Up 14.17 seconds.
ci-info: ++++++++++++++++++++++++++++++++++++++Net device info+++++++++++++++++++++++++++++++++++++++
ci-info: +--------+------+-----------------------------+---------------+--------+-------------------+
ci-info: | Device |  Up  |           Address           |      Mask     | Scope  |     Hw-Address    |
ci-info: +--------+------+-----------------------------+---------------+--------+-------------------+
ci-info: |  eth0  | True |          192.0.2.26         | 255.255.255.0 | global | 00:16:3e:4e:a4:c5 |
ci-info: |  eth0  | True | fe80::216:3eff:fe4e:a4c5/64 |       .       |  link  | 00:16:3e:4e:a4:c5 |
ci-info: |   lo   | True |          127.0.0.1          |   255.0.0.0   |  host  |         .         |
ci-info: |   lo   | True |           ::1/128           |       .       |  host  |         .         |
ci-info: +--------+------+-----------------------------+---------------+--------+-------------------+
ci-info: ++++++++++++++++++++++++++++Route IPv4 info++++++++++++++++++++++++++++
ci-info: +-------+-------------+-----------+---------------+-----------+-------+
ci-info: | Route | Destination |  Gateway  |    Genmask    | Interface | Flags |
ci-info: +-------+-------------+-----------+---------------+-----------+-------+
ci-info: |   0   |   0.0.0.0   | 192.0.2.1 |    0.0.0.0    |    eth0   |   UG  |
ci-info: |   1   |  192.0.2.0  |  0.0.0.0  | 255.255.255.0 |    eth0   |   U   |
ci-info: +-------+-------------+-----------+---------------+-----------+-------+
ci-info: +++++++++++++++++++Route IPv6 info+++++++++++++++++++
ci-info: +-------+-------------+---------+-----------+-------+
ci-info: | Route | Destination | Gateway | Interface | Flags |
ci-info: +-------+-------------+---------+-----------+-------+
ci-info: |   0   |  fe80::/64  |    ::   |    eth0   |   U   |
ci-info: |   2   |    local    |    ::   |    eth0   |   U   |
ci-info: |   3   |  multicast  |    ::   |    eth0   |   U   |
ci-info: +-------+-------------+---------+-----------+-------+
...
Cloud-init v. 24.1.3-0ubuntu1~22.04.1 running 'modules:config' at Fri, 31 May 2024 08:38:47 +0000. Up 19.41 seconds.
Generating locales (this might take a while)...
  es_ES.UTF-8... done
Generation complete.
Hit:1 http://archive.ubuntu.com/ubuntu jammy InRelease
Get:2 http://security.ubuntu.com/ubuntu jammy-security InRelease [129 kB]
Get:3 https://ppa.launchpadcontent.net/ondrej/php/ubuntu jammy InRelease [24.6 kB]
Get:4 http://security.ubuntu.com/ubuntu jammy-security/main amd64 Packages [1475 kB]
Get:5 http://security.ubuntu.com/ubuntu jammy-security/main Translation-en [254 kB]
Get:6 http://security.ubuntu.com/ubuntu jammy-security/restricted amd64 Packages [1876 kB]
Get:7 http://security.ubuntu.com/ubuntu jammy-security/restricted Translation-en [318 kB]
Get:8 http://security.ubuntu.com/ubuntu jammy-security/universe amd64 Packages [854 kB]
Get:9 http://security.ubuntu.com/ubuntu jammy-security/universe Translation-en [165 kB]
Get:10 http://security.ubuntu.com/ubuntu jammy-security/universe amd64 c-n-f Metadata [16.8 kB]
Get:11 http://security.ubuntu.com/ubuntu jammy-security/multiverse amd64 Packages [37.2 kB]
Get:12 http://security.ubuntu.com/ubuntu jammy-security/multiverse Translation-en [7588 B]
Get:13 http://security.ubuntu.com/ubuntu jammy-security/multiverse amd64 c-n-f Metadata [260 B]
...
Cloud-init v. 24.1.3-0ubuntu1~22.04.1 running 'modules:final' at Fri, 31 May 2024 08:39:03 +0000. Up 35.97 seconds.
Reading package lists...
Building dependency tree...
Reading state information...
bash-completion is already the newest version (1:2.11-5ubuntu1).
bash-completion set to manually installed.
The following additional packages will be installed:
  apache2-bin apache2-data apache2-utils bzip2 fontconfig-config
  fonts-dejavu-core libabsl20210324 libaom3 libapache2-mod-php8.3 libapr1
  libaprutil1 libaprutil1-dbd-sqlite3 libaprutil1-ldap libavif13 libdav1d5
  libde265-0 libdeflate0 libfontconfig1 libfreetype6 libgav1-0 libgd3 libheif1
  libjbig0 libjpeg-turbo8 libjpeg8 liblua5.3-0 libonig5 libtiff5 libwebp7
  libx265-199 libxmlrpc-epi0 libxpm4 libyuv0 libzip4 mailcap mime-support
  mysql-client-8.0 mysql-client-core-8.0 mysql-common php8.3 php8.3-cli
  php8.3-common php8.3-curl php8.3-gd php8.3-intl php8.3-mbstring php8.3-mysql
  php8.3-opcache php8.3-readline php8.3-soap php8.3-xml php8.3-xmlrpc
  php8.3-zip ssl-cert
Suggested packages:
  apache2-doc apache2-suexec-pristine | apache2-suexec-custom www-browser
  bzip2-doc php-pear libgd-tools
The following NEW packages will be installed:
  apache2 apache2-bin apache2-data apache2-utils bzip2 fontconfig-config
  fonts-dejavu-core libabsl20210324 libaom3 libapache2-mod-php
  libapache2-mod-php8.3 libapr1 libaprutil1 libaprutil1-dbd-sqlite3
  libaprutil1-ldap libavif13 libdav1d5 libde265-0 libdeflate0 libfontconfig1
  libfreetype6 libgav1-0 libgd3 libheif1 libjbig0 libjpeg-turbo8 libjpeg8
  liblua5.3-0 libonig5 libtiff5 libwebp7 libx265-199 libxmlrpc-epi0 libxpm4
  libyuv0 libzip4 mailcap mime-support mysql-client mysql-client-8.0
  mysql-client-core-8.0 mysql-common net-tools php php-cli php-common php-curl
  php-gd php-intl php-mbstring php-mysql php-soap php-xml php-xmlrpc php-zip
  php8.3 php8.3-cli php8.3-common php8.3-curl php8.3-gd php8.3-intl
  php8.3-mbstring php8.3-mysql php8.3-opcache php8.3-readline php8.3-soap
  php8.3-xml php8.3-xmlrpc php8.3-zip ssl-cert
0 upgraded, 70 newly installed, 0 to remove and 25 not upgraded.
...
Creating config file /etc/php/8.3/mods-available/calendar.ini with new version

Creating config file /etc/php/8.3/mods-available/ctype.ini with new version

Creating config file /etc/php/8.3/mods-available/exif.ini with new version

Creating config file /etc/php/8.3/mods-available/fileinfo.ini with new version

Creating config file /etc/php/8.3/mods-available/ffi.ini with new version

Creating config file /etc/php/8.3/mods-available/ftp.ini with new version

Creating config file /etc/php/8.3/mods-available/gettext.ini with new version

Creating config file /etc/php/8.3/mods-available/iconv.ini with new version

Creating config file /etc/php/8.3/mods-available/pdo.ini with new version
...
Creating config file /etc/php/8.3/mods-available/gd.ini with new version
Setting up php (2:8.3+94+ubuntu22.04.1+deb.sury.org+2) ...
Setting up php-gd (2:8.3+94+ubuntu22.04.1+deb.sury.org+2) ...
Processing triggers for ufw (0.36.1-4ubuntu0.1) ...
Processing triggers for man-db (2.10.2-1) ...
Processing triggers for libc-bin (2.35-0ubuntu3.7) ...
Processing triggers for php8.3-cli (8.3.7-2+ubuntu22.04.1+deb.sury.org+1) ...
Processing triggers for libapache2-mod-php8.3 (8.3.7-2+ubuntu22.04.1+deb.sury.org+1) ...
NEEDRESTART-VER: 3.5
Considering dependency setenvif for ssl:
Module setenvif already enabled
Considering dependency mime for ssl:
Module mime already enabled
Considering dependency socache_shmcb for ssl:
Enabling module socache_shmcb.
Enabling module ssl.
See /usr/share/doc/apache2/README.Debian.gz on how to configure SSL and create self-signed certificates.
To activate the new configuration, you need to run:
  systemctl restart apache2
Enabling site default-ssl.
To activate the new configuration, you need to run:
  systemctl reload apache2
Cloud-init v. 24.1.3-0ubuntu1~22.04.1 finished at Fri, 31 May 2024 08:39:35 +0000. Datasource DataSourceLXD.  Up 67.52 seconds

Tamén no log /var/log/cloud-init.log podemos atopar informacións sobre as actuacións feitas por cloud-init:

# less /var/log/cloud-init.log 
...
2024-05-31 08:38:42,058 - distros[DEBUG]: Adding user magasix
2024-05-31 08:38:42,059 - subp.py[DEBUG]: Running hidden command to protect sensitive input/output logstring: ['useradd', 'magasix', '--groups', 'sudo', '--password', 'REDACTED', 
'--shell', '/bin/bash', '-m']
2024-05-31 08:38:42,143 - util.py[DEBUG]: Reading from /etc/sudoers (quiet=False)
2024-05-31 08:38:42,144 - util.py[DEBUG]: Read 1671 bytes from /etc/sudoers
2024-05-31 08:38:42,145 - util.py[DEBUG]: Writing to /etc/sudoers.d/90-cloud-init-users - wb: [440] 143 bytes
2024-05-31 08:38:42,146 - util.py[DEBUG]: Reading from /etc/ssh/sshd_config (quiet=False)
2024-05-31 08:38:42,147 - util.py[DEBUG]: Read 3254 bytes from /etc/ssh/sshd_config
2024-05-31 08:38:42,148 - util.py[DEBUG]: Changing the ownership of /home/magasix/.ssh to 1000:1000
2024-05-31 08:38:42,148 - util.py[DEBUG]: Writing to /home/magasix/.ssh/authorized_keys - wb: [600] 0 bytes
2024-05-31 08:38:42,149 - util.py[DEBUG]: Changing the ownership of /home/magasix/.ssh/authorized_keys to 1000:1000
2024-05-31 08:38:42,149 - util.py[DEBUG]: Reading from /home/magasix/.ssh/authorized_keys (quiet=False)
2024-05-31 08:38:42,149 - util.py[DEBUG]: Read 0 bytes from /home/magasix/.ssh/authorized_keys
2024-05-31 08:38:42,149 - util.py[DEBUG]: Writing to /home/magasix/.ssh/authorized_keys - wb: [600] 759 bytes
2024-05-31 08:38:42,150 - handlers.py[DEBUG]: finish: init-network/config-users_groups: SUCCESS: config-users_groups ran successfully
...

Cloud-init proporciona un resumo da execución:

# cloud-init status
status: done
# cloud-init status --long
status: done
extended_status: degraded done
boot_status_code: enabled-by-generator
last_update: Thu, 01 Jan 1970 00:01:11 +0000
detail: DataSourceNoCloud [seed=/var/lib/cloud/seed/nocloud-net]
errors: []
recoverable_errors:
DEPRECATED:
    - Deprecated cloud-config provided: users.0.ssh-authorized-keys:  Deprecated in version 18.3. Use **ssh_authorized_keys** instead.

Escenario 2: cloud-config para despregue masivo de contedores cun script de xestión

O obxectivo deste é ver como xuntando ó visto ata o de agora podemos crear un script de xestión dun escenario con varios contedores (crear, arrincar, parar e borrar).

O noso obxectivo será montar un sistema con tres servidores coas seguintes características:

  • Nos servidores hai un usuario administrador.
  • Está habilitado o acceso por ssh mediante contrasinal.
  • Os servidores están configurados correctamente para poder saír a Internet.
  • Os servidores están configurados para usar o servidor apt-cacher-ng.
  • Os servidores corren Apache+php.

Preparación dos equipos do escenario

Tómase como punto de partida o estado do equipo apt-cacher-ng ó remate do escenario anterior. Non hai que crear ningún contedor xa que o obxectivo do escenario é a súa creación e configuración.

NOTA. Esta práctica hai que facela usando contedores xa que non funciona nas imaxes Ubuntu usadas en Virtualbox.

Script xestión escenario

NOTAS: o script básico e as plantillas poden descargarse:

Abordaremos o problema centrándonos en primeiro lugar na creación e configuración automática dos contedores server01, server02 e server03 xa que constitúe a parte fundamental do problema; para despois, ampliar as funcionalidades do script.

Cun editor de texto creamos o noso script e comezamos definindo unhas variables que permitirán adaptar o script rápidamente a outras redes:

#!/bin/bash
REDE=192.0.2.3
MS=255.255.255.0
GW=192.0.2.1
<(pre>

A continuación temos que crear un contedor para server01, asignarlle os arquivos config.yml e network.yml personalizados e arrincalo. Cun bucle for repetimos estas accións tantas veces como servidores desexemos. Pero, cómo podemos facer para ter un config.yml personalizado para cada server?.

A forma de poder asignar un config.yml personalizado é crear unha plantilla sobre a que sacar unha copia para personalizada. 

A modo de exemplo a miña plantilla chámase config_PLANTILLA.yml e o seu contido é:

<pre>
#cloud-config
# Configurar /etc/hostname e /etc/hosts
hostname: NOMBRE
fqdn: NOMBRE.platega.example
manage_etc_hosts: true
# Usuario
users:
  - default
  - name: magasix
    lock_passwd: false
    passwd: $y$j9T$ww80Jq/hcuhChau8w3Poe0$AuTOsqM0BL5Q3ltgrBaSGqLANZofUcOJuAMw3rdXNn6
#    ssh-authorized-keys:
#      - clave pública asociada a la clave privada para acceder por SSH
    sudo: ['ALL=(ALL) NOPASSWD:ALL']
    groups: sudo
    shell: /bin/bash
system_info:
  default_user:
    name: ubuntu
    gecos: Usuario por defecto
    plain_text_passwd: abc123.
    lock_passwd: false
# Habilitar PasswordAuthentication
#ssh_pwauth: True
# Configurar caché de paquetes para acelerar instalación
write_files:
  - path: /etc/apt/apt.conf.d/01apt-cacher-ng
    content: |
      Acquire::http { Proxy "http://192.0.2.20:3142"; }
# Conservar repositorios e instalar paquetes
apt:
  preserve_sources_list: true
# Actualizar sistema
package_upgrade: true
packages:
  - net-tools
  - apache2
  - php
  - php-cli
  - php-common
  - libapache2-mod-php
  - php-gd
  - php-curl
  - php-mbstring
  - php-xmlrpc
  - php-soap 
  - php-xml
  - php-intl
  - php-mysql
  - php-zip
  - mysql-client
  - bash-completion
  - openssh-server
  - sudo
  - bash
# Ejecutar comandos en el primer arranque
runcmd:
  - sed -i "s%#PermitRootLogin prohibit-password%PermitRootLogin no%g" /etc/ssh/sshd_config
 - sed -i "s%#PasswordAuthentication yes%PasswordAuthentication yes%g" /etc/ssh/sshd_config
  - sed -i "3iUseDNS no" /etc/ssh/sshd_config
  - a2enmod ssl
  - a2ensite default-ssl.conf
  - echo '<?php phpinfo(); ?>' > /var/www/html/info.php
  - echo '<?php echo "<html><head><title>Sitio web en ${_SERVER["SERVER_ADDR"]}</title></head><body><h1>Mi Sitio Web</h1>Estás en ${_SERVER["SERVER_ADDR"]}</body></html>";?>'  > /var/www/html/index.php
  - rm /var/www/html/index.html
  - systemctl restart sshd
  - systemctl restart apache2
# Zona horaria y locale
timezone: Europe/Madrid
locale: es_ES.UTF-8
# reinicio al acabar
#power_state:
#  mode: reboot

Coa configuración de rede faise o mesmo: unha plantilla de nome network_PLANTILLA.yml:

#cloud-config
version: 1
config:
  - type: physical
    name: eth0
    subnets:
      - type: static
        ipv4: true
        address: XXXX
        netmask: YYYY
        gateway: ZZZZ
        control: auto
  - type: nameserver
    address:
      - 8.8.8.8
      - 8.8.4.4

Fixarse en que o que está en amarelo usarémolo para facer sustitucións e o que está en negriña correspóndese á configuración desexada (usuario, apt-cacher-ng, acceso ssh por contrasinal).

Voltamos ó noso script e engadimos:

#!/bin/bash
REDE=192.0.2.3
MS=255.255.255.0
GW=192.0.2.1
for j in {1..3}
do
     # creamos contedor sen arricar
     incus init images:ubuntu/22.04/cloud server0$j --profile WAN
     # personalizar a configuración do contedor
     cp config_PLANTILLA.yml config.yml
     cp network_PLANTILLA.yml network.yml
     sed -i "s/NOMBRE/server0$j/g" config.yml
     sed -i "s/XXXX/$REDE$j/g" network.yml
     sed -i "s/YYYY/$MS/g" network.yml
     sed -i "s/ZZZZ/$GW/g" network.yml
     incus config set server0$j user.user-data -< config.yml
     incus config set server0$j user.network-config -< network.yml
     incus start server0$j 
     rm config.yml network.yml
done

Fixarse que na primeira execución do bucle:

  • Usamos un Ubuntu Jammy Jellyfish (22.04) para crear un contedor de nome server01 e profile WAN sen arrincalo (incus init). Indicar o alias ou imaxe que queirades usar.
  • Creamos un arquivo config.yml a partir da plantilla e procedemos a facer sustitucións:
  • hostname: NOMBRE --> hostname: server01
  • fqdn: NOMBRE.platega.example --> fqdn: server01.platega.example
  • Creamos un arquivo network.yml a partir da plantilla e procedemos a facer sustitucións:
  • XXXX --> 192.0.2.31
  • YYYY --> 255.255.255.0
  • ZZZZ --> 192.0.2.1
  • Asignamos o config.yml como user.user-data do contedor.
  • Asignamos o netwok.yml como user.network-config do contedor.
  • Arrincamos o contedor.

Grazas ó bucle repetimos as accións e temos así os tres servidores personalizados. Ollo co explicado no punto 4.2 Cloud-config en relación ó servidor dhcp; xa que no caso de non habelo, habería que poñer a propiedade user.network_mode=link-local do contedor para indicar que a configuración rede farase a man e non por dhcp e ademais engadir a sección bootcmd en config.yml

Procedemos a asignarlle permisos de execución ó script e a lanzalo:

$ chmod 755 escenario_8C.sh 
$ ./escenario_8C.sh 
$ incus ls -c n,4,s,l,P,m 
+---------------+-------------------+---------+----------------------+----------+--------------+
|     NAME      |       IPV4        |  STATE  |     LAST USED AT     | PROFILES | MEMORY USAGE |
+---------------+-------------------+---------+----------------------+----------+--------------+
| apt-cacher-ng | 192.0.2.20 (eth0) | RUNNING | 2026/03/01 12:01 CET | WAN      | 79.78MiB     |
+---------------+-------------------+---------+----------------------+----------+--------------+
| server01      | 192.0.2.31 (eth0) | RUNNING | 2026/03/01 13:30 CET | WAN      | 72.16MiB     |
+---------------+-------------------+---------+----------------------+----------+--------------+
| server02      | 192.0.2.32 (eth0) | RUNNING | 2026/03/01 13:30 CET | WAN      | 72.41MiB     |
+---------------+-------------------+---------+----------------------+----------+--------------+
| server03      | 192.0.2.33 (eth0) | RUNNING | 2026/03/01 13:30 CET | WAN      | 72.36MiB     |
+---------------+-------------------+---------+----------------------+----------+--------------+

Vemos como están arrincados e totalmete configurados os tres servidores ó cabo duns minutos.

$ incus exec server01 -- cloud-init status
status: done
$ incus exec server02 -- cloud-init status
status: done
$ incus exec server03 -- cloud-init status
status: done

Script de xestión mellorado

NOTAS: o script mellorado pode descargarse:

  • [http:// PENDIENTE script mellorado PENDIENTE]

Xa temos o núcleo do script creado e podemos proceder a melloralo creando un menú con opcións de creación, inicio, parada e destrucción dos contedores:

#!/bin/bash
REDE=192.0.2.3
MS=255.255.255.0
GW=192.0.2.1
#incus project switch APT-CACHER
clear
echo "----- Escenario 8C -----"
echo "Seleccionar a operación:"
echo "1. Crear escenario"
echo "2. Parar contedores escenario"
echo "3. Arrincar contedores escenario"
echo "4. Borrar escenario"
echo "------"
read opcion
case $opcion in
1) echo "Crear escenario"
   for j in {1..3}
   do
     # creamos contedor sen arricar
     incus init images:ubuntu/22.04/cloud server0$j --profile WAN
     # personalizar a configuración do contedor
     cp config_PLANTILLA.yml config.yml
     cp network_PLANTILLA.yml network.yml
     sed -i "s/HOSTNAME/server0$j/g" config.yml
     sed -i "s/FQDN/server0$j.platega.example/g" config.yml
     sed -i "s/XXXX/$REDE$j/g" network.yml
     sed -i "s/YYYY/$MS/g" network.yml
     sed -i "s/ZZZZ/$GW/g" network.yml
     incus config set server0$j user.user-data -< config.yml
     incus config set server0$j user.network-config -< network.yml
     incus start server0$j 
   done
   sleep 3
   incus ls -c n,4,s,l,P,m
   ;;
2) echo "Parar contedores escenario"
   for j in {1..3}
   do
     incus stop -f server0$j
   done
   echo " "
    ;;
3) echo "Arrincar containers escenario"
   for j in {1..3}
   do
     incus start server0$j
   done
   echo " "
   ;;
4) echo "Borrar escenario"
   for j in {1..3}
   do
     incus delete -f server0$j
   done
   echo " "
   ;;
*) echo "opción incorrecta"
   ;;
esac

Executamos o script e aparece o menú para xestionalo:

$ ./escenario_8C_con_menu.sh 
----- Escenario 8C -----
Seleccionar a operación:
1. Crear escenario
2. Parar contedores escenario
3. Arrincar contedores escenario
4. Borrar escenario
------
1
Crear escenario
Creando server01
Creando server02
Creando server03
+---------------+-------------------+---------+----------------------+----------+--------------+
|     NAME      |       IPV4        |  STATE  |     LAST USED AT     | PROFILES | MEMORY USAGE |
+---------------+-------------------+---------+----------------------+----------+--------------+
| apt-cacher-ng | 192.0.2.20 (eth0) | RUNNING | 2026/03/01 12:01 CET | WAN      | 79.78MiB     |
+---------------+-------------------+---------+----------------------+----------+--------------+
| server01      | 192.0.2.31 (eth0) | RUNNING | 2026/03/01 13:41 CET | WAN      | 41.63MiB     |
+---------------+-------------------+---------+----------------------+----------+--------------+
| server02      | 192.0.2.32 (eth0) | RUNNING | 2026/03/01 13:41 CET | WAN      | 41.69MiB     |
+---------------+-------------------+---------+----------------------+----------+--------------+
| server03      | 192.0.2.33 (eth0) | RUNNING | 2026/03/01 13:41 CET | WAN      | 42.69MiB     |
+---------------+-------------------+---------+----------------------+----------+--------------+

Referencias