All Products
Search
Document Center

Container Compute Service:Rotate general ACS application logs with a sidecar

Last Updated:Jan 15, 2026

Container Compute Service (ACS) clusters use a serverless architecture to manage cluster resources. In this architecture, you cannot deploy a DaemonSet to manage log rotation. If log files are not rotated, they can grow continuously and consume all available disk space. Therefore, ACS provides a general solution to rotate container logs using a sidecar. This topic describes how to configure a cron job in a sidecar to trigger logrotate and rotate container log files.

How it works

Important

This topic provides a general log rotation solution. This solution is not recommended in the following two scenarios:

  • Scenarios that output to a single file. In these scenarios, use standard output instead of file logs. Containers have a native rotation mechanism for standard output. This also makes it easier to observe logs if a container becomes abnormal.

  • Scenarios that use languages with built-in log rotation capabilities, such as Java and Python. In these scenarios, use the log rotation feature of the logging library directly.

The solution in this topic is designed as follows:

image

Configure a logrotate sidecar for an application

The following example shows how to use the native sidecar mechanism to deploy a logrotate container. This mechanism uses an init container that is 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 a regular container as a sidecar. This lets you manage its lifecycle in the same way as a native sidecar container. For more information, see Configure the startup and shutdown order of sidecar containers.

Important

The logrotate container must share a volume with the application container. You must also mount the /var/lib directory to save rotation state data. This prevents incorrect log rotation if the container restarts and its state is lost. Ensure that the application's output log files 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 main environment variables.

Environment variable

Description

Example

CRON_EXPR

The cron expression used to run logrotate.

5 * * * * means that logrotate runs at the fifth minute of every hour. Avoid running log rotation at the top of the hour to prevent conflicts with business activities that are scheduled to start on the hour.

LOGROTATE_LOGFILES

The path to the log files that you want to rotate.

/var/log/*/*.log scans for all files that end with .log in the subdirectories of the /var/log directory.

LOGROTATE_FILENUM

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

5.

LOGROTATE_FILESIZE

The maximum size of each log file. When a file exceeds this size, logrotate is triggered to rotate the log file.

10M.

Note

The value of LOGROTATE_FILESIZE × LOGROTATE_FILENUM determines the maximum disk space that the log files will occupy. Set these values based on the storage space that is requested for the instance.

__IGNORE_RESOURCE__

Ignores the resource declaration of the logrotate container to avoid extra resource costs. This ensures the logrotate container shares CPU and memory resources with the application container and remains constrained by the configured resource.limits. For more information, see Configure scheduling to ignore resources of specific containers.

"true".

__IGNORE_READY__

Ignores the Ready status of the logrotate container. This prevents the entire pod from being affected if the logrotate container enters a NotReady state. For more information, see Ignore the NotReady status of a sidecar container.

"true".

Shared volume and rotation result

  • Verify the shared volume:

    To verify the shared volume, check the /var/log/busybox directory in both the busybox and logrotate containers.

    image

    The busybox.log file exists in the same directory in both containers. This indicates that the shared volume is mounted successfully.

  • Log rotation result:

    Note

    To demonstrate the rotation results quickly, the following results are from a test where the CRON_EXPR and LOGROTATE_FILESIZE values were adjusted to accelerate the rotation cycle.

    image

Configure logrotate sidecars for applications in batches

Important

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

OpenKruise's SidecarSet lets you manage sidecar containers by automatically injecting and upgrading them independently. In this example, a SidecarSet injects a logrotate sidecar into all pods that have the kruise.io/inject-logrotate: "true" label. This SidecarSet also enables the shareVolumePolicy (shareVolumePolicy.type=enabled). When the shareVolumePolicy is enabled, all the pod's volumeMounts are automatically mounted into the sidecar. If all injected pods share a common volume name, you can also declare that name 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: {}

Related information

The following Dockerfile and script are used to build the logrotate image that is described in this topic. You can modify the Dockerfile or script as needed.

  • 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"]
  • start.sh file:

    #!/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