ブログリレー

【OpsWorks】AWSサービスしりとりリレー 第6日目

はじめに

こんにちは、テクニカルサポートの甫立です。

2021年6月8日にディーネットがAWSアドバンストコンサルティングパートナーに昇格しました。
APNアドバンストコンサルティングパートナー昇格記念特設サイト

今後もテクニカルサポートとしてお客様に適切なサポートができるようAWSについて理解を深めていこうと思います。

また、ブログで毎日AWSサービス名でしりとりリレーも開催中で、本記事は6日目です。
前回の5日目シングルサインオン(SSO)でしたので、今回はOpsWorksをご紹介します。

OpsWorksはサーバ内のインフラ設定などをコードで管理できるサービスです。

同じIaC(Infrastructure as Code)のサービスとしてCloudFormationと混同してしまいそうですが、OpsWorksサーバ内のパッケージの構成などをコードで管理できるサービスなので、AWSサービスの他のリソースをコードで書いたりはしません。

今回はOpsWorksのOpsWorks for Chef Automateを使ってnginx環境を作成するまでの流れをハンズオン形式で書いてみました。

AWS OpsWorks for Chef Automateの構築は以下も参考にすると簡単にできますので参考にしてみてください。

AWS OPSWORKS FOR CHEF AUTOMATEを触ってみる(1)

AWS OPSWORKS FOR CHEF AUTOMATEを触ってみる(2)

準備

Cloudformationを実行

今回はサクッとCloudFormationでAWS OpsWorks for Chef Automateを構築してみます。
使用するテンプレートは以下です。

AWSTemplateFormatVersion: '2010-09-09'
Parameters:
  MyKeyPair:
    Description: 'Choose your keypair for ec2 instance'
    Type: AWS::EC2::KeyPair::KeyName
  Password:
    Description: 'Enter Chef password'
    Type: String
Resources:
  MyChefServer:
    Type: AWS::OpsWorksCM::Server
    Properties:
      ServerName: myopsworks
      BackupRetentionCount: '12'
      DisableAutomatedBackup: False
      Engine: 'ChefAutomate'
      EngineVersion: '2'
      EngineAttributes:
          - Name: "CHEF_AUTOMATE_ADMIN_PASSWORD"
            Value:
                Ref: Password
      EngineModel: 'Single'
      InstanceProfileArn: !Sub arn:aws:iam::${AWS::AccountId}:instance-profile/aws-opsworks-cm-ec2-role
      ServiceRoleArn: !Sub arn:aws:iam::${AWS::AccountId}:role/service-role/aws-opsworks-cm-service-role
      InstanceType: 'm5.large'
      KeyPair: 
        Ref: MyKeyPair
Outputs:
  endpoint:
    Description: endpoint
    Value: !GetAtt [MyChefServer, Endpoint]

参考:AWS CloudFormation を使用して AWS OpsWorks for Chef Automate サーバーを作成する

上記のテンプレートをエディタなどにコピペして「opsworks_test.yaml」と名付けて保存します。

CloudFormationのコンパネにアクセスして「スタックの作成」から「テンプレートのアップロード」にチェックを入れてから「ファイルの選択」をクリックし、先ほど保存した「opsworks_test.yaml」をアップロードし、「次へ」をクリックします。

すると以下のように入力画面が出るのでそれぞれ入力しましょう。

スタックの名前はお好みで大丈夫です。
今回は「私の名前+-opsworks」で入力してみました。

MyKeyPairはChefサーバのEC2インスタンスにsshアクセスするためのkeypairです。
すでに作成してあるものから選択するので、未作成でしたらEC2のコンパネから作成しましょう。

PasswordはURLからchefサーバにアクセスする時のパスワードです。
こちらは後で使うのでエディタなどにコピペしておきましょう。

あとはデフォルトの設定で「スタックの作成」を実行していきましょう。

スターターキットのダウンロード

スタックの作成が完了したら、AWS OpsWorks for Chef Automateのコンパネにアクセスして、「myopsworks」があるので名前をクリックしましょう。

