다음을 통해 공유


빈 벡터 검색 엔드포인트 식별 및 삭제

이 페이지에서는 빈 벡터 검색 엔드포인트를 식별하고 삭제하는 방법을 설명합니다. Vector Search 엔드포인트는 작업 영역별 리소스이므로 각 작업 영역에 대해 이 프로세스를 별도로 반복해야 합니다.

요구 사항

  • Python용 Databricks SDK(databricks-sdk).
  • Databricks Vector Search Python SDK(databricks-vectorsearch).
  • 구성된 인증(OAuth, PAT 또는 구성 프로필).
  • CAN_MANAGE 대상 작업 영역의 벡터 검색 엔드포인트에 대한 사용 권한입니다.

Databricks Notebook 또는 로컬 Python 환경에 필요한 SDK를 설치하려면 다음을 수행합니다.

# In a Databricks notebook
%pip install databricks-sdk databricks-vectorsearch

# In local Python environment
# pip install databricks-sdk databricks-vectorsearch

빈 엔드포인트 식별

Databricks UI에서 벡터 검색 엔드포인트는 컴퓨팅 화면의 벡터 검색 탭에 표시됩니다. 연결된 인덱 스가 없는 엔드포인트를 표시하려면 빈 엔드 포인트 확인란을 전환합니다. 빈 엔드포인트도 표시된 것처럼 경고 삼각형 아이콘으로 표시됩니다.

인덱스가 없는 벡터 검색 엔드포인트를 보여 주는 컴퓨팅 화면입니다.

Authentication

이 섹션에서는 인증 옵션에 대해 설명합니다.

옵션 1. Databricks Notebook 내에서 실행

Databricks 작업 영역 Notebook에서 코드를 실행하면 인증이 자동으로 수행됩니다.

from databricks.vector_search.client import VectorSearchClient

# Credentials are picked up automatically from notebook context
client = VectorSearchClient()

옵션 2. PAT(개인용 액세스 토큰)

외부 환경의 경우 명시적 자격 증명을 제공합니다.

from databricks.vector_search.client import VectorSearchClient

client = VectorSearchClient(
    workspace_url="https://<your-instance>.cloud.databricks.com",
    personal_access_token="dapiXXXXXXXXXXXXXXXXXXXXXXXX"
)

.databrickscfg 홈 디렉터리에 파일을 만들고 각 작업 영역에 대한 프로필을 포함합니다.

[DEFAULT]
host = https://workspace1.cloud.databricks.com
token = dapiXXXXXXXXXXXXXXXXXXXXXXXX

[PRODUCTION]
host = https://workspace2.cloud.databricks.com
token = dapiYYYYYYYYYYYYYYYYYYYYYYYY

[DEVELOPMENT]
host = https://workspace3.cloud.databricks.com
token = dapiZZZZZZZZZZZZZZZZZZZZZZZZ

구성 프로필을 사용하지 않으려는 경우 자격 증명을 직접 지정할 수 있습니다.

# Define workspaces with explicit credentials
workspace_configs = [
    {
        'workspace_url': 'https://workspace1.cloud.databricks.com',
        'token': 'dapiXXXXXXXXXXXXXXXXXXXXXXXX'
    },
    {
        'workspace_url': 'https://workspace2.cloud.databricks.com',
        'token': 'dapiYYYYYYYYYYYYYYYYYYYYYYYY'
    }
]

# Run cleanup, set `dry_run=False` to perform actual deletion
results = cleanup_multiple_workspaces(workspace_configs, dry_run=True)

단일 작업 영역에서 엔드포인트 삭제

벡터 검색 엔드포인트는 작업 영역별입니다. 다음은 단일 작업 영역에서 빈 엔드포인트를 찾아 삭제하는 기본 스크립트입니다. 여러 작업 영역에서 빈 엔드포인트를 정리하려면 여러 작업 영역에서 엔드포인트 삭제를 참조하세요.

중요합니다

엔드포인트 삭제는 되돌릴 수 없습니다. 이 옵션을 dry_run=True 사용하여 삭제할 엔드포인트 목록을 볼 수 있습니다. 목록이 올바른지 확인한 후에는 다음을 사용하여 스크립트 dry_run=False를 실행합니다.

