Skip to content
목록으로

인증, 인가, 어드미션

Kubernetes2025년 6월 15일
인증, 인가, 어드미션

저번 포스팅에서는, 스케줄링과 오토스케일링을 공부했습니다. 이번에는 설정과 보안입니다. 설정값과 비밀번호를 컨테이너에 어떻게 넣는지부터 시작해, 2편에서 미뤄두었던 apiserver 의 요청 처리 단계를 제대로 파헤치겠습니다. 인증, 인가, 어드미션 컨트롤이 각각 무엇을 하는지가 이번 편의 핵심입니다.

면접에서 "RBAC 을 설명해보세요" 나 "Secret 은 안전한가요" 같은 질문이 자주 나오는 영역입니다.


1. ConfigMap


설정값을 이미지에서 분리하기 위한 오브젝트입니다. 같은 이미지를 개발과 운영에서 그대로 쓰되 설정만 다르게 주입하는 것이 목적입니다.

1.1. 주입하는 방법

크게 두 가지입니다.

  1. 환경 변수로 : 간단하지만 컨테이너가 시작될 때 한 번 읽고 끝입니다. ConfigMap 을 나중에 바꿔도 이미 떠 있는 컨테이너에는 반영되지 않습니다.
  2. 볼륨으로 마운트 : 키가 파일 이름, 값이 내용이 됩니다. 이쪽은 kubelet 이 주기적으로 갱신하기 때문에 ConfigMap 을 바꾸면 파일 내용이 바뀝니다. 다만 즉시는 아니고 수십 초 정도 걸립니다.

여기서 중요한 함정이 있습니다. 파일이 바뀌어도 애플리케이션이 다시 읽지 않으면 의미가 없습니다. 설정 파일을 시작할 때 한 번만 읽는 애플리케이션이라면 결국 재시작해야 합니다. 그래서 실무에서는 설정이 바뀌면 Pod 를 다시 띄우도록 하는 방법을 씁니다. ConfigMap 의 내용을 해시해서 Pod 템플릿의 어노테이션에 넣어두면, 내용이 바뀔 때 어노테이션이 바뀌고 그것이 곧 새 롤아웃을 일으킵니다. Helm 을 쓸 때 흔히 하는 방식입니다.

1.2. subPath 의 함정

볼륨을 마운트하면 그 디렉토리의 기존 내용이 가려집니다. 그래서 파일 하나만 넣고 싶을 때 subPath 를 씁니다. 그런데 subPath 로 마운트한 파일은 자동 갱신되지 않습니다. 갱신을 기대하고 있다가 반영이 안 돼 한참 헤매는 일이 흔합니다.

1.3. 크기 제한

ConfigMap 과 Secret 은 etcd 에 저장되고 1MB 를 넘을 수 없습니다. etcd 의 기본 요청 크기 제한 때문입니다. 큰 파일은 여기가 아니라 볼륨이나 오브젝트 스토리지에 두어야 합니다.


2. Secret


2.1. Base64 는 암호화가 아니다

가장 자주 나오는 오해입니다. Secret 의 값은 Base64 로 인코딩되어 있을 뿐이고 이것은 누구나 즉시 되돌릴 수 있는 표현 방식입니다. 암호화가 아닙니다. 인코딩을 하는 이유는 보안이 아니라 바이너리 데이터를 YAML 에 담기 위해서입니다. 인증서 파일 같은 것을 그대로 넣을 수 없기 때문입니다.

2.2. 그럼 Secret 은 무엇이 다른가