すると今回作成されたchefサーバのダッシュボードにアクセスできるので、「Actions」から「Regenerate starter kit」をクリックして、「Download Starter Kit」をクリックしてダウンロードしていきましょう。

インスタンス内での設定

次に作成されたインスタンスにsshアクセスしてstarter kitをセットアップしていきます。

アクセス先のインスタンスの情報はEC2インスタンスで「aws-opsworks-cm-instance-myopsworks」というインスタンスから確認できます。

先ほどダウンロードしたstarter kitは事前にSCPなどをしてサーバにアップロードしてください。

ChefDKダウンロードページにアクセスし、
最新バージョンのものをダウンロードします。

wget先は「Download ChefDK directly」のURLをコピーしrpmまでを抜き出したものです。
バージョンが違えばURLの記述も変わるので注意です。

#パッケージのアップデート
sudo yum update

#treeコマンドのインストール
sudo yum install tree

#zipファイルの解凍
ls
myopsworks_starter_kit.zip
#myopsworks_starter_kit.zipは事前にアップする。

unzip myopsworks_starter_kit.zip

rm myopsworks_starter_kit.zip

#ChefDKのインストール
wget https://packages.chef.io/files/stable/chefdk/4.13.3/el/8/chefdk-4.13.3-1.el7.x86_64.rpm

ls
chefdk-4.13.3-1.el7.x86_64.rpm  myopsworks-b6pdfvl9onlq6uwc

sudo yum install ./chefdk-4.13.3-1.el7.x86_64.rpm

chef verify
+---------------------------------------------+
            Chef License Acceptance

Before you can continue, 3 product licenses
must be accepted. View the license at
https://www.chef.io/end-user-license-agreement/

Licenses that need accepting:
  * Chef Development Kit
  * Chef Infra Client
  * Chef InSpec

Do you accept the 3 product licenses (yes/no)?

> yes

Persisting 3 product licenses...
✔ 3 product licenses persisted.
(以下略)

#rubyのバージョンをスターターキットに合わせる
echo 'eval "$(chef shell-init bash)"' >> ~/.bash_profile
source ~/.bash_profile
ruby --version
ruby 2.6.6p146 (2020-03-31 revision 67876) [x86_64-linux]

デフォルトのCookbookの確認

Cookbookはサーバ内部の構成を記述するファイル群です。
スターターキットのデフォルトで実行されるようになっているCookbookはnginxが動作するWEBサーバ環境がプロビジョニングされます。

どのようなファイル構成になっているのか見てみましょう。

cd myopsworks-b6pdfvl9onlq6uwc/site-cookbooks/

tree opsworks-webserver/
opsworks-webserver/
├── Berksfile
├── README.md
├── attributes
│   └── default.rb
├── chefignore
├── files
│   └── default
│       └── teaser_page
│           ├── images
│           │   ├── chef-logo.svg
│           │   ├── logo.png
│           │   ├── opsworks-logo-with-servicename.svg
│           │   ├── opsworks-logo.svg
│           │   └── sticker.png
│           ├── styles
│           │   └── styles.css
│           └── widgets.js
├── metadata.rb
├── recipes
│   └── default.rb
└── templates
    └── default
        ├── opsworks-demo.erb
        └── opsworks-index.html.erb

9 directories, 15 files
  • Berksfile
    外部から取得されるサービスが記述されています。

  • README
    Cookbookの説明が記述されています。

  • attributes
    変数を定義するファイルが格納されてます。
    配下のファイルにはrecipesやtemplates内のファイルに記述している変数が定義できます。

  • files
    サイトを構成する画像ファイルなどが配下にセッティングされています。

  • metadata
    Cookbookのメタ情報が記述されています。

  • recipes
    chefで構成されるインフラが記述されています。

  • templates
    実際に設置されるWEBページやconfファイルのソースとなるファイルが格納されています。

今回はrecipesとtemplatesを少々カスタムして別のドメイン名で使用していこうと思います。

Recipeの編集

「recipes/default.rb」を編集してWEBサーバのインフラ部分を変更していきます。
Recipeの記述にはRubyを使います。

