How to Archive Logs to Third-Party Storage

Currently, the logs generated by the platform will be stored in the log storage component; however, the retention period for these logs is relatively short. For enterprises with high compliance requirements, logs typically require longer retention times to meet audit demands. Additionally, the economic aspect of storage is also one of the key concerns for enterprises.

Based on the above scenarios, the platform offers a log archiving solution, allowing users to transfer logs to external NFS or object storage.

TOC

Transfer to External NFS

Prerequisites

ResourceDescription
NFSSet up the NFS service in advance and determine the NFS path to be mounted.
KafkaObtain the Kafka service address in advance.
Image AddressYou must use the CLI tool in the global cluster to execute the following commands to get the image addresses:
- Get alpine image address: kubectl get daemonset nevermore -n cpaas-system -o jsonpath='{.spec.template.spec.initContainers[0].image}'
- Get razor image address: kubectl get deployment razor -n cpaas-system -o jsonpath='{.spec.template.spec.containers[0].image}'

Create Log Synchronization Resources

  1. Click on Cluster Management > Clusters in the left navigation bar.

  2. Click the action button on the right side of the cluster where the logs will be transferred > CLI Tool.

  3. Modify the YAML based on the following parameter descriptions; after modifying, paste the code into the open CLI Tool command line and hit enter to execute.

    Resource TypeField PathDescription
    ConfigMapdata.export.yml.output.compressionCompress log text; supported options are none (no compression), zlib, gzip.
    ConfigMapdata.export.yml.output.file_typeThe type of exported log file; supports txt, csv, json.
    ConfigMapdata.export.yml.output.max_sizeSize of a single archived file; unit is MB. If it exceeds this value, logs will be automatically compressed and archived based on the compression field's configuration.
    ConfigMapdata.export.yml.scopesThe scope of log transfer; currently supported logs include: system logs, application logs, Kubernetes logs, product logs.
    Deploymentspec.template.spec.containers[0].command[7]Kafka service address.
    Deploymentspec.template.spec.volumes[3].hostPath.pathNFS path to be mounted.
    Deploymentspec.template.spec.initContainers[0].imageAlpine image address.
    Deploymentspec.template.spec.containers[0].imageRazor image address.
    cat << "EOF" |kubectl apply -f -
    apiVersion: v1
    data:
      export.yml: |
        scopes: # The scope of log transfer; by default, only application logs are collected
          system: false  # System logs
          workload: true # Application logs
          kubernetes: false # Kubernetes logs
          platform: false # Product logs
        output:
          type: local                              
          path: /cpaas/data/logarchive           
          layout: TimePrefixed
          # Size of a single archived file; unit is MB. If it exceeds this value, logs will be automatically compressed and archived based on the compression field's configuration.
          max_size: 200         
          compression: zlib    # Optional: none (no compression) / zlib / gzip
          file_type: txt   # Optional: txt csv json
    kind: ConfigMap
    metadata:
      name: log-exporter-config
      namespace: cpaas-system
     
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        service_name: log-exporter
      name: log-exporter
      namespace: cpaas-system
    spec:
      progressDeadlineSeconds: 600
      replicas: 1
      revisionHistoryLimit: 5
      selector:
        matchLabels:
          service_name: log-exporter
      strategy:
        rollingUpdate:
          maxSurge: 0
          maxUnavailable: 1
        type: RollingUpdate
      template:
        metadata:
          creationTimestamp: null
          labels:
            app: lanaya
            cpaas.io/product: Platform-Center
            service_name: log-exporter
            version: v1
          namespace: cpaas-system
        spec:
          affinity:
            podAffinity: {}
            podAntiAffinity:
              preferredDuringSchedulingIgnoredDuringExecution:
                - podAffinityTerm:
                    labelSelector:
                      matchExpressions:
                        - key: service_name
                          operator: In
                          values:
                            - log-exporter
                    topologyKey: kubernetes.io/hostname
                  weight: 50
          initContainers:
            - args:
                - -ecx
                - |
                  chown -R 697:697 /cpaas/data/logarchive
              command:
                - /bin/sh
              image: registry.example.cn:60080/ops/alpine:3.16 # Alpine image address
              imagePullPolicy: IfNotPresent
              name: chown
              resources:
                limits:
                  cpu: 100m
                  memory: 200Mi
                requests:
                  cpu: 10m
                  memory: 50Mi
              securityContext:
                runAsUser: 0
              terminationMessagePath: /dev/termination-log
              terminationMessagePolicy: File
              volumeMounts:
                - mountPath: /cpaas/data/logarchive
                  name: data
          containers:
            - command:
              - /razor
              - consumer
              - --v=1
              - --kafka-group-log=log-nfs
              - --kafka-auth-enabled=true
              - --kafka-tls-enabled=true
              - --kafka-endpoint=192.168.143.120:9092  # Fill in based on actual environment
              - --database-type=file
              - --export-config=/etc/log-export/export.yml
              image: registry.example.cn:60080/ait/razor:v3.16.0-beta.3.g3df8e987  # Razor image
              imagePullPolicy: Always
              livenessProbe:
                failureThreshold: 5
                httpGet:
                  path: /metrics
                  port: 8080
                  scheme: HTTP
                initialDelaySeconds: 20
                periodSeconds: 10
                successThreshold: 1
                timeoutSeconds: 3
              name: log-export
              ports:
                - containerPort: 80
                  protocol: TCP
              readinessProbe:
                failureThreshold: 5
                httpGet:
                  path: /metrics
                  port: 8080
                  scheme: HTTP
                initialDelaySeconds: 20
                periodSeconds: 10
                successThreshold: 1
                timeoutSeconds: 3
              resources:
                limits:
                  cpu: "2"
                  memory: 4Gi
                requests:
                  cpu: 440m
                  memory: 1280Mi
              securityContext:
                runAsGroup: 697
                runAsUser: 697
              terminationMessagePath: /dev/termination-log
              terminationMessagePolicy: File
              volumeMounts:
                - mountPath: /etc/secrets/kafka
                  name: kafka-basic-auth
                  readOnly: true
                - mountPath: /etc/log-export
                  name: config
                  readOnly: true
                - mountPath: /cpaas/data/logarchive 
                  name: data
          dnsPolicy: ClusterFirst
          nodeSelector:
            kubernetes.io/os: linux
          restartPolicy: Always
          schedulerName: default-scheduler
          securityContext:
            fsGroup: 697
          serviceAccount: lanaya
          serviceAccountName: lanaya
          terminationGracePeriodSeconds: 10
          tolerations:
            - effect: NoSchedule
              key: node-role.kubernetes.io/master
              operator: Exists
            - effect: NoSchedule
              key: node-role.kubernetes.io/control-plane
              operator: Exists
            - effect: NoSchedule
              key: node-role.kubernetes.io/cpaas-system
              operator: Exists
          volumes:
            - name: kafka-basic-auth
              secret:
                defaultMode: 420
                secretName: kafka-basic-auth
            - name: elasticsearch-basic-auth
              secret:
                defaultMode: 420
                secretName: elasticsearch-basic-auth
            - configMap:
                defaultMode: 420
                name: log-exporter-config
              name: config
            - hostPath:
                path: /cpaas/data/logarchive    # NFS path to be mounted
                type: DirectoryOrCreate
              name: data
    EOF
  4. Once the container status changes to Running, you can view the continuously archived logs in the NFS path; the log file directory structure is as follows:

    /cpaas/data/logarchive/$date/$project/$namespace-$cluster/logfile

