通常、k8sでsecrets.yamlファイルを定義した場合、Secretのvalueはbase64で、エンコードされるだけで、エンコードされた文字列を知れば、簡単にデコードできてしまう問題がある。エンコード前のvalueを知られない様にするにはどうすればよいか?という問題にぶち当たる。
kubernetes Secrets管理でsealed-secrets
を利用したシークレット管理についてキャッチアップした内容と手順をまとめておこうと思います。
sealed-secrets
Sealed Secretsでは一言で言うと、SealedSecrets自体をDeployした時に、得られる秘密鍵(と公開鍵)のペアを使用して、シークレット情報を暗号化します。
より具体的な説明。
また、Secret関連だと、AWEのパラメータストアに格納した、Secretを使用したいといった場合ですとExternal-Secret-Operatorなどを使ったりもします。
今回は、AlgoCDとsealed-secretを組み合わせたシークレット管理ハンズオンをしてみたいと思います。
下記で使用したハンズオンのリポジトリ
今回構築する構成
ArgoCDでGithub-repositoryとgit-syncさせて、argoCD管理下でkubernetesリソースを管理するものとする
secretの暗号化は、sealed-secretsをdeployした時に作成される、秘密鍵からローカルに公開鍵を落として行うやり方がありますが、key管理嫌なので、keyを作成せずにそのままkubeseal
コマンドで、.envファイルをEncriptionします。
実行手順
minikube start
minikube start
ArgoCDをDeploy
get-startedでDeploy
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
ArgoCDとGithubをsync
Argocdのdashboardに入るためにシークレットを取得
kubectl get secret argocd-initial-admin-secret -n argocd -o jsonpath={'.data.password'} | base64 -d
ArgocdのDashBoardにアクセスするために、port-forwardでlocalhost:8080
にアクセス可能へ
kubectl port-forward svc/argocd-server -n argocd 8080:443
DashBoardへログイン(IDはadmin)してリポジトリをgit-Syncさせる
ArgoCD準備完了
helmからsealed-secretsのChartをローカルに落とす
helmのrepoにAddする
使用するhelmのChart
helm repo add sealed-secrets https://bitnami-labs.github.io/sealed-secrets
helmのsealed-secretsコードをローカルにpull
格納したのは、algocd-sealed-secrets-template/services/sealed-secrets
に配置する。
pullしてきたときに、圧縮されてるので、解凍をして上げる。
helm pull sealed-secrets/sealed-secrets
ちなみにhelmをローカルに落とすのが手こずったので記事化しました。
pullできたらgithubにpushする。
Argocd application定義してArgoCDにApply
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: sealed-secrets
namespace: argocd
spec:
project: default
source:
repoURL: git@github.com:magisystem0408/algocd-sealed-secrets-template.git #repositoryのUR
targetRevision: main #syncさせるbranch指定
path: services/sealed-secrets/sealed-secrets/ #syncさせるディレクトリ指定
helm: #helmモードで読み込む合図
valueFiles:
- values.yaml
destination:
server: https://kubernetes.default.svc
namespace: sealed-secrets #どこのNamespaceにDeployするかを指定
# Sync policy
syncPolicy:
automated: # automated sync by default retries failed attempts 5 times with following delays between attempts ( 5s, 10s, 20s, 40s, 80s ); retry controlled using `retry` field.
prune: true # Specifies if resources should be pruned during auto-syncing ( false by default ).
selfHeal: true # Specifies if partial app sync should be executed when resources are changed only in target Kubernetes cluster and no git change detected ( false by default ).
syncOptions: # Sync options which modifies sync behavior
- Validate=true # disables resource validation (equivalent to 'kubectl apply --validate=true')
- CreateNamespace=true # Namespace Auto-Creation ensures that namespace specified as the application destination exists in the destination cluster.
retry:
limit: 5 less than 0
backoff:
duration: 5s # the amount to back off. Default unit is seconds, but could also be a duration (e.g. "2m", "1h")
factor: 2 # a factor to multiply the base duration after each failed retry
maxDuration: 3m # the maximum amount of time allowed for the backoff strategy
Argocdにapplyする。
kubectl apply -f sealed-secrets.yaml -n argocd
展開完了。
sealed-secretsでsecretをEncreptionする。
kubesealをinstall
brew install kubeseal
secretを生成
今回は.env
に以下の変数を格納する。
NEKO=mamushi
pemファイルをローカルに落として、そのpemファイルを元にEncryptionすることも可能だが、以下コマンドで、
ローカルに落とさないでEncryptionできる。/services/sample-app
配下でencryptionして、secret.yamlにする。注意として、-n sample-appで使用する、namespaceを指定してないと正しく、kubernetesに載せたときにエンコードができないので注意
kubeclt create secret generic secret --dry-run=client -n sample-app --from-env-file=.env -o json | kubeseal --controller-name=sealed-secrets --controller-namespace=sealed-secrets --format yaml > secret.yaml
実際に生成されたファイル
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
creationTimestamp: null
name: secret
namespace: sample-app
spec:
encryptedData: #encriptionされたデータ
NEKO: AgCrMWeBt3z2341++ylBJ2NnRx9PqbIolhLlhSKw/0d6qzgC5RlGiTm43cMbeBo/xyXAIy+ytK8h5lTdFKhuUczNrxEpiX6f+Sy01dDUuL9k2nco5WIcX3ynIZR8bgwFboh+PQMOB5Rlg4sxyngDYkqcjSkGQnjRgjjFdeQuKyY96I0QEM6g373RI3TvFRGoX6hMiXobp3GnDgGKc9ww8adjuYNQ3dhQaIx8skeF67k2/Bx/Olf+3diUU3mldr7vcskWBcygppOUAz+cb7uNvjznY+ePKNZ1ThKkxGFo16l7CpKfN4Ob89N5CtE1FkBTpNtWEV0v1wh+KBCKuZ1+UTWnmddXOaZE3icF7pLVyKGCB7NgKaI5NSHr3Pl5ZFpBBOtiUb4Eteeu57mAHfDkM2DMjrZQoBsSHpehBbaR+6C17/pGpavSNPDELbH12juzeVoUkYD8Zx6luJZIEBHcrNU/4+LXr/5BHQGayu6kKtWkUvkmoOdtiYpuPKIg0mZ+aTFzjkqoRAUjXXIzipU0yhkwjlGj4Z5vfvxyjyIMUFnvUQ5WD+yQg6V10/aBNyCXvunoP9pgGSuQfZwhTt7KNfVhCjnAx+gNY8De9+i7fK7wlYg7TPkmq2DwNuyuwINEQ+N9A9Emd8fvzHEGB4tpOVF8c1SoWKvTLvv3qqI5m+RZ2YYrGplGVOj0bf+ITxZcjqjfaJBp3n5I
template:
metadata:
creationTimestamp: null
name: secret
namespace: sample-app
実際にencordしても見ることはできない。
deploymentにsecretを生成したものを指定してgithubに上げてArgoCDにapply
secretをDeploymentにInjectしてあげる。
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: nginx
name: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
strategy: {}
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx
name: nginx
envFrom:
- secretRef: #ここでいつものように指定してあげる。
name: secret
optional: true
ArgoCDに読み込ませる様のmanifestsを定義
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: sample-app
namespace: argocd
spec:
project: default
source:
repoURL: git@github.com:magisystem0408/algocd-sealed-secrets-template.git
targetRevision: main
path: services/sample-app/
destination:
server: https://kubernetes.default.svc
namespace: sample-app
# Sync policy
syncPolicy:
automated: # automated sync by default retries failed attempts 5 times with following delays between attempts ( 5s, 10s, 20s, 40s, 80s ); retry controlled using `retry` field.
prune: true # Specifies if resources should be pruned during auto-syncing ( false by default ).
selfHeal: true # Specifies if partial app sync should be executed when resources are changed only in target Kubernetes cluster and no git change detected ( false by default ).
syncOptions: # Sync options which modifies sync behavior
- Validate=true # disables resource validation (equivalent to 'kubectl apply --validate=true')
- CreateNamespace=true # Namespace Auto-Creation ensures that namespace specified as the application destination exists in the destination cluster.
# The retry feature is available since v1.7
retry:
limit: 5 # number of failed sync attempt retries; unlimited number of attempts if less than 0
backoff:
duration: 5s # the amount to back off. Default unit is seconds, but could also be a duration (e.g. "2m", "1h")
factor: 2 # a factor to multiply the base duration after each failed retry
maxDuration: 3m # the maximum amount of time allowed for the backoff strategy
kubectl apply -f sample-app.yaml
ArgoCDのダッシュボードでsecretとdeploymentがapplyされているかを確認
試しにDeploymentが生成したpodの中に入って、secretがエンクリプトされているかをチェックする
podを取得
kubectl get pod -n sample-app
環境変数一覧出力
kubectl exec -it <pod名> -n sample-app -- env
DONE!
実際には、.envファイルなどはgithubに上げずに、kubesealでencryptionしたもののみをgithubに上げれば、良いです。
参考文献