Rubyと聞くとプログラミングと身構えてしまいそうですが、基本的にはChef専用の記述方式があるので基本構文は少し出てきますがChefの公式ドキュメントに乗っ取る形となります。

今回はドメインを別に変えたいのでドキュメントルートを変えます。
「/var/www/opsworks-demo」から「/var/www/vhosts/hodate-blog.com」に変えてみました。

cd opsworks-webserver/

vi recipes/default.rb

include_recipe "nginx"

nginx_site "hodate-blog.com.conf" do
  template "opsworks-demo.erb"
  action :enable
end

remote_directory "/var/www/vhosts/hodate-blog.com" do
  source "teaser_page"
  recursive true
  owner "root"
  group "root"
  mode "0755"
  files_mode "0755"
  overwrite true
  action :create
end

template "/var/www/vhosts/hodate-blog.com/index.html" do
  source "opsworks-index.html.erb"
  owner "root"
  group "root"
  mode "0755"
  action :create
end

参考:Custom Resources

内容を確認してみると以下のような操作をしているのがわかるかと思います。

  • 「nginx_site」でnginxサービスをenableにしている。
  • 「template」でテンプレートファイルをソースとしてファイルを設置している。
  • 「remote_directory」でディレクトリの作成している。
  • その他「action」操作を指定したり、属性も指定してファイルを作成している。

confファイルの編集

「templates/default/opsworks-demo.erb」を編集していきます。

先ほどのRecipeファイルに「nginx_site」の「template」としてopsworks-demo.erbが指定されているので、「templates/default/opsworks-demo.erb」はnginxに適用されるconfファイルであることがわかります。

ファイルはドキュメントルートとserver_nameを変更してます。

vi templates/default/opsworks-demo.erb

server {
        listen 80;
        listen [::]:80;

        root /var/www/vhosts/hodate-blog.com;
        index index.html index.htm index.nginx-debian.html;

        server_name hodate-blog.com;

        location / {
                try_files $uri $uri/ =404;
        }
}

また、metadata.rbも以下のように編集します。
最下部の「depends "nginx", "~> 9.0.0"」を削除。(消さずに実行するとエラーが出ました。)

name "opsworks-webserver"
maintainer "AWS OpsWorks Demos"
maintainer_email "opsworks-feedback@amazon.com"

description "Installs/Configures a webserver"
long_description "Installs/Configures a webserver"
version "0.6.1"

これでドメインの設定は完了したのでこのCookbookをChefサーバにアップしていきます。

Policyfile.rbを編集

以下のようにstarter kitのPolicyfile.rbを編集してインストールしていきます。

変更点

  • run_listからauditを削除
    「'opsworks-webserver'」の末尾に「,」が残っていたらエラーとなるので注意です。

  • default_sourceの編集

  • 最終行付近のauditの処理を削除

cd ../..

vi Policyfile.rb

# Policyfile.rb - Describe how you want Chef to build your system.
#
# For more information on the Policyfile feature, visit
# https://docs.chef.io/policyfile.html

# A name that describes what the system you're building with Chef does.
name 'opsworks-demo-webserver'

# The cookbooks directory is the preferred source for external cookbooks
default_source :supermarket, "https://supermarket.chef.io" do |s|
  s.preferred_for "windows", "powershell", "ms_dotnet4", "ms_dotnet45", "chef-client", "ms_dotnet2", "ms_dotnet", "ohai", "logrotate", "cron", "compat_resource", "chef_handler"
end

# Alternative source 
default_source :supermarket

# run_list: chef-client will run these recipes in the order specified.
run_list  'chef-client',
          'opsworks-webserver'
# add 'ssh-hardening' to your runlist to fix compliance issues detected by the ssh-baseline profile

# Specify a custom source for a single cookbook:
cookbook 'opsworks-webserver', path: 'site-cookbooks/opsworks-webserver'

chef install
Building policy opsworks-demo-webserver
Expanded run list: recipe[chef-client], recipe[opsworks-webserver]
Caching Cookbooks...
Installing opsworks-webserver >= 0.0.0 from path
Installing chef-client        12.3.4
Installing cron               7.0.2
Installing logrotate          3.0.3

