Does v8.6 anaconda use more memory?

Everyone,

Since Rocky 8.6 was released, I can no longer build a VM instance with only 2 GB of RAM assigned. It works with 4 GB now (3 GB might be sufficient also.) Rocky 8.5 anaconda worked fine with a 2 GB RAM partition.

Here’s the anaconda screenshot where it craps out:

The line containing “/lib/dracut-lib.sh: line 465: echo: write error: No space left on device” is indicative of what’s happening: There’s not enough space on the ramdisk to unpack all the components. I’ve already found a workaround (increase VM memory assignment) so it’s not an issue for me, but does anyone with more detailed knowledge of anaconda/dracut internals know what changed, from 8.5 to 8.6 – Where’s the bloat?

Hi,

At what point does it fail? During boot prior to getting to the graphical installer screen? Or once installation has completed or somewhere else? What ISO? Minimal or DVD iso? x86_64?

I’ve just tried from the 8.6 minimal install, created a KVM VM with 1cpu and 1gb of ram, the installer booted perfectly fine, and the installation process also completed successfully. The machine also restarted successfully after install. The install type is minimal server.

Did you check/verify the ISO download to make sure the checksums matched? Just to rule out a failed download which could cause weird issues during installation etc.

I am using Kickstart with PXE Linux, so no ISO file. The install stops at the last line of the screenshot, “Detaching DM devices.” This is right after the “vmlinuz” and “initrd” files are downloaded from the Cogent Rocky repo. No graphical installer, I stay with text throughout.

Again, I found a workaround – increasing the RAM assigned to the VM (a KVM instance) from 2 to 4 GB. I am just curious which components need more RAM in 8.6 vs. 8.5.

Could you copy/paste the kickstart file here as it might help narrow it down.

Here’s the anaconda-ks.cfg file from the system AFTER successful build with 4 GB RAM allocation (sanitized, of course):

#version=DEVEL
# System authorization information
auth --useshadow --passalgo=sha512 --kickstart
# Install OS instead of upgrade
install
# Use network installation
url --url="http://mirror.cc.columbia.edu/pub/linux/centos/7/os/x86_64"
repo --name="EPEL" --mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-7&arch=x86_64
# Use text mode install
text
# Firewall configuration
firewall --enabled --service=ssh
firstboot --disable
ignoredisk --only-use=vda
# Keyboard layouts
# old format: keyboard us
# new format:
keyboard --vckeymap=us --xlayouts=''
# System language
lang en_US.UTF-8

# Network information
network  --bootproto=dhcp --device=link --hostname=lb-b.example.com --activate
# Reboot after installation
reboot
# Root password
rootpw --iscrypted $*************************
# SELinux configuration
selinux --enforcing
# System services
services --disabled="gpm,sendmail,cups,pcmcia,isdn,rawdevices,hpoj,bluetooth,openibd,avahi-daemon,avahi-dnsconfd,hidd,hplip,pcscd" --enabled="chronyd"
# Do not configure the X Window System
skipx
# System timezone
timezone America/New_York --isUtc --ntpservers=amaranth.example.com,triticale.example.com
# System bootloader configuration
bootloader --append="nofb quiet splash=quiet crashkernel=auto" --location=mbr --boot-drive=vda
# Clear the Master Boot Record
zerombr
# Partition clearing information
clearpart --all --initlabel
# Disk partitioning information
part /boot --asprimary --fstype="xfs" --size=1024
part / --asprimary --fstype="xfs" --size=9215

%post --nochroot
exec < /dev/tty3 > /dev/tty3
#changing to VT 3 so that we can see whats going on....
/usr/bin/chvt 3
(
cp -va /etc/resolv.conf /mnt/sysimage/etc/resolv.conf
/usr/bin/chvt 1
) 2>&1 | tee /mnt/sysimage/root/install.postnochroot.log
%end

