<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>모래성 말고 철옹성</title>
    <link>https://jdhyeok.tistory.com/</link>
    <description>배운 기술들을 잊지 않기 위한 기술 블로그 :) 

email : jdhyeok97@gmail.com</description>
    <language>ko</language>
    <pubDate>Tue, 15 Sep 2026 11:26:08 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>JDhyeok</managingEditor>
    <image>
      <title>모래성 말고 철옹성</title>
      <url>https://tistory1.daumcdn.net/tistory/5262758/attach/4f4b64aacd714ad493dc88c2815b1788</url>
      <link>https://jdhyeok.tistory.com</link>
    </image>
    <item>
      <title>[AWS] EKS에서 Control Plane과 Data Plane의 통신</title>
      <link>https://jdhyeok.tistory.com/36</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;247&quot; data-origin-height=&quot;148&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IGYAt/dJMcafFoT7y/B89T5Jr4Fx9RVwF0kQF0u1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IGYAt/dJMcafFoT7y/B89T5Jr4Fx9RVwF0kQF0u1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IGYAt/dJMcafFoT7y/B89T5Jr4Fx9RVwF0kQF0u1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIGYAt%2FdJMcafFoT7y%2FB89T5Jr4Fx9RVwF0kQF0u1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;247&quot; height=&quot;148&quot; data-origin-width=&quot;247&quot; data-origin-height=&quot;148&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Amazon EKS를 사용하다 보면 재미있는 사실을 발견하게 된다. 클러스터를 생성할 때 우리는 VPC와 서브넷을 지정하고 생성하면 &lt;b&gt;EC2 목록에 Data Plane 노드가 생기는 Master인 Control Plane 노드는 생기지 않는다.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;궁금하여 찾아보니 EKS에서 &lt;b&gt;Control Plane 노드는 AWS가 관리하는 별도의 VPC에 존재&lt;/b&gt;하고 있기 떄문이다. 그렇다면 우리 VPC에 떠 있는 Data Plane노드들과 이들은 어떻게 통신하고, 문제가 생겼을 때 보이지도 않는 Control Plane을 어떻게 디버깅해야 할까?&lt;/p&gt;
&lt;h1&gt;Cross-Account ENI(X-ENI) - Control Plane과 Data Plane의 통신&lt;/h1&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;subnet_image.png&quot; data-origin-width=&quot;6312&quot; data-origin-height=&quot;2884&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RnfAb/dJMb996fDqf/l2rSkG6wkaFnF4jkw7QVeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RnfAb/dJMb996fDqf/l2rSkG6wkaFnF4jkw7QVeK/img.png&quot; data-alt=&quot;[출처] AWS&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RnfAb/dJMb996fDqf/l2rSkG6wkaFnF4jkw7QVeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRnfAb%2FdJMb996fDqf%2Fl2rSkG6wkaFnF4jkw7QVeK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;6312&quot; height=&quot;2884&quot; data-filename=&quot;subnet_image.png&quot; data-origin-width=&quot;6312&quot; data-origin-height=&quot;2884&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;[출처] AWS&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;EKS Control Plane과 사용자의 VPC 사이에는 Cross-Account ENI라는 다리&lt;/b&gt;가 놓여 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클러스터를 처음 생성할 때 서브넷을 지정하면, AWS는 해당 서브넷 안에 &lt;b&gt;EKS 관리형 ENI(Elastic Network Interface)&lt;/b&gt;를 자동으로 생성한다. 이 ENI는 사용자 VPC 안에 있지만, 실제로는 AWS 관리 VPC에 있는 Control Plane과 연결되어 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EKS는 API 서버 엔드포인트에 대해 세 가지 접근 방식을 제공된다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 80px;&quot; border=&quot;1&quot; data-path-to-node=&quot;12&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;&lt;b&gt;모드&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;&lt;b&gt;설명&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;&lt;b&gt;통신 경로&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;&lt;span data-path-to-node=&quot;12,1,0,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;12,1,0,0&quot;&gt;Public Only&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;&lt;span data-path-to-node=&quot;12,1,1,0&quot;&gt;기본값. 외부에서도 API 접근 가능&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;&lt;span data-path-to-node=&quot;12,1,2,0&quot;&gt;노드 -&amp;gt; NAT Gateway/IGW -&amp;gt; Public 엔드포인트&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;&lt;span data-path-to-node=&quot;12,2,0,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;12,2,0,0&quot;&gt;Public &amp;amp; Private&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;&lt;span data-path-to-node=&quot;12,2,1,0&quot;&gt;내부 통신은 VPC 안에서, 외부는 인터넷으로&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;&lt;span data-path-to-node=&quot;12,2,2,0&quot;&gt;노드 -&amp;gt; &lt;b data-index-in-node=&quot;6&quot; data-path-to-node=&quot;12,2,2,0&quot;&gt;X-ENI (VPC 내부)&lt;/b&gt; -&amp;gt; Control Plane&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;&lt;span data-path-to-node=&quot;12,3,0,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;12,3,0,0&quot;&gt;Private Only&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;&lt;span data-path-to-node=&quot;12,3,1,0&quot;&gt;인터넷 접근 차단. 폐쇄망 구성&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;&lt;span data-path-to-node=&quot;12,3,2,0&quot;&gt;노드 -&amp;gt; &lt;b data-index-in-node=&quot;6&quot; data-path-to-node=&quot;12,3,2,0&quot;&gt;X-ENI (VPC 내부)&lt;/b&gt; -&amp;gt; Control Plane&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자의 경우 Private Only의 모드로 Bastion 서버 생성하여 kubectl 명령어를 사용하게 구성했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;span&gt;Control Plane, 어떻게 로그를 볼 수 있을지?&lt;/span&gt;&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EKS는 Managed kubernetes 서비스 이지만 로그를 보고 싶을 수도 있을것이다. 로그나 디버깅을 하고싶다면 어떻게 해야할까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자는 &lt;b&gt;Control Plane 노드에 직접 SSH 접속을 할 수 없지만 이를 모니터링할 수 있는 도구&lt;/b&gt;들을 제공을 해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. CloudWatch Logs&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EKS 설정에서 로그 기능을 활성화하면 CloudWatch로 다음 로그를 전송하여 확인할 수 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;19&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;19,0,0&quot;&gt;API Server Logs:&lt;/b&gt; API 호출 기록 및 에러 확인&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;19,1,0&quot;&gt;Audit Logs:&lt;/b&gt; 누가, 언제, 어떤 명령을 내렸는지 기록 (보안 진단)&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;19,2,0&quot;&gt;Authenticator Logs:&lt;/b&gt; IAM 권한 관련 인증 실패 확인&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;19,3,0&quot;&gt;Controller Manager / Scheduler Logs:&lt;/b&gt; 파드 스케줄링이나 복제본 관리에 문제가 생겼을 때 확인&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2.&lt;span&gt; VPC Flow&lt;/span&gt;&amp;nbsp;Logs&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자 VPC 내에 생성된 &lt;b data-index-in-node=&quot;67&quot; data-path-to-node=&quot;21&quot;&gt;EKS 관리형 ENI&lt;/b&gt;의 Flow Logs를 확인하면, Control Plane과 워커 노드 사이에 패킷이 거부되거나 오류에 대해서 디버깅 할 수 있다.&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;3.&lt;span&gt;&lt;span&gt; Control Plane Metrics&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CloudWatch Metrics 또는 Prometheus를 통해 API 서버의 응답 속도(apiserver_request_duration_seconds)나 etcd의 상태를 모니터링할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;h1 style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;span&gt;참조&lt;/span&gt;&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.aws.amazon.com/ko_kr/eks/latest/best-practices/subnets.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://docs.aws.amazon.com/ko_kr/eks/latest/best-practices/subnets.html&lt;/a&gt;&lt;/p&gt;</description>
      <category>DevOps/Infra</category>
      <category>AWS</category>
      <category>it</category>
      <category>k8s</category>
      <category>SRE</category>
      <category>개발</category>
      <category>인프라</category>
      <category>쿠버네티스</category>
      <category>클라우드</category>
      <author>JDhyeok</author>
      <guid isPermaLink="true">https://jdhyeok.tistory.com/36</guid>
      <comments>https://jdhyeok.tistory.com/36#entry36comment</comments>
      <pubDate>Sat, 24 Jan 2026 13:32:16 +0900</pubDate>
    </item>
    <item>
      <title>[AWS] AWS의 Elastic Load Balancer(ELB) 톺아보기</title>
      <link>https://jdhyeok.tistory.com/35</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;247&quot; data-origin-height=&quot;148&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XAjcg/dJMcaf6npdm/KkJeGAbhkyuXIEflYysiTk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XAjcg/dJMcaf6npdm/KkJeGAbhkyuXIEflYysiTk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XAjcg/dJMcaf6npdm/KkJeGAbhkyuXIEflYysiTk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXAjcg%2FdJMcaf6npdm%2FKkJeGAbhkyuXIEflYysiTk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;247&quot; height=&quot;148&quot; data-origin-width=&quot;247&quot; data-origin-height=&quot;148&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h1&gt;AWS Elastic Load Balancer(ELB) 란?&lt;/h1&gt;
