C-0075 - Image pull policy on latest tag

Image pull policy on latest tag

Framework

DevOpsBest, AllControls, YAML-scanning

Severity

Low

Description of the the issue

While usage of the latest tag is not generally recommended, in some cases this is necessary. If it is, the ImagePullPolicy must be set to Always, otherwise Kubernetes may run an older image with the same name that happens to be present in the node cache. Note that using Always will not cause additional image downloads because Kubernetes will check the image hash of the local local against the registry and only pull the image if this hash has changed, which is exactly what users want when use the latest tag. This control will identify all PODs with latest tag that have ImagePullSecret not set to Always. Note as well that some vendors don't use the word latest in the tag. Some other word may also behave like the latest. For example, Redis uses redis:alpine to signify the latest. Therefore, this control treats any word that does not contain digits as the latest. If no tag is specified, the image is treated as latests too.

Related resources

CronJob, DaemonSet, Deployment, Job, Pod, ReplicaSet, StatefulSet

What does this control test

If imagePullPolicy = always pass, else fail.

Remediation

Set ImagePullPolicy to Always in all PODs found by this control.

Example

apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "8"
    meta.helm.sh/release-name: redis-aggregated
    meta.helm.sh/release-namespace: ca-production
  creationTimestamp: "2020-05-21T12:19:30Z"
  generation: 14
  labels:
    app: ca-redis-aggregared
    app-display-label: ca-redis-aggregared
    app.kubernetes.io/component: ca-redis-aggregared
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/part-of: visibilityAndReporting
    app.kubernetes.io/version: 1.0.0
    environment: producation
    region: aws-eu-north-1
  name: deployment-with-image-pull-not-always
  resourceVersion: "244972372"
  selfLink: /apis/apps/v1/namespaces/ca-production/deployments/ca-redis-aggregared
  uid: 3658319c-f69b-4e04-87b7-72992a721f22
spec:
  progressDeadlineSeconds: 600
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app.kubernetes.io/instance: redis-aggregated
      app.kubernetes.io/name: ca-redis-aggregared
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: ca-redis-aggregared
        app-display-label: ca-redis-aggregared
        app.kubernetes.io/component: ca-redis-aggregared
        app.kubernetes.io/instance: redis-aggregated
        app.kubernetes.io/managed-by: helm
        app.kubernetes.io/name: ca-redis-aggregared
        app.kubernetes.io/part-of: visibilityAndReporting
        app.kubernetes.io/version: 1.0.0
        environment: producation
        region: aws-eu-north-1
    spec:
      containers:
      - command:
        - redis-server
        - /redis.conf
        image: redis:latest
        imagePullPolicy: IfNotPresent
        name: ca-redis-aggregared
        ports:
        - containerPort: 6379
          name: redis-port
          protocol: TCP
        resources:
          limits:
            cpu: "2"
            memory: 14848Mi
          requests:
            cpu: 500m
            memory: 10Gi
        stdin: true
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        tty: true
        volumeMounts:
        - mountPath: /redis.conf
          name: ca-redis-aggregared-config-volume
          subPath: redis.conf
        - mountPath: /data
          name: ca-redis-aggregared-persistent-storage
      dnsPolicy: ClusterFirst
      imagePullSecrets:
      - name: caregcred
      nodeSelector:
        env: prod
        subgroup: prod-redis
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
      volumes:
      - configMap:
          defaultMode: 420
          name: ca-redis-aggregared-configmap
        name: ca-redis-aggregared-config-volume
      - name: ca-redis-aggregared-persistent-storage
        persistentVolumeClaim:
          claimName: ca-redis-aggregared-pv-claim