커스텀 제약조건 템플릿 작성

이 페이지에서는 특정 요구에 적합한 사전 작성된 제약조건 템플릿을 찾을 수 없을 때 커스텀 제약조건 템플릿을 작성하고 이를 사용해서 정책 컨트롤러를 확장하는 방법을 보여줍니다.

정책 컨트롤러 정책은 OPA 제약조건 프레임워크를 사용하여 설명되며 Rego로 작성됩니다. 정책은 Kubernetes 객체의 모든 필드를 평가할 수 있습니다.

Rego를 사용하여 정책을 작성하는 것은 전문 기술입니다. 이러한 이유로 공통 제약조건 템플릿 라이브러리가 기본 설치됩니다. 제약조건을 만들 때 이러한 제약조건 템플릿을 호출할 수 있습니다. 특별한 요구사항이 있으면 자체 제약조건 템플릿을 만들 수 있습니다.

제약조건 템플릿을 사용하면 재사용 및 위임을 목적으로 특정 요구사항으로부터 정책 논리를 분리할 수 있습니다. 오픈소스 프로젝트, 소프트웨어 공급업체, 규제 전문가와 같이 제3자가 개발한 제약조건 템플릿을 사용하여 제약조건을 만들 수 있습니다.

시작하기 전에

제약조건 템플릿 예시

다음은 제약조건의 생성자가 제공한 값과 이름이 일치하는 모든 리소스를 거부하는 제약조건 템플릿 예시입니다. 이 페이지의 나머지 부분에서는 몇 가지 중요한 개념을 중심으로 템플릿 내용을 설명합니다.

구조적 저장소를 사용하는 경우 cluster/ 디렉터리에 제약조건을 만드는 것이 좋습니다.

apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: k8sdenyname
spec:
  crd:
    spec:
      names:
        kind: K8sDenyName
      validation:
        # Schema for the `parameters` field
        openAPIV3Schema:
          properties:
            invalidName:
              type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8sdenynames
        violation[{"msg": msg}] {
          input.review.object.metadata.name == input.parameters.invalidName
          msg := sprintf("The name %v is not allowed", [input.parameters.invalidName])
        }

제약조건 예시

다음은 이름이 policy-violation인 모든 리소스를 거부하기 위해 구현할 수 있는 제약조건 예시입니다.

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sDenyName
metadata:
  name: no-policy-violation
spec:
  parameters:
    invalidName: "policy-violation"

제약조건 템플릿의 일부

제약조건 템플릿에는 두 가지 중요한 부분이 있습니다.

  • 사용자가 만들려는 제약조건의 스키마입니다. 제약조건 템플릿의 스키마는 crd 필드에 저장됩니다.

  • 제약조건이 평가될 때 실행되는 Rego 소스 코드입니다. 템플릿의 Rego 소스 코드는 targets 필드에 저장됩니다.

스키마(crd 필드)

CRD 필드는 Kubernetes API 서버에 대한 제약조건 리소스를 정의하는 Kubernetes 커스텀 리소스 정의를 작성하기 위한 청사진입니다. 다음 필드만 채우면 됩니다.

필드 설명
spec.crd.spec.names.kind 제약조건의 종류입니다. 소문자인 경우 이 필드의 값은 metadata.name과 같아야 합니다.
spec.crd.spec.validation.openAPIV3Schema

제약조건 리소스의 spec.parameters 필드에 대한 스키마(정책 컨트롤러가 제약조건의 스키마 나머지를 자동으로 정의). 일반 CRD 리소스와 동일한 규칙을 따릅니다.

제약조건 템플릿에 K8s 이름을 프리픽스로 사용하면 Google Cloud 리소스를 대상으로 하는 Forseti 템플릿과 같이, 다른 종류의 제약조건 템플릿과의 충돌을 방지할 수 있습니다.

Rego 소스 코드(targets 필드)

다음 섹션에서는 Rego 소스 코드에 대해 더 자세히 설명합니다.

위치

Rego 소스 코드는 spec.targets 필드 아래에 저장됩니다. 여기서 targets는 다음 형식의 객체 배열입니다.

{"target": "admission.k8s.gatekeeper.sh","rego": REGO_SOURCE_CODE, "libs": LIST_OF_REGO_LIBRARIES}
  • target: 정책 컨트롤러에 현재 조회 중인 시스템(이 경우 Kubernetes)을 알려줍니다. targets에는 한 개의 항목만 허용됩니다.
  • rego: 제약조건의 소스 코드입니다.
  • libs: 제약조건 템플릿에 제공되는 Rego 코드의 선택적인 라이브러리 목록입니다. 공유 라이브러리를 더 쉽게 사용하기 위한 용도로 사용되지만, 이 문서에서는 설명 범위를 벗어납니다.

소스 코드

다음은 앞의 제약조건에 대한 Rego 소스 코드입니다.

package k8sdenynames

violation[{"msg": msg}] {
   input.review.object.metadata.name == input.parameters.invalidName
   msg := sprintf("The name %v is not allowed", [input.parameters.invalidName])
}

다음에 유의하세요.

  • package k8sdenynames는 OPA(Rego 런타임)에 필요합니다. 값이 무시됩니다.
  • 위반이 있는지 확인하기 위해 정책 컨트롤러가 호출하는 Rego 규칙은 violation이라고 합니다. 이 규칙이 일치하면 제약조건 위반이 발생한 것입니다.
  • violation 규칙에는 violation[{"msg": "violation message for the user"}] 서명이 있습니다. 여기서 "msg"의 값은 사용자에게 반환되는 위반 메시지입니다.
  • 제약조건에 제공된 매개변수는 키워드 input.parameters에서 사용 가능합니다.
  • request-under-testinput.review 키워드 아래에 저장됩니다.

