IAM 인증 관리

이 페이지에서는 Memorystore for Redis Cluster의 IAM 인증 기능에 대한 일반적인 태스크를 설명합니다. 이 기능에 대한 자세한 내용은 IAM 인증 정보를 참조하세요.

IAM 인증으로 인스턴스 만들기

IAM 인증을 사용하는 Memorystore for Redis Cluster 인스턴스를 만들려면 create 명령어를 실행합니다.

gcloud beta redis clusters create INSTANCE_ID --region=REGION_ID --network=NETWORK --shard-count=SHARD_COUNT --auth-mode=iam-auth

다음을 바꿉니다.

  • INSTANCE_ID는 만들려는 Memorystore for Redis Cluster 인스턴스의 ID입니다. 인스턴스 ID는 1~63자(영문 기준)여야 하며 소문자, 숫자, 하이픈만 사용해야 합니다. 소문자로 시작하고 소문자나 숫자로 끝나야 합니다.

  • REGION_ID: 인스턴스를 배치할 리전

  • NETWORK는 인스턴스를 만드는 데 사용되는 네트워크입니다. projects/NETWORK_PROJECT_ID/global/networks/NETWORK_ID 형식을 사용해야 합니다. 여기에서 사용되는 네트워크 ID는 서비스 연결 정책에 사용되는 네트워크 ID와 일치해야 합니다. 그렇지 않으면 create 작업이 실패합니다. 자세한 내용은 네트워킹을 참조하세요.

  • SHARD_COUNT: 인스턴스의 13GB 샤드 수를 결정. 샤드 개수는 인스턴스 데이터를 저장하기 위한 총 메모리 용량을 결정합니다. 인스턴스 사양에 대한 자세한 내용은 클러스터 및 샤드 사양을 참조하세요.

IAM 인증 권한 관리

인스턴스에 대한 제한된 IAM 관리자 역할 만들기

전체 IAM 관리자 액세스 권한을 부여하지 않고도 인스턴스 연결 IAM 권한을 수정할 수 있는 역할을 만들 수 있습니다. 'roles/redis.dbConnectionUser' 역할에 대한 제한된 IAM 관리자를 만들면 됩니다. 자세한 내용은 제한된 IAM 관리자 만들기를 참고하세요.

IAM으로 인스턴스에 대한 액세스 권한 부여

기본적으로 주 구성원에게 roles/redis.dbConnectionUser 역할을 부여하면 주 구성원이 프로젝트의 모든 인스턴스에 액세스할 수 있습니다. 프로젝트의 리소스 하위 집합에 대한 액세스 권한을 부여하려면 roles/redis.dbConnectionUser 역할에 대한 IAM 리소스 기반 액세스를 설정합니다. 자세한 내용은 리소스 기반 액세스 구성을 참조하세요.

IAM 인증을 사용하는 인스턴스에 연결

  1. Redis 클러스터와 동일한 승인된 네트워크를 사용하는 Compute Engine VM이 아직 없으면 빠른 시작: Linux VM 사용을 따라 VM을 만들고 연결합니다.

  2. Compute Engine SSH 터미널에서 다음 명령어를 실행하여 Compute Engine VM에 redis-cli를 설치합니다.

    sudo apt-get install redis-tools
    
  3. 다음 명령어를 실행하여 IAM 사용자의 액세스 토큰을 가져옵니다.

    gcloud auth print-access-token
    
  4. 인스턴스의 검색 엔드포인트에 연결합니다.

    redis-cli -h NETWORK_ADDRESS -p PORT -a ACCESS_TOKEN -c
    

    다음을 바꿉니다.

    • NETWORK_ADDRESS는 인스턴스의 네트워크 주소입니다. 네트워크 주소를 보려면 인스턴스 정보 보기를 참조하세요.

    • PORT는 인스턴스 포트 번호입니다. 포트 번호를 보려면 인스턴스 정보 보기를 참조하세요.

    • ACCESS_TOKEN은 이전 단계에서 가져온 IAM 액세스 토큰입니다.

  5. CLUSTER SHARDS 명령어를 실행하여 클러스터 토폴로지를 확인합니다. 노드의 IP 주소와 포트 번호 중 하나를 기록해 둡니다.

  6. 다음 명령어를 실행하여 원하는 노드에 연결합니다.

    redis-cli -h NODE_IP_ADDRESS -p NODE_PORT -a ACCESS_TOKEN -c
    

    다음을 바꿉니다.

    • NODE_IP_ADDRESS는 이전 단계에서 찾은 노드의 IP 주소입니다.
    • NODE_PORT는 이전 단계에서 찾은 노드의 포트 번호입니다.
  7. Redis SETGET 명령어를 실행하여 클러스터 노드에 인증된 연결을 설정했는지 확인합니다.

  8. Redis 인스턴스에 대한 연결 테스트를 완료한 후 Redis 클러스터에 연결하는 데 사용한 Compute Engine VM을 삭제하는 것을 고려해야 합니다. 이렇게 하면 Cloud Billing 계정에 비용이 청구되지 않습니다.

  9. 변수를 적절한 값으로 바꿔 다음 명령어를 실행해 redis-cli를 사용하여 인증하고 인스턴스에 연결합니다.

    redis-cli -h NETWORK_ADDRESS -p PORT -a ACCESS_TOKEN -c
    

    다음을 바꿉니다.

    • NETWORK_ADDRESS는 인스턴스의 네트워크 주소입니다. 네트워크 주소를 보려면 인스턴스 정보 보기를 참조하세요.

    • PORT는 인스턴스 포트 번호입니다. 포트 번호를 보려면 인스턴스 정보 보기를 참조하세요.

    • ACCESS_TOKEN은 이전 단계에서 가져온 IAM 액세스 토큰입니다.

  10. Redis SETGET 명령어를 실행하여 인스턴스에 인증된 연결을 설정했는지 확인합니다.

  11. Redis 클러스터에 대한 연결 테스트를 완료한 후 Redis 클러스터에 연결하는 데 사용한 Compute Engine VM을 삭제하는 것을 고려해야 합니다. 이렇게 하면 Cloud Billing 계정에 비용이 청구되지 않습니다.

