[Kubbernetes] External Secrets Operator 시작

이거 뭐야?


Kubbernetes External Secrets(KES)가 유지보수 기간(새로운 기능의 추가 등에 대응할 수 없음)으로 이전하는 방송(이하 ISSUE)을 발표했기 때문에 External Secrets Operator(ESO)로 이전하기 위한 조사를 총괄했다.
*KES도 ESO로 이전을 권고한 바 있어 이번에는 다른 시크릿 관리 도구는 검토하지 않고 ESO에 대해서만 조사했다.
https://github.com/external-secrets/kubernetes-external-secrets/issues/864

External Secrets Operator란


ESO는 AWS 등 외부provider에 저장된 기밀 정보를 얻기 위해 Kubernetes의 시크릿 자원으로 사용되는 CRD입니다.
KES보다 문서의 충실도와 설정의 유연성이 좋다.그나저나 KES는 자바스크립트로, ESO는 골랑이다.
https://github.com/external-secrets/external-secrets
2021년 12월의 각종 외부provider의 유지보수 상황은 다음과 같다.
기본적으로 알파 버전이기 때문에 사용할 때 업데이트할 때의 파괴적 업데이트에 각별히 주의해야 한다(Kubbernetes의 생태계에서 알파 버전의 사용은 방법이 없다.)
Provider
Stability
maintenance
AWS Secrets Manager
alpha
Internally maintained
AWS Parameter Store
alpha
Internally maintained
Hashicorp Vault
stable
Internally maintained
Google Cloud Secrets Manager
alpha
Internally maintained
Azure Key Vault
alpha
Community maintained
IBM Cloud Secrets Manager
alpha
Community maintained
Yandex Lockbox
stable
Community maintained
Gitlab Project Variables
alpha
Community maintained
Alibaba Cloud KMS
alpha
Community maintained
Oracle Vault
alpha
Community maintained
Akeyless
alpha
Community maintained

생태계


