Fargateでnginxとspring bootを連携

Amazon ECS on Fargateでnginxとspring bootを連携した際に躓いた点を記事にします。

以前に業務外ですが、EC2上でDockerを利用しNginxとSpriing bootを連携させたことはあったので少し知識はありました。

 

以下、EC2上でDockerを利用しNginxとSpriing bootさせた手順です

rikues2012.hatenablog.com

 

構成図になります。
nginxとspring bootのコンテナは同一Service内にあります。
nginxの前段にALBなどがありますが必要な箇所のみ構成図としました。

躓いた箇所

nginxのnginx.confでspring bootと連携する箇所の記載方法が不明。

連携できずにECSのタスク起動時にエラーが発生。

 

解決方法

nginxのnginx.confを以下のようにする

   server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  _;
        #root         /usr/share/nginx/html; ←ここをコメント

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location / {
                proxy_pass http://localhost:8080/; ←ここがポイント
        }

localhost:8080」と記述し、
spring boot側で8080で受信できるようにして連携することができました。
別々のコンテナ間でlocalhostを認識することができました。

EC2上では以下で連携できますが、Fargateは「link」オプションを利用できないです。

① nginx.confに「proxy_pass http://app:8080/;」と記述

② 「docker run -d --link spring-container:app ・・・」のようにlinkオプションを利用

 

そもそも公式サイトに「link」オプションは非推奨と記載されていました。。

docs.docker.com

 

今回記事にした箇所で半日ぐらい躓きました。

ECSも初めて利用したため「どの箇所が間違っているのか?」特定するのに時間がかかりました。

気になっていること

・ネットでいろいろな構成図を参照するとnginxとspring bootのコンテナを別々のServiceにした方が良さそうな気もします。

 

ECS on Fargate 構築時のエラーと対応方法

ECS on Fargate 構築時のエラー一覧と対応方法です。
約半年ぐらい前に構築した内容で自分への振り返りとして纏めました。
初めてECSを業務で利用したので振り返ると初歩的なエラーばかりです。

一部環境ですが、以下構成イメージです。(CI/CD含む)

1、AWSServiceRoleForECSが存在しないエラー

エラーメッセージ

CloudFormationでECS Cluster作成時にエラーが発生

Resource handler returned message: "Invalid request provided: CreateService error: Unable to assume the service linked role. Please verify that the ECS service linked role exists.
(Service: AmazonECS; Status Code: 400; Error Code: InvalidParameterException; Request ID: xxxxxxxxxx; Proxy: null)" (RequestToken: xxxxxxxxxx, HandlerErrorCode: InvalidRequest)
原因

IAMロール「AWSServiceRoleForECS」が存在しない

対応方法

以下のどちらかで対応
対応パターン① AWSマネジメントコンソールからECSを作成する
       ⇒「AWSServiceRoleForECS」が自動で生成
対応パターン② CloudFormationでAWSServiceRoleForECSを作成。

  IAMRoleAWSServiceRoleForECS:
    Type: "AWS::IAM::ServiceLinkedRole"
    Properties:
      AWSServiceName: "ecs.amazonaws.com"
      Description: "Role to enable Amazon ECS to manage your cluster."

複数の環境でECSを作成するため、私は②(CloudFormation)で対応しました。
異なるエラーコード、メッセージでも「AWSServiceRoleForECS」が存在しないために発生するエラーがあるため、このIAMロールの存在は確認したほうが良いです。

詳細については以下のサイトに説明されています。
IAMのService-Linked RolesがCloudFormationに対応したので、とてもナイスなリリースということを詳しく書いてみた。 | DevelopersIO

2、IAMポリシーの不足

エラーメッセージ

CodePipelineのCodeCommitでエラーが発生

