다음을 통해 공유


Azure Arc 지원 Kubernetes 클러스터에서 오프라인 액세스를 위해 비밀 저장소 확장을 사용하여 비밀을 가져옵니다.

SSE(Kubernetes)용 Azure Key Vault 비밀 저장소 확장은 오프라인 액세스를 위해 Azure Key Vault 에서 Azure Arc 지원 Kubernetes 클러스터 로 비밀을 자동으로 동기화합니다. 즉, Kubernetes 클러스터를 반 연결이 끊긴 상태로 실행하는 경우에도 Azure Key Vault를 사용하여 비밀을 저장, 유지 관리하고 회전할 수 있습니다. 동기화된 비밀은 클러스터 비밀 저장소에 저장되어 Kubernetes 비밀로 제공되어 데이터 볼륨으로 탑재하거나 Pod의 컨테이너에 환경 변수로 노출하는 등 일반적인 모든 방식으로 사용할 수 있습니다.

동기화된 비밀은 중요한 비즈니스 자산이므로 SSE는 격리된 네임스페이스, RBAC(역할 기반 액세스 제어) 정책 및 동기화 컨트롤러에 대한 제한된 권한을 통해 보안을 유지합니다. 추가 보호를 위해 클러스터의 Kubernetes 비밀 저장소를 암호화합니다.

이 문서에서는 SSE를 Azure Arc 지원 Kubernetes 확장으로 설치하고 구성하는 방법을 보여 줍니다.

SSE는 Azure Key Vault에 대한 연결이 완벽하지 않을 수 있는 Azure 클라우드 외부의 클러스터에 권장됩니다. SSE는 기본적으로 Kubernetes 비밀 저장소에 비밀의 복사본을 만듭니다. 비밀의 로컬 복사본을 만들지 않으려는 경우 클러스터가 Azure Key Vault에 완벽하게 연결되어 있는 경우 Arc 지원 Kubernetes 클러스터에서 비밀 액세스를 위해 온라인 전용 Azure Key Vault 비밀 공급자 확장을 사용할 수 있습니다. 동일한 클러스터에서 온라인 Azure Key Vault 비밀 공급자 확장과 오프라인 SSE를 함께 실행하는 것은 권장되지 않습니다.

필수 구성 요소

  • Arc 지원 클러스터입니다. 이는 사용자가 직접 연결 한 것일 수 있습니다(이 가이드에서는 K3s 클러스터를 가정하고 Arc를 사용하도록 설정하는 방법에 대한 지침을 제공합니다.) 또는 Azure Arc 클러스터에서 사용하도록 설정된 Microsoft 관리 AKS 입니다. 클러스터는 Kubernetes 버전 1.27 이상을 실행해야 합니다.
  • Azure CLI 확장의 최신 버전을 포함하여 k8s-extension를 충족하는지 확인합니다.
  • cert-manager는 클러스터 내 로그 통신을 위해 TLS를 지원하는 데 필요합니다. 이 가이드의 뒷부분에 나오는 예에서는 설치 방법을 안내합니다. cert-manager에 대한 자세한 내용은 cert-manager.io를 참조하세요.

아직 Azure CLI를 설치하지 않았다면 설치하고 로그인합니다.

az login

시작하기 전에 Azure 및 클러스터 리소스를 구성하는 데 사용할 환경 변수를 설정합니다. 여기에 나열된 관리 ID, Azure Key Vault 또는 다른 리소스가 이미 있는 경우 해당 리소스를 반영하도록 환경 변수의 이름을 업데이트합니다. KEYVAULT_NAME은 전역적으로 고유해야 합니다. 이 이름이 Azure에서 이미 사용 중이면 나중에 KeyVault 만들기가 실패합니다.

export RESOURCE_GROUP="AzureArcTest"
export CLUSTER_NAME="AzureArcTest1"
export LOCATION="EastUS"
export SUBSCRIPTION="$(az account show --query id --output tsv)"
export AZURE_TENANT_ID="$(az account show -s $SUBSCRIPTION --query tenantId --output tsv)"
export CURRENT_USER="$(az ad signed-in-user show --query userPrincipalName --output tsv)"
export KEYVAULT_NAME="my-UNIQUE-kv-name"
export KEYVAULT_SECRET_NAME="my-secret"
export USER_ASSIGNED_IDENTITY_NAME="my-identity"
export FEDERATED_IDENTITY_CREDENTIAL_NAME="my-credential"
export KUBERNETES_NAMESPACE="my-namespace"
export SERVICE_ACCOUNT_NAME="my-service-account"

