Learn Chef Rally 學習筆記 part6 — 初始化及更新 node

Luyo
Luyo
Aug 23, 2017 · 21 min read

本文記錄 Learn Chef Rally 以下章節的學習歷程:

[Bootstrap your node]

回憶一下在最早的章節學過的 chef-client,是裝在 node 上的指令,可以套用 cookbooks 來定義這個 node 應該要長成什麼樣子。

而對一個 node 做「安裝 chef-client」並且「向 Chef server 報到」的這個流程,Chef 把它稱做 bootstrapping

這一個章節我們將會 bootstrap 一個 node,並將 learn_chef_httpd 這個 cookbook 套用在它上面。

bootstrapping 的指令是 knife bootstrap ,因為這個指令是從工作站去對 Chef server 下的,而 Chef server 會需要 node 的登入權限,所以必須將 node 的帳密或密鑰帶入 knife bootstrap 的參數之中。Chef 推薦使用密鑰,因其是比較安全的選擇。

使用密鑰做 bootstrap

指令長這樣:

$ knife bootstrap ADDRESS --ssh-user USER --sudo --identity-file IDENTITY_FILE --node-name node1-centos --run-list 'recipe[learn_chef_httpd]'

把其中的 ADDRESSUSERIDENTITY_FILE 換成自己的,執行後結果如下:

$ knife bootstrap 13.229.51.21 --ssh-user centos --sudo --identity-file ~/.ssh/test.pem --node-name node1-centos --run-list 'recipe[learn_chef_httpd]'
Creating new client for node1-centos
Creating new node for node1-centos
Connecting to 13.229.51.21
13.229.51.21 -----> Installing Chef Omnibus (-v 13)
13.229.51.21 downloading https://omnitruck-direct.chef.io/chef/install.sh
13.229.51.21 to file /tmp/install.sh.9145/install.sh
13.229.51.21 trying curl...
13.229.51.21 el 7 x86_64
13.229.51.21 Getting information for chef stable 13 for el...
13.229.51.21 downloading https://omnitruck-direct.chef.io/stable/chef/metadata?v=13&p=el&pv=7&m=x86_64
13.229.51.21 to file /tmp/install.sh.9151/metadata.txt
13.229.51.21 trying curl...
13.229.51.21 sha1 d3d26412b6304c92f72749d00e62e0191ceada05
13.229.51.21 sha256 fe051b504856a74ccce1fd23ff92c296506cb8292a3933c71069ae915e7a4a00
13.229.51.21 url https://packages.chef.io/files/stable/chef/13.3.42/el/7/chef-13.3.42-1.el7.x86_64.rpm
13.229.51.21 version 13.3.42
13.229.51.21 downloaded metadata file looks valid...
13.229.51.21 downloading https://packages.chef.io/files/stable/chef/13.3.42/el/7/chef-13.3.42-1.el7.x86_64.rpm
13.229.51.21 to file /tmp/install.sh.9151/chef-13.3.42-1.el7.x86_64.rpm
13.229.51.21 trying curl...
13.229.51.21 Comparing checksum with sha256sum...
13.229.51.21 Installing chef 13
13.229.51.21 installing with rpm...
13.229.51.21 警告:/tmp/install.sh.9151/chef-13.3.42-1.el7.x86_64.rpm: 表頭 V4 DSA/SHA1 Signature, key ID 83ef826a: NOKEY
13.229.51.21 正在準備… ################################# [100%]
13.229.51.21 Updating / installing...
13.229.51.21 1:chef-13.3.42-1.el7 ################################# [100%]
13.229.51.21 Thank you for installing Chef!
13.229.51.21 Starting the first Chef Client run...
13.229.51.21 Starting Chef Client, version 13.3.42
13.229.51.21 resolving cookbooks for run list: ["learn_chef_httpd"]
13.229.51.21 Synchronizing Cookbooks:
13.229.51.21 - learn_chef_httpd (0.1.0)
13.229.51.21 Installing Cookbook Gems:
13.229.51.21 Compiling Cookbooks...
13.229.51.21 Converging 3 resources
13.229.51.21 Recipe: learn_chef_httpd::default
13.229.51.21 * yum_package[httpd] action install
13.229.51.21 - install version 2.4.6-45.el7.centos.4 of package httpd
13.229.51.21 * service[httpd] action enable
13.229.51.21 - enable service service[httpd]
13.229.51.21 * service[httpd] action start
13.229.51.21 - start service service[httpd]
13.229.51.21 * template[/var/www/html/index.html] action create
13.229.51.21 - create new file /var/www/html/index.html
13.229.51.21 - update content in file /var/www/html/index.html from none to ef4ffd
13.229.51.21 --- /var/www/html/index.html 2017-08-23 16:12:52.612599519 +0000
13.229.51.21 +++ /var/www/html/.chef-index20170823-9222-19jv4ip.html 2017-08-23 16:12:52.612599519 +0000
13.229.51.21 @@ -1 +1,6 @@
13.229.51.21 +<html>
13.229.51.21 + <body>
13.229.51.21 + <h1>hello world</h1>
13.229.51.21 + </body>
13.229.51.21 +</html>
13.229.51.21 - restore selinux security context
13.229.51.21
13.229.51.21 Running handlers:
13.229.51.21 Running handlers complete
13.229.51.21 Chef Client finished, 4/4 resources updated in 37 seconds

