본문 바로가기
WIKI 기술 지식 베이스

Composition에서 연결 정보(Connection Details) 노출하기

원문 보기 위키 갱신

Composition에서 연결 정보(Connection Details) 노출하기 (Connection Details Composition)

이 가이드는 복합 리소스(XR)의 연결 정보(connection details)를 노출하는 방법을 보여 줍니다. 복합 리소스는 여러 리소스를 구성(compose)할 수 있기 때문에 노출하는 연결 정보는 종종 구성된 리소스(composed resources)들의 연결 정보를 합친 집계(aggregate) 형태가 됩니다.

출처: 문서

본문

권장하는 방법은 Composition에 쿠버네티스 Secret 리소스를 포함하여 다른 리소스들의 연결 정보를 집계하고 XR을 위해 노출하는 것입니다.

참고 Crossplane v1은 XR을 위한 연결 정보를 자동으로 생성하는 기능을 포함했습니다. Crossplane v2는 이 기능을 XR에 대해서만 제거합니다. 관리 리소스(MR)는 이 변경의 영향을 받지 않으며 여전히 writeConnectionSecretToRef 필드를 통해 연결 정보를 지원합니다.

Crossplane v1에서 XR 연결 정보를 지정하는 방법에 대해 더 알아보려면 v1 connection details 문서 페이지를 참고하세요.

예시 개요 (Example overview)

이 가이드는 UserAccessKey 복합 리소스를 생성하여 복합 리소스가 연결 정보를 노출하는 방법을 보여 줍니다. 이 XR은 여러 액세스 키를 가진 AWS IAM 사용자를 나타냅니다.

사용자가 UserAccessKey를 생성하면 크로스플레인은 AWS에 IAM User와 두 개의 AccessKeys를 프로비저닝합니다. 각 AccessKey는 username과 password 같은 자체 연결 정보를 생성합니다. UserAccessKey는 또한 composed resources의 집계된 연결 정보를 노출하는 Secret 리소스를 구성하여, 사용자와 애플리케이션이 그것을 소비할 수 있게 합니다.

UserAccessKey XR 예시는 다음과 같습니다.

apiVersion: example.org/v1alpha1
kind: UserAccessKey
metadata:
  namespace: default
  name: my-keys

배후에서 크로스플레인은:

  • AWS IAM User와 두 개의 AccessKeys(composed resources)를 생성합니다.
  • 두 AccessKeys의 연결 정보를 수집합니다.
  • 그것들을 Secret에서 UserAccessKey의 연결 정보로 노출합니다.

복합 리소스의 연결 정보 Secret은 다음과 같습니다.

apiVersion: v1
kind: Secret
metadata:
  namespace: default
  name: my-keys-connection-details
data:
  user-0: 
  password-0: 
  user-1: 
  password-1: 

사용자와 애플리케이션은 이 Secret을 읽어 UserAccessKey 연결 정보를 소비할 수 있습니다.

팁 이 가이드의 패턴은 연결 정보를 노출해야 하는 모든 복합 리소스에 적용됩니다. 예를 들어:

  • 데이터베이스 연결 문자열과 자격 증명
  • 클러스터 클라이언트 인증서와 키 데이터
  • 서비스와 ingress의 애플리케이션 엔드포인트

사전 요구 사항 (Prerequisites)

이 가이드에는 다음이 필요합니다.

  • 쿠버네티스 클러스터
  • 쿠버네티스 클러스터에 설치된 크로스플레인
  • 자격 증명과 함께 설치·구성된 provider-aws-iam

팁 AWS 프로바이더를 설정하려면 Get Started with Managed Resources 가이드를 따르되, provider provider-aws-iam:v2.3.0을 사용하세요. 프로바이더 설치와 자격 증명 구성 단계를 완료한 후 이 가이드로 돌아오세요.

복합 리소스 빌드 (Build the composite resource)

연결 정보를 노출하는 복합 리소스를 만들려면 다음 단계를 따르세요.

  • 복합 리소스의 스키마 정의
  • 사용할 Composition 함수 설치
  • Composition이 연결 정보를 노출하는 방법 구성

이 단계를 완료한 후 복합 리소스를 사용할 수 있습니다.

스키마 정의 (Define the schema)

CompositeResourceDefinition(XRD)은 복합 리소스를 정의합니다.

이 예시에서는 UserAccessKey 복합 리소스에 대한 XRD를 만듭니다.

apiVersion: apiextensions.crossplane.io/v2
kind: CompositeResourceDefinition
metadata:
  name: useraccesskeys.example.org
spec:
  group: example.org
  names:
    kind: UserAccessKey
    plural: useraccesskeys
  scope: Namespaced
  versions:
  - name: v1alpha1
    served: true
    referenceable: true
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            type: object
            properties:
              writeConnectionSecretToRef:
                type: object
                properties:
                  name:
                    type: string
kubectl apply -f https://docs.crossplane.io/latest/manifests/guides/connection-details-composition/xrd.yaml

