All Products
Search
Document Center

Container Compute Service:Rotate ACS container logs with logrotate sidecar

Last Updated:Jun 04, 2025

Container Compute Service (ACS) clusters use a serverless architecture to manage resources. Therefore, you cannot deploy DaemonSets to manage log rotation. Without log rotation, the size of log files consistently grows and will eventually exhaust the disk space. ACS architects a solution to rotate container logs with logrotate sidecar. This topic describes how to use logrotate sidecar to rotate container logs by configuring a cron expression.

How it works

Important

The log rotation solution described in this topic is not suitable for the following scenarios:

  • Scenarios where only one file is output. In this scenario, we recommend that you use stdout instead of log files because containers have a native log rotation mechanism for stdout and it is much easier to identify anomalies in container logs.

  • Scenarios where Java or Python is used. This programming languages come with log rotation. We recommend that you use the log rotation capability of Logstores.

The following figure show how this solution works.

image
  • When only a few workloads are deployed in the cluster (① in the preceding figure), you can configure logrotate sidecar for the application to implement log rotation.

  • When large numbers of workloads are deployed in the cluster (② in the preceding figure), you can create a SidecarSet and inject logrotate sidecar into workloads within the specified cluster or namespace range.

Configure logrotate sidecar for applications

In the following example, the native sidecar mechanism is used to deploy a logrotate container (an init container configured with restartPolicy: Always). For ACS clusters that run Kubernetes 1.28 or earlier, you can use the ACS enhanced environment variable __IS_SIDECAR=true to mark regular containers in order to manage their lifecycle in the same way as sidecar containers. For more information, see Configure the startup and exit priorities of sidecar containers.

Important

The logrotate container needs to share the volume with the application containers. In addition, the /var/lib directory must be mounted to the logrotate container to save rotation state data in case the state data is lost after the logrotate container restarts. If the state data is lost, log rotation errors will occur. You must also ensure that the log files generated by the application are stored in the shared volume.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-logrotate
  labels:
    app: test
spec:
  replicas: 1 
  selector:
    matchLabels:
      app: test
  template:
    metadata:
      labels:
        app: test
    spec:
      initContainers:
        - name: logrotate
          env:
            - name: CRON_EXPR
              value: "5 * * * *"
            - name: LOGROTATE_LOGFILES
              value: "/var/log/*/*.log"
            - name: LOGROTATE_FILENUM
              value: "5"
            - name: LOGROTATE_FILESIZE
              value: "10M"
            - name: __IGNORE_RESOURCE__
              value: "true"
            - name: __IGNORE_READY__
              value: "true"
          command: [ "sh", "/start.sh" ]
          image: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/logrotate:v1.1
          volumeMounts:
            - mountPath: /var/log
              name: shared-log
            - mountPath: /var/lib
              name: logrotate-state
          restartPolicy: Always
          resources:
            limits:
               cpu: 0.25
               memory: 0.5Gi
      containers:
        - name: busybox
          image: mirrors-ssl.aliyuncs.com/busybox:latest
          command: [ "sh", "-c" ]
          args:
            - |
              mkdir /var/log/busybox
              while true; do
                TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
                LOG_LEVEL=$(shuf -n1 -e INFO WARNING ERROR)
                APP_NAME="busybox"
                HOSTNAME=$(hostname)
                MESSAGE=$(shuf -n1 -e "Success" "Timeout" "Database error")
                echo "$TIMESTAMP $HOSTNAME [$LOG_LEVEL] $APP_NAME: $MESSAGE" >> /var/log/busybox/busybox.log
                sleep 1
              done
          volumeMounts:
            - mountPath: /var/log
              name: shared-log
      volumes:
        ## Collect stdout logs.
        - emptyDir:
          name: shared-log
        - emptyDir:
          name: logrotate-state

The following table describes the key environment variables.

Environment variable name

Description

Example

CRON_EXPR

The cron expression for performing log rotation.

5 * * * * means that log rotation is performed at the 5th minute of every hour. You need to avoid log rotation at the top of every hour in case other business activities are adversely affected.

LOGROTATE_LOGFILES

The path of the logs to be rotated.

