Kubernetesの1.4で追加されそうなImage Policy Webhookというイメージの制御ができる機能が面白そうだったので概要をまとめてみました。
Image Policy (Image Provenance)とは
Image PolicyとはKubernetesクラスタ上で動かすコンテナイメージを独自に制御したい場合に使える仕組みです。Proposalのドキュメントによると下記のようなユースケースを想定しているようです。
- 既知の脆弱性を含まないことを確認されたイメージだけを動かしたい
- 特定のベースイメージを使ったイメージだけを動かしたい
- レビュー済みのコードでビルドされたイメージだけを動かしたい
- 署名されたイメージだけを動かしたい
Image Policy Webhookは、ユーザが定義するWebAPIに対してそのPodに含まれるコンテナイメージの情報を渡し、実行可否をチェックする仕組みです。コンテナイメージ制御自体は自前のWebAPIで行う必要があります。Admission ControllerプラグインImagePolicyWebhook
として実装されています。参考: Kubernetes: Admission Controlとは何か
WebhookへのRequest/Response
webhookへのリクエスト、レスポンスにはImageReview
構造体のJSON形式が使われます。参考: pkg/apis/imagepolicy/types.go
type ImageReview struct {
unversioned.TypeMeta
api.ObjectMeta
Spec ImageReviewSpec // チェックするイメージの情報
Status ImageReviewStatus // チェック結果
}
type ImageReviewSpec struct {
Containers []ImageReviewContainerSpec // Podに含まれるコンテナ(複数)
Annotations map[string]string // Podに定義できるアノテーション `*.image-policy.k8s.io/*`
Namespace string
}
type ImageReviewContainerSpec struct {
Image string // image:tag or image@SHA:012345679abcde のような形式
}
type ImageReviewStatus struct {
Allowed bool // 許可するかどうか
Reason string // 否認の場合の理由
}
Request
リクエストのJSONは以下のようなイメージなります。spec.containers[].image
にはPodのコンテナのイメージタグ(image:tag
形式)またはイメージID(image@SHA:012345679abcde
形式)が入ります。
{
"kind": "ImageReview",
"apiVersion": "imagepolicy.k8s.io/v1alpha1",
"metadata": {
"creationTimestamp": null
},
"spec": {
"containers": [
{
"image": "nginx:latest" # チェック対象のコンテナ
}
],
"namespace": "namespace"
}
}
ProposalのImage tags and IDsで説明されていますが、初期の実装では複雑さを避けるため、PodTemplateのイメージ情報をそのままWebhookへ渡す形になっています。そのため、イメージタグで指定された場合はWebhookでチェックしたときのイメージと、クラスタがイメージをPullしたときのイメージの同一性を厳密に保証することは現状は難しいようです。ProposalではPodTemplateでイメージIDだけを許可するような形にするなどの対策などが提案されていました。
Response
許可する場合のレスポンスは以下のようなイメージになります。
{
"apiVersion": "imagepolicy.k8s.io/v1alpha1",
"kind": "ImageReview",
"status": {
"allowed": true, # 許可する
"reason": "" # 否認する場合は理由が入る
}
}
キャッシュ
Image Policy Webhookにはレスポンスは一定時間キャッシュをする仕組みがあります。ImageReviewSpec
構造体のJSON表記をキャシュのキーにしているようです。現時点のデフォルトはAllowが5分、Denyが30秒になっていました。参考: plugin/pkg/admission/imagepolicy/config.go#L32-L33
ソース
- pkg/apis/imagepolicy 型定義
- plugin/pkg/admission/imagepolicy Admission Controllerの実装