ConfigMap 과 비교했을 때 실제로 다른 점들입니다.

  1. 노드에서 tmpfs 에 저장된다 : 볼륨으로 마운트하면 디스크가 아니라 메모리에 올라갑니다. 노드 디스크에 평문으로 남지 않습니다.
  2. 필요한 노드에만 전달된다 : 그 Secret 을 쓰는 Pod 가 있는 노드로만 갑니다.
  3. etcd 저장 시 암호화할 수 있다 : apiserver 에 EncryptionConfiguration 을 설정하면 etcd 에 암호화된 상태로 저장됩니다. 이 설정을 하지 않으면 etcd 에 평문으로 들어갑니다. 기본값이 아니라는 점이 중요합니다.
  4. RBAC 으로 따로 통제할 수 있다 : ConfigMap 은 볼 수 있지만 Secret 은 볼 수 없게 권한을 가를 수 있습니다.

2.3. 그래도 남는 한계

Secret 을 읽을 수 있는 권한이 있으면 값을 그대로 볼 수 있고 그 Pod 안에 들어갈 수 있으면 마운트된 파일을 읽을 수 있습니다. 그래서 민감도가 높은 환경에서는 외부 비밀 관리 시스템(Vault, 클라우드의 Secrets Manager 등)을 쓰고 External Secrets Operator 나 Secrets Store CSI Driver 로 끌어오는 구성을 씁니다.

그리고 환경 변수로 주입한 Secret 은 프로세스 목록이나 크래시 덤프, 로그에 노출될 위험이 볼륨보다 큽니다. 가능하면 볼륨으로 넣는 편이 낫습니다.


3. 요청이 apiserver 를 통과하는 길


2편에서 미뤄둔 부분입니다. 모든 요청은 네 단계를 지납니다.

요청 → [인증] → [인가] → [어드미션] → [검증·저장]
       누구인가   권한있나   손볼것있나    etcd 기록

각 단계가 무엇을 하는지 차례로 보겠습니다.


4. 인증


"이 요청을 보낸 것이 누구인가" 를 판단합니다. 여러 방식을 동시에 켤 수 있고 하나라도 성공하면 통과합니다. 전부 실패하면 401 입니다.

4.1. 쿠버네티스에는 User 오브젝트가 없다

면접에서 자주 확인하는 지점입니다. Pod 나 Service 와 달리 사람 사용자를 나타내는 오브젝트가 없습니다. kubectl get users 같은 명령이 없습니다. 쿠버네티스는 사용자 관리를 외부에 맡겼습니다. 인증서의 주체 이름이든, OIDC 토큰의 클레임이든, 외부에서 온 신원을 받아 "이름과 그룹" 이라는 형태로만 다룹니다.

4.2. 주요 인증 방식

  1. 클라이언트 인증서 : 가장 기본입니다. 인증서의 CN(Common Name)이 사용자 이름, O(Organization)가 그룹이 됩니다. kubeadm 으로 만든 관리자 인증서가 system:masters 그룹에 속하는 것이 이 방식입니다. 단점은 폐기가 어렵다는 것입니다. 인증서를 발급하면 만료 전까지 무효화하기가 까다롭습니다.
  2. Bearer 토큰 (ServiceAccount) : Pod 안에서 도는 것들이 쓰는 방식입니다. 다음 장에서 다룹니다.
  3. OIDC : 사내 인증 시스템과 연동합니다. 사람 사용자에게는 이 방식이 권장됩니다. 토큰에 만료가 있고 중앙에서 통제할 수 있기 때문입니다.
  4. Webhook : 외부 서비스에 토큰 검증을 위임합니다. 클라우드 관리형 클러스터에서 클라우드 계정 체계와 붙일 때 쓰입니다.

4.3. ServiceAccount

Pod 안에서 돌아가는 것들의 신원입니다. 사람이 아니라 프로그램을 위한 계정이고 이것은 실제 오브젝트로 존재합니다. Pod 에 지정하지 않으면 그 네임스페이스의 default ServiceAccount 가 붙습니다. 그리고 토큰이 /var/run/secrets/kubernetes.io/serviceaccount/ 에 자동으로 마운트됩니다.

