<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>All About Dev/Ops</title>
    <link>https://zerone-code.tistory.com/</link>
    <description>BackEnd Developer와 DevOps Engineer의 길을 걷는 개발 블로그입니다.
</description>
    <language>ko</language>
    <pubDate>Tue, 28 Jul 2026 01:20:12 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>zeroneCoder</managingEditor>
    <image>
      <title>All About Dev/Ops</title>
      <url>https://tistory1.daumcdn.net/tistory/5188433/attach/8af9814ef2bb4e68b002188e27c1fd36</url>
      <link>https://zerone-code.tistory.com</link>
    </image>
    <item>
      <title>Terraform State는 안전한가요? State에 Secrets을 남기지 않는 방법</title>
      <link>https://zerone-code.tistory.com/20</link>
      <description>&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;&lt;a href=&quot;https://builder.aws.com/community/@zerone?tab=articles&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;AWS Community Builder&lt;/a&gt;이자 Datadog/HashiCorp Ambassbor인 DevOps Engineer인 &lt;/b&gt;&lt;b&gt;zerone-code입니다.&lt;/b&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;최근에 Massive Migration을 진행하기 위해 플랫폼적인 설계와 더불어 Secrets 보관 방법에 대해 여러 방법을 연구하고 있습니다.&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;AWS Secrets Manager나 Parameter Store에 저장하던 중요한 Secrets 값을 어떻게 하면 더 보안 수준이 높게 저장&lt;/b&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;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘 읽으셨다면 많은 공감과 구독 부탁드립니다!&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이번 글에서 사용한 예제 코드는 아래 링크에 있습니다. 참고하시면서 글을 읽으시면 더 도움이 될거 같습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/YoungJinJung/test-provisioning/tree/main/terraform/secretsmanager&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/YoungJinJung/test-provisioning/tree/main/terraform/secretsmanager&lt;/a&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 Resource는 생성된 후 그 상태(State)를 tfstate 파일에 기록하여 다음 실행 때 비교했습니다. 그래서 Secrets을 어떤 방법으로 감춰서 생성하더라도, &lt;b&gt;결국 Terraform State에는 남을 수 밖에 없었습니다.(Fig 1.)&lt;/b&gt; 아니면 Dummy값을 넣어서 콘솔에서 수정하는 방식을 사용하기도 했는데, 이는 값의 변화를 추적할 수 없다는 단점이 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1494&quot; data-origin-height=&quot;707&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btBB8e/dJMcaaYyAVF/UTwa8nsPDmr6P768fx6G6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btBB8e/dJMcaaYyAVF/UTwa8nsPDmr6P768fx6G6K/img.png&quot; data-alt=&quot;Fig 1. Terraform State에 남은 Secrets 값&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btBB8e/dJMcaaYyAVF/UTwa8nsPDmr6P768fx6G6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbtBB8e%2FdJMcaaYyAVF%2FUTwa8nsPDmr6P768fx6G6K%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;1494&quot; height=&quot;707&quot; data-origin-width=&quot;1494&quot; data-origin-height=&quot;707&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Fig 1. Terraform State에 남은 Secrets 값&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Terraform에서는 Ephemeral Resource라는 개념을 1.10.x 이후 버전부터 도입했습니다. &lt;b data-index-in-node=&quot;74&quot; data-path-to-node=&quot;4&quot;&gt;Ephemeral Resources&lt;/b&gt;는 이름 그대로 &lt;b&gt;'일시적으로 존재'&lt;/b&gt;하는 Resource입니다. 아래 두가지 메커니즘을 메인으로 Ephemeral resource는 동작하게 됩니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;5&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,0,0&quot;&gt;상태 저장 안 함:&lt;/b&gt; 실행 시점에만 메모리에 존재하며, 실행이 끝나면 tfstate나 plan 파일에 어떠한 정보도 남기지 않습니다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,1,0&quot;&gt;Write-only 메커니즘:&lt;/b&gt; 주로 외부 시스템(예: AWS Secrets Manager, Vault)에 데이터를 &lt;b data-index-in-node=&quot;64&quot; data-path-to-node=&quot;5,1,0&quot;&gt;쓰기&lt;/b&gt;만 하고, 그 값 자체를 Terraform이 보관할 필요가 없는 경우에 사용됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 &lt;b data-path-to-node=&quot;4&quot; data-index-in-node=&quot;74&quot;&gt;Ephemeral Resources&amp;nbsp;&lt;/b&gt;만으로는 tfstate에 secrets값이 남는 걸 막을 수 없었습니다.&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;Ephemeral Resource&lt;/b&gt;는 data구분이나 output 구문처럼 다른 Resource에 참고해서 사용하는 경우, 값을 저장하지 않게 해줬습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1548&quot; data-origin-height=&quot;248&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ab7wK/dJMcaiWyZZU/fZ37VXMEtQVs31so6BGK60/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ab7wK/dJMcaiWyZZU/fZ37VXMEtQVs31so6BGK60/img.png&quot; data-alt=&quot;Terraform Docs에서 Ephemeral Resource에 대한 설명&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ab7wK/dJMcaiWyZZU/fZ37VXMEtQVs31so6BGK60/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAb7wK%2FdJMcaiWyZZU%2FfZ37VXMEtQVs31so6BGK60%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;1548&quot; height=&quot;248&quot; data-origin-width=&quot;1548&quot; data-origin-height=&quot;248&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Terraform Docs에서 Ephemeral Resource에 대한 설명&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 생성하려는 Resource에도 &lt;b data-index-in-node=&quot;34&quot; data-path-to-node=&quot;13,1,0&quot;&gt;Write-only Arguments&lt;/b&gt;가 지원되야 Ephemeral Resource를 사용해서 Resource를 생성하고, Terraform State에 값이 남지 않도록 할 수 있다는 뜻이 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;주로 사용하는 AWS Secrets Manager와 Parameter Store Resource는 1.11.0 이상 버전부터 지원을 하기 시작했습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1432&quot; data-origin-height=&quot;1010&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/crEX3P/dJMcafS69cf/2kuvACaWhWUHldoi8qoIdK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/crEX3P/dJMcafS69cf/2kuvACaWhWUHldoi8qoIdK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/crEX3P/dJMcafS69cf/2kuvACaWhWUHldoi8qoIdK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcrEX3P%2FdJMcafS69cf%2F2kuvACaWhWUHldoi8qoIdK%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;1432&quot; height=&quot;1010&quot; data-origin-width=&quot;1432&quot; data-origin-height=&quot;1010&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;a href=&quot;https://registry.terraform.io/providers/carlpett/sops/latest/docs&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Sops라는 Provider&lt;/a&gt;를 활용해서 Terraform code에서는 Secrets이 보이지 않고, 이를 참조해서 AWS Secrets Manager나 Parameter Store 등 Secrets 값을 코드에 남기지 않도록 구성합니다. &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;그래서 아래와 같이 sops를 참조하는 부분은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;Ephemeral Resource로 구성하고 Write-only Arguments를 적용하지 않았을 때&lt;span style=&quot;color: #000000;&quot;&gt;(&lt;span style=&quot;text-align: center;&quot;&gt;Fig 2-1.)&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;, 아래와 같이 Resource 생성에 오류가 나는 것을 확인해볼 수 있습니다.&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(&lt;span style=&quot;text-align: center;&quot;&gt;Fig 2-2.)&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1109&quot; data-origin-height=&quot;517&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eBhkkq/dJMcagR1LKa/v6B6hP3WUtbJykwt51QPP1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eBhkkq/dJMcagR1LKa/v6B6hP3WUtbJykwt51QPP1/img.png&quot; data-alt=&quot;Fig 2-1. Sops Provider에 Ephemeral을 적용 후, AWS Secrets Manager를 생성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eBhkkq/dJMcagR1LKa/v6B6hP3WUtbJykwt51QPP1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeBhkkq%2FdJMcagR1LKa%2Fv6B6hP3WUtbJykwt51QPP1%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;1109&quot; height=&quot;517&quot; data-origin-width=&quot;1109&quot; data-origin-height=&quot;517&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Fig 2-1. Sops Provider에 Ephemeral을 적용 후, AWS Secrets Manager를 생성&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;943&quot; data-origin-height=&quot;206&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YWuVk/dJMcafyPfEy/k3O5UEQX6saSqS4oLAG8M0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YWuVk/dJMcafyPfEy/k3O5UEQX6saSqS4oLAG8M0/img.png&quot; data-alt=&quot;Fig 2-2. Resource 생성에 실패&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YWuVk/dJMcafyPfEy/k3O5UEQX6saSqS4oLAG8M0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYWuVk%2FdJMcafyPfEy%2Fk3O5UEQX6saSqS4oLAG8M0%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;943&quot; height=&quot;206&quot; data-origin-width=&quot;943&quot; data-origin-height=&quot;206&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Fig 2-2. Resource 생성에 실패&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;Write-Only Arguments&lt;/b&gt;만을 활용해서 Terraform State에 Secrets이 남는걸 막을 수 있을까요? &lt;b&gt;정답은 No입니다.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;어디선가 값을 읽어서 참조해야 하고, 그 값을 Write-Only Arguments로 사용하기 때문에 참조해서 생성되는 Resource&lt;b&gt;(&lt;span style=&quot;text-align: center;&quot;&gt;Fig 3-1.)&lt;/span&gt;&lt;/b&gt;는 Terraform State에 Secrets이 남지 않지만&lt;b&gt;(&lt;span style=&quot;text-align: center;&quot;&gt;Fig 3-2.)&lt;/span&gt;&lt;/b&gt;, 참조를 해야하는 Resource는 State에 어떤 값이 참조되는지에 대해 보이게 됩니다.&lt;b&gt;(&lt;span style=&quot;text-align: center;&quot;&gt;Fig 3-3.)&lt;/span&gt;&lt;/b&gt;&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;980&quot; data-origin-height=&quot;410&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/be3EjC/dJMcad10ra8/1J4eIB3TA9e9R0IrLAIFF0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/be3EjC/dJMcad10ra8/1J4eIB3TA9e9R0IrLAIFF0/img.png&quot; data-alt=&quot;Fig 3-1. Sops Provider를 적용 후, Write-Only Arguments를 활용해 AWS Secrets Manager를 생성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/be3EjC/dJMcad10ra8/1J4eIB3TA9e9R0IrLAIFF0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbe3EjC%2FdJMcad10ra8%2F1J4eIB3TA9e9R0IrLAIFF0%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;980&quot; height=&quot;410&quot; data-origin-width=&quot;980&quot; data-origin-height=&quot;410&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Fig 3-1. Sops Provider를 적용 후, Write-Only Arguments를 활용해 AWS Secrets Manager를 생성&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;947&quot; data-origin-height=&quot;620&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/r4d65/dJMcabb5y8Z/LdoKrJ2gF2zfbKqnCJYOCk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/r4d65/dJMcabb5y8Z/LdoKrJ2gF2zfbKqnCJYOCk/img.png&quot; data-alt=&quot;Fig 3-2. 참조되는 Sops 리소스에 어떤 값을 참조하는지에 대한 Terraform State&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/r4d65/dJMcabb5y8Z/LdoKrJ2gF2zfbKqnCJYOCk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fr4d65%2FdJMcabb5y8Z%2FLdoKrJ2gF2zfbKqnCJYOCk%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;620&quot; data-origin-width=&quot;947&quot; data-origin-height=&quot;620&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Fig 3-2. 참조되는 Sops 리소스에 어떤 값을 참조하는지에 대한 Terraform State&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1476&quot; data-origin-height=&quot;702&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHD2rX/dJMcagkawwl/DCjxlqGFlD9kSEFROaeICk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHD2rX/dJMcagkawwl/DCjxlqGFlD9kSEFROaeICk/img.png&quot; data-alt=&quot;Fig 3-3. 참조해서 만든 AWS Secrets Manager&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHD2rX/dJMcagkawwl/DCjxlqGFlD9kSEFROaeICk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbHD2rX%2FdJMcagkawwl%2FDCjxlqGFlD9kSEFROaeICk%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;1476&quot; height=&quot;702&quot; data-origin-width=&quot;1476&quot; data-origin-height=&quot;702&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Fig 3-3. 참조해서 만든 AWS Secrets Manager&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;Ephemeral Resource와 Write-Only Arguments를 모두 적용&lt;/b&gt;해서 AWS Secrets Manager Resource를 생성해보도록 하겠습니다. &lt;b&gt;Fig 4-1. 과 같이&amp;nbsp;&lt;/b&gt;참조할 값이 암호화 되있는 sops_file은 Ephemeral Resource로 임시로 참조해서 State에 남지 않도록 구성하고, secrets_string_wo 속성과 sercets_string_wo_version 속성을 활용해서 &lt;b&gt;Write-Only Arguments&lt;/b&gt;를 지정해서 Resource를 생성하도록 합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;879&quot; data-origin-height=&quot;412&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ody9p/dJMcahcjbyp/K7OQAMCBN5KU1NVY8ldIMk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ody9p/dJMcahcjbyp/K7OQAMCBN5KU1NVY8ldIMk/img.png&quot; data-alt=&quot;Fig 4-1. Ephemeral Resource와 Write-Only Arguments를 적용해서 Secrets Manager 생성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ody9p/dJMcahcjbyp/K7OQAMCBN5KU1NVY8ldIMk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fody9p%2FdJMcahcjbyp%2FK7OQAMCBN5KU1NVY8ldIMk%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;879&quot; height=&quot;412&quot; data-origin-width=&quot;879&quot; data-origin-height=&quot;412&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Fig 4-1. Ephemeral Resource와 Write-Only Arguments를 적용해서 Secrets Manager 생성&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1278&quot; data-origin-height=&quot;785&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HgKin/dJMcadnpRv9/vlFUE0K0qLV4sd7StmzoJk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HgKin/dJMcadnpRv9/vlFUE0K0qLV4sd7StmzoJk/img.png&quot; data-alt=&quot;Fig 4-2. Ephemeral Resource인 Sops로 복호화한 값이 State&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HgKin/dJMcadnpRv9/vlFUE0K0qLV4sd7StmzoJk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHgKin%2FdJMcadnpRv9%2FvlFUE0K0qLV4sd7StmzoJk%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;1278&quot; height=&quot;785&quot; data-origin-width=&quot;1278&quot; data-origin-height=&quot;785&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Fig 4-2. Ephemeral Resource인 Sops로 복호화한 값이 State&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1492&quot; data-origin-height=&quot;696&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pbrpE/dJMcaiWy0Bc/L2awYwITYOn6tuVfTnKaZ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pbrpE/dJMcaiWy0Bc/L2awYwITYOn6tuVfTnKaZ0/img.png&quot; data-alt=&quot;Fig 4-3. Write-Only Arguments를 적용해서 생성한 AWS Secrets Manager에도 값이 남지 않는 Terraform State&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pbrpE/dJMcaiWy0Bc/L2awYwITYOn6tuVfTnKaZ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpbrpE%2FdJMcaiWy0Bc%2FL2awYwITYOn6tuVfTnKaZ0%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;1492&quot; height=&quot;696&quot; data-origin-width=&quot;1492&quot; data-origin-height=&quot;696&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Fig 4-3. Write-Only Arguments를 적용해서 생성한 AWS Secrets Manager에도 값이 남지 않는 Terraform State&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 &lt;b&gt;Fig 4-2./Fig 4-3.&lt;/b&gt;을 확인해보면 &lt;b&gt;Ephemeral Resource로 임시로 참조한 sops 값은 Fig 3-2.와는 다르게 Terraform State에 남지 않는 것을 확인해볼 수 있습니다&lt;/b&gt;. 그리고 생성된 aws_secretsmanager_secret_version Resource에도 secrets_string_wo 속성과 sercets_string_wo_version 속성이 지정되서 &lt;b&gt;참조한 secrets값이 State에 없이 생성된 것을 확인해볼 수 있습니다&lt;/b&gt;. 실제로 생성된 Resource를 콘솔에서도 확인해보면&lt;b&gt;(Fig 4-4.)&lt;/b&gt;, 값이 잘 들어가서 생성된 것을 확인해 볼 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2318&quot; data-origin-height=&quot;1376&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cfmxpy/dJMcaflgRXu/qzJ62O1hVnhkgs7xY2VDX0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cfmxpy/dJMcaflgRXu/qzJ62O1hVnhkgs7xY2VDX0/img.png&quot; data-alt=&quot;Fig 4-4. Ephemeral Resource와 Write-Only Arguments를 적용한 AWS SecretsManager의 콘솔 값&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cfmxpy/dJMcaflgRXu/qzJ62O1hVnhkgs7xY2VDX0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcfmxpy%2FdJMcaflgRXu%2FqzJ62O1hVnhkgs7xY2VDX0%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;2318&quot; height=&quot;1376&quot; data-origin-width=&quot;2318&quot; data-origin-height=&quot;1376&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Fig 4-4. Ephemeral Resource와 Write-Only Arguments를 적용한 AWS SecretsManager의 콘솔 값&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;이와 같이 Ephemeral Resource와 Write-Only Argumenet가 모두 지원되는 Resource에 대해서는 Terraform State에 Secrets 을 남기지 않고 저장해서 활용할 수 있습니다. &lt;b&gt;여기서 관리 시, 주의할 점은 기존에는 값을 비교해서 변경점을 확인했지만 Write-Only Argumenets를 적용했기 때문에 State에 값이 남지 않아서 비교를 할 수 없습니다. 따라서 Version을 관리해야 하는데, 위의 AWS Secrets Manager의 예시에서는 sercets_string_wo_version 값을 변경할 때마다 올려줘야한다는 점을 주의해야합니다.&lt;/b&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 Systems Manager Parameter Store 도 동일하게 1.11.0 이상 버전 부터 지원하는 것을 확인해 볼 수 있습니다. 여기에도 동일하게 적용해 볼 수 있겠죠?&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1422&quot; data-origin-height=&quot;828&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/01TEg/dJMcabQG816/4L1tEyWm6UWCruYuqDD2M0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/01TEg/dJMcabQG816/4L1tEyWm6UWCruYuqDD2M0/img.png&quot; data-alt=&quot;Fig 5. AWS Systems Manager Parameter Store Terraform Resource&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/01TEg/dJMcabQG816/4L1tEyWm6UWCruYuqDD2M0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F01TEg%2FdJMcabQG816%2F4L1tEyWm6UWCruYuqDD2M0%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;1422&quot; height=&quot;828&quot; data-origin-width=&quot;1422&quot; data-origin-height=&quot;828&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Fig 5. AWS Systems Manager Parameter Store Terraform Resource&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지 Terraform State에 Secrets 을 남기지 않는 방법에 대해 공유해봤습니다.&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;&lt;b&gt;궁금한 부분은 댓글로 남겨주시면 아는 만큼 성심성의껏 답변해 드리도록 하겠습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘 읽으셨다면 많은 공감과 구독 부탁드립니다!&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Reference&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/YoungJinJung/test-provisioning/tree/main/terraform/secretsmanager&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/YoungJinJung/test-provisioning/tree/main/terraform/secretsmanager&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1771390769768&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;test-provisioning/terraform/secretsmanager at main &amp;middot; YoungJinJung/test-provisioning&quot; data-og-description=&quot;Contribute to YoungJinJung/test-provisioning development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/YoungJinJung/test-provisioning/tree/main/terraform/secretsmanager&quot; data-og-url=&quot;https://github.com/YoungJinJung/test-provisioning/tree/main/terraform/secretsmanager&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cRiUoE/dJMb9c9uk5O/mLpKTHBqyL3JZfiGZQ1n7K/img.png?width=1200&amp;amp;height=600&amp;amp;face=986_155_1036_211,https://scrap.kakaocdn.net/dn/dNnZMx/dJMb9gxhO5Q/A4EfkSuYM2ZkE18QfMqTc0/img.png?width=1200&amp;amp;height=600&amp;amp;face=986_155_1036_211&quot;&gt;&lt;a href=&quot;https://github.com/YoungJinJung/test-provisioning/tree/main/terraform/secretsmanager&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/YoungJinJung/test-provisioning/tree/main/terraform/secretsmanager&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cRiUoE/dJMb9c9uk5O/mLpKTHBqyL3JZfiGZQ1n7K/img.png?width=1200&amp;amp;height=600&amp;amp;face=986_155_1036_211,https://scrap.kakaocdn.net/dn/dNnZMx/dJMb9gxhO5Q/A4EfkSuYM2ZkE18QfMqTc0/img.png?width=1200&amp;amp;height=600&amp;amp;face=986_155_1036_211');&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;test-provisioning/terraform/secretsmanager at main &amp;middot; YoungJinJung/test-provisioning&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Contribute to YoungJinJung/test-provisioning development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developer.hashicorp.com/terraform/plugin/framework/ephemeral-resources&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developer.hashicorp.com/terraform/plugin/framework/ephemeral-resources&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1771390761108&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;Ephemeral resources | Terraform | HashiCorp Developer&quot; data-og-description=&quot;Ephemeral resources allow Terraform to reference external data, while guaranteeing that this data will not be persisted in plan or state. Learn how to implement ephemeral resources in the Terraform plugin framework.&quot; data-og-host=&quot;developer.hashicorp.com&quot; data-og-source-url=&quot;https://developer.hashicorp.com/terraform/plugin/framework/ephemeral-resources&quot; data-og-url=&quot;https://developer.hashicorp.com/terraform/plugin/framework/ephemeral-resources&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cIOaVI/dJMb86nTYvY/StoUDCR3KoeSSsOrDeGd4k/img.jpg?width=3200&amp;amp;height=1800&amp;amp;face=0_0_3200_1800,https://scrap.kakaocdn.net/dn/ewkkYq/dJMb87f2Qu3/BtWYcGjy98nfmbIS0aIpe0/img.jpg?width=3200&amp;amp;height=1800&amp;amp;face=0_0_3200_1800&quot;&gt;&lt;a href=&quot;https://developer.hashicorp.com/terraform/plugin/framework/ephemeral-resources&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.hashicorp.com/terraform/plugin/framework/ephemeral-resources&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cIOaVI/dJMb86nTYvY/StoUDCR3KoeSSsOrDeGd4k/img.jpg?width=3200&amp;amp;height=1800&amp;amp;face=0_0_3200_1800,https://scrap.kakaocdn.net/dn/ewkkYq/dJMb87f2Qu3/BtWYcGjy98nfmbIS0aIpe0/img.jpg?width=3200&amp;amp;height=1800&amp;amp;face=0_0_3200_1800');&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;Ephemeral resources | Terraform | HashiCorp Developer&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Ephemeral resources allow Terraform to reference external data, while guaranteeing that this data will not be persisted in plan or state. Learn how to implement ephemeral resources in the Terraform plugin framework.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.hashicorp.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://registry.terraform.io/providers/carlpett/sops/latest/docs&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://registry.terraform.io/providers/carlpett/sops/latest/docs&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1771390783072&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;Terraform Registry&quot; data-og-description=&quot;&quot; data-og-host=&quot;registry.terraform.io&quot; data-og-source-url=&quot;https://registry.terraform.io/providers/carlpett/sops/latest/docs&quot; data-og-url=&quot;https://registry.terraform.io/providers/carlpett/sops/latest/docs&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://registry.terraform.io/providers/carlpett/sops/latest/docs&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://registry.terraform.io/providers/carlpett/sops/latest/docs&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;Terraform Registry&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;registry.terraform.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_version&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_version&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1771390750470&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;Terraform Registry&quot; data-og-description=&quot;&quot; data-og-host=&quot;registry.terraform.io&quot; data-og-source-url=&quot;https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_version&quot; data-og-url=&quot;https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_version&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_version&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_version&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;Terraform Registry&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;registry.terraform.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>Dev&amp;amp;Ops</category>
      <category>AWS</category>
      <category>awscommunitybuilder</category>
      <category>IAC</category>
      <category>SecretsManagement</category>
      <category>Terraform</category>
      <author>zeroneCoder</author>
      <guid isPermaLink="true">https://zerone-code.tistory.com/20</guid>
      <comments>https://zerone-code.tistory.com/20#entry20comment</comments>
      <pubDate>Wed, 18 Feb 2026 13:59:51 +0900</pubDate>
    </item>
    <item>
      <title>Spring Boot와 함께하는 AWS RDS IAM Auth 활용법(2)</title>
      <link>https://zerone-code.tistory.com/19</link>
      <description>&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;&lt;a href=&quot;https://aws.amazon.com/developer/community/community-builders/community-builders-directory/?cb-cards.sort-by=item.additionalFields.cbName&amp;amp;cb-cards.sort-order=asc&amp;amp;awsf.builder-category=cb-type%23cloud-operations&amp;amp;awsf.location=*all&amp;amp;awsf.year=*all&amp;amp;cb-cards.q=youngjin&amp;amp;cb-cards.q_operator=AND&quot;&gt;AWS Community Builder&lt;/a&gt;이자 DevOps Engineer인 &lt;/b&gt;&lt;b&gt;zerone-code입니다.&lt;/b&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;이전 글에서는 RDS에 접근할 때, IAM을 설정하는 방법과 더불어 Lambda를 활용해서 MySQL RDS에 접근하는 방법에 대해 알아봤습니다.&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: #0f141a; text-align: start;&quot;&gt;이번 글에서는&amp;nbsp;&lt;b&gt;Springboot에서 이 방법을 적용한 코드 수준의 적용법&lt;/b&gt;을 알아보도록 하겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;궁금한 부분은 댓글로 남겨주시면 아는 만큼 성심성의껏 답변해 드리도록 하겠습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘 읽으셨다면 많은 공감과 구독 부탁드립니다!&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&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;이전에 다뤘던 IAM Auth를 사용해서 RDS에 접근하는 Flow를 다시 확인하고 시작하도록 하겠습니다.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;gherkin&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot;&gt;&lt;code&gt;                +--------------------+
                |      AWS IAM       |
                |--------------------|
                | rds-db:connect     |
                | STS Token (15min)  |
                +--------------------+
                          ▲
                          |
        (3) Validate Token|
                          |
   +--------------------------------------+
   |           AWS RDS (MySQL/Postgres)  |
   +--------------------------------------+
          ▲                         ▲
          | (2) Auth Token          |
          |                         |
