Kubernetes 객체 구성

이 주제에서는 Git에서 구성 동기화(Config Sync) 파일을 읽고 이를 클러스터에 자동으로 적용하는 구성을 만드는 방법에 대해 보여줍니다.

시작하기 전에

  • 저장소 구조를 파악해야 합니다. 저장소 내 구성 위치는 구성이 적용되는 클러스터와 네임스페이스에 영향을 줍니다. 이는 namespaces/ 디렉터리의 경우에 특히 그러합니다. namespaces/ 디렉터리의 하위 디렉터리가 추상 네임스페이스 디렉터리에서 구성을 상속할 수 있기 때문입니다.

  • 구성을 YAML과 JSON 등 두 가지 형식 중 하나로 작성해야 하므로 기본적으로 이러한 구문을 이해하고 있어야 합니다. 이 문서에 있는 모든 예시는 사용자가 쉽게 읽을 수 있는 YAML을 사용합니다.

  • 서로 다른 유형의 Kubernetes 객체는 각기 다른 구성을 가지고 있습니다. 이러한 객체 유형의 구성을 만들기 전에 원하는 구성을 수동으로 작성하는 방법을 파악하는 것이 좋습니다.

  • 여기서는 구성 동기화 작동 방식을 설명하기 위해 표준 저장소 예시를 작성했습니다. 이 주제의 예는 저장소에서 가져온 것이므로 저장소를 브라우저에서 열거나 로컬 시스템에 클론하면 유용할 수 있습니다.

구성 만들기

구성을 만들 때 저장소 내 가장 적합한 위치와 포함할 필드를 결정해야 합니다.

저장소 위치

저장소 내 구성 위치는 구성을 적용할 클러스터를 결정하는 하나의 요소입니다.

  • 네임스페이스를 제외한 클러스터 범위의 객체 구성은 저장소의 cluster/ 디렉터리에 저장됩니다.
  • 네임스페이스와 네임스페이스 범위 객체의 구성은 저장소의 namespaces/ 디렉터리에 저장됩니다.
  • 구성 동기화 구성요소의 구성은 저장소의 system/ 디렉터리에 저장됩니다.
  • Config Sync Operator 구성은 저장소에 직접 저장되지 않으며 동기화되지도 않습니다.

구성 내용

구성은 kubectl과 비슷한 가산적 방식을 사용합니다. 새 객체를 만들 경우 모든 필수 입력란을 포함해야 합니다. 그러나 기존 객체를 업데이트할 때는 업데이트해야 하는 입력란만 제공하면 됩니다.

구성을 적용할 때 유효한 Kubernetes 객체를 얻어야 합니다.

기존 Kubernetes 객체 구성

구성 동기화를 설치하기 전에 이미 클러스터에 있는 네임스페이스와 같은 기존의 Kubernetes 객체에 구성을 만들 수 있습니다. 그러나 객체에 configmanagement.gke.io/managed: enabled 주석이 없으면 이 구성은 무시됩니다. 기존 객체의 경우, 주석을 수동으로 적용해야 합니다.

특히 네임스페이스의 경우, 구성 동기화는 주석 처리되지 않은 네임스페이스 내에 새 객체를 만드는 구성을 적용하고 configmanagement.gke.io/managed: enabled 주석을 이 객체에 적용합니다. 그러나 구성 동기화는 주석 처리되지 않은 객체를 수정하거나 클러스터에서 삭제하지 않습니다. 이 내용은 시간 경과에 따른 구성 작업의 다이어그램에 설명되어 있습니다.

CustomResourceDefinitions 구성

Config Sync를 사용하면 다른 리소스를 동기화하는 것과 동일한 방식으로 CRD(CustomResourceDefinitions)를 동기화할 수 있습니다. CRD를 동기화할 때는 다음 사항에 유의해야 합니다.

  • 네임스페이스가 있는 커스텀 리소스를 선언할 때에도 CRD는 cluster/ 디렉터리에 있어야 합니다.

  • CRD 및 해당 CustomResources에 대한 업데이트는 예측 가능한 순서로 진행되지 않습니다. 동일한 커밋에서 CRD와 해당 CustomResources를 수정하면 커스텀 리소스가 업데이트되기 전에 CRD 업데이트를 예상하지 않습니다. 이로 인해 CustomResource와 CRD가 모두 클러스터에 나타날 때까지 syncer 로그에서 잠시 일시적인 오류를 보고할 수 있습니다.

  • CRD가 저장소의 CustomResource에 의존하는 경우 Config Sync는 CRD를 삭제할 수 없습니다. CRD를 삭제하려면 해당하는 CustomResource도 삭제해야 합니다. 저장소의 동일한 커밋에서 이 둘을 모두 삭제하는 것이 좋습니다.

  • 클러스터에 CRD가 이미 있으면 CRD를 동기화하지 않고도 CustomResource를 동기화할 수 있습니다.

구성 예시

다음 구성 예시는 모두 저장소 예시에서 가져온 것이며, 이를 바탕으로 자신의 구성을 작성할 수 있습니다. 이 목록은 완전한 목록이 아닙니다. 구성 동기화를 사용하면 모든 유형의 Kubernetes 객체를 구성할 수 있습니다.

