ry's Tech blog

Cloud Native技術などについて書いていきます。

kubelinter

kubelinterとは

Installation

まず、cliツールを使えるようにします。

# curl -LO https://github.com/stackrox/kube-linter/releases/download/0.1.3/kube-linter-linux.tar.gz
# tar -xvf kube-linter-linux.tar.gz
# mv kube-linter /usr/local/bin

# kube-linter version
0.1.3

実践

では、以下のmanifestを確認していきます。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-lint-test
  namespace: default
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          imagePullPolicy: IfNotPresent
          ports:
            - name: http
              containerPort: 80
              protocol: TCP
          livenessProbe:
            httpGet:
              path: /
              port: 80
          readinessProbe:
            httpGet:
              path: /
              port: 80

kube-linter lintコマンドで確認ができます。

# kube-linter lint nginx.yaml
nginx.yaml: (object: default/nginx-lint-test apps/v1, Kind=Deployment) container "nginx" does not have a read-only root file system (check: no-read-only-root-fs, remediation: Set readOnlyRootFilesystem to true in your container's securityContext.)

nginx.yaml: (object: default/nginx-lint-test apps/v1, Kind=Deployment) container "nginx" is not set to runAsNonRoot (check: run-as-non-root, remediation: Set runAsUser to a non-zero number, and runAsNonRoot to true, in your pod or container securityContext. See https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ for more details.)

nginx.yaml: (object: default/nginx-lint-test apps/v1, Kind=Deployment) container "nginx" has cpu request 0 (check: unset-cpu-requirements, remediation: Set your container's CPU requests and limits depending on its requirements. See https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits for more details.)

nginx.yaml: (object: default/nginx-lint-test apps/v1, Kind=Deployment) container "nginx" has cpu limit 0 (check: unset-cpu-requirements, remediation: Set your container's CPU requests and limits depending on its requirements. See https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits for more details.)

nginx.yaml: (object: default/nginx-lint-test apps/v1, Kind=Deployment) container "nginx" has memory request 0 (check: unset-memory-requirements, remediation: Set your container's memory requests and limits depending on its requirements. See https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits for more details.)

nginx.yaml: (object: default/nginx-lint-test apps/v1, Kind=Deployment) container "nginx" has memory limit 0 (check: unset-memory-requirements, remediation: Set your container's memory requests and limits depending on its requirements. See https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits for more details.)

Error: found 6 lint errors

今回のmanifestにおいて、以下のことを注意されています。

  • readOnlyRootFilesystemの設定がない
  • runAsNonRootが設定されていない
  • cpu request/limit が設定されていない
  • memory request/limit が設定されていない

チェックする項目は、以下のコマンドで確認することができます。 ただ、resource requirementはあるものの、limitがないなどまだ完璧ではなさそうです。

# kube-linter checks list
Name: dangling-service
Description: Alert on services that don't have any matching deployments
Remediation: Make sure your service's selector correctly matches the labels on one of your deployments.
Template: dangling-service
Parameters: map[]
Enabled by default: true

------------------------------

Name: default-service-account
Description: Alert on pods that use the default service account
Remediation: Create a dedicated service account for your pod. See https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ for more details.
Template: service-account
Parameters: map[serviceAccount:^(|default)$]
Enabled by default: false

------------------------------

Name: deprecated-service-account-field
Description: Alert on deployments that use the deprecated serviceAccount field
Remediation: Use the serviceAccountName field instead of the serviceAccount field.
Template: deprecated-service-account-field
Parameters: map[]
Enabled by default: true

------------------------------

Name: env-var-secret
Description: Alert on objects using a secret in an environment variable
Remediation: Don't use raw secrets in an environment variable. Instead, either mount the secret as a file or use a secretKeyRef. See https://kubernetes.io/docs/concepts/configuration/secret/#using-secrets for more details.
Template: env-var
Parameters: map[name:(?i).*secret.* value:.+]
Enabled by default: true

------------------------------

Name: mismatching-selector
Description: Alert on deployments where the selector doesn't match the pod template labels
Remediation: Make sure your deployment's selector correctly matches the labels in its pod template.
Template: mismatching-selector
Parameters: map[]
Enabled by default: true

------------------------------

Name: no-anti-affinity
Description: Alert on deployments with multiple replicas that don't specify inter pod anti-affinity to ensure that the orchestrator attempts to schedule replicas on different nodes
Remediation: Specify anti-affinity in your pod spec to ensure that the orchestrator attempts to schedule replicas on different nodes. You can do this by using podAntiAffinity, specifying a labelSelector that matches pods of this deployment, and setting the topologyKey to kubernetes.io/hostname. See https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity for more details.
Template: anti-affinity
Parameters: map[minReplicas:2]
Enabled by default: true

------------------------------

Name: no-extensions-v1beta
Description: Alert on objects using deprecated API versions under extensions v1beta
Remediation: Migrate to using the apps/v1 API versions for these objects. See https://kubernetes.io/blog/2019/07/18/api-deprecations-in-1-16/ for more details.
Template: disallowed-api-obj
Parameters: map[group:extensions version:v1beta.+]
Enabled by default: true

------------------------------

Name: no-liveness-probe
Description: Alert on containers which don't specify a liveness probe
Remediation: Specify a liveness probe in your container. See https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/ for more details.
Template: liveness-probe
Parameters: map[]
Enabled by default: false

------------------------------

Name: no-read-only-root-fs
Description: Alert on containers not running with a read-only root filesystem
Remediation: Set readOnlyRootFilesystem to true in your container's securityContext.
Template: read-only-root-fs
Parameters: map[]
Enabled by default: true

------------------------------

Name: no-readiness-probe
Description: Alert on containers which don't specify a readiness probe
Remediation: Specify a readiness probe in your container. See https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/ for more details.
Template: readiness-probe
Parameters: map[]
Enabled by default: false

------------------------------

Name: non-existent-service-account
Description: Alert on pods referencing a service account that isn't found
Remediation: Make sure to create the service account, or to refer to an existing service account.
Template: non-existent-service-account
Parameters: map[]
Enabled by default: true

------------------------------

Name: privileged-container
Description: Alert on deployments with containers running in privileged mode
Remediation: Don't run your container as privileged unless required.
Template: privileged
Parameters: map[]
Enabled by default: true

------------------------------

Name: required-annotation-email
Description: Alert on objects without an 'email' annotation with a valid email
Remediation: Add an email annotation to your object with the contact information of the object's owner.
Template: required-annotation
Parameters: map[key:email value:[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+]
Enabled by default: false

------------------------------

Name: required-label-owner
Description: Alert on objects without the 'owner' label
Remediation: Add an email annotation to your object with information about the object's owner.
Template: required-label
Parameters: map[key:owner]
Enabled by default: false

------------------------------

Name: run-as-non-root
Description: Alert on containers not set to runAsNonRoot
Remediation: Set runAsUser to a non-zero number, and runAsNonRoot to true, in your pod or container securityContext. See https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ for more details.
Template: run-as-non-root
Parameters: map[]
Enabled by default: true

------------------------------

Name: unset-cpu-requirements
Description: Alert on containers without CPU requests and limits set
Remediation: Set your container's CPU requests and limits depending on its requirements. See https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits for more details.
Template: cpu-requirements
Parameters: map[lowerBoundMillis:0 requirementsType:any upperBoundMillis:0]
Enabled by default: true

------------------------------

Name: unset-memory-requirements
Description: Alert on containers without memory requests and limits set
Remediation: Set your container's memory requests and limits depending on its requirements. See https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits for more details.
Template: memory-requirements
Parameters: map[lowerBoundMB:0 requirementsType:any upperBoundMB:0]
Enabled by default: true

------------------------------

Name: writable-host-mount
Description: Alert on containers that mount a host path as writable
Remediation: If you need to access files on the host, mount them as readOnly.
Template: writable-host-mount
Parameters: map[]
Enabled by default: false

意図的に、チェック項目を回避する場合は、Annotationに次の項目を記載することで対応できます。

ignore-check.kube-linter.io/<check-name>

今回、resourceに対するrequirement/limitをチェックしないように設定します。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-lint-test
  namespace: default
  labels:
    app: nginx
  annotations:
    ignore-check.kube-linter.io/unset-memory-requirements: ""
    ignore-check.kube-linter.io/unset-memory-limits: ""
    ignore-check.kube-linter.io/unset-cpu-requirements: ""
    ignore-check.kube-linter.io/unset-cpu-limits: ""

再度、kube-linterコマンドを実施します。

# kube-linter lint nginx.yaml
nginx.yaml: (object: default/nginx-lint-test apps/v1, Kind=Deployment) container "nginx" does not have a read-only root file system (check: no-read-only-root-fs, remediation: Set readOnlyRootFilesystem to true in your container's securityContext.)

nginx.yaml: (object: default/nginx-lint-test apps/v1, Kind=Deployment) container "nginx" is not set to runAsNonRoot (check: run-as-non-root, remediation: Set runAsUser to a non-zero number, and runAsNonRoot to true, in your pod or container securityContext. See https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ for more details.)

Error: found 2 lint errors

ちゃんと設定した4つ分減ったことを確認できました。

最後に

CIにおけるテストに統合するなど、様々な使い方が期待できそうですね!