%post
logger "Starting anaconda lb-b.example.com postinstall"
exec < /dev/tty3 > /dev/tty3
#changing to VT 3 so that we can see whats going on....
/usr/bin/chvt 3
(
#update local time
echo "updating system time"
/usr/sbin/ntpdate -sub time.example.com
/usr/sbin/hwclock --systohc


# update all the base packages from the updates repository
yum -t -y -e 0 update


echo "Configuring puppet"
cat > /etc/puppet/puppet.conf << EOF

[main]
vardir = /var/lib/puppet
logdir = /var/log/puppet
rundir = /var/run/puppet
ssldir = \$vardir/ssl

[agent]
pluginsync      = true
report          = true
ignoreschedules = true
daemon          = false
ca_server       = foreman.example.com
certname        = lb-b.example.com
environment     = development
server          = foreman.example.com

EOF

# Setup puppet to run on system reboot
/sbin/chkconfig --level 345 puppet on

/usr/bin/puppet agent --config /etc/puppet/puppet.conf -o --tags no_such_tag --server foreman.example.com --no-daemonize


sync

# Inform the build system that we are done.
echo "Informing Foreman that we are built"
wget -q -O /dev/null --no-check-certificate http://foreman.example.com:80/unattended/built?token=36f1cb35-705f-4a66-97fd-f028db12da77
# Sleeping an hour for debug
) 2>&1 | tee /root/install.post.log
exit 0

%end

%packages
@Core
bind-utils
chrony
dhclient
emacs
epel-release
kexec-tools
nano
net-tools
ntp
puppet
sysstat
wget
yum

%end

%addon com_redhat_kdump --enable --reserve-mb='auto'

%end

Hope this helps.

Are you sure that is the correct kickstart? The URL seems to show CentOS7 as well as EPEL7 repositories. I would expect to see Rocky repos being listed.

That is odd. The EPEL link is CentOS 7 – not good when those mirrors go dark in 2024.

Anyway, this KS file was generated by the standard Foreman v2.5 Kickstart Default template, which uses ruby ERB tags:

<%#
kind: provision
name: Kickstart default
model: ProvisioningTemplate
oses:
- AlmaLinux
- CentOS
- Fedora
- RedHat
- Rocky
%>
<%#
This template accepts the following parameters:
- lang: string (default="en_US.UTF-8")
- selinux-mode: string (default="enforcing")
- keyboard: string (default="us")
- time-zone: string (default="UTC")
- http-proxy: string (default="")
- http-proxy-port: string (default="")
- force-puppet: boolean (default=false)
- enable-epel: boolean (default=true)
- enable-puppetlabs-repo: boolean (default=false)
- enable-puppetlabs-puppet5-repo: boolean (default=false)
- enable-puppetlabs-puppet6-repo: boolean (default=false)
- salt_master: string (default=undef)
- ntp-server: string (default=undef)
- bootloader-append: string (default="nofb quiet splash=quiet")
- disable-firewall: boolean (default=false)
- package_upgrade: boolean (default=true)
- disable-uek: boolean (default=false)
- use-ntp: boolean (default depends on OS release)
- fips_enabled: boolean (default=false)
- encrypt_grub: boolean (default=false)

Reference links:
https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/installation_guide/s1-kickstart2-options
https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/installation_guide/sect-kickstart-syntax
https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/performing_an_advanced_rhel_installation/kickstart-commands-and-options-reference_installing-rhel-as-an-experienced-user
%>

# This kickstart file was rendered from the Foreman provisioning template "<%= @template_name %>".

<%
  rhel_compatible = @host.operatingsystem.family == 'Redhat' && @host.operatingsystem.name != 'Fedora'
  is_fedora = @host.operatingsystem.name == 'Fedora'
  os_major = @host.operatingsystem.major.to_i
  os_minor = @host.operatingsystem.minor.to_i
  realm_compatible = (@host.operatingsystem.name == 'Fedora' && os_major >= 20) || (rhel_compatible && os_major >= 7)
  # safemode renderer does not support unary negation
  proxy_uri = host_param('http-proxy') ? "http://#{host_param('http-proxy')}:#{host_param('http-proxy-port')}" : nil
  proxy_string = proxy_uri ? " --proxy=#{proxy_uri}" : ''
  puppet_enabled = host_puppet_server.present? || host_param_true?('force-puppet')
  salt_enabled = host_param('salt_master') ? true : false
  chef_enabled = @host.respond_to?(:chef_proxy) && @host.chef_proxy
  section_end = (rhel_compatible && os_major <= 5) ? '' : '%end'
  use_ntp = host_param_true?('use-ntp', (is_fedora && os_major < 16) || (rhel_compatible && os_major <= 7))
  iface = @host.provision_interface
  appstream_present = false