여기서 알아둘 변화가 있습니다. 예전에는 ServiceAccount 를 만들면 만료 없는 토큰이 Secret 으로 영구 생성되었습니다. 유출되면 계속 유효한 위험한 구조였습니다. 지금은 바운드 토큰(Bound Service Account Token) 방식입니다.

  1. 만료가 있다 : 기본 1시간이며 kubelet 이 자동 갱신합니다.
  2. 대상이 묶여 있다 : 특정 Pod 에 바인딩되어, 그 Pod 가 사라지면 토큰도 무효가 됩니다.
  3. 감사(audience)를 지정할 수 있다 : 의도한 수신자에게만 유효합니다.

API 를 호출할 필요가 없는 Pod 라면 automountServiceAccountToken: false 로 토큰 마운트를 꺼두는 것이 좋습니다. 컨테이너가 뚫렸을 때 API 로 넘어가는 경로를 막습니다.


5. 인가


"이 사람이 이 일을 해도 되는가" 를 판단합니다. 여러 인가 모듈을 순서대로 물어보고 하나라도 허용하면 통과합니다. 전부 거부하거나 아무도 결정하지 않으면 403 입니다.

5.1. RBAC

지금 사실상 표준인 방식입니다. 네 가지 오브젝트로 이루어집니다.

  1. Role : 네임스페이스 안에서의 권한 묶음
  2. ClusterRole : 클러스터 전체 또는 네임스페이스에 속하지 않는 리소스에 대한 권한 묶음
  3. RoleBinding : Role(또는 ClusterRole)을 사용자·그룹·ServiceAccount 에 연결
  4. ClusterRoleBinding : ClusterRole 을 클러스터 범위로 연결

권한은 "어떤 리소스에 어떤 동사(verb)를 허용하는가" 로 적습니다.

yaml
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]

5.2. RBAC 의 중요한 성질들

  1. 허용만 있고 거부가 없다 : RBAC 에는 "금지" 규칙이 없습니다. 모든 것은 기본 거부이고 규칙은 허용을 더할 뿐입니다. 여러 바인딩이 걸리면 권한은 합쳐집니다. 그래서 "이것만 빼고 다 허용" 같은 것을 표현할 수 없습니다.
  2. ClusterRole 을 RoleBinding 으로 묶을 수 있다 : 자주 쓰는 조합입니다. 권한 묶음은 ClusterRole 로 한 번만 정의해두고 RoleBinding 으로 연결하면 그 네임스페이스 안에서만 유효합니다. 같은 역할을 팀마다 각자의 네임스페이스에 적용할 때 유용합니다.
  3. 권한 상승이 막혀 있다 : 자기가 갖지 않은 권한을 담은 Role 을 만들 수 없습니다. 그렇지 않으면 Role 을 만들 수 있는 사람이 스스로 관리자가 될 수 있기 때문입니다. 다만 escalate 나 bind 권한이 있으면 가능한데 이 권한을 주는 것은 사실상 관리자 권한을 주는 것과 같습니다.

5.3. 확인하는 방법

권한 설정은 머리로 따지기보다 직접 물어보는 편이 빠릅니다.

bash
kubectl auth can-i create deployments --namespace dev
kubectl auth can-i list secrets --as=system:serviceaccount:dev:my-app

--as 로 다른 신원을 흉내 내어(impersonate) 확인할 수 있습니다.

5.4. 실무에서의 원칙

  1. default ServiceAccount 에 권한을 주지 않습니다. 아무 Pod 나 그 권한을 갖게 됩니다.
  2. 와일드카드를 피합니다. resources: ["*"], verbs: ["*"] 는 편하지만 위험합니다.
  3. cluster-admin 바인딩을 최소화합니다.
  4. Secret 에 대한 list 권한을 주의합니다. 목록 조회로 값까지 전부 읽을 수 있습니다.

6. 어드미션 컨트롤


인가까지 통과한 요청에 대해 "그대로 받아도 되는가, 손볼 것은 없는가" 를 판단합니다. 개인적으로 가장 흥미로웠던 부분입니다.