這樣就灌好一台 web server 了,對我這個 DevOps 的新手來說,覺得實在好恐怖。

用帳密做 bootstrap

就是把參數改掉用帳密如下:

$ knife bootstrap ADDRESS --ssh-user USER --ssh-password 'PASSWORD' --sudo --use-sudo-password --node-name node1-centos --run-list 'recipe[learn_chef_httpd]'

Bootstrap a local virtual machine 的部分目前用不到,跳過。

如果以上的指令失敗,有幾個可能的原因,除錯方法如下:

  • 確認目前執行 knife 指令所在的目錄在 learn-chef 或其子目錄底下
  • 確認 learn-chef/.chef 目錄存在,且其內有 knife.rb 及 RSA private key file
  • 確認 node 的 IP 正確且網路有通
  • 確認指令中使用的帳號具有 sudo 權限
  • 確認 node 的 22, 80, 443 這個 port 都有開啟

knife bootstrap 的文件在此,有比較詳細的參數說明。

確認結果

據說剛剛下完指令後發生了兩件事。第一,這個 node 跟 Chef server 之間做好了關聯,可以用 knife node list 確認:

$ knife node list
node1-centos

然後可以用 knife node show 觀看詳細的 node 資訊:

$ knife node show node1-centos
Node Name: node1-centos
Environment: _default
FQDN: ip-172-31-21-70.ap-southeast-1.compute.internal
IP: 13.229.51.21
Run List: recipe[learn_chef_httpd]
Roles:
Recipes: learn_chef_httpd, learn_chef_httpd::default
Platform: centos 7.3.1611
Tags:

第二件事是這個 node 去向 Chef server 做了初始的報到動作,並執行了 learn_chef_httpd 這個 cookbook,這是因為我們剛剛加了 --run-list learn_chef_httpd 這個參數。

現在可以來確認一下這個 node 的 web server 有沒有正常運作:

$ curl 13.229.51.21
<html>
<body>
<h1>hello world</h1>
</body>
</html>

已確認 web server 正常回應囉。

測驗

Which of the following most completely describes what happens during the bootstrap process?

  • The Chef client is installed on the node.
  • The node checks in with the Chef server for the first time.
  • The Chef client is installed on the node and the node then checks in with the Chef server.

Which argument to the knife bootstrap command specifies your node's run-list?

  • --run-list
  • --run_list
  • --cookbooks

答案是 3, 1。


[Update your node’s configuration]

要點:
1. 你可以用 knife bootstrap 建立 node 與 Chef server 的關聯並且做初始的報到動作,這個程序叫做 bootstrapping,是一個一次性的動作
2. 當 cookbook 有更動的時候,可以用 knife ssh 指令去更新 node 的設定。

Chef 可以提供 node 的資訊給 cookbooks,這裡的範例會將 node 的 FQDN 顯示在網頁上。

更新 HTML template

