

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 部署配方
<a name="create-custom-deploy"></a>

**重要**  
 AWS OpsWorks Stacks 此服務已於 2024 年 5 月 26 日終止，並已針對新客戶和現有客戶停用。我們強烈建議客戶盡快將其工作負載遷移至其他解決方案。如果您對遷移有任何疑問，請透過 [AWS re：Post](https://repost.aws/) 或透過 [AWS Premium Support](https://aws.amazon.com/support) 聯絡 AWS 支援 團隊。

部署配方會指派給 layer 的部署[生命週期](workingcookbook-events.md)事件。每當您部署應用程式時，它通常會在所有堆疊的執行個體上發生，但您可以選擇將事件限制為僅指定執行個體。安裝配方完成後， OpsWorks 堆疊也會在新執行個體上執行部署配方。部署配方的主要用途是從儲存庫將程式碼和相關檔案部署到應用程式伺服器 layer 的執行個體。但是，您通常也需要在其他 layer 執行部署配方。這可讓那些 layer 的執行個體進行像是更新其組態以適應新部署之應用程式等行為。當您實作部署配方時，請記得部署事件不一定表示應用程式正部署到執行個體。它可能只是一項針對應用程式正在部署到堆疊中其他執行個體的通知，讓執行個體進行任何必要的更新。配方必須要能適當地進行回應，其可能不會進行任何行為。

OpsWorks Stacks 會自動將標準應用程式類型的應用程式部署到對應的內建應用程式伺服器層。若要將應用程式部署到自訂 layer，您必須實作自訂部署配方，從儲存庫將應用程式檔案下載到執行個體上的適當位置。但是，您通常可以藉由使用內建的[部署技術指南](https://github.com/aws/opsworks-cookbooks/tree/release-chef-11.4/deploy)限制您必須撰寫的程式碼數量，處理一部分的部署。例如，若您將您的檔案存放在其中一個支援的儲存庫，內建技術指南可以處理從儲存庫將檔案下載到 layer 的執行個體的詳細資訊。

`tomcat::deploy` 技術指南用於指派給部署生命週期事件。

```
include_recipe 'deploy'

node[:deploy].each do |application, deploy|
  opsworks_deploy_dir do
    user deploy[:user]
    group deploy[:group]
    path deploy[:deploy_to]
  end

  opsworks_deploy do
    deploy_data deploy
    app application
  end
...
```

`tomcat::deploy` 配方針對部署中非應用程式限定的一部分使用內建的部署技術指南。`deploy` 配方 (為內建 `deploy::default` 配方的速記) 是一種內建的配方，可根據 `deploy` 屬性的資料處理設定使用者、群組等詳細資訊。

配方使用兩個內建 Chef 定義 (`opsworks_deploy_dir` 和 `opworks_deploy`) 安裝應用程式。

`opsworks_deploy_dir` 定義會根據應用程式部署 JSON 的資料設定目錄結構。定義基本上是封裝資源定義的便利方式，位於技術指南的 `definitions` 目錄中。配方可像資源一樣使用定義，但定義本身不具有關聯的提供者，只有包含在定義內的資源。您可以在配方中定義變數，該變數會傳遞到基礎資源定義。`tomcat::deploy` 配方會根據部署 JSON 的資料設定 `user`、`group` 和 `path` 變數。他們會傳遞到定義的 [directory 資源](https://docs.chef.io/chef/resources.html#directory)，該資源會管理目錄。

**注意**  
您部署應用程式的使用者和群組由 `[:opsworks][:deploy_user][:user]` 和 `[:opsworks][:deploy_user][:group]` 屬性決定，這兩個屬性的定義位於[內建部署技術指南的 `deploy.rb` 屬性檔案](https://github.com/aws/opsworks-cookbooks/blob/release-chef-11.4/deploy/attributes/deploy.rb)中。`[:opsworks][:deploy_user][:user]` 的預設值為 `deploy`。`[:opsworks][:deploy_user][:group]` 的預設值視執行個體的作業系統而定。  
若是 Ubuntu 執行個體，預設群組為 `www-data`。
對於使用 Nginx 和 Unicorn 的 Rails App Server layer 成員的 Amazon Linux 執行個體，預設群組為 `nginx`。
若是其他所有 Amazon Linux 執行個體，預設群組為 `apache`。
您可以透過使用自訂 JSON 或自訂屬性檔案覆寫適當的屬性，來變更設定。如需詳細資訊，請參閱[覆寫屬性](workingcookbook-attributes.md)。

其他定義 (`opsworks_deploy`) 會根據 `deploy` 屬性的資料，處理檢查來自儲存庫的應用程式程式碼和相關檔案，以及將他們部署到執行個體的詳細資訊。您可以針對任何應用程式類型使用此定義。部署詳細資訊 (例如目錄名稱) 會在主控台中或透過 API 指定，並置放於 `deploy` 屬性中。但是，`opsworks_deploy` 僅適用於四種[支援的儲存庫類型](workingcookbook-installingcustom-repo.md)：Git、Subversion、S3 和 HTTP。若您希望使用不同的儲存庫類型，您必須自行實作程式碼。

您會在 Tomcat `webapps` 目錄中安裝應用程式的檔案。典型的做法是將檔案直接複製到 `webapps`。不過， OpsWorks Stacks 部署的設計可在執行個體上保留最多五個版本的應用程式，因此您可以視需要轉返至較早的版本。 OpsWorks Stacks 因此會執行下列動作：

1. 將應用程式部署到名稱包含時間戳記的相異目錄，例如 `/srv/www/my_1st_jsp/releases/20130731141527`。

1. 建立連結到此唯一目錄，名為 `current` 的 symlink，例如 `/srv/www/my_1st_jsp/current`。

1. 若尚未存在，請從 `webapps` 目錄建立連結到步驟 2 中建立之 `current` symlink 的 symlink。

若您需要轉返至較早的版本，請修改 `current` symlink 指向包含適當時間戳記的相異目錄 (例如，變更 `/srv/www/my_1st_jsp/current` 的連結目標)。

`tomcat::deploy` 中間的區段會設定 symlink。

```
  ...
  current_dir = ::File.join(deploy[:deploy_to], 'current')
  webapp_dir = ::File.join(node['tomcat']['webapps_base_dir'], deploy[:document_root].blank? ? application : deploy[:document_root])

  # opsworks_deploy creates some stub dirs, which are not needed for typical webapps
  ruby_block "remove unnecessary directory entries in #{current_dir}" do
    block do
      node['tomcat']['webapps_dir_entries_to_delete'].each do |dir_entry|
        ::FileUtils.rm_rf(::File.join(current_dir, dir_entry), :secure => true)
      end
    end
  end

  link webapp_dir do
    to current_dir
    action :create
  end
  ...
```

配方首先會建立兩個變數 (`current_dir` 和 `webapp_dir`) 分別代表 `current` 和 `webapp`。它接著會使用 `link` 資源將 `webapp_dir` 連結到 `current_dir`。Stacks OpsWorks `deploy::default`配方會建立此範例不需要的一些 stub 目錄，因此摘錄的中間部分會將其移除。

`tomcat::deploy` 的最終部分會重新啟動 Tomcat 服務 (若必要的話)。

```
  ...
  include_recipe 'tomcat::service'

  execute 'trigger tomcat service restart' do
    command '/bin/true'
    not_if { node['tomcat']['auto_deploy'].to_s == 'true' }
    notifies :restart, resources(:service => 'tomcat')
  end
end

include_recipe 'tomcat::context'
```

配方首先會執行 `tomcat::service`，確保已為此 Chef 執行定義服務。它接著會使用 [execute 資源](https://docs.chef.io/chef/resources.html#execute)通知服務重新啟動，但只有在 `['tomcat']['auto_deploy']` 設為 `'true'` 時才會這麼做。否則，Tomcat 會接聽其 `webapps` 目錄中的變更，使明確重新啟動 Tomcat 服務為非必要事項。

**注意**  
`execute` 資源不會執行任何實際操作。`/bin/true` 僅是一個 dummy shell 指令碼，只會傳回成功代碼。在此使用它的目的只是為了方便產生重新啟動通知。如先前所述，使用通知可確保服務不會太頻繁的重新啟動。

最後，`tomcat::deploy` 會執行 `tomcat::context`，更新 web 應用程式內容組態檔案 (若您有變更後端資料庫的話)。