The service role or action role doesn’t have the permissions required to access the Amazon S3 bucket named 検証環境S3バケット
Update the IAM role permissions, and then try again. Error: Amazon S3:AccessDenied:User: arn:aws:sts::111111111111:assumed-role/ロール名/222222222222 is not authorized to perform:
kms:GenerateDataKey on this resource because no identity-based policy allows the kms:GenerateDataKey action
(Service: Amazon S3; Status Code: 403; Error Code: AccessDenied; Request ID: xxxxx; S3 Extended Request ID: xxxxx; Proxy: null)
原因

dev環境(111111111111)のロールにKMSのポリシーが不足していて、検証環境のS3バケットを参照できない

対応方法

dev環境(111111111111)のロールにKMSのポリシー(kms:GenerateDataKey)を追加


3、KMSのエイリアスが利用できないエラー

エラーメッセージ

CodePipelineのCodeCommitでエラーが発生

The service role or action role doesn’t have the permissions required to access the Amazon S3 bucket named xxx. Update the IAM role permissions, and then try again.
Error: Amazon S3:AccessDenied:Access Denied (Service: Amazon S3; Status Code: 403; Error Code: AccessDenied; Request ID: xxxxx; S3 Extended Request ID: xxxxx; Proxy: null)
原因

KMSを作成していないアカウント(構成図ではdev環境)からだとKMSのエイリアスは利用できないためエラー。

対応方法

KMSのエイリアスを利用しないように変更しました。
今振り返るともっと良い対応方法があったはず。


4、ECR参照先が存在しない

エラーメッセージ

CodePipelineのCodeBuildでエラーが発生

COMMAND_EXECUTION_ERROR: Error while executing command: docker push $REPOSITORY_URI:latest. Reason: exit status 1
CLIENT_ERROR: no matching artifact paths found
原因

buildspec.ymlに設定したECR参照先が存在しない

対応方法

buildspec.ymlに正しいECRの参照先を設定


5、buildspec.yml内の変数の規定外の文字列(記号)を使用

エラーメッセージ

CodePipelineのCodeBuildでエラーが発生

s3-cicd-api: not a valid identifier
原因

buildspec.yml内の変数に「-」があったため

対応方法

buildspec.ymlの変数に「-」などの記号を取る
詳細は以下の記事にしました。 rikues2012.hatenablog.com

6、エンドポイントが未作成

エラーメッセージ

CodePipelineのCodeDeployでエラーが発生

Resourceinitializationerror: unable to pull secrets or registry auth: execution resource retrieval failed:
unable to retrieve ecr registry auth: service call has been retried 3 time(s): RequestError: send request failed caused by:
Post "https://api.ecr.ap-northeast-1.amazonaws.com/": dial tcp xx.xx.xx.xx:443: i/o timeout
原因

ECRのエンドポイントが未作成のため、イメージを取得できない

対応方法

ECRのエンドポイントを作成
・サービス名:com.amazonaws.ap-northeast-1.ecr.api



参考サイト

以下、FargateのCI/CDパイプラインのエラー原因ポイントが記載されています。

AWS Fargate with CI/CDパイプラインでデプロイ失敗する原因について | クラウド・AWSのIT技術者向けブログ SKYARCH BROADCASTING

以下、CodeBuildのエラー原因のポイントが記載されています。

AWS CodeBuildで失敗したときに確認するポイント #AWS - Qiita

Azure App ServiceのWEBジョブを停止する3パターンを検証(手順あり)

Azure App ServiceのWEBジョブを停止方法について検証しました。

結論

アプリケーション設定に「WEBJOBS_STOPPED」を追加し、値を「1」にすることでWEBジョブは停止されます。
※アプリケーション設定の反映はApp Serviceの再起動が必要
公式サイトに記載していた通りでした。
learn.microsoft.com

検証(3パターンの検証と手順)

1、App Service:停止のみ

  結果: WEBジョブは停止しない

[App Serviceの停止手順]
対象のApp Serviceサービスを選択し、「停止」ボタンを押下


2、アプリケーション設定追加のみ

  結果: WEBジョブは停止する

