ツナワタリマイライフ

日常ネタから技術ネタ、音楽ネタまで何でも書きます。

2台の MacBook をクラムシェルで使いボタン2つで切り替える

今更ですがプライベート Mac と会社 Mac、利用用途ごとに分けるべきですが、周辺機器は共有したい。そう思いますよね。

ようやく整ったのでまとめます

どうなった

こうなった。

f:id:take_she12:20220223172801p:plain

f:id:take_she12:20220223171847p:plain

スイッチャー

紆余曲折ありこの2つのスイッチャーを使っている。

amzn.to

amzn.to

CableDeconn のほうは映像、LAN、電源いずれも転送できる。逆にいうと UGREEN の方ではディスプレイがダメだった。まぁ確かにできるとは書いていない。

2回ポチすれば切り替えられる。

f:id:take_she12:20220223173043p:plain

トラックパッドでカツカツ、とダブルクリックすれば起きてくれる。

こだわり

特にないが、

1ポチまでいかなかったが、2ポチでも今まで線繋ぎ直してたときより遥かに体験が良くて満足している。

おまけ:使ってる機器

Logitech Webcam C980OW

amzn.to

これまで内臓のカメラを使っていたが、クラムシェルにするので必要になり買った。

画質も良い。満足している。別に最高モデルが必要だった理由はない。

Blue Microphones Yeti Nano Condenser Microphone Streaming Set [Microphone Stand + Shock Mount Set]

amzn.to

これはだいぶ前から使っている。音質が良い。アームも安定している。

REALFORCE TKL SA for Mac / R2TLSA-US3M-BK

www.realforce.co.jp

これもだいぶ前から使っている。超打ちやすい。最高。

Filco Genuine Wood Wrist Rest

amzn.to

リストレスト。木なのが落ち着く。

Magic Trackpad

www.apple.com

有線の理由は充電が面倒だからです。あと切り替えた時も何も考えずに使えるのでなんだかんだ有線のほうが便利。

Anker PowerExpand

後ろに隠れているけれどこいつが便利。実家用にももう1つ買ったぐらい。

amzn.to

SD カードもつけられるのでカメラの画像をインポートするのにも便利。

そう考えると画面裏ではなく手が届くところに配置した方がいいことに今気づいた。

有線 LAN

はやいんです。有線 LAN 無線 LAN よりべんり。

twitter.com

Mackie CR4-XBT

amzn.to

こいつは Bluetooth で主に iPhone とつないで使います。

これ前のモデル CR4BT を使ってたんですが、壊れてしまい、修理に出したらいくらかお金を出したら新モデルを送ってくれるってシステムがあって、それでモデルチェンジできました。モスシステムさん好き。

https://www.soundhouse.co.jp/products/detail/item/217173/www.soundhouse.co.jp

修理交換プログラムというのがある。

mackie-jp.com

(今もだが)この時特に物をちゃんと長く使う、みたいな意識が高くなっていて、すぐに捨てて新しいものを買うのではなく、お金はかかっても修理して使う、っていうことをしたくて。結果的に元の製品はメーカーに送ることになったけど、自分が粗大ゴミとして出すよりは有効活用してもらえると思うのでやってよかった。

I-O Data EX-LD4K271DB 4K (60Hz) 27-inch Monitor

amzn.to

長く使っている。問題なく使えている。

今後買うもの

ディスプレイアーム

浮かせたい。

27インチ1枚でいくのか、もう少し大きいやつ1枚でいくのか、局面でいくのか、27インチ2枚でいくのか、など悩ましいので結局買えてない。

ディスプレイ構成決まらなくてもあとからアーム買い足したりできるのは知っているが、うーん。

イヤホン

もともとイヤホンジャックにつけてイヤホンは使っていたが、Air Pods の接続もそんなにストレスなさそうなのでしばらくこっちで試す。

Air Pods 接続めんどくさくなったら USB のイヤホン買うかも。

昇降式デスク

引っ越した時に買う。

今の机しなってる。もう長く使っている。

会議は立ってやる、っていう風にしたい。

椅子

良い椅子買いたい。座ってみたい。

おわりに

やっぱりギア買うのは楽しい。

PipeCD で AWS Lambda function を Canary Release する

する。

この example を使う。

github.com

Lambda と Canary Release

AWS Lambda では alias と version という概念によって Canary Release が実現できる。

docs.aws.amazon.com

複数の version の lambda application を deploy しておき、alias の weight を操作することで canary release を実現できる。

PipeCD はこの機能を操作し、PipeCD の持つ Pipeline 設定で実現している。

Cloud Run の例はこちら。

blog.chaspy.me

Container Image を ECR へ Push する

PipeCD の lambda の deploy には3種類の方法がある。

pipecd.dev

  1. container image
  2. zip file archives
  3. source code directly

nodejs や python などの場合、2 や 3 の方法が取れるが、Go の場合、通常ビルド済みバイナリはソースコードに含まないため、実質 1 のみ、あるいはビルドバイナリを zip にして S3 に置く方法で 2 を取ることができるが、面倒である。

一応 Go の Binary は GitHub Release などにアップロードされることがほとんどなので、url 指定で使う方式はどうか、と issue だけは書いた。が、他にそういう需要が増えない限りは実装されないだろう。

