중앙 로그 서버 설정

이 페이지에서는 Google Distributed Cloud (GDC) 오프라인 어플라이언스 기기의 중앙 로그 서버를 Google Distributed Cloud 오프라인 데이터 센터 조직을 통해 설정하는 방법을 설명합니다.

중앙 로깅 위치를 만들려면 GDC 어플라이언스에 GDC 데이터 센터 조직에 다음 구성요소가 있어야 합니다.

  • 고유 프로젝트
  • 감사 로그 버킷
  • 운영 로그 버킷

프로젝트 만들기

다음 단계는 로그가 내보내질 GDC 데이터 센터 조직에서 실행해야 합니다.

  1. KUBECONFIG을 조직 관리 API로 설정합니다.

    export KUBECONFIG=ORG_MANAGEMENT_API_KUBECONFIG_PATH
    
  2. 로그를 내보내는 데 필요한 권한을 얻으려면 조직 IAM 관리자에게 ClusterRole Project Creator (ClusterRole project-creator) 역할을 부여해 달라고 요청하세요. 이러한 역할에 대한 자세한 내용은 IAM 권한 준비를 참고하세요.

  3. 프로젝트 커스텀 리소스를 적용하여 로그가 내보내질 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                                                                                                                                   
    EOF
    
  4. 새 프로젝트가 GDC 어플라이언스에서 사용 가능한지 확인합니다.

    kubectl get namespace APPLIANCE_PROJECT_NAME
    
  5. 새 프로젝트를 결제 계정에 연결합니다. 프로젝트 리소스 비용을 추적하려면 프로젝트에 연결된 결제 계정이 있어야 합니다.

  6. 로그를 내보내는 데 필요한 권한을 얻으려면 조직 IAM 관리자에게 APPLIANCE_PROJECT_NAME 네임스페이스에서 프로젝트 IAM 관리자 (project-iam-admin) 역할을 부여해 달라고 요청하세요.

버킷 만들기

다음 단계는 로그가 내보내질 GDC 데이터 센터 조직의 플랫폼 관리자 (PA)가 실행해야 합니다.

  1. KUBECONFIG을 조직 관리 API로 설정합니다.

    export KUBECONFIG=ORG_MANAGEMENT_API_KUBECONFIG_PATH
    
  2. 로그를 내보내는 데 필요한 권한을 얻으려면 조직 IAM 관리자에게 APPLIANCE_PROJECT_NAME 네임스페이스에서 프로젝트 버킷 관리자 (project-bucket-admin) 역할을 부여해 달라고 요청하세요.

  3. 버킷 커스텀 리소스를 적용하여 버킷을 만듭니다.

    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
    
  4. 버킷이 생성된 후 다음을 실행하여 버킷의 세부정보를 확인합니다.

    kubectl describe buckets BUCKET_NAME -n APPLIANCE_PROJECT_NAME
    
  5. 버킷의 객체에 액세스하기 위한 ProjectServiceAccount를 만듭니다.

    kubectl apply -f - <<EOF
    ---
    apiVersion: resourcemanager.gdc.goog/v1
    kind: ProjectServiceAccount
    metadata:
      name: BUCKET_NAME-read-write-sa
      namespace: APPLIANCE_PROJECT_NAME
    spec: {}
    EOF
    
  6. ProjectServiceAccount이 전파되는지 확인합니다.

    kubectl get projectserviceaccount BUCKET_NAME-read-write-sa -n APPLIANCE_PROJECT_NAME -o json | jq '.status'
    
  7. ServiceAccountreadwrite 권한이 버킷에 추가되었는지 확인합니다.

    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
    
  8. 버킷의 액세스 사용자 인증 정보가 포함된 보안 비밀을 가져옵니다.

    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"
    
  9. 값을 변수로 내보냅니다.

    export BUCKET_RW_SECRET_NAME=BUCKET_RW_SECRET_NAME
    
  10. 버킷 액세스 권한의 키 ID를 가져옵니다.

    kubectl get secret $BUCKET_RW_SECRET_NAME -n appliance-xyz -o json | jq -r '.data."access-key-id"' | base64 -di
    

    출력은 다음 예시와 같이 표시되어야 합니다.

    PCEW2HU47Y8ACUWQO4SK
    
  11. 버킷의 보안 비밀 액세스 키를 가져옵니다.

    kubectl get secret $BUCKET_RW_SECRET_NAME -n appliance-xyz -o json | jq -r '.data."secret-access-key"' | base64 -di
    

    출력은 다음 예시와 같이 표시되어야 합니다.

    TzGdAbgp4h2i5UeiYa9k09rNPFQ2tkYADs67+65E
    
  12. 버킷의 엔드포인트를 가져옵니다.

    kubectl get bucket BUCKET_NAME -n APPLIANCE_PROJECT_NAME -o json | jq '.status.endpoint'
    

    출력은 다음 예시와 같이 표시되어야 합니다.

    https://objectstorage.org-1.zone1.google.gdch.test
    
  13. 버킷의 정규화된 이름을 가져옵니다.

    kubectl get bucket BUCKET_NAME -n APPLIANCE_PROJECT_NAME -o json | jq '.status.fullyQualifiedName'
    

    출력은 다음 예시와 같이 표시되어야 합니다.

    aaaoa9a-logs-bucket
    

GDC에서 데이터 전송

원격 버킷으로 로그 내보내기에 따라 버킷의 엔드포인트, 정규화된 이름, 액세스 키 ID, 보안 비밀 액세스 키를 사용하여 GDC 어플라이언스에서 이전에 GDC 에어갭 데이터 센터에서 만든 버킷으로 로그를 전송합니다.

Google Distributed Cloud(에어 갭 적용형) 데이터 센터에서 Loki 및 Grafana 설정

다음 단계는 로그가 내보내진 GDC 오프라인 데이터 센터 조직의 인프라 운영자 (IO)가 수행해야 합니다.

IAM 역할 획득

로그를 내보내는 데 필요한 권한을 얻으려면 조직 IAM 관리자에게 인프라 클러스터의 obs-system 네임스페이스에 로그 복원 관리자 (logs-restore-admin) 역할을 부여해 달라고 요청하고 관리 평면의 obs-system 네임스페이스에 데이터 소스 뷰어 (datasource-viewer) 및 데이터 소스 편집자 (datasource-editor) 역할을 부여해 달라고 요청하세요.

Loki 설정

  1. KUBECONFIG을 조직 인프라 클러스터로 설정합니다.

    export KUBECONFIG=ORG_INFRA_CLUSTER_KUBECONFIG_PATH
    
  2. PA에서 어플라이언스 로그 버킷의 액세스 키 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_KEY
    
  3. PA에서 어플라이언스 로그 버킷의 엔드포인트와 정규화된 이름을 가져와 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
    ---
    EOF
    
  4. Loki 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

  1. KUBECONFIG을 조직 관리 API로 설정합니다.

    export KUBECONFIG=ORG_MANAGEMENT_API_KUBECONFIG_PATH
    
  2. 인프라 및 플랫폼 로그에 대한 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 인스턴스에서 볼 수 있습니다.