1. はじめに
はじめまして、Sreake事業部インターン生の井上と村山です。
Sreake事業部はSRE関連技術に強みを持つエンジニアによるコンサルテーションサービスを提供する事業部であり、私たちもSRE技術の調査と研究を行う目的で2022年10月11日 ~ 24日に開催された短期インターンに参加しました。
2週間という期間を使って、Google CloudのConfig Connectorについて調査を行ったので、本記事ではその調査結果をまとめます。
自己紹介
- 井上 秀一
- 千葉工業大学 情報科学研究科 情報科学専攻 修士一年
- 趣味はオンプレミスのサーバ開発でSREやサーバ・インフラサイドに興味があります。
- 村山 諄
- 信州大学大学院 総合理工学研究科 工学専攻 修士一年
- 趣味は最近始めた競プロです。
2. Config Connectorとは?
概要
- Google Cloud側の設定をK8sリソース (DeploymentやServiceなど) と同じYAML形式で管理できるIaCサービス
- Terraformを利用する場合は、Google Cloud側の構成ファイル(HCL)と、K8sリソース(YAML)を管理する必要がある。
- Config Connectorを利用することで、どちらもYAMLで一元管理できるので、管理の複雑性の低下が見込める。
- K8sと同様、Google Cloudの設定を宣言された状態に保つ。
- config-connector exportコマンドで既存のGoogle CloudのリソースをYAML形式で取得して、Config Connectorで管理可能
- 途中からConfig Connectorの導入が可能
- Google CloudのサービスなのでAWSやAzureでは利用不可
- ただし、GKE on AWS等のGoogle Cloudを介するサービスでは利用可能 (他の Kubernetes ディストリビューションへのインストール)
仕組み
- 公式ドキュメントからの引用
Config Connector は、Identity and Access Management(IAM)サービス アカウントで認証し、GKE の Workload Identity を使用して IAM サービス アカウントを Kubernetes サービス アカウントにバインドすることで、Google Cloud リソースを作成、管理します。
- 要約すると、Google CloudのサービスアカウントにConfig ConnectorがGoogle Cloudのリソースを管理する上で必要な権限を付与し、GKEのWorkload Identityを利用してクラスタ内部からGoogle Cloudリソースを管理できるようにする。
- GKEクラスタが用意されていないと、そもそもConfig Connectorを利用できないので、Config Connectorの導入方法としては以下の流れが考えられる。
- UI、gcloudコマンド、TerraformでGKEクラスタの構築とConfig Connectorアドオンの有効化
- Config Connectorでその他のGoogle Cloudリソースを構築
なぜConfig Connectorを使うのか?
- K8sアプリケーションを管理するのと同じ方法でGoogle Cloudインフラ構成を管理でき、ADMINの負担を軽減することができる。
- リソースファイルをYAMLに統一する事で、ファイル管理の煩雑性を低下させる。
- K8sリソースとGoogle Cloudリソースの作成が一回で行える。
3. Config Connectorの検証で用いたお題
Config Connectorを活用して、下図のようなWordPress環境を構築した。
具体的に作成したリソースは以下。
- Google Cloud
- VPC
- GKEクラスタ
- Cloud SQL
- Cloud Load Balancing
- IAM
- K8s
- Config Connectorの各リソース
- WordPressコンテナとCloud SQL Auth Proxyコンテナを含むDeployment
- LoadBalancerタイプのService
- サービスアカウント
前提知識 (Terraform)
- インフラ設定を宣言的に記述し、反映する事ができるIaCツール
- AWS、Azure、Google Cloud等、有名処のクラウドプロバイダから、様々なインフラサービスに対応
- HCL(HashiCorp Configuration Language)と呼ばれる言語で記述
- jsonと互換性がある言語
前提知識 (Cloud SQL)
公式ドキュメントからの引用
Cloud SQL Manages your database instance. You manage your data.
つまり、Cloud SQLを利用しデータベースインスタンスの管理をCloud SQLに任せることで、ユーザはデータの管理だけに集中することが可能になる。 類似サービスとして、AWSだとAmazon RDS。AzureだとAzure SQL Databaseのようなサービスがある。 Cloud SQLの概要としては次のようなものである。
- Google Cloudのフルマネージドリレーショナルデータベースサービス
- MySQL、PostgreSQL、SQL Serverをホスト可能
今回のインターンではCloud SQL周りの要素として、次の3つの要素を主に扱った。
- Cloud SQL インスタンス
- データベースインスタンスを稼働するためのソフトウェアコンテナが含まれている仮想マシン
- 今回のデータベースインスタンスはMySQL
- Cloud SQL インスタンスのIP
- パブリックIPとプライベートIPを設定可能 (IPv4)
- プライベートIPのみを設定した場合、外部のインターネットからのアクセスはできないが、Cloud SQLインスタンスが存在するVPCとVPCピアリングを設定することで、任意のVPC(Virtual Private Cloud)からアクセスが可能
- 今回はプライベートIPのみを使用し、VPCからSQLインスタンスへアクセスを行う
- Cloud SQL Auth Proxy
- Cloud SQLインスタンスに安全に接続するためのプロキシ
- 特定のIPアドレスの承認やSSL / TLS証明書の構成を必要としない
- IAM(Identity and Access Management)権限によって認証を行う
- 同様の接続方法として、Java、Python、Go用のライブラリであるCloud SQL コネクタがある
- 今回はCloud SQL ↔ GKEクラスタ間をCloud SQL Auth Proxyを使用して接続
4. 実際にやってみた
上記の図は具体的にどこの項目を設定しているか補足している。
1. Config Connectorのセットアップ
公式ドキュメントのGKE アドオンでのインストールを参考に、Config Connectorをセットアップする。なお、Terraform等でVPCとGKEクラスタは作成済みである前提で話を進める。
(a) Config Connectorアドオンの有効化
TerraformでもConfig Connectorアドオンを有効化できるが、今回はgcloudコマンドを利用してアドオンを有効化する。
$ gcloud container clusters update <cluster-name> --zone <zone-name> --update-addons ConfigConnector=ENABLED
(b) Google Cloudのサービスアカウントを作成
Config Connectorが使用するGoogle Cloudのサービスアカウントを作成する。今回はconfig-connector-userという名前で作成する。
$ gcloud iam service-accounts create config-connector-user
(c) Google Cloudのサービスアカウントにロールを付与
先ほど作成したGoogle Cloudのサービスアカウントに、Config Connectorが必要とする権限を渡す。
今回は公式ドキュメントに従い、roles/editorを付与するが、roles/editorはほとんどのGoogle Cloudサービスのリソースを作成/削除できるロールなので、本番環境等では適切なロールを設定すること。
$ gcloud projects add-iam-policy-binding <project-id> \
--member="serviceAccount:config-connector-user@<project-id>.iam.gserviceaccount.com" \
--role="roles/editor"
(d) Config Connectorのインストール
以下のようなconfig-connector.yamlを作成し、googleServiceAccountに(b)で作成したGoogle Cloudのサービスアカウントを指定する。
apiVersion: core.cnrm.cloud.google.com/v1beta1
kind: ConfigConnector
metadata:
name: configconnector.core.cnrm.cloud.google.com
spec:
mode: cluster
googleServiceAccount: "config-connector-user@<project-id>.iam.gserviceaccount.com"
こちらのyamlをapplyし、Config Connectorをインストールする。
$ kubectl apply -f config-connector.yaml
以下のコマンドを実行し、インストール状況を確認する。
$ kubectl wait -n cnrm-system --for=condition=Ready pod --all
Config Connectorが正しくインストールされている場合、以下のように出力される。
pod/cnrm-controller-manager-0 condition met
(e) Google Cloudのサービスアカウントと、K8sサービスアカウントの紐づけ
先ほど作成したGoogle Cloudのサービスアカウントと、cnrm-controller-managerが利用するK8sサービスアカウントの間のIAMポリシーバインディングを作成する。
$ gcloud iam service-accounts add-iam-policy-binding \
config-connector-user@<project-id>.iam.gserviceaccount.com \
--member="serviceAccount:<project-id>.svc.id.goog[cnrm-system/cnrm-controller-manager]" \
--role="roles/iam.workloadIdentityUser"
(f) Google Cloudのリソースを管理するためのNamespaceを作成
Google CloudのリソースをConfig Connectorで管理するためのNamespaceを作成する。今回はgcpという名前で作成する。
$ kubectl create namespace gcp
(g) Namespaceにアノテーションを付けて、Google Cloudのリソースを作成するプロジェクトを指定
先ほど作成したNamespaceに、cnrm.cloud.google.com/project-idのアノテーションを付与し、対象プロジェクトを指定する。
$ kubectl annotate namespace gcp cnrm.cloud.google.com/project-id=<project-id>
2. Cloud SQLインスタンスの作成
事前にAPIへのアクセスの有効化よりCloud SQL Admin APIを有効化しておく。
今回は、Cloud SQLにパブリックIPを設定せず、プライベートIPのみを設定するので、Cloud SQLインスタンスへアクセスできるようにGoogle Cloudサービスプロバイダとのプライベートサービスアクセスを設定する必要がある。
(a) VPCのエクスポート
VPCピアリングの設定をConfig Connectorで行うには、まずGKEが存在するVPCをConfig Connectorで管理する必要がある。
config-connector exportコマンドを使うことで、既存のGoogle CloudリソースをConfig Connectorで管理できるyamlとしてエクスポートできる。
$ config-connector export //compute.googleapis.com/projects/<project-id>/global/networks/<network>
エクスポートすると以下のようなyamlの出力が得られる。
apiVersion: compute.cnrm.cloud.google.com/v1beta1
kind: ComputeNetwork
metadata:
annotations:
cnrm.cloud.google.com/project-id: <project-id>
name: <vpc-name>
spec:
autoCreateSubnetworks: false
resourceID: <vpc-name>
routingMode: REGIONAL
(b) SQLインスタンスの作成
sql-instance.yamlを作成し、先ほどエクスポートしたVPCと、プライベートIP、Google Cloudサービスプロバイダとのプライベートサービスアクセス、Cloud SQLインスタンスを定義する。
sql-instance.yamlをgcp(Namespace)にapplyし、Cloud SQLインスタンスを作成する。
$ kubectl apply -f sql-instance.yaml -n gcp
(c) データベースのユーザを作成
sql-user.yamlを作成し、先ほど作成したCloud SQLインスタンスに対してユーザを追加する。
apiVersion: sql.cnrm.cloud.google.com/v1beta1
kind: SQLUser
metadata:
name: <sqluser-name>
spec:
instanceRef:
name: <sql-instance-name>
namespace: gcp
host: "%"
password:
value: <sqluser-password>
sql-user.yamlをapply。
$ kubectl apply -f sql-user.yaml -n gcp
これで、Cloud SQLインスタンスの作成は完了。
ちなみに、この状態でgcloudコマンド等でCloud SQLインスタンスを削除しても、Config Connectorが再度Cloud SQLインスタンスを生成してくれる。
3. Cloud SQLへの疎通確認
(a) WordPress用のGoogle Cloudのサービスアカウントを作成し、Cloud SQLインスタンスへのアクセス権限を付与
今回はcloud-sql-auth-proxy-userという名前で、Google Cloudのサービスアカウントを作成する。
$ gcloud iam service-accounts create cloud-sql-auth-proxy-user --project=<project-id>
作成したサービスアカウントに、Cloud SQLインスタンスへのアクセス権限を付与する。
$ gcloud projects add-iam-policy-binding \
--member="serviceAccount:cloud-sql-auth-proxy-user@.iam.gserviceaccount.com" \
--role="roles/cloudsql.client"
(b) WordPress用のK8sサービスアカウントを作成
service-account.yamlを作成し、K8sのサービスアカウントを定義。今回は、wordpressという名前で作成する。
apiVersion: v1
kind: ServiceAccount
metadata:
name: wordpress
namespace: wordpress
annotations:
iam.gke.io/gcp-service-account: cloud-sql-auth-proxy-user@<project-id>.iam.gserviceaccount.com
service-account.yamlをapplyして、サービスアカウントを作成。
$ kubectl apply -f service-account.yaml -n wordpress
(c) Google Cloudのサービスアカウントと、K8sのサービスアカウントを紐付け
Google Cloudのサービスアカウントと、K8sのサービスアカウントの間のIAMポリシーを作成する。
$ gcloud iam service-accounts add-iam-policy-binding \
cloud-sql-auth-proxy-user@<project-name>.iam.gserviceaccount.com \
--member="serviceAccount:<project-id>.svc.id.goog[wordpress/wordpress]" \
--role="roles/iam.workloadIdentityUser"
(d) Cloud SQL インスタンスのインスタンス接続名を取得
$ gcloud sql instances describe <sql-instance-id> | grep connectionName
(e) 先ほど作成したK8sサービスアカウントを利用したDeploymentを作成
mysql-client.yamlを作成し、MySQL clientとCloud SQL Auth Proxyコンテナを含んだDeploymentを作成し、(b)で作成したK8sサービスアカウントをマウントする。
apiVersion: apps/v1
kind: Deployment
metadata:
name: wordpress
namespace: wordpress
spec:
selector:
matchLabels:
app: wordpress
template:
metadata:
labels:
app: wordpress
spec:
serviceAccountName: wordpress
containers:
- name: mysql-client
image: imega/mysql-client
command: ["/bin/sh", "-c", "sleep infinity"]
- name: cloud-sql-auth-proxy
image: gcr.io/cloudsql-docker/gce-proxy:latest
command:
- "/cloud_sql_proxy"
- "-ip_address_types=PRIVATE"
- "-log_debug_stdout"
- "-instances=<sqlinstance-connection-name>=tcp:3306" # sqlinstance-connection-nameには先ほど取得したインスタンス接続名を記載
securityContext:
runAsNonRoot: true
mysq-client.yamlをapplyする。
$ kubectl apply -f mysql-client.yaml -n wordpress
(f) MySQL clientのコンテナに作成したpodのpod名を取得
$ kubectl get pod -n <namespace>
NAME READY STATUS RESTARTS AGE
<pod-name> 2/2 Running 0 0s
(g) 作成したmysql-clientコンテナのシェルを起動
$ kubectl exec -n <namespace> <pod-name> -c mysql-client -it -- /bin/bash
(h) コンテナ内のシェルでMySQLにログイン
/ # mysql -u <sqluser-name> -p -h 127.0.0.1 -P 3306
Enter password: <sqluser-password>
ログインが成功すれば以下のような出力がされる
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MySQL connection id is <id>
Server version: 8.0.26-google (Google)
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MySQL [(none)]>
このような出力が確認できればCloud SQLとの接続は成功である
4. WordPressのデプロイ
(a) WordPress用のDeploymentを作成
wordpress.yamlを作成し、WordPressとCloud SQL Auth Proxyコンテナを含んだDeploymentを作成する。
apiVersion: apps/v1
kind: Deployment
metadata:
name: wordpress
spec:
replicas: 2
selector:
matchLabels:
app: wordpress
template:
metadata:
labels:
app: wordpress
spec:
serviceAccountName: wordpress
containers:
- name: wordpress
image: wordpress
env:
- name: WORDPRESS_DB_HOST
value: "127.0.0.1:3306"
- name: WORDPRESS_DB_USER
value: "<db-username>" # 先ほど作成したユーザ名
- name: WORDPRESS_DB_PASSWORD
value: "<db-password>" # 先ほど作成したパスワード
- name: WORDPRESS_DB_NAME
value: "<db-name>" # 事前にWordPress用のDBを作成し、そのDB名をこちらに記載
ports:
- containerPort: 80
- name: cloud-sql-proxy
image: gcr.io/cloudsql-docker/gce-proxy:latest
command:
- "/cloud_sql_proxy"
- "-log_debug_stdout"
- "-instances=<sqlinstance-connection-name>=tcp:3306" # sqlinstance-connection-nameはGoogle CloudのUI等を参照
securityContext:
runAsNonRoot: true
ports:
- containerPort: 3306
$ kubectl apply -f wordpress.yaml -n wordpress
(b) WordPress用のServiceを作成
service.yamlを作成し、LoadBalancerタイプのServiceを定義する。
apiVersion: v1
kind: Service
metadata:
name: wordpress-lb
spec:
selector:
app: wordpress
ports:
- protocol: TCP
port: 80
targetPort: 80
type: LoadBalancer
$ kubectl apply -f service.yaml -n wordpress
(c) WordPressにアクセスし、初期設定
LoadBalancerのExternal IPを取得し、http://<EXTERNAL_IP> に接続して、疎通確認と初期設定を行う。
$ kubectl apply -f service.yaml -n wordpress
5. 失敗談 IAMポリシーを吹き飛ばした
発生した事象
Cloud SQLに接続するために必要なサービスアカウント周りの設定を、Config Connectorで管理しようとした際に事件は起きた。
まず、Cloud SQLに接続したいPodで利用するK8sサービスアカウントを作成。
その後、Config ConnectorのIAMServiceAccountリソースを用いてGoogle Cloudサービスアカウントを定義し、IAMPolicyリソースを用いて必要なロールの付与、K8sサービスアカウントとの紐付けを定義した。
Config ConnectorがIAM周りを管理できる様に、Config Connectorが利用するサービスアカウントにProject IAM Adminのロールを付与し、先ほど定義したIAMServiceAccountやIAMPolicyのリソースをデプロイしたところ、既に存在していたIAMポリシーが全てなくなってしまった。
原因
Config ConnectorのIAMPolicyは既存の設定を上書きするため、IAMPolicyで定義していないポリシーは削除してしまうとのこと。
なお、IAMPolicyではなく、IAMPolicyMemberであれば上書きではなく追加される。
複数クラスタでConfig Connectorを用いる場合は、設定の管理が共有されていないと上記の事象が発生しうるため注意が必要。
6. おわりに
Config Connectorのメリット
- インストールが簡単
- GKEアドオンをオンにして、コマンドを少し叩くだけでインストールが可能である。
- Google Cloudの構成をK8sリソースと一緒に一元管理でき、管理の複雑性低下が図れる。
- Google Cloud側のサービス(今回はCloud SQL)構成も同じyamlファイルに記述が出来るため、ADMINはワンクリックでサービスの起動が出来る。
- K8sのCRD扱いで汎用性が高い。
- 現在設定されているGoogle Cloud構成をexport出来る。
- 途中から乗り換える事も出来る。
- Google Cloudの構成等、exportして書式を真似る、加筆する事が出来る。
Config Connectorのデメリット
- Google Cloud側の構成に追記ではなく上書きするリソースがある。
- 今回のケースではIAMPolicyが該当する。
- 宣言されていない物は全て消える。
- クラスタが作成済みで、KSA(K8s service account)、GSA(Google service account)のバインディングポリシーやアノテーション等が設定済みな事が前提である。
- UI、gcloudコマンド、TerraformでConfig Connectorが動作する最低限の構築。
- Config Connectorで利用するNamespaceへのアクセス管理が必要
- Google Cloudの構成をConnfig Connectorが動作しているNamespace上にapplyするだけで適用できるため、インフラリソースを操作する適切なユーザのみに権限を付与する必要があると考える。
インターンの感想
井上の感想
- 課題についての感想
- Config Connectorの検証を兼ねた実用的な課題でK8sの理解度が向上した。
- K8sオブジェクトの理解や構造について理解が深まった。
- 今後オンプレミスでK8sを構築し、サービスを運用する上での操作方法について理解が深まった。
- podが正常に起動しない時のトラブルシューティング、ログの確認方法等を実践的に学ぶ事が出来た。
- Google Cloudを触り、GUIでの非宣言的な操作だけでなく、IaCツール(Terraform, Config Connector)を用いて触れる事が出来た。
- Config Connectorの検証を兼ねた実用的な課題でK8sの理解度が向上した。
- インターンの総評
- 事前講義+有給インターン+専門書二冊の支給の手厚いサポート
- 初学者向けにハンズオン形式の事前講義が用意されている。
- 有給でK8sやGoogle Cloudをみっちり覚えられる。
- SREに関するO’Reillyの専門書二冊頂きました(割と高価)
- 原則フルリモートで、希望者はオフィス見学を兼ねて一回出社する事が出来る。
- 交通費全支給なので長野方面から来ている方もいました。
- 美味しい昼ご飯も支給されました。
- 適度な雑談や柔らかい雰囲気
- 就活や、SRE系の企業情報、働き方等、気兼ねなく聞く事が出来た。
- オンプレサーバ開発(趣味)の相談と実際のエンジニア視点でのアドバイス等を頂けた。
- 気軽に聞ける、チャレンジできる等、課題を遂行する上での心理的安全性が保障されていた。
- メンターの方々が技術的にも優秀かつ、とても和やかな雰囲気で、楽しくストレスフリーにインターンに取り組めた。
- WiFiルータ貸し出し
- インターン初日に自宅のネットワークが通信障害に陥った旨を相談した所、ポケットWiFiをインターン期間中貸与してもらいました。
- 事前講義+有給インターン+専門書二冊の支給の手厚いサポート
- 最後に
- 自身のスキルアップやインフラの世界の勉強になる最高のインターンです。二週間でK8sやGoogle Cloudの理解度が大幅に向上しました。設定された課題は、インターン参加前の興味度アンケートに基づいて設定されていたので自身のやりたい事を的確に学べました。K8sやGoogle Cloudは学生個人で勉強するには中々難しいので、今回の様なインターンは千載一遇のチャンスだと思っています。とても手厚いサポートで充実した二週間になりました。ありがとうございました。
村山の感想
- 課題についての感想今後の可能性を秘めているConfig Connectorについて調査し、実際に動かすことでどのような利点や可能性があるのか、どのような点に注意や工夫が必要なのかなどを身をもって学ぶことができました。また、KubernetesやGoogle Cloudについても同様に調査をしたり実験をしたりすることで、それらについての理解を深めることができました。
- インターンの総評インフラ未経験だった自分にとって、インフラについて理解し、インフラの面白さを知ることができ、とても楽しく、勉強になった2週間でした。事前講義や実際の作業の中で,インフラのプロフェッショナルなエンジニアの方々に直接指導をして頂き、エンジニアの方々の知識量や技術、それらを活用した問題解決能力の高さを実感しました。将来のキャリアも含め、自分の足りない部分や挑戦していきたいことが明確になり、今後のモチベーションも高めてくれた素晴らしいインターンでした!
7.参考資料
- Config Connectorについて
- Config Connector がGoogle Cloudの構成を操作する方法や仕組み
- Cloud SQLについて
オマケ
インターンの最後はGatherのゴーカートで締めくくりました。
他班のインターン生に一位取られましたが2位と3位は自班のインターン生で抑えました。