BeanstalkにおけるIaC実現のための提案

# 1-はじめに
最近、PJでBeanstalkを使用する機会がありましたが、
あまり需要がないのか他サービスに比べ情報が少ないような気がしました。

特に、IaCを実現するための```.ebextensions```配下に格納するものの仕様が
まとまりきっていないと感じました。

こちらの記事では、ベストプラクティスを提示するのではなく、
私が試行錯誤した結果、「BeanstalkにおけるIaCはこうしたら良いのではないか？」を提案するものです。
※より良い方法があれば、コメントなどでお教え頂けると大変助かります。


# 2-前提

今回はBeanstalkの環境までは一度手動で作成している前提とし、Beanstalkや周辺AWSリソースの作成、OS設定のカスタマイズをIaC化する方針とします。

Beanstalkでは、アプリケーションコードと同レイヤに```.ebextensions```フォルダを作成し、
その中でCFnのような定義を実装することでAWS～OS(ミドルウェア)など様々な設定を行うことができます。

https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/ebextensions.html

だいたいの仕様は上記に記載されているとおりですが、
詳細に説明されていない部分について以下の表で整理をします。
※以下は、AWS Docsには記載がないが、動作確認およびサポート回答による情報を含んでおります。
　そのため、ご自身で利用される際は最新の仕様をご確認されることをおすすめいたします。

|実装レイヤ|実装方法|備考|
|---|---|---|
|OS(MW)|サーバにパッケージを追加したり、ファイル操作、コマンド実行が可能。組み合わせることで自由にサーバ環境をカスタム可能。以下のセクションを利用可能。<br>```packages:```<br>```files:```<br>```commands:```|CFn関数のFindInMapなど利用可能|
|AWS各リソース|CFn互換のため以下のようなセクションを利用可能<br>```Resources:```|CFn関数のFindInMapなど利用可能|
|Beanstalk設定|Beanstalk自体の設定のカスタムが可能。デフォルトでは多くのパラメータが勝手に決められている。以下のセクションを利用可能。<br>```option_settings:```|CFn関数のFindInMapなど利用不可|

#### ★BeanstalkにおけるCFn関数の利用方法

https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/ebextensions-otherkeys.html


# 3-具体的な実装例

#### ★実装例

+ サーバ上の設定の環境差異の吸収（CloudwatchAgentを仕込んで、Cloudwatchに出力するロググループ名を設定する）

```yaml
packages:
  yum:
    awslogs: []
files:
(省略)
  "/etc/awslogs/config/httpdlogs.conf" :
    mode: "000644"
    owner: root
    group: root
    content: |
      [/var/log/httpd/access_log]
      # 環境名ごとにロググループを分けることで、自ずと環境差異を吸収するようにしている
      log_group_name=`{"Fn::Join":["/", ["/aws/eb", {"Ref":"AWSEBEnvironmentName"}, "var/log/httpd/access_log"]]}`
      log_stream_name={instance_id}
      file=/var/log/httpd/access_log

      [/var/log/httpd/error_log]
      # 環境名ごとにロググループを分けることで、自ずと環境差異を吸収するようにしている
      log_group_name=`{"Fn::Join":["/", ["/aws/eb", {"Ref":"AWSEBEnvironmentName"}, "var/log/httpd/error_log"]]}`
      log_stream_name={instance_id}
      file=/var/log/httpd/error_log
(省略)
commands:
  "01":
    command: systemctl enable awslogsd.service
  "02":
    command: systemctl restart awslogsd
  "remove_bak":
    command: "rm -f /etc/awslogs/config/*.bak"
```

+ .ebextensionsで作成する各AWSリソースの環境差異を吸収する（事前作成リソースのマッピングや、環境識別子による振り分け）

```yaml
Mappings:
  EB2Resouces: #任意のマッピング設定の名前
    prd-applicatoin-env: #事前に作成したEB環境名
      SNSArn: "arn:aws:sns:「リージョン」:123456789012:prd-sendmail-sns" #環境ごとに差異のあるものを定義
      ENV: "prd" #環境ごとに差異のあるものを定義
    prd-applicatoin-env: #事前に作成したEB環境名
      SNSArn: "arn:aws:sns:「リージョン」:123456789012:dev-sendmail-sns" #環境ごとに差異のあるものを定義
      ENV: "dev" #環境ごとに差異のあるものを定義
Resources:
（省略）
    EC2AverageDiskUsedPercentAlarm:
        Type: AWS::CloudWatch::Alarm
        Properties:
            #Mappingsから動的に値を取得（ここではSNSトピックを指定）
            AlarmActions:
            -
              ? "Fn::FindInMap"
              :
                - EB2Resouces
                -
                  Ref: "AWSEBEnvironmentName"
                - SNSArn
            #Mappingsから動的に値を取得（ここではアラーム名の一部に環境識別子prd or devを指定）
            AlarmName: { "Fn::Join" : ["-", [{"Fn::FindInMap" : ["EB2Resouces" ,{Ref: "AWSEBEnvironmentName"}, "ENV"]},"average-disk_used_percent",{ "Ref" : "AWSEBAutoScalingGroup" }, "metrics-alarm" ]]}
            MetricName: disk_used_percent
            Namespace: CWAgent
            Statistic: Average
            Period: 300
            EvaluationPeriods: 1
            Threshold: 84
            TreatMissingData: breaching
            ComparisonOperator: GreaterThanOrEqualToThreshold
            Dimensions:
            - Name: path
              Value: /
            - Name: AutoScalingGroupName
              Value:
                Ref: AWSEBAutoScalingGroup
            - Name: device
              Value: nvme0n1p1
            - Name: fstype
              Value: xfs
（省略）
```

#### ★できないこと

+ ALBのSGを、環境ごとに別々のSGに変更したい（事前に作成したSGにしたい）
    + ```option_settings:``` では```FindInMap``` が利用できないため環境ごとに自動で設定を変更するような実装はできません。



# 4-まとめ

Beanstalkは気軽にIaCやCI/CDを実現するのに便利なサービスと感じていますが、
情報が少ないため、便利そうだけどよくわからないサービスとなってしまっている気がします。

同じような考え、境遇をお持ちの方たちの中で、
今回の記事が読んで頂いたことで何か一助になれば幸いです。