Appearance
External Secrets Operatorの導入 GCP編
本章では、Qmonus Value Streamの応用として、Official Cloud Native AdapterであるExternal Secrets Operator AdapterとGKE Cluster Secret Store Adapterを使用して、GCPのSecret Managerの秘密情報をGKEのSecretリソースへ自動連携する手順を解説します。
External Secrets Operatorは、秘密情報を管理するプロバイダ(GCP Secret Manager, Azure Key Vault, AWS Secrets Managerなど)と連携し、Kubernetes環境のSecretリソースと同期できます。 External Secrets Operatorが提供する主なCustom Resourceとして、Cluster Secret StoreリソースとExternal Secretリソースが存在します。Cluster Secret Storeはクラスタ単位でデプロイされ、外部プロバイダへ認証し、External SecretはCluster Secret Storeを指定して外部プロバイダの秘密情報を取得し、Secretリソースを生成します。
公式イメージ:
Qmonus Value Streamを使用したExternal Secrets Operator導入の公式の手順として、Official Cloud Native Adapterを使用してCluster Secret StoreをGKEへデプロイし、GCP Secret ManagerがGKEのSecretリソースへ同期できる環境を提供します。
以下のプライベートリポジトリが作成されていることを前提とします。
- 持ち込みのGitリポジトリ
- GitHub、GitLabなどのインターネットからアクセス可能なGitリポジトリをご用意ください。
- 本チュートリアルではGitHubを使って説明しますが、適宜ご利用されているサービスに読み替えてください。
- GitHubリポジトリへの認証は Personal Access Token (GitLabの場合は Personal access tokens)を使用することを前提とします。
以降のステップでは主に下記の作業を通じて、External SecretリソースにSecret Managerの秘密情報が連携されていることを確認します。
- External Secrets Operator AdapterとGKE Cluster Secret Store AdapterをQmonus Values Streamでデプロイする
- GCP Secret Managerへ値を登録し、サンプルExternal SecretリソースをApplyして自動作成されるSecretリソースに秘密情報が連携されていることを確認する
0-1. 準備:External Secrets OperatorのCustom Resource Definition の適用
External Secrets OperatorのCustom Resource Definitionから、v0.5.0
以上の任意のバージョンを指定してGKEにApplyしてください。
bash
# v0.5.0以上の任意のバージョンをcloneする
git clone -b ${v0.5.0_or_more} https://github.com/external-secrets/external-secrets.git
# kubectl の現在のコンテキストを確認する
kubectl config current-context
(External Secrets Operatorをデプロイするクラスタ名)
# Custom Resource DefinitionをApplyする
kubectl apply -f external-secrets/deploy/crds/bundle.yaml
0-2. 準備:Workload Identityの構成
Workload Identityを使用することで、使用しているGCPのService Accountの権限をGKEのワークロードに付与することが可能になります。 これにより、ワークロードがGCPリソースにアクセス出来るようになります。 以下を参考に、Workload Identityの設定準備を行ってください。
- Workload Identityを有効にしてください。
- Kubernetes Service Account(以下、KSA)と紐づけるKSAと紐づけるGoogle Service Account(以下、GSA)の作成とIAMによるWorkloadIdentityを設定してください。
- GSAの作成
- GSAを任意の名前(
${gsaName}
)で作成してください。default値を使用する場合はGSAの名前を"external-secrets-operator"として作成してください。 - GSAにSecret Managerへの読み取り権限として、
roles/secretmanager.secretAccessor
を付与してください。
- GSAを任意の名前(
- Workload Identityの設定
- KSAにGSAのポリシーをバインディング、および
roles/iam.serviceAccountTokenCreator
を付与してください。
bashここで使用したパラメータについての詳細は以下の通りです。特に変更する必要がなければ、default値のあるものはdefault値を使用することを推奨します。また、このパラメータは手順5で再度使用します。# gcloudコマンド例(Secret Managerが存在するプロジェクトで実行してください) gcloud iam service-accounts add-iam-policy-binding ${gsaName}@${gsaGcpProject}.iam.gserviceaccount.com --role roles/iam.serviceAccountTokenCreator --member "serviceAccount:${k8sClusterGcpProject}.svc.id.goog[${ksaNamespace}/${appName}]"
Parameter Name Default Description appName gcp-secret-manager KSAおよびCluster Secret Storeのリソース名 gsaGcpProject - GSAが存在するGCPプロジェクトID k8sClusterGcpProject - GKEクラスタが存在するGCPプロジェクトID gsaName external-secrets-operator GSA名 ksaNamespace qmonus-system KSAをデプロイするksaNamespace - KSAにGSAのポリシーをバインディング、および
- GSAの作成
1. Kubeconfigの作成 (CLI)
Qmonus Value Streamは、Kubeconfigと呼ばれる認証ファイルを利用してKubernetesへアプリケーションをデプロイします。 ここでは、クラスタ・スコープのKubeconfigを生成します。
以下の手順にしたがって、Kubernetesクラスタにアクセスし、External Secrets Operator AdapterとGKE Cluster Secret Store Adapter によって定義されるリソースをデプロイするためのNamespaceを作成し、Kubeconfigを生成してください。Namespaceは、default値を使用するのであればqmonus-system
となります。 ここで、${k8sClusterGcpProject}
はKubernetesクラスタが存在するGCP Project ID、${k8sClusterName}
はKubernetesクラスタ名、${zone}
はGKEのZone名を指定します。
bash
# 利用するKubernetesへ接続
gcloud --project=${k8sClusterGcpProject} container clusters get-credentials ${k8sClusterName} --zone ${zone}
# Kunbernetes Service Accountをデプロイする、手順[0-2]で使用した${ksaNamespace}と同じNamespaceを作成する。
# ESOと同じであれば、skipしてください。
kubectl create ns ${ksaNamespace}
# External Secrets Operator AdapterとGKE Cluster Secret Store Adapter デプロイ用のKubeconfigを生成
# Namespaceがクラスタに存在しない場合は新たに作成されます。
# Namespaceは、default値を使用するのであれば"qmonus-system"
qvsctl plugin gen-kubeconfig -p -o cluster.kubeconfig.yaml [-n ${esoNamespace}]
WARNING
クラスタ・スコープのKubeconfigは権限が非常に強力なため、お取り扱いには注意してください。
なお、gcloudコマンドをはじめて実行する場合は、以下の手順によりgcloudコマンドを初期化してください。
bash
gcloud auth login
2. Applicationの登録 (GUI)
今回利用するサンプルアプリケーションを登録します。
- 左メニューより、Applicationを選択します。
- 画面右上の
NEW APPLICATION
ボタンを押下します。 - 各フォームに以下の値を入力し、画面右下の
NEXT
ボタンを押下します。- Display Name: External Secrets Operator
- Description: (任意の文章または空白)
- QVS Config Repository:
+ Create New Repository
を選択し、手順2-aに従いRepositoryを作成 - QVS Config File Path: eso-clustersecretstore/.valuestream/qvs.yaml
以下は、必要な値を入力した状態のApplicationの登録画面になります。
2-a. Repositoryの登録
今回用意したプライベートリポジトリをQmonus Value Streamに登録します。
以下のパラメータの値を変更し、画面右下のCREATE
ボタンを押下します。
- Repository Kind: github
- Git Clone Protocol: https
- Repository Visibility: private
- Git Clone URL: (チュートリアルで利用するリポジトリのURLを入力、例:https://github.com/sample-org/sample-repo-name.git)
- Description: (任意の文章または空白)
- Git Token:(プライベートリポジトリへの認証に利用するTokenを入力)
3. Deploymentの登録 (GUI)
手順1で生成した、クラスタ・スコープのkubeconfigを使用してDeploymentを作成します。
各フォームに以下の値を入力し、画面右下の CREATE
ボタンを押下します。
- Display Name: staging
- Name: (Environment選択時に自動入力)
- Environment:
+ Create New Environment
を選択し、手順3-aに従いEnvironmentを作成- 注) Application単位で、同一Environmentを選択できません
- Credentials
- kubeconfig: 手順1で生成した、cluster.kubeconfig.yamlの内容
以下は、必要な値を入力した状態のDeploymentの登録画面になります。
3-a. Environmentの登録
デプロイ先となる環境を登録します。検証環境、商用環境といった、プロジェクト/プロダクトに応じて任意の環境を定義してください。 また、Qmonus Value Streamが推奨する環境の考え方については、環境定義を参考にしてください。
各フォームに以下の値を入力し、画面右下のCREATE
ボタンを押下します。
- Display Name: (staging など、任意の環境名)
- Description: (任意の文章または空白)
- Provisioning Target:
- Kind:
kubernetes
- DisplayName: Provisioning Targetを一意に指定できるNameやID
- Alias:(空白)
- 同じタイプのProvisioning Targetを複数登録する際は、2つ目以降については Aliasのフォームに そのProvisioning Targetを特定できるエイリアス名を付与してください。
- Kind:
4. Official Cloud Native Adapterのダウンロード (CLI)
プライベートリポジトリでOfficial Cloud Native AdapterのCI/CD AdapterとInfrastructure Adapterをqvsctlコマンドでダウンロードします。
bash
# プライベートリポジトリをcloneする
git clone https://gihub.com/${your_organization}/${your_repository}
# プライベートリポジトリに移動
cd ${your_repository}
# 本チュートリアル用のブランチを作成する
git checkout -b qvs_eso_clustersecretstore
# KubeconfigをGitリポジトリの管理から除外する
echo 'cluster.kubeconfig.yaml' >> .gitignore
# 本チュートリアル用のディレクトリを作成する
mkdir -p eso-clustersecretstore/.valuestream
cd eso-clustersecretstore/.valuestream
# qvsctl auth コマンドを使用して認証する(出力されたurlへアクセスしてください)
qvsctl auth
# Official Cloud Native Adapter でダウンロードできるパッケージの確認
qvsctl adapter list
NAME LATEST RELEASED DATE
qmonus.net/adapter/official vx.x.x YYYY-MM-DD hh:mm:ss
# Official Cloud Native Adapterをダウンロードする
qvsctl adapter get qmonus.net/adapter/official
5. QVS Configの作成 (CLI)
ダウンロードしたOfficial Cloud Native Adapterから、Tekton Pipeline/Task を構成するCI/CD Adapterと、Kubernetesリソースを提供するInfrastructure Adapter(External Secrets Operator AdapterとGKE Cluster Secret Store Adapter)を指定するQVS Configを作成します。
bash
# QVS Configを作成する
vim qvs.yaml
yaml
params:
- name: version
type: string
- name: esoNamespace
type: string
- name: appName
type: string
- name: smGcpProject
type: string
- name: gsaGcpProject
type: string
- name: k8sClusterGcpProject
type: string
- name: gsaName
type: string
- name: ksaNamespace
type: string
- name: k8sClusterLocation
type: string
- name: k8sClusterName
type: string
modules:
- name: qmonus.net/adapter/official
local:
path: .
designPatterns:
- pattern: qmonus.net/adapter/official/kubernetes/secrets/eso
params:
version: $(params.version)
k8sNamespace: $(params.esoNamespace)
- pattern: qmonus.net/adapter/official/kubernetes/secrets/gke/clustersecretstore
params:
appName: $(params.appName)
smGcpProject: $(params.smGcpProject)
gsaGcpProject: $(params.gsaGcpProject)
k8sClusterGcpProject: $(params.k8sClusterGcpProject)
gsaName: $(params.gsaName)
ksaNamespace: $(params.ksaNamespace)
k8sClusterLocation: $(params.k8sClusterLocation)
k8sClusterName: $(params.k8sClusterName)
- pattern: qmonus.net/adapter/official/pipeline/deploy:simple
6. Pipeline Manifestの生成および登録 (CLI)
手順5で作成したQVS Configを用いてPipeline Manifestを生成し、Qmonus Value Streamへ登録します。 projectName
はQmonus Value StreamのProject Nameです。Project Nameは、qvsctl project list
で取得したPROJECT NAME
を指定してください。
bash
# コンパイルする
qvsctl pipeline compile -m . -c qvs.yaml -o pipelines --prefix external-secrets-operator
# Project Nameを取得する
qvsctl project list
# Pipeline Manifestを登録する
qvsctl pipeline apply -p ${projectName} -f pipelines/manifests.yml
7. AssemblyLineの登録(CLI)
作成したPipelineを実行するためのAssemblyLineを作成し、Qmonus Value Streamへ登録します。
bash
# AssemblyLineを作成する
vim pipelines/eso-clustersecretstore-deploy-assemblyline.yaml
yaml
apiVersion: vs.axis-dev.io/v1
kind: AssemblyLine
metadata:
name: eso-clustersecretstore-deploy
spec:
params:
- name: gitRevision
description: ""
results: []
artifacts: []
stages:
- name: eso-deploy
spec:
deployment:
app: external-secrets-operator
name: staging
params:
- name: gitRevision
value: $(inputs.gitRevision)
- name: providerType
value: kubernetes-helm
- name: deployStateName
value: externalsecretsoperator
pipeline: external-secrets-operator-deploy
- name: clustersecretstore-deploy
spec:
deployment:
app: external-secrets-operator
name: staging
params:
- name: gitRevision
value: $(inputs.gitRevision)
- name: deployStateName
value: clustersecretstore
pipeline: external-secrets-operator-deploy
runAfter:
- eso-deploy
info
ここでは、deployStateName
の値をPipeline毎に分けることで、Qmonus Value Streamでのリソース管理の単位を分割しています。基本的にはPipelineのデフォルトの値で定まっているため、今回は例外として、基本的には修正しないことを推奨します。
作成したAssemblyLineを登録します。
bash
# AssemblyLineを登録する
qvsctl pipeline apply -p ${projectName} -f pipelines/eso-clustersecretstore-deploy-assemblyline.yaml
リモートリポジトリに変更を反映します。
bash
git add --all
git commit -m "Qmonus Value Stream Official Introduction for External Secrets Operator"
git push origin qvs_eso_clustersecretstore
8. Deployment Configの登録 (GUI)
CLIで登録したAssemblyLineをGUIから確認し、AssemblyLine詳細画面より、不足しているパラメータを設定します。
- 左メニューより、AssemblyLineを選択します。
- 画面中央に表示される
eso-clustersecretstore-deploy
を選択します。 AssemblyLine
のPipeline Stages
のeso-deploy
パネルを選択します。AssemblyLine Stage
画面右に表示されるEdit Deployment Config
リンクを選択します。- YAMLモードのEditorが表示されますので、Infrastructure Adapterに必要なパラメータをYAML形式で入力します。
yaml
version: ${version}
esoNamespace: ${esoNamespace}
appName: ${appName}
smGcpProject: ${smGcpProject}
gsaGcpProject: ${gsaGcpProject}
k8sClusterGcpProject: ${k8sClusterGcpProject}
gsaName: ${gsaName}
ksaNamespace: ${ksaNamespace}
k8sClusterLocation: ${k8sClusterLocation}
k8sClusterName: ${k8sClusterName}
ここで、パラメータは以下の通りです。 External Secrets Operator Adapter:
${version}
: 手順0-1で指定したExternal Secrets OperatorのCRDのバージョン (0.5.0
など"v"を除いた状態で指定してください)${esoNamespace}
: 手順0-2で指定かつ手順1で作成した${esoNamespace}
GKE Cluster Secret Store Adapter:
${appName}
: 手順0-2で指定したKSAおよびCluster Secret Storeのリソース名${smGcpProject}
: 手順0-2で指定したSecret Managerが存在するGCPプロジェクトID${gsaGcpProject}
: 手順0-2で指定したGSAが存在するGCPプロジェクトID${k8sClusterGcpProject}
: GKEが存在するプロジェクトID${gsaName}
: 手順0-2で作成したGSA名${ksaNamespace}
: 手順0-2で指定かつ手順1で作成した${ksaNamespace}
${k8sClusterLocation}
: GKEクラスタが存在するリージョン名${k8sClusterName}
: GKEクラスタ名
Save
ボタンを押下し、Input Parameters
一覧全てが緑で表示されていることを確認します。
9. AssemblyLineの実行 (GUI)
登録したAssemblyLineを実行し、External Secrets OperatorとCluster Secret StoreをKubernetesにデプロイします。 以下のInput Parameterを入力し、eso-clustersecretstore-deploy
AssemblylineのRUN
ボタンを押下してCI/CDを開始します。
- gitRevision: qvs_eso_clustersecretstore
10. デプロイされたアプリケーションの確認(CLI)
Kubernetesにアクセスして、デプロイに成功したExternal Secrets Operator と Cluster Secret Storeを確認します。 ここで、${esoNamespace}
と${appName}
はそれぞれ手順8で指定したExternal Secrets Operatorが使用するnamespaceとCluster Secret Storeのリソース名です。
bash
# kubectl の現在のコンテキストを確認する
kubectl config current-context
(External Secrets Operatorをデプロイしたクラスタ名)
## External Secrets Opeartorのデプロイによって作成されたDeploymentリソースを確認する
kubectl get deployment -n ${esoNamespace}
NAME READY UP-TO-DATE AVAILABLE AGE
external-secrets-operator 1/1 1 1
external-secrets-operator-cert-controller 1/1 1 1
external-secrets-operator-webhook 1/1 1 1
# clustersecretstoreがデプロイされていることを確認する
kubectl get clustersecretstore
NAME AGE
${appName}
# clustersecretstoreのステータスを確認する
kubectl describe clustersecretstore ${appName}
[...]
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Valid cluster-secret-store store validated
11. External Secret の動作確認(CLI)
External Secretをデプロイし、GCP Secret Managerの秘密情報がKubernetes Secretリソースへ連携できていることを確認します。
以下の値の通り、動作確認用のSecret Managerのシークレットを作成します。
- シークレットの名前: qvs-secret-manager
- シークレットの値: Hello, Qmonus Value Stream!
External Secretリソースをデプロイします。以下のサンプルManifestを使用してください。
bash
vim qvs-sample-externalsecret.yaml
yaml
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: example
spec:
refreshInterval: "0"
secretStoreRef:
name: ${appName}
kind: ClusterSecretStore
target:
name: qvs-kubernetes-secret
creationPolicy: Owner
data:
- secretKey: greeting
remoteRef:
key: qvs-secret-manager
version: "1"
bash
# External SecretをDefault namespaceにApplyする
kubectl apply -f qvs-sample-externalsecret.yaml
# External SecretのStatusを確認する
kubectl get externalsecret.external-secrets.io/example
NAME STORE REFRESH INTERVAL STATUS
example ${appName} 0 SecretSynced
# Secretに値が連携できているかを確認する
kubectl get secrets qvs-kubernetes-secret -o json | jq -r .data.greeting | base64 --decode
Hello, Qmonus Value Stream!