Transfer to External S3 Storage

Prerequisites

ResourceDescription
S3 StoragePrepare the S3 storage service address in advance, and obtain the values for access_key_id and secret_access_key; create the bucket where the logs will be stored.
KafkaObtain the Kafka service address in advance.
Image AddressYou must use the CLI tool in the global cluster to execute the following commands to get the image addresses:
- Get alpine image address: kubectl get daemonset nevermore -n cpaas-system -o jsonpath='{.spec.template.spec.initContainers[0].image}'
- Get razor image address: kubectl get deployment razor -n cpaas-system -o jsonpath='{.spec.template.spec.containers[0].image}'

Create Log Synchronization Resources

  1. Click on Cluster Management > Clusters in the left navigation bar.

  2. Click the action button on the right side of the cluster where the logs will be transferred > CLI Tool.

  3. Modify the YAML based on the following parameter descriptions; after modifying, paste the code into the open CLI Tool command line and hit enter to execute.

    Resource TypeField PathDescription
    Secretdata.access_key_idBase64 encode the obtained access_key_id.
    Secretdata.secret_access_keyBase64 encode the obtained secret_access_key.
    ConfigMapdata.export.yml.output.compressionCompress log text; supported options are none (no compression), zlib, gzip.
    ConfigMapdata.export.yml.output.file_typeThe type of exported log file; supports txt, csv, json.
    ConfigMapdata.export.yml.output.max_sizeSize of a single archived file; unit is MB. If it exceeds this value, logs will be automatically compressed and archived based on the compression field's configuration.
    ConfigMapdata.export.yml.scopesThe scope of log transfer; currently supported logs include: system logs, application logs, Kubernetes logs, product logs.
    ConfigMapdata.export.yml.output.s3.bucket_nameBucket name.
    ConfigMapdata.export.yml.output.s3.endpointS3 storage service address.
    ConfigMapdata.export.yml.output.s3.regionRegion information for the S3 storage service.
    Deploymentspec.template.spec.containers[0].command[7]Kafka service address.
    Deploymentspec.template.spec.volumes[3].hostPath.pathLocal path to be mounted, used for temporarily storing log information. Log files will be automatically deleted after synchronization to S3 storage.
    Deploymentspec.template.spec.initContainers[0].imageAlpine image address.
    Deploymentspec.template.spec.containers[0].imageRazor image address.
    cat << "EOF" |kubectl apply -f -
    apiVersion: v1
    type: Opaque
    data:
      # Must include the following two keys
      access_key_id: bWluaW9hZG1pbg==  # Base64 encode the obtained access_key_id
      secret_access_key: bWluaW9hZG1pbg==  # Base64 encode the obtained secret_access_key
    kind: Secret
    metadata:
      name: log-export-s3-secret
      namespace: cpaas-system
      
    ---
    apiVersion: v1
    data:
      export.yml: |
        scopes: # The scope of log transfer; by default, only application logs are collected
          system: false  # System logs
          workload: true # Application logs
          kubernetes: false # Kubernetes logs
          platform: false # Product logs
        output:
          type: s3                             
          path: /cpaas/data/logarchive             
          
          s3:
            s3forcepathstyle: true
            bucket_name: baucket_name_s3           # Fill in the prepared bucket name
            endpoint: http://192.168.179.86:9000   # Fill in the prepared S3 storage service address
            region: "dummy"                        # Region information
            access_secret: log-export-s3-secret    
            insecure: true
                                
          layout: TimePrefixed
          # Size of a single archived file; unit is MB. If it exceeds this value, logs will be automatically compressed and archived based on the compression field's configuration.
          max_size: 200                            
          compression: zlib                        # Optional: none (no compression) / zlib / gzip
          file_type: txt                           # Optional: txt, csv, json
    kind: ConfigMap
    metadata:
      name: log-exporter-config
      namespace: cpaas-system
     
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        service_name: log-exporter
      name: log-exporter
      namespace: cpaas-system
    spec:
      progressDeadlineSeconds: 600
      replicas: 1
      revisionHistoryLimit: 5
      selector:
        matchLabels:
          service_name: log-exporter
      strategy:
        rollingUpdate:
          maxSurge: 0
          maxUnavailable: 1
        type: RollingUpdate
      template:
        metadata:
          creationTimestamp: null
          labels:
            app: lanaya
            cpaas.io/product: Platform-Center
            service_name: log-exporter
            version: v1
          namespace: cpaas-system
        spec:
          affinity:
            podAffinity: {}
            podAntiAffinity:
              preferredDuringSchedulingIgnoredDuringExecution:
                - podAffinityTerm:
                    labelSelector:
                      matchExpressions:
                        - key: service_name
                          operator: In
                          values:
                            - log-exporter
                    topologyKey: kubernetes.io/hostname
                  weight: 50
          initContainers:
            - args:
                - -ecx
                - |
                  chown -R 697:697 /cpaas/data/logarchive
              command:
                - /bin/sh
              image: registry.example.cn:60080/ops/alpine:3.16 # Alpine image address
              imagePullPolicy: IfNotPresent
              name: chown
              resources:
                limits:
                  cpu: 100m
                  memory: 200Mi
                requests:
                  cpu: 10m
                  memory: 50Mi
              securityContext:
                runAsUser: 0
              terminationMessagePath: /dev/termination-log
              terminationMessagePolicy: File
              volumeMounts:
                - mountPath: /cpaas/data/logarchive
                  name: data
          containers:
            - command:
                - /razor
                - consumer
                - --v=1
                - --kafka-group-log=log-s3   
                - --kafka-auth-enabled=true
                - --kafka-tls-enabled=true
                - --kafka-endpoint=192.168.179.86:9092  # Fill in the Kafka service address based on actual environment
                - --database-type=file
                - --export-config=/etc/log-export/export.yml
              image: registry.example.cn:60080/ait/razor:v3.16.0-beta.3.g3df8e987  # Razor image
              imagePullPolicy: Always
              livenessProbe:
                failureThreshold: 5
                httpGet:
                  path: /metrics
                  port: 8080
                  scheme: HTTP
                initialDelaySeconds: 20
                periodSeconds: 10
                successThreshold: 1
                timeoutSeconds: 3
              name: log-export
              ports:
                - containerPort: 80
                  protocol: TCP
              readinessProbe:
                failureThreshold: 5
                httpGet:
                  path: /metrics
                  port: 8080
                  scheme: HTTP
                initialDelaySeconds: 20
                periodSeconds: 10
                successThreshold: 1
                timeoutSeconds: 3
              resources:
                limits:
                  cpu: "2"
                  memory: 4Gi
                requests:
                  cpu: 440m
                  memory: 1280Mi
              securityContext:
                runAsGroup: 697
                runAsUser: 697
              terminationMessagePath: /dev/termination-log
              terminationMessagePolicy: File
              volumeMounts:
                - mountPath: /etc/secrets/kafka
                  name: kafka-basic-auth
                  readOnly: true
                - mountPath: /etc/log-export
                  name: config
                  readOnly: true
                - mountPath: /cpaas/data/logarchive
                  name: data
          dnsPolicy: ClusterFirst
          nodeSelector:
            kubernetes.io/os: linux
          restartPolicy: Always
          schedulerName: default-scheduler
          securityContext:
            fsGroup: 697
          serviceAccount: lanaya
          serviceAccountName: lanaya
          terminationGracePeriodSeconds: 10
          tolerations:
            - effect: NoSchedule
              key: node-role.kubernetes.io/master
              operator: Exists
            - effect: NoSchedule
              key: node-role.kubernetes.io/control-plane
              operator: Exists
            - effect: NoSchedule
              key: node-role.kubernetes.io/cpaas-system
              operator: Exists
          volumes:
            - name: kafka-basic-auth
              secret:
                defaultMode: 420
                secretName: kafka-basic-auth
            - name: elasticsearch-basic-auth
              secret:
                defaultMode: 420
                secretName: elasticsearch-basic-auth
            - configMap:
                defaultMode: 420
                name: log-exporter-config
              name: config
            - hostPath:
                path: /cpaas/data/logarchive    # Local temporary storage address for logs
                type: DirectoryOrCreate
              name: data
    EOF
  4. Once the container status changes to Running, you can view the continuously archived logs in the bucket.