github.com

というわけで、Go でやりたかったので container image を ECR に push する。

github.com

hello するだけの function である。

github.com

それをこの辺で build して login して push している。

github.com

ここまでが CI (lambda application) 側の責務。

無事 Push される。

f:id:take_she12:20220215134156p:plain

PipeCD Application の登録

登録する。

f:id:take_she12:20220215134504p:plain

PipeCD Configuration の追加

指定した repository の path に以下のファイルを push

function.yaml

apiVersion: pipecd.dev/v1beta1
kind: LambdaFunction
spec:
  name: SimpleFunction
  role: arn:aws:iam::655123516369:role/service-role/lambda
  image: 655123516369.dkr.ecr.ap-northeast-1.amazonaws.com/lambda-api-gateway:v1
  memory: 512
  timeout: 30
  tags:
    app: simple

app.pipecd.yaml

# Deployment pipeline with canary strategy.
# Using version, alias, additional version to do canary, bluegreen.
# https://docs.aws.amazon.com/lambda/latest/dg/configuration-aliases.html
apiVersion: pipecd.dev/v1beta1
kind: LambdaApp
spec:
  pipeline:
    stages:
      # Deploy workloads of the new version.
      # But this is still receiving no traffic.
      - name: LAMBDA_CANARY_ROLLOUT
      # Promote new version to receive amount of traffic.
      - name: LAMBDA_PROMOTE
        with:
          percent: 10
      - name: LAMBDA_PROMOTE
        with:
          percent: 50
      # Promote new version to receive all traffic.
      - name: LAMBDA_PROMOTE
        with:
          percent: 100

push すると最初の quick sync が走ります。quick sync では現在指定している lambda function を単に deploy します。

f:id:take_she12:20220215134810p:plain

完了すると v1 が deploy されています。

f:id:take_she12:20220215134903p:plain

f:id:take_she12:20220215135028p:plain

f:id:take_she12:20220215135033p:plain

f:id:take_she12:20220215135036p:plain

f:id:take_she12:20220215135039p:plain

v2 を canary release する

PipeCD Configuration がある repository で image を更新します。

commit fd3fac104294eebbfa82beeed705296567b12a61
Author: kondo takeshi <chaspy@users.noreply.github.com>
Date:   Tue Feb 15 13:52:34 2022 +0900

    Deploy v2

diff --git a/lambda/canary/function.yaml b/lambda/canary/function.yaml
index 58b1924..a565222 100644
--- a/lambda/canary/function.yaml
+++ b/lambda/canary/function.yaml
@@ -3,7 +3,7 @@ kind: LambdaFunction
 spec:
   name: SimpleFunction
   role: arn:aws:iam::655123516369:role/service-role/lambda
-  image: 655123516369.dkr.ecr.ap-northeast-1.amazonaws.com/lambda-api-gateway:v1
+  image: 655123516369.dkr.ecr.ap-northeast-1.amazonaws.com/lambda-api-gateway:v2
   memory: 512
   timeout: 30
   tags:

merge すると deployment が作成され、

pipeline が plan されます。

f:id:take_she12:20220215135637p:plain

まずは v2 の function が deploy されます。

f:id:take_she12:20220215135713p:plain

待ちがなかったのであっという間に 100% promotion されてしまいましたw

f:id:take_she12:20220215140031p:plain f:id:take_she12:20220215140034p:plain f:id:take_she12:20220215140037p:plain f:id:take_she12:20220215140039p:plain

WAIT STAGE を追加してみる

これだとあんまりなので、30秒ずつ待ち時間を追加する。

v3 を deploy する。

f:id:take_she12:20220215140844p:plain

ちゃんと WAIT が動作しました。

f:id:take_she12:20220215141319p:plain f:id:take_she12:20220215141322p:plain

というわけで本家 example に PR 出しました。(すぐマージされました、Thank you!)

github.com

他の Deploy tool との比較

他のツールは動かしていませんが、調べた範囲でいくつか紹介しています。

素の aws cli

canary を利用しないのであればこれで十分かもしれません。

github.com

build して zip にして aws lambda update-function-code で upload するシンプルなパターン。

AWS SAM

aws.amazon.com

AWS 製のツールで、CLI が提供される。

yaml を input にして、内部では cloudformation が動くようだ。

段階的デプロイについてのドキュメントは以下。

docs.aws.amazon.com

Deployment Preference Type が 10percent ずつしかないのか、というところが自由度が低い気がしますね。

lambroll

github.com

init で初期化できたり、設定ファイルをコード管理して deploy コマンドで扱えるなど、cli よりわかりやすく、かつシンプルなツールなようです。

すでに lambda が存在している場合に init で設定をダウンロードするのもユーザビリティがあって良いですね。

ただ、canary release には対応していないようです。

fujiwara さんのブログを置いておく。

sfujiwara.hatenablog.com

比較

(他にツールがあれば教えてください)

シンプルと、できる機能の大きさでこういう順番になりそうなので、用途に応じて使いわけるといいでしょう。

aws cli < lambroll < PipeCD < SAM

lambda の deploy だけしたいのであれば lambroll, Canary Release をしたいなら PipeCD か SAM になりますが、PipeCD は Control Plane と Piped が必要なので環境構築が他に比べて少し大変な一方、柔軟な Canary, Analysis, Approval の設定が可能なので、すでに PipeCD を使っている環境については強力な選択肢になると思います。

