Cloud-init是什麼
Cloud-init是開源的雲初始化程序,能夠對新創建彈性雲服務器中指定的自定義信息(主機名、密鑰和用戶數據等)進行初始化配置。通過Cloud-init進行彈性雲服務器的初始化配置,將對您使用彈性雲服務器、鏡像服務和彈性伸縮產生影響。簡單地講,cloud-init是一個Linux虛擬機的初始化工具,被廣泛應用在AWS和OpenStack等雲平臺中,用於在新建的虛擬機中進行時間設置、密碼設置、擴展分區、安裝軟件包等初始化設置。
官方討論:http://cloudinit.readthedocs.io/en/latest/topics/examples.html
對鏡像服務的影響
爲了保證使用私有鏡像新創建的彈性雲服務器可以自定義配置,您需要在創建私有鏡像前先安裝Cloud-init/Cloudbase-init。
如果是Windows操作系統,需下載並安裝Cloudbase-init。
如果是Linux操作系統,需下載並安裝Cloud-init。
在鏡像上安裝Cloud-init/Cloudbase-init後,即可在創建彈性雲服務器時,按照用戶的需要自動設置彈性雲服務器的初始屬性。
對彈性雲服務器的影響
在創建彈性雲服務器時,如果選擇的鏡像支持Cloud-init特性,此時,您可以通過系統提供的“用戶數據注入”功能,注入初始化自定義信息(例如爲彈性雲服務器設置登錄密碼),完成彈性雲服務器的初始化配置。
支持Cloud-init特性後ZQ,彈性雲服務器的登錄方式會產生影響。
對於運行中的的彈性雲服務器,支持Cloud-init特性後,用戶可以通過查詢、使用元數據,對正在運行的彈性雲服務器進行配置和管理。
對彈性伸縮的影響
創建伸縮配置時,您可以使用“用戶數據注入”功能,指定彈性雲服務器的初始化自定義信息。如果伸縮組使用了該伸縮配置,則伸縮組新創建的彈性雲服務器會自動完成初始化配置。
對於已有的伸縮配置,如果其私有鏡像沒有安裝Cloud-init/Cloudbase-init,則使用該伸縮配置的伸縮組創建的彈性雲服務器在登錄時會受到影響。
使用須知
使用Cloud-init特性時,需開啓彈性雲服務器所在VPC中子網的DHCP。
使用Cloud-init特性時,安全組出方向規則需滿足如下要求:
協議:TCP
端口範圍:80
遠端地址:169.254.0.0/16
說明:
如果您使用的是默認安全組出方向規則,則已經包括瞭如上要求,可以正常訪問元數據。默認安全組出方向規則爲:
協議:ANY
端口範圍:ANY
遠端地址:0.0.0.0/0
cloud-init簡介及組件說明
介紹:
cloud-init是專爲雲環境中虛擬機的初始化而開發的工具,它從各種數據源讀取相關數據並據此對虛擬機進行配置。
向一臺數據服務器獲取元數據(meta data)和用戶數據(user data),前者是指VM的必要信息,
如主機名、網絡地址等;後者是系統或用戶需要的數據和文件,如用戶組信息、啓動腳本等。
當cloud-init獲取這些信息後,開始使用一些模塊對數據進行處理,如新建用戶、啓動腳本等。常見的配置包括:設定虛擬機的hostname、hosts文件、設定用戶名密碼、更新apt -get的本地緩存、調整文件系統的大小(注意不是調整分區的大小)等。
工作原理:
首先,數據服務器開啓HTTP服務,cloud-init會向數據服務器發送請求,確認數據源模塊,依次獲取版本、數據類型和具體數據內容信息。
功能:
用戶可配置性
可以通過用戶數據配置Cloud-init的行爲。
用戶數據可以給用戶在實例啓動時輸出
例如,這可以通過--user-data或--user-data-file參數到ec2-run-instances
特徵
設置默認域
設置一個實例的主機名
生成實例SSH祕鑰
將SSH密鑰添加到用戶的.ssh / authorized_keys,以便他們可以登錄
設置臨時掛載點
配置網絡設備
可用性:
它目前安裝在Ubuntu Cloud Images中,還有在EC2,Azure,GCE和許多其他雲端上提供的官方Ubuntu映像。
支持諸多linux發行版本,ubuntu、fedora、debian、rhel、centos等等
Gzip壓縮:
發現gzip壓縮的內容將被解壓縮。 然後將使用未壓縮的數據,如同未壓縮的數據一樣。
這通常是有用的,因爲用戶數據被限制在〜16384 [1]個字節。
用戶數據:
配置文件(Cloud Config Data),類型爲Content-Type: text/cloud-config,系統配置文件,如管理用戶等,與/etc/cloud下的cloud.cfg最後合併配置項
啓動任務(Upstart Job),類型爲Content-Type: text/upstart-job,建立Upstart的服務
用戶數據腳本(User-Data Script),類型爲Content-Type: text/x-shellscript,用戶自定義的腳本,在啓動時執行
包含文件(Include File),類型爲Content-Type: text/x-include-url,該文件內容是一個鏈接,這個鏈接的內容是一個文件, (Cloud Boothook),類型爲Content-Type: text/cloud-boothook
壓縮內容( Gzip Compressed Content),
處理句柄(Part Handler),類型爲Content-Type: text/part-handler,內容爲python腳本,根據用戶數據文件的類型做相應的處理
多部分存檔(Mime Multi Part archive),當客戶端需要下載多個上述用戶數據文件時,可用Mime編碼爲Mime Multi Part archive一次下載
目錄結構:
cloud-init 是 linux 的一個工具,當系統啓動時,cloud-init 可從 nova metadata 服務或者 config drive 中獲取 metadata,完成包括但不限於下面的定製化工作:
- 設置默認語言環境
- 設置實例主機名
- 添加 ssh keys到 .ssh/authorized_keys
- 設置用戶密碼
- 配置網絡安裝軟件包
啓動階段:
Generator
Local
Network
Config
Final
爲了實現 instance 定製工作,cloud-init 會按 4 個階段執行任務:
- local
- init
- config
- final
cloud-init 安裝時會將這 4 個階段執行的任務以服務的形式註冊到系統中,比如在 systemd 的環境下,我們能夠看到這4個階段分別對應的服務:
- local - cloud-init-local.service
- init - cloud-init.service
- config - cloud-config.service
- final - cloud-final.service
當在systemd下引導時,將運行一個生成器,以確定cloud-init.target是否應包含在引導目標中。
默認情況下,此生成器將啓用cloud-init。 它不會啓用cloud-init,如果:
Generator:
當在systemd下引導時,將運行一個生成器,以確定cloud-init.target是否應包含在引導目標中。
默認情況下,此生成器將啓用cloud-init。 它不會啓用cloud-init,如果:A file exists: /etc/cloud/cloud-init.disabled
/proc/cmdline contains cloud-init=disabled
local:
cloud-init-local.service
找到本地的數據源
對系統應用及網絡進行配置
網絡配置:
數據源
網卡dhcp
禁用網絡
Network:
cloud-init.service
http
解壓gzip
格式化磁盤、分區
bootcmd
Config:
cloud-config.service
配置模塊modules
Final:
cloud-final.service
啓動最後階段rc.local
包的安裝
配置管理插件、chef、puppet
用戶腳本,runcmd
數據源:
數據源是cloud-init的配置數據源,通常來自用戶(也稱爲用戶數據)或來自創建配置驅動器(也稱爲元數據)的堆棧。
型的用戶數據將包括文件,yaml和shell腳本,而典型的元數據將包括服務器名稱,實例ID,
顯示名稱和其他雲具體細節。
由於有多種方式來提供這些數據(每個雲解決方案似乎都喜歡自己的方式)內部創建了一個數據源抽象類,
以允許單一方式訪問不同的雲系統方法,以通過典型的子類使用提供此數據。
支持的方式:
Alt Cloud:
RHEVm
vSphere
Azure
CloudSigma
CloudStack
Config Drive
Digital Ocean
Amazon EC2
MAAS
NoCloud
OpenNebula
OVF
SmartOS Datasource
OpenStack:
metadata_urls http://169.254.169.254返回200ok
max_wait default 1
timeout default 10
retries default 5重試次數
#cloud-config
datasource:
OpenStack:
metadata_urls: ["http://169.254.169.254"]
max_wait: -1
timeout: 10
retries: 5
Logging:
支持本地和遠程日誌記錄是通過 python 的內置-在日誌記錄配置並通過雲 init rsyslog 模塊可配置、
默認cloud-init將其輸出配置從/etc/cloud/cloud.cfg.d/05_logging.cfg加載
默認配置將stdout和stderr從所有cloud-init階段引導到/var/log/cloud-init-output.log
Modules:
Apt Configure配置ubuntu 源列表
Bootcmd:在引導過程的早期運行命令,用於在引導過程中不能完成的
Byobu:該模塊控制是否啓用或禁用系統範圍以及默認系統用戶
CA Certs:添加CA證書
Chef:安裝chef client
Debug:幫助調試內部數據結構
Disable EC2 Metadata:默認禁用,該模塊通過拒絕發送到169.254.169.254的路由,從而禁用ec2數據源。
Disk Setup:配置分區和文件系統
Emit Upstart:發出啓動配置,不需要配置
Fan:配置ubuntu網絡
Final Message:當cloud-init完成時輸出最終消息
version: cloud-init version版本
timestamp: time at cloud-init finish 完成耗時
datasource: cloud-init data source源數據
uptime: system uptime系統運行時間
Foo:示例顯示模塊結構,不做任何事情
Growpart:調整分區大小以填充可用磁盤空間
growpart:
mode: auto
devices: ["/"]
ignore_growroot_disabled: false
Grub Dpkg:配置哪個設備用作grub安裝的目標,默認情況下,此模塊應正常工作無須配置。
Keys to Console:控制哪些ssh密鑰可以寫入控制檯
出於安全考慮,可能不希望將ssh指紋和密鑰寫入控制檯。
爲了避免將ssh鍵的類型指紋寫入控制檯,可以使用ssh_fp_console_blacklist配置密鑰。
默認情況下,所有類型的鍵都將其指紋寫入控制檯。
爲了避免將密鑰類型的密鑰寫入控制檯,可以使用ssh_key_console_blacklist配置密鑰。
默認情況下,ssh-dss鍵不會寫入控制檯
Landscape:
Locale:配置系統區域設置並系統應用
LXD:
Mcollective:
Migrator:該模塊處理將舊版本的cloud-init數據移動到較新版本
Mounts:配置掛載點和交換文件
NTP:處理ntp配置
ntp:
pools:
- 0.company.pool.ntp.org
- 1.company.pool.ntp.org
- ntp.myorg.org
servers:
- my.ntp.server.local
- ntp.ubuntu.com
- 192.168.23.2
Package Update Upgrade Install:
更新,升級和安裝軟件包
此模塊允許在引導期間更新,升級或安裝軟件包
如果要安裝任何軟件包或執行升級,那麼軟件包緩存將首先更新。
如果軟件包安裝或升級需要重新啓動,則如果指定了package_reboot_if_required,則可以執行重新啓動。
可以提供要安裝的軟件包的列表。
列表中的每個條目可以是包名稱或具有兩個條目的列表,第一個是包名稱,第二個是要安裝的特定包版本。
Phone Home:
引導完成後,該模塊可用於將數據發佈到遠程主機, 可以發佈所有數據或發佈的密鑰列表。
Power State Change:
改變電源狀態
所有配置模塊都運行後,該模塊處理關機/重新啓動。
Puppet:
安裝、配置puppet
Resizefs:調;整文件系統的大小以使用分區上的所有可用空間。
Resolv Conf:
manage_resolv_conf: <true/false>
resolv_conf:
nameservers: ['8.8.4.4', '8.8.8.8']
searchdomains:
- foo.example.com
- bar.example.com
domain: example.com
options:
rotate: <true/false>
timeout: 1
Debian / Ubuntu默認情況下會使用resovlconf,同樣的RedHat也會使用sysconfig
RedHat Subscription:
通過用戶名和密碼或激活和組織註冊一個RedHat系統
Rsyslog:
此模塊使用rsyslog配置遠程系統日誌記錄
Runcmd:
在類似級別的rc.local上運行任意命令,並輸出到控制檯
所有的命令必須是正確的yaml,因此您必須引用yaml所符合的任何字符
runcmd:
- [ ls, -l, / ]
- [ sh, -xc, "echo $(date) ': hello world!'" ]
- [ sh, -c, echo "=========hello world'=========" ]
- ls -l /root
- [ wget, "http://example.org", -O, /tmp/index.html ]
如果項目是一個列表,它將被正確執行,就好像傳遞給execve()(以第一個arg爲命令)。
如果項目是一個字符串,它將被寫入一個文件並使用sh進行解釋
Salt Minion:配置公鑰和私鑰
Scripts Per Boot:運行啓動腳本
數據源中的scripts / per-boot目錄中的任何腳本都將在系統引導時運行。
Scripts Per Instance:實例運行腳本,系統引導時運行
Scripts Per Once:運行一次腳本
Scripts User:運行用戶腳本
該模塊運行所有用戶腳本。
用戶腳本未在數據源中的scripts目錄中指定,而是存在於實例配置中的腳本目錄中。
Scripts Vendor:數據源中腳本/供應商目錄中的任何腳本將在首次引導新實例時運行。
Seed Random:生成隨機祕鑰
Set Hostname:設置主機名和fqdn
Set Passwords:設置系統密碼,啓用或禁用ssh密碼認證。
chpasswd配置密鑰接受一個包含兩個密鑰中的一個的字典,即過期或列表。
如果expire被指定並設置爲false,那麼將使用password全局配置密鑰作爲所有用戶帳戶的密碼。
如果指定了過期密鑰,並設置爲true,則用戶密碼將過期,從而防止使用默認系統密碼。
ssh_pwauth: <yes/no/unchanged>
password: password1
chpasswd:
expire: <true/false>
chpasswd:
list: |
user1:password1
user2:RANDOM
user3:password3
user4:R
##
# or as yaml list
##
chpasswd:
list:
- user1:password1
- user2:RANDOM
- user3:password3
- user4:R
- user4:$6$rL..$ej...
SSH:該模塊處理ssh和ssh密鑰的大部分配置
SSH Authkey Fingerprints:爲每個用戶寫入授權密鑰的指紋記錄日誌
SSH Import Id:此模塊通過公鑰鑰匙服務器(通常是啓動板或github)使用ssh-import-id導入ssh密鑰
Timezone:設置系統時區
timezone: <timezone>
Update Etc Hosts:更新/etc/hosts
該模塊將根據config中指定的主機名/ fqdn更新/ etc / hosts的內容。
/ etc / hosts的管理使用manage_etc_hosts進行控制。
如果設置爲false,則cloud-init將不會管理/ etc / hosts
如果設置爲true或template,cloud-init將使用位於/etc/cloud/templates/hosts.tmpl中的模板生成/ etc / hosts。
如果manage_etc_hosts設置爲localhost,那麼cloud-init將不會完全重寫/ etc / hosts,而是確保/ etc / hosts中存在具有ip 127.0.1.1的fqdn的條目
manage_etc_hosts: <true/"template"/false/"localhost">
fqdn: <fqdn>
hostname: <fqdn/hostname>
Update Hostname:該模塊將更新系統主機名和fqdn。
preserve_hostname: <true/false>
fqdn: <fqdn>
hostname: <fqdn/hostname>
Users and Groups:配置用戶和組
groups:
- <group>: [<user>, <user>]
- <group>
users:
- default
- name: <username>
expiredate: <date>
gecos: <comment>
groups: <additional groups>
homedir: <home directory>
inactive: <true/false>
lock_passwd: <true/false>
no-create-home: <true/false>
no-log-init: <true/false>
no-user-group: <true/false>
passwd: <password>
primary-group: <primary group>
selinux-user: <selinux username>
shell: <shell path>
snapuser: <email>
ssh-authorized-keys:
- <key>
- <key>
ssh-import-id: <id>
sudo: <sudo config>
system: <true/false>
uid: <user id>
Write Files:
將任意內容寫入文件,可選擇設置權限。 內容可以用純文本或二進制格式指定。
可以指定使用base64或二進制gzip數據編碼的數據,並在寫入之前對其進行解碼。
write_files:
- encoding: b64
content: CiMgVGhpcyBmaWxlIGNvbnRyb2xzIHRoZSBzdGF0ZSBvZiBTRUxpbnV4...
owner: root:root
path: /etc/sysconfig/selinux
permissions: '0644'
- content: |
# My new /etc/sysconfig/samba file
SMDBOPTIONS="-D"
path: /etc/sysconfig/samba
- content: !!binary |
f0VMRgIBAQAAAAAAAAAAAAIAPgABAAAAwARAAAAAAABAAAAAAAAAAJAVAAAAAA
AEAAHgAdAAYAAAAFAAAAQAAAAAAAAABAAEAAAAAAAEAAQAAAAAAAwAEAAAAAAA
AAAAAAAAAwAAAAQAAAAAAgAAAAAAAAACQAAAAAAAAAJAAAAAAAAcAAAAAAAAAB
...
path: /bin/arch
permissions: '0555'
Yum Add Repo:
將yum存儲庫配置添加到/etc/yum.repos.d。
yum_repos:
<repo-name>:
baseurl: <repo url>
name: <repo name>
enabled: <true/false>
在本地KVM中使用cloud-init
本文主要研究在本地KVM虛擬機,也就是沒有云平臺的情況下,如何使用cloud-init進行初始化工作。示例虛擬機的操作系統是centos7.1。
安裝
在虛擬機內安裝cloud-init:
yum install cloud-init -y |
安裝完後,配置文件在/etc/cloud目錄,主配置文件爲/etc/cloud/cloud.cfg
DataSource
要讓cloud-init能夠順利完成初始化工作,必須把一些數據傳給cloud-init,例如讓cloud-init設置root密碼,必須要告訴cloud-init密碼是什麼。Cloud-init支持很多種數據來源,常見的有metadata service、config drive和nocloud等。
l metadata service提供一個可以獲取數據的url,例如OpenStack中的nova-api-metadat提供的http://169.254.169.254,虛擬機開機後cloud-init在完成網絡配置後,會向這個url發起請求。因此這種模式需要先配置好網絡;
l Config drive 把數據封裝進一個iso9660(也支持vfat,但是不常見)文件系統的鏡像中,然後把這個鏡像以光驅(ide接口)的形式掛載到虛擬機中,虛擬機開機後cloud-init會自動去該鏡像中獲取數據。文件結構一般如下:
openstack/ - 2012-08-10/ or latest/ - meta_data.json - user_data (not mandatory) - content/ - 0000 (referenced content files) - 0001 - .... ec2 - latest/ - meta-data.json (not mandatory) |
l Nocloud 這種模式與config drive類似,只是文件結構不同,一般由user-data和meta-data兩個文本文件構成。並且鏡像以普通磁盤(virtio接口)的方式掛載。
本文主要試驗nocloud模式。
封裝數據
製作鏡像需要cloud-localsd命令,默認沒有安裝,安裝命令如下:
yum install cloud-utils -y |
編寫user-data:
cat << EOF > my-user-data #cloud-config chpasswd: list: | root:123456 expire: false ssh_pwauth: true EOF |
cloud-init也支持多種數據格式,我們使用的是cloud-config格式,這種格式必須是以#cloud-config開頭的yaml格式。上面這段的意思是把root的密碼設置爲“123456”,然後配置ssh允許密碼登錄。
製作img:
cloud-localds -m local my-seed.img my-user-data |
-m指定的cloud-init的工作模式,local的意思是不需要依賴網絡,我們沒有使用metadata service,所以不需要網絡。
掛載數據
編輯虛擬機的libvirt xml配置文件,掛載鏡像:
<disk type='file' device='disk'> <driver name='qemu' type='raw' cache='none' io='native'/> <source file='/path/to/my-seed.img'/> <target dev='vdb' bus='virtio'/> <readonly/> </disk> |
修改cloud-init配置
在/etc/cloud/cloud.cfg最後一行添加以下內容,這句的意思是讓cloud-init接受NoCloud來源的數據:
datasource_list: ["NoCloud"] |
重啓虛擬機
在虛擬機內執行rm -rf /var/lib/cloud,不刪除這個目錄,cloud-init不會執行。
硬重啓虛擬機
virsh destroy vm virsh start vm |
虛擬機開機後,會發現root密碼變成了“123456”
查看數據
在虛擬機內mount /dev/vdb /mnt,可以查看數據的內容。
ls /mnt meta-data user-data cat user-data #cloud-config chpasswd: list: | root:123456 expire: false ssh_pwauth: true |
總結
本文測試了在無雲平臺管理的本地KVM虛擬機上使用cloud-init修改root密碼的功能。cloud-init還有很多功能和技術細節,後續會繼續研究。
更多應用參考
1、cloud-init的使用(cloud-init 的模塊衆多,功能很全,是實現 instance 定製的神器) - https://www.jianshu.com/p/f4fa583f022a
2、proxmox裏使用cloud-init和一些筆記 - 雲途主機 https://www.waimaospace.com/reed/414.html