<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Policy Governance on jyukki's Blog</title><link>https://jyukki.com/tags/policy-governance/</link><description>Recent content in Policy Governance on jyukki's Blog</description><generator>Hugo -- 0.147.0</generator><language>ko-KR</language><lastBuildDate>Mon, 07 Sep 2026 10:06:00 +0900</lastBuildDate><atom:link href="https://jyukki.com/tags/policy-governance/index.xml" rel="self" type="application/rss+xml"/><item><title>2026 개발 트렌드: Kubernetes v1.37 Manifest 기반 Admission Control, 정책 보호선을 API 밖으로 옮기다</title><link>https://jyukki.com/posts/2026-09-07-kubernetes-manifest-admission-bootstrap-governance-trend/</link><pubDate>Mon, 07 Sep 2026 10:06:00 +0900</pubDate><guid>https://jyukki.com/posts/2026-09-07-kubernetes-manifest-admission-bootstrap-governance-trend/</guid><description>Kubernetes v1.37에서 Beta가 된 manifest 기반 admission control을 계기로, API 안의 정책을 보호하려면 bootstrap 신뢰 경로·파일 권한·검증·rollback을 어떻게 다시 설계해야 하는지 정리합니다.</description><content:encoded><![CDATA[<p>Kubernetes에서 admission control은 보통 Pod 생성 전에 policy를 적용하는 기능으로 설명된다. 실제 운영에서 더 어려운 질문은 따로 있다. <strong>그 policy 객체 자체가 변경되거나 제거되는 일을 누가, 언제, 어느 신뢰 경로에서 막는가?</strong> API server와 etcd에 저장한 ValidatingAdmissionPolicy, webhook configuration, 관련 RBAC는 관리하기 편하지만, API server가 올라오는 bootstrap 구간에는 아직 그 정책이 적용되지 않을 수 있다. 또 API를 수정할 수 있는 강한 권한이 탈취되면 정책 자원을 먼저 약화시키려는 시도가 가능하다.</p>
<p>Kubernetes v1.37은 이 경계에 manifest 기반 admission control을 Beta로 올렸다. admission webhook과 CEL 기반 정책을 API가 아니라 API server가 읽는 디스크 manifest에서 startup부터 적용하고, 파일을 감시해 유효한 변경만 reload한다. invalid update가 들어오면 마지막 유효 구성을 유지한다. 이는 policy를 더 쉽게 쓰는 기능보다, <strong>cluster bootstrap과 policy 보호의 신뢰 원천을 어디에 둘 것인가</strong>라는 platform engineering 변화다. 공식 릴리스 노트는 이 기능이 API 기반 admission configuration을 보호할 수 있도록 별도 관리 경로를 제공한다고 설명한다. <a href="https://kubernetes.io/blog/2026/08/26/kubernetes-v1-37-release/">Kubernetes v1.37 release</a></p>
<p>이 글은 <a href="/learning/deep-dive/deep-dive-admission-control-concurrency-limits/">Admission Control과 Concurrency Limits</a>, <a href="/learning/deep-dive/deep-dive-authorization-policy-shadow-rollout-playbook/">Authorization Policy Shadow Rollout</a>, <a href="/learning/deep-dive/deep-dive-config-change-safety-rollout-playbook/">Config Change Safety 플레이북</a>, <a href="/posts/2026-08-31-artifact-attestation-deployment-admission-gate-trend/">Artifact Attestation과 Deployment Admission Gate</a>를 연결한다. 앞선 글들이 workload 요청이나 artifact를 어떤 기준으로 허용할지를 다뤘다면, 여기서는 <strong>그 기준을 누가 바꾸고 API server 시작 시점에 누가 먼저 적용하는가</strong>를 다룬다.</p>
<h2 id="이-글에서-얻는-것">이 글에서 얻는 것</h2>
<ul>
<li>API 기반 admission policy가 가진 bootstrap·자기보호 한계를 구분합니다.</li>
<li>manifest 기반 policy source를 도입할 때 파일 경로, CI 검증, 승인, rollback을 하나의 trust chain으로 설계할 수 있습니다.</li>
<li>어떤 policy를 파일 기반으로 옮기고 어떤 policy를 기존 API 관리로 남길지 결정 기준을 얻습니다.</li>
<li>Beta 기능을 운영에 넣을 때 기능 활성화 여부보다 중요한 관측·canary·break-glass 체크리스트를 가져갑니다.</li>
</ul>
<h2 id="핵심-개념이슈">핵심 개념/이슈</h2>
<h3 id="1-admission-policy의-문제는-무슨-rule인가와-누가-rule을-바꾸는가로-나뉜다">1) admission policy의 문제는 무슨 rule인가와 누가 rule을 바꾸는가로 나뉜다</h3>
<p>일반 admission policy는 Pod가 privileged인지, 검증되지 않은 image를 쓰는지, 특정 namespace에 배포되는지 판단한다. 이 층은 policy expression과 예외 조건이 핵심이다. 그러나 cluster root 권한을 가진 주체가 admission configuration을 수정하거나, control plane recovery 중 API policy가 아직 로드되지 않았다면, 좋은 expression도 보호 장치가 되지 못한다.</p>
<p>manifest 기반 admission control은 policy artifact를 API 객체와 분리한다. API server가 디스크에서 manifest를 읽어 startup부터 적용하므로, API 안에서 admission resource를 변경해도 그 파일 기반 rule은 같은 경로로 바로 무력화할 수 없다. 이 차이를 API 밖에 YAML 하나 더 둔다는 말로 축소하면 안 된다. 관리 경로가 다음처럼 바뀐다.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>기존: Git/운영자 -&gt; Kubernetes API -&gt; etcd -&gt; API 기반 admission policy
</span></span><span style="display:flex;"><span>변경: Git/승인 CI -&gt; signed/config artifact -&gt; API server의 제한된 manifest 경로 -&gt; bootstrap admission policy
</span></span></code></pre></div><p>둘째 경로의 보호 수준은 Git repository 이름으로 결정되지 않는다. API server host에서 누가 그 파일을 바꿀 수 있는지, control-plane image에 어떻게 들어가는지, mount가 쓰기 가능한지, 변경을 어떻게 추적하는지가 실제 root of trust다. 파일 권한이 넓거나 노드 접근이 느슨하면 API resource보다 더 약한 방어가 될 수 있다.</p>
<h3 id="2-startup-enforcement와-valid-only-reload는-장애-회복력과-변경-통제를-함께-바꾼다">2) startup enforcement와 valid-only reload는 장애 회복력과 변경 통제를 함께 바꾼다</h3>
<p>v1.37의 중요한 운영 특성은 valid manifest는 변경 시 reload하고, invalid update는 이전의 유효한 구성을 계속 쓴다는 점이다. 급하게 편집한 YAML의 문법 오류가 policy를 통째로 사라지게 만드는 위험은 낮춘다. 그러나 이것은 validation layer 하나일 뿐이다. 문법·schema가 맞지만 namespace selector를 넓히거나 deny 조건을 반대로 쓴 정책은 유효해도 서비스 배포를 멈출 수 있다.</p>
<p>그래서 검증을 세 층으로 나눠야 한다.</p>
<table>
  <thead>
      <tr>
          <th>검증 층</th>
          <th>확인할 것</th>
          <th>실패 시 조치</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>구조 검증</td>
          <td>manifest 형식, API version, 필수 필드, 참조 이름</td>
          <td>CI에서 즉시 차단</td>
      </tr>
      <tr>
          <td>의미 검증</td>
          <td>selector 범위, namespace 예외, CEL 표현식, 기존 rule과 충돌</td>
          <td>test cluster에서 allowed/denied fixture 실행</td>
      </tr>
      <tr>
          <td>운영 검증</td>
          <td>API server reload, denial rate, policy version, 배포 lead time</td>
          <td>canary cluster에서 관측 후 승격 또는 rollback</td>
      </tr>
  </tbody>