필요한 경우 리소스 그룹을 만듭니다.

az group create --name ${RESOURCE_GROUP}  --___location ${LOCATION}

클러스터에서 워크로드 ID 페더레이션을 활성화합니다.

SSE는 워크로드 ID 페더레이션이라는 기능을 사용하여 Azure Key Vault 비밀에 액세스하고 동기화합니다. 이 섹션에서는 기능을 설정하는 방법을 설명합니다. 다음 섹션에서는 이것이 어떻게 자세히 사용되는지 설명합니다.

다음 단계는 워크로드 ID 페더레이션을 사용하여 Arc 지원 Kubernetes를 구성하는 방법에 대한 방법 가이드를 기반으로 합니다. 추가 지원이 필요한 경우 해당 설명서를 참조하세요.

클러스터가 아직 Azure Arc에 연결되지 않은 경우 다음 단계를 따릅니다. 이러한 단계 동안 connect 명령의 일부로 워크로드 ID 페더레이션을 사용하도록 설정합니다.

az connectedk8s connect --name ${CLUSTER_NAME} --resource-group ${RESOURCE_GROUP} --enable-oidc-issuer

클러스터가 이미 Azure Arc에 연결되어 있는 경우 update 명령을 사용하여 워크로드 ID를 사용하도록 설정합니다.

az connectedk8s update --name ${CLUSTER_NAME} --resource-group ${RESOURCE_GROUP} --enable-oidc-issuer

이제 Microsoft Entra ID가 이러한 토큰의 유효성을 검사하는 데 필요한 공개 키를 찾을 수 있도록 하는 새 발급자 URL(service-account-issuer)을 사용하여 서비스 계정 토큰을 발급하도록 클러스터를 구성합니다. 이러한 공개 키는 클러스터의 자체 서비스 계정 토큰 발급자를 위한 것이며, 이전에 설정한 --enable-oidc-issuer 옵션의 결과로 이 URL에서 획득되어 클라우드에 호스트되었습니다.

선택적으로 OwnerReferencesPermissionEnforcement허용 컨트롤러를 구성하여 컨트롤 플레인에서 실행되는 권한 있는 리소스로서 SSE의 자체 권한에 대한 제한을 구성할 수도 있습니다. 이 허용 컨트롤러는 SSE가 클러스터의 다른 개체를 얼마나 변경할 수 있는지 제한합니다.

  1. 발급자 URL 필드와 권한 적용을 사용하여 kube-apiserver를 구성합니다. 다음 예에서는 k3s 클러스터에 대한 것입니다. 클러스터에는 API 서버 인수를 변경하는 데 사용할 수 있는 다양한 수단이 있을 수 있습니다. --kube-apiserver-arg="--service-account-issuer=${SERVICE_ACCOUNT_ISSUER}", "--kube-apiserver-arg=service-account-max-token-expiration=24h" and --kube-apiserver-arg="--enable-admission-plugins=OwnerReferencesPermissionEnforcement".

    • 서비스 계정 발급자 URL을 가져옵니다.

      export SERVICE_ACCOUNT_ISSUER="$(az connectedk8s show --name ${CLUSTER_NAME} --resource-group ${RESOURCE_GROUP} --query "oidcIssuerProfile.issuerUrl" --output tsv)"
      echo $SERVICE_ACCOUNT_ISSUER
      
    • K3s 클러스터의 구성 파일에서 API 서버 인수를 업데이트합니다.

      cat <<EOF > /tmp/k3s-config.yaml
      kube-apiserver-arg:
          - 'service-account-issuer=${SERVICE_ACCOUNT_ISSUER}'
          - 'service-account-max-token-expiration=24h'
          - 'enable-admission-plugins=OwnerReferencesPermissionEnforcement'
      EOF
      sudo mv /tmp/k3s-config.yaml /etc/rancher/k3s/config.yaml
      
  2. kube-apiserver를 다시 시작합니다.

    sudo systemctl restart k3s
    
  3. (선택 사항) 서비스 계정 발급자를 올바르게 구성했는지 확인합니다.

    kubectl cluster-info dump | grep service-account-issuer
    

비밀을 만들고 이에 액세스할 수 있는 ID를 구성합니다.

