[k8s] GateKeeper를 통한 리소스 제약조건 설정

[원본 링크]

GateKeeper는 쿠버네티스 리소스를 생성할때의 제약조건을 부여할 수 있게 해주는 도구다.
Pod에 리소스 제한을 의무화하거나, 포트 개방 등을 중복으로 하지 않게 막으려고 하는 등의 원칙을 강제하고 싶을 때 유용하다.




원리

기본 원리는 그렇게 복잡하진 않다. rule을 정의해두면, apply로 리소스를 생성할 때마다 내부 웹훅 시스템이 Gatekeeper rule을 확인해서 통과 여부를 확인하는 것이다.

만약 통과할 수 없는 리소스 생성이 들어온다면 API server는 클라이언트에게 오류를 반환한다.

참고로, apply 시점에만 검사하는 거라서 기존에 떠있던 리소스에는 영향을 주지 않는다.




GateKeeper 설치

이건 내장 도구는 아니고 서드파티다. 그래서 설치해야 쓸 수 있다.

kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/v3.22.0/deploy/gatekeeper.yaml

잘 설치가 되었다면, 다음과 같이 리소스들이 떠있을 것이다.

kubectl get all -n gatekeeper-system

이제 쓰면 된다.




사용해보기

한번 memory limit이 없을 경우 오류를 던지는 규칙을 만들어보겠다.

게이트키퍼는 2개의 계층으로 정의된다.
먼저 템플릿이라는 것을 만들어야 한다. 여기서 구체적인 제약사항을 정의한다.

apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: requirememorylimit
  annotations:
    description: >
      All containers and initContainers must have resources.limits.memory set.
spec:
  crd:
    spec:
      names:
        kind: RequireMemoryLimit
  targets:
    - target: admission.k8s.gatekeeper.sh
      code:
        - engine: Rego
          source:
            rego: |
              package requirememorylimit

              violation[{"msg": msg}] {
                container := input.review.object.spec.containers[_]
                not container.resources.limits.memory
                msg := sprintf("container '%v' has no memory limit", [container.name])
              }

              violation[{"msg": msg}] {
                container := input.review.object.spec.initContainers[_]
                not container.resources.limits.memory
                msg := sprintf("initContainer '%v' has no memory limit", [container.name])
              }

보통 Repo라고 하는 전용 스크립트 언어를 사용한다.

만들면 된다.

그리고, 저 템플릿을 실질적으로 생성해주는 과정이 필요하다.
템플릿은 조건을 정의할 뿐이고, 이걸 화이트리스트로 할지, 블랙리스트로 할지, 어떤 리소스에 적용할지 등은 실제 초기화 시점에서 적용할 수 있는 것이다.

여기서는 Pod에 대해서만 모두 deny 규칙으로 만들어보겠다.

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: RequireMemoryLimit
metadata:
  name: require-memory-limit
spec:
  enforcementAction: deny
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]

그리고 만들면 된다.

이제 조건에 맞지 않는 - memory limit이 없는 pod를 만들려고 시도한다면, 즉시 오류가 발생할 것이다.

이런 느낌으로 쓰면 된다.



참조
https://kubernetes.io/blog/2019/08/06/opa-gatekeeper-policy-and-governance-for-kubernetes/
https://open-policy-agent.github.io/gatekeeper/website/docs/install/