&lt;p&gt;ELB는 하나 이상의 AZ(가용 영역)에서 EC2 인스턴스, 컨테이너, IP 주소와 같은 여러 대상에 걸쳐 들어오는 애플리케이션 트래픽을 자동으로 분산해주는 &amp;quot;완전 관리형 로드 밸런싱 서비스&amp;quot;이다.&lt;/p&gt;
&lt;h1&gt;ELB를 왜 사용할까?&lt;/h1&gt;
&lt;p&gt;ELB를 사용하게 되면 단순히 트래픽을 전달하고 나누는 기능만이 아닌 아래와 같은 요소들을 만족시킬 수 있다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;고가용성(HA): 특정 서버가 고장 나도 정상적인 다른 서버로 트래픽을 보내 가용성을 보장&lt;/li&gt;
&lt;li&gt;Health Check: 서버가 살아있는지 주기적으로 체크하여 상태 보장&lt;/li&gt;
&lt;li&gt;Auto Scaling: 트래픽이 급증하는 상황에서 서버 Scale in/out에 대응하여 트래픽에 유연하게 대처&lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;AWS ELB의 종류&lt;/h1&gt;
&lt;p&gt;AWS ELB 종류에는 ALB, NLB, GWLB와 Classic Load Balancer가 있지만, 마지막 Classic Load Balancer는 구버전이기 때문에 세 가지 Load Balancer만 설명한다.&lt;/p&gt;
&lt;h3&gt;1.Application Load Balancer (ALB)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;OSI 계층: L7&lt;/li&gt;
&lt;li&gt;동작 방식: 패킷의 내용을 열어 HTTP 헤더, 메소드, URL 경로, 쿠키 등을 확인하고 라우팅 결정을 내린다.&lt;/li&gt;
&lt;li&gt;핵심 기능:&lt;ul&gt;
&lt;li&gt;경로 기반 라우팅: 요청의 URL을 기반으로 요청을 전달하는 리스너에 대한 규칙 구성, 이를 통해 애플리케이션을 규모가 더욱 작은 서비스로 구성하고, URL 콘텐츠를 기반으로 요청을 올바른 서비스로 라우팅할 수 있다.&lt;/li&gt;
&lt;li&gt;호스팅 기반 라우팅: HTTP 헤더의 호스트 필드 기반으로 요청을 전달하는 리스너에 대한 규칙 구성, 이에 따라 단일 ALB를 사용해 여러 개의 도메인 요청을 라우팅 할 수 있다.&lt;/li&gt;
&lt;li&gt;HTTP헤더 기반 라우팅: HTTP 헤더 메서드, 쿼리 param, IP 주소 등 요청의 필드를 기반으로 하는 라우팅을 할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;특이사항: 가변 IP 주소를 가지며, 접근 시 도메인 이름을 사용하는 것이 원칙&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. Network Load Balancer (NLB)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;OSI 계층: L4&lt;/li&gt;
&lt;li&gt;동작 방식: TCP, UDP, TLS 프로토콜의 헤더 정보(IP 및 포트)만을 참조하여 트래픽을 전달한다. 패킷의 페이로드를 분석하지 않으므로 처리 속도가 매우 빠르다.&lt;/li&gt;
&lt;li&gt;핵심 기능:&lt;ul&gt;
&lt;li&gt;초저지연(Ultra-low Latency): 밀리초(ms) 단위의 지연 시간을 보장하며, 초당 수백만 건의 요청을 처리하는 고성능 환경에 적합하다.&lt;/li&gt;
&lt;li&gt;고정 IP 할당: 로드밸런서의 가용 영역별로 고정 EIP(Elastic IP)를 할당할 수 있어, 클라이언트 측의 방화벽 화이트리스트 관리가 용이하다.&lt;/li&gt;
&lt;li&gt;Source IP 보존: 클라이언트의 IP 주소를 수정하지 않고 타겟 서버까지 그대로 전달한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;특이사항: 트래픽이 급증할 때 3-way handshake과정이 없어 ALB와 달리 Warming 없이 빠르게 Scale out이 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3. Gateway Load Balancer (GWLB)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;OSI 계층: L3&lt;/li&gt;
&lt;li&gt;동작 방식: 3rd Party 가상 보안 어플라이언스(방화벽, IDS/IPS)를 투명하게 배포하고 확장할 수 있도록 설계되었다.&lt;/li&gt;
&lt;li&gt;핵심 기능:&lt;ul&gt;
&lt;li&gt;GENEVE 프로토콜 (Port 6081): GWLB와 보안 어플라이언스 간에 GENEVE 엔캡슐레이션을 사용하여 원본 패킷의 데이터(L3 이상)를 손실 없이 전달한다.&lt;/li&gt;
&lt;li&gt;VPC 엔드포인트 통합: GWLB 엔드포인트를 통해 서비스 소비자 VPC와 공급자 VPC 간에 프라이빗하고 안전한 트래픽 교환을 지원한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;특이사항: 모든 포트에서 모든 IP 패킷을 수신하며, 주로 중앙 집중형 보안 검사 아키텍처에 사용된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;AWS ELB 정리 표&lt;/h1&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;left&quot;&gt;항목&lt;/th&gt;
&lt;th align=&quot;left&quot;&gt;ALB (Application)&lt;/th&gt;
&lt;th align=&quot;left&quot;&gt;NLB (Network)&lt;/th&gt;
&lt;th align=&quot;left&quot;&gt;GWLB (Gateway)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;작동 계층&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Layer 7&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Layer 4&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Layer 3&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;라우팅 기준&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;URL, Header, Cookie&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;IP, Port, Hash, CID&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;IP 패킷 (Raw)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;성능/확장&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;지연시간↑ (L7 분석)&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;초저지연 / 즉각 확장&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;어플라이언스 종속&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;IP 특징&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;가변 IP (DNS 권장)&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;고정 IP (EIP 지원)&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;엔드포인트 기반&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;주요 프로토콜&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;HTTP, gRPC, WSS&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;TCP, UDP, &lt;strong&gt;QUIC&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;GENEVE (6081)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;핵심 용도&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;웹 앱, MSA, 컨테이너&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;고성능, 실시간 데이터&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;보안/방화벽 장비&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;</description>
      <category>DevOps/Infra</category>
      <category>AWS</category>
      <category>ELB</category>
      <category>Network</category>
      <category>tech</category>
      <author>JDhyeok</author>
      <guid isPermaLink="true">https://jdhyeok.tistory.com/35</guid>
      <comments>https://jdhyeok.tistory.com/35#entry35comment</comments>
      <pubDate>Sat, 10 Jan 2026 14:41:56 +0900</pubDate>
    </item>
    <item>
      <title>[SRE] Policy-as-Code란 무엇인가?</title>
      <link>https://jdhyeok.tistory.com/34</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;300&quot; data-origin-height=&quot;168&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nrjD4/btsQ0wVJaK3/3EqZEzx02YtiWfkStHt7i0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nrjD4/btsQ0wVJaK3/3EqZEzx02YtiWfkStHt7i0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nrjD4/btsQ0wVJaK3/3EqZEzx02YtiWfkStHt7i0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnrjD4%2FbtsQ0wVJaK3%2F3EqZEzx02YtiWfkStHt7i0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;300&quot; height=&quot;168&quot; data-origin-width=&quot;300&quot; data-origin-height=&quot;168&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;i&gt;최근 한국 뿐만 아니라 전세계적으로 보안 사건, 사고들이 많아지면서 서비스를 운영하는데 고민이 많아지는 것 같다. 산더미 처럼 쌓여가는 레거시 시스템들을 보안패치 하는 것은 기업들에게 큰 고민거리일 듯 하다.&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;i&gt;이런 것들을 어떻게 자동화할 수 있을까? 하며 찾아보다 새로운 개념을 접하게 되어 정리해봤다.&lt;/i&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Policy-as-Code 란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Policy-as-code는 정책 관리 방식 중 하나로, &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;정책을 코드로 정의하고, 업데이트하며, 공유하고, 강제할 수 있게 하는 접근법&lt;/b&gt;&lt;/span&gt;이다. &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;수동 프로세스에 의존해 정책을 관리하는 대신 코드 기반 자동화&lt;/b&gt;&lt;/span&gt;를 활용함으로써, 팀은 더 빠르게 움직일 수 있고 사람의 실수로 인한 오류 가능성을 줄일 수 있다.&lt;/p&gt;
