중앙 로그 서버를 사용하면 Google Distributed Cloud 에어 갭 데이터 센터 조직을 통해 단일 위치에서 Google Distributed Cloud(GDC) 에어 갭 어플라이언스 기기의 로그를 집계, 저장, 쿼리할 수 있습니다.
이 중앙 집중식 로깅 환경을 설정하려면 데이터 센터 조직에서 감사 및 운영 로그를 위한 전용 프로젝트와 별도의 대상 버킷을 만듭니다. GDC 어플라이언스에서 해당 버킷으로 로그를 내보낸 후 데이터 센터 조직에서 Loki 및 Grafana 데이터 소스를 구성하여 내보낸 로그를 확인합니다.
프로젝트 만들기
로그를 내보낼 GDC 데이터 센터 조직에서 다음 단계를 수행해야 합니다.
KUBECONFIG를 Org Management API로 설정합니다.export KUBECONFIG=ORG_MANAGEMENT_API_KUBECONFIG_PATH로그를 내보내는 데 필요한 권한을 얻으려면 조직 IAM 관리자에게 ClusterRole 프로젝트 생성자(
ClusterRole project-creator) 역할을 부여해 달라고 요청하세요. 이러한 역할에 대한 자세한 내용은 IAM 권한 준비를 참조하세요.프로젝트 커스텀 리소스를 적용하여 로그를 내보낼 GDC 어플라이언스의 고유한 프로젝트를 만듭니다.
kubectl apply -f - <<EOF apiVersion: resourcemanager.gdc.goog/v1 kind: Project metadata: namespace: platform name: APPLIANCE_PROJECT_NAME labels: object.gdc.goog/tenant-category: user EOFGDC 어플라이언스에서 새 프로젝트를 사용할 수 있는지 확인합니다.
kubectl get namespace APPLIANCE_PROJECT_NAME새 프로젝트를 결제 계정에 연결합니다. 프로젝트 리소스 비용을 추적하려면 프로젝트에 연결된 결제 계정이 있어야 합니다.
로그를 내보내는 데 필요한 권한을 얻으려면 조직 IAM 관리자에게 네임스페이스
APPLIANCE_PROJECT_NAME의 프로젝트 IAM 관리자(project-iam-admin) 역할을 부여해 달라고 요청하세요.
버킷 만들기
다음 단계는 로그를 내보낼 GDC 데이터 센터 조직의 플랫폼 관리자(PA)가 수행해야 합니다.
KUBECONFIG를 Org Management API로 설정합니다.export KUBECONFIG=ORG_MANAGEMENT_API_KUBECONFIG_PATH로그를 내보내는 데 필요한 권한을 얻으려면 조직 IAM 관리자에게
APPLIANCE_PROJECT_NAME네임스페이스의 프로젝트 버킷 관리자(project-bucket-admin) 역할을 부여해 달라고 요청하세요.버킷 커스텀 리소스를 적용하여 버킷을 만듭니다.
apiVersion: object.gdc.goog/v1 kind: Bucket metadata: name: BUCKET_NAME namespace: APPLIANCE_PROJECT_NAME labels: object.gdc.goog/bucket-type: normal object.gdc.goog/encryption-version: v2 object.gdc.goog/tenant-category: user spec: description: Bucket for storing appliance xyz audit logs location: zone1 storageClass: Standard버킷이 생성되면 다음을 실행하여 버킷의 세부정보를 확인합니다.
kubectl describe buckets BUCKET_NAME -n APPLIANCE_PROJECT_NAME버킷의 객체에 액세스하기 위한
ProjectServiceAccount를 만듭니다.kubectl apply -f - <<EOF --- apiVersion: resourcemanager.gdc.goog/v1 kind: ProjectServiceAccount metadata: name: BUCKET_NAME-read-write-sa namespace: APPLIANCE_PROJECT_NAME spec: {} EOFProjectServiceAccount가 전파되었는지 확인합니다.kubectl get projectserviceaccount BUCKET_NAME-read-write-sa -n APPLIANCE_PROJECT_NAME -o json | jq '.status'ServiceAccount에 버킷에 대한read및write권한이 추가되었는지 확인합니다.kubectl apply -f - <<EOF --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: BUCKET_NAME-read-write-role namespace: APPLIANCE_PROJECT_NAME rules: - apiGroups: - object.gdc.goog resourceNames: - BUCKET_NAME resources: - buckets verbs: - read-object - write-object --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: BUCKET_NAME-read-write-rolebinding namespace: APPLIANCE_PROJECT_NAME roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: BUCKET_NAME-read-write-role subjects: - kind: ServiceAccount name: BUCKET_NAME-read-write-sa namespace: APPLIANCE_PROJECT_NAME EOF버킷의 액세스 사용자 인증 정보가 포함된 보안 비밀을 가져옵니다.
kubectl get secret -n APPLIANCE_PROJECT_NAME -o json| jq --arg jq_src BUCKET_NAME-read-write-sa '.items[].metadata|select(.annotations."object.gdc.goog/subject"==$jq_src)|.name'출력은 버킷의 보안 비밀 이름이 표시되는 다음 예시와 같이 표시되어야 합니다.
"object-storage-key-sysstd-sa-olxv4dnwrwul4bshu37ikebgovrnvl773owaw3arx225rfi56swa"값을 변수로 내보냅니다.
export BUCKET_RW_SECRET_NAME=BUCKET_RW_SECRET_NAME버킷 액세스를 위한 키 ID를 가져옵니다.
kubectl get secret $BUCKET_RW_SECRET_NAME -n appliance-xyz -o json | jq -r '.data."access-key-id"' | base64 -di출력은 다음 예시와 같이 표시됩니다.
PCEW2HU47Y8ACUWQO4SK버킷의 보안 비밀 액세스 키를 가져옵니다.
kubectl get secret $BUCKET_RW_SECRET_NAME -n appliance-xyz -o json | jq -r '.data."secret-access-key"' | base64 -di출력은 다음 예시와 같이 표시됩니다.
TzGdAbgp4h2i5UeiYa9k09rNPFQ2tkYADs67+65E버킷의 엔드포인트를 가져옵니다.
kubectl get bucket BUCKET_NAME -n APPLIANCE_PROJECT_NAME -o json | jq '.status.endpoint'출력은 다음 예시와 같이 표시됩니다.
https://objectstorage.org-1.zone1.google.gdch.test버킷의 정규화된 이름을 가져옵니다.
kubectl get bucket BUCKET_NAME -n APPLIANCE_PROJECT_NAME -o json | jq '.status.fullyQualifiedName'출력은 다음 예시와 같이 표시됩니다.
aaaoa9a-logs-bucket
GDC에서 데이터 전송
원격 버킷으로 로그 내보내기에 따라 GDC 어플라이언스에서 GDC 에어 갭 적용 데이터 센터에 이전에 만든 버킷으로 로그를 전송합니다. 이때 버킷의 엔드포인트, 정규화된 이름, 액세스 키 ID, 보안 비밀 액세스 키를 사용합니다.
Google Distributed Cloud 에어 갭 데이터 센터에서 Loki 및 Grafana 설정
로그를 내보낸 GDC 에어 갭 데이터 센터 조직의 인프라 운영자(IO)가 다음 단계를 수행해야 합니다.
IAM 역할 획득
로그를 내보내는 데 필요한 권한을 얻으려면 조직 IAM 관리자에게 인프라 클러스터의 obs-system 네임스페이스에 있는 로그 복원 관리자(logs-restore-admin) 역할과 관리 영역의 obs-system 네임스페이스에 있는 데이터 소스 뷰어(datasource-viewer) 및 데이터 소스 편집자(datasource-editor) 역할을 부여해 달라고 요청하세요.
Loki 설정
KUBECONFIG를 조직 인프라 클러스터로 설정합니다.export KUBECONFIG=ORG_INFRA_CLUSTER_KUBECONFIG_PATHPA에서 어플라이언스 로그 버킷의 액세스 키 ID와 보안 비밀 액세스 키를 가져오고
obs-system네임스페이스에 사용자 인증 정보가 포함된 보안 비밀을 만듭니다.kubectl create secret generic -n obs-system APPLIANCE_LOGS_BUCKET_SECRET_NAME --from-literal=access-key-id=APPLIANCE_LOGS_BUCKET_ACCESS_KEY_ID --from-literal=secret-access-key=APPLIANCE_LOGS_BUCKET_SECRET_ACCESS_KEYPA에서 어플라이언스 로그 버킷의 엔드포인트와 정규화된 이름을 가져와 Loki
configmap를 만듭니다.kubectl apply -f - <<EOF --- apiVersion: v1 kind: ConfigMap metadata: name: CONFIGMAP_NAME namespace: obs-system data: loki.yaml: |- auth_enabled: true common: ring: kvstore: store: inmemory compactor: working_directory: /data/loki/compactor compaction_interval: 10m retention_enabled: true retention_delete_delay: 2h retention_delete_worker_count: 150 delete_request_store: s3 ingester: chunk_target_size: 1572864 chunk_encoding: snappy max_chunk_age: 2h chunk_idle_period: 90m chunk_retain_period: 30s autoforget_unhealthy: true lifecycler: ring: kvstore: store: inmemory replication_factor: 1 heartbeat_timeout: 10m wal: enabled: false limits_config: discover_service_name: [] retention_period: 48h reject_old_samples: false ingestion_rate_mb: 256 ingestion_burst_size_mb: 256 max_streams_per_user: 20000 max_global_streams_per_user: 20000 max_line_size: 0 per_stream_rate_limit: 256MB per_stream_rate_limit_burst: 256MB shard_streams: enabled: false desired_rate: 3MB schema_config: configs: - from: "2020-10-24" index: period: 24h prefix: index_ object_store: s3 schema: v13 store: tsdb server: http_listen_port: 3100 grpc_server_max_recv_msg_size: 104857600 grpc_server_max_send_msg_size: 104857600 graceful_shutdown_timeout: 60s analytics: reporting_enabled: false storage_config: tsdb_shipper: active_index_directory: /tsdb/index cache_location: /tsdb/index-cache cache_ttl: 24h aws: endpoint: APPLIANCE_LOGS_BUCKET_ENDPOINT bucketnames: APPLIANCE_LOGS_BUCKET_FULLY_QUALIFIED_NAME access_key_id: ${S3_ACCESS_KEY_ID} secret_access_key: ${S3_SECRET_ACCESS_KEY} s3forcepathstyle: true --- EOFLoki
statefulset및 서비스를 만듭니다.kubectl apply -f - <<EOF --- apiVersion: apps/v1 kind: StatefulSet metadata: labels: app: STATEFULSET_NAME name: STATEFULSET_NAME namespace: obs-system spec: persistentVolumeClaimRetentionPolicy: whenDeleted: Retain whenScaled: Retain podManagementPolicy: OrderedReady replicas: 1 revisionHistoryLimit: 10 selector: matchLabels: app: STATEFULSET_NAME serviceName: STATEFULSET_NAME template: metadata: labels: app: STATEFULSET_NAME istio.io/rev: default spec: affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - preference: matchExpressions: - key: node-role.kubernetes.io/control-plane operator: DoesNotExist - key: node-role.kubernetes.io/master operator: DoesNotExist weight: 1 podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - podAffinityTerm: labelSelector: matchExpressions: - key: app operator: In values: - STATEFULSET_NAME topologyKey: kubernetes.io/hostname weight: 100 containers: - args: - -config.file=/etc/loki/loki.yaml - -config.expand-env=true - -target=all env: - name: S3_ACCESS_KEY_ID valueFrom: secretKeyRef: key: access-key-ID name: APPLIANCE_LOGS_BUCKET_SECRET_NAME optional: false - name: S3_SECRET_ACCESS_KEY valueFrom: secretKeyRef: key: secret-access-key name: APPLIANCE_LOGS_BUCKET_SECRET_NAME optional: false image: gcr.io/private-cloud-staging/loki:v3.0.1-gke.1 imagePullPolicy: Always livenessProbe: failureThreshold: 3 httpGet: path: /ready port: loki-server scheme: HTTP initialDelaySeconds: 330 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 name: STATEFULSET_NAME ports: - containerPort: 3100 name: loki-server protocol: TCP - containerPort: 7946 name: gossip-ring protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /ready port: loki-server scheme: HTTP initialDelaySeconds: 45 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 resources: limits: ephemeral-storage: 2000Mi memory: 8000Mi requests: cpu: 300m ephemeral-storage: 2000Mi memory: 1000Mi securityContext: readOnlyRootFilesystem: true terminationMessagePath: /dev/termination-log terminationMessagePolicy: File volumeMounts: - mountPath: /etc/loki name: config - mountPath: /data name: loki-storage - mountPath: /tsdb name: loki-tsdb-storage - mountPath: /tmp name: temp - mountPath: /tmp/loki/rules-temp name: tmprulepath - mountPath: /etc/ssl/certs name: trust-bundle readOnly: true dnsPolicy: ClusterFirst restartPolicy: Always schedulerName: default-scheduler securityContext: fsGroup: 10001 runAsGroup: 10001 runAsUser: 10001 terminationGracePeriodSeconds: 4800 volumes: - emptyDir: {} name: temp - emptyDir: {} name: tmprulepath - configMap: defaultMode: 420 name: trust-store-root-ext optional: true name: trust-bundle - configMap: defaultMode: 420 name: CONFIGMAP_NAME name: config updateStrategy: type: RollingUpdate volumeClaimTemplates: - apiVersion: v1 kind: PersistentVolumeClaim metadata: creationTimestamp: null name: loki-storage spec: accessModes: - ReadWriteOnce resources: requests: storage: 5Gi storageClassName: standard-rwo volumeMode: Filesystem - apiVersion: v1 kind: PersistentVolumeClaim metadata: creationTimestamp: null name: loki-tsdb-storage spec: accessModes: - ReadWriteOnce resources: requests: storage: 5Gi storageClassName: standard-rwo volumeMode: Filesystem --- apiVersion: v1 kind: Service metadata: name: STATEFULSET_NAME namespace: obs-system spec: internalTrafficPolicy: Cluster ipFamilies: - IPv4 ipFamilyPolicy: SingleStack ports: - name: loki-server port: 3100 protocol: TCP targetPort: loki-server selector: app: STATEFULSET_NAME sessionAffinity: None type: ClusterIP --- EOF
Grafana 설정 DataSource
KUBECONFIG를 Org Management API로 설정합니다.export KUBECONFIG=ORG_MANAGEMENT_API_KUBECONFIG_PATH인프라 및 플랫폼 로그에 대해
DataSources를 만듭니다.kubectl apply -f - <<EOF --- apiVersion: monitoring.private.gdc.goog/v1alpha1 kind: Datasource metadata: name: INFRA_DATASOURCE_NAME namespace: APPLIANCE_PROJECT_NAME-obs-system spec: datasource: access: proxy isDefault: false jsonData: httpHeaderName1: X-Scope-OrgID name: UI_FRIENDLY_NAME orgId: 1 readOnly: true secureJsonData: httpHeaderValue1: infra-obs type: loki uid: INFRA_DATASOURCE_NAME url: http://STATEFULSET_NAME.obs-system.svc:3100 version: 1 withCredentials: false --- apiVersion: monitoring.private.gdc.goog/v1alpha1 kind: Datasource metadata: name: PLATFORM_DATASOURCE_NAME namespace: APPLIANCE_PROJECT_NAME-obs-system spec: datasource: access: proxy isDefault: false jsonData: httpHeaderName1: X-Scope-OrgID name: UI_FRIENDLY_NAME orgId: 1 readOnly: true secureJsonData: httpHeaderValue1: platform-obs type: loki uid: PLATFORM_DATASOURCE_NAME url: http://STATEFULSET_NAME.obs-system.svc:3100 version: 1 withCredentials: false --- EOF
Google Distributed Cloud(에어 갭 적용형) 데이터 센터 Grafana에서 로그 보기
Google Distributed Cloud 에어 갭 데이터 센터 버킷으로 내보낸 로그는 GDC 어플라이언스 프로젝트의 Grafana 인스턴스에서 볼 수 있습니다.