-%>

<% if (is_fedora && os_major < 29) || (rhel_compatible && os_major <= 7) -%>
install
<% end -%>
<%
if host_param('kickstart_liveimg')
  img_name = host_param('kickstart_liveimg')
  liveimg_url = if host_param('kt_activation_keys')
    repository_url(img_name, 'isos')
  else
    if img_name.match(%r|^([\w\-\+]+)://|)
      img_name
    else
      "#{medium_uri}/#{img_name}"
    end
  end
%>
liveimg --url=<%= liveimg_url %> <%= proxy_string %>
<% else %>
<%= @mediapath %><%= proxy_string %>
<% @additional_media.each do |medium| -%>
<% if rhel_compatible && @host.operatingsystem.name.downcase.include?("centos") && os_major >= 8 && medium[:url] && medium[:url].include?("AppStream") -%>
<% appstream_present = true -%>
# renamed from "<%= medium[:url] %>" for CentOS Anaconda to work
repo --name AppStream --baseurl <%= medium[:url] %>
<% else -%>
repo --name <%= medium[:name] %> --baseurl <%= medium[:url] %> <%= medium[:install] ? ' --install' : '' %><%= proxy_string %>
<% end -%>
<% end -%>
<% if rhel_compatible && @host.operatingsystem.name.downcase.include?("centos") && os_major >= 8 && medium_uri && medium_uri.to_s.include?("BaseOS") && !appstream_present -%>
# repository added using BaseOS to AppStream string replacement
repo --name AppStream --baseurl <%= medium_uri.to_s.gsub("BaseOS", "AppStream") %>
<% end -%>
<%= snippet_if_exists(template_name + " custom repositories") %>
<% end %>
lang <%= host_param('lang') || 'en_US.UTF-8' %>
selinux --<%= host_param('selinux-mode') || host_param('selinux') || 'enforcing' %>
keyboard <%= host_param('keyboard') || 'us' %>
skipx

<%
  network_options = []
  nameservers = []
  subnet4 = iface.subnet
  subnet6 = iface.subnet6

  # device and hostname
  if iface.bond? && rhel_compatible && os_major >= 6
    network_options.push("--device=#{iface.identifier}")
  else
    network_options.push("--device=#{iface.mac || iface.identifier}")
  end
  network_options.push("--hostname #{@host.name}")

  # single stack
  if subnet4 && !subnet6
    network_options.push("--noipv6")
  elsif !subnet4 && subnet6
    network_options.push("--noipv4")
  end

  # dual stack MTU check
  raise("IPv4 and IPv6 subnets have different MTU") if subnet4 && subnet6 && subnet4.mtu.present? && subnet6.mtu.present? && subnet4.mtu != subnet6.mtu

  # IPv4
  if (subnet4 && !subnet4.dhcp_boot_mode?) || @static
    network_options.push("--bootproto static")
    network_options.push("--ip=#{iface.ip}")
    network_options.push("--netmask=#{subnet4.mask}")
    network_options.push("--gateway=#{subnet4.gateway}")
  elsif subnet4 && subnet4.dhcp_boot_mode?
    network_options.push("--bootproto dhcp")
  end
  if subnet4
    nameservers.concat(subnet4.dns_servers)
    network_options.push("--mtu=#{subnet4.mtu}") if subnet4.mtu.present?
  end

  # IPv6
  if rhel_compatible && os_major >= 6
    if (subnet6 && !subnet6.dhcp_boot_mode?) || @static6
      network_options.push("--ipv6=#{iface.ip6}/#{subnet6.cidr}")
      network_options.push("--ipv6gateway=#{subnet6.gateway}")
    elsif subnet6 && subnet6.dhcp_boot_mode?
      if host_param_true?('use-slaac')
        network_options.push("--ipv6 auto")
      else
        network_options.push("--ipv6 dhcp")
      end
    end
    if subnet6
      nameservers.concat(subnet6.dns_servers)
      network_options.push("--mtu=#{subnet6.mtu}") if subnet6.mtu.present?
    end
  end

  # bond
  if iface.bond? && rhel_compatible && os_major >= 6
    bond_slaves = iface.attached_devices_identifiers.join(',')
    network_options.push("--bondslaves=#{bond_slaves}")
    network_options.push("--bondopts=mode=#{iface.mode},#{iface.bond_options.tr(' ', ',')}")
  end

  # VLAN (only on physical is recognized)
  if iface.virtual? && iface.tag.present? && iface.attached_to.present?
    if rhel_compatible && os_major == 6
      network_options.push("--vlanid=#{iface.tag}")
    else
      network_options.push("--interfacename=vlan#{iface.tag}")
    end
  end

  # DNS
  if nameservers.size > 0
    network_options.push("--nameserver=#{nameservers.join(',')}")
  else
    network_options.push("--nodns")
  end
-%>
network <%= network_options.join(' ') %>

rootpw --iscrypted <%= root_pass %>
<% if host_param_true?('disable-firewall') -%>
firewall --disable
<% else -%>
firewall --<%= os_major >= 6 ? 'service=' : '' %>ssh
<% end -%>
<% if (is_fedora && os_major >= 28) || (rhel_compatible && os_major > 7) -%>
authselect --useshadow --passalgo=<%= @host.operatingsystem.password_hash.downcase || 'sha256' %> --kickstart
<% else -%>
authconfig --useshadow --passalgo=<%= @host.operatingsystem.password_hash.downcase || 'sha256' %> --kickstart
<% end -%>
timezone --utc <%= host_param('time-zone') || 'UTC' %> <%= host_param('ntp-server') ? "--ntpservers #{host_param('ntp-server')}" : '' %>

<% if rhel_compatible -%>
services --disabled gpm,sendmail,cups,pcmcia,isdn,rawdevices,hpoj,bluetooth,openibd,avahi-daemon,avahi-dnsconfd,hidd,hplip,pcscd
<% end -%>

<% if realm_compatible && host_enc['parameters']['realm'] && @host.realm && @host.realm.realm_type == 'Active Directory' -%>
# One-time password will be requested at install time. Otherwise, $HOST[OTP] is used as a placeholder value.
realm join --one-time-password='<%= @host.otp || "$HOST[OTP]" %>' <%= @host.realm %>
<% end -%>

<% if @host.operatingsystem.name == 'OracleLinux' && os_major == 7 && os_minor < 5 -%>
repo --name="Server-Mysql"
<% end -%>

<% if @host.operatingsystem.name == 'Fedora' && os_major <= 16 -%>
# Bootloader exception for Fedora 16:
bootloader --append="<%= host_param('bootloader-append') || 'nofb quiet splash=quiet' %> <%= ks_console %>" <%= grub_pass %>
part biosboot --fstype=biosboot --size=1
<% else -%>
bootloader --location=mbr --append="<%= host_param('bootloader-append') || 'nofb quiet splash=quiet' %>" <%= grub_pass %>
<% if os_major == 5 -%>
key --skip
<% end -%>
<% end -%>

<% if @dynamic -%>
%include /tmp/diskpart.cfg
<% else -%>
<%= @host.diskLayout %>
<% end -%>

text
reboot

%packages
<%= snippet_if_exists(template_name + " custom packages") %>
yum
dhclient
<% if use_ntp -%>
ntp
-chrony
<% else -%>
chrony
-ntp
<% end -%>
wget
@Core
<% if os_major >= 6 -%>
redhat-lsb-core
<% end -%>
<% if host_param_true?('fips_enabled') -%>
<%=   snippet 'fips_packages' %>
<% end -%>
<%= section_end %>

<% if @dynamic -%>
%pre --log=/tmp/install.pre.dynamic.log
<%= snippet_if_exists(template_name + " custom pre") %>
<%= @host.diskLayout %>
<%= section_end %>
<% end -%>

%post --nochroot --log=/mnt/sysimage/root/install.postnochroot.log
/usr/bin/chvt 3
echo "Changed to TTY3 for post installation..."
<%= snippet_if_exists(template_name + " custom postnochroot") -%>

<% if host_param_false?('no-resolv-override') -%>
cp -va /etc/resolv.conf /mnt/sysimage/etc/resolv.conf
<% end -%>
<%= section_end %>

<%#
Main post script, if it fails the last post is still executed.
%>
%post --log=/root/install.post.log
logger "Starting anaconda <%= @host %> postinstall"
<%= snippet 'kickstart_networking_setup' %>

<%= snippet 'ntp' %>

<%= snippet 'yum_proxy' %>

<% if rhel_compatible && !host_param_false?('enable-epel') -%>
<%= snippet 'epel' -%>
<% end -%>

<%= snippet 'redhat_register' %>

<% if host_enc['parameters']['realm'] && @host.realm && (@host.realm.realm_type == 'FreeIPA' || @host.realm.realm_type == 'Red Hat Identity Management') -%>
<%= snippet 'freeipa_register' %>
<% end -%>

<% unless host_param_false?('package_upgrade') -%>
# update all the base packages from the updates repository
if [ -f /usr/bin/dnf ]; then
  dnf -y update
else
  yum -t -y update
fi
<% end -%>

<%= snippet('remote_execution_ssh_keys') %>

<%= snippet "blacklist_kernel_modules" %>

<% if chef_enabled %>
<%= snippet 'chef_client' %>
<% end -%>

<% if puppet_enabled %>
<% if host_param_true?('enable-puppetlabs-repo') || host_param_true?('enable-puppetlabs-puppet6-repo')|| host_param_true?('enable-puppetlabs-puppet5-repo') -%>
<%= snippet 'puppetlabs_repo' %>
<% end -%>
<%= snippet 'puppet_setup' %>
<% end -%>

<% if salt_enabled %>
<%= snippet 'saltstack_setup' %>
<% end -%>

<% if @host.operatingsystem.name == 'OracleLinux' && host_param_true?('disable-uek') -%>
# Uninstall the Oracle Unbreakable Kernel packages
yum -t -y remove kernel-uek*
sed -e 's/DEFAULTKERNEL=kernel-uek/DEFAULTKERNEL=kernel/g' -i /etc/sysconfig/kernel
<% end -%>

<%= snippet('ansible_provisioning_callback') %>

<%= snippet 'efibootmgr_netboot' %>

<%= snippet 'insights' -%>
touch /tmp/foreman_built
<%= section_end %>

# copy %pre log files into chroot
%post --nochroot
cp -vf /tmp/*.pre.*.log /mnt/sysimage/root/
<%= section_end %>

%post --log=/root/install.post.custom.log
# Custom post snippet generated by "<%= template_name + " custom post" %>"
<%= snippet_if_exists(template_name + " custom post") %>
<%= section_end %>

<%#
The last post section halts Anaconda to prevent endless loop in case HTTP request fails
%>
<% if (is_fedora && os_major < 20) || (rhel_compatible && os_major < 7) -%>
%post
<% else -%>
%post --erroronfail
<% end -%>

<%= snippet 'eject_cdrom' -%>

if test -f /tmp/foreman_built; then
  echo "calling home: build is done!"
  <%= indent(2, skip1: true) { snippet('built', :variables => { :endpoint => 'built', :method => 'POST', :body_file => '/root/install.post.log' }) } -%>
else
  echo "calling home: build failed!"
  <%= indent(2, skip1: true) { snippet('built', :variables => { :endpoint => 'failed', :method => 'POST', :body_file => '/root/install.post.log' }) } -%>
fi

echo "Changing back to TTY1..."
/usr/bin/chvt 1
sync
<%= section_end %>

I don’t know Foreman, but these are clearly for installing CentOS 7, not for Rocky 8:

Besides, that is just base repo of CentOS 7 and EPEL (for EL7) – at this point it would make sense to have the updates repo too. I would expect the installation to crash regardless of amount of RAM, if it is booted with Rocky 8.6’s kernel+initramfs, because that installer does not expect EL7 content.

Right you are – this IS from a previous version of the host, running CentOS 7 (I am rebuilding it on Rocky 8 and need the old one around until the final cut-over.) My mistake.

Here is the anaconda-ks.cfg file from a recently provisioned Rocky 8.6 host, with 4 GB RAM assigned:

#version=RHEL8
# Reboot after installation
reboot
# Use text mode install
text

repo --name="appstream" --baseurl=http://dl.rockylinux.org/$contentdir/$releasever/AppStream/$basearch/os/
repo --name="AppStream" --baseurl=https://mirror.cogentco.com/pub/linux/rocky/8/AppStream/x86_64/kickstart

%post --nochroot --logfile=/mnt/sysimage/root/install.postnochroot.log
/usr/bin/chvt 3
echo "Changed to TTY3 for post installation..."

%end

%post --logfile=/root/install.post.log
logger "Starting anaconda foremantest1.example.com postinstall"


# ens13 interface
real=`grep -l aa:00:00:64:7e:c1 /sys/class/net/*/{bonding_slave/perm_hwaddr,address} 2>/dev/null | awk -F '/' '// {print $5}' | head -1`
sanitized_real=`echo $real | sed s/:/_/`

cat << EOF > /etc/sysconfig/network-scripts/ifcfg-$sanitized_real
BOOTPROTO="none"
IPADDR="192.168.1.231"
NETMASK="255.255.255.0"
GATEWAY="192.168.1.1"
DOMAIN="example.com"
DEVICE=$real
HWADDR="aa:00:00:64:7e:c1"
ONBOOT=yes
PEERDNS=yes
PEERROUTES=yes
DEFROUTE=yes
DNS1="192.168.1.200"
DNS2="192.168.3.10"
MTU=1500
EOF


echo "Updating system time"
systemctl enable --now chronyd
/usr/bin/chronyc -a makestep
/usr/sbin/hwclock --systohc


rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm


# update all the base packages from the updates repository
if [ -f /usr/bin/dnf ]; then
  dnf -y update
else
  yum -t -y update
fi


# SSH keys setup snippet for Remote Execution plugin
#
# Parameters:
#
# remote_execution_ssh_keys: public keys to be put in ~/.ssh/authorized_keys
#
# remote_execution_ssh_user: user for which remote_execution_ssh_keys will be
#                            authorized
#
# remote_execution_create_user: create user if it not already existing
#
# remote_execution_effective_user_method: method to switch from ssh user to
#                                         effective user
#
# This template sets up SSH keys in any host so that as long as your public
# SSH key is in remote_execution_ssh_keys, you can SSH into a host. This
# works in combination with Remote Execution plugin by querying smart proxies
# to build an array.
#
# To use this snippet without the plugin provide the SSH keys as host parameter
# remote_execution_ssh_keys. It expects the same format like the authorized_keys
# file.


rpm -Uvh https://yum.puppet.com/puppet6/puppet6-release-el-8.noarch.rpm

if [ -f /usr/bin/dnf ]; then
  dnf -y install puppet-agent
else
  yum -t -y install puppet-agent
fi

cat > /etc/puppetlabs/puppet/puppet.conf << EOF
[main]

[agent]
pluginsync      = true
report          = true
ca_server       = foreman2.example.com
certname        = foremantest1.example.com
server          = foreman2.example.com
environment     = development

EOF


puppet_unit=puppet
/usr/bin/systemctl list-unit-files | grep -q puppetagent && puppet_unit=puppetagent
/usr/bin/systemctl enable ${puppet_unit}

# export a custom fact called 'is_installer' to allow detection of the installer environment in Puppet modules
export FACTER_is_installer=true
# passing a non-existent tag like "no_such_tag" to the puppet agent only initializes the node
/opt/puppetlabs/bin/puppet agent --config /etc/puppetlabs/puppet/puppet.conf --onetime --tags no_such_tag --server foreman2.example.com --no-daemonize


touch /tmp/foreman_built
%end

%post --nochroot
cp -vf /tmp/*.pre.*.log /mnt/sysimage/root/
%end

%post --logfile=/root/install.post.custom.log
# Custom post snippet generated by "Kickstart default custom post"

%end

%post --erroronfail


if test -f /tmp/foreman_built; then
  echo "calling home: build is done!"
  if [ -x /usr/bin/curl ]; then
    /usr/bin/curl -o /dev/null --noproxy \* -H 'Content-Type: text/plain' --data @/root/install.post.log --silent 'http://foreman2.example.com/unattended/built?token=6a2e27e5-9a0d-4658-8eec-2a085b6336b3'
  elif [ -x /usr/bin/wget ]; then
    /usr/bin/wget -q -O /dev/null --no-proxy --method POST --header 'Content-Type: text/plain' --body-file=/root/install.post.log 'http://foreman2.example.com/unattended/built?token=6a2e27e5-9a0d-4658-8eec-2a085b6336b3'
  else
    wget -q -O /dev/null --header 'Content-Type: text/plain' 'http://foreman2.example.com/unattended/built?token=6a2e27e5-9a0d-4658-8eec-2a085b6336b3'
  fi
else
  echo "calling home: build failed!"
  if [ -x /usr/bin/curl ]; then
    /usr/bin/curl -o /dev/null --noproxy \* -H 'Content-Type: text/plain' --data @/root/install.post.log --silent 'http://foreman2.example.com/unattended/failed?token=6a2e27e5-9a0d-4658-8eec-2a085b6336b3'
  elif [ -x /usr/bin/wget ]; then
    /usr/bin/wget -q -O /dev/null --no-proxy --method POST --header 'Content-Type: text/plain' --body-file=/root/install.post.log 'http://foreman2.example.com/unattended/failed?token=6a2e27e5-9a0d-4658-8eec-2a085b6336b3'
  else
    wget -q -O /dev/null --header 'Content-Type: text/plain' 'http://foreman2.example.com/unattended/failed?token=6a2e27e5-9a0d-4658-8eec-2a085b6336b3'
  fi
fi

echo "Changing back to TTY1..."
/usr/bin/chvt 1
sync
%end

%packages
@Core
chrony
dhclient
kexec-tools
redhat-lsb-core
wget
yum
-ntp

%end

# Keyboard layouts
keyboard --vckeymap=us --xlayouts='us'
# System language
lang en_US.UTF-8

# Firewall configuration
firewall --disabled
# Network information
network  --bootproto=static --device=aa:00:00:64:7e:c1 --gateway=192.168.1.1 --hostname=foremantest1.example.com --ip=192.168.1.231 --mtu=1500 --nameserver=192.168.1.200,192.168.3.10 --netmask=255.255.255.0 --noipv6 --activate

# Use network installation
url --url="https://mirror.cogentco.com/pub/linux/rocky/8/BaseOS/x86_64/kickstart"

# System authorization information
authselect --useshadow --passalgo=sha256 --kickstart
# SELinux configuration
selinux --enforcing

# Do not configure the X Window System
skipx
# System services
services --disabled="gpm,sendmail,cups,pcmcia,isdn,rawdevices,hpoj,bluetooth,openibd,avahi-daemon,avahi-dnsconfd,hidd,hplip,pcscd"

ignoredisk --only-use=vda
# System bootloader configuration
bootloader --append="nofb quiet splash=quiet crashkernel=auto" --location=mbr --boot-drive=vda
# Clear the Master Boot Record
zerombr
# Partition clearing information
clearpart --all --initlabel
# Disk partitioning information
part /boot --fstype="xfs" --size=1024
part / --fstype="xfs" --size=19455

# System timezone
timezone America/New_York --isUtc

# Root password
rootpw --iscrypted $*******************************

%addon com_redhat_kdump --enable --reserve-mb='auto'

%end

This does not explain memory, but is odd – the appstream is twice. Not only that, but one is os and the other is kickstart (and from different servers).
Thing is, the ‘kickstart’ repo contains packages as 8.6 was released and the ‘os’ repo has all that plus all the updates after the release. The use of ‘kickstart’ repos makes sense if you want to install exact same set of packages every time (until next point release shows up). The use of ‘os’ repos installs directly the latest versions of everything, which is most convenient (when release date of current point release is far in the past).

Yeah, that’s because with Rocky 8.4, anaconda could not locate the Appstream repo and would choke on installing certain packages in the “core” group, like “wget” and “redhat-lsb-core”. Then, it would drop into interactive mode and ask if OK to continue. Since I need automated installation, I added the extra Appstream URL (at dl.rockylinux.org) to help “grease the wheels”, so to speak.

Just now, I tried removing the extra Appstream repo and rebuilding. Now, the build completes with no interruption! Nice to know it’s no longer an issue.

BTW, do you know how to capture anaconda logs for later review, outside of the VM that’s running it? Since they are being saved on the init ram disk, they all disappear once the host reboots from it’s new physical disk. The VM is running under the KVM hypervisor. Maybe by redirecting a virtual serial port somewhere?