콘텐츠로 이동

Pub/Sub를 통해 Google Cloud 로그에 액세스

Cloud Logging Sink를 사용하여 애플리케이션 로그를 필터링한 후 Pub/Sub, Cloud Run, DataKit을 통해 Guance로 보냅니다. 이 문서에서는 비공개 네트워크 호스트에 배포된 독립형 DataKit을 사용하며 GKE가 필요하지 않습니다. 포워더는 jsonPayload 및 textPayload를 지원하고 감사 로그 protoPayload를 지원하지 않습니다.

Cloud Logging 싱크 → Pub/Sub → Cloud Run Forwarder → Private DataKit → Guance.

트랜스폰더 소스 코드 및 README는 Apache License 2.0에 따라 공개적으로 제공됩니다. DataWay 주소와 토큰은 DataKit에만 저장되며 이러한 자격 증명은 전달자에게 필요하지 않습니다.

준비

  • Cloud Shell을 사용하거나 gcloud 및 Git을 설치하고 Google Cloud에 로그인하세요. 프로젝트에 결제가 활성화되어 있어야 합니다.
  • 현재 계정에는 API 사용 설정, 서비스 계정 생성, 로그 읽기 및 쓰기, 싱크, Pub/Sub, 방화벽 규칙 관리, Cloud Run 배포, IAM 구성을 위한 권한이 필요합니다. 또한 아래에 생성된 빌드, 실행 및 푸시 계정에 대한 iam.serviceAccounts.actAs 권한이 있어야 합니다.
  • 비공개 네트워크를 통해 DataKit 호스트에 액세스할 수 있도록 Cloud Run이 있는 지역에 /26 이상의 더 큰 VPC 서브넷을 준비합니다. 네트워크 요구 사항은 Direct VPC egress를 참조하세요.
  • 방화벽 예시에서는 동일한 VPC의 동일한 프로젝트에 있는 Compute Engine 가상 머신을 사용합니다. 다른 사설 네트워크 호스트를 사용하는 경우 먼저 네트워크 관리자에게 해당 라우팅 및 방화벽 규칙을 구성하도록 하십시오.

다음 변수를 바꿉니다. 모든 gcloud 명령은 동일한 터미널에서 실행되며 DataKit의 설치 및 구성은 해당 호스트 시스템에서 완료됩니다. 이 예에서는 동일한 프로젝트에 새 리소스를 만듭니다. 비어 있는 이름을 사용하거나, 기사 내 리소스 이름을 통일적으로 수정하시기 바랍니다.

PROJECT_ID="my-project"
REGION="us-central1"
NETWORK="my-vpc"
SUBNET="cloud-run-subnet"
DATAKIT_IPV4="10.0.1.10"
DATAKIT_VM="datakit-vm"
DATAKIT_ZONE="us-central1-a"

gcloud services enable run.googleapis.com pubsub.googleapis.com \
  logging.googleapis.com cloudbuild.googleapis.com artifactregistry.googleapis.com \
  compute.googleapis.com iam.googleapis.com --project "$PROJECT_ID"

PROJECT_NUMBER=$(gcloud projects describe "$PROJECT_ID" --format='value(projectNumber)')

1. DataKit 설정

Guance 작업공간에서 설치 명령을 받아 개인 네트워크 호스트 데이터킷 설치에서 실행합니다. 호스트는 워크스페이스에 해당하는 DataWay 주소에 접근할 수 있어야 합니다.

datakit.conf에서 [http_api]의 기존 수신 주소를 호스트의 개인 IPv4 주소로 변경합니다.

[http_api]
  listen = "10.0.1.10:9529"

이 주소는 DATAKIT_IPV4와 일치해야 합니다. DataKit 다시 시작를 저장한 후. TCP 9529는 Cloud Run 서브넷 및 지정된 관리 소스에서의 액세스만 허용하며 이를 공용 네트워크에 노출하지 않습니다.

Compute Engine VM에 대상 태그를 추가하고 Cloud Run 서브넷을 허용합니다.

SUBNET_CIDR=$(gcloud compute networks subnets describe "$SUBNET" \
  --project "$PROJECT_ID" --region "$REGION" --format='value(ipCidrRange)')
gcloud compute instances add-tags "$DATAKIT_VM" \
  --project "$PROJECT_ID" --zone "$DATAKIT_ZONE" --tags pubsub-datakit
gcloud compute firewall-rules create allow-pubsub-datakit \
  --project "$PROJECT_ID" --network "$NETWORK" --direction INGRESS \
  --action ALLOW --rules tcp:9529 --target-tags pubsub-datakit \
  --source-ranges "${SUBNET_CIDR:?Subnet CIDR is required}"