SAM は Lambda 以外の API Gateway など他のサーバレスサービスをまとめてデプロイする、リッチなツールという位置付けになるかと思います。

入社してから3年半

前回

blog.chaspy.me

半年ごとに書いていたのに1年開いてしまった。てへ。

一言で言うと、この1年は次の飛躍のための助走期間だった、と評価している。するしかないとも言う。

まずアウトプットベースで振り返る。

Blog

この1年で書いた会社ブログはわずか3本。

blog.studysapuri.jp

blog.studysapuri.jp

blog.studysapuri.jp

Talk

意外と多い。8本。

How to add a new lint to tflint-ruleset-aws · GitHub

何をしていたのか

9月までは前1年と変わらず Lead Software Engineer。10月からは Engineering Manager になった。

blog.chaspy.me

コードで問題を解決すること

1月 - 3月の間は Prometheus Exporter を中心に、Go をひたすら書いていた。Go に限らず、コードで問題を解決すること、をひたすらやっていた。

もともとコードを書くことが好きで好きでたまらないというタイプではなく、業務上でも機会が多いとも言えない状況で、「必要な時に高いクオリティでコードを書く」ためにはコードを書くしかない。(自明)

いろいろ書いたが、今でも役に立っているものはいくらかあるし、自分にとってコーディングは「苦手なもの」から、書けば書けるな、という感覚を持てる程度にはなった。(得意とは言っていない)

毎日書く、みたいなことは多分難しいが、それでも今後も定期的に、少なくとも1年に1度は最新技術のキャッチアップも兼ねて、集中してコードを書く期間というものは設けていきたいと思う。

github.com

aws config complience 違反のものを metric として送ることができるので、dashboard で眺めたりアラート設定したりできるようになった。MFA 違反のひとを捕らえるのに今でも役に立っている。

metrics-driven / fact-based で問題に向き合うこと

上記のネタに関連するが、Quipper のバリューの1つであり、あらゆるものを metrics 化してコントローラブルにして、事実ベースで問題に向き合うということを、それができていないところにコードを書き技術で解決する、というアプローチが幾分かできたと思う。

Platform を Product として考えること

6月ぐらいから Platform as Product ということについて考えた。考えただけで特に大きな成果が出たとかではないんだが(Output として登壇はした)

自分たちがやっている仕事、作っている Platform が何のために、誰のためにあるのか、その接続が少なくとも自分の中で明確になったことは大きかったように思う。

この時学んだ Product Management は今でもかなり活きている。また、Technical Product Manager との会話も増え、業務もより円滑に進むことができたと思う。

技術戦略を考えること

4月から立ち上がった技術戦略グループの、DevOps Working Group の Lead をやったことで、DevOps - SRE が実現する手段の1つである、デリバリーの高速化とサービス信頼性をコントローラブルにする取り組みを開発チームと密に連携して課題に向き合うことができた。

この活動によって、プロダクト開発部全体として、DevOps という観点でどういう部分に課題があるのかをより解像度高く知ることができ、かつ SRE Team としての優先順位づけのインプットにもなった。

DX Criteria の実施もその一環だった。

blog.studysapuri.jp

チームをより Sustainable にすること

としてのビジョン・ミッション・バリューは EM の yuya-takeyama が整えたのは大きかった。

blog.studysapuri.jp

それ以外にも、特に4月以降は新メンバーの加入が(嬉しいことに)多く、人が変わっても、むしろ人が入ることでより強くなるチームに進化してきているように思う。

具体的には Retrospective。前からも隔週で行ってきたが、単に書いてしゃべるだけ、だったものから、振り返り自体の振り返りを取り入れ、型に囚われることなく、よさそうな提案はまずはやってみて、ダメならやめる、みたいなことを気持ちよくやることができている。かける時間に対して得られるベネフィットは当初に比べてかなり大きくなってきている。

Working Agreement。働く上でのゆるい合意のようなものを数ヶ月に一度やっている。これにより期待値を擦り合わせることができるし、新メンバーにとってもカルチャーを掴むのによりやりやすくなるし、多様な価値観を受け入れられる土壌になっていると思う。

その他 Daily Standup, Alert Handling, Cost check などルーチンワークをチームでまわすということは1年前、2年前から比べるとはるかに良くなった。これは提案、実行、フィードバックをくれるメンバーのおかげである。感謝。

(Engineering Manager として) 期待値を合わせること

わずか3ヶ月間。やったこととしてはいろいろあるが、重点をおいたのはこの点かなと思う。かなり丁寧にやったつもりだ。

これまで所属していたメンバーで仕事ぶりや個人としての信頼関係はそれなりにあるとはいえ、マネージャが変わるというのはそれなりに身構えてしまうものだと思う。

Engineering Manager README を書いて、何をどれぐらいするのか。しないのか。期待してもらうのか、メンバーに何を期待するのか、ということを書いて、個別に話した。

ミッション設定は本人の Will をもとに、身につけていってもらいたい能力や現状の課題という背景と合わせて言語化し、さらにそれをツリー形式で可視化することでメンバー同士の期待値も明らかにした。