[アプリケーション設定追加手順]
① 対象のApp Serviceサービス内で「構成」を選択し、「アプリケーション設定」を選択

② 「新しいアプリケーション設定」を選択

③ 以下を入力し、「OK」ボタンを押下
 名前:WEBJOBS_STOPPED
 値 :1

④ 「保存」ボタンを押下
※この手順忘れがちです

⑤ 「続行」ボタンを押下

⑥ 以下のメッセージが画面右上に表示される。

3、App Service:停止 and アプリケーション設定追加

  結果: WEBジョブは停止する

手順は上記の1、2に記載しているため省略

最後に

私が担当したプロジェクトでは「3、App Service:停止 and アプリケーション設定追加」で対応しました。
App Serviceを停止してもサービス利用料は変わりませんが。。
いろんなパターンを試したサイトや画像付きの手順があるサイトが無かったため、少し不安になりながら作業しました。
備忘録として記事にしましたが、誰かのお役に立てれば幸いです。

AWS認定 MLSで覚える機械学習の用語を1行で説明(25単語)

AWS Certified Machine Learning - Specialty (MLS-C01)に合格しました。
私が機械学習初心者で専門用語を覚えるのが大変だったので、必要最低限の専門用語をまとめました。
試験は「2024/03/02」に受けたのですが、機械学習の専門用語としては本ブログに記載した内容を覚えれば合格できました。
点数は795点と高いわけではないですが。。

単語説明概要

単語説明の青字箇所をキーワードとして覚えば大丈夫です。
同じキーワードがいくつかあるので、その場合は「教師あり」or「教師なし」の違いなどを覚える必要もあります。

重要単語レベル:★★★

正則化過学習を防ぐ手法。訓練データに過剰に適合しないため一般化する。
ドロップアウト過学習を防ぐ手法。(正則化とセットで出題される)
・主成分分析:特徴を削減。(特徴を少ない次元の空間に変換)

・線形学習:分類や回帰ができる。例)分類:画像分類、回帰:数値予測
・線形分類:数値を予測。例)売上、気温、生産数の予測
・ロジステック回帰(分類):0 or 1を定義する不正検出アルゴリズム
             名前に「回帰」があるが「分類」問題を解決する。

協調フィルタリングレコメンデーションに最適。レコメンドの一般的アルゴリズム
・LDA:文書のトピックを検出。例)テキストの自動トピック識別、内容要約
ベイズ検索:最適なハイパーパラメータを調整する手法。
・ランタイムカットフォレスト:異常なデータポイントを検出するアルゴリズム
・XGBoost:複数のモデルを学習させ、1つにまとめて予測する。
      F1不正行為の分類も合わせて覚える

・畳み込みニューラルネットワーク(CNN):画像認識モデル。例)物体、顔、画像分類
再帰ニューラルネットワーク(RNN):時系列データのモデル。例)店の日次売上

・K-means:データをK個に類似性でグループ分け。外れ値検索。例)文書のグループ分け
・K-近傍法(K-NN):類似のデータポイントをK個見つける。

重要単語レベル:★★

・Bag-of-Words(BoW):各単語の出現回数を示すアルゴリズム
・Term Frequency – Inverse Document Frequency(TF-IDF):単語の重要度を測る指標。
・Object2Vec:類似している単語、画像、ビデオを検索。CNNベースモデル

・One-Hotエンコーディング:文字列の値を数値に変換。例)赤(1, 0, 0) 青(0, 1, 0)

重要単語レベル:★

・適合率:陽性と判断されたデータがどれだけ正しく分類できたか。
・特異率:陰性のデータの中でどれだけ陰性と分類できたか。
・リコール:正のクラスを正しく識別できた割合。例)病気の診断不正取引の検出

因数分解機:クリック予測項目推奨
ROC曲線下の面積(AVC):機械学習の分類モデルをや相互に比較/評価する。
・データのビニング:モデルの過学習を防ぐ

基礎

学習パターン

