1. Tổng quan.
Lệnh “boot_command” là một phần cấu hình quan trọng khi bạn tạo một máy ảo. Nó xác định các phím cần được nhập khi máy ảo được khởi động lần đầu để bắt đầu quá trình cài đặt hệ điều hành. Lệnh này được gửi sau khi thời gian “boot_wait” được định ra, cho phép máy ảo có đủ thời gian để khởi động.
Lệnh “boot_command” là một mảng các chuỗi (một danh sách các đoạn văn bản). Những chuỗi này sẽ được nhập vào máy ảo theo thứ tự mà bạn xác định. Việc sử dụng mảng chỉ để làm cho cấu hình dễ đọc hơn trong file cấu hình của máy ảo.
2. Các phím tắt.
Có một tập hợp các phím đặc biệt có sẵn để bạn sử dụng trong lệnh “boot_command”. Khi bạn sử dụng những phím này trong lệnh, chúng sẽ được thay thế bằng phím thực tế tương ứng:
- <bs> – Phím Backspace
- <del> – Phím Delete
- <enter> hoặc <return> – Mô phỏng việc nhấn phím “enter” hoặc “return” thực tế.
- <esc> – Mô phỏng việc nhấn phím escape.
- <tab> – Mô phỏng việc nhấn phím tab.
- <f1> đến <f12> – Mô phỏng việc nhấn phím chức năng.
- <up> hoặc <down> hoặc <left> hoặc <right> – Mô phỏng việc nhấn phím mũi tên.
- <spacebar> – Mô phỏng việc nhấn phím spacebar.
- <insert> – Mô phỏng việc nhấn phím insert.
- <home> hoặc <end> – Mô phỏng việc nhấn phím home và end.
- <pageUp> hoặc <pageDown> – Mô phỏng việc nhấn phím page up và page down.
- <menu> – Mô phỏng việc nhấn phím Menu.
- <leftAlt> hoặc <rightAlt> – Mô phỏng việc nhấn phím alt.
- <leftCtrl> hoặc <rightCtrl> – Mô phỏng việc nhấn phím ctrl.
- <leftShift> hoặc <rightShift> – Mô phỏng việc nhấn phím shift.
- <leftSuper> hoặc <rightSuper> – Mô phỏng việc nhấn phím ⌘ hoặc Windows.
- <wait> hoặc <wait5> hoặc <wait10> – Thêm một đợi 1, 5 hoặc 10 giây trước khi gửi bất kỳ phím nào tiếp theo. Điều này hữu ích nếu bạn cần đợi giao diện người dùng cập nhật trước khi nhập tiếp.
- <waitXX> – Thêm một thời gian đợi tùy chỉnh trước khi gửi bất kỳ phím nào tiếp theo. Định dạng của XX là một chuỗi số nguyên dương, mỗi số có thể đi kèm với phần thập phân và đơn vị thời gian tùy chọn, như 300ms (mili giây), 1.5h (giờ và nửa), hoặc 2h45m (2 giờ 45 phút). Đơn vị thời gian hợp lệ bao gồm ns (nanogiang), us (mikrogiây), ms, s (giây), m (phút), h (giờ). Ví dụ: <wait10m> hoặc <wait1m20s>.
- <XXXOn> hoặc <XXXOff> – Bất kỳ ký tự bàn phím in được nào và các biểu thức “đặc biệt” này, ngoại trừ loại <wait>, cũng có thể được bật hoặc tắt. Ví dụ, để mô phỏng ctrl+c, bạn có thể sử dụng <leftCtrlOn>c<leftCtrlOff>. Hãy đảm bảo thả chúng ra sau khi sử dụng, nếu không chúng sẽ được giữ xuống cho đến khi máy ảo khởi động lại. Để giữ phím c xuống, bạn sử dụng <cOn>. Tương tự, bạn có thể sử dụng <cOff> để thả phím.
- {{ .HTTPIP }} và {{ .HTTPPort }} – Đây là địa chỉ IP và cổng của máy chủ HTTP được sử dụng để phục vụ thư mục được chỉ định trong cấu hình http_directory. Nếu không có thư mục http_directory được xác định, thì chúng sẽ trống!
- {{ .Name }} – Tên của máy ảo.
Dưới đây là một ví dụ về lệnh “boot_command” được sử dụng để cài đặt CentOS 6.4:
Trong JSON:
"boot_command": [
"<tab><wait>",
"ks=http://{{ .HTTPIP }}:{{ .HTTPPort }}/centos6-ks.cfg<enter>"
]
Trong HCL2:
boot_command = [
"<tab><wait>",
"ks=http://{{ .HTTPIP }}:{{ .HTTPPort }}/centos6-ks.cfg<enter>"
]
Ở đây:
"<tab><wait>"
– Đầu tiên, máy ảo sẽ nhấn phím “Tab”, sau đó đợi một chút trước khi tiếp tục."ks=http://{{ .HTTPIP }}:{{ .HTTPPort }}/centos6-ks.cfg<enter>"
– Sau đó, máy ảo sẽ gửi lệnh “ks=http://{{ .HTTPIP }}:{{ .HTTPPort }}/centos6-ks.cfg” và nhấn phím “Enter”. Đây là một lệnh để truy cập file cấu hình và tiến hành cài đặt CentOS 6.4 thông qua mạng. Các placeholder{{ .HTTPIP }}
và{{ .HTTPPort }}
sẽ được thay thế bằng giá trị thực tế của địa chỉ IP và cổng của máy chủ HTTP.
Dưới đây là một ví dụ về lệnh “boot_command” được sử dụng để cài đặt Ubuntu 12.04:
Trong JSON:
"boot_command": [
"<esc><esc><enter><wait>",
"/install/vmlinuz noapic ",
"preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed.cfg ",
"debian-installer=en_US auto locale=en_US kbd-chooser/method=us ",
"hostname={{ .Name }} ",
"fb=false debconf/frontend=noninteractive ",
"keyboard-configuration/modelcode=SKIP keyboard-configuration/layout=USA ",
"keyboard-configuration/variant=USA console-setup/ask_detect=false ",
"initrd=/install/initrd.gz -- <enter>"
]
Trong HCL2:
boot_command = [
"<esc><esc><enter><wait>",
"/install/vmlinuz noapic ",
"preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed.cfg ",
"debian-installer=en_US auto locale=en_US kbd-chooser/method=us ",
"hostname={{ .Name }} ",
"fb=false debconf/frontend=noninteractive ",
"keyboard-configuration/modelcode=SKIP keyboard-configuration/layout=USA ",
"keyboard-configuration/variant=USA console-setup/ask_detect=false ",
"initrd=/install/initrd.gz -- <enter>"
]
Ở đây, lệnh “boot_command” này thực hiện một loạt thao tác để bắt đầu quá trình cài đặt Ubuntu 12.04:
"<esc><esc><enter><wait>"
– Đầu tiên, máy ảo sẽ nhấn phím “Esc” hai lần, sau đó nhấn phím “Enter” và đợi một chút trước khi tiếp tục."/install/vmlinuz noapic"
– Đây là đường dẫn đến file Linux Kernel mà máy ảo sẽ sử dụng."preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed.cfg"
– Là đường dẫn đến file cấu hình trước (preseed.cfg) trên máy chủ HTTP được thay thế bằng địa chỉ IP và cổng thực tế của máy chủ HTTP.- Các thông số khác như ngôn ngữ, bàn phím, và tên máy chủ cũng được xác định trong lệnh “boot_command”.
"<initrd=/install/initrd.gz -- <enter>"
– Cuối cùng, lệnh này chỉ định file initrd và nhấn phím “Enter” để bắt đầu quá trình cài đặt.
Lệnh “boot_command” này đặc thù cho quá trình cài đặt Ubuntu 12.04 và chứa các tùy chỉnh cần thiết để tự động hóa quá trình cài đặt.
Bạn có thể sử dụng tập hợp các phím đặc biệt để thực hiện thao tác như tạo tên người dùng và sau đó nhấn phím <enter>
. Để thực hiện việc này, bạn có thể chỉ cần thêm các phím đặc biệt và ký tự của tên người dùng vào lệnh “boot_command”.
Dưới đây là một ví dụ:
"boot_command": [
"<tab><wait>",
"ks=http://{{ .HTTPIP }}:{{ .HTTPPort }}/centos6-ks.cfg<enter>",
"<wait>",
"hoanghd<enter>"
]
Trong ví dụ này, sau khi bạn đã thiết lập file Kickstart thông qua URL, các lệnh trong lệnh “boot_command” tiếp theo là:
<wait>
: Đây là một thời gian chờ để đảm bảo rằng quá trình cài đặt đã tiến hành đủ để có thể nhập tên người dùng."hoanghd<enter>"
: Lệnh này nhập tên người dùng “hoanghd” và sau đó nhấn phím<enter>
để xác nhận.
4. Các thuộc tính tùy chọn.
Các thuộc tính tùy chọn liên quan đến quá trình cài đặt máy ảo trong cấu hình Packer bao gồm:
boot_keygroup_interval
(chuỗi thời gian): Đây là thời gian chờ sau khi gửi một nhóm các lệnh nhấn phím. Giá trị của thuộc tính này nên là một định dạng thời gian (duration string) như “1h5m2s”. Ví dụ, nếu bạn đặt giá trị là “5s”, Packer sẽ chờ 5 giây sau khi gửi một nhóm lệnh nhấn phím. Nếu không xác định, Packer sẽ sử dụng một giá trị mặc định hợp lý dựa trên loại builder.boot_wait
(chuỗi thời gian): Đây là thời gian chờ sau khi khởi động máy ảo ban đầu trước khi gửi lệnh “boot_command”. Giá trị của thuộc tính này cũng nên là định dạng thời gian (duration string) như “1h5m2s”. Ví dụ, nếu bạn đặt giá trị là “5s”, Packer sẽ chờ 5 giây sau khi khởi động máy ảo trước khi bắt đầu gửi các lệnh trong “boot_command”. Nếu không xác định, giá trị mặc định là 10 giây hoặc “10s”. Nếu bạn muốn đặtboot_wait
thành 0 giây, bạn có thể sử dụng số âm, ví dụ: “-1s”.boot_command
(mảng chuỗi): Đây là một mảng các lệnh được gửi khi máy ảo được khởi động lần đầu để bắt đầu quá trình cài đặt. Mục tiêu của các lệnh này là khởi động đủ để khởi chạy trình cài đặt hệ điều hành. Bạn có thể sử dụng cả phím đặc biệt và các lệnh bình thường trong mảng này để thực hiện các tác vụ cần thiết. Nếu bạn không xác định thuộc tính này, Packer sẽ giả định rằng trình cài đặt sẽ tự động khởi động mà không cần gửi lệnh.
Các thuộc tính này cho phép bạn tùy chỉnh cách Packer tương tác với máy ảo trong quá trình cài đặt, để đảm bảo rằng quá trình tự động hóa diễn ra một cách chính xác và hiệu quả.
5. Cấu hình để tạo máy chủ HTTP tạm thời.
Packer cung cấp cấu hình để tạo máy chủ HTTP tạm thời, giúp bạn phục vụ file từ thư mục hoặc nội dung HTTP cho máy ảo trong quá trình cài đặt. Dưới đây là các thuộc tính liên quan đến cấu hình máy chủ HTTP:
http_directory
(chuỗi): Đây là đường dẫn đến một thư mục chứa các file bạn muốn phục vụ qua máy chủ HTTP. Các file trong thư mục này sẽ sẵn sàng qua giao thức HTTP và có thể được yêu cầu từ máy ảo. Đây là cách bạn có thể đặt cấu hình máy chủ để phục vụ các file như file kickstart và nhiều file khác. Mặc định, giá trị này là chuỗi rỗng, có nghĩa là không có máy chủ HTTP nào được khởi động. Địa chỉ IP và cổng của máy chủ HTTP sẽ có sẵn như các biến trong lệnh “boot_command”.http_content
(map[string]string): Đây là một ánh xạ key/value, trong đó keys biểu thị đường dẫn tới file và values biểu thị nội dung của file. keys phải bắt đầu bằng dấu gạch chéo (/), ví dụ: “/path/to/file”.http_content
cho phép bạn cung cấp nội dung để phục vụ thông qua máy chủ HTTP, tương tự nhưhttp_directory
. Mặc định, giá trị này là một ánh xạ trống, có nghĩa là không có máy chủ HTTP nào được khởi động. Địa chỉ IP và cổng của máy chủ HTTP cũng sẽ có sẵn như các biến trong lệnh “boot_command”.http_port_min
vàhttp_port_max
(số nguyên): Đây là giá trị tối thiểu và tối đa cho cổng được sử dụng cho máy chủ HTTP. Packer thường chạy song song, do đó Packer sẽ chọn một cổng trống ngẫu nhiên trong khoảng này để chạy máy chủ HTTP. Nếu bạn muốn máy chủ HTTP chạy trên một cổng cố định, hãy đặt giá trị tối thiểu và tối đa giống nhau. Mặc định, giá trị tối thiểu là 8000 và tối đa là 9000.http_bind_address
(chuỗi): Đây là địa chỉ bind cho máy chủ HTTP. Giá trị mặc định là “0.0.0.0” để làm việc với bất kỳ interface nào.http_interface
(chuỗi): Đây là tên interface mà Packer sẽ lấy địa chỉ IP (HTTPIP) từ.
Dưới đây là một ví dụ cơ bản về việc tạo image Fedora 29 bằng cách sử dụng một file Kickstart và máy chủ HTTP của Packer. Lưu ý rằng bạn cần tải file ISO của Fedora 29 thủ công trước:
http_content = {
"/a/b" = file("http/b")
"/foo/bar" = templatefile("${path.root}/preseed.cfg", { packages = ["nginx"] })
}
http_content
(map[string]): Tùy chọn này cho phép bạn chỉ định các cặp key/value cho nội dung mà bạn muốn phục vụ qua máy chủ HTTP. Key đại diện cho đường dẫn để truy cập nội dung, và value xác định nguồn của nội dung đó. Ví dụ: bạn có thể sử dụng hàmfile()
để chỉ định một file cục bộ hoặc sử dụngtemplatefile()
để tạo nội dung động. Điều này giúp bạn tùy chỉnh nội dung bạn muốn phục vụ cho máy ảo trong quá trình cài đặt.http_port_min
(int) vàhttp_port_max
(int): Đây là tùy chọn để xác định dải cổng sử dụng cho máy chủ HTTP. Packer thường chạy nhiều quá trình cùng lúc, vì vậy nó có thể chọn ngẫu nhiên một cổng khả dụng trong khoảng này để chạy máy chủ HTTP. Nếu bạn muốn đảm bảo rằng máy chủ HTTP chạy trên một cổng cụ thể, bạn có thể đặt cảhttp_port_min
vàhttp_port_max
có cùng giá trị. Mặc định, giá trị mặc định là 8000 và 9000.http_bind_address
(string): Đây là địa chỉ kết nối cho máy chủ HTTP. Giá trị mặc định là “0.0.0.0” để cho phép máy chủ hoạt động với bất kỳ giao diện mạng nào.http_interface
(string): Đây là tên của giao diện mạng mà Packer sẽ sử dụng để xác định địa chỉ IP của máy chủ HTTP. Giá trị mặc định là giao diện mạng đầu tiên không phải là loopback (giao diện loopback là “lo”).
HCL2.
variable "password" {
type = string
default = "supersecret"
}
variable "username" {
type = string
default = "apiuser@pve"
}
source "proxmox-iso" "fedora-kickstart" {
boot_command = ["<up><tab> ip=dhcp inst.cmdline inst.ks=http://{{ .HTTPIP }}:{{ .HTTPPort }}/ks.cfg<enter>"]
boot_wait = "10s"
disks {
disk_size = "5G"
storage_pool = "local-lvm"
type = "scsi"
}
efi_config {
efi_storage_pool = "local-lvm"
efi_type = "4m"
pre_enrolled_keys = true
}
http_directory = "config"
insecure_skip_tls_verify = true
iso_file = "local:iso/Fedora-Server-dvd-x86_64-29-1.2.iso"
network_adapters {
bridge = "vmbr0"
model = "virtio"
}
node = "my-proxmox"
password = "${var.password}"
proxmox_url = "https://my-proxmox.my-domain:8006/api2/json"
ssh_password = "packer"
ssh_timeout = "15m"
ssh_username = "root"
template_description = "Fedora 29-1.2, generated on ${timestamp()}"
template_name = "fedora-29"
unmount_iso = true
username = "${var.username}"
}
build {
sources = ["source.proxmox-iso.fedora-kickstart"]
}
JSON.
{
"variables": {
"username": "apiuser@pve",
"password": "supersecret"
},
"builders": [
{
"type": "proxmox-iso",
"proxmox_url": "https://my-proxmox.my-domain:8006/api2/json",
"insecure_skip_tls_verify": true,
"username": "{{user `username`}}",
"password": "{{user `password`}}",
"node": "my-proxmox",
"network_adapters": [
{
"model": "virtio",
"bridge": "vmbr0"
}
],
"disks": [
{
"type": "scsi",
"disk_size": "5G",
"storage_pool": "local-lvm"
}
],
"efi_config": {
"efi_storage_pool": "local-lvm",
"pre_enrolled_keys": true,
"efi_type": "4m"
},
"iso_file": "local:iso/Fedora-Server-dvd-x86_64-29-1.2.iso",
"http_directory": "config",
"boot_wait": "10s",
"boot_command": [
"<up><tab> ip=dhcp inst.cmdline inst.ks=http://{{.HTTPIP}}:{{.HTTPPort}}/ks.cfg<enter>"
],
"ssh_username": "root",
"ssh_timeout": "15m",
"ssh_password": "packer",
"unmount_iso": true,
"template_name": "fedora-29",
"template_description": "Fedora 29-1.2, generated on {{ isotime \"2006-01-02T15:04:05Z\" }}"
}
]
}
Cách làm này hoàn toàn có thể được áp dụng cho file cấu hình preseed (preseed.cfg) của Debian hoặc Ubuntu. Tương tự như cách bạn đã thực hiện cho file Kickstart, bạn có thể sử dụng file preseed để tự động hóa quá trình cài đặt của hệ điều hành Debian hoặc Ubuntu.
Bước đầu tiên, bạn cần cung cấp file preseed và đặt nó trong thư mục hoặc thư mục cấu hình HTTP mà máy chủ HTTP của Packer phục vụ. Sau đó, bạn chỉ cần cung cấp URL của file preseed trong lệnh “boot_command” giống như bạn đã làm với file Kickstart.
Ví dụ, để trỏ đúng đến file preseed.cfg
và user-data.yml
trong thư mục http
như trong cây thư mục của bạn, bạn cần cấu hình “boot_command” để phản ánh đúng đường dẫn. Dưới đây là cách bạn có thể sửa lại lệnh “boot_command”:
Cấu trúc file và thư mục.
.
├── http
│ ├── authorized_keys
│ ├── id_rsa
│ ├── meta-data
│ ├── preseed.cfg
│ └── user-data.yml
└── ubuntu20.pkr.hcl
Chỉnh sửa boot_command.
"boot_command": [
"<esc><esc><enter><wait>",
"preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/http/preseed.cfg ",
"debian-installer=en_US auto locale=en_US kbd-chooser/method=us ",
"hostname={{ .Name }} ",
"fb=false debconf/frontend=noninteractive ",
"keyboard-configuration/modelcode=SKIP keyboard-configuration/layout=USA ",
"keyboard-configuration/variant=USA console-setup/ask_detect=false ",
"initrd=/install/initrd.gz -- <enter>",
"apt install wget -y",
"wget http://{{ .HTTPIP }}:{{ .HTTPPort }}/http/user-data.sh -O /tmp/user-data.sh",
"chmod +x /tmp/user-data.sh",
"/tmp/user-data.sh"
]
Trong ví dụ trên, dòng “preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/http/preseed.cfg” chỉ định URL của file preseed để cài đặt Debian hoặc Ubuntu. File preseed này sẽ chứa tất cả các tùy chọn cài đặt và cấu hình tương tự như Kickstart.
Và dòng “wget http://{{ .HTTPIP }}:{{ .HTTPPort }}/http/user-data.sh -O /tmp/user-data.sh” chúng ta sẽ dùng wget để download file user-data này về /tmp trong máy ảo và chạy nó.
Với cách này, bạn có thể tự động hóa quá trình cài đặt của Debian hoặc Ubuntu bằng cách cung cấp file preseed thông qua máy chủ HTTP của Packer.
Lưu ý, hướng dẫn preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/http/preseed.cfg
và autoinstall ds=nocloud-net;s=http://{{ .HTTPIP }}:{{ .HTTPPort }}/http/preseed.cfg
đều liên quan đến cách bạn cung cấp file cấu hình preseed cho quá trình cài đặt của Ubuntu.
- Hướng dẫn
preseed/url=
: Trong hướng dẫn này, bạn đang sử dụng URL của file preseed trực tiếp thông qua tùy chọnpreseed/url
. Điều này đơn giản là bạn đang trỏ trực tiếp đến file preseed thông qua đường dẫn URL và sử dụng cài đặt mặc định của Ubuntu. - Hướng dẫn
autoinstall ds=nocloud-net;s=
: Trong hướng dẫn này, bạn đang sử dụng gói cài đặt “nocloud-net” để thực hiện quá trình cài đặt tự động (autoinstall). Gói này cho phép bạn cung cấp file cấu hình preseed thông qua đường dẫn HTTP. Tùy chọnds=nocloud-net
chỉ định sử dụng gói “nocloud-net”, vàs=http://{{ .HTTPIP }}:{{ .HTTPPort }}/http/preseed.cfg
là đường dẫn URL đến file preseed.
Cả hai hướng dẫn đều đang thực hiện cùng một công việc, đó là cung cấp file cấu hình preseed qua HTTP. Lựa chọn sử dụng một trong hai phụ thuộc vào cách bạn muốn cấu hình hệ thống cụ thể của mình hoặc tùy theo yêu cầu của công việc cụ thể.