今後はメンバー間の期待値をよりわかるようにする場を設けたり、マネージャへのフィードバックをもらえる仕組みなんかも作っていきたいと思う。

今後やること

EM という成果は3ヶ月という短いスパンで出るものではなく、半年でも多分短い。成果がないことに焦る必要はないが、それでも時間がかかるからこそ種まきはなるべく早くやったほうがいい。

Product Security Engineering Team の立ち上げ

現在 Job Description を書いてコードテストを仕上げているところ。

Product Security Engineer とは、SRE が Reliability を Engineering で Product Team に実装していくのと同じように、Security を Engineering で組織に実装していくポジション。

横断組織であるが、横断の Security 課題を解決したり、単にそれっぽいセキュリティ施策を導入するのではない。

1月中には JD 公開予定です。

プロダクト開発組織をより Sustainable にする

組織開発ともいう。組織課題を解決するともいう。それで目指したいことは Sustainable にするってことかなと。

そのために、コーポレートエンジニアリング的なツールを(セキュリティ的な観点入りで)整備したり、エンジニアのキャリアパスを整備したり、EM 自体が育成する・される環境を作ったり、ミッションマネジメントをより洗練させたりしていく。

ビジネスにエンジニアリングで貢献する

去年も掲げていたけど、できていなかったというか、助走期間だった。

プロダクト開発部がいくら SLO を定めてみても、それにより機能開発と非機能開発の優先度が「数値」によって、異なる職種を通じて話し合い、変更されうる状態になっていない。

そこを変えに行く。

そのために、技術戦略グループのマネジメント/リードをして、技術的負債をコントロール化に置く活動を支援したり、自己診断能力を開発できるようにして現状把握できるようにしたりして、機能開発 - ビジネス開発と同じだけ、非機能開発や技術的負債解消活動にも説明責任が果たせるようにしていく。同じものを見て、異なるストーリーを持つ人々と、1つの目的を達成できるようにする。そのために組織も技術も両方見て世界を変えていく。

今のところは、これが無理だと諦めた時に転職を考えるのかなと思ってます。これをやれると思ってるうちはがんばります。

おわりに

楽しくやりましょう。今年もよろしくおねがいします。

PipeCD で Google Cloud Run を Canary Release する

Cloud Run とは

GCP が提供するサーバレスのコンピュートサービス。コンテナイメージを指定してデプロイすると、url が割り当てられ、http や grpc のリクエストが受けられる。

スケーリングも勝手に行えるので、Kubernetes でいう HPA や Cluster Autoscaler に気を遣う必要がない。

PipeCD とは

GitOps で Deploy できる Deploy tool。

過去回。

blog.chaspy.me

blog.chaspy.me

blog.chaspy.me

前回までは Terraform を試していたが、今回は Cloud Run を Deploy してみる。

事前準備

http request に対して hello を返す go のアプリを書き、CI で Artifact Registry に push するところまで整えた。

PipeCD は「Deploy」をするツール(CDだし)なので、それ以前の Image Build まではやる必要がある。

blog.chaspy.me

github.com

PipeCD の準備

PipeCD は Example の「canary」を参考にし、ほぼそのまま使った。

github.com

service.yaml はこんな感じ。

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: canary
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/maxScale: '2'
    spec:
      containerConcurrency: 80
      containers:
      - args:
        - server
        image: asia-northeast1-docker.pkg.dev/hello-cloudrun-336811/hello-cloudrun/hello-cloudrun:a50a3aae930b07c5ce46851fd04d4e2278c12c68
        ports:
        - containerPort: 8080
        resources:
          limits:
            cpu: 1000m
            memory: 128Mi

.pipe.yaml はこんな感じ。

# Deployment pipeline with canary strategy.
apiVersion: pipecd.dev/v1beta1
kind: CloudRunApp
spec:
  pipeline:
    stages:
      # Promote new version to receive amount of traffic.
      - name: CLOUDRUN_PROMOTE
        with:
          percent: 10
      - name: WAIT
        with:
          duration: 30s
      # Promote new version to receive amount of traffic.
      - name: CLOUDRUN_PROMOTE
        with:
          percent: 50
      - name: WAIT
        with:
          duration: 30s
      # Promote new version to receive all traffic.
      - name: CLOUDRUN_PROMOTE
        with:
          percent: 100

これは example そのまんまですね。

これを repository に push し、control plane で application を作成する。

f:id:take_she12:20220101145921p:plain

ちなみに CloudRun を Deploy するためには piped 側に Provider の設定が必要。

こういう piped.yaml を使って

apiVersion: pipecd.dev/v1beta1
kind: Piped
spec:
  projectID: pipecd
  pipedID: piped-id
  pipedKeyData: piped-key
  apiAddress: control-plane-fqdn:443
  webAddress: https://contol-plane-fqdn
  syncInterval: 1m

  git:
    sshKeyFile: /etc/piped-secret/ssh-key

  repositories:
    - repoId: chaspy-test
      remote: git@github.com:org/repo.git
      branch: main

  chartRepositories:
    - name: pipecd
      address: https://charts.pipecd.dev

  cloudProviders:
    - name: kubernetes-default
      type: KUBERNETES
    - name: terraform-dev
      type: TERRAFORM
      config:
        vars:
          - "project=pipecd-dev"
    - name: cloudrun-dev
      type: CLOUDRUN
      config:
        project: hello-cloudrun-336811
        region: asia-northeast1
        credentialsFile: /etc/piped-secret/cloudrun-sa
    - name: lambda-dev
      type: LAMBDA
      config:
        region: ap-northeast-1
        profile: default
    - name: ecs-dev
      type: ECS
      config:
        region: ap-northeast-1
        profile: default

  secretManagement:
    type: KEY_PAIR
    config:
      privateKeyFile: /etc/piped-secret/secret-management-private-key
      publicKeyFile: /etc/piped-secret/secret-management-public-key

