├── .travis.yml ├── Dockerfile ├── README.md ├── build.sh └── logrotate.conf /.travis.yml: -------------------------------------------------------------------------------- 1 | --- 2 | notifications: 3 | email: 4 | on_success: never 5 | on_failure: always 6 | 7 | services: 8 | - docker 9 | 10 | env: 11 | global: 12 | - DOCKERHUB_USERNAME="kicm" 13 | - IMAGE_NAME="logrotate" 14 | 15 | jobs: 16 | include: 17 | - stage: build docker image 18 | script: 19 | - ./build.sh 20 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.14 2 | 3 | USER root 4 | RUN apk --update add --no-cache logrotate && \ 5 | rm -f /etc/logrotate.d/* 6 | ADD logrotate.conf /etc/logrotate.conf 7 | RUN chmod 0400 /etc/logrotate.conf 8 | 9 | CMD ["/usr/sbin/logrotate", "-v", "-f", "--state","/tmp/logrotate.status", "/etc/logrotate.conf"] 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | We need a solution for legacy apps running in a kubernetes cluster writing logs to a file without rotating them (in a traditional way). 3 | 4 | # Example Setup 5 | I assume that a legacy app inside Kubernetes write logs to a PV resp. PVC called `app-logs-pv`. 6 | 7 | ## Kubernetes Prereqs 8 | The example PVC `app-logs-pv` has to be present and the legacy app writes its logfile to this. `accessMode` of this PVC must be **RWX** (ReadWriteMany) as we want to rotate them from a different Pod (seperate to the application). 9 | ```yaml 10 | apiVersion: v1 11 | kind: PersistentVolumeClaim 12 | metadata: 13 | name: app-logs-pv 14 | spec: 15 | accessModes: 16 | - ReadWriteMany 17 | resources: 18 | requests: 19 | storage: 500Mi 20 | ``` 21 | 22 | ## Cronjob example setup 23 | ### Define Logrotate Config 24 | ```yaml 25 | --- 26 | apiVersion: v1 27 | kind: ConfigMap 28 | metadata: 29 | name: logrotate-config 30 | data: 31 | my_logs.conf: | 32 | /var/log/app/*.log { 33 | daily 34 | missingok 35 | rotate 7 36 | compress 37 | delaycompress 38 | dateformat -%Y%m%d_%H%M%S 39 | notifempty 40 | copytruncate 41 | su 42 | } 43 | my_txt_logs.conf: | 44 | /var/log/app/*.txt { 45 | daily 46 | missingok 47 | rotate 3 48 | compress 49 | delaycompress 50 | dateformat -%Y%m%d_%H%M%S 51 | notifempty 52 | copytruncate 53 | su 54 | } 55 | ``` 56 | ### Define Cronjob 57 | ```yaml 58 | --- 59 | apiVersion: batch/v1beta1 60 | kind: CronJob 61 | metadata: 62 | name: app-logrotate 63 | spec: 64 | schedule: "*/1 * * * *" 65 | concurrencyPolicy: Forbid 66 | jobTemplate: 67 | spec: 68 | template: 69 | spec: 70 | containers: 71 | - name: logrotate 72 | image: docker.io/kicm/logrotate 73 | volumeMounts: 74 | - name: logrotate-conf 75 | mountPath: /etc/logrotate.d 76 | - name: app-logs 77 | mountPath: /var/log/app 78 | volumes: 79 | - name: logrotate-conf 80 | configMap: 81 | name: logrotate-config 82 | - name: app-logs 83 | persistentVolumeClaim: 84 | claimName: app-logs-pv 85 | restartPolicy: OnFailure 86 | ``` 87 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | TRAVIS_BRANCH_STRIPPED=${TRAVIS_BRANCH/[^a-zA-Z0-9]/_} 4 | 5 | # Build docker image 6 | docker build --no-cache -t myimage . 7 | 8 | # Extract version information 9 | LOGROTATE_VERSION_FULL=$(docker run --rm -it myimage /usr/sbin/logrotate --version | head -n 1 | awk '{print $2}' | sed -e 's/\r//g') 10 | LOGROTATE_VERSION_MAJOR=$(echo "${LOGROTATE_VERSION_FULL}" | awk -F '.' '{print $1}') 11 | LOGROTATE_VERSION_MINOR=$(echo "${LOGROTATE_VERSION_FULL}" | awk -F '.' '{print $2}') 12 | 13 | # Login into docker hub 14 | echo "${DOCKERHUB_PASSWORD}" | docker login -u "${DOCKERHUB_USERNAME}" --password-stdin 15 | 16 | # Handle main branch different 17 | if [ "${TRAVIS_BRANCH_STRIPPED}" == "main" ]; then 18 | IMAGE_EXACT_VERSION="${DOCKERHUB_USERNAME}/${IMAGE_NAME}:${LOGROTATE_VERSION_FULL}-build${TRAVIS_BUILD_NUMBER}" 19 | IMAGE_LATEST="${DOCKERHUB_USERNAME}/${IMAGE_NAME}:latest" 20 | IMAGE_MAJOR="${DOCKERHUB_USERNAME}/${IMAGE_NAME}:${LOGROTATE_VERSION_MAJOR}" 21 | IMAGE_MINOR="${DOCKERHUB_USERNAME}/${IMAGE_NAME}:${LOGROTATE_VERSION_MAJOR}.${LOGROTATE_VERSION_MINOR}" 22 | 23 | docker tag myimage "${IMAGE_EXACT_VERSION}" 24 | docker push "${IMAGE_EXACT_VERSION}" 25 | 26 | docker tag myimage "${IMAGE_LATEST}" 27 | docker push "${IMAGE_LATEST}" 28 | 29 | docker tag myimage "${IMAGE_MAJOR}" 30 | docker push "${IMAGE_MAJOR}" 31 | 32 | docker tag myimage "${IMAGE_MINOR}" 33 | docker push "${IMAGE_MINOR}" 34 | 35 | else 36 | IMAGE_NON_MAIN="${DOCKERHUB_USERNAME}/${IMAGE_NAME}:${TRAVIS_BRANCH_STRIPPED}" 37 | 38 | docker tag myimage "${IMAGE_NON_MAIN}" 39 | docker push "${IMAGE_NON_MAIN}" 40 | fi 41 | -------------------------------------------------------------------------------- /logrotate.conf: -------------------------------------------------------------------------------- 1 | # see "man logrotate" for details 2 | weekly 3 | rotate 4 4 | create 5 | dateext 6 | compress 7 | 8 | include /etc/logrotate.d 9 | --------------------------------------------------------------------------------