&lt;p data-end=&quot;357&quot; data-start=&quot;256&quot; data-ke-size=&quot;size18&quot;&gt;또한 보안과 같은 영역에서 Policy-as-code 접근법을 사용하면 개발자와 보안 엔지니어 같은 다양한 이해관계자가 이해할 수 있는 방식으로 정책을 정의하고 관리할 수 있다.&lt;/p&gt;
&lt;p data-end=&quot;357&quot; data-start=&quot;256&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;357&quot; data-start=&quot;256&quot; data-ke-size=&quot;size18&quot;&gt;Policy-as-code가 어떻게 작동하는지, 왜 중요한지, 그리고 보안 맥락에서 이를 어떻게 활용할 수 있는지 알아보자&lt;/p&gt;
&lt;p data-end=&quot;357&quot; data-start=&quot;256&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-end=&quot;357&quot; data-start=&quot;256&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Policy-as-Code 정의&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Policy-as-code를 이해하기 위해서는 먼저 &quot;정책(Policy)&quot;의 정의를 알아야 한다.&lt;/p&gt;
&lt;p data-end=&quot;658&quot; data-start=&quot;527&quot; data-ke-size=&quot;size18&quot;&gt;여기서 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;정책이란 IT 운영이나 프로세스를 지배하는 규칙, 조건, 지침을 의미&lt;/b&gt;&lt;/span&gt;한다. 예를 들어, 정책은 보안 검증을 통과해야 코드가 배포될 수 있다는 조건일 수도 있고, 보안 이벤트가 발생했을 때 자동으로 실행되는 절차일 수도 있다.&lt;/p&gt;
&lt;p data-end=&quot;658&quot; data-start=&quot;527&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;835&quot; data-start=&quot;660&quot; data-ke-size=&quot;size18&quot;&gt;Policy-as-code란 이러한 규칙과 조건을 코드로 정의하고 관리하는 것이다. Policy-as-code 접근 방식에서는 팀이 Python, YAML, Rego 같은 프로그래밍 언어로 정책을 작성한다. 사용하는 언어는 보통 어떤 Policy-as-code 관리 및 강제 도구를 사용하는지에 따라 달라진다.&lt;/p&gt;
&lt;p data-end=&quot;835&quot; data-start=&quot;660&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1037&quot; data-start=&quot;837&quot; data-ke-size=&quot;size18&quot;&gt;엔지니어가 업데이트해야 할 때는 기존 코드를 수정하면 된다. 또한 정책 코드를 버전 관리 시스템(VCS)을 통해 공유하여 다른 사람이 정책을 확인할 수 있도록 할 수 있다. 마지막으로, Policy-as-code 실행 엔진을 활용해 정책이 준수되도록 강제할 수 있다. 이 실행 엔진은 독립적인 형태일 수도 있고, 더 큰 플랫폼에 내장되어 있을 수도 있다.&lt;/p&gt;
&lt;h2 data-end=&quot;1037&quot; data-start=&quot;837&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-end=&quot;1037&quot; data-start=&quot;837&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Policy-as-Code vs. Infrastructure as Code&lt;/b&gt;&lt;/h2&gt;
&lt;p data-end=&quot;1037&quot; data-start=&quot;837&quot; data-ke-size=&quot;size18&quot;&gt;Policy-as-code 개념은 Infrastructure as Code(IaC)와 비슷하게 들릴 수 있다. IaC는 코드 기반 파일을 사용해 인프라를 자동으로 설정하고 프로비저닝하는 방법으로, IT 운영팀이 수년간 활용해온 일반적인 방식이다.&lt;/p&gt;
&lt;p data-end=&quot;1318&quot; data-start=&quot;1230&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;IaC가 인프라 프로비저닝에 유용하다면, Policy-as-code는 보안 운영, 컴플라이언스 관리, 데이터 관리 등 더 광범위한 영역을 개선&lt;/b&gt;&lt;/span&gt;할 수 있다.&lt;/p&gt;
&lt;p data-end=&quot;1318&quot; data-start=&quot;1230&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-end=&quot;1318&quot; data-start=&quot;1230&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Policy-as-Code의 이점&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;수동으로 규칙, 조건, 절차를 관리하는 방식과 비교했을 때, Policy-as-code는 다음과 같은 중요한 장점을 제공한다:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2126&quot; data-start=&quot;1421&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1576&quot; data-start=&quot;1421&quot;&gt;&lt;b&gt;효율성&lt;/b&gt;: 정책을 코드로 정의하면 사실상 무제한 규모에서 자동으로 공유 및 강제할 수 있다. 이는 엔지니어가 매번 수동으로 정책을 적용하는 것보다 훨씬 효율적이다. 또한 사람이 해석하기 애매할 수 있는 자연어보다 코드로 정의된 정책이 업데이트와 공유에 더 용이하다.&lt;/li&gt;
&lt;li data-end=&quot;1626&quot; data-start=&quot;1577&quot;&gt;&lt;b&gt;속도&lt;/b&gt;: 정책 강제를 자동화하면 수동 방식보다 훨씬 빠르게 운영할 수 있다.&lt;/li&gt;
&lt;li data-end=&quot;1769&quot; data-start=&quot;1627&quot;&gt;&lt;b&gt;가시성&lt;/b&gt;: 정책이 코드로 정의되어 있으면 모든 이해관계자가 시스템 내에서 무슨 일이 일어나고 있는지 쉽게 확인할 수 있다. 예를 들어, 알림이나 대응 규칙을 다른 엔지니어에게 물어보지 않고 코드 기반 정책을 직접 살펴봄으로써 이해할 수 있다.&lt;/li&gt;
&lt;li data-end=&quot;1893&quot; data-start=&quot;1770&quot;&gt;&lt;b&gt;협업&lt;/b&gt;: 정책을 관리하는 체계적이고 일관된 수단을 제공하기 때문에 협업이 단순해진다. 이는 같은 팀 내 협업뿐만 아니라 개발자(코드 중심 사고에 익숙한 사람)와 보안&amp;middot;운영 전문가 간 협업에도 특히 효과적이다.&lt;/li&gt;
&lt;li data-end=&quot;1965&quot; data-start=&quot;1894&quot;&gt;&lt;b&gt;정확성&lt;/b&gt;: 정책을 코드로 정의하고 관리하면 시스템을 수동으로 관리할 때 발생할 수 있는 구성 오류를 피할 수 있다.&lt;/li&gt;
&lt;li data-end=&quot;2027&quot; data-start=&quot;1966&quot;&gt;&lt;b&gt;버전 관리&lt;/b&gt;: 정책 파일의 버전을 추적하면 문제가 생겼을 때 이전 버전으로 쉽게 되돌릴 수 있다.&lt;/li&gt;
&lt;li data-end=&quot;2126&quot; data-start=&quot;2028&quot;&gt;&lt;b&gt;테스트 및 검증&lt;/b&gt;: 정책이 코드로 작성되면 자동화된 감사 도구를 통해 손쉽게 검증할 수 있다. 이를 통해 운영 환경에 치명적인 오류가 도입될 위험을 줄일 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Policy-as-Code 활용 방법&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;오늘날 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Policy-as-code를 활용하는 가장 쉬운 방법은 해당 접근법을 네이티브로 지원하는 도구를 도입&lt;/b&gt;&lt;/span&gt;하는 것이다.&lt;/p&gt;
&lt;p data-end=&quot;2408&quot; data-start=&quot;2228&quot; data-ke-size=&quot;size18&quot;&gt;예를 들어 보안 영역에서는 &lt;b&gt;Prisma Cloud, Bridgecrew, Checkov&lt;/b&gt; 같은 도구를 사용해 보안 정책을 코드로 정의할 수 있다. 또한 배포 전 정책 파일을 자동으로 스캔 및 감사하여 잘못된 설정이나 취약점을 탐지할 수 있다. 이는 클라우드 보안 태세 관리(CSPM)를 단순화하는 방식 중 하나다.&lt;/p&gt;
&lt;p data-end=&quot;2652&quot; data-start=&quot;2410&quot; data-ke-size=&quot;size18&quot;&gt;또한 &lt;b&gt;Open Policy Agent(OPA)&lt;/b&gt; 같은 도구를 활용해 어떤 도메인에서든 Policy-as-code를 적용할 수 있는 공통 프레임워크를 제공받을 수도 있다. 그러나 현재까지는 커뮤니티 기반 Policy-as-code 프레임워크의 벤더 채택률은 낮은 편이다. 따라서 보안이나 다른 IT 영역에서 Policy-as-code를 도입하려면 네이티브 지원 기능을 제공하는 벤더 도구를 사용하는 것이 가장 단순한 방법이다.&lt;/p&gt;
&lt;p data-end=&quot;2652&quot; data-start=&quot;2410&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2652&quot; data-start=&quot;2410&quot; data-ke-size=&quot;size18&quot;&gt;&lt;i&gt;보안은 늘 뒤처지기 쉬운 영역이라고 생각하는데, &lt;b&gt;Policy-as-Code는 이를 예방적으로 관리할 수 있는 중요한 도구&lt;/b&gt;다. 현대에 와서 IaC가 인프라 관리의 기본이 된 것처럼, Policy-as-Code도 앞으로는 보안 및 컴플라이언스 관리의 표준으로 자리잡을 수 있지 않을까? 싶다. 앞으로 지켜볼 필요가 있을 것 같다.&lt;/i&gt;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;원문&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://www.paloaltonetworks.com/cyberpedia/what-is-policy-as-code&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.paloaltonetworks.com/cyberpedia/what-is-policy-as-code&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1759421856458&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;What Is Policy-as-Code?&quot; data-og-description=&quot;Automate security with Policy as Code. Learn how coding policies enhance compliance, enforce access controls, and improve cloud security at scale.&quot; data-og-host=&quot;www.paloaltonetworks.com&quot; data-og-source-url=&quot;https://www.paloaltonetworks.com/cyberpedia/what-is-policy-as-code&quot; data-og-url=&quot;https://www.paloaltonetworks.com/cyberpedia/what-is-policy-as-code&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/uyPuC/hyZKq481ni/Ht5frMaK267I1ARL3CykKk/img.jpg?width=744&amp;amp;height=400&amp;amp;face=0_0_744_400,https://scrap.kakaocdn.net/dn/xg6tg/hyZKnABMHs/AaoaZ85chyRIMTkyoDhqpk/img.jpg?width=744&amp;amp;height=400&amp;amp;face=0_0_744_400&quot;&gt;&lt;a href=&quot;https://www.paloaltonetworks.com/cyberpedia/what-is-policy-as-code&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.paloaltonetworks.com/cyberpedia/what-is-policy-as-code&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/uyPuC/hyZKq481ni/Ht5frMaK267I1ARL3CykKk/img.jpg?width=744&amp;amp;height=400&amp;amp;face=0_0_744_400,https://scrap.kakaocdn.net/dn/xg6tg/hyZKnABMHs/AaoaZ85chyRIMTkyoDhqpk/img.jpg?width=744&amp;amp;height=400&amp;amp;face=0_0_744_400');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;What Is Policy-as-Code?&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Automate security with Policy as Code. Learn how coding policies enhance compliance, enforce access controls, and improve cloud security at scale.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.paloaltonetworks.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>DevOps/SRE</category>
      <category>devsecops</category>
      <category>it</category>
      <category>Security</category>
      <category>SRE</category>
      <category>보안</category>
      <author>JDhyeok</author>
      <guid isPermaLink="true">https://jdhyeok.tistory.com/34</guid>
      <comments>https://jdhyeok.tistory.com/34#entry34comment</comments>
      <pubDate>Fri, 3 Oct 2025 01:21:03 +0900</pubDate>
    </item>
    <item>
      <title>[SRE] Error Budget이란? - 서비스 안정성과 개발 속도의 균형점</title>
      <link>https://jdhyeok.tistory.com/33</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;290&quot; data-origin-height=&quot;174&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MEHpn/btsQFEkRLSx/nN1u1Q00wTA34uHOmC5YIk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MEHpn/btsQFEkRLSx/nN1u1Q00wTA34uHOmC5YIk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MEHpn/btsQFEkRLSx/nN1u1Q00wTA34uHOmC5YIk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMEHpn%2FbtsQFEkRLSx%2FnN1u1Q00wTA34uHOmC5YIk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;290&quot; height=&quot;174&quot; data-origin-width=&quot;290&quot; data-origin-height=&quot;174&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 style=&quot;text-align: center;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&quot;우리 시스템이 얼마나 에러가 나도 되나? 의 지표 Error Budget&quot;&lt;/b&gt;&lt;/h4&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Error Budget 이란?&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Error Budget(오류 예산)은 Google에서 개발한 SRE 방법론의 핵심개념이다. &lt;b&gt;서비스의 안정성과 새로운 기능 개발 속도간의 균형을 정량적으로 관리하는 개념&lt;/b&gt;으로 보면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;IT업계에 있는 분들이라면 다 아시겠지만 &lt;b&gt;100% 완벽한 소프트웨어는 불가능&lt;/b&gt;하다. 기술의 혁신을 가져가자니 시스템의 안정성이 떨어지고 안정성만 따지자니 기술 부채는 늘어간다. 이런 딜레마를 해결하는 방법 중에 하나가 Error Budget인 것 같다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Error Budget 계산&lt;/b&gt;&lt;/span&gt;&lt;b&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Error Budget은 보통 아래 식과 같이 계산된다.&lt;/p&gt;
