Hashicorp Vault์—์„œ Cassandra ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด ์ˆœํ™˜

๊ฐœ์š”

์ด ์ ˆ์ฐจ์—์„œ๋Š” Hashicorp Vault ๋‚ด์—์„œ Cassandra ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด๋ฅผ ์ˆœํ™˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. ํด๋Ÿฌ์Šคํ„ฐ์˜ Kubernetes ๋ณด์•ˆ ๋น„๋ฐ€์—์„œ ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด๋ฅผ ์ˆœํ™˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ Kubernetes ๋ณด์•ˆ ๋น„๋ฐ€์—์„œ Cassandra ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด ์ˆœํ™˜์„ ์ฐธ์กฐํ•˜์„ธ์š”.

์ด ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋ฉด ํ”Œ๋žซํผ ๊ด€๋ฆฌ์ž๊ฐ€ ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • Hashicorp Vault์—์„œ Cassandra ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด๋ฅผ ์ˆœํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  • ๋น„๋ฐ€๋ฒˆํ˜ธ ์ˆœํ™˜ ์ค‘ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด Vault์— ์žˆ๋Š” ์ด์ „ Cassandra ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด๋กœ ๋กค๋ฐฑํ•ฉ๋‹ˆ๋‹ค.
  • ํ•œ ๋ฒˆ์— ํ•˜๋‚˜์˜ ๋ฆฌ์ „์— ๋Œ€ํ•ด Cassandra ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ˆœํ™˜ํ•˜์—ฌ ์„œ๋น„์Šค ๊ฐ€์šฉ์„ฑ์— ๋Œ€ํ•œ ์˜ํ–ฅ์„ ์ตœ์†Œํ™”ํ•˜๊ณ  ์ˆœํ™˜ ํ”„๋กœ์„ธ์Šค๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋‹จ์ผ ๋ฆฌ์ „์˜ ์ˆœํ™˜ ์‹œ์ž‘, ์ง„ํ–‰๋ฅ  ๋ฐ ์™„๋ฃŒ๋ฅผ ์ถ”์ ํ•ฉ๋‹ˆ๋‹ค.

์ด ๊ธฐ๋Šฅ์€ Apigee Hybrid 1.13.1 ์ด์ƒ์—์„œ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค.

์‹œ์ž‘ํ•˜๊ธฐ ์ „์—

์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด ์ˆœํ™˜์„ ์„ค์ •ํ•˜๊ธฐ ์ „

  • Cassandra ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๋ฐฑ์—…ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฐฑ์—…์€ ์ˆœํ™˜ ์ „ ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด๋ฅผ ๋ณต์›ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๊ธฐ ์œ„ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
  • ํด๋Ÿฌ์Šคํ„ฐ๊ฐ€ ์ •์ƒ ์ƒํƒœ์ธ์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค(์ฆ‰, ๋ชจ๋“  Apigee ๋ฆฌ์†Œ์Šค๊ฐ€ ์‹คํ–‰ ์ค‘์ด๊ณ  ๋Œ€๊ธฐ ์ค‘์ธ ์ƒํƒœ ๋ณ€๊ฒฝ์‚ฌํ•ญ์ด ์—†์Œ).