지정된 Azure Key Vault 비밀에 액세스하고 동기화하려면 SSE가 해당 비밀에 액세스할 수 있는 적절한 Azure 권한이 있는 Azure 관리 ID에 액세스해야 합니다. 관리 ID는 이전에 활성화한 워크로드 ID 기능을 사용하여 Kubernetes 서비스 계정에 연결되어야 합니다. SSE는 연관된 페더레이션된 Azure 관리 ID를 사용하여 Azure Key Vault에서 Kubernetes 비밀 저장소로 비밀을 끌어옵니다. 다음 섹션에서는 이를 설정하는 방법을 설명합니다.

Azure Key Vault 만들기

Azure Key Vault 만들기 및 비밀을 추가합니다. 이미 Azure Key Vault와 비밀이 있는 경우 이 섹션을 건너뛸 수 있습니다.

  1. Azure Key Vault를 만듭니다.

    az keyvault create --resource-group "${RESOURCE_GROUP}" --___location "${LOCATION}" --name "${KEYVAULT_NAME}" --enable-rbac-authorization
    
  2. 자격 증명 모음에 대한 '비밀 관리자' 권한을 부여하여 비밀을 만들 수 있습니다.

    az role assignment create --role "Key Vault Secrets Officer" --assignee ${CURRENT_USER} --scope /subscriptions/${SUBSCRIPTION}/resourcegroups/${RESOURCE_GROUP}/providers/Microsoft.KeyVault/vaults/${KEYVAULT_NAME}
    
  3. 비밀을 만들고 업데이트하여 두 가지 버전을 만듭니다.

    az keyvault secret set --vault-name "${KEYVAULT_NAME}" --name "${KEYVAULT_SECRET_NAME}" --value 'Hello!'
    az keyvault secret set --vault-name "${KEYVAULT_NAME}" --name "${KEYVAULT_SECRET_NAME}" --value 'Hello2'
    

사용자 할당 관리 ID 만들기

다음으로, 사용자가 할당한 관리 ID를 만들고 Azure Key Vault에 액세스할 수 있는 권한을 부여합니다. Azure Key Vault에 대한 Key Vault 읽기 권한자 및 Key Vault 비밀 사용자 권한의 관리 ID가 이미 있는 경우 이 섹션을 건너뛸 수 있습니다. 자세한 내용은 Key Vault에서 사용자 할당 관리 ID 만들기Azure RBAC 비밀, 키 및 인증서 권한 사용을 참조하세요.

  1. 사용자가 할당한 관리 ID 만들기:

    az identity create --name "${USER_ASSIGNED_IDENTITY_NAME}" --resource-group "${RESOURCE_GROUP}" --___location "${LOCATION}" --subscription "${SUBSCRIPTION}"
    
  2. ID에 Key Vault 읽기 권한자 및 Key Vault 비밀 사용자 권한을 부여합니다. 이러한 명령이 성공하기 전에 ID 만들기 복제가 완료될 때까지 잠시 기다려야 할 수도 있습니다.

    export USER_ASSIGNED_CLIENT_ID="$(az identity show --resource-group "${RESOURCE_GROUP}" --name "${USER_ASSIGNED_IDENTITY_NAME}" --query 'clientId' -otsv)"
    az role assignment create --role "Key Vault Reader" --assignee "${USER_ASSIGNED_CLIENT_ID}" --scope /subscriptions/${SUBSCRIPTION}/resourcegroups/${RESOURCE_GROUP}/providers/Microsoft.KeyVault/vaults/${KEYVAULT_NAME}
    az role assignment create --role "Key Vault Secrets User" --assignee "${USER_ASSIGNED_CLIENT_ID}" --scope /subscriptions/${SUBSCRIPTION}/resourcegroups/${RESOURCE_GROUP}/providers/Microsoft.KeyVault/vaults/${KEYVAULT_NAME}
    

페더레이션 ID 자격 증명 만들기

비밀에 액세스해야 하는 워크로드에 대한 Kubernetes 서비스 계정을 만듭니다. 그런 다음 관리 ID, OIDC 서비스 계정 발급자, Kubernetes 서비스 계정을 연결하는 페더레이션된 ID 자격 증명을 만듭니다.

  1. 관리 ID에 페더레이션될 Kubernetes 서비스 계정을 만듭니다. 연관된 사용자가 할당한 관리 ID에 대한 세부 정보로 주석을 추가합니다.

    kubectl create ns ${KUBERNETES_NAMESPACE}
    
    cat <<EOF | kubectl apply -f -
      apiVersion: v1
      kind: ServiceAccount
      metadata:
        name: ${SERVICE_ACCOUNT_NAME}
        namespace: ${KUBERNETES_NAMESPACE}
    EOF
    
  2. 페더레이션 ID 자격 증명 만들기:

    az identity federated-credential create --name ${FEDERATED_IDENTITY_CREDENTIAL_NAME} --identity-name ${USER_ASSIGNED_IDENTITY_NAME} --resource-group ${RESOURCE_GROUP} --issuer ${SERVICE_ACCOUNT_ISSUER} --subject system:serviceaccount:${KUBERNETES_NAMESPACE}:${SERVICE_ACCOUNT_NAME} --audience api://AzureADTokenExchange
    

