Kubernetes CronJob 的一個應用案例

最近 Kubernetes 集羣中出現過幾次 Redis 故障,具體表現是每次集羣重啓(雲資源按需啓動), Redis Pod 都要老半天才能啓動起來,後來逐漸排查定位才發現原來是由於 Redis 開啓了 aof 持久化機制。

我們知道在 AOF 持久化機制下,Resdis 的每一條寫命令都會被同步、並且追加的方式持久化的磁盤文件,當 Redis 由於意外故障時,下次重啓就會原封不動地執行 AOF 文件中的命令來恢復 Redis。那麼顯然這種方式會帶來一個問題是隨着時間的推移 aof 文件體積會越來越大,每次 Redis 重啓都要執行一遍 aof 持久化的命令,速度也會越來越慢,從而導致 Redis 啓動變慢。

顯然解決方法是怎麼把 AOF 文件變小,丟棄沒用的記錄。Redis 有一條 BGREWRITE 命令就是解決這問題的,這條命令的工作原理是將當前 Redis 中的數據都導出成 Redis 寫語句,然後生成新的 aof 文件,替換掉舊的。顯然新的 aof 文件體積會原因小於長時間運行的舊的 aof 文件,因爲新的 aof 只是當前 Redis 的數據恢復語句,只記錄當前的狀態。

由於我們 Redis 是運行在 Kubernetes 集羣中,所以藉助於 Kubernetes 的 CronJob 機制定期執行 Redis BGREWRITE 命令來重寫 aof 文件,從而縮小文件體積。

Kubernetes CronJob 簡介

Kubernetes CronJob 資源用來定義一些需要定時執行的任務,類似於 Linux/Unix 的 Crontab。CronJob 資源創建後會按照寫的定時任務規則啓動 Pod 執行定義的任務。關於 CronJob 更詳細的信息見這裏:https://kubernetes.io/docs/tasks/job/automated-tasks-with-cron-jobs

基於 k8s CronJob 定期 AOF 重寫

定義 CronJob 資源文件,每兩小時進行一次 Redis AOF 重寫,資源文件如下:
redis-cron.yaml

apiVersion: batch/v1beta1 #for API server versions >= 1.8.0 use batch/v1beta1
kind: CronJob
metadata:
  name: redis-bgrewriteaof-cron
  labels:
    app: redis-bgrewriteaof-cron
spec:
  schedule: "0 */2 * * *"
  successfulJobsHistoryLimit: 1
  failedJobsHistoryLimit: 3
  concurrencyPolicy: Forbid
  startingDeadlineSeconds: 120
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: redis
            image: docker.io/bitnami/redis:4.0.12
            env:
              - name: REDIS_PASSWORD
                valueFrom:
                  secretKeyRef:
                    name: redis-test
                    key: redis-password
            args: [redis-cli, -h, redis-stage-master, -a, $(REDIS_PASSWORD), BGREWRITEAOF]
          restartPolicy: OnFailure

關於上面資源裏面的一些配置項含義在此不做具體介紹,很多都能看懂,具體每個配置項含義看官方文檔,都有詳細的解釋。這裏有一點需要「特別注意」的是 redis 容器的 args 字段引用環境變量的方法:
比如這裏引用了 REDIS_PASSWORD 環境變量,需要寫成:$(REDIS_PASSWORD) 這樣的方式引用,而不能寫成:$REDIS_PASSWORD 或者 ${REDIS_PASSWORD}。

執行 kubectl create 創建定義的 CronJob 資源

kubectl create -f redis-cron.yaml -n test

查看 CronJob 執行情況

$ kubectl get cronjob -n test
NAME                      SCHEDULE      SUSPEND   ACTIVE    LAST SCHEDULE   AGE
redis-bgrewriteaof-cron   0 */2 * * *   False     0         1h              14h

可以看出最近一小時前已經調度過一次,如果要看調度是否成功可以看對應 Pod 的 log,也可以 kubectl get jobs -n test 查看啓動的 Job 的狀態。

相關文檔

https://kubernetes.io/docs/tasks/job/automated-tasks-with-cron-jobs | Running Automated Tasks with a CronJob
https://redis.io/commands/bgrewriteaof | Redis之AOF重寫及其實現原理

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章