Creating a Simple Policy
Kyvernoには2種類のポリシーリソースがあります:クラスター全体のリソースに使用されるClusterPolicyと、名前空間付きリソースに使用されるPolicyです。Kyvernoポリシーの理解を深めるために、まずはシンプルなPodラベル要件から始めましょう。ご存知の通り、Kubernetesではラベルがクラスター内のリソースにタグ付けするために使用されます。
以下は、CostCenterラベルを持たないPodの作成をブロックするClusterPolicyのサンプルです:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-labels
spec:
validationFailureAction: Enforce
rules:
- name: check-team
match:
any:
- resources:
kinds:
- Pod
validate:
message: "Label 'CostCenter' is required to deploy the Pod"
pattern:
metadata:
labels:
CostCenter: "?*"
spec.validationFailureActionは、検証に失敗したリソースを許可して報告する(Audit)か、ブロックする(Enforce)かをKyvernoに指示します。デフォルトはAuditですが、この例ではEnforceに設定されています
rulesセクションには、検証する1つ以上のルールが含まれています
matchステートメントはチェックの範囲を設定します。この場合、すべてのPodリソースが対象になります
validateステートメントは、定義 された内容を肯定的にチェックしようとします。このステートメントがリクエストされたリソースと比較して真の場合、許可されます。偽の場合は、ブロックされます
messageは、このルールが検証に失敗した場合にユーザーに表示されるメッセージです
patternオブジェクトは、リソースでチェックされるパターンを定義します。この場合、metadata.labels内にCostCenterがあるかをチェックします
次のコマンドを使用してポリシーを作成します:
clusterpolicy.kyverno.io/require-labels created
次に、ui名前空間で実行されているPodを確認し、適用されているラベルを確認してください:
NAME READY STATUS RESTARTS AGE LABELS
ui-67d8cf77cf-d4j47 1/1 Running 0 9m app.kubernetes.io/component=service,app.kubernetes.io/created-by=eks-workshop,app.kubernetes.io/instance=ui,app.kubernetes.io/name=ui,pod-template-hash=67d8cf77cf
実行中のPodに必要なラベルがなく、Kyvernoがそれを終了しなかったことに注目してください。これは、KyvernoがAdmissionControllerとして機能し、クラスターに既に存在するリソースには干渉しないためです。
ただし、実行中のPodを削除すると、必要なラベルがないため再作成されることはありません。ui名前空間で実行中のPodを削除してみましょう:
pod "ui-67d8cf77cf-d4j47" deleted
No resources found in ui namespace.
前述の通り、Podは再作成されませんでした。uiデプロイメントの強制的なロールアウトを試みてみましょう:
error: failed to patch: admission webhook "validate.kyverno.svc-fail" denied the request:
resource Deployment/ui/ui was blocked due to the following policies
require-labels:
autogen-check-team: 'validation error: Label ''CostCenter'' is required to deploy
the Pod. rule autogen-check-team failed at path /spec/template/metadata/labels/CostCenter/'
ロールアウトは、require-labels Kyvernoポリシーによってリクエストが拒否されたため、失敗しました。
また、uiデプロイメントを記述したり、ui名前空間のeventsを表示したりしてこのerrorメッセージを確認することもできます:
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning PolicyViolation 12m (x2 over 9m) kyverno-scan policy require-labels/autogen-check-team fail: validation error: Label 'CostCenter' is required to deploy the Pod. rule autogen-check-team failed at path /spec/template/metadata/labels/CostCenter/
9m Warning PolicyViolation pod/ui-67d8cf77cf-hvqcd policy require-labels/check-team fail: validation error: Label 'CostCenter' is required to deploy the Pod. rule check-team failed at path /metadata/labels/CostCenter/
9m Warning PolicyViolation replicaset/ui-67d8cf77cf policy require-labels/autogen-check-team fail: validation error: Label 'CostCenter' is required to deploy the Pod. rule autogen-check-team failed at path /spec/template/metadata/labels/CostCenter/
9m Warning PolicyViolation deployment/ui policy require-labels/autogen-check-team fail: validation error: Label 'CostCenter' is required to deploy the Pod. rule autogen-check-team failed at path /spec/template/metadata/labels/CostCenter/
次に、以下のKustomizationパッチを使用して、uiデプロイメントに必要なラベルCostCenterを追加します:
- Kustomize Patch
- Deployment/ui
- Diff
apiVersion: apps/v1
kind: Deployment
metadata:
name: ui
spec:
template:
metadata:
labels:
CostCenter: IT
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/created-by: eks-workshop
app.kubernetes.io/type: app
name: ui
namespace: ui
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/component: service
app.kubernetes.io/instance: ui
app.kubernetes.io/name: ui
template:
metadata:
annotations:
prometheus.io/path: /actuator/prometheus
prometheus.io/port: "8080"
prometheus.io/scrape: "true"
labels:
CostCenter: IT
app.kubernetes.io/component: service
app.kubernetes.io/created-by: eks-workshop
app.kubernetes.io/instance: ui
app.kubernetes.io/name: ui
spec:
containers:
- env:
- name: JAVA_OPTS
value: -XX:MaxRAMPercentage=75.0 -Djava.security.egd=file:/dev/urandom
- name: METADATA_KUBERNETES_POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: METADATA_KUBERNETES_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: METADATA_KUBERNETES_NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
envFrom:
- configMapRef:
name: ui
image: public.ecr.aws/aws-containers/retail-store-sample-ui:1.2.1
imagePullPolicy: IfNotPresent
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
initialDelaySeconds: 45
periodSeconds: 20
name: ui
ports:
- containerPort: 8080
name: http
protocol: TCP
resources:
limits:
memory: 1.5Gi
requests:
cpu: 250m
memory: 1.5Gi
securityContext:
capabilities:
add:
- NET_BIND_SERVICE
drop:
- ALL
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1000
volumeMounts:
- mountPath: /tmp
name: tmp-volume
securityContext:
fsGroup: 1000
serviceAccountName: ui
volumes:
- emptyDir:
medium: Memory
name: tmp-volume
prometheus.io/path: /actuator/prometheus
prometheus.io/port: "8080"
prometheus.io/scrape: "true"
labels:
+ CostCenter: IT
app.kubernetes.io/component: service
app.kubernetes.io/created-by: eks-workshop
app.kubernetes.io/instance: ui
app.kubernetes.io/name: ui
namespace/ui unchanged
serviceaccount/ui unchanged
configmap/ui unchanged
service/ui unchanged
deployment.apps/ui configured
NAME READY STATUS RESTARTS AGE LABELS
ui-5498685db8-k57nk 1/1 Running 0 60s CostCenter=IT,app.kubernetes.io/component=service,app.kubernetes.io/created-by=eks-workshop,app.kubernetes.io/instance=ui,app.kubernetes.io/name=ui,pod-template-hash=5498685db8
ご覧の通り、アドミッションウェブフックはポリシーを正常に検証し、正しいラベルCostCenter=ITでPodが作成されました!
ミューテーションルールについて
上記の例では、validationFailureActionで定義されたデフォルトの動作でバリデーションポリシーがどのように機能するかを確認しました。しかし、Kyvernoはポリシー内でミューテーションルールを管理するためにも使用でき、APIリクエストを変更して、Kubernetesリソースに指定された要件を満たしたり強制したりすることができます。リソースの変更はバリデーションの前に行われるため、バリデーションルールはミューテーションセクションによって実行された変更と矛盾しません。
以下はミューテーションルールを定義したポリシーのサンプルです:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: add-labels
spec:
rules:
- name: add-labels
match:
any:
- resources:
kinds:
- Pod
mutate:
patchStrategicMerge:
metadata:
labels:
CostCenter: IT
match.any.resources.kinds: [Pod]は、このClusterPolicyをクラスター全体のすべてのPodリソースに対象としています
mutateはリソースの作成中に変更を行います(validateがブロック/許可するのに対して)。patchStrategicMerge.metadata.labels.CostCenter: ITは、すべてのPodに自動的にCostCenter: ITラベルを追加します
以下のコマンドを使用して上記のポリシーを作成しましょう:
clusterpolicy.kyverno.io/add-labels created
ミューテーションウェブフックを検証するために、ラベルを明示的に追加せずにcartsデプロイメントをロールアウトしてみましょう:
deployment.apps/carts restarted
deployment "carts" successfully rolled out
デプロイメントにラベルが指定されていなくても、ポリシー要件を満たすためにPodにCostCenter=ITラベルが自動的に追加され、Podの作成が成功したことを検証します:
NAME READY STATUS RESTARTS AGE LABELS
carts-bb88b4789-kmk62 1/1 Running 0 25s CostCenter=IT,app.kubernetes.io/component=service,app.kubernetes.io/created-by=eks-workshop,app.kubernetes.io/instance=carts,app.kubernetes.io/name=carts,pod-template-hash=bb88b4789
KyvernoポリシーでpatchStrategicMergeおよびpatchesJson6902パラメータを使用して、Amazon EKSクラスター内の既存のリソースを変更することも可能です。
これはPodにラベルを付けるシンプルな例でした。これはさまざまなシナリオに適用できます。例えば、未知のレジストリからの画像の制限、ConfigMapsへのデータの追加、許容の設定など多岐にわたります。今後のラボでは、より高度なユースケースをいくつか探索します。