from databricks.vector_search.client import VectorSearchClient

def cleanup_empty_endpoints(client, dry_run=True):
    """
    Find and delete empty Vector Search endpoints.

    Args:
        client: VectorSearchClient instance
        dry_run: If True, only print what would be deleted without actually deleting

    Returns:
        List of deleted endpoint names
    """
    deleted_endpoints = []

    # List all Vector Search endpoints
    endpoints = client.list_endpoints()

    for endpoint in endpoints["endpoints"]:
        # List indexes in this endpoint
        indexes = list(client.list_indexes(name=endpoint["name"])['vector_indexes'])

        if len(indexes) == 0:
            if dry_run:
                print(f"[DRY RUN] Would delete empty endpoint: '{endpoint["name"]}'")
            else:
                print(f"Deleting empty endpoint: '{endpoint["name"]}'")
                try:
                    client.delete_endpoint(endpoint["name"])
                    deleted_endpoints.append(endpoint["name"])
                    print(f"✓ Successfully deleted: {endpoint["name"]}")
                except Exception as e:
                    print(f"✗ Failed to delete {endpoint["name"]}: {str(e)}")
        else:
            print(f"Endpoint '{endpoint["name"]}' has {len(indexes)} indexes - keeping")

    return deleted_endpoints

# Example usage
client = VectorSearchClient()  # Uses default authentication
# Set `dry_run=False` when you are ready to delete endpoints
deleted = cleanup_empty_endpoints(client, dry_run=True)
print(f"\nTotal endpoints deleted: {len(deleted)}")

여러 작업 영역에서 엔드포인트 삭제

여러 작업 영역에서 빈 엔드포인트를 정리하려면 구성 프로필을 반복합니다.

중요합니다

  • 엔드포인트 삭제는 되돌릴 수 없습니다. 이 옵션을 dry_run=True 사용하여 삭제할 엔드포인트 목록을 볼 수 있습니다. 목록이 올바른지 확인한 후에는 다음을 사용하여 스크립트 dry_run=False를 실행합니다.

  • 많은 작업 영역을 처리할 때 API 속도 제한을 염두에 두어야 합니다. 필요한 경우 지연을 추가합니다.

    import time
    
    for config in workspace_configs:
        # Set `dry_run=False` to perform actual deletion
        result = cleanup_workspace(**config, dry_run=True)
        time.sleep(2)  # Add delay between workspaces
    
from databricks.sdk import WorkspaceClient
from databricks.vector_search.client import VectorSearchClient
import logging

# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

def cleanup_workspace(profile_name=None, workspace_url=None, token=None, dry_run=True):
    """
    Clean up empty endpoints in a specific workspace.

    Args:
        profile_name: Name of configuration profile to use
        workspace_url: Direct workspace URL (if not using profile)
        token: PAT token (if not using profile)
        dry_run: If True, only show what would be deleted

    Returns:
        Dict with cleanup results
    """
    try:
        # Initialize client based on authentication method
        if profile_name:
            # Use Databricks SDK to get credentials from profile
            w = WorkspaceClient(profile=profile_name)
            workspace_url = w.config.host
            client = VectorSearchClient(
                workspace_url=workspace_url,
                personal_access_token=w.config.token
            )
            logger.info(f"Connected to workspace using profile '{profile_name}': {workspace_url}")
        elif workspace_url and token:
            client = VectorSearchClient(
                workspace_url=workspace_url,
                personal_access_token=token
            )
            logger.info(f"Connected to workspace: {workspace_url}")
        else:
            # Use default authentication (notebook context)
            client = VectorSearchClient()
            logger.info("Connected using default authentication")

        # Perform cleanup
        deleted = cleanup_empty_endpoints(client, dry_run=dry_run)

        return {
            'workspace': workspace_url or 'default',
            'success': True,
            'deleted_count': len(deleted),
            'deleted_endpoints': deleted
        }

    except Exception as e:
        logger.error(f"Failed to process workspace: {str(e)}")
        return {
            'workspace': workspace_url or profile_name or 'default',
            'success': False,
            'error': str(e)
        }

