pokutuna.com

pokutuna

Web Developer / Software Engineer
Hyogo, Japan

Blog Entries

  • ぽ靴な缶

    gcloud の configurations を切り替える

    前回の記事では --project を毎回渡せという主張を展開していたけど切り替える話。 blog.pokutuna.com gcloud コマンドには構成を管理するサブコマンド gcloud config configurations がある。管理するプロジェクトが多くない場合は、カレントプロジェクトを設定しつつ切り替える運用でもよいのではないでしょうか。 また、複数の Google アカウントを切り替える場合も configuration を作って切り替えるのがいい。カレントプロジェクトは設定しない派だけど、個人の @gmail.com と勤務先の Google Workspace のログイン状態を切り替えるのに使ってる。 ちなみに configurations を切り替えても ADC はそのままで、最後に gcloud auth application-default login した時点の認証情報から変わらないのが注意ポイント。 gcloud config configurations Cloud SDK 構成の管理 | Cloud SDK のドキュメント | Google Cloud 触ってみないと微妙に分かりづらいけど、Google アカウントやカレントプロジェクトなど一連の設定を 1 つのエントリとしてまるっと切り替えることができる。 "プロジェクトを切り替えることができる" と説明されていたりするけど、Google アカウントを含む一連の構成を切り替えると思っておかないと、 gcloud config set project でプロジェクトを切り替えたり、ログインし直したりしているとよく分からなくなる。 プロジェクトを切り替えるには、同じ Google アカウントでログインした複数の構成を作って、別々のカレントプロジェクトを設定しておいて、それらを切り替えるという感じ。 # configuration の一覧 $ gcloud config configurations list # configuration を作る & 同時にその設定名がアクティブになる $ gcloud config configurations create NAME # configuration に設定する $ gcloud init # 最初から $ gcloud auth login --project=PROJECT_ID # ログインしてプロジェクト ID 設定する $ gcloud config set project PROJECT_ID # プロジェクト ID だけ設定する $ gcloud config set compute/region REGION # region $ gcloud config set comute/zone ZONE # zone # NAME の設定に切り替える $ gcloud config configurations activate NAME 例のように、region や zone も保存しておけるので、Compute Engine などこれらの引数を要求するコマンドをよく使うなら、設定してあるとちょっと楽になる。 gcloud config に設定できるもの 先に挙げたものが config に設定できるものとしてメジャーだけど、他にもいろんな設定を保存できるし、configuration で切り替えられる。 例えば以下のように設定しておくと、Cloud Functions に新しい関数をデプロイする際に region を省略しても asia-northeast1 になる。 $ gcloud config set functions/region asia-northeast1 設定可能な項目はドキュメントにちゃんとまとまってある。 gcloud config | Google Cloud CLI Documentation あるいは json や yaml で出力してみると雰囲気が分かっておもしろい。 $ gcloud config configurations list --format=json accessibility/screen_reader を true に設定すると gcloud の出力がスクリーンリーダーフレンドリーになったり、core/log_http すると gcloud の API リクエストとレスポンスが出力されたりして面白いですね。 fzf や peco で切り替える よくあるやつ。fzf でも peco でも動くので読み替える。 gcloud-switch() { local selected=$( gcloud config configurations list --format='table[no-heading](is_active.yesno(yes="[x]",no="[_]"), name, properties.core.account, properties.core.project.yesno(no="(unset)"))' \ | fzf --select-1 --query="$1" \ | awk '{print $2}' ) if [ -n "$selected" ]; then gcloud config configurations activate $selected fi } gcloud にはグローバルな `--format=NAME[ATTRIBUTES](PROJECTION) オプションがあって、単体で出力をかなり加工できる。他のツールと組み合わせるときに使うとかわいいですね。 gcloud topic formats | Google Cloud CLI Documentation gcloud topic projections | Google Cloud CLI Documentation あるいは direnv を使っている場合は CLOUDSDK_ACTIVE_CONFIG_NAME 環境変数で切り替えることもできる。チームで configuration 名をプロジェクト名にしてリポジトリに入れたりするのもよいかもしれません。 Cloud SDK 構成の管理 | Cloud SDK のドキュメント | Google Cloud

  • ぽ靴な缶

    gcloud にカレントプロジェクトを設定しない派

    gcloud CLI にカレントプロジェクトをなるべく持たせないようにして暮らしている。 gcloud はデフォルトでカレントプロジェクトのリソースを操作する。操作するプロジェクトが 1 つなら良いけど、仕事でも遊びでもいくつもの GCP プロジェクトを扱っているので、うっかり異なるプロジェクトのリソースを操作してしまったり、意図しないプロジェクトに費用が計上されてしまうのが嫌だから。 カレントプロジェクトは設定しないようにして、gcloud を使う時は都度 --project=PROJECT_ID で渡すようにしている。 # カレントプロジェクトを確認するには以下のコマンドなど $ gcloud config get-value project $ gcloud config list # カレントプロジェクトの設定を消す $ gcloud config unset project ローカルの ADC の quota project 忘れられがちだけど、ローカルの Application Default Credentials にもカレントプロジェクトに相当する "quota project" がある。 ADC についてはこちら blog.pokutuna.com ADC の quota project は、gcloud auth application-default login した時点のカレントプロジェクトが設定される。 ~/.config/gcloud/application_default_credentials.json を見ると分かるし、ログイン時のメッセージにも出てくる。 Credentials saved to file: [/Users/pokutuna/.config/gcloud/application_default_credentials.json] These credentials will be used by any library that requests Application Default Credentials (ADC). Quota project "pokutuna-playground" was added to ADC which can be used by Google client libraries for billing and quota. Note that some services may still bill the project owning the resource. 普段からカレントプロジェクトを設定しないようにしていると気にしなくて良いが、unset したり切り替えたりしていると gcloud のカレントプロジェクトと ADC の quota project が異なる状態になるのがややこしい。 なのでこれも設定しないようにしている。 カレントプロジェクトを ADC に伝播させたくない場合は ADC ログイン時に --disable-quota-project オプションを使う。 $ gcloud auth application-default login --disable-quota-project ADC に quota project を設定しない場合、以下のような警告を見ることになるけど、アプリケーションコードからプロジェクト ID を与えればよいので気にしない。 WARNING: Cannot find a quota project to add to ADC. You might receive a "quota exceeded" or "API not enabled" error. Run $ gcloud auth application-default set-quota-project to add a quota project. ADC にプロジェクト ID を持たせない暮らし ADC に quota project を設定しない場合、アプリケーションコード中にプロジェクトIDが登場することになるけど、意図しないプロジェクトを操作してしまう危険を避けることを優先している。 認証情報はメンドイので ADC に解決してほしいが、プロジェクト ID まで暗黙に解決したいことはほぼないし、複数のプロジェクトで同じコードを実行する場合でも、設定や環境変数などでアプリケーションに伝えればいいという考え。 GCP 上の実行環境でも、実行環境とプロジェクト ID が異なってないなら問題はない。 Node Google Cloud の各種プロダクトに用意されたクライアントライブラリはコンストラクタに渡せばいい。 // Imports the Google Cloud client library const {BigQuery} = require('@google-cloud/bigquery'); const client = new BigQuery({ projectId: "<PROJECT_ID>" }); Spreadsheet など、Google Cloud 感ないものは GoogleAuth に渡す。Spreadsheet や Calendar なども API を有効にしたり使用量を管理するために Google Cloud プロジェクトが必要。 googleapis/google-api-nodejs-client import { google } from "googleapis"; const auth = new google.auth.GoogleAuth({ projectId: "<PROJECT_ID>", scopes: [ "https://www.googleapis.com/auth/cloud-platform", "https://www.googleapis.com/auth/spreadsheets.readonly", ], }); const sheets = google.sheets({ version: "v4", auth }); Node の場合、明に指定しない場合は google-auth-library がプロジェクト ID を解決しようとする。その過程で GCLOUD_PROJECT や GOOGLE_CLOUD_PROJECT 環境変数を参照したり、gcloud のカレントプロジェクトを参照したりする(歴史的経緯だろうけど、この挙動が嫌だなあ)。 Go Go でも Google Cloud 系のクライアントライブラリでは素直に渡せばいい。 googleapis/google-cloud-go import ( "context" "cloud.google.com/go/bigquery" ) func main() { ctx := context.Background() client, err := bigquery.NewClient(ctx, "<PROJECT_ID>") ... } Google Cloud 感のないものは google.golang.org/api を使うことになるが、こちらは option.WithQuotaProject() を使う。google.golang.org/api 以下でほぼすべての Google の API を叩けるので、Cloud API もこちらの方法で叩ける。 googleapis/google-api-go-client import ( "context" "google.golang.org/api/option" "google.golang.org/api/sheets/v4" ) func main() { ctx := context.Background() client, err := sheets.NewService(ctx, option.WithQuotaProject("<PROJECT_ID>")) ... } まとめ いろんなプロジェクトを触る場合は gcloud にカレントプロジェクトを設定しないのをおすすめしている ローカルの ADC も quota project があり、ログイン時のカレントプロジェクトが引き継がれる、これも設定しないのがいい アプリケーションコードでプロジェクト ID を明に指定すればいい blog.pokutuna.com

  • ぽ靴な缶

    GCP IAM ロールの持つ権限を比較するテク

    メンバーやサービスアカウントの権限を考える際に、ロールの持つ権限を比較したいことがしばしばある。そういう時は gcloud と diff を使うことで比較できるという素朴なテク。 ロールと権限 ロール(role)は roles/{roleName}, roles/{service}.{roleName} などで表され、許可されている操作を表す権限(permission)の集合である。 例えば BigQuery データ閲覧者 (roles/bigquery.dataViewer) は、以下の permission を持つ。 bigquery.datasets.get bigquery.datasets.getIamPolicy bigquery.models.export bigquery.models.getData bigquery.models.getMetadata bigquery.models.list bigquery.routines.get bigquery.routines.list bigquery.tables.createSnapshot bigquery.tables.export bigquery.tables.get bigquery.tables.getData bigquery.tables.getIamPolicy bigquery.tables.list resourcemanager.projects.get resourcemanager.projects.list cloud.google.com ロールの比較 個別のロールと権限について確認したいときは以下のドキュメントを見る、GCP 屈指の縦に長いページ role から permission Understanding roles | IAM Documentation | Google Cloud permission からそれを持つ role IAM permissions reference | IAM Documentation | Google Cloud role をいじっていると以下のような疑問が湧いてくることがある。 roles/bigquery.dataViewer と roles/bigquery.metadataViewer ってテーブルのデータ読める以外に何が違うんだっけ? roles/browser と roles/resourcemanager.folderViewer ってどう違うんだっけ? roles/editor は強い権限だけど、意外と SecretManager で出来ない操作あった気がする 上のドキュメントを行ったり来たりしてもいいけど、* でサービス内の個別の permission が省略されていたりするのでいまいち分からないし大変。 diff で比較する そういう時は gcloud コマンドで role の permission を得つつ、diff で比較するとよい $ gcloud iam roles describe ROLE で権限のリストが得られるので、これを diff -y で左右に並べる。 roles/bigquery.dataViewer と roles/bigquery.metadataViewer の違いは、 $ diff -y -W80 <(gcloud iam roles describe roles/bigquery.dataViewer) <(gcloud iam roles describe roles/bigquery.metadataViewer) description: Access to view datasets | description: Access to view table and etag: AA== etag: AA== includedPermissions: includedPermissions: - bigquery.datasets.get - bigquery.datasets.get - bigquery.datasets.getIamPolicy - bigquery.datasets.getIamPolicy - bigquery.models.export < - bigquery.models.getData < - bigquery.models.getMetadata - bigquery.models.getMetadata - bigquery.models.list - bigquery.models.list - bigquery.routines.get - bigquery.routines.get - bigquery.routines.list - bigquery.routines.list - bigquery.tables.createSnapshot < - bigquery.tables.export < - bigquery.tables.get - bigquery.tables.get - bigquery.tables.getData < - bigquery.tables.getIamPolicy - bigquery.tables.getIamPolicy - bigquery.tables.list - bigquery.tables.list - resourcemanager.projects.get - resourcemanager.projects.get - resourcemanager.projects.list - resourcemanager.projects.list name: roles/bigquery.dataViewer | name: roles/bigquery.metadataViewer stage: GA stage: GA title: BigQuery Data Viewer | title: BigQuery Metadata Viewer ほうほう、roles/bigquery.dataViewer はテーブルやモデルのスナップショットやエクスポートも取れるんですね。 includedPermissions 以下だけ欲しいなら --format オプションで中身だけ取ることもできる。 --format='value[delimiter="\\n"](includedPermissions)' gcloud の format オプションについてはこちら。 roles/browser と roles/resourcemanager.folderViewer の違いは、 $ diff -y \ <(gcloud iam roles describe roles/browser --format='value[delimiter="\\n"](includedPermissions)') \ <(gcloud iam roles describe roles/resourcemanager.folderViewer --format='value[delimiter="\\n"](includedPermissions)') > orgpolicy.constraints.list > orgpolicy.policies.list > orgpolicy.policy.get resourcemanager.folders.get resourcemanager.folders.get resourcemanager.folders.list resourcemanager.folders.list resourcemanager.organizations.get < resourcemanager.projects.get resourcemanager.projects.get resourcemanager.projects.getIamPolicy < resourcemanager.projects.list resourcemanager.projects.list フムフム。 多くの permission を持つ権限なら比較したい部分で grep すればいいですね。 roles/editor のうち、SecretManager で、roles/secretmanager.admin より弱いのは、 $ diff -y <(gcloud iam roles describe roles/editor | grep secretmanager) <(gcloud iam roles describe roles/secretmanager.admin | grep secretmanager) - secretmanager.locations.get - secretmanager.locations.get - secretmanager.locations.list - secretmanager.locations.list - secretmanager.secrets.create - secretmanager.secrets.create - secretmanager.secrets.delete - secretmanager.secrets.delete - secretmanager.secrets.get - secretmanager.secrets.get - secretmanager.secrets.getIamPolicy - secretmanager.secrets.getIamPolicy - secretmanager.secrets.list - secretmanager.secrets.list > - secretmanager.secrets.setIamPolicy - secretmanager.secrets.update - secretmanager.secrets.update > - secretmanager.versions.access - secretmanager.versions.add - secretmanager.versions.add - secretmanager.versions.destroy - secretmanager.versions.destroy - secretmanager.versions.disable - secretmanager.versions.disable - secretmanager.versions.enable - secretmanager.versions.enable - secretmanager.versions.get - secretmanager.versions.get - secretmanager.versions.list - secretmanager.versions.list > name: roles/secretmanager.admin roles/editor でも、secret に IAM Policy を設定することと、実際の version の読み取りができないのだな〜ということが分かる。 gcloud と diff を使うとこういう感じで比較できます。 適切なロールを選ぶとともに、IAM の推奨事項を見て絞ったりできるとよりよいですね。 cloud.google.com

  • ぽ靴な缶

    3/17 Born Digital Summit 2022 で発表します

    来週 2022-03-17(木) の Google Cloud オンラインイベント 16:20- 『はてな広告配信システムのクラウドネイティブ化への道のり』で発表します。 データセンター環境で運用していた広告配信システムを GCP へ移転する話です。 派手なメッセージな感じではなく、約1年のプロジェクトの中での採用技術やテクについて紹介する風情の発表になります。EOL 過ぎたソフトウェアたちをまるごとマネージド化し、Elasticsearch を BigQuery に置き換える様子などをご覧にいただけます。 たぶん登録しておけば後日動画で見れると思います。 cloudonair.withgoogle.com 笑顔の写真は締め切り当日にがんばって撮りました。

  • ぽ靴な缶

    Google Colaboratory でデータフローのドキュメントを書く試み

    この記事ははてなエンジニアのカレンダー | Advent Calendar 2021 - Qiita 2日目の記事です。 最近、データパイプラインの整備や営業チームの人力混じりの運用フローを機械化するなどの業務改善に取り組んでいます。 その過程で、運用ドキュメントを読んだりヒアリングして図を描くことがよくあります。 描いた図をもとに「この流れであってますか?」と確認したり「ここ手間結構かかってそうですが困ってませんか?」とコミュニケーションをします。暗黙的な業務の流れが明確になるだけでなく、改善点の発見にも繋がります。 ひととおり改善タスクが終わった後にも図を最新にします。ドキュメントと併せて成果物とします。 どんなデータがあってどのようにビジネスに使われているか、データがどのように取得&保存されているかを残しておくのは今後のデータ活用や改善のためにも必要です。 俺はそんな個々の業務のデータフロー図を描いていって、やがてはおっきなエンタープライズデータモデルを絵にしたいんだ。 でも図やドキュメントを書いていく上で様々な悩みがある!! GUI 作図ツールを使う データフロー図を描くために、draw.io や Cacoo といった作図ツールを使ったり、Google スライド や miro といったスライドツールやホワイトボードツールを使う選択肢がある。 ツリーやダイアグラムを作るためのパーツが用意されていたり、リアルタイム同時編集できるものも多く複数人での認識合わせにも使えて大変便利だけど、いろいろ不満もある。 レイアウトにこだわりがち 自由な絵が描けるのはよいけど、レイアウトに結構な時間を使ってしまう。 ボックスの大きさは揃っているほうがよいしX軸Y軸のアラインを揃えたい、矢印は交差してほしくないし、矢印やボックスの形に一貫した意味が欲しい...とやっていると必要以上に時間を使っていることに気づく。 きれいな図は理解を助けるけど、一世一代のプレゼンテーションでもないのにこだわりすぎるのも無駄が多い。 とはいえある程度は整えないと読み解くのにストレスがあり、ちょうどよい塩梅が難しい。 一貫したルールがないと複数の図を並べた時にもごちゃごちゃした印象になってしまう。 その他いろいろ ドキュメントと別の所にあるので更新されなくなりがち えてして検索性が悪がち 画像として書き出したりスクリーンショットを撮ってドキュメントに移すのがダルいがち やる気のある1人だけがメンテナンスする羽目になりがち 差分管理できながち 図を作る部分の体験はよいけど、その図をどう運用していくか...というところで悩みが出てくる。 Graphviz や PlantUML を使う Graphviz、PlantUMLで図を書く手もある。 普段のテキストエディタで書けて一定のクオリティの図が作れるので重宝している。 レイアウトも多少意識する面はあるものの細かく手をいれられないので適度に妥協できるのも逆に良い点。 社内 Wiki にドキュメントを書く時に、ページ下の方にソースを貼り付けてドキュメントと図のソースの距離を近くすることもできる。 一方で満たされない思いもある。 記法の学習コストがあるがち リポジトリに入れると権限が必要だったりしがち 特に営業チームのメンバーが利用したい時に困りがち 巨大な図を作るとメチャクチャになりがち ドキュメント ここまで図の話をしてきたけど、実際にはドキュメントの一部として図を描きたい。 この業務の背景や目的、関連するドキュメントやダッシュボードへのリンク、新たにデータを利用する際の方法、実装を行っているリポジトリ、権限や窓口、データの更新頻度や扱う諸注意...などなど、図だけで説明しきるのは難しくて、ある程度文章で説明することになる。 ドキュメントを作ってメンテしていく上で、もっとドキュメントと図を近づけたい。 Google Colaboratory でドキュメントを書く Colaboratory は Google の提供する Jupyter Notebook & Python ランタイム。 これを使ってドキュメントを書くのはどうか、というのが今回の試みです。 データを扱うエンジニアには Jupyter はお馴染みだろうから親和性も高い。 Colaboratory へようこそ - Colaboratory やってみます データフローとドキュメント Google Colaboratory でデータフローのドキュメントを書く試み - Colaboratory いかがでしょうか。 果たしてまな板やすし桶はデータストアなのか、これはデータフローなのか、寿司酢を入れなくてよいのか、異論はあるだろうけどデータフロー図とドキュメントを書くことができた。 Colab を使うと 図のソース置き場と表示をどちらも満たせる Markdown を使ってドキュメントを書ける 環境構築にあまり煩わされない BigQuery など実際のデータにアクセスしてサンプルデータを表示したり可視化できる Google アカウントによる権限管理ができる Google Drive 検索にひっかかる 変更履歴が残り古い版に戻せる これらのいいことがある。 やっていること 依存のインストール ! に続けてコマンドを打つことでシェルで実行される。 !apt や !pip で依存を入れることができる。 これをコピペして使っている #@title !pip install graphviz plantuml fonts-noto-cjk #@title は後述 graphviz, plantuml をよく使う fonts-noto-cjk 日本語フォントに Noto Sans Japanese を入れる 入れないと図中に日本語が表示できないことがある 他のフォントウェイトは fonts-noto-cjk-extra にあるけど大きめなので使ってない fonts-ipafont とかでも良いと思います Graphviz や PlantUML のソースを置く %%writefile {filename} から始まるセルを評価すると、以降の内容が filename に保存される。 Python コードで open して文字列を書いている例がよくあるけど、特定のテキストをファイルに書きたいだけならマジックコマンドを使うのが簡単。 Built-in magic commands — IPython 7.30.0 documentation 画像の生成 & 表示 単に Graphviz や PlantUML で画像を作って表示する !dot -Tpng my-flow.dot > my-flow.png # graphviz !plantuml my-flow.puml # plantuml from IPython.display import Image Image('my-flow.png') 一旦完成したらコードを非表示にする ドキュメントとして見せるにはコードを非表示にしておくほうが見栄えがいい。 メニューの "表示" からコードを非表示にするとセルを折りたたむことができる。 非表示にするとセルの先頭に #@title が挿入されるのは、フォームから変数に値を入れる機能を転用して非表示を実装しているからのようだ。つまりメニューを経由しなくてもセルの先頭に #@title を書いて右側の空白をダブルクリックしてもよい。 Forms - Colaboratory 感想 どうでしょうか、Colab にドキュメントを書くのはまだお試し中ですが、悪くない気がします。 特に、ちょっとラベルを変えたり 1~2本フローを増やしたりなどの微修正は画像を生成して Wiki に貼り付けたり、リポジトリにコミットする必要もなくて気楽にできます。 コードセルを非表示にしていても余白ができるのでがちゃがちゃした見た目になりがちだったり、Colab に詳細めなドキュメントが描いてあるという期待がないので社内 Wiki からリンクしていても読まれにくい、という点は気になる。 データアーキテクチャを図にしたりドキュメントにする良いツールやプラクティスがあれば教えて下さい。 アドベントカレンダーについて はてなエンジニアのカレンダー | Advent Calendar 2021 - Qiita 前日は id:nanto_vi による HTMLのdialog要素とフォーム機能 - Hatena Developer Blog でした。 明日は id:gurrium さんの WoTのMODを作りたい - ぜのぜ です。 参考 データフロー図 - Wikipedia DFD(データフロー図)ってなに?DFDの概要と書き方をあわせて紹介 | Cacooブログ

  • ぽ靴な缶

    GCP の Application Default Credentials を使った認証

    公式ドキュメントで説明されているけど、同僚に何度か説明する機会があったり、作る必要のないサービスアカウントキーを目にすることも多いのでまとめておく。 認証情報が登場しないアプリケーションコード 例えば以下のコードで Secret Manager に保存したトークンを取得することができる。SecretManagerServiceClient にサービスアカウントキーを渡さずとも動作する。 const {SecretManagerServiceClient} = require('@google-cloud/secret-manager'); const client = new SecretManagerServiceClient(); (async () => { const [secret] = await client.accessSecretVersion({ name: 'projects/pokutuna-playground/secrets/token/versions/latest', }); console.log(secret.payload.data.toString('utf8')); })(); これは僕の手元であれば動作するし、みなさんの手元ではエラーになるでしょう。 このコードでアクセス制御ができているのは、クライアントライブラリが実行環境から認証情報を解決しているからです。 Cloud SDKをインストールして gcloud auth application-default login し、name をあなたのシークレットに置き換えれば、あなたのシークレットが読めるでしょう。1 Application Default Credentials Google が提供するクライアントライブラリは以下の優先順位で認証情報を解決している。 GOOGLE_APPLICATION_CREDENTIALS 環境変数に設定されたサービスアカウントキー(のファイルパス) ~/.config/gcloud/applicstion_default_credentials.json に配置された OAuth2 Secret メタデータサーバーに問い合わせて得られた認証情報 これは言語問わず共通して実装されており、Node の場合 google-auth-library-nodejs で実装され、googleapis や、@google-cloud/ 以下のクライアントライブラリで利用されている。 はサービスアカウントキーを使って実行ユーザを上書きするための仕組み で利用されるファイルは gcloud auth application-default login によって配置される Google アカウントログインが求められ、ログインしたユーザの認証情報が配置される。 は GCP 上の実行環境で解決される GCP 上の実行環境では、メタデータサーバーが、アクセス元に応じた認証情報を返してくれる。 Compute Engine、App Engine や Cloud Functions などではインスタンス作成時やデプロイ時にアタッチするサービスアカウントを指定できる。何も指定していなければデフォルトのサービスアカウントがアタッチされている。 Workload Identity を利用して、Kubernetes Service Account と Google Service Account を紐付けて認証情報を解決できる。 この仕組みを使うことで ローカル開発環境ではサービスアカウントキーを使わない(2を利用する) GCP の実行環境ではサービスアカウントキーをデプロイしない(3に任せる) となって、サービスアカウントキーが必要な場面はかなり限定される。 どうしてもサービスアカウントキーを指定したい場合も環境変数で与える(1を使う)ことで、アプリケーションコードに登場しないようにできる。 サービスアカウントキーを配るのを最小にしたい 公式ドキュメントにおいても、開発中は ADC に任せることを推奨している。 サービス アカウントの使用と管理のベスト プラクティス  |  Cloud IAM のドキュメント  |  Google Cloud 開発中にサービス アカウントを使用しない 日常業務で、gcloud コマンドライン ツール、gsutil、terraform などのツールを使用する場合があります。これらのツールの実行でサービス アカウントを使用しないでください。代わりに、gcloud auth login(gcloud ツールと gsutil の場合)または gcloud auth application-default login(terraform などのサードパーティ ツールの場合)を実行して、ツールがユーザーの認証情報を使用することを許可します。 キーの権限や流出に気を使う必要があるので、極力 ADC に寄せたい。 セキュリティ面以外では、1つのサービスアカウントにつきサービスアカウントキーは10個という管理上の制約もある。 開発用サービスアカウントキーを開発者のローカルに配るとすると、先着10回までしか生成できず、10人以上で開発できないし、古いものを消そうにも気を使う、という状況に陥る。 実際のところ、一番サービスアカウントキーを置きたくなるのは外部の CI だろう。 Github Actions などでは渋々配置することになる。AWS や Azure などからは、Workload Identity 連携を使うことで、サービスアカウントキーなしに認証できるようになった。外から BigQuery を叩きたい場合も Workload Identity を設定する手間を厭わなければキーが要らない。 ADC を使うことによる不安と対策 GCP 上で動作させる際に ADC を利用しない理由はほぼない。 開発者はオーナー(roles/owner)などの強力な権限を持っていることが多く、複数のプロジェクトを操作するので、 ローカルでは上手くいくがデプロイして権限が足りないことに気づく 意図したものと異なるプロジェクトに対して操作を実行してしまう ということが起きうる。 1 に関して、サービスアカウントになりすまして確認することができる。 roles/iam.serviceAccountTokenCreator ロールを持っているとサービスアカウントに成り代わって認証情報を取得できる。 このロールは2つのリソース(なりすます側とサービスアカウント)の間の設定であるため、オーナーでもデフォルトで持っていない。以下の手順で設定する。 メンバーに 1 つのサービス アカウントの権限の使用を許可する - サービス アカウントの権限借用の管理  |  Cloud IAM のドキュメント  |  Google Cloud このロールを持っていると gcloud コマンドでは CLOUDSDK_AUTH_IMPERSONATE_SERVICE_ACCOUNT={SA_EMAIL} 環境変数または --impersonate-service-account={SA_EMAIL} でなりすまして操作を実行できる。gcloud コマンドで、このサービスアカウントが PubSub トピックへメッセージをパブリッシュできるか確認できる。 2021-08 現在、まだクライアントライブラリも環境変数などから透過的に解決してくれるわけではなく追加の実装が必要である。 bq コマンドも impersonate に対応していなかったり対応が限定的、gcloud & gsutil 以外で気楽に使える状態ではないので、面倒なのでクライアントライブラリ側で解決するプロトコルを決めて実装してほしいものである。bq は長期的には gcloud bq に機能が移植されていって普段遣いできるようになるんじゃないかなあ〜 有効期間が短いサービス アカウント認証情報の作成  |  Cloud IAM のドキュメント  |  Google Cloud 2 に関して、破壊的な操作で起きると悲惨である。 GCLOUD_PROJECT や GOOGLE_CLOUD_PROJECT 環境変数を設定していない場合、gcloud config list した際の core.project がデフォルトとして使われてしまい、落とし穴として働いてしまう。 googleapis/google-auth-library-nodejs@2fcab77 - src/auth/googleauth.ts#L205L210) 対策としては クライアントに渡すプロジェクトIDを省略しない カレントプロジェクトを設定しない gcloud config unset project するとカレントプロジェクトを設定しないままで居られる 普段から gcloud --project=... で都度プロジェクトを指定する ぐらいしかないので、ややイマイチである。 関連する話題 デフォルトのサービスアカウント GCP の実行環境にアタッチするサービスアカウントを明に指定しない場合はデフォルトのものが使われる。 Compute Engine などでは {PROJECT_NUMBER}-compute@developer.gserviceaccount.com App Engine や Cloud Functions などでは {PROJECT_ID}@appspot.gserviceaccount.com デフォルトでは編集者(roles/editor)ロールという広い範囲を操作できる権限が付いている。 十分強力な権限が付いていることは、初心者に優しかったり、プロジェクト開始時にいきなり IAM の設定を要求されないという良い面もあるのだけど、慣れているユーザはあまり使いたくないだろう。必要最小限の role を与えたサービスアカウントをアタッチするのが理想的だけど、管理の手間もあるので個人的には以下のようにやっている。 小さなプロジェクトでは気にせずデフォルトのサービスアカウントのまま動かす デフォルトサービスアカウントを何かから参照したくなったら変える 別プロジェクトの IAM に追加して権限を与えたくなったりキーを外部に置きたくなったとき ちなみに Secret Manager のシークレットを読むには 編集者(roles/editor) では足りず、Secret Manager のシークレット アクセサー(roles/secretmanager.secretAccessor)ロールが必要である。 gcloud auth login と gcloud auth application-default login の違い gcloud auth login は CloudSDK(gcloudコマンド) で使われる認証情報を設定する。 gcloud auth application-default login は ADC で使われる ~/.config/gcloud/application_default_credentials.json を配置する。 用途が分かれており、ADC を利用したくない場合でも gcloud コマンドの利用に不都合がないように分かれているものと思われる。 両方更新するには gcloud auth login --update-adc ローカルの application_default_credentials.json を使うのを止めたい場合は gcloud auth application-default revoke で削除できる。 コンテナではどうするのか google/cloud-sdk - Docker Image | Docker Hub では named volume に gcloud auth login した認証情報を保管して必要な時にマウントする方法が案内されている。application default についても同様にセットできるだろう。 ADC を使いたいだけなら、ホスト側で作った application_default_credential.json をマウントするのが楽である。 $ docker run -v ~/.config/gcloud/application_default_credentials.json:/root/.config/gcloud/application_default_credentials.json ... Cloud SQL Proxy では実行ユーザが nonroot なのでマウント先を変えなければならない、このあたりは都度調べることになる。 $ docker run -p3306:3306 --rm --hostname=mysql -v ~/.config/gcloud/application_default_credentials.json:/home/nonroot/.config/gcloud/application_default_credentials.json gcr.io/cloudsql-docker/gce-proxy:latest /cloud_sql_proxy -instances=... もちろん自作か Google 提供のイメージ以外に ~/.config/gcloud をマウントするのはリスクがあるので避けるべきである。 リンク 関連する話題への良いドキュメント サービス アカウントとして認証する  |  Google Cloud GCP と OAuth2. | by Yuki Furuyama | google-cloud-jp | Medium Service Accountの運用について · gcpug/nouhau GCP の Compute Metadata Credentials について 関連記事 blog.pokutuna.com 正確にはカレントプロジェクトの設定も必要になる↩

  • ぽ靴な缶

    GKE Autopilot で節約のために asia.gcr.io を使う

    GKE Autopilot に移行してみたところ、意外と費用がかかっていた。 クラスタのロケーションに合わせた GCR レジストリを使うのがよい。 原因 GCR のイメージレジストリには gcr.io と、ホストされるロケーションが付いた us.gcr.io, eu.gcr.io, asia.gcr.io がある。 gcr.io にイメージを保存していた。内部的には US にホストされており、asia-northeast1 のクラスタへ pull する際には US からの storage egress の費用がかかる。 Standard の GKE クラスタではノードとなる GCE インスタンスを確保するので pull されたイメージはインスタンス内で使い回されてキャッシュとして働く。 ノード管理が要らない Autopilot では実行ごとに同じインスタンスに当たるとは限らない(当たることもある)。 Cloud Logging 上では以下のようなログで pull されたか判別できる - Pulling image "..." - Container image "..." already present on machine 解決 GCP 内の同ロケーションでの Cloud Storage データの移動は無料!! なのでクラスタのリージョンに合わせた GCR ロケーションにイメージを置いて利用することでこの費用はゼロになる。 ネットワーク - 料金  |  Cloud Storage  |  Google Cloud 今回 GKE Autopilot へお試し移行したサービスは CronJob ばかり実行するシステムで、継続的にインスタンスが確保されにくく高頻度でイメージを pull していた。 $100/month 程度のインフラ費用を見込んでいた小規模なサービスだったけど、無料枠を超えたところから storage egress に $10/day 払う羽目になっていたので急いで対処した。 おまけ 挙動確認のために 30分おきに起動する CronJob を動かしたプロジェクトの費用、クラスタは asia-northeast1。 Cloud Storage 費用 7/30 ~ 8/2 は gcr.io 8/2 ~ 8/4 は asia.gcr.io → 費用なし 7/31 の24時間の間 gcr.io を使った CronJob が動いていた 7/31 の転送量は 3.1 Gibibyte docker image の転送サイズ(イメージサイズではなく圧縮されたもの)を調べるには $ docker manifest inspect IMAGE | jq '[.layers[].size] | add' 今回使ったイメージのサイズは 69285060 byte, このイメージを 24*2 回 pull していて 69285060 * 24 * 2 / 2**30.to_f => 3.0972835421562195 なので 3.1Gibibyte と一致する。よかったですね。 リンク GKE Autopilot のご紹介: マネージド Kubernetes における革命 | Google Cloud Blog レジストリ - Container Registry の概要  |  Container Registry のドキュメント  |  Google Cloud

  • ぽ靴な缶

    Chrome 拡張を Manifest v3 対応した

    公式のガイドに従ってやればよい Migrating to Manifest V3 - Chrome Developers background pages が Service Worker に置き換えられた 各 chrome API の Promise 化 リモートのコードが実行できなくなる browser_action と page_action の統合 executeScript の変更 あたりが大きい cocopy の場合 blog.pokutuna.com browser_action と page_action の統合 Action API unification - Migrating to Manifest V3 - Chrome Developers 上記のように manifest を修正し、chrome.browserAction などの呼び出しを chrome.action に置換すれば良い。 ハマったのはキーボードショートカットを定義する commands の方も undocumented に変更されていた点。_execute_browser_action などを _execute_action に置き換える必要がある。 web_accessible_resources の指定が変わった Web-accesible resources - Migrating to Manifest V3 - Chrome Developers 外部から拡張の options.html にクエリパラメータを付けてリンクしたい。 matches 以下にリンク元の origin を書いておけばリンクが開けるようになる。でも任意の origin からリンクすることはできなくなっていそう。 "web_accessible_resources": [{ "resources": [ "options.html" ], "matches": [ "https://github.com/*" ] }] その他 ユーザ入力を js として解釈するのがコア機能なので、Remotely hosted code - Migrating to Manifest V3 - Chrome Developers の変更で詰むかと思ったけど、以前より sandbox で eval するようにしていたので何もする必要なかった。 ページタイトルや HTML の取得は、動的にコードを変更する必要がないので素直に function にして chrome.scripting.executeScript(...) する。scripting の permission も要求する。

  • ぽ靴な缶

    Flexispot 鬼目ナット化の記録

    引越しを機に前から欲しかったスタンディングデスクを買った。 組立てには本体付属の木ねじ(ぐりぐりとねじ込んでいく)を使わず、鬼目ナットを埋め込んで組み立てた。 鬼目ナットを使うと、分解&再組み立てができるし、投機的に埋め込んでおいてリモコン位置やケーブルダクトを左右入れ替えたりできる。 いろいろ調べつつ作ってうまくいったものの、ネジを複数回買いに行ったり手戻りもあったので記録に残しておく。 126cm 周りに物がないとよくわからないしスケール感が変な気がするけど、最大の 126cm まで上げています。 本体 FlexiSpot | 昇降スタンディングデスク 上位モデルの E7 を購入した。 注意したいのは昇降範囲で、モデルによっては下限が意外と高く、710mm や 730mm だったりする。 174cm の僕が座って仕事する際の机の高さは 71cm で、モデルによっては既に下限以下である。 裸足なので低めになるとはいえ、気分で変えたり姿勢が悪くなってきたと思ったら上下させたいし、作業内容や身長によってはさらに下げたいだろうから、昇降をエンジョイするなら下限が 580mm の E7 か、ディスコンの E3 (下限 600 mm)しか実質的に選択肢がないと思える。 ちなみに昇降範囲は脚のチューブの数からきている。上位モデルは3段でそれ以外は2段。 3段は2箇所が昇降する 鬼目ナット 鬼目ナットはこういうやつ。 Flexispot の天板で使うには、つば付きのもの、ムラコシでいう D タイプがよい。六角レンチを使ってねじ込めて、表面で止まってくれる。 鬼目ナット | ムラコシ精工オンラインショップ 先にドリルで下穴を空け、そこに六角レンチでねじ込む、Youtube とかで動画をみてください。 鬼目ナット - YouTube 鬼目ナットには以下のパラメータがある 下穴径 長さ(深さ) ボルトのサイズ(M4など) ボルトのねじ切りの長さ 下穴径は、M4 であれば 5.7~6.0mm とスペックシートに書いてあるけど、中途半端なビットは普通手に入らないので 6mm の下穴を空けることになる。 深さはドリルの先端ではなく太いところで合わせること、十分な太さの穴がないとねじ込みが途中で止まってしまう。 下穴の長さは太いところであわせる ナットにつばがあるので、多少余裕を持って深く(ナットより長く)掘ればよいが、天板を突き破らないようにはしないといけない。 鬼目ナット選び 鬼目ナットのサイズを何にするかは悩ましい。 鬼目ナットの内側上部 5mm ぐらいはねじ込み用の六角で、続いてボルトのねじが切られている。短い鬼目ナットはねじ切り部分も短い。例えば 10mm の鬼目ナットだと 5mm ぐらいしかねじ切りがないので、重い机の天板なんかを固定するのは不安。Flexispot のコントローラーならいいかも。天板の厚みとマージンを考慮して十分長いものを選びたい。 僕は Amazon で TUISKU の M4x15mm の鬼目ナットを購入して使った。 15mm というちょうどよい深さに惹かれて購入したが、いまいち精度がよくないし変形しやすいので強くおすすめはしない。 TUISKU の鬼目ナット ひどいものだとこのぐらい六角穴がガバガバである 信頼できて精度も(おそらく)よいムラコシのものを使いたかったが、M4 は 20mm しかラインナップしていない。 Flexispot の公式の天板や、よく同時に名前の上がる天板の厚さは 25mm で、余裕が少ないのでドリルストッパーを買うの良いと思う(もう1度やるならそうする)。 あるいはムラコシの M5x13mm か M6x16mm を買うのが良いと思う(確認してないけどたぶん入る)が、太くなると中心の精度が求められる。 天板と脚(ビーム)を合わせ、脚の穴にあうように鬼目ナットを埋めてボルトで固定するのだけど、脚の穴の径とボルトの間に余裕がないと中心がぴっちり合ってないと締められなくなる。M4 あたりであれば素人作業でも余裕だが、M6 あたりから厳しくなってくるのではないかと想像する。 鬼目ナットは、Flexispot E7 は脚に12個 + コントローラーに2個必要。 その他 CPU スタンドやケーブルダクトなどオプション品の必要個数を買っておく。練習用や予備にいくつかあると安心。 下穴を空ける 2段階で下穴を空ける。 正確に中心を合わせて垂直に穴をあけるのは難しいけど、正直2cm程度の深さなら目で垂直を確認する程度の精度で実用上問題ないと思う。僕は手でやりました。不安であれば垂直ドリルガイドなどを買うと良いと思います。 3mm の穴はめちゃくちゃきれいだけど、6mm に広げたら汚い 空けた下穴に鬼目ナットを埋めていく。 ボルト ボルトは、鬼目ナット+締結するものの厚み の長さのものを買う。 脚とゴムの厚みは約9mm 締めるとゴムはびちゃっとなる 工具 ここまで特に言及してないけど、電動ドリルまたはインパクトドライバーとドリルビットが必要である。ビットは下のリンクのものを購入した。 M4 の鬼目ナットをねじ込むには 4mm の六角レンチ、M4 の六角穴付きボルトを回すには(大抵) 3mm の六角レンチが必要になる。 自転車が趣味だったら一揃い持っているものだけど、このためにセットを買うのはバカバカしい気もするので、鬼目ナットは Flexispot 付属の 4mm の六角で埋めて、ボルトは手持ちのドライバーで回るものを選んでもよいかもしれない。ただ精度のいまいちな鬼目ナットに力を加えるとナメがちなので、いいものを使うと作業が楽である。 その他 ケーブルまとめたりするやつがあると見た目がマシになる。脚には磁石がくっつくのでフックをつけたり、電源タップを貼り付けることもできる。裏につけるマグネットもおすすめ。 ケーブルクリップ & 電源タップマグネット 初めて電動ドリルを使ったけど、とにかく良かった。 YouTube のレコメンドが DIY で埋まっている。なんでもいいから家具を作りたい。顧客が欲しいのは穴ではなくドリルである。あと電ノコとサンダーも欲しい。

  • ぽ靴な缶

    js を書いて URL やページの内容を加工してコピーできる Chrome 拡張ココピーのご紹介

    この記事は はてなエンジニア Advent Calendar 2020 - Qiita の23日目の記事です。 qiita.com 昨日は id:Krouton さんの 30日でできる! OS自作入門 を読むために nasm_of_nask というコンパイラを作った話 - KRAZY感情STYLE でした。よかったですね。 コードでコピーするココピーです 今日はちょっと前に作ったブラウザ拡張、cocopy を紹介します。 chrome.google.com しゅぴっと拡張を開いてコピーするフォーマットを選択できます。 コピー機がブーンとスキャンする感じをイメージしています。 利用者が js を書いてフォーマットを追加できます。 コードからは URL、タイトル、選択中のテキスト、ページの HTML にアクセスできます。 Markdown, Scrapbox HTML, はてな記法, Textile, Backlog など、さまざまな記法でリンクを張りたい Amazon 商品 URL をシンプルにして共有したい、あわよくば自分のアフィリエイトIDを埋めたい 選択範囲を引用しつつ元ページ情報へリンクしたい 今のページ内リンクの見出しをリンクテキストに含めてコピーしたい などのユースケースがあります。 モチベーション 文章中に URL が入ってると読みにくくないですか。 昔から、はてな記法には [http://~~:title] というタイトルを取得してリンクしてくれる記法があって、めちゃめちゃ便利に使っていた。でも今は仕事でのコミュニケーションの場が Github や Scrapbox、その他ツールへ広がっていて、いい感じにリンクするためにはいろんな記法を書く必要がある。リンクをコピーするためのブラウザ拡張はいろいろあるけど、Markdown に限られていたり、テンプレート機能が提供されていてもエスケープが不十分であったり、いまいち希望を満たすものがない。 コロナ禍でテキストコミュニケーションが増えてきたこともあり、いい感じのリンクを楽チンに作りまくりたい。 満足できるツールがほしいなーと思っていたので作りました。 作ってみると意外といろんな使い道が見つかるもので コピーする内容が1行である必要もないので、ページ内リンクのある見出しだけ集めて目次を作ったり Cloud Storage や BigQuery コンソールページから gs://{bucket}/{path} や {project}.{dataset}.{table} をシュッとコピーしたり Kibana やら何かしら検索できるサービスでクエリを querySelector('input[aria-label*="search"]').value で引っ張ってリンクテキストに含めたり ちまちましたコードを書いて日々の作業を改善するのが好きな人にはおすすめです。 使ってる技術 Preact + styled-components でもろもろ作っている。 Preact | Preact: Fast 3kb React alternative with the same ES6 API. Components & Virtual DOM. なるべくしゅぴっと素早くポップアップを開きたいと思って興味本位で使ってみたけど速度の比較はしていない。 これは実装が小さい頃のビルドサイズの比較だけどだいぶ違いますね。今リリースしているバージョンでも popup はギリギリ 900KiB に収まっている。 # react options.js 2.63 MiB options [emitted] options popup.js 2.38 MiB popup [emitted] popup sandbox.js 12.4 KiB sandbox [emitted] sandbox # preact options.js 346 KiB options [emitted] options popup.js 63.5 KiB popup [emitted] popup sandbox.js 12.4 KiB sandbox [emitted] sandbox はじめは jsxFactory 周りだけ設定して react を aliasしなくてもいけるんじゃないかと思ったけど、styled-components が普通に import しているのでダメだった その他 eslint やテストツールとの噛み合わせは Preact 使う - pokutuna にメモしてある。そのうち別途エントリにしたい。 アイコン かわいくないですか? いっしょうけんめい描きました。 アイコン 以前 Mackerel で仕事のがんばり具合を見える化する - ポクポク で書いた鯖くんから大きな成長が見られるのではないでしょうか。 鯖くん 明日の担当は id:hitode909 さんです。たのしみですね。