Lockfile written to /home/ec2-user/myopsworks-b6pdfvl9onlq6uwc/Policyfile.lock.json
Policy revision id: 54833e00d99723d04f489523765b85c6d9a6b62141e87aef0ab2ba58cf6cdd65

参考:スターターキットを使用して Chef サーバーを設定する

Cookbookのアップロード

knife cookbook upload --all
Uploading apache2      [8.6.0]
Uploading audit        [9.5.0]
Uploading build-essential [8.2.1]
Uploading chef-client  [12.3.2]
Uploading cron         [6.3.1]
Uploading logrotate    [2.2.3]
Uploading mingw        [2.1.1]
Uploading nginx        [9.0.0]
Uploading ohai         [5.3.0]
Uploading seven_zip    [3.1.2]
Uploading ssh-hardening [2.9.0]
Uploading windows      [7.0.2]
Uploading yum-epel     [3.3.0]
Uploaded all cookbooks.

knife cookbook upload -o site-cookbooks/ --all
Uploading opsworks-webserver [0.6.1]
Uploaded all cookbooks.

ノードの追加とCookbookの実行

今回はノードに追加する用のEC2インスタンスを新規で作成しました。

VPCはChefサーバに合わせなくても良いですが、パブリックサブネットに配置してセキュリティグループでhttpとsshは許可しておきましょう。

また、ブーストラップには秘密鍵が必要なのでsshするための秘密鍵はChefサーバにアップしておきます。
こちらも事前にFTPなどで設置しましょう

さあ、無事にブーストラップしてサーバ内のnginxの設定がうまくいくでしょうか
(ネタバレすると失敗します。)

cd

ls 
chefdk-4.13.3-1.el7.x86_64.rpm  hodate-verification-key.pem  myopsworks-b6pdfvl9onlq6uwc
#秘密鍵を事前にアップ

#ブーストラップのためにPolicyfile.rbと同じディレクトリに移動
cd myopsworks-b6pdfvl9onlq6uwc

#ノードをブーストラップ
knife bootstrap {chefノードIP} -N testnode -x ec2-user --sudo -i /home/ec2-user/hodate-verification-key.pem --run-list "recipe[nginx]"

(中略)

    ================================================================================
    Error executing action `install` on resource 'yum_package[nginx]'
    ================================================================================

(中略)

Running handlers:
[2021-07-03T22:58:53+00:00] ERROR: Running exception handlers
Running handlers complete
[2021-07-03T22:58:53+00:00] ERROR: Exception handlers complete
Chef Infra Client failed. 10 resources updated in 14 seconds
 [[ChefクライアントIP]] [2021-07-03T22:58:53+00:00] FATAL: Stacktrace dumped to /var/chef/cache/chef-stacktrace.out
 [[ChefクライアントIP]] [2021-07-03T22:58:53+00:00] FATAL: Please provide the contents of the stacktrace.out file if you file a bug report
 [[ChefクライアントIP]] [2021-07-03T22:58:53+00:00] FATAL: Mixlib::ShellOut::ShellCommandFailed: yum_package[nginx] (nginx::package line 43) had an error: Mixlib::ShellOut::ShellCommandFailed: Expected process to exit with [0], but received '1'
---- Begin output of ["yum", "-y", "install", "nginx-0:1.18.0-2.el6.ngx.x86_64"] ----
STDOUT: Loaded plugins: extras_suggestions, langpacks, priorities, update-motd
Resolving Dependencies
--> Running transaction check
---> Package nginx.x86_64 0:1.18.0-2.el6.ngx will be installed
--> Processing Dependency: libpcre.so.0()(64bit) for package: nginx-1.18.0-2.el6.ngx.x86_64
--> Finished Dependency Resolution
 You could try using --skip-broken to work around the problem
 You could try running: rpm -Va --nofiles --nodigest
STDERR: Error: Package: nginx-1.18.0-2.el6.ngx.x86_64 (nginx)
           Requires: libpcre.so.0()(64bit)