&lt;pre id=&quot;code_1758199941771&quot; class=&quot;subunit&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Error budget = [100% - availability target] &lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;조직에&amp;nbsp;&lt;a href=&quot;https://jdhyeok.tistory.com/23&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;서비스 수준 목표&lt;/a&gt;를 측정할 수 있다면 SLI, SLO로 더 정교하게 Budget을 계산해볼 수도 있을 것 같다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;예시:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SLO: 99.9% 가용성&lt;/li&gt;
&lt;li&gt;월간 1억 건 요청 처리&lt;/li&gt;
&lt;li&gt;Error Budget: 0.1% X 100,000,000 = 100,000개 요청 오류 허용&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이렇게 계산하면 일일 허용 오류는 33,333건 요청이 된다. 이 안에서 조직은 자유롭게 시스템 개선이나 실험을 진행해볼 수 있고, 범위를 초과하면 안정성에 집중하면 될 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Error Budget 활용 전략&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;현 회사에서 이런 저런 이슈로 시스템에 사소한 작업을 할 때마다 검토를 받아야 하는 Pain Point가 있다.(&lt;s&gt;실무진들의 Pain Point이지 사실 경영/임원진 입장에서는 그래야 마음이 놓일 것 같기도 하다&lt;/s&gt;) 우리 조직에 Error Budget 개념을 사용한다면 어떨까? 라는 생각이 들어 내 맘대로 몇 가지 전략을 생각해 봤다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Error Budget을 사용하려면 이를 측정할 수 있는 Observability 체계가 필요하다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;단계별 대응 정책 설정하기&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;반기별로 Error Budget 설정 및 KPI 지표 설정 해놓는다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 90px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style10&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 15.31%; text-align: center; height: 18px;&quot;&gt;&lt;b&gt;소진률&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 23.4496%; text-align: center; height: 18px;&quot;&gt;&lt;b&gt;단계&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 61.2403%; text-align: center; height: 18px;&quot;&gt;&lt;b&gt;대응 방안&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 15.31%; text-align: center; height: 18px;&quot;&gt;50%&lt;/td&gt;
&lt;td style=&quot;width: 23.4496%; text-align: center; height: 18px;&quot;&gt;주의&lt;/td&gt;
&lt;td style=&quot;width: 61.2403%; text-align: center; height: 18px;&quot;&gt;모니터링 체계 강화 ex. cpu, memory alert 임계치 낮추기 등&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 15.31%; text-align: center; height: 18px;&quot;&gt;75%&lt;/td&gt;
&lt;td style=&quot;width: 23.4496%; text-align: center; height: 18px;&quot;&gt;경고&lt;/td&gt;
&lt;td style=&quot;width: 61.2403%; text-align: center; height: 18px;&quot;&gt;신규배포 및 시스템 작업 시 리더급 검토&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 15.31%; text-align: center; height: 18px;&quot;&gt;90%&lt;/td&gt;
&lt;td style=&quot;width: 23.4496%; text-align: center; height: 18px;&quot;&gt;위험&lt;/td&gt;
&lt;td style=&quot;width: 61.2403%; text-align: center; height: 18px;&quot;&gt;신규배포 중단&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 15.31%; text-align: center; height: 18px;&quot;&gt;100%&lt;/td&gt;
&lt;td style=&quot;width: 23.4496%; text-align: center; height: 18px;&quot;&gt;긴급&lt;/td&gt;
&lt;td style=&quot;width: 61.2403%; text-align: center; height: 18px;&quot;&gt;안정성 우선 모드&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;팀별 Error Budget 할당&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;하나의 시스템에 Error Budget을 설정해놔도 R&amp;amp;R이 모호할 수 있을 것 같다. 하나의 시스템에도 백엔드, 프론트엔드, 인프라, DevOps, 네트워크 등등 여러 이해관계가 있기 때문에 팀단위 별로 Error Budget을 할당해서 해소하는 전략을 생각해봤다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프론트엔드: 월 30% 할당&lt;/li&gt;
&lt;li&gt;백엔드: 월 50% 할당&lt;/li&gt;
&lt;li&gt;인프라: 월 20% 할당&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;에러나면 어느 팀의 Budget에서 차감해?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;점점 전략을 짜볼 수록 현실적인 문제에 직면하는 것 같다. :)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;- MSA 환경에서는 연쇄 장애 시 책임 소재 모호&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;- 대규모 Enterprise급의 경우 아예 사업부 자체가 다른 조직 이슈일 수 있는 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;등등이 있을 것 같다. 기본적으로 어찌됐든 에러가 났다면 고객의 신뢰를 잃어버린 것이니 외부의 불가항력적인 요소에 의한 거라도 (통신사 네트워크의 문제, 물리적인 천재지변 등) 공통 1/N로 차감해야할 것 같다.&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;결론&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;결국 빠르게 이슈를 파악하고 대응하기 위해서는 Observability가 확보된 시스템을 만들어야 한다. Observability가 없이 이런 전략을 도입했다면 서로 싸우게 만드는 전략이 될 수도 있을듯 하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;참고.&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://jdhyeok.tistory.com/23&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://jdhyeok.tistory.com/23&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1758199713574&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[SRE] 서비스 수준 목표 - 서비스가 잘 돌아 가는지에 대한 척도&quot; data-og-description=&quot;&amp;quot;측정할 수 없으면, 개선할 수도 없다&amp;rdquo;서비르를 운영하다 보면 사용자, 운영자, 개발자 마다 &amp;quot;서비스가 잘 되고 있구나&amp;quot;의 기준은 제각각이다. 운영자는 &amp;quot;로그가 안보여요&amp;quot;, 고객은 &amp;quot;너무 느려요&quot; data-og-host=&quot;jdhyeok.tistory.com&quot; data-og-source-url=&quot;https://jdhyeok.tistory.com/23&quot; data-og-url=&quot;https://jdhyeok.tistory.com/23&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/xvL1q/hyZJM7LeN3/RBYJgOkR1h9dXU7FtP7i21/img.png?width=223&amp;amp;height=172&amp;amp;face=0_0_223_172,https://scrap.kakaocdn.net/dn/baedF1/hyZJveDvoX/3kyszvX5Pc1JQUMYijfEc1/img.png?width=223&amp;amp;height=172&amp;amp;face=0_0_223_172,https://scrap.kakaocdn.net/dn/JMpzG/hyZJMs9ETs/7rHshdTPuur0Vux9x0Npw0/img.jpg?width=1440&amp;amp;height=1080&amp;amp;face=0_0_1440_1080&quot;&gt;&lt;a href=&quot;https://jdhyeok.tistory.com/23&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://jdhyeok.tistory.com/23&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/xvL1q/hyZJM7LeN3/RBYJgOkR1h9dXU7FtP7i21/img.png?width=223&amp;amp;height=172&amp;amp;face=0_0_223_172,https://scrap.kakaocdn.net/dn/baedF1/hyZJveDvoX/3kyszvX5Pc1JQUMYijfEc1/img.png?width=223&amp;amp;height=172&amp;amp;face=0_0_223_172,https://scrap.kakaocdn.net/dn/JMpzG/hyZJMs9ETs/7rHshdTPuur0Vux9x0Npw0/img.jpg?width=1440&amp;amp;height=1080&amp;amp;face=0_0_1440_1080');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[SRE] 서비스 수준 목표 - 서비스가 잘 돌아 가는지에 대한 척도&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&quot;측정할 수 없으면, 개선할 수도 없다&amp;rdquo;서비르를 운영하다 보면 사용자, 운영자, 개발자 마다 &quot;서비스가 잘 되고 있구나&quot;의 기준은 제각각이다. 운영자는 &quot;로그가 안보여요&quot;, 고객은 &quot;너무 느려요&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;jdhyeok.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>DevOps/SRE</category>
      <author>JDhyeok</author>
      <guid isPermaLink="true">https://jdhyeok.tistory.com/33</guid>
      <comments>https://jdhyeok.tistory.com/33#entry33comment</comments>
      <pubDate>Thu, 18 Sep 2025 22:53:17 +0900</pubDate>
    </item>
    <item>
      <title>1편.  분산 합의란 무엇인가? - Raft의 기본 개념</title>
      <link>https://jdhyeok.tistory.com/32</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cdaMbX/btsQDXLBWUR/39RHKQoEuDtWnSZg7hY6xK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cdaMbX/btsQDXLBWUR/39RHKQoEuDtWnSZg7hY6xK/img.jpg&quot; data-alt=&quot;Raft&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cdaMbX/btsQDXLBWUR/39RHKQoEuDtWnSZg7hY6xK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcdaMbX%2FbtsQDXLBWUR%2F39RHKQoEuDtWnSZg7hY6xK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;565&quot; height=&quot;318&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Raft&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;분산 시스템에서 여로 노드가 마치 하나의 물리 노드처럼 일관된 상태를 유지하는 것은 어렵다. 네트워크 장애, 노드 실패, 패킷 손실 등등 다양한 문제들이 발생할 수 있고, 민감한 시스템의 경우 이는 큰 장애로 이어질 수도 있다. 이러한 문제를 해결하기 위해 등장한 개념이 &lt;b&gt;합의 알고리즘(Consensus Algorithm)&lt;/b&gt; 이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;그 중에서도 Raft 알고리즘이 가장 대표적이어 Raft를 한번 톺아보기로 했다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Raft의 탄생 배경&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Raft 이전의 대표적인 합의 알고리즘은 Paxos였다. 하지만 Paxos 알고리즘은 구현의 난이도가 높다는 단점이 있었다. 2013년 스탠포드에서 &quot;Understandability&quot;를 최 우선으로 하는 Raft 알고리즘을 개발했다.&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Raft의 핵심 개념&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;서버 상태 (Server States)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Raft에서 서버의 상태는 아래 세 가지 상태 중에 하나다&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1. follwer&lt;/b&gt;: 수동적인 상태로, leader와 candidate 요청에만 응답&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2.&lt;/b&gt; &lt;b&gt;candidate&lt;/b&gt;: 리더 선출 과정에서의 임시 상태&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3. leader&lt;/b&gt;: 모든 클라이언트 요청을 처리하고 로그 항목을 다른 서버들에 복제&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Term&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Raft는 시간을 Term이라는 단위로 나눈다. 각 term은 고유한 번호를 가지며, 최대 하나의 리더만 존재할 수 있다. term은 선거가 시작될 때마다 증가하며, &lt;b&gt;분산 시스템에서 논리적인 시계 역할&lt;/b&gt;을 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Raft의 세 가지 핵심 메커니즘&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;517&quot; data-origin-height=&quot;408&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/X522a/btsQBW7Tfwg/HW5IWQElpHJokf6dRiOfW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/X522a/btsQBW7Tfwg/HW5IWQElpHJokf6dRiOfW0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/X522a/btsQBW7Tfwg/HW5IWQElpHJokf6dRiOfW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FX522a%2FbtsQBW7Tfwg%2FHW5IWQElpHJokf6dRiOfW0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;437&quot; height=&quot;345&quot; data-origin-width=&quot;517&quot; data-origin-height=&quot;408&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 리더 선출 (Leader Election)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;선거 과정:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;서버가 시작하면 follower 상태로 시작&lt;/li&gt;
