こんにちは!虎の穴ラボのKanonです。
突然ですが、虎の穴ラボでは、技術セミナーの受講時間を業務時間として計上できます! *1
フレックス制度もあるので、上記のような昼開催のセミナーの場合は早めに退勤して受講という選択肢も取れるのですがお仕事が詰まってる場合に退勤してしまうと翌日以降が辛い。
そんな場合でも、お昼にセミナーに参加して終わったらまたお仕事再開…というように仕事と自己研鑽のバランスが取れるところが魅力的な制度です。*2
今回はその制度を活用して、オンラインで開催されたGoogle Cloud 様のこちら2日間のセミナーを満喫してきました 🎉*3
というわけで、タイトルの通りこちらのセミナーに参加して学んだことについてお話ししたいと思います!
(´-`).。oO ( Platform Engineering... ふわっとはわかるけど具体的にどういうものかピンときてない・よくわかんない )
っていう人に刺さる記事になってると思います!
参加のきっかけ・動機
私はGoogleという会社(特にGoogleのソフトウェア)が好きなので、開催予定のイベントを定期的にwatchしています。
余談ですが、Google Cloud関係のイベントはこちらのページでウォッチすることができます。
Google Cloudが主催されているイベントは基本的にそのほとんどが無料…にもかかわらず、毎回参加体験が非常に良いところがすごく魅力的です。
そのうえで『Google Cloud で始める Platform Engineering』に参加した1番の理由は、"Platform Engineering"について紹介されているスライドやブログを読んでも「言いたいことはわかるけど、具体的になにすればいいの?」という疑問を解消したいと思ったからです。
例えばCNCFでは以下のように記載されています。*4
プラットフォーム エンジニアリングは「コンピューティング プラットフォームを計画してデベロッパーとユーザーに提供し、プラットフォームのあらゆる部分とその機能(人、プロセス、ポリシー、テクノロジー)を網羅して、さらにそれらを推進するために必要なビジネス成果を提供する業務である」
書いてる内容はわかるのですが、「技術的に、なにをどうエンジニアリングすればよいのか?」という具体的なイメージを持つことができませんでした。
そこで今回のセミナーに参加することで、Google Cloudを使ってPlatform Engineeringをする具体的なイメージを持ちたいと思ったのが1番の目的でした。
そして結論から言うと、その目的を十分に達成することができました!
以降の章では実際のセミナー内容をご紹介しながら、目的を達成するまでのプロセスを見ていただければと思います。
当日の資料
具体的なお話の前に、公開されているスライドとハンズオンのチュートリアルを置いておきます。
1 日目 入門編
初日は入門編でした。ゴールとしてはこんな感じ。
先に紹介したチュートリアルを見れば、皆さんも実践していくことが可能です。*5
余談ですが、Google Cloudのこの手のチュートリアルを見たことある人もいるかもしれませんが、ここを押すとコマンドがコンソールに反映されるので便利です。
座学
まずは改めて「Platform Engineeringとはなんぞ?」というお話しから始まりました。
加えて、「Platform Engineeringはなぜ生まれたのか?」という経緯にも触れられていたことで、これまで「How」だけを見ていたことに気づきます。
とはいえまだ「技術的に、なにをどうエンジニアリングすればよいのか?」という疑問は解決しませんが、次のハンズオンでしっかりと理解することができました。
ハンズオン
今回のハンズオンではGKE で Cloud Workstation を作り、code-oss
による開発環境を提供するということをやりました。
「具体的にどういうものを作るか?」という完成図を最初に見せてくださっているおかげで、チュートリアルを進めていく上でも「いまこれをやってる」と意識できて非常によかったです。
実践
まずはチームと fleet を作り、サンプルのアプリケーションと紐付け。これにより、チーム別のモニタリングやログ表示が可能となることを確認しました。
ログバケットも別にできているのがわかります。
次に Workstations で Java のランタイムを作るのですが、ここではペルソナが用意されていて、みんなで「どういう要件が必要になりそうか?」を考えたりしました。
で、実際に作る Workstation は、こういうやつです。いろいろ Java のライブラリなどが入ってることがわかります。
FROM us-central1-docker.pkg.dev/cloud-workstations-images/predefined/code-oss:latest # Install Maven RUN apt-get update && apt-get install -y maven # Spring Boot Extension RUN wget https://open-vsx.org/api/VMware/vscode-boot-dev-pack/0.1.0/file/VMware.vscode-boot-dev-pack-0.1.0.vsix && \ unzip VMware.vscode-boot-dev-pack-0.1.0.vsix "extension/*" &&\ mv extension /opt/code-oss/extensions/vscode-boot-dev-pack # Spring Initializr Java Support RUN wget https://open-vsx.org/api/vscjava/vscode-spring-initializr/0.11.2/file/vscjava.vscode-spring-initializr-0.11.2.vsix && \ unzip vscjava.vscode-spring-initializr-0.11.2.vsix "extension/*" &&\ mv extension /opt/code-oss/extensions/vscode-spring-initializr # Spring Boot Dashboard RUN wget https://open-vsx.org/api/vscjava/vscode-spring-boot-dashboard/0.13.1/file/vscjava.vscode-spring-boot-dashboard-0.13.1.vsix && \ unzip vscjava.vscode-spring-boot-dashboard-0.13.1.vsix "extension/*" &&\ mv extension /opt/code-oss/extensions/vscode-spring-boot-dashboard # Extension pack for Java RUN wget https://open-vsx.org/api/vscjava/vscode-java-pack/0.26.0/file/vscjava.vscode-java-pack-0.26.0.vsix && \ unzip vscjava.vscode-java-pack-0.26.0.vsix "extension/*" &&\ mv extension /opt/code-oss/extensions/vscode-java-pack # ESLint extension RUN wget https://open-vsx.org/api/dbaeumer/vscode-eslint/2.4.4/file/dbaeumer.vscode-eslint-2.4.4.vsix && \ unzip dbaeumer.vscode-eslint-2.4.4.vsix "extension/*" &&\ mv extension /opt/code-oss/extensions/vscode-eslint # Docker Extension RUN wget https://open-vsx.org/api/ms-azuretools/vscode-docker/1.25.2/file/ms-azuretools.vscode-docker-1.25.2.vsix && \ unzip ms-azuretools.vscode-docker-1.25.2.vsix "extension/*" &&\ mv extension /opt/code-oss/extensions/vscode-docker # yaml Extension RUN wget https://open-vsx.org/api/redhat/vscode-yaml/1.14.0/file/redhat.vscode-yaml-1.14.0.vsix && \ unzip redhat.vscode-yaml-1.14.0.vsix "extension/*" &&\ mv extension /opt/code-oss/extensions/vscode-yamlstudent_01_1907e0c5bfce@cloudshell:
これをCloud Workstations に先のイメージをビルドしてデプロイします。デプロイ後、エディタを立ち上げられるかどうかを確認します。
エディタを起動できたら、このマシンローカルでサンプルアプリを動かします。
mvn clean install -DskipTests java -jar \ target/spring-boot-complete-0.0.1-SNAPSHOT.jar
無事にSpringのアプリケーションが起動できたところで、このアプリケーションを GKE にデプロイして動くことを確認します。
(この手順の前に CloudBuild でパイプラインを作っていました)
通常は GitHub Acions をトリガーにしますが、今回はリポジトリがないので手動でコマンドを叩いてWorkstationsからテスト環境にデプロイができることを確認します。
gcloud builds submit --config \ cloudbuild.yaml .
デプロイ後、Kubenetes Enginsを確認するとサービスが出来上がったことを確認し…
ステージング環境にデプロイができたことが確認できました。
これで、新規参入者が入った際にCloud Workstationsを事前に用意しておけば、特段開発者側でセットアップの諸々をせずともすぐに開発サイクルを回すことができるようになりました。
2 日目 実践編
実践編ではセキュリティを考慮したCI/CDパイプラインを構築しました。
Cloud Workstations までは初日にやったところで、2日目はそれより右側の部分を構築していきました。
Cloud Deployによる承認つきリリースパイプラインの構築
まずはCDを構築しました。利用するサービスはCloud Deploy
です。
今回はFlaskで出来た、ランダムに犬種を返すバックエンドサービスをデプロイします。
student_01_1907e0c5bfce@cloudshell:~ (qwiklabs-gcp-01-e272185c28ea)$ curl http://localhost:5000/random-pets {"breed":"Golden Retriever"} student_01_1907e0c5bfce@cloudshell:~ (qwiklabs-gcp-01-e272185c28ea)$ curl http://localhost:5000/random-pets {"breed":"Labrador Retriever"}
まずはCloud Deployに"リリース"という一つのデリバリーの単位を作ります。
gcloud deploy releases create \ release-$(date +%Y%m%d%H%M%S) \ --delivery-pipeline=pfe-cicd \ --region=asia-northeast1 \ --project=$PROJECT_ID \ --images=pets=asia-northeast1-docker.pkg.dev/$PROJECT_ID/app-repo/pets:v1
コンソールを見ると、dev環境へデプロイが走っているのがわかります。
しばらく待つと dev 環境にデプロイされました!
dev環境にデプロイされたアプリケーションの動作を確認すると…
犬種を返してくれました。というわけで、めでたく動作を確認できたので本番へ昇格します。
すると、今度は本番へデプロイが始まります。
デプロイ完了後、今度は本番で動作を確認します。
無事にレスポンスを得ることができました🎉
ガードレールを引く
次にやったのは、ガードレールを引くということです。
ガートレールとは一言で言えば、セキュリティ担保を運用ではなく自動化した仕組みで行うことです。
今回のハンズオンでは、以下のことに取り組みました。
脆弱性スキャン
これを有効にすると、Artifact Registry内部のコンテナイメージをスキャンし、脆弱性が認められた場合は警告を出してくれます。
今回はあえて脆弱性があるイメージを保存し、スキャンを有効にすることで動作を確認しました。このようにいっぱい怒られます。
継続的脆弱性スキャン
Artifact Registory の脆弱性スキャンだけでなく、Kubernetes にも継続的脆弱性スキャンという機能があります。
こちらも有効にすることで、Console上で脆弱性を報告してくれるようになります。
Policy Controller
今回一番面白かったのがこれでした。有効にすることで、許可されたリポジトリ上のイメージしかデプロイできなくなります。
やり方はまず、 Policy Controller を有効にします。
これは有効になるまで15 分くらいかかります。有効になったら制約を適用していきます。
今回利用する制約テンプレートは K8sAllowedRepos という、GKE から Pull 可能なリポジトリを allowlist 方式で定義する制約です。
# allow-myrepo.yaml apiVersion: constraints.gatekeeper.sh/v1beta1 kind: K8sAllowedRepos metadata: name: allow-my-app-repo spec: match: kinds: - apiGroups: - "" kinds: - Pod namespaces: - default parameters: repos: - asia-northeast1-docker.pkg.dev/PROJECT_ID/app-repo/
まずは、kubernetes-manifests/allow-myrepo.yaml
をデプロイします。こちらは成功します。
kubectl apply -f \ kubernetes-manifests/allow-myrepo.yaml
その後、kubernetes-manifests/maven-vulns.yaml
をデプロイしようとすると…
kubectl apply -f \ kubernetes-manifests/maven-vulns.yaml
すると、以下のようにPolicy Controller の制約違反によりデプロイが拒否されました。
理由としてはデプロイしようとした maven-vulns-app
という Pod のコンテナイメージは us-docker.pkg.dev/google-samples/containers/gke/security/maven-vulns
という別プロジェクト上のリポジトリに保管されており、今回の制約ではこのリポジトリを許可していないためです。
Error from server (Forbidden): error when creating "kubernetes-manifests/maven-vulns.yaml": admission webhook "validation.gatekeeper.sh" denied the request: [repo-is-openpolicyagent] container <maven-vulns-app> has an invalid image repo <us-docker.pkg.dev/google-samples/containers/gke/security/maven-vulns>, allowed repos are ["asia-northeast1-docker.pkg.dev/kkuchima-2405282/app-repo/"]
感想
座学とハンズオンの両方を行うことで、イメージを持ちつつ具体的な成果物を見ることができました。おかげでPlatform Engineeringの解像度が一気に上がったように思います。
実はつい最近、副業でCloud Build, Cloud Deploy を使って一から CD パイプラインを作ったりもしました。その過程でArtifact Registryの脆弱性スキャンを設定したりもしました。
なので、「気づかぬうちに実はPlatform Engineeringやってたんだな…」ということにも気づけてよかったです。
余談ですが、Cloud Build, Cloud Deployを構築したその時は一人でドキュメントを読み解きながら対応してました。
今日の内容を先に聞けていればどれだけ楽だったか… モデレーターだった関本さんの説明がめちゃくちゃ上手で、もっと早くこのセミナーを受講したかったです。
今回のセミナーでPlatform Engineeringがどういうものかは理解できたので、次はプロダクトに対してできることを自分の頭で考えていきたいと思います。
採用情報
虎の穴ラボでは一緒に働く仲間を募集中です!
この記事を読んで、興味を持っていただけた方はぜひ弊社の採用情報をご覧ください。
toranoana-lab.co.jp