SSE 설치

SSE는 Azure Arc 확장 기능으로 제공됩니다. Azure Arc 지원 Kubernetes 클러스터Azure Arc 지원 Kubernetes 확장으로 확장할 수 있습니다. 확장 기능은 연결된 클러스터에서 Azure 기능을 사용하도록 설정하고 확장 기능 설치 및 수명 주기 관리를 위한 Azure Resource Manager 기반 환경을 제공합니다.

cert-managertrust-manager도 클러스터 서비스 간 로그의 보안 통신에 필요하며 Arc 확장보다 먼저 설치해야 합니다.

  1. cert-manager를 설치합니다.

    helm repo add jetstack https://charts.jetstack.io/ --force-update
    helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace --set crds.enabled=true 
    
  2. trust-manager를 설치합니다.

    helm upgrade trust-manager jetstack/trust-manager --install --namespace cert-manager --wait
    
  3. 다음 명령을 사용하여 Arc 지원 클러스터에 SSE를 설치합니다.

    az k8s-extension create \
      --cluster-name ${CLUSTER_NAME} \
      --cluster-type connectedClusters \
      --extension-type microsoft.azure.secretstore \
      --resource-group ${RESOURCE_GROUP} \
      --name ssarcextension \
      --scope cluster
    

    원하는 경우 필요에 따라 기본 회전 폴링 간격을 추가하여 --configuration-settings rotationPollIntervalInSeconds=<time_in_seconds> 수정할 수 있습니다( 구성 참조 참조).

SSE 구성

Kubernetes 사용자 지정 리소스 인스턴스를 정의하여 Azure Key Vault에 대한 정보와 클러스터에 동기화할 비밀로 설치된 확장을 구성합니다. 두 가지 형식의 사용자 지정 리소스를 만듭니다.

  • Key Vault에 대한 연결을 정의하는 SecretProviderClass 개체입니다.
  • 동기화할 각 비밀에 대한 SecretSync 개체입니다.

SecretProviderClass 리소스를 만들기

SecretProviderClass 리소스는 Azure Key Vault에 대한 연결, 자격 증명 모음에 액세스하는 데 사용할 ID, 동기화할 비밀, 로컬로 보존할 각 비밀의 버전 수를 정의하는 데 사용됩니다.

동기화하려는 각 Azure Key Vault, Azure Key Vault에 액세스하는 데 사용되는 각 ID 및 각 대상 Kubernetes 네임스페이스에 대해 별도의 SecretProviderClass가 필요합니다.

다음 예에 따라 Key Vault 및 비밀에 적절한 값으로 하나 이상의 SecretProviderClass YAML 파일을 만듭니다.

cat <<EOF > spc.yaml
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
  name: secret-provider-class-name                       # Name of the class; must be unique per Kubernetes namespace
  namespace: ${KUBERNETES_NAMESPACE}                     # Kubernetes namespace to make the secrets accessible in
spec:
  provider: azure
  parameters:
    clientID: "${USER_ASSIGNED_CLIENT_ID}"               # Managed Identity Client ID for accessing the Azure Key Vault with.
    keyvaultName: ${KEYVAULT_NAME}                       # The name of the Azure Key Vault to synchronize secrets from.
    objects: |
      array:
        - |
          objectName: ${KEYVAULT_SECRET_NAME}            # The name of the secret to synchronize.
          objectType: secret
          objectVersionHistory: 2                        # [optional] The number of versions to synchronize, starting from latest.
    tenantID: "${AZURE_TENANT_ID}"                       # The tenant ID of the Key Vault 
EOF

SecretProviderClass 참조를 보면 추가 구성 지침을 얻을 수 있습니다.

SecretSync 개체 만들기

SecretSync 개체는 SecretsProviderClass가 가져온 항목이 Kubernetes에 저장되는 방법을 정의하는 데 필요합니다. Kubernetes 비밀은 ConfigMaps와(과) 마찬가지로 키-값 맵이며, SecretSync 객체는 SSE에 연결된 SecretsProviderClass의 정의된 항목을 Kubernetes 비밀의 키에 매핑하는 방법을 알려줍니다. SSE는 SecretSync를 설명하는 이름과 동일한 Kubernetes 시크릿을 생성합니다.