๋‹จ์ผ ๋ฆฌ์ „ ์„ค์ •

  1. ์ƒˆ Cassandra ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด์— ๋Œ€ํ•ด Apigee ๋„ค์ž„์ŠคํŽ˜์ด์Šค์— ์ƒˆ๋กœ์šด SecretProviderClass Kubernetes ๋ฆฌ์†Œ์Šค๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์‚ฌ์šฉํ•  ํ…œํ”Œ๋ฆฟ์€ Hashicorp Vault์— Cassandra ๋ณด์•ˆ ๋น„๋ฐ€ ์ €์žฅ์„ ์ฐธ์กฐํ•˜์„ธ์š”. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด Vault ์—ญํ• ์ด Kubernetes ๋„ค์ž„์ŠคํŽ˜์ด์Šค ๋‚ด์˜ ๋ณด์•ˆ ๋น„๋ฐ€์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  2. ๋‹ค์Œ ํ…œํ”Œ๋ฆฟ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ƒˆ SecretRotation ์ปค์Šคํ…€ ๋ฆฌ์†Œ์Šค๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
    # rotation.yaml
    
    apiVersion: apigee.cloud.google.com/v1alpha1
    kind: SecretRotation
    metadata:
      name: ROTATION_PROCESS_NAME
      namespace: APIGEE_NAMESPACE
    spec:
      organizationId: ORG_NAME
      rotationId: ROTATION_ID
      timeoutMinutes: 480 # optional. overrides the default (480m == 8hr).
                          # less than or equal to 0 means infinite timeout.
      precheck: true
      cassandra:
        oldSecretProviderClass: OLD_SPC_NAME
        newSecretProviderClass: NEW_SPC_NAME
        jobType: ROTATE
    
    • ROTATION_PROCESS_NAME: ์ˆœํ™˜ ์ž‘์—…์˜ ๊ณ ์œ  ์ด๋ฆ„์ž…๋‹ˆ๋‹ค. ์ˆœํ™˜ ์‚ฌ์ „ ํ™•์ธ ์ž‘์—… ๋ฐ ์ˆœํ™˜ ์ž‘์—…์— ๋Œ€ํ•ด metadata.name์„ ๊ณ ์œ ํ•œ ๊ฐ’์œผ๋กœ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด sr-1-precheck ๋‹ค์Œ์— sr-1๊ณผ ๊ฐ™์ด ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ROTATION_ID: spec.rotationId๋ฅผ ์ปค์Šคํ…€ ์‹๋ณ„์ž(์˜ˆ: rotation-1-precheck)๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
    • NEW_SPC_NAME: spec.cassandra.newSecretProviderClass๋ฅผ ์ด์ „ ๋‹จ๊ณ„์—์„œ ๋งŒ๋“  ์ƒˆ๋กœ์šด ๋ณด์•ˆ ๋น„๋ฐ€ ์ œ๊ณต์ž ํด๋ž˜์Šค ์ด๋ฆ„์œผ๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
    • OLD_SPC_NAME: spec.cassandra.oldSecretProviderClass๋ฅผ ApigeeDatastore์—์„œ ํ˜„์žฌ ์‚ฌ์šฉ ์ค‘์ธ SPC ์ด๋ฆ„์œผ๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
  3. rotation.yaml ํŒŒ์ผ์„ ์ ์šฉํ•˜์—ฌ ์ˆœํ™˜ ์‚ฌ์ „ ํ™•์ธ ์ž‘์—…์„ ํŠธ๋ฆฌ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.
    kubectl -n APIGEE_NAMESPACE apply -f rotation.yaml
  4. ์‚ฌ์ „ ํ™•์ธ ์ž‘์—…์ด ์™„๋ฃŒ๋˜์—ˆ์„ ๋•Œ ํ™•์ธํ•  ์ž‘์—… ์ƒํƒœ๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
    kubectl -n APIGEE_NAMESPACE get job sr-(rotationId)-(rotate|rollback|cleanup)-job
  5. ์ˆœํ™˜ ์‚ฌ์ „ ํ™•์ธ ์ž‘์—…์ด ์™„๋ฃŒ๋˜๋ฉด metadata.name ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜๊ณ  spec.precheck๋ฅผ false๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ํŒŒ์ผ์„ ๋‹ค์‹œ ์ ์šฉํ•˜์—ฌ ์ˆœํ™˜์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
    kubectl -n APIGEE_NAMESPACE apply -f rotation.yaml
  6. ์ˆœํ™˜ ์ž‘์—…์ด ์™„๋ฃŒ๋˜๊ณ  ํŠธ๋ž˜ํ”ฝ์ด ๊ณ„์† ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์ธ๋˜์—ˆ์œผ๋ฉด ๋‹ค์Œ ๋‘ ๋‹จ๊ณ„์— ๋”ฐ๋ผ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ •๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
    1. metadata.name์˜ ๊ฐ’์„ ์—…๋ฐ์ดํŠธํ•˜๊ณ  spec.cassandra.jobType์„ CLEANUP์œผ๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
    2. ํŒŒ์ผ์„ ์ ์šฉํ•˜์—ฌ ์ •๋ฆฌ ์ž‘์—…์„ ํŠธ๋ฆฌ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.
      kubectl -n APIGEE_NAMESPACE apply -f rotation.yaml

    ์ •๋ฆฌ ์ž‘์—…์ด ๋๋‚˜๋ฉด ์ˆœํ™˜ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์™„๋ฃŒ๋ฉ๋‹ˆ๋‹ค.

  7. ์žฌ์ •์˜ ํŒŒ์ผ์„ ์—…๋ฐ์ดํŠธํ•˜๊ณ  cassandra.auth.secretProviderClass๋ฅผ ์ƒˆ ๋ณด์•ˆ ๋น„๋ฐ€ ์ œ๊ณต์ž ํด๋ž˜์Šค(newSecretProviderClass)๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
    cassandra:
      auth:
        secretProviderClass: NEW_SPC_NAME
  8. Cassandra ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๋ฐฑ์—…ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฐฑ์—…์€ ์ˆœํ™˜๋œ ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด๋ฅผ ๋ณต์›ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๊ธฐ ์œ„ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
  9. Vault์—์„œ ์ด์ „ Cassandra ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด, ์—ญํ• , ์ •์ฑ…์„ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.

