どうやら最近Cloud SQL Auth Proxyのプログラムが新しくなったらしい。

スネークケース(cloud_sql_proxy)からハイフン(cloud-sql-proxy)のプログラムに変わってました。しれっとオプションとかも全然違うのでちょっとハマりました。

Apple Silicon版を入れる

Cloud SQL Auth Proxy について  |  Cloud SQL for PostgreSQL  |  Google Cloud

$ curl -o cloud-sql-proxy https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.7.1/cloud-sql-proxy.darwin.arm64
$ chmod +x cloud-sql-proxy

TCP接続用に起動する。プロジェクト名とリージョン名とインスタンス名をコロン区切りで指定します。

$ ./cloud-sql-proxy --port 5433 プロジェクト名:リージョン名:インスタンス名

今までのcloud_sql_proxyだとこれでよかったんですが、新しいやつはそのままだと認証が通りません。

gcloud CLIの認証情報を使う

Cloud SQL Auth Proxy を使用して接続する  |  Cloud SQL for PostgreSQL  |  Google Cloud

gcloud auth loginで認証している情報をcloud-sql-proxyで使うには下記をやります。

$ gcloud auth application-default login

これでlocalhostの5433番ポートに接続するとCloud SQLのインスタンスに接続できます。

フィヨルドブートキャンプではチャットをSlackからDiscordに移行しようとしています。

DiscordにはSlackのようなReminder機能がメジャーなBotの中には無いので定期的なミーティングのリマインドを簡単に移行することができません。

有名なreminder-botでは「72時間おきにリマインド」のような単純Interval形式しか対応してません。「毎月1日の9時にリマインド」のようなことができないので困ってました。

ブートキャンプでは現在リマインドすべきものは3つしかなく、SlackのようなReminder Botを僕が作るのも面倒なのでCloud Functionsでやってみました。

流れ

Cloud Scheduler -> Pub/Sub -> Cloud Functions -> Discord

Cloud Schedulerでcronと同じインターフェースで時間を指定できるのでjobを作ります。

Image from Gyazo

ターゲットにはHTTPを指定してリクエストを飛ばしたりもできますが、Pub/Subも指定できます。

Pub/Subはややこしいかと思ってたんですが単に名前決めて作るだけでした。

Cloud FunctionsではPub/Subで作ったイベントをSubscriptionしてそのタイミングで実行できます。

コード

Image from Gyazo

require 'functions_framework'
require 'net/http'
require 'json'

FunctionsFramework.cloud_event 'reminder_sub' do |event|
  uri = URI.parse(ENV['WEBHOOK_URL'])
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  params = { "content" => "💬 14:00からふりかえりミーティングが 🔈ミーティング チャンネルで始まります。" }
  headers = { "Content-Type" => "application/json" }
  http.post(uri.path, params.to_json, headers)
end

Discordの発言はwebhookにPOSTするだけです。Cloud Schedulerからpayloadに何か値を入れてれば上記のeventの中にそれが(base64でエンコードされて)入っているのでその内容を使って処理を分けたりもできます。(実際のコードでは3種類の通知をそれで出し分けてます。)

最初のテンプレにGemfileも含まれていて、gemを使うのも何にも苦労せずでした。

Image from Gyazo

Cloud Functionsは高度な用途もありますが、こういうふうに週1回しか動かないクソちょっとしたプログラムを動かすにも安くていいなと思います。

公式ドキュメントにもしっかりあるし、みんなデフォルトでやってるかもしれないけど、すごく早くなったのでご紹介。

ビルドを高速化する際のおすすめの方法  |  Cloud Build のドキュメント  |  Google Cloud

今まではCloud BuildでCloud Runにデプロイするときにでdockerイメージをbuildするところを下記のようにしてたんですが、

  - id: Build
    name: gcr.io/cloud-builders/docker
    args: ['build',
           '-t', 'asia.gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA',
           '-t', 'asia.gcr.io/$PROJECT_ID/$REPO_NAME:latest',
           '.',
           '-f', 'Dockerfile']

そこの前に下記のように前回最後にbuildしたイメージを取ってくるようにして、build時に--cache-fromを入れると良い感じに前回のイメージを使ってくれる。

  - id: Fetch
    name: gcr.io/cloud-builders/docker
    entrypoint: 'bash'
    args: ['-c', 'docker pull asia.gcr.io/$PROJECT_ID/$REPO_NAME:latest || exit 0']
  - id: Build
    name: gcr.io/cloud-builders/docker
    args: ['build',
           '-t', 'asia.gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA',
           '-t', 'asia.gcr.io/$PROJECT_ID/$REPO_NAME:latest',
           '--cache-from', 'asia.gcr.io/$PROJECT_ID/$REPO_NAME:latest',
           '.',
           '-f', 'Dockerfile']

24分ぐらいかかってたのが4分になって嬉しい。

フィヨルドブートキャンプというプログラミングスクールのEラーニングアプリをCloud Run + Railsで動かしています。

1ヶ月使ってみた結果、8,000円ぐらいでした。

Image from Gyazo

Cloud Runが300円でCloud SQLが7,000円って感じです。Cloud Buildとかちょこまかしたのはありますが誤差の範囲。

Cloud Runは1コンテナだったら1日10円ぐらいなんですよね。信じられないほど安い。

これでDockerイメージ放り込んでおけば自動スケールの環境が手に入るならほとんどの仕事のアプリはこれでいい気がします。パフォーマンスもいいし、これからのアプリは全部これで行こうと思います。

postgresでいうgenerate_series的なのは無いようなのでベタに書く。

SELECT * FROM
  (SELECT 1 as n),
  (SELECT 2 as n),
  (SELECT 3 as n),
  (SELECT 4 as n),
  (SELECT 5 as n),
  (SELECT 6 as n),
  (SELECT 7 as n),
  (SELECT 8 as n),
  (SELECT 9 as n),
  (SELECT 10 as n)

https://gyazo.com/c5222b1be7c9412d4ca285f9ebac360e

ホントにこれでいいのかな?

テーブル作成・データインポートは一気にできる。

$ bq load --source_format=CSV my_dataset.posts gs://my-bucket/posts.csv.gz "id:INTEGER,title:STRING,created_at:TIMESTAMP"
  • ローカルからアップしてのインポートは遅く、Cloud Storageからのインポートの方が断然速い。
  • gzip圧縮したCSVに対応してるので料金・速度の面からもやっといたほうがいい。
  • スキーマは引数で指定できる。
  • TIMESTAMPは色々なフォーマットをパースしてくれる。(今回はUNIXTIMESTAMP形式を読み込ませた。)Data Types  |  BigQuery Documentation  |  Google Cloud Platform

GCSへのアップは速いのに、BigQueryへの直接アップが遅いのはズルい。

スキーマを作る。

posts.json:

[
  {
     "name": "id",
     "type": "INTEGER"
  },
  {
     "name": "title",
     "type": "STRING"
  },
  {
     "name": "created_at",
     "type": "TIMESTAMP"
  }
]

テーブルを作る。

$ bq mk -t my_dataset.posts ./posts.json

https://gyazo.com/64ec12b4124fea7fbc2c7e003e87d047

便利じゃのう。

$ gsutil cp foo_*.csv gs://my-bucket-name/

便利ですね。

  1. GCPの管理画面から静的IPアドレスを割り当てる。
  2. Cloud SQLの管理画面からrootユーザーにパスワードを設定する。
  3. Cloud SQLの管理画面から上記IPアドレスを許可する。

接続できることを確認する。

$ mysql -u root -p -h xxx.xxx.xxx.xxx