הגדרת שרת מרכזי ליומנים

בדף הזה מוסבר איך להגדיר שרת מרכזי ליומנים עבור מכשירי Google Distributed Cloud (GDC) במודל Air-gapped appliance דרך ארגון מרכז הנתונים של Google Distributed Cloud במודל Air-gapped.

כדי ליצור מיקום מרכזי לרישום ביומן, למכשיר GDC צריכים להיות הרכיבים הבאים בארגון מרכז הנתונים של GDC:

  • פרויקט ייחודי
  • קטגוריה ליומני הביקורת
  • קטגוריה ביומן לפעולות

יצירת פרויקט

את השלבים הבאים צריך לבצע בארגון של מרכז הנתונים של GDC שאליו ייוצאו היומנים.

  1. הגדרת KUBECONFIG ל-Org Management 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 בארגון להקצות לכם את תפקיד אדמין ה-IAM בפרויקט (project-iam-admin) במרחב השמות APPLIANCE_PROJECT_NAME.

יצירת קטגוריה

את השלבים הבאים צריך לבצע מנהל הפלטפורמה (PA) בארגון של מרכז הנתונים של GDC שאליו ייוצאו היומנים.

  1. הגדרת KUBECONFIG ל-Org Management API:

    export KUBECONFIG=ORG_MANAGEMENT_API_KUBECONFIG_PATH
    
  2. כדי לקבל את ההרשאות שנדרשות לייצוא יומנים, צריך לבקש מאדמין ה-IAM בארגון להקצות לכם את התפקיד 'אדמין של קטגוריית פרויקט' (project-bucket-admin) במרחב השמות APPLIANCE_PROJECT_NAME.

  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. אחרי שיוצרים את ה-bucket, מריצים את הפקודה הבאה כדי לאשר ולבדוק את הפרטים של ה-bucket:

    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. מוודאים שההרשאות read ו-write של ServiceAccount נוספו לקטגוריה.

    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. מקבלים את מזהה המפתח לגישה לקטגוריה:

    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. מקבלים את נקודת הקצה של ה-bucket:

    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

כדי להעביר יומנים ממכשיר GDC לקטגוריה שנוצרה קודם לכן במרכז הנתונים של GDC עם air gap, פועלים לפי ההוראות שבמאמר ייצוא יומנים לקטגוריה מרוחקת. צריך להשתמש בנקודת הקצה של הקטגוריה, בשם המלא, במזהה מפתח הגישה ובמפתח הגישה הסודי.

הגדרת Loki ו-Grafana ב-Google Distributed Cloud במודל Air-gapped

את השלבים הבאים צריך לבצע מפעיל התשתית (IO) בארגון של מרכז הנתונים עם GDC עם air gap שאליו יובאו היומנים.

קבלת תפקידי IAM

כדי לקבל את ההרשאות שדרושות לייצוא יומנים, צריך לבקש מאדמין ה-IAM בארגון להקצות לכם את התפקיד Logs Restore Admin (אדמין לשחזור יומנים) ‏(logs-restore-admin) במרחב השמות obs-system באשכול התשתית, ואת התפקידים Datasource Viewer (צפייה במקור נתונים) ‏(datasource-viewer) ו-Datasource Editor (עריכה של מקור נתונים) ‏(datasource-editor) במרחב השמות obs-system במישור הניהול.

הגדרת Loki

  1. מגדירים את KUBECONFIG לאשכול Org Infra:

    export KUBECONFIG=ORG_INFRA_CLUSTER_KUBECONFIG_PATH
    
  2. מקבלים את המזהה של מפתח הגישה ואת מפתח הגישה הסודי של קטגוריית היומנים של מכשיר ה-PA מ-PA ויוצרים Secret שמכיל את פרטי הכניסה במרחב השמות 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 ל-Org Management 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
    

הצגת יומנים ב-Grafana של מרכז נתונים במודל Air-gapped ב-Google Distributed Cloud

אפשר לראות את היומנים שמיוצאים לקטגוריה של Google Distributed Cloud במודל Air-gapped במופע Grafana של פרויקט מכשיר GDC.