

# Amazon ECS クラスターの NGINX Plus ワークロードのサンプル
<a name="ContainerInsights-Prometheus-Setup-nginx-plus-ecs"></a>

NGINX Plus は NGINX の商用バージョンです。これを使用するには、ライセンスが必要です。詳細については、「[NGINX Plus](https://www.nginx.com/products/nginx/)」をご参照ください。

NGINX Prometheus エクスポーターは、NGINX データを Prometheus のメトリクスとしてスクレイピングして公開できます。この例では、エクスポーターを Amazon ECS 用の NGINX Plus リバースプロキシサービスと連動させて使用します。

NGINX Prometheus エクスポーターの詳細については、GitHub の [nginx-prometheus-exporter](https://github.com/nginxinc/nginx-prometheus-exporter) をご参照ください。NGINX リバースプロキシの詳細については、GitHub の [ecs-nginx-reverse-proxy](https://github.com/awslabs/ecs-nginx-reverse-proxy)をご参照ください。

Prometheus をサポートする CloudWatch エージェントは、Amazon ECS クラスターのサービス検出設定に基づいて NGINX Plus Prometheus メトリクスをスクレイプします。別のポートまたはパスでメトリクスを公開するように NGINX Prometheus Exporter を設定できます。ポートまたはパスを変更する場合は、CloudWatch エージェント設定ファイルの `ecs_service_discovery` セクションを更新します。

## Amazon ECS クラスター用の NGINX Plus リバースプロキシサンプルワークロードをインストールする
<a name="ContainerInsights-Prometheus-nginx-plus-ecs-setup"></a>

NGINX リバースプロキシサンプルワークロードをインストールするには、次の手順を実行します。

### Docker イメージを作成する
<a name="ContainerInsights-Prometheus-nginx-plus-ecs-setup-docker"></a>

**NGINX Plus リバースプロキシサンプルワークロード用の Docker イメージを作成するには**

1. NGINX リバースプロキシリポジトリから次のフォルダをダウンロードします: [ https://github.com/awslabs/ecs-nginx-reverse-proxy/tree/master/reverse-proxy/](https://github.com/awslabs/ecs-nginx-reverse-proxy/tree/master/reverse-proxy/)。

1. `app` ディレクトリを検索し、そのディレクトリからイメージを作成します。

   ```
   docker build -t web-server-app ./path-to-app-directory
   ```

1. NGINX Plus 用のカスタムイメージを作成します。NGINX Plus のイメージを作成する前に、ライセンスされている NGINX Plus の `nginx-repo.key` という名前のキーと SSL 証明書 `nginx-repo.crt` を取得する必要があります。ディレクトリを作成し、その中に `nginx-repo.key` ファイルと `nginx-repo.crt` ファイルを格納します。

   作成したディレクトリに、次の 2 つのファイルを作成します。
   + 以下の内容を含むサンプル Dockerfile。この docker ファイルは [https://docs.nginx.com/nginx/admin-guide/installing-nginx/installing-nginx-docker/\$1docker\$1plus\$1image](https://docs.nginx.com/nginx/admin-guide/installing-nginx/installing-nginx-docker/#docker_plus_image) で提供されているサンプルファイルから採用されています。実行する重要な変更は、次のステップで作成される `nginx.conf` と呼ばれる別個のファイルをロードすることです。

     ```
     FROM debian:buster-slim
     
     LABEL maintainer="NGINX Docker Maintainers <docker-maint@nginx.com>“
     
     # Define NGINX versions for NGINX Plus and NGINX Plus modules
     # Uncomment this block and the versioned nginxPackages block in the main RUN
     # instruction to install a specific release
     # ENV NGINX_VERSION 21
     # ENV NJS_VERSION 0.3.9
     # ENV PKG_RELEASE 1~buster
     
     # Download certificate and key from the customer portal (https://cs.nginx.com (https://cs.nginx.com/))
     # and copy to the build context
     COPY nginx-repo.crt /etc/ssl/nginx/
     COPY nginx-repo.key /etc/ssl/nginx/
     # COPY nginx.conf /etc/ssl/nginx/nginx.conf
     
     RUN set -x \
     # Create nginx user/group first, to be consistent throughout Docker variants
     && addgroup --system --gid 101 nginx \
     && adduser --system --disabled-login --ingroup nginx --no-create-home --home /nonexistent --gecos "nginx user" --shell /bin/false --uid 101 nginx \
     && apt-get update \
     && apt-get install --no-install-recommends --no-install-suggests -y ca-certificates gnupg1 \
     && \
     NGINX_GPGKEY=573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62; \
     found=''; \
     for server in \
     ha.pool.sks-keyservers.net (http://ha.pool.sks-keyservers.net/) \
     hkp://keyserver.ubuntu.com:80 \
     hkp://p80.pool.sks-keyservers.net:80 \
     pgp.mit.edu (http://pgp.mit.edu/) \
     ; do \
     echo "Fetching GPG key $NGINX_GPGKEY from $server"; \
     apt-key adv --keyserver "$server" --keyserver-options timeout=10 --recv-keys "$NGINX_GPGKEY" && found=yes && break; \
     done; \
     test -z "$found" && echo >&2 "error: failed to fetch GPG key $NGINX_GPGKEY" && exit 1; \
     apt-get remove --purge --auto-remove -y gnupg1 && rm -rf /var/lib/apt/lists/* \
     # Install the latest release of NGINX Plus and/or NGINX Plus modules
     # Uncomment individual modules if necessary
     # Use versioned packages over defaults to specify a release
     && nginxPackages=" \
     nginx-plus \
     # nginx-plus=${NGINX_VERSION}-${PKG_RELEASE} \
     # nginx-plus-module-xslt \
     # nginx-plus-module-xslt=${NGINX_VERSION}-${PKG_RELEASE} \
     # nginx-plus-module-geoip \
     # nginx-plus-module-geoip=${NGINX_VERSION}-${PKG_RELEASE} \
     # nginx-plus-module-image-filter \
     # nginx-plus-module-image-filter=${NGINX_VERSION}-${PKG_RELEASE} \
     # nginx-plus-module-perl \
     # nginx-plus-module-perl=${NGINX_VERSION}-${PKG_RELEASE} \
     # nginx-plus-module-njs \
     # nginx-plus-module-njs=${NGINX_VERSION}+${NJS_VERSION}-${PKG_RELEASE} \
     " \
     && echo "Acquire::https::plus-pkgs.nginx.com::Verify-Peer \"true\";" >> /etc/apt/apt.conf.d/90nginx \
     && echo "Acquire::https::plus-pkgs.nginx.com::Verify-Host \"true\";" >> /etc/apt/apt.conf.d/90nginx \
     && echo "Acquire::https::plus-pkgs.nginx.com::SslCert \"/etc/ssl/nginx/nginx-repo.crt\";" >> /etc/apt/apt.conf.d/90nginx \
     && echo "Acquire::https::plus-pkgs.nginx.com::SslKey \"/etc/ssl/nginx/nginx-repo.key\";" >> /etc/apt/apt.conf.d/90nginx \
     && printf "deb https://plus-pkgs.nginx.com/debian buster nginx-plus\n" > /etc/apt/sources.list.d/nginx-plus.list \
     && apt-get update \
     && apt-get install --no-install-recommends --no-install-suggests -y \
     $nginxPackages \
     gettext-base \
     curl \
     && apt-get remove --purge --auto-remove -y && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/nginx-plus.list \
     && rm -rf /etc/apt/apt.conf.d/90nginx /etc/ssl/nginx
     
     # Forward request logs to Docker log collector
     RUN ln -sf /dev/stdout /var/log/nginx/access.log \
     && ln -sf /dev/stderr /var/log/nginx/error.log
     
     COPY nginx.conf /etc/nginx/nginx.conf
     
     EXPOSE 80
     
     STOPSIGNAL SIGTERM
     
     CMD ["nginx", "-g", "daemon off;"]
     ```
   + [https://github.com/awslabs/ecs-nginx-reverse-proxy/tree/master/reverse-proxy/nginx](https://github.com/awslabs/ecs-nginx-reverse-proxy/tree/master/reverse-proxy/nginx) から変更された `nginx.conf` ファイル:

     ```
     events {
       worker_connections 768;
     }
     
     http {
       # Nginx will handle gzip compression of responses from the app server
       gzip on;
       gzip_proxied any;
       gzip_types text/plain application/json;
       gzip_min_length 1000;
     
       upstream backend {
         zone name 10m;
         server app:3000    weight=2;
         server app2:3000    weight=1;
       }
     
       server{
         listen 8080;
         location /api {
           api write=on;
         }
       }
     
       match server_ok {
         status 100-599;
       }
     
       server {
         listen 80;
         status_zone zone;
         # Nginx will reject anything not matching /api
         location /api {
           # Reject requests with unsupported HTTP method
           if ($request_method !~ ^(GET|POST|HEAD|OPTIONS|PUT|DELETE)$) {
             return 405;
           }
     
           # Only requests matching the whitelist expectations will
           # get sent to the application server
           proxy_pass http://backend;
           health_check uri=/lorem-ipsum match=server_ok;
           proxy_http_version 1.1;
           proxy_set_header Upgrade $http_upgrade;
           proxy_set_header Connection 'upgrade';
           proxy_set_header Host $host;
           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
           proxy_cache_bypass $http_upgrade;
         }
       }
     }
     ```

1. 新しいディレクトリのファイルからイメージを作成します。

   ```
   docker build -t nginx-plus-reverse-proxy ./path-to-your-directory
   ```

1. 後で使用するために、新しいイメージをイメージリポジトリにアップロードします。

### Amazon ECS で NGINX Plus とウェブサーバーアプリを実行するタスク定義を作成します。
<a name="ContainerInsights-Prometheus-nginx-plus-ecs-setup-task"></a>

次に、タスク定義を設定します。

このタスク定義により、NGINX Plus Prometheus メトリクスの収集とエクスポートが可能になります。NGINX コンテナは、アプリからの入力を追跡し、(`nginx.conf` で設定されているとおり) そのデータをポート 8080 に公開します。NGINX Prometheus エクスポーターコンテナは、CloudWatch で使用するために、これらのメトリクスをスクレイピングし、ポート 9113 に投稿します。

**NGINX サンプル Amazon ECS ワークロードのタスク定義を設定するには**

1. 次の内容でタスク定義 JSON ファイルを作成します。*your-customized-nginx-plus-image* をカスタマイズした NGINX Plus イメージのイメージ URI に置き換え、*your-web-server-app-image* をウェブサーバーアプリイメージのイメージ URI に置き換えます。

   ```
   {
     "containerDefinitions": [
       {
         "name": "nginx",
         "image": "your-customized-nginx-plus-image",
         "memory": 256,
         "cpu": 256,
         "essential": true,
         "portMappings": [
           {
             "containerPort": 80,
             "protocol": "tcp"
           }
         ],
         "links": [
           "app",
           "app2"
         ]
       },
       {
         "name": "app",
         "image": "your-web-server-app-image",
         "memory": 256,
         "cpu": 128,
         "essential": true
       },
       {
         "name": "app2",
         "image": "your-web-server-app-image",
         "memory": 256,
         "cpu": 128,
         "essential": true
       },
       {
         "name": "nginx-prometheus-exporter",
         "image": "docker.io/nginx/nginx-prometheus-exporter:0.8.0",
         "memory": 256,
         "cpu": 256,
         "essential": true,
         "command": [
           "-nginx.plus",
           "-nginx.scrape-uri",
            "http://nginx:8080/api"
       ],
       "links":[
         "nginx"
       ],
         "portMappings":[
           {
             "containerPort": 9113,
             "protocol": "tcp"
           }
         ]
       }
     ],
     "networkMode": "bridge",
     "placementConstraints": [],
     "family": "nginx-plus-sample-stack"
   }
   ```

1. タスク定義を登録します。

   ```
   aws ecs register-task-definition --cli-input-json file://path-to-your-task-definition-json
   ```

1. 次のコマンドを入力して、タスクを実行するサービスを作成します。

   ```
   aws ecs create-service \
    --cluster your-cluster-name \
    --service-name nginx-plus-service \
    --task-definition nginx-plus-sample-stack:1 \
    --desired-count 1
   ```

   サービス名は変更しないでください。CloudWatch エージェントサービスは、タスクを開始したサービスの名前パターンを使用してタスクを検索する設定を使用して実行します。例えば、このコマンドによって起動されたタスクを CloudWatch エージェントが検出するには、`sd_service_name_pattern` の値を `^nginx-plus-service$` に指定します。次のセクションでは、詳細を説明します。

### NGINX Plus Prometheus メトリクスをスクレイプするように CloudWatch エージェントを設定する
<a name="ContainerInsights-Prometheus-nginx-plus-ecs-setup-agent"></a>

最後のステップでは、NGINX メトリクスをスクレイピングするように CloudWatch エージェントを設定します。この例では、CloudWatch エージェントはサービス名パターンとポート 9113 を使用してタスクを検出します。このポートでは、エクスポーターは NGINX の Prometheus メトリクスを公開します。タスクが検出され、メトリクスが使用可能になると、CloudWatch エージェントは、ログストリーム **nginx-prometheus-exporter** への収集したメトリクスの投稿を開始します。

**NGINX メトリクスをスクレイピングするように CloudWatch エージェントを設定するには**

1. 次のコマンドを入力して、必要な YAML ファイルの最新バージョンをダウンロードします。

   ```
   curl -O https://raw.githubusercontent.com/aws-samples/amazon-cloudwatch-container-insights/latest/ecs-task-definition-templates/deployment-mode/replica-service/cwagent-prometheus/cloudformation-quickstart/cwagent-ecs-prometheus-metric-for-bridge-host.yaml
   ```

1. テキストエディタでファイルを開き、`value` セクションの `resource:CWAgentConfigSSMParameter` キーにある完全な CloudWatch エージェント設定を見つけます。その後、`ecs_service_discovery` セクションで、次の `service_name_list_for_tasks` セクションを追加します。

   ```
   "service_name_list_for_tasks": [
     {
       "sd_job_name": "nginx-plus-prometheus-exporter",
       "sd_metrics_path": "/metrics",
       "sd_metrics_ports": "9113",
       "sd_service_name_pattern": "^nginx-plus.*"
      }
   ],
   ```

1. 同じファイルで、`metric_declaration` セクションに次のセクションを追加して、NGINX Plus メトリクスを許可します。デフォルトのインデントパターンに従ってください。

   ```
   {
     "source_labels": ["job"],
     "label_matcher": "^nginx-plus.*",
     "dimensions": [["ClusterName", "TaskDefinitionFamily", "ServiceName"]],
     "metric_selectors": [
       "^nginxplus_connections_accepted$",
       "^nginxplus_connections_active$",
       "^nginxplus_connections_dropped$",
       "^nginxplus_connections_idle$",
       "^nginxplus_http_requests_total$",
       "^nginxplus_ssl_handshakes$",
       "^nginxplus_ssl_handshakes_failed$",
       "^nginxplus_up$",
       "^nginxplus_upstream_server_health_checks_fails$"
     ]
   },
   {
     "source_labels": ["job"],
     "label_matcher": "^nginx-plus.*",
     "dimensions": [["ClusterName", "TaskDefinitionFamily", "ServiceName", "upstream"]],
     "metric_selectors": [
       "^nginxplus_upstream_server_response_time$"
     ]
   },
   {
     "source_labels": ["job"],
     "label_matcher": "^nginx-plus.*",
     "dimensions": [["ClusterName", "TaskDefinitionFamily", "ServiceName", "code"]],
     "metric_selectors": [
       "^nginxplus_upstream_server_responses$",
       "^nginxplus_server_zone_responses$"
     ]
   },
   ```

1. このクラスターにまだ CloudWatch エージェントがデプロイされていない場合は、ステップ 8 に進みます。

   AWS CloudFormation を使用することによって Amazon ECS クラスターに CloudWatch エージェントを既にデプロイしている場合は、次のコマンドを入力して変更セットを作成できます。

   ```
   ECS_CLUSTER_NAME=your_cluster_name
   AWS_REGION=your_aws_region
   ECS_NETWORK_MODE=bridge
   CREATE_IAM_ROLES=True
   ECS_TASK_ROLE_NAME=your_selected_ecs_task_role_name
   ECS_EXECUTION_ROLE_NAME=your_selected_ecs_execution_role_name
   
   aws cloudformation create-change-set --stack-name CWAgent-Prometheus-ECS-${ECS_CLUSTER_NAME}-EC2-${ECS_NETWORK_MODE} \
       --template-body file://cwagent-ecs-prometheus-metric-for-bridge-host.yaml \
       --parameters ParameterKey=ECSClusterName,ParameterValue=$ECS_CLUSTER_NAME \
                    ParameterKey=CreateIAMRoles,ParameterValue=$CREATE_IAM_ROLES \
                    ParameterKey=ECSNetworkMode,ParameterValue=$ECS_NETWORK_MODE \
                    ParameterKey=TaskRoleName,ParameterValue=$ECS_TASK_ROLE_NAME \
                    ParameterKey=ExecutionRoleName,ParameterValue=$ECS_EXECUTION_ROLE_NAME \
       --capabilities CAPABILITY_NAMED_IAM \
       --region $AWS_REGION \
       --change-set-name nginx-plus-scraping-support
   ```

1. [https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/) で CloudFormation コンソール を開きます。

1. 新しく作成されたチェンジセット **nginx-plus-scraping-support** を確認します。**CWAgentConfigSSMParameter** リソースに適用された変更が 1 つ表示されます。次のコマンドを入力して、変更セットを実行し、CloudWatch エージェントタスクを再起動します。

   ```
   aws ecs update-service --cluster $ECS_CLUSTER_NAME \
   --desired-count 0 \
   --service cwagent-prometheus-replica-service-EC2-$ECS_NETWORK_MODE \
   --region $AWS_REGION
   ```

1. 10 秒ほど待ってから、次のコマンドを入力します。

   ```
   aws ecs update-service --cluster $ECS_CLUSTER_NAME \
   --desired-count 1 \
   --service cwagent-prometheus-replica-service-EC2-$ECS_NETWORK_MODE \
   --region $AWS_REGION
   ```

1. クラスターの Prometheus メトリクス収集を使用して CloudWatch エージェントを初めてインストールする場合は、次のコマンドを入力します。

   ```
   ECS_CLUSTER_NAME=your_cluster_name
   AWS_REGION=your_aws_region
   ECS_NETWORK_MODE=bridge
   CREATE_IAM_ROLES=True
   ECS_TASK_ROLE_NAME=your_selected_ecs_task_role_name
   ECS_EXECUTION_ROLE_NAME=your_selected_ecs_execution_role_name
   
   aws cloudformation create-stack --stack-name CWAgent-Prometheus-ECS-${ECS_CLUSTER_NAME}-EC2-${ECS_NETWORK_MODE} \
       --template-body file://cwagent-ecs-prometheus-metric-for-bridge-host.yaml \
       --parameters ParameterKey=ECSClusterName,ParameterValue=$ECS_CLUSTER_NAME \
                    ParameterKey=CreateIAMRoles,ParameterValue=$CREATE_IAM_ROLES \
                    ParameterKey=ECSNetworkMode,ParameterValue=$ECS_NETWORK_MODE \
                    ParameterKey=TaskRoleName,ParameterValue=$ECS_TASK_ROLE_NAME \
                    ParameterKey=ExecutionRoleName,ParameterValue=$ECS_EXECUTION_ROLE_NAME \
       --capabilities CAPABILITY_NAMED_IAM \
       --region $AWS_REGION
   ```

## NGINX Plus メトリクスとログの表示
<a name="ContainerInsights-Prometheus-Setup-nginx-plus-view"></a>

これで、収集されている NGINX Plus メトリクスを表示できるようになりました。

**サンプル NGINX ワークロードのメトリクスを表示するには**

1. CloudWatch コンソールの [https://console.aws.amazon.com/cloudwatch/](https://console.aws.amazon.com/cloudwatch/) を開いてください。

1. クラスターが実行されているリージョンにおいて、左のナビゲーションペインで [**Metrics**] (メトリクス) を選択します。**ContainerInsights/Prometheus** 名前空間を検索して、メトリクスを確認します。

1. CloudWatch Logs イベントを表示するには、ナビゲーションペインで [**Log Groups (ロググループ)**] を選択します。イベントは、ログストリーム *nginx-plus-prometheus-exporter* のロググループ **/aws/containerinsights/*your\$1cluster\$1name*/prometheus** にあります。