팁 이 XRD 스키마는 사용자가 XR 연결 정보 secret의 이름을 선택적으로 설정할 수 있게 해 주는 .spec.writeConnectionSecretToRef.name 필드를 정의합니다. Cluster 범위 XRD의 경우 .spec.writeConnectionSecretToRef.namespace 필드를 추가하여 사용자가 secret의 네임스페이스도 지정할 수 있게 할 수 있습니다.

이제 쿠버네티스 API가 UserAccessKey 복합 리소스에 대한 요청을 서비스합니다.

함수 설치 (Install the function)

Composition 함수는 리소스를 구성하고 연결 정보를 노출하는 데 도움이 되는 일반적인 기능을 제공합니다. 이 가이드는 여러 함수로 연결 정보를 구성하는 방법을 보여 줍니다. 아래 탭에서 사용할 언어를 선택하세요.

YAML — YAML 지원을 설치하려면 이 Composition 함수를 만드세요.

apiVersion: pkg.crossplane.io/v1
kind: Function
metadata:
  name: function-patch-and-transform
spec:
  package: xpkg.crossplane.io/crossplane-contrib/function-patch-and-transform:v0.10.0
kubectl apply -f https://docs.crossplane.io/latest/manifests/guides/connection-details-composition/fn-patch-and-transform.yaml

크로스플레인이 함수를 설치했는지 확인하세요.

kubectl get -f https://docs.crossplane.io/latest/manifests/guides/connection-details-composition/fn-patch-and-transform.yaml
NAME                              INSTALLED   HEALTHY   PACKAGE                                                                      AGE
function-patch-and-transform      True        True      xpkg.crossplane.io/crossplane-contrib/function-patch-and-transform:v0.10.0   8s

Templated YAML — Helm 차트 작성에 익숙하다면 Templated YAML이 좋은 선택입니다. 템플릿 YAML 지원을 설치하려면 이 Composition 함수를 만드세요.

apiVersion: pkg.crossplane.io/v1
kind: Function
metadata:
  name: function-go-templating
spec:
  package: xpkg.crossplane.io/crossplane-contrib/function-go-templating:v0.11.2
kubectl apply -f https://docs.crossplane.io/latest/manifests/guides/connection-details-composition/fn-go-templating.yaml
kubectl get -f https://docs.crossplane.io/latest/manifests/guides/connection-details-composition/fn-go-templating.yaml
NAME                     INSTALLED   HEALTHY   PACKAGE                                                                AGE
function-go-templating   True        True      xpkg.crossplane.io/crossplane-contrib/function-go-templating:v0.11.2   15s

Python — Python 지원을 설치하려면 이 Composition 함수를 만드세요.

apiVersion: pkg.crossplane.io/v1
kind: Function
metadata:
  name: function-python
spec:
  package: xpkg.crossplane.io/crossplane-contrib/function-python:v0.2.0
kubectl apply -f https://docs.crossplane.io/latest/manifests/guides/connection-details-composition/fn-python.yaml
kubectl get -f https://docs.crossplane.io/latest/manifests/guides/connection-details-composition/fn-python.yaml
NAME                                 INSTALLED   HEALTHY   PACKAGE                                                        AGE
function-python                      True        True      xpkg.crossplane.io/crossplane-contrib/function-python:v0.2.0   12s

KCL — KCL 지원을 설치하려면 이 Composition 함수를 만드세요.

apiVersion: pkg.crossplane.io/v1
kind: Function
metadata:
  name: function-kcl
spec:
  package: xpkg.crossplane.io/crossplane-contrib/function-kcl:v0.11.6
kubectl apply -f https://docs.crossplane.io/latest/manifests/guides/connection-details-composition/fn-kcl.yaml
kubectl get -f https://docs.crossplane.io/latest/manifests/guides/connection-details-composition/fn-kcl.yaml
NAME                              INSTALLED   HEALTHY   PACKAGE                                                      AGE
function-kcl                      True        True      xpkg.crossplane.io/crossplane-contrib/function-kcl:v0.11.6   6s