こういうふうにいくらかは local file を渡して helm で deploy している。

#!/bin/bash
helm upgrade -i dev-piped pipecd/piped \
    --version=v0.22.0 \
    --namespace=pipecd \
    --set-file config.data=piped.yaml \
    --set-file secret.data.ssh-key="/Users/chaspy/.ssh/id_rsa" \
    --set-file secret.secretManagementKeyPair.publicKey.data=./public-key \
    --set-file secret.secretManagementKeyPair.privateKey.data=./private-key \
    --set-file secret.data.cloudrun-sa=cloudrun/canary/sa.json

GCP 側の準備

Cloud Run の API の有効化などは必要だと思うが、必要なのは Service Account とその Key。

もともと Artifact Registry に Push するための Service Account があったので、それに Key を発行しました。

権限としては Cloud Run 管理者サービス アカウント ユーザー の2つのロールをつけています。

Cloud Run は多分管理者じゃなくてもっと小さくてもいいと思う。

特にハマったのがここで、

cloud.google.com

servive accout user role は

iam.serviceAccounts.actAs
iam.serviceAccounts.get
iam.serviceAccounts.list
resourcemanager.projects.get
resourcemanager.projects.list

を持っていて、特に iam.serviceAccounts.actAs が必要。これは何かというと、特定のサービスにおいては、SA がそれらのサービスを触る権限に加えて、その SA を使うことそのものを許可する必要があるようだ。

以下のエラーでハマっていた。(しかもなぜかこの時の ID が compute engine default account がでていてさらに混乱した。ci-build という別の ID の SA を使っていたのに。)

googleapi: Error 403: Permission 'iam.serviceaccounts.actAs' denied on service account 1111111111111-compute@developer.gserviceaccount.com (or it may not exist)., forbidden

cloud.google.com

によると App Engine とか Cloud Composer がそうだと言っているように見えるけど Cloud Run は書いてない。まぁとにかく最近のサービスはこれが必要ということにしておこう。

Let's Deploy

こういう Image を更新する PR を作ります。

f:id:take_she12:20220101161549p:plain

初回だったので plan-preview は何も言っていません。

f:id:take_she12:20220101161635p:plain

初回デプロイ終了後はこういう状況で、

f:id:take_she12:20220101161716p:plain

PR をマージすると PipeCD の UI で Deploy が進んでいます。CloudRunApp で設定したように、10% -> 30秒待つ -> 50% -> 30秒待つ -> 100% という風に Rollout していきます。

f:id:take_she12:20220101161825p:plain

10% Deploy 完了

f:id:take_she12:20220101161838p:plain

さらに Pipeline は進んで

f:id:take_she12:20220101161850p:plain

50% 完了

f:id:take_she12:20220101161900p:plain

最後まで終わりました

f:id:take_she12:20220101161913p:plain

最終バージョンにトラフィックが 100% 割り振られています。

f:id:take_she12:20220101161921p:plain

Cloud Run が持つ Canary Release の仕組み

PipeCD がこのような Canary Release をなぜ実現できるのかというと、そもそも Cloud Run 自体が Traffic Splitting の機能を持っているからです。

Cloud Run の実態は Knative が動いているようで、今回用意したservice.yaml もそうですが、Cloud Run を Deploy するとそれを表現した yaml を確認することができます。

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: canary
  namespace: '111111111111'
  selfLink: /apis/serving.knative.dev/v1/namespaces/111111111111/services/canary
  generation: 3
  creationTimestamp: '2022-01-01T03:18:48.557008Z'
  labels:
    cloud.googleapis.com/location: asia-northeast1
  annotations:
    serving.knative.dev/creator: ci-build@hello-cloudrun-111111.iam.gserviceaccount.com
    serving.knative.dev/lastModifier: ci-build@hello-cloudrun-111111.iam.gserviceaccount.com
    run.googleapis.com/ingress: all
    run.googleapis.com/ingress-status: all
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/maxScale: '2'
    spec:
      containerConcurrency: 80
      timeoutSeconds: 300
      containers:
      - image: asia-northeast1-docker.pkg.dev/hello-cloudrun-336811/hello-cloudrun/hello-cloudrun:a50a3aae930b07c5ce46851fd04d4e2278c12c68
        args:
        - server
        ports:
        - name: http1
          containerPort: 8080
        resources:
          limits:
            cpu: 1000m
            memory: 128Mi
  traffic:
  - revisionName: canary-a50a3aae930b07c5ce46851fd04d4e2278c12c68-246c0b4
    percent: 50
  - revisionName: canary-787644e4f49946792ff4044b7da399874a377269-d60586c
    percent: 50