當你對一個 node 做完 bootstrap,Chef server 會產生一個叫 node object 的東西,它會包含一些關於這個 node 的屬性資訊,並存放於 Chef server 上。當一個 recipe 在 node 上跑起來的時候,Chef 程式就會回去 Chef server 上把這個 node 的屬性叫出來,並放入進 node 物件裡,我們就可以在 Chef recipes 之中去存取這些資訊。

現在先來更新 template 檔案 learn_chef_httpd/templates/index.html.erb

<html>
<body>
<h1>hello from <%= node['fqdn'] %></h1>
</body>
</html>

更新 cookbook 的 version metadata

在上傳一個修改過後的 cookbook 到 Chef server 之前,最好是每次都可以檢查一下 cookbook 的 version metadata,確保每個版本跟功能的記載無誤。

cookbook 的版本資訊會寫在 metadata.rb 之中,當你執行 chef generate cookbook 指令產生 cookbook 的時候,初始的版本會被訂為 0.1.0。用 cat 看一下 learn_chef_httpd/metadata.rb 的內容:

$ cat metadata.rb
name 'learn_chef_httpd'
maintainer 'The Authors'
maintainer_email 'you@example.com'
license 'all_rights'
description 'Installs/Configures learn_chef_httpd'
long_description 'Installs/Configures learn_chef_httpd'
version '0.1.0'
issues_url 'https://github.com/learn-chef/learn_chef_httpd/issues' if respond_to?(:issues_url)
source_url 'https://github.com/learn-chef/learn_chef_httpd' if respond_to?(:source_url)

可以看到 version 用前是 0.1.0。大部分 Chef cookbooks 的版號原則上會按照 Semantic Versioning 的原則來命名,也就是 MAJOR.MINOR.PATCH。

而剛剛我們更新了 HTML template,可以算是一個功能上的 minor change,所以我們可以將 metadata.rb 裡的 version 更新為 0.2.0:

version '0.2.0'

cookbook 版號的說明文件:https://docs.chef.io/cookbook_versions.html

上傳 cookbook 至 Chef server

執行上傳指令:

$ knife cookbook upload learn_chef_httpd
Uploading learn_chef_httpd [0.2.0]
Uploaded 1 cookbook.

在 node 上跑 cookbook

現在更新過的 cookbook 已經被傳上 Chef server 了,我們接著可以在 node 上跑 chef-client 指令,它會將這個 node 的 run-list 裡所列的最新版本的 cookbook 從 Chef server 上 pull 下來,然後套用 run-list 在這個 node 上。

若要在 node 上執行 chef-client,最基本的就是 ssh 進去 node 裡下 chef-client 指令。但既然我是們在學 DevOps 當然不能用這麼傻逼的方法!

Chef 提供比較厲害的方法叫做 knife ssh 指令,它可以一次讓多個 node 去執行 chef-client 指令。

更厲害的是 knife ssh 除了用 IP 以外,還可以用 search query 去指定要連到哪些機器去下指令,它提供了多種搜尋的 patterns,還可以包含多種搜尋條件。

knife bootstrap 一樣,我們可以用帳密或密鑰來做 ssh 連線。

以密鑰連線更新 node

指令的基本型態長這樣,要自己把 USERIDENTITY_FILE 換掉:

$ knife ssh 'name:node1-centos' 'sudo chef-client' --ssh-user USER --identity-file IDENTITY_FILE --attribute ipaddress

BUT!如果 node 機器是開在 Amazon EC2 或 Microsoft Azure 或 Google Compute Engine 這幾個平台上,就要把 --attribute 換成對應的值:

EC2 — cloud.public_hostname
Azure — cloud.public_ip
GCP — cloud_v2.public_ipv4

我的機器是開在 EC2 上,所以指令就會長這樣:

$ knife ssh 'name:node1-centos' 'sudo chef-client' --ssh-user centos --identity-file ~/.ssh/test.pem --attribute cloud.public_hostname
ec2-13-229-51-21.ap-southeast-1.compute.amazonaws.com Starting Chef Client, version 13.3.42
ec2-13-229-51-21.ap-southeast-1.compute.amazonaws.com resolving cookbooks for run list: ["learn_chef_httpd"]
...(略)
ec2-13-229-51-21.ap-southeast-1.compute.amazonaws.com + <h1>hello from ip-172-31-21-70.ap-southeast-1.compute.internal</h1>
...(略)