&lt;li&gt;리더로부터 hearbeat 받지 못하면 candidate가 됨&lt;/li&gt;
&lt;li&gt;자신의 term을 증가시키고 다른 서버들에게 투표 요청&lt;/li&gt;
&lt;li&gt;과반수 표를 얻으면 리더가 됨&lt;/li&gt;
&lt;li&gt;같은 term 에서 다른 서버가 리더가 되었다면 팔로워로 전환&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;선거 타임아웃:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;각 서버는 랜덤한 타임아웃을 가짐 (150~300ms)&lt;/li&gt;
&lt;li&gt;이를 통해 동시에 여러 서버가 후보자가 되는 것을 방지&lt;/li&gt;
&lt;li&gt;split vote 상황 최소화&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;2. 로그 복제 (Log Replication)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;로그 구조:&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 56.0465%; height: 58px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 14.7445%; text-align: center; height: 20px;&quot;&gt;인덱스&lt;/td&gt;
&lt;td style=&quot;width: 17.1365%; text-align: center; height: 20px;&quot;&gt;1&lt;/td&gt;
&lt;td style=&quot;width: 18.119%; text-align: center; height: 20px;&quot;&gt;2&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; text-align: center; height: 20px;&quot;&gt;3&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; text-align: center; height: 20px;&quot;&gt;4&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; text-align: center; height: 20px;&quot;&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 14.7445%; text-align: center; height: 18px;&quot;&gt;term&lt;/td&gt;
&lt;td style=&quot;width: 17.1365%; text-align: center; height: 18px;&quot;&gt;1&lt;/td&gt;
&lt;td style=&quot;width: 18.119%; text-align: center; height: 18px;&quot;&gt;1&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; text-align: center; height: 18px;&quot;&gt;2&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; text-align: center; height: 18px;&quot;&gt;3&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; text-align: center; height: 18px;&quot;&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 14.7445%; text-align: center; height: 20px;&quot;&gt;명령&lt;/td&gt;
&lt;td style=&quot;width: 17.1365%; text-align: center; height: 20px;&quot;&gt;x=3&lt;/td&gt;
&lt;td style=&quot;width: 18.119%; text-align: center; height: 20px;&quot;&gt;y=1&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; text-align: center; height: 20px;&quot;&gt;y=9&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; text-align: center; height: 20px;&quot;&gt;x=2&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; text-align: center; height: 20px;&quot;&gt;x=0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;복제 과정:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;클라이언트가 leader에게 명령 전송&lt;/li&gt;
&lt;li&gt;leader가 자신의 로그에 항목 추가&lt;/li&gt;
&lt;li&gt;leader가 follower들에게 AppendEntries RPC 전송&lt;/li&gt;
&lt;li&gt;과반수의 follower가 응답하면 로그 항목을 커밋&lt;/li&gt;
&lt;li&gt;리더가 클라이언트에게 성공 응답&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;로그 일관성 보장:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;로그 매칭 속성&lt;/b&gt;: 두 로그에서 같은 인덱스와 term을 가진 항목이 있다면, 해당 위치까지의 모든 항목이 동일&lt;/li&gt;
&lt;li&gt;&lt;b&gt;leader 완정성&lt;/b&gt;: 특정 term에서 커밋된 로그 항목은 그보다 높은 term의 모든 leader에 존재&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;3. 안정성 (Safety)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;핵심 안정성 속성:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;선거 안정성&lt;/b&gt;: 특정 용어에서 최대 하나의 리더만 선출&lt;/li&gt;
&lt;li&gt;&lt;b&gt;리더 추가 전용&lt;/b&gt;: 리더는 기존 로그 항목을 덮어쓰거나 삭제하지 않음&lt;/li&gt;
&lt;li&gt;&lt;b&gt;로그 매칭&lt;/b&gt;: 두 로그의 특정 위치가 같은 용어라면 모든 이전 항목도 동일&lt;/li&gt;
&lt;li&gt;&lt;b&gt;리더 완전성&lt;/b&gt;: 커밋된 항목은 모든 미래 리더에 존재&lt;/li&gt;
&lt;li&gt;&lt;b&gt;상태 머신 안정성&lt;/b&gt;: 서버가 특정 인덱스에 로그 항목을 적용했다면, 다른 서버도 같은 항목 적용&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Raft의 장점과 한계&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;장점&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;제작자의 철학에 맞게 이해하기 쉬워 구현에 용이&lt;/li&gt;
&lt;li&gt;엄격한 안정성 보장&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;단점&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;과반수 원칙으로 가용성 제한&lt;/li&gt;
&lt;li&gt;모든 변경사항에서 과반수 합의 필요로 인한 성능 오버헤드&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;실제 Raft 알고리즘으로 구현된 오픈소스&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;etcd: 클러스터 메타데이터의 일관성 보장&lt;/li&gt;
&lt;li&gt;Consul: 서비스 디스커버리와 구성관리&lt;/li&gt;
&lt;li&gt;TiKV: 분산 트랜잭션 key-value 스토어로 데이터 복제를 위해 Raft 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;참고.&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://raft.github.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://raft.github.io/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1758119712371&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Raft Consensus Algorithm&quot; data-og-description=&quot;What is Raft? Raft is a consensus algorithm that is designed to be easy to understand. It's equivalent to Paxos in fault-tolerance and performance. The difference is that it's decomposed into relatively independent subproblems, and it cleanly addresses all&quot; data-og-host=&quot;raft.github.io&quot; data-og-source-url=&quot;https://raft.github.io/&quot; data-og-url=&quot;https://raft.github.io/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://raft.github.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://raft.github.io/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Raft Consensus Algorithm&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;What is Raft? Raft is a consensus algorithm that is designed to be easy to understand. It's equivalent to Paxos in fault-tolerance and performance. The difference is that it's decomposed into relatively independent subproblems, and it cleanly addresses all&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;raft.github.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://raft.github.io/raft.pdf&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://raft.github.io/raft.pdf&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>실험실</category>
      <category>algorithm</category>
      <category>Distributed System</category>
      <category>it</category>
      <category>분산시스템</category>
      <author>JDhyeok</author>
      <guid isPermaLink="true">https://jdhyeok.tistory.com/32</guid>
      <comments>https://jdhyeok.tistory.com/32#entry32comment</comments>
      <pubDate>Wed, 17 Sep 2025 23:35:36 +0900</pubDate>
    </item>
    <item>
      <title>[Python] Python LRU Cache 성능 최적화</title>
      <link>https://jdhyeok.tistory.com/31</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;225&quot; data-origin-height=&quot;225&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VHs6m/btsQAGcjmHL/PasnpG3HbsFD0PjKKunZG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VHs6m/btsQAGcjmHL/PasnpG3HbsFD0PjKKunZG0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VHs6m/btsQAGcjmHL/PasnpG3HbsFD0PjKKunZG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVHs6m%2FbtsQAGcjmHL%2FPasnpG3HbsFD0PjKKunZG0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;225&quot; height=&quot;225&quot; data-origin-width=&quot;225&quot; data-origin-height=&quot;225&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;DP유형의 알고리즘 문제를 풀다 모범 답안으로 &lt;b&gt;@lru_cache &lt;/b&gt;데코레이터를 쓴 파이썬 함수가 있어 궁금해서 찾아봤다. &lt;s&gt;라떼는 이런거 없었는데....&lt;/s&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;LRU Cache란 무엇인가?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;LRU(Least Recently Used) Cache는 가장 최근에 사용되지 않은 항목을 제거하는 캐싱 전략&lt;/b&gt;이다. 메모리가 제한된 환경에서 효율적인 데이터 관리를 위해 사용되며, 프로그램의 성능을 크게 향상시킬 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;LRU Cache의 핵심 개념&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;캐시 히트(Cache Hit)&lt;/b&gt;: 요청된 데이터가 캐시에 있는 경우&lt;/li&gt;