ESO는 CRDSecretStore(또는 ClusterSecretStoreExternalSecret를 사용하여 외부provider로부터 기밀 정보를 얻습니다.SecretStore(orClusterSecretStore는 외부provider를 인증하고 ExternalSecret참조하고자 하는 기밀 정보를 지정한다.
KES에서는 다음과 같이 준비ExternalSecret됐으면 좋겠다는 점에서 디자인 마인드가 다르고 ESO의 역할(인증과 자원 지정)은 CRD로 분리된 형태로 이뤄졌다.
# KESではこれだけ定義すればよかった
apiVersion: 'kubernetes-client.io/v1'
kind: ExternalSecret
metadata:
  name: hoge-secret
spec:
  backendType: systemManager
  roleArn: IAM_ROLE_ARN
  data:
  - name: name
    key: key
ESO의 각 자원의 역할은 다음과 같다External Secrets Operator API Overview.

AWS의 Parameter Store 등을 사용하는 경우 다음과 같은 인상External Secrets Operator AWS Parameter Store에서 차용).

SecretStore


Secret Store는 원하는 리소스에 액세스하는 방법(provider의 인증 방식)을 정의합니다.
AWS의 Parameter Store에 액세스하려면 다음과 같은 설정이 필요합니다.
인증은 IFRS A를 사용할 수 있기 때문에 기본적으로 KES에서 사용하는 자원을 직접 전용할 수 있다.
apiVersion: external-secrets.io/v1alpha1
kind: SecretStore
metadata:
  name: secretstore-sample
spec:
  # 機密情報を保管しているproviderに対する設定を記載する
  provider:
    aws:
      # `ParameterStore` or `SecretsManager` が指定可能
      service: ParameterStore
      # Parameter Storeに対してアクセス時にAssumeRoleするためのIAM Role。
      # IRSAを経由して認証する場合には
      # IRSAのIAM Roleに必要な権限を指定することでこちらは無指定でも良さそう?(要検証)
      role: iam-role
      region: ap-northeast-1
      # AWSに対する認証を行うためのリソースを指定する
      auth:
       # IRSAを経由して認証する場合にはこれを使う
        jwt:
          serviceAccountRef:
            name: my-serviceaccount
       # Access Key ID, Secret Access Keyを経由して認証する場合にはこれを使う
        secretRef:
          accessKeyIDSecretRef:
            name: awssm-secret
            key: access-key
          secretAccessKeySecretRef:
            name: awssm-secret
            key: secret-access-key

---
# ServiceAccount経由での認証の場合にはServiceAccountを作成
 apiVersion: v1
 kind: ServiceAccount
 metadata:
   annotations:
     # IAM Role側で `ssm:GetParameter` などの権限を付与しておくと良さそう
     eks.amazonaws.com/role-arn: <IAM_ROLE_ARN>
   name: my-serviceaccount
   namespace: xxxxx

ExternalSecret


가져오려는 리소스를 정의하여 Kubernetes의 Secret 리소스로 기밀 정보를 저장합니다.
External Secret은 다음 시기에 데이터 업데이트를 진행합니다(Secret Store에 문의하여 기밀 정보를 얻고 차이가 있으면 업데이트).

  • 지정된 경우.spec.refreshInterval
  • .metadata.labels 또는 .metadata.annotations 차이가 있는 경우
  • .spec차이가 있는 경우
  • AWS의 Parameter Store에 액세스하려면 다음과 같은 설정이 필요합니다.
    apiVersion: external-secrets.io/v1alpha1
    kind: ExternalSecret
    metadata:
      name: example
      # `labels` と `annotations` は作成されるSecretにも引き継がれる
      labels:
        acme.org/owned-by: "q-team"
      annotations:
        foo: bar
    spec:
      # 外部providerに対してデータ参照を行いSecretの値を更新する頻度
      refreshInterval: 1h
      # 該当データをどのように取得するかを定義したSecretStoreを指定する
      secretStoreRef:
        name: secretstore-sample
        kind: SecretStore
      # ExternalSecretから作成される `kind: Secret` リソースの情報を定義する
      # ExternalSecretにつき1つだけ定義できる
      target:
        # `kind: Secret` として作成されたリソースの名前であり、無指定の場合には `.metadata.name` が指定される。
        name: secret-to-be-created
        # `Owner`, `Merge`, `None` から指定する。デフォルトは `Owner`
        # `Owner` は Secretリソースを作成し、 `.metadata.ownerReferences` をセットする。
        # `Merge` は Secretリソースを作成しないが `.spec.data` の値をSecretリソースに反映させる
        # `None` は Secretリソースを作成しない(将来的にはinjectorとして利用可能になる想定)
        creationPolicy: Owner
      # key/valueで何のデータがほしいかを明示的に指定する
      data:
      - secretKey: secret-key-to-be-managed
        remoteRef:
          # parameter storeの場合にはpathを指定
          key: provider-key
      # 指定したものを一括で取得することもできる
      dataFrom:
      - key: remote-key-in-the-provider
    

    Helm Chart


    ESO의 Helm Chart는 아래 공개(ESO의 GiitHub의 루트에서 charts 시스템의 디렉터리를 찾지 못했기 때문에 아래를 보면 비교적 빠를 것이다).
    https://artifacthub.io/packages/helm/external-secrets-operator/external-secrets
    설정값이 KES와 같은 것이 많기 때문에 KES가 활용하는 것(Service Acount 등)이 어느 정도 이곳으로 바로 옮겨갈 수 있는 분위기가 있다.

    기타

    External Secrets 프로젝트를 보면 KES에서 ESO로 마이그레이션한 Repository가 있습니다.아직 개발 중이라 앞으로의 발전을 기대합니다.
    https://github.com/external-secrets/kes-to-eso

    총결산


    저한테는 도서관을 처음 갈아타는 거라 전전긍긍했는데 찾아보니 ESO의 학습 비용과 자원 재제작이 생각보다 적은 것 같아 안심이 됐어요(대부분의 프로젝트가 똑같은 것도 영향을 미친다고 생각해요).
    여러분도 좋은 Kubernetes 생활 하세요!

    참고 자료


    ESO 공식 문서
    https://external-secrets.io/

    좋은 웹페이지 즐겨찾기