status:
  observedGeneration: 3
  conditions:
  - type: Ready
    status: 'True'
    lastTransitionTime: '2022-01-01T03:34:57.321507Z'
  - type: ConfigurationsReady
    status: 'True'
    lastTransitionTime: '2022-01-01T03:34:57.321507Z'
  - type: RoutesReady
    status: 'True'
    lastTransitionTime: '2022-01-01T03:34:54.385969Z'
  latestReadyRevisionName: canary-n9jvd
  latestCreatedRevisionName: canary-n9jvd
  traffic:
  - revisionName: canary-a50a3aae930b07c5ce46851fd04d4e2278c12c68-246c0b4
    percent: 50
  - revisionName: canary-787644e4f49946792ff4044b7da399874a377269-d60586c
    percent: 50
  url: https://canary-jqu5pzsjea-an.a.run.app
  address:
    url: https://canary-jqu5pzsjea-an.a.run.app

apiVersion: serving.knative.dev/v1Service という kind に traffic というものが存在し、これで Revision に対するトラフィックの割合を指定できます。PipeCD は CloudRunApp に従ってこれを操作していると思われます。

kind は他に Route, Revision, Configuration があるようです。

knative.dev

Test in Production

Cloud Run は Traffic 0% でデプロイして、タグを付与することで特別な url でアクセスすることができます。本番の実トラフィックに影響を与えることなく、本番相当の環境でテストできる Test In Production を実現できます。

例えば新規でデプロイした Revision に test タグをつけると、https://test---canary-jqu5pzsjea-an.a.run.app/ という url でアクセスが可能です。

この機能は Knative の機能ではなく Cloud Run の拡張機能のようで、PipeCD 側からもこの設定をすることは残念ながらできないようです。

これ自体は gcloud run deploy で実現可能です。--tag と --no-traffic を組み合わせれば Preview URL を発行することができます。

cloud.google.com

PipeCD は Analysis という、対象の url へのヘルスチェックの機能があるため、個人的にはせっかく CloudRun が 0% Deploy & preview url (tag) をサポートしているので、0% でリリースし、そこへアクセスして成功率が問題ないことを確認しながら徐々にロールアウト、ということが実現できればかなり安全にアプリケーションのリリースができるだろうと思いました。

pipecd.dev

他のデプロイ方式との比較

もっともストレートなのは Google Cloud Build を使った継続的デプロイだと思います。 それ以外にも GitHub Actions でも gcloud auth/cli を使うための actions が用意されている&Workload identity Federation もあることから、良い選択肢かと思います。Image の Build と Push は https://github.com/chaspy/hello-cloudrun でしたように簡単ですし、デプロイは gcloud run deploy をすれば実現可能です。

PipeCD を使う優位性は WAIT や APPROVE を使った Pipeline が実現可能という点だと思います。また、ANALYSIS によって、徐々に展開しながらエラーが増えたらすぐ戻すということも実現できます。 GitHub Actions などで自前でやる場合は、Rollout の Promotion は別途何か自分で仕組みを書いてあげる必要があります。

おわりに

Cloud Run の準備に手間取りましたがよくできていると思いましたし、PipeCD が Canary Release をサポートしている Cloud Run のサポートに目をつけたのは賢いなと思いました。

GCP Workload Identity Federation を使って GitHub Actions から Artifact Registry に Image を Push する

した。コードはこれ。

github.com

思い出せる限りにやったこと。

GCP

1. Project 新規作成

2. SA 作成、Artifact Registry Writer Role を付与する。

ミニマムだと artifactregistry.repositories.uploadArtifacts があればいいはず。

cloud.google.com

3. Workflow Identity Federation の設定

cloud.google.com

この記事を参考に、GitHub Actions の ID 連携の設定 セクションで CLI でやってる部分を GUI でいれていった。

プールを1つ作って、プロバイダはこんな感じで作った。

f:id:take_she12:20211231234421p:plain

4. Service Account に WIF provider

#!/bin/bash
PROJECT_ID="hello-cloudrun-111111"
gcloud iam service-accounts add-iam-policy-binding "ci-build@${PROJECT_ID}.iam.gserviceaccount.com" \
  --project="${PROJECT_ID}" \
  --role="roles/iam.workloadIdentityUser" \
  --member="principalSet://iam.googleapis.com/projects/222222222222/locations/global/workloadIdentityPools/github-actions/attribute.repository/chaspy/hello-cloudrun"

これは CLI で設定。これで subject を指定することで repository を絞った。

GitHub Actions

5. Secret 追加

GCP_PROJECT_IDGCP_WIF_ID の2つを secret にした。別に見えてもいいような気もしつつ。

6. GitHub Actions を書く

使ってる Actions はこれら。

github.com

github.com

workflow 定義ははこれをみてくれ。

github.com

artifact registry はこの辺見て動かした。

cloud.google.com

ハマったこと

gcloud auth configure-docker asia-northeast1-docker.pkg.dev の部分で指定する region を間違っていて、push が永遠に成功しなかったが、permission がない、としか言われず原因がわからずハマった。ハマるときは絶対に凡ミスなのである。

復習

WIF (Workload Identity Federation) とはなんなのか

cloud.google.com

GCP 上の IAM を他の Provider から使う仕組みのこと。

