概要
最近、GKEの導入を進めており、GKEへのデプロイは、Cloud Buildから行うようにしています。
Manifestの管理は、Kustomizeを活用しています。
よく課題となるが、GCPのサービスアカウントといった秘匿性のある情報の管理です。
例えば、GKE上のコンテナからCloud SQL Proxy経由でCloud SQLに接続する場合、
Cloud SQL ProxyのコンテナにGCPのサービスアカウントを食わせる必要があると思います。
このサービスアカウントは、KMSで暗号化することでGitHubでも管理できるようにしていますが、
この場合、デプロイする際に暗号化をほどいてからGKEにデプロイする必要があります。
今回は、Cloud Buildによるサービスアカウントの復号とKustomizeの secretGenerator
を活用した例をご紹介できればと思います。
環境
- GKE 1.14.10-gke.27
- Kustomize 3.4.0
- Cloud Build
詳細
ディレクト構成
以下のようなディレクトリ構成を前提にしています。
.gcp
├── secrets
│ └── service-account.$PROJECT_ID.json.enc #サービスアカウントをKMSで暗号化していたもの
k8s
└── ops
├── base
│ ├── envoy
│ │ ├── configmap.yaml
│ │ ├── deployment.yaml
│ │ └── service.yaml
│ ├── grpc-gateway
│ │ ├── ingress.yaml
│ │ └── service.yaml
│ ├── grpc-server
│ │ └── service.yaml
│ └── kustomization.yaml
└── overlays
└── development
├── grpc-gateway
│ ├── deployment.yaml
│ ├── ingress.yaml
│ └── ssl.yaml
├── grpc-server
│ └── deployment.yaml
└── kustomization.yaml # secretGeneratorの設定を入れる
前提条件
- Cloud KMSで暗号化したサービウアカウントが
.gcp/secrets/service-account.$PROJECT_ID.json.enc
にあるものとします。 - Cloud KMSのキーリングは、
secrets
、キーはservice-account
とします。事前に作成していただくか、適宜読み替えてください。
事前準備
Cloud Build上で起動させるkustomizeの公式イメージがなかったので、
こちらのリポジトリを参考に、Kustomizeイメージをビルドしました。
ビルドしたkustomizeのDockerイメージは、GKEをデプロイするGCPと同じプロジェクト内のGCRにPushします。
このリポジトリには、cloudbuild.yaml
があるので、READMEを参考にすればCloud Build経由でイメージをビルドできるかと思います。
Cloud Build
Cloud Build側でgcloud kms decrypt
を実行し、特定のディレクトリ(今回ですとk8s/ops/overlays/development/grpc-server)に配置します。
$PROJECT_ID
には、指定せずともCloud Buildを実行しているGCPのプロジェクト名が入ります。
環境(devとかstg等)ごとにGCPプロジェクトが分かれているので、このようなサービスアカウント名にすることで各環境にも転用できるようにしています。
次に上述の手順でBuildしたKustomizeイメージを指定し、kustomize経由でkubernetesにdeployします。
このkustomizeイメージでは、kustomize.bashがENTRYPOINTで指定されています。
引数にbuild
を指定することで、kustomize $@ | kubectl apply -f -
を実行しているようです。
- id: decrypt service accout
name: gcr.io/cloud-builders/gcloud
args:
- kms
- decrypt
- --ciphertext-file=.gcp/secrets/service-account.$PROJECT_ID.json.enc
- --plaintext-file=${_DIR}/grpc-server/service-account.$PROJECT_ID.json
- --location=global
- --keyring=secrets
- --key=service-account
- id: deploy
name: 'gcr.io/$PROJECT_ID/kustomize' # 自分でBuildしたKustomizeイメージを指定
dir: '${_DIR}'
args:
- 'build'
env:
- 'APPLY=true'
- 'CLOUDSDK_COMPUTE_ZONE=${_CLOUDSDK_COMPUTE_ZONE}'
- 'CLOUDSDK_CONTAINER_CLUSTER=${_CLOUDSDK_CONTAINER_CLUSTER}'
substitutions:
_CLOUDSDK_COMPUTE_ZONE: asia-northeast1-a
_CLOUDSDK_CONTAINER_CLUSTER: <your GKE cluster name>
_DIR: k8s/ops/overlays/development
Kustomize
Cloud Buildでk8s/ops/overlays/development/grpc-server/
にサービスアカウントをdecryptしましたが
そのサービスアカウントを secretGenerator
を使用してリソースを作成します。
bases:
- ../../base
patchesStrategicMerge:
- grpc-gateway/ingress.yaml
resources:
- grpc-gateway/deployment.yaml
- grpc-gateway/ssl.yaml
- grpc-server/deployment.yaml
secretGenerator: # secretGeneratorを使用し、復号したサービスアカウントを基にsecretsを作成
- name: service-account
files:
- grpc-server/service-account.<your project name>.json
実行結果
secretGeneratorで生成されたsecretsは以下のようにSuffixがつきます。
$ kubectl get secrets
NAME TYPE DATA AGE
service-account-f25f88gf6d Opaque 1 24d
Secretsのmount
セキュリティ的にあまり良くないようですが、Deploymentのvolumesにmountする形で使用しました。要改善。
さきほど確認したsecretsにはSuffixがついていましたが、そのたありはよろしくやってくれるようです。
volumeMounts:
- name: service-account-file
mountPath: /mnt
readOnly: true
env:
- name: GOOGLE_APPLICATION_CREDENTIALS
value: "/mnt/service-account.visits-for-innovators-dev.json"
volumes:
- name: service-account-file
secret:
secretName: service-account
まとめ
GCPのサービスアカウントといった秘匿性のあるファイルを、kustomize構成で管理、デプロイする方法についてご紹介でした。
他にいい方法があれば教えてください。
参考
以下の文献を参考にさせていただきました。
Cloud Build + Cloud KMS + kustomizeでGKEへデプロイする