6.1. 두 종류

  1. Mutating : 요청 내용을 고칩니다. 먼저 실행됩니다.
  2. Validating : 요청을 검사해 받거나 거부합니다. 나중에 실행됩니다.

순서가 이렇게 정해진 이유는 분명합니다. 고친 다음에 검사해야 최종 형태를 검증할 수 있기 때문입니다.

6.2. 내장 어드미션 플러그인

apiserver 안에 이미 여러 개가 들어 있습니다.

  1. ServiceAccount : Pod 에 ServiceAccount 와 토큰을 자동으로 붙여줍니다.
  2. LimitRanger : 6편의 LimitRange 에 따라 기본 requests/limits 를 채워 넣습니다.
  3. ResourceQuota : 네임스페이스 총량을 넘으면 거부합니다.
  4. NamespaceLifecycle : 삭제 중인 네임스페이스에 오브젝트를 만들지 못하게 합니다.
  5. PodSecurity : 다음 장에서 다룹니다.

LimitRange 로 적어둔 기본값이 실제로 채워지는 것이 이 단계라는 것을 알고 나니, 6편의 내용이 어디서 실행되는지 연결이 되었습니다.

6.3. 동적 어드미션 웹훅

직접 만든 규칙을 끼워 넣을 수 있습니다. apiserver 가 외부 웹훅 서버를 호출해 판단을 위임합니다. 이것으로 할 수 있는 일이 많습니다.

  1. 모든 Pod 에 특정 라벨이 없으면 거부
  2. 이미지 태그가 latest 인 Pod 를 거부
  3. 서비스 메시의 사이드카를 자동으로 주입 (Istio 가 이 방식입니다)
  4. 회사 정책에 맞는 자원 설정 강제

주의할 점이 있습니다. 웹훅 서버가 죽으면 클러스터가 마비될 수 있습니다. failurePolicy: Fail 로 두면 웹훅이 응답하지 않을 때 모든 관련 요청이 거부됩니다. 그래서 웹훅 서버 자체는 고가용성으로 두고 자기 네임스페이스는 대상에서 제외하는 등의 설계가 필요합니다. 웹훅이 자기 자신을 만들지 못해 되살아나지 못하는 상황을 막기 위해서입니다.

6.4. 정책 엔진

웹훅을 직접 구현하는 대신, 정책을 선언적으로 적을 수 있게 해주는 도구들이 있습니다. OPA Gatekeeper 와 Kyverno 가 대표적입니다. 최근에는 쿠버네티스 자체에도 ValidatingAdmissionPolicy 가 들어왔습니다. CEL 이라는 표현식으로 정책을 적으면 apiserver 안에서 직접 평가합니다. 외부 웹훅 서버를 띄우지 않아도 되므로 앞서 말한 가용성 문제에서 자유롭습니다. 1.30 에서 정식이 되었습니다.


7. Pod Security


7.1. PSP 에서 PSA 로

예전에는 PodSecurityPolicy(PSP) 가 있었습니다. 그런데 쓰기가 어려웠습니다. 여러 정책이 겹치면 어느 것이 적용될지 예측하기 힘들었고 RBAC 으로 정책을 사용자에게 연결하는 방식이 직관적이지 않았습니다. 결국 1.25 에서 제거되었습니다.

대체로 들어온 것이 Pod Security Admission(PSA) 입니다. 네임스페이스에 라벨을 붙이는 것만으로 정책이 적용됩니다.

7.2. 세 가지 수준

  1. privileged : 제한 없음
  2. baseline : 알려진 권한 상승 경로를 막음. 특권 컨테이너, 호스트 네임스페이스 사용, 대부분의 hostPath 등을 금지
  3. restricted : 강하게 제한. 루트가 아닌 사용자로 실행, 모든 capability 제거, 읽기 전용 루트 파일 시스템 권장, seccomp 프로필 적용 등

