여기에서는 최소 ISO 이미지를 사용하지만, DVD 이미지(훨씬 더 크고 아마도 너무 큼) 또는 부트 이미지(훨씬 작고 아마도 너무 작음)를 선택할 수도 있습니다. 이 선택은 사용자의 몫입니다. 이는 설치에 필요한 대역폭과 따라서 프로비저닝 시간에 영향을 미칩니다. 다음에서는 기본 선택의 영향과 그 해결 방법에 대해 논의하겠습니다.
또한 가상 머신을 템플릿으로 변환하지 않을 수도 있습니다. 이 경우 Packer를 사용하여 각 새 VM을 배포할 수 있으며, 이는 여전히 꽤 실행 가능한 방법입니다. 0에서 시작하는 설치는 인간의 개입 없이 10분 이내에 완료됩니다.
Packer는 HashiCorp에서 개발한 오픈 소스 가상 머신 이미징 도구로, MPL 2.0 라이선스로 출시되었습니다. Packer를 사용하면 클라우드 및 온프레미스 가상화 환경 모두에서 사전 구성된 운영 체제와 설치된 소프트웨어가 포함된 가상 머신 이미지를 자동화하여 생성할 수 있습니다.
다음 부분은 흥미로우며, 나중에 requirements.sh 스크립트를 제공함으로써 다루겠습니다:
"builders": [
{
"type": "vsphere-iso",
설치가 완료되면 VM이 재부팅됩니다. Packer가 IP 주소를 감지하면(requirements.sh를 실행하는 데 필요한 VMware Tools 덕분에), requirements.sh를 복사하고 실행합니다. 이는 설치 프로세스 이후 VM을 정리(SSH 키 제거, 히스토리 삭제 등)하고 추가 패키지를 설치하는 데 유용한 기능입니다.
이제 CPU_hot_plug를 포함하지 않는 것을 잊지 않을 것입니다. 이제 자동으로 포함됩니다!
디스크, CPU 등을 사용하여 더 멋진 작업을 수행할 수 있습니다. 다른 조정을 하려면 문서를 참조하면 됩니다.
설치를 시작하려면 Rocky Linux의 ISO 이미지가 필요합니다. 다음은 vSphere 콘텐츠 라이브러리에 있는 이미지를 사용하는 예입니다. 물론 ISO를 다른 위치에 저장할 수도 있습니다. vSphere 콘텐츠 라이브러리의 경우, 콘텐츠 라이브러리를 호스트하는 서버에서 ISO 파일의 전체 경로를 얻어야 합니다. 이 예에서는 Synology에서 직접 DSM 탐색기에서 가져옵니다.
위에서 언급한 대로, Anaconda에서 사용할 Kickstart 응답 파일을 제공해야 합니다.
다음은 해당 파일의 예시입니다:
# CD-ROM 설치 미디어 사용
repo --name="AppStream" --baseurl="http://download.rockylinux.org/pub/rocky/8.4/AppStream/x86_64/os/"
cdrom
# 텍스트 설치 사용
text
# 처음 부팅할 때 설정 에이전트를 실행하지 마십시오. firstboot --disabled
eula --agreed
ignoredisk --only-use=sda
# 키보드 레이아웃
keyboard --vckeymap=us --xlayouts='us'
# 시스템 언어
lang en_US.UTF-8
# 네트워크 정보
network --bootproto=static --device=ens192 --gateway=192.168.1.254 --ip=192.168.1.11 --nameserver=192.168.1.254,4.4.4.4 --netmask=255.255.255.0 --onboot=on --ipv6=auto --activate
# 루트 암호
rootpw mysecurepassword
# 시스템 서비스
selinux --permissive
firewall --enabled
services --enabled="NetworkManager,sshd,chronyd"
# 시스템 시간대
timezone Europe/Paris --isUtc
# 시스템 부로더 구성
bootloader --location=mbr --boot-drive=sda
# 파티션 정리 정보
clearpart --all --initlabel --drives=sda
# 디스크 파티션 정보
part /boot --fstype="xfs" --ondisk=sda --size=512
part pv.01 --fstype="lvmpv" --ondisk=sda --grow
volgroup vg_root --pesize=4096 pv.01
logvol /home --fstype="xfs" --size=5120 --name=lv_home --vgname=vg_root
logvol /var --fstype="xfs" --size=10240 --name=lv_var --vgname=vg_root
logvol / --fstype="xfs" --size=10240 --name=lv_root --vgname=vg_root
logvol swap --fstype="swap" --size=4092 --name=lv_swap --vgname=vg_root
skipx
reboot
%packages --ignoremissing --excludedocs
openssh-clients
curl
dnf-utils
drpm
net-tools
open-vm-tools
perl
perl-File-Temp
sudo
vim
wget
python3
# 불필요한 펌웨어
-aic94xx-firmware
-atmel-firmware
-b43-openfwwf
-bfa-firmware
-ipw2100-firmware
-ipw2200-firmware
-ivtv-firmware
-iwl*-firmware
-libertas-usb8388-firmware
-ql*-firmware
-rt61pci-firmware
-rt73usb-firmware
-xorg-x11-drv-ati-firmware
-zd1211-firmware
-cockpit
-quota
-alsa-*
-fprintd-pam
-intltool
-microcode_ctl
%end
%addon com_redhat_kdump --disable
%end
%post
# Ansible 액세스 관리
groupadd -g 1001 ansible
useradd -m -g 1001 -u 1001 ansible
mkdir /home/ansible/.ssh
echo -e "<---- PAST YOUR PUBKEY HERE ---->" > /home/ansible/.ssh/authorized_keys
chown -R ansible:ansible /home/ansible/.ssh
chmod 700 /home/ansible/.ssh
chmod 600 /home/ansible/.ssh/authorized_keys
echo "ansible ALL=(ALL:ALL) NOPASSWD:ALL" > /etc/sudoers.d/ansible
chmod 440 /etc/sudoers.d/ansible
systemctl enable vmtoolsd
systemctl start vmtoolsd
%end
이 경우, 최소한의 iso를 사용하기로 선택했으므로 부팅 또는 DVD 대신 AppStream 리포지토리에만 포함된 필수 설치 패키지만 사용할 수 있습니다.
Packer는 설치 종료를 감지하기 위해 VMware Tools에 의존하며, open-vm-tools 패키지는 AppStream 리포지토리에만 존재하므로 설치 프로세스에서 CD-ROM과 이 원격 리포지토리를 모두 사용하도록 지정해야 합니다.
참고
외부 리포지토리에 액세스할 수 없는 경우 리포지토리의 미러, squid 프록시 또는 DVD를 사용할 수 있습니다.
# CD-ROM 설치 미디어 사용
repo --name="AppStream" --baseurl="http://download.rockylinux.org/pub/rocky/8.4/AppStream/x86_64/os/"
cdrom
네트워크 구성으로 이동하겠습니다. 이 예제에서는 DHCP 서버를 사용하지 않으므로 다시 한번 기억해 주세요.
# 네트워크 정보
network --bootproto=static --device=ens192 --gateway=192.168.1.254 --ip=192.168.1.11 --nameserver=192.168.1.254,4.4.4.4 --netmask=255.255.255.0 --onboot=on --ipv6=auto --activate
설치가 끝날 때 SSH를 통해 Packer에 연결할 사용자를 지정했음을 기억하십시오. 이 사용자와 암호가 일치해야 합니다.
# 루트 암호
rootpw mysecurepassword
주의
예를 들어 Ansible을 사용하여 VM을 배포한 직후 이 암호가 변경되는지 확인하는 한 여기에서 안전하지 않은 암호를 사용할 수 있습니다.
선택한 파티션 구성입니다. 더 복잡한 설정도 가능합니다. Packer에서 정의된 디스크 공간에 맞게 파티션 구성을 정의하고 환경에 정의된 보안 규칙(예: /tmp용 별도 파티션)을 준수하도록 설정을 맞출 수 있습니다.
# 시스템 부트로더 구성
bootloader --location=mbr --boot-drive=sda
# 파티션 초기화 정보
clearpart --all --initlabel --drives=sda
# 디스크 파티션 정보
part /boot --fstype="xfs" --ondisk=sda --size=512
part pv.01 --fstype="lvmpv" --ondisk=sda --grow
volgroup vg_root --pesize=4096 pv.01
logvol /home --fstype="xfs" --size=5120 --name=lv_home --vgname=vg_root
logvol /var --fstype="xfs" --size=10240 --name=lv_var --vgname=vg_root
logvol / --fstype="xfs" --size=10240 --name=lv_root --vgname=vg_root
logvol swap --fstype="swap" --size=4092 --name=lv_swap --vgname=vg_root
다음 섹션은 설치될 패키지에 관한 것입니다. "Best practice(최선의 방법)"는 필요한 패키지만 설치하여 공격 표면을 최소화하는 것입니다. 특히 서버 환경에서는 매우 중요합니다.
참고
작성자는 설치 프로세스에서 수행할 작업을 제한하고 Packer의 후설치 스크립트에서 필요한 것을 설치하는 것을 선호합니다. 따라서 이 경우에는 최소한의 필수 패키지만 설치합니다.
Packer가 해당 스크립트를 VM에 복사하려면 openssh-clients 패키지가 필요한 것 같습니다.
open-vm-tools도 Packer가 설치 종료를 감지하는 데 필요하며, 이를 위해 AppStream 리포지토리가 추가되었습니다. 패키지 perl과 perl-File-Temp은 VMware Tools이 배포 단계에서 필요합니다. 그러나 이로 인해 많은 종속 패키지가 필요하게 됩니다. 또한 미래에 Ansible이 작동하려면 python3 (3.6)도 필요합니다. (Ansible이나 python을 사용하지 않을 경우에는 제거하십시오!)
# 불필요한 펌웨어
-aic94xx-firmware
-atmel-firmware
...
패키지를 추가하는 것뿐만 아니라 제거할 수도 있습니다. 하드웨어가 작동할 환경을 제어하므로 필요 없는 firmware도 제거할 수 있습니다.
# 불필요한 펌웨어
-aic94xx-firmware
-atmel-firmware
...
다음 섹션은 몇 명의 사용자를 추가합니다. 우리 경우에는 암호 없이 공개 키를 가진 ansible 사용자를 만드는 것이 흥미로워 보입니다. 이렇게 하면 새로운 VM에는 Ansible 서버에서 접근하여 후설치 작업을 실행할 수 있습니다.
이제 vmtoolsd(오픈-vm-tools를 관리하는 프로세스)를 활성화하고 시작해야 합니다. VM이 재부팅되면 vSphere에서 IP 주소를 감지합니다.
#!/bin/sh -eux
echo "Updating the system..."
dnf -y update
echo "Installing cloud-init..."
dnf -y install cloud-init
# https://bugs.launchpad.net/cloud-init/+bug/1712680 참조
# 및 https://kb.vmware.com/s/article/71264
# cloud-init로 사용자 정의된 가상 머신은 재부팅 후 DHCP로 설정됩니다.
echo "manual_cache_clean: True " > /etc/cloud/cloud.cfg.d/99-manual.cfg
echo "Disable NetworkManager-wait-online.service"
systemctl disable NetworkManager-wait-online.service
# 현재 SSH 키를 정리하여 템플릿 VM이 새 키를 얻도록 합니다.
rm -f /etc/ssh/ssh_host_*
# 우리가 필요로 하지 않는 ~200메가 펌웨어 패키지를 피하십시오
# 이것은 KS 파일에서 수행할 수 없으므로 여기에서 수행합니다.
echo "Removing extra firmware packages"
dnf -y remove linux-firmware
dnf -y autoremove
echo "Remove previous kernels that preserved for rollbacks"
dnf -y remove -y $(dnf repoquery --installonly --latest-limit=-1 -q)
dnf -y clean all --enablerepo=\*;
echo "truncate any logs that have built up during the install"
find /var/log -type f -exec truncate --size=0 {} \;
echo "remove the install log"
rm -f /root/anaconda-ks.cfg /root/original-ks.cfg
echo "remove the contents of /tmp and /var/tmp"
rm -rf /tmp/* /var/tmp/*
echo "Force a new random seed to be generated"
rm -f /var/lib/systemd/random-seed
echo "Wipe netplan machine-id (DUID) so machines get unique ID generated on boot"
truncate -s 0 /etc/machine-id
echo "Clear the history so our install commands aren't there"
rm -f /root/.wget-hsts
export HISTSIZE=0
기억해 주세요, 우리는 Packer에서 .sh 스크립트에 해당하는 Provisioner를 선언했습니다. 이 스크립트는 json 파일과 동일한 서브디렉토리에 저장됩니다.
다양한 유형의 Provisioner가 있으며, Ansible을 사용할 수도 있습니다. 이러한 가능성들을 자유롭게 탐색할 수 있습니다.
이 파일은 완전히 변경할 수 있지만, 이 부분의 자동화 과정에서 무엇을 할 수 있는지의 예시로 제공되는 것입니다. 이 경우 requirements.sh라는 스크립트의 내용입니다:
#!/bin/sh -eux
echo "Updating the system..." dnf -y update
echo "Installing cloud-init..." dnf -y install cloud-init
# https://bugs.launchpad.net/cloud-init/+bug/1712680 참조
# 및 https://kb.vmware.com/s/article/71264
# cloud-init로 사용자 정의된 가상 머신은 재부팅 후 DHCP로 설정됩니다. echo "manual_cache_clean: True " > /etc/cloud/cloud.cfg.d/99-manual.cfg
echo "Disable NetworkManager-wait-online.service"
systemctl disable NetworkManager-wait-online.service
# 현재 SSH 키를 정리하여 템플릿 VM이 새 키를 얻도록 합니다. rm -f /etc/ssh/ssh_host_*
# 우리가 필요로 하지 않는 ~200메가 펌웨어 패키지를 피하십시오
# 이것은 KS 파일에서 수행할 수 없으므로 여기에서 수행합니다. echo "Removing extra firmware packages"
dnf -y remove linux-firmware
dnf -y autoremove
echo "Remove previous kernels that preserved for rollbacks"
dnf -y remove -y $(dnf repoquery --installonly --latest-limit=-1 -q)
dnf -y clean all --enablerepo=\*;
echo "truncate any logs that have built up during the install"
find /var/log -type f -exec truncate --size=0 {} \;
echo "remove the install log"
rm -f /root/anaconda-ks.cfg /root/original-ks.cfg
echo "remove the contents of /tmp and /var/tmp"
rm -rf /tmp/* /var/tmp/*
echo "Force a new random seed to be generated"
rm -f /var/lib/systemd/random-seed
echo "Wipe netplan machine-id (DUID) so machines get unique ID generated on boot"
truncate -s 0 /etc/machine-id
echo "Clear the history so our install commands aren't there"
rm -f /root/.wget-hsts
export HISTSIZE=0
몇 가지 설명이 필요합니다.
echo "Installing cloud-init..." dnf -y install cloud-init
# https://bugs.launchpad.net/cloud-init/+bug/1712680 참조
# 및 https://kb.vmware.com/s/article/71264
# cloud-init로 사용자 정의된 가상 머신은 재부팅 후 DHCP로 설정됩니다. echo "manual_cache_clean: True" > /etc/cloud/cloud.cfg.d/99-manual.cfg
vSphere는 이제 VMware Tools를 통해 cloud-init을 사용하여 centos8 게스트 머신의 네트워크를 구성하므로 cloud-init을 설치해야 합니다. 그러나 아무것도 하지 않으면 설정은 첫 번째 재부팅 시 적용되며 모든 것이 정상적으로 작동할 것입니다. 그러나 다음 재부팅에서는 cloud-init이 vSphere에서 새 정보를 받지 못하게 됩니다. 이 경우 cloud-init은 자신의 캐시를 자동으로 삭제하지 않도록 지정해야 하며, 따라서 첫 번째 재부팅 시 받은 구성 정보를 재사용하고 각 재부팅 이후에도 계속 사용할 수 있습니다.
이것은 우리가 원하는 동작이 아니므로 캐시를 자동으로 삭제하지 않도록 cloud-init에 지정해야 합니다. 따라서 첫 번째 재부팅과 이후 재부팅할 때마다 받은 구성 정보를 재사용합니다.
이를 위해 manual_cache_clean: True 지시문을 사용하여 /etc/cloud/cloud.cfg.d/99-manual.cfg 파일을 생성합니다.
참고사항
이는 vSphere 게스트 사용자 지정을 통해 네트워크 구성을 다시 적용해야 하는 경우(일반적인 사용에서는 매우 드물어야 함) cloud-init 캐시를 직접 삭제해야 함을 의미합니다.
스크립트의 나머지 부분은 주석 처리되어 더 자세한 설명이 필요하지 않습니다.
Bento 프로젝트를 확인하여 자동화 프로세스의 이 부분에서 수행할 수 있는 작업에 대한 자세한 아이디어를 얻을 수 있습니다.