๋ฉ€ํ‹ฐ ๋ฆฌ์ „ ์„ค์ •

๋ฉ€ํ‹ฐ ๋ฆฌ์ „ ์„ค์ • ์ ˆ์ฐจ๋Š” ์ฒซ ๋ฒˆ์งธ ๋ฆฌ์ „ ์„ค์ •๊ณผ ๋‚จ์€ ๋ฆฌ์ „ ์„ค์ •์˜ ๋‘ ์„น์…˜์œผ๋กœ ๊ตฌ๋ถ„๋ฉ๋‹ˆ๋‹ค.

  1. ํ›„์† ๋ฆฌ์ „์„ ์‹œ์ž‘ํ•˜๊ธฐ ์ „์— ์ฒซ ๋ฒˆ์งธ ๋ฆฌ์ „์—์„œ ๋‹ค์Œ ๋‹จ๊ณ„๋ฅผ ์™„๋ฃŒํ•ฉ๋‹ˆ๋‹ค.
    1. ์ƒˆ Cassandra ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด์— ๋Œ€ํ•ด APIGEE_NAMESPACE ๋„ค์ž„์ŠคํŽ˜์ด์Šค์— ์ƒˆ๋กœ์šด SecretProviderClass Kubernetes ๋ฆฌ์†Œ์Šค๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์‚ฌ์šฉํ•  ํ…œํ”Œ๋ฆฟ์€ Hashicorp Vault์— Cassandra ๋ณด์•ˆ ๋น„๋ฐ€ ์ €์žฅ์„ ์ฐธ์กฐํ•˜์„ธ์š”. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด Vault ์—ญํ• ์ด Kubernetes ๋„ค์ž„์ŠคํŽ˜์ด์Šค ๋‚ด์˜ ๋ณด์•ˆ ๋น„๋ฐ€์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    2. ๋‹ค์Œ ํ…œํ”Œ๋ฆฟ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ƒˆ SecretRotation ์ปค์Šคํ…€ ๋ฆฌ์†Œ์Šค๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
      # rotation.yaml
      
      apiVersion: apigee.cloud.google.com/v1alpha1
      kind: SecretRotation
      metadata:
        name: ROTATION_PROCESS_NAME
        namespace: APIGEE_NAMESPACE
      spec:
        organizationId: ORG_NAME
        rotationId: ROTATION_ID
        timeoutMinutes: -1 # this value is required and should not be changed.
        precheck: true
        cassandra:
          oldSecretProviderClass: OLD_SPC_NAME
          newSecretProviderClass: NEW_SPC_NAME
          jobType: ROTATE
      
      • ROTATION_PROCESS_NAME: ์ˆœํ™˜ ์ž‘์—…์˜ ๊ณ ์œ  ์ด๋ฆ„์ž…๋‹ˆ๋‹ค. ์ˆœํ™˜ ์‚ฌ์ „ ํ™•์ธ ์ž‘์—… ๋ฐ ์ˆœํ™˜ ์ž‘์—…์— ๋Œ€ํ•ด metadata.name์„ ๊ณ ์œ ํ•œ ๊ฐ’์œผ๋กœ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด sr-1-precheck ๋‹ค์Œ์— sr-1๊ณผ ๊ฐ™์ด ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
      • ROTATION_ID: spec.rotationId๋ฅผ ์ปค์Šคํ…€ ์‹๋ณ„์ž(์˜ˆ: rotation-1-precheck)๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
      • NEW_SPC_NAME: spec.cassandra.newSecretProviderClass๋ฅผ ์ด์ „ ๋‹จ๊ณ„์—์„œ ๋งŒ๋“  ์ƒˆ๋กœ์šด ๋ณด์•ˆ ๋น„๋ฐ€ ์ œ๊ณต์ž ํด๋ž˜์Šค ์ด๋ฆ„์œผ๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
      • OLD_SPC_NAME: spec.cassandra.oldSecretProviderClass๋ฅผ ApigeeDatastore์—์„œ ํ˜„์žฌ ์‚ฌ์šฉ ์ค‘์ธ SPC ์ด๋ฆ„์œผ๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
    3. rotation.yaml ํŒŒ์ผ์„ ์ ์šฉํ•˜์—ฌ ์ˆœํ™˜ ์‚ฌ์ „ ํ™•์ธ ์ž‘์—…์„ ํŠธ๋ฆฌ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.
      kubectl -n APIGEE_NAMESPACE apply -f rotation.yaml
    4. ์‚ฌ์ „ ํ™•์ธ ์ž‘์—…์ด ์™„๋ฃŒ๋˜์—ˆ์„ ๋•Œ ํ™•์ธํ•  ์ž‘์—… ์ƒํƒœ๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
      kubectl -n APIGEE_NAMESPACE get job sr-(rotationId)-(rotate|rollback|cleanup)-job
    5. ์ˆœํ™˜ ์‚ฌ์ „ ํ™•์ธ ์ž‘์—…์ด ์™„๋ฃŒ๋œ ํ›„ ๋‹ค์Œ ์•ˆ๋‚ด๋ฅผ ๋”ฐ๋ฅด์„ธ์š”.
      • metadata.name ๊ฐ’์„ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค(์˜ˆ: sr-1-precheck์—์„œ sr-1๋กœ).
      • spec.precheck๋ฅผ false๋กœ ์„ค์ •ํ•˜์—ฌ ์‚ฌ์ „ ํ™•์ธ์„ ์‚ฌ์šฉ ์ค‘์ง€ํ•˜๊ณ  ์ˆœํ™˜์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
      • spec.rotationId๋ฅผ ์ƒˆ ์‹๋ณ„์ž๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค(์˜ˆ: rotation-1).
    6. ํŒŒ์ผ์„ ๋‹ค์‹œ ์ ์šฉํ•˜์—ฌ ์ˆœํ™˜์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
      kubectl -n APIGEE_NAMESPACE apply -f rotation.yaml
    7. SecretRotation ์ƒํƒœ๋ฅผ ํ™•์ธํ•˜๊ณ  complete๊ฐ€ ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค.
      kubectl -n APIGEE_NAMESPACE get sr SR_NAME
  2. ์ดํ›„ ๊ฐ ๋ฆฌ์ „์—์„œ ๋‹ค์Œ ๋‹จ๊ณ„๋ฅผ ์™„๋ฃŒํ•ฉ๋‹ˆ๋‹ค.
    1. ์ƒˆ Cassandra ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด์— ๋Œ€ํ•ด Apigee ๋„ค์ž„์ŠคํŽ˜์ด์Šค์— ์ƒˆ๋กœ์šด SecretProviderClass Kubernetes ๋ฆฌ์†Œ์Šค๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์‚ฌ์šฉํ•  ํ…œํ”Œ๋ฆฟ์€ Hashicorp Vault์— Cassandra ๋ณด์•ˆ ๋น„๋ฐ€ ์ €์žฅ์„ ์ฐธ์กฐํ•˜์„ธ์š”. 1a๋‹จ๊ณ„์™€ ๋™์ผํ•œ ์ •์˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    2. overrides.yaml์„ ์—…๋ฐ์ดํŠธํ•˜๊ณ  rotation.yaml ํŒŒ์ผ์˜ spec.cassandra.newSecretProviderClass ๊ฐ’๊ณผ ์ผ์น˜ํ•˜๋„๋ก cassandra.auth.secretProviderClass๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
      cassandra:
        auth:
          secretProviderClass: NEW_SPC_NAME
    3. ์—ฐ์‚ฐ์ž ์ฐจํŠธ๋ฅผ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.
      helm upgrade operator apigee-operator/ \
        --namespace APIGEE_NAMESPACE \
        --atomic \
        -f OVERRIDES_FILE
    4. ์ƒˆ ReplicaSet๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. ์ƒˆ ์ปจํŠธ๋กค๋Ÿฌ ๊ด€๋ฆฌ์ž ํฌ๋“œ๊ฐ€ ์ƒˆ SPC๋ฅผ ์‚ฌ์šฉํ•˜๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
      export POD=NEW_CONTROLLER_MANAGER_POD_NAME
      kubectl -n APIGEE_NAMESPACE get pods $POD -o jsonpath='{.spec.volumes[?(@.name=="apigee-external-secrets")].csi.volumeAttributes.secretProviderClass}'
      

      ๊ฒฐ๊ณผ๋Š” rotation.yaml์—์„œ spec.cassandra.newSecretProviderClass์— ์„ค์ •ํ•œ ๊ฐ’๊ณผ ์ผ์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

      kubectl -n apigee get pods $POD -o jsonpath='{.spec.volumes[?(@.name=="apigee-external-secrets")].csi.volumeAttributes.secretProviderClass}'
      
      my-new-spc
    5. ๋ฐ์ดํ„ฐ ์Šคํ† ์–ด ์ฐจํŠธ๋ฅผ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.
      helm upgrade datastore apigee-datastore/ \
        --namespace APIGEE_NAMESPACE \
        --atomic \
        -f OVERRIDES_FILE
    6. ๋ฐ์ดํ„ฐ ์Šคํ† ์–ด๊ฐ€ ์ถœ์‹œ ์ƒํƒœ๋กœ ์ „ํ™˜๋ฉ๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ ์Šคํ† ์–ด์˜ ์ถœ์‹œ๊ฐ€ ์™„๋ฃŒ๋˜๊ณ  ์‹คํ–‰ ์ƒํƒœ๊ฐ€ ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค.
      kubectl -n APIGEE_NAMESPACE get apigeedatastore DATASTORE_NAME

      ๋Œ€๋ถ€๋ถ„์˜ ์„ค์น˜์—์„œ DATASTORE_NAME์€ default์ž…๋‹ˆ๋‹ค.

    7. ์ƒˆ ๋ฐ์ดํ„ฐ ์Šคํ† ์–ด ํฌ๋“œ์—์„œ ์ƒˆ SPC๋ฅผ ์‚ฌ์šฉํ•˜๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
      export POD=NEW_DATASTORE_POD_NAME
      kubectl -n APIGEE_NAMESPACE get pods $POD -o jsonpath='{.spec.volumes[?(@.name=="apigee-external-secrets")].csi.volumeAttributes.secretProviderClass}'
      

      ๊ฒฐ๊ณผ๋Š” rotation.yaml์—์„œ spec.cassandra.newSecretProviderClass์— ์„ค์ •ํ•œ ๊ฐ’๊ณผ ์ผ์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

      kubectl -n apigee get pods $POD -o jsonpath='{.spec.volumes[?(@.name=="apigee-external-secrets")].csi.volumeAttributes.secretProviderClass}'
      
      my-new-spc
    8. ์กฐ์ง ๋ฐ ํ™˜๊ฒฝ ์ถœ์‹œ๊ฐ€ ์™„๋ฃŒ๋˜๊ณ  ์‹คํ–‰ ์ค‘ ์ƒํƒœ๋กœ ๋Œ์•„๊ฐˆ ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค.
      kubectl -n APIGEE_NAMESPACE get apigeeorg ORG_NAME
      kubectl -n APIGEE_NAMESPACE get apigeeenv ENV_NAME
    9. ์ƒˆ MART, ๋Ÿฐํƒ€์ž„, ๋™๊ธฐํ™”๊ธฐ ํฌ๋“œ๊ฐ€ ์ƒˆ SPC๋ฅผ ์‚ฌ์šฉํ•˜๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
      export POD=NEW_MART_POD_NAME
      kubectl -n APIGEE_NAMESPACE get pods $POD -o jsonpath='{.spec.volumes[?(@.name=="apigee-external-secrets")].csi.volumeAttributes.secretProviderClass}'
      export POD=NEW_RUNTIME_POD_NAME
      kubectl -n APIGEE_NAMESPACE get pods $POD -o jsonpath='{.spec.volumes[?(@.name=="apigee-external-secrets")].csi.volumeAttributes.secretProviderClass}'
      export POD=NEW_SYNCHRONIZER_POD_NAME
      kubectl -n APIGEE_NAMESPACE get pods $POD -o jsonpath='{.spec.volumes[?(@.name=="apigee-external-secrets")].csi.volumeAttributes.secretProviderClass}'
      

      ๊ฒฐ๊ณผ๋Š” rotation.yaml์—์„œ spec.cassandra.newSecretProviderClass์— ์„ค์ •ํ•œ ๊ฐ’๊ณผ ์ผ์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

      kubectl -n apigee get pods $POD -o jsonpath='{.spec.volumes[?(@.name=="apigee-external-secrets")].csi.volumeAttributes.secretProviderClass}'
      
      my-new-spc
  3. ๋ชจ๋“  ๋ฆฌ์ „์˜ ๋‹จ๊ณ„๋ฅผ ์™„๋ฃŒํ•˜๊ณ  ํŠธ๋ž˜ํ”ฝ์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์ธํ•œ ํ›„ ๋‹ค์Œ ๋‘ ๋‹จ๊ณ„์— ๋”ฐ๋ผ ์ฒซ ๋ฒˆ์งธ ๋ฆฌ์ „์—์„œ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ •๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
    1. ์ฒซ ๋ฒˆ์งธ ๋ฆฌ์ „์—์„œ metadata.name ๊ฐ’์„ ์—…๋ฐ์ดํŠธํ•˜๊ณ  spec.cassandra.jobType์„ CLEANUP์œผ๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
    2. ํŒŒ์ผ์„ ์ ์šฉํ•˜์—ฌ ์ •๋ฆฌ ์ž‘์—…์„ ํŠธ๋ฆฌ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.
      kubectl -n APIGEE_NAMESPACE apply -f rotation.yaml
    3. ์ž‘์—… ์ƒํƒœ๋ฅผ ํ™•์ธํ•˜๊ณ  ์ž‘์—… ๋กœ๊ทธ๋ฅผ ํ†ตํ•ด ์ •๋ฆฌ ์ž‘์—…์ด ์™„๋ฃŒ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

    ์ •๋ฆฌ ์ž‘์—…์ด ๋๋‚˜๋ฉด ์ˆœํ™˜ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์™„๋ฃŒ๋ฉ๋‹ˆ๋‹ค.

  4. ์žฌ์ •์˜ ํŒŒ์ผ์„ ์—…๋ฐ์ดํŠธํ•˜๊ณ  cassandra.auth.secretProviderClass๋ฅผ ์ƒˆ ๋ณด์•ˆ ๋น„๋ฐ€ ์ œ๊ณต์ž ํด๋ž˜์Šค(newSecretProviderClass)๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
    cassandra:
      auth:
        secretProviderClass: NEW_SPC_NAME
  5. Cassandra ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๋ฐฑ์—…ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฐฑ์—…์€ ์ˆœํ™˜๋œ ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด๋ฅผ ๋ณต์›ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๊ธฐ ์œ„ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
  6. Vault์—์„œ ์ด์ „ Cassandra ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด, ์—ญํ• , ์ •์ฑ…์„ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.