&lt;li&gt;&lt;b&gt;캐시 미스(Cache Miss)&lt;/b&gt;: 요청된 데이터가 캐시에 없어서 새로 계산해야 하는 경우&lt;/li&gt;
&lt;li&gt;&lt;b&gt;용량 제한&lt;/b&gt;: 메모리 사용량 제어를 위한 최대 항목 수 설정&lt;/li&gt;
&lt;li&gt;&lt;b&gt;교체 정책&lt;/b&gt;: 캐시가 가득 찼을 때 어떤 항목을 제거할지 결정&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Python @lru_cache 데코레이터 사용법 (python 3.2 이상)&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기본 사용법&lt;/h3&gt;
&lt;pre id=&quot;code_1757945239017&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from functools import lru_cache

@lru_cache(maxsize=128)
def expensive_function(n):
    print(f&quot;Computing for {n}&quot;)
    result = sum(i**2 for i in range(n)) # 복잡한 연산
    return result


print(expensive_function(100))  # 계산 실행
print(expensive_function(100))  # 캐시에서 반환 (빠름)
print(expensive_function(200))  # 새로운 계산 실행&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;캐시 정보 확인 및 관리&lt;/h3&gt;
&lt;pre id=&quot;code_1757945305880&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@lru_cache(maxsize=100)
def fibonacci(n):
    if n &amp;lt; 2:
        return n
    return fibonacci(n-1) + fibonacci(n-2) # 재귀함수에서도 사용 가능 (Memoization)

# 캐시 통계 확인
print(fibonacci.cache_info())  # CacheInfo(hits=0, misses=0, maxsize=100, currsize=0)

fibonacci(50)
print(fibonacci.cache_info())  # 히트/미스 정보 확인

# 캐시 초기화
fibonacci.cache_clear()&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;LRU Cache 내부 구현 원리&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Python의 LRU Cache의 구현을 위해서는 HashMap과 Double Linked-List 구조로 이루어지고 동작 과정은 아래와같다.thread saftey 하기 때문에 멀티쓰레드 환경에서도 사용 가능하다.&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;1. 함수 호출 시 키 생성&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;_make_key(args, kwds, typed)로 인자와 키워드를 튜플로 묶어 캐시 키를 만듦.&lt;/li&gt;
&lt;li&gt;단일 값이 int, str이면 그대로 키로 사용하고, 아니면&lt;span&gt;&amp;nbsp;&lt;/span&gt;_HashedSeq로 래핑.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2. 캐시 조회/추가&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;캐시에서 키를 조회.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;있으면&lt;/b&gt;: 연결 리스트에서 해당 노드를 가장 최근 위치로 이동시키고, 저장된 결과 반환(hits&lt;span&gt;&amp;nbsp;&lt;/span&gt;증가).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;없으면&lt;/b&gt;: 실제 함수 실행, 결과를 캐시에 저장(misses&lt;span&gt;&amp;nbsp;&lt;/span&gt;증가).
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;캐시가 가득 차 있으면 가장 오래된 노드(루트의 NEXT)를 삭제하고 새 노드를 삽입.&lt;/li&gt;
&lt;li&gt;캐시가 가득 차 있지 않으면 새 노드를 루트의 PREV 위치에 삽입.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;3. 연결 리스트 관리&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;캐시의 순서를 관리하기 위해 이중 연결 리스트(원형)를 사용.&lt;/li&gt;
&lt;li&gt;최근 사용한 노드는 리스트의 뒤(root[PREV])로 보내고, 오래된 노드는 앞(root[NEXT])로 이동.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;lru_cahce 실제 구현된 Python 함수&lt;/p&gt;
&lt;pre id=&quot;code_1757946691833&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def lru_cache(maxsize=128, typed=False):
    def decorating_function(user_function):
        wrapper = _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo)
        wrapper.cache_parameters = lambda : {'maxsize': maxsize, 'typed': typed}
        return update_wrapper(wrapper, user_function)
    return decorating_function

def _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo):
    # cache: 실제 저장소
    # root: 이중 연결 리스트의 루트
    # wrapper: 함수 호출 시 캐시 처리 담당&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;lru_cache를 쓰면 hash이기 때문에 DP문제에 대해&lt;b&gt; time-complexity O(1)으로 해결&lt;/b&gt; 가능하고, 알고리즘 문제 뿐만 아니라, 실제 비즈니스 어플리케이션에서도 캐시가 필요할 때 사용할 수 있어서 참고하면 좋을 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;참고.&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.python.org/3/library/functools.html#functools.lru_cache&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://docs.python.org/3/library/functools.html#functools.lru_cache&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1757945559518&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;functools &amp;mdash; Higher-order functions and operations on callable objects&quot; data-og-description=&quot;Source code: Lib/functools.py The functools module is for higher-order functions: functions that act on or return other functions. In general, any callable object can be treated as a function for t...&quot; data-og-host=&quot;docs.python.org&quot; data-og-source-url=&quot;https://docs.python.org/3/library/functools.html#functools.lru_cache&quot; data-og-url=&quot;https://docs.python.org/3/library/functools.html&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/m6ANX/hyZIZgH0Cl/bhmX9iccdJxkmqfBtYCsh0/img.png?width=1146&amp;amp;height=600&amp;amp;face=0_0_1146_600&quot;&gt;&lt;a href=&quot;https://docs.python.org/3/library/functools.html#functools.lru_cache&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.python.org/3/library/functools.html#functools.lru_cache&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/m6ANX/hyZIZgH0Cl/bhmX9iccdJxkmqfBtYCsh0/img.png?width=1146&amp;amp;height=600&amp;amp;face=0_0_1146_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;functools &amp;mdash; Higher-order functions and operations on callable objects&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Source code: Lib/functools.py The functools module is for higher-order functions: functions that act on or return other functions. In general, any callable object can be treated as a function for t...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.python.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/python/cpython/blob/3.13/Lib/functools.py&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/python/cpython/blob/3.13/Lib/functools.py&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1757945577577&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;cpython/Lib/functools.py at 3.13 &amp;middot; python/cpython&quot; data-og-description=&quot;The Python programming language. Contribute to python/cpython development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/python/cpython/blob/3.13/Lib/functools.py&quot; data-og-url=&quot;https://github.com/python/cpython/blob/3.13/Lib/functools.py&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/UX2CN/hyZJloWU52/cZAEJgVXCzTIlIotIpiggk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/chk8bK/hyZJbt4Fut/BTRKPKppo5wc3yZF6Ohcik/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/python/cpython/blob/3.13/Lib/functools.py&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/python/cpython/blob/3.13/Lib/functools.py&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/UX2CN/hyZJloWU52/cZAEJgVXCzTIlIotIpiggk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/chk8bK/hyZJbt4Fut/BTRKPKppo5wc3yZF6Ohcik/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;cpython/Lib/functools.py at 3.13 &amp;middot; python/cpython&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;The Python programming language. Contribute to python/cpython development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>실험실</category>
      <category>cache</category>
      <category>it</category>
      <category>optimization</category>
      <category>python</category>
      <category>최적화</category>
      <author>JDhyeok</author>
      <guid isPermaLink="true">https://jdhyeok.tistory.com/31</guid>
      <comments>https://jdhyeok.tistory.com/31#entry31comment</comments>
      <pubDate>Mon, 15 Sep 2025 23:37:58 +0900</pubDate>
    </item>
    <item>
      <title>[Tomcat] 톰캣 클러스터링 - Multicast</title>
      <link>https://jdhyeok.tistory.com/30</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;318&quot; data-origin-height=&quot;159&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OnlVc/btsQjCAlBQL/l3vXeUNPdNHvHjWcfkEDek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OnlVc/btsQjCAlBQL/l3vXeUNPdNHvHjWcfkEDek/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OnlVc/btsQjCAlBQL/l3vXeUNPdNHvHjWcfkEDek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOnlVc%2FbtsQjCAlBQL%2Fl3vXeUNPdNHvHjWcfkEDek%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;318&quot; height=&quot;159&quot; data-origin-width=&quot;318&quot; data-origin-height=&quot;159&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;들어가며&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회사에서 아주 오래된 On-premise서버의 OS가 EoS가 되며, 신규 서버로 Clean-install을 진행하며 tomcat을 처음부터 다시 설치해야하는 요건이 생겼다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이중화 구조여서 Clustering을 해야했고, 직면한 문제가 있어 트러블슈팅한 기록과 알게된 개념을 남긴다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제 발생&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 Tomcat 을 기동하니 아래와 같은 오류가 발생했다.&lt;/p&gt;
