Actions Runner Controller (ARC)とNew Relicを使って無料でCI/CD環境の構築とモニタリングをしてみた

# はじめに
本記事では無料でCI/CD環境とその環境のモニタリング、アラート発砲をActions Runner Controller (ARC)とNew Relicを使って構築する方法を紹介します。

# Actions Runner Controller (ARC)とは
ARCとはGitHub Actionsのランナーになります。GitHub Actionsで使用できるランナーには以下の2種類がありますが、後者に該当します
- GitHub-hosted runner
  - GitHubが管理・保守されるランナー
  - 無料枠やパブリックリポジトリでは無料などはあるが、基本的に[有料](https://docs.github.com/ja/billing/managing-billing-for-github-actions/about-billing-for-github-actions)
- Self-hosted runner
  - 自身で管理・保守する必要のあるランナー
  - 自身のマシンにインストールすれば追加料金は不要

Self-hosted runnerはLinux, Windows, Macなどにインストールすることが可能ですが、Kubernetes上で自動スケーリングなどが可能なため、今回選択しました。

# New Relicとは
[公式ホームページ](https://newrelic.com/jp)にいろいろと書いていますが、監視・モニタリングなどのオブザーバビリティを導入できるSaaSです。業務でDataDogなどを利用している方も多いと思いますが、今回は無料で使用できる機能が多かったので、New Relicを選択しました。今回構築したモニタリング、アラート発砲をDataDogで実現する場合には、[Proプラン](https://www.datadoghq.com/ja/pricing/)の`$18.75/month`は必要になります(2024/4/21時点)。

# 使用環境
今回は以下の環境に構築していきました。
- OS: Windows10 home
- WSL
  - ubuntu 20.04：kubectl/helmをたたく環境
- Kubernetes環境
  - 使用ツール：Rancher Desktop v1.12.3
```bash
$ kubectl version
Client Version: v1.28.2
Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
Server Version: v1.28.6+k3s2
$ helm version
version.BuildInfo{Version:"v3.13.3", GitCommit:"c8b948945e52abba22ff885446a1486cb5fd3474", GitTreeState:"clean", GoVersion:"go1.20.11"}
```

# インストール
## ARC
ARCを[公式手順](https://docs.github.com/ja/actions/hosting-your-own-runners/managing-self-hosted-runners-with-actions-runner-controller/quickstart-for-actions-runner-controller)に従ってインストールしていきます。
コントローラーのインストールから実施していきます。
```bash
$ helm install arc     --namespace "arc"     --create-namespace     oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set-controller --version 0.9.1
docker-credential-secretservice: error while loading shared libraries: libsecret-1.so.0: cannot open shared object file: No such file or directory
Pulled: ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set-controller:0.8.2
Digest: sha256:d4e2835bc2e96adb210efc10264c9864393aa3e24bdb8c5f8ccae059488765fc
NAME: arc
LAST DEPLOYED: Sun Feb 18 00:34:56 2024
NAMESPACE: arc
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Thank you for installing gha-runner-scale-set-controller.

Your release is named arc.
```
次にランナーセットのインストールをしていきます。ここで環境変数`GITHUB_CONFIG_URL`と`GITHUB_PAT`は各自の環境に合わせて事前に設定してください。
`GITHUB_CONFIG_URL`はGitHubのURLです。ランナーはリポジトリ毎やorganization毎に作成が可能です。それぞれ以下のようなURLになります。
- リポジトリランナー：`https://github.com/<organization名>/<リポジトリ名>`
- organizationランナー：`https://github.com/<organization名>`

`GITHUB_PAT`は必要な[権限](https://docs.github.com/ja/actions/hosting-your-own-runners/managing-self-hosted-runners-with-actions-runner-controller/authenticating-to-the-github-api#personal-access-token-classic-%E3%81%A7-arc-%E3%81%AE%E8%AA%8D%E8%A8%BC%E3%82%92%E8%A1%8C%E3%81%86)がランナーの単位によって違います。
- リポジトリランナー：`repo`
- organizaitonランナー：`admin:org`
```bash
helm install "arc-runner-set"     --namespace "arc-runners"     --create-namespace     --set githubConfigUrl="${GITHUB_CONFIG_URL}"     --set githubConfigSecret.github_token="${GITHUB_PAT}"     oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set --version 0.9.1
docker-credential-secretservice: error while loading shared libraries: libsecret-1.so.0: cannot open shared object file: No such file or directory
Pulled: ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set:0.8.2
Digest: sha256:e715cbd53bd1d186dd7c1430ea105cb14f27f6dae185a5b5820c82c057555b71
NAME: arc-runner-set
LAST DEPLOYED: Sun Feb 18 00:43:11 2024
NAMESPACE: arc-runners
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Thank you for installing gha-runner-scale-set.

Your release is named arc-runner-set.
$ helm list -A

NAME            NAMESPACE       REVISION        UPDATED                                 STATUS          CHART                                   APP VERSION
arc             arc             1               2024-02-18 00:34:56.7723247 +0900 JST   deployed        gha-runner-scale-set-controller-0.8.2   0.8.2      
arc-runner-set  arc-runners     1               2024-02-18 00:43:11.8433244 +0900 JST   deployed        gha-runner-scale-set-0.8.2              0.8.2

$ kubectl get pods -n arc
NAME                                     READY   STATUS    RESTARTS      AGE
arc-gha-rs-controller-7dd75477f8-8h8gk   1/1     Running   2 (25m ago)   19d
arc-runner-set-754b578d-listener         1/1     Running   0             9m46s
```
ここまでで、ARCのインストールは完了しましたが、メトリクスはデフォルトで無効になっているので、[公式手順](https://docs.github.com/ja/actions/hosting-your-own-runners/managing-self-hosted-runners-with-actions-runner-controller/deploying-runner-scale-sets-with-actions-runner-controller#enabling-metrics)に従って有効化していきます。

また、口述しますが、New Relicでpromethus形式のメトリクスをとるためには`prometheus.io/scrape: "true"` annotationが必要になります。上記の2つの設定をhelm valueファイルに記載すると以下のようになります。
```yaml:values.yaml
podAnnotations:
  prometheus.io/scrape: "true"

metrics:
  controllerManagerAddr: ":8080"
  listenerAddr: ":8080"
  listenerEndpoint: "/metrics"
```

上記ファイルでコントローラーの`helm update`していきます。
```bash
$ helm upgrade -n arc arc -f values.yaml oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set-controller --version 0.9.1
docker-credential-secretservice: error while loading shared libraries: libsecret-1.so.0: cannot open shared object file: No such file or directory
docker-credential-secretservice: error while loading shared libraries: libsecret-1.so.0: cannot open shared object file: No such file or directory
Pulled: ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set-controller:0.9.0
Digest: sha256:06b038d924d82eb1f803fd7dbde7a6674e4aea83f681815cb3cffb610e424cff
Release "arc" has been upgraded. Happy Helming!
NAME: arc
LAST DEPLOYED: Thu Mar 28 19:37:54 2024
NAMESPACE: arc
STATUS: deployed
REVISION: 2
TEST SUITE: None
NOTES:
Thank you for installing gha-runner-scale-set-controller.

Your release is named arc.

WARNING: Older version of the listener (githubrunnerscalesetlistener) is deprecated and will be removed in the future gha-runner-scale-set-0.10.0 release. If you are using environment variable override to force the old listener, please remove the environment variable and use the new listener (ghalistener) instead.
```
listnerも同様にannotationを付与するためのhelm valueファイルは以下のようになります。
```yaml:listenr-values.yaml
listenerTemplate:
  metadata:
    annotations:
      prometheus.io/scrape: "true"
  spec:
    containers:
    # Use this section to append additional configuration to the listener container.
    # If you change the name of the container, the configuration will not be applied to the listener,
    # and it will be treated as a side-car container.
    - name: listener
```
上記ファイルでlistenrの`helm update`をしていきます。
```bash
helm upgrade -n arc-runners arc-runner-set -f listner-values.yaml oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set --set githubConfigSecret.github_token="<GitHub Token>"  --set githubConfigUrl="<GITHUB URL>" --version 0.9.1
WARNING: Kubernetes configuration file is group-readable. This is insecure. Location: /home/uc/.kube/config
WARNING: Kubernetes configuration file is world-readable. This is insecure. Location: /home/uc/.kube/config
docker-credential-secretservice: error while loading shared libraries: libsecret-1.so.0: cannot open shared object file: No such file or directory
Pulled: ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set:0.9.0
Digest: sha256:f76dbf77a28206f030ab3165360cc6c028b13bcefde26284e6959323176e803e
Release "arc-runner-set" has been upgraded. Happy Helming!
NAME: arc-runner-set
LAST DEPLOYED: Thu Apr 18 17:48:41 2024
NAMESPACE: arc-runners
STATUS: deployed
REVISION: 5
TEST SUITE: None
NOTES:
Thank you for installing gha-runner-scale-set.

Your release is named arc-runner-set.
```
## New Relic
続いてNew Relicをインストールしていきます。
![newrelic-install.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3775581/1ece7702-c7b7-bcc9-1222-4ef5c17c5cee.png)
上記画像のGuided installを選ぶと環境に合わせてインストールコマンドが表示されるので、それに従ってインストールできます。今回はKubernetes環境なので以下を選択してインストールしていきます。
- Kubernetes -> Helm

基本的には各自の取得したい項目を選んでいけばインストールコマンドが生成されます。ログなどはデータ量が多くなり、無料枠を超える可能性があるので今回はオフにしています。

ARCはpromethus形式でメトリクスを出力するため、newrelicプロメテウスエージェントによってメトリクスを収集します。今回は対象を絞るために、以下のように対象を絞ります。
- prometheus.io/scrape: "true"のannotationが付与されているpod
- podのラベルがいかに一致するpod
  - `app.kubernetes.io/name=gha-rs-controller`
  - `app.kubernetes.io/component=runner-scale-set-listener`
  - [デフォルト値](https://github.com/newrelic/newrelic-prometheus-configurator/blob/main/charts/newrelic-prometheus-agent/values.yaml#L225-L228)

今回の選んだオプションをhelm valueファイルにあらわしたものは以下になります。
```yaml:nri-values.yaml
newrelic-infrastructure:
  enabled: true
  
nri-prometheus:
  enabled: false

nri-metadata-injection:
  enabled: true

kube-state-metrics:
  enabled: true

nri-kube-events:
  enabled: true

newrelic-logging:
  enabled: false
  
newrelic-pixie:
  enabled: false

pixie-chart:
  enabled: false

newrelic-infra-operator:
  enabled: false

newrelic-prometheus-agent:
  enabled: true
  config:
    kubernetes:
      integrations_filter:
        enabled: true
        source_labels: ["app.kubernetes.io/name", "app.kubernetes.io/component"]
        app_values: ["gha-rs-controller", "runner-scale-set-listener"]

newrelic-k8s-metrics-adapter:
  enabled: false
```
上記ファイルを使ってインストール
```bash
$ KSM_IMAGE_VERSION="v2.10.0" && helm repo add newrelic https://helm-charts.newrelic.com && helm repo update && kubectl create namespace newrelic ; helm upgrade --install newrelic-bundle newrelic/nri-bundle --values nri-values.yaml --set global.licenseKey=<license key> --set global.cluster=rancher-desktop --namespace=newrelic 
WARNING: Kubernetes configuration file is group-readable. This is insecure. Location: /home/uc/.kube/config
WARNING: Kubernetes configuration file is world-readable. This is insecure. Location: /home/uc/.kube/config
"newrelic" already exists with the same configuration, skipping
WARNING: Kubernetes configuration file is group-readable. This is insecure. Location: /home/uc/.kube/config
WARNING: Kubernetes configuration file is world-readable. This is insecure. Location: /home/uc/.kube/config
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "datadog" chart repository
...Successfully got an update from the "newrelic" chart repository
Update Complete. ⎈Happy Helming!⎈
Error from server (AlreadyExists): namespaces "newrelic" already exists
WARNING: Kubernetes configuration file is group-readable. This is insecure. Location: /home/uc/.kube/config
WARNING: Kubernetes configuration file is world-readable. This is insecure. Location: /home/uc/.kube/config
Release "newrelic-bundle" has been upgraded. Happy Helming!
NAME: newrelic-bundle
LAST DEPLOYED: Sun Apr 14 15:30:52 2024
NAMESPACE: newrelic
STATUS: deployed
REVISION: 2
TEST SUITE: None

$ kubectl get pod -n newrelic -w
NAME                                                      READY   STATUS    RESTARTS   AGE
newrelic-bundle-nri-metadata-injection-56df859c76-jw27c   1/1     Running   0          33m
newrelic-bundle-newrelic-prometheus-agent-0               1/1     Running   0          13m
newrelic-bundle-kube-state-metrics-7d4f664976-5lv86       1/1     Running   0          9m44s
newrelic-bundle-nrk8s-kubelet-5wvjv                       2/2     Running   0          62s
newrelic-bundle-nrk8s-controlplane-l9rw5                  2/2     Running   0          61s
newrelic-bundle-nrk8s-ksm-64785f445f-z2hs4                2/2     Running   0          61s
newrelic-bundle-nri-kube-events-784688f776-x5p8q          2/2     Running   0          5s
```

# DashBoard作成
ここまででARC, New Relicのインストールは終わり、メトリクスが取れているはずなので、ダッシュボードを作成していきます。
![newrelic-metrics.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3775581/d963ee07-98da-2c02-fd3b-59560c716a2e.png)
メトリクスから`gha`で検索すると画像のようにARCに関するメトリクスが取れるので、`Add to dashboard`からダッシュボードに追加していくのが楽だと思います。今回作ったダッシュボードのjsonを以下に貼っておくので参考にカスタマイズして使ってみてください。
<details><summary>dashboardのjsonファイル</summary>

```json
{
  "name": "GHA",
  "description": null,
  "permissions": "PRIVATE",
  "pages": [
    {
      "name": "Controller",
      "description": null,
      "widgets": [
        {
          "title": "failed_ephemeral_runners",
          "layout": {
            "column": 1,
            "row": 1,
            "width": 4,
            "height": 3
          },
          "linkedEntityGuids": null,
          "visualization": {
            "id": "viz.line"
          },
          "rawConfiguration": {
            "nrqlQueries": [
              {
                "accountId": <account id>,
                "query": "SELECT latest(gha_controller_failed_ephemeral_runners) FROM Metric FACET app_kubernetes_io_name SINCE 30 MINUTES AGO TIMESERIES"
              }
            ]
          }
        },
        {
          "title": "pending_ephemeral_runners",
          "layout": {
            "column": 5,
            "row": 1,
            "width": 4,
            "height": 3
          },
          "linkedEntityGuids": null,
          "visualization": {
            "id": "viz.line"
          },
          "rawConfiguration": {
            "nrqlQueries": [
              {
                "accountId": <account id>,
                "query": "SELECT latest(gha_controller_pending_ephemeral_runners) FROM Metric FACET app_kubernetes_io_name SINCE 30 MINUTES AGO TIMESERIES"
              }
            ]
          }
        },
        {
          "title": "running_ephemeral_runners",
          "layout": {
            "column": 9,
            "row": 1,
            "width": 4,
            "height": 3
          },
          "linkedEntityGuids": null,
          "visualization": {
            "id": "viz.line"
          },
          "rawConfiguration": {
            "nrqlQueries": [
              {
                "accountId": <account id>,
                "query": "SELECT latest(gha_controller_running_ephemeral_runners) FROM Metric FACET app_kubernetes_io_name SINCE 30 MINUTES AGO TIMESERIES"
              }
            ]
          }
        }
      ]
    },
    {
      "name": "Listner",
      "description": null,
      "widgets": [
        {
          "title": "Number of Runners Missing",
          "layout": {
            "column": 1,
            "row": 1,
            "width": 4,
            "height": 3
          },
          "linkedEntityGuids": null,
          "visualization": {
            "id": "viz.billboard"
          },
          "rawConfiguration": {
            "facet": {
              "showOtherSeries": false
            },
            "nrqlQueries": [
              {
                "accountIds": [
                  <account id>
                ],
                "query": "SELECT latest(gha_desired_runners) - latest(gha_busy_runners) FROM Metric FACET actions_github_com_scale_set_name "
              }
            ],
            "platformOptions": {
              "ignoreTimeRange": false
            }
          }
        },
        {
          "title": "assigned_jobs",
          "layout": {
            "column": 5,
            "row": 1,
            "width": 4,
            "height": 3
          },
          "linkedEntityGuids": null,
          "visualization": {
            "id": "viz.line"
          },
          "rawConfiguration": {
            "colors": {
              "seriesOverrides": [
                {
                  "color": "#3302f7",
                  "seriesName": "arc-runner-set-2"
                }
              ]
            },
            "nrqlQueries": [
              {
                "accountId": <account id>,
                "query": "SELECT latest(gha_assigned_jobs) FROM Metric FACET actions_github_com_scale_set_name SINCE 30 MINUTES AGO TIMESERIES"
              }
            ]
          }
        },
        {
          "title": "running_jobs",
          "layout": {
            "column": 9,
            "row": 1,
            "width": 4,
            "height": 3
          },
          "linkedEntityGuids": null,
          "visualization": {
            "id": "viz.line"
          },
          "rawConfiguration": {
            "colors": {
              "seriesOverrides": [
                {
                  "color": "#3302f7",
                  "seriesName": "arc-runner-set-2"
                }
              ]
            },
            "nrqlQueries": [
              {
                "accountId": <account id>,
                "query": "SELECT latest(gha_running_jobs) FROM Metric FACET actions_github_com_scale_set_name SINCE 30 MINUTES AGO TIMESERIES"
              }
            ]
          }
        },
        {
          "title": "registered_runners",
          "layout": {
            "column": 1,
            "row": 4,
            "width": 4,
            "height": 3
          },
          "linkedEntityGuids": null,
          "visualization": {
            "id": "viz.line"
          },
          "rawConfiguration": {
            "colors": {
              "seriesOverrides": [
                {
                  "color": "#3302f7",
                  "seriesName": "arc-runner-set-2"
                }
              ]
            },
            "nrqlQueries": [
              {
                "accountId": <account id>,
                "query": "SELECT latest(gha_registered_runners) FROM Metric FACET actions_github_com_scale_set_name SINCE 30 MINUTES AGO TIMESERIES"
              }
            ]
          }
        },
        {
          "title": "busy_runners",
          "layout": {
            "column": 5,
            "row": 4,
            "width": 4,
            "height": 3
          },
          "linkedEntityGuids": null,
          "visualization": {
            "id": "viz.line"
          },
          "rawConfiguration": {
            "colors": {
              "seriesOverrides": [
                {
                  "color": "#3302f7",
                  "seriesName": "arc-runner-set-2"
                }
              ]
            },
            "nrqlQueries": [
              {
                "accountId": <account id>,
                "query": "SELECT latest(gha_busy_runners) FROM Metric FACET actions_github_com_scale_set_name SINCE 30 MINUTES AGO TIMESERIES"
              }
            ]
          }
        },
        {
          "title": "desired_runners",
          "layout": {
            "column": 9,
            "row": 4,
            "width": 4,
            "height": 3
          },
          "linkedEntityGuids": null,
          "visualization": {
            "id": "viz.line"
          },
          "rawConfiguration": {
            "colors": {
              "seriesOverrides": [
                {
                  "color": "#3302f7",
                  "seriesName": "arc-runner-set-2"
                }
              ]
            },
            "facet": {
              "showOtherSeries": false
            },
            "legend": {
              "enabled": true
            },
            "nrqlQueries": [
              {
                "accountIds": [
                  <account id>
                ],
                "query": "SELECT latest(gha_desired_runners) FROM Metric FACET actions_github_com_scale_set_name AS actions_github_com_scale_set_name SINCE 30 MINUTES AGO TIMESERIES"
              }
            ],
            "platformOptions": {
              "ignoreTimeRange": false
            },
            "thresholds": {
              "isLabelVisible": true
            },
            "yAxisLeft": {
              "zero": true
            },
            "yAxisRight": {
              "zero": true
            }
          }
        }
      ]
    }
  ],
  "variables": []
}
```
</details>

ダッシュボードはこんな感じになりました。
![newrelic-dashboard-controller.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3775581/e149685b-b12d-2fb1-cc01-e389a9b5cbf0.png)
![newrelic-dashboard-listner.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3775581/de2d14c8-e735-c726-fa0d-fef1aced1064.png)

listnerの最初のウィジェットは以下のクエリで作成してます
```sql
SELECT latest(gha_desired_runners) - latest(gha_busy_runners) FROM Metric FACET actions_github_com_scale_set_name
```
これは必要なrunnnerの数(`gha_desired_runners`)と実行中のrunnerの数(`gha_busy_runners`)の数を比較しています。これが0より大きい状態が続いた場合は、何らかの理由でrunnerが起動しないという状態であることがわかります。このウィジェットを利用してアラームを設定していきます。
# Alert作成
Alertはウィジェットの`Create alert condition`から作成が可能です。
![newrelic-create-alert.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3775581/35315f9d-4861-a06d-f9aa-fd4ccd128fd2.png)

先ほどのクエリを利用してGUIの画面に沿って作成していきます。
以下の設定以外はすべてデフォルト設定で作成しました。
- 閾値：1以上を5min以上
- ギャップ埋め：最後の値を利用
  - 個人利用のため、マシンのシャットダウンをするため、設定しないとアラームが鳴り続ける

terraformで作成する場合は以下のコードで作成可能です。
<details><summary>Alertのterraformコード</summary>

```terraform
resource "newrelic_nrql_alert_condition" "runner" {
  account_id = 4419235
  policy_id = 5243229
  type = "static"
  name = "Runnerが起動しない"

  description = <<-EOT
  必要とされているRunnerよりも実行中のRunnnerの数が少ないのが5min以上発生
  EOT

  enabled = true
  violation_time_limit_seconds = 259200 # 3 days

  nrql {
    query = "SELECT latest(gha_desired_runners) - latest(gha_busy_runners) FROM Metric FACET actions_github_com_scale_set_name"
  }

  critical {
    operator = "above_or_equals"
    threshold = 1
    threshold_duration = 300
    threshold_occurrences = "all"
  }
  fill_option = "last_value"
  aggregation_window = 60
  aggregation_method = "event_flow"
  aggregation_delay = 120
}

```
</details>


今回はalert発生した場合はslack通知を設定しました。テスト結果は以下です。
![newrelic-alert-test.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3775581/fbde91a6-93d0-49ba-a307-cf20136465ae.png)
### Alert通知確認
アラートの通知がうまく動作するかを試してみました。今回はrunnerが作成される`namespace`に以下のリソースクオーターをつけてrunnerが作成されないようにしました。
```yaml:resource-quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: pods-medium
  namespace: arc-runners
spec:
  hard:
    cpu: "10"
    memory: 20Gi
```
```bash
$ kubectl apply -f resource-quota.yaml 
resourcequota/pods-medium created
$ kubectl get resourcequotas -n arc-runners 
NAME          AGE   REQUEST                     LIMIT
pods-medium   9s    cpu: 0/10, memory: 0/20Gi   
$ kubectl get ephemeralrunners.actions.github.com -n arc-runners 
NAME                                  GITHUB CONFIG URL                RUNNERID   STATUS   JOBREPOSITORY   JOBWORKFLOWREF   WORKFLOWRUNID   JOBDISPLAYNAME   MESSAGE                                                                                                                                                          AGE
arc-runner-set-p6gnd-runner-2s2dn     https://github.com/arc-poc-org   46         Failed                                                                     Failed to create the pod: pods "arc-runner-set-p6gnd-runner-2s2dn" is forbidden: failed quota: pods-medium: must specify cpu for: runner; memory for: runner     5h9m
arc-runner-set-2-w7946-runner-74jq7   https://github.com/arc-poc-org   47         Failed                                                                     Failed to create the pod: pods "arc-runner-set-2-w7946-runner-74jq7" is forbidden: failed quota: pods-medium: must specify cpu for: runner; memory for: runner   5h9m
```
runnerが待っても立ち上がらないので、5minまってるとアラートがslackに飛んできます
![newrelic-alert.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3775581/247586e7-7ac8-4497-cc8b-3ac6ac344d06.png)
`Acknowledged`を押すとnewrelicに飛びます
![newrelic-alert-acknowled.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3775581/e6ba8a9a-2a97-173e-c348-2f209a4e727d.png)
リソースクオーターを削除してクローズさせに行きます
```bash
$ kubectl delete -f ARC/manifest/resource-quota.yaml 
resourcequota "pods-medium" deleted

$ kubectl get pod -n arc-runners -w
NAME                                  READY   STATUS    RESTARTS   AGE
arc-runner-set-2-99rxd-runner-mnp9v   0/1     Pending   0          0s
arc-runner-set-2-99rxd-runner-mnp9v   0/1     Pending   0          0s
arc-runner-set-2-99rxd-runner-mnp9v   0/1     ContainerCreating   0          0s
arc-runner-set-pxlw8-runner-q6f7s     0/1     Pending             0          0s
arc-runner-set-pxlw8-runner-q6f7s     0/1     Pending             0          0s
arc-runner-set-pxlw8-runner-q6f7s     0/1     ContainerCreating   0          0s
arc-runner-set-pxlw8-runner-q6f7s     1/1     Running             0          5s
arc-runner-set-2-99rxd-runner-mnp9v   1/1     Running             0          5s
```
![newrelic-alert-close-dashboard.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3775581/bf417c00-08dd-2c51-a359-de4d46f9e4c9.png)
エラーが解消したことが確認できたのでslackの`Close`をおしてクローズします
![newrelic-alert-close.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3775581/57ec0dfe-9270-a9e2-c96b-86cede2c235f.png)

# まとめ
今回はARCとNew Relicを利用して無料でCI/CD環境とモニタリング、アラートを構築してみました。ARCはGitHub Actions チームが開発に参加する前のlegacy時代に苦労した苦い思い出がありますが、その時とは違ってインストールや設定がだいぶ楽になってましね！今回の記事を書くにあたって使ったNer Relicの使用量は一日1Gなので無料枠で収まると思います。(もちろん使い方によるので注意してください。)
![newrelic-usage.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3775581/1f03dc1d-eedb-fe5e-26bb-a6d3b89d12e5.png)


快適なCI/CDライフを過ごしてください！