可以看到原本的 hello world 被換成 hello from ip-172-31-21-70.ap-southeast-1.compute.internal 了。

'name:node1-centos' 的部分是所謂的 “search query”,它會回傳名稱叫 “node1-centos” 的所有 nodes。

但實務上一個 name 應該只會對應一個 node,所以我們可以進一步用 'name:node1-*' 這樣的 wildcard parttern 來選出所有以 “node1-” 開頭的 nodes。

不過很好奇用 --attribute的值用 cloud.public_hostname 跟用 ipaddress 有什麼不一樣,所以再下一次指令來實驗一下:

$ knife ssh 'name:node1-centos' 'sudo chef-client' --ssh-user centos --identity-file ~/.ssh/test.pem --attribute ipaddress
172.31.21.70 Starting Chef Client, version 13.3.42
172.31.21.70 resolving cookbooks for run list: ["learn_chef_httpd"]
...(略)

看起來是都可以 work 的,差別是前者開頭寫的是 public dns,後者開頭是寫 private ip address。

接下來就解釋了,--attribute 是用來告訴 knife 要用什麼來開啟 ssh 連線。預設值是 FQDN,但因為你的 node 不一定會有可解析的 FQDN,如果沒有的話就可以用 ipaddress 去對應到 private IP 來建立連線。

但用 cloud.public_hostname 的好處這邊並沒有解釋,再實驗了一下不帶 --attribute 參數會怎樣:

$ knife ssh 'name:node1-centos' 'sudo chef-client' --ssh-user centos --identity-file ~/.ssh/test.pem
ec2-13-229-51-21.ap-southeast-1.compute.amazonaws.com Starting Chef Client, version 13.3.42
ec2-13-229-51-21.ap-southeast-1.compute.amazonaws.com resolving cookbooks for run list: ["learn_chef_httpd"]
...(略)

結果前面的 host 跟第一次帶 cloud.public_hostname 是一樣的,應該是因為這台機器的 FQDN 跟 public DNS是一樣的吧?

NOTE: node attributes 的文件 — https://docs.chef.io/attributes.html#automatic-ohai。但看了一下,發現這頁並沒有提到 cloud.public_hostname 這系列的說明。

確認結果

最後來看一下現在的 index 長什麼樣子:

$ curl 172.31.21.70
<html>
<body>
<h1>hello from ip-172-31-21-70.ap-southeast-1.compute.internal</h1>
</body>
</html>

結果有趣了,這裡顯示的結果 node[‘fqdn’] 居然是 private DNS!

好吧,只好再來試一次,將 --attribute 內的值改成 fqdn 看會發生什麼事:

$ knife ssh 'name:node1-centos' 'sudo chef-client' --ssh-user centos --identity-file ~/.ssh/test.pem --attribute fqdn
ip-172-31-21-70.ap-southeast-1.compute.internal Starting Chef Client, version 13.3.42
ip-172-31-21-70.ap-southeast-1.compute.internal resolving cookbooks for run list: ["learn_chef_httpd"]
...(略)

真相大白了,FQDN 的確是 EC2 instance 的 private DNS 而不是 public DNS!而且在這個 case 中 --attribute 的預值不是教學中說的 fqdn 而是 cloud.public_hostname

測驗

What is a node object?

  • Any system that is managed by Chef.
  • An object on the Chef server that contains attributes that describe a node.
  • The more formal name for “node”.

Where do you change a cookbook’s version?

  • In the metadata.rb file.
  • In the cookbook itself.
  • In the template file.

True or False: A template enables you to provide placeholders that are replaced with their values when chef-client runs.

  • True.
  • False.

答案是 2, 1, 1。


verybuy-dev

VeryBuy 研發手札

)
Luyo

Written by

Luyo

Founder, Developer of VeryBuy — https://www.verybuy.cc

verybuy-dev

VeryBuy 研發手札

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade