이 페이지에서는 특정 요구에 적합한 사전 작성된 제약조건 템플릿을 찾을 수 없을 때 커스텀 제약조건 템플릿을 작성하고 이를 사용해서 정책 컨트롤러를 확장하는 방법을 보여줍니다.
이 페이지는 감사 또는 시행 자동화를 제공 및 유지하며 선언적 구성 템플릿을 사용하여 클라우드 플랫폼 내에서 실행되는 모든 리소스가 조직의 규정 준수 요구사항을 충족하도록 보장하려는 IT 관리자와 운영자를 위해 작성되었습니다. Google Cloud 콘텐츠에서 참조하는 일반적인 역할과 예시 태스크에 대한 자세한 내용은 일반 GKE Enterprise 사용자 역할 및 태스크를 참조하세요.
정책 컨트롤러 정책은 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 |
제약조건 리소스의 |
제약조건 템플릿에 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-test
는input.review
키워드 아래에 저장됩니다.
input.review
키워드에는 다음 필드가 포함됩니다.
필드 | 설명 |
---|---|
uid |
이 특정 요청의 고유 ID입니다. 감사 중에 사용할 수 없습니다. |
kind |
|
name |
리소스 이름입니다. 사용자가 CREATE 요청 시 이름을 생성하는 데 API 서버를 사용하는 경우에는 비어 있을 수 있습니다. |
namespace |
리소스 네임스페이스입니다(클러스터 범위 리소스에 제공되지 않음). |
operation |
요청된 작업(예: CREATE 또는 UPDATE)입니다. 감사 중에 사용할 수 없습니다. |
userInfo |
요청 사용자의 정보입니다. 감사 중에 사용할 수 없습니다. 형식은 다음과 같습니다.
|
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
필드에 표시된 observedGeneration
은 metadata.generation
필드와 같아야 합니다.
템플릿을 수집한 후에는 제약조건 만들기에 설명된 대로 템플릿을 적용할 수 있습니다.
제약조건 템플릿 삭제
제약조건 템플릿을 삭제하려면 다음 단계를 완료합니다.
보존하려는 제약조건에 제약조건 템플릿이 사용되지 않는지 확인합니다.
kubectl get TEMPLATE_NAME
제약조건 템플릿 이름과 클러스터에 있는 다른 객체 사이에 이름 지정 충돌이 있으면 대신 다음 명령어를 사용합니다.
kubectl get TEMPLATE_NAME.constraints.gatekeeper.sh
제약조건 템플릿을 제거합니다.
kubectl delete constrainttemplate CONSTRAINT_TEMPLATE_NAME
제약조건 템플릿을 제거하면 더 이상 제약조건을 참조하는 제약조건을 작성할 수 없습니다.
다음 단계
- 정책 컨트롤러 자세히 알아보기
- 제약조건 템플릿 라이브러리 참고 문서 보기
- PodSecurityPolicies 대신 제약조건을 사용하는 방법 알아보기