+-------------------+      +-------------------+
| Lambda / EC2 /   |      | Local Developer   |
| ECS Task / App   |      | Environment       |
+-------------------+      +-------------------+
          │
          │ (1) Assume Role / Generate Token
          ▼
   +-------------------+
   | AWS SDK or CLI    |
   +-------------------+
&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;요약 흐름&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;애플리케이션이 IAM Role을 이용해 토큰 발급 요청&lt;/li&gt;
&lt;li&gt;AWS RDS Auth Token 생성 (15분 유효)&lt;/li&gt;
&lt;li&gt;애플리케이션이 이 토큰으로 RDS 로그인&lt;/li&gt;
&lt;li&gt;RDS가 AWS IAM에 토큰 검증 &amp;rarr; OK 시 접속 허용&lt;/li&gt;
&lt;/ol&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;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/YoungJinJung/springboot-sample&quot;&gt;https://github.com/YoungJinJung/springboot-sample&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1766732920054&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - YoungJinJung/springboot-sample&quot; data-og-description=&quot;Contribute to YoungJinJung/springboot-sample development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/YoungJinJung/springboot-sample&quot; data-og-url=&quot;https://github.com/YoungJinJung/springboot-sample&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dlgDG2/hyZPKppiHE/KWA5QfhjwRuZDe5CPHdTEk/img.png?width=1200&amp;amp;height=600&amp;amp;face=986_155_1036_211,https://scrap.kakaocdn.net/dn/7OEZO/hyZPFPa1l6/Vx0MEBDcOVhBQUWoQzFYNk/img.png?width=1200&amp;amp;height=600&amp;amp;face=986_155_1036_211&quot;&gt;&lt;a href=&quot;https://github.com/YoungJinJung/springboot-sample&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/YoungJinJung/springboot-sample&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dlgDG2/hyZPKppiHE/KWA5QfhjwRuZDe5CPHdTEk/img.png?width=1200&amp;amp;height=600&amp;amp;face=986_155_1036_211,https://scrap.kakaocdn.net/dn/7OEZO/hyZPFPa1l6/Vx0MEBDcOVhBQUWoQzFYNk/img.png?width=1200&amp;amp;height=600&amp;amp;face=986_155_1036_211');&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;GitHub - YoungJinJung/springboot-sample&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Contribute to YoungJinJung/springboot-sample development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드는 Writer와 Reader Datasource를 분리해서 적용하는 Multi Datasource를 적용한 코드입니다.&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;library&lt;/b&gt; &lt;b&gt;dependency 설정파일인 build.gradle, application&lt;/b&gt;&amp;nbsp;&lt;b&gt;설정파일인&lt;/b&gt; &lt;b&gt;src/main/resources/application-dev.yml&amp;nbsp;&lt;/b&gt;과 Datasouce를 설정한 main 하위의 &lt;b&gt;configuration/datasource 경로의 Java 파일들&lt;/b&gt;을 자세히 봐주시면 되겠습니다.&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;1️⃣ build.gradle&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-12-26 오후 4.22.08.png&quot; data-origin-width=&quot;1744&quot; data-origin-height=&quot;594&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bp6uxp/dJMcab3SYkN/Wjv5RpVkTIWbBQdpcxhZr0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bp6uxp/dJMcab3SYkN/Wjv5RpVkTIWbBQdpcxhZr0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bp6uxp/dJMcab3SYkN/Wjv5RpVkTIWbBQdpcxhZr0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbp6uxp%2FdJMcab3SYkN%2FWjv5RpVkTIWbBQdpcxhZr0%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;1744&quot; height=&quot;594&quot; data-filename=&quot;스크린샷 2025-12-26 오후 4.22.08.png&quot; data-origin-width=&quot;1744&quot; data-origin-height=&quot;594&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 제일 위에 부분의 aws-advanced-jdbc-wrapper은 aws에서 만든 jdbc connector를 사용하기 위한 library 입니다. 그리고 사용할 DB에 따른 library도 지정해줘야합니다. 샘플 코드에서는 postgesql을 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,0,0&quot;&gt;애플리케이션&lt;/b&gt; &amp;harr; &lt;b data-index-in-node=&quot;9&quot; data-path-to-node=&quot;9,0,0&quot;&gt;AWS Advanced JDBC Wrapper&lt;/b&gt; &amp;harr; &lt;b data-index-in-node=&quot;37&quot; data-path-to-node=&quot;9,0,0&quot;&gt;표준 JDBC 드라이버&lt;/b&gt; &amp;harr; &lt;b data-index-in-node=&quot;52&quot; data-path-to-node=&quot;9,0,0&quot;&gt;AWS RDS/Aurora&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 그 아래 는 각각 IAM Auth를 RDS에 사용하기 위해 필요한 것들입니다. sts를 사용해서 IAM Role로 RDS접근하는 것이기 때문에 세 가지 library가 모두 필요합니다.&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2️⃣&lt;span&gt; application-dev.yml&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-12-26 오후 4.23.33.png&quot; data-origin-width=&quot;1690&quot; data-origin-height=&quot;964&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bKE9Jz/dJMcafkUHv8/EXkV1DjxCbCdExIfwoZkf0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bKE9Jz/dJMcafkUHv8/EXkV1DjxCbCdExIfwoZkf0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bKE9Jz/dJMcafkUHv8/EXkV1DjxCbCdExIfwoZkf0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbKE9Jz%2FdJMcafkUHv8%2FEXkV1DjxCbCdExIfwoZkf0%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;1690&quot; height=&quot;964&quot; data-filename=&quot;스크린샷 2025-12-26 오후 4.23.33.png&quot; data-origin-width=&quot;1690&quot; data-origin-height=&quot;964&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 설정을 보시면 import 부분은 AWS SecretsManager를 통해서 가져올 값을 지정하는 부분입니다. 예제에서는 /secret/sample_dev라는 이름을 가지 SecretsManager리소스를 가져와서 사용하게 됩니다.&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;그리고 그 아래 writer 설정과 reader 설정을 보시면 비슷하지만 약간 다른데요, url과 username이 약간 다릅니다. driver-class-name에는 aws jdbc wrapper를 사용하기 위해 클래스를 지정해주고, 그 아래는 url과 username을 지정하게 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;url의 경우에는 아래와 같은 형태로 지정해주시면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #0f141a; text-align: start;&quot;&gt;jdbc:aws-wrapper:postgresql://&amp;lt;cluster-writer|reader&amp;gt;:&amp;lt;port&amp;gt;/&amp;lt;db&amp;gt;?wrapperPlugins=iam&amp;amp;iamRegion=&amp;lt;region&amp;gt;&amp;amp;sslMode=require&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;3️⃣ Multi datasource configuration&amp;nbsp;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-12-26 오후 4.25.09.png&quot; data-origin-width=&quot;2592&quot; data-origin-height=&quot;816&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDB3ml/dJMcadm2EcY/vmq0egvIjvAHY6rR2IjfN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDB3ml/dJMcadm2EcY/vmq0egvIjvAHY6rR2IjfN0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDB3ml/dJMcadm2EcY/vmq0egvIjvAHY6rR2IjfN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDB3ml%2FdJMcadm2EcY%2Fvmq0egvIjvAHY6rR2IjfN0%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;2592&quot; height=&quot;816&quot; data-filename=&quot;스크린샷 2025-12-26 오후 4.25.09.png&quot; data-origin-width=&quot;2592&quot; data-origin-height=&quot;816&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 위에 Qualifier가 붙은 객체를 보면, 해당 객체는&lt;b&gt; 2번 과정의 application-dev.yml에서 설정했던 writer관련 설정&lt;/b&gt;을 가진 객체입니다. 해당 객체의 값 중&amp;nbsp;&lt;b&gt;url, username&lt;/b&gt;을 가지고 &lt;b&gt;getAuthToken 함수&lt;/b&gt;의 매개변수로 넘겨서 &lt;b&gt;Auth 토큰을 생성하는데 넘겨줍니다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-12-31 오후 10.23.00.png&quot; data-origin-width=&quot;2174&quot; data-origin-height=&quot;1072&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/A1ddX/dJMcajgw0xC/48Ryl85PgtU2GPDZvQLt80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/A1ddX/dJMcajgw0xC/48Ryl85PgtU2GPDZvQLt80/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/A1ddX/dJMcajgw0xC/48Ryl85PgtU2GPDZvQLt80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FA1ddX%2FdJMcajgw0xC%2F48Ryl85PgtU2GPDZvQLt80%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;2174&quot; height=&quot;1072&quot; data-filename=&quot;스크린샷 2025-12-31 오후 10.23.00.png&quot; data-origin-width=&quot;2174&quot; data-origin-height=&quot;1072&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;getAuthToken 함수&lt;/b&gt;를 확인해보면 매개변수로 받은 url을 가지고 먼저 host와 port를 parsing하는 과정을 거칩니다. 이 과정을 거치는 이유는 &lt;b&gt;GenerateAuthenticationTokenRequest&lt;/b&gt;를 보낼 때, &lt;b&gt;parameter&lt;/b&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;username&lt;/b&gt;, 그리고 &lt;b&gt;parsing된 url 정보인 endpoint 배열의 요소&lt;/b&gt;를 각각 설정에 넣고 token을 요청하고 &lt;b&gt;성공적으로 값이 생성되면 이를 반환하고, 아닌 경우에는 excpetion을 출력하는 과정을 거치게 됩니다.&lt;/b&gt;&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;4️⃣&lt;span&gt;&amp;nbsp; 적용 후 Appliation 확인&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3422&quot; data-origin-height=&quot;1390&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KAqTs/dJMcahpxJcC/aMKF4xzmWWZt9sCnI5NzRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KAqTs/dJMcahpxJcC/aMKF4xzmWWZt9sCnI5NzRk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KAqTs/dJMcahpxJcC/aMKF4xzmWWZt9sCnI5NzRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKAqTs%2FdJMcahpxJcC%2FaMKF4xzmWWZt9sCnI5NzRk%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;3422&quot; height=&quot;1390&quot; data-origin-width=&quot;3422&quot; data-origin-height=&quot;1390&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EC2에 Sample용 Application을 구성해서, dev profile로 기동을 해보면 빨간 부분 처럼 Cluster Endpoint 중 writer와 reader의 endpoint에 각각 연결된 것을 확인해 보실 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 AWS RDS IAM Auth를 Springboot 에 적용하는 부분을 코드 수준에서 살펴봤습니다.&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 data-ke-size=&quot;size16&quot;&gt;크게 3가지 부분으로 나눠보면 &lt;b&gt;DB에서 설정해야하는 부분, IAM에서 설정해야하는 부분, SpringBoot App에서 설정해야하는 부분&lt;/b&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;DB에서 설정해야하는 부분&lt;/b&gt;으로는 IAM Role로 제어할 DB용 User를 생성해주는 것이 필요합니다. 이 때 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;&lt;b&gt;IAM에서 설정해야하는 부분&lt;/b&gt;으로는 rds-connect policy로 앞에서 생성한 Aurora Cluster에 해당하는 DB User를 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;b&gt;SpringBoot App에서 설정해야하는 부분&lt;/b&gt;으로는 1️⃣&lt;span&gt; 처럼 &lt;/span&gt;build.gradle에서 library 의존성을 맞춰서 설정해주고 2️⃣ 3️⃣부분에 대한 설정을 적용하려는 환경에 맞춰서 적절히 수정해주시면 됩니다. writer만 사용하는 경우에는 multi datasource가 필요 없겠죠?&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;이렇게 세가지 부분을 설정해서 적용하면 ID/Password기반보다 안전한 Application 보안을 챙길 수 있습니다.&amp;nbsp;막상 해보시면 쉽게 적용할 수 있습니다.(운영까지 적용하는데 3일도 걸리지 않았습니다)&lt;/p&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;niniz&quot; data-emoticon-name=&quot;024&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/024.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/024.gif&quot; width=&quot;150&quot; /&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;&lt;u&gt;&lt;b&gt;기존에 username/password 방식이었던 방식을 이번 기회에 한번 바꿔보시는 건 어떨까요?&lt;/b&gt;&lt;/u&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;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘 읽으셨다면 많은 공감과 구독 부탁드립니다!&lt;/b&gt;&lt;/p&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;b&gt;연말 마지막 글이 되겠네요! 모두들 새해 복 많이 받으시길 바랍니다!&lt;/b&gt;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Reference&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.Connecting.Java.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.Connecting.Java.html&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1766735806525&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;Connecting to your DB instance using IAM authentication and the AWS SDK for Java - Amazon Relational Database Service&quot; data-og-description=&quot;Connecting to your DB instance using IAM authentication and the AWS SDK for Java You can connect to an RDS for MariaDB, MySQL, or PostgreSQL DB instance with the AWS SDK for Java as described following. Prerequisites The following are prerequisites for con&quot; data-og-host=&quot;docs.aws.amazon.com&quot; data-og-source-url=&quot;https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.Connecting.Java.html&quot; data-og-url=&quot;https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.Connecting.Java.html&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.Connecting.Java.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.Connecting.Java.html&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;Connecting to your DB instance using IAM authentication and the AWS SDK for Java - Amazon Relational Database Service&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Connecting to your DB instance using IAM authentication and the AWS SDK for Java You can connect to an RDS for MariaDB, MySQL, or PostgreSQL DB instance with the AWS SDK for Java as described following. Prerequisites The following are prerequisites for con&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.aws.amazon.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;&lt;a href=&quot;https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/java_rds_code_examples.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/java_rds_code_examples.html&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1766735824174&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;Amazon RDS examples using SDK for Java 2.x - AWS SDK for Java 2.x&quot; data-og-description=&quot;Amazon RDS examples using SDK for Java 2.x The following code examples show you how to perform actions and implement common scenarios by using the AWS SDK for Java 2.x with Amazon RDS. Basics are code examples that show you how to perform the essential ope&quot; data-og-host=&quot;docs.aws.amazon.com&quot; data-og-source-url=&quot;https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/java_rds_code_examples.html&quot; data-og-url=&quot;https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/java_rds_code_examples.html&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/java_rds_code_examples.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/java_rds_code_examples.html&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;Amazon RDS examples using SDK for Java 2.x - AWS SDK for Java 2.x&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Amazon RDS examples using SDK for Java 2.x The following code examples show you how to perform actions and implement common scenarios by using the AWS SDK for Java 2.x with Amazon RDS. Basics are code examples that show you how to perform the essential ope&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.aws.amazon.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Dev&amp;amp;Ops</category>
      <category>ApplicaitonSecurity</category>
      <category>AWS</category>
      <category>awscommunitybuilder</category>
      <category>devops</category>
      <category>IAMAuth</category>
      <category>RDS</category>
      <category>springboot</category>
      <author>zeroneCoder</author>
      <guid isPermaLink="true">https://zerone-code.tistory.com/19</guid>
      <comments>https://zerone-code.tistory.com/19#entry19comment</comments>
      <pubDate>Wed, 31 Dec 2025 22:33:47 +0900</pubDate>
    </item>
    <item>
      <title>Spring Boot와 함께하는 AWS RDS IAM Auth 활용법(1)</title>
      <link>https://zerone-code.tistory.com/18</link>
      <description>&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;&lt;a href=&quot;https://aws.amazon.com/developer/community/community-builders/community-builders-directory/?cb-cards.sort-by=item.additionalFields.cbName&amp;amp;cb-cards.sort-order=asc&amp;amp;awsf.builder-category=cb-type%23cloud-operations&amp;amp;awsf.location=*all&amp;amp;awsf.year=*all&amp;amp;cb-cards.q=youngjin&amp;amp;cb-cards.q_operator=AND&quot;&gt;AWS Community Builder&lt;/a&gt;이자 DevOps Engineer인 &lt;/b&gt;&lt;b&gt;zerone-code입니다.&lt;/b&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에서 어떻게 DB에 접근하고 계시나요?&lt;br /&gt;&lt;br /&gt;AWS에서는&lt;b&gt; Password 기반 접근과 IAM 기반 접근, &lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #0f141a; text-align: start;&quot;&gt;&lt;b&gt;Kerberos 기반 접근&lt;/b&gt;을 지원하고 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #0f141a; text-align: start;&quot;&gt;아마 대부분 Password 기반 접근을 사용하실거라고 생각이 되는데요.&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: #0f141a; text-align: start;&quot;&gt;이번 블로그에서는 &lt;b&gt;IAM Role 기반 접근 하는 방식에 대해서 설명&lt;/b&gt;하고, 다음 블로그에서는 &lt;b&gt;Springboot에서 이 방법을 적용한 코드 수준의 적용법&lt;/b&gt;을 알아보도록 하겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;궁금한 부분은 댓글로 남겨주시면 아는 만큼 성심성의껏 답변해 드리도록 하겠습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘 읽으셨다면 많은 공감과 구독 부탁드립니다!&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS를 쓰다 보면 한 번쯤 이런 고민을 해봤을 겁니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;DB 비밀번호를 어디에 저장하지?&amp;rdquo;&lt;br /&gt;&amp;ldquo;Lambda에서 비밀번호 노출 안 되게 관리하려면 어떻게 하지?&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이럴 때 딱 등장하는 게 바로 &lt;b&gt;IAM 기반 인증 (IAM Database Authentication)&lt;/b&gt; 입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1️⃣ IAM Auth란?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단히 말해서 RDS에 접속할 때 비밀번호 대신 IAM Role을 통해 받은 임시 자격 증명을 사용하는 방식입니다.&lt;br /&gt;즉, AWS IAM Role이 &amp;ldquo;DB 로그인 권한 발급기&amp;rdquo; 역할을 하는 거죠.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;✅ 비밀번호를 코드나 환경 변수에 저장할 필요 없음&lt;/li&gt;
&lt;li&gt;✅ 15분짜리 임시 토큰으로 로그인 &amp;rarr; 보안성 강화&lt;/li&gt;
&lt;li&gt;✅ IAM Role 기반 접근 제어 &amp;rarr; 누가, 언제, 어떤 DB에 접속했는지 추적 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style7&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2️⃣ 작동 원리: IAM이 DB 로그인도 대신한다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RDS IAM 인증의 흐름은 다음과 같습니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;[1] IAM 사용자 또는 Role에 RDS 접속 권한 부여
        &amp;darr;
[2] AWS SDK / CLI를 통해 Auth Token 생성 (15분 유효)
        &amp;darr;
[3] 클라이언트가 해당 토큰을 비밀번호처럼 사용해 RDS 접속
        &amp;darr;
