Cloud RunからBudgetいじくる実装例

# まえがき
私自身、管理職とエンジニアの両立が20年近く続いています。

「手を動かし続けないとエンジニアとして劣化する」と、以前の同僚が話していました。
自分自身、普段の業務では管理業務の割合が増え続けてはいますが、管理作業や事務作業の中で発生する作業も、DRY精神を忘れずに、手でやる方がいいのか、コード書くのがいいのかを考えながら、必要に応じて手を動かすようにしています。

Google Cloudの利用において、不正利用や意図しないリソースの消し忘れなどによって、経済的損失を最小化する課題について考えていました。
結果、予算設定を、お客様やエンジニアがよりカジュアルに設定できるような仕組みを作ればいいと考えました。
弊社の運用業務で標準利用しているBacklogに課題を起票することで、予算設定をできるシステムを作ってみました。

正式実装は開発部隊に依頼するかもですが、そのたたき台としてモノを作ったので、この場で共有しておこうと思います。
BillingをGo言語で操作するサンプルは、インターネット上に見つからなかったので、同じようなことをされる方にお役に立てればと、実際のコードも上げておくようにします。


# 構成
![Budget Setter.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51320/a3cfc6ca-e7b6-7808-0aa3-c219061f0559.png)

Cloud Runで実現してみました。冗長化しておきます。
Cloud Armorで保護するなど、改善の余地はありますが、とりあえず。

まだまだ改善の余地は残していますが、とりあえず、インフラ＆アプリはまとめて以下のリポジトリに上げておきました。
こういうふうに、リポジトリを作ってみると、インフラとアプリの垣根が益々低くなってきていることを感じます。
https://github.com/pict3/googlecloud-budget-setter

リポジトリ構成はこんな感じです。
```
.
├── LICENSE
├── README.md
├── docker
│   ├── Dockerfile
│   └── src
│       ├── go.mod
│       ├── go.sum
│       └── main.go
└── terraform
    ├── main.tf
    ├── terraform.tfstate
    ├── terraform.tfstate.backup
    ├── terraform.tfvars
    └── variables.tf
```

## 構築手順

### コンテナイメージの作成＆格納
あらかじめ、Artifactレジストリを作成しておきます。

その後、dockerディレクトリ配下で作業します。
必要に応じて、src以下のGo言語プログラムやDockerfileを変更します。

変更が終われば、イメージをビルドしてプッシュします。
```
% docker build -t us-central1-docker.pkg.dev/<project-id>/budget-setter/budget-setter . 
% docker push us-central1-docker.pkg.dev/<project-id>/budget-setter/budget-setter 
```

### Google Cloudリソースの作成
今回、Terraformで実施しました。
terraformディレクトリで操作してください。

必要に応じて、terraform.tfvarsを作成し、入力パラメータをしていするなどしてください。
あとは、plan & apply！
```
% terraform plan
% terraform apply
```

### DNSレコードの登録
当然、Cloud DNSでも可能で、そうしておけば先の手順でまとめてIaC化できるのですが、筆者環境では別のクラウドで取得済みのドメインを利用したため、個別に対応しました。
Load BalancerのIPアドレスをAレコードで登録しました。
TerraformのアウトプットでIPを出力するようにしておいたのでご利用ください。

### イメージの更新
Goプログラムの更新を行ったあとは、イメージをBuild&Pushします。
```
docker build -t <リポジトリパス> .
docker push <リポジトリパス>
```

完了後、Cloud Runにデプロイします。
実際に作業する場合は、CI/CDを組んで行った方が早いですが、今回はコンソールで実施しました。

### Backlogの設定
Webhook Integrationにて、Load Balancerのエンドポイントを指定します。

### 動作確認
Backlogで起票してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51320/03f2054f-039e-7473-79ed-207f19cb0c5f.png)

Budjetを確認すると、ちゃんと作られてました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51320/4c1ffce7-0dd7-c11c-96c2-d693584e4860.png)


## 構成の解説
以前はリポジトリにGCRを使うことが多かったですが、今はArtifact推奨のようですので、それに合わせています。
利点は[本家のブログ](https://cloud.google.com/blog/ja/products/application-development/understanding-artifact-registry-vs-container-registry)を参照ください。

今回の用途的に、冗長化は不要な気もしましたが、参考コードなので一応。

あまり複雑な構成ではないので、あまり注意点はないですが、１点挙げるとすれば、SSLポリシーがデフォルトだと一般的なブラウザで警告になるような危殆性の高いバージョンまで含んでしまうため、独自で定義しました。
```
  ssl_policy = google_compute_ssl_policy.upper_1_2_policy.name
```

## コードの解説
普段、Go言語は使っていないため、もっと綺麗に書ける気はしていますがご了承ください。

こちらも、そこまで複雑ではないため、解説は不要かもですが、一点、便利なものを共有。
Backlogからのインプットを解析する際に、JsonをGo言語の構造体に落としますが、定義を手動で作るのが辛いなぁと思っていました。
たまたま発見した以下のサイトにJsonをくわすことで、構造体定義に直してくれました！素晴らしい:-)
https://mholt.github.io/json-to-go/

# まとめ
今回作成したシステムはまだまだ改善の余地はありますが、Slackからの要求を受け付けたり、通知設定も可能にしたりと、さまざまなアプリケーションの拡張性が考えられます。
また、Cloud ArmorやCloud CDNを取り入れるなど、インフラの拡張性も考えられます。
お互いを近い距離で運用管理可能にしつつ、疎結合に保守できるCloud Runは非常に強力なツールです。
また、本文ではほとんど触れてませんが、今回のシステム構築のきっかけになったBudget、とりあえず、設定することを強くお勧めします。
どれだけ注意していても、不正利用や設計誤りで料金が跳ね上がる可能性はゼロにはできません。
セキュリティ対策で発生確率を下げることも大事ですが、発生した（料金が跳ね上がった）ことをいち早く検知して、早急な対応ができるBudgetを活用しましょう！