---- End output of ["yum", "-y", "install", "nginx-0:1.18.0-2.el6.ngx.x86_64"] ----
Ran ["yum", "-y", "install", "nginx-0:1.18.0-2.el6.ngx.x86_64"] returned 1
ERROR: The following error occurred on [ChefクライアントIP]:
ERROR: 

ここまで順調でしたが、エラーが出てnginxのインストールコマンド(yum -y install nginx-0:1.18.0-2.el6.ngx.x86_64)の終了値が1になりエラーとなりました。
考えられる理由としては以下。

  • 実行エラーが出てから「/etc/yum.repos.d/nginx.repo」を確認するとbaseurlが「 https://nginx.org/packages/rhel/6/$basearch/ 」に書き変わっていたのでおそらく参照しようとしているリポジトリが古い。

  • baseurlを正しい記述に変えてもインストールしようとしている「nginx-1.18.0-2.el6.ngx.x86_64」はインストールできないので、ローカルのCookbookのバージョンが古い。

仕方がないので、Chefノード側でnginxをインストールし、Recipeのnginxのインストールの部分は消しました。

#Chefノード側
#nginxのリポジトリを修正(baseurlを戻す)
sudo vi /etc/yum.repos.d/nginx.repo

# This file was generated by Chef
# Do NOT modify this file by hand.

[nginx]
name=Nginx.org Repository
baseurl=http://nginx.org/packages/mainline/centos/7/$basearch/
enabled=1
fastestmirror_enabled=0
gpgcheck=1
gpgkey=https://nginx.org/keys/nginx_signing.key

#nginxのインストール
sudo yum install nginx

#Chefサーバ側

#Recipeファイルの修正
vi site-cookbooks/opsworks-webserver/recipes/default.rb

service "nginx" do
  action :start
end

template "/etc/nginx/conf.d/hodate-blog.com.conf" do
  source "opsworks-demo.erb"
  owner "root"
  group "root"
  mode "0644"
  action :create
end

remote_directory "/var/www/vhosts/hodate-blog.com" do
  source "teaser_page"
  recursive true
  owner "root"
  group "root"
  mode "0755"
  files_mode "0755"
  overwrite true
  action :create
end

template "/var/www/vhosts/hodate-blog.com/index.html" do
  source "opsworks-index.html.erb"
  owner "root"
  group "root"
  mode "0755"
  action :create
end

#再度Cookbookアップロード
knife cookbook upload -o site-cookbooks/ --all
Uploading opsworks-webserver [0.6.4]
Uploaded all cookbooks.

#Policyfileを再度作成
rm Policyfile.lock.json 

chef install

#再度ノードをブーストラップ
knife bootstrap [ChefクライアントIP] -N testnode -x ec2-user --sudo -i /home/ec2-user/hodate-verification-key.pem --run-list "recipe[opsworks-webserver]"

Connecting to [ChefクライアントIP] using ssh
The authenticity of host '[ChefクライアントIP] ()' can't be established.
fingerprint is SHA256:UXmjJrUGFLj/WuRnMDTR86xdVyi20O2O3qGY3LZZPRc.

Are you sure you want to continue connecting
? (Y/N) y
Connecting to [ChefクライアントIP] using ssh
Node testnode exists, overwrite it? (Y/N) y
Client testnode exists, overwrite it? (Y/N) y
Creating new client for testnode
Creating new node for testnode
Bootstrapping [ChefクライアントIP]

(中略)

 [[ChefクライアントIP]] * service[automate-liveness-agent] action enable
 [[ChefクライアントIP]]  (up to date)
  * service[automate-liveness-agent] action start
 [[ChefクライアントIP]]  (up to date)
 [[ChefクライアントIP]] 
 [[ChefクライアントIP]] 
 [[ChefクライアントIP]] Running handlers:
 [[ChefクライアントIP]] 
 [[ChefクライアントIP]] Running handlers complete

 [[ChefクライアントIP]] Chef Infra Client finished, 1/21 resources updated in 02 seconds
 [[ChefクライアントIP]] 
 [[ChefクライアントIP]] [2021-07-04T00:49:13+00:00] WARN: This release of Chef Infra Client became end of life (EOL) on May 1st 2021. Please update to a supported release to receive new features, bug fixes, and security updates.