[4] RDS는 AWS IAM에 토큰을 검증 요청 &amp;rarr; 유효하면 로그인 성공
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style7&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3️⃣ 기본 설정 절차&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IAM Auth를 활성화하기 위해서는 다음 4단계를 따라가면 됩니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;  1. RDS 인스턴스에서 IAM 인증 활성화&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RDS 콘솔 &amp;rarr; &lt;b&gt;Modify DB instance&lt;/b&gt; &amp;rarr; &lt;b&gt;IAM DB authentication&lt;/b&gt; 옵션을 &lt;b&gt;Enable&lt;/b&gt;로 변경 &amp;rarr; Apply changes.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1996&quot; data-origin-height=&quot;418&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bqyEsk/dJMcabbuZbW/O7Ww61iDqBSdedc4AlQItk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bqyEsk/dJMcabbuZbW/O7Ww61iDqBSdedc4AlQItk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqyEsk/dJMcabbuZbW/O7Ww61iDqBSdedc4AlQItk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbqyEsk%2FdJMcabbuZbW%2FO7Ww61iDqBSdedc4AlQItk%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;1996&quot; height=&quot;418&quot; data-origin-width=&quot;1996&quot; data-origin-height=&quot;418&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;  2. DB 사용자에 IAM 인증 플러그인 설정&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MySQL 기준으로:&lt;/p&gt;
&lt;pre class=&quot;sql&quot; data-ke-language=&quot;sql&quot;&gt;&lt;code&gt;CREATE USER 'testuser'@'%' IDENTIFIED WITH AWSAuthenticationPlugin AS 'RDS';
GRANT ALL PRIVILEGES ON test.* TO 'testuser'@'%';&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;PostgreSQL 기준으로:&lt;/p&gt;
&lt;pre id=&quot;code_1763265191471&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CREATE USER testuser; 
GRANT rds_iam TO testuser;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;  3. IAM 정책 추가&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 클러스터에 설정된 Resource ID를 확인해야 합니다. 해당 Resource ID와 username을 조합으로 IAM policy에 권한을 부여하게 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2080&quot; data-origin-height=&quot;1286&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dAseI0/dJMcaaKqzyY/ucZTu23WPqhHf9XljYIVi0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dAseI0/dJMcaaKqzyY/ucZTu23WPqhHf9XljYIVi0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dAseI0/dJMcaaKqzyY/ucZTu23WPqhHf9XljYIVi0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdAseI0%2FdJMcaaKqzyY%2FucZTu23WPqhHf9XljYIVi0%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;2080&quot; height=&quot;1286&quot; data-origin-width=&quot;2080&quot; data-origin-height=&quot;1286&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;위에서 확인한 Resrouce ID와 username을 조합해서 dbuser 뒤에 추가해줍니다.&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;sql&quot; data-ke-language=&quot;sql&quot;&gt;&lt;code&gt;{
  &quot;Version&quot;: &quot;2012-10-17&quot;,
  &quot;Statement&quot;: [
    {
      &quot;Effect&quot;: &quot;Allow&quot;,
      &quot;Action&quot;: &quot;rds-db:connect&quot;,
      &quot;Resource&quot;: &quot;arn:aws:rds-db:ap-northeast-2:123456789012:dbuser:cluster-DM7O*****6OQ/mydbuser&quot;
    }
  ]
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;  4. Auth Token 생성 및 DB 접근&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CLI를 통해 Token을 발급받아야하는데, generate-db-auth-token은 15분간 유효한 토큰입니다.&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;MySQL 예시:&lt;/p&gt;
&lt;pre class=&quot;shell&quot; data-ke-language=&quot;shell&quot;&gt;&lt;code&gt;RDSHOST=&quot;mysqldb.123456789012.ap-northeast-2.rds.amazonaws.com&quot;
TOKEN=&quot;$(aws rds generate-db-auth-token --hostname $RDSHOST --port 3306 --region ap-northeast-2 --username testuser )&quot;

mysql -h $RDSHOST \
      -P 3306 \
      -u testuser \
      -p $TOKEN \
      --enable-cleartext-plugin&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;PostgeSQL 예시:&lt;/p&gt;
&lt;pre id=&quot;code_1763265973133&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export RDSHOST=&quot;rdspostgres.123456789012.ap-northeast-2.rds.amazonaws.com&quot;
export PGPASSWORD=&quot;$(aws rds generate-db-auth-token --hostname $RDSHOST --port 5432 --region ap-northeast-2 --username testuser )&quot;
                    
psql &quot;host=$RDSHOST port=5432 dbname=DBName user=testuser password=$PGPASSWORD&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style7&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4️⃣ 아키텍처 다이어그램&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 AWS RDS IAM Auth의 전형적인 구성입니다.&lt;/p&gt;
&lt;pre class=&quot;gherkin&quot;&gt;&lt;code&gt;                +--------------------+
                |      AWS IAM       |
                |--------------------|
                | rds-db:connect     |
                | STS Token (15min)  |
                +--------------------+
                          ▲
                          |
        (3) Validate Token|
                          |
   +--------------------------------------+
   |           AWS RDS (MySQL/Postgres)  |
   +--------------------------------------+
          ▲                         ▲
          | (2) Auth Token          |
          |                         |
+-------------------+      +-------------------+
| Lambda / EC2 /   |      | Local Developer   |
| ECS Task / App   |      | Environment       |
+-------------------+      +-------------------+
          │
          │ (1) Assume Role / Generate Token
          ▼
   +-------------------+
   | AWS SDK or CLI    |
   +-------------------+
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;요약 흐름&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;애플리케이션이 IAM Role을 이용해 토큰 발급 요청&lt;/li&gt;
&lt;li&gt;AWS RDS Auth Token 생성 (15분 유효)&lt;/li&gt;
&lt;li&gt;애플리케이션이 이 토큰으로 RDS 로그인&lt;/li&gt;
&lt;li&gt;RDS가 AWS IAM에 토큰 검증 &amp;rarr; OK 시 접속 허용&lt;/li&gt;
&lt;/ol&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style7&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5️⃣ 실제 사용 예시: Lambda &amp;rarr; RDS MySQL&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS Lambda 함수에서 IAM 인증을 활용할 때는 아래처럼 작성합니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;import pymysql
import boto3
import os

rds_host = os.environ['RDS_HOST']
rds_user = os.environ['RDS_USER']
rds_port = 3306
region = 'ap-northeast-2'

# Generate Auth Token
token = boto3.client('rds').generate_db_auth_token(
    DBHostname=rds_host,
    Port=rds_port,
    DBUsername=rds_user,
    Region=region
)

# Connect to RDS
conn = pymysql.connect(
    host=rds_host,
    user=rds_user,
    password=token,
    port=rds_port,
    ssl={'ssl': {}}
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 &lt;b&gt;비밀번호 노출 없이 완전한 IAM 기반 인증 흐름&lt;/b&gt;이 완성됩니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style7&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같은 방식으로 하면 Password를 IAM 기반 인증을 통해서 별도로 관리하지 않아도 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만, 위 방식도 제약사항이 존재하는데요, AWS 공식 문서에는 아래와 같은 제약사항을 두고 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1844&quot; data-origin-height=&quot;1094&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/daz4HT/dJMcag4WTPr/aFwxbEIOh4E1Zczcg5zrbk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/daz4HT/dJMcag4WTPr/aFwxbEIOh4E1Zczcg5zrbk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/daz4HT/dJMcag4WTPr/aFwxbEIOh4E1Zczcg5zrbk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdaz4HT%2FdJMcag4WTPr%2FaFwxbEIOh4E1Zczcg5zrbk%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;1844&quot; height=&quot;1094&quot; data-origin-width=&quot;1844&quot; data-origin-height=&quot;1094&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;저희 팀에서도 요즘 위 방식을 통해서 기존에 Password 기반의 인증방식에서 IAM 인증 방식으로 하나씩 마이그레이션을 하고 있는데요,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 제약사항 중에 걸렸던 부분은 &lt;b&gt;사용자 지정 Route53 DNS 레코드을 사용할 수 없다는 제약사항 외에는&lt;/b&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;다음 블로그에서는 &lt;b&gt;Springboot sample 코드를 통해 RDS IAM Auth를 사용하는 방법&lt;/b&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;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘 읽으셨다면 많은 공감과 구독 부탁드립니다!&lt;/b&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Reference&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.html&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1763266063995&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;MariaDB, MySQL 및 PostgreSQL IAM 데이터베이스 인증 - Amazon Relational Database Service&quot; data-og-description=&quot;MariaDB, MySQL 및 PostgreSQL IAM 데이터베이스 인증 AWS Identity and Access Management(IAM) 데이터베이스 인증을 사용하여 DB 인스턴스에 인증할 수 있습니다. IAM 데이터베이스 인증은 MariaDB, MySQL, PostgreSQL과 함&quot; data-og-host=&quot;docs.aws.amazon.com&quot; data-og-source-url=&quot;https://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.html&quot; data-og-url=&quot;https://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.html&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.html&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;MariaDB, MySQL 및 PostgreSQL IAM 데이터베이스 인증 - Amazon Relational Database Service&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;MariaDB, MySQL 및 PostgreSQL IAM 데이터베이스 인증 AWS Identity and Access Management(IAM) 데이터베이스 인증을 사용하여 DB 인스턴스에 인증할 수 있습니다. IAM 데이터베이스 인증은 MariaDB, MySQL, PostgreSQL과 함&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.aws.amazon.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;&lt;/p&gt;</description>
      <category>Dev&amp;amp;Ops/DevOps</category>
      <author>zeroneCoder</author>
      <guid isPermaLink="true">https://zerone-code.tistory.com/18</guid>
      <comments>https://zerone-code.tistory.com/18#entry18comment</comments>
      <pubDate>Sun, 16 Nov 2025 13:20:00 +0900</pubDate>
    </item>
    <item>
      <title>Terraform CLI 버전 관리 어떻게 하고 있나요?</title>
      <link>https://zerone-code.tistory.com/17</link>
      <description>&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;&lt;a href=&quot;https://aws.amazon.com/developer/community/community-builders/community-builders-directory/?cb-cards.sort-by=item.additionalFields.cbName&amp;amp;cb-cards.sort-order=asc&amp;amp;awsf.builder-category=cb-type%23cloud-operations&amp;amp;awsf.location=*all&amp;amp;awsf.year=*all&amp;amp;cb-cards.q=youngjin&amp;amp;cb-cards.q_operator=AND&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;AWS Community Builder&lt;/a&gt;이자 DevOps Engineer인 &lt;/b&gt;&lt;b&gt;zerone-code입니다.&lt;/b&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;2024년도에 많은 일로 인해서... 블로그 관리를 잘 못했던 저를 반성하며,&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1047&quot; data-origin-height=&quot;271&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7qRl2/btsMUmBaFOi/lIHOryvkvvL56puYKIOPy1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7qRl2/btsMUmBaFOi/lIHOryvkvvL56puYKIOPy1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7qRl2/btsMUmBaFOi/lIHOryvkvvL56puYKIOPy1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7qRl2%2FbtsMUmBaFOi%2FlIHOryvkvvL56puYKIOPy1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1047&quot; height=&quot;271&quot; data-origin-width=&quot;1047&quot; data-origin-height=&quot;271&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘은 Terraform CLI 버전 관리를 하는 쉬운 도구를 소개하려고 합니다.&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;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘 읽으셨다면 많은 공감과 구독 부탁드립니다!&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 DevOps를 시작하면서, Terraform v0.11부터 시작을 했었습니다. 지금은 Terraform 이 v1.12.0-alpha까지 빠르게 발전했는데요,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무래도 현업에서는 특정 버전을 고정해서 쓰기 때문에 Terraform v1.5.7 이상으로는 올리지 않고 쓰고 있었습니다.&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 v1.9.0이상의 최신 버전을 적용하다 보니 Local Setting을 좀 쉽게 할 수 있는 게 없나 하다가 찾게 된 오픈 소스인데요, 바로 tfenv라는 오픈소스입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/tfutils/tfenv&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/tfutils/tfenv&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1742694776946&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - tfutils/tfenv: Terraform version manager&quot; data-og-description=&quot;Terraform version manager. Contribute to tfutils/tfenv development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/tfutils/tfenv&quot; data-og-url=&quot;https://github.com/tfutils/tfenv&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bzcSPK/hyYud0XuXw/TrPUBkkVlyscLoAqN9Jal1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/vzG7X/hyYukTlwU3/uo6r0Zcxu1oDI5UAJW5JKk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/tfutils/tfenv&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/tfutils/tfenv&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bzcSPK/hyYud0XuXw/TrPUBkkVlyscLoAqN9Jal1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/vzG7X/hyYukTlwU3/uo6r0Zcxu1oDI5UAJW5JKk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - tfutils/tfenv: Terraform version manager&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Terraform version manager. Contribute to tfutils/tfenv development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;tfenv는 rbenv에서 영감을 받아 Terraform cli 버전도 동일하게 관리할 수 있지 않을까? 에서 출발해서 만들어진 오픈 소스입니다.&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;여러 버전을 사용할 때, 자바도 sudo alternatives --config java와 같이 java version을 관리하는 것처럼 Terraform cli도 쉽게 관리할 수 있을 것 같습니다.&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;h3 data-ke-size=&quot;size23&quot;&gt;tfenv 설치&lt;/h3&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;Automatic 방식과 Manual 방식 두 가지를 제공하고 있는데요,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Automatic 방식으로는 Mac User들은 brew로 설치를 쉽게 가능하고, yay와 &lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;puppet 모듈을 사용해서 설치를 할 수 있다고 합니다.(아마 잘 안 쓰이지 않나.. 싶은데)&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;1684&quot; data-origin-height=&quot;1018&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HY6qI/btsMSSBvDnU/1Nx2MMr45mSE3wKxdKchF0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HY6qI/btsMSSBvDnU/1Nx2MMr45mSE3wKxdKchF0/img.png&quot; data-alt=&quot;brew install tfenv&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HY6qI/btsMSSBvDnU/1Nx2MMr45mSE3wKxdKchF0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHY6qI%2FbtsMSSBvDnU%2F1Nx2MMr45mSE3wKxdKchF0%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;667&quot; height=&quot;403&quot; data-origin-width=&quot;1684&quot; data-origin-height=&quot;1018&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;brew install tfenv&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Manual 방식으로는 git을 직접 clone 받아서 미리 구성된 shell file을 bin으로 잡아서 동작하도록 만드는 방식입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1742695886059&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#tfenv clone
git clone --depth=1 https://github.com/tfutils/tfenv.git ~/.tfenv

#1 or 2를 선택
#1 tfenv 하위 bin directory를 PATH 환경변수로 설정
echo 'export PATH=&quot;$HOME/.tfenv/bin:$PATH&quot;' &amp;gt;&amp;gt; ~/.zprofile

#2 symbolic link
ln -s ~/.tfenv/bin/* /usr/local/bin&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;위처럼 구성하게 되면, Mac user들은 brew로 설치하지 않고도 tfenv 명령어를 사용할 수 있게 됩니다.&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;tfenv로 terraform cli 버전 관리하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 과정을 통해 설치했다면, 이번엔 terraform cli 버전도 관리해 보도록 하겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1260&quot; data-origin-height=&quot;494&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bPiIwp/btsMSEXBBRd/iddbv4rTioihkmZwCXSkL0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bPiIwp/btsMSEXBBRd/iddbv4rTioihkmZwCXSkL0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bPiIwp/btsMSEXBBRd/iddbv4rTioihkmZwCXSkL0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbPiIwp%2FbtsMSEXBBRd%2Fiddbv4rTioihkmZwCXSkL0%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;561&quot; height=&quot;220&quot; data-origin-width=&quot;1260&quot; data-origin-height=&quot;494&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;tfenv를 한번 입력해 보시면 위와 같이 command list가 나오게 됩니다.&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 cli 버전을 확인하기 위해서는 tfenv list-remote를 실행하면 아래 사진과 같이 설치 가능한 목록이 나오게 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1472&quot; data-origin-height=&quot;1022&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Lb0lN/btsMT4U2oSR/yB2jvEJKkr8nhy3Sv9mPvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Lb0lN/btsMT4U2oSR/yB2jvEJKkr8nhy3Sv9mPvK/img.png&quot; data-alt=&quot;tfenv list-remote&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Lb0lN/btsMT4U2oSR/yB2jvEJKkr8nhy3Sv9mPvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLb0lN%2FbtsMT4U2oSR%2FyB2jvEJKkr8nhy3Sv9mPvK%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;575&quot; height=&quot;399&quot; data-origin-width=&quot;1472&quot; data-origin-height=&quot;1022&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;tfenv list-remote&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 버전을 확인한 후, tfenv install &amp;lt;x.y.x&amp;gt; 형식으로 지정을 해주거나, tfenv install latest와 같은 형태로 명령어를 실행하면 terraform cli가 특정 버전에 맞춰 설치가 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1742696302723&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# TFENV_TERRAFORM_VERSION 혹은 .terraform-version에 지정된 버전으로 설치
# priority : TFENV_TERRAFORM_VERSION &amp;gt; .terraform-version
tfenv install

# terraform 1.9.0 버전을 지정
tfenv install 1.9.0

# terraform 최신 버전
tfenv install latest

# terraform 1.8 버전 중 최신 버전
tfenv install latest:^1.8

# 최신 허용, 최소 필수에 해당하는 terraform cli 설치
tfenv install latest-allowed
tfenv install min-required&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;local 환경에 제일 첫 번째 방법을 통해 1.9.0을 설치해 보도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 TFENV_TERRAFORM_VESION이나. terraform-version을 지정해줘야 합니다. 아래 사진처럼. terraform-version을 지정해 주도록 하겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;716&quot; data-origin-height=&quot;320&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b1ElcW/btsMTLnTrJr/2DrU5HlOm8l6xltOYdnZ1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b1ElcW/btsMTLnTrJr/2DrU5HlOm8l6xltOYdnZ1k/img.png&quot; data-alt=&quot;설치할 버전에 대한 명시&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b1ElcW/btsMTLnTrJr/2DrU5HlOm8l6xltOYdnZ1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb1ElcW%2FbtsMTLnTrJr%2F2DrU5HlOm8l6xltOYdnZ1k%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;183&quot; data-origin-width=&quot;716&quot; data-origin-height=&quot;320&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;설치할 버전에 대한 명시&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 tfenv install을 실행해 보면, 위에서 지정한 대로. terraform-version에 따라 terraform cli가 download 되는 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1654&quot; data-origin-height=&quot;796&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFm6eX/btsMTghBR7f/rz1KkdZDk3GpeLrY6WzcoK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFm6eX/btsMTghBR7f/rz1KkdZDk3GpeLrY6WzcoK/img.png&quot; data-alt=&quot;terraform 1.9.0 설치&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFm6eX/btsMTghBR7f/rz1KkdZDk3GpeLrY6WzcoK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFm6eX%2FbtsMTghBR7f%2Frz1KkdZDk3GpeLrY6WzcoK%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;604&quot; height=&quot;291&quot; data-origin-width=&quot;1654&quot; data-origin-height=&quot;796&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;terraform 1.9.0 설치&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 설치된 terraform v1.9.0을 사용하기 위해서는 tfenv use 1.9.0을 수행해 주면 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1418&quot; data-origin-height=&quot;408&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dZOuvu/btsMTisQTwq/rtI4Z5t89P1cNXCZEVYkI0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dZOuvu/btsMTisQTwq/rtI4Z5t89P1cNXCZEVYkI0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dZOuvu/btsMTisQTwq/rtI4Z5t89P1cNXCZEVYkI0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdZOuvu%2FbtsMTisQTwq%2FrtI4Z5t89P1cNXCZEVYkI0%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;634&quot; height=&quot;182&quot; data-origin-width=&quot;1418&quot; data-origin-height=&quot;408&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번엔 다른 버전도 한번 설치해 보면 latest로 설치하고 버전 전환을 해보도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;그전에 먼저 환경변수를 제거해줘야 합니다. &lt;br /&gt;그렇게 않으면, 새로운 버전을 설치하고 전환을 해도 환경변수가 우선적으로 적용되기 때문에 버전이 전환된 게 제대로 적용되지 않습니다.&lt;/b&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;그리고 latest로 설치를 하게 되면 terraform 1.11.2가 설치됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1372&quot; data-origin-height=&quot;808&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CE3K5/btsMSwFvQ8D/G7QHB1rF5D1O3o9EZZ3POk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CE3K5/btsMSwFvQ8D/G7QHB1rF5D1O3o9EZZ3POk/img.png&quot; data-alt=&quot;tfenv install latest&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CE3K5/btsMSwFvQ8D/G7QHB1rF5D1O3o9EZZ3POk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCE3K5%2FbtsMSwFvQ8D%2FG7QHB1rF5D1O3o9EZZ3POk%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;663&quot; height=&quot;390&quot; data-origin-width=&quot;1372&quot; data-origin-height=&quot;808&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;tfenv install latest&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 설치된 1.9.0에서 1.11.2로 전환을 하면 아래와 같이 tfenv use를 통해 쉽게 전환을 할 수 있게 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1286&quot; data-origin-height=&quot;520&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bXljHe/btsMTCY1yhG/xZ20Qr6GVjtHLsgVuObdg0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bXljHe/btsMTCY1yhG/xZ20Qr6GVjtHLsgVuObdg0/img.png&quot; data-alt=&quot;tfenv use&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bXljHe/btsMTCY1yhG/xZ20Qr6GVjtHLsgVuObdg0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbXljHe%2FbtsMTCY1yhG%2FxZ20Qr6GVjtHLsgVuObdg0%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;507&quot; height=&quot;205&quot; data-origin-width=&quot;1286&quot; data-origin-height=&quot;520&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;tfenv use&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 외에도 DEBUG와 관련된 환경 변수들도 있으니 &lt;b&gt;꼭!!&lt;/b&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;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘 읽으셨다면 많은 공감과 구독 부탁드립니다!&lt;/b&gt;&lt;/p&gt;</description>
      <category>Dev&amp;amp;Ops/DevOps</category>
      <category>AWS</category>
      <category>awscommunitybuilder</category>
      <category>hashicorp</category>
      <category>Terraform</category>
      <author>zeroneCoder</author>
      <guid isPermaLink="true">https://zerone-code.tistory.com/17</guid>
      <comments>https://zerone-code.tistory.com/17#entry17comment</comments>
      <pubDate>Sun, 23 Mar 2025 11:32:35 +0900</pubDate>
    </item>
    <item>
      <title>Nginx Proxy Server가 이상하다!</title>
      <link>https://zerone-code.tistory.com/16</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요!&amp;nbsp;&lt;b&gt;zerone-code입니다.&lt;/b&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;에 관련된 내용을 공유해볼까 합니다.&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 VPC와 Direct Connect를 사용하여 On-premise 환경의 서버와 통신하는 경우가 점차 많아지고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저희 팀에서는 Network용 Account를 별도로 구성하고 여러 팀에서 해당 환경을 사용하여 On-premise환경의 서버와 통신할 수 있도록 지원을 해주고 있습니다.&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 사설 대역으로 인해 On-premise환경과 통신이 제대로 되지 않는 현상을 겪었습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;어떤 현상을 어떤 과정으로 분석했고, 어떻게 해결했는지를 자세하게 공유해보도록 하겠습니다.&lt;/b&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;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘 읽으셨다면 많은 공감과 구독 부탁드립니다!&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. Situation&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같은 구성도로 협업하는 팀의 VPC(오른쪽 VPC들)에 구성된 Service들(EC2, EKS...)에서는 On-premise 환경의 서버를 호출하는 구성입니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;nginx.drawio.png&quot; data-origin-width=&quot;1918&quot; data-origin-height=&quot;422&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dCAmmE/btsH7VQa9Y2/tE8dSWV2w1W94lQVSaxQZk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dCAmmE/btsH7VQa9Y2/tE8dSWV2w1W94lQVSaxQZk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dCAmmE/btsH7VQa9Y2/tE8dSWV2w1W94lQVSaxQZk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdCAmmE%2FbtsH7VQa9Y2%2FtE8dSWV2w1W94lQVSaxQZk%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;978&quot; height=&quot;215&quot; data-filename=&quot;nginx.drawio.png&quot; data-origin-width=&quot;1918&quot; data-origin-height=&quot;422&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;b&gt;10대역의 CIDR&lt;/b&gt;로 구성되있고, &lt;b&gt;On-premise 환경과 통신&lt;/b&gt;을 하기 위해서는 &lt;b&gt;172대역으로 IP를 변경&lt;/b&gt;해야합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 중간에 Network 계정을 구성하고 &lt;b&gt;NLB와 Nginx Proxy Server&lt;/b&gt;를 두어 특정 도메인으로 요청이 들어오는 경우에는 &lt;b&gt;Nginx Proxy Server&lt;/b&gt;&lt;b&gt;의 Proxy 설정&lt;/b&gt;에 따라 &lt;b&gt;지정된 IP로 라우팅&lt;/b&gt;이 되도록 설정해뒀습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(사내에서 사용되는 IDC가 여러개가 있는데, 그 중 Target이 되는 IDC의 Routing 설정상&amp;nbsp; On-premise에서 10대역으로 라우팅을 하면 다른 IDC로 가기 때문에 중간에 172대역으로 변환을 해야합니다.)&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;Nginx로 a.b.c로 호출된 도메인에 대해 다른 172대역의 IP는 다 Routing이 되는데, 172.17대역의 &lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;b&gt;On-premise 서버로 호출이 되지 않는 현상&lt;/b&gt;이 벌어졌습니다.&lt;b&gt; Nginx Proxy 설정도 정상&lt;/b&gt;적이었고,&lt;b&gt; NLB에서 트래픽도 정상&lt;/b&gt;적으로 들어오는 상황이었습니다. 그리고 &lt;b&gt;VPC의 Routing도 Static으로 VGW로 흘러가도록 잡아둔 상태&lt;/b&gt;였는데, 그럼에도 불구하고 &lt;b&gt;요청이 흘러가지 않았습니다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;과연 문제는 뭐였을까요?&lt;/span&gt;&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;b&gt;2. Analysis&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;먼저 확인해 본 것은 &lt;b&gt;Nginx Proxy Server&lt;/b&gt;가 정상적으로 동작하고 있는지를 확인해봤습니다.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;확인을 해보니 아래와 같이 No route to host라는 error.log가 남고 있는 것을 확인할 수 있었습니다.&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;&lt;b&gt;2024/06/20 12:56:51 [error] 30948#0: *1556311 connect() failed (113: No route to host) while connecting to upstream, client: 10.x.x.x, server: &lt;b&gt;&lt;a style=&quot;background-color: #e6f5ff; color: #0070d1;&quot; href=&quot;http://mms-gw.cloud.lguplus.co.kr&quot;&gt;http://a.b.c&lt;/a&gt;&lt;/b&gt;&lt;a href=&quot;http://mms-gw.cloud.lguplus.co.kr,&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;,&lt;/a&gt; request: &quot;POST / HTTP/1.1&quot;, upstream: &quot;http://172.17.xxx.xxx:xxxx/&quot;, host: &quot;&lt;a href=&quot;http://mms-gw.cloud.lguplus.co.kr&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;http://a.b.c&lt;/a&gt;&quot;&lt;/b&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt; &lt;b&gt;Nginx Proxy Server&lt;/b&gt;&lt;/span&gt;의 &lt;b&gt;Proxy 설정&lt;/b&gt;을 확인을 해봤을 떄는 정상적으로 Mapping이 되있는 것을 확인할 수 있었기 때문에 AWS의 설정도 확인을 해봤습니다.&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;b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;두번째로 AWS Private Subnet의 Route table을 확인해봤습니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;VPC Reachability Analyzer에서 Source와 Destination을 지정해주게 되면 경로상 막히는 부분이 없는지를 확인할 수 있습니다. 그래서 &lt;b&gt;Nginx Proxy &lt;b&gt;Server&lt;/b&gt;&lt;/b&gt;로부터 DXGW를 타기 전까지인 VGW까지 정상적으로 트래픽이 도달하는지를 확인해 본 결과 아래와 같이 정상적으로 도달하는 것을 확인할 수 있었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;KakaoTalk_Photo_2024-06-22-12-14-34 001.png&quot; data-origin-width=&quot;1601&quot; data-origin-height=&quot;1658&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btnUMc/btsH8VPFwxd/8zrwPD39qaigb8140890F1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btnUMc/btsH8VPFwxd/8zrwPD39qaigb8140890F1/img.png&quot; data-alt=&quot;VPC Reachability Analyzer&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btnUMc/btsH8VPFwxd/8zrwPD39qaigb8140890F1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbtnUMc%2FbtsH8VPFwxd%2F8zrwPD39qaigb8140890F1%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;605&quot; height=&quot;627&quot; data-filename=&quot;KakaoTalk_Photo_2024-06-22-12-14-34 001.png&quot; data-origin-width=&quot;1601&quot; data-origin-height=&quot;1658&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;VPC Reachability Analyzer&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;인스턴스 외부 즉, Subnet 단위에서는 정상인 것을 확인했기 때문에 Instance 내부에서의 문제로 좁힐 수 있었습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;세번째로 확인한 부분은 traceroute를 통한 routing 확인이었습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;KakaoTalk_Photo_2024-06-22-12-20-10.jpeg&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;61&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zRnEw/btsH7Bri82C/D1HaC6VIt70kZkE2KGoCiK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zRnEw/btsH7Bri82C/D1HaC6VIt70kZkE2KGoCiK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zRnEw/btsH7Bri82C/D1HaC6VIt70kZkE2KGoCiK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzRnEw%2FbtsH7Bri82C%2FD1HaC6VIt70kZkE2KGoCiK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;900&quot; height=&quot;61&quot; data-filename=&quot;KakaoTalk_Photo_2024-06-22-12-20-10.jpeg&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;61&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 그림과 같이 172.31 Private Subnet에 있는 &lt;b&gt;Nginx Proxy&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Server&lt;/b&gt;&lt;/b&gt;로부터 타겟이 되는 172.17 대역으로 traceroute를 해본 결과 정상적으로 나가지 못하는 것을 확인할 수 있었습니다.&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;172.17.0.1&lt;/b&gt;로 가려고 하는 것일까?&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;172.17.0.1&lt;/b&gt; 어디서 많이 본 IP이지 않나요?&amp;nbsp;&lt;br /&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;아마 컨테이너나 &lt;b&gt;Docker&lt;/b&gt;를 좀 많이 만져보신 분이고, 눈치가 빠르신 분은 답을 아실 수 있을 것입니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;Docker를 설치하게 되면 /etc/docker/daemon.json에서 확인하실 수 있는 Docker Bridge Network의 Default Subnet Range입니다.&amp;nbsp; 여기에서 Docker Bridge Network가 설정되는 자세한 과정을 알고 싶으시면 &lt;a href=&quot;https://substack.com/home/post/p-145836197&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;코드 수준에서 분석한 Docker 사설 대역&lt;/a&gt;에 대한 글을 참고해보시면 좋을 것 같습니다.&lt;/span&gt;&lt;/b&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;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;분석을 해보면 &lt;b&gt;Nginx Proxy&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Server&lt;/b&gt;&lt;/b&gt;까지는 정상적으로 도달했으나, Docker를 설치하고 Daemon이 실행되는 과정에서 내부에서 Docker Bridge Network(172.17.0.0/16)로 Iptables를 변경했고, VGW를 통해 172.17대역으로 흘러가야할 트래픽이 Bridge Network로 흘러갔다라는 결론을 내릴 수 있었습니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3. Solution&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해결책으로는 Docker를 해당 환경에 설치하지 않으면 된다는 결론이 났습니다. 따라서 &lt;b&gt;Nginx Proxy&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Server&lt;/b&gt;&lt;/b&gt;를 배포할 때, &lt;b&gt;Ansible에서 Docker을 설치하는 과정&lt;/b&gt;에서 조건문을 추가하는 것으로 선택적으로 Docker를 설치하도록 함으로서 해결할 수 있었습니다.&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;1288&quot; data-origin-height=&quot;636&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/elNXwF/btsH8fOUrZF/Se7sNNK3nYXwkgjDH9ifNk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/elNXwF/btsH8fOUrZF/Se7sNNK3nYXwkgjDH9ifNk/img.png&quot; data-alt=&quot;Ansible 코드&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/elNXwF/btsH8fOUrZF/Se7sNNK3nYXwkgjDH9ifNk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FelNXwF%2FbtsH8fOUrZF%2FSe7sNNK3nYXwkgjDH9ifNk%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;489&quot; height=&quot;241&quot; data-origin-width=&quot;1288&quot; data-origin-height=&quot;636&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Ansible 코드&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Docker를 설치하지 않도록 설정하고 Nginx Proxy Server가 다 뜬 다음 iptables 명령어와 traceroute 명령어로 확인을 해봤습니다. iptables 명령어로 확인해본 결과 Docker가 설치되지 않았기 때문에 iptable이 변경된 부분은 확인할 수 없었습니다. 그리고 traceroute 명령어로 확인해본 결과 172.31대역을 타고 나가서 정상적으로 172.17대역으로 나가는 것을 확인할 수 있었습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1380&quot; data-origin-height=&quot;416&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b4ARNS/btsH8LGsyrI/MGDZL4fVM1gTyiK8sjh2i1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b4ARNS/btsH8LGsyrI/MGDZL4fVM1gTyiK8sjh2i1/img.png&quot; data-alt=&quot;iptables 명령어 실행 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b4ARNS/btsH8LGsyrI/MGDZL4fVM1gTyiK8sjh2i1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb4ARNS%2FbtsH8LGsyrI%2FMGDZL4fVM1gTyiK8sjh2i1%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;558&quot; height=&quot;168&quot; data-origin-width=&quot;1380&quot; data-origin-height=&quot;416&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;iptables 명령어 실행 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-06-22 오후 12.15.27.png&quot; data-origin-width=&quot;1922&quot; data-origin-height=&quot;272&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/znq46/btsH9GjT9ra/KqElWsNROWAbhlUQpX5skK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/znq46/btsH9GjT9ra/KqElWsNROWAbhlUQpX5skK/img.png&quot; data-alt=&quot;172.31 대역의 Target으로 traceroute&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/znq46/btsH9GjT9ra/KqElWsNROWAbhlUQpX5skK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fznq46%2FbtsH9GjT9ra%2FKqElWsNROWAbhlUQpX5skK%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;1922&quot; height=&quot;272&quot; data-filename=&quot;스크린샷 2024-06-22 오후 12.15.27.png&quot; data-origin-width=&quot;1922&quot; data-origin-height=&quot;272&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;172.31 대역의 Target으로 traceroute&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 설정한 이후, 실제 호출되는 10대역의 VPC에서도 172.17대역의 On-premise 서버로 정상적으로 호출되는 것을 확인할 수 있었습니다.&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;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘 읽으셨다면 많은 공감과 구독 부탁드립니다!&lt;/b&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Reference&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;코드 수준에서 분석한 Docker 사설 대역&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://substack.com/home/post/p-145836197?utm_campaign=post&amp;amp;utm_medium=web&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://substack.com/home/post/p-145836197?utm_campaign=post&amp;amp;utm_medium=web&lt;/a&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>Dev&amp;amp;Ops/DevOps</category>
      <category>AWS</category>
      <category>devops</category>
      <category>docker</category>
      <category>NGINX</category>
      <category>proxy</category>
      <category>Troubleshooting</category>
      <author>zeroneCoder</author>
      <guid isPermaLink="true">https://zerone-code.tistory.com/16</guid>
      <comments>https://zerone-code.tistory.com/16#entry16comment</comments>
      <pubDate>Sat, 22 Jun 2024 12:55:35 +0900</pubDate>
    </item>
    <item>
      <title>AWS Summit Seoul 2024 세션 발표 Postmortem</title>
      <link>https://zerone-code.tistory.com/15</link>
      <description>&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;AWS Community Builder이자 DevOps Engineer인 &lt;/b&gt;&lt;b&gt;zerone-code입니다.&lt;/b&gt;&lt;b&gt;&lt;/b&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 Summit Seoul 2023에서 Community Track의&lt;a href=&quot;https://www.youtube.com/watch?v=QJdp2rlADCs&amp;amp;t=24s&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt; Amazon EKS 데이터 전송 비용 절감 및 카오스 엔지니어링 적용 사례&lt;/b&gt;&lt;/a&gt;에서 카오스 엔지니어링 적용사례로 발표를 했었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/QJdp2rlADCs?si=rU0bBri9joxETTai&amp;amp;start=1172&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen&gt;&lt;/iframe&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;br /&gt;이번년도에도&amp;nbsp;&lt;b&gt;AWS Summit Seoul 2024&lt;/b&gt;의 &lt;b&gt;Day 1 &lt;/b&gt;중&lt;b&gt; 통신, 미디어 및 엔터테인먼트 Track&lt;/b&gt;에서 &lt;b&gt;LG Uplus의 BSS 현대화를 위한 클라우드 마이그레이션 여정&lt;/b&gt;라는 주제로 발표를 진행했습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1086&quot; data-origin-height=&quot;840&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bw8S1d/btsHBBdHaoh/HZnIgckmm4YWMSs0L8jSu1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bw8S1d/btsHBBdHaoh/HZnIgckmm4YWMSs0L8jSu1/img.png&quot; data-alt=&quot;https://aws.amazon.com/ko/events/summits/seoul/agenda/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bw8S1d/btsHBBdHaoh/HZnIgckmm4YWMSs0L8jSu1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbw8S1d%2FbtsHBBdHaoh%2FHZnIgckmm4YWMSs0L8jSu1%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;515&quot; height=&quot;398&quot; data-origin-width=&quot;1086&quot; data-origin-height=&quot;840&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://aws.amazon.com/ko/events/summits/seoul/agenda/&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;회고(Postmortem)&lt;/b&gt;를 해보려고 합니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;궁금한 부분은 댓글로 남겨주시면 아는 만큼 성심성의껏 답변해드리도록 하겠습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘 읽으셨다면 많은 공감과 구독 부탁드립니다!&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;준비 과정&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2024년도 3월경, 제가 있는 조직의 리더이신 AWS Container Hero 송주영님에게 이번 Summit에는 어떤 주제로 누가 발표할지에 대해 이야기를 나눴습니다. 이 때는 사실 제가 작년에 Community Track을 했었기 때문에 팀 내 다른 분들도 한번 해보면 좋은 기회라고 생각되서 운을 띄워봤습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러다가 우연치 않게 &quot;영진님은 이번에 Breakout seesion 한번 해볼까?&quot; 라고 하셔서 순간 당황을 했었습니다. 저는 내년이나 내후년 쯤 발표를 한번 해볼까라는 생각을 가지고 있었는데, 이 기회를 놓치면 못할거 같다는 생각도 들었습니다. 그래서 &quot;네, 근데 40분을 저혼자 다하나요?&quot;라고 했더니 BSS 현대화를 오픈하기 위해 많은 기여를 하신 곽효신님과 함께 발표를 할 기회를 만들게 됐습니다.&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의 담당 SA분께 연락이 온 후, 다음의 흐름으로 준비를 하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1차 Deck 제출 &amp;amp; 리뷰 -&amp;gt; 2차 Deck 제출 &amp;amp; 리뷰 -&amp;gt; Dry-Run(실제처럼 연습발표) -&amp;gt; 리허설 -&amp;gt; 본 발표&lt;/b&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;1차 Deck&lt;/b&gt;을 제출할 때는 각 PPT 장표에 어떤 주제로 할지 대략적으로 스케치를 하는 과정이라고 생각하시면 됩니다. 대부분 발표자 분들이 여기에서 제출한 내용을 토대로 발표를 준비하십니다.&amp;nbsp; 저도 동일하게 어떤 내용으로 할지 간단하게 적어서 보낸 후 2차 Deck을 준비했습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1196&quot; data-origin-height=&quot;690&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bS4rbw/btsHBmVvPn8/7XLHbGT1AxQtk0LBTBhRW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bS4rbw/btsHBmVvPn8/7XLHbGT1AxQtk0LBTBhRW1/img.png&quot; data-alt=&quot;Abstract&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bS4rbw/btsHBmVvPn8/7XLHbGT1AxQtk0LBTBhRW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbS4rbw%2FbtsHBmVvPn8%2F7XLHbGT1AxQtk0LBTBhRW1%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;541&quot; height=&quot;312&quot; data-origin-width=&quot;1196&quot; data-origin-height=&quot;690&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Abstract&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2차 Deck&lt;/b&gt;은 1차 Deck과 대략 2주정도 기간을 두고 준비하게 됩니다. 이 때는 발표에서 어떤 걸 말하고 싶은지 명확하게 적으셔서 제출하셔야 합니다. 저는 말하고 싶은 내용을 크게 2가지 꼭지점을 잡고 준비를 했습니다. 현재 하고 있는 일을 앞에 내용과 어떻게 연결할 것인지, 그리고 현재 하고 있는 일 이후에는 어떻게 할 것인지 이런 식으로 큰 주제를 잡고 준비를 했고, Top-Down 방식으로 설명을 준비했습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1180&quot; data-origin-height=&quot;674&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blfzU7/btsHDcjjq9R/C8Px0L94P20KbZ8KfaiLKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blfzU7/btsHDcjjq9R/C8Px0L94P20KbZ8KfaiLKK/img.png&quot; data-alt=&quot;탑-다운 방식으로 설명하기 위한 Keyword&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blfzU7/btsHDcjjq9R/C8Px0L94P20KbZ8KfaiLKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblfzU7%2FbtsHDcjjq9R%2FC8Px0L94P20KbZ8KfaiLKK%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;505&quot; height=&quot;288&quot; data-origin-width=&quot;1180&quot; data-origin-height=&quot;674&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;탑-다운 방식으로 설명하기 위한 Keyword&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;b&gt;Dry-Run&lt;/b&gt;은&amp;nbsp;&lt;/span&gt;2차 Deck제출 이후 2일 정도 후에 진행했습니다. Dry-Run 때는 시간 측정과 더불어 영상촬영도 같이 진행되기 이 부분까지 생각하셔서 준비하셔야 합니다. 이 때는 내가 준비한 자료가 어느 정도 시간이 나오는지 측정한다고 생각하면 됩니다. 개인적으로는 딱 맞으면 좋긴 하겠지만 한번에 딱 맞기는 힘들기 때문에 좀 많이 담고 줄이는 것이 좋다고 생각됩니다.(내용을 늘이는건 정말 어려워요.)&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;이렇게 Dry-Run까지하면 대략적인 발표 준비를 마쳤기 때문에 리허설을 기다리게 됩니다. 그 과정에서 발표할 내용을 크게 바꿀 순 없지만 전하고자 하는 내용은 계속 다듬어야 합니다.&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;b&gt;리허설&lt;/b&gt;&lt;/h3&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;2023년도 AWS Community Day 때도 스크립트를 다 준비해 갔지만 결과적으로는 문어체로 말하는게 정말 어렵다는 것을 느끼고, 구어체로 좀 더 쉽게 풀어서 설명하자 라는 마인드로 스크립트의 키워드만 떠올려서 진행을 했었습니다. 이번에는 PPT 자체에 키워드를 넣었기 때문에 별 무리 없을 것이라고 생각됐지만 실제 해보니까 긴장이 많이 됐습니다. 아무래도 회사의 이름을 걸고 발표를 한다고 생각하니까 문어체로 말을 해야할 것 같고, 청중들이 전부 같은 분야의 경험, 지식을 가진 분들이 아니기 때문에 쉽게 설명하는 것을 포함해야 했습니다.&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;2가지&lt;/b&gt; 정도였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 현장의 좌석을 보면 분위기에 살짝 압도를 당하기 때문에 안하던 긴장감도 찾아옵니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 청중들에게 보이는 PPT는 단상 아래의 스크린에 있기 때문에 시선처리까지 신경쓰면서 해야하기 때문에 생각할 부분이 많았습니다.&lt;/b&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;리허설이 끝난 이후, 저는 부랴부랴 말이 잘 안나오는 부분에 대해 스크립트를 대략적으로 적기 시작했습니다. 이미 머릿속에는 있었기 때문에 15-20분안에 작성해서 다시 PPT를 전달해드렸습니다.&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;b&gt;발표 당일&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리허설 때의 긴장감과 내가 준비가 잘 됐는가에 대한 스스로 질문을 계속 하면서 AWS Summit 행사장까지 갔습니다. 오후 1시 10분 발표다보니 근처 카페에서 계속 되뇌었습니다. 오후 1시 10분 발표였는데, 막상 발표가 시작되니까 긴장감이 싹 사라지는 기분이었습니다. 역시 실전을 한 두번 해보니까 크게 긴장은 되지 않았고 리허설 때보다 오히려 더 천천히 말하고, 명확히 제가 말하고자 하는 부분을 잘 전달했던 것 같습니다.&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-filename=&quot;KakaoTalk_Photo_2024-05-25-12-36-52.png&quot; data-origin-width=&quot;2250&quot; data-origin-height=&quot;2192&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bteHaq/btsHBViAj29/DgPSchLCVArYGTn7rzWpK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bteHaq/btsHBViAj29/DgPSchLCVArYGTn7rzWpK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bteHaq/btsHBViAj29/DgPSchLCVArYGTn7rzWpK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbteHaq%2FbtsHBViAj29%2FDgPSchLCVArYGTn7rzWpK0%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;405&quot; height=&quot;395&quot; data-filename=&quot;KakaoTalk_Photo_2024-05-25-12-36-52.png&quot; data-origin-width=&quot;2250&quot; data-origin-height=&quot;2192&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;

            &lt;figure class=&quot;unsupported component-kakaotv&quot; contenteditable=&quot;false&quot; style=&quot;background:#000;margin:16px 0;min-height:72px;padding:10px 16px;display:flex;align-items:center;justify-content:center;text-align:center;box-sizing:border-box;width:100%;max-width:100%;&quot;&gt;
                &lt;p contenteditable=&quot;false&quot; style=&quot;margin:0;color:#8a8a8a;font-size:13px;line-height:1.6;user-select:none;pointer-events:none;&quot;&gt;동영상 서비스가 종료되어 해당 콘텐츠를 재생할 수 없습니다.&lt;/p&gt;
            &lt;/figure&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;b&gt;발표 이후&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;발표 이후에는 Expo를 돌아다니면서 발표를 잘들었다는 말도 들었고, 타 회사에 가있는 대학교 동기도 제 발표를 듣고 연락이 오기도 했습니다. AWS Summit에서 Keynote와 미니세션을 제외하고는 다했다는 생각이 들었습니다. 그리고 다음 목표도 생겨났습니다.&lt;/p&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;'AWS 해외 Summit 혹은 Community Day에서 영어로 발표해보기'&lt;/b&gt;&lt;/h3&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;마무리&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 AWS Summit Seoul 2024에 발표한 세션들은 7월쯤에 발표 영상이 유튜브에 공개될 예정입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내용이 궁금하신 분들은 &lt;a href=&quot;https://www.youtube.com/@AWSKorea&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.youtube.com/@AWSKorea&lt;/a&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;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘 읽으셨다면 많은 공감과 구독 부탁드립니다!&lt;/b&gt;&lt;/p&gt;</description>
      <category>Dev&amp;amp;Ops/Postmortem</category>
      <category>AWS</category>
      <category>awscommunitybuilder</category>
      <category>awssummitsecoul</category>
      <category>telecommunication</category>
      <author>zeroneCoder</author>
      <guid isPermaLink="true">https://zerone-code.tistory.com/15</guid>
      <comments>https://zerone-code.tistory.com/15#entry15comment</comments>
      <pubDate>Sat, 25 May 2024 18:13:53 +0900</pubDate>
    </item>
    <item>
      <title>Karpenter와 Empty Pod을 활용한 스케일링(2)</title>
      <link>https://zerone-code.tistory.com/14</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;917&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VuCAs/btsy05tFOyo/KwdgzUlov5KOS0jVHPqPI0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VuCAs/btsy05tFOyo/KwdgzUlov5KOS0jVHPqPI0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VuCAs/btsy05tFOyo/KwdgzUlov5KOS0jVHPqPI0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVuCAs%2Fbtsy05tFOyo%2FKwdgzUlov5KOS0jVHPqPI0%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;1400&quot; height=&quot;917&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;917&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;b&gt;안녕하세요!&amp;nbsp;&lt;b&gt;zerone-code입니다.&lt;/b&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;지난&lt;a href=&quot;https://zerone-code.tistory.com/13&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Karpenter와 Empty Pod을 활용한 스케일링(1)&lt;/a&gt;에 이어&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;쿠버네티스에서 제공하는 PriorityClass와 빈 파드(Empty Pod), 그리고&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;카펜터(Karpenter)를 활용한 오버프로비저닝(Overprovisioning)&lt;/b&gt;에 대해 공유하고자 합니다. 이번 글에서는 PriorityClass와 빈 파드를 중점적으로 다루고 카펜터가 어떻게 활용되는지 알아보도록 하겠습니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;궁금한 부분은 댓글로 남겨주시면 아는 만큼 성심성의껏 답변해 드리도록 하겠습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘 읽으셨다면 많은 공감과 구독 부탁드립니다!&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h1 id=&quot;3f33&quot; style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot;&gt;오버프로비저닝이란?&lt;/h1&gt;
&lt;p id=&quot;5cda&quot; style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;먼저 그림들을 통해 오버프로비저닝이 어떤 개념인지 알아보도록 하겠습니다.&lt;/p&gt;
&lt;p id=&quot;2b1b&quot; style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;보통 EKS 환경에서 사용자 요청이 늘어나 CPU나 메모리 사용률이 올라가면, HPA(Horizontal Pod Autoscaling)가 파드를 증설합니다. (그림 1) 이때 기존에 존재하는 노드 중 증설되는 파드에 할당해야 할 CPU 혹은 메모리가 부족하다면 파드는 노드에 할당되지 못하고 대기 상태로 노드가 생성될 때까지 기다리게 됩니다. 그리고 어느 정도 시간이 지나면 노드가 프로비저닝 됩니다. 노드가 정상적으로 준비되면, 쿠버네티스 스케줄러는 파드를 새롭게 생성된 노드에 할당합니다. HPA에 의해 증설된 파드는 이 때가 돼서야 비로소 요청을 처리할 수 있습니다. 이렇게 새로운 노드에 증설되는 파드가 정상 동작할 때까지 기다리는 과정에서 갑작스럽게 많은 요청이 들어오게 되는 경우, 기존에 버티고 있던 파드들이 요청을 제대로 소화하지 못해 500 에러가 발생하거나 OOM으로 파드가 죽을수도 있습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;403&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cYWFiO/btsy357Ko0J/yg4IHzZSn9RT54yJaShm90/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cYWFiO/btsy357Ko0J/yg4IHzZSn9RT54yJaShm90/img.png&quot; data-alt=&quot;그림 1. 오버프로비저닝이 적용되지 않은 경우&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cYWFiO/btsy357Ko0J/yg4IHzZSn9RT54yJaShm90/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcYWFiO%2Fbtsy357Ko0J%2Fyg4IHzZSn9RT54yJaShm90%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;700&quot; height=&quot;202&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;403&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림 1. 오버프로비저닝이 적용되지 않은 경우&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p id=&quot;f154&quot; style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;만약 요청이 많이 들어오기 전에 필요한 노드 수보다 더 많이 노드를 생성해 놓았다면 어떻게 될까요?&lt;/p&gt;
&lt;p id=&quot;e5b6&quot; style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;사용자로부터 요청이 많지 않은 경우, 아무런 동작은 하지 않지만, CPU와 메모리가 할당되어야 하는 파드가 몇 개의 노드에 할당되었다고 가정해보겠습니다. 이 상황에서 갑작스럽게 많이 요청이 들어오는 경우, HPA를 통해 증설되는 파드가 그림 1에서 기존에 아무런 동작은 하지 않지만 자원을 점유하고 있는 파드 덕분에 여유분의 노드가 생성되어 있어 해당 노드에 바로 할당이 가능합니다. 이처럼 서비스의 안정성을 위해 필요한 노드 수보다 더 많은 노드를 생성해서 증설되는 파드가 빠르게 할당될 수 있도록 하는 것을&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;오버프로비저닝(Overprovisioning)&lt;/b&gt;이라고 합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;431&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cO7Llw/btsy3htLgN3/TEuV3KlMwBDDCkK8CGgLrk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cO7Llw/btsy3htLgN3/TEuV3KlMwBDDCkK8CGgLrk/img.png&quot; data-alt=&quot;그림 2. 오버프로비저닝이 적용된 경우&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cO7Llw/btsy3htLgN3/TEuV3KlMwBDDCkK8CGgLrk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcO7Llw%2Fbtsy3htLgN3%2FTEuV3KlMwBDDCkK8CGgLrk%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;700&quot; height=&quot;216&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;431&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림 2. 오버프로비저닝이 적용된 경우&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h1 id=&quot;d681&quot; style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot;&gt;PriorityClass와 빈 파드&lt;/h1&gt;
&lt;p id=&quot;8a98&quot; style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;오버프로비저닝에서는 파드의 우선순위를 결정하는 요소인&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/&quot;&gt;PriorityClass&lt;/a&gt;와 PriorityClass가 적용된 빈 파드가 필요합니다.&lt;/p&gt;
&lt;p id=&quot;6c14&quot; style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;워커 노드에 CPU나 메모리가 충분하지 않거나, 사용하려는 포트를 이미 실행 중인 다른 파드가 점유 중인 경우에는 새로운 파드를 배포하지 못하는 상황이 발생할 수 있습니다. 하지만, 새롭게 생성할 파드가 매우 중요한 역할을 하는 애플리케이션이라면, 이러한 제약조건에도 불구하고 반드시 배포되어야 합니다. 이런 상황을 해결하기 위해 사용할 수 있는 것이 바로 PriorityClass입니다.&lt;/p&gt;
&lt;p id=&quot;da61&quot; style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;EKS 클러스터를 제일 처음 생성하고, priorityClass를 조회해 보면 기본적으로&lt;span&gt;&amp;nbsp;&lt;/span&gt;system-cluster-critical과&lt;span&gt;&amp;nbsp;&lt;/span&gt;system-node-critical이라는 2개의 PriorityClass가 높은 value를 가지고 생성되어 있는 것을 확인할 수 있습니다. 이 ProrityClass는 시스템에서 중요한 파드들에 적용되어 높은 우선순위를 가지도록 해줍니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;227&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d5RFhf/btsy2q5IPhX/KBfVr34WHDKy6qkvtRy1U1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d5RFhf/btsy2q5IPhX/KBfVr34WHDKy6qkvtRy1U1/img.png&quot; data-alt=&quot;그림 3. EKS Default PriorityClass(system-cluster-critical, system-node-critical)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d5RFhf/btsy2q5IPhX/KBfVr34WHDKy6qkvtRy1U1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd5RFhf%2Fbtsy2q5IPhX%2FKBfVr34WHDKy6qkvtRy1U1%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;700&quot; height=&quot;114&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;227&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림 3. EKS Default PriorityClass(system-cluster-critical, system-node-critical)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p id=&quot;4a19&quot; style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;시스템에서 제공하는 PriorityClass 외에 사용자가 PriorityClass를 생성하여 원하는 파드에 지정할 수 있습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1390&quot; data-origin-height=&quot;500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SoTpG/btsyX0Gveb6/7HAXHvX7KGchBr3yKVExk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SoTpG/btsyX0Gveb6/7HAXHvX7KGchBr3yKVExk1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SoTpG/btsyX0Gveb6/7HAXHvX7KGchBr3yKVExk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSoTpG%2FbtsyX0Gveb6%2F7HAXHvX7KGchBr3yKVExk1%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;700&quot; height=&quot;252&quot; data-origin-width=&quot;1390&quot; data-origin-height=&quot;500&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p id=&quot;2817&quot; style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;위의 YAML 설정파일을 보면 value에 지정된 값에 따라서 파드에 우선순위를 설정할 수 있습니다. 새로 배포되어야 하는 파드의 우선 순위가 높은데 리소스 부족 등 다양한 이슈로 배포할 수 없다면 해당 파드보다 낮은 우선순위를 가지고 있는 파드를 기존의 노드에서&lt;b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;축출(Eviction)&lt;/b&gt;하고&lt;b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;우선 순위가 높은 새로운 파드가 배포됩니다. 이러한 동작 원리를 이용하면, 우선순위가 낮은 빈 파드를 만들어 CPU와 메모리만 점유하도록 설정하면, 우선순위가 높은 서비스 파드가 들어왔을 때 밀어내도록 만들 수 있습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;858&quot; data-origin-height=&quot;168&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cgICdx/btsy4nmKH0i/cF1eNSWGn3xAD7mDFIZwU0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cgICdx/btsy4nmKH0i/cF1eNSWGn3xAD7mDFIZwU0/img.png&quot; data-alt=&quot;그림 4. 별도의 PriorityClass가 적용되지 않은 파드&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cgICdx/btsy4nmKH0i/cF1eNSWGn3xAD7mDFIZwU0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcgICdx%2Fbtsy4nmKH0i%2FcF1eNSWGn3xAD7mDFIZwU0%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;700&quot; height=&quot;138&quot; data-origin-width=&quot;858&quot; data-origin-height=&quot;168&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림 4. 별도의 PriorityClass가 적용되지 않은 파드&lt;/figcaption&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;h1 id=&quot;b892&quot; style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot;&gt;카펜터를 활용한 오버프로비저닝&lt;/h1&gt;
&lt;p id=&quot;2831&quot; style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;이제 위에서 설명한 PriorityClass와 빈 파드, 그리고 카펜터를 활용해서 어떻게 오버프로비저닝을 적용하는지 그림 5를 통해 순서대로 알아보도록 하겠습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;636&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xBaHX/btsy7i6jtN1/Dz36lk8MzoSLEU0nveRY80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xBaHX/btsy7i6jtN1/Dz36lk8MzoSLEU0nveRY80/img.png&quot; data-alt=&quot;그림 5. 카펜터를 통한 오버프로비저닝 동작 과정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xBaHX/btsy7i6jtN1/Dz36lk8MzoSLEU0nveRY80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxBaHX%2Fbtsy7i6jtN1%2FDz36lk8MzoSLEU0nveRY80%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;700&quot; height=&quot;318&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;636&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림 5. 카펜터를 통한 오버프로비저닝 동작 과정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li id=&quot;e096&quot; style=&quot;list-style-type: decimal; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;1번 노드에는 높은 우선순위를 가진 파드(Nginx-1)가 할당돼 있고 2번 노드에는 낮은 우선순위를 가진 파드(빈 파드)가 할당돼 있습니다.&lt;/li&gt;
&lt;li id=&quot;a496&quot; style=&quot;list-style-type: decimal; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;높은 우선순위를 가진 파드(Nginx-2)를 할당할 노드가 없습니다.&lt;/li&gt;
&lt;li id=&quot;763f&quot; style=&quot;list-style-type: decimal; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;낮은 우선순위를 가진 파드(빈 파드)는 축출됩니다.&lt;/li&gt;
&lt;li id=&quot;446c&quot; style=&quot;list-style-type: decimal; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;높은 우선순위를 가진 파드(Ningx-2)는 낮은 우선순위를 가진 파드가 있던 2번 노드에 할당됩니다.&lt;/li&gt;
&lt;li id=&quot;e4e4&quot; style=&quot;list-style-type: decimal; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;카펜터는 낮은 우선순위를 가진 파드(빈 파드)를 할당하기 위해 새로운 노드를 증설합니다.&lt;/li&gt;
&lt;li id=&quot;f52e&quot; style=&quot;list-style-type: decimal; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;새롭게 증설된 노드에 낮은 우선순위를 가진 파드(빈 파드)가 할당됩니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p id=&quot;c07e&quot; style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;위의 과정을 실제 EKS 환경에서 적용한 예를 한번 살펴보도록 하겠습니다.&lt;/p&gt;
&lt;p id=&quot;3160&quot; style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;그림 6를 보면 12대의 워커 노드가 있는 클러스터가 있습니다. 이 워커 노드들에는 aws-node나 kube-proxy, argoCD와 같은 여러 파드들이 떠 있습니다. 여기에 그림 7과 같이 other라는 네임스페이스를 생성하고 Priority가 -1인 PriorityClass를 빈 파드에 적용했습니다. 빈 파드는&lt;span&gt;&amp;nbsp;&lt;/span&gt;10.102.108.161이라는 주소를 가진 노드에 할당된 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;584&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9te2b/btsy4i0dbsh/NW9t92tr0IvHpuzkJygXs0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9te2b/btsy4i0dbsh/NW9t92tr0IvHpuzkJygXs0/img.png&quot; data-alt=&quot;그림 6. EKS에 구성된 노드들&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9te2b/btsy4i0dbsh/NW9t92tr0IvHpuzkJygXs0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9te2b%2Fbtsy4i0dbsh%2FNW9t92tr0IvHpuzkJygXs0%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;700&quot; height=&quot;292&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;584&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림 6. EKS에 구성된 노드들&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;260&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FfEhr/btsy36yNFIF/ceyHANbElRfOUSc2mA41O0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FfEhr/btsy36yNFIF/ceyHANbElRfOUSc2mA41O0/img.png&quot; data-alt=&quot;그림 7. PriorityClass가 적용된 빈 파드&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FfEhr/btsy36yNFIF/ceyHANbElRfOUSc2mA41O0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFfEhr%2Fbtsy36yNFIF%2FceyHANbElRfOUSc2mA41O0%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;700&quot; height=&quot;130&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;260&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림 7. PriorityClass가 적용된 빈 파드&lt;/figcaption&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 id=&quot;34dc&quot; style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;그 다음 서비스 파드를 가정하기 위해 별도의 PriorityClass가 적용되지 않은 nginx 파드를 같은 클러스터에 배포해 줍니다. 그림 8에서 볼 수 있듯이 nginx 파드들이 할당될 자원이 충분하기 때문에 빈 파드가 바로 축출되지 않고, nginx도 정상적으로 배포되는 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;p id=&quot;2650&quot; style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;이 상황에서 nginx 파드에 부하를 줘서 새로운 파드가 증설되도록 합니다. 새롭게 증설되어야 할 파드에 할당될 CPU나 메모리가 부족하기 때문에 우선순위가 낮은 빈 파드를 축출시키고 해당 노드에 할당되게 됩니다. 그리고 빈 파드는 대기 상태가 되기 때문에 카펜터는 이를 감지해서 새로운 노드를 증설하게 되고 그림 10와 같이&lt;span&gt;&amp;nbsp;&lt;/span&gt;10.102.111로 시작되는 주소를 가진 노드에 새롭게 할당된 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;227&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cBd19i/btsyUIGd1bw/SsulVZwRS4k5JfCk8U2Vy1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cBd19i/btsyUIGd1bw/SsulVZwRS4k5JfCk8U2Vy1/img.png&quot; data-alt=&quot;그림 8. 서비스용 nginx 파드&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cBd19i/btsyUIGd1bw/SsulVZwRS4k5JfCk8U2Vy1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcBd19i%2FbtsyUIGd1bw%2FSsulVZwRS4k5JfCk8U2Vy1%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;700&quot; height=&quot;114&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;227&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림 8. 서비스용 nginx 파드&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;140&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dzEbiS/btsyWhn8lAt/L110A46eLH64JMqouHQBf0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dzEbiS/btsyWhn8lAt/L110A46eLH64JMqouHQBf0/img.png&quot; data-alt=&quot;그림 9. 새로운 노드에 뜨고 있는 빈 파드&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dzEbiS/btsyWhn8lAt/L110A46eLH64JMqouHQBf0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdzEbiS%2FbtsyWhn8lAt%2FL110A46eLH64JMqouHQBf0%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;700&quot; height=&quot;71&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;140&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림 9. 새로운 노드에 뜨고 있는 빈 파드&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;538&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2k5Iz/btsy03WUwEH/KOI8lUd6M9iWyCQy2Bu2T0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2k5Iz/btsy03WUwEH/KOI8lUd6M9iWyCQy2Bu2T0/img.png&quot; data-alt=&quot;그림 10. 새로운 노드에 정상적으로 할당된 빈 파드&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2k5Iz/btsy03WUwEH/KOI8lUd6M9iWyCQy2Bu2T0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2k5Iz%2Fbtsy03WUwEH%2FKOI8lUd6M9iWyCQy2Bu2T0%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;700&quot; height=&quot;269&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;538&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림 10. 새로운 노드에 정상적으로 할당된 빈 파드&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
      <category>Dev&amp;amp;Ops/DevOps</category>
      <category>AWS</category>
      <category>devops</category>
      <category>Karpenter</category>
      <category>kubernetes</category>
      <author>zeroneCoder</author>
      <guid isPermaLink="true">https://zerone-code.tistory.com/14</guid>
      <comments>https://zerone-code.tistory.com/14#entry14comment</comments>
      <pubDate>Tue, 24 Oct 2023 11:22:58 +0900</pubDate>
    </item>
    <item>
      <title>[Infra] Karpenter와 Empty Pod을 활용한 스케일링(1)</title>
      <link>https://zerone-code.tistory.com/13</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;요즘에 Microservices Architecture(이하 MSA)와 쿠버네티스(Kubernetes)에 대한 관심이 많아지고 AWS를 사용하는 많은 회사에서&lt;b&gt; 온프레미스 혹은 EC2, ECS 환경&lt;/b&gt;에서 Elastic Kubernetes Services(이하 EKS)로 많이 옮기고 있는 추세입니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;230&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;79cafe75-043e-4e98-9569-fbc7a6867884&quot;&gt;EKS 환경에서 보다 안정적인 서비스를 &lt;/span&gt;&lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;000c8438-8a90-4264-adb9-fa5e05ba42f0&quot;&gt;&lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;79cafe75-043e-4e98-9569-fbc7a6867884&quot;&gt;제공하기 위해서는&lt;/span&gt;&lt;/span&gt;&lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;79cafe75-043e-4e98-9569-fbc7a6867884&quot;&gt; 빠르게 &lt;/span&gt;&lt;b&gt;&lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;9e4bae2f-c8f5-4f38-bd49-d95581e0a4ba&quot;&gt;&lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;79cafe75-043e-4e98-9569-fbc7a6867884&quot;&gt;파드 프로비저닝(pod provisioning)&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;79cafe75-043e-4e98-9569-fbc7a6867884&quot;&gt;이 필요하고, 파드(Pod)가 많이 생기게 되면 &lt;/span&gt;&lt;b&gt;&lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;79cafe75-043e-4e98-9569-fbc7a6867884&quot;&gt;노드 프로비저닝(node provisioning)&lt;/span&gt;&lt;/b&gt;&lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;79cafe75-043e-4e98-9569-fbc7a6867884&quot;&gt;이 필요하게 됩니다.&lt;/span&gt; 그러나 &lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;fd5d8f75-8415-4640-86c3-30606818fb1e&quot;&gt;필요한 만큼 빠르게&lt;/span&gt; 파드 및 &lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;79cafe75-043e-4e98-9569-fbc7a6867884&quot;&gt;노드 프로비저닝&lt;/span&gt;으로 서비스의 안정성을 확보하고, 동시에 비용 효율적으로 조정하는 것은 쉽지 않습니다.&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-layout=&quot;center&quot; data-node-type=&quot;mediaSingle&quot;&gt;
&lt;div&gt;
&lt;div data-context-id=&quot;37801105721&quot; data-type=&quot;file&quot; data-node-type=&quot;media&quot; data-width=&quot;274&quot; data-height=&quot;184&quot; data-id=&quot;3eed2a3b-5170-46bd-b9a4-9cfaa37b2c1f&quot; data-collection=&quot;contentId-37801105721&quot; data-file-name=&quot;image-20230616-082451.png&quot; data-file-size=&quot;58798&quot; data-file-mime-type=&quot;image/png&quot; data-alt=&quot;&quot;&gt;
&lt;div id=&quot;newFileExperienceWrapper&quot; data-testid=&quot;media-card-view&quot;&gt;
&lt;div data-testid=&quot;media-file-card-view&quot; data-test-status=&quot;complete&quot; data-test-media-name=&quot;image-20230616-082451.png&quot; data-test-progress=&quot;1&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-layout=&quot;center&quot; data-node-type=&quot;mediaSingle&quot;&gt;
&lt;div&gt;
&lt;div data-context-id=&quot;37801105721&quot; data-type=&quot;file&quot; data-node-type=&quot;media&quot; data-width=&quot;274&quot; data-height=&quot;184&quot; data-id=&quot;3eed2a3b-5170-46bd-b9a4-9cfaa37b2c1f&quot; data-collection=&quot;contentId-37801105721&quot; data-file-name=&quot;image-20230616-082451.png&quot; data-file-size=&quot;58798&quot; data-file-mime-type=&quot;image/png&quot; data-alt=&quot;&quot;&gt;
&lt;div id=&quot;newFileExperienceWrapper&quot; data-testid=&quot;media-card-view&quot;&gt;
&lt;div data-testid=&quot;media-file-card-view&quot; data-test-status=&quot;complete&quot; data-test-media-name=&quot;image-20230616-082451.png&quot; data-test-progress=&quot;1&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;274&quot; data-origin-height=&quot;184&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xWb5q/btsnru6dqee/uj80zJkzMBKQiJ3kjIjKw0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xWb5q/btsnru6dqee/uj80zJkzMBKQiJ3kjIjKw0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xWb5q/btsnru6dqee/uj80zJkzMBKQiJ3kjIjKw0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxWb5q%2Fbtsnru6dqee%2Fuj80zJkzMBKQiJ3kjIjKw0%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;274&quot; height=&quot;184&quot; data-origin-width=&quot;274&quot; data-origin-height=&quot;184&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;484&quot; data-ke-size=&quot;size16&quot;&gt;오늘 공유해볼 내용은 저희 팀에서 &lt;b&gt;빠른 &lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;0648b8fe-0862-4d85-b42c-4a499c05861f&quot;&gt;프로비저닝&lt;/span&gt;&lt;/b&gt;을 위해 사용하고 있는 &lt;b&gt;카펜터&lt;/b&gt;(&lt;b&gt;Karpenter)와 빈(empty) 파드를 활용한 스케일링 전략&lt;/b&gt;에 대해 공유해보도록 하겠습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;584&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1부&lt;/b&gt;에서는 &lt;b&gt;카펜터&lt;/b&gt;에 대해서 설명드리고, &lt;b&gt;2부&lt;/b&gt;에서는 &lt;b&gt;빈 파드를 활용한 스케일링 전략&lt;/b&gt;에 대해 설명할 예정이니 다음 글까지 꼭!!읽어보시면 좋을 거 같습니다.&lt;/p&gt;
&lt;h2 id=&quot;EKS-환경에서-왜-카펜터를-써야하지?&quot; style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;671&quot; data-ke-size=&quot;size26&quot;&gt;EKS 환경에서 왜 카펜터를 써야하지?&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;210&quot; data-origin-height=&quot;210&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cShnpe/btsnwoKjPdI/jNJM5MEkO1kbQQtxtsBikK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cShnpe/btsnwoKjPdI/jNJM5MEkO1kbQQtxtsBikK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cShnpe/btsnwoKjPdI/jNJM5MEkO1kbQQtxtsBikK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcShnpe%2FbtsnwoKjPdI%2FjNJM5MEkO1kbQQtxtsBikK%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;210&quot; height=&quot;210&quot; data-origin-width=&quot;210&quot; data-origin-height=&quot;210&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-layout=&quot;center&quot; data-node-type=&quot;mediaSingle&quot;&gt;
&lt;div&gt;
&lt;div data-context-id=&quot;37801105721&quot; data-type=&quot;file&quot; data-node-type=&quot;media&quot; data-width=&quot;210&quot; data-height=&quot;210&quot; data-id=&quot;8ba08a3b-1480-46e1-9e0f-074210e77f5b&quot; data-collection=&quot;contentId-37801105721&quot; data-file-name=&quot;image-20230616-082253.png&quot; data-file-size=&quot;19172&quot; data-file-mime-type=&quot;image/png&quot; data-alt=&quot;&quot;&gt;
&lt;div id=&quot;newFileExperienceWrapper&quot; data-testid=&quot;media-card-view&quot;&gt;
&lt;div data-testid=&quot;media-file-card-view&quot; data-test-status=&quot;complete&quot; data-test-media-name=&quot;image-20230616-082253.png&quot; data-test-progress=&quot;1&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;697&quot; data-ke-size=&quot;size16&quot;&gt;AWS EKS 클러스터를 자동으로 조정하기 위한 프로비저닝 도구로, 많이 알려져있는 쿠버네티스 클러스터 오토스케일러(Cluster Autoscaler, 이하 CA)가 있고, 카펜터도 있습니다. 이 중에서 왜 카펜터를 사용해야 하는지에 대해 이야기 해보도록 하겠습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;848&quot; data-ke-size=&quot;size16&quot;&gt;먼저 Auto Scaling Group(이하 ASG)을 기반으로 동작하는 CA의 동작 방식에 대해 알아야 합니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;848&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;파드&lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;665e2aaf-b13e-4914-b25e-eb4b134bde00&quot;&gt;는&lt;/span&gt; 하나 이상의 EC2 노드에 배포되며, 노드는 Amazon EC2 ASG와 연결된 노드 그룹을 통해 배포됩니다. CA는 스케줄링 되지 못한 파드가 있으면 ASG를 통해 노드를 EKS 클러스터에 추가하여 프로비저닝을 합니다. 이 때 두 가지 동작이 있습니다. 한 가지는 추가적으로 늘어나는 경우인 프로비저닝과 반대로 줄어드는 경우인 디프로비저닝(deprovisioning)입니다.&lt;/p&gt;
&lt;h3 id=&quot;Provisioning&quot; style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;1130&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;dac74b45-5c06-4ff8-a93f-66230a789a87&quot;&gt;Provisioning&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;741&quot; data-origin-height=&quot;387&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bG8sV9/btsnrsN54p5/Berhp2d4R4CL4uxgkhAPh0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bG8sV9/btsnrsN54p5/Berhp2d4R4CL4uxgkhAPh0/img.png&quot; data-alt=&quot;그림 1. Cluster Autoscaler의 동작 과정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bG8sV9/btsnrsN54p5/Berhp2d4R4CL4uxgkhAPh0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbG8sV9%2FbtsnrsN54p5%2FBerhp2d4R4CL4uxgkhAPh0%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;741&quot; height=&quot;387&quot; data-origin-width=&quot;741&quot; data-origin-height=&quot;387&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림 1. Cluster Autoscaler의 동작 과정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;자원 부족으로 Pending 상태인 파드가 존재한다.&lt;/li&gt;
&lt;li&gt;CA는 ASG의 Desired 수를 증가시킨다.&lt;/li&gt;
&lt;li&gt;AWS ASG은 새로운 노드를 프로비저닝 시킨다.&lt;/li&gt;
&lt;li&gt;kube-scheduler는 Pending된 파드를 새로운 노드에 할당한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;1322&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;d1749d8b-ba38-4cf6-85ed-12800b0950e7&quot;&gt;CA는 노드를 추가로 프로비저닝할 때, 노드의 리소스 &lt;/span&gt;&lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;d1749d8b-ba38-4cf6-85ed-12800b0950e7&quot;&gt;사용률&lt;/span&gt;&lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;d1749d8b-ba38-4cf6-85ed-12800b0950e7&quot;&gt;이 아니라 할당되지 않는 파드의 여부를 기준으로 판단합니다. &lt;/span&gt;이 때, CA는 ASG에 desired 수를 변경하고, 새롭게 노드를 프로비저닝 하는 구조입니다. 그리고 새롭게 뜬 노드에 파드가 할당되어 동작합니다.&lt;/p&gt;
&lt;h3 id=&quot;Deprovisioning&quot; style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;1475&quot; data-ke-size=&quot;size23&quot;&gt;Deprovisioning&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;1491&quot; data-ke-size=&quot;size16&quot;&gt;디프로비저닝의 경우에는 노드의 할당 가능한 리소스를 기준으로 사용률이 50% 이하인 경우 디프로비저닝 대상으로 간주하며, 해당 노드에 실행 중이던 파트를 다른 곳으로 옮길 수 있는지 계산한 뒤 노드의 삭제를 진행합니다. &lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;beedaa1a-d5c3-4511-bec1-d661eab8dd87&quot;&gt;그리고 ASG의 desired 수를 변경하게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;1645&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;1647&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;be508dd5-cd42-40cb-9256-75f370338798&quot;&gt;위 두 경우에서 공통적으로 &lt;/span&gt;CA는 노드 그룹에 연결된 ASG에 따라 노드의 타입이 한정된다는 &lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;8a60a547-b2cd-4bac-ad50-795255a0dba5&quot;&gt;제약이&lt;/span&gt; 있습니다. 즉 필요 이상으로 더 많은 노드 타입이 생길 수도 있습니다. 그렇게 되면 비용 최적화가 되기가 어렵겠죠?&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;1770&quot; data-ke-size=&quot;size16&quot;&gt;CA에서 비용 최적화적인 부분과 ASG과 별개로 행동할 수 있도록 카펜터는 더 고도화되었습니다. 카펜터와 CA의 차이점을 비교해보면 크게 세 가지로 볼 수 있습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;그룹 불필요&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;CA&lt;/b&gt;는 ASG에 요청을 보내는 구조이기 때문에 여러 타입의 인스턴스를 사용하기 위해서는 노드 그룹을 여러 개를 구성해야 합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;카펜터&lt;/b&gt;는 다양한 타입의 인스턴스 목록을 지정하고 프로비저닝 시점에 지정된 조건을 만족하고 리전의 가용 영역에서 사용할 수 있는 인스턴스 중 최적 비용의 인스턴스를 할당해서 사용합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;kube-scheduler 우회&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;CA&lt;/b&gt;는 kube-scheduler에 의해 할당되지 않은 파드를 감지해서 ASG에 알리는 구조이기 때문에 바로 노드가 생기지 않습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;카펜터&lt;/b&gt;는 kube-scheduler에 의해 동작하지 않고, 현재 kube-scheduler에서 표시된 pending 상태인 파드가 있으면 kube-scheduler를 거치지 않고 바로 노드를 생성해서 파드를 할당하기 때문에 비교적 빠르게 동작합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt; 비용 최적화&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;카펜터&lt;/b&gt;는 온디멘드 타입으로 프로비저닝된 노드에 대해 현재의 인스턴스 가격과 리소스를 비교해서 더 적절한 형태의 노드 타입으로 합치는 작업을 해줍니다. (엄청 싸게 할당된 스팟 타입은 해주지 않네요.) 따라서 비용을 최적화 할 수 있습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;2454&quot; data-ke-size=&quot;size16&quot;&gt;이렇게 3가지 관점에서 CA를 대체할 수 있게 되었기 때문에 저희 팀에서는 노드 프로비저닝 도구로 카펜터를 도입했습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;2523&quot; data-ke-size=&quot;size16&quot;&gt;자, 지금까지는 CA의 동작 방식과 카펜터를 도입해서 사용하는 이유에 대해 알아봤습니다. CA의 동작을 알아봤으니까 카펜터의 동작도 함께 봐야지 확실히 비교가 되겠죠?&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;2618&quot; data-ke-size=&quot;size16&quot;&gt;이번에는 카펜터가 어떻게 동작하는지에 대해 알아보도록 하겠습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;2656&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;카펜터,-넌-누구냐?&quot; style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;2658&quot; data-ke-size=&quot;size26&quot;&gt;카펜터, 넌 누구냐?&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h3 id=&quot;카펜터-구성은-어떻게-되지?&quot; style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;2671&quot; data-ke-size=&quot;size23&quot;&gt;카펜터 구성은 어떻게 되지?&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;2688&quot; data-ke-size=&quot;size16&quot;&gt;카펜터의 동작을 이해하기 전에 구성 요소를 살펴볼 필요가 있습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;2688&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;2727&quot; data-ke-size=&quot;size16&quot;&gt;카펜터는 Provisioner와 NodeTemplate을 통해 조건에 알맞은 노드 타입을 빠르게 프로비저닝 해줍니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;2794&quot; data-ke-size=&quot;size16&quot;&gt;먼저 Provisioner는 프로비저닝이 될 때 사용할 수 있는 인스턴스 패밀리나 가용영역, 가중치 등으로 구성해서 노드가 생성될 때 필요한 프로바이더(providerref)의 역할을 하게 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1689231092364&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: karpenter.sh/v1alpha5
kind: Provisioner
metadata:
  name: on-demand
spec:
  providerRef:
    name: on-demand
  ttlSecondsAfterEmpty: 30
  limits:
    resources:
      cpu: 1k
      memory: 1000Gi
  requirements:
    # Include general purpose instance families
    - key: karpenter.sh/capacity-type
      operator: In
      values: [&quot;on-demand&quot;]
    - key: karpenter.k8s.aws/instance-family
      operator: In
      values: [&quot;t3&quot;]
    - key: karpenter.k8s.aws/instance-size
      operator: NotIn
      values: [&quot;nano&quot;, &quot;micro&quot;, &quot;small&quot;]
    - key: kubernetes.io/arch
      operator: In
      values: [&quot;amd64&quot;]
    - key: topology.kubernetes.io/zone
      operator: In
      values: [&quot;ap-northeast-2a&quot;, &quot;ap-northeast-2b&quot;, &quot;ap-northeast-2c&quot;]&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;3658&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;3658&quot; data-ke-size=&quot;size16&quot;&gt;다음으로 NodeTemplate는 Provisioner의 spec.providerRef부분에 들어가고, 프로비저닝될 노드가 어떤 AMI로 실행하고, 혹은 어떤 보안 그룹을 사용할 것인지 등 노드에 대한 정의를 하는 템플릿이라고 볼 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1689231133346&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: karpenter.k8s.aws/v1alpha1
kind: AWSNodeTemplate
metadata:
  name: spot
spec:
  subnetSelector:
    karpenter.sh/discovery: cluster-name
  securityGroupSelector:
    karpenter.sh/discovery: cluster-name
  instanceProfile: MyInstanceProfile
  amiFamily: Bottlerocket&lt;/code&gt;&lt;/pre&gt;
&lt;div style=&quot;background-color: #000000; color: #172b4d; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;4079&quot; data-ke-size=&quot;size16&quot;&gt;이렇게 카펜터의 두 가지 구성요소에 대해 알아봤습니다. 이제 본격적으로 카펜터의 동작을 알아보겠습니다.&lt;/p&gt;
&lt;h3 id=&quot;카펜터는-어떻게-동작할까?&quot; style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;4138&quot; data-ke-size=&quot;size23&quot;&gt;카펜터는 어떻게 동작할까?&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;4154&quot; data-ke-size=&quot;size16&quot;&gt;먼저 아래 카펜터의 동작 과정 그림을 보겠습니다. 그림을 보시면 CA와는 다르게 ASG와 관계없이 동작하는 것을 확인할 수 있습니다. 이렇기 때문에 파드를 할당할 수 있는 노드가 부족할 때, JIT(Just-In-Time)으로 노드 프로비저닝이 일어나기 &lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;49127798-0922-43a7-9789-d24267342ccf&quot;&gt;때문에&lt;/span&gt; 보다 빠르게 파드를 할당 할 수 있게 됩니다.&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-layout=&quot;center&quot; data-node-type=&quot;mediaSingle&quot;&gt;
&lt;div&gt;
&lt;div data-context-id=&quot;37801105721&quot; data-type=&quot;file&quot; data-node-type=&quot;media&quot; data-width=&quot;2142&quot; data-height=&quot;1204&quot; data-id=&quot;e5c08c49-9101-4dc0-b0ca-caa7e6fd936f&quot; data-collection=&quot;contentId-37801105721&quot; data-file-name=&quot;image-20230623-015904.png&quot; data-file-size=&quot;366718&quot; data-file-mime-type=&quot;image/png&quot; data-alt=&quot;&quot;&gt;
&lt;div id=&quot;newFileExperienceWrapper&quot; data-testid=&quot;media-card-view&quot;&gt;
&lt;div data-testid=&quot;media-file-card-view&quot; data-test-status=&quot;complete&quot; data-test-media-name=&quot;image-20230623-015904.png&quot; data-test-progress=&quot;1&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2142&quot; data-origin-height=&quot;1204&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bq01Fr/btsnrvqr0Ut/q2kOif9jyyKSrBF4nj2JmK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bq01Fr/btsnrvqr0Ut/q2kOif9jyyKSrBF4nj2JmK/img.png&quot; data-alt=&quot;Karpenter 동작 원리&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bq01Fr/btsnrvqr0Ut/q2kOif9jyyKSrBF4nj2JmK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbq01Fr%2Fbtsnrvqr0Ut%2Fq2kOif9jyyKSrBF4nj2JmK%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;2142&quot; height=&quot;1204&quot; data-origin-width=&quot;2142&quot; data-origin-height=&quot;1204&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Karpenter 동작 원리&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;4330&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;45eaba19-e8a7-49b7-b9b0-e5cf842aaf48&quot;&gt;카펜터도 CA와 마찬가지로&lt;/span&gt; 프로비저닝과 디프로비저닝이 있겠죠? 각 동작에 대해서 딥 다이브해보도록 하겠습니다.&lt;/p&gt;
&lt;h3 id=&quot;Provisioning.1&quot; style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;4393&quot; data-ke-size=&quot;size23&quot;&gt;Provisioning&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;div style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-layout=&quot;center&quot; data-node-type=&quot;mediaSingle&quot;&gt;
&lt;div&gt;
&lt;div data-context-id=&quot;37801105721&quot; data-type=&quot;file&quot; data-node-type=&quot;media&quot; data-width=&quot;1235&quot; data-height=&quot;244&quot; data-id=&quot;22fe9b34-5ff1-4e8a-a280-feae9e5a0a1d&quot; data-collection=&quot;contentId-37801105721&quot; data-file-name=&quot;image-20230315-082419.png&quot; data-file-size=&quot;210967&quot; data-file-mime-type=&quot;image/png&quot; data-alt=&quot;&quot;&gt;
&lt;div id=&quot;newFileExperienceWrapper&quot; data-testid=&quot;media-card-view&quot;&gt;
&lt;div data-testid=&quot;media-file-card-view&quot; data-test-status=&quot;complete&quot; data-test-media-name=&quot;image-20230315-082419.png&quot; data-test-progress=&quot;1&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div style=&quot;color: #000000; text-align: center;&quot; data-media-caption=&quot;true&quot; data-testid=&quot;media-caption&quot; data-renderer-start-pos=&quot;4409&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2470&quot; data-origin-height=&quot;488&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/I48uo/btsnqfBHZk8/XxxQEMvQqt0BC5xBYjQSK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/I48uo/btsnqfBHZk8/XxxQEMvQqt0BC5xBYjQSK0/img.png&quot; data-alt=&quot;Karpenter Pod의 동작 Log&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/I48uo/btsnqfBHZk8/XxxQEMvQqt0BC5xBYjQSK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FI48uo%2FbtsnqfBHZk8%2FXxxQEMvQqt0BC5xBYjQSK0%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;2470&quot; height=&quot;488&quot; data-origin-width=&quot;2470&quot; data-origin-height=&quot;488&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Karpenter Pod의 동작 Log&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;4433&quot; data-ke-size=&quot;size16&quot;&gt;카펜터 파드의 &lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;bcf7d5a2-7940-4e9b-9ae8-8ed67a3c81af&quot;&gt;로그&lt;/span&gt;를 보면 Pending상태인 파드가 3개 가 있고 이를 위해 3개의 온디맨드 타입의 노드가 새롭게 뜨는 것을 확인해 볼 수 있습니다. 이 동작이 어떻게 이뤄질까요? 프로비저닝도 Provisioner의 특정 조건에 만족해야 하는데, 이 조건들이 무엇인지에 대해 하나씩 짚어보도록 하겠습니다.&lt;/p&gt;
&lt;h4 id=&quot;조건-1---리소스-요청-:-띄우려는-파드의-리소스가-현재-있는-노드보다-많이-필요한-경우,-Provisioner가-동작하도록-지정합니다.&quot; style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;4606&quot; data-ke-size=&quot;size20&quot;&gt;조건 1 - &lt;b&gt;&lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;aa183dc5-ef2f-4ce4-b242-be4c16432b5c&quot;&gt;리소스 &lt;/span&gt;&lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;61551099-e7d3-47c5-b1a4-9a65cc9546c2&quot;&gt;요청 : &lt;/span&gt;&lt;/b&gt;띄우려는 파드의 리소스가 현재 있는 노드보다 많이 필요한 경우, Provisioner가 동작하도록 &lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;a91b4dc5-d079-4184-aeba-b6a8369ca15f&quot;&gt;지정합니다&lt;/span&gt;.&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;b995253e-3d65-4d50-92d2-bef171035902&quot;&gt;아래 예시에서는 vCpu 2core와 메모리 2.5Gi가 필요하기 때문에 xlarge타입의 노드가 프로비저닝됩니다.&lt;/span&gt;&lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;b995253e-3d65-4d50-92d2-bef171035902&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1689231170918&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;spec:
  containers:
    - name: reserve-resources
      image: k8s.gcr.io/pause
      resources:
        requests:
          cpu: 2000m
          memory: 2.5Gi
        limits:
          cpu: 2000m
          memory: 2.5Gi&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;조건-2---노드-선택:-NodeSelector-에-레이블을-지정해서-원하는-Provisioner가-동작하도록-지정합니다.&quot; style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;4977&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;조건 2 - 노드 선택:&lt;/b&gt; NodeSelector 에 레이블을 지정해서 원하는 Provisioner가 동작하도록 지정합니다.&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;b861ad12-f8cb-4acb-b5b0-b36c40f1aa22&quot;&gt;아래 예시에서는 NodeSelector에 지정된 레이블과 맞는 온디맨스 혹은 스팟 &lt;/span&gt;&lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;b861ad12-f8cb-4acb-b5b0-b36c40f1aa22&quot;&gt;provisioner&lt;/span&gt;&lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;b861ad12-f8cb-4acb-b5b0-b36c40f1aa22&quot;&gt;가 동작해서 새로운 노드가 뜨거나 기존의 노드 중 레이블에 매칭된 노드에 파드가 할당됩니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1689231186349&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;spec:
  template:
    metadata:
      labels:
        app: nginx
    spec:
      NodeSelector:
        topology.kubernetes.io/zone: ap-northeast-2a
        karpenter.sh/capacity-type: spot&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;조건-3---NodeAffinity를-만족하는-경우에-Provisioner가-동작하도록-지정합니다.&quot; style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;5351&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;조건 3 - &lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;cb9452fd-2b31-4f05-a049-208c67254735&quot;&gt;NodeAffinity&lt;/span&gt;&lt;/b&gt;를 만족하는 경우에 Provisioner가 동작하도록 지정합니다.&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;5408&quot; data-ke-size=&quot;size16&quot;&gt;Node affinity에는 두 가지 조건으로 동작을 결정됩니다. requiredDuringSchedulingIgnoredDuringExecution(반드시 조건을 만족해야 한다.)와 preferredDuringSchedulingIgnoredDuringExecution(되도록 조건을 만족해야 한다.) 입니다. 두 가지의 Node affinity에 NodeSelectTerms로 Provisioner에 지정된 레이블이나 requirements의 키/값을 지정해서 원하는 Provisioner로 동작할 수 있도록 지정할 수 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아래 예시에서는 requiredDuringSchedulingIgnoredDuringExecution 가 걸려있기 때문에 아래 조건과 반드시 만족한 노드가 아니면 새로운 노드가 프로비저닝됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1689231196533&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;      affinity:
        NodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            NodeSelectorTerms:
              - matchExpressions:
                  - key: &quot;Nodetype&quot;
                    operator: &quot;In&quot;
                    values: [&quot;on-demand&quot;]&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;조건-4---토폴로지-분배:-topologySpreadConstraints의-조건으로-지정해서-만족하는-경우-Provisioner가-동작하도록-지정합니다.&quot; style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;6096&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;조건 4 - &lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;b0bb7680-594f-4d33-b70a-dda045bba778&quot;&gt;토폴로지 분배:&lt;/span&gt;&lt;/b&gt; topologySpreadConstraints의 조건으로 지정해서 만족하는 경우 Provisioner가 동작하도록 지정합니다.&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;6184&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;cf6a50f3-ded1-40a4-bc8e-605d6033e18c&quot;&gt;하나의 노드에 같은 파드가 &lt;/span&gt;&lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;791659fc-8a9a-404c-951a-fc1742edda55&quot;&gt;뜨지&lt;/span&gt; 않도록 제약사항을 걸어 여러 노드가 프로비저닝 될 수 있도록 조건을 걸 수 있습니다. 현재 지원하는 topologyKey는 topology.kubernetes.io/zone kubernetes.io/hostname karpenter.sh/capacity-type 3가지 입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아래 예시에서는 같은 kubernetes.io/hostname &lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;b6e1dcd6-d5e6-493e-a418-378aaa7978f5&quot;&gt;레이블&lt;/span&gt;이 있는 노드에 1개의 파드만 있을 수 있도록 설정했습니다. 설정대로라면 새로운 파드가 뜰 때마다 노드가 프로비저닝 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1689231206067&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;      topologySpreadConstraints:
        - maxSkew: 1
          topologyKey: kubernetes.io/hostname
          whenUnsatisfiable: DoNotSchedule
          labelSelector:
            matchLabels:
              run: empty-Pods&lt;/code&gt;&lt;/pre&gt;
&lt;div style=&quot;background-color: #000000; color: #172b4d; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 id=&quot;조건-5---Pod-affinity/anti-affinity:-affinity-조건에-맞는-경우,-파드를-할당하기-위해-필요한-노드가-없으면-Provisioner가-동작하도록-지정합니다.&quot; style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;6696&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;조건 5 - Pod affinity/anti-affinity&lt;/b&gt;: affinity 조건에 맞는 경우, 파드를 &lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;50c011de-d69a-4acd-8ef5-5e80e76283d7&quot;&gt;할당하기 위해 필요한&lt;/span&gt; 노드가 없으면 Provisioner가 동작하도록 지정합니다.&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;6802&quot; data-ke-size=&quot;size16&quot;&gt;PodAffinity와 PodAntiAffinity조건에 부합하는 노드에 파드를 할당할 수 있습니다. 만약 파드를 할당했는데 필요한 노드가 없다면 Provisioner가 동작해서 노드를 새롭게 프로비저닝&lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;013c43b0-2301-4bb5-a6e0-dd57d77e8d00&quot;&gt;합니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아래 예시에서는 system: backend 레이블이 있는 노드에는 뜨고, app: inflate label이 있는 노드에는 파드가 뜨지 않도록 &lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;21528d2e-f897-43db-8b2d-102588f8fe69&quot;&gt;지정했습니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1689231217332&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;spec:
  affinity:
    PodAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: system
            operator: In
            values:
            - backend
        topologyKey: topology.kubernetes.io/zone
    PodAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchLabels:
            app: inflate
        topologyKey: kubernetes.io/hostname&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;Deprovisioning.1&quot; style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;7488&quot; data-ke-size=&quot;size23&quot;&gt;Deprovisioning&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;7504&quot; data-ke-size=&quot;size16&quot;&gt;프로비저닝 됐다가 더이상 사용하지 않는 노드를 비용 최적화를 하기 위해 스케일을 줄이게 됩니다. 이 때 디프로비저닝을 하기 위한 조건은 4가지로 구성되는데 각각에 대해 알아보겠습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Provisioner의 삭제&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Provisioner에 의해 &lt;span data-renderer-mark=&quot;true&quot; data-mark-type=&quot;annotation&quot; data-mark-annotation-type=&quot;inlineComment&quot; data-id=&quot;b32febfa-9cb8-4503-a049-7a72943873e0&quot;&gt;생성된&lt;/span&gt; 노드는 Provisioner가 소유한 것으로 간주가 됩니다. 따라서 Provisioner가 삭제되면 Provisioner에 의해 생성된 노드가 중지되서 디프로비저닝 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Empty&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Deamonset이 아닌 파드가 사라진 다음 Provisioner에 지정된 ttlSecondsAfterEmpty 이 지난 이후 디프로비저닝이 동작해서 노드를 중지합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Interrupt&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Spot stop interrupt나 Node termination등의 노드와 관련된 중단 이벤트가 Event Bridge를 통해 SQS의 대기열로 들어오면 이를 받아 디프로비저닝 동작을 하게 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Expire&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;노드가 프로비저닝 된 이후 Provisioner에 지정된 ttlSecondsUntilExpired 시간이 지나면 디프로비저닝이 동작해서 노드를 중지하게 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Integration&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;비용 최적화를 하기 위해서 현재 생성된 단일 혹은 여러 노드의 비용를 비교해서 더 적절한 하나의 노드로 합치는 작업을 하게 됩니다. 이 때 스팟 타입의 경우에는 동작하지 않으며 온디맨드 타입의 노드의 경우에만 합치게 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;8242&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;8244&quot; data-ke-size=&quot;size16&quot;&gt;지금까지 &lt;b&gt;카펜터 구성요소와 어떻게 동작하는지&lt;/b&gt;에 대해 자세히 알아봤습니다. &lt;b&gt;CA와 카펜터의 동작&lt;/b&gt;이 좀 다르다는게 느껴지시나요? 와닿지 않으시다면 직접 구축해보시는건 어떨까요?&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;8343&quot; data-ke-size=&quot;size16&quot;&gt;이번 글에서는 Empty Pod에 대한 내용은 언급하지 않았습니다. 여러분의 궁금증을 풀려면&amp;hellip;다음 글을 읽어주셔야 합니다~&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;8413&quot; data-ke-size=&quot;size16&quot;&gt;다음 글에서는 &lt;b&gt;PriorityClass와 빈 파드, &lt;/b&gt;그리고 오늘 설명드린 &lt;b&gt;카펜터를 활용한 스케일링 전략&lt;/b&gt;을 집중적으로 다뤄보도록 하겠습니다.&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-layout=&quot;center&quot; data-node-type=&quot;mediaSingle&quot;&gt;
&lt;div&gt;
&lt;div data-context-id=&quot;37801105721&quot; data-type=&quot;file&quot; data-node-type=&quot;media&quot; data-width=&quot;419&quot; data-height=&quot;106&quot; data-id=&quot;0a6b1bf4-ccbd-4b97-81c9-ec5601e65beb&quot; data-collection=&quot;contentId-37801105721&quot; data-file-name=&quot;image-20230616-090455.png&quot; data-file-size=&quot;37265&quot; data-file-mime-type=&quot;image/png&quot; data-alt=&quot;&quot;&gt;
&lt;div id=&quot;newFileExperienceWrapper&quot; data-testid=&quot;media-card-view&quot;&gt;
&lt;div data-testid=&quot;media-file-card-view&quot; data-test-status=&quot;complete&quot; data-test-media-name=&quot;image-20230616-090455.png&quot; data-test-progress=&quot;1&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;838&quot; data-origin-height=&quot;212&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2HCDh/btsnruZpHac/0hGhIi1yBgoGtjFeGXPzs1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2HCDh/btsnruZpHac/0hGhIi1yBgoGtjFeGXPzs1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2HCDh/btsnruZpHac/0hGhIi1yBgoGtjFeGXPzs1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2HCDh%2FbtsnruZpHac%2F0hGhIi1yBgoGtjFeGXPzs1%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;415&quot; height=&quot;105&quot; data-origin-width=&quot;838&quot; data-origin-height=&quot;212&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 id=&quot;Reference&quot; style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;8497&quot; data-ke-size=&quot;size26&quot;&gt;Reference&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://karpenter.sh/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://karpenter.sh/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1689231277443&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;Karpenter&quot; data-og-description=&quot;Just-in-time Nodes for Any Kubernetes Cluster&quot; data-og-host=&quot;karpenter.sh&quot; data-og-source-url=&quot;https://karpenter.sh/&quot; data-og-url=&quot;https://karpenter.sh/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/b5C5Nk/hyTjHx25Dg/Bo2mkLaF4mbCVXwYdZRfok/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640,https://scrap.kakaocdn.net/dn/bfCjht/hyTipZ45kc/8GXgWWIHlhPWeS5mpzbe8K/img.png?width=2142&amp;amp;height=1204&amp;amp;face=0_0_2142_1204&quot;&gt;&lt;a href=&quot;https://karpenter.sh/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://karpenter.sh/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/b5C5Nk/hyTjHx25Dg/Bo2mkLaF4mbCVXwYdZRfok/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640,https://scrap.kakaocdn.net/dn/bfCjht/hyTipZ45kc/8GXgWWIHlhPWeS5mpzbe8K/img.png?width=2142&amp;amp;height=1204&amp;amp;face=0_0_2142_1204');&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;Karpenter&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Just-in-time Nodes for Any Kubernetes Cluster&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;karpenter.sh&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p style=&quot;background-color: #ffffff; color: #172b4d; text-align: start;&quot; data-renderer-start-pos=&quot;8602&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://catalog.us-east-1.prod.workshops.aws/workshops/fd6ccd33-980d-422f-b6a6-cb3c3424a78c/en-US/scaling/scaling-clusters&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://catalog.us-east-1.prod.workshops.aws/workshops/fd6ccd33-980d-422f-b6a6-cb3c3424a78c/en-US/scaling/scaling-clusters&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1689231238012&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;Workshop Studio&quot; data-og-description=&quot;&quot; data-og-host=&quot;catalog.us-east-1.prod.workshops.aws&quot; data-og-source-url=&quot;https://catalog.us-east-1.prod.workshops.aws/workshops/fd6ccd33-980d-422f-b6a6-cb3c3424a78c/en-US/scaling/scaling-clusters&quot; data-og-url=&quot;https://catalog.us-east-1.prod.workshops.aws/workshops/fd6ccd33-980d-422f-b6a6-cb3c3424a78c/en-US/scaling/scaling-clusters&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://catalog.us-east-1.prod.workshops.aws/workshops/fd6ccd33-980d-422f-b6a6-cb3c3424a78c/en-US/scaling/scaling-clusters&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://catalog.us-east-1.prod.workshops.aws/workshops/fd6ccd33-980d-422f-b6a6-cb3c3424a78c/en-US/scaling/scaling-clusters&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;Workshop Studio&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;catalog.us-east-1.prod.workshops.aws&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://aws.amazon.com/ko/blogs/tech/amazon-eks-cluster-auto-scaling-karpenter-bp/&quot;&gt;https://aws.amazon.com/ko/blogs/tech/amazon-eks-cluster-auto-scaling-karpenter-bp/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1689231247621&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;Amazon EKS 클러스터를 비용 효율적으로 오토스케일링하기 | Amazon Web Services&quot; data-og-description=&quot;애플리케이션 현대화를 위해 많은 고객이 컨테이너를 선택하며, 컨테이너 운영 부담을 완화하기 위해 Amazon Elastic Container Service (Amazon ECS) 또는 Amazon Elastic Kubernetes Service (Amazon EKS)와 같은 관리형 &quot; data-og-host=&quot;aws.amazon.com&quot; data-og-source-url=&quot;https://aws.amazon.com/ko/blogs/tech/amazon-eks-cluster-auto-scaling-karpenter-bp/&quot; data-og-url=&quot;https://aws.amazon.com/ko/blogs/tech/amazon-eks-cluster-auto-scaling-karpenter-bp/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/d9Jdpc/hyTiqxW4Mw/qksPFTxzkck0EoIPbgobUk/img.png?width=855&amp;amp;height=400&amp;amp;face=0_0_855_400,https://scrap.kakaocdn.net/dn/bzaTro/hyTiwLGB9f/6YaaK9Cke4wphOSlGtdOt1/img.png?width=855&amp;amp;height=400&amp;amp;face=0_0_855_400,https://scrap.kakaocdn.net/dn/bJyqBw/hyTjLHdtKU/TJzDnXHmIokOBsjFkJoJuk/img.png?width=1024&amp;amp;height=975&amp;amp;face=0_0_1024_975&quot;&gt;&lt;a href=&quot;https://aws.amazon.com/ko/blogs/tech/amazon-eks-cluster-auto-scaling-karpenter-bp/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://aws.amazon.com/ko/blogs/tech/amazon-eks-cluster-auto-scaling-karpenter-bp/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/d9Jdpc/hyTiqxW4Mw/qksPFTxzkck0EoIPbgobUk/img.png?width=855&amp;amp;height=400&amp;amp;face=0_0_855_400,https://scrap.kakaocdn.net/dn/bzaTro/hyTiwLGB9f/6YaaK9Cke4wphOSlGtdOt1/img.png?width=855&amp;amp;height=400&amp;amp;face=0_0_855_400,https://scrap.kakaocdn.net/dn/bJyqBw/hyTjLHdtKU/TJzDnXHmIokOBsjFkJoJuk/img.png?width=1024&amp;amp;height=975&amp;amp;face=0_0_1024_975');&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;Amazon EKS 클러스터를 비용 효율적으로 오토스케일링하기 | Amazon Web Services&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;애플리케이션 현대화를 위해 많은 고객이 컨테이너를 선택하며, 컨테이너 운영 부담을 완화하기 위해 Amazon Elastic Container Service (Amazon ECS) 또는 Amazon Elastic Kubernetes Service (Amazon EKS)와 같은 관리형&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;aws.amazon.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/kubernetes/autoscaler&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/kubernetes/autoscaler&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1689231255996&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - kubernetes/autoscaler: Autoscaling components for Kubernetes&quot; data-og-description=&quot;Autoscaling components for Kubernetes. Contribute to kubernetes/autoscaler development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/kubernetes/autoscaler&quot; data-og-url=&quot;https://github.com/kubernetes/autoscaler&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cBozfz/hyTiA8l2fR/I9u0Vk1elKxKeKWqr12df0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/kubernetes/autoscaler&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/kubernetes/autoscaler&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cBozfz/hyTiA8l2fR/I9u0Vk1elKxKeKWqr12df0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - kubernetes/autoscaler: Autoscaling components for Kubernetes&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Autoscaling components for Kubernetes. Contribute to kubernetes/autoscaler development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.wisen.co.kr/pages/blog/blog-detail.html?idx=12079&quot;&gt;https://www.wisen.co.kr/pages/blog/blog-detail.html?idx=12079&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1689231264587&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;[Re2021] 새로운 K8s Cluster Autoscaler, Karpenter 소개&quot; data-og-description=&quot;GS네오텍의 IT서비스 브랜드 WiseN으로 진정한 프리미엄을 경험하세요&quot; data-og-host=&quot;www.wisen.co.kr:443&quot; data-og-source-url=&quot;https://www.wisen.co.kr/pages/blog/blog-detail.html?idx=12079&quot; data-og-url=&quot;http://www.wisen.co.kr/pages/blog/blog-detail.html?idx=12079&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bosJ0y/hyTjJ3Iimg/jfNMZMbJaOSIn0kcGdNvnK/img.png?width=558&amp;amp;height=270&amp;amp;face=0_0_558_270,https://scrap.kakaocdn.net/dn/dfc6lF/hyTiu8apIR/rb4z8fO2iMDnl62F1tYRIk/img.png?width=558&amp;amp;height=270&amp;amp;face=0_0_558_270,https://scrap.kakaocdn.net/dn/bXje5q/hyTiv63j1c/8PbWBgE70QNXK6hl2UqM00/img.png?width=840&amp;amp;height=800&amp;amp;face=0_0_840_800&quot;&gt;&lt;a href=&quot;https://www.wisen.co.kr/pages/blog/blog-detail.html?idx=12079&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.wisen.co.kr/pages/blog/blog-detail.html?idx=12079&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bosJ0y/hyTjJ3Iimg/jfNMZMbJaOSIn0kcGdNvnK/img.png?width=558&amp;amp;height=270&amp;amp;face=0_0_558_270,https://scrap.kakaocdn.net/dn/dfc6lF/hyTiu8apIR/rb4z8fO2iMDnl62F1tYRIk/img.png?width=558&amp;amp;height=270&amp;amp;face=0_0_558_270,https://scrap.kakaocdn.net/dn/bXje5q/hyTiv63j1c/8PbWBgE70QNXK6hl2UqM00/img.png?width=840&amp;amp;height=800&amp;amp;face=0_0_840_800');&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;[Re2021] 새로운 K8s Cluster Autoscaler, Karpenter 소개&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;GS네오텍의 IT서비스 브랜드 WiseN으로 진정한 프리미엄을 경험하세요&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.wisen.co.kr:443&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>Dev&amp;amp;Ops/DevOps</category>
      <category>autoscaling</category>
      <category>AWS</category>
      <category>devops</category>
      <category>eks</category>
      <category>Karpenter</category>
      <author>zeroneCoder</author>
      <guid isPermaLink="true">https://zerone-code.tistory.com/13</guid>
      <comments>https://zerone-code.tistory.com/13#entry13comment</comments>
      <pubDate>Thu, 13 Jul 2023 15:55:24 +0900</pubDate>
    </item>
    <item>
      <title>[Infra] EKS 환경에서 Springboot에 IRSA 적용해보기</title>
      <link>https://zerone-code.tistory.com/12</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;안녕하세요!&amp;nbsp;&lt;b&gt;zerone-code입니다.&lt;/b&gt;&lt;/b&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;Springboot&lt;/b&gt;, 그리고 요즘 &lt;b&gt;MSA&lt;/b&gt;환경으로 전환 혹은 개발한다고 하면 빠질 수 없는 &lt;b&gt;EKS&lt;/b&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 환경에서 Springboot Application에 IRSA(IAM Role for Service Account)를 적용하는 방법에 대해 정리해 보도록 하겠습니다.&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;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘 읽으셨다면 많은 공감과 구독 부탁드립니다!&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;AWS 환경&lt;/b&gt;에서 동작하는 &lt;b&gt;Springboot Application&lt;/b&gt;에서는 &lt;b&gt;Secrets Value&lt;/b&gt;들을 &lt;b&gt;Parameter Store&lt;/b&gt; 혹은 &lt;b&gt;Secrets Manager&lt;/b&gt;를 사용해서 많이 사용하고 합니다. &lt;b&gt;EC2나 ECS 등의 환경&lt;/b&gt;에서 &lt;b&gt;Parameter Store&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;혹은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;Secrets Manager&lt;/b&gt;를 사용하기 위해서는 &lt;b&gt;IAM Role&lt;/b&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;figure id=&quot;og_1686463522414&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;[Infra]  Springboot에 AWS Secrets Manager 적용해보기(2)&quot; data-og-description=&quot;안녕하세요! zerone-code입니다. 지난 글에서 AWS의 Secrets Manager를 이용해서 Application의 보안 측면을 높이는 방법을 소개했습니다. AWS Secrets Manager가 무엇이고, 왜 적용해야 하며, 어떻게 적용되는지&quot; data-og-host=&quot;zerone-code.tistory.com&quot; data-og-source-url=&quot;https://zerone-code.tistory.com/9&quot; data-og-url=&quot;https://zerone-code.tistory.com/9&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/b0PHuV/hySW7EH41N/iOyNm7RFExwfkj2df0gF0k/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/evRh4Z/hySW1kcDTj/s0JbwucoSAVIjx7JOctbJ0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800&quot;&gt;&lt;a href=&quot;https://zerone-code.tistory.com/9&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://zerone-code.tistory.com/9&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/b0PHuV/hySW7EH41N/iOyNm7RFExwfkj2df0gF0k/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/evRh4Z/hySW1kcDTj/s0JbwucoSAVIjx7JOctbJ0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800');&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;[Infra] Springboot에 AWS Secrets Manager 적용해보기(2)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;안녕하세요! zerone-code입니다. 지난 글에서 AWS의 Secrets Manager를 이용해서 Application의 보안 측면을 높이는 방법을 소개했습니다. AWS Secrets Manager가 무엇이고, 왜 적용해야 하며, 어떻게 적용되는지&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;zerone-code.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;EKS&lt;/b&gt;도 마찬가지 입니다. 하지만 EKS에서는 &lt;b&gt;Node 단위의 IAM Role 이 아닌 Pod 단위의 IAM Role을 사용&lt;/b&gt;해서 &lt;b&gt;각 서비스 별로 접근할 수 있는 Secrets Value&lt;/b&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;A라는 서비스가 돌고 있는 Pod&lt;/b&gt;와 &lt;b&gt;B라는 서비스가 돌고 있는 Pod&lt;/b&gt;가 있다고 가정해보겠습니다. 서로 다른 서비스이지만 같은 EKS Cluster안에 돈다고 가정하면, 같은 Node에 뜰 수도 있게 되고 Node 단위의 IAM Role을 사용하게 된다면 A 서비스와 B 서비스는 &lt;b&gt;같은 IAM Role을 사용하기 때문에 각 서비스의 Secrets Value들을 볼 수 있게 됩니다.&amp;nbsp;&lt;/b&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;a style=&quot;color: #666666; text-align: left;&quot; href=&quot;https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html&quot; data-hook=&quot;linkViewer&quot;&gt;&lt;span style=&quot;color: #1155cc;&quot;&gt;&lt;u&gt;Security best practices in IAM&lt;/u&gt;&lt;/span&gt;&lt;/a&gt;에 어긋나게 됩니다. 따라서 우리는!! &lt;u&gt;&lt;b&gt;Best Practice&lt;/b&gt;&lt;/u&gt;를 지향하는 개발자들이기 때문에 가만히 있을 수 없겠죠? 따라서 &lt;b&gt;Pod 별로 IAM Role&lt;/b&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 별로 IAM Role을 사용하기 위해서는? &lt;b&gt;&lt;u&gt;바로 Servcie Account를 통해 적용해 줄 수 있습니다.&lt;/u&gt;&lt;/b&gt; 이를 사용할 수 있게 만든게 바로 &lt;a href=&quot;https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;IRSA(IAM Role for Service Account)&lt;/a&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 수준에서의 설정과 Infra(EKS) 수준에서의 설정으로 나눠서 설명해 보도록 하겠습니다.&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;b&gt;1. Application 수준에서의 설정&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존에 EC2나 ECS에서 설정한대로 Springboot Application을 Docker Image 형태로 빌드한 후, Pod로 배포하게 된다면 다음과 같은 Error를 맞이하게 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2554&quot; data-origin-height=&quot;770&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cbqyUZ/btsjtAuwJRq/cpIHxbnwxnrcEpowZxjFkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cbqyUZ/btsjtAuwJRq/cpIHxbnwxnrcEpowZxjFkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cbqyUZ/btsjtAuwJRq/cpIHxbnwxnrcEpowZxjFkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcbqyUZ%2FbtsjtAuwJRq%2FcpIHxbnwxnrcEpowZxjFkK%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;2554&quot; height=&quot;770&quot; data-origin-width=&quot;2554&quot; data-origin-height=&quot;770&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바로 Application에서 Secrets Manager를 사용해서 application.yml에 지정된 Secrets Value를 가져와야 하는데 Secrets Manager에 접근을 할 수 없다는 뜻입니다.&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에서 사용하고 있는 Library의 문제입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.awspring.io/spring-cloud-aws/docs/2.3.2/reference/html/index.html#spring-boot-auto-configuration&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Spring Cloud AWS 공식 문서&lt;/a&gt;에 따르면 SpringBoot Auto Configuration Library를 Dependency로 지정해 주게 되면 아래와 같은 순서로 DefaultAWSCredentialsProviderChain을 타게 되는데, 아래 세 가지 경우에 해당하는 값이 아무것도 없기 때문에 문제가 발생하게 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1976&quot; data-origin-height=&quot;684&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AEc4p/btsjqw0e7ZN/PJtsXKQ6Kvf1hY6dN7nJKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AEc4p/btsjqw0e7ZN/PJtsXKQ6Kvf1hY6dN7nJKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AEc4p/btsjqw0e7ZN/PJtsXKQ6Kvf1hY6dN7nJKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAEc4p%2Fbtsjqw0e7ZN%2FPJtsXKQ6Kvf1hY6dN7nJKK%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;1976&quot; height=&quot;684&quot; data-origin-width=&quot;1976&quot; data-origin-height=&quot;684&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 도대체 어떻게 적용하는거지? 라는 생각이 드는 와중 공식문서에서 조금 위로 가보도록 하겠습니다. 위에 정답이 있었네요. 친절하게도 EKS환경에서 IRSA설정을 사용하기 위해서는 아래와 같은 추가 설정을 해야지만 ServiceAccount로 생성된 WebIdentity Token을 사용할 수 있게 됩니다. 이 부분은 Springboot 2.3.1부터 추가된 부분입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2002&quot; data-origin-height=&quot;722&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xC6SY/btsjnbvnIgg/llp57uXqOsF9GWKQTXCW80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xC6SY/btsjnbvnIgg/llp57uXqOsF9GWKQTXCW80/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xC6SY/btsjnbvnIgg/llp57uXqOsF9GWKQTXCW80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxC6SY%2FbtsjnbvnIgg%2Fllp57uXqOsF9GWKQTXCW80%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;2002&quot; height=&quot;722&quot; data-origin-width=&quot;2002&quot; data-origin-height=&quot;722&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 이를 적용하게 되면 아래와 같이 정상적으로 지정한 Spring profile에 맞는 Secrets Manager 값들이 로딩되는 것을 확인해 볼 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1300&quot; data-origin-height=&quot;218&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bRln4v/btsjwrEaoLy/dkUKF4RLplJkh0DUiWnLB1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bRln4v/btsjwrEaoLy/dkUKF4RLplJkh0DUiWnLB1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bRln4v/btsjwrEaoLy/dkUKF4RLplJkh0DUiWnLB1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbRln4v%2FbtsjwrEaoLy%2FdkUKF4RLplJkh0DUiWnLB1%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;1300&quot; height=&quot;218&quot; data-origin-width=&quot;1300&quot; data-origin-height=&quot;218&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;85027d9e-7bae-4acd-a0cc-04da04ab5d71.png&quot; data-origin-width=&quot;2750&quot; data-origin-height=&quot;406&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SmXk6/btsjnHgGCR5/fSANz6iW3b8Xi6bFX6bIgK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SmXk6/btsjnHgGCR5/fSANz6iW3b8Xi6bFX6bIgK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SmXk6/btsjnHgGCR5/fSANz6iW3b8Xi6bFX6bIgK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSmXk6%2FbtsjnHgGCR5%2FfSANz6iW3b8Xi6bFX6bIgK%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;2750&quot; height=&quot;406&quot; data-filename=&quot;85027d9e-7bae-4acd-a0cc-04da04ab5d71.png&quot; data-origin-width=&quot;2750&quot; data-origin-height=&quot;406&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. Infra(EKS) 수준에서의 설정&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번엔 EKS 수준에서 지정해줘야 할 부분에 대해 알아보도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 IRSA를 사용하기 위해서 &lt;b&gt;IAM Role의 Trusted entities&lt;/b&gt;부분에 사용할 EKS와 신뢰 관계를 아래 사진처럼 맺어주도록 합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-06-11 오후 3.39.52.png&quot; data-origin-width=&quot;2622&quot; data-origin-height=&quot;836&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/czAj2R/btsjjCHXjAL/3K4SVjKl78SMonhTS9FLf0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/czAj2R/btsjjCHXjAL/3K4SVjKl78SMonhTS9FLf0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/czAj2R/btsjjCHXjAL/3K4SVjKl78SMonhTS9FLf0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FczAj2R%2FbtsjjCHXjAL%2F3K4SVjKl78SMonhTS9FLf0%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;2622&quot; height=&quot;836&quot; data-filename=&quot;스크린샷 2023-06-11 오후 3.39.52.png&quot; data-origin-width=&quot;2622&quot; data-origin-height=&quot;836&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그다음은 실제로 사용되는 ServiceAccount를 만들어야겠죠? 아래의 yaml의 형태로 생성해 주도록 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1686466087711&quot; class=&quot;go&quot; data-ke-language=&quot;go&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: v1
kind: ServiceAccount
metadata:
  name: &amp;lt;ServiceAccount Name&amp;gt;
  namespace: &amp;lt;NameSpace&amp;gt;
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::&amp;lt;aws-account-id&amp;gt;:role/&amp;lt;iam-role-name&amp;gt;
---
apiVersion: v1
kind: Pod
metadata:
  name: service-pod
  namespace: &amp;lt;NameSpace&amp;gt;
spec:
  serviceAccount: &amp;lt;ServiceAccount Name&amp;gt;
  containers:
    name: &amp;lt;service name&amp;gt;
    image: &amp;lt;service image&amp;gt;
    imagePullPolicy: Always
    ...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 ServiceAccount를 생성하고, 해당 ServiceAccount를 Pod에 지정하게 되면 EKS 내부에 설치된 &lt;a href=&quot;https://github.com/aws/amazon-eks-pod-identity-webhook&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;pod-identity-webhook&lt;/a&gt;에 의해 배포되는 Pod의 manifest가 변형(mutation)되어 ServiceAccount에서 사용되는 Token이 mount 됩니다.&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;1068&quot; data-origin-height=&quot;150&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xmPr6/btsjx3Dbowb/2YF4GasHctM6k1bauMSZQ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xmPr6/btsjx3Dbowb/2YF4GasHctM6k1bauMSZQ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xmPr6/btsjx3Dbowb/2YF4GasHctM6k1bauMSZQ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxmPr6%2Fbtsjx3Dbowb%2F2YF4GasHctM6k1bauMSZQ1%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;1068&quot; height=&quot;150&quot; data-origin-width=&quot;1068&quot; data-origin-height=&quot;150&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-06-11 오후 3.56.38.png&quot; data-origin-width=&quot;1462&quot; data-origin-height=&quot;486&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cmkUiN/btsjnacd6Uo/MuR9GH4QAaCzsQxKH0q1q1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cmkUiN/btsjnacd6Uo/MuR9GH4QAaCzsQxKH0q1q1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cmkUiN/btsjnacd6Uo/MuR9GH4QAaCzsQxKH0q1q1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcmkUiN%2Fbtsjnacd6Uo%2FMuR9GH4QAaCzsQxKH0q1q1%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;1462&quot; height=&quot;486&quot; data-filename=&quot;스크린샷 2023-06-11 오후 3.56.38.png&quot; data-origin-width=&quot;1462&quot; data-origin-height=&quot;486&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;마무리&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지 해본 내용을 정리해보도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. Application 수준에서는 SpringBoot Auto Configuration 외에 aws-java-sdk-sts library를 추가로 지정해준다.&lt;br /&gt;&amp;nbsp; &amp;nbsp;1-1. Docker Image를 새로 빌드해준다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. Infra(EKS)수준에서는&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;IAM Role의 Trusted entities를 EKS와 맺어준다.&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; 2-1. ServicAccount에 Annotation을 사용해서 IAM Role을 지정해서 생성해준다.&lt;br /&gt;&amp;nbsp; &amp;nbsp; 2-2. 사용할 Deployment에 SeviceAccount를 지정해서 생성해준다.&lt;br /&gt;&lt;br /&gt;위와 같은 과정으로 EKS 환경에서 SpringBoot Application을 사용하는 서비스에서 IRSA를 사용하는 과정을 살펴봤습니다.&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;글이 길어지는 관계로 생성하려는 Pod가 pod-identity-webhook에 의해 변형(mutation)되는 부분에 대해서는 자세히 언급하지는 않았지만, 아래 참고 자료를 같이 읽어보시면 좋을거 같습니다.&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;글을 읽어 보시는 것 뿐만 아니라 직접 해보시면 더 빠른 이해가 되실 것이라고 생각됩니다.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;궁금한 부분은 댓글로 남겨주시면 아는 만큼 성심성의껏 답변해드리도록 하겠습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘 읽으셨다면 많은 공감과 구독 부탁드립니다!&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Reference&lt;br /&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.awspring.io/spring-cloud-aws/docs/2.4.0/reference/html/index.html#sdk-credentials-configuration&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://docs.awspring.io/spring-cloud-aws/docs/2.4.0/reference/html/index.html#sdk-credentials-configuration&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1686467699687&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;Spring Cloud AWS&quot; data-og-description=&quot;Spring Cloud for Amazon Web Services, part of the Spring Cloud umbrella project, eases the integration with hosted Amazon Web Services. It offers a convenient way to interact with AWS provided services using well-known Spring idioms and APIs, such as the m&quot; data-og-host=&quot;docs.awspring.io&quot; data-og-source-url=&quot;https://docs.awspring.io/spring-cloud-aws/docs/2.4.0/reference/html/index.html#sdk-credentials-configuration&quot; data-og-url=&quot;https://docs.awspring.io/spring-cloud-aws/docs/2.4.0/reference/html/index.html#sdk-credentials-configuration&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://docs.awspring.io/spring-cloud-aws/docs/2.4.0/reference/html/index.html#sdk-credentials-configuration&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.awspring.io/spring-cloud-aws/docs/2.4.0/reference/html/index.html#sdk-credentials-configuration&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;Spring Cloud AWS&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Spring Cloud for Amazon Web Services, part of the Spring Cloud umbrella project, eases the integration with hosted Amazon Web Services. It offers a convenient way to interact with AWS provided services using well-known Spring idioms and APIs, such as the m&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.awspring.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/aws/amazon-eks-pod-identity-webhook&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/aws/amazon-eks-pod-identity-webhook&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1686467584495&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - aws/amazon-eks-pod-identity-webhook: Amazon EKS Pod Identity Webhook&quot; data-og-description=&quot;Amazon EKS Pod Identity Webhook. Contribute to aws/amazon-eks-pod-identity-webhook development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/aws/amazon-eks-pod-identity-webhook&quot; data-og-url=&quot;https://github.com/aws/amazon-eks-pod-identity-webhook&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/mzyyo/hySW3CkKOt/uN9cXxOckZUGQLcxbJBU5k/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/aws/amazon-eks-pod-identity-webhook&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/aws/amazon-eks-pod-identity-webhook&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/mzyyo/hySW3CkKOt/uN9cXxOckZUGQLcxbJBU5k/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - aws/amazon-eks-pod-identity-webhook: Amazon EKS Pod Identity Webhook&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Amazon EKS Pod Identity Webhook. Contribute to aws/amazon-eks-pod-identity-webhook development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://aws.amazon.com/blogs/opensource/introducing-fine-grained-iam-roles-service-accounts/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://aws.amazon.com/blogs/opensource/introducing-fine-grained-iam-roles-service-accounts/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1686467684470&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;Introducing fine-grained IAM roles for service accounts | Amazon Web Services&quot; data-og-description=&quot;Here at AWS we focus first and foremost on customer needs. In the context of access control in Amazon EKS, you asked in issue #23 of our public container roadmap for fine-grained IAM roles in EKS. To address this need, the community came up with a number o&quot; data-og-host=&quot;aws.amazon.com&quot; data-og-source-url=&quot;https://aws.amazon.com/blogs/opensource/introducing-fine-grained-iam-roles-service-accounts/&quot; data-og-url=&quot;https://aws.amazon.com/blogs/opensource/introducing-fine-grained-iam-roles-service-accounts/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/VVII5/hySWrdaxV9/0ihgX7prVkdYMo1fskmX91/img.png?width=636&amp;amp;height=630&amp;amp;face=0_0_636_630,https://scrap.kakaocdn.net/dn/bOjqWw/hySXd52epe/mVlE8kINBrHz4C9ANC3s9K/img.png?width=636&amp;amp;height=630&amp;amp;face=0_0_636_630,https://scrap.kakaocdn.net/dn/HVTnW/hySWlKK6vg/O79QKR8SGvQo0xCzZljth1/img.png?width=1200&amp;amp;height=1200&amp;amp;face=76_260_649_884&quot;&gt;&lt;a href=&quot;https://aws.amazon.com/blogs/opensource/introducing-fine-grained-iam-roles-service-accounts/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://aws.amazon.com/blogs/opensource/introducing-fine-grained-iam-roles-service-accounts/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/VVII5/hySWrdaxV9/0ihgX7prVkdYMo1fskmX91/img.png?width=636&amp;amp;height=630&amp;amp;face=0_0_636_630,https://scrap.kakaocdn.net/dn/bOjqWw/hySXd52epe/mVlE8kINBrHz4C9ANC3s9K/img.png?width=636&amp;amp;height=630&amp;amp;face=0_0_636_630,https://scrap.kakaocdn.net/dn/HVTnW/hySWlKK6vg/O79QKR8SGvQo0xCzZljth1/img.png?width=1200&amp;amp;height=1200&amp;amp;face=76_260_649_884');&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;Introducing fine-grained IAM roles for service accounts | Amazon Web Services&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Here at AWS we focus first and foremost on customer needs. In the context of access control in Amazon EKS, you asked in issue #23 of our public container roadmap for fine-grained IAM roles in EKS. To address this need, the community came up with a number o&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;aws.amazon.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Dev&amp;amp;Ops/DevOps</category>
      <category>AWS</category>
      <category>devops</category>
      <category>eks</category>
      <category>IRSA</category>
      <category>springboot</category>
      <author>zeroneCoder</author>
      <guid isPermaLink="true">https://zerone-code.tistory.com/12</guid>
      <comments>https://zerone-code.tistory.com/12#entry12comment</comments>
      <pubDate>Sun, 11 Jun 2023 16:15:23 +0900</pubDate>
    </item>
    <item>
      <title>[CI/CD] GitHub Action AWS에 IAM Role로 접근하기</title>
      <link>https://zerone-code.tistory.com/11</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요!&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;zerone-code입니다.&lt;/b&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을 이용한다면 사용해봤을 GitHub Action에 대해 말해보고자 합니다.&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;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;GitHub Action을 이용해서 CI/CD를&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt; 많이 하는데, 이 과정에서 AWS에 접근하는 방법에 대해 다뤄보고자 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. GitHub Action에서 AWS&amp;nbsp; 접근하기&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GitHub Action에서 AWS를 접근하기 위해 정보를 찾아보면 대부분 I&lt;b&gt;AM User를 생성하고, Access Key ID와 Secret Access Key&lt;/b&gt;를 설정해서 사용하는 use case가 정말 많습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;676&quot; data-origin-height=&quot;260&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bRMNJH/btr1KwELKas/qyk0hME3ArthuKftNlS0b1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bRMNJH/btr1KwELKas/qyk0hME3ArthuKftNlS0b1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bRMNJH/btr1KwELKas/qyk0hME3ArthuKftNlS0b1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbRMNJH%2Fbtr1KwELKas%2Fqyk0hME3ArthuKftNlS0b1%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;320&quot; height=&quot;123&quot; data-origin-width=&quot;676&quot; data-origin-height=&quot;260&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1548&quot; data-origin-height=&quot;1288&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dbfnZT/btr1POZwjpf/vxyyEVOPveCyJtDs0Kmonk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dbfnZT/btr1POZwjpf/vxyyEVOPveCyJtDs0Kmonk/img.png&quot; data-alt=&quot;Action Secrets and variables&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dbfnZT/btr1POZwjpf/vxyyEVOPveCyJtDs0Kmonk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdbfnZT%2Fbtr1POZwjpf%2FvxyyEVOPveCyJtDs0Kmonk%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;609&quot; height=&quot;507&quot; data-origin-width=&quot;1548&quot; data-origin-height=&quot;1288&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Action Secrets and variables&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 설정에서 Action에서 사용될 secrets를 설정하고, Action에서 아래와 같이 설정해서 사용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 예시는 Access Key ID와 Secret Access Key를 적용해서 ECR에 접근하는 예시입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1677928192417&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;name: Java CI with Gradle

on:
  push:
    branches: [ &quot;main&quot; ]

env:
  AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
  AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
  
 jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout Src
      uses: actions/checkout@v3

    - name: Set up JDK 17
      uses: actions/setup-java@v3
      with:
        java-version: '17'
        distribution: 'temurin'
        
    # AWS credentials 설정
    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@v1
      with:
        aws-access-key-id: ${{ env.AWS_ACCESS_KEY_ID }}
        aws-secret-access-key: ${{ env.AWS_SECRET_ACCESS_KEY }}
        aws-region: ${{ env.AWS_REGION }}

    # AWS ECR 로그인
    - name: Login to Amazon ECR
      id: login-ecr
      uses: aws-actions/amazon-ecr-login@v1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 이게 과연 최선일까라는 고민을 하게 됐습니다. 요즘 보안사고가 많이 일어나고, 해킹사고도 많이 일어나기 때문에 Github가 해킹당한다면..?이라는 생각이 들었습니다. &lt;a href=&quot;https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html&quot; data-hook=&quot;linkViewer&quot;&gt;&lt;span style=&quot;color: #1155cc;&quot;&gt;&lt;u&gt;Security best practices in IAM&lt;/u&gt;&lt;/span&gt;&lt;/a&gt;에도 보면 Application에서는 IAM User가 아닌 IAM Role을 사용하길 권고하고 있습니다.&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;그래서 특정 User를 생성해서 사용하는 Key 기반이 아닌 Role기반으로 변경하는 것이 좋을 거 같다는 생각으로 접근을 했습니다.&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;분명히 Action도 Container 기반으로 돌기 때문에 Key를 기반으로 동작한다면 Role 기반으로도 동작하지 않을까라는 생각을 했습니다. 역시나... AWS에 리소스에 접근하기 위해서 IAM Role을 Assume하여 사용할 수 있었습니다.&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;3 가지 사전 작업&lt;/b&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;1. External Identity Provider 생성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html&quot; data-hook=&quot;linkViewer&quot;&gt;&lt;span style=&quot;color: #1155cc;&quot;&gt;IAM OIDC identity providers&lt;/span&gt;&lt;/a&gt;는 외부 자격 공급자(&lt;span style=&quot;background-color: #ffffff; color: #605e5e;&quot;&gt;external identity provider - IdP)로부터 AWS 계정에 접근할 수 있도록 아래와 같이 설정해줘야합니다. Provider URL에서 Assume을 할 수 있도록 Audience에 sts.amazoeaws.com을 지정해줍니다.&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #605e5e;&quot;&gt;&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;1718&quot; data-origin-height=&quot;1460&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWcEsl/btr1Vc6mssB/epUQBzwbD9qNUazBsNYUu1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWcEsl/btr1Vc6mssB/epUQBzwbD9qNUazBsNYUu1/img.png&quot; data-alt=&quot;Identity Providers&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWcEsl/btr1Vc6mssB/epUQBzwbD9qNUazBsNYUu1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWcEsl%2Fbtr1Vc6mssB%2FepUQBzwbD9qNUazBsNYUu1%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;616&quot; height=&quot;523&quot; data-origin-width=&quot;1718&quot; data-origin-height=&quot;1460&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Identity Providers&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. AWS IAM Role 생성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 GitHub Action에서 사용할 IAM Role을 생성해줍니다.&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;여기서 Trust Relationships에는 앞서서 생성해준 Identity Providers에서 생성한 IdP의 arn을 추가해주고, Role을 사용할 Condition으로 Assume role을 할 수 있도록 sts.amazonaws.com과 어떤 조직의 Repository에서 사용할지를 명시해줍니다.&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을 Orginization 내의 모든 Repository에서 사용할다면 &quot;repo:OrgName/*:*&quot;로 해주면 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1392&quot; data-origin-height=&quot;842&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QSXkA/btr1Y8oqj3Y/QY331KP4KgGQswcB01E791/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QSXkA/btr1Y8oqj3Y/QY331KP4KgGQswcB01E791/img.png&quot; data-alt=&quot;Trust Relationship&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QSXkA/btr1Y8oqj3Y/QY331KP4KgGQswcB01E791/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQSXkA%2Fbtr1Y8oqj3Y%2FQY331KP4KgGQswcB01E791%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;494&quot; height=&quot;299&quot; data-origin-width=&quot;1392&quot; data-origin-height=&quot;842&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Trust Relationship&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 Role을 이용해 사용할 IAM Policy들을 생성해서 붙여줍니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1650&quot; data-origin-height=&quot;608&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ct3VjQ/btr1Y8vcI83/P2Et5kGTd0lCckROK6IDlK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ct3VjQ/btr1Y8vcI83/P2Et5kGTd0lCckROK6IDlK/img.png&quot; data-alt=&quot;IAM Policy&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ct3VjQ/btr1Y8vcI83/P2Et5kGTd0lCckROK6IDlK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fct3VjQ%2Fbtr1Y8vcI83%2FP2Et5kGTd0lCckROK6IDlK%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;632&quot; height=&quot;233&quot; data-origin-width=&quot;1650&quot; data-origin-height=&quot;608&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;IAM Policy&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. GitHub Action에서 Role 적용&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 마지막 단계로 생성한 IAM Role을 Github Action에 적용해주는 과정입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 적용했던 Action의 yaml을 변경해보도록 하겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;env의 &lt;span&gt;Access Key ID와 Secret Access Key를&lt;span&gt; 제거해주고, 아래의 AWS 인증 부분에 role-to-assume에 앞서 만든 IAM Role의 arn을 지정해줍니다.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1677929690318&quot; class=&quot;go&quot; data-ke-language=&quot;go&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;name: Java CI with Gradle

on:
  push:
    branches: [ &quot;main&quot; ]
  
 jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout Src
      uses: actions/checkout@v3

    - name: Set up JDK 17
      uses: actions/setup-java@v3
      with:
        java-version: '17'
        distribution: 'temurin'
        
   # AWS 인증
    - name: configure aws credentials
      uses: aws-actions/configure-aws-credentials@v1
      with:
        role-to-assume: ${{ env.AWS_ROLE_NAME }}
        aws-region: ${{ env.AWS_DEFAULT_REGION }}

    # AWS ECR 로그인
    - name: Login to Amazon ECR
      id: login-ecr
      uses: aws-actions/amazon-ecr-login@v1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 session name을 지정해주기 위해서는 아래에 aws-region 아래에 role-session-name이라는 key로 지정을 해줍니다.&lt;/p&gt;
&lt;div&gt;
&lt;pre class=&quot;go&quot; data-ke-language=&quot;go&quot;&gt;&lt;code&gt;role-session-name: MySessionName&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 설정한 다음 GitHub Action을 다시 돌려보면 정상적으로 Role을 사용하여 AWS에 접근하는 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-03-04 오후 8.49.25.png&quot; data-origin-width=&quot;1322&quot; data-origin-height=&quot;544&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WHcMM/btr1UtAyIpa/MCQyEKOOwIXbIZZMgINtUK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WHcMM/btr1UtAyIpa/MCQyEKOOwIXbIZZMgINtUK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WHcMM/btr1UtAyIpa/MCQyEKOOwIXbIZZMgINtUK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWHcMM%2Fbtr1UtAyIpa%2FMCQyEKOOwIXbIZZMgINtUK%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;593&quot; height=&quot;244&quot; data-filename=&quot;스크린샷 2023-03-04 오후 8.49.25.png&quot; data-origin-width=&quot;1322&quot; data-origin-height=&quot;544&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-03-04 오후 8.55.19.png&quot; data-origin-width=&quot;1630&quot; data-origin-height=&quot;944&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bAiegm/btr115LTs9m/pfvnOEQW98niFHmiPkarw0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bAiegm/btr115LTs9m/pfvnOEQW98niFHmiPkarw0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bAiegm/btr115LTs9m/pfvnOEQW98niFHmiPkarw0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbAiegm%2Fbtr115LTs9m%2FpfvnOEQW98niFHmiPkarw0%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;599&quot; height=&quot;347&quot; data-filename=&quot;스크린샷 2023-03-04 오후 8.55.19.png&quot; data-origin-width=&quot;1630&quot; data-origin-height=&quot;944&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;되도록이면 IAM User의 AWS Acess Key와 Secret Key를 쓰지 않는 방법으로 Key의 유출을 최소화해서 보안사고를 막는 방법을 항상 생각하고 적용해야 할 것 같습니다.&lt;/b&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;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘 읽으셨다면 많은 공감과 구독 부탁드립니다!&lt;/b&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Reference&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/aws-actions/configure-aws-credentials&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/aws-actions/configure-aws-credentials&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1677931187522&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - aws-actions/configure-aws-credentials: Configure AWS credential environment variables for use in other GitHub Actions.&quot; data-og-description=&quot;Configure AWS credential environment variables for use in other GitHub Actions. - GitHub - aws-actions/configure-aws-credentials: Configure AWS credential environment variables for use in other Git...&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/aws-actions/configure-aws-credentials&quot; data-og-url=&quot;https://github.com/aws-actions/configure-aws-credentials&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ebfEAZ/hyROLct6AU/lEgqTuwK92C6TEoNVMia01/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/aws-actions/configure-aws-credentials&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/aws-actions/configure-aws-credentials&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ebfEAZ/hyROLct6AU/lEgqTuwK92C6TEoNVMia01/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - aws-actions/configure-aws-credentials: Configure AWS credential environment variables for use in other GitHub Actions.&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Configure AWS credential environment variables for use in other GitHub Actions. - GitHub - aws-actions/configure-aws-credentials: Configure AWS credential environment variables for use in other Git...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1677931168473&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;Security best practices in IAM - AWS Identity and Access Management&quot; data-og-description=&quot;Thanks for letting us know this page needs work. We're sorry we let you down. If you've got a moment, please tell us how we can make the documentation better.&quot; data-og-host=&quot;docs.aws.amazon.com&quot; data-og-source-url=&quot;https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html&quot; data-og-url=&quot;https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html&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;Security best practices in IAM - AWS Identity and Access Management&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Thanks for letting us know this page needs work. We're sorry we let you down. If you've got a moment, please tell us how we can make the documentation better.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.aws.amazon.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Dev&amp;amp;Ops/DevOps</category>
      <category>AWS</category>
      <category>bestpractice</category>
      <category>CI/CD</category>
      <category>GithubAction</category>
      <category>Iam</category>
      <category>Role</category>
      <category>Security</category>
      <author>zeroneCoder</author>
      <guid isPermaLink="true">https://zerone-code.tistory.com/11</guid>
      <comments>https://zerone-code.tistory.com/11#entry11comment</comments>
      <pubDate>Sat, 4 Mar 2023 21:03:41 +0900</pubDate>
    </item>
  </channel>
</rss>