def cleanup_multiple_workspaces(workspace_configs, dry_run=True):
    """
    Clean up empty endpoints across multiple workspaces.

    Args:
        workspace_configs: List of workspace configurations
        dry_run: If True, only show what would be deleted

    Returns:
        Summary of cleanup results
    """
    results = []

    for config in workspace_configs:
        logger.info(f"\n{'='*60}")
        result = cleanup_workspace(**config, dry_run=dry_run)
        results.append(result)
        logger.info(f"{'='*60}\n")

    # Print summary
    total_deleted = sum(r['deleted_count'] for r in results if r['success'])
    successful = sum(1 for r in results if r['success'])
    failed = sum(1 for r in results if not r['success'])

    logger.info("\n" + "="*60)
    logger.info("CLEANUP SUMMARY")
    logger.info("="*60)
    logger.info(f"Workspaces processed: {len(results)}")
    logger.info(f"Successful: {successful}")
    logger.info(f"Failed: {failed}")
    logger.info(f"Total endpoints deleted: {total_deleted}")

    if failed > 0:
        logger.warning("\nFailed workspaces:")
        for r in results:
            if not r['success']:
                logger.warning(f"  - {r['workspace']}: {r['error']}")

    return results

# Example: Clean up using configuration profiles
workspace_configs = [
    {'profile_name': 'DEFAULT'},
    {'profile_name': 'PRODUCTION'},
    {'profile_name': 'DEVELOPMENT'}
]

# Set `dry_run=False` to do actual deletion.
results = cleanup_multiple_workspaces(workspace_configs, dry_run=True)

사용자 지정 필터링

다음과 같이 삭제에서 특정 엔드포인트를 제외하는 사용자 지정 논리를 추가할 수 있습니다.

def should_delete_endpoint(endpoint, indexes):
    """
    Custom logic to determine if an endpoint should be deleted.

    Args:
        endpoint: Endpoint object
        indexes: List of indexes in the endpoint

    Returns:
        Boolean indicating if endpoint should be deleted
    """
    # Don't delete if it has indexes
    if len(indexes) > 0:
        return False

    # Don't delete endpoints with specific naming patterns
    protected_patterns = ['prod-', 'critical-', 'do-not-delete']
    for pattern in protected_patterns:
        if pattern in endpoint.name.lower():
            logger.warning(f"Skipping protected endpoint: {endpoint.name}")
            return False

    # Add more custom logic as needed
    return True

결과 내보내기

감사를 위해 정리 결과를 파일에 저장하려면 다음을 수행합니다.

import json
from datetime import datetime

def export_results(results, filename=None):
    """Export cleanup results to JSON file."""
    if not filename:
        timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
        filename = f'vector_search_cleanup_{timestamp}.json'

    with open(filename, 'w') as f:
        json.dump({
            'timestamp': datetime.now().isoformat(),
            'results': results
        }, f, indent=2)

    logger.info(f"Results exported to: {filename}")

Troubleshooting

인증 문제

  • PAT 토큰이 유효하고 만료되지 않았는지 확인합니다.
  • 구성 프로필의 형식이 올바르게 지정되었는지 확인합니다.
  • 토큰에 필요한 권한이 있는지 확인합니다.

권한 오류

사용자 또는 서비스 주체에게 CAN_MANAGE Vector Search 엔드포인트에 대한 권한이 있는지 확인합니다.

네트워크 문제

프록시 요구 사항이 있는 환경의 경우 SDK를 적절하게 구성합니다.

import os
os.environ['HTTPS_PROXY'] = 'http://your-proxy:po

다음 단계

  • Lakeflow 작업을 사용하여 주기적으로 실행되도록 이 스크립트를 예약합니다.
  • 코드로서의 인프라 파이프라인과 통합합니다.
  • 정리 요약을 위한 전자 메일 또는 Slack 알림을 추가합니다.
  • 작업 영역에서 엔드포인트 사용량을 추적하는 대시보드를 만듭니다.