이 템플릿에 따라 각 kubernetes 비밀에 대해 하나의 SecretSync 개체 YAML 파일을 만듭니다. Kubernetes 네임스페이스는 SecretProviderClass 네임스페이스와 일치해야 합니다.

cat <<EOF > ss.yaml
apiVersion: secret-sync.x-k8s.io/v1alpha1
kind: SecretSync
metadata:
  name: secret-sync-name                                   # Name of the object; must be unique per Kubernetes namespace
  namespace: ${KUBERNETES_NAMESPACE}                       # Kubernetes namespace
spec:
  serviceAccountName: ${SERVICE_ACCOUNT_NAME}              # The Kubernetes service account to be given permissions to access the secret.
  secretProviderClassName: secret-provider-class-name      # The name of the matching SecretProviderClass with the configuration to access the AKV storing this secret
  secretObject:
    type: Opaque
    data:
    - sourcePath: ${KEYVAULT_SECRET_NAME}/0                # Name of the secret in Azure Key Vault with an optional version number (defaults to latest)
      targetKey: ${KEYVAULT_SECRET_NAME}-data-key0         # Target name of the secret in the Kubernetes secret store (must be unique)
    - sourcePath: ${KEYVAULT_SECRET_NAME}/1                # [optional] Next version of the AKV secret. Note that versions of the secret must match the configured objectVersionHistory in the secrets provider class 
      targetKey: ${KEYVAULT_SECRET_NAME}-data-key1         # [optional] Next target name of the secret in the K8s secret store
EOF

비밀을 SecretProviderClass에서 참조할 때는 위치 objectVersionHistory< 2의 "/0"을 포함하지 마세요. 최신 버전은 암시적으로 사용됩니다.

추가 구성 지침에 대해서는 SecretSync 참조를 참조하십시오.

구성 CR 적용

kubectl apply 명령을 사용하여 구성 CR(사용자 지정 리소스)을 적용합니다.

kubectl apply -f ./spc.yaml
kubectl apply -f ./ss.yaml

SSE는 자동으로 비밀을 찾아 클러스터와 동기화를 시작합니다.

클러스터와 동기화되는 비밀 관찰

구성이 적용되면 SSE를 설치할 때 지정한 주기에 따라 비밀이 클러스터와 자동으로 동기화되기 시작합니다.

동기화된 비밀 보기

다음 명령을 실행하여 클러스터에 동기화된 비밀을 확인합니다.

# View a list of all secrets in the namespace
kubectl get secrets -n ${KUBERNETES_NAMESPACE}

-o yaml 또는 -o json를 추가하여 kubectl getkubectl describe 명령의 출력 형식을 변경하십시오.

비밀 값 보기

Kubernetes 비밀 저장소에 저장된 동기화된 비밀 값을 보려면 다음 명령을 사용합니다.

kubectl get secret secret-sync-name -n ${KUBERNETES_NAMESPACE} -o jsonpath="{.data.${KEYVAULT_SECRET_NAME}-data-key0}" | base64 -d && echo
kubectl get secret secret-sync-name -n ${KUBERNETES_NAMESPACE} -o jsonpath="{.data.${KEYVAULT_SECRET_NAME}-data-key1}" | base64 -d && echo

문제 해결

문제 진단 및 해결에 대한 지원은 문제 해결 가이드 를 참조하세요.

SSE 제거

SSE를 제거하고 비밀 동기화를 중지하려면 az k8s-extension delete 명령을 사용하여 제거합니다.

az k8s-extension delete --name ssarcextension --cluster-name $CLUSTER_NAME  --resource-group $RESOURCE_GROUP  --cluster-type connectedClusters    

확장을 제거해도 클러스터에서 비밀, SecretSync 개체 또는 CRD는 제거되지 않습니다. 이러한 개체는 kubectl을 사용하여 직접 제거해야 합니다.

SecretSync CRD를 삭제하면 모든 SecretSync 개체가 제거되고 기본적으로 소유한 모든 비밀이 제거되지만 다음과 같은 경우 비밀이 지속될 수 있습니다.

  • 비밀의 소유권을 수정했습니다.
  • 클러스터에서 가비지 수집 설정을 변경했으며 여기에는 다른 종료자 설정도 포함됩니다.

이런 경우에는 kubectl을 사용하여 비밀을 직접 삭제해야 합니다.

다음 단계