그리고 각 수준에 대해 세 가지 모드를 걸 수 있습니다.

  1. enforce : 어기면 거부
  2. audit : 감사 로그에 기록만
  3. warn : 사용자에게 경고만 표시

이 조합이 실용적입니다. 기존 클러스터에 곧바로 enforce 를 걸면 많은 워크로드가 멈추니, 먼저 warn 과 audit 으로 걸어 무엇이 걸리는지 확인하고 하나씩 고친 뒤에 enforce 로 올리는 식으로 옮겨갑니다.

7.3. securityContext

개별 Pod 와 컨테이너에 거는 설정입니다. PSA 는 이 값들이 정책에 맞는지를 검사합니다.

  1. runAsNonRoot / runAsUser : 루트로 실행하지 않게 합니다.
  2. allowPrivilegeEscalation: false : 실행 중 권한 상승을 막습니다.
  3. readOnlyRootFilesystem: true : 루트 파일 시스템을 읽기 전용으로 만듭니다. 침투 후 도구를 내려받아 실행하는 것을 어렵게 합니다.
  4. capabilities : 리눅스 권한을 개별적으로 떼어내거나 붙입니다. drop: ["ALL"] 로 전부 떼고 필요한 것만 더하는 것이 원칙입니다.
  5. seccompProfile : 허용할 시스템 콜을 제한합니다.

privileged: true 는 사실상 노드 루트 권한입니다. 컨테이너가 호스트의 거의 모든 것에 접근할 수 있게 되므로, 정말 필요한 시스템 컴포넌트가 아니면 쓰지 않아야 합니다.


8. 그 밖의 보안 요소


8.1. 이미지

  1. 태그가 아니라 다이제스트로 고정한다 : latest 는 언제 무엇이 바뀔지 알 수 없습니다.
  2. 취약점을 검사한다 : Trivy 같은 도구로 CI 단계에서 확인합니다.
  3. 서명을 검증한다 : Sigstore 등으로 서명하고 어드미션 단계에서 검증을 강제할 수 있습니다.
  4. 최소 이미지를 쓴다 : distroless 처럼 셸조차 없는 이미지는 침투 후 할 수 있는 일을 크게 줄입니다.

8.2. 감사 로그

apiserver 는 누가 언제 무엇을 했는지를 남길 수 있습니다. 어느 수준까지 남길지는 정책으로 정합니다. 사고가 났을 때 추적할 수 있는 유일한 단서인 경우가 많으므로, 운영 클러스터라면 반드시 켜두어야 합니다.

8.3. 다층 방어

한 겹만으로는 부족합니다. 각 계층이 서로를 보완합니다.

  1. 이미지 : 취약점이 적은 최소 이미지
  2. 런타임 : securityContext 로 권한 축소
  3. 네트워크 : 4편의 NetworkPolicy 로 통신 제한
  4. API : RBAC 으로 권한 최소화, 토큰 자동 마운트 해제
  5. 정책 : 어드미션으로 위 항목들을 강제
  6. 감사 : 무슨 일이 있었는지 기록

9. 조금 더 들어가보기 : 인증서와 토큰은 어떻게 검증되는가


인증과 인가를 절차로 정리했는데 그 아래에서 실제로 무엇이 오가는지까지 보겠습니다. 암호학적인 부분을 알아두면 왜 이렇게 설계했는지가 분명해집니다.

9.1. 인증서로 인증한다는 것

클라이언트 인증서 방식은 TLS 핸드셰이크 안에서 신원 확인이 끝납니다.

  1. 클라이언트가 자기 인증서를 제시합니다.
  2. apiserver 는 그 인증서가 신뢰하는 기관의 서명을 받았는지 확인합니다.
  3. 그리고 클라이언트가 개인키를 실제로 갖고 있는지를 서명 검증으로 확인합니다.
  4. 통과하면 인증서 안의 이름과 조직을 사용자와 그룹으로 씁니다.