호스트 방화벽이 활성화된 경우 동일한 서브넷도 허용하고 기존 규칙이 다른 소스를 허용하는지 확인해야 합니다. DataKit 호스트에서 다음 명령을 실행하여 수신 대기를 확인하고 예제 IP를 바꿉니다. HTTP 200을 반환할 것으로 예상됩니다. 5단계에서는 DataKit에 대한 Cloud Run의 연결을 확인합니다.

curl -i --fail --show-error --max-time 5 "http://10.0.1.10:9529/v1/ping"

전달자는 로그 스트리밍 수집기를 추가로 열지 않고 /v1/write/logging를 통해 JSON 레코드를 작성합니다. 대상 주소는 10.0.0.0/8, 172.16.0.0/12 또는 192.168.0.0/16 네트워크 세그먼트 내에 있어야 합니다.

2. 포워더 배포

gcloud가 실행된 터미널로 돌아가 각각 빌드, 실행, 푸시 계정을 생성합니다. 빌드 계정에만 roles/run.builder를 부여하고 배포 시 명시적으로 지정하세요. 배포 담당자에게 필요한 권한은 서비스 계정 만들기를 참조하세요.

gcloud iam service-accounts create forwarder-build --project "$PROJECT_ID"
gcloud iam service-accounts create forwarder-run --project "$PROJECT_ID"
gcloud iam service-accounts create forwarder-push --project "$PROJECT_ID"

gcloud projects add-iam-policy-binding "$PROJECT_ID" \
  --member "serviceAccount:forwarder-build@${PROJECT_ID}.iam.gserviceaccount.com" \
  --role roles/run.builder

git clone https://github.com/TrueWatchTech/google-cloud-log-forwarder.git
cd google-cloud-log-forwarder

cat > env.yaml <<EOF
DATAKIT_URL: "http://${DATAKIT_IPV4}:9529/v1/write/logging"
EXPECTED_PROJECT_ID: "${PROJECT_ID}"
EXPECTED_SUBSCRIPTION: "projects/${PROJECT_ID}/subscriptions/application-logs-push"
MEASUREMENT: "gcp_pubsub"
EOF

gcloud run deploy pubsub-log-forwarder \
  --source . --project "$PROJECT_ID" --region "$REGION" \
  --no-allow-unauthenticated \
  --build-service-account "projects/${PROJECT_ID}/serviceAccounts/forwarder-build@${PROJECT_ID}.iam.gserviceaccount.com" \
  --service-account "forwarder-run@${PROJECT_ID}.iam.gserviceaccount.com" \
  --network "$NETWORK" --subnet "$SUBNET" --vpc-egress private-ranges-only \
  --cpu 1 --memory 512Mi --min-instances 0 --max-instances 1 --concurrency 1 \
  --env-vars-file env.yaml

배포가 성공하고 서비스 URL이 표시될 때까지 기다립니다. 승인 직후 권한 오류가 발생하는 경우 배포 명령을 실행하기 전에 IAM 변경 사항이 적용될 때까지 몇 분 정도 기다리십시오. env.yaml에 자격 증명을 추가하지 마십시오. 위 CPU, 메모리, 인스턴스 수는 시작 구성일 뿐이며 생산을 위한 최소 사양을 측정한 것이 아니며 실제 부하 테스트를 기준으로 조정되어야 합니다.

3. 인증된 푸시 설정

이 Cloud Run 서비스에만 호출자 권한을 부여하세요. Pub/Sub 서비스 프록시가 생성되었는지 확인하고 푸시 계정에 대한 토큰을 생성하도록 허용한 후 구독을 생성합니다.

SERVICE_URL=$(gcloud run services describe pubsub-log-forwarder \
  --project "$PROJECT_ID" --region "$REGION" --format='value(status.url)')

gcloud run services add-iam-policy-binding pubsub-log-forwarder \
  --project "$PROJECT_ID" --region "$REGION" \
  --member "serviceAccount:forwarder-push@${PROJECT_ID}.iam.gserviceaccount.com" \
  --role roles/run.invoker

gcloud pubsub topics create application-logs --project "$PROJECT_ID"
gcloud beta services identity create \
  --service pubsub.googleapis.com --project "$PROJECT_ID"
gcloud iam service-accounts add-iam-policy-binding \
  "forwarder-push@${PROJECT_ID}.iam.gserviceaccount.com" \
  --project "$PROJECT_ID" \
  --member "serviceAccount:service-${PROJECT_NUMBER}@gcp-sa-pubsub.iam.gserviceaccount.com" \
  --role roles/iam.serviceAccountTokenCreator

