<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>junkmm blog</title>
    <link>https://junkmm.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Wed, 20 May 2026 00:49:56 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>junkmm</managingEditor>
    <item>
      <title>[O-Tel] Opentelemetry로 .Net Trace 구성하기</title>
      <link>https://junkmm.tistory.com/46</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;개요&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요. 오늘은 회사에서 PoC를 진행했던 O-Tel을 통한 Observalbility 구성하기 중 .Net Core App을 대상으로 Trace 메트릭을 수집하는 방법에 대해 정리하고자 합니다. 공식 문서를 참고하며 구성하였고, PoC를 진행했던 것보단 최소한으로 핵심적인 것들만 정리해 보려 합니다.&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;image.png&quot; data-origin-width=&quot;6172&quot; data-origin-height=&quot;1472&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDk29h/btsJ4QSartC/flSFB5hNsi34NyOVtxfUi1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDk29h/btsJ4QSartC/flSFB5hNsi34NyOVtxfUi1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDk29h/btsJ4QSartC/flSFB5hNsi34NyOVtxfUi1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDk29h%2FbtsJ4QSartC%2FflSFB5hNsi34NyOVtxfUi1%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;6172&quot; height=&quot;1472&quot; data-filename=&quot;image.png&quot; data-origin-width=&quot;6172&quot; data-origin-height=&quot;1472&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;이번 글에서의 흐름은 아래와 같이 진행됩니다.&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;1. kind를 통해 간단한 kubernetes 클러스터를 생성합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. Trace Metrics을 확인하기 위한 Grafana를 설치합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. Trace Metrics의 수집, 저장을 위한 Tempo를 설치합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. Open Telemetry Collector를 설치하고, Trace Metrics 자동 수집을 위한 CRD를 구성합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. .Net Application을 배포합니다. 이 때 Trace Metrics을 자동 수집해주기 위한 Annotation을 설정합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. Grafana에서 Tempo 데이터를 추가하고, 조회 합니다.&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;쿠버네티스 환경에서 .Net Application의 별도 코드 수정 없이, O-Tel 구성을 통해 Trace Metrics을 자동 수집하는 것을 목표로 합니다.&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;참고로 .Net Application에 O-Tel SDK를 구성하여 수집할 메트릭을 직접 정의할 수도 있습니다.&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;h3 data-ke-size=&quot;size23&quot;&gt;Step 1. Kind로 간단한 Kubernetes 클러스터 생성하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 사진처럼 kind로 간단한 Kubernetes 클러스터를 생성합니다. kind는 로컬 환경에서 소규모로 kubernetes 클러스터를 간단히 생성할 수 있게 도와주며, 처음 접해보신다면 공식 문서를 참고하여 설정해 보시기 바랍니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2034&quot; data-origin-height=&quot;1010&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HTiSf/btsJ4nJuqXp/a7xyZEbz0w6f9BrlCrcKOk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HTiSf/btsJ4nJuqXp/a7xyZEbz0w6f9BrlCrcKOk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HTiSf/btsJ4nJuqXp/a7xyZEbz0w6f9BrlCrcKOk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHTiSf%2FbtsJ4nJuqXp%2Fa7xyZEbz0w6f9BrlCrcKOk%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;2034&quot; height=&quot;1010&quot; data-origin-width=&quot;2034&quot; data-origin-height=&quot;1010&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;figure id=&quot;og_1728711265016&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;kind &amp;ndash; Quick Start&quot; data-og-description=&quot;Quick Start This guide covers getting started with the kind command. If you are having problems please see the known issues guide. NOTE: kind does not require kubectl, but you will not be able to perform some of the examples in our docs without it. To inst&quot; data-og-host=&quot;kind.sigs.k8s.io&quot; data-og-source-url=&quot;https://kind.sigs.k8s.io/docs/user/quick-start/&quot; data-og-url=&quot;https://kind.sigs.k8s.io/docs/user/quick-start/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://kind.sigs.k8s.io/docs/user/quick-start/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://kind.sigs.k8s.io/docs/user/quick-start/&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;kind &amp;ndash; Quick Start&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Quick Start This guide covers getting started with the kind command. If you are having problems please see the known issues guide. NOTE: kind does not require kubectl, but you will not be able to perform some of the examples in our docs without it. To inst&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;kind.sigs.k8s.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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Step 2. Grafana 설치하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Trace Metrics을 시각화 하여 볼 수 있도록 공식 문서를 참고하여 Helm을 통해 Grafana를 설치합니다.&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;먼저 Helm 설치가 안되어 있다면, Helm을 설치합니다.&lt;/p&gt;
&lt;figure id=&quot;og_1728711598335&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;Installing Helm&quot; data-og-description=&quot;Learn how to install and get running with Helm.&quot; data-og-host=&quot;helm.sh&quot; data-og-source-url=&quot;https://helm.sh/docs/intro/install/&quot; data-og-url=&quot;https://helm.sh/docs/intro/install/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bbbUCp/hyXhJTdCTL/2gqvZJkjgklII4Zk7kWVPk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://helm.sh/docs/intro/install/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://helm.sh/docs/intro/install/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bbbUCp/hyXhJTdCTL/2gqvZJkjgklII4Zk7kWVPk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&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;Installing Helm&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Learn how to install and get running with Helm.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;helm.sh&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 다음 아래 명령을 통해 Grafana repo를 등록합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1728711647675&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;helm repo add grafana https://grafana.github.io/helm-charts
helm repo update&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;Grafana 컴포넌트를 설치할 네임스페이스를 생성하고, Grafana 설치를 진행합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1728711786777&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl create namespace monitoring
helm install my-grafana grafana/grafana --namespace monitoring&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;설치가 정상적으로 완료되었는지 확인합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1674&quot; data-origin-height=&quot;306&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/B1nUM/btsJ3LRMKMd/PQ9gHCYJtv2TLlBQrPShN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/B1nUM/btsJ3LRMKMd/PQ9gHCYJtv2TLlBQrPShN1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/B1nUM/btsJ3LRMKMd/PQ9gHCYJtv2TLlBQrPShN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FB1nUM%2FbtsJ3LRMKMd%2FPQ9gHCYJtv2TLlBQrPShN1%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;1674&quot; height=&quot;306&quot; data-origin-width=&quot;1674&quot; data-origin-height=&quot;306&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;size16&quot;&gt;관리자 비밀번호를 확인하기 위해 secret 데이터를 조회합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1728711904639&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl get secret --namespace monitoring my-grafana -o jsonpath=&quot;{.data.admin-password}&quot; | base64 --decode ; echo&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;새로운 터미널을 띄우고 `kubectl port-forward` 명령을 사용하여 Grafana 대시보드에 접근할 수 있도록 합니다. 호스트 포트에 접근하여 Grafana에 접근합니다. 이 때 로그인 ID는 `admin` 이고, 비밀번호는 위에서 확인한 비밀번호를 입력합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1728712040587&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl port-forward -n monitoring services/my-grafana 30080:80&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2598&quot; data-origin-height=&quot;1562&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cy0b1X/btsJ3Qlohok/ipJS3v1LciKObNiiEKoHd0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cy0b1X/btsJ3Qlohok/ipJS3v1LciKObNiiEKoHd0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cy0b1X/btsJ3Qlohok/ipJS3v1LciKObNiiEKoHd0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcy0b1X%2FbtsJ3Qlohok%2FipJS3v1LciKObNiiEKoHd0%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;2598&quot; height=&quot;1562&quot; data-origin-width=&quot;2598&quot; data-origin-height=&quot;1562&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;h3 data-ke-size=&quot;size23&quot;&gt;Step 3. Tempo 설치하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Trace 메트릭을 받고, 저장, 관리할 수 있도록 Tempo를 설치합니다. Tempo는 Grafana와 같은 Helm repo를 사용하기 때문에 윗 단계에서 repo add를 진행하였다면 바로 설치할 수 있습니다.&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;먼저 `vi values.yaml`을 통해 Tempo 설치에 사용될 Helm value 파일을 생성합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1728714043450&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;traces:
  otlp:
    http:
      enabled: true
      receiverConfig: {}
    grpc:
      enabled: true
      receiverConfig: {}
global_overrides:
  metrics_generator_processors:
  - service-graphs&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;아래 명령어로 Tempo를 설치하기 위한 네임스페이스를 생성 및 설치를 진행합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1728714075606&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl create namespace tempo
helm -n tempo install tempo grafana/tempo-distributed -f values.yaml&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;설치가 정상적으로 완료되었는지 확인합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;1104&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cqBCyj/btsJ4LpQEzZ/JEI4SJGAtljG9MDjEb9sj0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cqBCyj/btsJ4LpQEzZ/JEI4SJGAtljG9MDjEb9sj0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cqBCyj/btsJ4LpQEzZ/JEI4SJGAtljG9MDjEb9sj0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcqBCyj%2FbtsJ4LpQEzZ%2FJEI4SJGAtljG9MDjEb9sj0%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;3024&quot; height=&quot;1104&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;1104&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;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;Step 4. Opentelemetry Collector 설치 및 CRD(Auto-Instrument) 구성하기&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Otel Operator 설치 및 Otel Collector 설치하기&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Open Telemetry Collector의 경우 Helm 설치와 Operator를 통한 설치가 가능합니다. Helm을 통한 구성이 무조건 안되는 것인지는 모르겠으나 저의 경우 Helm을 통해 구성시 실패하였고, Operator를 통해 구성 시 성공하였기에 Operator를 통한 구성으로 내용을 정리하겠습니다.&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;먼저 Otel-Opertaor 설치 시 Cert-manager가 선제적으로 설치되어 있어야 하기에 cert-manager를 설치해 줍니다.&lt;/p&gt;
&lt;pre id=&quot;code_1728714380142&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.16.1/cert-manager.yaml&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;다음으로, Otel-Operator를 설치 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1728714416343&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl apply -f https://github.com/open-telemetry/opentelemetry-operator/releases/latest/download/opentelemetry-operator.yaml&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;설치가 성공적으로 완료되면 Otel CRD도 설치됩니다. 따라서 아래와 같이 `kind: OpenTelemetryCollector`인 리소스도 쿠버네티스 환경에 설치할 수 있게 됩니다. 아래 파일을 생성하고 `kubectl apply -f &amp;lt;filename.yaml&amp;gt;`을 통해 Opentelemetry Collector를 설치합니다. 저는 otel.yaml 이라는 이름으로 생성하였습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1728715090193&quot; class=&quot;less&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;apiVersion: opentelemetry.io/v1alpha1
kind: OpenTelemetryCollector
metadata:
  name: collector
  namespace: otel-trace
spec:
  config: |
    receivers:
      otlp:
        protocols:
          grpc:
            endpoint: 0.0.0.0:4317
          http:
            endpoint: 0.0.0.0:4318
    processors:
      memory_limiter:
        check_interval: 1s
        limit_percentage: 75
        spike_limit_percentage: 15
      batch:
        send_batch_size: 10000
        timeout: 10s
    exporters:
      otlphttp/tempo:
        endpoint: http://tempo-distributor.tempo.svc.cluster.local:4318
    service:
      pipelines:
        traces:
          receivers: [otlp]
          processors: [memory_limiter, batch]
          exporters: [otlphttp/tempo]&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;위 Otel Collector Config를 해석 해보겠습니다. pipeline쪽을 보시면 traces 메트릭에 대해 recivers가 otlp로 구성되어 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상단의 `config.receivers.otlp.protocols` 부분에 4317, 4318 포트로 OTLP를 리슨하는 것을 의미합니다. 아래 단계에서 .Net Application 구성 중 Trace 메트릭을 Otel Collector의 4317 혹은 4318 포트로 전송하면 될 것 입니다.&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;다음으로 processors가 있습니다. 수집된 데이터를 가공하는 단계 입니다. 마지막으로 exporters가 있습니다. 수집, 가공한 데이터를 tempo로 송신하게 됩니다.&amp;nbsp;&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;이로써 유추할 수 있는 Trace 데이터의 흐름은 .Net App -&amp;gt; Otel-Collector -&amp;gt; Tempo -&amp;gt; Grafana를 통한 Trace 데이터 시각화 일 것 입니다.&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;위 YAML 파일을 작성하였다면 Otel Collector 설치를 위한 네임스페이스 생성 및 Collector 설치를 진행합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1728717146397&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl create namespace otel-trace
kubectl apply -f otel.yaml&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;설치가 잘 되었는지 확인합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2344&quot; data-origin-height=&quot;404&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cSMAs0/btsJ4RjeFA2/fcg9E2DrHvecozOkCW64HK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cSMAs0/btsJ4RjeFA2/fcg9E2DrHvecozOkCW64HK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cSMAs0/btsJ4RjeFA2/fcg9E2DrHvecozOkCW64HK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcSMAs0%2FbtsJ4RjeFA2%2Ffcg9E2DrHvecozOkCW64HK%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;2344&quot; height=&quot;404&quot; data-origin-width=&quot;2344&quot; data-origin-height=&quot;404&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;h4 data-ke-size=&quot;size20&quot;&gt;Auto-Instrument 구성하기&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 Auto-Instrument에 대해 간략히 설명하겠습니다. Traces 메트릭은 Application의 상태 혹은 성능과 관련된 메트릭 입니다. 따라서 Trace 메트릭을 수집하기 위해서는 아래의 간단한 예시처럼 소스 코드에 Otel SDK를 적용하여 Trace 메트릭의 생성에 대해 정의해야 합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1240&quot; data-origin-height=&quot;1214&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c0iFpG/btsJ4qTNV4s/cUkKmEyGh7V1n174758NAk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c0iFpG/btsJ4qTNV4s/cUkKmEyGh7V1n174758NAk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c0iFpG/btsJ4qTNV4s/cUkKmEyGh7V1n174758NAk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc0iFpG%2FbtsJ4qTNV4s%2FcUkKmEyGh7V1n174758NAk%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;1240&quot; height=&quot;1214&quot; data-origin-width=&quot;1240&quot; data-origin-height=&quot;1214&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;size16&quot;&gt;반면 Auto-Instrument를 사용하면, 기존 Application의 코드 수정 없이 Traces와 관련된 메트릭을 수집할 수 있습니다.(정확히는 metrics, logs, traces 모든 메트릭에 대해 수집 가능합니다.)&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Datadog에서는 별도의 Agent 설치를 통해 코드 수정 없이 APM 메트릭을 수집합니다. 쿠버네티스 환경에서의 Opentelemetry는 Instrument라는 리소스를 통해 메트릭을 수집하게 됩니다.&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;윗 단계에서 Opentelemetry Operator를 설치하며 Instrument를 배포할 수 있습니다. 그럼 아래의 YAML파일을 생성하고, Instrument 리소스 배포를 진행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1728719580501&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
  name: dotnet-instrumentation
spec:
  exporter:
    endpoint: http://collector-collector.otel-trace.svc.cluster.local:4318
  propagators:
    - tracecontext
    - baggage
  sampler:
    type: parentbased_traceidratio
    argument: '1'
  dotnet:
    env:
    - name: OTEL_DOTNET_AUTO_TRACES_INSTRUMENTATION_ENABLED
      value: &quot;true&quot;
    - name: OTEL_DOTNET_AUTO_METRICS_INSTRUMENTATION_ENABLED
      value: &quot;false&quot;
    - name: OTEL_DOTNET_AUTO_LOGS_INSTRUMENTATION_ENABLED
      value: &quot;false&quot;&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;위 config를 살펴 보겠습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;spec.exporter : Instrument에서 수집한 메트릭을 전송할 Otel Collector의 주소입니다. 이전 단계에서 생성한 Otel-Collector의 서비스 주소를 입력하였습니다.&lt;/li&gt;
&lt;li&gt;spec.propagators: Trace ID의 Context를 관리하기 위해 설정합니다. 만약 여러 서비스를 호출하는 MSA 구조인 Application이 존재한다면 API GW -&amp;gt; Backend -&amp;gt; DB 간의 Trace 추적을 해야할 것입니다. 이 옵션을 활성화 함으로써 1개의 요청에 대한 서비스 간 흐름을 1개의 Trace ID로 파악할 수 있습니다.&lt;/li&gt;
&lt;li&gt;spec.sampler: Trace 추적을 필터링 합니다. 현재 argument는 1(100%)로 모든 요청에 대한 Trace를 기록하게 됩니다.&lt;/li&gt;
&lt;li&gt;spec.dotnet.env: 메트릭 수집에 대한 옵션을 제공합니다. 현재는 Trace 메트릭만 수집하게 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 Instrument를 배포하고, 리소스가 잘 배포되었는지 확인합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1728720433271&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 위 instrument yaml을 생성
kubectl apply -f instrument.yaml
# 리소스 배포 확인
kubectl get instrumentations.opentelemetry.io&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3006&quot; data-origin-height=&quot;152&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DLjSM/btsJ3NISEgq/1HgkPspSq8kHn6GcrgfOV1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DLjSM/btsJ3NISEgq/1HgkPspSq8kHn6GcrgfOV1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DLjSM/btsJ3NISEgq/1HgkPspSq8kHn6GcrgfOV1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDLjSM%2FbtsJ3NISEgq%2F1HgkPspSq8kHn6GcrgfOV1%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;3006&quot; height=&quot;152&quot; data-origin-width=&quot;3006&quot; data-origin-height=&quot;152&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;h3 data-ke-size=&quot;size23&quot;&gt;Step 5. .Net Core App 배포하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글의 핵심(?)인 .Net Core Application을 배포합니다. 샘플 코드는 Opentelemetry의 문서를 참고 하였으며 핵심 로직은 아래 코드를 참고 합니다.&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;/rolldice를 호출하면 1~6 의 숫자 중 한 개의 숫자를 리턴하는 샘플 코드입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1728720892660&quot; class=&quot;vbnet&quot; data-ke-language=&quot;vbnet&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;using System.Globalization;

using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

string HandleRollDice([FromServices]ILogger&amp;lt;Program&amp;gt; logger, string? player)
{
    var result = RollDice();

    if (string.IsNullOrEmpty(player))
    {
        logger.LogInformation(&quot;Anonymous player is rolling the dice: {result}&quot;, result);
    }
    else
    {
        logger.LogInformation(&quot;{player} is rolling the dice: {result}&quot;, player, result);
    }

    return result.ToString(CultureInfo.InvariantCulture);
}

int RollDice()
{
    return Random.Shared.Next(1, 7);
}

app.MapGet(&quot;/rolldice/{player?}&quot;, HandleRollDice);

app.Run();&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;위 .Net Core App을 컨테이너 이미지화 하였으며, 아래의 Yaml을 배포하여 deployment 리소스를 배포합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1728721372296&quot; class=&quot;vbnet&quot; data-ke-language=&quot;vbnet&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: myapp
  name: myapp-deployment
  namespace: app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      annotations:
        instrumentation.opentelemetry.io/inject-dotnet: &quot;default/dotnet-instrumentation&quot;
      labels:
        app: myapp
    spec:
      containers:
      - image: kimhj4270/rolldice:0.1
        name: myapp
        ports:
        - containerPort: 80
          protocol: TCP&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;배포 후 리소스가 잘 배포되었는지 확인합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1728721636645&quot; class=&quot;vbnet&quot; data-ke-language=&quot;vbnet&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl apply -f app.yaml
kubectl get pod -n app&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1498&quot; data-origin-height=&quot;152&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dAsC5m/btsJ20hYGyu/EnMr0TmDiqBvFXT1lZ9uNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dAsC5m/btsJ20hYGyu/EnMr0TmDiqBvFXT1lZ9uNK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dAsC5m/btsJ20hYGyu/EnMr0TmDiqBvFXT1lZ9uNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdAsC5m%2FbtsJ20hYGyu%2FEnMr0TmDiqBvFXT1lZ9uNK%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;1498&quot; height=&quot;152&quot; data-origin-width=&quot;1498&quot; data-origin-height=&quot;152&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;h3 data-ke-size=&quot;size23&quot;&gt;Step 6. Grafana에 Tempo 데이터 연결 및 Trace 데이터 조회하기&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Tempo Datasource 추가하기&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 Grafana의 &amp;nbsp;Connections &amp;gt; Data sources &amp;gt; Add new Data source에 접근합니다. `Tempo`를 검색하고 클릭합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1090&quot; data-origin-height=&quot;512&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/do7zIa/btsJ4ooaB3E/gLSZ09LnGPoftwX9g4KkFk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/do7zIa/btsJ4ooaB3E/gLSZ09LnGPoftwX9g4KkFk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/do7zIa/btsJ4ooaB3E/gLSZ09LnGPoftwX9g4KkFk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdo7zIa%2FbtsJ4ooaB3E%2FgLSZ09LnGPoftwX9g4KkFk%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;1090&quot; height=&quot;512&quot; data-origin-width=&quot;1090&quot; data-origin-height=&quot;512&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;size16&quot;&gt;Connection URL에 `&lt;a href=&quot;http://tempo-query-frontend-discovery.tempo.svc.cluster.local:3100/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;http://tempo-query-frontend-discovery.tempo.svc.cluster.local:3100/&lt;/a&gt;`를 입력합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1176&quot; data-origin-height=&quot;220&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FF7E8/btsJ3juMZf2/gZzHYse00kQfdQ1jDpWqek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FF7E8/btsJ3juMZf2/gZzHYse00kQfdQ1jDpWqek/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FF7E8/btsJ3juMZf2/gZzHYse00kQfdQ1jDpWqek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFF7E8%2FbtsJ3juMZf2%2FgZzHYse00kQfdQ1jDpWqek%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;1176&quot; height=&quot;220&quot; data-origin-width=&quot;1176&quot; data-origin-height=&quot;220&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;size16&quot;&gt;하단의 [Save &amp;amp; Test]를 클릭합니다. 성공적으로 데이터가 연결 됐는지 확인합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1514&quot; data-origin-height=&quot;476&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nsDf5/btsJ20Wyn9V/mD6tmnnQCwc2kupez4IW60/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nsDf5/btsJ20Wyn9V/mD6tmnnQCwc2kupez4IW60/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nsDf5/btsJ20Wyn9V/mD6tmnnQCwc2kupez4IW60/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnsDf5%2FbtsJ20Wyn9V%2FmD6tmnnQCwc2kupez4IW60%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;1514&quot; height=&quot;476&quot; data-origin-width=&quot;1514&quot; data-origin-height=&quot;476&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;h4 data-ke-size=&quot;size20&quot;&gt;Trace 데이터 조회하기&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Trace 데이터를 조회하려면, Trace 데이터를 생성해야 합니다. 따라서 아래의 절차에 따라 Application에 요청을 보내 Trace 메트릭을 발생 시킵니다.&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;먼저 새로운 터미널에서 `kubectl port-forward` 명령으로 로컬호스트에서 App 파드로 요청할 수 있는 환경을 만들어 줍니다.&lt;/p&gt;
&lt;pre id=&quot;code_1728722160057&quot; class=&quot;vbnet&quot; data-ke-language=&quot;vbnet&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl port-forward -n app pods/myapp-deployment-d7bd896fd-t6gsk 30081:80&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;다음으로 `curl localhost/rolldice` 명령으로 App 파드에 http 요청을 보냅니다. 사진과 같이 1~6 사일의 랜덤 숫자를 리턴 받아야 합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1466&quot; data-origin-height=&quot;106&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/19Ybo/btsJ29Tx4J4/gCDpcurvxNCwDVQhkQ08fk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/19Ybo/btsJ29Tx4J4/gCDpcurvxNCwDVQhkQ08fk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/19Ybo/btsJ29Tx4J4/gCDpcurvxNCwDVQhkQ08fk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F19Ybo%2FbtsJ29Tx4J4%2FgCDpcurvxNCwDVQhkQ08fk%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;1466&quot; height=&quot;106&quot; data-origin-width=&quot;1466&quot; data-origin-height=&quot;106&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;size16&quot;&gt;Trace 메트릭을 발생 시켰으니 Grafana에서 확인 합니다. &lt;span style=&quot;color: #000000; text-align: center;&quot;&gt;Explore&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: center;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: center;&quot;&gt;메뉴에&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: center;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: center;&quot;&gt;접근하고&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: center;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: center;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: center;&quot;&gt;Data&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: center;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: center;&quot;&gt;Source&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: center;&quot;&gt;를&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: center;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: center;&quot;&gt;Tempo&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: center;&quot;&gt;로&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: center;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: center;&quot;&gt;지정합니다. Query type을 Search로 변경하면 하위에 Trace ID를 확인할 수 있습니다. Trace ID를 클릭합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2570&quot; data-origin-height=&quot;1200&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8Zcxa/btsJ31GSBut/B4dhZFoKNBp9sLDhmbF1M1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8Zcxa/btsJ31GSBut/B4dhZFoKNBp9sLDhmbF1M1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8Zcxa/btsJ31GSBut/B4dhZFoKNBp9sLDhmbF1M1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8Zcxa%2FbtsJ31GSBut%2FB4dhZFoKNBp9sLDhmbF1M1%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;2570&quot; height=&quot;1200&quot; data-origin-width=&quot;2570&quot; data-origin-height=&quot;1200&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;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: center;&quot;&gt;Trace 메트릭을 아래 사진처럼 확인할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1712&quot; data-origin-height=&quot;1162&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TE3xz/btsJ3QFH6Ll/t1lnaFL3Cls0Xv8D4a72ik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TE3xz/btsJ3QFH6Ll/t1lnaFL3Cls0Xv8D4a72ik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TE3xz/btsJ3QFH6Ll/t1lnaFL3Cls0Xv8D4a72ik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTE3xz%2FbtsJ3QFH6Ll%2Ft1lnaFL3Cls0Xv8D4a72ik%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;1712&quot; height=&quot;1162&quot; data-origin-width=&quot;1712&quot; data-origin-height=&quot;1162&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;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;이번 글에서는 Otel과 Tempo를 사용한 Trace 메트릭 수집 과정을 살펴 보았습니다. 사실 Application의 성능 관측을 위해선 Trace 메트릭 뿐만 아니라, Metrics, Logs 메트릭도 수집하고, 대시보드화 해야 할 것입니다. Trace는 단지 최초 요청으로 부터의 서비스 호출 흐름과 시간, 실패 여부만 파악할 수 있기 때문이죠.&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;Metrics을 통해 HTTP 요청이 초당 얼마나 들어오는지, 1 req당 응답 시간이 얼마나 걸리는지 확인할 수 있으며, Logs를 통해 오류가 발생한 요청의 TraceID를 검색하여 Error Logs도 손쉽게 확인해 볼 수 있을것입니다. (아래는 PoC를 완료한 샘플 대시보드 입니다. 물론 공개된 대시보드를 불러와, 일부 수정해서 사용했습니다.)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1600&quot; data-origin-height=&quot;784&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bij0eG/btsJ3FYF3gt/u4wu5stCE2be9cxtmZ2II1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bij0eG/btsJ3FYF3gt/u4wu5stCE2be9cxtmZ2II1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bij0eG/btsJ3FYF3gt/u4wu5stCE2be9cxtmZ2II1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbij0eG%2FbtsJ3FYF3gt%2Fu4wu5stCE2be9cxtmZ2II1%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;1850&quot; height=&quot;907&quot; data-origin-width=&quot;1600&quot; data-origin-height=&quot;784&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;size16&quot;&gt;여러분도 이 과정을 참고하여 Metrics과 Logs를 수집하고 대시보드화 하는데 도움이 되었으면 합니다.&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>클라우드</category>
      <category>grafana</category>
      <category>kubernetes</category>
      <category>observability</category>
      <category>TEMPO</category>
      <category>trace</category>
      <category>tracing</category>
      <author>junkmm</author>
      <guid isPermaLink="true">https://junkmm.tistory.com/46</guid>
      <comments>https://junkmm.tistory.com/46#entry46comment</comments>
      <pubDate>Sat, 12 Oct 2024 17:46:51 +0900</pubDate>
    </item>
    <item>
      <title>[cks][killershell] Auditing Enable Audit Logging 실습</title>
      <link>https://junkmm.tistory.com/44</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Configure the Apiserver for Audit Logging.&lt;br /&gt;The log path should be /etc/kubernetes/audit-logs/audit.log on the host and inside the container.&lt;br /&gt;The existing Audit Policy to use is at /etc/kubernetes/audit-policy/policy.yaml . The path should be the same on the host and inside the container.&lt;br /&gt;&lt;br /&gt;Set argument --audit-log-maxsize=7&lt;br /&gt;Set&amp;nbsp;argument&amp;nbsp;--audit-log-maxbackup=2&lt;br /&gt;---&lt;br /&gt;감사 로깅을 위해 Apiserver를 구성합니다.&lt;br /&gt;로그 경로는 호스트 및 컨테이너 내부의 /etc/kubernetes/audit-logs/audit.log여야 합니다.&lt;br /&gt;사용할&amp;nbsp;기존&amp;nbsp;감사&amp;nbsp;정책은&amp;nbsp;/etc/kubernetes/audit-policy/policy.yaml&amp;nbsp;에&amp;nbsp;있습니다.&amp;nbsp;경로는&amp;nbsp;호스트와&amp;nbsp;컨테이너&amp;nbsp;내부에서&amp;nbsp;동일해야&amp;nbsp;합니다.&lt;br /&gt;&lt;br /&gt;인수 설정 --audit-log-maxsize=7&lt;br /&gt;인수&amp;nbsp;설정&amp;nbsp;--audit-log-maxbackup=2&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&gt; &lt;/span&gt;&amp;nbsp;문제 분석하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;kube-apiserver에&amp;nbsp;audit&amp;nbsp;log를&amp;nbsp;활성화&amp;nbsp;하는&amp;nbsp;문제입니다.&amp;nbsp;api-server&amp;nbsp;manifest에&amp;nbsp;arg&amp;nbsp;값을&amp;nbsp;조절하여&amp;nbsp;감사&amp;nbsp;로그를&amp;nbsp;활성화&amp;nbsp;하고,&amp;nbsp;HostPath&amp;nbsp;볼륨을&amp;nbsp;마운트&amp;nbsp;시켜&amp;nbsp;노드의&amp;nbsp;특정&amp;nbsp;폴더에서&amp;nbsp;감사로그를&amp;nbsp;확인해볼&amp;nbsp;수&amp;nbsp;있습니다.&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;&lt;span&gt; &lt;/span&gt; Step 1. 노드에 audit log 저장할 디렉터리 생성하기&lt;/h3&gt;
&lt;pre id=&quot;code_1722419628331&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;mkdir /etc/kubernetes/audit-log&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; Step&amp;nbsp;2.&amp;nbsp;kube-apiserver&amp;nbsp;manifest&amp;nbsp;백업하기&lt;/span&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1722419663388&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cp /etc/kubernetes/manifests/kube-apiserver.yaml ~/kube-apiserver.yaml&lt;/code&gt;&lt;/pre&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;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt; Step&amp;nbsp;3.&amp;nbsp;kube-apiserver.yaml&amp;nbsp;수정하기&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1722419697385&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;spec:
  containers:
  - command:
    - kube-apiserver
... 중략
    - --audit-policy-file=/etc/kubernetes/audit-policy/policy.yaml # 정책이 정의된 파일
    - --audit-log-path=/etc/kubernetes/audit-logs/audit.log # 로그 저장 경로 정의, arg 값이 없으면 audit log 비활성화와 같은 의미
    - --audit-log-maxsize=7 # 오래된 감사 로그 파일을 보관할 최대 일수를 정의
    - --audit-log-maxbackup=2 # 보관할 감사 로그 파일의 최대 수를 정의
... 중략
    volumeMounts:
    - mountPath: /etc/kubernetes/audit-policy/policy.yaml
      name: audit
      readOnly: true
    - mountPath: /etc/kubernetes/audit-logs
      name: audit-log
      readOnly: false
... 중략
  volumes:
  - name: audit
    hostPath:
      path: /etc/kubernetes/audit-policy/policy.yaml
      type: File
  - name: audit-log
    hostPath:
      path: /etc/kubernetes/audit-logs
      type: DirectoryOrCreate&lt;/code&gt;&lt;/pre&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;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt; Step&amp;nbsp;4.&amp;nbsp;Audit&amp;nbsp;Log&amp;nbsp;생성되는지&amp;nbsp;확인하기&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1722419837578&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; cat /etc/kubernetes/audit-logs/audit.log&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;767&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bGRYwB/btsIRZxaMpH/U6kvCUref43OXLOUgNxsi1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bGRYwB/btsIRZxaMpH/U6kvCUref43OXLOUgNxsi1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bGRYwB/btsIRZxaMpH/U6kvCUref43OXLOUgNxsi1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbGRYwB%2FbtsIRZxaMpH%2FU6kvCUref43OXLOUgNxsi1%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;2000&quot; height=&quot;767&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;767&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;size16&quot;&gt;Json Viewer로 확인하면 잘 식별 됨!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1852&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cFkMRb/btsISe8G9Gx/O8PPgaKTOjsdDJYIqx62Uk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cFkMRb/btsISe8G9Gx/O8PPgaKTOjsdDJYIqx62Uk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cFkMRb/btsISe8G9Gx/O8PPgaKTOjsdDJYIqx62Uk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcFkMRb%2FbtsISe8G9Gx%2FO8PPgaKTOjsdDJYIqx62Uk%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;2000&quot; height=&quot;1852&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1852&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;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1722419907907&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;감사(auditing)&quot; data-og-description=&quot;쿠버네티스 감사(auditing) 는 클러스터의 작업 순서를 문서화하는 보안 관련 시간별 레코드 세트를 제공한다. 클러스터는 사용자, 쿠버네티스 API를 사용하는 애플리케이션 및 컨트롤 플레인 자체&quot; data-og-host=&quot;kubernetes.io&quot; data-og-source-url=&quot;https://kubernetes.io/ko/docs/tasks/debug/debug-cluster/audit/#%EA%B0%90%EC%82%AC-%EC%A0%95%EC%B1%85&quot; data-og-url=&quot;https://kubernetes.io/ko/docs/tasks/debug/debug-cluster/audit/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/RhJ6g/hyWGWNC56y/r2dnBkbi1cyJEKjoSnEIx0/img.png?width=1727&amp;amp;height=373&amp;amp;face=0_0_1727_373&quot;&gt;&lt;a href=&quot;https://kubernetes.io/ko/docs/tasks/debug/debug-cluster/audit/#%EA%B0%90%EC%82%AC-%EC%A0%95%EC%B1%85&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://kubernetes.io/ko/docs/tasks/debug/debug-cluster/audit/#%EA%B0%90%EC%82%AC-%EC%A0%95%EC%B1%85&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/RhJ6g/hyWGWNC56y/r2dnBkbi1cyJEKjoSnEIx0/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;감사(auditing)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;쿠버네티스 감사(auditing) 는 클러스터의 작업 순서를 문서화하는 보안 관련 시간별 레코드 세트를 제공한다. 클러스터는 사용자, 쿠버네티스 API를 사용하는 애플리케이션 및 컨트롤 플레인 자체&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>클라우드</category>
      <category>cks</category>
      <author>junkmm</author>
      <guid isPermaLink="true">https://junkmm.tistory.com/44</guid>
      <comments>https://junkmm.tistory.com/44#entry44comment</comments>
      <pubDate>Wed, 31 Jul 2024 18:58:47 +0900</pubDate>
    </item>
    <item>
      <title>[cks][killershell] NodeRestriction 실습</title>
      <link>https://junkmm.tistory.com/43</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The&amp;nbsp;Kubelet&amp;nbsp;on&amp;nbsp;node01&amp;nbsp;shouldn't&amp;nbsp;be&amp;nbsp;able&amp;nbsp;to&amp;nbsp;set&amp;nbsp;Node&amp;nbsp;labels&lt;br /&gt;&lt;br /&gt;starting&amp;nbsp;with&amp;nbsp;node-restriction.kubernetes.io/*&lt;br /&gt;on&amp;nbsp;other&amp;nbsp;Nodes&amp;nbsp;than&amp;nbsp;itself&lt;br /&gt;Verify this is not restricted atm by performing the following actions as the Kubelet from node01&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; &amp;nbsp;분석하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;api-server의 구성 변경을 검증(제한)하는 admission 적용하는 방법에 대한 실습. node01과 controlplane 총 2대의 워커노드가 있고, node01에서는 controlplane의 노드 라벨을 추가할 수 없도록 하기&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; &amp;nbsp;Step&amp;nbsp;1.&amp;nbsp;[admission&amp;nbsp;적용&amp;nbsp;전]&amp;nbsp;node01에서&amp;nbsp;node&amp;nbsp;label&amp;nbsp;추가해보기&amp;nbsp;&amp;rarr;&amp;nbsp;잘&amp;nbsp;작동함&lt;/h3&gt;
&lt;pre id=&quot;code_1722333567798&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;controlplane $ ssh node01
Last login: Tue Jul 30 09:15:19 2024 from 10.244.6.54

node01 $ kubectl label node controlplane killercoda/one=123 # works but should be restricted
node/controlplane labeled

node01 $ kubectl label node node01 node-restriction.kubernetes.io/one=123 # works but should be restricted
node/node01 labeled&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;410&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vpVEt/btsIQodj2yZ/KLQ4bZDvS579ETxmU8eOxk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vpVEt/btsIQodj2yZ/KLQ4bZDvS579ETxmU8eOxk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vpVEt/btsIQodj2yZ/KLQ4bZDvS579ETxmU8eOxk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvpVEt%2FbtsIQodj2yZ%2FKLQ4bZDvS579ETxmU8eOxk%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;2000&quot; height=&quot;410&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;410&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;h3 data-ke-size=&quot;size23&quot;&gt; &amp;nbsp;Step&amp;nbsp;2.&amp;nbsp;매니페스트를&amp;nbsp;수정해서&amp;nbsp;static&amp;nbsp;pod(kube-apiserver)&amp;nbsp;장애&amp;nbsp;발생시키기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;아래 명령으로 kube-apiserver 편집, `spec.containers.command`에 `--enable-admission-plugins=NodeRestriction` 옵션 추가하기&lt;/p&gt;
&lt;pre id=&quot;code_1722333621587&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# controlplane 노드에서 실행
vi /etc/kubernetes/manifests/kube-apiserver.yaml

---

spec:
  containers:
  - command:
    - kube-apiserver
    - --advertise-address=172.30.1.2
... 중략 ...
    - --enable-admission-plugins=NodeRestriction&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;node01에 접속해서 라벨 수정 해보기 &amp;rarr; node01 외 다른 노드는 label 추가 안됨&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;312&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VPahg/btsIP7v609L/BInnDqkIIzuYUUqjptJkcK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VPahg/btsIP7v609L/BInnDqkIIzuYUUqjptJkcK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VPahg/btsIP7v609L/BInnDqkIIzuYUUqjptJkcK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVPahg%2FbtsIP7v609L%2FBInnDqkIIzuYUUqjptJkcK%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;2000&quot; height=&quot;312&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;312&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;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;아래 홈페이지를 가보면 api-server의 addmission을 사용해 여러가지 활동에 대한 제약을 줄 수 있음을 알 수 있습니다. 이번 실습에서 자용한 addmission은 `NodeRestriction`입니다. 설명 중 일부를 발췌 해보면 해당 옵션은 검증 작업을 수행하는 옵션이고, Node 및 Pod API 호출 시 요청자 kubelet이 설치된 노드에서만 수정을 허용하는 옵션임을 알 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Such kubelets will only be allowed to modify their own Node API object, and only modify Pod API objects that are bound to their node.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1722333732033&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;Admission Controllers Reference&quot; data-og-description=&quot;This page provides an overview of Admission Controllers. What are they? An admission controller is a piece of code that intercepts requests to the Kubernetes API server prior to persistence of the object, but after the request is authenticated and authoriz&quot; data-og-host=&quot;kubernetes.io&quot; data-og-source-url=&quot;https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#how-do-i-turn-on-an-admission-controller&quot; data-og-url=&quot;https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/gEwmZ/hyWGRkWrMO/6vuLvCJ12hNPiDXul2bLak/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/access-authn-authz/admission-controllers/#how-do-i-turn-on-an-admission-controller&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#how-do-i-turn-on-an-admission-controller&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/gEwmZ/hyWGRkWrMO/6vuLvCJ12hNPiDXul2bLak/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;Admission Controllers Reference&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;This page provides an overview of Admission Controllers. What are they? An admission controller is a piece of code that intercepts requests to the Kubernetes API server prior to persistence of the object, but after the request is authenticated and authoriz&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>클라우드</category>
      <category>cks</category>
      <author>junkmm</author>
      <guid isPermaLink="true">https://junkmm.tistory.com/43</guid>
      <comments>https://junkmm.tistory.com/43#entry43comment</comments>
      <pubDate>Tue, 30 Jul 2024 19:08:39 +0900</pubDate>
    </item>
    <item>
      <title>[cks][killershell] Apiserver Crash 실습</title>
      <link>https://junkmm.tistory.com/42</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The idea here is to misconfigure the Apiserver in different ways, then check possible log locations for errors.&lt;br /&gt;You should be very comfortable with situations where the Apiserver is not coming back up.&lt;br /&gt;Configure the Apiserver manifest with a new argument --this-is-very-wrong .&lt;br /&gt;Check if the Pod comes back up and what logs this causes.&lt;br /&gt;Fix&amp;nbsp;the&amp;nbsp;Apiserver&amp;nbsp;again.&lt;br /&gt;---&lt;br /&gt;(구글 번역)&lt;br /&gt;여기서의 아이디어는 Apiserver를 다양한 방식으로 잘못 구성한 다음 가능한 로그 위치에 오류가 있는지 확인하는 것입니다.&lt;br /&gt;Apiserver가 다시 작동하지 않는 상황이 매우 편안할 것입니다.&lt;br /&gt;새로운 인수 --this-is-very-wrong 으로 Apiserver 매니페스트를 구성합니다.&lt;br /&gt;Pod가 다시 작동하는지 확인하고 이로 인해 발생하는 로그를 확인하세요.&lt;br /&gt;Apiserver를&amp;nbsp;다시&amp;nbsp;수정하세요.&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&gt; &lt;/span&gt;&amp;nbsp;문제 분석하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;kube-apiserver의 매니페스트가 위치한 `/etc/kubernetes/manifests` 폴더에 `kube-apiserver.yaml` 파일을 백업한 뒤 일부러 고장시키고, 복구시키는 방법에 대한 방법 확인하기&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;&lt;span&gt; &lt;/span&gt;&amp;nbsp;Step 1. 매니페스트 백업하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;static pod를 생성하는 위치인 /etc/kubernetes/manifest 폴더 내 kube-apiserver.yaml 파일을 Home dir에 백업합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1722250684143&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cp /etc/kubernetes/manifests/kube-apiserver.yaml ~/kube-apiserver.orig&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;span&gt; &lt;/span&gt;&amp;nbsp;Step 2. 매니페스트를 수정해서 static pod(kube-apiserver) 장애 발생시키기&lt;/h3&gt;
&lt;pre id=&quot;code_1722250753701&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;vi /etc/kubernetes/manifests/kube-apiserver.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1511&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EO9qO/btsIPuE1rqg/aNw5Kj9DnPiEhwUmuQuAaK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EO9qO/btsIPuE1rqg/aNw5Kj9DnPiEhwUmuQuAaK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EO9qO/btsIPuE1rqg/aNw5Kj9DnPiEhwUmuQuAaK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEO9qO%2FbtsIPuE1rqg%2FaNw5Kj9DnPiEhwUmuQuAaK%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;2000&quot; height=&quot;1511&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1511&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;`spec.containers.command` 하위에 `--this-is-very-wrong` 이라는 오류를 발생시키는 인자값을 추가 입력한 뒤 저장합니다.&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;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;93&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cXMd4N/btsIRXrLlRU/2PBFjqSZF8R9E91uGD8R11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cXMd4N/btsIRXrLlRU/2PBFjqSZF8R9E91uGD8R11/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cXMd4N/btsIRXrLlRU/2PBFjqSZF8R9E91uGD8R11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcXMd4N%2FbtsIRXrLlRU%2F2PBFjqSZF8R9E91uGD8R11%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;2000&quot; height=&quot;93&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;93&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;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt; &lt;/span&gt;&amp;nbsp;Step 3. kube-apiserver 장애 시 로그 확인 방법&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;방법 1.&amp;nbsp; `/var/log/pods` 하위 로그 확인&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;98&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eaNyAX/btsIQwolmXK/gW2rFiwzZVKKQX8B5awtq0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eaNyAX/btsIQwolmXK/gW2rFiwzZVKKQX8B5awtq0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eaNyAX/btsIQwolmXK/gW2rFiwzZVKKQX8B5awtq0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeaNyAX%2FbtsIQwolmXK%2FgW2rFiwzZVKKQX8B5awtq0%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;2000&quot; height=&quot;98&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;98&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;방법 2.&amp;nbsp; `/var/log/containers` 하위 로그 확인&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;84&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjkpiP/btsIR0u8l8b/IM8OrpH7nL9ZKw2Pw8P1yk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjkpiP/btsIR0u8l8b/IM8OrpH7nL9ZKw2Pw8P1yk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjkpiP/btsIR0u8l8b/IM8OrpH7nL9ZKw2Pw8P1yk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjkpiP%2FbtsIR0u8l8b%2FIM8OrpH7nL9ZKw2Pw8P1yk%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;2000&quot; height=&quot;84&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;84&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;방법 3. `crictl ps -a&amp;nbsp;&amp;nbsp;+ crictl logs` 명령으로 확인&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;222&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cb2lIC/btsIPJ9Ozlv/ma0zLbA2KZNNtD6PxAhLj0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cb2lIC/btsIPJ9Ozlv/ma0zLbA2KZNNtD6PxAhLj0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cb2lIC/btsIPJ9Ozlv/ma0zLbA2KZNNtD6PxAhLj0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcb2lIC%2FbtsIPJ9Ozlv%2Fma0zLbA2KZNNtD6PxAhLj0%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;2000&quot; height=&quot;222&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;222&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;100&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UQcdm/btsIQHcepJd/D52TQn7IHeaY1vXLhrhTd1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UQcdm/btsIQHcepJd/D52TQn7IHeaY1vXLhrhTd1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UQcdm/btsIQHcepJd/D52TQn7IHeaY1vXLhrhTd1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUQcdm%2FbtsIQHcepJd%2FD52TQn7IHeaY1vXLhrhTd1%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;2000&quot; height=&quot;100&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;100&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;방법&amp;nbsp;4.&amp;nbsp;kubelet&amp;nbsp;logs&amp;nbsp;:&amp;nbsp;`/var/log/syslog`&amp;nbsp;or&amp;nbsp;`journalctl&amp;nbsp;-u&amp;nbsp;kubelet&amp;nbsp;|&amp;nbsp;tail&amp;nbsp;-5`&amp;nbsp;&amp;nbsp;&amp;nbsp;명령으로&amp;nbsp;확인&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;337&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lMeki/btsIPKHBiHJ/1V62FXvu3Jm4ASPECHS61k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lMeki/btsIPKHBiHJ/1V62FXvu3Jm4ASPECHS61k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lMeki/btsIPKHBiHJ/1V62FXvu3Jm4ASPECHS61k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlMeki%2FbtsIPKHBiHJ%2F1V62FXvu3Jm4ASPECHS61k%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;2000&quot; height=&quot;337&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;337&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;h2 data-ke-size=&quot;size26&quot;&gt; &amp;nbsp;정리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 kubectl get pod -A가 안된다면(apiserver가 응답을 못하는 경우), control-plane 노드에 접속해서 kubelet 데몬 상태를 확인 해본다. 그 후 로그를 확인해 봤을 때 6443 포트를 사용하는 kube-apiserver의 문제가 있음을 확인하고, /var/log/pods 혹은 crictl 명령을 사용해 api-server의 로그를 확인하고, 해당 로그 메시지에 맞춰 문제 해결을 진행하자!&lt;/p&gt;</description>
      <category>클라우드</category>
      <category>cks</category>
      <author>junkmm</author>
      <guid isPermaLink="true">https://junkmm.tistory.com/42</guid>
      <comments>https://junkmm.tistory.com/42#entry42comment</comments>
      <pubDate>Mon, 29 Jul 2024 20:03:38 +0900</pubDate>
    </item>
    <item>
      <title>[devocen 오픈랩] kubernetes 스터디 1주 - 컨테이너 실습</title>
      <link>https://junkmm.tistory.com/41</link>
      <description>&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;a href=&quot;https://devocean.sk.com/community/detail.do?ID=165736&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;devocean&lt;/a&gt; 오픈랩 Deep Dive Kubernetes 1주차 기록입니다.&lt;/blockquote&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;5/7(화) 오후 7시 을지로 삼화타워에서 &lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;Deep Dive Kubernetes 팀의 오프라인 미팅을 진행했습니다. 스터디 운영자님이신 안승규님 께서 컨테이너와 쿠버네티스에 대한 설명을 진행 해 주셨는데요, 초반 컨테이너에 대한 이론 설명과 간단한 실습 자료를 보여주셨는데 시간관계상 실습을 진행하지 못했어서, 직접 실습 해보며 내용을 정리해보고자 합니다.&lt;/span&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;Container&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Container의 구조&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;841&quot; data-origin-height=&quot;470&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdc0y8/btsHpwvtSc0/AewFgCro1IkqrSpotJqmPK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdc0y8/btsHpwvtSc0/AewFgCro1IkqrSpotJqmPK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdc0y8/btsHpwvtSc0/AewFgCro1IkqrSpotJqmPK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbdc0y8%2FbtsHpwvtSc0%2FAewFgCro1IkqrSpotJqmPK%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;841&quot; height=&quot;470&quot; data-origin-width=&quot;841&quot; data-origin-height=&quot;470&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;size16&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;Host O/S 기반에 Container Engine이 컨테이너의 구동을 관리합니다. 컨테이너 엔진은 CPU, RAM, Disk자원을 컨테이너에 할당 시켜주고, 각 컨테이너를 격리하여 프로세스를 구동시킵니다. 컨테이너 엔진은 Host OS 위에서 동작하기 때문에, 컨테이너의 커널 사양에 따라 구동시키지 못하는 경우가 발생할 수 있습니다.&lt;/span&gt;&lt;/p&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;872&quot; data-origin-height=&quot;403&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cEW9D2/btsHodqbZ6g/LKWNyP4IWCU8DnCd2Rppm0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cEW9D2/btsHodqbZ6g/LKWNyP4IWCU8DnCd2Rppm0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cEW9D2/btsHodqbZ6g/LKWNyP4IWCU8DnCd2Rppm0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcEW9D2%2FbtsHodqbZ6g%2FLKWNyP4IWCU8DnCd2Rppm0%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;872&quot; height=&quot;403&quot; data-origin-width=&quot;872&quot; data-origin-height=&quot;403&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;자원의 분배와 격리는 각 각 cgroup, namespace를 사용하여 구현합니다. 프로세스 단위로 격리시켜 컨테이너를 구동하기 때문에 컨테이너는 자신에 할당된 자원만큼만 사용할 수 있습니다. namespace에서 격리되는 자원의 정보는 다음과 같습니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;호스트 네임 : `uts`&lt;/li&gt;
&lt;li&gt;프로세스 ID : `pid`&lt;/li&gt;
&lt;li&gt;유저 : `user`&lt;/li&gt;
&lt;li&gt;네트워크 : `net`&lt;/li&gt;
&lt;li&gt;스토리지 : `mnt`&lt;/li&gt;
&lt;li&gt;프로세스간 통신 : `ipc`&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;실습 1. Container에 대한 기본개념 확인&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 init process인 pid 1번에 대한 네임스페이스 정보를 확인하는 명령어 입니다. init process도 네임스페이스를 가지고 있음을 확인해볼 수 있습니다. `echo $$`라는 명령을 실행시켜 `echo` 프로세스의 pid를 조회하고, 해당 pid의 네임스페이스를 확인해보면 init process와 동일한 네임스페이스를 사용중인 것을 확인해볼 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1715596964091&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# pid 1번에 대한 네임스페이스 조회
root@ip-172-31-37-95:~# lsns -p 1
        NS TYPE   NPROCS PID USER COMMAND
4026531834 time      105   1 root /sbin/init
4026531835 cgroup    105   1 root /sbin/init
4026531836 pid       105   1 root /sbin/init
4026531837 user      105   1 root /sbin/init
4026531838 uts        99   1 root /sbin/init
4026531839 ipc       105   1 root /sbin/init
4026531840 net       105   1 root /sbin/init
4026531841 mnt        96   1 root /sbin/init

# echo 명령어의 현재 pid 조회
root@ip-172-31-37-95:/proc# echo $$
1220

# echo 명령어 1220의 네임스페이스 조회
root@ip-172-31-37-95:/proc# lsns -p 1220
        NS TYPE   NPROCS PID USER COMMAND
4026531834 time      108   1 root /sbin/init
4026531835 cgroup    108   1 root /sbin/init
4026531836 pid       108   1 root /sbin/init
4026531837 user      108   1 root /sbin/init
4026531838 uts       102   1 root /sbin/init
4026531839 ipc       108   1 root /sbin/init
4026531840 net       108   1 root /sbin/init
4026531841 mnt        97   1 root /sbin/init&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;이번 실습으로 각 프로세스는 pid, user, uts 등 네임스페이스 단위로 자원을 할당받는 다는 점과, init process는 `/` 프로세스가 되어 OS단에서 실행되는 프로세스는 모두 init process와 동일한 네임스페이스를 사용한다는 점을 알 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;실습 2. namespace 생성 - uts&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는`unshare -u`라는 명령어로 namespace 중 uts를 격리하여 새로운 Child Process를 생성하는 실습입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;629&quot; data-origin-height=&quot;169&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cVXUfl/btsHpwI3Icq/i68K56raKn0kUclGjKyGk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cVXUfl/btsHpwI3Icq/i68K56raKn0kUclGjKyGk0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cVXUfl/btsHpwI3Icq/i68K56raKn0kUclGjKyGk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcVXUfl%2FbtsHpwI3Icq%2Fi68K56raKn0kUclGjKyGk0%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;629&quot; height=&quot;169&quot; data-origin-width=&quot;629&quot; data-origin-height=&quot;169&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1715597862945&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# pid 1220번 ps를 실행합니다.
root@ip-172-31-37-95:/proc# echo $$
1220

# unshare -u 명령으로 Child Bash Process를 생성합니다.
root@ip-172-31-37-95:/proc# unshare -u

# Child Bash에서 echo $$ 명령으로 ps를 생성합니다.
# 기존 1220 ps가 아닌 1304 ps가 생성됩니다.
root@ip-172-31-37-95:/proc# echo $$
1304

# lsns로 process의 네임스페이스를 비교합니다.
# Child Process인 1304번의 uts 네임스페이스만 달라진 걸 확인해볼 수 있습니다.
root@ip-172-31-37-95:/proc# lsns -p 1304
        NS TYPE   NPROCS   PID USER COMMAND
4026531834 time      107     1 root /sbin/init
4026531835 cgroup    107     1 root /sbin/init
4026531836 pid       107     1 root /sbin/init
4026531837 user      107     1 root /sbin/init
4026531839 ipc       107     1 root /sbin/init
4026531840 net       107     1 root /sbin/init
4026531841 mnt        98     1 root /sbin/init
4026532247 uts         2  1304 root -bash

root@ip-172-31-37-95:/proc# lsns -p 1220
        NS TYPE   NPROCS PID USER COMMAND
4026531834 time      107   1 root /sbin/init
4026531835 cgroup    107   1 root /sbin/init
4026531836 pid       107   1 root /sbin/init
4026531837 user      107   1 root /sbin/init
4026531838 uts        99   1 root /sbin/init
4026531839 ipc       107   1 root /sbin/init
4026531840 net       107   1 root /sbin/init
4026531841 mnt        98   1 root /sbin/init&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;위 실습으로 unshare는 네임스페이스 중 특정 자원을 격리시켜 Child Process를 생성할 수 있음을 확인 해 봤습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;실습 3. namespace 생성 - pid, mnt&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 pid, filesystem, mount 네임스페이스를 분리 생성하는 예시입니다. /root/sample_rootfs 라는 폴더를 생성하고, 해당 폴더에 `/bin`, `/lib`등 프로세스가 구동되기 위한 최소한의 파일시스템을 준비 합니다. 그리고 `unshare` 명령으로 mount를 격리시키고, 동시에 `chroot` 명령으로 격리된 프로세스의 파일시스템, 마운트 위치를 /root/sample_rootfs로 설정합니다. 그 후 proc을 /proc에 마운트 시켜 프로세스의 정보를 확인 해 봅니다.&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;먼저 /root/sample_rootfs를 생성하고 주요 directory를 복사합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1715599798701&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# root 로그인 상태에서 Home 디렉토리 이동 후 sample_rootfs 디렉토리를 생성합니다.
root@ip-172-31-37-95:~# cd
root@ip-172-31-37-95:~# mkdir sample_rootfs

# /bin, /lib, /var 등 주요 파일을 sample_rootfs에 복사합니다.
root@ip-172-31-37-95:~# cp -R /bin /root/sample_rootfs/
root@ip-172-31-37-95:~# cp -R /sbin /root/sample_rootfs/
root@ip-172-31-37-95:~# cp -R /lib /root/sample_rootfs/
root@ip-172-31-37-95:~# cp -R /lib64 /root/sample_rootfs/
root@ip-172-31-37-95:~# cp -R /etc /root/sample_rootfs/
root@ip-172-31-37-95:~# cp -R /usr /root/sample_rootfs/
root@ip-172-31-37-95:~# cp -R /var /root/sample_rootfs/&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;아래 명령으로 Process, Filesystem, Mount를 격리한 Child Process를 생성하고, Chroot로 격리된 파일시스템에 진입합니다. 그 후 프로세스 정보를 확인 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1715599988520&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;root@ip-172-31-37-95:~# unshare -p -f -m chroot /root/sample_rootfs

# pwd, ls 명령을 통해 chroot로 파일시스템, 마운트 격리가 잘 됐는지 확인합니다.
root@ip-172-31-37-95:/# pwd
/
root@ip-172-31-37-95:/# ls
bin  etc  lib  lib64  sbin  usr  var

# process 정보를 마운트 하기 위해 proc 폴더를 생성하고, proc 정보를 마운트 시킵니다.
root@ip-172-31-37-95:/# mkdir proc
root@ip-172-31-37-95:/# mount -t proc proc /proc

# lsns -1로 각 자원의 네임스페이스를 확인합니다.
root@ip-172-31-37-95:/# lsns -p 1
        NS TYPE   NPROCS PID USER COMMAND
4026531834 time        2   1 root /bin/bash -i
4026531835 cgroup      2   1 root /bin/bash -i
4026531837 user        2   1 root /bin/bash -i
4026531839 ipc         2   1 root /bin/bash -i
4026531840 net         2   1 root /bin/bash -i
4026532247 uts         2   1 root /bin/bash -i
4026532249 mnt         2   1 root /bin/bash -i
4026532250 pid         2   1 root /bin/bash -i

# ps -ef로 현재 구동중인 process 정보를 확인합니다.
root@ip-172-31-37-95:/# ps -ef
UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0 11:33 ?        00:00:00 /bin/bash -i
root          66       1  0 11:39 ?        00:00:00 ps -ef

# exit로 chroot를 빠져나온 뒤, Host OS의 process 정보를 확인 해봅니다.
root@ip-172-31-37-95:/proc# ps -ef
UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0 09:38 ?        00:00:04 /sbin/init
root           2       0  0 09:38 ?        00:00:00 [kthreadd]
root           3       2  0 09:38 ?        00:00:00 [pool_workqueue_release]
root           4       2  0 09:38 ?        00:00:00 [kworker/R-rcu_g]
...&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;이번 실습으로 unshare를 통한 프로세스의 네임스페이스 분리 방법과 process, filesystem 격리 시 구동중인 Host OS의 Process Namespace가 달라지게 되어 `ps -ef`명령을 했을 때 보여지는 정보가 상이했던 것을 확인할 수 있었고, 이를 통해 각 자원별 네임스페이스 분리는 결국 각 각의 프로세스의 격리를 의미한다는 것을 확인해 볼 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;정리&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1006&quot; data-origin-height=&quot;559&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dATK7X/btsHn5y5LJM/LK2lhrRktSR1zXYtmjQq20/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dATK7X/btsHn5y5LJM/LK2lhrRktSR1zXYtmjQq20/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dATK7X/btsHn5y5LJM/LK2lhrRktSR1zXYtmjQq20/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdATK7X%2FbtsHn5y5LJM%2FLK2lhrRktSR1zXYtmjQq20%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;1006&quot; height=&quot;559&quot; data-origin-width=&quot;1006&quot; data-origin-height=&quot;559&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;</description>
      <category>운영체제</category>
      <category>Container</category>
      <category>devocean</category>
      <author>junkmm</author>
      <guid isPermaLink="true">https://junkmm.tistory.com/41</guid>
      <comments>https://junkmm.tistory.com/41#entry41comment</comments>
      <pubDate>Mon, 13 May 2024 20:46:37 +0900</pubDate>
    </item>
    <item>
      <title>[EKS] IaC</title>
      <link>https://junkmm.tistory.com/40</link>
      <description>&lt;blockquote data-ke-style=&quot;style2&quot;&gt;이번 게시글은 가시다님의 AEWS [2기] 스터디 내용을 정리한 포스트 입니다.&lt;br /&gt;이번 게시글은 8 주차의 스터디 내용인 EKS IaC에 대해 살펴봅니다.&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Terraform&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테라폼은 하시코프사에서 공개한 IaC 도구이다. Terraform Provider는 AWS, GCP, Azure등 다양한 벤더에 대한 배포를 지원한다. 사용자는 테라폼 1개의 문법으로 다양한 프로바이더를 사용하여 여러 벤더사의 클라우드 리소스 배포를 관리할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1630&quot; data-origin-height=&quot;1418&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/l6dUZ/btsGZKBzd79/i2lD5c65mfGyfVvMwJKz6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/l6dUZ/btsGZKBzd79/i2lD5c65mfGyfVvMwJKz6K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/l6dUZ/btsGZKBzd79/i2lD5c65mfGyfVvMwJKz6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fl6dUZ%2FbtsGZKBzd79%2Fi2lD5c65mfGyfVvMwJKz6K%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;1630&quot; height=&quot;1418&quot; data-origin-width=&quot;1630&quot; data-origin-height=&quot;1418&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;h2 data-ke-size=&quot;size26&quot;&gt;실습환경 준비&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;macOS 기준으로 설명합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1714198449896&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# tfenv 설치
brew install tfenv

# 설치 가능 버전 리스트 확인
tfenv list-remote

# 테라폼 1.5.1 버전 설치
tfenv install 1.8.1

# 테라폼 1.5.1 버전 사용 설정 
tfenv use 1.8.1

# tfenv로 설치한 버전 확인
tfenv list

# 테라폼 버전 정보 확인
terraform version

# 자동완성
terraform -install-autocomplete
## 참고 .zshrc 에 아래 추가됨
cat ~/.zshrc
autoload -U +X bashcompinit &amp;amp;&amp;amp; bashcompinit
complete -o nospace -C /usr/local/bin/terraform terraform

#AWSCLI 설치
brew install awscli

#EKSCTL
brew install eksctl

#KUBECTL
brew install kubernetes-cli

#HELM
brew install helm&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;VSCode의 Extentions을 설치합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;621&quot; data-origin-height=&quot;261&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/byiKk4/btsGZyVuDSf/oYmdwCXMPZfbWnuPwd6NV1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/byiKk4/btsGZyVuDSf/oYmdwCXMPZfbWnuPwd6NV1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/byiKk4/btsGZyVuDSf/oYmdwCXMPZfbWnuPwd6NV1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbyiKk4%2FbtsGZyVuDSf%2FoYmdwCXMPZfbWnuPwd6NV1%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;621&quot; height=&quot;261&quot; data-origin-width=&quot;621&quot; data-origin-height=&quot;261&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;646&quot; data-origin-height=&quot;254&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dyj8uY/btsGZzfNKna/tfJ5AQRx7okkp4bEV4HBoK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dyj8uY/btsGZzfNKna/tfJ5AQRx7okkp4bEV4HBoK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dyj8uY/btsGZzfNKna/tfJ5AQRx7okkp4bEV4HBoK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdyj8uY%2FbtsGZzfNKna%2FtfJ5AQRx7okkp4bEV4HBoK%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;646&quot; height=&quot;254&quot; data-origin-width=&quot;646&quot; data-origin-height=&quot;254&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;size16&quot;&gt;`aws configure`를 구성한 뒤 아래 명령으로 default VPC가 존재하는지 확인합니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1714198998066&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;aws ec2 describe-vpcs --filter 'Name=isDefault,Values=true' | jq&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;772&quot; data-origin-height=&quot;510&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dlz7GY/btsGYLuFDMc/8f0wygHL3fgw6gLzQynwzk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dlz7GY/btsGYLuFDMc/8f0wygHL3fgw6gLzQynwzk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dlz7GY/btsGYLuFDMc/8f0wygHL3fgw6gLzQynwzk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdlz7GY%2FbtsGYLuFDMc%2F8f0wygHL3fgw6gLzQynwzk%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;772&quot; height=&quot;510&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;772&quot; data-origin-height=&quot;510&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;size16&quot;&gt;만약 기본 VPC가 없으면 아래 명령으로 생성해야 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1714199160669&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# default VPC를 생성
aws ec2 create-default-vpc

# default Subnet 생성
aws ec2 create-default-subnet --availability-zone ap-northeast-2a
aws ec2 create-default-subnet --availability-zone ap-northeast-2b
aws ec2 create-default-subnet --availability-zone ap-northeast-2c
aws ec2 create-default-subnet --availability-zone ap-northeast-2d&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;기본 환경을 준비합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1714202615855&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;mkdir learn-terraform
cd learn-terraform
touch main.tf&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;Amazon Linux 2 최신 ami id를 찾습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1714208401741&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#aws ec2 describe-images --owners self amazon
aws ec2 describe-images --owners self amazon --query 'Images[*].[ImageId]' --output text
aws ec2 describe-images --owners amazon --filters &quot;Name=name,Values=amzn2-ami-hvm-2.0.*-x86_64-gp2&quot; &quot;Name=state,Values=available&quot;
aws ec2 describe-images --owners amazon --filters &quot;Name=name,Values=amzn2-ami-hvm-2.0.*-x86_64-gp2&quot; &quot;Name=state,Values=available&quot; --query 'Images|sort_by(@, &amp;amp;CreationDate)[-1].[ImageId, Name]' --output text
ami-0217b147346e48e84	amzn2-ami-hvm-2.0.20240412.0-x86_64-gp2

aws ec2 describe-images --owners amazon --filters &quot;Name=name,Values=amzn2-ami-hvm-2.0.*-x86_64-gp2&quot; &quot;Name=state,Values=available&quot; --query 'Images|sort_by(@, &amp;amp;CreationDate)[-1].[ImageId]' --output text
ami-0217b147346e48e84

AL2ID=`aws ec2 describe-images --owners amazon --filters &quot;Name=name,Values=amzn2-ami-hvm-2.0.*-x86_64-gp2&quot; &quot;Name=state,Values=available&quot; --query 'Images|sort_by(@, &amp;amp;CreationDate)[-1].[ImageId]' --output text`
echo $AL2ID&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;터미널 1개를 추가로 열고, 아래 명령으로 EC2 생성을 모니터링 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1714208436808&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# [터미널1] EC2 생성 모니터링
export AWS_PAGER=&quot;&quot;
while true; do aws ec2 describe-instances --query &quot;Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}&quot; --filters Name=instance-state-name,Values=running --output text ; echo &quot;------------------------------&quot; ; sleep 1; done&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;테라폼 코드를 작성합니다. HCL 이라고 부르며, Block 단위로 구성되어 있습니다. 아래는 2개의 블록으로 이루어 져 있습니다. Provider는 배포할 타겟의 클라우드 환경을 설정한다고 이해하면 됩니다, resource는 실제 배포할 인프라 자원을 의미합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1714208599928&quot; class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;cat &amp;lt;&amp;lt;EOT &amp;gt; main.tf
provider &quot;aws&quot; {
  region = &quot;ap-northeast-2&quot;
}

resource &quot;aws_instance&quot; &quot;example&quot; {
  ami           = &quot;$AL2ID&quot;
  instance_type = &quot;t2.micro&quot;
}
EOT&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;Terraform 배포를 진행합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1714208700573&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 초기화
terraform init
ls -al
tree .terraform

# plan 확인
terraform plan

# apply 실행
terraform apply
 Enter a value: yes 입력&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;AWS cli에서 아래처럼 EC2 list를 확인해볼 수 있습니다. 테라폼을 통해서 EC2 인스턴스를 배포해 보았습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;267&quot; data-origin-height=&quot;155&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bsmgZ5/btsG0UpWtdw/0GQqZPKFWFy3GtRaZAjU4k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bsmgZ5/btsG0UpWtdw/0GQqZPKFWFy3GtRaZAjU4k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bsmgZ5/btsG0UpWtdw/0GQqZPKFWFy3GtRaZAjU4k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbsmgZ5%2FbtsG0UpWtdw%2F0GQqZPKFWFy3GtRaZAjU4k%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;267&quot; height=&quot;155&quot; data-origin-width=&quot;267&quot; data-origin-height=&quot;155&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;size16&quot;&gt;`terraform show` 명령을 통해서도 테라폼에 의해 배포된 리소스 정보를 확인해볼 수 있습니다.&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;현재 배포되어있는 EC2의 태그정보를 수정해 봅니다.&lt;/p&gt;
&lt;pre id=&quot;code_1714208827751&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cat &amp;lt;&amp;lt;EOT &amp;gt; main.tf
provider &quot;aws&quot; {
  region = &quot;ap-northeast-2&quot;
}

resource &quot;aws_instance&quot; &quot;example&quot; {
  ami           = &quot;$AL2ID&quot;
  instance_type = &quot;t2.micro&quot;

  tags = {
    Name = &quot;aews-study&quot;
  }

}
EOT&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;`terraform plan`후 `terraform apply`를 통해 배포를 실행 해 봅니다. terraform plan의 결과를 보면 In-place 방식으로 업데이트 된다고 안내되어 있어, 배포된 리소스의 중지 없이 배포할 수 있음을 알 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1714208939460&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;erraform plan
aws_instance.example: Refreshing state... [id=i-0fe9e466fca30f1cc]

Terraform used the selected providers to
generate the following execution plan. Resource
actions are indicated with the following
symbols:
  ~ update in-place

Terraform will perform the following actions:

  # aws_instance.example will be updated in-place
  ~ resource &quot;aws_instance&quot; &quot;example&quot; {
        id                                   = &quot;i-0fe9e466fca30f1cc&quot;
      ~ tags                                 = {
          + &quot;Name&quot; = &quot;aews-study&quot;
        }
      ~ tags_all                             = {
          + &quot;Name&quot; = &quot;aews-study&quot;
        }
        # (30 unchanged attributes hidden)

        # (8 unchanged blocks hidden)
    }

Plan: 0 to add, 1 to change, 0 to destroy.

───────────────────────────────────────────────

Note: You didn't use the -out option to save
this plan, so Terraform can't guarantee to take
exactly these actions if you run &quot;terraform
apply&quot; now.&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;`terraform apply`에 성공하면 아래처럼 EC2 리소스에 name이 확인되는것을 볼 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;347&quot; data-origin-height=&quot;102&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/crfS63/btsG0s8hHxp/feTr0mB0yah9XqV8Iu79kK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/crfS63/btsG0s8hHxp/feTr0mB0yah9XqV8Iu79kK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/crfS63/btsG0s8hHxp/feTr0mB0yah9XqV8Iu79kK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcrfS63%2FbtsG0s8hHxp%2FfeTr0mB0yah9XqV8Iu79kK%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;347&quot; height=&quot;102&quot; data-origin-width=&quot;347&quot; data-origin-height=&quot;102&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;size16&quot;&gt;`terraform destoy`를 통해 삭제합니다.&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;[HCL의 표현식 참고]&lt;/p&gt;
&lt;pre id=&quot;code_1714209147956&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 한줄 주석 방법1
# 한줄 주석 방법2

/*
라인
주석
*/

locals {
  key1     = &quot;value1&quot;     # = 를 기준으로 키와 값이 구분되며
  myStr    = &quot;TF ♡ UTF-8&quot; # UTF-8 문자를 지원한다.
  multiStr = &amp;lt;&amp;lt;EOF
  Multi
  Line
  String
  with anytext
EOF

  boolean1    = true   # boolean true
  boolean2    = false  # boolean false를 지원한다.
  deciaml     = 123    # 기본적으로 숫자는 10진수,
  octal       = 0123   # 0으로 시작하는 숫자는 8진수,
  hexadecimal = &quot;0xD5&quot; # 0x 값을 포함하는 스트링은 16진수,
  scientific  = 1e10   # 과학표기 법도 지원한다.

  # funtion 호출 예
  myprojectname = format(&quot;%s is myproject name&quot;, var.project)

  # 3항 연산자 조건문을 지원한다.
  credentials = var.credentials == &quot;&quot; ? file(var.credentials_file) : var.credentials
}&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;Terraform Version&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테라폼 내에서 버전이 명시되는 terraform, module에서 사용 가능하며 버전에 대한 제약을 둠으로써 언제 실행하든 항상 의도한 정의대로 실행되는 것을 목적으로 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1714209227785&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;terraform {
  required_version = &quot;~&amp;gt; 1.3.0&quot; # 테라폼 버전

  required_providers { # 프로바이더 버전을 나열
    random = {
      version = &quot;&amp;gt;= 3.0.0, &amp;lt; 3.1.0&quot;
    }
    aws = {
      version = &quot;4.2.0&quot;
    }
  }

  cloud { # Cloud/Enterprise 같은 원격 실행을 위한 정보
    organization = &quot;&amp;lt;MY_ORG_NAME&amp;gt;&quot;
    workspaces {
      name = &quot;my-first-workspace&quot;
    }
  }

  backend &quot;local&quot; { # state를 보관하는 위치를 지정
    path = &quot;relative/path/to/terraform.tfstate&quot;
  }
}&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;프로바이더의 버전도 각 벤더 별 상이하게 적용할 수 있습니다. 테라폼 0.13 버전 이전에서는 provider 블록에 함께 버전을 명시했지만, 해당 버전 이후 provider 버전은 terraform 블록에서 required_providers에 정의합니다.&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;리소스 구성 실습을 진행합니다. 신규 디렉터리를 생성하고 main.tf 파일을 생성합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1714209517608&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cd ..
mkdir 2
cd 2&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;리소스 블록은 resource로 시작합니다. 이후 리소스 블록이 생성할 리소스 유형을 정의합니다. 리소스 유형에는 &quot;프로바이더 이름_제공 리소스 유형&quot; 으로 선언할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1714209620886&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;resource &quot;&amp;lt;리소스 유형&amp;gt;&quot; &quot;&amp;lt;이름&amp;gt;&quot; {
  &amp;lt;인수&amp;gt; = &amp;lt;값&amp;gt;
}

resource &quot;local_file&quot; &quot;abc&quot; {
  content  = &quot;123&quot;
  filename = &quot;${path.module}/abc.txt&quot;
}&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;main.tf 파일에 아래 내용을 붙여넣고 `terraform init`을 입력합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1714209782107&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;resource &quot;local_file&quot; &quot;abc&quot; {
  content  = &quot;123&quot;
  filename = &quot;${path.module}/abc.txt&quot;
}

resource &quot;aws_instance&quot; &quot;web&quot; {
  ami = &quot;ami-a1b2c3d4&quot;
  instance_type = &quot;t2.micro&quot;  
}&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;현재 디렉터리에 숨김 폴더로 .terraform 폴더가 생성되고, 하위에 local과 aws에 관한 provider 다운이 자동으로 된 것을 확인해볼 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;176&quot; data-origin-height=&quot;157&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ckvq5X/btsGZWu7g8B/Aes1JRWB2ROC18VVFxle51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ckvq5X/btsGZWu7g8B/Aes1JRWB2ROC18VVFxle51/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ckvq5X/btsGZWu7g8B/Aes1JRWB2ROC18VVFxle51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fckvq5X%2FbtsGZWu7g8B%2FAes1JRWB2ROC18VVFxle51%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;176&quot; height=&quot;157&quot; data-origin-width=&quot;176&quot; data-origin-height=&quot;157&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;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테라폼의 종속성은 resource, module 선언으로 프로비저닝 되는 각 요소의 생성 순서를 자동으로 구분 짓습니다. 관리자가 별도의 종속성을 적용해야 하는 경우 depends_on을 활용해야 합니다.&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;아래 코드로 main.tf를 수정합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1714209983568&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;resource &quot;local_file&quot; &quot;abc&quot; {
  content  = &quot;123!&quot;
  filename = &quot;${path.module}/abc.txt&quot;
}

resource &quot;local_file&quot; &quot;def&quot; {
  content  = &quot;456!&quot;
  filename = &quot;${path.module}/def.txt&quot;
}&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;`terraform apply -auto-approve`를 진행합니다. abc.txt와 def.txt가 생성된 것을 볼 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;169&quot; data-origin-height=&quot;54&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/boDote/btsGYfwb6KI/67WOCy8jK6TJViwd90ITt1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/boDote/btsGYfwb6KI/67WOCy8jK6TJViwd90ITt1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/boDote/btsGYfwb6KI/67WOCy8jK6TJViwd90ITt1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FboDote%2FbtsGYfwb6KI%2F67WOCy8jK6TJViwd90ITt1%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;169&quot; height=&quot;54&quot; data-origin-width=&quot;169&quot; data-origin-height=&quot;54&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;size16&quot;&gt;`terraform graph &amp;gt; &lt;span data-token-index=&quot;1&quot;&gt;graph-1.dot`명령을 통해&amp;nbsp;&lt;/span&gt;종속성 확인을 해봅니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;703&quot; data-origin-height=&quot;321&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b7oUpR/btsG1gsRuwc/lf380Cz3pl6VANJoRi6W6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b7oUpR/btsG1gsRuwc/lf380Cz3pl6VANJoRi6W6K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b7oUpR/btsG1gsRuwc/lf380Cz3pl6VANJoRi6W6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb7oUpR%2FbtsG1gsRuwc%2Flf380Cz3pl6VANJoRi6W6K%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;703&quot; height=&quot;321&quot; data-origin-width=&quot;703&quot; data-origin-height=&quot;321&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재는 두개의 resource에 별다른 종속성이 없습니다.&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;pre id=&quot;code_1714210259215&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;terraform destroy -auto-approve
ls *.txt
terraform state list&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;리소스 참조값을 설정해 두 개의 리소스 간 암시적 종속성을 부여합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1714210282574&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;resource &quot;local_file&quot; &quot;abc&quot; {
  content  = &quot;123!&quot;
  filename = &quot;${path.module}/abc.txt&quot;
}

resource &quot;local_file&quot; &quot;def&quot; {
  content  = local_file.abc.content
  filename = &quot;${path.module}/def.txt&quot;
}&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;`terraform apply -auto-approve`를 통해 배포합니다. 그 후 `terraform graph &amp;gt; &lt;span data-token-index=&quot;1&quot;&gt;graph-2.dot` 명령으로 종속성을 확인해 봅니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;718&quot; data-origin-height=&quot;420&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FvjtE/btsGZztnG3I/KuvSaqZ0BiqB1CPU5kFtTk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FvjtE/btsGZztnG3I/KuvSaqZ0BiqB1CPU5kFtTk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FvjtE/btsGZztnG3I/KuvSaqZ0BiqB1CPU5kFtTk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFvjtE%2FbtsGZztnG3I%2FKuvSaqZ0BiqB1CPU5kFtTk%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;718&quot; height=&quot;420&quot; data-origin-width=&quot;718&quot; data-origin-height=&quot;420&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;size16&quot;&gt;위와 동일하게 terraform 삭제 후 depends_on으로 명시적인 종속성을 적용해도 동일한 결과가 나옵니다. 원래는 def 리소스가 병렬로 실행되어 별도 종속성이 없어야 하지만 depends_on의 옵션으로 인해 abc가 생성된 뒤 def가 생성되게 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1714210496376&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;resource &quot;local_file&quot; &quot;abc&quot; {
  content  = &quot;123!&quot;
  filename = &quot;${path.module}/abc.txt&quot;
}

resource &quot;local_file&quot; &quot;def&quot; {
  depends_on = [
    local_file.abc
  ]

  content  = &quot;456!&quot;
  filename = &quot;${path.module}/def.txt&quot;
}&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;리소스 속성 참조는 배포된 리소스의 속성 SG의 ID 같은 정보를 참조할 수 있는 기능입니다. 아래 예시는 namesapce를 생성하고, secret을 배포할 때, Terraform에 의해 배포된 namespace의 이름을 사용하는 예시 입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1714210611791&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;resource &quot;kubernetes_namespace&quot; &quot;example&quot; {
  metadata {
    annotations = {
      name = &quot;example-annotation&quot;
    }
    name = &quot;terraform-example-namespace&quot;
  }
}

resource &quot;kubernetes_secret&quot; &quot;example&quot; {
  metadata {
    namespace = kubernetes_namespace.example.metadata.0.name # namespace 리소스 인수 참조
    name      = &quot;terraform-example&quot;
  }
  data = {
    password = &quot;P4ssw0rd&quot;
  }
}&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;데이터 소스 구성은 테라폼으로 정의되지 않은 외부 리소스 또는 저장된 정보를 테라폼 내에서 참조할 때 사용합니다.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1714210807678&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;resource &quot;local_file&quot; &quot;abc&quot; {
  content  = &quot;123!&quot;
  filename = &quot;${path.module}/abc.txt&quot;
}

data &quot;local_file&quot; &quot;abc&quot; {
  filename = local_file.abc.filename
}

resource &quot;local_file&quot; &quot;def&quot; {
  content  = data.local_file.abc.content
  filename = &quot;${path.module}/def.txt&quot;
}&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;위 코드를 `terraform apply`하면 아래와 같은 종속관계를 가집니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;725&quot; data-origin-height=&quot;517&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cL78NI/btsGZNSDWDU/6CbSTplQzTiWIX9JGFHTkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cL78NI/btsGZNSDWDU/6CbSTplQzTiWIX9JGFHTkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cL78NI/btsGZNSDWDU/6CbSTplQzTiWIX9JGFHTkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcL78NI%2FbtsGZNSDWDU%2F6CbSTplQzTiWIX9JGFHTkk%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;725&quot; height=&quot;517&quot; data-origin-width=&quot;725&quot; data-origin-height=&quot;517&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;size16&quot;&gt;아래 data 블록을 신규 추가하고 `terraform apply`를 재실행 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1714211243989&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;data &quot;aws_availability_zones&quot; &quot;available&quot; {
  state = &quot;available&quot;
}&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;`terraform console`로 외부 data의 정보를 확인해볼 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;617&quot; data-origin-height=&quot;446&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1uxlO/btsGYRhiz6M/9drjKoiap2KDxATGNd0OHK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1uxlO/btsGYRhiz6M/9drjKoiap2KDxATGNd0OHK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1uxlO/btsGYRhiz6M/9drjKoiap2KDxATGNd0OHK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1uxlO%2FbtsGYRhiz6M%2F9drjKoiap2KDxATGNd0OHK%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;617&quot; height=&quot;446&quot; data-origin-width=&quot;617&quot; data-origin-height=&quot;446&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;size16&quot;&gt;변수 선언 방식으로는 입력 변수의 경우 인프라를 구성하는 데 필요한 속성 값을 정의해 코드의 변경 없이 여러 인프라를 생성하는 데 목적이 있습니다. 테라폼에서는 이것을 입력 변수로 정의합니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1714211391340&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;variable &quot;string&quot; {
  type        = string
  description = &quot;var String&quot;
  default     = &quot;myString&quot;
}

variable &quot;number&quot; {
  type    = number
  default = 123
}

variable &quot;boolean&quot; {
  default = true
}

variable &quot;list&quot; {
  default = [
    &quot;google&quot;,
    &quot;vmware&quot;,
    &quot;amazon&quot;,
    &quot;microsoft&quot;
  ]
}

output &quot;list_index_0&quot; {
  value = var.list.0
}

output &quot;list_all&quot; {
  value = [
    for name in var.list : upper(name)
  ]
}

variable &quot;map&quot; { # Sorting
  default = {
    aws   = &quot;amazon&quot;,
    azure = &quot;microsoft&quot;,
    gcp   = &quot;google&quot;
  }
}

variable &quot;set&quot; { # Sorting
  type = set(string)
  default = [
    &quot;google&quot;,
    &quot;vmware&quot;,
    &quot;amazon&quot;,
    &quot;microsoft&quot;
  ]
}

variable &quot;object&quot; {
  type = object({ name = string, age = number })
  default = {
    name = &quot;abc&quot;
    age  = 12
  }
}

variable &quot;tuple&quot; {
  type    = tuple([string, number, bool])
  default = [&quot;abc&quot;, 123, true]
}

variable &quot;ingress_rules&quot; { # optional ( &amp;gt;= terraform 1.3.0)
  type = list(object({
    port        = number,
    description = optional(string),
    protocol    = optional(string, &quot;tcp&quot;),
  }))
  default = [
    { port = 80, description = &quot;web&quot; },
  { port = 53, protocol = &quot;udp&quot; }]
}&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;생성한 변수의 참조는 var.&quot;name&quot; 방식으로 참조할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1714211504240&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;variable &quot;my_password&quot; {}

resource &quot;local_file&quot; &quot;abc&quot; {
  content  = var.my_password
  filename = &quot;${path.module}/abc.txt&quot;
}&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;VPC 배포 실습&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;신규 디렉터리 생성&lt;/p&gt;
&lt;pre id=&quot;code_1714211636154&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 신규 디렉터리 생성
mkdir my-vpc-ec2
cd my-vpc-ec2&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;vpc.tf&lt;/p&gt;
&lt;pre id=&quot;code_1714211697637&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;provider &quot;aws&quot; {
  region  = &quot;ap-northeast-2&quot;
}

resource &quot;aws_vpc&quot; &quot;myvpc&quot; {
  cidr_block       = &quot;10.10.0.0/16&quot;
  enable_dns_support   = true
  enable_dns_hostnames = true

  tags = {
    Name = &quot;t101-study&quot;
  }
}

resource &quot;aws_subnet&quot; &quot;mysubnet1&quot; {
  vpc_id     = aws_vpc.myvpc.id
  cidr_block = &quot;10.10.1.0/24&quot;

  availability_zone = &quot;ap-northeast-2a&quot;

  tags = {
    Name = &quot;t101-subnet1&quot;
  }
}

resource &quot;aws_subnet&quot; &quot;mysubnet2&quot; {
  vpc_id     = aws_vpc.myvpc.id
  cidr_block = &quot;10.10.2.0/24&quot;

  availability_zone = &quot;ap-northeast-2c&quot;

  tags = {
    Name = &quot;t101-subnet2&quot;
  }
}


resource &quot;aws_internet_gateway&quot; &quot;myigw&quot; {
  vpc_id = aws_vpc.myvpc.id

  tags = {
    Name = &quot;t101-igw&quot;
  }
}

resource &quot;aws_route_table&quot; &quot;myrt&quot; {
  vpc_id = aws_vpc.myvpc.id

  tags = {
    Name = &quot;t101-rt&quot;
  }
}

resource &quot;aws_route_table_association&quot; &quot;myrtassociation1&quot; {
  subnet_id      = aws_subnet.mysubnet1.id
  route_table_id = aws_route_table.myrt.id
}

resource &quot;aws_route_table_association&quot; &quot;myrtassociation2&quot; {
  subnet_id      = aws_subnet.mysubnet2.id
  route_table_id = aws_route_table.myrt.id
}

resource &quot;aws_route&quot; &quot;mydefaultroute&quot; {
  route_table_id         = aws_route_table.myrt.id
  destination_cidr_block = &quot;0.0.0.0/0&quot;
  gateway_id             = aws_internet_gateway.myigw.id
}

output &quot;aws_vpc_id&quot; {
  value = aws_vpc.myvpc.id
}&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;배포&lt;/p&gt;
&lt;pre id=&quot;code_1714211721004&quot; class=&quot;bash&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# 배포
terraform plan &amp;amp;&amp;amp; terraform apply -auto-approve
terraform state list
aws_internet_gateway.myigw
aws_route.mydefaultroute
aws_route_table.myrt
aws_route_table_association.myrtassociation1
aws_route_table_association.myrtassociation2
aws_subnet.mysubnet1
aws_subnet.mysubnet2
aws_vpc.myvpc

terraform state show aws_route.mydefaultroute

# graph 확인 &amp;gt; graph.dot 파일 선택 후 오른쪽 상단 DOT 클릭
terraform graph &amp;gt; graph.dot

# 라우팅 테이블 확인
#aws ec2 describe-route-tables --filters 'Name=tag:Name,Values=t101-rt' --query 'RouteTables[].Associations[].SubnetId'
aws ec2 describe-route-tables --filters 'Name=tag:Name,Values=t101-rt' --output table&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;723&quot; data-origin-height=&quot;298&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Eu3Mx/btsGZZrKJYc/dB5tylsBayZjVkw3Rv2kf1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Eu3Mx/btsGZZrKJYc/dB5tylsBayZjVkw3Rv2kf1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Eu3Mx/btsGZZrKJYc/dB5tylsBayZjVkw3Rv2kf1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEu3Mx%2FbtsGZZrKJYc%2FdB5tylsBayZjVkw3Rv2kf1%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;723&quot; height=&quot;298&quot; data-origin-width=&quot;723&quot; data-origin-height=&quot;298&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;949&quot; data-origin-height=&quot;293&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KYAIq/btsGZloDeCj/pcA9GcaVjxkuXYcXn8Qzi1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KYAIq/btsGZloDeCj/pcA9GcaVjxkuXYcXn8Qzi1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KYAIq/btsGZloDeCj/pcA9GcaVjxkuXYcXn8Qzi1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKYAIq%2FbtsGZloDeCj%2FpcA9GcaVjxkuXYcXn8Qzi1%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;949&quot; height=&quot;293&quot; data-origin-width=&quot;949&quot; data-origin-height=&quot;293&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;724&quot; data-origin-height=&quot;319&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cX1CKl/btsGZOcWRlL/iUpBVHFew6rbMvFbx4Akz1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cX1CKl/btsGZOcWRlL/iUpBVHFew6rbMvFbx4Akz1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cX1CKl/btsGZOcWRlL/iUpBVHFew6rbMvFbx4Akz1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcX1CKl%2FbtsGZOcWRlL%2FiUpBVHFew6rbMvFbx4Akz1%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;724&quot; height=&quot;319&quot; data-origin-width=&quot;724&quot; data-origin-height=&quot;319&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;size16&quot;&gt;보안그룹과 EC2를 배포해 봅니다. sg.tf, ec2.tf&lt;/p&gt;
&lt;pre id=&quot;code_1714212194087&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;resource &quot;aws_security_group&quot; &quot;mysg&quot; {
  vpc_id      = aws_vpc.myvpc.id
  name        = &quot;T101 SG&quot;
  description = &quot;T101 Study SG&quot;
}

resource &quot;aws_security_group_rule&quot; &quot;mysginbound&quot; {
  type              = &quot;ingress&quot;
  from_port         = 80
  to_port           = 80
  protocol          = &quot;tcp&quot;
  cidr_blocks       = [&quot;0.0.0.0/0&quot;]
  security_group_id = aws_security_group.mysg.id
}

resource &quot;aws_security_group_rule&quot; &quot;mysgoutbound&quot; {
  type              = &quot;egress&quot;
  from_port         = 0
  to_port           = 0
  protocol          = &quot;-1&quot;
  cidr_blocks       = [&quot;0.0.0.0/0&quot;]
  security_group_id = aws_security_group.mysg.id
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1714212202697&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;data &quot;aws_ami&quot; &quot;my_amazonlinux2&quot; {
  most_recent = true
  filter {
    name   = &quot;owner-alias&quot;
    values = [&quot;amazon&quot;]
  }

  filter {
    name   = &quot;name&quot;
    values = [&quot;amzn2-ami-hvm-*-x86_64-ebs&quot;]
  }

  owners = [&quot;amazon&quot;]
}

resource &quot;aws_instance&quot; &quot;myec2&quot; {

  depends_on = [
    aws_internet_gateway.myigw
  ]

  ami                         = data.aws_ami.my_amazonlinux2.id
  associate_public_ip_address = true
  instance_type               = &quot;t2.micro&quot;
  vpc_security_group_ids      = [&quot;${aws_security_group.mysg.id}&quot;]
  subnet_id                   = aws_subnet.mysubnet1.id

  user_data = &amp;lt;&amp;lt;-EOF
              #!/bin/bash
              wget https://busybox.net/downloads/binaries/1.31.0-defconfig-multiarch-musl/busybox-x86_64
              mv busybox-x86_64 busybox
              chmod +x busybox
              echo &quot;Web Server&amp;lt;/h1&amp;gt;&quot; &amp;gt; index.html
              nohup ./busybox httpd -f -p 80 &amp;amp;
              EOF

  user_data_replace_on_change = true

  tags = {
    Name = &quot;t101-myec2&quot;
  }
}

output &quot;myec2_public_ip&quot; {
  value       = aws_instance.myec2.public_ip
  description = &quot;The public IP of the Instance&quot;
}&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;배포 확인&lt;/p&gt;
&lt;pre id=&quot;code_1714212268111&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 
ls *.tf
terraform plan &amp;amp;&amp;amp; terraform apply -auto-approve
terraform state list
data.aws_ami.my_amazonlinux2
aws_instance.myec2
...

terraform state show data.aws_ami.my_amazonlinux2
terraform state show aws_instance.myec2

# 데이터소스 값 확인
terraform console
&amp;gt; 
data.aws_ami.my_amazonlinux2.id
&quot;ami-01c81850a6167bb81&quot;
data.aws_ami.my_amazonlinux2.image_id
data.aws_ami.my_amazonlinux2.name
data.aws_ami.my_amazonlinux2.owners
data.aws_ami.my_amazonlinux2.platform_details
data.aws_ami.my_amazonlinux2.hypervisor
data.aws_ami.my_amazonlinux2.architecture
exit

# graph 확인 &amp;gt; graph.dot 파일 선택 후 오른쪽 상단 DOT 클릭
terraform graph &amp;gt; graph.dot

# 출력된 EC2 퍼블릭IP로 cul 접속 확인
terraform output -raw myec2_public_ip
3.35.214.63

MYIP=$(terraform output -raw myec2_public_ip)
while true; do curl --connect-timeout 1  http://$MYIP/ ; echo &quot;------------------------------&quot;; date; sleep 1; done&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1305&quot; data-origin-height=&quot;341&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mxzk5/btsGZVC0iPA/cJ4RBeGofh4E1Y2xqRe8z0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mxzk5/btsGZVC0iPA/cJ4RBeGofh4E1Y2xqRe8z0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mxzk5/btsGZVC0iPA/cJ4RBeGofh4E1Y2xqRe8z0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fmxzk5%2FbtsGZVC0iPA%2FcJ4RBeGofh4E1Y2xqRe8z0%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;1305&quot; height=&quot;341&quot; data-origin-width=&quot;1305&quot; data-origin-height=&quot;341&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&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;963&quot; data-origin-height=&quot;366&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rMtxw/btsGY7KQdbA/9BIeLkwfkpZsmwDrmtnA1K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rMtxw/btsGY7KQdbA/9BIeLkwfkpZsmwDrmtnA1K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rMtxw/btsGY7KQdbA/9BIeLkwfkpZsmwDrmtnA1K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrMtxw%2FbtsGY7KQdbA%2F9BIeLkwfkpZsmwDrmtnA1K%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;963&quot; height=&quot;366&quot; data-origin-width=&quot;963&quot; data-origin-height=&quot;366&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;size16&quot;&gt;삭제 : `terraform destroy -auto-approve`&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단일 프로바이더의 다중 정의도 적용할 수 있습니다. 아래 예제는 리전을 다르게 구성한 AWS 프로바이더를 aws_instance에 지정하는 예시입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1714212634475&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;provider &quot;aws&quot; {
  region = &quot;ap-southeast-1&quot;
}

provider &quot;aws&quot; {
  alias = &quot;seoul&quot;
  region = &quot;ap-northeast-2&quot;
}

resource &quot;aws_instance&quot; &quot;app_server1&quot; {
  ami           = &quot;ami-06b79cf2aee0d5c92&quot;
  instance_type = &quot;t2.micro&quot;
}

resource &quot;aws_instance&quot; &quot;app_server2&quot; {
  provider      = aws.seoul
  ami           = &quot;ami-0ea4d4b8dc1e46212&quot;
  instance_type = &quot;t2.micro&quot;
}&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모듈의 경우 테라폼으로 관리하는데 시간이 지날수록 구성이 복잡해지고, 관리하는 리소스가 늘어가게 되는데 모듈은 테라폼 구성의 집합으로 구성해 두어 관리 및 재사용에 용이하도록 합니다. 새로운 폴더를 생성하고 main.tf를 작성합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1714212814745&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# main.tf
resource &quot;random_pet&quot; &quot;name&quot; {
  keepers = {
    ami_id = timestamp()
  }
}

resource &quot;random_password&quot; &quot;password&quot; {
  length           = var.isDB ? 16 : 10
  special          = var.isDB ? true : false
  override_special = &quot;!#$%*?&quot;
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1714212887081&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# variable.tf
variable &quot;isDB&quot; {
  type        = bool
  default     = false
  description = &quot;패스워드 대상의 DB 여부&quot;
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1714212895655&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# output.tf
output &quot;id&quot; {
  value = random_pet.name.id
}

output &quot;pw&quot; {
  value = nonsensitive(random_password.password.result) 
}&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;실행&lt;/p&gt;
&lt;pre id=&quot;code_1714212977878&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#
terraform init &amp;amp;&amp;amp; terraform plan

# 테스트를 위해 apply 시 변수 지정
terraform apply -auto-approve -var=isDB=true
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
Outputs:
id = &quot;pleased-ghost&quot;
pw = &quot;5Iq3*liXG*DWGkOp&quot;

# 확인
terraform state list
terraform state show random_pet.name
terraform state show random_password.password

# tfstate에 모듈 정보 확인
cat terraform.tfstate | grep module

# graph 확인
terraform graph &amp;gt; graph.dot&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;자식 모듈 호출을 확인해 봅니다. module을 통해 위에서 정의한 리소스를 재사용합니다. 새로운 폴더를 만들고 main.tf를 생성합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1714213157649&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;module &quot;mypw1&quot; {
  source = &quot;../modules/terraform-random-pwgen&quot;
}

module &quot;mypw2&quot; {
  source = &quot;../modules/terraform-random-pwgen&quot;
  isDB   = true
}

output &quot;mypw1&quot; {
  value  = module.mypw1
}

output &quot;mypw2&quot; {
  value  = module.mypw2
}&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;확인&lt;/p&gt;
&lt;pre id=&quot;code_1714213184437&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#
cd 06-module-traning/06-01-basic

#
terraform init &amp;amp;&amp;amp; terraform plan &amp;amp;&amp;amp; terraform apply -auto-approve
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
Outputs:

mypw1 = {
  &quot;id&quot; = &quot;sure-coral&quot;
  &quot;pw&quot; = &quot;W4zEVZ1wXK&quot;
}
mypw2 = {
  &quot;id&quot; = &quot;adapted-troll&quot;
  &quot;pw&quot; = &quot;4WXyjq*o3M6xIg5l&quot;
}

# 확인
terraform state list

# tfstate에 모듈 정보 확인
cat terraform.tfstate | grep module

# terraform init 시 생성되는 modules.json 파일 확인
tree .terraform
.terraform
├── modules
│   └── modules.json
...

## 모듈로 묶여진 리소스는 module이라는 정의를 통해 단순하게 재활용하고 반복 사용할 수 있다.
## 모듈의 결과 참조 형식은 module.&amp;lt;모듈 이름&amp;gt;.&amp;lt;output 이름&amp;gt;으로 정의된다.
cat .terraform/modules/modules.json | jq
{
  &quot;Modules&quot;: [
    {
      &quot;Key&quot;: &quot;&quot;,
      &quot;Source&quot;: &quot;&quot;,
      &quot;Dir&quot;: &quot;.&quot;
    },
    {
      &quot;Key&quot;: &quot;mypw1&quot;,
      &quot;Source&quot;: &quot;../4&quot;,
      &quot;Dir&quot;: &quot;../4&quot;
    },
    {
      &quot;Key&quot;: &quot;mypw2&quot;,
      &quot;Source&quot;: &quot;../4&quot;,
      &quot;Dir&quot;: &quot;../4&quot;
    }
  ]
}

# graph 확인
terraform graph &amp;gt; graph.dot&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;&amp;nbsp;&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;Terraform EKS 배포&lt;/p&gt;
&lt;pre id=&quot;code_1714213447039&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 코드 가져오기
git clone https://github.com/gasida/aews-cicd.git
cd aews-cicd/4

# terraform 환경 변수 저장
export TF_VAR_KeyName=[각자 ssh keypair]
export TF_VAR_KeyName='hj42700eks'
echo $TF_VAR_KeyName

# 
terraform init
terraform plan

# 10분 후 배포 완료
terraform apply -auto-approve&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;p data-ke-size=&quot;size16&quot;&gt;vpc.tf&lt;/p&gt;
&lt;pre id=&quot;code_1714213702936&quot; class=&quot;nix&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;provider &quot;aws&quot; {
  region = var.TargetRegion
}

module &quot;vpc&quot; {
  source  = &quot;terraform-aws-modules/vpc/aws&quot;
  version = &quot;~&amp;gt;5.7&quot;

  name = &quot;${var.ClusterBaseName}-VPC&quot;
  cidr = var.VpcBlock
  azs  = var.availability_zones

  enable_dns_support   = true
  enable_dns_hostnames = true

  public_subnets  = var.public_subnet_blocks
  private_subnets = var.private_subnet_blocks

  enable_nat_gateway = true
  single_nat_gateway = true
  one_nat_gateway_per_az = false
  
  map_public_ip_on_launch = true
 
  igw_tags = {
    &quot;Name&quot; = &quot;${var.ClusterBaseName}-IGW&quot;
  }
 
  nat_gateway_tags = {
    &quot;Name&quot; = &quot;${var.ClusterBaseName}-NAT&quot;
  }
 
  public_subnet_tags = {
    &quot;Name&quot;                     = &quot;${var.ClusterBaseName}-PublicSubnet&quot;
    &quot;kubernetes.io/role/elb&quot;   = &quot;1&quot;
  }

  private_subnet_tags = {
    &quot;Name&quot;                             = &quot;${var.ClusterBaseName}-PrivateSubnet&quot;
    &quot;kubernetes.io/role/internal-elb&quot; = &quot;1&quot;
  }

  tags = {
    &quot;Environment&quot; = &quot;${var.ClusterBaseName}-lab&quot;
  }
}&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;var.tf&lt;/p&gt;
&lt;pre id=&quot;code_1714213702938&quot; class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;variable &quot;KeyName&quot; {
  description = &quot;Name of an existing EC2 KeyPair to enable SSH access to the instances.&quot;
  type        = string
}

variable &quot;ClusterBaseName&quot; {
  description = &quot;Base name of the cluster.&quot;
  type        = string
  default     = &quot;myeks&quot;
}

variable &quot;KubernetesVersion&quot; {
  description = &quot;Kubernetes version for the EKS cluster.&quot;
  type        = string
  default     = &quot;1.29&quot;
}

variable &quot;WorkerNodeInstanceType&quot; {
  description = &quot;EC2 instance type for the worker nodes.&quot;
  type        = string
  default     = &quot;t3.medium&quot;
}

variable &quot;WorkerNodeCount&quot; {
  description = &quot;Number of worker nodes.&quot;
  type        = number
  default     = 3
}

variable &quot;WorkerNodeVolumesize&quot; {
  description = &quot;Volume size for worker nodes (in GiB).&quot;
  type        = number
  default     = 30
}

variable &quot;TargetRegion&quot; {
  description = &quot;AWS region where the resources will be created.&quot;
  type        = string
  default     = &quot;ap-northeast-2&quot;
}

variable &quot;availability_zones&quot; {
  description = &quot;List of availability zones.&quot;
  type        = list(string)
  default     = [&quot;ap-northeast-2a&quot;, &quot;ap-northeast-2b&quot;, &quot;ap-northeast-2c&quot;]
}

variable &quot;VpcBlock&quot; {
  description = &quot;CIDR block for the VPC.&quot;
  type        = string
  default     = &quot;192.168.0.0/16&quot;
}

variable &quot;public_subnet_blocks&quot; {
  description = &quot;List of CIDR blocks for the public subnets.&quot;
  type        = list(string)
  default     = [&quot;192.168.1.0/24&quot;, &quot;192.168.2.0/24&quot;, &quot;192.168.3.0/24&quot;]
}

variable &quot;private_subnet_blocks&quot; {
  description = &quot;List of CIDR blocks for the private subnets.&quot;
  type        = list(string)
  default     = [&quot;192.168.11.0/24&quot;, &quot;192.168.12.0/24&quot;, &quot;192.168.13.0/24&quot;]
}&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;eks.tf&lt;/p&gt;
&lt;pre id=&quot;code_1714213702940&quot; class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;data &quot;aws_caller_identity&quot; &quot;current&quot; {}

resource &quot;aws_iam_policy&quot; &quot;external_dns_policy&quot; {
  name        = &quot;${var.ClusterBaseName}ExternalDNSPolicy&quot;
  description = &quot;Policy for allowing ExternalDNS to modify Route 53 records&quot;

  policy = jsonencode({
    &quot;Version&quot;: &quot;2012-10-17&quot;,
    &quot;Statement&quot;: [
      {
        &quot;Effect&quot;: &quot;Allow&quot;,
        &quot;Action&quot;: [
          &quot;route53:ChangeResourceRecordSets&quot;
        ],
        &quot;Resource&quot;: [
          &quot;arn:aws:route53:::hostedzone/*&quot;
        ]
      },
      {
        &quot;Effect&quot;: &quot;Allow&quot;,
        &quot;Action&quot;: [
          &quot;route53:ListHostedZones&quot;,
          &quot;route53:ListResourceRecordSets&quot;
        ],
        &quot;Resource&quot;: [
          &quot;*&quot;
        ]
      }
    ]
  })
}

resource &quot;aws_iam_role_policy_attachment&quot; &quot;external_dns_policy_attach&quot; {
  role       = &quot;${var.ClusterBaseName}-node-group-eks-node-group&quot;
  policy_arn = aws_iam_policy.external_dns_policy.arn

  depends_on = [module.eks]
}

resource &quot;aws_security_group&quot; &quot;node_group_sg&quot; {
  name        = &quot;${var.ClusterBaseName}-node-group-sg&quot;
  description = &quot;Security group for EKS Node Group&quot;
  vpc_id      = module.vpc.vpc_id

  tags = {
    Name = &quot;${var.ClusterBaseName}-node-group-sg&quot;
  }
}

module &quot;eks&quot; {
  source  = &quot;terraform-aws-modules/eks/aws&quot;
  version = &quot;~&amp;gt;20.0&quot;

  cluster_name = var.ClusterBaseName
  cluster_version = var.KubernetesVersion
  cluster_endpoint_private_access = false
  cluster_endpoint_public_access  = true

  cluster_addons = {
    coredns = {
      most_recent = true
    }
    kube-proxy = {
      most_recent = true
    }
    vpc-cni = {
      most_recent = true
    }
  }

  vpc_id = module.vpc.vpc_id
  enable_irsa = true
  subnet_ids = module.vpc.public_subnets

  eks_managed_node_groups = {
    default = {
      name             = &quot;${var.ClusterBaseName}-node-group&quot;
      use_name_prefix  = false
      instance_type    = var.WorkerNodeInstanceType
      desired_size     = var.WorkerNodeCount
      max_size         = var.WorkerNodeCount + 2
      min_size         = var.WorkerNodeCount - 1
      disk_size        = var.WorkerNodeVolumesize
      subnets          = module.vpc.public_subnets
      key_name         = var.KeyName
      vpc_security_group_ids = [aws_security_group.node_group_sg.id]
      iam_role_name    = &quot;${var.ClusterBaseName}-node-group-eks-node-group&quot;
      iam_role_use_name_prefix = false
      iam_role_additional_policies = {
        &quot;${var.ClusterBaseName}ExternalDNSPolicy&quot; = aws_iam_policy.external_dns_policy.arn
      }
   }
  }

  access_entries = {
    admin = {
      kubernetes_groups = []
      principal_arn     = &quot;${data.aws_caller_identity.current.arn}&quot;

      policy_associations = {
        myeks = {
          policy_arn = &quot;arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy&quot;
          access_scope = {
            namespaces = []
            type       = &quot;cluster&quot;
          }
        }
      }
    }
  }

  tags = {
    Environment = &quot;${var.ClusterBaseName}-lab&quot;
    Terraform   = &quot;true&quot;
  }
}&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;irsa.tf&lt;/p&gt;
&lt;pre id=&quot;code_1714213702942&quot; class=&quot;nix&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;locals {
  cluster_oidc_issuer_arn = &quot;arn:aws:iam::${data.aws_caller_identity.current.account_id}:oidc-provider/${replace(module.eks.cluster_oidc_issuer_url, &quot;https://&quot;, &quot;&quot;)}&quot;
}

module &quot;eks-external-dns&quot; {
  source = &quot;DNXLabs/eks-external-dns/aws&quot;
  version = &quot;0.2.0&quot;

  cluster_name                     = var.ClusterBaseName
  cluster_identity_oidc_issuer     = module.eks.cluster_oidc_issuer_url
  cluster_identity_oidc_issuer_arn = local.cluster_oidc_issuer_arn

  enabled = false

}

module &quot;aws_load_balancer_controller_irsa_role&quot; {
  source  = &quot;terraform-aws-modules/iam/aws//modules/iam-role-for-service-accounts-eks&quot;
  version = &quot;5.3.1&quot;

  role_name = &quot;${var.ClusterBaseName}-aws-load-balancer-controller&quot;

  attach_load_balancer_controller_policy = true

  oidc_providers = {
    ex = {
      provider_arn               = module.eks.oidc_provider_arn
      namespace_service_accounts = [&quot;kube-system:aws-load-balancer-controller&quot;]
    }
  }
}

provider &quot;kubernetes&quot; {
  host                   = module.eks.cluster_endpoint
  token                  = data.aws_eks_cluster_auth.cluster.token
  cluster_ca_certificate = base64decode(module.eks.cluster_certificate_authority_data)
}

data &quot;aws_eks_cluster&quot; &quot;cluster&quot; {
  name = module.eks.cluster_name
  depends_on = [module.eks]
}

data &quot;aws_eks_cluster_auth&quot; &quot;cluster&quot; {
  name = module.eks.cluster_name
  depends_on = [module.eks]
}

resource &quot;kubernetes_service_account&quot; &quot;aws_lb_controller&quot; {
  metadata {
    name      = &quot;aws-load-balancer-controller&quot;
    namespace = &quot;kube-system&quot;
    annotations = {
      &quot;eks.amazonaws.com/role-arn&quot; = module.aws_load_balancer_controller_irsa_role.iam_role_arn
    }
  }
}&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;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;367&quot; data-origin-height=&quot;179&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/csxRTL/btsGZmnyEz2/RSIXdT2eyrPlre7fuqtNW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/csxRTL/btsGZmnyEz2/RSIXdT2eyrPlre7fuqtNW0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/csxRTL/btsGZmnyEz2/RSIXdT2eyrPlre7fuqtNW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcsxRTL%2FbtsGZmnyEz2%2FRSIXdT2eyrPlre7fuqtNW0%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;367&quot; height=&quot;179&quot; data-origin-width=&quot;367&quot; data-origin-height=&quot;179&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;972&quot; data-origin-height=&quot;325&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cLfnIs/btsG0VCpA7H/kVPT4YcY3mvepyntaaWiCk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cLfnIs/btsG0VCpA7H/kVPT4YcY3mvepyntaaWiCk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cLfnIs/btsG0VCpA7H/kVPT4YcY3mvepyntaaWiCk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcLfnIs%2FbtsG0VCpA7H%2FkVPT4YcY3mvepyntaaWiCk%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;972&quot; height=&quot;325&quot; data-origin-width=&quot;972&quot; data-origin-height=&quot;325&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;size16&quot;&gt;배포 정보 확인&lt;/p&gt;
&lt;pre id=&quot;code_1714214224870&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#
kubectl get node -v=6

# EKS 클러스터 인증 정보 업데이트
CLUSTER_NAME=myeks
aws eks update-kubeconfig --region ap-northeast-2 --name $CLUSTER_NAME
kubectl config rename-context &quot;arn:aws:eks:ap-northeast-2:$(aws sts get-caller-identity --query 'Account' --output text):cluster/$CLUSTER_NAME&quot; &quot;Aews-Labs&quot;

#
kubectl cluster-info
kubectl get node --label-columns=node.kubernetes.io/instance-type,eks.amazonaws.com/capacityType,topology.kubernetes.io/zone
kubectl get pod -A&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;기타 설치&lt;/p&gt;
&lt;pre id=&quot;code_1714214259906&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# ExternalDNS
MyDomain=&amp;lt;자신의 도메인&amp;gt;
MyDomain=junkmm.site
MyDnzHostedZoneId=$(aws route53 list-hosted-zones-by-name --dns-name &quot;${MyDomain}.&quot; --query &quot;HostedZones[0].Id&quot; --output text)
echo $MyDomain, $MyDnzHostedZoneId
curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/aews/externaldns.yaml
MyDomain=$MyDomain MyDnzHostedZoneId=$MyDnzHostedZoneId envsubst &amp;lt; externaldns.yaml | kubectl apply -f -

# kube-ops-view
helm repo add geek-cookbook https://geek-cookbook.github.io/charts/
helm install kube-ops-view geek-cookbook/kube-ops-view --version 1.2.2 --set env.TZ=&quot;Asia/Seoul&quot; --namespace kube-system
kubectl patch svc -n kube-system kube-ops-view -p '{&quot;spec&quot;:{&quot;type&quot;:&quot;LoadBalancer&quot;}}'
kubectl annotate service kube-ops-view -n kube-system &quot;external-dns.alpha.kubernetes.io/hostname=kubeopsview.$MyDomain&quot;
echo -e &quot;Kube Ops View URL = http://kubeopsview.$MyDomain:8080/#scale=1.5&quot;

# AWS LB Controller
helm repo add eks https://aws.github.io/eks-charts
helm repo update
helm install aws-load-balancer-controller eks/aws-load-balancer-controller -n kube-system --set clusterName=$CLUSTER_NAME \
  --set serviceAccount.create=false --set serviceAccount.name=aws-load-balancer-controller

# gp3 스토리지 클래스 생성
kubectl apply -f https://raw.githubusercontent.com/gasida/PKOS/main/aews/gp3-sc.yaml&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;두 번째 EKS 를 배포합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1714214399162&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#
cd ..
mkdir 5
cd 5
cp ../4/*.tf .
ls

#
terraform init
terraform apply -auto-approve -var=ClusterBaseName=myeks2 -var=KubernetesVersion=&quot;1.28&quot;

# EKS 클러스터 인증 정보 가져오기
CLUSTER_NAME2=myeks2
aws eks update-kubeconfig --region ap-northeast-2 --name $CLUSTER_NAME2 --kubeconfig ./myeks2config

# EKS 클러스터 정보 확인
kubectl --kubeconfig ./myeks2config get node 
kubectl --kubeconfig ./myeks2config get pod -A&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;삭제&lt;/p&gt;
&lt;pre id=&quot;code_1714214475549&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# CLB는 terraform으로 배포하지 않고 직접 수동으로 배포되었으니, 수동으로 삭제를 해주어야 함
helm uninstall kube-ops-view --namespace kube-system

# 클러스터 삭제
terraform destroy -auto-approve&lt;/code&gt;&lt;/pre&gt;</description>
      <category>클라우드</category>
      <author>junkmm</author>
      <guid isPermaLink="true">https://junkmm.tistory.com/40</guid>
      <comments>https://junkmm.tistory.com/40#entry40comment</comments>
      <pubDate>Sat, 27 Apr 2024 19:42:36 +0900</pubDate>
    </item>
    <item>
      <title>[k8s] Pod의 전략적 배치 - Node Affinity</title>
      <link>https://junkmm.tistory.com/39</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;개요&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쿠버네티스&amp;nbsp;환경에서&amp;nbsp;Pod를&amp;nbsp;특정&amp;nbsp;워커&amp;nbsp;노드에&amp;nbsp;배치하는&amp;nbsp;방법을&amp;nbsp;정리합니다.&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;frontend&amp;nbsp;Appilication은&amp;nbsp;Worker&amp;nbsp;Node&amp;nbsp;1,3에&amp;nbsp;backend&amp;nbsp;Application은&amp;nbsp;Worker&amp;nbsp;Node&amp;nbsp;2,4에&amp;nbsp;배치시키려&amp;nbsp;합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3880&quot; data-origin-height=&quot;1440&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zxv9m/btsGIURRvaA/TZjuJFkyMiVFTGVIPmnMkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zxv9m/btsGIURRvaA/TZjuJFkyMiVFTGVIPmnMkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zxv9m/btsGIURRvaA/TZjuJFkyMiVFTGVIPmnMkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fzxv9m%2FbtsGIURRvaA%2FTZjuJFkyMiVFTGVIPmnMkK%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;3880&quot; height=&quot;1440&quot; data-origin-width=&quot;3880&quot; data-origin-height=&quot;1440&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;노드에 Label 추가하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 클러스터의 노드 Label 확인&lt;/p&gt;
&lt;pre id=&quot;code_1713347003844&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl get nodes --show-labels&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;결과&lt;/p&gt;
&lt;pre id=&quot;code_1713347023592&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;NAME                                               STATUS   ROLES    AGE   VERSION               LABELS
ip-10-100-39-3.ap-northeast-3.compute.internal   Ready    &amp;lt;none&amp;gt;   52m   v1.28.5-eks-5e0fdde   ...,kubernetes.io/host=worker1
ip-10-100-42-191.ap-northeast-3.compute.internal   Ready    &amp;lt;none&amp;gt;   52m   v1.28.5-eks-5e0fdde   ...,kubernetes.io/host=worker2
ip-10-100-46-137.ap-northeast-3.compute.internal   Ready    &amp;lt;none&amp;gt;   52m   v1.28.5-eks-5e0fdde   ...,kubernetes.io/host=worker3
ip-10-100-49-146.ap-northeast-3.compute.internal   Ready    &amp;lt;none&amp;gt;   52m   v1.28.5-eks-5e0fdde   ...,kubernetes.io/host=worker4
ip-10-100-50-238.ap-northeast-3.compute.internal   Ready    &amp;lt;none&amp;gt;   52m   v1.28.5-eks-5e0fdde   ...,kubernetes.io/host=worker5&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;2.&amp;nbsp;특정&amp;nbsp;노드에&amp;nbsp;Label을&amp;nbsp;추가합니다.&amp;nbsp;워커노드&amp;nbsp;2대씩&amp;nbsp;`tier=front`,&amp;nbsp;`tier=back`으로&amp;nbsp;할당합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713347033543&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl label nodes ip-10-100-39-3.ap-northeast-3.compute.internal tier=front
kubectl label nodes ip-10-100-42-191.ap-northeast-3.compute.internal tier=front
kubectl label nodes ip-10-100-46-137.ap-northeast-3.compute.internal tier=back
kubectl label nodes ip-10-100-49-146.ap-northeast-3.compute.internal tier=back&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;3.&amp;nbsp;워커&amp;nbsp;노드에&amp;nbsp;Label이&amp;nbsp;잘&amp;nbsp;적용&amp;nbsp;되었는지&amp;nbsp;확인합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713347041407&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl get nodes --show-labels&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;결과&lt;/p&gt;
&lt;pre id=&quot;code_1713347048992&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;NAME                                               STATUS   ROLES    AGE   VERSION               LABELS
ip-10-100-39-3.ap-northeast-3.compute.internal   Ready    &amp;lt;none&amp;gt;   52m   v1.28.5-eks-5e0fdde   ...,tier=front
ip-10-100-42-191.ap-northeast-3.compute.internal   Ready    &amp;lt;none&amp;gt;   52m   v1.28.5-eks-5e0fdde   ...,tier=front
ip-10-100-46-137.ap-northeast-3.compute.internal   Ready    &amp;lt;none&amp;gt;   52m   v1.28.5-eks-5e0fdde   ...,tier=back
ip-10-100-49-146.ap-northeast-3.compute.internal   Ready    &amp;lt;none&amp;gt;   52m   v1.28.5-eks-5e0fdde   ...,tier=back
ip-10-100-50-238.ap-northeast-3.compute.internal   Ready    &amp;lt;none&amp;gt;   52m   v1.28.5-eks-5e0fdde   ...,kubernetes.io/host=worker5&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Node Affinity&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Required Affinity&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Required Affinity는 Pod가 특정 Label이 있는 노드에만 스케줄되어야 할 때 사용합니다. 아래는 총 2개의 Statefulset을 배포하는 Yaml파일 이고, front Pod는 `requiredDuringSchedulingIgnoredDuringExecution` 옵션을 통해 nginx-front Statefulset은 `tier=front` 라벨이 적용된 워커노드에만 배포하고 , nginx-back Statefulset은 `tier=back` 라벨이 적용된 워커노드에만 배포하게 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713347096371&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nginx-front
spec:
  replicas: 2
  serviceName: nginx-front
  selector:
    matchLabels:
      app: nginx-front
  template:
    metadata:
      labels:
        app: nginx-front
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: tier
                operator: In
                values:
                - front
      containers:
      - name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nginx-back
spec:
  replicas: 2
  serviceName: nginx-back
  selector:
    matchLabels:
      app: nginx-back
  template:
    metadata:
      labels:
        app: nginx-back
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: tier
                operator: In
                values:
                - back
      containers:
      - name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;위&amp;nbsp;yaml&amp;nbsp;파일을&amp;nbsp;배포하면&amp;nbsp;아래와&amp;nbsp;같이&amp;nbsp;front&amp;nbsp;Statefulset은&amp;nbsp;`tier=front`&amp;nbsp;Label을&amp;nbsp;가지고&amp;nbsp;있는&amp;nbsp;워커노드,&amp;nbsp;back&amp;nbsp;Statefulset은&amp;nbsp;`tier=back`&amp;nbsp;Label을&amp;nbsp;가지고&amp;nbsp;있는&amp;nbsp;워커노드에&amp;nbsp;배치된&amp;nbsp;것을&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있습니다. &lt;br /&gt;&lt;br /&gt;배포&lt;/p&gt;
&lt;pre id=&quot;code_1713347107308&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl apply -f Nodeaffinity.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;확인&lt;/p&gt;
&lt;pre id=&quot;code_1713347120167&quot; class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;kubectl get pod -o wide&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;결과&lt;/p&gt;
&lt;pre id=&quot;code_1713347132617&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;NAME            READY   STATUS    RESTARTS   AGE   IP              NODE                                               NOMINATED NODE   READINESS GATES
nginx-back-0    1/1     Running   0          19s   10.100.32.197   ip-10-100-46-137.ap-northeast-3.compute.internal   &amp;lt;none&amp;gt;           &amp;lt;none&amp;gt;
nginx-back-1    1/1     Running   0          18s   10.100.61.48    ip-10-100-49-146.ap-northeast-3.compute.internal   &amp;lt;none&amp;gt;           &amp;lt;none&amp;gt;
nginx-front-0   1/1     Running   0          19s   10.100.33.132   ip-10-100-39-3.ap-northeast-3.compute.internal     &amp;lt;none&amp;gt;           &amp;lt;none&amp;gt;
nginx-front-1   1/1     Running   0          18s   10.100.32.87    ip-10-100-42-191.ap-northeast-3.compute.internal   &amp;lt;none&amp;gt;           &amp;lt;none&amp;gt;&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;Preferred Affinity&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Preferred&amp;nbsp;Affinity는&amp;nbsp;Pod를&amp;nbsp;배포할&amp;nbsp;때&amp;nbsp;특정&amp;nbsp;Label이&amp;nbsp;있는&amp;nbsp;노드를&amp;nbsp;선호한다는&amp;nbsp;것을&amp;nbsp;의미합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713347159551&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nginx-front
spec:
  replicas: 2
  serviceName: nginx-front
  selector:
    matchLabels:
      app: nginx-front
  template:
    metadata:
      labels:
        app: nginx-front
    spec:
      affinity:
        nodeAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 1
            preference:
              matchExpressions:
              - key: tier
                operator: In
                values:
                - front
      containers:
      - name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nginx-back
spec:
  replicas: 2
  serviceName: nginx-back
  selector:
    matchLabels:
      app: nginx-back
  template:
    metadata:
      labels:
        app: nginx-back
    spec:
      affinity:
        nodeAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 1
            preference:
              matchExpressions:
              - key: tier
                operator: In
                values:
                - back
      containers:
      - name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent&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;위&amp;nbsp;yaml&amp;nbsp;파일을&amp;nbsp;배포하면&amp;nbsp;아래와&amp;nbsp;같이&amp;nbsp;front&amp;nbsp;Statefulset은&amp;nbsp;`tier=front`&amp;nbsp;Label을&amp;nbsp;가지고&amp;nbsp;있는&amp;nbsp;워커노드,&amp;nbsp;back&amp;nbsp;Statefulset은&amp;nbsp;`tier=back`&amp;nbsp;Label을&amp;nbsp;가지고&amp;nbsp;있는&amp;nbsp;워커노드에&amp;nbsp;배치된&amp;nbsp;것을&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있습니다. &lt;br /&gt;&lt;br /&gt;배포&lt;/p&gt;
&lt;pre id=&quot;code_1713347169268&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl apply -f Nodeaffinity_preferrd.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;확인&lt;/p&gt;
&lt;pre id=&quot;code_1713347175860&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl get pod -o wide&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;결과&lt;/p&gt;
&lt;pre id=&quot;code_1713347182927&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;NAME            READY   STATUS    RESTARTS   AGE   IP              NODE                                               NOMINATED NODE   READINESS GATES
nginx-back-0    1/1     Running   0          30s   10.100.45.24    ip-10-100-46-137.ap-northeast-3.compute.internal   &amp;lt;none&amp;gt;           &amp;lt;none&amp;gt;
nginx-back-1    1/1     Running   0          29s   10.100.52.149   ip-10-100-49-146.ap-northeast-3.compute.internal   &amp;lt;none&amp;gt;           &amp;lt;none&amp;gt;
nginx-front-0   1/1     Running   0          30s   10.100.34.117   ip-10-100-39-3.ap-northeast-3.compute.internal     &amp;lt;none&amp;gt;           &amp;lt;none&amp;gt;
nginx-front-1   1/1     Running   0          30s   10.100.39.16    ip-10-100-42-191.ap-northeast-3.compute.internal   &amp;lt;none&amp;gt;           &amp;lt;none&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Required Affinity VS Preferred Affinity&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Required와&amp;nbsp;Prefferd의&amp;nbsp;핵심적인&amp;nbsp;차이는&amp;nbsp;필수(강력),&amp;nbsp;선호(유연)&amp;nbsp;입니다.&amp;nbsp;워커노드에&amp;nbsp;더이상&amp;nbsp;Pod를&amp;nbsp;할당할&amp;nbsp;수&amp;nbsp;없는&amp;nbsp;상황이&amp;nbsp;왔을&amp;nbsp;때&amp;nbsp;Required는&amp;nbsp;해당&amp;nbsp;Label이&amp;nbsp;없는&amp;nbsp;워커노드에&amp;nbsp;배치가&amp;nbsp;안되지만&amp;nbsp;Prefferd의&amp;nbsp;경우&amp;nbsp;Label이&amp;nbsp;없는&amp;nbsp;워커노드에도&amp;nbsp;배치가&amp;nbsp;가능합니다. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Required 방식 |&amp;nbsp;&lt;/b&gt;&lt;br /&gt;아래는 Reqired 방식으로 Replicas를 늘렸을 때의 결과 입니다. 두 대의 워커노드에 더이상 Pod를 배치할 수 없는 상황이 오면, Pod는 Pending 상태로 멈춰있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713347214994&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;NAME             READY   STATUS    RESTARTS   AGE     IP              NODE                                               NOMINATED NODE   READINESS GATES
nginx-back-0     1/1     Running   0          7m54s   10.100.37.243   ip-10-100-46-137.ap-northeast-3.compute.internal   &amp;lt;none&amp;gt;           &amp;lt;none&amp;gt;
...
nginx-back-29    0/1     Pending   0          6m44s   &amp;lt;none&amp;gt;          &amp;lt;none&amp;gt;                                             &amp;lt;none&amp;gt;           &amp;lt;none&amp;gt;
nginx-front-0    1/1     Running   0          7m54s   10.100.33.132   ip-10-100-39-3.ap-northeast-3.compute.internal     &amp;lt;none&amp;gt;           &amp;lt;none&amp;gt;
...
nginx-front-29   0/1     Pending   0          7m10s   &amp;lt;none&amp;gt;          &amp;lt;none&amp;gt;                                             &amp;lt;none&amp;gt;           &amp;lt;none&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;b&gt;Preferred 방식 |&amp;nbsp;&lt;/b&gt;&lt;br /&gt;반면&amp;nbsp;Preferred&amp;nbsp;방식은&amp;nbsp;Replicas를&amp;nbsp;늘려&amp;nbsp;두&amp;nbsp;대의&amp;nbsp;워커노드에&amp;nbsp;더이상&amp;nbsp;Pod를&amp;nbsp;배치할&amp;nbsp;수&amp;nbsp;없는&amp;nbsp;상황이&amp;nbsp;왔을&amp;nbsp;때,&amp;nbsp;특정&amp;nbsp;Label이&amp;nbsp;없는&amp;nbsp;워커노드에도&amp;nbsp;정상적으로&amp;nbsp;배치되는&amp;nbsp;모습을&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713347236123&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;NAME             READY   STATUS    RESTARTS   AGE   IP              NODE                                               NOMINATED NODE   READINESS GATES
nginx-back-0     1/1     Running   0          89s   10.100.37.243   ip-10-100-46-137.ap-northeast-3.compute.internal   &amp;lt;none&amp;gt;           &amp;lt;none&amp;gt;
...
nginx-back-34    1/1     Running   0          35s   10.100.54.249   ip-10-100-50-238.ap-northeast-3.compute.internal   &amp;lt;none&amp;gt;           &amp;lt;none&amp;gt;
nginx-front-0    1/1     Running   0          89s   10.100.33.132   ip-10-100-39-3.ap-northeast-3.compute.internal     &amp;lt;none&amp;gt;           &amp;lt;none&amp;gt;
...
nginx-front-34   1/1     Running   0          17s   10.100.55.198   ip-10-100-50-238.ap-northeast-3.compute.internal   &amp;lt;none&amp;gt;           &amp;lt;none&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;참고&lt;/p&gt;
&lt;figure id=&quot;og_1713347261462&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;노드에 파드 할당하기&quot; data-og-description=&quot;특정한 노드(들) 집합에서만 동작하거나 특정한 노드 집합에서 동작하는 것을 선호하도록 파드를 제한할 수 있다. 이를 수행하는 방법에는 여러 가지가 있으며 권장되는 접근 방식은 모두 레이&quot; data-og-host=&quot;kubernetes.io&quot; data-og-source-url=&quot;https://kubernetes.io/ko/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity&quot; data-og-url=&quot;https://kubernetes.io/ko/docs/concepts/scheduling-eviction/assign-pod-node/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/fnoE1/hyVPNKTmER/IFMluB6eZLu4opGiHklnuk/img.png?width=1727&amp;amp;height=373&amp;amp;face=0_0_1727_373,https://scrap.kakaocdn.net/dn/clScM8/hyVPLfe4Dx/rOXRun703yR8xqZ9jrJoDk/img.png?width=512&amp;amp;height=512&amp;amp;face=0_0_512_512&quot;&gt;&lt;a href=&quot;https://kubernetes.io/ko/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://kubernetes.io/ko/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/fnoE1/hyVPNKTmER/IFMluB6eZLu4opGiHklnuk/img.png?width=1727&amp;amp;height=373&amp;amp;face=0_0_1727_373,https://scrap.kakaocdn.net/dn/clScM8/hyVPLfe4Dx/rOXRun703yR8xqZ9jrJoDk/img.png?width=512&amp;amp;height=512&amp;amp;face=0_0_512_512');&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;노드에 파드 할당하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;특정한 노드(들) 집합에서만 동작하거나 특정한 노드 집합에서 동작하는 것을 선호하도록 파드를 제한할 수 있다. 이를 수행하는 방법에는 여러 가지가 있으며 권장되는 접근 방식은 모두 레이&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>클라우드</category>
      <author>junkmm</author>
      <guid isPermaLink="true">https://junkmm.tistory.com/39</guid>
      <comments>https://junkmm.tistory.com/39#entry39comment</comments>
      <pubDate>Wed, 17 Apr 2024 18:48:50 +0900</pubDate>
    </item>
    <item>
      <title>[Nginx] 사설 인증서로 Proxy 구성하기</title>
      <link>https://junkmm.tistory.com/38</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;개요&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근 프로젝트 진행 중 &lt;span style=&quot;letter-spacing: 0px;&quot;&gt;Nginx Proxy 구성 요청을 받아 진행했던 기록을 남깁니다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;문제점&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트에서 인터넷에 운영중인 Web-server에 접근하고 싶어 했으나. 기본적으로 On-prem 환경에서 인터넷 접근이 보안상 불가한 상황이었습니다. 따라서, DX로 연결된 AWS를 통해 Nginx Proxy를 구성하고, AWS 경유해 인터넷에 운영중인 Web-server에 접근하기를 원했습니다. &lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1287&quot; data-origin-height=&quot;404&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YiD0o/btsGEqLpI9G/UBXHohb68NsOY09fJx0ys1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YiD0o/btsGEqLpI9G/UBXHohb68NsOY09fJx0ys1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YiD0o/btsGEqLpI9G/UBXHohb68NsOY09fJx0ys1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYiD0o%2FbtsGEqLpI9G%2FUBXHohb68NsOY09fJx0ys1%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;1287&quot; height=&quot;404&quot; data-origin-width=&quot;1287&quot; data-origin-height=&quot;404&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;요구사항&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1.&amp;nbsp;Client는&amp;nbsp;Nginx&amp;nbsp;Proxy를&amp;nbsp;통해&amp;nbsp;Public&amp;nbsp;Web-server에&amp;nbsp;접근&amp;nbsp;가능해야&amp;nbsp;합니다. &lt;br /&gt;2.&amp;nbsp;사용하는&amp;nbsp;도메인&amp;nbsp;주소는&amp;nbsp;총&amp;nbsp;3개&amp;nbsp;입니다. &lt;br /&gt;3.&amp;nbsp;Client&amp;nbsp;-&amp;nbsp;Nginx&amp;nbsp;-&amp;nbsp;Origin&amp;nbsp;Web&amp;nbsp;간의&amp;nbsp;통신은&amp;nbsp;HTTPS(보안&amp;nbsp;웹),&amp;nbsp;WSS(보안&amp;nbsp;웹소켓)을&amp;nbsp;사용해야&amp;nbsp;합니다. &lt;br /&gt;4.&amp;nbsp;Client의&amp;nbsp;요청&amp;nbsp;URL을&amp;nbsp;그대로&amp;nbsp;Origin&amp;nbsp;Web에&amp;nbsp;전달해야&amp;nbsp;합니다. &lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1049&quot; data-origin-height=&quot;658&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dKV1ku/btsGGRul2js/qsiZ8NKZZK1D5fvPlDds5K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dKV1ku/btsGGRul2js/qsiZ8NKZZK1D5fvPlDds5K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dKV1ku/btsGGRul2js/qsiZ8NKZZK1D5fvPlDds5K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdKV1ku%2FbtsGGRul2js%2FqsiZ8NKZZK1D5fvPlDds5K%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;1049&quot; height=&quot;658&quot; data-origin-width=&quot;1049&quot; data-origin-height=&quot;658&quot;/&gt;&lt;/span&gt;&lt;/figure&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;구현 순서&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1.&amp;nbsp;공인&amp;nbsp;인증서를&amp;nbsp;사용하는&amp;nbsp;Web&amp;nbsp;Server,&amp;nbsp;Web&amp;nbsp;Socket&amp;nbsp;Server를&amp;nbsp;구성합니다. &lt;br /&gt;2.&amp;nbsp;Nginx가&amp;nbsp;사용할&amp;nbsp;사설&amp;nbsp;공인인증서를&amp;nbsp;발급하고,&amp;nbsp;클라이언트에&amp;nbsp;적용합니다. &lt;br /&gt;3.&amp;nbsp;Nginx에&amp;nbsp;Proxy를&amp;nbsp;구성합니다. &lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Web, Web Socket 서버 구성 (아키텍터 상 Web-server)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위&amp;nbsp;아키텍처&amp;nbsp;중&amp;nbsp;Web&amp;nbsp;Server&amp;nbsp;구성에&amp;nbsp;관한&amp;nbsp;부분입니다.&amp;nbsp;2대의&amp;nbsp;EC2&amp;nbsp;Instance를&amp;nbsp;사용합니다. &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Nginx Public Web Server&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Nginx&amp;nbsp;서비스를&amp;nbsp;설치하고,&amp;nbsp;Certbot을&amp;nbsp;사용해&amp;nbsp;Let's&amp;nbsp;Encrypt&amp;nbsp;공인인증서&amp;nbsp;발급&amp;nbsp;후&amp;nbsp;HTTPS&amp;nbsp;서비스를&amp;nbsp;게시합니다.&amp;nbsp;이를&amp;nbsp;위해선&amp;nbsp;공인&amp;nbsp;DNS를&amp;nbsp;구성해야&amp;nbsp;합니다.&amp;nbsp;AWS&amp;nbsp;EC2&amp;nbsp;Instance의&amp;nbsp;Amazon&amp;nbsp;Linux&amp;nbsp;2023을&amp;nbsp;사용합니다. &lt;br /&gt;&lt;br /&gt;1.&amp;nbsp;관리자&amp;nbsp;권한을&amp;nbsp;위해&amp;nbsp;`sudo&amp;nbsp;su`를&amp;nbsp;입력합니다. &lt;br /&gt;2.&amp;nbsp;yum&amp;nbsp;패키지를&amp;nbsp;통해&amp;nbsp;nginx를&amp;nbsp;설치하고,&amp;nbsp;systemctl을&amp;nbsp;통해&amp;nbsp;서비스&amp;nbsp;시작&amp;nbsp;및&amp;nbsp;자동&amp;nbsp;시작을&amp;nbsp;등록합니다. &lt;/p&gt;
&lt;pre id=&quot;code_1713317877617&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  yum update
  yum install nginx
  systemctl enable nginx.service
  systemctl restart nginx.service&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;3.&amp;nbsp;(선택사항)&amp;nbsp;`curl&amp;nbsp;localhost`를&amp;nbsp;통해&amp;nbsp;nginx가&amp;nbsp;잘&amp;nbsp;구동중인지&amp;nbsp;확인합니다. &lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;367&quot; data-origin-height=&quot;30&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dIxW08/btsGHjjCEPt/5rCmIToXgnaWBHSRKMnka0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dIxW08/btsGHjjCEPt/5rCmIToXgnaWBHSRKMnka0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dIxW08/btsGHjjCEPt/5rCmIToXgnaWBHSRKMnka0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdIxW08%2FbtsGHjjCEPt%2F5rCmIToXgnaWBHSRKMnka0%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;367&quot; height=&quot;30&quot; data-origin-width=&quot;367&quot; data-origin-height=&quot;30&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;4.&amp;nbsp;DNS&amp;nbsp;A&amp;nbsp;레코드를&amp;nbsp;Nginx&amp;nbsp;서버의&amp;nbsp;공인IP로&amp;nbsp;등록합니다.&amp;nbsp;nslookup을&amp;nbsp;통해&amp;nbsp;조회&amp;nbsp;합니다. &lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;983&quot; data-origin-height=&quot;40&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SNlYY/btsGHckBYt8/a9z3pz7GFF1voFayH7c8tK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SNlYY/btsGHckBYt8/a9z3pz7GFF1voFayH7c8tK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SNlYY/btsGHckBYt8/a9z3pz7GFF1voFayH7c8tK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSNlYY%2FbtsGHckBYt8%2Fa9z3pz7GFF1voFayH7c8tK%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;983&quot; height=&quot;40&quot; data-origin-width=&quot;983&quot; data-origin-height=&quot;40&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;373&quot; data-origin-height=&quot;79&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vo5eb/btsGGXaabRt/ZQPPMjx85Fu5WtWeavY420/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vo5eb/btsGGXaabRt/ZQPPMjx85Fu5WtWeavY420/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vo5eb/btsGGXaabRt/ZQPPMjx85Fu5WtWeavY420/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fvo5eb%2FbtsGGXaabRt%2FZQPPMjx85Fu5WtWeavY420%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;373&quot; height=&quot;79&quot; data-origin-width=&quot;373&quot; data-origin-height=&quot;79&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;5. Certbot을 통해 Lets's Encrypt 공인인증서 발급 및 HTTPS 서비스를 게시합니다. 아래&amp;nbsp;명령으로&amp;nbsp;certbot을&amp;nbsp;설치합니다. &lt;/p&gt;
&lt;pre id=&quot;code_1713317903382&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;yum install certbot python-certbot-nginx&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;nginx&amp;nbsp;구성&amp;nbsp;파일에&amp;nbsp;도메인을&amp;nbsp;등록합니다.&amp;nbsp;/etc/nnginx/conf.d&amp;nbsp;디렉토리에&amp;nbsp;domain-name.conf&amp;nbsp;라는&amp;nbsp;파일을&amp;nbsp;만듭니다.&amp;nbsp;demo.te.kocron.com&amp;nbsp;이라는&amp;nbsp;도메인을&amp;nbsp;사용하는&amp;nbsp;서비스&amp;nbsp;구성으로&amp;nbsp;작성합니다. &lt;/p&gt;
&lt;pre id=&quot;code_1713317912264&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name demo.te.kocron.com;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;Nginx&amp;nbsp;서비스를&amp;nbsp;재기동&amp;nbsp;합니다. &lt;/p&gt;
&lt;pre id=&quot;code_1713317923716&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;systemctl restart nginx.service&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;아래&amp;nbsp;certbot&amp;nbsp;명령으로&amp;nbsp;demo.te.kocron.com에&amp;nbsp;대한&amp;nbsp;도메인&amp;nbsp;등록을&amp;nbsp;진행합니다.&amp;nbsp;이메일&amp;nbsp;주소&amp;nbsp;입력과&amp;nbsp;약관을&amp;nbsp;동의해야&amp;nbsp;합니다. &lt;/p&gt;
&lt;pre id=&quot;code_1713317932892&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;certbot --nginx -d demo.te.kocron.com&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;성공적으로&amp;nbsp;작업이&amp;nbsp;완료되면&amp;nbsp;domain-name.conf&amp;nbsp;에&amp;nbsp;구성파일이&amp;nbsp;아래와&amp;nbsp;같이&amp;nbsp;변경되고,&amp;nbsp;공인인증서를&amp;nbsp;사용하는&amp;nbsp;nginx&amp;nbsp;웹서버가&amp;nbsp;구성됩니다. &lt;/p&gt;
&lt;pre id=&quot;code_1713317947004&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;server {
    server_name demo.te.kocron.com;

    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/demo.te.kocron.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/demo.te.kocron.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}
server {
    if ($host = demo.te.kocron.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

    listen 80 default_server;
    listen [::]:80 default_server;
    server_name demo.te.kocron.com;
    return 404; # managed by Certbot
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;903&quot; data-origin-height=&quot;331&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6EhXM/btsGHjRs3CB/THE373i5rHvj31Tv2fS07K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6EhXM/btsGHjRs3CB/THE373i5rHvj31Tv2fS07K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6EhXM/btsGHjRs3CB/THE373i5rHvj31Tv2fS07K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6EhXM%2FbtsGHjRs3CB%2FTHE373i5rHvj31Tv2fS07K%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;903&quot; height=&quot;331&quot; data-origin-width=&quot;903&quot; data-origin-height=&quot;331&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;`demo1.kocron.com`&amp;nbsp;도메인에&amp;nbsp;대해서도&amp;nbsp;동일하게&amp;nbsp;구성을&amp;nbsp;진행합니다. &lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Web Socket Server&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Web&amp;nbsp;Socket&amp;nbsp;Server는&amp;nbsp;Node.js&amp;nbsp;를&amp;nbsp;통해&amp;nbsp;구동합니다.&amp;nbsp;먼저&amp;nbsp;Node를&amp;nbsp;설치합니다. &lt;/p&gt;
&lt;pre id=&quot;code_1713317971066&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo yum install yum-utils
sudo yum update
sudo yum install g++ make
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
source ~/.bashrc
nvm install --lts
npm install websocket&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;websocket.js&amp;nbsp;파일을&amp;nbsp;생성하고&amp;nbsp;아래&amp;nbsp;코드를&amp;nbsp;붙여&amp;nbsp;넣습니다. &lt;/p&gt;
&lt;pre id=&quot;code_1713317984970&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var WebSocketServer = require('websocket').server;
var http = require('http');
var clients = [];
var idlist = [];
var id = 0;
var array = [];

var server = http.createServer(function(request, response) {
    console.log(new Date() + ' Received request for ' + request.url);
    // 요청 URL 경로가 '/session'인 경우에만 처리
    if (request.url === '/session') {
        console.log(new Date() + ' Received request for session');
        // WebSocket 요청 처리
        wsServer.handleRequest(request, response);
    } else {
        response.writeHead(404);
        response.end();
    }
});
server.listen(9000, function(){
   console.log((new Date()) + 'Server is listening on port 9000')
});

wsServer = new WebSocketServer({
    httpServer: server,
    autoAcceptConnections: false
});

function originIsAllowed(origin) {
    return true;
}

wsServer.on('request', function(request) {
    if (!originIsAllowed(request.origin)) {
        request.reject();
        console.log((new Date()) + 'Connection from origin' + request.origin + 'rejected.');
        return;
    }

    var connection = request.accept(null, request.origin);

    clients.push(connection);
    idlist[request.key] = id++;

    console.log((new Date()) + 'Connection accepted.');
        for(var i=0; i&amp;lt;array.length;i++){
            console.log(array[i]); connection.sendUTF(array[i]);
    }

    connection.on('message', function(message){
        if (message.type === 'utf8'){
            console.log('Received Message: ' + message.utf8Data);
            msg = message.utf8Data;
                        if(msg.indexOf(&quot;move&quot;) != -1){
                            if(array.length &amp;lt; 50000){
                                array.push(msg);
                            }else{
                                array.shift();
                                array.push(msg);
                            }
                        }else if(msg.indexOf(&quot;refresh&quot;) != -1){
                            array = [];
                        }else{

                        }
                        clients.forEach(function(cli){
                            cli.sendUTF(msg);
                });
        }
        else if (message.type ==='binary'){
            console.log('Received Binary Message of' + message.binaryData.length + 'bytes');
        }
    });
    connection.on('close', function(reasonCode,description) {
        console.log((new Date() + 'Peer' + connection.remoteAddress + 'desconnected.'));
    });
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;websock.js&amp;nbsp;파일에&amp;nbsp;실행&amp;nbsp;권한을&amp;nbsp;추가합니다. &lt;/p&gt;
&lt;pre id=&quot;code_1713317994756&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;chmod +x websock.js&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;`node&amp;nbsp;websock.js`명령으로&amp;nbsp;웹소켓&amp;nbsp;서버를&amp;nbsp;실행합니다. &lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;933&quot; data-origin-height=&quot;76&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QcGGm/btsGFi0woVs/OnZvFnWjQJbyvVdeu9vJwk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QcGGm/btsGFi0woVs/OnZvFnWjQJbyvVdeu9vJwk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QcGGm/btsGFi0woVs/OnZvFnWjQJbyvVdeu9vJwk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQcGGm%2FbtsGFi0woVs%2FOnZvFnWjQJbyvVdeu9vJwk%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;933&quot; height=&quot;76&quot; data-origin-width=&quot;933&quot; data-origin-height=&quot;76&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;웹소켓 테스트는 Simple Web Socket Client 크롬 확장 프로그램을 통해 테스트 합니다.&lt;/p&gt;
&lt;figure id=&quot;og_1713318026321&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;WebSocket Test Client&quot; data-og-description=&quot;A Simple tool to help test WebSocket Service&quot; data-og-host=&quot;chromewebstore.google.com&quot; data-og-source-url=&quot;https://chromewebstore.google.com/detail/websocket-test-client/fgponpodhbmadfljofbimhhlengambbn?hl=ko&quot; data-og-url=&quot;https://chromewebstore.google.com/detail/websocket-test-client/fgponpodhbmadfljofbimhhlengambbn&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bTjPE5/hyVSUVPn91/KM0CqJLIjqEwyjfP5mQ6v0/img.jpg?width=128&amp;amp;height=128&amp;amp;face=0_0_128_128&quot;&gt;&lt;a href=&quot;https://chromewebstore.google.com/detail/websocket-test-client/fgponpodhbmadfljofbimhhlengambbn?hl=ko&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://chromewebstore.google.com/detail/websocket-test-client/fgponpodhbmadfljofbimhhlengambbn?hl=ko&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bTjPE5/hyVSUVPn91/KM0CqJLIjqEwyjfP5mQ6v0/img.jpg?width=128&amp;amp;height=128&amp;amp;face=0_0_128_128');&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;WebSocket Test Client&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;A Simple tool to help test WebSocket Service&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;chromewebstore.google.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;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹소켓의&amp;nbsp;경우&amp;nbsp;http&amp;nbsp;-&amp;gt;&amp;nbsp;ws,&amp;nbsp;https&amp;nbsp;-&amp;gt;&amp;nbsp;wss와&amp;nbsp;매핑된다고&amp;nbsp;생각하시면&amp;nbsp;됩니다.&amp;nbsp;원래라면&amp;nbsp;인증서를&amp;nbsp;설정한&amp;nbsp;wss로&amp;nbsp;접근해야&amp;nbsp;하지만,&amp;nbsp;부득이하게&amp;nbsp;ws로&amp;nbsp;테스트&amp;nbsp;합니다.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;server&amp;nbsp;location에&amp;nbsp;web&amp;nbsp;socket&amp;nbsp;서버의&amp;nbsp;주소와&amp;nbsp;포트번호를&amp;nbsp;입력하고,&amp;nbsp;[open]을&amp;nbsp;클릭하면&amp;nbsp;web&amp;nbsp;socket이&amp;nbsp;활성화&amp;nbsp;되며,&amp;nbsp;Request에&amp;nbsp;메시지를&amp;nbsp;입력하고&amp;nbsp;Send를&amp;nbsp;클릭하면&amp;nbsp;Message&amp;nbsp;Log에&amp;nbsp;해당&amp;nbsp;내용이&amp;nbsp;출력되는것을&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있습니다. &lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;358&quot; data-origin-height=&quot;236&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kV2F3/btsGEjMo2Qj/0l7cvlYTj2QG4Ne0HwctFk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kV2F3/btsGEjMo2Qj/0l7cvlYTj2QG4Ne0HwctFk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kV2F3/btsGEjMo2Qj/0l7cvlYTj2QG4Ne0HwctFk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkV2F3%2FbtsGEjMo2Qj%2F0l7cvlYTj2QG4Ne0HwctFk%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;358&quot; height=&quot;236&quot; data-origin-width=&quot;358&quot; data-origin-height=&quot;236&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;h3 data-ke-size=&quot;size23&quot;&gt;Nginx Proxy가 사용할 사설인증서 구성 (아키텍터 상 Nginx에서 작업)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Client&amp;nbsp;&amp;lt;-&amp;gt;&amp;nbsp;Nginx&amp;nbsp;Proxy&amp;nbsp;통신에&amp;nbsp;적용할&amp;nbsp;사설인증서를&amp;nbsp;구성합니다.&amp;nbsp;공인&amp;nbsp;인증서&amp;nbsp;대신&amp;nbsp;사설&amp;nbsp;인증서를&amp;nbsp;사용하다&amp;nbsp;보니,&amp;nbsp;자체&amp;nbsp;CA&amp;nbsp;기관&amp;nbsp;인증서를&amp;nbsp;발급하고,&amp;nbsp;Client&amp;nbsp;단에&amp;nbsp;신뢰할&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;인증기관&amp;nbsp;인증서로&amp;nbsp;설치해야&amp;nbsp;합니다.&amp;nbsp;그&amp;nbsp;후&amp;nbsp;자체&amp;nbsp;CA&amp;nbsp;기관에&amp;nbsp;Nginx가&amp;nbsp;사용할&amp;nbsp;Server&amp;nbsp;인증서에&amp;nbsp;대해&amp;nbsp;서명을&amp;nbsp;요청하고,&amp;nbsp;이를&amp;nbsp;적용합니다.&amp;nbsp;현재&amp;nbsp;Sector에서는&amp;nbsp;자체(root)&amp;nbsp;CA&amp;nbsp;구성&amp;nbsp;및&amp;nbsp;Client&amp;nbsp;설치에&amp;nbsp;대해&amp;nbsp;작성합니다. &lt;br /&gt;&lt;br /&gt;아래&amp;nbsp;구성은&amp;nbsp;Nginx-Proxy&amp;nbsp;서버에서&amp;nbsp;진행해야&amp;nbsp;합니다.&amp;nbsp;위에서&amp;nbsp;구성한&amp;nbsp;서버외&amp;nbsp;별도의&amp;nbsp;EC2&amp;nbsp;Instance에서&amp;nbsp;진행합니다. &lt;br /&gt;&lt;br /&gt;우선&amp;nbsp;Self-sigend&amp;nbsp;root&amp;nbsp;CA를&amp;nbsp;발급합니다.&amp;nbsp;`Enter&amp;nbsp;PEM&amp;nbsp;pass&amp;nbsp;phrase&amp;nbsp;:`&amp;nbsp;문구가&amp;nbsp;나오면&amp;nbsp;비밀번호를&amp;nbsp;입력합니다. &lt;/p&gt;
&lt;pre id=&quot;code_1713318060671&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cd ~ # /home/ec2-user 경로 입니다.
mkdir ssl &amp;amp;&amp;amp; cd ssl
openssl genrsa -des3 -out localCA.key 2048&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;941&quot; data-origin-height=&quot;105&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dJbG9z/btsGGYGSTHz/VtUFkoqxJ1jfdupvNl2ck0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dJbG9z/btsGGYGSTHz/VtUFkoqxJ1jfdupvNl2ck0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dJbG9z/btsGGYGSTHz/VtUFkoqxJ1jfdupvNl2ck0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdJbG9z%2FbtsGGYGSTHz%2FVtUFkoqxJ1jfdupvNl2ck0%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;941&quot; height=&quot;105&quot; data-origin-width=&quot;941&quot; data-origin-height=&quot;105&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;`localCA.key`파일이 생성되면 private key를 이용해서 root CA 인증서를 아래 명령어로 생성합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713318070499&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;openssl req -x509 -new -nodes -key localCA.key -sha256 -days 365 -out localCA.pem&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;인증서&amp;nbsp;구성&amp;nbsp;정보를&amp;nbsp;아래와&amp;nbsp;같이&amp;nbsp;입력합니다.&amp;nbsp;`te.kocron.com`&amp;nbsp;도메인을&amp;nbsp;사용하는&amp;nbsp;예시&amp;nbsp;입니다. &lt;/p&gt;
&lt;pre id=&quot;code_1713318086204&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Enter pass phrase for localCA.key:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:KR
State or Province Name (full name) []:Seoul
Locality Name (eg, city) [Default City]:Shindo-rim
Organization Name (eg, company) [Default Company Ltd]:Cloudmt
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:*.te.kocron.com
Email Address []:demo@cloudmt.co.kr&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;윈도우&amp;nbsp;클라이언트에&amp;nbsp;인증서를&amp;nbsp;설치하기&amp;nbsp;위해&amp;nbsp;`.pem`&amp;nbsp;파일을&amp;nbsp;`.crt`&amp;nbsp;파일로&amp;nbsp;추출&amp;nbsp;합니다. &lt;/p&gt;
&lt;pre id=&quot;code_1713318094434&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;openssl x509 -outform der -in localCA.pem -out localCA.crt&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;변환된&amp;nbsp;`.crt`&amp;nbsp;파일을&amp;nbsp;scp를&amp;nbsp;사용해&amp;nbsp;Windows&amp;nbsp;Client에&amp;nbsp;옮겨준&amp;nbsp;뒤&amp;nbsp;인증서를&amp;nbsp;설치합니다. &lt;/p&gt;
&lt;pre id=&quot;code_1713318307103&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;scp -i hakjun_osaka.pem ec2-user@13.208.245.223:/home/ec2-user/ssl/localCA.crt .&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;Windows로 옮긴 localCA.crt 파일을 실행하고, 다음과 같이 설치합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;465&quot; data-origin-height=&quot;585&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cm2nwD/btsGFqxogab/sceoXsRl5eFfrgr80Jswu1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cm2nwD/btsGFqxogab/sceoXsRl5eFfrgr80Jswu1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cm2nwD/btsGFqxogab/sceoXsRl5eFfrgr80Jswu1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcm2nwD%2FbtsGFqxogab%2FsceoXsRl5eFfrgr80Jswu1%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;465&quot; height=&quot;585&quot; data-origin-width=&quot;465&quot; data-origin-height=&quot;585&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;615&quot; data-origin-height=&quot;573&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cE4zdH/btsGGcFw0vU/CDWXNpw0Adui1Ctj97UJak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cE4zdH/btsGGcFw0vU/CDWXNpw0Adui1Ctj97UJak/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cE4zdH/btsGGcFw0vU/CDWXNpw0Adui1Ctj97UJak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcE4zdH%2FbtsGGcFw0vU%2FCDWXNpw0Adui1Ctj97UJak%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;615&quot; height=&quot;573&quot; data-origin-width=&quot;615&quot; data-origin-height=&quot;573&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;615&quot; data-origin-height=&quot;611&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oLcG0/btsGFq5depQ/d5VO53dMSjyJ1DnvwWezek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oLcG0/btsGFq5depQ/d5VO53dMSjyJ1DnvwWezek/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oLcG0/btsGFq5depQ/d5VO53dMSjyJ1DnvwWezek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoLcG0%2FbtsGFq5depQ%2Fd5VO53dMSjyJ1DnvwWezek%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;615&quot; height=&quot;611&quot; data-origin-width=&quot;615&quot; data-origin-height=&quot;611&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;615&quot; data-origin-height=&quot;574&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tZnpQ/btsGGjR2EgG/30aGCjwVgODCYKjm27azpk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tZnpQ/btsGGjR2EgG/30aGCjwVgODCYKjm27azpk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tZnpQ/btsGGjR2EgG/30aGCjwVgODCYKjm27azpk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtZnpQ%2FbtsGGjR2EgG%2F30aGCjwVgODCYKjm27azpk%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;615&quot; height=&quot;574&quot; data-origin-width=&quot;615&quot; data-origin-height=&quot;574&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;h3 data-ke-size=&quot;size23&quot;&gt;Nginx Proxy 구성하기 (아키텍터 상 Nginx에서 작업)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 Self-signed CA를 구성한 EC2 Instance에서 Nginx를 설치하고, Proxy 기능을 구현합니다. 먼저 아래 명령으로 Nginx 서버를 설치합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713318339008&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  yum update
  yum install nginx
  systemctl enable nginx.service
  systemctl restart nginx.service&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;https&amp;nbsp;및&amp;nbsp;wss를&amp;nbsp;사용하기&amp;nbsp;위한&amp;nbsp;서버&amp;nbsp;인증서를&amp;nbsp;발급한&amp;nbsp;뒤&amp;nbsp;Self-signed&amp;nbsp;CA에게&amp;nbsp;서명&amp;nbsp;요청을&amp;nbsp;진행합니다. &lt;/p&gt;
&lt;pre id=&quot;code_1713318349493&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cd ~
cd ssl
openssl genrsa -out server.key 2048&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;CSR을&amp;nbsp;생성합니다. &lt;/p&gt;
&lt;pre id=&quot;code_1713318356577&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;openssl req -new -key server.key -out server.csr&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;938&quot; data-origin-height=&quot;344&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dA6dGK/btsGIfug0ch/TCCWvW4Rs2d0LFM3YCJTS0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dA6dGK/btsGIfug0ch/TCCWvW4Rs2d0LFM3YCJTS0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dA6dGK/btsGIfug0ch/TCCWvW4Rs2d0LFM3YCJTS0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdA6dGK%2FbtsGIfug0ch%2FTCCWvW4Rs2d0LFM3YCJTS0%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;938&quot; height=&quot;344&quot; data-origin-width=&quot;938&quot; data-origin-height=&quot;344&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;`vim&amp;nbsp;server.ext`를&amp;nbsp;통해&amp;nbsp;CA에&amp;nbsp;인증요청&amp;nbsp;시&amp;nbsp;참고&amp;nbsp;정보를&amp;nbsp;작성합니다.&amp;nbsp;[alt_names]에서&amp;nbsp;사용할&amp;nbsp;도메인&amp;nbsp;주소를&amp;nbsp;입력합니다. &lt;/p&gt;
&lt;pre id=&quot;code_1713318365937&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = demo.te.kocron.com
DNS.2 = demo1.te.kocron.com
DNS.3 = demo2.te.kocron.com&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;아래 명령을 수행하여 pass pharese를 입력면 `demo.te.kocron.com`, `demo1.te.kocron.com`, `demo2.te.kocron.com` 호스트를 `te.kocron.com` CA가 인증하는 인증서를 발급받을 수 있습니다. &lt;/p&gt;
&lt;pre id=&quot;code_1713318415148&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;openssl x509 -req -in server.csr -CA localCA.pem -CAkey localCA.key \
-CAcreateserial -out server.crt -days 365 -sha256 -extfile server.ext&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;938&quot; data-origin-height=&quot;181&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cXLTiv/btsGFy9TPoR/zlvvKIXCk6vn4r1iAsnRr0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cXLTiv/btsGFy9TPoR/zlvvKIXCk6vn4r1iAsnRr0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cXLTiv/btsGFy9TPoR/zlvvKIXCk6vn4r1iAsnRr0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcXLTiv%2FbtsGFy9TPoR%2FzlvvKIXCk6vn4r1iAsnRr0%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;938&quot; height=&quot;181&quot; data-origin-width=&quot;938&quot; data-origin-height=&quot;181&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;Nginx&amp;nbsp;Proxy가&amp;nbsp;사용할&amp;nbsp;Private&amp;nbsp;인증서&amp;nbsp;발급은&amp;nbsp;완료되었으니,&amp;nbsp;Nginx&amp;nbsp;Proxy&amp;nbsp;구성을&amp;nbsp;진행합니다. &lt;br /&gt;우선&amp;nbsp;생성한&amp;nbsp;인증서를&amp;nbsp;nginx&amp;nbsp;폴더에&amp;nbsp;붙여넣습니다.&amp;nbsp;지금&amp;nbsp;부턴&amp;nbsp;`sudo&amp;nbsp;su`로&amp;nbsp;root&amp;nbsp;권한으로&amp;nbsp;진행합니다. &lt;/p&gt;
&lt;pre id=&quot;code_1713318440385&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo su
cp -arp /home/ec2-user/ssl/ /etc/nginx/
cd /etc/nginx/conf.d&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;`vi server.conf`를 통해 proxy를 구성합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713318455350&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# nginx가 https 요청을 web socket으로 변환하기 위한 변수로 사용됩니다.
map $http_upgrade $connection_upgrade {
        default upgrade;
        '' close;
    }
# upstream은 proxy 대상의 Pool을 지정합니다.
upstream websocket {
        server demo2.te.kocron.com:9000;
    }

server {
# 443 ssl, demo2.te.kocron.com으로 들어오는 패킷에 대해 처리합니다.
        listen 443 ssl;
        server_name  demo2.te.kocron.com;
# ssl 통신을 위한 인증서 구성입니다. rootCA에게 서명받은 인증서 경로를 설정합니다.
        ssl_certificate &quot;/etc/nginx/ssl/server.crt&quot;;
        ssl_certificate_key &quot;/etc/nginx/ssl/server.key&quot;;
        ssl_session_cache shared:SSL:1m;
        ssl_session_timeout  10m;
        ssl_prefer_server_ciphers on;

# client로 부터 요청받은 모든 URL에 대해 proxy_pass로 http://websocket을 보냅니다.
# websocket은 인증서 적용이 되어있지 않아 http로 구성되었습니다.
        location ~ ^/.*$ {
            proxy_pass http://websocket;
# http -&amp;gt; websocket으로 변환하기 위해 header를 변경합니다.
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
            proxy_set_header Host $host;
            access_log /var/log/nginx/websocket.log;
        }
    }

server {
# 443 ssl, demo.te.kocron.com으로 들어오는 패킷에 대해 처리합니다.
        listen       443 ssl http2;
        listen       [::]:443 ssl http2;
        server_name  demo.te.kocron.com;
# ssl 통신을 위한 인증서 구성입니다. rootCA에게 서명받은 인증서 경로를 설정합니다.
        ssl_certificate &quot;/etc/nginx/ssl/server.crt&quot;;
        ssl_certificate_key &quot;/etc/nginx/ssl/server.key&quot;;
        ssl_session_cache shared:SSL:1m;
        ssl_session_timeout  10m;
        ssl_prefer_server_ciphers on;
# client로 부터 요청받은 모든 URL에 대해 proxy_pass를 사용해 https://demo.te.kocron.com 쪽으로 보냅니다.
        location ~ ^/.*$ {
          proxy_pass https://demo.te.kocron.com;
          proxy_set_header Host $host;
        }
    }

    server {
        listen       443 ssl http2;
        listen       [::]:443 ssl http2;
        server_name  demo1.te.kocron.com;

        ssl_certificate &quot;/etc/nginx/ssl/server.crt&quot;;
        ssl_certificate_key &quot;/etc/nginx/ssl/server.key&quot;;
        ssl_session_cache shared:SSL:1m;
        ssl_session_timeout  10m;
        ssl_prefer_server_ciphers on;

        location = / {
          proxy_pass https://demo1.te.kocron.com/;
          proxy_set_header Host $host;
        }
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;nginx를&amp;nbsp;재기동&amp;nbsp;합니다. &lt;/p&gt;
&lt;pre id=&quot;code_1713318466110&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;systemctl restart nginx.service&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;Windows의&amp;nbsp;hosts파일을&amp;nbsp;수정합니다.&amp;nbsp;`C:\Windows\System32\drivers\etc\hosts`&amp;nbsp;경로에서&amp;nbsp;아래&amp;nbsp;내용을&amp;nbsp;추가합니다.(관리자&amp;nbsp;권한) &lt;/p&gt;
&lt;pre id=&quot;code_1713318485948&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Copyright (c) 1993-2009 Microsoft Corp.
---생략---
13.208.164.94 demo.te.kocron.com demo1.te.kocron.com demo2.te.kocron.com&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;웹&amp;nbsp;브라우저로&amp;nbsp;demo.te.kocron에&amp;nbsp;접속해&amp;nbsp;사설인증서로&amp;nbsp;https&amp;nbsp;접근이&amp;nbsp;가능함을&amp;nbsp;확인합니다. &lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1089&quot; data-origin-height=&quot;637&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcNj2g/btsGG0q988C/PAvcLzeiRXkRe3k61WiUiK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcNj2g/btsGG0q988C/PAvcLzeiRXkRe3k61WiUiK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcNj2g/btsGG0q988C/PAvcLzeiRXkRe3k61WiUiK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcNj2g%2FbtsGG0q988C%2FPAvcLzeiRXkRe3k61WiUiK%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;1089&quot; height=&quot;637&quot; data-origin-width=&quot;1089&quot; data-origin-height=&quot;637&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;Proxy의&amp;nbsp;Access&amp;nbsp;log를&amp;nbsp;확인해보면&amp;nbsp;클라이언트&amp;nbsp;요청을&amp;nbsp;304&amp;nbsp;Redirect&amp;nbsp;한&amp;nbsp;것을&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있고 &lt;/p&gt;
&lt;pre id=&quot;code_1713318496322&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;211.44.192.110 - - [11/Apr/2024:02:08:31 +0000] &quot;GET / HTTP/2.0&quot; 304 0 &quot;-&quot; &quot;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.0.0&quot; &quot;-&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;Origin&amp;nbsp;Web-server의&amp;nbsp;Access&amp;nbsp;log를&amp;nbsp;확인해보면&amp;nbsp;Proxy로부터&amp;nbsp;요청받아&amp;nbsp;응답하는것을&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있습니다. &lt;/p&gt;
&lt;pre id=&quot;code_1713318504550&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;13.208.164.94 - - [11/Apr/2024:02:08:31 +0000] &quot;GET / HTTP/1.0&quot; 304 0 &quot;-&quot; &quot;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.0.0&quot; &quot;-&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>운영체제</category>
      <category>cert-bot</category>
      <category>HTTPS</category>
      <category>Nginx</category>
      <category>proxy</category>
      <author>junkmm</author>
      <guid isPermaLink="true">https://junkmm.tistory.com/38</guid>
      <comments>https://junkmm.tistory.com/38#entry38comment</comments>
      <pubDate>Wed, 17 Apr 2024 11:03:40 +0900</pubDate>
    </item>
    <item>
      <title>[EKS] CI/CD</title>
      <link>https://junkmm.tistory.com/37</link>
      <description>&lt;blockquote data-ke-style=&quot;style2&quot;&gt;이번 게시글은 가시다님의 AEWS [2기] 스터디 내용을 정리한 포스트 입니다.&lt;br /&gt;이번 게시글은 7 주차의 스터디 내용인 EKS CI/CD에 대해 살펴봅니다.&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;EKS 배포&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실습을 위해 EKS 클러스터를 배포합니다. AWS 콘솔에 로그인 한 뒤 CloudFormation에서 아래 YAML 파일로 스택을 생성하시면 됩니다. 진행 과정은 아래 링크를 참고해 주세요.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignLeft&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/bAtYN0/btsGGeiPupI/QNUAc2IaMyWHLdPSMSfu0K/eks-oneclick6.yaml?attach=1&amp;amp;knm=tfile.yaml&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;eks-oneclick6.yaml&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.02MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1713261663258&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;[EKS] Networking&quot; data-og-description=&quot;이번 게시글은 가시다님의 AEWS [2기] 스터디 내용을 정리한 포스트 입니다. 이번 게시글은 2 주차의 스터디 내용인 EKS Networking에 대해 살펴봅니다. EKS 원클릭 배포 사전 준비 AWS 계정 SSH 키 페어 IA&quot; data-og-host=&quot;junkmm.tistory.com&quot; data-og-source-url=&quot;https://junkmm.tistory.com/32&quot; data-og-url=&quot;https://junkmm.tistory.com/32&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bbIYhx/hyVPYyE7tH/VD0WrEfd8dpL7A5Ivb9Alk/img.png?width=800&amp;amp;height=411&amp;amp;face=0_0_800_411,https://scrap.kakaocdn.net/dn/Kq0XP/hyVPYyE7yY/VTLayZObKNpsX9Ht4LqPg0/img.png?width=800&amp;amp;height=411&amp;amp;face=0_0_800_411,https://scrap.kakaocdn.net/dn/SpKQE/hyVPIP9inf/0mRfOvN0lVuAxBVNKIiHVK/img.png?width=2060&amp;amp;height=1226&amp;amp;face=0_0_2060_1226&quot;&gt;&lt;a href=&quot;https://junkmm.tistory.com/32&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://junkmm.tistory.com/32&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bbIYhx/hyVPYyE7tH/VD0WrEfd8dpL7A5Ivb9Alk/img.png?width=800&amp;amp;height=411&amp;amp;face=0_0_800_411,https://scrap.kakaocdn.net/dn/Kq0XP/hyVPYyE7yY/VTLayZObKNpsX9Ht4LqPg0/img.png?width=800&amp;amp;height=411&amp;amp;face=0_0_800_411,https://scrap.kakaocdn.net/dn/SpKQE/hyVPIP9inf/0mRfOvN0lVuAxBVNKIiHVK/img.png?width=2060&amp;amp;height=1226&amp;amp;face=0_0_2060_1226');&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;[EKS] Networking&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이번 게시글은 가시다님의 AEWS [2기] 스터디 내용을 정리한 포스트 입니다. 이번 게시글은 2 주차의 스터디 내용인 EKS Networking에 대해 살펴봅니다. EKS 원클릭 배포 사전 준비 AWS 계정 SSH 키 페어 IA&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;junkmm.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;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;배포 확인&lt;/h3&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;p data-ke-size=&quot;size16&quot;&gt;Bastion EC2 인스턴스의 공인 IP로 SSH 접근을 시도합니다. 공인 IP는 CloudFormation의 결과에 나오는 출력값 혹은 EC2 메뉴에서 bastion 호스트의 공인IP를 확인합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713261723392&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# ssh -i &quot;Keyname&quot; ec2-user@&quot;Public IP&quot;
ssh -i hj42700eks.pem ec2-user@3.36.133.15&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;Bastion 접속 후 아래와 같이 기본 설정을 진행합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713261824139&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# default 네임스페이스 적용
kubectl ns default

# 노드 정보 확인 : t3.medium
kubectl get node --label-columns=node.kubernetes.io/instance-type,eks.amazonaws.com/capacityType,topology.kubernetes.io/zone

# ExternalDNS
MyDomain=&amp;lt;자신의 도메인&amp;gt;
echo &quot;export MyDomain=&amp;lt;자신의 도메인&amp;gt;&quot; &amp;gt;&amp;gt; /etc/profile
MyDomain=junkmm.site
echo &quot;export MyDomain=junkmm.site&quot; &amp;gt;&amp;gt; /etc/profile
MyDnzHostedZoneId=$(aws route53 list-hosted-zones-by-name --dns-name &quot;${MyDomain}.&quot; --query &quot;HostedZones[0].Id&quot; --output text)
echo $MyDomain, $MyDnzHostedZoneId
curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/aews/externaldns.yaml
MyDomain=$MyDomain MyDnzHostedZoneId=$MyDnzHostedZoneId envsubst &amp;lt; externaldns.yaml | kubectl apply -f -

# kube-ops-view
helm repo add geek-cookbook https://geek-cookbook.github.io/charts/
helm install kube-ops-view geek-cookbook/kube-ops-view --version 1.2.2 --set env.TZ=&quot;Asia/Seoul&quot; --namespace kube-system
kubectl patch svc -n kube-system kube-ops-view -p '{&quot;spec&quot;:{&quot;type&quot;:&quot;LoadBalancer&quot;}}'
kubectl annotate service kube-ops-view -n kube-system &quot;external-dns.alpha.kubernetes.io/hostname=kubeopsview.$MyDomain&quot;
echo -e &quot;Kube Ops View URL = http://kubeopsview.$MyDomain:8080/#scale=1.5&quot;

# AWS LB Controller
helm repo add eks https://aws.github.io/eks-charts
helm repo update
helm install aws-load-balancer-controller eks/aws-load-balancer-controller -n kube-system --set clusterName=$CLUSTER_NAME \
  --set serviceAccount.create=false --set serviceAccount.name=aws-load-balancer-controller

# gp3 스토리지 클래스 생성
kubectl apply -f https://raw.githubusercontent.com/gasida/PKOS/main/aews/gp3-sc.yaml

# 노드 보안그룹 ID 확인
NGSGID=$(aws ec2 describe-security-groups --filters Name=group-name,Values=*ng1* --query &quot;SecurityGroups[*].[GroupId]&quot; --output text)
aws ec2 authorize-security-group-ingress --group-id $NGSGID --protocol '-1' --cidr 192.168.1.100/32&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;프로메테우스 &amp;amp; 그라파나(admin/prom-operator) 설치, 대시보드 추천 15757 17900 15172&lt;/p&gt;
&lt;pre id=&quot;code_1713261936638&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 사용 리전의 인증서 ARN 확인
CERT_ARN=`aws acm list-certificates --query 'CertificateSummaryList[].CertificateArn[]' --output text`
echo $CERT_ARN

# repo 추가
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts

# 파라미터 파일 생성 : PV/PVC(AWS EBS) 삭제에 불편하니, 4주차 실습과 다르게 PV/PVC 미사용
cat &amp;lt;&amp;lt;EOT &amp;gt; monitor-values.yaml
prometheus:
  prometheusSpec:
    podMonitorSelectorNilUsesHelmValues: false
    serviceMonitorSelectorNilUsesHelmValues: false
    retention: 5d
    retentionSize: &quot;10GiB&quot;

  ingress:
    enabled: true
    ingressClassName: alb
    hosts: 
      - prometheus.$MyDomain
    paths: 
      - /*
    annotations:
      alb.ingress.kubernetes.io/scheme: internet-facing
      alb.ingress.kubernetes.io/target-type: ip
      alb.ingress.kubernetes.io/listen-ports: '[{&quot;HTTPS&quot;:443}, {&quot;HTTP&quot;:80}]'
      alb.ingress.kubernetes.io/certificate-arn: $CERT_ARN
      alb.ingress.kubernetes.io/success-codes: 200-399
      alb.ingress.kubernetes.io/load-balancer-name: myeks-ingress-alb
      alb.ingress.kubernetes.io/group.name: study
      alb.ingress.kubernetes.io/ssl-redirect: '443'

grafana:
  defaultDashboardsTimezone: Asia/Seoul
  adminPassword: prom-operator
  defaultDashboardsEnabled: false

  ingress:
    enabled: true
    ingressClassName: alb
    hosts: 
      - grafana.$MyDomain
    paths: 
      - /*
    annotations:
      alb.ingress.kubernetes.io/scheme: internet-facing
      alb.ingress.kubernetes.io/target-type: ip
      alb.ingress.kubernetes.io/listen-ports: '[{&quot;HTTPS&quot;:443}, {&quot;HTTP&quot;:80}]'
      alb.ingress.kubernetes.io/certificate-arn: $CERT_ARN
      alb.ingress.kubernetes.io/success-codes: 200-399
      alb.ingress.kubernetes.io/load-balancer-name: myeks-ingress-alb
      alb.ingress.kubernetes.io/group.name: study
      alb.ingress.kubernetes.io/ssl-redirect: '443'

alertmanager:
  enabled: false
EOT
cat monitor-values.yaml | yh

# 배포
kubectl create ns monitoring
helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack --version 57.2.0 \
--set prometheus.prometheusSpec.scrapeInterval='15s' --set prometheus.prometheusSpec.evaluationInterval='15s' \
-f monitor-values.yaml --namespace monitoring

# Metrics-server 배포
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

# 프로메테우스 ingress 도메인으로 웹 접속
echo -e &quot;Prometheus Web URL = https://prometheus.$MyDomain&quot;

# 그라파나 웹 접속 : 기본 계정 - admin / prom-operator
echo -e &quot;Grafana Web URL = https://grafana.$MyDomain&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 style=&quot;text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;Docker&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 실습에서는 개인 Docker Hub에 컨테이너 이미지를 Push 하기 때문에, &lt;a href=&quot;https://hub.docker.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Docker&lt;/a&gt;에 회원 가입을 진행해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Bastion 호스트에서 간단한 웹 서비스 컨테이너 이미지를 생성하고, Push 해 보도록 하겠습니다.&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;아래 명령으로 base 이미지인 ubuntu:20.04를 다운로드 받습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713262276023&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker pull ubuntu:20.04
docker images&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;678&quot; data-origin-height=&quot;65&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qF2Iu/btsGFqRtZrI/KpgqZTfhR70MIzGjrZpRK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qF2Iu/btsGFqRtZrI/KpgqZTfhR70MIzGjrZpRK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qF2Iu/btsGFqRtZrI/KpgqZTfhR70MIzGjrZpRK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqF2Iu%2FbtsGFqRtZrI%2FKpgqZTfhR70MIzGjrZpRK1%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;678&quot; height=&quot;65&quot; data-origin-width=&quot;678&quot; data-origin-height=&quot;65&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;size16&quot;&gt;실습을 위해 디렉터리를 생성 및 이동합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713262354602&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;mkdir -p /root/myweb &amp;amp;&amp;amp; cd /root/myweb&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;`vi Dockerfile` 명령으로 Dockerfile을 생성합니다. NICK 변수를 본인의 이름으로 변경합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713262393561&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;FROM ubuntu:20.04
ENV TZ=Asia/Seoul VERSION=1.0.0 NICK=&amp;lt;자신의 닉네임&amp;gt;
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime &amp;amp;&amp;amp; echo $TZ &amp;gt; /etc/timezone &amp;amp;&amp;amp; \
    sed -i 's/archive.ubuntu.com/mirror.kakao.com/g' /etc/apt/sources.list &amp;amp;&amp;amp; \
    sed -i 's/security.ubuntu.com/mirror.kakao.com/g' /etc/apt/sources.list &amp;amp;&amp;amp; \
    apt-get update &amp;amp;&amp;amp; apt-get install -y apache2 figlet &amp;amp;&amp;amp; \
    echo &quot;$NICK Web Server $VERSION&amp;lt;br&amp;gt;&quot; &amp;gt; /var/www/html/index.html &amp;amp;&amp;amp; \
    echo &quot;&amp;lt;pre&amp;gt;&quot; &amp;gt;&amp;gt; /var/www/html/index.html &amp;amp;&amp;amp; \
    figlet AEWS Study &amp;gt;&amp;gt; /var/www/html/index.html &amp;amp;&amp;amp; \
    echo &quot;&amp;lt;/pre&amp;gt;&quot; &amp;gt;&amp;gt; /var/www/html/index.html
EXPOSE 80
CMD [&quot;usr/sbin/apache2ctl&quot;, &quot;-DFOREGROUND&quot;]&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;`:wq`로 저장 및 편집 종료한 뒤, 터미널에서 아래 명령으로 컨테이너 이미지를 생성합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713262532164&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker build -t myweb:v1.0.0 .&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;아래 명령으로 image가 잘 생성되었는지 확인합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713262560870&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker images&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;722&quot; data-origin-height=&quot;91&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bl3CLQ/btsGGmA4LaM/i5LDanSUNZcjwaCQLOSz3k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bl3CLQ/btsGGmA4LaM/i5LDanSUNZcjwaCQLOSz3k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bl3CLQ/btsGGmA4LaM/i5LDanSUNZcjwaCQLOSz3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbl3CLQ%2FbtsGGmA4LaM%2Fi5LDanSUNZcjwaCQLOSz3k%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;722&quot; height=&quot;91&quot; data-origin-width=&quot;722&quot; data-origin-height=&quot;91&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;size16&quot;&gt;아래 명령으로 컨테이너를 실행시킵니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713262622123&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker run -d -p 80:80 --rm --name myweb myweb:v1.0.0&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;아래 명령으로 웹 접속 URL을 확인합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713262640317&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;curl -s ipinfo.io/ip | awk '{ print &quot;myweb = http://&quot;$1&quot;&quot; }'&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;462&quot; data-origin-height=&quot;205&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dPIZPC/btsGFyPnpCQ/YMciImOzj5xIqrqK3k6hV1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dPIZPC/btsGFyPnpCQ/YMciImOzj5xIqrqK3k6hV1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dPIZPC/btsGFyPnpCQ/YMciImOzj5xIqrqK3k6hV1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdPIZPC%2FbtsGFyPnpCQ%2FYMciImOzj5xIqrqK3k6hV1%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;462&quot; height=&quot;205&quot; data-origin-width=&quot;462&quot; data-origin-height=&quot;205&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;size16&quot;&gt;아래 명령으로 docker hub에 이미지를 업로드 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713262797818&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 도커 이미지 태그 변경
DHUB=&amp;lt;도커 허브 계정&amp;gt;
DHUB=junkmm.site
docker tag myweb:v1.0.0 $DHUB/myweb:v1.0.0
docker images

# 도커 허브 로그인
docker login
Username: &amp;lt;자신의 ID&amp;gt;
Password: &amp;lt;암호&amp;gt;

# push 로 이미지를 저장소에 업로드
docker push $DHUB/myweb:v1.0.0&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;자신의 Repository에 myweb 저장소가 생기고, v1.0.0 이미지가 생성되었는지 확인합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;881&quot; data-origin-height=&quot;566&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nbRtL/btsGHbeJmXj/DyaiZBlv56NrTchlOxhka1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nbRtL/btsGHbeJmXj/DyaiZBlv56NrTchlOxhka1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nbRtL/btsGHbeJmXj/DyaiZBlv56NrTchlOxhka1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnbRtL%2FbtsGHbeJmXj%2FDyaiZBlv56NrTchlOxhka1%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;881&quot; height=&quot;566&quot; data-origin-width=&quot;881&quot; data-origin-height=&quot;566&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;size16&quot;&gt;아래 명령으로 Local 이미지로 실행한 web을 중지하고, Docker Hub에 업로드한 이미지로 컨테이너를 실행시킵니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713263001792&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 컨테이너 종료
docker rm -f myweb
docker ps

# 로컬 이미지 삭제
docker rmi $DHUB/myweb:v1.0.0
docker images

# 
docker run -d -p 80:80 --rm --name myweb $DHUB/myweb:v1.0.0
docker iamges

# 확인
docker ps
curl localhost
curl -s ipinfo.io/ip | awk '{ print &quot;myweb = http://&quot;$1&quot;&quot; }'

# 삭제
docker rm -f myweb&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;920&quot; data-origin-height=&quot;333&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxkx1U/btsGE6scrwu/6DOPQxhowxrCi7JjJOWNz0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxkx1U/btsGE6scrwu/6DOPQxhowxrCi7JjJOWNz0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxkx1U/btsGE6scrwu/6DOPQxhowxrCi7JjJOWNz0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbxkx1U%2FbtsGE6scrwu%2F6DOPQxhowxrCi7JjJOWNz0%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;920&quot; height=&quot;333&quot; data-origin-width=&quot;920&quot; data-origin-height=&quot;333&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;size16&quot;&gt;로컬 환경에서 Docker를 통해 Web 서비스를 배포해 보았습니다. 해당 이미지를 이번 CI/CD 실습에 활용 할 예정입니다.&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;Jenkins&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CI(Continuous Intergration)를 위해 Jenkins를 사용합니다. 오픈 소스이 개발 소스를 빌드하거나 배포할 때 사용할 수 있습니다.&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;설치 및 설정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Bastion 호스트에서 아래 명령어로 Jenkins를 설치합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713433574663&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 실습 편리를 위해서 root 계정 전환
sudo su -

# Add required dependencies for the jenkins package
# https://docs.aws.amazon.com/corretto/latest/corretto-17-ug/amazon-linux-install.html
sudo yum install fontconfig java-17-amazon-corretto -y
java -version
alternatives --display java
JAVA_HOME=/usr/lib/jvm/java-17-amazon-corretto.x86_64
echo $JAVA_HOME

# 젠킨스 설치
sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo
sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io-2023.key
sudo yum upgrade
sudo yum install jenkins -y
sudo systemctl daemon-reload
sudo systemctl enable jenkins &amp;amp;&amp;amp; sudo systemctl start jenkins   # 다소 시간 걸림
sudo systemctl status jenkins&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;Jenkins의 초기 암호를 확인합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713433598307&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 초기 암호 확인
cat /var/lib/jenkins/secrets/initialAdminPassword&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;925&quot; data-origin-height=&quot;58&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lT5H4/btsGJnUPgCy/E7i84HMkZJx0EUKBIP8Ik0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lT5H4/btsGJnUPgCy/E7i84HMkZJx0EUKBIP8Ik0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lT5H4/btsGJnUPgCy/E7i84HMkZJx0EUKBIP8Ik0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlT5H4%2FbtsGJnUPgCy%2FE7i84HMkZJx0EUKBIP8Ik0%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;925&quot; height=&quot;58&quot; data-origin-width=&quot;925&quot; data-origin-height=&quot;58&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;size16&quot;&gt;접속 URL을 확인합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713433630857&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;curl -s ipinfo.io/ip | awk '{ print &quot;Jenkins = http://&quot;$1&quot;:8080&quot; }'&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;928&quot; data-origin-height=&quot;60&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dpwJzu/btsGJOxTrRD/GXGLZ7ffrydf4ctKMnJxf1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dpwJzu/btsGJOxTrRD/GXGLZ7ffrydf4ctKMnJxf1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dpwJzu/btsGJOxTrRD/GXGLZ7ffrydf4ctKMnJxf1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdpwJzu%2FbtsGJOxTrRD%2FGXGLZ7ffrydf4ctKMnJxf1%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;928&quot; height=&quot;60&quot; data-origin-width=&quot;928&quot; data-origin-height=&quot;60&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;size16&quot;&gt;Jenkins URL로 접근하여 위에서 조회한 관리자 비밀번호를 입력합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;825&quot; data-origin-height=&quot;434&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dcM9yL/btsGEjFxjxs/hz0huDslcfevZ30N9X5tX1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dcM9yL/btsGEjFxjxs/hz0huDslcfevZ30N9X5tX1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dcM9yL/btsGEjFxjxs/hz0huDslcfevZ30N9X5tX1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdcM9yL%2FbtsGEjFxjxs%2Fhz0huDslcfevZ30N9X5tX1%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;825&quot; height=&quot;434&quot; data-origin-width=&quot;825&quot; data-origin-height=&quot;434&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;size16&quot;&gt;다음 화면에서 Install suggested plugins를 설치해 플러그인을 설치합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;774&quot; data-origin-height=&quot;466&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bl8dMx/btsGFlvRcfz/kmjfrzuqtpDXKkX8vqnp01/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bl8dMx/btsGFlvRcfz/kmjfrzuqtpDXKkX8vqnp01/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bl8dMx/btsGFlvRcfz/kmjfrzuqtpDXKkX8vqnp01/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbl8dMx%2FbtsGFlvRcfz%2FkmjfrzuqtpDXKkX8vqnp01%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;774&quot; height=&quot;466&quot; data-origin-width=&quot;774&quot; data-origin-height=&quot;466&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;size16&quot;&gt;기본 플러그인이 설치됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;868&quot; data-origin-height=&quot;450&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/43yar/btsGJO5IbLb/K1mRrKWAmpLjgebUZMxkkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/43yar/btsGJO5IbLb/K1mRrKWAmpLjgebUZMxkkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/43yar/btsGJO5IbLb/K1mRrKWAmpLjgebUZMxkkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F43yar%2FbtsGJO5IbLb%2FK1mRrKWAmpLjgebUZMxkkK%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;868&quot; height=&quot;450&quot; data-origin-width=&quot;868&quot; data-origin-height=&quot;450&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;size16&quot;&gt;Admin 유저를 설정합니다. (admin/qwe123)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;868&quot; data-origin-height=&quot;666&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cQXIIr/btsGJdEOFuR/z7A4sC0eNs0wXyXNyQzdx1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cQXIIr/btsGJdEOFuR/z7A4sC0eNs0wXyXNyQzdx1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cQXIIr/btsGJdEOFuR/z7A4sC0eNs0wXyXNyQzdx1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcQXIIr%2FbtsGJdEOFuR%2Fz7A4sC0eNs0wXyXNyQzdx1%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;868&quot; height=&quot;666&quot; data-origin-width=&quot;868&quot; data-origin-height=&quot;666&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;h3 data-ke-size=&quot;size23&quot;&gt;기본 사용, Tools 설정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Jenkins 메인 화면 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Item은 젠킨스에서 사용하는 최소 작업 단위이고, 사람은 Jenkins의 계정 관련 설정, Jenkins 관리는 전역 설정을 적용하는 메뉴 입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;947&quot; data-origin-height=&quot;701&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Jvjj5/btsGJnN2ZYV/aJXkaHce92GsesL3DAV5K1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Jvjj5/btsGJnN2ZYV/aJXkaHce92GsesL3DAV5K1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Jvjj5/btsGJnN2ZYV/aJXkaHce92GsesL3DAV5K1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJvjj5%2FbtsGJnN2ZYV%2FaJXkaHce92GsesL3DAV5K1%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;947&quot; height=&quot;701&quot; data-origin-width=&quot;947&quot; data-origin-height=&quot;701&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;size16&quot;&gt;Jenkins 기본 사용을 위해 JDK 정의를 진행합니다. Jenkins 관리 -&amp;gt; Tools에 진입합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;948&quot; data-origin-height=&quot;485&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bN0TRr/btsGJmuOndD/UF7pagpbiAaePRGWh8oOH0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bN0TRr/btsGJmuOndD/UF7pagpbiAaePRGWh8oOH0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bN0TRr/btsGJmuOndD/UF7pagpbiAaePRGWh8oOH0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbN0TRr%2FbtsGJmuOndD%2FUF7pagpbiAaePRGWh8oOH0%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;948&quot; height=&quot;485&quot; data-origin-width=&quot;948&quot; data-origin-height=&quot;485&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;size16&quot;&gt;JDK Installations에서 `Add JDK`를 클릭하고, 아래와 같이 정보를 입력합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;906&quot; data-origin-height=&quot;464&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xjH8N/btsGJm9soR1/UXl6tMinOyPMk6evnk7A90/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xjH8N/btsGJm9soR1/UXl6tMinOyPMk6evnk7A90/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xjH8N/btsGJm9soR1/UXl6tMinOyPMk6evnk7A90/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxjH8N%2FbtsGJm9soR1%2FUXl6tMinOyPMk6evnk7A90%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;906&quot; height=&quot;464&quot; data-origin-width=&quot;906&quot; data-origin-height=&quot;464&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;size16&quot;&gt;첫 번째 Item을 생성합니다. 메인화면 -&amp;gt; Item으로 진입하고, 이름 입력 후 Freestyle project를 선택합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;934&quot; data-origin-height=&quot;401&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NwsKt/btsGK2B8BaF/QtZvKwkvrBwegqDo9pp7qk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NwsKt/btsGK2B8BaF/QtZvKwkvrBwegqDo9pp7qk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NwsKt/btsGK2B8BaF/QtZvKwkvrBwegqDo9pp7qk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNwsKt%2FbtsGK2B8BaF%2FQtZvKwkvrBwegqDo9pp7qk%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;934&quot; height=&quot;401&quot; data-origin-width=&quot;934&quot; data-origin-height=&quot;401&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;size16&quot;&gt;Build Steps -&amp;gt; Add build step -&amp;gt; Excute shell을 선택합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;551&quot; data-origin-height=&quot;555&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EMY0r/btsGH3pf29N/qxqspZypK6nNkLp20isVS1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EMY0r/btsGH3pf29N/qxqspZypK6nNkLp20isVS1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EMY0r/btsGH3pf29N/qxqspZypK6nNkLp20isVS1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEMY0r%2FbtsGH3pf29N%2FqxqspZypK6nNkLp20isVS1%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;551&quot; height=&quot;555&quot; data-origin-width=&quot;551&quot; data-origin-height=&quot;555&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;size16&quot;&gt;간단한 문장 출력이 될 수 있게 `echo &quot;Aws Workshop Study&quot;`를 입력하고 저장합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;637&quot; data-origin-height=&quot;416&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tW9GH/btsGLud2D87/9psKwMjiQ7YzUKAkxVhrD1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tW9GH/btsGLud2D87/9psKwMjiQ7YzUKAkxVhrD1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tW9GH/btsGLud2D87/9psKwMjiQ7YzUKAkxVhrD1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtW9GH%2FbtsGLud2D87%2F9psKwMjiQ7YzUKAkxVhrD1%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;637&quot; height=&quot;416&quot; data-origin-width=&quot;637&quot; data-origin-height=&quot;416&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;size16&quot;&gt;지금 빌드를 클릭하여 Jenkins의 Item을 실행합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;939&quot; data-origin-height=&quot;587&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bca0fb/btsGLHKZgho/ec1xK6N6j8Fs5NQ0jlFqjk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bca0fb/btsGLHKZgho/ec1xK6N6j8Fs5NQ0jlFqjk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bca0fb/btsGLHKZgho/ec1xK6N6j8Fs5NQ0jlFqjk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbca0fb%2FbtsGLHKZgho%2Fec1xK6N6j8Fs5NQ0jlFqjk%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;939&quot; height=&quot;587&quot; data-origin-width=&quot;939&quot; data-origin-height=&quot;587&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;size16&quot;&gt;하단 Build History에 새로운 내역이 생깁니다. 해당 내역에 마우스를 위치하면 아래 사진과 같이 Side Menu가 표시됩니다. Console Output을 클릭합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;291&quot; data-origin-height=&quot;291&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/laTaz/btsGH4hozNZ/pGvMOJzsumeqLPMp0WGHr1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/laTaz/btsGH4hozNZ/pGvMOJzsumeqLPMp0WGHr1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/laTaz/btsGH4hozNZ/pGvMOJzsumeqLPMp0WGHr1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlaTaz%2FbtsGH4hozNZ%2FpGvMOJzsumeqLPMp0WGHr1%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;291&quot; height=&quot;291&quot; data-origin-width=&quot;291&quot; data-origin-height=&quot;291&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;size16&quot;&gt;콘솔 출력에 Excute Shell에 정의한 Welcome to my first project가 찍혀있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;901&quot; data-origin-height=&quot;272&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wzwye/btsGI5UqG95/29WB42wL7ILyJsnEkpKKuk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wzwye/btsGI5UqG95/29WB42wL7ILyJsnEkpKKuk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wzwye/btsGI5UqG95/29WB42wL7ILyJsnEkpKKuk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fwzwye%2FbtsGI5UqG95%2F29WB42wL7ILyJsnEkpKKuk%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;901&quot; height=&quot;272&quot; data-origin-width=&quot;901&quot; data-origin-height=&quot;272&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;size16&quot;&gt;Item(Job) 메뉴로 돌아와 구성 탭에서 Excute shell 부분을 아래와 같이 수정하고, 실행 시킵니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;645&quot; data-origin-height=&quot;420&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uGXOr/btsGKVQK8ah/EgimkfHIZRnfrV6uyyCZy1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uGXOr/btsGKVQK8ah/EgimkfHIZRnfrV6uyyCZy1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uGXOr/btsGKVQK8ah/EgimkfHIZRnfrV6uyyCZy1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuGXOr%2FbtsGKVQK8ah%2FEgimkfHIZRnfrV6uyyCZy1%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;645&quot; height=&quot;420&quot; data-origin-width=&quot;645&quot; data-origin-height=&quot;420&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;size16&quot;&gt;다시 Console Output을 확인 해보면,&amp;nbsp; 위에서 정의한 명령어를 실행한 출력값들을 확인해볼 수 있습니다. 이로 인해 Jenkins는 사용자가 정의한 작업을 순서대로 처리하는 특성을 확인해볼 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;919&quot; data-origin-height=&quot;467&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cOFbjD/btsGKTFpKdX/UUYbkB6dCF3hqTKug6qlTk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cOFbjD/btsGKTFpKdX/UUYbkB6dCF3hqTKug6qlTk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cOFbjD/btsGKTFpKdX/UUYbkB6dCF3hqTKug6qlTk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcOFbjD%2FbtsGKTFpKdX%2FUUYbkB6dCF3hqTKug6qlTk%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;919&quot; height=&quot;467&quot; data-origin-width=&quot;919&quot; data-origin-height=&quot;467&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;size16&quot;&gt;위 로그를 보면 Building in workspace라고 정의된 경로가 있습니다. 한국 말로 직역하면 작업 공간이고, 해당 디렉터리에 가보면 touch hello.txt에 의해 hello.txt 파일이 생성되어 있는것을 확인해볼 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;708&quot; data-origin-height=&quot;80&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bEuNvj/btsGJTlALv9/KWGj1M3JqNg3uk0ckyB0b1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bEuNvj/btsGJTlALv9/KWGj1M3JqNg3uk0ckyB0b1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bEuNvj/btsGJTlALv9/KWGj1M3JqNg3uk0ckyB0b1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbEuNvj%2FbtsGJTlALv9%2FKWGj1M3JqNg3uk0ckyB0b1%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;708&quot; height=&quot;80&quot; data-origin-width=&quot;708&quot; data-origin-height=&quot;80&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;size16&quot;&gt;whoami 명령어로 조회한 Linux의 user명은 jenkins로 확인됩니다. 즉 jenkins가 설치된 Bastion호스트의 shell을 jenkins라는 user가 접근하여 위 명령어들을 조회한 것으로 이해가 됩니다.&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;Docker 사용&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Jenkins에서 Docker 빌드를 하기 위해 jenkins 유저가 docker를 실행할 수 있는 권한을 부여해야 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713435542905&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#docker sock에 666 권한 할당
chmod 666 /var/run/docker.sock
usermod -aG docker jenkins

# Jeknins 유저로 확인
su - jenkins
docker info

# Dockerhub로 로그인 하기
docker login
Username: &amp;lt;자신의 계정명&amp;gt;
Password: &amp;lt;자신의 암호&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;924&quot; data-origin-height=&quot;189&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHauWv/btsGKeQE5TB/UGHpaHFaCciCKSVuoBNgfk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHauWv/btsGKeQE5TB/UGHpaHFaCciCKSVuoBNgfk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHauWv/btsGKeQE5TB/UGHpaHFaCciCKSVuoBNgfk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbHauWv%2FbtsGKeQE5TB%2FUGHpaHFaCciCKSVuoBNgfk%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;924&quot; height=&quot;189&quot; data-origin-width=&quot;924&quot; data-origin-height=&quot;189&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;size16&quot;&gt;Dockerfile을 생성합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713436227554&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# myweb:v2.0.0 컨테이너 이미지 생성을 위한 Dockerfile 준비
# 실습을 위한 디렉터리 생성 및 이동
mkdir -p ~/myweb2 &amp;amp;&amp;amp; cd ~/myweb2

# Dockerfile 파일 생성
vi Dockerfile
FROM ubuntu:20.04
ENV TZ=Asia/Seoul VERSION=2.0.0 NICK=&amp;lt;자신의 닉네임&amp;gt;
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime &amp;amp;&amp;amp; echo $TZ &amp;gt; /etc/timezone &amp;amp;&amp;amp; \
    sed -i 's/archive.ubuntu.com/mirror.kakao.com/g' /etc/apt/sources.list &amp;amp;&amp;amp; \
    sed -i 's/security.ubuntu.com/mirror.kakao.com/g' /etc/apt/sources.list &amp;amp;&amp;amp; \
    apt-get update &amp;amp;&amp;amp; apt-get install -y apache2 figlet &amp;amp;&amp;amp; \
    echo &quot;$NICK Web Server $VERSION&amp;lt;br&amp;gt;&quot; &amp;gt; /var/www/html/index.html &amp;amp;&amp;amp; \
    echo &quot;&amp;lt;pre&amp;gt;&quot; &amp;gt;&amp;gt; /var/www/html/index.html &amp;amp;&amp;amp; \
    figlet AEWS Study &amp;gt;&amp;gt; /var/www/html/index.html &amp;amp;&amp;amp; \
    echo &quot;&amp;lt;/pre&amp;gt;&quot; &amp;gt;&amp;gt; /var/www/html/index.html
EXPOSE 80
CMD [&quot;usr/sbin/apache2ctl&quot;, &quot;-DFOREGROUND&quot;]&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;Jenkins에서 새로운 Item을 생성합니다. Add build step으로 총 2개의 Execute shell을 아래와 같이 생성합니다. 해석하자면 jenkins는 /var/lib/jenkins/myweb2 디렉토리로 이동하고, 해당 dir에서 `docker build`를 진행합니다. 이때 위에서 생성한 Dockerfile을 기반으로 build 합니다.&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;build가 완료되면 `docker run` 명령을 통해 해당 이미지를 실행시킵니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713436383096&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# shell 1
cd /var/lib/jenkins/myweb2
docker build -t myweb:v2.0.0 .

# shell 2
docker run -d -p 80:80 --rm --name myweb myweb:v2.0.0&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;652&quot; data-origin-height=&quot;691&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nIJxt/btsGLBjNRyv/HIiqOMI8l5MYPEXixX8XpK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nIJxt/btsGLBjNRyv/HIiqOMI8l5MYPEXixX8XpK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nIJxt/btsGLBjNRyv/HIiqOMI8l5MYPEXixX8XpK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnIJxt%2FbtsGLBjNRyv%2FHIiqOMI8l5MYPEXixX8XpK%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;652&quot; height=&quot;691&quot; data-origin-width=&quot;652&quot; data-origin-height=&quot;691&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;size16&quot;&gt;빌드가 성공했습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;927&quot; data-origin-height=&quot;540&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cWCWHj/btsGIMAPG8H/9BV0MGGwPlYcRwkkCBkEj0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cWCWHj/btsGIMAPG8H/9BV0MGGwPlYcRwkkCBkEj0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cWCWHj/btsGIMAPG8H/9BV0MGGwPlYcRwkkCBkEj0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcWCWHj%2FbtsGIMAPG8H%2F9BV0MGGwPlYcRwkkCBkEj0%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;927&quot; height=&quot;540&quot; data-origin-width=&quot;927&quot; data-origin-height=&quot;540&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;size16&quot;&gt;아래와 같이 docker image가 생성되고, 실행 중인것을 확인할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;927&quot; data-origin-height=&quot;428&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ynehk/btsGIdrQ2ja/nLhKHJxExmFzxenlJz5OFk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ynehk/btsGIdrQ2ja/nLhKHJxExmFzxenlJz5OFk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ynehk/btsGIdrQ2ja/nLhKHJxExmFzxenlJz5OFk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYnehk%2FbtsGIdrQ2ja%2FnLhKHJxExmFzxenlJz5OFk%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;927&quot; height=&quot;428&quot; data-origin-width=&quot;927&quot; data-origin-height=&quot;428&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;size16&quot;&gt;아래 명령으로 실습 리소스를 삭제합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713436627123&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker rm -f myweb
docker rmi myweb:v2.0.0&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;Github 가입&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Github에 가입하고 &lt;span&gt;&lt;/span&gt;&lt;a href=&quot;https://github.com/gasida/aews-cicd.git&quot;&gt;https://github.com/gasida/aews-cicd.git&lt;/a&gt; 레포지토리를 &lt;span data-token-index=&quot;2&quot;&gt;포크합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;905&quot; data-origin-height=&quot;524&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Wh3sM/btsGIPqNeAQ/skPy8EEsYkBT1bz7pwYIpk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Wh3sM/btsGIPqNeAQ/skPy8EEsYkBT1bz7pwYIpk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Wh3sM/btsGIPqNeAQ/skPy8EEsYkBT1bz7pwYIpk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWh3sM%2FbtsGIPqNeAQ%2FskPy8EEsYkBT1bz7pwYIpk%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;905&quot; height=&quot;524&quot; data-origin-width=&quot;905&quot; data-origin-height=&quot;524&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;h3 data-ke-size=&quot;size23&quot;&gt;Jenkins Trigger-Project&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Git Repo의 변화가 생기면 Jenkins Item(Job)이 실행되는 환경을 실습합니다.&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;Freestyle project를 생성합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;903&quot; data-origin-height=&quot;280&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KD9HI/btsGKMGnK9m/gHIiK3TVvYMPKKwmyD6VIk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KD9HI/btsGKMGnK9m/gHIiK3TVvYMPKKwmyD6VIk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KD9HI/btsGKMGnK9m/gHIiK3TVvYMPKKwmyD6VIk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKD9HI%2FbtsGKMGnK9m%2FgHIiK3TVvYMPKKwmyD6VIk%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;903&quot; height=&quot;280&quot; data-origin-width=&quot;903&quot; data-origin-height=&quot;280&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;size16&quot;&gt;아래와 같이 변수를 추가합니다.(string)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;649&quot; data-origin-height=&quot;778&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/duKu8d/btsGKck0uGR/IqVmRz8CVHgiohJVN01J8k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/duKu8d/btsGKck0uGR/IqVmRz8CVHgiohJVN01J8k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/duKu8d/btsGKck0uGR/IqVmRz8CVHgiohJVN01J8k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FduKu8d%2FbtsGKck0uGR%2FIqVmRz8CVHgiohJVN01J8k%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;649&quot; height=&quot;778&quot; data-origin-width=&quot;649&quot; data-origin-height=&quot;778&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;size16&quot;&gt;Git 부분을 수정합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;630&quot; data-origin-height=&quot;832&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDI03a/btsGKVpJW0i/RQ1r5Rek1fzyIvYHDzOdok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDI03a/btsGKVpJW0i/RQ1r5Rek1fzyIvYHDzOdok/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDI03a/btsGKVpJW0i/RQ1r5Rek1fzyIvYHDzOdok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDI03a%2FbtsGKVpJW0i%2FRQ1r5Rek1fzyIvYHDzOdok%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;630&quot; height=&quot;832&quot; data-origin-width=&quot;630&quot; data-origin-height=&quot;832&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;size16&quot;&gt;빌드 유발을 설정합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;633&quot; data-origin-height=&quot;375&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SO6nf/btsGKfIPCdB/p5eZA3cxYAvBWA6fntJGVk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SO6nf/btsGKfIPCdB/p5eZA3cxYAvBWA6fntJGVk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SO6nf/btsGKfIPCdB/p5eZA3cxYAvBWA6fntJGVk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSO6nf%2FbtsGKfIPCdB%2Fp5eZA3cxYAvBWA6fntJGVk%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;633&quot; height=&quot;375&quot; data-origin-width=&quot;633&quot; data-origin-height=&quot;375&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;size16&quot;&gt;빌드 스텝을 설정합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713439951531&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Shell 1
cd /var/lib/jenkins/myweb2
rm -rf Dockerfile
wget https://raw.githubusercontent.com/$NICK/aews-cicd/main/1/Dockerfile

# Shell 2
cd /var/lib/jenkins/myweb2
docker build --build-arg VERSION=$VERSION -t myweb:$VERSION .
docker run -d -p 80:80 --rm --name myweb -e VERSION=$VERSION myweb:$VERSION&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;629&quot; data-origin-height=&quot;781&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/biJMnT/btsGK4mw8TX/wYxoFhyYYkLzYvJxAmamD1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/biJMnT/btsGK4mw8TX/wYxoFhyYYkLzYvJxAmamD1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/biJMnT/btsGK4mw8TX/wYxoFhyYYkLzYvJxAmamD1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbiJMnT%2FbtsGK4mw8TX%2FwYxoFhyYYkLzYvJxAmamD1%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;629&quot; height=&quot;781&quot; data-origin-width=&quot;629&quot; data-origin-height=&quot;781&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;size16&quot;&gt;본인의 Github 계정에서 1/Dockerfile 의 Version 부분을 수정합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1739&quot; data-origin-height=&quot;557&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cwTujv/btsGLsHlczD/6KSwankCac1LXOQI97QDY1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cwTujv/btsGLsHlczD/6KSwankCac1LXOQI97QDY1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cwTujv/btsGLsHlczD/6KSwankCac1LXOQI97QDY1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcwTujv%2FbtsGLsHlczD%2F6KSwankCac1LXOQI97QDY1%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;1739&quot; height=&quot;557&quot; data-origin-width=&quot;1739&quot; data-origin-height=&quot;557&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;size16&quot;&gt;파라미터와 함께 빌드를 클릭하고, Version을 변경합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;919&quot; data-origin-height=&quot;488&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SemJ6/btsGJcMKO50/VWtlPK8ZhKG62B4mSjzlW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SemJ6/btsGJcMKO50/VWtlPK8ZhKG62B4mSjzlW0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SemJ6/btsGJcMKO50/VWtlPK8ZhKG62B4mSjzlW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSemJ6%2FbtsGJcMKO50%2FVWtlPK8ZhKG62B4mSjzlW0%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;919&quot; height=&quot;488&quot; data-origin-width=&quot;919&quot; data-origin-height=&quot;488&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;size16&quot;&gt;완료 후 `curl localhost`로 결과를 확인합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;702&quot; data-origin-height=&quot;196&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b6zPZ4/btsGJTsrLig/xykXy3K4plMaHfusrt1Qn1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b6zPZ4/btsGJTsrLig/xykXy3K4plMaHfusrt1Qn1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b6zPZ4/btsGJTsrLig/xykXy3K4plMaHfusrt1Qn1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb6zPZ4%2FbtsGJTsrLig%2FxykXy3K4plMaHfusrt1Qn1%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;702&quot; height=&quot;196&quot; data-origin-width=&quot;702&quot; data-origin-height=&quot;196&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;size16&quot;&gt;실습 내용을 정리합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713440109081&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker rm -f myweb
docker rmi myweb:v5.3.1
docker rmi myweb:v1.0.0&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Jenkins with Kubernetes&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EKS 환경에 배포하는 Jenkins를 구성합니다. 이를 위해 Bastion Jenkins 사용자에서 사전 작업을 진행합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713440294641&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# jenkins 사용자에서 아래 작업 진행
su - jenkins
whoami
mkdir ~/.kube

# root 계정에서 아래 복사 실행
cp ~/.kube/config /var/lib/jenkins/.kube/config
chown jenkins:jenkins /var/lib/jenkins/.kube/config

# jenkins 사용자에서 aws eks 사용(sts 호출 등)을 위한 자격증명 설정
aws configure
AWS Access Key ID [None]: ###
AWS Secret Access Key [None]: ###
Default region name [None]: ap-northeast-2

# jenkins 사용자에서 kubectl 명령어 사용 확인
kubectl get pods -A&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;409&quot; data-origin-height=&quot;42&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cB9HL3/btsGK4tht4b/uLdBKp2QbQYCMslOidoBR1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cB9HL3/btsGK4tht4b/uLdBKp2QbQYCMslOidoBR1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cB9HL3/btsGK4tht4b/uLdBKp2QbQYCMslOidoBR1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcB9HL3%2FbtsGK4tht4b%2FuLdBKp2QbQYCMslOidoBR1%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;409&quot; height=&quot;42&quot; data-origin-width=&quot;409&quot; data-origin-height=&quot;42&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;size16&quot;&gt;Jenkins의 파이프라인으로 Deployment/Service를 배포합니다.&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;먼저 본인 Github계정의 3/deploy/deployment-svc.yaml에 image 부분을 수정합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;873&quot; data-origin-height=&quot;580&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/F0yb6/btsGLfnOulo/ayZJB44QtPHD1exqAKxuE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/F0yb6/btsGLfnOulo/ayZJB44QtPHD1exqAKxuE1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/F0yb6/btsGLfnOulo/ayZJB44QtPHD1exqAKxuE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FF0yb6%2FbtsGLfnOulo%2FayZJB44QtPHD1exqAKxuE1%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;873&quot; height=&quot;580&quot; data-origin-width=&quot;873&quot; data-origin-height=&quot;580&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;size16&quot;&gt;Jenkins에서 새로운 Item에 진입 후 Pipeline을 선택합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;903&quot; data-origin-height=&quot;373&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UBXdO/btsGI5fUI8o/A5V1v6ERznv3FRTtNuYBk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UBXdO/btsGI5fUI8o/A5V1v6ERznv3FRTtNuYBk0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UBXdO/btsGI5fUI8o/A5V1v6ERznv3FRTtNuYBk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUBXdO%2FbtsGI5fUI8o%2FA5V1v6ERznv3FRTtNuYBk0%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;903&quot; height=&quot;373&quot; data-origin-width=&quot;903&quot; data-origin-height=&quot;373&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;size16&quot;&gt;pipeline 부분에 아래 내용을 입력합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713440740465&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pipeline {
    agent any

    tools {
        jdk 'jdk-17'
    }

    environment {
        DOCKERHUB_USERNAME = 'kimhj4270'
        GITHUB_URL = 'https://github.com/junkmm/aews-cicd.git'
        DIR_NUM = '3'
    }

    stages {
        stage('Container Build') {
            steps {	
                // 릴리즈파일 체크아웃
                checkout scmGit(branches: [[name: '*/main']], 
                    extensions: [[$class: 'SparseCheckoutPaths', 
                    sparseCheckoutPaths: [[path: &quot;/${DIR_NUM}&quot;]]]], 
                    userRemoteConfigs: [[url: &quot;${GITHUB_URL}&quot;]])

                // 컨테이너 빌드 및 업로드
                sh &quot;docker build -t ${DOCKERHUB_USERNAME}/myweb:v1.0.0 ./${DIR_NUM}&quot;
                sh &quot;docker push ${DOCKERHUB_USERNAME}/myweb:v1.0.0&quot;
            }
        }

        stage('K8S Deploy') {
            steps {
                sh &quot;kubectl apply -f ./${DIR_NUM}/deploy/deployment-svc.yaml&quot;
            }
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;631&quot; data-origin-height=&quot;788&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cfNwhR/btsGJSf1USK/y1Y83XAZIChBaj9NHmrvLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cfNwhR/btsGJSf1USK/y1Y83XAZIChBaj9NHmrvLK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cfNwhR/btsGJSf1USK/y1Y83XAZIChBaj9NHmrvLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcfNwhR%2FbtsGJSf1USK%2Fy1Y83XAZIChBaj9NHmrvLK%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;631&quot; height=&quot;788&quot; data-origin-width=&quot;631&quot; data-origin-height=&quot;788&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;size16&quot;&gt;지금 빌드를 클릭합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;927&quot; data-origin-height=&quot;614&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nMs5r/btsGLafULqf/RXa7Puy8iKxERo4p6euWr1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nMs5r/btsGLafULqf/RXa7Puy8iKxERo4p6euWr1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nMs5r/btsGLafULqf/RXa7Puy8iKxERo4p6euWr1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnMs5r%2FbtsGLafULqf%2FRXa7Puy8iKxERo4p6euWr1%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;927&quot; height=&quot;614&quot; data-origin-width=&quot;927&quot; data-origin-height=&quot;614&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;size16&quot;&gt;Bastion에서 접속 테스트용 파드를 배포합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713440900281&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 배포
cat &amp;lt;&amp;lt;EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
  name: netpod
  labels:
    app: pod
spec:
  containers:
  - name: netshoot-pod
    image: nicolaka/netshoot
    command: [&quot;tail&quot;]
    args: [&quot;-f&quot;, &quot;/dev/null&quot;]
  terminationGracePeriodSeconds: 0
EOF&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;아래 명령어로 myweb pod가 잘 배포되었는지 확인합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713440964463&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl exec -it netpod -- curl myweb:8080&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;926&quot; data-origin-height=&quot;209&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bZsPVT/btsGJejvP95/ZOhTzt105ttsloMozK5yY1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bZsPVT/btsGJejvP95/ZOhTzt105ttsloMozK5yY1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bZsPVT/btsGJejvP95/ZOhTzt105ttsloMozK5yY1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbZsPVT%2FbtsGJejvP95%2FZOhTzt105ttsloMozK5yY1%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;926&quot; height=&quot;209&quot; data-origin-width=&quot;926&quot; data-origin-height=&quot;209&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;size16&quot;&gt;실습 리소스를 삭제합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713440991214&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl delete deploy,svc myweb&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Argo Project&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Argo는 Kubernetes 환경에서 gitops패턴의 배포 환경을 지원해주는 CNCF 프로젝트 입니다. Argo CD는 쿠버네티스 환경에 배포를 담당하고, Argo Rollouts는 쿠버네티스 배포 시 Blue-Green, Canary 등 무중단 배포를 지원합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;ArgoCD&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ArgoCD는 API, Repository Service, Application Controller 크게 3가지 서비스가 내장되어 있습니다. API는 Web UI 대시보드를 제공하고, API 서비스를 제공합니다. Repository Server는 Git 연결 및 배포할 yaml을 생성합니다. Application Controller는 K8s 리소스와 Git을 비교하며 Sync를 비교합니다. 동적으로 Git과 k8s를 동기화 할 수 있고, 수동으로 동기화 시킬 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;1649&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/w0s6d/btsGOwpjtvh/ijgIKyKW9Zbo8o9s4r8Bmk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/w0s6d/btsGOwpjtvh/ijgIKyKW9Zbo8o9s4r8Bmk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/w0s6d/btsGOwpjtvh/ijgIKyKW9Zbo8o9s4r8Bmk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fw0s6d%2FbtsGOwpjtvh%2FijgIKyKW9Zbo8o9s4r8Bmk%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;1730&quot; height=&quot;1649&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;1649&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 명령으로 ArgoCD를 설치합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713590455971&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# helm 설치
cat &amp;lt;&amp;lt;EOT &amp;gt; argocd-values.yaml
global:
  domain: argocd.$MyDomain

configs:
  params:
    server.insecure: true

controller:
  metrics:
    enabled: true
    serviceMonitor:
      enabled: true

server:
  ingress:
    enabled: true
    controller: aws
    ingressClassName: alb
    hostname: &quot;argocd.$MyDomain&quot;
    annotations:
      alb.ingress.kubernetes.io/scheme: internet-facing
      alb.ingress.kubernetes.io/target-type: ip
      alb.ingress.kubernetes.io/backend-protocol: HTTP
      alb.ingress.kubernetes.io/listen-ports: '[{&quot;HTTPS&quot;:80}, {&quot;HTTPS&quot;:443}]'
      alb.ingress.kubernetes.io/certificate-arn: $CERT_ARN
      alb.ingress.kubernetes.io/ssl-redirect: '443'
    aws:
      serviceType: ClusterIP
      backendProtocolVersion: GRPC
  metrics:
    enabled: true
    serviceMonitor:
      enabled: true

repoServer:
  metrics:
    enabled: true
    serviceMonitor:
      enabled: true

applicationSet:
  metrics:
    enabled: true
    serviceMonitor:
      enabled: true

notifications:
  metrics:
    enabled: true
    serviceMonitor:
      enabled: true
EOT

kubectl create ns argocd
helm repo add argo https://argoproj.github.io/argo-helm
helm install argocd argo/argo-cd --version 6.7.11 -f argocd-values.yaml --namespace argocd&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;확인&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1241&quot; data-origin-height=&quot;580&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/twSZh/btsGM9V7LAv/lXFkUtvvkUHfk9fsXCNrdk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/twSZh/btsGM9V7LAv/lXFkUtvvkUHfk9fsXCNrdk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/twSZh/btsGM9V7LAv/lXFkUtvvkUHfk9fsXCNrdk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtwSZh%2FbtsGM9V7LAv%2FlXFkUtvvkUHfk9fsXCNrdk%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;1241&quot; height=&quot;580&quot; data-origin-width=&quot;1241&quot; data-origin-height=&quot;580&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Redis는 k8s api와 git 요청을 줄이기 위한 캐싱으로 사용됩니다. notification은 이벤트 알림 및 트리거를 제공하고, Applicationset-controller는 멀티 클러스터를 위한 App 패키징 관리를 위해 사용 됩니다.&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;`https://argocd.junkmm.site/admin`으로 접속합니다. 아래 명령으로 초기 admin의 암호를 확인합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713591176391&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath=&quot;{.data.password}&quot; | base64 -d ;echo&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1239&quot; data-origin-height=&quot;41&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CY3DM/btsGNaAJ1Wf/F7nqT5VrQwCtvBE15UE7PK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CY3DM/btsGNaAJ1Wf/F7nqT5VrQwCtvBE15UE7PK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CY3DM/btsGNaAJ1Wf/F7nqT5VrQwCtvBE15UE7PK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCY3DM%2FbtsGNaAJ1Wf%2FF7nqT5VrQwCtvBE15UE7PK%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;1239&quot; height=&quot;41&quot; data-origin-width=&quot;1239&quot; data-origin-height=&quot;41&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;size16&quot;&gt;admin/위 비밀번호로 로그인 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NewAPP을 클릭합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1248&quot; data-origin-height=&quot;296&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfISkn/btsGL2p5CWR/EmrrSmNPnKWH6FAHgWhfHk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfISkn/btsGL2p5CWR/EmrrSmNPnKWH6FAHgWhfHk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfISkn/btsGL2p5CWR/EmrrSmNPnKWH6FAHgWhfHk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfISkn%2FbtsGL2p5CWR%2FEmrrSmNPnKWH6FAHgWhfHk%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;1248&quot; height=&quot;296&quot; data-origin-width=&quot;1248&quot; data-origin-height=&quot;296&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;size16&quot;&gt;아래와 같이 내용을 기입하고 생성합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;970&quot; data-origin-height=&quot;826&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cjqZNF/btsGMKWLvCn/KrtCBgdTuUImULAxku5Z20/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cjqZNF/btsGMKWLvCn/KrtCBgdTuUImULAxku5Z20/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cjqZNF/btsGMKWLvCn/KrtCBgdTuUImULAxku5Z20/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcjqZNF%2FbtsGMKWLvCn%2FKrtCBgdTuUImULAxku5Z20%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;970&quot; height=&quot;826&quot; data-origin-width=&quot;970&quot; data-origin-height=&quot;826&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;956&quot; data-origin-height=&quot;416&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnv00k/btsGLFV5sGA/bVceR1RzEgH8X1Azy9dIj1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnv00k/btsGLFV5sGA/bVceR1RzEgH8X1Azy9dIj1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnv00k/btsGLFV5sGA/bVceR1RzEgH8X1Azy9dIj1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbnv00k%2FbtsGLFV5sGA%2FbVceR1RzEgH8X1Azy9dIj1%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;956&quot; height=&quot;416&quot; data-origin-width=&quot;956&quot; data-origin-height=&quot;416&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;957&quot; data-origin-height=&quot;307&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ctk9dF/btsGOxPi6uS/ONZmqaAjgWnG6p0tE3N1pk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ctk9dF/btsGOxPi6uS/ONZmqaAjgWnG6p0tE3N1pk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ctk9dF/btsGOxPi6uS/ONZmqaAjgWnG6p0tE3N1pk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fctk9dF%2FbtsGOxPi6uS%2FONZmqaAjgWnG6p0tE3N1pk%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;957&quot; height=&quot;307&quot; data-origin-width=&quot;957&quot; data-origin-height=&quot;307&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;size16&quot;&gt;생성된 Application에 접근합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1248&quot; data-origin-height=&quot;488&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFdKCR/btsGNsupJ8j/7XMdQNN16tH3IKlrh9MqoK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFdKCR/btsGNsupJ8j/7XMdQNN16tH3IKlrh9MqoK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFdKCR/btsGNsupJ8j/7XMdQNN16tH3IKlrh9MqoK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFdKCR%2FbtsGNsupJ8j%2F7XMdQNN16tH3IKlrh9MqoK%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;1248&quot; height=&quot;488&quot; data-origin-width=&quot;1248&quot; data-origin-height=&quot;488&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;size16&quot;&gt;Sync -&amp;gt; Syncronize를 클릭합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1252&quot; data-origin-height=&quot;859&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yEnuf/btsGMBluzQ7/FOEu7WzZ6GyRgMzckOrlzk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yEnuf/btsGMBluzQ7/FOEu7WzZ6GyRgMzckOrlzk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yEnuf/btsGMBluzQ7/FOEu7WzZ6GyRgMzckOrlzk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyEnuf%2FbtsGMBluzQ7%2FFOEu7WzZ6GyRgMzckOrlzk%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;1252&quot; height=&quot;859&quot; data-origin-width=&quot;1252&quot; data-origin-height=&quot;859&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;size16&quot;&gt;Application이 Health되었습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1401&quot; data-origin-height=&quot;355&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/baCWem/btsGMFgZEo4/6BrzxwvklRC1g0aS8cXq10/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/baCWem/btsGMFgZEo4/6BrzxwvklRC1g0aS8cXq10/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/baCWem/btsGMFgZEo4/6BrzxwvklRC1g0aS8cXq10/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbaCWem%2FbtsGMFgZEo4%2F6BrzxwvklRC1g0aS8cXq10%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;1401&quot; height=&quot;355&quot; data-origin-width=&quot;1401&quot; data-origin-height=&quot;355&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;size16&quot;&gt;`kubectl get all -n first`로 조회 시 리소스가 조회된것을 알 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;595&quot; data-origin-height=&quot;273&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMP18K/btsGPasNxzQ/qOhkuPrOSJKD3D7VkHVBwk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMP18K/btsGPasNxzQ/qOhkuPrOSJKD3D7VkHVBwk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMP18K/btsGPasNxzQ/qOhkuPrOSJKD3D7VkHVBwk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMP18K%2FbtsGPasNxzQ%2FqOhkuPrOSJKD3D7VkHVBwk%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;595&quot; height=&quot;273&quot; data-origin-width=&quot;595&quot; data-origin-height=&quot;273&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;size16&quot;&gt;Github의 Yaml파일을 수정해 보겠습니다. yaml의 label을 추가하고 저장합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;927&quot; data-origin-height=&quot;249&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Jtm8C/btsGL4OYm4L/RcmFqspboNQ2bbfIBZaMr0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Jtm8C/btsGL4OYm4L/RcmFqspboNQ2bbfIBZaMr0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Jtm8C/btsGL4OYm4L/RcmFqspboNQ2bbfIBZaMr0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJtm8C%2FbtsGL4OYm4L%2FRcmFqspboNQ2bbfIBZaMr0%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;927&quot; height=&quot;249&quot; data-origin-width=&quot;927&quot; data-origin-height=&quot;249&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;size16&quot;&gt;Refresh를 누르거나 3분을 기다리면 Status가 OutOfSync로 변경됩니다. Sync를 누르게 되면 Git에서 추가한 labels가 반영된 Deployment가 배포 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1022&quot; data-origin-height=&quot;294&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CfBkG/btsGNGsrnyU/NivKR2xICj7FuLBxdWot0k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CfBkG/btsGNGsrnyU/NivKR2xICj7FuLBxdWot0k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CfBkG/btsGNGsrnyU/NivKR2xICj7FuLBxdWot0k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCfBkG%2FbtsGNGsrnyU%2FNivKR2xICj7FuLBxdWot0k%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;1022&quot; height=&quot;294&quot; data-origin-width=&quot;1022&quot; data-origin-height=&quot;294&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;946&quot; data-origin-height=&quot;390&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bSw1gi/btsGNDvI5j7/QCXD1kKYTn5g9VMdN2NtgK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bSw1gi/btsGNDvI5j7/QCXD1kKYTn5g9VMdN2NtgK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bSw1gi/btsGNDvI5j7/QCXD1kKYTn5g9VMdN2NtgK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbSw1gi%2FbtsGNDvI5j7%2FQCXD1kKYTn5g9VMdN2NtgK%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;946&quot; height=&quot;390&quot; data-origin-width=&quot;946&quot; data-origin-height=&quot;390&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;size16&quot;&gt;위와 같이 Gitops를 하기 위해선 배포 yaml 수정을 git에서 진행해야 합니다.&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;생성한 Application은 Delete를 누른 뒤 아래와 같이 삭제합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;370&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b07hG9/btsGMfbMpNN/SSNa4TDBw4pxvh6WuYZuG1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b07hG9/btsGMfbMpNN/SSNa4TDBw4pxvh6WuYZuG1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b07hG9/btsGMfbMpNN/SSNa4TDBw4pxvh6WuYZuG1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb07hG9%2FbtsGMfbMpNN%2FSSNa4TDBw4pxvh6WuYZuG1%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;1024&quot; height=&quot;370&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;370&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;size16&quot;&gt;위 방식은 Web UI를 통해 구현한 예시입니다. Jenkins와 같은 도구나 CLI환경에서 배포해야 하는경우 argo cli를 설치한 뒤 사용할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713596975415&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#
curl -sSL -o argocd-linux-amd64 https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64
sudo install -m 555 argocd-linux-amd64 /usr/local/bin/argocd
rm -f argocd-linux-amd64

#
argocd version

#
argocd login argocd.$MyDomain
Username: admin
Password: ###
'admin:login' logged in successfully

#
kubectl config get-contexts -o name
hakjunadmin@myeks.ap-northeast-2.eksctl.io
argocd cluster add hakjunadmin@myeks.ap-northeast-2.eksctl.io
y 입력

#
argocd app list
NAME  CLUSTER  NAMESPACE  PROJECT  STATUS  HEALTH  SYNCPOLICY  CONDITIONS  REPO  PATH  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;size16&quot;&gt;아래 명령으로 Application을 생성할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713597029151&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl config set-context --current --namespace=argocd
argocd app create guestbook --repo https://github.com/argoproj/argocd-example-apps.git --path guestbook --dest-server https://kubernetes.default.svc --dest-namespace default&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;538&quot; data-origin-height=&quot;493&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GE4j5/btsGN1C7YG7/DfNktrzeXBH01OQvWu0WW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GE4j5/btsGN1C7YG7/DfNktrzeXBH01OQvWu0WW0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GE4j5/btsGN1C7YG7/DfNktrzeXBH01OQvWu0WW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGE4j5%2FbtsGN1C7YG7%2FDfNktrzeXBH01OQvWu0WW0%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;538&quot; height=&quot;493&quot; data-origin-width=&quot;538&quot; data-origin-height=&quot;493&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;size16&quot;&gt;아래 명령으로 sync를 맞출 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713597100028&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;argocd app sync guestbook&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1018&quot; data-origin-height=&quot;624&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cUp08R/btsGOfBewAi/rGbrwAt212OHCIWOjHwsK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cUp08R/btsGOfBewAi/rGbrwAt212OHCIWOjHwsK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cUp08R/btsGOfBewAi/rGbrwAt212OHCIWOjHwsK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcUp08R%2FbtsGOfBewAi%2FrGbrwAt212OHCIWOjHwsK0%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;1018&quot; height=&quot;624&quot; data-origin-width=&quot;1018&quot; data-origin-height=&quot;624&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;size16&quot;&gt;Application 삭제&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;648&quot; data-origin-height=&quot;114&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ye36T/btsGLFhykuB/fRxHclLZnpSGKEoy3mTnNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ye36T/btsGLFhykuB/fRxHclLZnpSGKEoy3mTnNK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ye36T/btsGLFhykuB/fRxHclLZnpSGKEoy3mTnNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fye36T%2FbtsGLFhykuB%2FfRxHclLZnpSGKEoy3mTnNK%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;648&quot; height=&quot;114&quot; data-origin-width=&quot;648&quot; data-origin-height=&quot;114&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;h3 data-ke-size=&quot;size23&quot;&gt;Argo Rollouts&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Argo Project 중 하나로 고급 배포 전략을 제공합니다. 그 중 대표적인 것으로 Blue-Green, Canary 배포 전략입니다.&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;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1340&quot; data-origin-height=&quot;1733&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/smeR5/btsGNNLJ6x7/xjjmPYg2WBKNAgnqWRahTK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/smeR5/btsGNNLJ6x7/xjjmPYg2WBKNAgnqWRahTK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/smeR5/btsGNNLJ6x7/xjjmPYg2WBKNAgnqWRahTK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsmeR5%2FbtsGNNLJ6x7%2FxjjmPYg2WBKNAgnqWRahTK%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;1340&quot; height=&quot;1733&quot; data-origin-width=&quot;1340&quot; data-origin-height=&quot;1733&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;size16&quot;&gt;카나리&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1340&quot; data-origin-height=&quot;1733&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lVW5m/btsGM4gqJ6c/Log0FM1knt510njYUOhEPK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lVW5m/btsGM4gqJ6c/Log0FM1knt510njYUOhEPK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lVW5m/btsGM4gqJ6c/Log0FM1knt510njYUOhEPK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlVW5m%2FbtsGM4gqJ6c%2FLog0FM1knt510njYUOhEPK%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;1340&quot; height=&quot;1733&quot; data-origin-width=&quot;1340&quot; data-origin-height=&quot;1733&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;size16&quot;&gt;아래 명령으로 설치를 진행합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713597364719&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#
cat &amp;lt;&amp;lt;EOT &amp;gt; argorollouts-values.yaml
dashboard:
  enabled: true
  ingress:
    enabled: true
    ingressClassName: alb
    hosts:
      - argorollouts.$MyDomain
    annotations:
      alb.ingress.kubernetes.io/scheme: internet-facing
      alb.ingress.kubernetes.io/target-type: ip
      alb.ingress.kubernetes.io/backend-protocol: HTTP
      alb.ingress.kubernetes.io/listen-ports: '[{&quot;HTTPS&quot;:80}, {&quot;HTTPS&quot;:443}]'
      alb.ingress.kubernetes.io/certificate-arn: $CERT_ARN
      alb.ingress.kubernetes.io/ssl-redirect: '443'
EOT

kubectl create ns argo-rollouts
helm install argo-rollouts argo/argo-rollouts --version 2.35.1 -f argorollouts-values.yaml --namespace argo-rollouts

# 확인
kubectl get all -n argo-rollouts
kubectl get crd | grep argo

curl -LO https://github.com/argoproj/argo-rollouts/releases/download/v1.6.4/kubectl-argo-rollouts-linux-amd64
chmod +x ./kubectl-argo-rollouts-linux-amd64
mv ./kubectl-argo-rollouts-linux-amd64 /usr/local/bin/kubectl-argo-rollouts

# 설치 확인
kubectl argo rollouts version&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;661&quot; data-origin-height=&quot;173&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qs7VL/btsGOJ3a8SD/peTP3ju8t1bL64eEiemy80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qs7VL/btsGOJ3a8SD/peTP3ju8t1bL64eEiemy80/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qs7VL/btsGOJ3a8SD/peTP3ju8t1bL64eEiemy80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fqs7VL%2FbtsGOJ3a8SD%2FpeTP3ju8t1bL64eEiemy80%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;661&quot; height=&quot;173&quot; data-origin-width=&quot;661&quot; data-origin-height=&quot;173&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;size16&quot;&gt;아래 yaml을 배포합니다. Canary 배포를 진행하며, 최초 20% 비율로 트래픽을 흘리고, 승인 뒤&amp;nbsp; 40%, 10초 단위로 20% 증가하는 방식의 배포입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713597648143&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;spec:
  replicas: 5
  strategy:
    canary:
      steps:
      - setWeight: 20
      - pause: {}
      - setWeight: 40
      - pause: {duration: 10}
      - setWeight: 60
      - pause: {duration: 10}
      - setWeight: 80
      - pause: {duration: 10}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1713597703068&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Run the following command to deploy the initial Rollout and Service:
kubectl apply -f https://raw.githubusercontent.com/argoproj/argo-rollouts/master/docs/getting-started/basic/rollout.yaml
kubectl apply -f https://raw.githubusercontent.com/argoproj/argo-rollouts/master/docs/getting-started/basic/service.yaml&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;rollouts으로 배포된 리소스는 아래 명령어로 확인 가능합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713597753396&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl argo rollouts get rollout rollouts-demo&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;656&quot; data-origin-height=&quot;439&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFnP4P/btsGMJDB1hX/bX5nOdMNMAXpewyH8hn0k1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFnP4P/btsGMJDB1hX/bX5nOdMNMAXpewyH8hn0k1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFnP4P/btsGMJDB1hX/bX5nOdMNMAXpewyH8hn0k1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFnP4P%2FbtsGMJDB1hX%2FbX5nOdMNMAXpewyH8hn0k1%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;656&quot; height=&quot;439&quot; data-origin-width=&quot;656&quot; data-origin-height=&quot;439&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;size16&quot;&gt;`https://argorollouts.junkmm.site/rollouts/default`에 접근합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1246&quot; data-origin-height=&quot;859&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VBJXb/btsGM9V9vlP/dnJOUiuK0mrSDISTw0EyU1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VBJXb/btsGM9V9vlP/dnJOUiuK0mrSDISTw0EyU1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VBJXb/btsGM9V9vlP/dnJOUiuK0mrSDISTw0EyU1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVBJXb%2FbtsGM9V9vlP%2FdnJOUiuK0mrSDISTw0EyU1%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;1246&quot; height=&quot;859&quot; data-origin-width=&quot;1246&quot; data-origin-height=&quot;859&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;size16&quot;&gt;아래의 명령어로 기존 리소스의 컨테이너 이미지를 업데이트 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713598048313&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl argo rollouts set image rollouts-demo rollouts-demo=argoproj/rollouts-demo:yellow&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;위 yaml의 정의에 따라 관리자의 수동 승인 전 까지는 새로운 버전에 대핸 20%를 유지합니다. 총 5개 파드이니, 1개의 신규 버전과 4개의 기존 버전이 배포됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1208&quot; data-origin-height=&quot;837&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HDm3z/btsGLGtYOty/RlivCKdZCNXjbCraMHRaRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HDm3z/btsGLGtYOty/RlivCKdZCNXjbCraMHRaRk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HDm3z/btsGLGtYOty/RlivCKdZCNXjbCraMHRaRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHDm3z%2FbtsGLGtYOty%2FRlivCKdZCNXjbCraMHRaRk%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;1208&quot; height=&quot;837&quot; data-origin-width=&quot;1208&quot; data-origin-height=&quot;837&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;size16&quot;&gt;상단의 Promote를 클릭합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;568&quot; data-origin-height=&quot;153&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uwy4L/btsGOwCT4Bh/XRJChNsH0DVKUJtSxtMuOk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uwy4L/btsGOwCT4Bh/XRJChNsH0DVKUJtSxtMuOk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uwy4L/btsGOwCT4Bh/XRJChNsH0DVKUJtSxtMuOk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fuwy4L%2FbtsGOwCT4Bh%2FXRJChNsH0DVKUJtSxtMuOk%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;568&quot; height=&quot;153&quot; data-origin-width=&quot;568&quot; data-origin-height=&quot;153&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;size16&quot;&gt;승인되면 순차적으로 신규버전이 80%가 되기 까지 10초 씩 증가합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1189&quot; data-origin-height=&quot;910&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nJS69/btsGNCRdZrn/EIuytSmPSjUbTU23jT6wF1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nJS69/btsGNCRdZrn/EIuytSmPSjUbTU23jT6wF1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nJS69/btsGNCRdZrn/EIuytSmPSjUbTU23jT6wF1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnJS69%2FbtsGNCRdZrn%2FEIuytSmPSjUbTU23jT6wF1%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;1189&quot; height=&quot;910&quot; data-origin-width=&quot;1189&quot; data-origin-height=&quot;910&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;size16&quot;&gt;rollback을 누르게 되면 기존 버전으로 되돌아 갑니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1166&quot; data-origin-height=&quot;478&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DRf14/btsGN1iNiuy/alewkRwSgFKlK7CklyQMkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DRf14/btsGN1iNiuy/alewkRwSgFKlK7CklyQMkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DRf14/btsGN1iNiuy/alewkRwSgFKlK7CklyQMkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDRf14%2FbtsGN1iNiuy%2FalewkRwSgFKlK7CklyQMkk%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;1166&quot; height=&quot;478&quot; data-origin-width=&quot;1166&quot; data-origin-height=&quot;478&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;size16&quot;&gt;이전(승인 전)으로 되돌아간 생태에서 Abort를 누르면 모든 파드가 완전히 이전 버전으로 배포됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1229&quot; data-origin-height=&quot;907&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2R0bT/btsGNZk1UhV/H6CLd9l8KBCS04k905VWg1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2R0bT/btsGNZk1UhV/H6CLd9l8KBCS04k905VWg1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2R0bT/btsGNZk1UhV/H6CLd9l8KBCS04k905VWg1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2R0bT%2FbtsGNZk1UhV%2FH6CLd9l8KBCS04k905VWg1%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;1229&quot; height=&quot;907&quot; data-origin-width=&quot;1229&quot; data-origin-height=&quot;907&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;size16&quot;&gt;&amp;nbsp;&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;pre id=&quot;code_1713598579156&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;eksctl delete cluster --name $CLUSTER_NAME &amp;amp;&amp;amp; aws cloudformation delete-stack --stack-name $CLUSTER_NAME&lt;/code&gt;&lt;/pre&gt;</description>
      <category>클라우드</category>
      <author>junkmm</author>
      <guid isPermaLink="true">https://junkmm.tistory.com/37</guid>
      <comments>https://junkmm.tistory.com/37#entry37comment</comments>
      <pubDate>Tue, 16 Apr 2024 20:32:21 +0900</pubDate>
    </item>
    <item>
      <title>[EKS] Security</title>
      <link>https://junkmm.tistory.com/36</link>
      <description>&lt;blockquote data-ke-style=&quot;style2&quot;&gt;이번 게시글은 가시다님의 AEWS [2기] 스터디 내용을 정리한 포스트 입니다.&lt;br /&gt;이번 게시글은 6 주차의 스터디 내용인 EKS Security에 대해 살펴봅니다.&lt;/blockquote&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;EKS 배포&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실습을 위해 EKS 클러스터를 배포합니다. AWS 콘솔에 로그인 한 뒤 CloudFormation에서 아래 YAML 파일로 스택을 생성하시면 됩니다. 진행 과정은 아래 링크를 참고해 주세요.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignLeft&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/FTx3f/btsGx3Ivqvj/eTKseKbTYGyTfdXRZ9ZqIK/eks-oneclick5.yaml?attach=1&amp;amp;knm=tfile.yaml&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;eks-oneclick5.yaml&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.02MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;figure id=&quot;og_1712829771207&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;[EKS] Networking&quot; data-og-description=&quot;이번 게시글은 가시다님의 AEWS [2기] 스터디 내용을 정리한 포스트 입니다. 이번 게시글은 2 주차의 스터디 내용인 EKS Networking에 대해 살펴봅니다. EKS 원클릭 배포 사전 준비 AWS 계정 SSH 키 페어 IA&quot; data-og-host=&quot;junkmm.tistory.com&quot; data-og-source-url=&quot;https://junkmm.tistory.com/32&quot; data-og-url=&quot;https://junkmm.tistory.com/32&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bsBTgE/hyVMVWsC3I/ERrMAYTRV23Fv8QkzE7Jh1/img.png?width=800&amp;amp;height=411&amp;amp;face=0_0_800_411,https://scrap.kakaocdn.net/dn/IKIDe/hyVPNbnP4W/nf6ukCGQzghiKXfFvwvpy0/img.png?width=800&amp;amp;height=411&amp;amp;face=0_0_800_411,https://scrap.kakaocdn.net/dn/bPWu9c/hyVMYFCzOk/KZWb7SMqZVOkPel6yesSS1/img.png?width=2060&amp;amp;height=1226&amp;amp;face=0_0_2060_1226&quot;&gt;&lt;a href=&quot;https://junkmm.tistory.com/32&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://junkmm.tistory.com/32&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bsBTgE/hyVMVWsC3I/ERrMAYTRV23Fv8QkzE7Jh1/img.png?width=800&amp;amp;height=411&amp;amp;face=0_0_800_411,https://scrap.kakaocdn.net/dn/IKIDe/hyVPNbnP4W/nf6ukCGQzghiKXfFvwvpy0/img.png?width=800&amp;amp;height=411&amp;amp;face=0_0_800_411,https://scrap.kakaocdn.net/dn/bPWu9c/hyVMYFCzOk/KZWb7SMqZVOkPel6yesSS1/img.png?width=2060&amp;amp;height=1226&amp;amp;face=0_0_2060_1226');&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;[EKS] Networking&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이번 게시글은 가시다님의 AEWS [2기] 스터디 내용을 정리한 포스트 입니다. 이번 게시글은 2 주차의 스터디 내용인 EKS Networking에 대해 살펴봅니다. EKS 원클릭 배포 사전 준비 AWS 계정 SSH 키 페어 IA&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;junkmm.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;배포 확인&lt;/h3&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;p data-ke-size=&quot;size16&quot;&gt;Bastion EC2 인스턴스의 공인 IP로 SSH 접근을 시도합니다. 공인 IP는 CloudFormation의 결과에 나오는 출력값 혹은 EC2 메뉴에서 bastion 호스트의 공인 IP를 확인합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1712829859004&quot; class=&quot;angelscript&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# ssh -i &quot;Keyname&quot; ec2-user@&quot;Public IP&quot;
ssh -i hj42700eks.pem ec2-user@3.36.133.15&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;Bastion 접속 후 아래와 같이 기본 설정을 진행합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1712829916093&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# default 네임스페이스 적용
kubectl ns default

# 노드 정보 확인 : t3.medium
kubectl get node --label-columns=node.kubernetes.io/instance-type,eks.amazonaws.com/capacityType,topology.kubernetes.io/zone

# ExternalDNS
MyDomain=&amp;lt;자신의 도메인&amp;gt;
echo &quot;export MyDomain=&amp;lt;자신의 도메인&amp;gt;&quot; &amp;gt;&amp;gt; /etc/profile
MyDomain=junkmm.site
echo &quot;export MyDomain=junkmm.site&quot; &amp;gt;&amp;gt; /etc/profile
MyDnzHostedZoneId=$(aws route53 list-hosted-zones-by-name --dns-name &quot;${MyDomain}.&quot; --query &quot;HostedZones[0].Id&quot; --output text)
echo $MyDomain, $MyDnzHostedZoneId
curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/aews/externaldns.yaml
MyDomain=$MyDomain MyDnzHostedZoneId=$MyDnzHostedZoneId envsubst &amp;lt; externaldns.yaml | kubectl apply -f -

# kube-ops-view
helm repo add geek-cookbook https://geek-cookbook.github.io/charts/
helm install kube-ops-view geek-cookbook/kube-ops-view --version 1.2.2 --set env.TZ=&quot;Asia/Seoul&quot; --namespace kube-system
kubectl patch svc -n kube-system kube-ops-view -p '{&quot;spec&quot;:{&quot;type&quot;:&quot;LoadBalancer&quot;}}'
kubectl annotate service kube-ops-view -n kube-system &quot;external-dns.alpha.kubernetes.io/hostname=kubeopsview.$MyDomain&quot;
echo -e &quot;Kube Ops View URL = http://kubeopsview.$MyDomain:8080/#scale=1.5&quot;

# AWS LB Controller
helm repo add eks https://aws.github.io/eks-charts
helm repo update
helm install aws-load-balancer-controller eks/aws-load-balancer-controller -n kube-system --set clusterName=$CLUSTER_NAME \
  --set serviceAccount.create=false --set serviceAccount.name=aws-load-balancer-controller

# gp3 스토리지 클래스 생성
kubectl apply -f https://raw.githubusercontent.com/gasida/PKOS/main/aews/gp3-sc.yaml

# 노드 IP 확인 및 PrivateIP 변수 지정
N1=$(kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2a -o jsonpath={.items[0].status.addresses[0].address})
N2=$(kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2b -o jsonpath={.items[0].status.addresses[0].address})
N3=$(kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2c -o jsonpath={.items[0].status.addresses[0].address})
echo &quot;export N1=$N1&quot; &amp;gt;&amp;gt; /etc/profile
echo &quot;export N2=$N2&quot; &amp;gt;&amp;gt; /etc/profile
echo &quot;export N3=$N3&quot; &amp;gt;&amp;gt; /etc/profile
echo $N1, $N2, $N3

# 노드 보안그룹 ID 확인
NGSGID=$(aws ec2 describe-security-groups --filters Name=group-name,Values=*ng1* --query &quot;SecurityGroups[*].[GroupId]&quot; --output text)
aws ec2 authorize-security-group-ingress --group-id $NGSGID --protocol '-1' --cidr 192.168.1.100/32
aws ec2 authorize-security-group-ingress --group-id $NGSGID --protocol '-1' --cidr 192.168.1.200/32

# 워커 노드 SSH 접속
for node in $N1 $N2 $N3; do ssh -o StrictHostKeyChecking=no ec2-user@$node hostname; done
for node in $N1 $N2 $N3; do ssh ec2-user@$node hostname; done&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;프로메테우스 &amp;amp; 그라파나(admin / prom-operator) 설치 : 대시보드 추천 15757 17900 15172&lt;/p&gt;
&lt;pre id=&quot;code_1712830155294&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 사용 리전의 인증서 ARN 확인
CERT_ARN=`aws acm list-certificates --query 'CertificateSummaryList[].CertificateArn[]' --output text`
echo $CERT_ARN

# repo 추가
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts

# 파라미터 파일 생성 : PV/PVC(AWS EBS) 삭제에 불편하니, 4주차 실습과 다르게 PV/PVC 미사용
cat &amp;lt;&amp;lt;EOT &amp;gt; monitor-values.yaml
prometheus:
  prometheusSpec:
    podMonitorSelectorNilUsesHelmValues: false
    serviceMonitorSelectorNilUsesHelmValues: false
    retention: 5d
    retentionSize: &quot;10GiB&quot;

  ingress:
    enabled: true
    ingressClassName: alb
    hosts: 
      - prometheus.$MyDomain
    paths: 
      - /*
    annotations:
      alb.ingress.kubernetes.io/scheme: internet-facing
      alb.ingress.kubernetes.io/target-type: ip
      alb.ingress.kubernetes.io/listen-ports: '[{&quot;HTTPS&quot;:443}, {&quot;HTTP&quot;:80}]'
      alb.ingress.kubernetes.io/certificate-arn: $CERT_ARN
      alb.ingress.kubernetes.io/success-codes: 200-399
      alb.ingress.kubernetes.io/load-balancer-name: myeks-ingress-alb
      alb.ingress.kubernetes.io/group.name: study
      alb.ingress.kubernetes.io/ssl-redirect: '443'

grafana:
  defaultDashboardsTimezone: Asia/Seoul
  adminPassword: prom-operator
  defaultDashboardsEnabled: false

  ingress:
    enabled: true
    ingressClassName: alb
    hosts: 
      - grafana.$MyDomain
    paths: 
      - /*
    annotations:
      alb.ingress.kubernetes.io/scheme: internet-facing
      alb.ingress.kubernetes.io/target-type: ip
      alb.ingress.kubernetes.io/listen-ports: '[{&quot;HTTPS&quot;:443}, {&quot;HTTP&quot;:80}]'
      alb.ingress.kubernetes.io/certificate-arn: $CERT_ARN
      alb.ingress.kubernetes.io/success-codes: 200-399
      alb.ingress.kubernetes.io/load-balancer-name: myeks-ingress-alb
      alb.ingress.kubernetes.io/group.name: study
      alb.ingress.kubernetes.io/ssl-redirect: '443'

alertmanager:
  enabled: false
EOT
cat monitor-values.yaml | yh

# 배포
kubectl create ns monitoring
helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack --version 57.2.0 \
--set prometheus.prometheusSpec.scrapeInterval='15s' --set prometheus.prometheusSpec.evaluationInterval='15s' \
-f monitor-values.yaml --namespace monitoring

# Metrics-server 배포
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

# 프로메테우스 ingress 도메인으로 웹 접속
echo -e &quot;Prometheus Web URL = https://prometheus.$MyDomain&quot;

# 그라파나 웹 접속 : 기본 계정 - admin / prom-operator
echo -e &quot;Grafana Web URL = https://grafana.$MyDomain&quot;&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;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Kubernetes 인증/인가&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Overview&lt;/b&gt; | 아래 그림은 kubernetes API를 호출하는 과정을 도식화 한 것입니다. 사용자는 `kubectl`같은 cli 도구로 `kubectl delete namespace demo`와 같은 명령어를 전송할 수 있습니다. 명령을 전달받은 API는 첫 째, 인증/인가를 수행합니다. 이 요청자의 신원을 파악하고, 신원이 파악되었다면 demo namespace를 지울 수 있는지에 대한 권한을 확인합니다. 추 후 validating admission는 demo namespace가 Terminating 중일 때 다른 사용자가 demo namespace에 리소스를 생성하지 못하도록 제약을 걸 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;715&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnAMaT/btsGzZkJqGJ/kYpzY8fslVougJcsZjGC61/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnAMaT/btsGzZkJqGJ/kYpzY8fslVougJcsZjGC61/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnAMaT/btsGzZkJqGJ/kYpzY8fslVougJcsZjGC61/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnAMaT%2FbtsGzZkJqGJ%2FkYpzY8fslVougJcsZjGC61%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;1920&quot; height=&quot;715&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;715&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;For example, when a namespace is deleted and subsequently enters the Terminating state, the&amp;nbsp;NamespaceLifecycle admission controller is what prevents any new objects from being created in this namespace.&lt;br /&gt;https://kubernetes.io/blog/2019/03/21/a-guide-to-kubernetes-admission-controllers/&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;b&gt;User Account의 종류&lt;/b&gt; | 아래 그림은 Kubernetes Api-server를 호출할 수 있는 User Account 종류에 대해 설명하고 있습니다. 사용자(제가)가 가장 많이 사용하는 kubectl로도 API를 호출할 수 있고, 별도의 Kubernetes Dashboard, 혹은 Service Account를 생성하고, 특정 리소스에 할당하여 Kubernetes API를 호출할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;979&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMWwKH/btsGwbHAX3p/zR73519ajpIqdhimh4txlK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMWwKH/btsGwbHAX3p/zR73519ajpIqdhimh4txlK/img.png&quot; data-alt=&quot;출처 :&amp;amp;amp;nbsp;&amp;amp;amp;nbsp;https://kubetm.github.io/k8s/07-intermediate-basic-resource/authentication/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMWwKH/btsGwbHAX3p/zR73519ajpIqdhimh4txlK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMWwKH%2FbtsGwbHAX3p%2FzR73519ajpIqdhimh4txlK%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;1920&quot; height=&quot;979&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;979&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처 :&amp;amp;nbsp;&amp;amp;nbsp;https://kubetm.github.io/k8s/07-intermediate-basic-resource/authentication/&lt;/figcaption&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;size16&quot;&gt;&lt;b&gt;인증&lt;/b&gt; | 아래 그림은 Kubernetes의 인증(Authentication)처리 방법에 대해 설명하고 있습니다. 크게 X.509 Client Certs, kubectl, Service Account 세 가지가 존재합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;949&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lNab7/btsGy8iqbdl/GkEN63yFQ83MiYRFWmtsQ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lNab7/btsGy8iqbdl/GkEN63yFQ83MiYRFWmtsQ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lNab7/btsGy8iqbdl/GkEN63yFQ83MiYRFWmtsQ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlNab7%2FbtsGy8iqbdl%2FGkEN63yFQ83MiYRFWmtsQ1%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;1920&quot; height=&quot;949&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;949&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;X.509 Client Certs 방식은 kubeconfig에 CA crt(발급 기관 인증서), Client crt(클라이언트 인증서), Client key(클라이언트 개인키)를 통해 인증하는 방식입니다. 호출 방식은 아래와 같습니다. kubectl이 아닌 `curl`을 통해 API를 호출합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1712832894063&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 출처 : https://coffeewhale.com/kubernetes/authentication/x509/2020/05/02/auth01/
# API 서버 주소 및 포트 설정
API_SERVER_ADDR=XXXX  # 예시) localhost
API_SERVER_PORT=XXX   # 예시) 6443

# kubectl - 신규 X.509 사용자 인증
curl --cacert k8s-rootCA.pem --cert k8s-new-client.pem --key k8s-new-client-key.pem https://$API_SERVER_ADDR:$API_SERVER_PORT/api
# kubectl - 신규 X.509 사용자 인증
kubectl --kubeconfig=$HOME/kubeconfig get pod -n kube-system&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;kubectl 방식은 사용자 cli를 통해 API를 호출하는 것으로 보통 `~/.kube/config`에 기재된 kubernetes 접속, 인증 정보를 기반으로 API를 호출합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service Account는 &lt;span style=&quot;background-color: #ffffff; color: #222222; text-align: left;&quot;&gt;파드의 일부 컨테이너에서 실행되는 애플리케이션 프로세스를 위한 것으로, Token을 사용해 API를 호출할 수 있습니다.&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;span style=&quot;background-color: #ffffff; color: #222222; text-align: left;&quot;&gt;&lt;b&gt;인가&lt;/b&gt; | 인가의 경우 인증을 통해 식별된 안전한 사용자가 수행하는 행위(create, delete 등)에 대해 제어합니다. RBAC방식으로 이를 구현합니다. RBAC은 역할 기반의 권한 관리로, 사용자와 역할을 별개로 선언한 뒤 두가지를 조합(binding)하여 사용자에게 권한을 부여하는 방식으로 kubectl 혹은 API로 관리할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;940&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZcyfU/btsGyEhsm2y/6HkbYSkzlc5Wngftt9zdb1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZcyfU/btsGyEhsm2y/6HkbYSkzlc5Wngftt9zdb1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZcyfU/btsGyEhsm2y/6HkbYSkzlc5Wngftt9zdb1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZcyfU%2FbtsGyEhsm2y%2F6HkbYSkzlc5Wngftt9zdb1%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;1920&quot; height=&quot;940&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;940&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;size16&quot;&gt;간단한 실습으로 인증/인가를 확인해 보겠습니다. dev, infra user, dev, infra namespace를 생성한 뒤 각 사용자는 본인의 namespace에 대해서만 제어할 수 있도록 구성해봅니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1340&quot; data-origin-height=&quot;968&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XEWwB/btsGyHFkiMe/ysF9QrP3BwPAKUmUnhISM0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XEWwB/btsGyHFkiMe/ysF9QrP3BwPAKUmUnhISM0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XEWwB/btsGyHFkiMe/ysF9QrP3BwPAKUmUnhISM0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXEWwB%2FbtsGyHFkiMe%2FysF9QrP3BwPAKUmUnhISM0%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;1340&quot; height=&quot;968&quot; data-origin-width=&quot;1340&quot; data-origin-height=&quot;968&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;size16&quot;&gt;먼저 dev-team, infra-team 이름의 네임스페이스와 서비스 어카운트를 생성합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1712834550235&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 네임스페이스(Namespace, NS) 생성 및 확인
kubectl create namespace dev-team
kubectl create ns infra-team

# 네임스페이스 확인
kubectl get ns
---
NAME              STATUS   AGE
default           Active   104m
dev-team          Active   3s
infra-team        Active   2s
kube-node-lease   Active   104m
kube-public       Active   104m
kube-system       Active   104m
monitoring        Active   73m

# 네임스페이스에 각각 서비스 어카운트 생성 : serviceaccounts 약자(=sa)
kubectl create sa dev-k8s -n dev-team
kubectl create sa infra-k8s -n infra-team

# 서비스 어카운트 정보 확인
kubectl get sa -n dev-team
kubectl get sa dev-k8s -n dev-team -o yaml | yh
---
apiVersion: v1
kind: ServiceAccount
metadata:
  creationTimestamp: &quot;2024-04-11T11:23:06Z&quot;
  name: dev-k8s
  namespace: dev-team
  resourceVersion: &quot;29441&quot;
  uid: 904ccd47-9588-42cc-a73a-b7d59563652a

kubectl get sa -n infra-team
kubectl get sa infra-k8s -n infra-team -o yaml | yh
---
apiVersion: v1
kind: ServiceAccount
metadata:
  creationTimestamp: &quot;2024-04-11T11:23:07Z&quot;
  name: infra-k8s
  namespace: infra-team
  resourceVersion: &quot;29446&quot;
  uid: 253d7d10-29d2-4f21-90a6-89979f528448&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;그 다음 각 네임스페이스에 kubectl 명령을 사용할 수 있는 Pod를 배포합니다. 이 때 `spec.serviceAccountName`을 주어 위에서 생성한 서비스 어카운트를 파드에 매핑합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1712834964156&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 각각 네임스피이스에 kubectl 파드 생성 - 컨테이너이미지
# docker run --rm --name kubectl -v /path/to/your/kube/config:/.kube/config bitnami/kubectl:latest
cat &amp;lt;&amp;lt;EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
  name: dev-kubectl
  namespace: dev-team
spec:
  serviceAccountName: dev-k8s
  containers:
  - name: kubectl-pod
    image: bitnami/kubectl:1.28.5
    command: [&quot;tail&quot;]
    args: [&quot;-f&quot;, &quot;/dev/null&quot;]
  terminationGracePeriodSeconds: 0
EOF

cat &amp;lt;&amp;lt;EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
  name: infra-kubectl
  namespace: infra-team
spec:
  serviceAccountName: infra-k8s
  containers:
  - name: kubectl-pod
    image: bitnami/kubectl:1.28.5
    command: [&quot;tail&quot;]
    args: [&quot;-f&quot;, &quot;/dev/null&quot;]
  terminationGracePeriodSeconds: 0
EOF

# 확인
kubectl get pod -A
kubectl get pod -o dev-kubectl -n dev-team -o yaml
 serviceAccount: dev-k8s
 ...
kubectl get pod -o infra-kubectl -n infra-team -o yaml
 serviceAccount: infra-k8s
...

# 파드에 기본 적용되는 서비스 어카운트(토큰) 정보 확인
kubectl exec -it dev-kubectl -n dev-team -- ls /run/secrets/kubernetes.io/serviceaccount
kubectl exec -it dev-kubectl -n dev-team -- cat /run/secrets/kubernetes.io/serviceaccount/token
kubectl exec -it dev-kubectl -n dev-team -- cat /run/secrets/kubernetes.io/serviceaccount/namespace
kubectl exec -it dev-kubectl -n dev-team -- cat /run/secrets/kubernetes.io/serviceaccount/ca.crt

# 각각 파드로 Shell 접속하여 정보 확인 : 단축 명령어(alias) 사용
alias k1='kubectl exec -it dev-kubectl -n dev-team -- kubectl'
alias k2='kubectl exec -it infra-kubectl -n infra-team -- kubectl'

# 권한 테스트
k1 get pods # kubectl exec -it dev-kubectl -n dev-team -- kubectl get pods 와 동일한 실행 명령이다!
k1 run nginx --image nginx:1.20-alpine
k1 get pods -n kube-system

k2 get pods # kubectl exec -it infra-kubectl -n infra-team -- kubectl get pods 와 동일한 실행 명령이다!
k2 run nginx --image nginx:1.20-alpine
k2 get pods -n kube-system

# (옵션) kubectl auth can-i 로 kubectl 실행 사용자가 특정 권한을 가졌는지 확인
k1 auth can-i get pods
no&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;`k1 get pods -n kube-system` 시 아래와 같이 dev-team 서비스 어카운트는 kube-system 네임스페이스에 pods의 list를 확인해볼 수 없다는 오류가 발생합니다.(forbidden)&lt;/p&gt;
&lt;pre id=&quot;code_1712834992356&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Error from server (Forbidden): pods is forbidden: User &quot;system:serviceaccount:dev-team:dev-k8s&quot; cannot list resource &quot;pods&quot; in API group &quot;&quot; in the namespace &quot;kube-system&quot;
command terminated with exit code 1&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 아래와 같이 각각 네임스페이스에 롤(Role)을 생성한 뒤 서비스 어카운트에 바인딩 하고, 결과를 확인 해 보겠습니다. 여기서 롤(Role,역할)은 apiGroups와 resources로 지정된 리소스에 대해 verbs 권한을 인가 해줌을 정의하고, verbs에는 *(모두 처리), create(생성), delete(삭제), get(조회), list(목록조회), patch(일부업데이트), update(업데이트), watch(변경감시) 옵션이 있습니다.&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;아래 코드에선 Role 정의 후 Role Binding을 진행합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1712835190567&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 각각 네임스페이스내의 모든 권한에 대한 롤 생성
cat &amp;lt;&amp;lt;EOF | kubectl create -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: role-dev-team
  namespace: dev-team
rules:
- apiGroups: [&quot;*&quot;]
  resources: [&quot;*&quot;]
  verbs: [&quot;*&quot;]
EOF

cat &amp;lt;&amp;lt;EOF | kubectl create -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: role-infra-team
  namespace: infra-team
rules:
- apiGroups: [&quot;*&quot;]
  resources: [&quot;*&quot;]
  verbs: [&quot;*&quot;]
EOF

# 롤 확인 
kubectl get roles -n dev-team
kubectl get roles -n infra-team
kubectl get roles -n dev-team -o yaml
kubectl describe roles role-dev-team -n dev-team
...
PolicyRule:
  Resources  Non-Resource URLs  Resource Names  Verbs
  ---------  -----------------  --------------  -----
  *.*        []                 []              [*]

# 롤바인딩 생성 : '서비스어카운트 &amp;lt;-&amp;gt; 롤' 간 서로 연동
cat &amp;lt;&amp;lt;EOF | kubectl create -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: roleB-dev-team
  namespace: dev-team
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: role-dev-team
subjects:
- kind: ServiceAccount
  name: dev-k8s
  namespace: dev-team
EOF

cat &amp;lt;&amp;lt;EOF | kubectl create -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: roleB-infra-team
  namespace: infra-team
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: role-infra-team
subjects:
- kind: ServiceAccount
  name: infra-k8s
  namespace: infra-team
EOF

# 롤바인딩 확인
kubectl get rolebindings -n dev-team
kubectl get rolebindings -n infra-team
kubectl get rolebindings -n dev-team -o yaml
kubectl describe rolebindings roleB-dev-team -n dev-team
...
Role:
  Kind:  Role
  Name:  role-dev-team
Subjects:
  Kind            Name     Namespace
  ----            ----     ---------
  ServiceAccount  dev-k8s  dev-team&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;서비스 어카운트를 지정한 뒤 파드에서 다시 권한을 테스트 해봅니다.&lt;/p&gt;
&lt;pre id=&quot;code_1712835532584&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 각각 파드로 Shell 접속하여 정보 확인 : 단축 명령어(alias) 사용
alias k1='kubectl exec -it dev-kubectl -n dev-team -- kubectl'
alias k2='kubectl exec -it infra-kubectl -n infra-team -- kubectl'

# 권한 테스트
k1 get pods 
k1 run nginx --image nginx:1.20-alpine
k1 get pods
k1 delete pods nginx
k1 get pods -n kube-system
k1 get nodes

k2 get pods 
k2 run nginx --image nginx:1.20-alpine
k2 get pods
k2 delete pods nginx
k2 get pods -n kube-system
k2 get nodes

# (옵션) kubectl auth can-i 로 kubectl 실행 사용자가 특정 권한을 가졌는지 확인
k1 auth can-i get pods
yes&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;dev Role에서 namespace를 dev-team으로 지정했기 때문에 아래와 같이 dev-pod에서는 dev-team 네임스페이스에 대한 리소스 조회, 생성이 가능하지만, 이 외 네임스페이스에 대해선 동일하게 forbidden 권한 오류가 발생하며 접근하지 못하는 것을 확인해볼 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1712835845354&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;(hakjunadmin@myeks:N/A) [root@myeks-bastion ~]# k1 get pods -n dev-team
NAME          READY   STATUS    RESTARTS   AGE
dev-kubectl   1/1     Running   0          17m
(hakjunadmin@myeks:N/A) [root@myeks-bastion ~]# k1 get pods -n infra-team
Error from server (Forbidden): pods is forbidden: User &quot;system:serviceaccount:dev-team:dev-k8s&quot; cannot list resource &quot;pods&quot; in API group &quot;&quot; in the namespace &quot;infra-team&quot;
command terminated with exit code 1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 서비스어카운트에 여러 네임스페이스에 대한 역할을 부여하고 싶다면, Role 대신 ClusterRole을 사용해야 합니다.&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;pre id=&quot;code_1712835871727&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl delete ns dev-team infra-team&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;EKS 인증/인가&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자는 EKS 클러스터에 kubectl 명령을 전송하면, 인증은 AWS IAM에서 처리하고, 인가는 Kubernetes RBAC에서 제어됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1401&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LobGg/btsGwxKohLq/dasGFYsZTy2kdlfgO4bd5K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LobGg/btsGwxKohLq/dasGFYsZTy2kdlfgO4bd5K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LobGg/btsGwxKohLq/dasGFYsZTy2kdlfgO4bd5K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLobGg%2FbtsGwxKohLq%2FdasGFYsZTy2kdlfgO4bd5K%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;1920&quot; height=&quot;1401&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1401&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;size16&quot;&gt;우선 EKS RBAC 분석을 용이하게 하기 위한 krew 플러그인 설치를 진행합니다.&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;pre id=&quot;code_1712932838699&quot; class=&quot;elixir&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# 설치
kubectl krew install access-matrix rbac-tool rbac-view rolesum whoami

# k8s 인증된 주체 확인
kubectl whoami
arn:aws:iam::6546...:user/hakjunadmin&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span data-token-index=&quot;0&quot;&gt;`access-matrix`는 EKS 리소스에 대한 권한을 확인할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1712932838700&quot; class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Show an RBAC access matrix for server resources
kubectl access-matrix # Review access to cluster-scoped resources
kubectl access-matrix --namespace default # Review access to namespaced resources in 'default'&lt;/code&gt;&lt;/pre&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;774&quot; data-origin-height=&quot;291&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b9IPG4/btsGzZZpaUi/KJWLUOxqr359ytagVqlldk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b9IPG4/btsGzZZpaUi/KJWLUOxqr359ytagVqlldk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b9IPG4/btsGzZZpaUi/KJWLUOxqr359ytagVqlldk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb9IPG4%2FbtsGzZZpaUi%2FKJWLUOxqr359ytagVqlldk%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;774&quot; height=&quot;291&quot; data-origin-width=&quot;774&quot; data-origin-height=&quot;291&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;`rback-tool lookup`은 사용자 별 역할을 확인해볼 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1712932838701&quot; class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# RBAC Lookup by subject (user/group/serviceaccount) name
kubectl rbac-tool lookup
kubectl rbac-tool lookup system:masters
  SUBJECT        | SUBJECT TYPE | SCOPE       | NAMESPACE | ROLE
+----------------+--------------+-------------+-----------+---------------+
  system:masters | Group        | ClusterRole |           | cluster-admin

kubectl rbac-tool lookup system:nodes # eks:node-bootstrapper
kubectl rbac-tool lookup system:bootstrappers # eks:node-bootstrapper
kubectl describe ClusterRole eks:node-bootstrapper&lt;/code&gt;&lt;/pre&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;818&quot; data-origin-height=&quot;71&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ceUqNn/btsGyS1hwCx/zFNkIbfcZCCPPAeMHSXqWk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ceUqNn/btsGyS1hwCx/zFNkIbfcZCCPPAeMHSXqWk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ceUqNn/btsGyS1hwCx/zFNkIbfcZCCPPAeMHSXqWk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FceUqNn%2FbtsGyS1hwCx%2FzFNkIbfcZCCPPAeMHSXqWk%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;818&quot; height=&quot;71&quot; data-origin-width=&quot;818&quot; data-origin-height=&quot;71&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;`kubectl rbac-tool whoami`는 현재 사용자 정보에 대해 출력합니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;668&quot; data-origin-height=&quot;155&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DepDY/btsGCcryn3F/AUKq9oXqOZRaCktkkTsH00/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DepDY/btsGCcryn3F/AUKq9oXqOZRaCktkkTsH00/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DepDY/btsGCcryn3F/AUKq9oXqOZRaCktkkTsH00/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDepDY%2FbtsGCcryn3F%2FAUKq9oXqOZRaCktkkTsH00%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;668&quot; height=&quot;155&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;668&quot; data-origin-height=&quot;155&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;`kubectl rolesum`은 서비스어카운트, 사용자, 그룹에 대한 RBAC 정보를 요약하여 알려줍니다.&lt;/p&gt;
&lt;pre id=&quot;code_1712932838701&quot; class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl rolesum -h
kubectl rolesum aws-node -n kube-system
kubectl rolesum -k User system:kube-proxy
kubectl rolesum -k Group system:masters
kubectl rolesum -k Group system:authenticated&lt;/code&gt;&lt;/pre&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;812&quot; data-origin-height=&quot;196&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNLT0L/btsGwB7uWK1/9XbithslezXQCT4enLGaS0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNLT0L/btsGwB7uWK1/9XbithslezXQCT4enLGaS0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNLT0L/btsGwB7uWK1/9XbithslezXQCT4enLGaS0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNLT0L%2FbtsGwB7uWK1%2F9XbithslezXQCT4enLGaS0%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;812&quot; height=&quot;196&quot; data-origin-width=&quot;812&quot; data-origin-height=&quot;196&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span data-token-index=&quot;0&quot;&gt;`kubectl rbac-view`는 RBAC 권한을 웹 페이지로 시각화하여 제공합니다.&lt;/span&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;917&quot; data-origin-height=&quot;79&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8KBAT/btsGxAfLruF/mAVYD9kqnikA3KcfIhbzKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8KBAT/btsGxAfLruF/mAVYD9kqnikA3KcfIhbzKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8KBAT/btsGxAfLruF/mAVYD9kqnikA3KcfIhbzKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8KBAT%2FbtsGxAfLruF%2FmAVYD9kqnikA3KcfIhbzKK%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;917&quot; height=&quot;79&quot; data-origin-width=&quot;917&quot; data-origin-height=&quot;79&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;890&quot; data-origin-height=&quot;609&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dQ5qYS/btsGySGZfVA/xN0MrMWQI5zSfrtaHrA3uK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dQ5qYS/btsGySGZfVA/xN0MrMWQI5zSfrtaHrA3uK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dQ5qYS/btsGySGZfVA/xN0MrMWQI5zSfrtaHrA3uK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdQ5qYS%2FbtsGySGZfVA%2FxN0MrMWQI5zSfrtaHrA3uK%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;890&quot; height=&quot;609&quot; data-origin-width=&quot;890&quot; data-origin-height=&quot;609&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&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 인증/인가 부분을 자세히 확인해 보겠습니다.&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;1. 사용자가 kube-api를 호출할 때 BearerToken(Pre-signed URL)을 함께 전달합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. kube-api는 admission과 연동된 Webhok Token Authentication에, Token Review를 요청합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. Webhok은 IAM에 sts GetCallerIdentity를 요청합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. IAM은 사용자 정보를 Webhok에 전달합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. Webhok은 IAM으로부터 전달받은 사용자 정보를 aws-auth Configmaps에 확인을 요청합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. IAM, Configmaps로 부터 사용자 인증이 완료되면, kube-api는 해당 사용자에 대한 권한을 확인합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7. 사용자 보유 권한 내 요청이 확인되면 요청을 승인합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1127&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QBwHZ/btsGAKQc3ab/L7M2wyF9aIpJGzGceu1HBk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QBwHZ/btsGAKQc3ab/L7M2wyF9aIpJGzGceu1HBk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QBwHZ/btsGAKQc3ab/L7M2wyF9aIpJGzGceu1HBk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQBwHZ%2FbtsGAKQc3ab%2FL7M2wyF9aIpJGzGceu1HBk%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;2000&quot; height=&quot;1127&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1127&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1457&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2a4bK/btsGA0FjpK8/fAH8LtwsZYpia0VvdQnLx0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2a4bK/btsGA0FjpK8/fAH8LtwsZYpia0VvdQnLx0/img.png&quot; data-alt=&quot;출처 :&amp;amp;amp;nbsp;https://devlos.tistory.com/75&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2a4bK/btsGA0FjpK8/fAH8LtwsZYpia0VvdQnLx0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2a4bK%2FbtsGA0FjpK8%2FfAH8LtwsZYpia0VvdQnLx0%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;2000&quot; height=&quot;1457&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1457&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처 :&amp;amp;nbsp;https://devlos.tistory.com/75&lt;/figcaption&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;size16&quot;&gt;위 과정을 상세히 확인해보겠습니다. 먼저 Token입니다. 아래 aws cli를 입력하면 Token값을 반환 합니다. Token은 만료 기간이 있습니다. 기간이 만료되면 토큰이 노출되더라도 실제 사용은 불가능합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1712933364675&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;aws eks get-token --cluster-name $CLUSTER_NAME | jq&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1247&quot; data-origin-height=&quot;152&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b9w7b7/btsGAd6g74X/a3FTv7Etg9KfGGa47gXYK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b9w7b7/btsGAd6g74X/a3FTv7Etg9KfGGa47gXYK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b9w7b7/btsGAd6g74X/a3FTv7Etg9KfGGa47gXYK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb9w7b7%2FbtsGAd6g74X%2Fa3FTv7Etg9KfGGa47gXYK0%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;1247&quot; height=&quot;152&quot; data-origin-width=&quot;1247&quot; data-origin-height=&quot;152&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Bastion 호스트에서 `cat ~/.kube/config` 명령으로 kubeconfig 파일을 확인 해 보겠습니다. kubectl을 요청할 때 cluster의 endpoint를 확인할 수 있고, 하단 users 정보에는 위에서 사용한 `aws eks get-token`명령을 사용하는것을 확인할 수 있습니다. 따라서 kubectl 명령을 보낼때, Token을 발급받아 사용하는 것임을 알 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1712933727924&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: L...K
    server: https://A4.gr7.ap-northeast-2.eks.amazonaws.com
  name: myeks.ap-northeast-2.eksctl.io
contexts:
- context:
    cluster: myeks.ap-northeast-2.eksctl.io
    user: hakjunadmin@myeks.ap-northeast-2.eksctl.io
  name: hakjunadmin@myeks.ap-northeast-2.eksctl.io
current-context: hakjunadmin@myeks.ap-northeast-2.eksctl.io
kind: Config
preferences: {}
users:
- name: hakjunadmin@myeks.ap-northeast-2.eksctl.io
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1beta1
      args:
      - eks
      - get-token
      - --output
      - json
      - --cluster-name
      - myeks
      - --region
      - ap-northeast-2
      command: aws
      env:
      - name: AWS_STS_REGIONAL_ENDPOINTS
        value: regional
      provideClusterInfo: false&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;아래 그림은 API 호출 예제라고 합니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1820&quot; data-origin-height=&quot;886&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bb5PHS/btsGB41dagu/OKw1osPMs3HSZ0dJgbbJ21/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bb5PHS/btsGB41dagu/OKw1osPMs3HSZ0dJgbbJ21/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bb5PHS/btsGB41dagu/OKw1osPMs3HSZ0dJgbbJ21/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbb5PHS%2FbtsGB41dagu%2FOKw1osPMs3HSZ0dJgbbJ21%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;1820&quot; height=&quot;886&quot; data-origin-width=&quot;1820&quot; data-origin-height=&quot;886&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;size16&quot;&gt;위에서 발급한 토큰을 jwt.io 페이지에서 디코드를 진행 해보면, 아래와 같은 DATA가 확인되는것을 확인할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;2404&quot; data-origin-height=&quot;1586&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/36kyD/btsGBXVloMB/LPrvoKGyhkIBj9MZL9F9m1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/36kyD/btsGBXVloMB/LPrvoKGyhkIBj9MZL9F9m1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/36kyD/btsGBXVloMB/LPrvoKGyhkIBj9MZL9F9m1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F36kyD%2FbtsGBXVloMB%2FLPrvoKGyhkIBj9MZL9F9m1%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;2404&quot; height=&quot;1586&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;2404&quot; data-origin-height=&quot;1586&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1712935173006&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&quot;https://sts.ap-northeast-2.amazonaws.com/?
Action=GetCallerIdentity&amp;amp;
Version=2011-06-15&amp;amp;
X-Amz-Algorithm=AWS4-HMAC-SHA256&amp;amp;
X-Amz-Credential=AK%2Fap-northeast-2%2Fsts%2Faws4_request&amp;amp;
X-Amz-Date=20240412T144854Z&amp;amp;
X-Amz-Expires=60&amp;amp;
X-Amz-SignedHeaders=host%3Bx-k8s-aws-id&amp;amp;
X-Amz-Signature=0a4&quot;&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;위 API호출을 받은 EKS API는 Token Review를 Webhook token authenticator에 요청합니다. AWS IAM은 해당 호출을 인증 완료한 뒤 User/Role에 대한 ARN을 반환합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;939&quot; data-origin-height=&quot;58&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YDq7k/btsGCsAzYC1/U4ibpPT3lKJXsurj1tSYw0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YDq7k/btsGCsAzYC1/U4ibpPT3lKJXsurj1tSYw0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YDq7k/btsGCsAzYC1/U4ibpPT3lKJXsurj1tSYw0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYDq7k%2FbtsGCsAzYC1%2FU4ibpPT3lKJXsurj1tSYw0%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;939&quot; height=&quot;58&quot; data-origin-width=&quot;939&quot; data-origin-height=&quot;58&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;size16&quot;&gt;쿠버네티스 RBAC 인가는 IAM User/Role이 확인되면 k8s aws-auth configmaps에서 mapping 정보를 확인하게 됩니다. aws-auth 컨피그맵에 IAM 사용자, 역할ARN, K8S 오브젝트로 권한을 확인한 뒤 인가 허가가 되면 최종적으로 동작을 수행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고로 EKS를 생성한 IAM principal은 aws-auth와 상관없이 kubernetes-admin Username으로 system:masters 그룹에 권한을 가집니다.&lt;/p&gt;
&lt;pre id=&quot;code_1712936812796&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Webhook api 리소스 확인 
kubectl api-resources | grep Webhook
mutatingwebhookconfigurations                  admissionregistration.k8s.io/v1        false        MutatingWebhookConfiguration
validatingwebhookconfigurations                admissionregistration.k8s.io/v1        false        ValidatingWebhookConfiguration

# validatingwebhookconfigurations 리소스 확인
kubectl get validatingwebhookconfigurations
NAME                                        WEBHOOKS   AGE
aws-load-balancer-webhook                   3          70m
eks-aws-auth-configmap-validation-webhook   1          93m
kube-prometheus-stack-admission             1          68m
vpc-resource-validating-webhook             2          93m

kubectl get validatingwebhookconfigurations eks-aws-auth-configmap-validation-webhook -o yaml | kubectl neat | yh
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
  name: eks-aws-auth-configmap-validation-webhook
webhooks:
- admissionReviewVersions:
  - v1
  clientConfig:
    caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURCVENDQWUyZ0F3SUJBZ0lJV3NiR1dNRFN1c3d3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TkRBME1USXhOREE1TVRSYUZ3MHpOREEwTVRBeE5ERTBNVFJhTUJVeApFekFSQmdOVkJBTVRDbXQxWW1WeWJtVjBaWE13Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLCkFvSUJBUUNpak9CRGloaXFNSkVOdlp4VHFWZEJmZERJN090dGtjWXhvbnlOcjlzbjJ3c3loNVR5cFdpbSt0eDYKZTQrQnZ5ZkRpMGk0bXVCVzhHZm9PZFovZFQ0d3ZOckl4bFYxckNEOE9XRUNPNWQyR29QeGs2RWlHUitsVzlqZgpXL1BWWHVMa0UvVHVJYUlRaS8vT09OU3Y2SnNkdW0yQUdwaDRvdjl5cmcwa1dxTy9LdVdmUEJwelBya3BsTjhuCkJ2ZmZMSXpBZFpLOEFJdzlyOE1PZ05vVnNqd0hnalBzU0R6cGpqck9YZWZaZ3p3ZFZHZEFaTDlCNWV4cTFKeU8KWHZkbHA0Lytnb3djcTZtMWw1WDJhQ1l3MTByUlVIRTMwdjM5U21zaEJFajFkTG0vNWVUWDBuL1FheVlzYXN5RApNTVcxbnBFNS9WekFOVm5JdHBrTlZ5OXRzVXhqQWdNQkFBR2pXVEJYTUE0R0ExVWREd0VCL3dRRUF3SUNwREFQCkJnTlZIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJTaWFKU2x6TUV4ZG9QSDhWcWdZYnNoV0dYVkJUQVYKQmdOVkhSRUVEakFNZ2dwcmRXSmxjbTVsZEdWek1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQldKNHlGV1ZobgpUNlFHTmZ3bC9ybHNYMEZtU2FkT1JnWCtjaDR6dUlaZUNoY3Ziek1wbVNNUEhyZXdBWGhTUnZIc2hxeDdIbTRoCmxNeWE1SGRrajllOVdlNCt2a3ZuZkY1Y3FjODBybnNJczVTM2hVMDhRNnhVRFpGMmVPY1J4RURtWlovcEk4bHYKSFl4U1ZsRGtycWdYVHhNbzNnZVVCenlPVm1telVUa1BBWGM2QmVESHhKZUVDZ1kvWFVYVERGK0JPaW9OMDhCVgozVW56QTd3bzdtNHA4WGsrOWtpMm81SkJVZmo1MDVNSkxxdEpFVlgvQVQ0MXhxOHpSQThNQVhmZnZMNENEYWFzCmpmMXc2aHZMNUlwejluTDUwZjMxdDRTTFAvcEVYOWU1TXlwb0lmZWwrMVZwblpQTmpBQnpzM1VaSldXRG9BeUIKMktMZXQvdVdCMk4wCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
    url: https://127.0.0.1:21375/validate
  failurePolicy: Ignore
  matchConditions:
  - expression: (request.name == &quot;aws-auth&quot;)
    name: aws-auth-configmap
  matchPolicy: Equivalent
  name: eks-aws-auth-configmap-validation-webhook.amazonaws.com
  namespaceSelector:
    matchLabels:
      kubernetes.io/metadata.name: kube-system
  rules:
  - apiGroups:
    - &quot;&quot;
    apiVersions:
    - v1
    operations:
    - UPDATE
    resources:
    - configmaps
    scope: '*'
  sideEffects: None
  timeoutSeconds: 5


# aws-auth 컨피그맵 확인
kubectl get cm -n kube-system aws-auth -o yaml | kubectl neat | yh
apiVersion: v1
data:
  mapRoles: |
    - groups:
      - system:bootstrappers
      - system:nodes
      rolearn: arn:aws:iam::6546:role/eksctl-myeks-nodegroup-ng1-NodeInstanceRole-nexe8GYoQa63
      username: system:node:{{EC2PrivateDNSName}}
kind: ConfigMap
metadata:
  name: aws-auth
  namespace: kube-system
#---&amp;lt;아래 생략(추정), ARN은 EKS를 설치한 IAM User , 여기 있었을경우 만약 실수로 삭제 시 복구가 가능했을까?---
  mapUsers: |
    - groups:
      - system:masters
      userarn: arn:aws:iam::111122223333:user/admin
      username: kubernetes-admin

# EKS 설치한 IAM User 정보 &amp;gt;&amp;gt; system:authenticated는 어떤 방식으로 추가가 되었는지 궁금???
{Username: &quot;arn:aws:iam::6546:user/hakjunadmin&quot;,
 UID:      &quot;aws-iam-authenticator:6546:AI&quot;,
 Groups:   [&quot;system:authenticated&quot;],
 Extra:    {accessKeyId:  [&quot;AKIAZQ3DNPORYDDXLK27&quot;],
            arn:          [&quot;arn:aws:iam::6546:user/hakjunadmin&quot;],
            canonicalArn: [&quot;arn:aws:iam::6546:user/hakjunadmin&quot;],
            principalId:  [&quot;AIDAZQ&quot;],
            sessionName:  [&quot;&quot;]}}
...

# system:masters , system:authenticated 그룹의 정보 확인
kubectl rbac-tool lookup system:masters
kubectl rbac-tool lookup system:authenticated
kubectl rolesum -k Group system:masters
kubectl rolesum -k Group system:authenticated

# system:masters 그룹이 사용 가능한 클러스터 롤 확인 : cluster-admin
kubectl describe clusterrolebindings.rbac.authorization.k8s.io cluster-admin
Name:         cluster-admin
Labels:       kubernetes.io/bootstrapping=rbac-defaults
Annotations:  rbac.authorization.kubernetes.io/autoupdate: true
Role:
  Kind:  ClusterRole
  Name:  cluster-admin
Subjects:
  Kind   Name            Namespace
  ----   ----            ---------
  Group  system:masters

# cluster-admin 의 PolicyRule 확인 : 모든 리소스  사용 가능!
kubectl describe clusterrole cluster-admin
Name:         cluster-admin
Labels:       kubernetes.io/bootstrapping=rbac-defaults
Annotations:  rbac.authorization.kubernetes.io/autoupdate: true
PolicyRule:
  Resources  Non-Resource URLs  Resource Names  Verbs
  ---------  -----------------  --------------  -----
  *.*        []                 []              [*]
             [*]                []              [*]

# system:authenticated 그룹이 사용 가능한 클러스터 롤 확인
kubectl describe ClusterRole system:discovery
kubectl describe ClusterRole system:public-info-viewer
kubectl describe ClusterRole system:basic-user
kubectl describe ClusterRole eks:podsecuritypolicy:privileged&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 데브옵스 신입 사원을 위한 myeks-bastion-2에 설정을 진행해보겠습니다. aws iam user를 생성하고, EKS 클러스터에 접근할 수 있도록 구성해 봅니다. 현재 Bastion에서 IAM 유저를 생성하고, Access Key 발급 및 권한 부여를 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1712937440674&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;(hakjunadmin@myeks:N/A) [root@myeks-bastion ~]# aws iam create-user --user-name testuser
{
    &quot;User&quot;: {
        &quot;Path&quot;: &quot;/&quot;,
        &quot;UserName&quot;: &quot;testuser&quot;,
        &quot;UserId&quot;: &quot;###&quot;,
        &quot;Arn&quot;: &quot;arn:aws:iam::###:user/testuser&quot;,
        &quot;CreateDate&quot;: &quot;2024-04-12T15:53:36+00:00&quot;
    }
}
(hakjunadmin@myeks:N/A) [root@myeks-bastion ~]# aws iam create-access-key --user-name testuser
{
    &quot;AccessKey&quot;: {
        &quot;UserName&quot;: &quot;testuser&quot;,
        &quot;AccessKeyId&quot;: &quot;###&quot;,
        &quot;Status&quot;: &quot;Active&quot;,
        &quot;SecretAccessKey&quot;: &quot;###+###&quot;,
        &quot;CreateDate&quot;: &quot;2024-04-12T15:53:42+00:00&quot;
    }
}
(hakjunadmin@myeks:N/A) [root@myeks-bastion ~]# aws iam attach-user-policy --policy-arn arn:aws:iam::aws:policy/AdministratorAccess --user-name testuser&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;Bastion2 호스트에 접속 후 testuser의 AccessKey로 aws configure를 진행합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;338&quot; data-origin-height=&quot;134&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8TOVA/btsGBv54Fdw/qLip9MBFXCNhwNLiqKyuyK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8TOVA/btsGBv54Fdw/qLip9MBFXCNhwNLiqKyuyK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8TOVA/btsGBv54Fdw/qLip9MBFXCNhwNLiqKyuyK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8TOVA%2FbtsGBv54Fdw%2FqLip9MBFXCNhwNLiqKyuyK%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;338&quot; height=&quot;134&quot; data-origin-width=&quot;338&quot; data-origin-height=&quot;134&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;size16&quot;&gt;testuser가 kubectl 명령을 사용할 수 있게 설정합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1712937715625&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;eksctl create iamidentitymapping --cluster $CLUSTER_NAME --username testuser --group system:masters --arn arn:aws:iam::$ACCOUNT_ID:user/testuser&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1253&quot; data-origin-height=&quot;76&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1u0xH/btsGBQB87Fx/y9ayc7BR9mgBu3OPhYs2h0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1u0xH/btsGBQB87Fx/y9ayc7BR9mgBu3OPhYs2h0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1u0xH/btsGBQB87Fx/y9ayc7BR9mgBu3OPhYs2h0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1u0xH%2FbtsGBQB87Fx%2Fy9ayc7BR9mgBu3OPhYs2h0%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;1253&quot; height=&quot;76&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1253&quot; data-origin-height=&quot;76&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;size16&quot;&gt;aws-auth를 확인해보면 아래와 같이 추가된 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1712937753278&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  mapUsers: |
    - groups:
      - system:masters
      userarn: arn:aws:iam::##:user/testuser
      username: testuser&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;Bastion2에서 아래 명령으로 Kubeconfig를 생성합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1712937797107&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;aws eks update-kubeconfig --name $CLUSTER_NAME --user-alias testuser&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;Bastion2 에서도 kubectl명령을 사용할 수 있게 되었습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;766&quot; data-origin-height=&quot;92&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdOafu/btsGCm1CJrG/Cdn6YK3LceVqVk5XVKzZsK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdOafu/btsGCm1CJrG/Cdn6YK3LceVqVk5XVKzZsK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdOafu/btsGCm1CJrG/Cdn6YK3LceVqVk5XVKzZsK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbdOafu%2FbtsGCm1CJrG%2FCdn6YK3LceVqVk5XVKzZsK%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;766&quot; height=&quot;92&quot; data-origin-width=&quot;766&quot; data-origin-height=&quot;92&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;size16&quot;&gt;configmap의 중요성을 확인해보기 위해 aws-auth에 매핑된 그룹을 바꿔보겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1712938006567&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl edit cm -n kube-system aws-auth

system:authenticated으로 수정&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;수정 뒤 아래와 같이 권한이 없어 조회가 불가능함을 확인합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1090&quot; data-origin-height=&quot;37&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xZ17S/btsGzOlkATS/6TZX85TrIye3CF6SAmA8G1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xZ17S/btsGzOlkATS/6TZX85TrIye3CF6SAmA8G1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xZ17S/btsGzOlkATS/6TZX85TrIye3CF6SAmA8G1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxZ17S%2FbtsGzOlkATS%2F6TZX85TrIye3CF6SAmA8G1%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;1090&quot; height=&quot;37&quot; data-origin-width=&quot;1090&quot; data-origin-height=&quot;37&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;size16&quot;&gt;아래 명령으로 IAM 맵핑을 삭제할 수도 있습니다. 아래 명령을 수행하면 aws-auth 컨피그맵에 testuser의 내용이 삭제됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1712938080531&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;eksctl delete iamidentitymapping --cluster $CLUSTER_NAME --arn  arn:aws:iam::$ACCOUNT_ID:user/testuser&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;EC2 Instance Profile | (IAM Role)에 매핑된 K8S RBAC 확인해보기, 최근 추가된 기능&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;718&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LDo1b/btsGBgHTNZH/i7CjMMGaujQacy0NCjbIIK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LDo1b/btsGBgHTNZH/i7CjMMGaujQacy0NCjbIIK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LDo1b/btsGBgHTNZH/i7CjMMGaujQacy0NCjbIIK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLDo1b%2FbtsGBgHTNZH%2Fi7CjMMGaujQacy0NCjbIIK%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;2000&quot; height=&quot;718&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;718&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;873&quot; data-origin-height=&quot;550&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IrQ8i/btsGB48j7fU/ZpGnkKn7UjVlpLKvgalOZ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IrQ8i/btsGB48j7fU/ZpGnkKn7UjVlpLKvgalOZ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IrQ8i/btsGB48j7fU/ZpGnkKn7UjVlpLKvgalOZ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIrQ8i%2FbtsGB48j7fU%2FZpGnkKn7UjVlpLKvgalOZ1%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;873&quot; height=&quot;550&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;873&quot; data-origin-height=&quot;550&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;size16&quot;&gt;노드에 매핑관 Role을 확인해봅니다. 워커노드 각각 별도의 Role을 사용하고 있음을 확인합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1712938602722&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 노드에 STS ARN 정보 확인 : Role 뒤에 인스턴스 ID!
for node in $N1 $N2 $N3; do ssh ec2-user@$node aws sts get-caller-identity --query Arn; done
&quot;arn:aws:sts::65:assumed-role/eksctl-myeks-nodegroup-ng1-NodeInstanceRole-nexe8GYoQa63/i-051140852d9fddf15&quot;
&quot;arn:aws:sts::65:assumed-role/eksctl-myeks-nodegroup-ng1-NodeInstanceRole-nexe8GYoQa63/i-038360583545cfdae&quot;
&quot;arn:aws:sts::65:assumed-role/eksctl-myeks-nodegroup-ng1-NodeInstanceRole-nexe8GYoQa63/i-006b15c6dca84673f&quot;&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;aws-auth 컨피그맵을 확인해보면, mapRoles: 필드에서 rolearn:으로 인스턴스에 할당된 Role에 대해 사용자 인증을 해주고 있는것을 확인할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1712938802584&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl describe configmap -n kube-system aws-auth&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;796&quot; data-origin-height=&quot;142&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9tHaw/btsGBe4H4sK/Vz4IQZTzTkux7sinp0vffK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9tHaw/btsGBe4H4sK/Vz4IQZTzTkux7sinp0vffK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9tHaw/btsGBe4H4sK/Vz4IQZTzTkux7sinp0vffK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9tHaw%2FbtsGBe4H4sK%2FVz4IQZTzTkux7sinp0vffK%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;796&quot; height=&quot;142&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;796&quot; data-origin-height=&quot;142&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;size16&quot;&gt;그럼 워커노드에 할당된 역할 정보를 불러와 aws cli를 사용하는 파드를 배포한 뒤 aws cli를 작동해 보겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1712938955641&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# awscli 파드 생성
cat &amp;lt;&amp;lt;EOF | kubectl create -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: awscli-pod
spec:
  replicas: 2
  selector:
    matchLabels:
      app: awscli-pod
  template:
    metadata:
      labels:
        app: awscli-pod
    spec:
      containers:
      - name: awscli-pod
        image: amazon/aws-cli
        command: [&quot;tail&quot;]
        args: [&quot;-f&quot;, &quot;/dev/null&quot;]
      terminationGracePeriodSeconds: 0
EOF

# 파드 생성 확인
kubectl get pod -owide

# 파드 이름 변수 지정
APODNAME1=$(kubectl get pod -l app=awscli-pod -o jsonpath={.items[0].metadata.name})
APODNAME2=$(kubectl get pod -l app=awscli-pod -o jsonpath={.items[1].metadata.name})
echo $APODNAME1, $APODNAME2

# awscli 파드에서 EC2 InstanceProfile(IAM Role)의 ARN 정보 확인
kubectl exec -it $APODNAME1 -- aws sts get-caller-identity --query Arn
kubectl exec -it $APODNAME2 -- aws sts get-caller-identity --query Arn

# awscli 파드에서 EC2 InstanceProfile(IAM Role)을 사용하여 AWS 서비스 정보 확인 &amp;gt;&amp;gt; 별도 IAM 자격 증명이 없는데 어떻게 가능한 것일까요?
# &amp;gt; 최소권한부여 필요!!! &amp;gt;&amp;gt;&amp;gt; 보안이 허술한 아무 컨테이너나 탈취 시, IMDS로 해당 노드의 IAM Role 사용 가능!
kubectl exec -it $APODNAME1 -- aws ec2 describe-instances --region ap-northeast-2 --output table --no-cli-pager
kubectl exec -it $APODNAME2 -- aws ec2 describe-vpcs --region ap-northeast-2 --output table --no-cli-pager
 
# EC2 메타데이터 확인 : IDMSv1은 Disable, IDMSv2 활성화 상태, IAM Role - 링크
kubectl exec -it $APODNAME1 -- bash
-----------------------------------
아래부터는 파드에 bash shell 에서 실행
curl -s http://169.254.169.254/ -v
...

# Token 요청 
curl -s -X PUT &quot;http://169.254.169.254/latest/api/token&quot; -H &quot;X-aws-ec2-metadata-token-ttl-seconds: 21600&quot; ; echo
curl -s -X PUT &quot;http://169.254.169.254/latest/api/token&quot; -H &quot;X-aws-ec2-metadata-token-ttl-seconds: 21600&quot; ; echo

# Token을 이용한 IMDSv2 사용
TOKEN=$(curl -s -X PUT &quot;http://169.254.169.254/latest/api/token&quot; -H &quot;X-aws-ec2-metadata-token-ttl-seconds: 21600&quot;)
echo $TOKEN
curl -s -H &quot;X-aws-ec2-metadata-token: $TOKEN&quot; &amp;ndash;v http://169.254.169.254/ ; echo
curl -s -H &quot;X-aws-ec2-metadata-token: $TOKEN&quot; &amp;ndash;v http://169.254.169.254/latest/ ; echo
curl -s -H &quot;X-aws-ec2-metadata-token: $TOKEN&quot; &amp;ndash;v http://169.254.169.254/latest/meta-data/iam/security-credentials/ ; echo

# 위에서 출력된 IAM Role을 아래 입력 후 확인
curl -s -H &quot;X-aws-ec2-metadata-token: $TOKEN&quot; &amp;ndash;v http://169.254.169.254/latest/meta-data/iam/security-credentials/eksctl-myeks-nodegroup-ng1-NodeInstanceRole-nexe8GYoQa63
{
  &quot;Code&quot; : &quot;Success&quot;,
  &quot;LastUpdated&quot; : &quot;2024-04-12T16:13:46Z&quot;,
  &quot;Type&quot; : &quot;&quot;,
  &quot;AccessKeyId&quot; : &quot;&quot;,
  &quot;SecretAccessKey&quot; : &quot;&quot;,
  &quot;Token&quot; : &quot;&quot;,
  &quot;Expiration&quot; : &quot;2024-04-12T22:25:02Z&quot;
}
## 출력된 정보는 AWS API를 사용할 수 있는 어느곳에서든지 Expiration 되기전까지 사용 가능

# 파드에서 나오기
exit
---&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존에 권한 관리를 쉽게 적용한 방법&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;972&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IdnVn/btsGCa1xAOb/bn9NzJLwZK5wB7Hrkpg4Uk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IdnVn/btsGCa1xAOb/bn9NzJLwZK5wB7Hrkpg4Uk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IdnVn/btsGCa1xAOb/bn9NzJLwZK5wB7Hrkpg4Uk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIdnVn%2FbtsGCa1xAOb%2Fbn9NzJLwZK5wB7Hrkpg4Uk%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;2000&quot; height=&quot;972&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;972&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;size16&quot;&gt;AWS EKS 액세스 구성모드가 EKS API 및 ConfigMap 이면 정책 중복 시 EKS API가 우선시 된다. 결론적으로 Configmap보다 EKS API를 사용하게 되며, 최근들어 API 사용을 권장한다고 합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;882&quot; data-origin-height=&quot;535&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dzWTjY/btsGCbsBg6D/mpXn0t8I7QQVdd2EiKk0wK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dzWTjY/btsGCbsBg6D/mpXn0t8I7QQVdd2EiKk0wK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dzWTjY/btsGCbsBg6D/mpXn0t8I7QQVdd2EiKk0wK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdzWTjY%2FbtsGCbsBg6D%2FmpXn0t8I7QQVdd2EiKk0wK%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;882&quot; height=&quot;535&quot; data-origin-width=&quot;882&quot; data-origin-height=&quot;535&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;size16&quot;&gt;EKS API 호출 방법을 확인해보겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1713024080294&quot; class=&quot;pgsql&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;aws eks update-cluster-config --name $CLUSTER_NAME --access-config authenticationMode=API​&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;액세스가 EKS API 인증모드로 변경되었습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;874&quot; data-origin-height=&quot;506&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/trAF0/btsGCqXAIu8/fXawKcanHSVVryqPkG2N1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/trAF0/btsGCqXAIu8/fXawKcanHSVVryqPkG2N1k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/trAF0/btsGCqXAIu8/fXawKcanHSVVryqPkG2N1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtrAF0%2FbtsGCqXAIu8%2FfXawKcanHSVVryqPkG2N1k%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;874&quot; height=&quot;506&quot; data-origin-width=&quot;874&quot; data-origin-height=&quot;506&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;size16&quot;&gt;기존에 EKS를 생성한 User가 EKS클러스터에 접근 가능한 이유는 해당 User에 대한 액세스 정책으로 `AmazonEKSClusterAdminPolicy`를 보유하고 있기 때문입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1111&quot; data-origin-height=&quot;324&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sc1tL/btsGBejzyyv/NOosrV0VOKNeq6UIXS0sCk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sc1tL/btsGBejzyyv/NOosrV0VOKNeq6UIXS0sCk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sc1tL/btsGBejzyyv/NOosrV0VOKNeq6UIXS0sCk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fsc1tL%2FbtsGBejzyyv%2FNOosrV0VOKNeq6UIXS0sCk%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;1111&quot; height=&quot;324&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1111&quot; data-origin-height=&quot;324&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;액세스 정책 별 접근 가능한 권한(크게 4 가지)은 &lt;a href=&quot;https://docs.aws.amazon.com/eks/latest/userguide/access-policies.html#access-policy-permissions&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;링크&lt;/a&gt;에서 확인 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1713024437177&quot; class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# 맵핑 클러스터롤 정보 확인
kubectl get clusterroles -l 'kubernetes.io/bootstrapping=rbac-defaults' | grep -v 'system:'​&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;739&quot; data-origin-height=&quot;111&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/otBA9/btsGCoeoAMz/0ijt3MkKpG1GmkEevDwg10/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/otBA9/btsGCoeoAMz/0ijt3MkKpG1GmkEevDwg10/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/otBA9/btsGCoeoAMz/0ijt3MkKpG1GmkEevDwg10/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FotBA9%2FbtsGCoeoAMz%2F0ijt3MkKpG1GmkEevDwg10%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;739&quot; height=&quot;111&quot; data-origin-width=&quot;739&quot; data-origin-height=&quot;111&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;size16&quot;&gt;그럼 testuser를 API방식으로 사용하기위한 설정을 적용합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713024911435&quot; class=&quot;bash&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# testuser 의 access entry 생성
aws eks create-access-entry --cluster-name $CLUSTER_NAME --principal-arn arn:aws:iam::$ACCOUNT_ID:user/testuser
{
    &quot;accessEntry&quot;: {
        &quot;clusterName&quot;: &quot;myeks&quot;,
        &quot;principalArn&quot;: &quot;arn:aws:iam::6:user/testuser&quot;,
        &quot;kubernetesGroups&quot;: [],
        &quot;accessEntryArn&quot;: &quot;arn:aws:eks:ap-northeast-2:65:access-entry/myeks/user/65/testuser/54c76c1d-e41a-812d-3347-fad17fdffab8&quot;,
        &quot;createdAt&quot;: &quot;2024-04-14T01:13:00.394000+09:00&quot;,
        &quot;modifiedAt&quot;: &quot;2024-04-14T01:13:00.394000+09:00&quot;,
        &quot;tags&quot;: {},
        &quot;username&quot;: &quot;arn:aws:iam::654654143395:user/testuser&quot;,
        &quot;type&quot;: &quot;STANDARD&quot;
    }
}

aws eks list-access-entries --cluster-name $CLUSTER_NAME | jq -r .accessEntries[]
arn:aws:iam::654654143395:role/eksctl-myeks-nodegroup-ng1-NodeInstanceRole-c1AQaMSrbK4x
arn:aws:iam::654654143395:user/hakjunadmin
arn:aws:iam::654654143395:user/testuser


# testuser에 AmazonEKSClusterAdminPolicy 연동
aws eks associate-access-policy --cluster-name $CLUSTER_NAME --principal-arn arn:aws:iam::$ACCOUNT_ID:user/testuser \
  --policy-arn arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy --access-scope type=cluster

{
    &quot;clusterName&quot;: &quot;myeks&quot;,
    &quot;principalArn&quot;: &quot;arn:aws:iam::654:user/testuser&quot;,
    &quot;associatedAccessPolicy&quot;: {
        &quot;policyArn&quot;: &quot;arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy&quot;,
        &quot;accessScope&quot;: {
            &quot;type&quot;: &quot;cluster&quot;,
            &quot;namespaces&quot;: []
        },
        &quot;associatedAt&quot;: &quot;2024-04-14T01:13:14.146000+09:00&quot;,
        &quot;modifiedAt&quot;: &quot;2024-04-14T01:13:14.146000+09:00&quot;
    }
}

#
aws eks list-associated-access-policies --cluster-name $CLUSTER_NAME --principal-arn arn:aws:iam::$ACCOUNT_ID:user/testuser | jq
aws eks describe-access-entry --cluster-name $CLUSTER_NAME --principal-arn arn:aws:iam::$ACCOUNT_ID:user/testuser | jq​&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1110&quot; data-origin-height=&quot;359&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDaI7H/btsGBhHbJt5/h30ZE1ofKXv3XKqr73f5Y0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDaI7H/btsGBhHbJt5/h30ZE1ofKXv3XKqr73f5Y0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDaI7H/btsGBhHbJt5/h30ZE1ofKXv3XKqr73f5Y0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDaI7H%2FbtsGBhHbJt5%2Fh30ZE1ofKXv3XKqr73f5Y0%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;1110&quot; height=&quot;359&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1110&quot; data-origin-height=&quot;359&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;size16&quot;&gt;Bastion2에서 testuser로 kubectl이 가능한것을 확인할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1252&quot; data-origin-height=&quot;146&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdQEOe/btsGBQvIrDn/ix6PZNQ6jHvWuK5S6ybYe0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdQEOe/btsGBQvIrDn/ix6PZNQ6jHvWuK5S6ybYe0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdQEOe/btsGBQvIrDn/ix6PZNQ6jHvWuK5S6ybYe0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbdQEOe%2FbtsGBQvIrDn%2Fix6PZNQ6jHvWuK5S6ybYe0%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;1252&quot; height=&quot;146&quot; data-origin-width=&quot;1252&quot; data-origin-height=&quot;146&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;size16&quot;&gt;EKS API를 사용해 IAM User를 액세스 정책과 연동해 EKS 연결방법을 확인 해 보았습니다. 아래 명령으로 access entry를 제거합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713025194024&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;aws eks delete-access-entry --cluster-name $CLUSTER_NAME --principal-arn arn:aws:iam::$ACCOUNT_ID:user/testuser&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;이번에는 미리 만들어진 정책을 사용하지 않고, 사용자 지정 Role을 매핑하여 적용하는 것을 실습해보겠습니다. viewr, admin role 2개를 생성합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713025297996&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#
cat &amp;lt;&amp;lt;EoF&amp;gt; ~/pod-viewer-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: pod-viewer-role
rules:
- apiGroups: [&quot;&quot;]
  resources: [&quot;pods&quot;]
  verbs: [&quot;list&quot;, &quot;get&quot;, &quot;watch&quot;]
EoF

cat &amp;lt;&amp;lt;EoF&amp;gt; ~/pod-admin-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: pod-admin-role
rules:
- apiGroups: [&quot;&quot;]
  resources: [&quot;pods&quot;]
  verbs: [&quot;*&quot;]
EoF

kubectl apply -f ~/pod-viewer-role.yaml
kubectl apply -f ~/pod-admin-role.yaml

#
kubectl create clusterrolebinding viewer-role-binding --clusterrole=pod-viewer-role --group=pod-viewer
kubectl create clusterrolebinding admin-role-binding --clusterrole=pod-admin-role --group=pod-admin&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;test user를 viewer와 연결합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713025351219&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;aws eks create-access-entry --cluster-name $CLUSTER_NAME --principal-arn arn:aws:iam::$ACCOUNT_ID:user/testuser --kubernetes-group pod-viewer&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1086&quot; data-origin-height=&quot;106&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VzuDX/btsGBew59pQ/A4O6LfVhhAfiDKcziT6g5k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VzuDX/btsGBew59pQ/A4O6LfVhhAfiDKcziT6g5k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VzuDX/btsGBew59pQ/A4O6LfVhhAfiDKcziT6g5k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVzuDX%2FbtsGBew59pQ%2FA4O6LfVhhAfiDKcziT6g5k%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;1086&quot; height=&quot;106&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1086&quot; data-origin-height=&quot;106&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;size16&quot;&gt;test user는 kubectl get pod 는 가능하지만 delete pod는 불가능 합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1251&quot; data-origin-height=&quot;129&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eELL9G/btsGDHRQ43i/VjOPGkU1vAxAUbtiG95zp1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eELL9G/btsGDHRQ43i/VjOPGkU1vAxAUbtiG95zp1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eELL9G/btsGDHRQ43i/VjOPGkU1vAxAUbtiG95zp1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeELL9G%2FbtsGDHRQ43i%2FVjOPGkU1vAxAUbtiG95zp1%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;1251&quot; height=&quot;129&quot; data-origin-width=&quot;1251&quot; data-origin-height=&quot;129&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;size16&quot;&gt;testuser의 권한을 admin으로 수정합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713025522062&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;aws eks update-access-entry --cluster-name $CLUSTER_NAME --principal-arn arn:aws:iam::$ACCOUNT_ID:user/testuser --kubernetes-group pod-admin | jq -r .accessEntry&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;pod delete가 가능해 집니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;711&quot; data-origin-height=&quot;40&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ImYq7/btsGB1qefGh/9UaNO1Hyze5pyoIFgcZtdK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ImYq7/btsGB1qefGh/9UaNO1Hyze5pyoIFgcZtdK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ImYq7/btsGB1qefGh/9UaNO1Hyze5pyoIFgcZtdK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FImYq7%2FbtsGB1qefGh%2F9UaNO1Hyze5pyoIFgcZtdK%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;711&quot; height=&quot;40&quot; data-origin-width=&quot;711&quot; data-origin-height=&quot;40&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;h2 data-ke-size=&quot;size26&quot;&gt;EKS IRSA &amp;amp; Pod Identitty&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EKS의 Pod가 AWS S3등 AWS 리소스를 사용할 때 AWS STS/IAM과 IAM OIDC를 사용해 인증/인가를 처리하는 방식입니다. 기존 인스턴스 프로필, 액세스 키 사용시 키 노출로 인한 보안 허점을 보완할 수 있는 방법입니다.&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;우선 Pod의 Token 처리 방법을 확인해 보겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1713025988598&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Create the Secrets:
## Create files containing the username and password:
echo -n &quot;admin&quot; &amp;gt; ./username.txt
echo -n &quot;1f2d1e2e67df&quot; &amp;gt; ./password.txt

## Package these files into secrets:
kubectl create secret generic user --from-file=./username.txt
kubectl create secret generic pass --from-file=./password.txt

# 파드 생성
kubectl apply -f https://k8s.io/examples/pods/storage/projected.yaml

# 파드 확인
kubectl get pod test-projected-volume -o yaml | kubectl neat | yh&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;357&quot; data-origin-height=&quot;443&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/y61O0/btsGDAd9XIW/lBuwDVe2sqeuzvKa8vnySk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/y61O0/btsGDAd9XIW/lBuwDVe2sqeuzvKa8vnySk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/y61O0/btsGDAd9XIW/lBuwDVe2sqeuzvKa8vnySk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fy61O0%2FbtsGDAd9XIW%2FlBuwDVe2sqeuzvKa8vnySk%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;357&quot; height=&quot;443&quot; data-origin-width=&quot;357&quot; data-origin-height=&quot;443&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&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1046&quot; data-origin-height=&quot;127&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cuF1Lt/btsGCbF9uN5/5QgtzFoNIxFvTiSrKRurO1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cuF1Lt/btsGCbF9uN5/5QgtzFoNIxFvTiSrKRurO1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cuF1Lt/btsGCbF9uN5/5QgtzFoNIxFvTiSrKRurO1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcuF1Lt%2FbtsGCbF9uN5%2F5QgtzFoNIxFvTiSrKRurO1%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;1046&quot; height=&quot;127&quot; data-origin-width=&quot;1046&quot; data-origin-height=&quot;127&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;size16&quot;&gt;&amp;nbsp;&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;IRSA는 파드에 할당하여 사용하는 서비스 어카운트입니다. 파드에 Role이 매핑되어 있어 최소권한부여를 만족할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;3425&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLdhLj/btsGBy9GhXR/twsrljCKSHzf4XJpMk68T1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLdhLj/btsGBy9GhXR/twsrljCKSHzf4XJpMk68T1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLdhLj/btsGBy9GhXR/twsrljCKSHzf4XJpMk68T1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLdhLj%2FbtsGBy9GhXR%2FtwsrljCKSHzf4XJpMk68T1%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;2000&quot; height=&quot;3425&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;3425&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;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상세 과정을 도식화 하면 아래와 같습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1127&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wPeXF/btsGBOxVYnh/ZE7Y2maJR3l0WHicVm5mY1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wPeXF/btsGBOxVYnh/ZE7Y2maJR3l0WHicVm5mY1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wPeXF/btsGBOxVYnh/ZE7Y2maJR3l0WHicVm5mY1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwPeXF%2FbtsGBOxVYnh%2FZE7Y2maJR3l0WHicVm5mY1%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;2000&quot; height=&quot;1127&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1127&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;size16&quot;&gt;실습으로 내용을 확인해 보겠습니다. 먼저 파드를 생성하고 서비스 어카운트는 별도 지정해보지 않도록 구성해보겠습니다. 아래 파드는 s3 ls 명령을 입력하는 파드입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713026581914&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cat &amp;lt;&amp;lt;EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: eks-iam-test1
spec:
  containers:
    - name: my-aws-cli
      image: amazon/aws-cli:latest
      args: ['s3', 'ls']
  restartPolicy: Never
  automountServiceAccountToken: false
  terminationGracePeriodSeconds: 0
EOF&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;`automountServiceAccountToken`이 `false`로 설정되어 있어 Pod에 서비스어카운트를 별도 할당하지 않게 됩니다. 권한이 없어, Cloud Trail에서 Access Denied가 발생한 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;570&quot; data-origin-height=&quot;331&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cw3xx8/btsGBzgtg7C/kyYLEbBZPMNDC1foGMcu61/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cw3xx8/btsGBzgtg7C/kyYLEbBZPMNDC1foGMcu61/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cw3xx8/btsGBzgtg7C/kyYLEbBZPMNDC1foGMcu61/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcw3xx8%2FbtsGBzgtg7C%2FkyYLEbBZPMNDC1foGMcu61%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;570&quot; height=&quot;331&quot; data-origin-width=&quot;570&quot; data-origin-height=&quot;331&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;size16&quot;&gt;두 번째 파드를 생성해보겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713027064083&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 파드2 생성
cat &amp;lt;&amp;lt;EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: eks-iam-test2
spec:
  containers:
    - name: my-aws-cli
      image: amazon/aws-cli:latest
      command: ['sleep', '36000']
  restartPolicy: Never
  terminationGracePeriodSeconds: 0
EOF

# 확인
kubectl get pod
kubectl describe pod
kubectl get pod eks-iam-test2 -o yaml | kubectl neat | yh
kubectl exec -it eks-iam-test2 -- ls /var/run/secrets/kubernetes.io/serviceaccount
kubectl exec -it eks-iam-test2 -- cat /var/run/secrets/kubernetes.io/serviceaccount/token ;echo

# aws 서비스 사용 시도
kubectl exec -it eks-iam-test2 -- aws s3 ls

# 서비스 어카운트 토큰 확인
SA_TOKEN=$(kubectl exec -it eks-iam-test2 -- cat /var/run/secrets/kubernetes.io/serviceaccount/token)
echo $SA_TOKEN&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;&lt;a href=&quot;https://jwt.io/에서&quot;&gt;https://jwt.io/에서&lt;/a&gt; 토큰 정보를 확인합니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;edited_blob&quot; data-origin-width=&quot;2432&quot; data-origin-height=&quot;1370&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpPapv/btsGAPElIfX/5TCcqcLylQ5k8QyYj20Qw1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpPapv/btsGAPElIfX/5TCcqcLylQ5k8QyYj20Qw1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpPapv/btsGAPElIfX/5TCcqcLylQ5k8QyYj20Qw1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbpPapv%2FbtsGAPElIfX%2F5TCcqcLylQ5k8QyYj20Qw1%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;2432&quot; height=&quot;1370&quot; data-filename=&quot;edited_blob&quot; data-origin-width=&quot;2432&quot; data-origin-height=&quot;1370&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;size16&quot;&gt;기본 서비스 어카운트는 생성되어 파트에 Project로 Service Account의 토큰이 마운트 되었지만, 다시 Cloud Trail 로그를 확인해보면 아직 Access Denied입니다.&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;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;1865&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cQZy7I/btsGAyiApL2/7Hkh4s7mYF4OxaASBiOwB0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cQZy7I/btsGAyiApL2/7Hkh4s7mYF4OxaASBiOwB0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cQZy7I/btsGAyiApL2/7Hkh4s7mYF4OxaASBiOwB0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcQZy7I%2FbtsGAyiApL2%2F7Hkh4s7mYF4OxaASBiOwB0%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;1440&quot; height=&quot;1865&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;1865&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 명령으로 IAM과 K8S 서비스어카운트를 매핑합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713029157761&quot; class=&quot;dsconfig&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# Create an iamserviceaccount - AWS IAM role bound to a Kubernetes service account
eksctl create iamserviceaccount \
  --name my-sa \
  --namespace default \
  --cluster $CLUSTER_NAME \
  --approve \
  --attach-policy-arn $(aws iam list-policies --query 'Policies[?PolicyName==`AmazonS3ReadOnlyAccess`].Arn' --output text)​&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1150&quot; data-origin-height=&quot;78&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwaOGF/btsGABzCg8h/iAPD6Wa6CG9IdN3gjKke8k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwaOGF/btsGABzCg8h/iAPD6Wa6CG9IdN3gjKke8k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwaOGF/btsGABzCg8h/iAPD6Wa6CG9IdN3gjKke8k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwaOGF%2FbtsGABzCg8h%2FiAPD6Wa6CG9IdN3gjKke8k%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;1150&quot; height=&quot;78&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1150&quot; data-origin-height=&quot;78&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1194&quot; data-origin-height=&quot;171&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VgBOQ/btsGCdjHosY/iNQBRc4jkLx2HCAwjTc6iK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VgBOQ/btsGCdjHosY/iNQBRc4jkLx2HCAwjTc6iK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VgBOQ/btsGCdjHosY/iNQBRc4jkLx2HCAwjTc6iK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVgBOQ%2FbtsGCdjHosY%2FiNQBRc4jkLx2HCAwjTc6iK%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;1194&quot; height=&quot;171&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1194&quot; data-origin-height=&quot;171&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;size16&quot;&gt;my-sa를 사용하는 Pod로 배포합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713029350148&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 파드3번 생성
cat &amp;lt;&amp;lt;EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: eks-iam-test3
spec:
  serviceAccountName: my-sa
  containers:
    - name: my-aws-cli
      image: amazon/aws-cli:latest
      command: ['sleep', '36000']
  restartPolicy: Never
  terminationGracePeriodSeconds: 0
EOF&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;aws s3 ls조회가 가능해 졌습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;765&quot; data-origin-height=&quot;44&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/deTFoz/btsGCZZx801/QFAHoKBSOVHLR5xYDekzgk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/deTFoz/btsGCZZx801/QFAHoKBSOVHLR5xYDekzgk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/deTFoz/btsGCZZx801/QFAHoKBSOVHLR5xYDekzgk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdeTFoz%2FbtsGCZZx801%2FQFAHoKBSOVHLR5xYDekzgk%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;765&quot; height=&quot;44&quot; data-origin-width=&quot;765&quot; data-origin-height=&quot;44&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;size16&quot;&gt;Pod 내용을 보면 projected에 seviceAccount 부분이 변경된걸 확인할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713029429762&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl get pod eks-iam-test3 -o yaml | kubectl neat | yh&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;304&quot; data-origin-height=&quot;145&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c033OC/btsGAOk8kkC/GzLymDK9mSlQ6bnQ549PH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c033OC/btsGAOk8kkC/GzLymDK9mSlQ6bnQ549PH1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c033OC/btsGAOk8kkC/GzLymDK9mSlQ6bnQ549PH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc033OC%2FbtsGAOk8kkC%2FGzLymDK9mSlQ6bnQ549PH1%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;304&quot; height=&quot;145&quot; data-origin-width=&quot;304&quot; data-origin-height=&quot;145&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1061&quot; data-origin-height=&quot;116&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xg6Zc/btsGDLfE6CG/K4ZJWKyMnJ6SLuOQJvI5y1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xg6Zc/btsGDLfE6CG/K4ZJWKyMnJ6SLuOQJvI5y1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xg6Zc/btsGDLfE6CG/K4ZJWKyMnJ6SLuOQJvI5y1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fxg6Zc%2FbtsGDLfE6CG%2FK4ZJWKyMnJ6SLuOQJvI5y1%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;1061&quot; height=&quot;116&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1061&quot; data-origin-height=&quot;116&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;size16&quot;&gt;위와같이 생성하면 AWS 콘솔 역할에서 아래 내용을 확인할 수 있습니다. OIDC주소는 Public이기 때문에 보안 위협이 될 수 있는데 Condition에 있는 서비스 어카운트를 *로 변경하면, Token이 발급되어 보안에 위협이 생길 수 있다고 합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;889&quot; data-origin-height=&quot;233&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FyLmZ/btsGAbubrnd/tM1zIpKuJCvP8LJLQ98KpK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FyLmZ/btsGAbubrnd/tM1zIpKuJCvP8LJLQ98KpK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FyLmZ/btsGAbubrnd/tM1zIpKuJCvP8LJLQ98KpK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFyLmZ%2FbtsGAbubrnd%2FtM1zIpKuJCvP8LJLQ98KpK%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;889&quot; height=&quot;233&quot; data-origin-width=&quot;889&quot; data-origin-height=&quot;233&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;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Pod Identity는 OIDC Provider를 개선한 방식입니다. Add-on을 추가하고 사용하기만 하면 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;2359&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/baPXjS/btsGBgVMdAw/bghTIiGcLbMdzp9Y47Unp0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/baPXjS/btsGBgVMdAw/bghTIiGcLbMdzp9Y47Unp0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/baPXjS/btsGBgVMdAw/bghTIiGcLbMdzp9Y47Unp0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbaPXjS%2FbtsGBgVMdAw%2FbghTIiGcLbMdzp9Y47Unp0%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;2000&quot; height=&quot;2359&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;2359&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&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1820&quot; data-origin-height=&quot;1824&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/czUZ5I/btsGBceVqs4/rwGftawtqLbiuT8ZHNWHjK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/czUZ5I/btsGBceVqs4/rwGftawtqLbiuT8ZHNWHjK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/czUZ5I/btsGBceVqs4/rwGftawtqLbiuT8ZHNWHjK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FczUZ5I%2FbtsGBceVqs4%2FrwGftawtqLbiuT8ZHNWHjK%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;1820&quot; height=&quot;1824&quot; data-origin-width=&quot;1820&quot; data-origin-height=&quot;1824&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;size16&quot;&gt;Pod-Identity를 설치합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713030070224&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;aws eks create-addon --cluster-name $CLUSTER_NAME --addon-name eks-pod-identity-agent

# 확인
eksctl get addon --cluster $CLUSTER_NAME&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;866&quot; data-origin-height=&quot;235&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mY1rp/btsGB1qeH56/8ASbOMcdVeTQXEvCAeEbs1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mY1rp/btsGB1qeH56/8ASbOMcdVeTQXEvCAeEbs1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mY1rp/btsGB1qeH56/8ASbOMcdVeTQXEvCAeEbs1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmY1rp%2FbtsGB1qeH56%2F8ASbOMcdVeTQXEvCAeEbs1%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;866&quot; height=&quot;235&quot; data-origin-width=&quot;866&quot; data-origin-height=&quot;235&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;size16&quot;&gt;해당 Add-on을 배포하면, eks-pod-identity-agent가 배포됩니다. 해당 파드는 워커노드의 호스트 네트워크를 사용하고, local에서만 접근 가능한 169.254.170.23주소에 80번 포트로 서비스를 게시하고, 파드들은 이쪽으로 credential 요청을 전송합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1220&quot; data-origin-height=&quot;227&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JwDFt/btsGAdeqcVN/s6y0xqEPyp9UinDKoLq2pK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JwDFt/btsGAdeqcVN/s6y0xqEPyp9UinDKoLq2pK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JwDFt/btsGAdeqcVN/s6y0xqEPyp9UinDKoLq2pK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJwDFt%2FbtsGAdeqcVN%2Fs6y0xqEPyp9UinDKoLq2pK%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;1220&quot; height=&quot;227&quot; data-origin-width=&quot;1220&quot; data-origin-height=&quot;227&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 기능을 사용하려면 노드그룹이 사용하는 역할에 AmazonEKSWorkerNodePolicy 정책 부분에 eks-auth 부분이 추가 되어 있어야 합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;867&quot; data-origin-height=&quot;529&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/csFzjz/btsGBZFWkNG/ICFtGRlfUJbTNiftTPGtn1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/csFzjz/btsGBZFWkNG/ICFtGRlfUJbTNiftTPGtn1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/csFzjz/btsGBZFWkNG/ICFtGRlfUJbTNiftTPGtn1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcsFzjz%2FbtsGBZFWkNG%2FICFtGRlfUJbTNiftTPGtn1%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;867&quot; height=&quot;529&quot; data-origin-width=&quot;867&quot; data-origin-height=&quot;529&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;size16&quot;&gt;podientity를 생성합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713030781166&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;eksctl create podidentityassociation \
--cluster $CLUSTER_NAME \
--namespace default \
--service-account-name s3-sa \
--role-name s3-eks-pod-identity-role \
--permission-policy-arns arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess \
--region $AWS_REGION&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1254&quot; data-origin-height=&quot;74&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btU56L/btsGCnmhxkp/EksY2nJtSplkHmmt26es00/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btU56L/btsGCnmhxkp/EksY2nJtSplkHmmt26es00/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btU56L/btsGCnmhxkp/EksY2nJtSplkHmmt26es00/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbtU56L%2FbtsGCnmhxkp%2FEksY2nJtSplkHmmt26es00%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;1254&quot; height=&quot;74&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1254&quot; data-origin-height=&quot;74&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;863&quot; data-origin-height=&quot;267&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvHNvX/btsGC1whorG/09XDDeffSjBsJyxTy9Lek1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvHNvX/btsGC1whorG/09XDDeffSjBsJyxTy9Lek1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvHNvX/btsGC1whorG/09XDDeffSjBsJyxTy9Lek1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvHNvX%2FbtsGC1whorG%2F09XDDeffSjBsJyxTy9Lek1%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;863&quot; height=&quot;267&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;863&quot; data-origin-height=&quot;267&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;size16&quot;&gt;파드를 배포합니다. s3 조회가 정상적으로 작동합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713030950646&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 서비스어카운트, 파드 생성
kubectl create sa s3-sa

cat &amp;lt;&amp;lt;EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: eks-pod-identity
spec:
  serviceAccountName: s3-sa
  containers:
    - name: my-aws-cli
      image: amazon/aws-cli:latest
      command: ['sleep', '36000']
  restartPolicy: Never
  terminationGracePeriodSeconds: 0
EOF&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1002&quot; data-origin-height=&quot;75&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dkTEdI/btsGDJB9fDw/kfx5aSHIgSzZblLkT4Eb9k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dkTEdI/btsGDJB9fDw/kfx5aSHIgSzZblLkT4Eb9k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dkTEdI/btsGDJB9fDw/kfx5aSHIgSzZblLkT4Eb9k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdkTEdI%2FbtsGDJB9fDw%2Fkfx5aSHIgSzZblLkT4Eb9k%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;1002&quot; height=&quot;75&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1002&quot; data-origin-height=&quot;75&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;h2 data-ke-size=&quot;size26&quot;&gt;OWASP Kubernetes Top Ten&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1076&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oDmb6/btsGBPQ5Tuk/o34PsX2dk2Gn8KSQ7Z4cN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oDmb6/btsGBPQ5Tuk/o34PsX2dk2Gn8KSQ7Z4cN0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oDmb6/btsGBPQ5Tuk/o34PsX2dk2Gn8KSQ7Z4cN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoDmb6%2FbtsGBPQ5Tuk%2Fo34PsX2dk2Gn8KSQ7Z4cN0%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;1920&quot; height=&quot;1076&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1076&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;size16&quot;&gt;mysql 배포&lt;/p&gt;
&lt;pre id=&quot;code_1713031330161&quot; class=&quot;yaml&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;cat &amp;lt;&amp;lt;EOT &amp;gt; mysql.yaml
apiVersion: v1
kind: Secret
metadata:
  name: dvwa-secrets
type: Opaque
data:
  # s3r00tpa55
  ROOT_PASSWORD: czNyMDB0cGE1NQ==
  # dvwa
  DVWA_USERNAME: ZHZ3YQ==
  # p@ssword
  DVWA_PASSWORD: cEBzc3dvcmQ=
  # dvwa
  DVWA_DATABASE: ZHZ3YQ==
---
apiVersion: v1
kind: Service
metadata:
  name: dvwa-mysql-service
spec:
  selector:
    app: dvwa-mysql
    tier: backend
  ports:
    - protocol: TCP
      port: 3306
      targetPort: 3306
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: dvwa-mysql
spec:
  replicas: 1
  selector:
    matchLabels:
      app: dvwa-mysql
      tier: backend
  template:
    metadata:
      labels:
        app: dvwa-mysql
        tier: backend
    spec:
      containers:
        - name: mysql
          image: mariadb:10.1
          resources:
            requests:
              cpu: &quot;0.3&quot;
              memory: 256Mi
            limits:
              cpu: &quot;0.3&quot;
              memory: 256Mi
          ports:
            - containerPort: 3306
          env:
            - name: MYSQL_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: dvwa-secrets
                  key: ROOT_PASSWORD
            - name: MYSQL_USER
              valueFrom:
                secretKeyRef:
                  name: dvwa-secrets
                  key: DVWA_USERNAME
            - name: MYSQL_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: dvwa-secrets
                  key: DVWA_PASSWORD
            - name: MYSQL_DATABASE
              valueFrom:
                secretKeyRef:
                  name: dvwa-secrets
                  key: DVWA_DATABASE
EOT
kubectl apply -f mysql.yaml​&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;Web서버 배포&lt;/p&gt;
&lt;pre id=&quot;code_1713031389547&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cat &amp;lt;&amp;lt;EOT &amp;gt; dvwa.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: dvwa-config
data:
  RECAPTCHA_PRIV_KEY: &quot;&quot;
  RECAPTCHA_PUB_KEY: &quot;&quot;
  SECURITY_LEVEL: &quot;low&quot;
  PHPIDS_ENABLED: &quot;0&quot;
  PHPIDS_VERBOSE: &quot;1&quot;
  PHP_DISPLAY_ERRORS: &quot;1&quot;
---
apiVersion: v1
kind: Service
metadata:
  name: dvwa-web-service
spec:
  selector:
    app: dvwa-web
  type: ClusterIP
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: dvwa-web
spec:
  replicas: 1
  selector:
    matchLabels:
      app: dvwa-web
  template:
    metadata:
      labels:
        app: dvwa-web
    spec:
      containers:
        - name: dvwa
          image: cytopia/dvwa:php-8.1
          ports:
            - containerPort: 80
          resources:
            requests:
              cpu: &quot;0.3&quot;
              memory: 256Mi
            limits:
              cpu: &quot;0.3&quot;
              memory: 256Mi
          env:
            - name: RECAPTCHA_PRIV_KEY
              valueFrom:
                configMapKeyRef:
                  name: dvwa-config
                  key: RECAPTCHA_PRIV_KEY
            - name: RECAPTCHA_PUB_KEY
              valueFrom:
                configMapKeyRef:
                  name: dvwa-config
                  key: RECAPTCHA_PUB_KEY
            - name: SECURITY_LEVEL
              valueFrom:
                configMapKeyRef:
                  name: dvwa-config
                  key: SECURITY_LEVEL
            - name: PHPIDS_ENABLED
              valueFrom:
                configMapKeyRef:
                  name: dvwa-config
                  key: PHPIDS_ENABLED
            - name: PHPIDS_VERBOSE
              valueFrom:
                configMapKeyRef:
                  name: dvwa-config
                  key: PHPIDS_VERBOSE
            - name: PHP_DISPLAY_ERRORS
              valueFrom:
                configMapKeyRef:
                  name: dvwa-config
                  key: PHP_DISPLAY_ERRORS
            - name: MYSQL_HOSTNAME
              value: dvwa-mysql-service
            - name: MYSQL_DATABASE
              valueFrom:
                secretKeyRef:
                  name: dvwa-secrets
                  key: DVWA_DATABASE
            - name: MYSQL_USERNAME
              valueFrom:
                secretKeyRef:
                  name: dvwa-secrets
                  key: DVWA_USERNAME
            - name: MYSQL_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: dvwa-secrets
                  key: DVWA_PASSWORD
EOT
kubectl apply -f dvwa.yaml&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;Ingress 배포&lt;/p&gt;
&lt;pre id=&quot;code_1713031407150&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cat &amp;lt;&amp;lt;EOT &amp;gt; dvwa-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    alb.ingress.kubernetes.io/certificate-arn: $CERT_ARN
    alb.ingress.kubernetes.io/group.name: study
    alb.ingress.kubernetes.io/listen-ports: '[{&quot;HTTPS&quot;:443}, {&quot;HTTP&quot;:80}]'
    alb.ingress.kubernetes.io/load-balancer-name: myeks-ingress-alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/ssl-redirect: &quot;443&quot;
    alb.ingress.kubernetes.io/success-codes: 200-399
    alb.ingress.kubernetes.io/target-type: ip
  name: ingress-dvwa
spec:
  ingressClassName: alb
  rules:
  - host: dvwa.$MyDomain
    http:
      paths:
      - backend:
          service:
            name: dvwa-web-service
            port:
              number: 80
        path: /
        pathType: Prefix
EOT
kubectl apply -f dvwa-ingress.yaml
echo -e &quot;DVWA Web https://dvwa.$MyDomain&quot;&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;접속 (admin/admin)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;890&quot; data-origin-height=&quot;435&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ta8zD/btsGC1wht2V/PHicrK50BHkVyrVKaYNQuK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ta8zD/btsGC1wht2V/PHicrK50BHkVyrVKaYNQuK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ta8zD/btsGC1wht2V/PHicrK50BHkVyrVKaYNQuK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTa8zD%2FbtsGC1wht2V%2FPHicrK50BHkVyrVKaYNQuK%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;890&quot; height=&quot;435&quot; data-origin-width=&quot;890&quot; data-origin-height=&quot;435&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Create Database 클릭&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;678&quot; data-origin-height=&quot;843&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k3ie7/btsGC4ftHrF/FW7kEV8NkjIZhRbk2Fv7J1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k3ie7/btsGC4ftHrF/FW7kEV8NkjIZhRbk2Fv7J1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k3ie7/btsGC4ftHrF/FW7kEV8NkjIZhRbk2Fv7J1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk3ie7%2FbtsGC4ftHrF%2FFW7kEV8NkjIZhRbk2Fv7J1%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;678&quot; height=&quot;843&quot; data-origin-width=&quot;678&quot; data-origin-height=&quot;843&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;size16&quot;&gt;재 로그인 (admin/password)&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;DVWA Security 수준 Low로 저장&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;875&quot; data-origin-height=&quot;633&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cpEFu4/btsGBAGsjiG/CMe2q0ewuTHkM4twK7gqjK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cpEFu4/btsGBAGsjiG/CMe2q0ewuTHkM4twK7gqjK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cpEFu4/btsGBAGsjiG/CMe2q0ewuTHkM4twK7gqjK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcpEFu4%2FbtsGBAGsjiG%2FCMe2q0ewuTHkM4twK7gqjK%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;875&quot; height=&quot;633&quot; data-origin-width=&quot;875&quot; data-origin-height=&quot;633&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;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Command Injection 공격 유형 |&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자가 입력한 명령어 그대로 shell 스크립트를 실행할 수 있음을 확인했을 때&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;880&quot; data-origin-height=&quot;328&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nL1fQ/btsGBg2vJem/C12E7t932BxlrcC2nqeZTK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nL1fQ/btsGBg2vJem/C12E7t932BxlrcC2nqeZTK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nL1fQ/btsGBg2vJem/C12E7t932BxlrcC2nqeZTK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnL1fQ%2FbtsGBg2vJem%2FC12E7t932BxlrcC2nqeZTK%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;880&quot; height=&quot;328&quot; data-origin-width=&quot;880&quot; data-origin-height=&quot;328&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;size16&quot;&gt;아래처럼 EC2의 인스턴스 프로필을 요청하는 방식으로 취약점이 생길 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;889&quot; data-origin-height=&quot;309&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dywM07/btsGAXWs9hc/RriQP4V1Z1oTXlFmY5JAmK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dywM07/btsGAXWs9hc/RriQP4V1Z1oTXlFmY5JAmK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dywM07/btsGAXWs9hc/RriQP4V1Z1oTXlFmY5JAmK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdywM07%2FbtsGAXWs9hc%2FRriQP4V1Z1oTXlFmY5JAmK%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;889&quot; height=&quot;309&quot; data-origin-width=&quot;889&quot; data-origin-height=&quot;309&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;size16&quot;&gt;Kubelet 미흡한 인증/인가 설정 시 위험 |&lt;/p&gt;
&lt;pre id=&quot;code_1713032121117&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;(hakjunadmin@myeks:N/A) [root@myeks-bastion ~]# ssh ec2-user@$N1 sudo ss -tnlp | grep kubelet
LISTEN 0      4096        127.0.0.1:10248      0.0.0.0:*    users:((&quot;kubelet&quot;,pid=3024,fd=16))
LISTEN 0      4096                *:10250            *:*    users:((&quot;kubelet&quot;,pid=3024,fd=13))

# 데모를 위해 awscli 파드 생성
cat &amp;lt;&amp;lt;EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: myawscli
spec:
  #serviceAccountName: my-sa
  containers:
    - name: my-aws-cli
      image: amazon/aws-cli:latest
      command: ['sleep', '36000']
  restartPolicy: Never
  terminationGracePeriodSeconds: 0
EOF&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;Bastion2에서 kubeletfct 설치 및 사용&lt;/p&gt;
&lt;pre id=&quot;code_1713032353633&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 기존 kubeconfig 삭제
rm -rf ~/.kube

# 다운로드
curl -LO https://github.com/cyberark/kubeletctl/releases/download/v1.11/kubeletctl_linux_amd64 &amp;amp;&amp;amp; chmod a+x ./kubeletctl_linux_amd64 &amp;amp;&amp;amp; mv ./kubeletctl_linux_amd64 /usr/local/bin/kubeletctl
kubeletctl version
kubeletctl help

# 노드1 IP 변수 지정
N1=&amp;lt;각자 자신의 노드1의 PrivateIP&amp;gt;
N1=192.168.1.206

# 노드1 IP로 Scan
kubeletctl scan --cidr $N1/32

# 노드1에 kubelet API 호출 시도
curl -k https://$N1:10250/pods; echo
Unauthorized&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1251&quot; data-origin-height=&quot;472&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CNlws/btsGC2Wfwhu/RhTao4PyBtsgdmCHpcB6TK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CNlws/btsGC2Wfwhu/RhTao4PyBtsgdmCHpcB6TK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CNlws/btsGC2Wfwhu/RhTao4PyBtsgdmCHpcB6TK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCNlws%2FbtsGC2Wfwhu%2FRhTao4PyBtsgdmCHpcB6TK%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;1251&quot; height=&quot;472&quot; data-origin-width=&quot;1251&quot; data-origin-height=&quot;472&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;size16&quot;&gt;Node 1 접속 후 kubelet-config.json 수정&lt;/p&gt;
&lt;pre id=&quot;code_1713032501226&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 노드1 접속
ssh ec2-user@$N1
-----------------------------
# 미흡한 인증/인가 설정으로 변경
sudo vi /etc/kubernetes/kubelet/kubelet-config.json
...
&quot;authentication&quot;: {
    &quot;anonymous&quot;: {
      &quot;enabled&quot;: true
...
  },
  &quot;authorization&quot;: {
    &quot;mode&quot;: &quot;AlwaysAllow&quot;,
...

# kubelet restart
sudo systemctl restart kubelet
systemctl status kubelet
-----------------------------&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1252&quot; data-origin-height=&quot;507&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bje2ae/btsGAXWtakz/pYdQFKbMRrJhOlOvRVY4sK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bje2ae/btsGAXWtakz/pYdQFKbMRrJhOlOvRVY4sK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bje2ae/btsGAXWtakz/pYdQFKbMRrJhOlOvRVY4sK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbje2ae%2FbtsGAXWtakz%2FpYdQFKbMRrJhOlOvRVY4sK%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;1252&quot; height=&quot;507&quot; data-origin-width=&quot;1252&quot; data-origin-height=&quot;507&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;size16&quot;&gt;Bastion2에서 kubeletct 사용, 기존에 접근 안되던 부분들이 접근 가능해 짐.&lt;/p&gt;
&lt;pre id=&quot;code_1713032610473&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 파드 목록 확인
curl -s -k https://$N1:10250/pods | jq

# kubelet-config.json 설정 내용 확인
curl -k https://$N1:10250/configz | jq

# kubeletct 사용
# Return kubelet's configuration
kubeletctl -s $N1 configz | jq

# Get list of pods on the node
kubeletctl -s $N1 pods

# Scans for nodes with opened kubelet API &amp;gt; Scans for for all the tokens in a given Node
kubeletctl -s $N1 scan token

# 단, 아래 실습은 워커노드1에 myawscli 파드가 배포되어 있어야 실습이 가능. 물론 노드2~3에도 kubelet 수정하면 실습 가능함.
# kubelet API로 명령 실행 : &amp;lt;네임스페이스&amp;gt; / &amp;lt;파드명&amp;gt; / &amp;lt;컨테이너명&amp;gt;
curl -k https://$N1:10250/run/default/myawscli/my-aws-cli -d &quot;cmd=aws --version&quot;

# Scans for nodes with opened kubelet API &amp;gt; remote code execution on their containers
kubeletctl -s $N1 scan rce

# Run commands inside a container
kubeletctl -s $N1 exec &quot;/bin/bash&quot; -n default -p myawscli -c my-aws-cli
--------------------------------
export
aws --version
aws ec2 describe-vpcs --region ap-northeast-2 --output table --no-cli-pager
exit
--------------------------------

# Return resource usage metrics (such as container CPU, memory usage, etc.)
kubeletctl -s $N1 metrics&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1250&quot; data-origin-height=&quot;718&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dmV8Td/btsGAbOtgXM/3P3r50iOsylxoRlyPWBvW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dmV8Td/btsGAbOtgXM/3P3r50iOsylxoRlyPWBvW0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dmV8Td/btsGAbOtgXM/3P3r50iOsylxoRlyPWBvW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdmV8Td%2FbtsGAbOtgXM%2F3P3r50iOsylxoRlyPWBvW0%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;1250&quot; height=&quot;718&quot; data-origin-width=&quot;1250&quot; data-origin-height=&quot;718&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;905&quot; data-origin-height=&quot;902&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bA02WN/btsGCsgBlmh/IW42Xi6RMjuJh0lNz2CKe0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bA02WN/btsGCsgBlmh/IW42Xi6RMjuJh0lNz2CKe0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bA02WN/btsGCsgBlmh/IW42Xi6RMjuJh0lNz2CKe0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbA02WN%2FbtsGCsgBlmh%2FIW42Xi6RMjuJh0lNz2CKe0%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;905&quot; height=&quot;902&quot; data-origin-width=&quot;905&quot; data-origin-height=&quot;902&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;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Kyverno&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Kubernetes Native Policy Management&lt;/p&gt;
&lt;figure id=&quot;og_1713032853462&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;Kyverno&quot; data-og-description=&quot;Kyverno is a policy engine designed for Kubernetes&quot; data-og-host=&quot;kyverno.io&quot; data-og-source-url=&quot;https://kyverno.io/&quot; data-og-url=&quot;https://kyverno.io/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://kyverno.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://kyverno.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;Kyverno&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Kyverno is a policy engine designed for Kubernetes&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;kyverno.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;
&lt;p data-ke-size=&quot;size16&quot;&gt;동작 |&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Mutating, Validating admission 과정에서 허용/차단 정책을 제공해 준다. kyverno는 rule의 집합으로 사용됨.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1033&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Vnbng/btsGCWIw2SH/zlFG8zjJAGNWfS5E8IANik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Vnbng/btsGCWIw2SH/zlFG8zjJAGNWfS5E8IANik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Vnbng/btsGCWIw2SH/zlFG8zjJAGNWfS5E8IANik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVnbng%2FbtsGCWIw2SH%2FzlFG8zjJAGNWfS5E8IANik%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;2000&quot; height=&quot;1033&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1033&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YGPko/btsGB1wYsfy/vtwzYEUyyjFqCeR8gEkBKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YGPko/btsGB1wYsfy/vtwzYEUyyjFqCeR8gEkBKk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YGPko/btsGB1wYsfy/vtwzYEUyyjFqCeR8gEkBKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYGPko%2FbtsGB1wYsfy%2FvtwzYEUyyjFqCeR8gEkBKk%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;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치, EKS에서 사용 시 kube-system ns에 배포된 리소스는 대상에서 제외&lt;/p&gt;
&lt;pre id=&quot;code_1713032958706&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cat &amp;lt;&amp;lt; EOF &amp;gt; kyverno-value.yaml
config:
  resourceFiltersExcludeNamespaces: [ kube-system ]

admissionController:
  serviceMonitor:
    enabled: true

backgroundController:
  serviceMonitor:
    enabled: true

cleanupController:
  serviceMonitor:
    enabled: true

reportsController:
  serviceMonitor:
    enabled: true
EOF
kubectl create ns kyverno
helm repo add kyverno https://kyverno.github.io/kyverno/
helm install kyverno kyverno/kyverno --version 3.2.0-rc.3 -f kyverno-value.yaml -n kyverno

# 확인
kubectl get all -n kyverno
kubectl get crd | grep kyverno
kubectl get pod,svc -n kyverno

# (참고) 기본 인증서 확인 https://kyverno.io/docs/installation/customization/#default-certificates
# step-cli 설치 https://smallstep.com/docs/step-cli/installation/
wget https://dl.smallstep.com/cli/docs-cli-install/latest/step-cli_amd64.rpm
sudo rpm -i step-cli_amd64.rpm

#
kubectl -n kyverno get secret
kubectl -n kyverno get secret kyverno-svc.kyverno.svc.kyverno-tls-ca -o jsonpath='{.data.tls\.crt}' | base64 -d
kubectl -n kyverno get secret kyverno-svc.kyverno.svc.kyverno-tls-ca -o jsonpath='{.data.tls\.crt}' | base64 -d | step certificate inspect --short


#
kubectl get validatingwebhookconfiguration kyverno-policy-validating-webhook-cfg -o jsonpath='{.webhooks[0].clientConfig.caBundle}' | base64 -d | step certificate inspect --short&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;프로메테우스 확인&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;377&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/by5ZRY/btsGBvFjhaG/FIkIEKsHbe2wcXGe87ZFb1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/by5ZRY/btsGBvFjhaG/FIkIEKsHbe2wcXGe87ZFb1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/by5ZRY/btsGBvFjhaG/FIkIEKsHbe2wcXGe87ZFb1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fby5ZRY%2FbtsGBvFjhaG%2FFIkIEKsHbe2wcXGe87ZFb1%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;600&quot; height=&quot;377&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;377&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;size16&quot;&gt;그라파나 대시보드 확인 15804&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1239&quot; data-origin-height=&quot;781&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Krc99/btsGDzl1RPb/dmD2y22hsTOtp2GZf2WQM1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Krc99/btsGDzl1RPb/dmD2y22hsTOtp2GZf2WQM1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Krc99/btsGDzl1RPb/dmD2y22hsTOtp2GZf2WQM1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKrc99%2FbtsGDzl1RPb%2FdmD2y22hsTOtp2GZf2WQM1%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;1239&quot; height=&quot;781&quot; data-origin-width=&quot;1239&quot; data-origin-height=&quot;781&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;size16&quot;&gt;cluster policy 생성, pod 라벨에 team이 있어야 함.&lt;/p&gt;
&lt;pre id=&quot;code_1713033388595&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl create -f- &amp;lt;&amp;lt; EOF
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-labels
spec:
  validationFailureAction: Enforce
  rules:
  - name: check-team
    match:
      any:
      - resources:
          kinds:
          - Pod
    validate:
      message: &quot;label 'team' is required&quot;
      pattern:
        metadata:
          labels:
            team: &quot;?*&quot;
EOF&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;755&quot; data-origin-height=&quot;291&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HWGMQ/btsGBguF5uC/LWU1gIGwEoxnj1FkkOIlpK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HWGMQ/btsGBguF5uC/LWU1gIGwEoxnj1FkkOIlpK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HWGMQ/btsGBguF5uC/LWU1gIGwEoxnj1FkkOIlpK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHWGMQ%2FbtsGBguF5uC%2FLWU1gIGwEoxnj1FkkOIlpK%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;755&quot; height=&quot;291&quot; data-origin-width=&quot;755&quot; data-origin-height=&quot;291&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;size16&quot;&gt;디플로이먼트 생성을 시도했으나, 생성 실패&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;824&quot; data-origin-height=&quot;146&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2JJTm/btsGBdEW1tm/dqjKh8jk59k1VeZbcSmnn0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2JJTm/btsGBdEW1tm/dqjKh8jk59k1VeZbcSmnn0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2JJTm/btsGBdEW1tm/dqjKh8jk59k1VeZbcSmnn0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2JJTm%2FbtsGBdEW1tm%2FdqjKh8jk59k1VeZbcSmnn0%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;824&quot; height=&quot;146&quot; data-origin-width=&quot;824&quot; data-origin-height=&quot;146&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;size16&quot;&gt;key가 team인 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;label 추가 후 재배포 성공&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;823&quot; data-origin-height=&quot;39&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JRLKk/btsGAX3dAZE/IQR7SuRY1qovxy0iCeUyHk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JRLKk/btsGAX3dAZE/IQR7SuRY1qovxy0iCeUyHk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JRLKk/btsGAX3dAZE/IQR7SuRY1qovxy0iCeUyHk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJRLKk%2FbtsGAX3dAZE%2FIQR7SuRY1qovxy0iCeUyHk%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;823&quot; height=&quot;39&quot; data-origin-width=&quot;823&quot; data-origin-height=&quot;39&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;size16&quot;&gt;validation 리포트 확인&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;999&quot; data-origin-height=&quot;222&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JwDea/btsGA0FEqqQ/83lkBkyisbKqHndKdhVWV0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JwDea/btsGA0FEqqQ/83lkBkyisbKqHndKdhVWV0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JwDea/btsGA0FEqqQ/83lkBkyisbKqHndKdhVWV0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJwDea%2FbtsGA0FEqqQ%2F83lkBkyisbKqHndKdhVWV0%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;999&quot; height=&quot;222&quot; data-origin-width=&quot;999&quot; data-origin-height=&quot;222&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;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Mutating |&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파드를 대상으로 mutate 정책으로 라벨을 추가로 할당&lt;/p&gt;
&lt;pre id=&quot;code_1713033653943&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl create -f- &amp;lt;&amp;lt; EOF
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: add-labels
spec:
  rules:
  - name: add-team
    match:
      any:
      - resources:
          kinds:
          - Pod
    mutate:
      patchStrategicMerge:
        metadata:
          labels:
            +(team): bravo
EOF&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;723&quot; data-origin-height=&quot;237&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/S6U0s/btsGCcyjJ9O/vaosAPDbycEtN4lOjESAw1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/S6U0s/btsGCcyjJ9O/vaosAPDbycEtN4lOjESAw1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/S6U0s/btsGCcyjJ9O/vaosAPDbycEtN4lOjESAw1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FS6U0s%2FbtsGCcyjJ9O%2FvaosAPDbycEtN4lOjESAw1%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;723&quot; height=&quot;237&quot; data-origin-width=&quot;723&quot; data-origin-height=&quot;237&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;size16&quot;&gt;파드 생성 시, team: bravo가 자동 추가됨&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;672&quot; data-origin-height=&quot;108&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EyL45/btsGAbubJhp/egWwlsoeKVU6n3cV2YrzG1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EyL45/btsGAbubJhp/egWwlsoeKVU6n3cV2YrzG1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EyL45/btsGAbubJhp/egWwlsoeKVU6n3cV2YrzG1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEyL45%2FbtsGAbubJhp%2FegWwlsoeKVU6n3cV2YrzG1%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;672&quot; height=&quot;108&quot; data-origin-width=&quot;672&quot; data-origin-height=&quot;108&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;size16&quot;&gt;key에 team으로 지정하고 생성하면 value는 Override되어 들어간다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;822&quot; data-origin-height=&quot;128&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9QPJG/btsGCZL0Ubp/veQ9iPkAF8MiSODJ3fQUHk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9QPJG/btsGCZL0Ubp/veQ9iPkAF8MiSODJ3fQUHk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9QPJG/btsGCZL0Ubp/veQ9iPkAF8MiSODJ3fQUHk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9QPJG%2FbtsGCZL0Ubp%2FveQ9iPkAF8MiSODJ3fQUHk%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;822&quot; height=&quot;128&quot; data-origin-width=&quot;822&quot; data-origin-height=&quot;128&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;size16&quot;&gt;Generation |&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1713033911016&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl -n default create secret docker-registry regcred \
  --docker-server=myinternalreg.corp.com \
  --docker-username=john.doe \
  --docker-password=Passw0rd123! \
  --docker-email=john.doe@corp.com
  
kubectl create -f- &amp;lt;&amp;lt; EOF
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: sync-secrets
spec:
  rules:
  - name: sync-image-pull-secret
    match:
      any:
      - resources:
          kinds:
          - Namespace
    generate:
      apiVersion: v1
      kind: Secret
      name: regcred
      namespace: &quot;{{request.object.metadata.name}}&quot;
      synchronize: true
      clone:
        namespace: default
        name: regcred
EOF&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;642&quot; data-origin-height=&quot;63&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwoWwm/btsGCvK9CYW/7Jy5kB57P9ykUat7tZJtOk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwoWwm/btsGCvK9CYW/7Jy5kB57P9ykUat7tZJtOk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwoWwm/btsGCvK9CYW/7Jy5kB57P9ykUat7tZJtOk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwoWwm%2FbtsGCvK9CYW%2F7Jy5kB57P9ykUat7tZJtOk%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;642&quot; height=&quot;63&quot; data-origin-width=&quot;642&quot; data-origin-height=&quot;63&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;size16&quot;&gt;새로운 namespace 생성 후 secret을 확인해보면, regcred 시크릿이 자동으로 생성된 것을 확인할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;630&quot; data-origin-height=&quot;92&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/55dwT/btsGDLGJqt7/pPw2Bc3mZc6QKFzARNbM3k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/55dwT/btsGDLGJqt7/pPw2Bc3mZc6QKFzARNbM3k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/55dwT/btsGDLGJqt7/pPw2Bc3mZc6QKFzARNbM3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F55dwT%2FbtsGDLGJqt7%2FpPw2Bc3mZc6QKFzARNbM3k%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;630&quot; height=&quot;92&quot; data-origin-width=&quot;630&quot; data-origin-height=&quot;92&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&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1238&quot; data-origin-height=&quot;1372&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cQ7vij/btsGB32DgQi/X3jZ06TKF6am73GUVYvrJk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cQ7vij/btsGB32DgQi/X3jZ06TKF6am73GUVYvrJk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cQ7vij/btsGB32DgQi/X3jZ06TKF6am73GUVYvrJk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcQ7vij%2FbtsGB32DgQi%2FX3jZ06TKF6am73GUVYvrJk%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;1238&quot; height=&quot;1372&quot; data-origin-width=&quot;1238&quot; data-origin-height=&quot;1372&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <author>junkmm</author>
      <guid isPermaLink="true">https://junkmm.tistory.com/36</guid>
      <comments>https://junkmm.tistory.com/36#entry36comment</comments>
      <pubDate>Thu, 11 Apr 2024 20:46:29 +0900</pubDate>
    </item>
  </channel>
</rss>