여기서 앞서 말한 폐기가 어렵다는 문제가 설명됩니다. 인증서는 자기 안에 유효 기간을 담고 있고 검증은 서명과 기간만 봅니다. 발급 후에 무효로 만들려면 별도의 폐기 목록을 유지하고 매번 확인해야 하는데 이 구조가 무겁습니다.

그래서 사람 사용자에게는 인증서 대신 만료가 짧고 중앙에서 통제 가능한 토큰을 권장합니다.

9.2. 토큰은 어떻게 검증되는가

서비스어카운트 토큰은 세 부분으로 이루어진 문자열입니다.

헤더.페이로드.서명

앞의 두 부분은 그냥 인코딩된 JSON 이라 누구나 열어볼 수 있습니다. 안에는 어느 서비스어카운트인지, 언제까지 유효한지, 어떤 대상에게 유효한지가 들어 있습니다. 비밀은 세 번째 조각에 있습니다. apiserver 가 개인키로 서명해두었고 검증은 공개키로 합니다. 내용을 한 글자만 바꿔도 서명이 맞지 않습니다.

여기서 중요한 성질이 나옵니다. 검증에 저장소 조회가 필요 없습니다. 서명만 확인하면 되므로 빠릅니다. 대신 발급한 토큰을 즉시 무효화하기 어렵다는 같은 문제를 안습니다. 그래서 유효 기간을 짧게 두고 자동으로 갱신하는 방식을 씁니다.

앞서 본 대상 지정도 여기서 의미를 갖습니다. 토큰 안에 "이 토큰은 누구에게 유효한가" 가 박혀 있으므로, 다른 서비스가 그 토큰을 가로채 apiserver 에 써먹을 수 없습니다.

9.3. Secret 이 tmpfs 에 올라간다는 것

볼륨으로 마운트한 Secret 은 디스크가 아니라 메모리 기반 파일 시스템에 올라갑니다. 이것의 의미는 두 가지입니다.

  1. 노드 디스크에 평문이 남지 않습니다. 노드의 디스크를 떼어가도 거기에는 없습니다.
  2. 노드가 재시작되면 사라집니다. 다시 받아와야 합니다.

다만 그 컨테이너 안에 들어갈 수 있으면 파일을 읽을 수 있습니다. 메모리에 있다는 것이 접근을 막아주지는 않습니다. tmpfs 는 디스크에 흘리지 않는다는 목적이지 접근 통제 수단이 아닙니다.

9.4. etcd 암호화가 왜 기본이 아닌가

앞서 짚은 대로 etcd 저장 시 암호화는 따로 켜야 합니다. 왜 기본이 아닐까요.

  1. 키를 어디에 둘 것인가를 정해야 합니다. 같은 서버에 두면 의미가 줄고 외부 키 관리 서비스를 쓰려면 그 연동이 필요합니다.
  2. 성능 비용이 있습니다. 모든 Secret 읽기와 쓰기에 암복호화가 더해집니다.
  3. 키를 교체할 때 기존 데이터를 다시 써야 합니다.

결정이 필요한 항목이라 기본값으로 강제하지 않은 것인데 모르고 지나가면 평문으로 남는다는 점에서 위험한 기본값이기도 합니다.

9.5. 어드미션 웹훅은 요청 경로 위에 있다

웹훅은 요청을 처리하는 도중에 호출됩니다. 비동기가 아닙니다. 그래서 웹훅의 응답 시간이 모든 관련 요청의 응답 시간에 그대로 더해집니다. 여기서 몇 가지가 따라옵니다.

  1. 웹훅이 느리면 클러스터가 느려집니다. Pod 를 만들 때마다 호출된다면 배포 속도가 그만큼 늘어납니다.
  2. 웹훅이 죽으면 실패 정책에 따라 모든 관련 요청이 거부됩니다.
  3. 자기 자신을 대상으로 삼으면 죽었을 때 되살아날 수 없습니다. 웹훅을 띄우려면 Pod 를 만들어야 하는데 그 Pod 생성이 죽은 웹훅의 승인을 기다리기 때문입니다.