今回は無事に成功しました!

それでは、サーバ内でも本当にサーバ内の設定は自動でされたのでしょうか?
それは次でみていきましょう。

事後確認

#Chefノード側

systemctl status nginx
● nginx.service - nginx - high performance web server
   Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
   Active: active (running) since 日 2021-07-04 00:49:13 UTC; 12s ago
     Docs: http://nginx.org/en/docs/
  Process: 3248 ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf (code=exited, status=0/SUCCESS)
 Main PID: 3249 (nginx)
   CGroup: /system.slice/nginx.service
           ├─3249 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
           └─3250 nginx: worker process

 7月 04 00:49:13 ip-10-0-0-131.ap-northeast-1.compute.internal systemd[1]: Starting nginx - high performance web server...
 7月 04 00:49:13 ip-10-0-0-131.ap-northeast-1.compute.internal systemd[1]: Can't open PID file /var/run/nginx.pid (yet?) after start: No such file or directory
 7月 04 00:49:13 ip-10-0-0-131.ap-northeast-1.compute.internal systemd[1]: Started nginx - high performance web server.

#nginxが動いている

ll /var/www/vhosts/hodate-blog.com/
合計 120
drwxr-xr-x 2 root root    129  7月  4 00:49 images
-rwxr-xr-x 1 root root   1431  7月  4 00:46 index.html
drwxr-xr-x 2 root root     24  7月  4 00:49 styles
-rwxr-xr-x 1 root root 115092  7月  4 00:46 widgets.js

#ファイルも作成されている

less /etc/nginx/conf.d/hodate-blog.com.conf 

server {
        listen 80;
        listen [::]:80;

        root /var/www/vhosts/hodate-blog.com;
        index index.html index.htm index.nginx-debian.html;

        server_name hodate-blog.com;

        location / {
                try_files $uri $uri/ =404;
        }
}

#テンプレートファイルの配置されている。

無事ブーストラップが成功していました。
WEB閲覧も問題ないはずです。

確認のためにhostsファイルに以下を記載してみましょう。

[ChefクライアントIP] hodate-blog.com

ブラウザで hodate-blog.com を検索して以下の表示が出たら成功です!

うまくいきました。

あとはChefの管理画面から今回のノードを確認してみましょう。

再度AWS OpsWorks for Chef Automateのコンパネにアクセスして、「myopsworks」があるので名前をクリックしましょう。

すると「Open Chef Automate dashboard」と書いてある箇所があるのでクリック。

以下のようなログイン画面に移動するはずです。

※ChromeでNET::ERR_CERT_INVALIDのエラーが出た場合の対応
そのエラー画面のまま「thisisunsafe」と入力してEnterを押しましょう。
ログイン画面に遷移するはずです。

ここでは以下でログインができます。

Username:admin
Password:冒頭のCloudFormationのPasswordで入力したもの

ログインができたら「Infrastructure」をクリック。

今回作成したtestnodeが存在するので名前をクリック。

以下の画面が出ていたらChefサーバの管理ノードとして機能しているので成功です。

作成したリソースの削除

最後にリソースは残しておくと費用が発生するので削除しましょう。

作成したリソースはCloudFormationのコンパネにアクセスして今回作成したスタックにチェックを入れて、「削除」をクリックすることで作成したリソースを自動で全て削除してくれます。

その他、ノード追加用に作ったインスタンスがあればEC2のコンパネから削除しましょう。

最後に

バージョン違いのエラーもありましたが、RubyでRecipeを記述することでサービスのスタートだけでなくファイルやディレクトリの作成までしてくれることがわかりました。

CloudFormation + OpsWorksの組み合わせはうまく使えば、他のリソースと内部設定の組み合わせをいろんなパターンでコードで管理ができるのではないでしょうか。

それではこれにてブログリレー6日目でした。

ブログリレーは明日以降も続いていくので次の記事もどうぞお楽しみにお願いします。

返信を残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA