AWS CopilotでAWS App Runnerプライベートアクセスのデプロイを試す！

# 背景
最近のAWSアップデートにて、AWS App RunnerでVPC内からのアクセスのみ受け入れる設定ができるようになりました！
これによりPrivate用途での利用が可能になり、App Runnerの幅が広がりました。

https://aws.amazon.com/jp/about-aws/whats-new/2022/11/aws-app-runner-supports-privately-accessible-services-amazon-vpc/

こちらのアップデートに追随する形で、AWS Copilotでもプライベートに対応したデプロイができるようになりました。

https://aws.amazon.com/jp/about-aws/whats-new/2022/11/aws-copilot-aws-app-runners-privately-services/

# 試してみる
AWS CopilotからApp Runnerのプライベートアクセスのデプロイを試してみます。

## 前提
Copilotのインストールは以下を参考に実施。

https://aws.github.io/copilot-cli/ja/docs/overview/

App Runnerにデプロイするコンテナは以下のページをもとに作成しています。(ECRにPush済み)

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/create-container-image.html

実行環境はCloud9(ec2)を利用しています。

## Application,Serviceの作成

まず、initをします。workload typeはApp Runnerを選択し、表示された内容に沿って値を入力します。

```shell
$ copilot init
    Note: It's best to run this command in the root of your Git repository.
    Welcome to the Copilot CLI! We're going to walk you through some questions
    to help you get set up with a containerized application on AWS. An application is a collection of
    containerized services that operate together.

    Application name: test-app

    Which workload type best represents your architecture?  [Use arrows to move, type to filter, ? for more help]
    Workload type: Request-Driven Web Service
    Service name: test-svc
    Dockerfile: Use an existing image instead
    Image: <AccountID>.dkr.ecr.<Region>.amazonaws.com/<REP_NAME>:<TAG>
    Port: 80
    Ok great, we'll set up a Request-Driven Web Service named test-svc in application test-app listening on port 80.
```
ここまで実施したところで、アカウント内にCFnスタックからロールが作成されます。
スタックの作成が完了した時点で、Deployを行われるか聞かれるため、**No**を選択します。

:::note ingfo
このままデプロイを行うと、パブリックに展開されます。
:::

```shell
    All right, you're all set for local development.
    Deploy: No

    No problem, you can deploy your service later:
    - Run `copilot env init` to create your environment.
    - Run `copilot deploy` to deploy your service.
    - Be a part of the Copilot ✨community✨!
      Ask or answer a question, submit a feature request...
      Visit 👉 https://aws.github.io/copilot-cli/community/get-involved/ to see how!
```
`copilot/test-svc/`内に、`manifest.yml`が生成されているので、以下のように修正します。

<details><summary>manifest.yml</summary>

```diff_yaml
# The manifest for the "sample-service" service.
# Read the full specification for the "Request-Driven Web Service" type at:
# https://aws.github.io/copilot-cli/docs/manifest/rd-web-service/

# Your service name will be used in naming your resources like log groups, App Runner services, etc.
name: sample-service
# The "architecture" of the service you're running.
type: Request-Driven Web Service

image:
  # The name of the Docker image.
  location: ACCOUNT_ID.dkr.ecr.REGION.amazonaws.com/REPO_NAME
  # Port exposed through your container to route traffic to it.
  port: 80

- # http:
+ http:
+   private: true
#   healthcheck:
#     path: /
#     healthy_threshold: 3
#     unhealthy_threshold: 5
#     interval: 10s
#     timeout: 5s

# Number of CPU units for the task.
cpu: 1024
# Amount of memory in MiB used by the task.
memory: 2048

# Connect your App Runner service to your environment's VPC.
# network:
#   vpc:
#     placement: private

# Enable tracing for the service.
# observability:
#   tracing: awsxray

# Optional fields for more advanced use-cases.
#
# variables:                    # Pass environment variables as key value pairs.
#   LOG_LEVEL: info
#
# tags:                         # Pass tags as key value pairs.
#   project: project-name

# You can override any of the values defined above by environment.
# environments:
#   test:
#     variables:
#       LOG_LEVEL: debug        # Log level for the "test" environment.
```

</details>

## Environmentの作成,展開
デフォルトの環境設定を利用します。