学習名 説明 利用ケース
強化学習(報酬獲得) 環境からのフィードバックから最適な行動を学習 動的な環境での意思決定、ゲーム
教師あり(ラベルあり) データラベルからパターンを学習して予測する 分類、回帰問題
教師なし(ラベルなし) ラベルなしのデータからパターンを探索する クラスタリング、異常検出


教師あり、なしで分ける

教師あり 教師なし
線形学習 主成分分析(PCA)
線形分類 ランタイムカットフォレスト(RCF)
ロジステック回帰 K-means
XGBoost
因数分解
K-近傍法

教師なしの3つを覚える

参考書

この本を読んで学習しました。
とても分かりやすい本ですが、半分ぐらいしか理解できずMLS合格のために最低限覚える用語をまとめました。 www.amazon.co.jp

[参考サイト]
私が見た中では一番分かりやすいのでお勧めです。 zenn.dev

サンドボックスOUに適用したサービスコントロールポリシーのサンプル

社内のAWSアカウント管理を行うことになりました。
標準的なSCP(サービスコトロールポリシー)を作成したので、記事にします。
サンドボックスOUに付与したSCPになります。

1はセキュリティ強化と管理を楽にするため
2~4は費用の適正化のため

1、利用リージョンの制限

以下の利用リージョンに制限する
・東京(ap-northeast-1)
・大阪(ap-northeast-3)
バージニア北部(us-east-1)
オハイオ(us-east-2)
オレゴン(us-west-2)

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "denyRegion",
      "Effect": "Deny",
      "Action": [
        "*"
      ],
      "Resource": [
        "*"
      ],
      "Condition": {
        "StringNotEquals": {
          "aws:RequestedRegion": [
            "ap-northeast-1",
            "ap-northeast-3",
            "us-east-1",
            "us-east-2",
            "us-west-1"
          ]
        }
      }
    }
  ]
}


2、RDSのインスタンスクラスを制限する

個別に記事にしたので、以下に記載しています rikues2012.hatenablog.com


3、EC2のインスタンスタイプを制限する

以下のインスタンスタイプに制限する
・t2:nano、micro、small
・t3:nano、micro、small
・t4g:nano、micro、small

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "RequireMicroInstanceType",
      "Effect": "Deny",
      "Action": "ec2:RunInstances",
      "Resource": [
        "arn:aws:ec2:*:*:instance/*"
      ],
      "Condition": {
        "StringNotEquals": {
          "ec2:InstanceType": [
            "t2.nano",
            "t2.micro",
            "t2.small",
            "t3.nano",
            "t3.micro",
            "t3.small",
            "t4g.nano",
            "t4g.micro",
            "t4g.small"
            ]
        }
      }
    }
  ]
}


4、サービス利用を制限する

利用料が高いもの&弊社では利用しないサービスに限定しました
以下のサービスを利用不可にする
・Braket(量子アルゴリズム)
・CloudHSM
・DeepRacer、DeepComposer、DeepLens
・Shield
・Show Family
・Storage Gateway
・R53(ドメイン購入操作)

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Deny",
            "Action": [
                "braket:*",
                "cloudhsm:*",
                "deepracer:*",
                "deepcomposer:*",
                "deeplens:*",
                "shield:*",
                "snowball:*",
                "snow-device-management:*",
                "storagegateway:*",
                "route53domains:*"
            ],
      "Resource": "*"
    }
  ]
}

全サービスで400以上?あるので全ては精査できていないです。
もっと利用制限した方が良いサービスはあると思いますが、まずは上記としました。
Shield(Advanced)は年契約してしまうと500万ぐらいかかるので、制限したほうが良いです。


【参考サイト】
blog.serverworks.co.jp

dev.classmethod.jp

SCPでRDSのインスタンスクラスを制限する

SCP(サービスコトロールポリシー)でRDSのインスタンスクラスを制限する方法になります。
初めてSCPを作成したので微妙にハマりました。

RDSのインスタンスクラスを制限する