세 번째가 실제로 클러스터를 통째로 마비시키는 경로입니다. 그래서 웹훅의 대상 범위에서 자기 네임스페이스와 시스템 네임스페이스를 빼두는 것이 기본 설계입니다. 최근에 들어온 apiserver 안에서 직접 평가하는 정책 방식은 이 문제 자체를 없앱니다. 외부 호출이 없으니 느려지지도, 죽지도 않습니다.

9.6. 대규모에서 부딪히는 것들

  1. Secret 과 ConfigMap 수 : 전부 etcd 에 들어가므로 오브젝트가 쌓이면 저장 크기에 영향을 줍니다.
  2. 토큰 갱신 부하 : Pod 마다 주기적으로 토큰이 갱신되므로, Pod 가 수만 개면 그만큼의 요청이 apiserver 로 갑니다.
  3. RBAC 규칙 평가 : 규칙이 많아지면 인가 판단에 걸리는 시간이 늘어납니다. 와일드카드를 남발한 규칙이 많을수록 나빠집니다.
  4. 웹훅 지연 : 위의 이유로, 클러스터 규모에 비례해 영향이 커집니다.

여기서도 정리하지 않은 오브젝트가 결국 성능 문제로 돌아온다는 이야기가 반복됩니다.


결론


이번 편에서 가장 크게 정리된 것은 인증 · 인가 · 어드미션이 전혀 다른 일을 한다는 구분이었습니다. 전에는 셋을 뭉뚱그려 "보안" 으로 알고 있었는데 누구인지 확인하는 단계, 해도 되는지 보는 단계, 내용을 손보고 검사하는 단계로 갈려 있었습니다. 401 과 403 이 왜 다른 단계에서 나오는지도 이제 설명할 수 있게 되었습니다.

두 번째로 인상 깊었던 것은 쿠버네티스에 사용자 오브젝트가 없다는 사실이었습니다. 처음에는 빠진 기능처럼 보였는데 사용자 관리를 외부에 맡기고 "이름과 그룹" 이라는 최소한의 형태로만 받아들인 설계였습니다. 덕분에 인증서든 OIDC 든 클라우드 계정이든 같은 자리에 끼워 넣을 수 있었습니다. CNI 와 CSI 에서 본 것과 같은 태도가 여기서도 반복되고 있었습니다.

세 번째는 Secret 에 대한 오해를 걷어낸 것입니다. Base64 가 암호화가 아니라는 것, etcd 암호화는 기본이 아니라 따로 켜야 한다는 것은 알아두지 않으면 위험한 지식이었습니다. 동시에 Secret 이 그냥 ConfigMap 과 같은 것은 아니라는 점(tmpfs, 노드 한정 전달, RBAC 분리)도 함께 정리되었습니다.

마지막으로 어드미션 웹훅이 클러스터를 멈출 수 있다는 것이 기억에 남습니다. 보안을 강화하려고 넣은 장치가 가용성의 단일 장애점이 되는 구조인데 안전장치를 더할 때 그것 자체의 실패를 함께 설계해야 한다는 것을 보여주는 예였습니다.


공부 참고 자료


📑 1. Kubernetes 공식 문서 - ConfigMaps

📑 2. Kubernetes 공식 문서 - Secrets

📑 3. Kubernetes 공식 문서 - Encrypting Secret Data at Rest

📑 4. Kubernetes 공식 문서 - Authenticating

📑 5. Kubernetes 공식 문서 - Using RBAC Authorization

📑 6. Kubernetes 공식 문서 - Service Accounts

📑 7. Kubernetes 공식 문서 - Admission Controllers

📑 8. Kubernetes 공식 문서 - Dynamic Admission Control

📑 9. Kubernetes 공식 문서 - Pod Security Standards

📑 10. Kubernetes 공식 문서 - Validating Admission Policy

📑 11. Kubernetes 공식 문서 - Auditing

Comments