```shell
$ copilot env init
    Environment name: test-env
    Credential source: [profile default]
    Default environment configuration? Yes, use default.
    ✔ Wrote the manifest for environment test-env at copilot/environments/test-env/manifest.yml
    - Update regional resources with stack set "test-app-infrastructure"  [succeeded]  [0.0s]
    - Update regional resources with stack set "test-app-infrastructure"  [succeeded]        [131.4s]
      - Update resources in region "us-west-2"                            [create complete]  [128.0s]
        - KMS key to encrypt pipeline artifacts between stages            [create complete]  [121.4s]
        - ECR container image repository for "test-svc"                   [create complete]  [2.2s]
        - S3 Bucket to store local artifacts                              [create complete]  [2.3s]
    ✔ Proposing infrastructure changes for the test-app-test-env environment.
    - Creating the infrastructure for the test-app-test-env environment.  [create complete]  [56.3s]
      - An IAM Role for AWS CloudFormation to manage resources            [create complete]  [21.8s]
      - An IAM Role to describe resources in your environment             [create complete]  [22.6s]
    ✔ Provisioned bootstrap resources for environment test-env in region us-west-2 under application test-app.
    Recommended follow-up actions:
      - Update your manifest copilot/environments/test-env/manifest.yml to change the defaults.
      - Run `copilot env deploy --name test-env` to deploy your environment.
```

環境のデプロイの実施
```shell
$ copilot env deploy --name test-env
✔ Proposing infrastructure changes for the test-app-test-env environment.
- Creating the infrastructure for the test-app-test-env environment.          [update complete]  [76.6s]
  - An ECS cluster to group your services                                     [create complete]  [3.7s]
  - A security group to allow your containers to talk to each other           [create complete]  [3.2s]
  - An Internet Gateway to connect to the public internet                     [create complete]  [15.4s]
  - Private subnet 1 for resources with no internet access                    [create complete]  [5.3s]
  - Private subnet 2 for resources with no internet access                    [create complete]  [2.8s]
  - A custom route table that directs network traffic for the public subnets  [create complete]  [11.3s]
  - Public subnet 1 for resources that can access the internet                [create complete]  [2.6s]
  - Public subnet 2 for resources that can access the internet                [create complete]  [2.6s]
  - A private DNS namespace for discovering services within the environment   [create complete]  [44.3s]
  - A Virtual Private Cloud to control networking of your AWS resources       [create complete]  [12.6s]
```

## Serviceのデプロイ
アプリケーションと環境を指定してサービスをデプロイします。
```shell
$ copilot svc deploy --name test-svc --env test-env --app test-app
    ✔ Proposing infrastructure changes for stack test-app-test-env-test-svc
    - Creating the infrastructure for stack test-app-test-env-test-svc                [create complete]  [333.9s]
      - An IAM Role for App Runner to use on your behalf to pull your image from ECR  [create complete]  [21.0s]
      - The ingress connection from your environment to this service                  [create complete]  [22.7s]
      - Update your environment's shared resources                                    [update complete]  [54.0s]
        - A security group for App Runner private services                            [create complete]  [4.6s]
        - VPC Endpoint to connect environment to App Runner for private services      [create complete]  [32.0s]
      - An IAM role to update your environment stack                                  [create complete]  [23.1s]
      - An IAM role to control permissions for the containers in your service         [create complete]  [21.0s]
      - An App Runner service to run and manage your containers                       [create complete]  [277.6s]
    ✔ Deployed service test-svc.
    Recommended follow-up action:
      - You can access your service at https://p36nuj6uyk.us-west-2.awsapprunner.com from your internal network.
```

デプロイが完了したのでApp runnerのコンソールを見に行くと、Privateで作成されていることが確認できます。

![スクリーンショット 2022-12-01 154444.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675893/936dcc2c-e088-0de2-e9da-1f3491013c21.png)

デフォルトのエンドポイントは外からだとアクセスできませんが、VPC内にインスタンスを立ててリクエストを送るとアクセスできます。
※VPC EndpointのSecurity Group設定の修正が必要
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675893/29e73441-04e9-375b-206e-32f7d00c2210.png)

# 終わりに
App RunnerのプライベートアクセスをCopilotからデプロイしてみた記事でした。気軽にコンテナを実行したい際にApp Runnerを利用するのですが、中に閉じておきたいときはプライベートアクセスを利用したいと思います。