Cette page explique comment configurer un serveur de journaux central pour les appliances Google Distributed Cloud (GDC) isolées, via l'organisation de centre de données Google Distributed Cloud isolée.
Pour créer un emplacement de journalisation central, l'appliance GDC doit disposer des composants suivants dans l'organisation du centre de données GDC :
- projet unique ;
- bucket pour les journaux d'audit.
- bucket pour les journaux opérationnels
Créer un projet
Les étapes suivantes doivent être effectuées dans l'organisation du centre de données GDC vers lequel les journaux seront exportés.
Définissez
KUBECONFIG
sur l'API Organization Management :export KUBECONFIG=ORG_MANAGEMENT_API_KUBECONFIG_PATH
Pour obtenir les autorisations nécessaires pour exporter des journaux, demandez à votre administrateur IAM de l'organisation de vous accorder le rôle ClusterRole Project Creator (
ClusterRole project-creator
). Pour en savoir plus sur ces rôles, consultez Préparer les autorisations IAM.Appliquez la ressource personnalisée du projet pour créer un projet unique pour l'appliance GDC à partir de laquelle les journaux seront exportés :
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
Vérifiez si le nouveau projet est disponible dans l'appliance GDC :
kubectl get namespace APPLIANCE_PROJECT_NAME
Associez votre nouveau projet à un compte de facturation. Pour suivre les coûts des ressources d'un projet, vous devez y associer un compte de facturation.
Pour obtenir les autorisations nécessaires pour exporter des journaux, demandez à votre administrateur IAM de l'organisation de vous accorder le rôle d'administrateur IAM du projet (
project-iam-admin
) dans l'espace de nomsAPPLIANCE_PROJECT_NAME
.
Créer un bucket
Les étapes suivantes doivent être effectuées par l'administrateur de plate-forme (AP) dans l'organisation du centre de données GDC vers laquelle les journaux seront exportés.
Définissez
KUBECONFIG
sur l'API Organization Management :export KUBECONFIG=ORG_MANAGEMENT_API_KUBECONFIG_PATH
Pour obtenir les autorisations nécessaires pour exporter des journaux, demandez à votre administrateur IAM de l'organisation de vous accorder le rôle Administrateur de bucket de projet (
project-bucket-admin
) dans l'espace de nomsAPPLIANCE_PROJECT_NAME
.Appliquez la ressource personnalisée de bucket pour créer un bucket :
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
Une fois le bucket créé, exécutez la commande suivante pour confirmer et vérifier les détails du bucket :
kubectl describe buckets BUCKET_NAME -n APPLIANCE_PROJECT_NAME
Créez un
ProjectServiceAccount
pour accéder aux objets du bucket.kubectl apply -f - <<EOF --- apiVersion: resourcemanager.gdc.goog/v1 kind: ProjectServiceAccount metadata: name: BUCKET_NAME-read-write-sa namespace: APPLIANCE_PROJECT_NAME spec: {} EOF
Vérifiez que
ProjectServiceAccount
est propagé :kubectl get projectserviceaccount BUCKET_NAME-read-write-sa -n APPLIANCE_PROJECT_NAME -o json | jq '.status'
Assurez-vous que les autorisations
read
etwrite
sont ajoutées àServiceAccount
pour le bucket.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
Obtenez le secret contenant les identifiants d'accès au bucket :
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'
Le résultat doit ressembler à l'exemple suivant, où le nom secret du bucket est affiché :
"object-storage-key-sysstd-sa-olxv4dnwrwul4bshu37ikebgovrnvl773owaw3arx225rfi56swa"
Exportez la valeur vers une variable :
export BUCKET_RW_SECRET_NAME=BUCKET_RW_SECRET_NAME
Obtenez l'ID de clé pour l'accès au bucket :
kubectl get secret $BUCKET_RW_SECRET_NAME -n appliance-xyz -o json | jq -r '.data."access-key-id"' | base64 -di
Le résultat doit ressembler à l'exemple ci-dessous :
PCEW2HU47Y8ACUWQO4SK
Obtenez la clé d'accès secrète pour le bucket :
kubectl get secret $BUCKET_RW_SECRET_NAME -n appliance-xyz -o json | jq -r '.data."secret-access-key"' | base64 -di
Le résultat doit ressembler à l'exemple ci-dessous :
TzGdAbgp4h2i5UeiYa9k09rNPFQ2tkYADs67+65E
Obtenez le point de terminaison du bucket :
kubectl get bucket BUCKET_NAME -n APPLIANCE_PROJECT_NAME -o json | jq '.status.endpoint'
Le résultat doit ressembler à l'exemple ci-dessous :
https://objectstorage.org-1.zone1.google.gdch.test
Obtenez le nom complet du bucket :
kubectl get bucket BUCKET_NAME -n APPLIANCE_PROJECT_NAME -o json | jq '.status.fullyQualifiedName'
Le résultat doit ressembler à l'exemple ci-dessous :
aaaoa9a-logs-bucket
Transférer des données depuis GDC
Suivez les instructions de la section Exporter les journaux vers un bucket distant pour transférer les journaux de l'appliance GDC vers le bucket créé précédemment dans le centre de données GDC isolé, en utilisant le point de terminaison du bucket, le nom complet, l'ID de clé d'accès et la clé d'accès secrète.
Configurer Loki et Grafana dans un centre de données Google Distributed Cloud sous air gap
Les étapes suivantes doivent être effectuées par l'opérateur d'infrastructure (IO) dans l'organisation du centre de données GDC air-gapped vers laquelle les journaux ont été exportés.
Obtenir des rôles IAM
Pour obtenir les autorisations nécessaires pour exporter des journaux, demandez à votre administrateur IAM de l'organisation de vous accorder le rôle Administrateur de la restauration des journaux (logs-restore-admin
) dans l'espace de noms obs-system
du cluster d'infrastructure, ainsi que les rôles Lecteur de source de données (datasource-viewer
) et Éditeur de source de données (datasource-editor
) dans l'espace de noms obs-system
du plan de gestion.
Configurer Loki
Définissez
KUBECONFIG
sur le cluster d'infrastructure de l'organisation :export KUBECONFIG=ORG_INFRA_CLUSTER_KUBECONFIG_PATH
Obtenez l'ID de clé d'accès et la clé d'accès secrète pour le bucket de journaux de l'appliance auprès de l'administrateur de parc, puis créez un secret contenant les identifiants dans l'espace de noms
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
Obtenez le point de terminaison et le nom complet du bucket de journaux de l'appliance à partir de l'AP, puis créez un
configmap
Loki :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
Créez un
statefulset
et un service Loki :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
Configurer Grafana DataSource
Définissez
KUBECONFIG
sur l'API Organization Management :export KUBECONFIG=ORG_MANAGEMENT_API_KUBECONFIG_PATH
Créez
DataSources
pour les journaux d'infrastructure et de plate-forme :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
Afficher les journaux dans Grafana du centre de données Google Distributed Cloud sous air gap
Les journaux exportés vers le bucket du centre de données isolé Google Distributed Cloud peuvent être consultés dans l'instance Grafana du projet d'appliance GDC.