AWS および OIDC をサポートしている。

これによって Service Account Key を発行せず、短命の Key を都度発行して認証することができるため、セキュリティ上のリスクを大きく減らすことができる。

テクい例がこちら。

blog.studysapuri.jp

OIDC(OpenID Connect) とはなんなのか

openid.net

なんらかの認証情報によって認証されたユーザに対して、ID トークンを払い出す仕様が標準化されたもの。これによって1度認証すればその ID トークンを「連携」することができる。

OAuth 2.0 に乗っかって動く。

OAuth 2.0 とはなんなのか

oauth.net

なんらかのリソースを操作、あるいは API 実行などを行うためのアクセストークンを要求する方法と応答を標準化したもの。

RFC6749 は読んでないけどだいたいそんな感じ。

JWT とはなんなのか

jwt.io

JSON Web Token のこと。

JSON で、署名ができるので改善確認ができるトークンの仕様で、OAuth で発行されるトークンとして使われる。

GitHub Actions が OIDC をサポートしたとはどういうことなのか

github.blog

そのままであるが、OIDC Provider の機能を持ち、Issuer として token の要求あるいは検証ができるようになったため、対応できる Cloud Provider と ID 連携が可能となった。

つまり

  • GitHub Actions の OIDC サポート、および GCP Workload Identity Federation が OIDC をサポートしていることにより、GitHub Actions から Keyless で GCP Resource にアクセス可能になった

めでたしめでたし。

CloudRun をデプロイしようとしてただけなんだがおかしいな...

SRE チームで Engineering Manager になって二ヶ月経っての心境など

この記事は前任 EM の yuya-takeyama の記事へのアンサーソングであり、

blog.yuyat.jp

Engineering Manager Advent Calendar 2021 その2 2日目の記事として寄稿します。

qiita.com

背景

僕は引用記事の SRE チームの Software Enginner でした。ひょんなことから前任が別のミッションを担うことになり、このチームの後任としてどうか、となり 2021年10月より同チームの Engineering Manager をやっています。

以下、引用したりしなかったりしてこの2ヶ月の心境などを語っていきます。

Engineering Manager として置かれている状況

先ほど言った経緯に引き続き、情報的な話でいうと

  • 自分含め7人のチーム
  • もともと中途採用をしていた会社でもあり、自走可能なメンバーで構成されている
  • プロダクト開発チーム複数に対して存在する横断チームである

という感じで、規模こそこれ以上の拡大は難しい状況にありつつも、多様性があり、広範囲の業務内容をいい感じに分散し、共有すべきことは共有し、バランス感を持ってやれている実感があります。

会社的な状況は2年前とは異なるとはいえ、個人記事なのでそこには触れないことにします。

現状は共通言語は日本語になり、英語の使用頻度はかなり減っています。(Global Development Team との会話の機会はなくなってはいませんが、以前よりかなり減っています)

Engineering Manager として大変なこと

Engineering Manager の引き継ぎ

これは個人がどうというわけでなく、人事評価などの引き継ぎの難しさです。 これまでメンバーとして関わっていたということもあり、いきなり外部から任用されるシチュエーションに比べて難易度は高くないとはいえ、それを短い時間で引き継ぐのはかなり難しいというか、不可能だと思います。 不可能なら不可能で、自分の目で見ていくでいいんですが、そうはいかないのが評価です。現職では評価と来期のグレード設定(給与に連動する)が分けられており、僕の場合、評価は前任、来期に任せるグレードは新任となっていました。 理屈としては評価と次に任せるグレードは可分なのはわかりますが、”とはいえ"評価なくして任せ切れるかという判断をするのは難しく、ここはかなり苦戦しました。

ミッションマネジメントの難しさ

現職では本人の Will, 本人の能力である Can , そしてチームや組織にとってやるべきである "Must" の3つを言語化して、適切らしいミッションを設定するというフレームワークを使っています。 このフレームワークは非常によくできていて、マネジメントとしてはポジティブな面も大きいのですが、納得感を持ったミッションをメンバー全員分設定し、評価基準や背景を言語化して伝えるというのはなかなか難しいということを体感しました。

ミッションマネジメントは、(めちゃくちゃ厳格なものではないとはいえ)メンバーにとっては評価につながるものですし、やるべきことは状況によって刻々と変わっていくので、半年に1度設定すればそれで終わりというものではありません。(その辻褄を合わせる裁量はもちろん与えられています)

それに、チームとしての成果を最大化するために、あるいはメンバーの成長やモチベーションのために、どういうことをしてほしいか、という期待値をマネージャからメンバーに伝える場所になっています。それゆえ、全体最適と個別最適のバランスを、様々な観点から1つの確からしい答えを出すという行為は正解がなく、マネージャとしてかなり難しい仕事の1つだと思いました。

Engineering Manager になってありがたかったこと

これは前任とほぼ同感で、以下2点です。

  • 人事や人事制度の存在
  • チームの内外のメンバーの優秀さ

追加で言うと、同じ Engineering Manager の存在のありがたさがあります。