gcloud pubsub subscriptions create application-logs-push \
  --project "$PROJECT_ID" --topic application-logs --ack-deadline 60 \
  --push-endpoint "${SERVICE_URL}/pubsub" \
  --push-auth-service-account "forwarder-push@${PROJECT_ID}.iam.gserviceaccount.com" \
  --push-auth-token-audience "$SERVICE_URL"

페이로드 언래핑을 유지하려면 전달자에 전체 Pub/Sub JSON 메시지 캡슐화가 필요합니다. OIDC 토큰은 Cloud Run에서 확인되며 ID 인증 및 호출자 IAM 확인을 사용 설정해야 합니다. 자세한 내용은 인증 푸시 요구 사항를 참조하세요.

4. 테스트용 Sink 생성

먼저, 테스트 중에 관련 없는 로그가 전달되지 않도록 전용 로그 ID pubsub-guide-demo에만 액세스하세요.

gcloud logging sinks create application-logs \
  "pubsub.googleapis.com/projects/${PROJECT_ID}/topics/application-logs" \
  --project "$PROJECT_ID" \
  --log-filter="logName=\"projects/${PROJECT_ID}/logs/pubsub-guide-demo\" AND (jsonPayload:* OR textPayload:*)"

SINK_WRITER=$(gcloud logging sinks describe application-logs \
  --project "$PROJECT_ID" --format='value(writerIdentity)')

gcloud pubsub topics add-iam-policy-binding application-logs \
  --project "$PROJECT_ID" --member "$SINK_WRITER" --role roles/pubsub.publisher

싱크 구성이 완료되면 조건에 맞는 새로운 로그가 전송되며, 기록 로그는 재생되지 않습니다. 먼저 다음 샘플 확인을 완료한 후 실제 애플리케이션 로그를 선택하세요. 자세한 내용은 로그 라우팅를 참조하세요.

5. 로그 저장 확인

테스트 로그에 JSON 및 일반 텍스트 로그를 작성합니다.

TEST_ID="pubsub-$(date -u +%Y%m%dT%H%M%SZ)"
gcloud logging write pubsub-guide-demo \
  "{\"message\":\"${TEST_ID}-json\"}" \
  --payload-type=json --severity=INFO --project "$PROJECT_ID"
gcloud logging write pubsub-guide-demo "${TEST_ID}-text" \
  --payload-type=text --severity=INFO --project "$PROJECT_ID"

테스트 로그 및 전달자 처리 기록 읽기:

gcloud logging read \
  "logName=\"projects/${PROJECT_ID}/logs/pubsub-guide-demo\" AND SEARCH(\"${TEST_ID}\")" \
  --project "$PROJECT_ID" --freshness=1h --limit=10 --format=json
gcloud logging read \
  "resource.type=\"cloud_run_revision\" AND resource.labels.service_name=\"pubsub-log-forwarder\" AND resource.labels.location=\"${REGION}\" AND jsonPayload.receipt:*" \
  --project "$PROJECT_ID" --freshness=1h --limit=20 --format=json
  1. 첫 번째 명령은 두 개의 테스트 로그를 반환해야 하며 각각의 insertId, timestamp 및 로그 내용을 기록해 두어야 합니다. 아직 결과가 없다면 잠시 기다렸다가 다시 시도해 보세요.
  2. 두 번째 명령으로 반환된 jsonPayload에서 해당 google_insert_id를 찾아 http_status가 204이고 datakit_status가 2xx인지 확인합니다. 실패할 경우 reason 및 FAQ 표에 따라 문제를 해결하세요.
  3. Guance의 로그 페이지에서 소스 gcp_pubsub와 적용되는 테스트 시간 범위를 선택하고 google_insert_id를 눌러 각각 기록을 검색합니다.
  4. 두 레코드의 메시지 내용이 올바른지, log_timestamp가 원래 시간과 일치하는지 확인하세요. JSON 로그의 message는 JSON 문자열이며 일반 텍스트 로그는 원본 텍스트를 유지합니다.

Cloud Run이 204를 반환하거나 DataKit이 2xx를 반환한다고 해서 데이터베이스에 저장되었다는 의미는 아닙니다. Guance에서 두 개의 로그를 찾아야 합니다. 프로덕션에서 사용하기 전에 처리량, 안정성, 리소스 사양 및 애플리케이션 오버헤드를 실제 부하에서 테스트해야 합니다.

6. 실제 애플리케이션 로그로 전환