&lt;pre id=&quot;code_1756823832795&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Unable to join multicast group, make sure your system has multicasting enabled.
Unable to start cluster.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;알아보니 내가 맡게된 서버의 tomcat은 Multicast 방식으로 clustering 하고 있었다. 보통 내 구축 경험으로는 Unicast로 1:1 통신을 통한 clustering을 했는데, 이런&amp;nbsp;Multicast 방식은 생소했고 어떤 통신 방식인지 궁금해졌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 설정은 Unicast, Multicast 방식이니 참고하길 바란다.&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;# Multicast Clustering server.xml 설정 예시&lt;/p&gt;
&lt;pre id=&quot;code_1756826109234&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;Cluster className=&quot;org.apache.catalina.ha.tcp.SimpleTcpCluster&quot;
  channelSendOptions=&quot;8&quot;&amp;gt;
  &amp;lt;Manager className=&quot;org.apache.catalina.ha.session.DeltaManager&quot;
    expireSessionsOnShutdown=&quot;false&quot; notifyListenersOnReplication=&quot;true&quot; /&amp;gt;
  &amp;lt;Channel className=&quot;org.apache.catalina.tribes.group.GroupChannel&quot;&amp;gt;
    &amp;lt;Membership className=&quot;org.apache.catalina.tribes.membership.McastService&quot;
      address=&quot;228.0.0.4&quot;
      port=&quot;45564&quot;
      frequency=&quot;500&quot;
      dropTime=&quot;3000&quot; /&amp;gt;
    &amp;lt;Receiver className=&quot;org.apache.catalina.tribes.transport.nio.NioReceiver&quot;
      address=&quot;auto&quot;
      port=&quot;4000&quot;
      autoBind=&quot;100&quot;
      selectorTimeout=&quot;5000&quot;
      maxThreads=&quot;6&quot; /&amp;gt;
    &amp;lt;Sender className=&quot;org.apache.catalina.tribes.transport.ReplicationTransmitter&quot;&amp;gt;
      &amp;lt;Transport className=&quot;org.apache.catalina.tribes.transport.nio.PooledParallelSender&quot; /&amp;gt;
    &amp;lt;/Sender&amp;gt;
    &amp;lt;Interceptor className=&quot;org.apache.catalina.tribes.group.interceptors.TcpFailureDetector&quot; /&amp;gt;
    &amp;lt;Interceptor
      className=&quot;org.apache.catalina.tribes.group.interceptors.MessageDispatchInterceptor&quot; /&amp;gt;
  &amp;lt;/Channel&amp;gt;
  &amp;lt;Valve className=&quot;org.apache.catalina.ha.tcp.ReplicationValve&quot; filter=&quot;&quot; /&amp;gt;
  &amp;lt;Valve className=&quot;org.apache.catalina.ha.session.JvmRouteBinderValve&quot; /&amp;gt;
  &amp;lt;Deployer className=&quot;org.apache.catalina.ha.deploy.FarmWarDeployer&quot;
    tempDir=&quot;/tmp/war-temp/&quot;
    deployDir=&quot;/tmp/war-deploy/&quot;
    watchDir=&quot;/tmp/war-listen/&quot;
    watchEnabled=&quot;false&quot; /&amp;gt;
  &amp;lt;ClusterListener className=&quot;org.apache.catalina.ha.session.ClusterSessionListener&quot; /&amp;gt;
&amp;lt;/Cluster&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;# Unicast&lt;span style=&quot;background-color: #fafafa; color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Clustering server.xml 설정 예시&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fafafa; color: #333333; text-align: start;&quot;&gt;(Tomcat 9부터 공식 지원된다)&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756826375751&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;Cluster channelSendOptions=&quot;8&quot; channelStartOptions=&quot;3&quot; className=&quot;org.apache.catalina.ha.tcp.SimpleTcpCluster&quot;&amp;gt;
&amp;lt;Manager className=&quot;org.apache.catalina.ha.session.DeltaManager&quot; expireSessionsOnShutdown=&quot;false&quot; notifyListenersOnReplication=&quot;true&quot;/&amp;gt;
&amp;lt;Channel className=&quot;org.apache.catalina.tribes.group.GroupChannel&quot;&amp;gt;
  &amp;lt;Sender className=&quot;org.apache.catalina.tribes.transport.ReplicationTransmitter&quot;&amp;gt;
    &amp;lt;Transport className=&quot;org.apache.catalina.tribes.transport.nio.PooledParallelSender&quot; /&amp;gt;
  &amp;lt;/Sender&amp;gt;
  &amp;lt;Receiver address=&quot;1.1.1.1&quot; autoBind=&quot;0&quot; className=&quot;org.apache.catalina.tribes.transport.nio.NioReceiver&quot; maxThreads=&quot;6&quot; port=&quot;3101&quot; selectorTimeout=&quot;5000&quot;/&amp;gt;
  &amp;lt;Interceptor className=&quot;org.apache.catalina.tribes.group.interceptors.StaticMembershipInterceptor&quot;&amp;gt;
    &amp;lt;Member className=&quot;org.apache.catalina.tribes.membership.StaticMember&quot; port=&quot;3101&quot; host=&quot;1.1.1.2&quot; uniqueId=&quot;{0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2}&quot;/&amp;gt;
  &amp;lt;/Interceptor&amp;gt;
&amp;lt;/Channel&amp;gt;
	&amp;lt;ClusterListener className=&quot;org.apache.catalina.ha.session.ClusterSessionListener&quot;/&amp;gt;
&amp;lt;/Cluster&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Multicast란? (feat. Unicast, Broadcast)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단히 비교해보면&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;304&quot; data-start=&quot;268&quot;&gt;&lt;b&gt;Unicast&lt;/b&gt;: 1:1 통신 (클라이언트 &amp;rarr; 서버)&lt;/li&gt;
&lt;li data-end=&quot;343&quot; data-start=&quot;305&quot;&gt;&lt;b&gt;Broadcast&lt;/b&gt;: 네트워크 대역 내 모든 장비에 뿌림&lt;/li&gt;
&lt;li data-end=&quot;381&quot; data-start=&quot;344&quot;&gt;&lt;b&gt;Multicast&lt;/b&gt;: 특정 그룹에 가입된 장비들만 받음&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Tomcat은 같은 클러스터에 속한 서버들이 서로의 상태를 주고받기 위해 &lt;b&gt;멀티캐스트 그룹에 조인(join)&lt;/b&gt; 하는 구조를 사용한다. 예를 들어, 세션 변경 사항을 동시에 여러 서버에 전송할 때 Multicast가 효율적이다.&lt;/p&gt;
&lt;pre id=&quot;code_1756826451194&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;Membership className=&quot;org.apache.catalina.tribes.membership.McastService&quot;
      address=&quot;228.0.0.4&quot;
      port=&quot;45564&quot;
      frequency=&quot;500&quot;
      dropTime=&quot;3000&quot; /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 Tomcat을 사용하게 되면&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Tomcat&amp;nbsp;노드들은&amp;nbsp;228.0.0.4:45564&amp;nbsp;멀티캐스트&amp;nbsp;그룹에&amp;nbsp;들어간다.&lt;/li&gt;
&lt;li&gt;각 노드는 0.5초(500ms)마다 hearbeat 신호를 그룹에 UDP 통신으로 전송한다.&lt;/li&gt;
&lt;li&gt;만약 어떤 노드가 3초 동안 응답하지 않으면, 클러스터에서 제외된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;문제가 뭘까?&lt;/h2&gt;
&lt;pre id=&quot;code_1756826702983&quot; class=&quot;routeros&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;Unable to join multicast group, make sure your system has multicasting enabled.
Unable to start cluster.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 에러로 보았을 때 Tomcat이 Multicast 그룹에 가입을 시도했으나 실패했다는 의미.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 경우 원인은 OS 레벨과, 네트워크 장비 레벨 둘 중 하나일 것이라 판단했다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서버/OS 레벨
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;NIC(Network Interface Card)가 멀티캐스트를 미지원&lt;/li&gt;
&lt;li&gt;방화벽에서 멀티캐스트 트래픽 차단&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;네트워크 장비 정책
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;스위치/라우터 단에서 멀티캐스트 패킷을 필터링 하는 경우&lt;/li&gt;
&lt;li&gt;IGMP Snooping 설정이 필요하거나, 방화벽 정책 때문에 막히는 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아직 네트워크 담당자에게 확인 중이라 결과는 더 지켜봐야 하지만, 둘 중 하나로 예상된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내 환경은 보안이 중요시되는 폐쇄망 환경이다 보니 whitelist 기반으로 접근하다 보니 초기 설정에 공수가 많이 든다. 특히 오래된 서버일 수록 히스토리가 쌓이고 담당자가 변경되다 보면 이런 경우가 많은데, 이런 조사를 어떻게 해야할지 고민해 봐야겠다.&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;대안 아키텍처&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 네트워크단에서 Multicast가 안된다면, tomcat9은 Unicast가 가능하지만 tomcat7,8 에는 Unicast가 공식 지원이 아니기에 불가능은 아니지만 권장되진 않을것이다. 그렇다면 StickySession, 혹은 third-party로 redis같은 메모리 캐시를 두면 되지 않을까 싶다.&lt;/p&gt;</description>
      <category>DevOps/SRE</category>
      <category>it</category>
      <category>middleware</category>
      <category>Multicast</category>
      <category>Network</category>
      <author>JDhyeok</author>
      <guid isPermaLink="true">https://jdhyeok.tistory.com/30</guid>
      <comments>https://jdhyeok.tistory.com/30#entry30comment</comments>
      <pubDate>Wed, 3 Sep 2025 00:35:12 +0900</pubDate>
    </item>
    <item>
      <title>밑바닥부터 시작하는 분산 시스템 시리즈</title>
      <link>https://jdhyeok.tistory.com/29</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;654&quot; data-origin-height=&quot;473&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bd37lt/btsQaocG0Gz/e3IapMUGCOHX3GQb7raTDK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bd37lt/btsQaocG0Gz/e3IapMUGCOHX3GQb7raTDK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bd37lt/btsQaocG0Gz/e3IapMUGCOHX3GQb7raTDK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbd37lt%2FbtsQaocG0Gz%2Fe3IapMUGCOHX3GQb7raTDK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;654&quot; height=&quot;473&quot; data-origin-width=&quot;654&quot; data-origin-height=&quot;473&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;개요&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회사에서 Elasticsearch, Tomcat 등의 클러스터를 구축하고, 혼자 Kubernetes를 공부해보다가 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;&quot;물리적으로 분산된 서버들이 어떻게 하나의 서버처럼 동작할 수 있을까?&quot;&lt;/b&gt;&lt;/span&gt; 라는 궁금증이 생겼다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;누군가도 나와 같은 생각을 했을 것 같아서 분산 시스템을 공부해보고, 실제로 분산 시스템을 구축해보는 사이드 프로젝트를 해 공유해보기로 했다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;목차&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1편.&amp;nbsp; 분산 합의란 무엇인가? - Raft의 기본 개념 (TBD)&lt;br /&gt;2편. 클러스터의 심장, 리더 선출 구현기 (TBD)&lt;br /&gt;3편. 데이터 복제와 최종 일관성 보장하기 (TBD)&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;</description>
      <category>실험실</category>
      <category>distributed</category>
      <category>etcd</category>
      <category>Kafka</category>
      <category>대규모시스템</category>
      <category>분산시스템</category>
      <category>설계</category>
      <category>엘라스틱서치</category>
      <category>쿠버네티스</category>
      <author>JDhyeok</author>
      <guid isPermaLink="true">https://jdhyeok.tistory.com/29</guid>
      <comments>https://jdhyeok.tistory.com/29#entry29comment</comments>
      <pubDate>Thu, 28 Aug 2025 21:23:03 +0900</pubDate>
    </item>
    <item>
      <title>[1분 쿠버네티스] Taint &amp;amp; Tolerations란? Kubernetes 노드 스케줄링 제약</title>
      <link>https://jdhyeok.tistory.com/28</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;512&quot; data-origin-height=&quot;256&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ExfTx/btsP1xlJPc5/4yCS9hbiX3wvnft9M5w01k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ExfTx/btsP1xlJPc5/4yCS9hbiX3wvnft9M5w01k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ExfTx/btsP1xlJPc5/4yCS9hbiX3wvnft9M5w01k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FExfTx%2FbtsP1xlJPc5%2F4yCS9hbiX3wvnft9M5w01k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;512&quot; height=&quot;256&quot; data-origin-width=&quot;512&quot; data-origin-height=&quot;256&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #5c5c5c; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Taints &amp;amp; Tolerations 이란?&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Taint와 Tolerations 는 Kubernetes의 &lt;b&gt;Pod 스케줄링 제약 조건을 정의&lt;/b&gt;하는 기능이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;b&gt;Taint&lt;/b&gt;: 노드에 &quot;특정 Pod는 오지 마라&quot;라는 표시&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Tolerations&lt;/b&gt;: Pod가 특정 Taint를 무시하고 해당 노드에 스케줄링 될 수 있도록 허용&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;노드에 들어올 수 있는 Pod를 필터링 하는 기능&lt;/b&gt;&lt;/span&gt;이라고 생각하면 된다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;*Taint &amp;amp; Toleration을 직역하면 오염 &amp;amp; 관용 이라는 뜻이다. 즉, 노드를 오염시켜 Pod를 받지 않고, Pod에 오염을 참을 수 있는 관용을 부여한다 라고 보면 된다.&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #5c5c5c; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Kube-Scheduler의 주요 기능&lt;/b&gt;&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #5c5c5c; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li style=&quot;list-style-type: decimal;&quot;&gt;&lt;b&gt;노드 전용화 (Node Isolation)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;특정 워크로드만 실행하도록 노드를 전용으로 할당&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li style=&quot;list-style-type: decimal;&quot;&gt;&lt;b&gt;리소스 보호 (Resource Protection)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;중요 리소스를 차지하지 않도록 일반 Pod의 접근을 제한&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;master노드에 일반 Pod를 위치시키지 않는 예시&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li style=&quot;list-style-type: decimal;&quot;&gt;&lt;b&gt;장애 처리 (Failure Handling)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;장애 난 노드를 자동으로 격리&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #5c5c5c; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;사용 예시&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;노드에 Taint 추가&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1755695128429&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# node01에는 Toleration이 없는 Pod는 스케줄링되지 않음