액세스 토큰 가져오기 자동화

액세스 토큰은 수명이 짧아서 액세스 코드를 쉽게 하드 코딩할 수 없으므로 애플리케이션에서 액세스 토큰 가져오기를 자동화하는 것이 좋습니다.

  1. (선택사항) 아직 서비스 계정을 만들지 않은 경우 애플리케이션의 서비스 계정을 만듭니다(서비스 계정 만들기 및 관리 참조).

    gcloud iam service-accounts create SA_NAME \
        --description="DESCRIPTION" \
        --display-name="DISPLAY_NAME"
    

    다음을 바꿉니다.

    • SA_NAME은 서비스 계정의 이름입니다.
    • DESCRIPTION은 서비스 계정에 대한 설명입니다(선택사항).
    • DISPLAY_NAME은 Google Cloud 콘솔에 표시할 서비스 계정 이름입니다.
  2. 서비스 계정에 프로젝트에 대한 redis.dbConnectionUser 권한을 부여합니다.

    gcloud projects add-iam-policy-binding PROJECT_ID \
    --member="serviceAccount:SA_NAME@PROJECT_ID.iam.gserviceaccount.com" \
    --role="redis.dbConnectionUser"
    

    다음을 바꿉니다.

    • PROJECT_ID는 프로젝트 ID입니다.
    • SA_NAME은 서비스 계정의 이름입니다.
    • ROLE_NAME은 역할 이름입니다(예: roles/compute.osLogin).
  3. 지정된 서비스 계정으로 애플리케이션을 인증합니다. 자세한 내용은 서비스 계정을 참조하세요.

    널리 사용되는 클라이언트 라이브러리를 사용하여 애플리케이션을 인증하는 방법을 보여주는 코드 샘플은 IAM 인증 클라이언트 라이브러리 코드 샘플을 참조하세요.

IAM 인증 클라이언트 라이브러리 코드 샘플

이 섹션에서는 Lettuce 클라이언트 라이브러리를 사용하여 Memorystore 클러스터에 대해 IAM 인증으로 인증하는 클라이언트 코드의 일반적인 예시를 제공합니다.

Lettuce


public void example() {
  String discoveryEndpointIp = "insert discovery endpoint ip"
  String discoveryEndpointPort = "insert discovery endpoint port"
  RedisCredentialsProvider provider =
     () ->
           Mono.just(RedisCredentials.just("default", retrieveAccessToken().toCharArray()));
  RedisURI redisUri =
     RedisURI.Builder.redis(discoveryEndpointIp, discoveryEndpointPort)
           .withAuthentication(provider)
           .build();
  ClientResources resources =
     DefaultClientResources.builder()
           .reconnectDelay(
              Delay.fullJitter(
                 Duration.ofMillis(100),
                 Duration.ofSeconds(5),
                 100,
                 TimeUnit.MILLISECONDS))
           .build();
  ClusterTopologyRefreshOptions topologyRefreshOptions = ClusterTopologyRefreshOptions.builder()
     .enablePeriodicRefresh(1, TimeUnit.MINUTES)
     .enableAllAdaptiveRefreshTriggers()
     .dynamicRefreshSources(false)
     .closeStaleConnections(true)
     .build();

  SocketOptions socketOptions = SocketOptions.builder()
     .connectTimeout(Duration.ofSeconds(5))
     .keepAlive(true)
     .build();

  // Create Redis Cluster Client
  RedisClusterClient clusterClient = RedisClusterClient.create(resources, redisUri);
  clusterClient.setOptions(
     ClusterClientOptions.builder()
           .topologyRefreshOptions(topologyRefreshOptions)
           .socketOptions(socketOptions)
           .autoReconnect(true)
           .nodeFilter(
              it ->
                 !(it.is(RedisClusterNode.NodeFlag.FAIL)
                       || it.is(RedisClusterNode.NodeFlag.EVENTUAL_FAIL)
                       || it.is(RedisClusterNode.NodeFlag.NOADDR)))
           .validateClusterNodeMembership(false)
           .build());

  // Establish connection to Redis Cluster
  StatefulRedisClusterConnection connection = clusterClient.connect();
  // Retrieve synchronous Redis Cluster commands
  RedisAdvancedClusterCommands syncCommands = connection.sync();
  // Perform Redis operations
  syncCommands.set("key1", "value1");

  // Close the connection and shutdown the client
  connection.close();
  clusterClient.shutdown();
}