最近在與客戶探討DevOps轉型的相關規劃和設計,當我們統計現有虛擬化管理員工作量的時候,發現大部分時間用在為應用部門準備各種虛擬機,由於每個應用對虛擬機的要求不同(CPU、內存、硬盤、硬盤分區、系統參數配置等),最後管理員不得不每次都全新安裝虛擬機,這就產生了大量重複性工作,無法學習新技術和業務創建。
很多時候管理員會直接通過歷史模版克隆,再進行調整,雖然時間上節約了一些,但是依然存在以下的挑戰:
- 虛擬機磁盤分區的調整難,這會導致大量的磁盤資源浪費;
- 模版補丁更新不及時,管理員很難做到每週/月更新一次模版,導致模版克隆出來的機器存在大量漏洞;
- 模版包含大量無用組件,為適應多種應用的環境,一般模版中會包含大量各應用無關的組件,帶來潛在的風險;
- 二次修改帶來的不穩定性,如果在克隆後的模版中再進行修改,穩定性會產生影響;
- 在“自動化”的背景下,CI/CD會基於模版進行自動化部署或伸縮,模版的更新不僅僅包含操作系統,還包含應用在內。
基於以上的分析,企業需要具備一個“自動化”的模版管理工具,實現模版自動化構建和聲明式定義,以釋放管理員的重複性工作,同時,也是企業向DevOps轉型的儲備,進而加速企業信息化建設步伐。
本系列一共分為四部分:
[自動化系列]一、使用Packer自動化構建模版—CentOS7.x
「自動化系列」二、使用Packer自動化構建模版—WindowsServer2016
[自動化系列]三、使用Terraform結合Packer批量部署虛擬機
[自動化系列]四、使用GitLab CI/CD實現虛擬機聲明式管理和自動化集成
相關
- Packer是一個開源的自動化虛擬機模版構建工具,支持私有云和公有云,幾乎涵蓋所有的環境。
http://www.packer.io/
- vSphere是VMware企業級虛擬化軟件,被企業客戶廣泛使用,具備穩定性高、性能好、安全性高和易使用的特點。
https://www.vmware.com/cn/products/vsphere.html
- 示例代碼中包含Packer所需的json文件和CentOS7的kickstart文件
https://github.com/6547709/packer-vsphere/tree/master/CentOS7
- kickstart語法參考中詳細說明了kickstart的語法
https://access.redhat.com/documentation/zh-cn/red_hat_enterprise_linux/7/html/installation_guide/sect-kickstart-syntax
- VMware虛擬機硬件版本中詳細列出了vSphere對虛擬機硬件版本的支持
https://kb.vmware.com/s/article/2007240
使用時請根據實際環境進行修改
環境需求:
- 一臺Windows/Linux/MacOS電腦,能夠連接vCenter Server;
- Packer程序:https://packer.io/downloads.html
- CentOS 7.x ISO:https://wiki.centos.org/Download
Packer安裝
Packer採用GO語言編寫,安裝非常簡單,只需要將解壓後的packer文件拷貝到系統bin目錄下即可,下面是在Linux下的安裝方式:
<code>wget
https://releases.hashicorp.com/packer/1.5.4/packer_1.5.4_linux_amd64.zip unzip packer_1.5
.4_linux_amd64.zip cp packer /usr/loca/bin chmod +x /usr/local/bin/packer packer version/<code>
CentOS 7的Packer模版
我們需要兩個基礎文件,用於使用Packer在vSphere環境中構建CentOS 7.x模版:
- centos-vsphere.json文件(Packer模版);
- ks.cfg文件(無人值守配置文件)
推薦下載倉庫的文件,避免拷貝粘貼可能造成的字符問題;
https://github.com/6547709/packer-vsphere/tree/master/CentOS7
centos-vsphere.json文件說明
variables段落,用於定義vCenter的相關信息和虛擬機配置,其會在Builders段落引用,注意虛擬機文件夾需要預先創建好。
- vm-name:定義虛擬機模版基礎名稱,在build階段會自己增加日期後綴,以方便卻別版本;
- vm-version:定義虛擬機使用什麼硬件版本,當前vSphere6.7U3使用15,其他版本請查詢相關工具中心的VMware虛擬機硬件版本;
- vm-folder:定義虛擬機模版保存在哪個文件夾中;
- vm-cpu-num:定義虛擬機模版配置的CPU數量,通過模版再進行部署時可以修改;
- vm-mem-size:定義虛擬機模版配置的內存容量(MB單位),通過模版再進行部署時可以修改;
- vm-disk-size:定義虛擬機磁盤容量(MB單位),後續的kickstart會基於此容量進行分區,/boot、swap、/var/log、/分區是固定的配置(通過修改ks.cfg更改),/app-date用於存放應用,會使用所有剩餘空間;
- iso_url:指定系統安裝光盤位置,本示例使用vSphere環境構建,所以指定共享存儲的路徑;
提示1:為保證ISO文件有效,可以通過參數(iso_checksum、iso_checksum_type和iso_checksum_url)驗證ISO是否完成;
提示2:變量部分可以獨立為var.json文件,在build時單獨指定;
<code>"variables"
: {"vsphere-server"
:"vcenter.corp.local"
,"vsphere-user"
: ,"vsphere-password"
:"VMware1!"
,"vsphere-datacenter"
:"Labs-DC02"
,"vsphere-cluster"
:"DC02-Cluster"
,"vsphere-network"
:"vlan100"
,"vsphere-datastore"
:"SSD_DATASTORE"
,"vm-name"
:"CentOS7-T"
,"vm-version"
:"15"
,"vm-folder"
:"Templates"
,"vm-cpu-num"
:"1"
,"vm-mem-size"
:"1024"
,"vm-disk-size"
:"81920"
,"iso_url"
:"[SSD_DATASTORE] 0-ISO/CentOS-7-x86_64-DVD-1908.iso"
,"magic_reference_date"
:"2006-01-02 15-04-05+0800"
},/<code>
builders段落,用於真正的構建配置,本示例中將經常需要改變的部分通過variables定義,並在此階段引用。
- vm_name:我們採用variables中的名字和日期進行組合,isotime會獲取當前日期;
- notes:顯示在虛擬機的備註屬性中,用於查看模版具體的構建時間;
- guest_os_type:定義虛擬機客戶機操作系統,可以通VMware官方文檔或者創建虛擬機後查詢.vmx文件獲得正確的客戶機操作系統代碼;
- ssh_username:定義provisioners階段連接模版虛擬機的口令,此口令來自ks.cfg中的配置;
- disk_controller_type:定義虛擬機的SCSI控制器類型,這裡採用更高性能的VMware準虛擬;
- disk_thin_provisioned:定義虛擬機是否使用精簡磁盤;
- network_card:網卡類型,這裡選擇了性能最好的vmxnet3;
- convert_to_template:定義是否自動轉換成模版,請根據需要選擇,如果虛擬機部署編排工具不支持從模版克隆,就需要配置為false;
- floppy_files:定義CentOS無人值守安裝的kickstart文件;
<code>"builders"
: [ {"type"
:"vsphere-iso"
,"vcenter_server"
:"{{user `vsphere-server`}}"
,"username"
:"{{user `vsphere-user`}}"
,"password"
:"{{user `vsphere-password`}}"
,"insecure_connection"
:"true"
,"datacenter"
:"{{user `vsphere-datacenter`}}"
,"cluster"
:"{{user `vsphere-cluster`}}"
,"network"
:"{{user `vsphere-network`}}"
,"datastore"
:"{{user `vsphere-datastore`}}"
,"vm_name"
:"{{user `vm-name`}}-{{isotime "2006-01-02"}}"
,"vm_version"
:"{{user `vm-version`}}"
,"folder"
:"{{user `vm-folder`}}"
,"notes"
:"Build via Packer in {{ (isotime | (user `magic_reference_date`)) }}"
,"boot_wait"
:"10s"
,"boot_order"
:"disk,cdrom,floppy"
,"guest_os_type"
:"centos7_64Guest"
,"ssh_username"
:"root"
,"ssh_password"
:"VMware1!"
,"CPUs"
:"{{user `vm-cpu-num`}}"
,"RAM"
:"{{user `vm-mem-size`}}"
,"RAM_reserve_all"
:false
,"disk_controller_type"
:"pvscsi"
,"disk_size"
:"{{user `vm-disk-size`}}"
,"disk_thin_provisioned"
:true
,"network_card"
:"vmxnet3"
,"convert_to_template"
:true
,"iso_paths"
: ["{{user `iso_url`}}"
],"floppy_files"
: ["ks.cfg"
],"boot_command"
: [""
,"linux ks=hd:fd0:/ks.cfg"
] } ],/<code>
provissioners段落,用於系統自動化安全完成後的自定義操作,例如:更新系統補丁,清理模版等,本示例中進行了系統更新。
<code>"provisioners"
: [ {"type"
:"shell"
,"inline"
: ["rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7"
,"yum install deltarpm -y"
,"yum update -y"
,"yum clean all"
] } ] }/<code>
ks.cfg文件說明
kickstart文件的介紹很多,這裡不進行詳細介紹,可以參考官方文檔說明,下面僅針對我定製化的內容進行說明;
- 第9行rootpw,定義root密碼,—plainetext參數表示不會在部署目標系統中記錄密碼;
- 第20行bootloader,更改默認網卡名為eth0,禁用ipv6;
- 第26行network,設定虛擬機網絡和主機名,本示例採用dhcp,如果使用靜態IP地址請參考上一行;
- 第33行lang,設定語言支持,添加簡體中文;
- 第39行timezone,設定亞洲/上海時區;
- 第47-63行,定義磁盤分區,按照企業生產規範進行分區,採用xfs文件系統,採用lvm以便後期擴展;
- 第145-151行,刪除系統無用用戶,減少風險;
- 第158-160行,創建本地用戶ops,用於應用用戶登陸,請根據實際情況定義;
- 第166-169行,授權ops用戶sudo權限,請根據實際情況定義;
- 第176-197行,更新ntp;
- 第202-205行,優化SSH登錄速度;
- 第210-229行,優化系統最大打開文件參數;請根據實際情況定義;
- 第235-246行,清理模版中的網卡UUID和更改ifcfg-eth0參數;此示例採用DHCP;
- 第252-291行,用於靜態IP地址配置和禁用NetworkManager管理DNS;
- 第334-403行,更改系統默認yum源為aliyun;請根據企業環境進行修改,一般內網使用yum私服(例如:nexus3);
本示例中的密碼均為VMware1!,請注意自行修改。
<code> firewall --disabled selinux --disabled rootpw --plaintext VMware1! bootloader --location=mbr --append="elevator=noop pci=bfsort net.ifnames=0 biosdevname=0 ipv6.disable=1"
network --bootproto=dhcp --device=eth0 --noipv6 --onboot=yes --device=eth0 --hostname=CentOS7Template --activate authconfig --enableshadow --passalgo=sha512 keyboard --vckeymap=us --xlayouts='us'
lang en_US.UTF-8 --addsupport=zh_CN.UTF-8 skipx install timezone Asia/Shanghai --ntpservers=3.centos.pool.ntp.org,0.centos.pool.ntp.org eula --agreed services --enabled=NetworkManager,sshd zerombr ignoredisk --only-use=sda clearpart --all --drives=sda part /boot --fstype=xfs --size=512 part pv.01 --grow --size=1 volgroup sys_vg pv.01 logvol / --fstype=xfs --name=root --vgname=sys_vg --size=10240 logvol swap --name=swap --vgname=sys_vg --size=4096 logvol /tmp --fstype=xfs --name=tmp --vgname=sys_vg --size=4096 logvol /usr --fstype=xfs --name=usr --vgname=sys_vg --size=3072 logvol /var --fstype=xfs --name=var --vgname=sys_vg --size=2048 logvol /var/log
--fstype=xfs --name=var_log --vgname=sys_vg --size=4096 logvol /app-data --fstype=xfs --name=app-data --vgname=sys_vg --size=1 --grow %packages --ignoremissing Require @Base @Base @core biosdevname sed perl less dmidecode bzip2 iproute iputils sysfsutils rsync nano mdadm setserial man-pages.noarch findutils tar net-tools tmpwatch lsof python screen lvm2 curl ypbind yp-tools smartmontools openssh-clients acpid irqbalancewhich
bind
-utils ntsysv ntp man open-vm-tools vim lrzsz wget tree screen tcpdump chkconfig gzip %end %post --log
=/root/ks-post.log (set
-x /bin/sed -i -e's/ rhgb//'
-e's/ quiet//'
/boot/grub2/grub.cfg /bin/sed -i -e's/ rhgb//'
-e's/ quiet//'
/etc/grub2.cfg /bin/sed -i -e's/ rhgb//'
-e's/ quiet//'
/etc/default/grub plymouth-set-default-theme text /usr/libexec/plymouth/plymouth-update-initrd /usr/sbin/userdel operator /usr/sbin/userdel games /usr/sbin/userdel lp /usr/sbin/userdel sync /usr/sbin/userdel shutdown /usr/sbin/userdel halt /usr/sbin/groupdel games /usr/sbin/useradd ops;echo
'VMware1!'
| passwd --stdin ops /usr/sbin/usermod -a -G wheel ops /usr/bin/chage -M -1 -E -1 ops /bin/cat'EOF'
>> /etc/sudoers Defaults:ops !requiretty ops ALL=(ALL) NOPASSWD: ALL EOF /usr/sbin/ntpdate 192.168.10.1 /sbin/hwclock --systohc --utc /bin/cat'EOF'
> /etc/ntp.conf restrict default ignore restrict 127.0.0.1 driftfile /var/lib/ntp/drift logfile /var/log
/ntpd broadcastdelay 0.008 server 192.168.10.1 restrict 192.168.10.1 mask 255.255.255.255 nomodify notrap noquery EOF /bin/cat'EOF'
> /etc/ntp/step-tickers 192.168.10.1 EOF /bin/touch /var/log
/ntpd /bin/sed -i /etc/ssh/sshd_config \ -e's/^#UseDNS yes$/UseDNS no/'
\ -e's/^GSSAPIAuthentication yes$/GSSAPIAuthentication no/'
\ /bin/cat'EOF'
>> /etc/sysctl.conf fs.file-max = 65536 EOF /bin/cat'EOF'
>> /etc/security/limits.conf EOF /bin/cat'EOF'
> /etc/security/limits.d/10-nofile.conf * soft nofile 65535 * hard nofile 65535 EOF /bin/cat'EOF'
> /etc/security/limits.d/11-stack.conf * soft stack 65535 * hard stack 65535 EOF /bin/sed -i'/^DNS1*..*$/d'
/etc/sysconfig/network-scripts/ifcfg-e
* /bin/sed -i'/^DNS2*..*$/d'
/etc/sysconfig/network-scripts/ifcfg-e
* /bin/sed -i'/^GATEWAY*..*$/d'
/etc/sysconfig/network-scripts/ifcfg-e
* /bin/sed -i'/^HOSTNAME*..*$/d'
/etc/sysconfig/network-scripts/ifcfg-e
* /bin/sed -i'/^HWADDR*..*$/d'
/etc/sysconfig/network-scripts/ifcfg-e
* /bin/sed -i'/^NM_CONTROLLED*..*$/d'
/etc/sysconfig/network-scripts/ifcfg-e
* /bin/sed -i'/^UUID*..*$/d'
/etc/sysconfig/network-scripts/ifcfg-e
* /bin/mv /etc/sysconfig/network-scripts/ifcfg-e
* /etc/sysconfig/network-scripts/ifcfg-eth0 /bin/sed -i's/ens192/eth0/g'
/etc/sysconfig/network-scripts/ifcfg-eth0 /bin/sed -i"s\ONBOOT=no\ONBOOT=yes\g"
/etc/sysconfig/network-scripts/ifcfg-eth0 /bin/sed -i"s\IPV6INIT=yes\IPV6INIT=no\g"
/etc/sysconfig/network-scripts/ifcfg-eth0 touch /root/.dir_colors /bin/cat'EOF'
>> /root/.i18n LC_COLLATE=C EOF /bin/cat'EOF'
> /etc/logrotate.conf monthly rotate 12 create compress include /etc/logrotate.d /var/log
/wtmp { create 0664 root utmp } EOF /bin/rm -f /etc/yum.repos.d/CentOS-* /bin/cat'EOF'
> /etc/yum.repos.d/CentOS-Base.repo [base] name=CentOS-$releasever
- Base - mirrors.aliyun.com failovermethod=priority baseurl=http://mirrors.aliyun.com/centos/$releasever
/os/$basearch
/ gpgcheck=1 gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7 [updates] name=CentOS-$releasever
- Updates - mirrors.aliyun.com failovermethod=priority baseurl=http://mirrors.aliyun.com/centos/$releasever
/updates/$basearch
/ gpgcheck=1 gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7 [extras] name=CentOS-$releasever
- Extras - mirrors.aliyun.com failovermethod=priority baseurl=http://mirrors.aliyun.com/centos/$releasever
/extras/$basearch
/ gpgcheck=1 gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7 [centosplus] name=CentOS-$releasever
- Plus - mirrors.aliyun.com failovermethod=priority baseurl=http://mirrors.aliyun.com/centos/$releasever
/centosplus/$basearch
/ gpgcheck=1 enabled=0 gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7 [contrib] name=CentOS-$releasever
- Contrib - mirrors.aliyun.com failovermethod=priority baseurl=http://mirrors.aliyun.com/centos/$releasever
/contrib/$basearch
/ gpgcheck=1 enabled=0 gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7 EOF /bin/cat'EOF'
> /etc/yum.repos.d/epel-7.repo [epel] name=Extra Packagesfor
Enterprise Linux 7 -$basearch
baseurl=http://mirrors.aliyun.com/epel/7/$basearch
failovermethod=priority enabled=1 gpgcheck=0 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7 [epel-debuginfo] name=Extra Packagesfor
Enterprise Linux 7 -$basearch
- Debug baseurl=http://mirrors.aliyun.com/epel/7/$basearch
/debug failovermethod=priority enabled=0 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7 gpgcheck=0 [epel-source] name=Extra Packagesfor
Enterprise Linux 7 -$basearch
- Source baseurl=http://mirrors.aliyun.com/epel/7/SRPMS failovermethod=priority enabled=0 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7 gpgcheck=0 EOF /bin/sed -i"s/UUID*..*\/boot/\/dev\/sda1\t\t\/boot/"
/etc/fstab /bin/rm -rf /var/tmp /bin/ln -s /tmp /var/tmp /usr/bin/systemctlenable
autofs /usr/bin/systemctlenable
ntpd /usr/bin/systemctldisable
firewalld.service /usr/bin/systemctldisable
auditd /usr/bin/systemctldisable
mdmonitor /usr/bin/systemctldisable
postfix /usr/bin/systemctldisable
abrt-ccpp.service /usr/bin/systemctldisable
abrt-oops.service /usr/bin/systemctldisable
abrt-vmcore.service /usr/bin/systemctldisable
abrt-xorg.service /usr/bin/systemctldisable
abrtd.service /usr/bin/systemctldisable
iscsi.service /usr/bin/systemctldisable
iscsid.socket /usr/bin/systemctldisable
iscsiuio.socket /usr/bin/systemctldisable
libstoragemgmt.service /usr/bin/systemctldisable
multipathd.service /usr/bin/systemctldisable
wpa_supplicant.service ) 2>&1 %end reboot --eject/<code>
Packer驗證配置
完成配置文件的準備後,我們需要驗證packer的配置文件是否正確,使用一下命令:
<code>packer
validate
centos-vsphere
.json
/<code>
Packer執行構建
<code>packer
build
centos-vsphere
.json
/<code>
如果第一次構建成功,並且虛擬機名稱是固定的(本示例是基於日期的)下一次構建時可以增加-force參數覆蓋上一次模版;
<code>packer
build
-froce
centos-vsphere
.json
/<code>
構建完成後,命令行如下提示;
令行如下提示;
登陸到vSpehre中可以看到模版:
完成
至此我們通過Packer實現了vSphere環境下虛擬機模版的自動構建,如果希望構建其他環境可以參考官方文檔。下一章我會帶來通過Packer構建Windows Server 2016虛擬機模版。