Pythonic — Pythonic(https://github.com/crossplane-contrib/function-pythonic) 지원을 설치하려면 이 Composition 함수를 만드세요.

apiVersion: pkg.crossplane.io/v1
kind: Function
metadata:
  name: function-pythonic
spec:
  package: xpkg.crossplane.io/crossplane-contrib/function-pythonic:v0.3.0
kubectl apply -f https://docs.crossplane.io/latest/manifests/guides/connection-details-composition/fn-pythonic.yaml
kubectl get -f https://docs.crossplane.io/latest/manifests/guides/connection-details-composition/fn-pythonic.yaml
NAME               INSTALLED  HEALTHY  PACKAGE                                                         AGE
function-pythonic  True       True     xpkg.crossplane.io/crossplane-contrib/function-pythonic:v0.3.0  1m

이 가이드는 또한 function-auto-ready를 사용합니다. 이 함수는 composed resources가 건강할 때 자동으로 ready로 표시합니다.

apiVersion: pkg.crossplane.io/v1
kind: Function
metadata:
  name: function-auto-ready
spec:
  package: xpkg.crossplane.io/crossplane-contrib/function-auto-ready:v0.6.0
kubectl apply -f https://docs.crossplane.io/latest/manifests/guides/connection-details-composition/fn-auto-ready.yaml

Composition 구성 (Configure the composition)

Composition은 복합 리소스에 대한 리소스 구성 방법을 크로스플레인에 알려줍니다. 이 가이드는 또한 복합 리소스의 연결 정보를 노출하기 위한 composed Secret 리소스를 포함합니다.

일반적인 패턴은:

  • Composed resources가 자신의 연결 정보를 개별 Secrets에 씁니다.
  • Composition이 함수 실행 시 그 연결 정보를 읽습니다.
  • Composition이 XR을 위한 집계된 연결 정보를 나타내는 composed Secret을 만듭니다.

팁 복합 리소스의 연결 정보 secret은 원하는 모든 데이터를 포함할 수 있고 필요에 따라 변환할 수 있습니다. 관리 리소스의 연결 정보에만 국한되지 않습니다. ConfigMaps나 Services 같은 임의의 쿠버네티스 리소스를 포함한 모든 composed resource의 데이터를 포함할 수 있습니다.

UserAccessKey 복합 리소스에 대한 연결 정보를 노출하는 Composition을 만듭니다.

이 예시에서 Composition은 두 개의 AccessKey 관리 리소스를 생성하고 그 자격 증명을 복합 리소스의 연결 정보 Secret으로 노출합니다.

YAML:

apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: useraccesskeys-patch-and-transform
spec:
  compositeTypeRef:
    apiVersion: example.org/v1alpha1
    kind: UserAccessKey
  mode: Pipeline
  pipeline:
  - step: patch-and-transform
    functionRef:
      name: function-patch-and-transform
    input:
      apiVersion: pt.fn.crossplane.io/v1beta1
      kind: Resources
      writeConnectionSecretToRef:
        patches:
        - type: FromCompositeFieldPath
          fromFieldPath: spec.writeConnectionSecretToRef.name
          toFieldPath: name
      resources:
      - name: user
        base:
          apiVersion: iam.aws.m.upbound.io/v1beta1
          kind: User
          spec:
            forProvider: {}
      - name: accesskey-0
        base:
          apiVersion: iam.aws.m.upbound.io/v1beta1
          kind: AccessKey
          spec:
            forProvider:
              userSelector:
                matchControllerRef: true
            writeConnectionSecretToRef:
              name: accesskey-secret-0
        connectionDetails:
        - name: user-0
          type: FromConnectionSecretKey
          fromConnectionSecretKey: username
        - name: password-0
          type: FromConnectionSecretKey
          fromConnectionSecretKey: password
        patches:
        - type: FromCompositeFieldPath
          fromFieldPath: metadata.name
          toFieldPath: spec.writeConnectionSecretToRef.name
          transforms:
          - type: string
            string:
              type: Format
              fmt: "%s-accesskey-secret-0"
      - name: accesskey-1
        base:
          apiVersion: iam.aws.m.upbound.io/v1beta1
          kind: AccessKey
          spec:
            forProvider:
              userSelector:
                matchControllerRef: true
            writeConnectionSecretToRef:
              name: accesskey-secret-1
        connectionDetails:
        - name: user-1
          type: FromConnectionSecretKey
          fromConnectionSecretKey: username
        - name: password-1
          type: FromConnectionSecretKey
          fromConnectionSecretKey: password
        patches:
        - type: FromCompositeFieldPath
          fromFieldPath: metadata.name
          toFieldPath: spec.writeConnectionSecretToRef.name
          transforms:
          - type: string
            string:
              type: Format
              fmt: "%s-accesskey-secret-1"
  - step: ready
    functionRef:
      name: function-auto-ready
kubectl apply -f https://docs.crossplane.io/latest/manifests/guides/connection-details-composition/composition-patch-and-transform.yaml

이 Composition이 연결 정보를 노출하는 방법:

  • 각 composed AccessKey는 writeConnectionSecretToRef가 설정되어 있습니다. 이것은 각 AccessKey가 자격 증명을 개별 Secret에 쓰도록 지시합니다.
  • 각 AccessKey는 connectionDetails를 정의하여 어떤 키가 XR의 집계된 연결 정보 secret에 포함되어야 하는지 지정합니다.
  • 각 연결 정보 항목의 name 필드는 집계된 secret에서 키 이름을 설정합니다.
  • fromConnectionSecretKey 필드는 composed resource의 개별 연결 secret에서 읽을 키를 지정합니다.
  • 함수의 입력에는 연결 secret을 만들 위치를 지정할 수 있는 최상위 writeConnectionSecretToRef 섹션이 포함되어 있습니다.
  • writeConnectionSecretToRef 섹션의 patches는 XR의 .spec.writeConnectionSecretToRef.name 필드에서 secret 이름을 읽습니다.
  • 함수는 XR의 composed resources에 XR의 집계된 연결 정보를 나타내는 Secret 객체를 자동으로 포함합니다.
  • 이 Secret을 직접 만들거나 구성할 필요가 없습니다. 자동으로 처리됩니다.

Templated YAML:

apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: useraccesskeys-go-templating
spec:
  compositeTypeRef:
    apiVersion: example.org/v1alpha1
    kind: UserAccessKey
  mode: Pipeline
  pipeline:
  - step: render-templates
    functionRef:
      name: function-go-templating
    input:
      apiVersion: gotemplating.fn.crossplane.io/v1beta1
      kind: GoTemplate
      source: Inline
      inline:
        template: |
          ---
          apiVersion: iam.aws.m.upbound.io/v1beta1
          kind: User
          metadata:
            annotations:
              {{ setResourceNameAnnotation "user" }}
          spec:
            forProvider: {}
          ---
          apiVersion: iam.aws.m.upbound.io/v1beta1
          kind: AccessKey
          metadata:
            annotations:
              {{ setResourceNameAnnotation "accesskey-0" }}
          spec:
            forProvider:
              userSelector:
                matchControllerRef: true
            writeConnectionSecretToRef:
              name: {{ $.observed.composite.resource.metadata.name }}-accesskey-secret-0
          ---
          apiVersion: iam.aws.m.upbound.io/v1beta1
          kind: AccessKey
          metadata:
            annotations:
              {{ setResourceNameAnnotation "accesskey-1" }}
          spec:
            forProvider:
              userSelector:
                matchControllerRef: true
            writeConnectionSecretToRef:
              name: {{ $.observed.composite.resource.metadata.name }}-accesskey-secret-1
          ---
          apiVersion: v1
          kind: Secret
          metadata:
            name: {{ dig "spec" "writeConnectionSecretToRef" "name" "" $.observed.composite.resource}}
            annotations:
              {{ setResourceNameAnnotation "connection-secret" }}
          {{ if eq $.observed.resources nil }}
          data: {}
          {{ else }}
          data:
            user-0: {{ ( index $.observed.resources "accesskey-0" ).connectionDetails.username }}
            user-1: {{ ( index $.observed.resources "accesskey-1" ).connectionDetails.username }}
            password-0: {{ ( index $.observed.resources "accesskey-0" ).connectionDetails.password }}
            password-1: {{ ( index $.observed.resources "accesskey-1" ).connectionDetails.password }}
          {{ end }}
  - step: ready
    functionRef:
      name: function-auto-ready
kubectl apply -f https://docs.crossplane.io/latest/manifests/guides/connection-details-composition/composition-go-templating.yaml

이 Composition이 연결 정보를 노출하는 방법:

  • 각 composed AccessKey는 writeConnectionSecretToRef가 설정되어 있습니다. 이것은 각 AccessKey가 자격 증명을 개별 Secret에 쓰도록 지시합니다.
  • Composition은 복합 리소스의 연결 정보를 나타내는 명시적인 Secret 리소스를 만듭니다.
  • Secret의 이름은 dig 함수를 사용하여 XR의 .spec.writeConnectionSecretToRef.name 필드가 존재하면 읽어서 설정합니다.
  • 크로스플레인은 각 AccessKey의 연결 정보를 관찰하고 함수 실행 시 Composition에서 사용할 수 있게 만듭니다.
  • Secret은 $.observed.resources를 통해 관찰된 composed resources에서 연결 정보를 읽습니다.
  • {{ if eq $.observed.resources nil }} 검사는 composed resources가 아직 생성 중인 초기 단계를 처리합니다.
  • function-go-templating에서 연결 정보는 이미 base64로 인코딩되어 있으므로 Secret의 data 필드에 직접 사용합니다.

Python:

apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: useraccesskeys-python
spec:
  compositeTypeRef:
    apiVersion: example.org/v1alpha1
    kind: UserAccessKey
  mode: Pipeline
  pipeline:
  - step: render-python
    functionRef:
      name: function-python
    input:
      apiVersion: python.fn.crossplane.io/v1beta1
      kind: Script
      script: |
        def compose(req, rsp):
            # Get observed composite resource
            oxr = req.observed.composite.resource
            oxr_name = oxr["metadata"]["name"]

            # IAM User
            rsp.desired.resources["user"].resource.update({
                "apiVersion": "iam.aws.m.upbound.io/v1beta1",
                "kind": "User",
                "spec": {
                    "forProvider": {}
                }
            })

            # Access Key 0
            rsp.desired.resources["accesskey-0"].resource.update({
                "apiVersion": "iam.aws.m.upbound.io/v1beta1",
                "kind": "AccessKey",
                "spec": {
                    "forProvider": {
                        "userSelector": {
                            "matchControllerRef": True
                        }
                    },
                    "writeConnectionSecretToRef": {
                        "name": f"{oxr_name}-accesskey-secret-0"
                    }
                }
            })

            # Access Key 1
            rsp.desired.resources["accesskey-1"].resource.update({
                "apiVersion": "iam.aws.m.upbound.io/v1beta1",
                "kind": "AccessKey",
                "spec": {
                    "forProvider": {
                        "userSelector": {
                            "matchControllerRef": True
                        }
                    },
                    "writeConnectionSecretToRef": {
                        "name": f"{oxr_name}-accesskey-secret-1"
                    }
                }
            })

            # Secret representing the composite resource's connection details
            secret_resource = {
                "apiVersion": "v1",
                "kind": "Secret",
                "metadata": {}
            }

            # If a secret name was provided then use it
            secret_name = ""
            if "writeConnectionSecretToRef" in oxr["spec"] and "name" in oxr["spec"]["writeConnectionSecretToRef"]:
              secret_name = oxr["spec"]["writeConnectionSecretToRef"]["name"]

            secret_resource["metadata"]["name"] = secret_name

            # Only add data if we have connection details to populate
            data = {}
            if "accesskey-0" in req.observed.resources:
                accesskey0_conn = req.observed.resources["accesskey-0"].connection_details
                if "username" in accesskey0_conn:
                    data["user-0"] = accesskey0_conn["username"].decode("utf-8")
                if "password" in accesskey0_conn:
                    data["password-0"] = accesskey0_conn["password"].decode("utf-8")

            if "accesskey-1" in req.observed.resources:
                accesskey1_conn = req.observed.resources["accesskey-1"].connection_details
                if "username" in accesskey1_conn:
                    data["user-1"] = accesskey1_conn["username"].decode("utf-8")
                if "password" in accesskey1_conn:
                    data["password-1"] = accesskey1_conn["password"].decode("utf-8")

            if data:
                secret_resource["stringData"] = data

            rsp.desired.resources["connection-secret"].resource.update(secret_resource)
  - step: ready
    functionRef:
      name: function-auto-ready
kubectl apply -f https://docs.crossplane.io/latest/manifests/guides/connection-details-composition/composition-python.yaml

이 Composition이 연결 정보를 노출하는 방법:

  • 각 composed AccessKey는 writeConnectionSecretToRef가 설정되어 있습니다. 이것은 각 AccessKey가 자격 증명을 개별 Secret에 쓰도록 지시합니다.
  • Composition은 복합 리소스의 연결 정보를 나타내는 명시적인 Secret 리소스를 만듭니다.
  • secret_name은 XR의 .spec.writeConnectionSecretToRef.name 필드가 존재하는지 확인한 후에만 설정됩니다.
  • 크로스플레인은 각 AccessKey의 연결 정보를 관찰하고 함수 실행 시 Composition에서 사용할 수 있게 만듭니다.
  • Secret은 req.observed.resources["accesskey-0"].connection_details를 통해 관찰된 composed resources에서 연결 정보를 읽습니다.
  • if "accesskey-0" in req.observed.resources 검사는 composed resources가 아직 생성 중인 초기 단계를 처리합니다.
  • function-python에서 연결 정보는 평문 바이트(plaintext bytes)입니다. Secret에 저장하려면 .decode("utf-8")로 문자열로 변환한 후 secret의 stringData 필드를 사용해 저장합니다.

KCL:

apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: useraccesskeys-kcl
spec:
  compositeTypeRef:
    apiVersion: example.org/v1alpha1
    kind: UserAccessKey
  mode: Pipeline
  pipeline:
  - step: render-kcl
    functionRef:
      name: function-kcl
    input:
      apiVersion: krm.kcl.dev/v1alpha1
      kind: KCLInput
      spec:
        source: |
          oxr = option("params").oxr
          ocds = option("params").ocds

          user = {
              apiVersion = "iam.aws.m.upbound.io/v1beta1"
              kind = "User"
              metadata.annotations = {
                  "krm.kcl.dev/composition-resource-name" = "user"
              }
              spec.forProvider = {}
          }

          accesskey0 = {
              apiVersion = "iam.aws.m.upbound.io/v1beta1"
              kind = "AccessKey"
              metadata.annotations = {
                  "krm.kcl.dev/composition-resource-name" = "accesskey-0"
              }
              spec.forProvider.userSelector.matchControllerRef = True
              spec.writeConnectionSecretToRef.name = "${oxr.metadata.name}-accesskey-secret-0"
          }

          accesskey1 = {
              apiVersion = "iam.aws.m.upbound.io/v1beta1"
              kind = "AccessKey"
              metadata.annotations = {
                  "krm.kcl.dev/composition-resource-name" = "accesskey-1"
              }
              spec.forProvider.userSelector.matchControllerRef = True
              spec.writeConnectionSecretToRef.name = "${oxr.metadata.name}-accesskey-secret-1"
          }

          secret = {
              apiVersion = "v1"
              kind = "Secret"
              metadata.name = oxr?.spec?.writeConnectionSecretToRef?.name or ""
              metadata.annotations = {
                  "krm.kcl.dev/composition-resource-name" = "connection-secret"
              }
              data = {
                  "user-0" = ocds["accesskey-0"]?.ConnectionDetails?.username or ""
                  "user-1" = ocds["accesskey-1"]?.ConnectionDetails?.username or ""
                  "password-0" = ocds["accesskey-0"]?.ConnectionDetails?.password or ""
                  "password-1" = ocds["accesskey-1"]?.ConnectionDetails?.password or ""
              } if ocds else {}
          }

          items = [user, accesskey0, accesskey1, secret]
  - step: ready
    functionRef:
      name: function-auto-ready
kubectl apply -f https://docs.crossplane.io/latest/manifests/guides/connection-details-composition/composition-kcl.yaml

이 Composition이 연결 정보를 노출하는 방법:

  • 각 composed AccessKey는 writeConnectionSecretToRef가 설정되어 있습니다. 이것은 각 AccessKey가 자격 증명을 개별 Secret에 쓰도록 지시합니다.
  • Composition은 복합 리소스의 연결 정보를 나타내는 명시적인 Secret 리소스를 만듭니다.
  • Secret의 이름은 ?. 선택적 체이닝(optional chaining) 연산자를 사용하여 XR의 .spec.writeConnectionSecretToRef.name 필드가 존재하면 읽어서 설정합니다.
  • 크로스플레인은 각 AccessKey의 연결 정보를 관찰하고 함수 실행 시 Composition에서 사용할 수 있게 만듭니다.
  • Secret은 ocds["accesskey-0"]?.ConnectionDetails?.username을 통해 관찰된 composed resources에서 연결 정보를 읽으며, 연결 정보가 아직 존재하지 않는 경우를 처리합니다.
  • if ocds else {}는 composed resources가 아직 생성 중인 단계를 처리합니다.
  • function-kcl에서 연결 정보는 이미 base64로 인코딩되어 있으므로 Secret의 data 필드에 직접 사용합니다.

Pythonic:

apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: useraccesskeys-pythonic
spec:
  compositeTypeRef:
    apiVersion: example.org/v1alpha1
    kind: UserAccessKey
  mode: Pipeline
  pipeline:
  - step: render-pythonic
    functionRef:
      name: function-pythonic
    input:
      apiVersion: pythonic.fn.crossplane.io/v1alpha1
      kind: Composite
      composite: |
        class Composite(BaseComposite):
          def compose(self):
            self.connectionSecret = self.spec.writeConnectionSecretToRef

            user = self.resources.user('iam.aws.m.upbound.io/v1beta1', 'User')
            user.spec.forProvider = {}

            for ix in range(2):
              key = self.resources[f"access-key-{ix}"]('iam.aws.m.upbound.io/v1beta1', 'AccessKey')
              key.spec.forProvider.user = user.status.atProvider.id
              key.spec.writeConnectionSecretToRef.name = f"{self.metadata.name}-accesskey-{ix}"
              self.connection[f"user-{ix}"] = key.connection.username
              self.connection[f"password-{ix}"] = key.connection.password
kubectl apply -f https://docs.crossplane.io/latest/manifests/guides/connection-details-composition/composition-pythonic.yaml

이 Composition이 연결 정보를 노출하는 방법:

  • 각 composed AccessKey는 writeConnectionSecretToRef가 설정되어 있습니다. 이것은 각 AccessKey가 자격 증명을 개별 Secret에 쓰도록 지시합니다.
  • 크로스플레인은 각 AccessKey의 연결 정보를 관찰하고 함수 실행 시 Composition에서 사용할 수 있게 만듭니다.
  • Secret은 connection.username과 connection.password를 통해 AccessKey의 연결 정보를 읽습니다.
  • 함수는 XR의 spec.writeConnectionSecretToRef가 존재하면 그것으로 연결 Secret 이름을 설정합니다.
  • 함수는 XR의 composed resources에 XR의 집계된 연결 정보를 나타내는 Secret 객체를 자동으로 포함합니다.
  • 이 Secret을 직접 만들거나 구성할 필요가 없습니다. 자동으로 처리됩니다.
  • function-pythonic에서 연결 정보의 base64 인코딩과 디코딩은 자동으로 처리됩니다.

복합 리소스 사용 (Use the composite resource)

Composition은 이제 UserAccessKey 복합 리소스에 대한 연결 정보 구성 방법을 지정합니다.

실제 동작을 보려면 UserAccessKey를 생성하세요.

apiVersion: example.org/v1alpha1
kind: UserAccessKey
metadata:
  namespace: default
  name: my-keys
spec:
  writeConnectionSecretToRef:
    name: my-keys-connection-details
kubectl apply -f https://docs.crossplane.io/latest/manifests/guides/connection-details-composition/my-keys.yaml

복합 리소스가 준비되었는지 확인하세요.

kubectl get -f https://docs.crossplane.io/latest/manifests/guides/connection-details-composition/my-keys.yaml
NAME      SYNCED   READY   COMPOSITION                    AGE
my-keys   True     True    useraccesskeys-go-templating   45s

참고 AWS가 IAM 리소스를 프로비저닝하는 데 1분 정도 걸릴 수 있습니다. 복합 리소스는 모든 composed resources가 건강해지면 READY가 됩니다.

연결 정보 검증 (Verify the connection details)

복합 리소스는 Secret을 통해 연결 정보를 노출합니다. 크로스플레인이 Secret을 만들었는지 확인하세요.

crossplane CLI를 사용하여 모든 composed resources(연결 정보 Secret 포함)를 함께 확인할 수 있습니다.

팁 Crossplane CLI 설치와 사용 방법은 Crossplane CLI 문서를 참고하세요.

crossplane beta trace useraccesskey.example.org/my-keys
NAME                                             SYNCED   READY   STATUS
UserAccessKey/my-keys (default)                  True     True    Available
├─ AccessKey/my-keys-14c0578cad85 (default)      True     True    Available
├─ AccessKey/my-keys-e420789d13a3 (default)      True     True    Available
├─ User/my-keys-c63b530f8e68 (default)           True     True    Available
└─ Secret/my-keys-connection-details (default)   -        -

my-keys 복합 리소스는 IAM User와 두 개의 IAM AccessKeys를 만들었고, 복합 리소스의 집계된 연결 정보를 포함하는 Secret도 생성되었습니다.

복합 리소스의 집계된 연결 정보 Secret을 확인하세요.

kubectl get secret -n default -l crossplane.io/composite=my-keys
NAME                   TYPE     DATA   AGE
my-keys-586e2994bda1   Opaque   4      5m37s

팁 복합 리소스의 연결 정보 Secret은 편리한 조회를 위해 crossplane.io/composite=my-keys 라벨을 가집니다. XR에 .spec.writeConnectionSecretToRef.name을 설정했다면 Secret은 그 정확한 이름을 가집니다.

복합 리소스의 연결 정보 Secret이 모든 예상 자격 증명을 포함하는지 확인하세요.

kubectl get secret -n default -l crossplane.io/composite=my-keys -o jsonpath='{.items[0].data}' | jq

다음과 같은 출력이 보여야 합니다.

{
  "password-0": "",
  "password-1": "",
  "user-0": "",
  "user-1": ""
}

값 중 하나를 디코딩하여 예상 데이터를 포함하는지 확인하세요.

kubectl get secret -n default -l crossplane.io/composite=my-keys -o jsonpath='{.items[0].data.user-0}' | base64 -d

연결 정보 구성 방법 이해 (Understanding how composing connection details works)

복합 리소스의 연결 정보를 노출하는 데는 두 가지 접근 방식이 있습니다.

수동 구성 (Manual composition) — 대부분의 함수

function-go-templating, function-python, function-kcl 같은 함수를 사용하면 Secret 리소스를 수동으로 구성합니다.

  • 리소스 구성: Composition에서 평소처럼 IAM User, AccessKeys 같은 composed resources를 만듭니다. 이 리소스들은 연결 정보를 Secret에 노출합니다.
  • writeConnectionSecretToRef 설정: 연결 정보를 저장해야 하는 각 composed resource는 Composition에서 writeConnectionSecretToRef가 설정되어 있어야 합니다.
  • 관찰된 연결 정보: 크로스플레인은 각 composed resource의 실제 상태를 관찰하고, 그 연결 정보를 포함하여 함수 실행 시 이 데이터를 사용할 수 있게 만듭니다.
  • 결합된 Secret 구성: composed resources의 관찰된 연결 정보에서 읽어 XR을 위해 노출하려는 중요한 연결 정보를 결합하는 Secret 리소스를 구성합니다. XR 소비자가 이 secret의 이름을 지정할 수 있게 하는 것을 고려하세요.
  • 일시적 상태 처리: XR이 처음 생성될 때 composed resources 및/또는 그 연결 정보가 아직 존재하지 않을 수 있습니다. Composition은 접근하기 전에 리소스와 그 연결 정보가 존재하는지 검사하여 이러한 경우를 처리해야 합니다.

자동 집계 — function-patch-and-transform

function-patch-and-transform은 composed resources에서 연결 정보를 자동으로 관찰하고, v1 동작과의 역호환성을 유지하기 위해 집계된 연결 secret을 만듭니다.

Secret 리소스를 직접 수동으로 구성할 필요는 없습니다.

  • 리소스 구성: Composition에서 평소처럼 IAM User, AccessKeys 같은 composed resources를 만듭니다. 이 리소스들은 연결 정보를 Secret에 노출합니다.
  • writeConnectionSecretToRef 설정: 연결 정보를 저장해야 하는 각 composed resource는 Composition에서 writeConnectionSecretToRef가 설정되어 있어야 합니다.
  • connectionDetails 정의: 각 composed resource에서 connectionDetails 필드를 사용하여 집계된 secret에 포함할 연결 secret 키를 정의합니다.
  • Secret 구성: 필요에 따라 함수 입력에 writeConnectionSecretToRef 섹션을 추가하여 집계된 secret의 이름과 네임스페이스를 설정합니다. 필요하면 XR의 데이터를 사용해 이 값들을 구성하도록 patches를 사용하세요.

자동 집계 — function-pythonic

function-pythonic은 composed resources에서 연결 정보를 자동으로 관찰하고, v1 동작과의 역호환성을 유지하기 위해 집계된 연결 secret을 만듭니다.

Secret 리소스를 직접 수동으로 구성할 필요는 없습니다.

  • 리소스 구성: Composition에서 평소처럼 IAM User, AccessKeys 같은 composed resources를 만듭니다. 이 리소스들은 연결 정보를 Secret에 노출합니다.
  • writeConnectionSecretToRef 설정: 연결 정보를 저장해야 하는 각 composed resource는 Composition에서 resource.spec.writeConnectionSecretToRef가 설정되어 있어야 합니다.
  • connection 정의: 각 composed resource에 대해 self.connection[key] = resource.connection[key]를 사용하여 집계된 secret에 원하는 연결 secret 값을 할당합니다.
  • Secret 구성: XR의 self.connectionSecret 필드를 설정하여 집계된 secret의 기본 이름과 네임스페이스를 덮어씁니다.

문제 해결 (Troubleshooting)

복합 리소스의 연결 정보 Secret이 비어 있음

원인:

  • Composed resources에 writeConnectionSecretToRef가 설정되지 않음
  • Composed resources가 아직 ready/healthy하지 않음
  • (function-patch-and-transform) composed resources에 connectionDetails 필드 누락
  • (수동 구성) Composition에서 초기 nil 상태를 올바르게 처리하지 않음

해결책:

  • 모든 composed 관리 리소스에 writeConnectionSecretToRef가 설정되었는지 확인
  • composed resources가 ready가 될 때까지 대기 (kubectl get으로 READY 열 확인)
  • composed resource가 실제로 연결 정보를 생성하는지 확인: kubectl get secret <name> -o yaml
  • (function-patch-and-transform) 각 composed resource에 원하는 secret 키를 매핑하는 connectionDetails 섹션이 있는지 확인
  • (수동 구성) Composition 로직에 nil/empty 검사를 추가하여 아직 존재하지 않을 수 있는 데이터 접근을 보호

연결 정보가 올바르게 인코딩되지 않음

원인: Composition 로직에서 결합된 secret 데이터를 올바르게 인코딩하지 않음

해결책: 이는 수동 구성 방식에만 적용됩니다. 사용하는 함수에 대해 연결 정보 데이터가 올바르게 인코딩되었는지 확인하세요. 예를 들어 function-python은 연결 정보를 base64 인코딩 문자열로 변환해야 하지만, function-go-templating과 function-kcl의 연결 정보는 이미 이렇게 인코딩되어 있어 변환 로직이 필요 없습니다.

function-patch-and-transform과 function-pythonic은 composed 연결 secret을 자동으로 생성할 때 인코딩을 처리합니다.

Secret에 빈 네임스페이스가 있음

원인: Cluster 범위 XR의 Secret 네임스페이스를 설정하지 않아서 an empty namespace may not be set when a resource name is provided 같은 오류가 발생함

해결책: Cluster 범위 XR이 Secret 같은 네임스페이스 범위 리소스를 구성할 때는 리소스에 네임스페이스를 명시적으로 설정해야 합니다. Composition에서 XR 소비자가 네임스페이스 값을 지정할 수 있게 하는 것을 고려하세요. Namespaced XR은 크로스플레인이 비어 있는 composed resource의 네임스페이스를 기본적으로 XR의 네임스페이스로 설정하므로 이 문제가 없습니다.

정리 (Clean up)

복합 리소스를 삭제하여 정리합니다.

kubectl delete -f https://docs.crossplane.io/latest/manifests/guides/connection-details-composition/my-keys.yaml

복합 리소스를 삭제하면 크로스플레인은 다음을 삭제합니다.

  • AWS의 composed IAM User와 AccessKeys
  • composed resources의 개별 Secrets
  • 복합 리소스의 연결 정보 Secret

중요 프로바이더를 제거하거나 컨트롤 플레인을 종료하기 전에 복합 리소스를 삭제하세요. 더 이상 실행 중이 아니면 composed resources를 정리할 수 없으므로 수동으로 삭제해야 합니다.

더 알아보기 (Learn more)