네임스페이스 구성

이 구성은 audit이라는 네임스페이스를 만듭니다.

apiVersion: v1
kind: Namespace
metadata:
  name: audit

네임스페이스 구성을 만들 때 네임스페이스에 라벨이나 주석을 추가할 수도 있습니다. NamespaceSelector를 사용하는 경우 라벨이 필요합니다.

다음 구성 예시에서는 shipping-prod라는 네임스페이스가 없거나 관리되지 않는 경우 해당 네임스페이스를 만듭니다. 네임스페이스의 라벨은 env: prod이고 주석은 audit: true입니다. 누군가가 직접 객체의 메타데이터를 수정하면 구성 동기화는 구성의 값으로 신속하게 재설정합니다.

apiVersion: v1
kind: Namespace
metadata:
  name: shipping-prod
  labels:
    env: prod
  annotations:
    audit: "true"

네임스페이스 작업에 대한 자세한 내용은 네임스페이스 및 네임스페이스 범위의 객체 구성을 참조하세요.

ClusterRole 구성

다음 구성에서는 클러스터의 모든 namespace 객체를 읽을 수 있는 권한(get, watch, list)을 제공하는 namespace-reader라는 ClusterRole을 만듭니다. ClusterRole 구성은 주로 ClusterRoleBinding 구성과 함께 사용됩니다.

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: namespace-reader
rules:
- apiGroups: [""]
  resources: ["namespaces"]
  verbs: ["get", "watch", "list"]

ClusterRoleBinding 구성

다음 구성에서는 사용자에게 cheryl@foo-corp.com namespace-reader ClusterRole 권한을 부여하는 namespace-readers라는 ClusterRoleBinding을 만듭니다.

kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: namespace-readers
subjects:
- kind: User
  name: cheryl@foo-corp.com
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: namespace-reader
  apiGroup: rbac.authorization.k8s.io

ClusterRoleBinding은 클러스터 범위이며 네임스페이스 디렉터리나 추상 네임스페이스에 배치될 수 없습니다.

PodSecurityPolicy 구성

다음 예시에서는 psp라는 PodSecurityPolicy를 만듭니다. 이 정책은 권한을 사용하는 컨테이너 실행을 허용하지 않지만 노드의 유효한 사용자가 컨테이너를 실행할 수 있게 허용합니다.

apiVersion: extensions/v1beta1
kind: PodSecurityPolicy
metadata:
  name: psp
spec:
  privileged: false
  seLinux:
    rule: RunAsAny
  supplementalGroups:
    rule: RunAsAny
  runAsUser:
    rule: RunAsAny
  fsGroup:
    rule: RunAsAny
  volumes:
  - '*'

PodSecurityPolicy는 클러스터 범위이며 네임스페이스 디렉터리나 추상 네임스페이스에 배치될 수 없습니다.

NetworkPolicy 구성

다음 예시에서는 default-deny-all-traffic이라는 NetworkPolicy를 만듭니다.

kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: default-deny-all-traffic
spec:
  podSelector: {}

NetworkPolicy는 네임스페이스 범위이며 네임스페이스 디렉터리나 추상 네임스페이스에만 배치될 수 있습니다.

위의 NetworkPolicy를 단일 네임스페이스에 적용하면 이 네임스페이스에 있는 모든 Pod가 인그레스 트래픽과 이그레스 트래픽에서 분리됩니다.

하위 네임스페이스가 있는 추상 네임스페이스에 동일한 NetworkPolicy를 배치하여 여러 네임스페이스에 적용하면 각 네임스페이스가 NetworkPolicy를 상속합니다. 저장소 예시에서 shipping-app-backendshipping-dev, shipping-prod, shipping-stage의 구성이 포함된 추상 네임스페이스입니다. 위의 NetworkPolicy 예를 여기에 추가하면 각각 NetworkPolicy를 상속하므로 각 Pod가 인그레스 트래픽과 이그레스 트래픽으로부터 보호됩니다.

네임스페이스 상속을 사용하면 최소 권한 보안 방식을 적용할 수 있습니다. 예를 들어, 이전 NetworkPolicy 예시가 shipping-app-backend에 적용되고 다음 NetworkPolicy가 shipping-dev 네임스페이스에 추가되는 경우 인그레스 트래픽은 app:nginx 라벨이 있는 해당 네임스페이스의 Pod에만 적용됩니다. shipping-prodshipping-staging 네임 스페이스는 이 NetworkPolicy의 영향을 받지 않습니다.

kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: allow-nginx-ingress
spec:
  podSelector:
    matchLabels:
      app: nginx
  ingress:
  - {}

ResourceQuota 구성

다음 예시에서는 Pod 1개, 100밀리 CPU, 100MiB 메모리에 엄격한 제한을 설정하는 quota라는 ResourceQuota를 만듭니다.

kind: ResourceQuota
apiVersion: v1
metadata:
  name: quota
spec:
  hard:
    pods: "1"
    cpu: "100m"
    memory: 100Mi

지정된 유형의 새 객체 생성이 기존의 ResourceQuota를 위반하는 경우, Kubernetes는 ResourceQuota를 위반하지 않을 때까지 객체를 만들 수 없습니다.

다음 단계