※Auroraも同じSCPで制限できます
コスト最適化のために以下のインスタンスクラスに制限
・db.t2:micro、small、medium
・db.t3:micro、small、medium
・db.t4g:micro、small、medium

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Deny",
      "Action": "rds:CreateDBInstance",
      "Resource": "arn:aws:rds:*:*:*:*",
      "Condition": {
        "StringNotLike": {
          "rds:DatabaseClass": [
            "db.t2.micro",
            "db.t2.small",
            "db.t2.medium",
            "db.t3.micro",
            "db.t3.small",
            "db.t3.medium",
            "db.t4g.micro",
            "db.t4g.small",
            "db.t4g.medium"
          ]
        }
      }
    }
  ]
}


気を付けるところ1

以下の「Resource」記述にするとエラーとなりました

"Resource": "arn:aws:rds:*"

「Missing ARN Field: リソース ARN には、少なくとも 6 フィールドが含まれていて、次の構造が含まれている必要があります: arn:partition:service:region:account:resource。」

対応としては以下にしました。

"Resource": "arn:aws:rds:*:*:*:*",


気を付けるところ2

インスタンスクラスの先頭に「db」を付ける。 当たり前ですが「t2.micro」だとダメで、「db.t2.micro」にすること。


気を付けるところ3

Aurora MySQLを利用する場合は
Aurora(Mysql8.0~)はmedium以下のインスタンスタイプは選択できないため、mediumも含める。


動作確認(制限確認)

エラーとなりインスタンスは作成できませんが、クラスターは作成できてしまう。。


クラスターが作成されてしまう問題はありますが、
RDS及びAuroraのインスタンスクラスは制限することができました。

ECS on Fargateで複数環境のDockerfileを共通で利用する

複数環境(本番、検証、開発)でECS on Fargateを構築した際にDockerfileを共通化した備忘録です。

前提情報

  • 各環境は別々のAWSアカウント
  • ECSのタスク内は「Nginx」と「SpringBoot」のコンテナで連携
  • 本記事の共通化対象は「SpringBoot」のコンテナで利用するDockerfile

手順

buildspec.yml内のdocker buildするところでDockerfileに引数を渡すことで共通化できます。
例)Javaのメモリ割り当てのところを共通化する

1、パラメータストアにメモリの初期値と最大値を設定する

メモリ初期値のキー名:/web/java-min-memsize

メモリ最大値のキー名:/web/java-max-memsize ※画像は省略

2、buildspec.ymlでパラメータストアの値を取得し、Dockerfileに引数で渡す

--build-arg」を利用してDockerfileに引数で渡す
複数の値を渡したい場合は以下のように「--build-arg」を複数書く。

buildspec.yml

version: 0.2

env:
  parameter-store:
    maxsize: "/web/java-max-memsize"
    minsize: "/web/java-min-memsize" 

phases:
  install:
    runtime-versions:
      python: 3.9
  pre_build:
    commands:
   pre_buildは省略    

  build:
    commands:
      - mv buildConf/backOffice/* .
      - docker build -t $REPOSITORY_URI:latest --build-arg MAXSIZE=${maxsize} --build-arg MINSIZE=${minsize} .
      - docker tag $REPOSITORY_URI:latest $REPOSITORY_URI:$IMAGE_TAG


3、Dockerfileで値を受け取る

「ARG」で引数を受け取り、「ENV」で環境変数に設定します。
最後に${}で括って環境変数名を入れます。
環境変数に入れないと実行時に参照することができません。

Dockerfile

FROM public.ecr.aws/amazoncorretto/amazoncorretto:17

ARG MINSIZE
ARG MAXSIZE

ENV MINSIZE ${MINSIZE}
ENV MAXSIZE ${MAXSIZE}

CMD java -Xms${MINSIZE}m -Xmx${MAXSIZE}m -Dloader.path=/test/conf -jar /test/sample.jar

以上で設定は完了です。