/var/log/*/*.log means that log files suffixed with .log in all subdirectories of /var/log are scanned.

LOGROTATE_FILENUM

The number of historical log files to keep for each log file.

5.

LOGROTATE_FILESIZE

The maximum amount of space occupied by each log file. Logrotate sidecar is called to rotate logs when the space usage exceeds LOGROTATE_FILESIZE.

10M.

Note

LOGROTATE_FILESIZE × LOGROTATE_FILENUM determines the maximum disk space that can be occupied by all log files. Set it to a proper value based on the storage capacity of the instance.

__IGNORE_RESOURCE__

Ignore the resource claim of the logrotate container. This ensures that the logrotate container can share CPU and memory resources with application containers while the logrotate container is still constrained by resource.limits. For more information, see Configure scheduling policies to ignore the resource requests of specific sidecar containers.

"true".

__IGNORE_READY__

Ignore the NotReady state of the logrotate container in case the pod is affected when the logrotate container is in the NotReady state. For more information, see Ignore the NotReady state of the sidecar container.

"true".

Shared volume and log rotation result

  • Verify the shared volume:

    Check the /var/log/busybox directory of the busybox and logrotate containers.

    image

    You can find the busybox.log log in the directory of both containers, which indicates that the shared volume is successfully mounted.

  • Log rotation result:

    Note

    To quickly demonstrate log rotation, the values of the cron expression and LOGROTATE_FILESIZE are adjusted in the following example.

    image

Configure logrotate sidecar for application containers in batches

Important

To create and use SidecarSets in an ACS cluster, you must first install the ack-kruise component. For more information, see Manage components.

OpenKruise SidecarSets allow you to manage sidecar containers by automatically injecting and separately upgrading sidecar containers. The SidecarSet in this example injects logrotate sidecar into all pods with the kruise.io/inject-logrotate: "true" label. The SidecarSet also enables the shareVolume policy shareVolumePolicy.type=enabled. This way, all volumeMounts of the pods are automatically mounted to the logrotate sidecar. If all pods to be injected have an agreed volume name, you can also claim the volume in the SidecarSet.

apiVersion: apps.kruise.io/v1alpha1
kind: SidecarSet
metadata:
  name: logrotate-sidecarset
spec:
  selector:
    matchLabels:
      kruise.io/inject-logrotate: "true"
  shareVolumePolicy:
    type: enabled
  updateStrategy: 
    type: NotUpdate
  initContainers:
    - name: logrotate
      env:
        - name: CRON_EXPR
          value: "5 * * * *"
        - name: LOGROTATE_LOGFILES
          value: "/var/log/*/*.log"
        - name: LOGROTATE_FILENUM
          value: "5"
        - name: LOGROTATE_FILESIZE
          value: "10M"
        - name: __IGNORE_RESOURCE__
          value: "true"
      command: [ "sh", "/start.sh" ]
      image: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/logrotate:v1.1
      volumeMounts:
        - mountPath: /var/lib/
          name: logrotate-state
      restartPolicy: Always
      resources:
        limits:
           cpu: 0.25
           memory: 0.5Gi
  volumes:
    - name: logrotate-state
      emptyDir: {}

References

The following example shows the dockerfile and script used to build the logrotate image in this topic. You can modify the dockerfile or script accordingly.

  • The dockerfile:

    FROM registry-cn-hangzhou.ack.aliyuncs.com/dev/alpine:3.20-update
    
    RUN apk --update add bash logrotate
    
    ADD start.sh /start.sh
    
    CMD ["/start.sh"]
  • The start.sh script:

    #!/bin/sh
    
    LOGROTATE_LOGFILES="${LOGROTATE_LOGFILES:?Files for rotating must be given}"
    LOGROTATE_FILESIZE="${LOGROTATE_FILESIZE:-10M}"
    LOGROTATE_FILENUM="${LOGROTATE_FILENUM:-5}"
    
    cat > /etc/logrotate.conf << EOF
    ${LOGROTATE_LOGFILES}
    {
      size ${LOGROTATE_FILESIZE}
      missingok
      notifempty
      copytruncate
      rotate ${LOGROTATE_FILENUM}
    }
    EOF
    
    if [ -z "$CRON_EXPR" ]; then
      CRON_EXPR="0 6 * * *"
      echo "CRON_EXPR environment variable is not set. Set to default: $CRON_EXPR"
    else
      echo "CRON_EXPR environment variable set to $CRON_EXPR"
    fi
    
    echo "$CRON_EXPR	/usr/sbin/logrotate -v /etc/logrotate.conf" >> /etc/crontabs/root
    
    (crond -f) & CRONPID=$!
    trap "kill $CRONPID; wait $CRONPID" SIGINT SIGTERM
    wait $CRONPID