Appearance
External Secrets Operatorの導入 Azure編
本章では、Qmonus Value Streamの応用として、Official Cloud Native AdapterであるExternal Secrets Operator AdapterとAKS Cluster Secret Store Adapterを使用して、AzureのKey Vault(キーコンテナ)の秘密情報をAKSの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をAKSへデプロイし、Azure Key VaultがAKSのSecretリソースへ同期できる環境を提供します。
以下のプライベートリポジトリが作成されていることを前提とします。
- 持ち込みのGitリポジトリ
- GitHub、GitLabなどのインターネットからアクセス可能なGitリポジトリをご用意ください。
- 本チュートリアルではGitHubを使って説明しますが、適宜ご利用されているサービスに読み替えてください。
- GitHubリポジトリへの認証は Personal Access Token (GitLabの場合は Personal access tokens)を使用することを前提とします。
以降のステップでは主に下記の作業を通じて、External SecretリソースにAzure Key Vaultの秘密情報が連携されていることを確認します。
- External Secrets Operator AdapterとAKS Cluster Secret Store AdapterをQmonus Values Streamでデプロイする
- Azure Key Vault内のキーコンテナへ機密情報を登録し、サンプルExternal SecretリソースをApplyして自動作成されるSecretリソースに秘密情報が連携されていることを確認する
0-1. 準備:External Secrets OperatorのCustom Resource Definition の適用
External Secrets OperatorのCustom Resource Definitionから、v0.5.0
以上の任意のバージョンを指定してAKSに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の構成
Azure Workload Identityを使用することで、Key Vaultへのアクセス権限を持つMicrosoft Entra External ID アプリケーションの権限をAKSのService Accountへ付与することが可能になります。これにより、ワークロードがAzureリソースにアクセス出来るようになります。
コマンド例を以下に記しますので、それらを参考にAzure Workload Identityを設定してください。ただし、詳細はAzureのドキュメントを参照してください。
事前準備として下記のツールのインストールを行ってください。また、インストールしてある場合でも最新版へアップデートを行ってください。
Tool Guide Azure CLI (azcli) install aks-preview install Entra ID Workload CLI (azwi) install AKSクラスタのEnableOIDCIssuerPreview 機能 の有効化とOIDC issuer URLを取得します。
- azコマンドを用いてEnableOIDCIssuerPreview機能を有効化するbash
# azコマンド例 # 初めてazコマンドを実施する場合は下記コマンドを実施ください # tenant_idはonmicrosoft.comで終わるAzureドメイン名です az login --tenant ${tenant_id} # EnableOIDCIssuerPreview 機能を登録する az feature register --name EnableOIDCIssuerPreview --namespace Microsoft.ContainerService # StateがRegisteredになることをaz feature listコマンドを利用して確認します(登録までに時間がかかる場合があります) az feature list -o table --query "[?contains(name, 'Microsoft.ContainerService/EnableOIDCIssuerPreview')].{Name:name,State:properties.state}" # StateがRegisteredとなったらMicrosoft.ContainerService リソースプロバイダの登録を更新します az provider register --namespace Microsoft.ContainerService
- OIDC issuer URLを取得する 下記コマンドを実行しOIDC issuer URLを取得します。
${k8sClusterName}
はAKSクラスタ名、${myResourceGroup}
はAKSクラスタが所属するリソースグループに読み替えてくださいbash出力されたhttpsから始まるURLは今後の手順で使用するため控えておいてください。# azコマンド例 # AKSクラスタへ OIDC issuer を有効化 az aks update -n ${k8sClusterName} -g ${myResourceGroup} --enable-oidc-issuer # OIDC issuer URLを表示 az aks show -n ${k8sClusterName} -g ${myResourceGroup} --query "oidcIssuerProfile.issuerUrl" -otsv
- azコマンドを用いてEnableOIDCIssuerPreview機能を有効化する
Microsoft Entra External ID のアプリケーション(以下、AADアプリケーション)を作成し、Azure Key Vaultへの権限を付与します。
- Azureポータルからキーコンテナーの画面へアクセスし、キーコンテナーを作成します。 詳細はAzure Key Vaultのクイックスタートより、ご確認ください。
- AADアプリケーションを作成します。
${applicationName}
は、登録するアプリケーションの名前です。bash上記コマンドを実行すると下記のように出力されますazwi serviceaccount create phase app --aad-application-name ${applicationName}
bashINFO[0000] No subscription provided, using selected subscription from Azure CLI: REDACTED INFO[0005] [aad-application] created an AAD application clientID=REDACTED name=${applicationName} objectID=REDACTED WARN[0005] --service-principal-name not specified, falling back to AAD application name INFO[0005] [aad-application] created service principal clientID=REDACTED name=${applicationName} objectID=REDACTED
- 作成したAADアプリケーションへKey Vaultへのアクセス権限を付与します。
${azureKeyContainerName}
は作成したキーコンテナ名となります。bash# AADアプリケーションのクライアントIDを取得します export applicationCliendId="$(az ad sp list --display-name ${applicationName} --query '[0].appId' -otsv)" # AADアプリケーションへKey Vaultへのアクセス権限を付与します az keyvault set-policy --name ${azureKeyContainerName} --secret-permissions get --spn ${applicationCliendId}
Kubernetes Service Account(以下、KSA)を作成し、Entra ID Workload Identityを使用してAzure Key Vaultへのアクセス権限を付与します。
- Namespaceを作成し、そのNamespace配下へKSAを作成します。
${ksaName}
はKSA名、${ksaNamespace}
はKSAが属するnamespaceとしてください。 default値を使用する場合は、それぞれ"azure-key-vault", "qmonus-system"として指定してください。bash# Namespaceを作成する kubectl create ns ${ksaNamespace} # KSAを作成する azwi serviceaccount create phase sa --aad-application-name ${applicationName} --service-account-namespace ${ksaNamespace} --service-account-name ${ksaName}
- 作成したKSAとKey Vaultへの権限を持つAADアプリケーション間で認証する 下記コマンドを実行することで認証します。ここで
${oidcIssuerUrl}
は手順0-2の2.で取得したOIDC issuer URLを記載してください。bashazwi serviceaccount create phase federated-identity --aad-application-name ${applicationName} --service-account-name ${ksaName} --service-account-namespace ${ksaNamespace} --service-account-issuer-url ${oidcIssuerUrl}
ここで使用したパラメータのうちadapterで使用するパラメータの詳細は以下の通りです。特に変更する必要がなければ、default値のあるものはdefault値を使用することを推奨します。また、このパラメータは手順5で再度使用します。
Parameter Name Default Description azureKeyContainerName - Azure キーコンテナ名 ksaName azure-key-vault KSA名 ksaNamespace qmonus-system KSAが存在するnamespace - Namespaceを作成し、そのNamespace配下へKSAを作成します。
1. Kubeconfigの作成 (CLI)
Qmonus Value Streamは、Kubeconfigと呼ばれる認証ファイルを利用してKubernetesへアプリケーションをデプロイします。 ここでは、クラスタ・スコープのKubeconfigを生成します。
以下の手順にしたがって、Kubernetesクラスタにアクセスし、External Secrets Operator AdapterとAKS Cluster Secret Store Adapter によって定義されるリソースをデプロイするためのNamespaceを作成し、Kubeconfigを生成してください。Namespaceは、default値を使用するのであればqmonus-system
となります。 ここで、${cluster_name}
はKubernetesクラスタ名、${cluster_name}
はAzure Resource Group名を指定します。
bash
# 利用するKubernetesへ接続
az aks get-credentials --admin --name ${cluster_name} --resource-group ${resource_group}
# 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は権限が非常に強力なため、お取り扱いには注意してください。
なお、azコマンドをはじめて実行する場合は、以下の手順によりazコマンドを初期化してください。ここで、${tenant_id}
はonmicrosoft.comで終わるAzureドメイン名です。
bash
az login --tenant ${tenant_id}
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とAKS 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: azureKeyContainerName
type: string
- name: ksaName
type: string
- name: ksaNamespace
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/aks/clustersecretstore
params:
appName: $(params.appName)
azureKeyContainerName: $(params.azureKeyContainerName)
ksaName: $(params.ksaName)
ksaNamespace: $(params.ksaNamespace)
- 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}
azureKeyContainerName: ${azureKeyContainerName}
ksaName: ${ksaName}
appName: ${appName}
ksaNamespace: ${ksaNamespace}
ここで、パラメータは以下の通りです。 External Secrets Operator Adapter:
${version}
: 手順0-1で指定したExternal Secrets OperatorのCRDのバージョン (0.5.0
など"v"を除いた状態で指定してください)${esoNamespace}
: 手順1で作成した${esoNamespace}
AKS Cluster Secret Store Adapter:
${azureKeyContainerName}
: 手順0-2で作成したキーコンテナ名${ksaName}
: 手順0-2で指定したKSA${ksaNamespace}
: 手順0-2で作成した${ksaNamespace}
${appName}
: Cluster Secret Storeのリソース名を指定。今回はazure-key-vault
とDeployment Configに記載してください
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をデプロイし、キーコンテナの秘密情報がKubernetes Secretリソースへ連携できていることを確認します。
以下の値の通り、動作確認用のキーコンテナのシークレットを作成します。
- シークレットの名前: qvs-secret-manager
- シークレットの値: Hello, Qmonus Value Stream! Azureポータル、もしくは下記のコマンドでシークレットを作成して下さい。
bash
az keyvault secret set --vault-name ${azureKeyContainerName} --name "qvs-secret-manager" --value "Hello, Qmonus Value Stream!"
上記コマンドを実行した際、下記のようにjsonの形で出力されます。 ここでの出力結果からid列の末尾${keyVersion}
と記載している部分にバージョンが記載されます。この値はSecretを取得する際に扱うため記録してください。 AzureポータルからSecretを作成した場合は、作成したSecretをクリックし"現在のバージョン"と記載されている文字列を記録してください。
json
{
"attributes": {
"created": "YYYY-MM-DDTHH:MM:SS+00:00",
"enabled": true,
"expires": null,
"notBefore": null,
"recoveryLevel": "Recoverable+Purgeable",
"updated": "YYYY-MM-DDTHH:MM:SS+00:00"
},
"contentType": null,
"id": "https://${azureKeyContainerName}.vault.azure.net/secrets/qvs-secret-manager/${keyVersion}",
"kid": null,
"managed": null,
"name": "qvs-secret-manager",
"tags": {
"file-encoding": "utf-8"
},
"value": "Hello, Qmonus Value Stream!"
}
External Secretリソースをデプロイします。以下のサンプルManifestを使用してください。
bash
vim qvs-sample-externalsecret.yaml
なお${keyVersion}
はバージョンを登録したさいのバージョンの値を記載してください。 また、Versionについては省略も可能です。省略した場合は最新のバージョンが取得できます。
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: "${keyVersion}"
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!