今回は同じ部で同期で EM となった @ojiry と @shunsuke-nishimura がいるのに加え、これまでマネージャだったメンバーに相談したり壁打ちにのってもらったりとかなり助けられています。 Engineering Management は画一的なこれをやればいいという仕事は少なく、組織課題に代表されているような抽象度が高い課題が多くあります。そういった点をこれまでのように自分1人で解決するのは難しく、日々フィードバックをもらえて感謝しています。

Engineering Manager になって気づいたこと

これまで自分たちが「当たり前」に思っていたことは、誰かが頑張って当たり前にした、ということです。 これまではそういうものの恩恵に預かることが多かったですが、EM になって驚くほど「こういうことも整備されていないのか」ということにぶつかります。これは EM になって気づけてよかったと思っています。 制度や仕組み。こういうときにどうするのか、というのは過去の誰かが同じ問題にぶつかって、向き合い、話し合って、その解決策やフローが整備されてきたということをあらためて実感し、自分もその道を建設的に作っていこうと思っています。

Engineering Manager として今後やっていくこと

  • Feature Team による プロダクトのデリバリーを高速にする仕組みづくり
  • Security Engineering Team の立ち上げ
  • プロダクト開発チームをより魅力的に、持続可能にする取り組み

「良いものを、もっと速く」を実現するために、プロダクト開発に閉じない視野と視座で、世界中の"学び"の体験、そしてそれを届ける全ての人の体験を最適化するために、なんでもやっていこうと思います。

Engineering Manager としてこの3ヶ月やってきたこと

別エントリで振り返ろうと思います。 あせっているつもりはないが、それなりにそれなりをやってきたと思うので。

おわりに

あせらないあせらない。ひとやすみひとやすみ。

PipeCD で Terraform Apply する前に plan-preview で実行計画を確認する

Terraform アドベントカレンダー3日目の記事です

前回

blog.chaspy.me

というわけで plan-preview を試してみる。

公式ドキュメントは以下。

pipecd.dev

plan-preview は pipectl という CLI のサブコマンドとして提供される。

そしてこれには github-actions が提供されている。

github.com

サンプルのものをそのまま使えば良い。以下は実際に自分のリポジトリで動かしたもの。

on:
  pull_request:
    branches:
      - main
    types: [opened, synchronize, reopened]
  issue_comment:
    types: [created]

jobs:
  plan-preview:
    runs-on: ubuntu-latest
    if: "github.event_name == 'pull_request'"
    steps:
      - uses: pipe-cd/actions-plan-preview@v1.1.5
        with:
          address: ${{ secrets.PIPECD_API_ADDRESS }}
          api-key: ${{ secrets.PIPECD_PLAN_PREVIEW_API_KEY }}
          token: ${{ secrets.GITHUB_TOKEN }}

  plan-preview-on-comment:
    runs-on: ubuntu-latest
    if: "github.event_name == 'issue_comment' && github.event.issue.pull_request && startsWith(github.event.comment.body, '/pipecd plan-preview')"
    steps:
      - uses: pipe-cd/actions-plan-preview@v1.1.5
        with:
          address: ${{ secrets.PIPECD_API_ADDRESS }}
          api-key: ${{ secrets.PIPECD_PLAN_PREVIEW_API_KEY }}
          token: ${{ secrets.GITHUB_TOKEN }}

PIPECD_API_ADDRESSPIPECD_PLAN_PREVIEW_API_KEY を repository secret に入れる。

f:id:take_she12:20211207220358p:plain

PIPECD_API_ADDRESShostname:443 みたいなのをいれる。 PIPECD_PLAN_PREVIEW_API_KEY は control plane の settings から発行する。

こういう gcs object を追加するとする。

+ resource "google_storage_bucket_object" "object2" {
+   name    = "examples/waitapproval/test.txt"
+   bucket  = "pipecd-terraform-chaspy-dev"
+   content = var.content
+ }

こういう通知が来る。

f:id:take_she12:20211207221046p:plain

details を開くと普通に plan の結果が出ている。

f:id:take_she12:20211207221213p:plain

便利。

まとめ

  • pipecd の plan-preview 機能は actions が提供されており、サンプル通りに記載するだけで動く
  • plan-preview は terraform 以外にも apply 予定の"plan"を CI で閲覧することができる

他のツールとの比較

CI での plan 結果の通知は自前で実装することもできるが、Terraform に特化したツールといえば tfnotify と tfcmt がある。

github.com

github.com

tfnotify はメンテされていないので、tfcmt と比較する。tfcmt は Terraform での通知に特化しているので多くの優位点がある。その内容は tfcmt の README にある通りだが、

  • 結果がより見やすい
  • 削除時に警告される
  • PR にラベルが付与される
  • terraform 以外での変更が行われた部分をわけて表示する
  • github-comment と連携し、過去の comment を hide する

今回は terraform を試したが、kubernetes, lambda, cloudrun, ecs に関しては優位性があるかもしれない。他のツールでも同じような機能を提供しているものはあるかもしれないが、pipecd を使っていれば同様の設定1つだけで実装できるのは pipecd の有意な点だろう。

plan-preview は"plan" preview であることから、plan の結果しか通知できない。merge 後に結果どうなったかの通知もあるとよさそうである。このあたりも tfcmt に優位性がある。

ArgoCD の場合、sync 後の通知には argocd-commenter がある。

github.com


2021-01-31 追記: 過去のコメント hide が実装されたようです