Blog株式会社オールアバウトのエンジニアブログです。2023-03-29GCPを1ミリも知らなかった新卒が業務で学んだ知識でデプロイできるようになるまではじめにオールアバウトグループの新卒1年目エンジニアが投稿する企画『テックブログ新卒週間2023』2日目の投稿です。オールアバウトでPrimeAd関連サービスの開発をしているhinakochiです。サービスの一つのリビルドに関わる中で、アプリをGKEでデプロイする経験をしました。入社するまでGCP自体ほぼ触ったことがなかったので、当時はついていくので精一杯になってしまいました。何が起こっていたのかを理解するため、一度最初から最後までを自分でやりきりたいと思いました。約3ヶ月間、主に平日に一日一時間程度を使って簡単なアプリのデプロイに挑戦してきたので、これを機にその過程と学んだことをまとめてみました。遠回りが多くできたことはごくわずかですが、少しでもどなたかの参考になれば幸いです。(dbサーバ)Laravelのappコンテナとリバースプロキシ用のnginxのwebコンテナを自作イメージを使って立てます。これは業務で関わったものとほぼ同じ構成です。Proxyで接続します(ローカルではMySQLコンテナを立てていました)。今回はデータベースに保存したテキストを取得して表示する簡単なテストページを用意しました。外部IPアドレスに接続してこれが表示できればゴールとします。最終的な構成のイメージはこのようになります。Engineコンテナの自動管理ツールです。コンテナの集合体の最小単位をポッド、ポッドを実行するマシンをノード、ノード群をクラスターと呼びます。マニフェストファイルでポッドの構成やスケーリングの条件などを定義しておき、リクエストに応じて自動的にスケールさせることができます。SQLクラウドベースのリレーショナルデータベースシステムです。Registoryコンテナイメージを保存・管理できるサービス。Storageが担っています。Registoryが推奨されています。ドキュメント)IAMサービスというより、GCPの各サービスを使用するためのアカウント体系です。個人、組織、サービスなどの固有のアドレスをプリンシパルという概念で並列に扱い、様々な権限を付与します。個人的にはここで一番よく引っかかりました。具体的には、足りない権限が何か、それをどう与えるのかがわからない、IAMのサービスアカウントとKubernetesなどサービス特有のアカウントとの関係がわからないなどの点で悩みました。ちなみに90日間30$分の無料トライアルを利用しました。実は間に合わず期限後少しだけアップグレードすることになったのですが、クレジットが残っている分は引き継げるので大した負担にならなくてよかったです。ActionsCI/CDツール。コードもGitHubで管理しています。KustomizeKubernetesのマニフェストファイルを複数まとめて管理できるツールです。参考にしたチュートリアルに登場したので試しに触ってみました。今回はデプロイ環境を一種類しか用意していないのでそこまでメリットはないのですが、ベースのマニフェストファイルを動的に書き換えて使う方法を学べました。やったこと実際の手順を辿りながらハマった部分をピックアップしていきます。ローカルで動くアプリは一旦完成している状態です。デプロイ前のGCP側の準備プロジェクト作成ブラウザの管理コンソールで作成しました。プロジェクトはKubernetesに限らずGCP内の様々なサービスに跨がります。container.googleapis.comこれで該当サービスが使えるようになります。SQL周りはまだ何もしていません。このあたりの工程から下記の記事を参考にさせていただきました。使用してGKEにアプリケーションをデプロイするKubernetesクラスタ作成Kubernetesクラスタは作成の際、標準モードとAutopilotモードを選択できます。Autopilotモードは設定しなくとも自動スケーリングやノード管理をある程度やってくれるようです。使ってみましたが、小規模なアプリなので特に恩恵はなかったと思われます。クラスタは以下のチュートリアルを参考に作成できます。クラスタの作成クラスタ作成の過程で誤って飛ばしてしまい、その結果長時間悩むことになったステップを紹介します。sample-project-nameKubernetesのCLIツールであるkubectlを使用するにはクラスタを選択して接続する必要があります。この設定ができていないうちは下記のようなエラーが出ており、次のセクションで出てくるような個別のロールの設定が必要なのかとしばらく誤解していました。base64サービスアカウントは各サービスを利用するためのアカウントです。サービスアカウントにプロジェクトにおけるロールを与えると、ロールによってできることが追加されます。Storageに対する管理者ロールです。Storageはプロジェクト内のオブジェクトを保持するストレージサービスなのでこちらの権限も必要になります。Actions側でsecretsに登録し、Actionsから操作できるようにします。※今回は個人的な学習目的の環境なので大きな問題はありませんでしたが、最近はサービスアカウントキーをCI/CDツールに登録することのリスクが指摘されています。Identityなどを利用して直接サービスアカウントキーを登録せずに運用することができます。OIDCを利用しています。appコンテナとwebコンテナのデプロイKustomizeの設定ファイル構成は以下の通りです。imageでkustomization.yamlで用意した変数にイメージ名を設定し、変数が置き換わった状態でbuildすることができます。後略ちなみに、次のコマンドもbuildができるのですが、buildした結果のdeploymentが出力されるのでデバッグに役立ちました。kustomize正しいイメージを使用できているかの確認デプロイが成功したらまずこれが大事だと振り返ってみて思います。私の場合は、Podが動いていなくてPodの設定まわりを確認するのに時間を費やしてしまったのですが、実はイメージがpushできていない、イメージを指定できていない、古いイメージを使ってしまっているなどのミスがありました。前セクションのocコマンドで最新のdeploymentを確認できるほか、ターミナルから次のコマンドで実際のPodで使用されているイメージを含む様々な情報を確認できます。今回はUnixドメインソケットを使用しています。Unixドメインソケットを用いた通信はTCP通信より高速で、同じマシン内であればデータ通信用のファイルパスを通すことで通信できます(今回はappコンテナとwebコンテナが同一のマシンに乗っている状態なのでこの方法が可能です)。GCPとは話がずれますが、こちらもうまく接続できるまで非常に時間がかかった部分なので、どなたかの参考になることを願い簡潔に残しておきます。{}上記の設定では、nginx-sockというボリュームを確保し、コンテナごとに設定したパスでマウントします。次はnginx側の設定です。中略}appコンテナ側では、ソケットファイルにアクセス可能なシステムユーザーを用意する必要があります。/dataconfファイルをzz-www.confという名前に変更していることに注意してください。ここで使用している公式イメージでは、ビルド時にデフォルトのwww.confで上書きをしてしまう仕様があるようです。辞書順で後ろになるファイルを用意すればその内容が優先になるため、名前を変えて対応できるということのようです。app-name次のコマンドで得られる外部IPとnodePortの値をコロンで繋いで接続できます。SQLのインスタンス作成これだけ管理コンソールで作成しました。MySQLを選択したほかはデフォルト設定です。データベースはLaravel側でマイグレーションファイルを用意しています。Identity」を参考にしています。SQLに接続するためのコネクタです。今回はこのコネクタの公式イメージを使用してPodにコンテナを生成して接続します。オブジェクトを作成するKubernetesで使えるkey-value型のオブジェクトを作成します。後ほどマニフェストに使用します。Identityとは、Kubernetesのクラスタ内のサービスアカウントにIAMで作成したサービスアカウントを紐づけて接続する仕組みです。認証回数が減る、サービスアカウントキーを保持する必要がなくなる、アクセス範囲を狭められるなどのメリットがあります。Identityを用いた改善の余地があります。こちらは今後の課題とします。Autopilotモードでクラスタを作成すると、デフォルトで有効になっています。sample-ksadeploymentなどと同様にマニフェストファイルを作成し、applyすることで作成されます。iam.gke.io/gcp-service-account=sample-project-service-account@sample-project-name.iam.gserviceaccount.comこれによりプロジェクトのサービスアカウントが様々なサービスに認証なしでアクセスできるようになります。アノテーションに間違いがあった場合、--overwriteオプションをつけて再実行することで更新できます。{}KubernetesのSecretに登録した値をappコンテナの環境変数に設定します。Laravelの.envに同名の環境変数があれば、それを上書きします(つまり.env側の記述が不要になります)。--user=sample-db-userこれで直接データベースを操作できます。appコンテナに入ってマイグレーションを実行してから接続すれば、テーブルができています。終わりにGCPに関してほぼ無知な状態から、業務で触れる中で多少は理解できてきたと思っていました。自分で全てをやってみるうちに、氷山の一角でしかないという実感が強くなる一方でした。Identityの件に気づくのが遅すぎて手が回らなかったことなど、悔しい面はたくさんありますが、自分の力量を知る良い機会になりましたし、曲がりなりにもデプロイに漕ぎ着けたことはある程度自信になったと思います。今後もGCPに限らず実践的な学習を続けていき、業務に活かしていきたいです。SR...こんにちは。@s_ishiiと申します。@s_ishiiと申します。