kubectl taint nodes node01 key=value:NoSchedule&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Pod에 Toleration 추가&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1755695325591&quot; class=&quot;go&quot; data-ke-language=&quot;go&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 위 node01에 스케줄링 될 수 있도록 만든 tolerations
tolerations:
- key: key
  operator: Equal
  value: value
  effect: NoSchedule&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #5c5c5c; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;주의점&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;잘못 설정하면 Pod가 계속 Pending 상태에서 멈출 수 있음&lt;/li&gt;
&lt;li&gt;운영 환경에서는 핵심적인 비즈니스가 있는 서비스의 전용 노드나 GPU노드에 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Taint &amp;amp; Tolerations를 잘 활용하면&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt; Kubernetes 클러스터 자원 관리와 워크로드 격리&lt;/b&gt;&lt;/span&gt;를 정교하게 다룰 수 있게된다.&lt;/p&gt;</description>
      <category>it</category>
      <category>k8s</category>
      <category>Kubernetes</category>
      <category>tech</category>
      <category>개발</category>
      <category>개발자</category>
      <category>인프라</category>
      <category>쿠버네티스</category>
      <author>JDhyeok</author>
      <guid isPermaLink="true">https://jdhyeok.tistory.com/28</guid>
      <comments>https://jdhyeok.tistory.com/28#entry28comment</comments>
      <pubDate>Wed, 20 Aug 2025 22:11:42 +0900</pubDate>
    </item>
    <item>
      <title>[1분 쿠버네티스] Kube Controller Manager란? Kubernetes 클러스터 제어 핵심</title>
      <link>https://jdhyeok.tistory.com/27</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;512&quot; data-origin-height=&quot;256&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Q2GzZ/btsPVF69ZgE/bHh3qL0CELcbRvdQ6lQ9lK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Q2GzZ/btsPVF69ZgE/bHh3qL0CELcbRvdQ6lQ9lK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Q2GzZ/btsPVF69ZgE/bHh3qL0CELcbRvdQ6lQ9lK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQ2GzZ%2FbtsPVF69ZgE%2FbHh3qL0CELcbRvdQ6lQ9lK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;512&quot; height=&quot;256&quot; data-origin-width=&quot;512&quot; data-origin-height=&quot;256&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #5c5c5c; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Kube-Scheduler란?&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Kube-Controller-Manager는 Kubernetes &lt;b&gt;클러스터의 상태를 원하는 목표 상태(Desired State)로 유지하도록 관리&lt;/b&gt;하는 핵심 컴포넌트이다. 쉽게 말해, &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;&amp;ldquo;쿠버네티스의 자동화 관리자(Controller 집합체)&amp;rdquo;&lt;/b&gt;&lt;/span&gt;라고 할 수 있다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #5c5c5c; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Kube-Scheduler의 주요 역할과 기능&lt;/b&gt;&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #5c5c5c; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li style=&quot;list-style-type: decimal;&quot;&gt;ReplicaSet Controller
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;지정된 수의 Pod가 항상 실행되도록 보장&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li style=&quot;list-style-type: decimal;&quot;&gt;Node Controller
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;노드의 상태(정상/비정상) 모니터링 및 조치&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li style=&quot;list-style-type: decimal;&quot;&gt;Endpoint Controller
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;Service와 Pod를 연결 (네트워크 엔드포인트 관리)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li style=&quot;list-style-type: decimal;&quot;&gt;Service Account &amp;amp; Token Controller
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;Pod가 API Server와 안전하게 통신 가능하도록 인증자격 발급&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이런 다양한 Controller를 &lt;b&gt;하나의 프로세스로 통합하여 실행하는 것이 Kube Controller Manager&lt;/b&gt;이다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #5c5c5c; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Kubernetes 아키텍처에서의 위치&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Kube-API Server에 명령 전달&lt;/li&gt;
&lt;li&gt;Kube Controller Manager는 API Server를 통해 etcd에 기록된 클러스터 상태 확인&lt;/li&gt;
&lt;li&gt;실제 상태가 Desired 상태와 다르면, 새로운 Pod를 생성하거나, 노드를 교체, 엔드포인트 갱신 등의 조치를 자동으로 수행&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #5c5c5c; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;장애 시 영향&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클러스터가 자동으로 복구/조정하는 기능을 잃게 됨&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, &lt;span style=&quot;background-color: #f3c000;&quot;&gt;&lt;b&gt;Kube Controller Manager는 Kubernetes의 Self-Healing 능력을 가능하게 하는 핵심적인 컴포넌트&lt;/b&gt;&lt;/span&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #5c5c5c; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;참조.&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://kubernetes.io/docs/reference/command-line-tools-reference/kube-controller-manager/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://kubernetes.io/docs/reference/command-line-tools-reference/kube-controller-manager/&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1755616875216&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;kube-controller-manager&quot; data-og-description=&quot;Synopsis The Kubernetes controller manager is a daemon that embeds the core control loops shipped with Kubernetes. In applications of robotics and automation, a control loop is a non-terminating loop that regulates the state of the system. In Kubernetes, a&quot; data-og-host=&quot;kubernetes.io&quot; data-og-source-url=&quot;https://kubernetes.io/docs/reference/command-line-tools-reference/kube-controller-manager/&quot; data-og-url=&quot;https://kubernetes.io/docs/reference/command-line-tools-reference/kube-controller-manager/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/8x9je/hyZDcZGnVw/cWkI0tVnX52PvtDMil0wgk/img.png?width=1727&amp;amp;height=373&amp;amp;face=0_0_1727_373&quot;&gt;&lt;a href=&quot;https://kubernetes.io/docs/reference/command-line-tools-reference/kube-controller-manager/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://kubernetes.io/docs/reference/command-line-tools-reference/kube-controller-manager/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/8x9je/hyZDcZGnVw/cWkI0tVnX52PvtDMil0wgk/img.png?width=1727&amp;amp;height=373&amp;amp;face=0_0_1727_373');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;kube-controller-manager&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Synopsis The Kubernetes controller manager is a daemon that embeds the core control loops shipped with Kubernetes. In applications of robotics and automation, a control loop is a non-terminating loop that regulates the state of the system. In Kubernetes, a&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;kubernetes.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>DevOps/쿠버네티스</category>
      <category>it</category>
      <category>k8s</category>
      <category>Kubernetes</category>
      <category>tech</category>
      <category>개발</category>
      <category>개발자</category>
      <category>인프라</category>
      <category>쿠버네티스</category>
      <author>JDhyeok</author>
      <guid isPermaLink="true">https://jdhyeok.tistory.com/27</guid>
      <comments>https://jdhyeok.tistory.com/27#entry27comment</comments>
      <pubDate>Wed, 20 Aug 2025 00:21:33 +0900</pubDate>
    </item>
  </channel>
</rss>