input.review 키워드에는 다음 필드가 포함됩니다.

필드 설명
uid 이 특정 요청의 고유 ID입니다. 감사 중에 사용할 수 없습니다.
kind

object-under-test의 종류 정보입니다. 형식은 다음과 같습니다.

  • kind: 리소스 종류
  • group: 리소스 그룹
  • version: 리소스 버전
name 리소스 이름입니다. 사용자가 CREATE 요청 시 이름을 생성하는 데 API 서버를 사용하는 경우에는 비어 있을 수 있습니다.
namespace 리소스 네임스페이스입니다(클러스터 범위 리소스에 제공되지 않음).
operation 요청된 작업(예: CREATE 또는 UPDATE)입니다. 감사 중에 사용할 수 없습니다.
userInfo

요청 사용자의 정보입니다. 감사 중에 사용할 수 없습니다. 형식은 다음과 같습니다.

  • username: 요청을 수행하는 사용자
  • uid: 사용자의 UID
  • groups: 사용자가 구성원인 그룹의 목록
  • extra: Kubernetes에서 제공되는 모든 추가 사용자 정보
object 사용자가 수정하거나 만들려는 객체입니다.
oldObject 객체의 원래 상태입니다. UPDATE 작업에만 사용할 수 있습니다.
dryRun 이 요청이 kubectl --dry-run으로 호출되었는지 여부입니다. 감사 중에 사용할 수 없습니다.

참조 제약조건 템플릿 작성

참조 제약조건 템플릿은 사용자가 한 객체를 다른 객체와 관련하여 제약할 수 있는 템플릿입니다. 이에 대한 예시는 '일치하는 인그레스가 존재하는 것으로 알려지기 전에 pod를 만들 수 없음'일 수 있습니다. 다른 예시는 '두 서비스가 동일한 호스트 이름을 갖도록 허용하지 않음'일 수 있습니다.

정책 컨트롤러를 사용하면 API 서버에서 사용자가 제공한 리소스 집합을 확인하여 참조 제약조건을 작성할 수 있습니다. 리소스가 수정되면 정책 컨트롤러는 리소스를 로컬에서 캐시하여 Rego 소스 코드에서 쉽게 참조할 수 있도록 합니다. 정책 컨트롤러는 이 캐시를 data.inventory 키워드 아래에서 사용할 수 있도록 합니다.

클러스터 범위 리소스는 다음 위치에 캐시됩니다.

data.inventory.cluster["GROUP_VERSION"]["KIND"]["NAME"]

예를 들어 이름이 my-favorite-node라는 노드는 다음 위치에서 찾을 수 있습니다.

data.inventory.cluster["v1"]["Node"]["my-favorite-node"]

네임스페이스 범위의 리소스는 여기에 캐시됩니다.

data.inventory.namespace["NAMESPACE"]["GROUP_VERSION"]["KIND"]["NAME"]

예를 들어, 네임스페이스 shipping-prod의 이름이 production-variables 인 ConfigMap은 아래에 있습니다.

data.inventory.namespace["shipping-prod"]["v1"]["ConfigMap"]["production-variables"]

객체의 전체 내용은 이 캐시 위치에 저장되며 Rego 소스 코드에서 참조할 수 있지만 적합하다고 생각됩니다.

Rego 자세히 알아보기

앞의 정보는 Rego의 Kubernetes 리소스에 대한 제약조건을 쉽게 작성할 수 있는 정책 컨트롤러의 고유한 기능을 제공합니다. Rego로 작성하는 방법에 대한 전체 튜토리얼은 이 가이드에서 다루지 않습니다. 그러나 Open Policy Agent 문서에 Rego 언어 자체의 구문 및 기능에 대한 정보가 포함되어 있습니다.

제약조건 템플릿 설치

제약조건 템플릿을 만든 후 kubectl apply를 사용하여 이를 적용하면 정책 컨트롤러가 수집을 처리합니다. 제약조건 템플릿의 status 필드에서 인스턴스화 오류가 없는지 확인합니다. 수집에 성공하면 status 필드에 created: true가 표시되고 status 필드에 표시된 observedGenerationmetadata.generation 필드와 같아야 합니다.

템플릿을 수집한 후에는 제약조건 만들기에 설명된 대로 템플릿을 적용할 수 있습니다.

제약조건 템플릿 삭제

제약조건 템플릿을 삭제하려면 다음 단계를 완료합니다.

  1. 보존하려는 제약조건에 제약조건 템플릿이 사용되지 않는지 확인합니다.

    kubectl get TEMPLATE_NAME
    

    제약조건 템플릿 이름과 클러스터에 있는 다른 객체 사이에 이름 지정 충돌이 있으면 대신 다음 명령어를 사용합니다.

    kubectl get TEMPLATE_NAME.constraints.gatekeeper.sh
    
  2. 제약조건 템플릿을 제거합니다.

    kubectl delete constrainttemplate CONSTRAINT_TEMPLATE_NAME
    

제약조건 템플릿을 제거하면 더 이상 제약조건을 참조하는 제약조건을 작성할 수 없습니다.

다음 단계