KubeLinterについて

# はじめに
KuberentesのLinterツールはいくつかありますが、今回はKubeLinterについてご紹介していきたいと思います。

元々はStackRoxという企業が開発していたツールですが、[昨年RedHatに買収](https://www.redhat.com/en/blog/red-hat-closes-acquisition-stackrox)されており現在はRedHatのメンバー中心に開発が進んでいるものかと思われます。

現時点において開発の初期段階にあるため、今後大きく仕様が変更される可能性があります。
個人的に初期段階のツールに触れた経験があまりないため、この機会に触れてみることで今後のアップデートを実感できるようになれれば良いと思いました。

# KubeLinterとは

Kubernetesのマニフェスト（YAMLファイル)とHelmチャートに対して、構成とセキュリティの2つ観点で検証するLinterです。

デフォルトで検証するためのチェックが既にあるので、基本的にはそれだけである程度の検証が可能です。また、組織によってポリシーが違ったりすると思いますが、必要に応じてカスタムチェックの設定を追加して使用することが可能です。

公式ドキュメント等は以下になります。

■ 概要
https://www.redhat.com/ja/topics/containers/what-is-kubelinter

■ GitHub Repository
https://github.com/stackrox/kube-linter

■ 公式ドキュメント
https://docs.kubelinter.io/#/

# 使い方その１
KubeLinterでは48個のチェックが組み込まれており、デフォルトではそのうちの23個が有効化されています。

以下のマニフェストに対してkube-lintコマンドを実行すればデフォルトのチェックによって検証されます。

```deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: test-deploy
  name: test-deploy
spec:
  replicas: 1
  selector:
    matchLabels:
      app: test-deploy
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: test-deploy
    spec:
      containers:
      - image: nginx
        name: nginx
        resources: {}
status: {}
```
```bash
$ kube-linter lint deploy.yaml
KubeLinter 0.5.0

deploy.yaml: (object: <no namespace>/test-deploy apps/v1, Kind=Deployment) The container "nginx" is using an invalid container image, "nginx". Please use images that are not blocked by the `BlockList` criteria : [".*:(latest)$" "^[^:]*$" "(.*/[^:]+)$"] (check: latest-tag, remediation: Use a container image with a specific tag other than latest.)

deploy.yaml: (object: <no namespace>/test-deploy 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 the container securityContext.)

deploy.yaml: (object: <no namespace>/test-deploy apps/v1, Kind=Deployment) no label matching "company.io/release=<any>" found (check: required-label-release, remediation: )

deploy.yaml: (object: <no namespace>/test-deploy 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. Refer to https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ for details.)

deploy.yaml: (object: <no namespace>/test-deploy apps/v1, Kind=Deployment) container "nginx" has cpu request 0 (check: unset-cpu-requirements, remediation: Set CPU requests and limits for your container based on its requirements. Refer to https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits for details.)

deploy.yaml: (object: <no namespace>/test-deploy apps/v1, Kind=Deployment) container "nginx" has cpu limit 0 (check: unset-cpu-requirements, remediation: Set CPU requests and limits for your container based on its requirements. Refer to https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits for details.)

deploy.yaml: (object: <no namespace>/test-deploy apps/v1, Kind=Deployment) container "nginx" has memory request 0 (check: unset-memory-requirements, remediation: Set memory requests and limits for your container based on its requirements. Refer to https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits for details.)

deploy.yaml: (object: <no namespace>/test-deploy apps/v1, Kind=Deployment) container "nginx" has memory limit 0 (check: unset-memory-requirements, remediation: Set memory requests and limits for your container based on its requirements. Refer to https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits for details.)

Error: found 8 lint errors
```


# 使い方その２

組み込まれている48個のチェックにおいて、どのチェックを有効化するか、どのAPIオブジェクトに対して適用するかといったことが構成ファイルを使うことで設定可能です。

以下のように構成ファイル`.kube-linter.yaml`を作成すると、デフォルトチェックを全て無効化し、指定した`latest-tag`チェックのみを有効化することができます。
```.kube-linter.yaml
checks:
  doNotAutoAddDefaults: true
  include:
    - "latest-tag"
```

```bash
$ kube-linter lint deploy.yaml
KubeLinter 0.5.0

deploy.yaml: (object: <no namespace>/test-deploy apps/v1, Kind=Deployment) The container "nginx" is using an invalid container image, "nginx". Please use images that are not blocked by the `BlockList` criteria : [".*:(latest)$" "^[^:]*$" "(.*/[^:]+)$"] (check: latest-tag, remediation: Use a container image with a specific tag other than latest.)

Error: found 1 lint errors
```

特定のAPIオブジェクトにアノテーションを付与することでチェックを無視することができます。

```deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: test-deploy
  name: test-deploy
  annotations:                    # 追加
    kube-linter.io/ignore-all: "" # 追加
spec:
  replicas: 1
  selector:
    matchLabels:
      app: test-deploy
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: test-deploy
    spec:
      containers:
      - image: nginx
        name: nginx
        resources: {}
status: {}
```
```bash
$ kube-linter lint deploy.yaml
KubeLinter 0.5.0

No lint errors found!
```

# 使い方その３

既存チェックの使い回しだけではなく、チェックする内容自体をカスタマイズすることが可能です。
KubeLinterではテンプレートが用意されており、このテンプレートで使用するパラメータの値を変更することでカスタムチェックを行うことができます。

```.kube-linter.yaml
checks:
  doNotAutoAddDefaults: true
  include:
    - "custom-check-label"
customChecks:
  - name: "custom-check-label"
    template: "required-label"
    params:
      key: "app"
      value: "hoge"
```

※　`使い方その2`で`deploy.yaml`に付与したアノテーションは削除して以下実行します。
```bash
$ kube-linter lint deploy.yaml
KubeLinter 0.5.0

deploy.yaml: (object: <no namespace>/test-deploy apps/v1, Kind=Deployment) no label matching "app=hoge" found (check: custom-check-label, remediation: )

Error: found 1 lint errors
```

テンプレートで必要なパラメータは[公式ドキュメント](https://docs.kubelinter.io/#/generated/templates?id=required-label)か、以下コマンドで確認することができます。
```bash
$ kube-linter templates list
(省略)
Name: Required Label
Key: required-label
Description: Flag objects not carrying at least one label matching the provided patterns
Supported Objects: [Any]
Parameters:
	key:
		Description: Key of the required label.
		Required: true
	value:
		Description: Value of the required label.
		Required: false

(省略)
```

他にも適用するAPIオブジェクトのタイプを指定することや、カスタムチェックがfailしたときのメッセージを変更することなどが可能です。

今回説明した内容について、詳しくは以下ご参照ください。
https://docs.kubelinter.io/#/configuring-kubelinter

# おわりに

KubeLinterを調べる前は、Ansible LintのPythonで作成するカスタムルールのように、KubeLinterでもGoでユーザ独自のチェックを作成するのかなと思っていました。しかし、現在のKubeLinterでは用意されたテンプレートのパラメータを変更してユーザー独自のチェックを作成するようで、調べてみる前の自分の想像と違う使い方をするツールでした。Goで実装するとなると結構大変そうなイメージだったので使いやすいとは思う反面、どこまで柔軟に対応できるのかが重要なポイントだと感じました。