์ˆœํ™˜ ๋กค๋ฐฑ

๋ฉ€ํ‹ฐ ๋ฆฌ์ „์˜ ๊ฒฝ์šฐ ๊ฐ ๋ฆฌ์ „์—์„œ ๋กค๋ฐฑ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

  1. ๋‹ค์Œ ํ…œํ”Œ๋ฆฟ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ƒˆ SecretRotation ์ปค์Šคํ…€ ๋ฆฌ์†Œ์Šค๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
    # rollback-rotation.yaml
    
    apiVersion: apigee.cloud.google.com/v1alpha1
    kind: SecretRotation
    metadata:
      name: ROLLBACK_NAME
      namespace: APIGEE_NAMESPACE
    spec:
      organizationId: APIGEE_ORG
      rotationId: ROTATION_ID # match the current rotation.
      timeoutMinutes: TIMEOUT_MINUTES # optional.
      precheck: false
      cassandra:
        oldSecretProviderClass: OLD_SPC_NAME # Must match the previous oldSecretProviderClass.
        newSecretProviderClass: NEW_SPC_NAME # Must match the previous newSecretProviderClass.
        jobType: ROLLBACK
    

    ๊ฐ ํ•ญ๋ชฉ์˜ ์˜๋ฏธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

    • ROLLBACK_NAME: ๋กค๋ฐฑ ์ž‘์—…์˜ ์ด๋ฆ„์ž…๋‹ˆ๋‹ค(์˜ˆ: sr-1-rollback).
    • APIGEE_NAMESPACE: Apigee ๋„ค์ž„์ŠคํŽ˜์ด์Šค์ž…๋‹ˆ๋‹ค.
    • APIGEE_ORG: Apigee ์กฐ์ง ID์ž…๋‹ˆ๋‹ค.
    • ROTATION_ID: ๋กค๋ฐฑ ์ค‘์ธ ํ˜„์žฌ ์ˆœํ™˜์˜ ID์ž…๋‹ˆ๋‹ค(์˜ˆ: rot-1).
    • TIMEOUT_MINUTES: ์„ ํƒ์‚ฌํ•ญ. ๊ธฐ๋ณธ๊ฐ’์„ ์žฌ์ •์˜ํ•ฉ๋‹ˆ๋‹ค(480m == 8์‹œ๊ฐ„). <=0์€ ๋ฌดํ•œ ์ œํ•œ ์‹œ๊ฐ„์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
    • OLD_SPC_NAME: ๋‹จ์ผ ๋ฆฌ์ „ ์„ค์ • ๋˜๋Š” ๋ฉ€ํ‹ฐ ๋ฆฌ์ „ ์„ค์ • ํ”„๋Ÿฌ์‹œ์ €์—์„œ ์‚ฌ์šฉํ•œ ์ˆœํ™˜ YAML ํŒŒ์ผ์˜ oldSecretProviderClass: ๋ณด์•ˆ ๋น„๋ฐ€ ์ด๋ฆ„๊ณผ ์ผ์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • NEW_SPC_NAME: ๋‹จ์ผ ๋ฆฌ์ „ ์„ค์ • ๋˜๋Š” ๋ฉ€ํ‹ฐ ๋ฆฌ์ „ ์„ค์ • ํ”„๋Ÿฌ์‹œ์ €์—์„œ ์‚ฌ์šฉํ•œ ์ˆœํ™˜ YAML ํŒŒ์ผ์˜ newSecretProviderClass: ๋ณด์•ˆ ๋น„๋ฐ€ ์ด๋ฆ„๊ณผ ์ผ์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  2. ๋กค๋ฐฑ์„ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.
    kubectl -n APIGEE_NAMESPACE apply -f ROLLBACK_YAML_FILE
    
  3. ์ž‘์—… ์ƒํƒœ๋ฅผ ํ™•์ธํ•˜๊ณ  ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค.
    kubectl -n APIGEE_NAMESPACE describe sr ROTATION_NAME
    
  4. ๋กค๋ฐฑ์ด ์™„๋ฃŒ๋˜๋ฉด ํŠธ๋ž˜ํ”ฝ์ด ๊ณ„์† ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ํ๋ฅด๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
  5. ๋ฉ€ํ‹ฐ ๋ฆฌ์ „ ์„ค์น˜์˜ ๊ฒฝ์šฐ ํŠธ๋ž˜ํ”ฝ์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ํ๋ฅด๋ฉด ๊ฐ ๋ฆฌ์ „์—์„œ ๋กค๋ฐฑ ํ”„๋กœ์„ธ์Šค๋ฅผ ๋ฐ˜๋ณตํ•ฉ๋‹ˆ๋‹ค.
  6. ๋กค๋ฐฑ์„ ์™„๋ฃŒํ•˜๊ณ  ๋ชจ๋“  ๋ฆฌ์ „์—์„œ ํŠธ๋ž˜ํ”ฝ์ด ๊ณ„์† ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ํ๋ฅด๋Š”์ง€ ํ™•์ธํ•œ ํ›„ ์‚ญ์ œ ํ”„๋กœ์„ธ์Šค๋ฅผ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.

    ์ˆœํ™˜ YAML ํŒŒ์ผ์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.

    • metadata.name์„ ์ •๋ฆฌ ์ž‘์—…์ž„์„ ๋‚˜ํƒ€๋‚ด๋Š” ์ด๋ฆ„(์˜ˆ: sr-1-cleanup-rollback)์œผ๋กœ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.
    • spec.cassandra.jobType๋ฅผ CLEANUP_ROLLBACK๋กœ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.
  7. ํŒŒ์ผ์„ ์ ์šฉํ•˜์—ฌ ์ •๋ฆฌ ์ž‘์—…์„ ํŠธ๋ฆฌ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.
    kubectl -n APIGEE_NAMESPACE apply -f ROTATION_YAML_FILE
    
  8. ์ž‘์—… ์ƒํƒœ๋ฅผ ํ™•์ธํ•˜๊ณ  ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค.
    kubectl -n APIGEE_NAMESPACE describe sr ROTATION_NAME
    

    ์ •๋ฆฌ ์ž‘์—…์ด ๋๋‚˜๋ฉด ์ˆœํ™˜ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์™„๋ฃŒ๋ฉ๋‹ˆ๋‹ค.

  9. ์žฌ์ •์˜ ํŒŒ์ผ์„ ์—…๋ฐ์ดํŠธํ•˜๊ณ  cassandra.auth.secretProviderClass๋ฅผ ์ด์ „ ๋ณด์•ˆ ๋น„๋ฐ€ ์ œ๊ณต์ž ํด๋ž˜์Šค(oldSecretProviderClass)๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
    cassandra:
      auth:
        secretProviderClass: OLD_SPC_NAME