Cloud Logging에서 애플리케이션 로그를 쿼리할 수 있는지 확인한 후 테스트 필터 조건을 교체하세요. 다음 GKE 예시에서는 애플리케이션 컨테이너의 stdout 및 stderr에만 액세스합니다. 비즈니스 컨테이너만 선택하고 DataKit을 제외하려면 클러스터, 네임스페이스 및 컨테이너 이름을 바꾸십시오. k8s_container 조건은 Cloud Run 전달자도 제외합니다.

APP_FILTER=$(cat <<'EOF'
resource.type="k8s_container"
resource.labels.cluster_name="my-cluster"
resource.labels.namespace_name="my-namespace"
resource.labels.container_name="my-app"
(log_id("stdout") OR log_id("stderr"))
(jsonPayload:* OR textPayload:*)
EOF
)
gcloud logging read "$APP_FILTER" \
  --project "$PROJECT_ID" --freshness=1h --limit=5 --format=json

쿼리 결과에 예상된 애플리케이션 로그만 포함되어 있는지 확인하세요. 결과가 없으면 먼저 애플리케이션이 로그를 생성하도록 하고 로그 탐색기에서 필터를 확인하세요. 비GKE 애플리케이션은 대신 해당 리소스 유형과 애플리케이션 태그를 사용해야 합니다. 확인 후 싱크 업데이트:

gcloud logging sinks update application-logs \
  --project "$PROJECT_ID" --log-filter="$APP_FILTER"

업데이트가 적용된 후 애플리케이션이 새 로그를 생성하도록 하고 APP_FILTER를 사용하여 Cloud Logging에서 찾은 다음 5단계에 따라 Guance의 기록으로 식별, 시간, 메시지 내용을 확인합니다. 현재 pubsub-guide-demo 테스트 로그는 더 이상 싱크와 일치하지 않습니다. 전달 루프를 방지하려면 필터 범위에서 항상 전달자와 DataKit 자체 로그를 제외해야 합니다.

필드 매핑

각 Cloud Logging 로그는 DataKit 로그로 변환됩니다. 기본 소스는 MEASUREMENT에 의해 설정된 gcp_pubsub입니다.

Cloud Logging 콘텐츠 DataKit 콘텐츠
jsonPayload 또는 textPayload message: 압축 JSON 문자열 또는 원시 텍스트
timestamp Unix 나노초 기록 시간 및 log_timestamp에 원래 문자열 보존
receiveTimestamp 존재하는 경우 receive_timestamp 작성
insertId 태그 google_insert_id
logName의 프로젝트 ID 태그 project는 EXPECTED_PROJECT_ID와 일치해야 합니다.
logName의 로그 ID 태그 log_name, URL 디코딩됨
resource.type resource_type를 태그하거나, 누락된 경우 unknown를 태그하세요.
severity 태그 severity 및 필드 status

status에서 DEFAULT 및 INFO는 info로 변환되고, EMERGENCY는 emerg로 변환되며, 다른 레벨은 소문자로 변환됩니다. JSON 콘텐츠는 자동으로 독립 필드로 확장되지 않으며 리source 라벨이 매핑되지 않습니다.

자주 묻는 질문

현상 확인항목
Cloud Run 배포 실패 빌드 권한, 서브넷 영역 및 나머지 주소
푸시 반환 401 또는 403 푸시 서비스 계정, 서비스 수준 호출자 권한, OIDC 대상 및 토큰 생성 권한 전달자가 403을 반환하면 reason, EXPECTED_PROJECT_ID 및 EXPECTED_SUBSCRIPTION도 확인해야 합니다.
전달자가 400 또는 413을 반환합니다. 로그 유형 및 크기, 필수 insertId, logName, timestamp 및 페이로드 래핑 해제 설정
전달자가 502를 반환합니다. DataKit 수신 주소, VPC 경로, TCP 9529 방화벽 규칙 및 DataKit 쓰기 응답
작업공간에 로그가 없습니다. 싱크 필터 및 게시 권한, 구독 전달 상태, DataKit에서 DataWay로의 연결, 작업 공간 및 쿼리 시간 범위

푸시 요청 본문은 1MiB로 제한되고 변환된 레코드는 512KiB로 제한됩니다. Pub/Sub는 전송을 한 번 이상 사용하며 재시도하면 중복 레코드가 생성될 수 있습니다. google_insert_id는 용이한 상관 관계를 위해 유지되지만 자동으로 중복 제거되지는 않습니다.

확인되지 않은 메시지는 구독 보존 기간이 지나면 만료될 수 있습니다. 구독 백로그를 모니터링해야 하며 반복적으로 전달되지 않는 메시지를 처리하기 위해 필요에 따라 데드 레터 주제를 구성해야 합니다.

문서 평가

이 페이지가 도움이 되었나요?