</table>
<p>특히 허용되어야 하는 workload와 거부되어야 하는 workload를 같은 fixture 세트에 넣어야 한다. 차단 케이스만 통과시키면 운영 daemon, monitoring agent, bootstrap component가 막히는 회귀를 놓친다. <a href="/learning/deep-dive/deep-dive-authorization-policy-shadow-rollout-playbook/">Authorization Policy Shadow Rollout</a>처럼 처음에는 audit 또는 제한된 namespace 관측으로 false positive를 찾고, 실제 차단 범위를 단계적으로 넓히는 편이 안전하다.</p>
<h3 id="3-모든-admission-policy를-manifest로-옮기는-것은-정답이-아니다">3) 모든 admission policy를 manifest로 옮기는 것은 정답이 아니다</h3>
<p>파일 기반 source는 API 변경을 넘어 보호해야 하는 좁은 bootstrap policy에 적합하다. 반면 application team이 namespace별로 자주 조정하는 quota, 개발용 예외, 빠르게 바뀌는 label rule까지 모두 control-plane 파일로 묶으면 platform 팀이 병목이 되고 변경 반경이 커진다.</p>
<p>다음 기준으로 나누면 실무적이다.</p>
<table>
  <thead>
      <tr>
          <th>policy 성격</th>
          <th>권장 source</th>
          <th>판단 이유</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>admission resource 자체의 무단 변경 방지, control-plane bootstrap 보호</td>
          <td>manifest 우선 검토</td>
          <td>API 안의 policy만으로 자신을 보호하기 어려운 경계다.</td>
      </tr>
      <tr>
          <td>전사적으로 고정된 privileged workload·host path·critical namespace 보호</td>
          <td>manifest 또는 강하게 관리된 중앙 policy</td>
          <td>낮은 변경 빈도와 큰 blast radius를 별도 승인으로 다룬다.</td>
      </tr>
      <tr>
          <td>팀별 resource rule, 점진적 실험, 자주 바뀌는 제품 정책</td>
          <td>Kubernetes API + GitOps</td>
          <td>namespace ownership과 빠른 feedback이 더 중요하다.</td>
      </tr>
      <tr>
          <td>일회성 incident 완화</td>
          <td>명시적 만료가 있는 API policy</td>
          <td>긴급 변경을 permanent host artifact로 남기지 않는다.</td>
      </tr>
  </tbody>
</table>
<p>핵심은 두 source를 병렬로 오래 두지 않는 것이다. 같은 rule이 API와 manifest에 중복되면 한쪽은 allow, 다른 쪽은 deny하는 상황에서 운영자는 어떤 source가 권위인지 알기 어렵다. 각 정책마다 policy ID, owner, authoritative source, scope, effective version, rollback target을 registry에 기록하고 중복 enforcement는 migration 기간으로 제한한다.</p>
<h3 id="4-filesystem은-이제-control-plane-security-boundary다">4) filesystem은 이제 control-plane security boundary다</h3>
<p>manifest 방식은 etcd ACL 문제 일부를 줄이는 대신 host filesystem과 artifact delivery를 보안 경계로 올린다. API server 노드에서 policy directory에 쓸 수 있는 계정, CI가 push하는 image, configuration management agent, break-glass shell access는 모두 policy editor가 된다. 일반 ConfigMap보다 높은 등급으로 취급해야 하는 이유다.</p>
<p>최소 운영 기준은 다음과 같다.</p>
<ul>
<li>manifest는 versioned repository에서 review하며, 생성 artifact에는 source commit과 policy version을 남긴다.</li>
<li>API server process가 읽는 경로는 일반 workload mount와 분리하고, runtime write 권한을 최소화한다.</li>
<li>배포 주체와 break-glass 수정자는 최소 인원으로 제한하며, host-level 변경도 audit log에 남긴다.</li>
<li>변경 artifact에 schema lint, policy fixture test, diff 기반 blast-radius 요약을 붙인다.</li>
<li>마지막 유효 artifact와 그것을 되돌리는 절차를 control plane 접근 장애 상황에서도 실행 가능하게 문서화한다.</li>
</ul>
<p>이 방식은 <a href="/learning/deep-dive/deep-dive-config-change-safety-rollout-playbook/">Config Change Safety 플레이북</a>의 config registry 개념을 control-plane policy에 적용한 것이다. Kubernetes API 호출이 성공했는지보다 어떤 version이 어느 API server에서 effective인지, reload failure가 없는지, 누가 변경했는지가 더 중요하다.</p>
<h2 id="실무-적용">실무 적용</h2>
<h3 id="1-4단계-도입으로-trust-chain을-먼저-검증한다">1) 4단계 도입으로 trust chain을 먼저 검증한다</h3>
<p><strong>1단계: policy inventory</strong><br>
현재 validating webhook, CEL policy, 관련 RBAC를 모아 API policy 변경을 보호하는 rule과 일반 workload rule을 분리한다. source owner와 만료일이 없는 emergency exception도 같이 찾는다.</p>
<p><strong>2단계: offline fixture와 artifact pipeline</strong><br>
정상 control-plane component, 운영 agent, 승인된 workload, 막혀야 하는 privileged Pod, policy resource를 수정하려는 요청을 fixture로 만든다. CI는 syntax 성공만이 아니라 expected allow/deny와 policy diff의 selector 범위 변화를 검증해야 한다.</p>
<p><strong>3단계: non-production canary</strong><br>
개발 또는 staging cluster 한 곳에 먼저 적용한다. 최소 24시간 동안 API server reload error, admission deny count, deployment failure, bootstrap/restart 성공 여부를 기준선과 비교한다. control plane restart와 invalid manifest 배포를 실제로 재현해 이전 유효 구성이 유지되는지도 확인한다.</p>
<p><strong>4단계: production slice와 rollback rehearsal</strong><br>
전체 fleet에 일괄 적용하지 않고 단일 cluster 또는 영향이 제한된 environment에서 시작한다. abort 조건을 미리 적는다. 예를 들어 예상하지 않은 deny가 5분에 10건 이상이거나, platform namespace deployment가 실패하거나, API server reload error가 1회라도 발생하면 이전 artifact로 되돌리고 원인을 분류한다.</p>
<h3 id="2-관측은-deny-숫자-하나로-끝나지-않는다">2) 관측은 deny 숫자 하나로 끝나지 않는다</h3>
<p>성공 기준을 denied requests 0으로 잡으면 보호 정책은 아무 일도 하지 않는 것처럼 보인다. 반대로 deny가 늘었다고 항상 나쁜 것도 아니다. 차단해야 할 privileged Pod를 막았다면 정상이다. policy version과 reason을 붙여 분리해야 한다.</p>
<p>최소 대시보드에는 다음을 둔다.</p>
<ul>
<li>admission decisions: policy ID, source, decision, reason별 건수</li>
<li>manifest policy effective version: API server별 version과 reload success/failure timestamp</li>
<li>deployment failure 및 API request latency를 policy version 전후로 비교한 지표</li>
<li>allowed fixture·denied fixture의 정기 synthetic 결과</li>
<li>host artifact 변경자, source commit, break-glass 사용 여부</li>
</ul>
<p>이 지표들은 policy가 켜져 있다는 상태와 실제로 예측 가능한 방식으로 동작한다는 증거를 나눈다. <a href="/posts/2026-08-31-artifact-attestation-deployment-admission-gate-trend/">Artifact Attestation과 Deployment Admission Gate</a>가 artifact의 출처를 확인하는 문제라면, 여기서는 그 확인 규칙이 부팅부터 유지되는지를 확인하는 문제다.</p>
<h3 id="3-의사결정-기준숫자조건우선순위">3) 의사결정 기준(숫자·조건·우선순위)</h3>
<p>권장 우선순위는 <strong>bootstrap 정책의 무결성 &gt; control plane 가용성 &gt; 일반 배포의 속도 &gt; 운영 편의</strong>다. 이 순서가 없으면 emergency 편집 편의 때문에 high-trust 경로의 쓰기 권한이 넓어진다.</p>
<p>실행 기준 예시는 다음과 같다.</p>
<ul>
<li>최근 30일 동안 변경이 0~2회이고, 무력화되면 cluster 전체에 영향을 주는 policy만 첫 manifest 후보로 둔다.</li>
<li>각 policy는 최소 10개의 allow fixture와 10개의 deny fixture를 유지하며, 정책 변경 PR에서 모두 통과해야 한다.</li>
<li>production 승격 전 canary는 24시간 이상, control-plane restart 1회 이상, invalid artifact recovery 1회 이상을 포함한다.</li>
<li>reload error, control-plane component의 예상 밖 deny, 새 policy version에서 deployment failure 증가가 있으면 자동 승격하지 않는다.</li>
<li>break-glass는 만료 시각과 사후 review ticket을 필수로 하고, permanent manifest 편집으로 우회하지 않는다.</li>
</ul>
<p>숫자는 시작점일 뿐이다. 더 중요한 것은 어떤 policy가 API 밖의 source를 필요로 하는가와 rollback에 API가 정상이어야만 하는가를 각 cluster topology에서 답하는 일이다. managed Kubernetes처럼 control-plane filesystem에 접근할 수 없는 환경이라면, 기능 자체를 쓸 수 있다는 설명과 실제 운영 가능성은 다르다. 이 경우 기존 API policy, provider guardrail, GitOps admission 경로 중 어디가 bootstrap 보호를 제공하는지 다시 평가해야 한다.</p>
<h2 id="트레이드오프주의점">트레이드오프/주의점</h2>
<ol>
<li>
<p><strong>policy source를 API 밖으로 옮겼다고 자동으로 더 안전해지지 않는다.</strong> Host 접근, image supply chain, configuration agent가 약하면 API RBAC보다 넓은 우회 경로가 생긴다.</p>
</li>
<li>
<p><strong>valid-only reload는 semantic safety를 보장하지 않는다.</strong> 문법이 맞는 broad deny는 더 위험할 수 있다. negative/positive fixture와 canary가 필요하다.</p>
</li>
<li>
<p><strong>manifest와 API policy의 중복은 drift를 만든다.</strong> 한 policy ID에는 권위 있는 source 하나, migration 기간에는 명확한 precedence와 종료일이 있어야 한다.</p>
</li>
<li>
<p><strong>Beta라는 상태를 무시하면 안 된다.</strong> Version compatibility, feature 활성화 방식, managed provider의 지원 범위를 upgrade plan에서 별도로 확인해야 한다. 새 security control을 단독 방어선으로 승격하기 전에는 기존 policy와 recovery 절차를 유지한다.</p>
</li>
</ol>
<h2 id="체크리스트-또는-연습">체크리스트 또는 연습</h2>
<ul>
<li><input disabled="" type="checkbox"> 현재 cluster에서 admission resource를 수정할 수 있는 principal과 API server host artifact를 수정할 수 있는 principal을 각각 목록화했다.</li>
<li><input disabled="" type="checkbox"> manifest 후보 policy마다 owner, scope, authoritative source, source commit, effective version, rollback target을 기록했다.</li>
<li><input disabled="" type="checkbox"> allow/deny fixture가 privileged workload뿐 아니라 control-plane·monitoring·bootstrap component를 포함한다.</li>
<li><input disabled="" type="checkbox"> invalid manifest, API server restart, 이전 artifact rollback을 non-production에서 실제 실행해 결과를 남겼다.</li>
<li><input disabled="" type="checkbox"> policy version별 deny reason, reload error, deployment failure, API server health를 한 대시보드에서 비교한다.</li>
<li><input disabled="" type="checkbox"> API policy와 manifest policy가 같은 rule을 중복 적용하는 migration에 종료일과 precedence가 있다.</li>
</ul>
<p>연습으로 현재 운영 중인 admission rule 하나를 고른다. 그 rule을 변경할 수 있는 API principal, Git reviewer, CI deployer, control-plane host 수정자를 모두 적어 보자. 그중 한 경로만 탈취되어도 rule이 약화되는지 확인하면, manifest 기반 admission control이 필요한지와 어떤 보호를 먼저 강화해야 하는지가 훨씬 명확해진다.</p>
]]></content:encoded></item></channel></rss>