<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>jay-side-project.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Mon, 24 Mar 2025 13:03:13 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>jay-side-project.log</title>
            <url>https://images.velog.io/images/jay-side-project/profile/7ba8a9fd-c064-4e8a-82b2-30d12f620df4/다람풍선유리컵용.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. jay-side-project.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/jay-side-project" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[구름 COMMIT 정리] 고객을 사로잡는 사용자 가이드 쓰기]]></title>
            <link>https://velog.io/@jay-side-project/%EA%B5%AC%EB%A6%84-COMMIT-%EC%A0%95%EB%A6%AC-%EA%B3%A0%EA%B0%9D%EC%9D%84-%EC%82%AC%EB%A1%9C%EC%9E%A1%EB%8A%94-%EC%82%AC%EC%9A%A9%EC%9E%90-%EA%B0%80%EC%9D%B4%EB%93%9C-%EC%93%B0%EA%B8%B0</link>
            <guid>https://velog.io/@jay-side-project/%EA%B5%AC%EB%A6%84-COMMIT-%EC%A0%95%EB%A6%AC-%EA%B3%A0%EA%B0%9D%EC%9D%84-%EC%82%AC%EB%A1%9C%EC%9E%A1%EB%8A%94-%EC%82%AC%EC%9A%A9%EC%9E%90-%EA%B0%80%EC%9D%B4%EB%93%9C-%EC%93%B0%EA%B8%B0</guid>
            <pubDate>Mon, 24 Mar 2025 13:03:13 GMT</pubDate>
            <description><![CDATA[<p>이 글은 2025년 3월 19일에 진행된 <a href="https://tech.goorm.io/ko/category/commit-ko/">구름 COMMIT</a> &lt;고객을 사로잡는 사용자 가이드 쓰기&gt;의 내용을 정리한 글입니다. </p>
<h1 id="테크니컬-라이팅이란-📝">테크니컬 라이팅이란 📝</h1>
<p>테크니컬 라이팅(Technical Writing)이란 이번 세미나에서 다룰 <strong>사용자 가이드</strong>의 상위 개념으로, 
&quot;특정 독자를 대상으로 특정 목적의 정보를 전달하는 글쓰기&quot;를 말한다. </p>
<h2 id="문학-글쓰기와-테크니컬-라이팅">문학 글쓰기와 테크니컬 라이팅</h2>
<p>문학 글쓰기와 다르게 <strong>사실</strong>을 <strong>명확하고 간결</strong>하게 <strong>특정 대상 독자</strong>에게 <strong>직설</strong>적이고 <strong>순차</strong>적으로 전달하는 것이 목적이다. 
그래서, 원칙을 가지고 연습을 한다면 <strong>누구나 잘 쓸 수 있다</strong>는 것이 큰 장점이다. </p>
<p>예를 들어보자. </p>
<p>먼저 문학 글쓰기의 예시는 다음과 같다. </p>
<blockquote>
<p>나는 버튼을 조심스럽게 눌렀고, 어둠 속에서 작은 녹색 불빛이 천천히 퍼져나갔다.</p>
</blockquote>
<p>같은 글을 테크니컬 라이팅에서는 다음과 같이 쓸 수 있다. </p>
<blockquote>
<p>가운데 전원 버튼을 눌러 장치를 켭니다. 전원이 켜지면 LED 표시 등이 녹색으로 변합니다.</p>
</blockquote>
<p>어떤 동작을 하면 어떤 반응이 나타나는지 사실만을 명확하고 간결하게 서술하고 있다. </p>
<h2 id="테크니컬-라이팅의-범위">테크니컬 라이팅의 범위</h2>
<p>테크니컬 라이팅 범주 안에 드는 문서, 즉 기술문서의 범위는 어디까지일까?</p>
<p><img src="https://velog.velcdn.com/images/jay-side-project/post/4daf88e1-972a-49d6-9e14-9eae7804bdb1/image.png" alt=""></p>
<p>제안서나 메일, 회의록도 기술 문서에 해당하는지 헷갈릴 수 있다. 
하지만 <strong>특정 독자가 있다면, 넓은 범위에서 모두 기술 문서</strong>에 해당한다. </p>
<h1 id="사용자-가이드란-📄">사용자 가이드란 📄</h1>
<p>그중에서도 이번 세미나의 주제인 사용자 가이드에 초점을 맞춰보자. 
사용자 가이드는 <strong>사용자가 제품을 빠르게 이해하고 활용하도록 지원한다</strong>는 점에서 중요한 문서이다.</p>
<p>대표적인 사용자 가이드로는 <a href="https://learn.microsoft.com/ko-kr/azure/">마이크로소프트 설명서</a>가 있다. </p>
<h2 id="핵심-역할">핵심 역할</h2>
<p>사용자는 즐기려고 가이드를 읽는 것이 아니라 <strong>문제를 해결하기 위해</strong> 읽는 것이므로 정확한 답변을 쉽고 빠르게 제공해야 한다.</p>
<p>다음과 같은 핵심 역할을 잘 기억해두자.</p>
<ul>
<li>사용자 경험 개선</li>
<li>고객 지원 부담 감소</li>
<li>제품 신뢰도 향상</li>
<li>글로벌 확장 지원</li>
</ul>
<h1 id="사용자-가이드-쓰기-👩💻">사용자 가이드 쓰기 👩‍💻</h1>
<p>사용자 가이드는 총 3단계로 나눠서 작성한다. 
<img src="https://velog.velcdn.com/images/jay-side-project/post/85693938-0597-4184-9681-53c0dc23712b/image.png" alt=""></p>
<h2 id="계획-수립">계획 수립</h2>
<p>사용자 가이드를 쓰기 전 계획을 세우는 단계이다. </p>
<h3 id="대상-독자-정하기">대상 독자 정하기</h3>
<p>가이드에서 다룰 기술의 깊이를 지정하기 위해서는 대상 독자의 범주를 정해야 한다. </p>
<p>대상 독자는 크게 다음과 같이 나눌 수 있을 것이다. </p>
<ul>
<li>개발자</li>
<li>기술 직군</li>
<li>비기술 직군</li>
</ul>
<p>대상 독자에 따라 다음과 같이 개념과 전문 용어를 어떻게 서술할지 기준을 정할 수 있다. 
(순서대로 개발자, 기술 직군, 비기술 직군)
<img src="https://velog.velcdn.com/images/jay-side-project/post/09822406-302a-4a04-b6cf-3527b503a774/image.png" alt="">
만약 대상 독자의 범위가 넓다면, 잘 아는 사람들은 건너뛸 수 있도록 가이드하는 것도 중요하다. </p>
<h3 id="가이드-유형-정하기">가이드 유형 정하기</h3>
<p>가이드의 유형으로는 빠른 시작 가이드, 튜토리얼, 매뉴얼, 레퍼런스, 문제 해결 가이드, 비디오 가이드, FAQ 등이 있다. 
서비스 특성에 따라 가장 어울리는 가이드 유형을 정해야 한다. </p>
<h3 id="일정-세우기">일정 세우기</h3>
<p>전체 단계인 <strong>계획 - 작성 - 고치기 / 검토</strong>에서 
마지막 단계인 <strong>고치기 / 검토</strong>에 전체 일정의 40% 정도의 시간을 할애하는 것이 가장 이상적이다. 
따라서 초안을 빠르게 작성하고 마지막 단계에 많은 시간을 쓰는 것이 좋다. </p>
<h3 id="스타일-가이드-만들기">스타일 가이드 만들기</h3>
<p>가이드는 함께 쓰는 경우가 많기 때문에 전체 문서의 일관성을 유지하기 위해 스타일 가이드를 잡는 것이 좋다. 시간이 걸리더라도 <strong>샘플 문서를 작성</strong>하고 어조, 템플릿, 스크린샷 환경, UI 요소 표현 등 <strong>스타일 요소 별로 가이드</strong>를 만들자.</p>
<p>스타일 요소 별로 살펴보자.</p>
<h4 id="어조">어조</h4>
<p>크게 해요체와 합쇼체로 나눌 수 있다. 서비스의 어조에 맞추면 되지만, 기본적으로 사용자 가이드는 친절하고 정중한 합쇼체를 사용하는 것을 추천한다. </p>
<blockquote>
<p>해요체: 버튼을 클릭해요.
합쇼체: 버튼을 클릭합니다.</p>
</blockquote>
<h4 id="ui-요소-표현">UI 요소 표현</h4>
<p>메뉴명이나 버튼명은 사용자 눈에 잘 보이게 표현하는 것이 좋다. 
&#39;작은 따옴표&#39;를 쓰거나 <strong>굵게</strong> 쓰거나 [대괄호]로 쓸 수 있다. 
일반적으로는 <strong>굵게</strong> 표시하는 경우가 많지만 불가능하다면 [대괄호]를 쓰기도 한다. </p>
<h2 id="초안-작성">초안 작성</h2>
<p>문서를 본격적으로 작성하는 단계이다.  </p>
<h3 id="3c-원칙">3C 원칙</h3>
<p>검토 단계에서 부담을 줄이려면 초안부터 3C 원칙에 맞추어 작성하는 것이 좋다. 
(이 원칙은 문서 작성 뿐 아니라 모든 의사소통에 적용됨)
<img src="https://velog.velcdn.com/images/jay-side-project/post/b4f36994-2528-47f7-81af-a6a5dd8faac4/image.png" alt=""></p>
<h4 id="용어와-약어-풀이">용어와 약어 풀이</h4>
<p>독자가 모르는 용어를 다시 찾아보지 않도록, 전문 용어는 풀이를 넣는 것이 좋다. 
약어는 문서에서 처음 나올 때 한 번 풀어쓰고, 이후에는 약어로 사용한다. 
편의상 사용하는 약어가 아닌, 사전에 등재된 약어만 줄여써야 한다. 
용어와 약어를 정리한 <a href="https://docs.aws.amazon.com/ko_kr/glossary/latest/reference/glos-chap.html">용어집</a>을 따로 만들어 제공하는 것이 가장 좋다. </p>
<h4 id="은어-사용에-주의">은어 사용에 주의</h4>
<p>판교체라고 불리는, 흔히 회사에서 통용되는 은어를 공식 문서에 쓰지 않도록 주의한다. 
만약 은어를 대체할 단어를 찾지 못하겠다면 상황을 설명해서 풀어쓴다.</p>
<blockquote>
<p>엑박이 뜨면 (X)
이미지가 표시되지 않으면 (O)</p>
</blockquote>
<h4 id="객관적인-근거나-수치-제시">객관적인 근거나 수치 제시</h4>
<p>사용자가 명확하게 받아들일 수 있도록 객관적인 정보를 포함하는 것이 좋다. </p>
<blockquote>
<p>앱 시작 시간이 너무 길면 알림을 보냅니다. (X)
앱 시작에 2초 이상 걸리면 알림을 보냅니다. (O)</p>
</blockquote>
<h4 id="대명사보다는-일반-명사-사용">대명사보다는 일반 명사 사용</h4>
<p>문학에서는 대명사로 지칭하는 경우가 많지만, 사용자 가이드는 필요한 부분만 보는 경우가 많으므로 대명사보다는 단어를 다시 쓰는 것이 좋다. </p>
<blockquote>
<p>새로 나온 공통 플랫폼을 알아보자. 이를 사용하면 유지보수 비용을 절약할 수 있다. (X)
새로 나온 공통 플랫폼을 알아보자. 공통 플랫폼을 사용하면 유지보수 비용을 절약할 수 있다. (O)</p>
</blockquote>
<p>링크를 연결할 때는 어떤 링크인지 명확하게 적으면 독자의 불필요한 행동을 줄일 수 있다. </p>
<blockquote>
<p>자세한 설명은 여기를 참고하세요. (X)
자세한 설명은 오류 코드를 참고하세요. (O)</p>
</blockquote>
<h4 id="쉽게-말하듯이-서술">쉽게 말하듯이 서술</h4>
<p>돌려 말하지 않고 사실을 단정적으로 전달해야 명확한 정보를 전달할 수 있다. </p>
<blockquote>
<p>결제 기능 편의를 제고하고자 익월 말까지 시스템을 정비할 예정입니다. (X)
결제 기능을 편하게 사용할 수 있게 다음 달 말까지 시스템을 정비할 예정입니다. (O)</p>
</blockquote>
<h4 id="의미없는-표현은-정리">의미없는 표현은 정리</h4>
<p>&#39;~을 진행한다&#39;처럼 의미 없이 사용되는 표현은 줄이고 간결한 문장을 사용한다. </p>
<blockquote>
<p>고객이 상품 등록 요청을 진행하면 담당자가 검토 처리를 한 후 5일 내에 결과를 전달하는 방식으로 이루어지고 있습니다. (X)
고객이 상품 등록을 요청하면 담당자가 검토 후 5일 내에 결과를 전달합니다. (O)</p>
</blockquote>
<h4 id="용어나-표현의-일관성을-유지">용어나 표현의 일관성을 유지</h4>
<p>용어 통일안을 구성하여, 같은 용어는 일관성을 유지해서 사용한다. </p>
<blockquote>
<p>인스턴스의 보안 그룹 ID를 지합니다. 시큐리티 그룹에는 instance와 통신할 수 있는 룰이 있어야 합니다. (X)</p>
</blockquote>
<h3 id="시각-자료">시각 자료</h3>
<p>이미지, 도해, 도표 등 시각 자료는 제작에 많은 시간이 걸리지만 독자의 이해를 돕기에 가장 좋은 요소이다. 
시각 자료를 활용할 때는 본문 내용과 일치하는지 확인하는 것도 중요하다. 
아무런 설명 없이 시각 자료부터 제시하기보다는 자료를 소개하는 글을 먼저 제시해서 독자의 이해도를 높이는 것이 좋다. </p>
<h3 id="글로벌-현지화">글로벌 현지화</h3>
<p>현지화는 단순 번역이 아닌 <strong>문화</strong>에 맞게 조정하는 과정이다.
현지 전문가의 도움을 빌려, 문화를 반영하는 것이 좋다. 
스크린샷에는 최대한 텍스트를 표시하지 않고 숫자나 기호로 표기하고 본문에서 설명하는 것이 현지화에 좋다. 
언어마다 같은 말도 길이가 다르므로 텍스트가 들어갈 공간은 50퍼센트 정도 여유를 두고 설계하자.</p>
<h3 id="우리말-순화">우리말 순화</h3>
<p>정작 우리나라에서 쓸 기술 문서에 외국어가 많이 사용되는 경우가 있다. 다음과 같이 우리말로 순화해서 사용하는 것이 좋다. </p>
<ul>
<li>적당한 우리말이 없다면 음차</li>
<li>전문 용어는 원문 병기</li>
<li>타사 서비스나 제품 이름은 고유 명사인 원문대로</li>
</ul>
<h2 id="고치기--검토">고치기 / 검토</h2>
<p>3단계 중 가장 중요한 단계로, 지금까지의 단계에서 해온 것을 모두 반복한다고 보면 된다. </p>
<h3 id="문서-구조">문서 구조</h3>
<p>목차 단계가 너무 깊어지면 목차의 역할을 하지 못 하는 것이다. 
장제목을 제외하고 3~4 단계로 구성하는 것이 좋다. 
만약 목차 단계가 깊어진다면 문서를 분리하는 것을 권장한다.</p>
<h3 id="문장과-맞춤법">문장과 맞춤법</h3>
<p>문장과 맞춤법은 문서의 신뢰도에도 영향을 준다. 
어느 정도 맞춤법을 알고 있는 것이 좋지만, 도구의 도움을 빌리는 것이 정확하다. </p>
<h3 id="동료-검토">동료 검토</h3>
<p>시간을 내서 동료끼리 서로 바꿔 읽는 것을 추천한다. 
이 과정으로 <strong>분석적 읽기</strong>를 연습하고 자신의 글을 되돌아 볼 수 있다. 
한 번에 모든 항목을 검토하기보다는 1회차는 본문 위주, 2회차는 구조 위주, 3회차는 링크 테스트 등 집중해서 볼 부분을 정해서 여러 번 읽는 것이 좋다. </p>
<h3 id="검토-방법">검토 방법</h3>
<p>분석적 읽기를 할 때는 다음과 같은 방법을 활용한다.</p>
<ul>
<li>객관화 - 하루 지나서 읽기</li>
<li>다른 감각 활용 - 소리 내어 읽기</li>
<li>매체 변경 - 인쇄해서 읽기</li>
</ul>
<h1 id="정리를-마치며">정리를 마치며</h1>
<p>이번 세미나는 사용자 가이드를 잘 쓰는 방법을 다뤘지만,
결국 핵심은 &#39;정보를 효과적으로 전달하는 글쓰기&#39;의 본질에 관한 이야기였다.</p>
<p>대상 독자를 고려하고, 명확하게 쓰고, 불필요한 표현은 줄이고, 용어를 일관되게 사용하는 것.
이 모든 원칙은 사용자 가이드뿐 아니라 기획 문서, 개발 문서, 심지어 블로그 글에도 똑같이 적용된다.</p>
<p>무엇을 설명하든, 글은 결국 누군가를 위한 도구인 만큼, 그 글이 잘 쓰였는지보다, 잘 전달됐는지가 더 중요하다고 생각한다.</p>
<p>그래서 이 세미나에서 배운 내용을 가이드 작성에만 한정 짓지 않고,
앞으로 내가 쓰는 모든 글에 한 번씩 적용해 보려고 한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Kubernetes] Pod Security Admission & Standard]]></title>
            <link>https://velog.io/@jay-side-project/PSA-PSS</link>
            <guid>https://velog.io/@jay-side-project/PSA-PSS</guid>
            <pubDate>Wed, 31 Jul 2024 04:40:24 GMT</pubDate>
            <description><![CDATA[<p>사용자에게 혼란을 줄 수 있다는 이유로 PodSecurityPolicy가 deprecated된 이후로 1.26 버전부터는 Pod Security Admission과 Pod Secrutiy Standard가 사용되게 되었다고 한다.</p>
<h1 id="pod-security-admission">Pod Security Admission</h1>
<p><a href="https://kubernetes.io/docs/concepts/security/pod-security-admission/">https://kubernetes.io/docs/concepts/security/pod-security-admission/</a></p>
<p>Kubernetes 클러스터에서 파드의 보안 설정을 제어하기 위해 기본 제공되는 Admission Controller이다.
PSA는 특정 네임스페이스에서 파드가 PSS를 충족하는지 확인하고, 이를 준수하지 않았을 경우에 3개 모드 중 하나로 작동한다.</p>
<h2 id="psa-mode">PSA Mode</h2>
<h3 id="enforce">Enforce</h3>
<ul>
<li>정책 위반 시, 해당 파드는 생성 불가/거부<h3 id="audit">Audit</h3>
</li>
<li>정책 위반 시, 감사로그에 기록</li>
<li>파드 생성에 영향은 없음<h3 id="warn">Warn</h3>
</li>
<li>정책 위반 시, 사용자에게 경고 메시지 출력</li>
<li>파드 생성에 영향은 없음<h1 id="pods-security-standard">Pods Security Standard</h1>
<a href="https://kubernetes.io/docs/concepts/security/pod-security-standards/">https://kubernetes.io/docs/concepts/security/pod-security-standards/</a><h2 id="표준-보안-정책-구분">표준 보안 정책 구분</h2>
<h3 id="privileged">Privileged</h3>
</li>
<li>모든 기능을 허용하는 가장 낮은 레벨의 보안 설정<h3 id="baseline">Baseline</h3>
</li>
<li>이미 알려진 권한 상승을 방지하기 위한 최소한의 제한 정책</li>
<li>Default 파드 설정은 허용</li>
</ul>
<p>예를 들면, 호스트 네임스페이스(PID, IPC, Network) 사용 불가, Pod를 Privileged 모드로 실행 불가, HostPath 사용 불가 등의 항목이 있다. </p>
<h3 id="restricted">Restricted</h3>
<ul>
<li>보안 모범 사례를 모두 준수하기 위한 엄격한 제한 정책</li>
</ul>
<p>Baseline에 해당하는 정책에 추가하여 Volume Type이 제한되거나, root 유저로 실행 불가, Seccomp 프로필 강제 등의 항목이 있다. </p>
<h1 id="사용법-📄">사용법 📄</h1>
<p>Namespace에 라벨을 추가하여 사용할 수 있다.</p>
<pre><code class="language-yaml">apiVersion: v1
kind: Namespace
metadata:
  name: policy-test
  labels:
    pod-security.kubernetes.io/enforce: baseline
    pod-security.kubernetes.io/warn: restricted</code></pre>
<p>이 경우, baseline 보안 정책에 대해서는 강제적으로 적용하도록 하고, restrict 보안 정책에 대해서는 경고 메시지만 출력하도록 할 수 있다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[HashiTalks: Japan 2023 Terraform의 올바른 디렉토리 구성에 대해 ]]></title>
            <link>https://velog.io/@jay-side-project/HashiTalks-Japan-2023-1-Terraform%EC%9D%98-%EC%98%AC%EB%B0%94%EB%A5%B8-%EB%94%94%EB%A0%89%ED%86%A0%EB%A6%AC-%EA%B5%AC%EC%84%B1%EC%97%90-%EB%8C%80%ED%95%B4</link>
            <guid>https://velog.io/@jay-side-project/HashiTalks-Japan-2023-1-Terraform%EC%9D%98-%EC%98%AC%EB%B0%94%EB%A5%B8-%EB%94%94%EB%A0%89%ED%86%A0%EB%A6%AC-%EA%B5%AC%EC%84%B1%EC%97%90-%EB%8C%80%ED%95%B4</guid>
            <pubDate>Mon, 22 May 2023 13:33:57 GMT</pubDate>
            <description><![CDATA[<p>최근 업로드 된 HashiTalks: Japan 중에 평소 궁금했던 주제가 몇 개 있어서 간단히 번역/정리했다. </p>
<p>아무래도 가장 많이 써 본 HashiCorp 제품이 Terraform이다보니, 주로 Terraform에 대한 영상부터 정리를 시작했지만, <em>시간이 되면</em> 다른 제품에 대한 내용도 정리해볼 생각이다. </p>
<p>오늘은 가장 먼저, <a href="https://youtu.be/raU19TGHD9w"><strong>Terraform의 올바른 디렉토리 구성이란 무엇인가</strong>에 대해 고찰해 본 경험을 소개해준 영상</a>을 듣고 정리해보았다.</p>
<h1 id="가장-좋은-terraform-디렉토리-구성에-대해-고찰해-본-결과">가장 좋은 Terraform 디렉토리 구성에 대해 고찰해 본 결과</h1>
<h2 id="terraform-코드-디렉토리-구성-패턴">Terraform 코드 디렉토리 구성 패턴</h2>
<p><img src="https://velog.velcdn.com/images/jay-side-project/post/dc4ef2c4-e415-455c-b94c-9e2e640f579e/image.JPG" alt="">
비교적 적은 리소스를 배포할 경우에는 한 개의 디렉토리에 필요한 파일을 넣어두고 사용할 수 있겠지만, <strong>리소스가 많거나 개발/스테이지/운영 등 배포할 환경이 다양한 경우</strong>, 디렉토리를 분리하고자 하는 요구사항이 있을 수 있다.</p>
<p>그런 경우에 구체적으로 어떤 식으로 디렉토리를 구분할 지에 대해서는 다양한 의견이 있겠지만, 이번에는 2개의 패턴을 골라서 비교를 해보았다. </p>
<h2 id="패턴-1-환경별로-구분하는-패턴">패턴 1: 환경별로 구분하는 패턴</h2>
<p><img src="https://velog.velcdn.com/images/jay-side-project/post/0de49c3c-2d25-40bc-bdb3-5b4fce028087/image.JPG" alt=""></p>
<p>첫번째는 <strong>최상위 디렉토리를 환경별로 구분하는 패턴</strong>이다.</p>
<p>각 환경에서 사용할 IaC 코드를 환경별 디렉토리에 저장하는 패턴이다. 
여러 환경에서 설정 값만 변경하여 같은 리소스를 정의하고 싶을 때는, 로컬 모듈로 정의하여 사용할 수도 있다. 
이렇게 사용하면 같은 소스를 디렉토리별로 모두 저장하는 것이 아니라 모듈을 호출하여 사용할 수 있다. </p>
<h2 id="패턴-2-리소스별로-구분하는-패턴">패턴 2: 리소스별로 구분하는 패턴</h2>
<p><img src="https://velog.velcdn.com/images/jay-side-project/post/819bb756-0cbf-49f8-af23-9f8c3c8d5600/image.JPG" alt=""></p>
<p>두번째는 <strong>최상위 디렉토리를 리소스별로 구분하는 패턴</strong>이다.</p>
<p>배포하고 싶은 리소스 종류에 따라 디렉토리를 구분하는 패턴이다. 
각각의 리소스 디렉토리 내에 환경별로 사용할 IaC 코드를 저장한다. 
위 이미지 상에 표현은 되어있지 않으나, 이 패턴에서도 로컬 모듈을 사용하여 중복되는 코드를 줄이는 것은 가능하다.</p>
<p>이제 두 패턴을 아래의 세가지 관점에서 비교해보려고 한다. </p>
<ul>
<li>apply 횟수</li>
<li>tfstate 파일 크기</li>
<li>동시작업 가능 수</li>
</ul>
<h2 id="1-apply-횟수">1) apply 횟수</h2>
<p>스테이지 환경을 구축하는 상황을 가정하고 비교해보았다.</p>
<p>패턴 1의 경우, envs/stg 내에서 <code>terraform apply</code>를 한 번만 실행하면 stg에 배포하고 싶은 리소스를 모두 배포할 수 있다. </p>
<p>패턴 2의 경우, 각 리소스 별 디렉토리 하위의 stg 디렉토리 내에서 <code>terraform apply</code>를 실행해야 하므로, 리소스 종류가 많아질수록 apply 실행 횟수가 많아진다.
다만, 스크립트를 작성하거나, <a href="https://www.runatlantis.io/">Atlantis</a> 등의 툴을 사용하여 실행 횟수를 줄이는 방법도 있다. </p>
<h2 id="2-tfstate-파일-크기">2) tfstate 파일 크기</h2>
<p>tfstate란, Terraform이 실제 환경에 배포되어 있는 리소스를 파악하고 관리하기 위해 사용되는 파일을 뜻한다. </p>
<p><code>terraform apply</code> 명령어가 실행되면 tfstate와 관련하여 크게 두 가지의 작업이 수행된다. 
하나는 tfstate의 내용을 읽어서 코드와 실제 환경 간의 차이점을 파악하는 것이다. 
다른 하나는 배포가 완료되고 난 후, 실제 환경에 어떤 변경이 있었는지를 tfstate에 기록하고, tfstate 파일의 내용을 실제 환경과 동일한 상태로 유지하는 것이다. </p>
<p>tfstate 파일이 관리하는 리소스가 많으면 많을수록, 즉 파일의 크기가 크면 클수록 plan/apply 명령이 수행되는 속도가 느려지게 된다. </p>
<p>이번에는 DB 리소스만을 변경하는 상황을 가정하고 비교해보았다.</p>
<p>패턴 1의 경우, 환경별 디렉토리 내에 모든 리소스에 대한 정의가 기록되어 있으므로, tfstate 파일의 크기가 리소스 양에 따라 커지게 된다. 
반면, 패턴 2의 경우, 리소스별로 디렉토리가 다르게 구성되어 있기 때문에 패턴 1에 비하여 tfstate 파일의 크기가 작다.</p>
<h2 id="3-동시작업-가능-수">3) 동시작업 가능 수</h2>
<p>여러 명이서 같은 환경에 리소스를 배포하고자 할 때, 동시에 얼마나 많은 사람이 같은 환경에 대해 작업이 가능한지를 비교하고자 한다. </p>
<p>이 내용은 앞서 말한 tfstate 파일과도 관련이 있는데, 패턴 1의 경우에는 모든 리소스가 하나의 tfstate 파일을 통해 관리되는 반면, 패턴 2의 경우에는 리소스별로 별도 tfstate 파일이 존재한다.</p>
<p>따라서 패턴 2는 plan/apply가 리소스별로 이루어지게 된다. </p>
<p>즉, 패턴 1에서는 같은 환경에 대해 하나의 tfstate 파일을 쓰기 때문에, 동시 작업이 불가능하다. 하지만 패턴 2에서는 같은 환경이더라도 리소스 종류가 다르면 동시에 작업이 가능하다. </p>
<h2 id="디렉토리-구성-비교-총평">디렉토리 구성 비교 총평</h2>
<p><img src="https://velog.velcdn.com/images/jay-side-project/post/aab8e020-b00b-4386-84b5-a92dc8206475/image.JPG" alt=""></p>
<p>세 가지 관점에서 비교해 본 결과, <strong>패턴 2가 패턴 1보다 효율적으로 사용될 수 있는 것</strong>으로 보인다. 
각자의 환경에 따라 어떤 구성이 맞는지는 다르겠지만, tfstate 파일을 작게 분할하는 것이 많은 리소스를 관리하는 환경에서는 더욱 적합할 수 있음을 알 수 있다.</p>
<p>필요에 따라 두 가지 패턴을 적재적소에 사용하는 것이 좋을 것으로 보인다.</p>
<h1 id="💡">💡</h1>
<p>Terraform에 대해 발표했을 때, Terraform Enterprise 운영자 역할을 했을 때, 가장 많이 들었던 질문 중 하나가 &quot;Terraform 디렉토리는 어떻게 구성하는 게 정답인가요?&quot;였다. 
이에 대해서 IaC 경험이 많은 분들께 물어보면, 그 때 그 때 다르다는 답을 해주셨고, 결국 나도 정답을 찾지 못해서 질문주신 분께 죄송하단 생각이 들기도 했다. 
그래서 이 영상의 제목만 보고, 이건 반드시 봐야겠다는 생각을 했다. 이 영상을 보고도 아직 정답은 찾지 못한 것 같긴하다. <del>아마 몇년간 Terraform 쓸 일이 없긴 하겠지만..</del> 그래도 언젠가, 누군가, 내게 Terraform 디렉토리 구성 어떻게 해야하나요?하고 질문하면 생각한 척이라도 한 번 해볼 수 있을 것 같다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Terraform Cloud - Dynamic Provider Credentials 기능]]></title>
            <link>https://velog.io/@jay-side-project/Terraform-Cloud-Dynamic-Provider-Credentials-%EA%B8%B0%EB%8A%A5</link>
            <guid>https://velog.io/@jay-side-project/Terraform-Cloud-Dynamic-Provider-Credentials-%EA%B8%B0%EB%8A%A5</guid>
            <pubDate>Sun, 16 Apr 2023 06:03:32 GMT</pubDate>
            <description><![CDATA[<p>HashiCorp 유튜브 채널을 보다가, <a href="https://youtu.be/6k1fn5Zfyk0">이전부터 필요했던 기능이 추가된 것</a>을 확인해서 간단하게 정리해보았다.</p>
<h1 id="dynamic-provider-credentials">Dynamic Provider Credentials</h1>
<p>Dynamic Provider Credentials 기능 이전에는 CSP 환경에 접근하기 위한 인증정보(키)를 정적인 변수로 등록해야 했다.</p>
<p><img src="https://velog.velcdn.com/images/jay-side-project/post/71d868c5-cd5b-4e69-a63a-957d8d3c18ae/image.png" alt=""></p>
<p>위와 같이 Workspace 별로 지정을 하거나, Organization에 Variable set을 지정하는 방식을 사용하였다. </p>
<p>이러한 방식은 플랫폼 팀의 운영 복잡도를 늘릴 뿐 아니라, 보안적인 리스크도 줄 수 있다는 위험성이 있었다. </p>
<p>Dynamic Provider Credentials를 사용하여, 기존처럼 키를 등록하는 것이 아니라 Role을 등록하여 동적으로 인증정보(키)를 발행하여 테라폼 클라우드에서 각 프로바이더로 인증을 할 수 있도록 변경되었다. </p>
<p><img src="https://velog.velcdn.com/images/jay-side-project/post/0769dcc8-edc8-4c14-9a50-c5ecb68b0ff7/image.png" alt=""></p>
<p>예를 들어, AWS 프로바이더에 동적으로 인증하기 위해서는 다음과 같은 변수를 지정한다.</p>
<ol>
<li>TFC_AWS_PROVIDER_AUTH
이 값을 true로 지정하면, TFC는 AWS 프로바이더에 인증을 할 때, Dynamic Provider Credentials를 사용하게 된다.</li>
<li>TFC_AWS_PLAN_ROLE_ARN: (ROLE ARN)
Plan 단계에서 인증을 할 때, 어떤 Role을 사용할 지 지정한다.</li>
<li>TFC_AWS_APPLY_ROLE_ARN: (ROLE ARN)
Apply 단계에서 인증을 할 때, 어떤 Role을 사용할 지 지정한다.</li>
</ol>
<p>현재 이 기능은 Vault, AWS, Azure, Google Cloud 프로바이더에서 사용이 가능하다.</p>
<h1 id="개선점">개선점</h1>
<ul>
<li>정적으로 인증정보를 입력하는 것에 비해 운영/관리 부담이 적어진다.</li>
<li>유효기간이 짧은 동적 인증정보를 사용하기 때문에 인증정보가 노출되거나 재이용될 위험이 감소한다.</li>
<li>워크스페이스 및 프로젝트 단위로 권한 부여가 가능하므로 최소권한만으로 Terraform Cloud를 사용할 수 있다.</li>
</ul>
<hr>
<p>여기까지가 영상에서 소개한 내용이고, 이후 내용은 데모라서 특별히 캡처하거나 정리하지 않았다.</p>
<p>Terraform Cloud/Enterprise를 Prod 환경에 적용함에 있어서 반드시 필요한 기능 중 하나가 드디어 추가된 것 같은 느낌이다. 기존에는 Terraform Enterprise에 크레덴셜을 입력하기 위해서 각각의 AWS 계정에서 IAM User를 만들고, 크레덴셜을 생성하고, 전달하고 입력하고, 사용기간이 길어지면 이 키를 교체하는 작업도 했어야 했는데, 이 부분에서 할 일이 간소화될 것 같다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[eksctl을 사용하여 EKS 클러스터 생성하기 (1.21 ver)]]></title>
            <link>https://velog.io/@jay-side-project/eksctl%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC-EKS-%ED%81%B4%EB%9F%AC%EC%8A%A4%ED%84%B0-%EC%83%9D%EC%84%B1%ED%95%98%EA%B8%B0-1.21-ver</link>
            <guid>https://velog.io/@jay-side-project/eksctl%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC-EKS-%ED%81%B4%EB%9F%AC%EC%8A%A4%ED%84%B0-%EC%83%9D%EC%84%B1%ED%95%98%EA%B8%B0-1.21-ver</guid>
            <pubDate>Sun, 03 Apr 2022 09:25:58 GMT</pubDate>
            <description><![CDATA[<h1 id="개요">개요</h1>
<p>eksctl은 Amazon EKS에서 Kubernetes 클러스터를 생성하고 관리하기 위한 명령줄 유틸리티이다. </p>
<p>본 문서에서는 eksctl을 실행할 수 있는 환경을 구성하고, 클러스터 및 노드 그룹을 생성하는 과정을 설명한다.</p>
<h1 id="사전-구성">사전 구성</h1>
<h2 id="iam-user-생성">IAM User 생성</h2>
<p>EKS 클러스터 생성을 위한 IAM User를 생성한다.</p>
<h3 id="액세스-유형">액세스 유형</h3>
<p>aws cli에 Credential을 등록하여 사용할 것이므로, <strong>프로그래밍 방식 액세스</strong>을 선택한다.</p>
<h3 id="연결-정책">연결 정책</h3>
<ul>
<li>AmazonEC2FullAccess (Managed)</li>
<li>AWSCloudFormationFullAccess (Managed)</li>
<li>EKSFullAccess </li>
</ul>
<pre><code class="language-json">{
    &quot;Version&quot;: &quot;2012-10-17&quot;,
    &quot;Statement&quot;: [
        {
            &quot;Effect&quot;: &quot;Allow&quot;,
            &quot;Action&quot;: &quot;eks:*&quot;,
            &quot;Resource&quot;: &quot;*&quot;
        },
        {
            &quot;Action&quot;: [
                &quot;ssm:GetParameter&quot;,
                &quot;ssm:GetParameters&quot;
            ],
            &quot;Resource&quot;: [
                &quot;arn:aws:ssm:*:&lt;account_id&gt;:parameter/aws/*&quot;,
                &quot;arn:aws:ssm:*::parameter/aws/*&quot;
            ],
            &quot;Effect&quot;: &quot;Allow&quot;
        },
        {
             &quot;Action&quot;: [
               &quot;kms:CreateGrant&quot;,
               &quot;kms:DescribeKey&quot;
             ],
             &quot;Resource&quot;: &quot;*&quot;,
             &quot;Effect&quot;: &quot;Allow&quot;
        },
        {
             &quot;Action&quot;: [
               &quot;logs:PutRetentionPolicy&quot;
             ],
             &quot;Resource&quot;: &quot;*&quot;,
             &quot;Effect&quot;: &quot;Allow&quot;
        }        
    ]
}</code></pre>
<ul>
<li>IAMLimitedAccess</li>
</ul>
<pre><code class="language-json">{
    &quot;Version&quot;: &quot;2012-10-17&quot;,
    &quot;Statement&quot;: [
        {
            &quot;Effect&quot;: &quot;Allow&quot;,
            &quot;Action&quot;: [
                &quot;iam:CreateInstanceProfile&quot;,
                &quot;iam:DeleteInstanceProfile&quot;,
                &quot;iam:GetInstanceProfile&quot;,
                &quot;iam:RemoveRoleFromInstanceProfile&quot;,
                &quot;iam:GetRole&quot;,
                &quot;iam:CreateRole&quot;,
                &quot;iam:DeleteRole&quot;,
                &quot;iam:AttachRolePolicy&quot;,
                &quot;iam:PutRolePolicy&quot;,
                &quot;iam:ListInstanceProfiles&quot;,
                &quot;iam:AddRoleToInstanceProfile&quot;,
                &quot;iam:ListInstanceProfilesForRole&quot;,
                &quot;iam:PassRole&quot;,
                &quot;iam:DetachRolePolicy&quot;,
                &quot;iam:DeleteRolePolicy&quot;,
                &quot;iam:GetRolePolicy&quot;,
                &quot;iam:GetOpenIDConnectProvider&quot;,
                &quot;iam:CreateOpenIDConnectProvider&quot;,
                &quot;iam:DeleteOpenIDConnectProvider&quot;,
                &quot;iam:TagOpenIDConnectProvider&quot;,                
                &quot;iam:ListAttachedRolePolicies&quot;,
                &quot;iam:TagRole&quot;
            ],
            &quot;Resource&quot;: [
                &quot;arn:aws:iam::&lt;account_id&gt;:instance-profile/eksctl-*&quot;,
                &quot;arn:aws:iam::&lt;account_id&gt;:role/eksctl-*&quot;,
                &quot;arn:aws:iam::&lt;account_id&gt;:oidc-provider/*&quot;,
                &quot;arn:aws:iam::&lt;account_id&gt;:role/aws-service-role/eks-nodegroup.amazonaws.com/AWSServiceRoleForAmazonEKSNodegroup&quot;,
                &quot;arn:aws:iam::&lt;account_id&gt;:role/eksctl-managed-*&quot;
            ]
        },
        {
            &quot;Effect&quot;: &quot;Allow&quot;,
            &quot;Action&quot;: [
                &quot;iam:GetRole&quot;
            ],
            &quot;Resource&quot;: [
                &quot;arn:aws:iam::&lt;account_id&gt;:role/*&quot;
            ]
        },
        {
            &quot;Effect&quot;: &quot;Allow&quot;,
            &quot;Action&quot;: [
                &quot;iam:CreateServiceLinkedRole&quot;
            ],
            &quot;Resource&quot;: &quot;*&quot;,
            &quot;Condition&quot;: {
                &quot;StringEquals&quot;: {
                    &quot;iam:AWSServiceName&quot;: [
                        &quot;eks.amazonaws.com&quot;,
                        &quot;eks-nodegroup.amazonaws.com&quot;,
                        &quot;eks-fargate.amazonaws.com&quot;
                    ]
                }
            }
        }
    ]
}</code></pre>
<p>User 생성 후 액세스 키와 비밀 키를 저장한다.</p>
<h2 id="aws-cli-업데이트-및-자격-증명-구성">AWS CLI 업데이트 및 자격 증명 구성</h2>
<h3 id="aws-cli-업데이트">AWS CLI 업데이트</h3>
<p>EKS 클러스터에 kubectl를 사용하여 접근하기 위해, AWS CLI를 버전 1.21 이상으로 업데이트한다.
다음 명령을 사용하여 AWS CLI를 최신 버전으로 업데이트할 수 있다.</p>
<pre><code class="language-bash">$ aws --version # 버전을 확인하여, 1.21 이하인 경우 업데이트
$ pip install awscli --upgrade --user</code></pre>
<p>위에서 생성한 IAM User의 Credential을 등록한다.</p>
<pre><code class="language-bash">$ aws configure</code></pre>
<h2 id="사용-툴-설치">사용 툴 설치</h2>
<h3 id="eksctl-설치">eksctl 설치</h3>
<p>eksctl 바이너리를 다운로드받아 설치한다.</p>
<pre><code class="language-bash">$ curl --silent --location &quot;https://github.com/weaveworks/eksctl/releases/download/latest_release/eksctl_$(uname -s)_amd64.tar.gz&quot; | tar xz -C /tmp
$ sudo mv -v /tmp/eksctl /usr/local/bin</code></pre>
<h3 id="kubectl-설치">kubectl 설치</h3>
<p>생성된 쿠버네티스 클러스터 API와 통신하기 위해 kubectl을 설치한다.</p>
<pre><code class="language-bash">$ curl -o kubectl https://amazon-eks.s3.us-west-2.amazonaws.com/1.21.2/2021-07-05/bin/linux/amd64/kubectl
$ chmod +x ./kubectl
$ mkdir -p $HOME/bin &amp;&amp; cp ./kubectl $HOME/bin/kubectl &amp;&amp; export PATH=$PATH:$HOME/bin
$ echo &#39;export PATH=$PATH:$HOME/bin&#39; &gt;&gt; ~/.bashrc
$ kubectl version --client</code></pre>
<h1 id="eks-클러스터-및-노드-그룹-생성">EKS 클러스터 및 노드 그룹 생성</h1>
<p>생성할 EKS 클러스터와 노드그룹의 정보는 다음과 같다.</p>
<table>
<thead>
<tr>
<th>클러스터 이름</th>
<th>eks-an2-cnl-dev</th>
</tr>
</thead>
<tbody><tr>
<td>쿠버네티스 버전</td>
<td>1.21</td>
</tr>
<tr>
<td>리전</td>
<td>ap-northeast-2</td>
</tr>
<tr>
<td>노드 그룹 이름</td>
<td>nodegroup-an2-cnl-dev</td>
</tr>
<tr>
<td>- 인스턴스 타입</td>
<td>t3.micro</td>
</tr>
<tr>
<td>- min</td>
<td>1</td>
</tr>
<tr>
<td>- desired</td>
<td>2</td>
</tr>
<tr>
<td>- max</td>
<td>3</td>
</tr>
</tbody></table>
<h2 id="flag를-사용하는-방법">flag를 사용하는 방법</h2>
<pre><code class="language-bash">$ eksctl create cluster \
        --name eks-an2-cnl-dev \
        --version 1.21 \
        --vpc-private-subnets SUBNET-ID-1,SUBNET-ID-2
        --without-nodegroup</code></pre>
<pre><code class="language-bash">$ eksctl create nodegroup \
        --cluster eks-an2-cnl-dev \
        --name nodegroup-an2-cnl-dev \
        --node-type t3.micro \
        --nodes 2 \
        --nodes-min 1 \
        --nodes-max 3 \
        --node-private-networking \
        --managed=false</code></pre>
<p>그 외에 사용할 수 있는 플래그는 다음과 같다.</p>
<pre><code class="language-bash">General flags:
  -n, --name string               EKS cluster name (generated if unspecified, e.g. &quot;scrumptious-sculpture-1648975311&quot;)
      --tags stringToString       A list of KV pairs used to tag the AWS resources (e.g. &quot;Owner=John Doe,Team=Some Team&quot;) (default [])
  -r, --region string             AWS region
      --zones strings             (auto-select if unspecified)
      --version string            Kubernetes version (valid options: 1.12, 1.13, 1.14, 1.15) (default &quot;1.14&quot;)
  -f, --config-file string        load configuration from a file (or stdin if set to &#39;-&#39;)
      --timeout duration          maximum waiting time for any long-running operation (default 25m0s)
      --install-vpc-controllers   Install VPC controller that&#39;s required for Windows workloads
      --managed                   Create EKS-managed nodegroup
      --fargate                   Create a Fargate profile scheduling pods in the default and kube-system namespaces onto Fargate

Initial nodegroup flags:
      --nodegroup-name string          name of the nodegroup (generated if unspecified, e.g. &quot;ng-46273157&quot;)
      --without-nodegroup              if set, initial nodegroup will not be created
  -t, --node-type string               node instance type (default &quot;m5.large&quot;)
  -N, --nodes int                      total number of nodes (for a static ASG) (default 2)
  -m, --nodes-min int                  minimum nodes in ASG (default 2)
  -M, --nodes-max int                  maximum nodes in ASG (default 2)
      --node-volume-size int           node volume size in GB
      --node-volume-type string        node volume type (valid options: gp2, io1, sc1, st1) (default &quot;gp2&quot;)
      --max-pods-per-node int          maximum number of pods per node (set automatically if unspecified)
      --ssh-access                     control SSH access for nodes. Uses ~/.ssh/id_rsa.pub as default key path if enabled
      --ssh-public-key string          SSH public key to use for nodes (import from local path, or use existing EC2 key pair)
      --node-ami string                Advanced use cases only. If &#39;ssm&#39; is supplied (default) then eksctl will use SSM Parameter; if &#39;auto&#39; is supplied then eksctl will automatically set the AMI based on version/region/instance type; if static is supplied (deprecated), then static AMIs will be used; if any other value is supplied it will override the AMI to use for the nodes. Use with extreme care.
      --node-ami-family string         Advanced use cases only. If &#39;AmazonLinux2&#39; is supplied (default), then eksctl will use the official AWS EKS AMIs (Amazon Linux 2); if &#39;Ubuntu1804&#39; is supplied, then eksctl will use the official Canonical EKS AMIs (Ubuntu 18.04). (default &quot;AmazonLinux2&quot;)
  -P, --node-private-networking        whether to make nodegroup networking private
      --node-security-groups strings   Attach additional security groups to nodes, so that it can be used to allow extra ingress/egress access from/to pods
      --node-labels stringToString     Extra labels to add when registering the nodes in the nodegroup, e.g. &quot;partition=backend,nodeclass=hugememory&quot; (default [])
      --node-zones strings             (inherited from the cluster if unspecified)

Cluster and nodegroup add-ons flags:
      --asg-access            enable IAM policy for cluster-autoscaler
      --external-dns-access   enable IAM policy for external-dns
      --full-ecr-access       enable full access to ECR
      --appmesh-access        enable full access to AppMesh
      --alb-ingress-access    enable full access for alb-ingress-controller

VPC networking flags:
      --vpc-cidr ipNet                 global CIDR to use for VPC (default 192.168.0.0/16)
      --vpc-private-subnets strings    re-use private subnets of an existing VPC
      --vpc-public-subnets strings     re-use public subnets of an existing VPC
      --vpc-from-kops-cluster string   re-use VPC from a given kops cluster
      --vpc-nat-mode string            VPC NAT mode, valid options: HighlyAvailable, Single, Disable (default &quot;Single&quot;)</code></pre>
<h2 id="config-file을-사용하는-방법">Config File을 사용하는 방법</h2>
<p>config.yaml</p>
<pre><code class="language-yaml">apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: eks-an2-cnl-dev
  region: ap-northeast-2
  version: 1.21

vpc:
  subnets:
    private:
      ap-northeast-2a: {id: [SUBNET-ID-1]}
      ap-northeast-2b: {id: [SUBNET-ID-2]}

nodeGroups:
  - name: nodegroup-an2-cnl-dev
    instanceType: t3.micro
    desiredCapacity: 2
    minCapacity: 1
    maxCapacity: 3
    privateNetworking: true</code></pre>
<p>EKS 클러스터 생성을 위한 Config File을 작성한다.
아래 설정 파일은 기존에 구성된 VPC 내에 EKS 클러스터를 생성하고, 노드가 2개인 노드그룹을 생성한다.
그 외의 설정에 대해서는 다음 링크를 참고한다.</p>
<p><a href="https://eksctl.io/usage/creating-and-managing-clusters">https://eksctl.io/usage/creating-and-managing-clusters</a></p>
<pre><code class="language-yaml">apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: eks-an2-cnl-birdbox-0
  region: ap-northeast-2

vpc:
  subnets:
    private:
      ap-northeast-2a: {id: [subnet-id]}
      ap-northeast-2b: {id: [subnet-id]}

nodeGroups:
  - name: ng-1-workers
    labels: {role: worker}
    instanceType: t2.micro
    desiredCapacity: 2
    privateNetworking: true</code></pre>
<p>작성한 config 파일을 기반으로 클러스터를 생성하기 위해 eksctl crate cluster 명령을 사용한다.</p>
<pre><code class="language-bash">$ eksctl create cluster -f cluster.yaml</code></pre>
<p>kubectl 명령으로 생성된 노드를 확인할 수 있다.</p>
<pre><code class="language-bash">$ kubectl get nodes</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[eksctl을 사용하여 EKS 클러스터 생성하기 (1.15 ver)]]></title>
            <link>https://velog.io/@jay-side-project/eksctl%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC-EKS-%ED%81%B4%EB%9F%AC%EC%8A%A4%ED%84%B0-%EC%83%9D%EC%84%B1%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@jay-side-project/eksctl%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC-EKS-%ED%81%B4%EB%9F%AC%EC%8A%A4%ED%84%B0-%EC%83%9D%EC%84%B1%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sat, 02 Apr 2022 13:08:45 GMT</pubDate>
            <description><![CDATA[<p>본문 작성일은 2020년 7월 14일로, 현 시점에서의 생성 방법과 다를 수 있음.</p>
<h1 id="개요">개요</h1>
<p>eksctl은 Amazon EKS에서 Kubernetes 클러스터를 생성하고 관리하기 위한 명령줄 유틸리티이다. 본 문서에서는 eksctl을 실행할 수 있는 환경을 구성하고, 클러스터 및 노드 그룹을 생성하는 과정을 설명한다.</p>
<h1 id="사전-구성">사전 구성</h1>
<h2 id="iam-user-생성">IAM User 생성</h2>
<p>EKS 클러스터 생성을 위한 IAM User를 생성한다. </p>
<ul>
<li>액세스 유형: 프로그래밍 방식 액세스</li>
<li>연결 정책: AdministratorAccess</li>
</ul>
<p>User 생성 후 액세스 키와 비밀 키를 저장한다.</p>
<h2 id="aws-cli-업데이트-및-자격-증명-구성">AWS CLI 업데이트 및 자격 증명 구성</h2>
<p>EKS 클러스터에 kubectl를 사용하여 접근하기 위해, AWS CLI를 버전 1.18.17 이상으로 업데이트한다.
다음 명령을 사용하여 AWS CLI를 최신 버전으로 업데이트한다.</p>
<pre><code class="language-bash">$ pip install awscli --upgrade --user</code></pre>
<p>위에서 생성한 IAM User의 자격 증명을 구성한다. </p>
<pre><code class="language-bash">$ aws configure</code></pre>
<h1 id="eksctl-설치">eksctl 설치</h1>
<p>eksctl을 설치한다.</p>
<pre><code class="language-bash">$ curl --silent --location &quot;https://github.com/weaveworks/eksctl/releases/latest/download/eksctl$(uname -s)_amd64.tar.gz&quot; | tar xz -C .tmp
$ sudo mv /tmp/eksctl /usr/local/bin</code></pre>
<p>Kubernetes 클러스터에 인증할 수 있도록 aws-iam-authenticator를 설치한다. </p>
<pre><code class="language-bash">$ curl -o aws-iam-authenticator https://amazon-eks.s3.us-west-2.amazonaws.com/1.16.8/2020-04-16/bin/linux/amd64/aws-iam-authenticator
$ chmod +x ./aws-iam-authenticator
$ mkdir -p $HOME/bin &amp;&amp; cp ./aws-iam-authenticator $HOME/bin/aws-iam-authenticator &amp;&amp; export PATH=$PATH:$HOME/bin
$ echo &#39;export PATH=$PATH:$HOME/bin&#39; &gt;&gt; ~/.bashrd
$ aws-iam-authenticator help</code></pre>
<p>kubectl을 설치한다.</p>
<pre><code class="language-bash">$ curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt` /bin/linux/amd63/kubectl
$ chmod +x ./kubectl
$ sudo mv ./kubectl /usr/local/bin/kubectl
$ kubectl version --client</code></pre>
<h1 id="eks-클러스터-및-노드-그룹-생성">EKS 클러스터 및 노드 그룹 생성</h1>
<p>EKS 클러스터 생성을 위한 Config File을 작성한다.
아래 설정 파일은 기존에 구성된 VPC 내에 EKS 클러스터를 생성하고, 노드가 2개인 노드그룹을 생성한다.
그 외의 설정에 대해서는 다음 링크를 참고한다.</p>
<p><a href="https://eksctl.io/usage/creating-and-managing-clusters">https://eksctl.io/usage/creating-and-managing-clusters</a></p>
<pre><code class="language-yaml">apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: eks-an2-cnl-birdbox-0
  region: ap-northeast-2

vpc:
  subnets:
    private:
      ap-northeast-2a: {id: [subnet-id]}
      ap-northeast-2b: {id: [subnet-id]}

nodeGroups:
  - name: ng-1-workers
    labels: {role: worker}
    instanceType: t2.micro
    desiredCapacity: 2
    privateNetworking: true
    ssh:
      allow:true</code></pre>
<p>작성한 config 파일을 기반으로 클러스터를 생성하기 위해 eksctl crate cluster 명령을 사용한다. </p>
<pre><code class="language-bash">$ eksctl create cluster -f cluster.yaml</code></pre>
<p>kubectl 명령으로 생성된 노드를 확인할 수 있다.</p>
<pre><code class="language-bash">$ kubectl get nodes</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Calico Cloud/Enterprise에 대해 알아보자]]></title>
            <link>https://velog.io/@jay-side-project/Calico-Cloud%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC-Kubernetes-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EB%B3%B4%EC%95%88-%EA%B0%95%ED%99%94%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@jay-side-project/Calico-Cloud%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC-Kubernetes-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EB%B3%B4%EC%95%88-%EA%B0%95%ED%99%94%ED%95%98%EA%B8%B0</guid>
            <pubDate>Tue, 22 Feb 2022 16:34:38 GMT</pubDate>
            <description><![CDATA[<h1 id="개요">개요</h1>
<p>Kubernetes의 CNI 플러그인으로 유명한 Calico. 
Calico를 사용하면 어떤 점이 좋을지, Calico 솔루션의 종류에는 어떤 것이 있는지, 어떻게 시작하면 될 지 간단 정리해보았습니다.</p>
<h1 id="들어가기-전-알아두면-좋을">들어가기 전, 알아두면 좋을</h1>
<h2 id="클라우드-네이티브-아키텍처">클라우드 네이티브 아키텍처</h2>
<h3 id="전통적인-아키텍처와의-차이점">전통적인 아키텍처와의 차이점</h3>
<h4 id="전통적인-아키텍처">전통적인 아키텍처</h4>
<ul>
<li>호스트 또는 가상머신 단위로 구성</li>
<li>워크로드는 대부분 정적이며, 라이프사이클이 긴 편</li>
<li>perimeter 기반의 보안에 의존</li>
<li>전통적인 모니터링 방식 사용<h4 id="클라우드-네이티브-아키텍처-1">클라우드 네이티브 아키텍처</h4>
</li>
<li>컨테이너 단위로 구성</li>
<li>워크로드는 대부분 동적이고 라이프사이클이 짧은 마이크로서비스로 구성</li>
<li>perimeter 기반의 보안으로는 충분하지 않음</li>
<li>분산형 애플리케이션의 모니터링 방안 필요<h3 id="쿠버네티스-기반-클라우드-네이티브-아키텍처의-문제점">(쿠버네티스 기반) 클라우드 네이티브 아키텍처의 문제점</h3>
<h4 id="보안-문제점">보안 문제점</h4>
</li>
<li>Pod/Service 수준의 ingress/egress 접근제어 어려움</li>
<li>CSP 사 마다 서로 다른 보안 정책 관리 방식을 채택하고 있으므로, 보안 정책 통합 관리가 어려움</li>
<li>동적인 특성(자주 변경되는 IP 등)으로 인한 정책 적용의 어려움</li>
<li>East-West 제어의 부재로 인해 파드 간 통신 제어 어려움</li>
<li>기존에 사용하던 방화벽 또는 SIEM과의 연동 어려움<h4 id="모니터링-문제점">모니터링 문제점</h4>
</li>
<li>가시성 미확보로 인한 상황 파악의 어려움</li>
<li>세분화된 마이크로서비스에 대한 추적 어려움</li>
<li>컨테이너 추상화 및 다양한 컴포넌트로 인해 기존 툴로 분석하기 어려움<h1 id="calico">Calico</h1>
<h2 id="calico-project">Calico Project</h2>
</li>
<li>Tigera사가 개발/운영하고 있는 오픈소스 프로젝트로 쿠버네티스에서 가장 많이 사용되는 CNI 플러그인</li>
<li>대부분의 CSP 및 쿠버네티스 배포판에서 지원되며, 쿠버네티스 외에 VM이나 베어메탈 수준까지 지원</li>
<li>기본적인 Kubernetes NetworkPolicy를 확장하여 보안을 강화</li>
<li>Rancher RKE, IBM Cloud, Mirantis MKE 등에서 디폴트 CNI 플러그인으로 채택</li>
</ul>
<h2 id="calico-cloudenterprise">Calico Cloud/Enterprise</h2>
<ul>
<li>Calico Cloud/Enterprise는 Calico OSS 기반으로 구축된 솔루션으로, 네트워크 정책 및 Observability, 보안 컴플라이언스 등을 제공</li>
<li>Calico Cloud는 SaaS로 제공되며, Calico Enterprise는 온프레미스 또는 클라우드에 직접 설치하여 사용하는 Self-managed 서비스<h3 id="calico-cloud-구조">Calico Cloud 구조</h3>
<img src="https://images.velog.io/images/jay-side-project/post/d360d2d1-86fa-49b9-b91c-1c754023be2b/image.png" alt=""><h3 id="calico-enterprise-구조">Calico Enterprise 구조</h3>
<img src="https://images.velog.io/images/jay-side-project/post/92b00087-2d5c-413c-abbf-5226b6b8bf94/image.png" alt=""></li>
</ul>
<h1 id="calico-cloudenterprise의-특장점">Calico Cloud/Enterprise의 특장점</h1>
<h2 id="🧭-north-south-control">🧭 North-South Control</h2>
<h3 id="egress-접근-제어">Egress 접근 제어</h3>
<p>쿠버네티스는 외부의 다양한 리소스에 안전하게 접근하기 위해 Egress 트래픽을 제어할 필요가 있으나, 쿠버네티스에서는 IP 등이 고정되어 있지 않으므로, FQDN 또는 IP 주소 기반의 전통적인 접근제어 방식을 사용하기는 어려운 점이 있다.
Calico에서는 3가지 방식으로 Egress 접근 제어를 하고 있다.</p>
<h4 id="1-dns-policy">1) DNS Policy</h4>
<ul>
<li>클러스터 외부 접근 제어를 위해 Calico 보안 정책에서 도메인 이름 사용을 활성화</li>
<li>Pod 별 표준 Label을 기반으로 외부 접근 제어<h4 id="2-egress-gateway">2) Egress Gateway</h4>
</li>
<li>각 네임스페이스에 Routable IP를 할당</li>
<li>네임스페이스에 속한 Pod의 모든 Egress 트래픽에 대해 할당된 IP 주소로 NAT</li>
<li>접근제어 정책을 클러스터 외부에서 정의 가능<h4 id="3-aws-sg-통합">3) AWS SG 통합</h4>
</li>
<li>Annotation을 추가하여 AWS SG와 통합</li>
<li>ingress/egress 모두 제어 가능<h3 id="기존-방화벽-및-siem-연동">기존 방화벽 및 SIEM 연동</h3>
방화벽이나 SIEM 등 기존에 사용하던 시스템과 절차를 활용하여 쿠버네티스 워크로드를 보호할 수 있다. 
기존의 방화벽 규칙은 정적인 source 및 destination IP 주소가 필요하지만, 쿠버네티스에서는 IP가 계속해서 바뀌기 때문에 규칙 적용이 어렵다는 문제점이 있다. 
Calico에서는 다음과 같은 방법으로 문제를 해결하고 기존 시스템과 통합을 가능하게 한다.<h4 id="1-calico-egress-gateway를-통하여-방화벽과-통합">1) Calico Egress Gateway를 통하여 방화벽과 통합</h4>
</li>
<li>네임스페이스에 Routable IP를 할당하고 네임스페이스 내 모든 Pod에 해당 IP를 할당하여 방화벽 규칙에서 IP 사용 가능</li>
<li>쿠버네티스 리소스가 방화벽 뒷단의 엔드포인트에 접근하도록 함<h4 id="2-방화벽-관리시스템을-쿠버네티스로-확장">2) 방화벽 관리시스템을 쿠버네티스로 확장</h4>
</li>
<li>방화벽 규칙을 쿠버네티스 Network Policy로 변환하여, 보안팀이 쿠버네티스 또는 YAML 등에 대해 학습할 필요 없이 전통적인 워크로드와 같이 Segmentation할 수 있음</li>
</ul>
<h2 id="🚅-east-west-control">🚅 East-West Control</h2>
<p>클라우드 환경에서는 클라우드 서비스 간 공통 세그멘테이션 모델이 없다는 한계점이 있다. 또한, 클라우드 워크로드는 기존의 워크로드에 비해 빠르게 확장되고 동적으로 변화하지만 기존의 세그멘테이션 도구들은 정적인 워크로드에 특화되어 설계 되어있다. 그 뿐 아니라 기존의 세그멘테이션 도구들은 애플리케이션의 확장성을 지원하지 못해 배포시에 지연이 발생하거나 서비스 중단으로 이어지는 경우도 있을 수 있다.
Calico에서는 Microsegmentation을 통해서 위와 같은 문제를 해결하였다.</p>
<h3 id="microsegmentation">Microsegmentation</h3>
<ul>
<li>모든 클라우드, Host, VM, 컨테이너 등에 공통으로 적용할 수 있는 세그멘테이션 모델을 통해 단일 관리포인트를 마련</li>
<li>세그멘테이션을 위해 Label을 사용하여, 새로운 워크로드를 위해 정책을 변경할 필요가 없음 </li>
<li>빠른 오토스케일링을 지원하여 워크로드 변화에 따른 서비스 장애 가능성을 제거 <h2 id="🚨-security-compliance">🚨 Security Compliance</h2>
기존의 워크로드와 마찬가지로 쿠버네티스 상의 워크로드도 기존 조직의 보안 규제사항을 준수해야 하지만, 기존의 규제 도구는 쿠버네티스 상의 워크로드에 적합하지 않다. 또한, 규제 준수를 입증하기 위한 리포트 등을 제공하는 것이 번거롭다는 점도 문제가 될 수 있다. 침해 관점에서는, 쿠버네티스는 개방적인 속성으로 인해 침해의 타겟이 되고 있지만, 전통적인 침입탐지 시스템은 쿠버네티스 워크로드에 적용하기에는 한계점이 있다. </li>
</ul>
<p>Calico에서는 위와 같은 문제를 해결하기 위해 Compliance 리포트 기능을 제공하고, IDS for Kubernetes를 제공한다.</p>
<h3 id="security-compliance-report">Security Compliance Report</h3>
<p><img src="https://images.velog.io/images/jay-side-project/post/e93a1b0e-0f89-48fb-8c9a-0794db10102f/image.png" alt=""></p>
<ul>
<li>감사에 필요한 증빙 보고서를 쉽게 생성 및 확인 가능하도록 대시보드와 리포트를 제공</li>
<li>내/외부 규제 요구사항(PCI, GDPR 등) 준수 여부를 확인할 수 있는 컴플라이언스 보고서 및 보고서에 대한 Audit 로그를 제공</li>
</ul>
<h3 id="ids-for-kubernetes">IDS for Kubernetes</h3>
<p><img src="https://images.velog.io/images/jay-side-project/post/7a4189fa-636b-4f52-b342-f87575508c26/image.png" alt=""></p>
<ul>
<li>Calico 침입탐지 시스템은 악의적인 활동의 소스를 찾아내고 머신러닝을 통해 비정상동작을 탐지</li>
<li>클러스터 외부의 악의적인 트래픽 소스를 확인할 수 있는 화면을 제공</li>
<li>클러스터 내에 미끼 역할을 하는 Honeypods를 설치</li>
<li>주요 SIEM과의 통합을 통해 정확도가 높은 경고를 발생시킴</li>
</ul>
<h2 id="📊-observability">📊 Observability</h2>
<p>쿠버네티스 내에서 발생한 문제 해결을 위해 클러스터 전반에 걸친 가시성 확보가 필요하다. 서비스가 서로 어떻게 통신하고 있으며, 어느 서비스가 문제를 발생시키고 있는지 등 클러스터 내 통신에 대한 가시성 확보를 위해 Calico는 다양한 도구를 제공한다.</p>
<h3 id="1-dynamic-service-graph">1) Dynamic Service Graph</h3>
<p><img src="https://images.velog.io/images/jay-side-project/post/62ea3f83-a1f8-4034-878f-509a4a90047b/image.png" alt=""></p>
<ul>
<li>세부 서비스 통신 현황을 동적으로 시각화하여 클러스터 내에서 서비스가 어떻게 통신하고 운영되는지 파악할 수 있음</li>
<li>문제 발생 시에는 경고를 발생시키고 Service Graph 상에 표시</li>
<li>필터링을 통해 원하는 리소스만 확인할 수 있음<h3 id="2-application-level-observability">2) Application Level Observability</h3>
<img src="https://images.velog.io/images/jay-side-project/post/503261da-3539-4084-9fe3-5b7225286165/image.png" alt=""></li>
</ul>
<blockquote>
<p>기존의 데브옵스 팀은 1) 모니터링이 필요한 부분 정의 2) 문제의 영향도 이해 및 해결 방안 파악 3) 애플리케이션 계층 데이터 보호를 위한 방법 고민하는 과정으로 문제를 해결</p>
</blockquote>
<ul>
<li>대부분 서비스 간의 트래픽을 효과적으로 파악할 수 있음</li>
<li>Kibana와 연동하여 L7 네트워크 가시성 제공 및 HTTP 등 어플리케이션 수준 트래픽에 대한 플로우 로그 제공</li>
<li>모든 데이터는 WireGuard를 통해 암호화됨 </li>
</ul>
<h3 id="3-flow-visualizer">3) Flow Visualizer</h3>
<p><img src="https://images.velog.io/images/jay-side-project/post/7971eeb4-b577-4688-a17c-563555362569/image.png" alt=""></p>
<ul>
<li><p>기존에도 서비스 메시를 사용하여 서비스 흐름을 가시화할 수 있었으나, 서비스 메시를 사용하는 경우 사이드카 컨테이너가 추가되기 때문에 관리대상 컨테이너가 증가하고, 시스템 리소스 사용률도 증가</p>
</li>
<li><p>별도 사이드카 추가하지 않아도 파드나 네임스페이스에 대한 네트워크 흐름 표현 가능</p>
</li>
<li><p>빠르게 문제 원인을 파악할 수 있도록 쿠버네티스의 플로우 로그를 제공</p>
</li>
<li><p>대화형 방식의 UI를 통해 네트워크 플로우 파악 가능</p>
</li>
<li><p>필터링을 통해 필요한 플로우만 확인할 수 있고, 해당하는 팀에 특정 플로우만 보여줄 수 있도록 RBAC 지원</p>
<h3 id="4-dynamic-packet-capture">4) Dynamic Packet Capture</h3>
<p><img src="https://images.velog.io/images/jay-side-project/post/3a92b626-0a09-4fae-8499-05c2b608822b/image.png" alt=""></p>
</li>
<li><p>쿠버네티스 클러스터에서 네트워크 트래픽을 캡쳐하기 위한 단일 또는 다중 워크로드 엔드포인트 식별</p>
</li>
<li><p>수동 프로세스를 제거하였기 때문에, 패킷 캡쳐 및 분석을 수행하고 문제를 해결하는데 필요한 노력과 시간 감소</p>
</li>
<li><p>생성된 PCAP 파일은 클라우드 내에 저장ㅍ</p>
</li>
</ul>
<h3 id="5-dns-dashboard">5) DNS Dashboard</h3>
<p><img src="https://images.velog.io/images/jay-side-project/post/c7bc716b-a392-4e57-8540-5755dba0031f/image.png" alt=""></p>
<ul>
<li>전체 DNS 쿼리 및 응답수 확인, 레코드 타입으로 쿼리 및 응답 분류 가능</li>
<li>마이크로 서비스 및 애플리케이션의 연동 이슈에 대해 DNS가 그 원인인지 파악</li>
<li>침해된 도메인 파악에 도움</li>
</ul>
<h1 id="참고자료">참고자료</h1>
<p>Tigera: <a href="https://www.tigera.io/">https://www.tigera.io/</a>
Calico Enterprise 소개 및 데모: <a href="https://youtu.be/I_d12dAVI_s">https://youtu.be/I_d12dAVI_s</a>
AWS MODERNIZATION WITH CALICO: <a href="https://tigera.awsworkshop.io/">https://tigera.awsworkshop.io/</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Kubernetes] 리소스 정적 분석하기]]></title>
            <link>https://velog.io/@jay-side-project/Kubernetes-%EB%A6%AC%EC%86%8C%EC%8A%A4-%EC%A0%95%EC%A0%81-%EB%B6%84%EC%84%9D%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@jay-side-project/Kubernetes-%EB%A6%AC%EC%86%8C%EC%8A%A4-%EC%A0%95%EC%A0%81-%EB%B6%84%EC%84%9D%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sun, 02 Jan 2022 11:27:37 GMT</pubDate>
            <description><![CDATA[<h2 id="유저-워크로드에-대한-정적-분석">유저 워크로드에 대한 정적 분석</h2>
<p><img src="https://images.velog.io/images/jay-side-project/post/847bd814-58b4-4861-8869-3c3c85d3db63/image-20220101234528518.png" alt=""></p>
<p>kubectl을 사용해서 Pod를 생성하는 요청을 보냈다고 하면, Authentication, Authorization, Admission Controller를 거쳐서 Pod를 생성하게 된다.</p>
<p>이러한 수많은 과정을 거치기 전, 클러스터에 배포되기 전에 먼저 검토하고 보안 정책을 적용할 수 있다면 어떨까?</p>
<h2 id="kubesec">kubesec</h2>
<p>유저 워크로드를 정적 분석하여, 리소스 파일을 검토하고 정책을 적용하기 위해, kubesec이라는 툴을 사용할 수 있다.</p>
<p><a href="https://kubesec.io">https://kubesec.io</a></p>
<p>kubesec은 리소스 파일을 분석하여, 보안 위협을 발생시킬 수 있는 이슈가 포함되어 있는지, 어떤 이유에서 위협이 발생할 수 있는지 기재되어 있는 결과 파일이 출력된다. 결과 파일에는 분석 결과에 따른 점수도 포함되어 있다. </p>
<pre><code class="language-json">[
  {
    &quot;object&quot;: &quot;Pod/node.default&quot;,
    &quot;valid&quot;: true,
    &quot;fileName&quot;: &quot;node.yaml&quot;,
    &quot;message&quot;: &quot;Failed with a score of -27 points&quot;,
    &quot;score&quot;: -27,
    &quot;scoring&quot;: {
      &quot;critical&quot;: [
        {
          &quot;id&quot;: &quot;Privileged&quot;,
          &quot;selector&quot;: &quot;containers[] .securityContext .privileged == true&quot;,
          &quot;reason&quot;: &quot;Privileged containers can allow almost completely unrestricted host access&quot;,
          &quot;points&quot;: -30
        }
      ],
      &quot;passed&quot;: [
        {
          &quot;id&quot;: &quot;ServiceAccountName&quot;,
          &quot;selector&quot;: &quot;.spec .serviceAccountName&quot;,
          &quot;reason&quot;: &quot;Service accounts restrict Kubernetes API access and should be configured with least privilege&quot;,
          &quot;points&quot;: 3
        }
      ],
...</code></pre>
<p>위 결과 예시에서는 Privileged 관련 항목을 위반한 것으로 확인이 되었으며, 이에 따라 -27점을 기록하여 검사를 통과하지 못하였다. </p>
<h3 id="kubesec-설치하기">kubesec 설치하기</h3>
<p>직접 설치하는 방법은 다음과 같다. 그 외에도 도커 컨테이너로 실행하는 방법도 있다.</p>
<pre><code class="language-bash">$ wget https://github.com/controlplaneio/kubesec/releases/download/v2.11.0/kubesec_linux_amd64.tar.gz
$ tar -xvf  kubesec_linux_amd64.tar.gz
$ mv kubesec /usr/bin/</code></pre>
<p>정상적으로 설치되었는지 확인한다.</p>
<pre><code class="language-bash">$ kubesec

Validate Kubernetes resource security policies

Usage:
  kubesec [command]

Available Commands:
  help        Help about any command
  http        Starts kubesec HTTP server on the specified port
  scan        Scans Kubernetes resource YAML or JSON
  version     Prints kubesec version

Flags:
  -h, --help   help for kubesec</code></pre>
<h3 id="kubesec-사용해보기">kubesec 사용해보기</h3>
<p>kubesec scan 명령어를 사용하여 리소스 정의 파일을 분석할 수 있다.</p>
<pre><code class="language-bash">$ kubesec scan pod.yaml</code></pre>
<p>그 외에 kubesec을 직접 설치하지 않고, kubesec의 퍼블릭 호스트 서비스에 요청을 보내는 방법도 있다.</p>
<pre><code class="language-bash">$ curl -sSX POST --data-binary @&quot;pod.yaml&quot; http://v2.kubesec.io/scan</code></pre>
<p>kubesec을 로컬 서버로 실행한 후에 요청을 보내는 방법도 사용할 수 있다. </p>
<pre><code class="language-bash">$ kubesec http 8080&amp;</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Kubernetes] 도커 컨테이너 이미지 취약점 진단하기]]></title>
            <link>https://velog.io/@jay-side-project/Kubernetes-%EB%8F%84%EC%BB%A4-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%B7%A8%EC%95%BD%EC%A0%90-%EC%A7%84%EB%8B%A8%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@jay-side-project/Kubernetes-%EB%8F%84%EC%BB%A4-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%B7%A8%EC%95%BD%EC%A0%90-%EC%A7%84%EB%8B%A8%ED%95%98%EA%B8%B0</guid>
            <pubDate>Wed, 29 Dec 2021 17:09:04 GMT</pubDate>
            <description><![CDATA[<h2 id="cvecommon-vulnerabilities-and-exposures">CVE(Common Vulnerabilities and Exposures)</h2>
<blockquote>
<p>컴퓨터 코드는 완벽하지 않기 때문에 취약점이 존재할 수 있다. </p>
<p>나쁜 의도를 가진 사람이 취약점을 발견하면, 시스템을 공격할 때에 취약점을 쓸 수 있다. 반면 좋은 의도를 가진 사람이 취약점을 발견한다면 그 내용을 세상에 알리고, 이 내용을 알게 된 사람들은 코드를 수정하고, 소프트웨어를 업데이트하여 더욱 안전한 시스템을 만들 수 있다. </p>
</blockquote>
<p>CVE는 취약점을 가진 다른 도구, 저장소 및 서비스 간에 데이터를 공유하기 위해 만들어진, &quot;<strong>공개적으로 알려진 소프트웨어의 보안 취약점을 가리키는 고유 표기</strong>&quot;를 의미한다.</p>
<p>CVE 체계는 미국 비영리 회사인 MITRE사에서 1999년 처음 만들어 운영하기 시작했다. 이후 미국 국립표준기술연구소(NIST)가 국가 취약성 데이터베이스(NVD)를 만들어 협력체계를 구축하면서 체계화되기 시작됐다. </p>
<p>각 CVE에는 <strong>CVE-해당년도-취약점번호</strong>의 형식으로 이루어진 식별자가 부여되며, 0-10 사이의 숫자 및 NONE, LOW, MEDIUM, HIGH, CRITICAL 중 하나의 등급으로 표시되는 심각도가 부여된다. </p>
<p>심각도에 따라 어떤 취약점을 먼저 조치해야 할 지, 어떤 부분에 더 신경을 쓰고 어떤 부분에는 덜 신경을 써도 될 지 파악할 수 있다.</p>
<p>최근 큰 이슈가 되었던, Log4Shell 취약점(CVE-2021-44228)을 확인해보면, 심각도가 10.0 CRITICAL로 표시되어 있는 것을 볼 수 있다. 
<a href="https://nvd.nist.gov/vuln/detail/CVE-2021-44228">https://nvd.nist.gov/vuln/detail/CVE-2021-44228</a>
<img src="https://images.velog.io/images/jay-side-project/post/4a1e0773-0e73-4792-a6f0-872f7d9bfeb7/image-20211230012021783.png" alt=""></p>
<h2 id="컨테이너-이미지-취약점-진단">컨테이너 이미지 취약점 진단</h2>
<p>그렇다면, 컨테이너 내에 어떤 취약점이 있는지는 어떻게 알 수 있을까?</p>
<p>CVE Scanner를 사용하여, 컨테이너 이미지 내에 포함되어 있는 취약점을 진단할 수 있다. 진단 결과를 확인하고, 취약점이 있는 패키지를 업데이트하거나, 불필요한 패키지를 삭제하는 등 조치를 취할 수 있다.</p>
<p>결국 설치되어 있는 패키지가 많으면, 그만큼 취약점이 많이 발생할 수 있는 위험이 있기 때문에 불필요한 패키지를 식별하고 삭제하여 공격할 수 있는 범위를 줄이는 것이 바람직하다.</p>
<h2 id="trivy">Trivy</h2>
<p>Trivy는 Aqua Security에서 제작한 취약점 스캐너로, 사용법이 간단하고, CI/CD와 통합해서 사용이 가능하다. 컨테이너 이미지, 파일 시스템 등에 대한 취약점 스캔을 할 수 있다. 
<img src="https://images.velog.io/images/jay-side-project/post/1cc3a884-4d8e-48c3-a7e3-d6cbff577f19/image.png" alt=""></p>
<h3 id="설치">설치</h3>
<p>Ubuntu 기준으로 다음과 같이 설치가 가능하다. </p>
<pre><code>$ wget https://github.com/aquasecurity/trivy/releases/download/v0.22.0/trivy_0.22.0_Linux-64bit.deb
$ sudo dpkg -i trivy_0.22.0_Linux-64bit.deb</code></pre><h3 id="이미지-스캔해보기">이미지 스캔해보기</h3>
<p>trivy image 또는 trivy i 명령어를 사용해서 이미지를 스캔할 수 있다. </p>
<pre><code>$ trivy i python:3.10.0a4-alpine
2021-12-29T17:03:01.390Z        INFO    Detected OS: alpine
2021-12-29T17:03:01.390Z        INFO    Detecting Alpine vulnerabilities...
2021-12-29T17:03:01.392Z        INFO    Number of language-specific files: 1
2021-12-29T17:03:01.392Z        INFO    Detecting python-pkg vulnerabilities...

python:3.10.0a4-alpine (alpine 3.12.3)
======================================
Total: 43 (UNKNOWN: 0, LOW: 2, MEDIUM: 8, HIGH: 30, CRITICAL: 3)

+-----------------------+------------------+----------+-------------------+------------------+---------------------------------------+
|        LIBRARY        | VULNERABILITY ID | SEVERITY | INSTALLED VERSION |  FIXED VERSION   |                 TITLE                 |
+-----------------------+------------------+----------+-------------------+------------------+---------------------------------------+
| apk-tools             | CVE-2021-36159   | CRITICAL | 2.10.5-r1         | 2.10.7-r0        | libfetch before 2021-07-26, as        |
|                       |                  |          |                   |                  | used in apk-tools, xbps, and          |
|                       |                  |          |                   |                  | other products, mishandles...         |
|                       |                  |          |                   |                  | --&gt;avd.aquasec.com/nvd/cve-2021-36159 |
+                       +------------------+----------+                   +------------------+---------------------------------------+
|                       | CVE-2021-30139   | HIGH     |                   | 2.10.6-r0        | In Alpine Linux apk-tools             |
|                       |                  |          |                   |                  | before 2.12.5, the tarball            |
|                       |                  |          |                   |                  | parser allows a buffer...             |
|                       |                  |          |                   |                  | --&gt;avd.aquasec.com/nvd/cve-2021-30139 |
+-----------------------+------------------+          +-------------------+------------------+---------------------------------------+
| busybox               | CVE-2021-28831   |          | 1.31.1-r19        | 1.31.1-r20       | busybox: invalid free or segmentation |
|                       |                  |          |                   |                  | fault via malformed gzip data         |
...</code></pre><h3 id="많이-사용되는-옵션">많이 사용되는 옵션</h3>
<p>옵션을 사용하여 특정 심각도에 해당하는 취약점만 출력하거나, 픽스되지 않은 취약점은 제외하고 출력할 수 있다. 출력결과를 파일에 저장할 수도 있다.</p>
<pre><code>$ trivy i --severity CRITICAL,HIGH python:3.10.0a4-alpine     
$ trivy i --ignore-unfixed  python:3.10.0a4-alpine
$ trivy i --severity HIGH --output /root/python.txt python:3.10.0a4-alpine
</code></pre><p>docker save 명령어로 이미지를 tar 파일에 저장한 경우에도 스캔이 가능하다.</p>
<pre><code>$ trivy i --input python.tar </code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[Kubernetes] CKS(Certified Kubernetes Security Specialist) 합격 후기]]></title>
            <link>https://velog.io/@jay-side-project/Kubernetes-CKS-%ED%95%A9%EA%B2%A9-%ED%9B%84%EA%B8%B0</link>
            <guid>https://velog.io/@jay-side-project/Kubernetes-CKS-%ED%95%A9%EA%B2%A9-%ED%9B%84%EA%B8%B0</guid>
            <pubDate>Tue, 28 Dec 2021 16:57:21 GMT</pubDate>
            <description><![CDATA[<h2 id="tldr">TL;DR</h2>
<ul>
<li>시험 준비 기간은 3~4주, 강의는 Kode Kloud, 모의 시험은 Kode Kloud + killer.sh</li>
<li>CKS 시험이 CKA 시험보다 조금 어렵긴 하지만, 정신만 잘 차리면 시간 내에 충분히 풀 수 있는 수준</li>
<li>쿠버네티스 보안에 대해 완벽하게 이해하려면 조금 부족하지만, 그래도 어느정도 개념은 잡을 수 있는 시험</li>
</ul>
<h2 id="시험을-보기-전까지">시험을 보기 전까지</h2>
<h3 id="준비-기간">준비 기간</h3>
<p>11월 말부터 3~4주 정도 퇴근 후 시간과 주말을 활용해서 강의를 듣고 모의 시험을 풀면서 공부를 했다.</p>
<p>중간 한 주 정도는 각종 이슈(AWS, log4j..)로 인해 공부를 거의 하지 못해서 집중해서 공부를 한 기간은 3주 정도라고 보면 될 것 같다.</p>
<h3 id="학습-자료">학습 자료</h3>
<p><a href="https://velog.io/@jay-side-project/Kubernetes-CKS-%EC%A4%80%EB%B9%84%EA%B3%BC%EC%A0%95-0-CKS-%EC%A4%80%EB%B9%84%EA%B3%BC%EC%A0%95%EC%9D%84-%EC%A4%80%EB%B9%84%ED%95%98%EA%B8%B0">준비과정을 준비하기 글</a>에서 썼던 것처럼 Kode Kloud의 강의를 듣고 정리하면서 공부를 했고, 시험 연습은 Kode Kloud 강의에 포함된 Mock Exam과, CKS 시험 신청 시 제공되는 killer.sh을 활용했다. </p>
<h2 id="시험에-도움이-된-🍯팁">시험에 도움이 된 🍯팁</h2>
<h3 id="내가-쓰고-있는-클러스터가-무엇인지-확인하기">내가 쓰고 있는 클러스터가 무엇인지 확인하기</h3>
<p>시험에서는 한 문제 당 한 개의 클러스터가 제공된다. 그래서 다른 문제에서 클러스터를 고장내도 다른 문제는 풀 수 있는 환경이다. 하지만, 그래서 엉뚱한 클러스터에 엉뚱한 리소스를 배포할 수 있다는 말이기도 하다. 그래서 시험을 볼 때는 꼭 내가 어느 노드에 있는지, 어느 클러스터에 접근하고 있는 지 확인할 필요가 있다.</p>
<pre><code class="language-bash">$ k config current-context</code></pre>
<h3 id="꼭-필요한-북마크만-지정해두기">꼭 필요한 북마크만 지정해두기</h3>
<p>깃허브를 찾아보면 이미 많은 사람들이 CKS에서 유용하게 사용할 수 있는 북마크를 정리해두었지만, 직접 정리한 북마크가 아니라 그런지, 어떤 내용이 어디에 들어가 있는지 찾는 시간이 오히려 더 오래 걸리는 단점이 있었다. </p>
<p>그래서 Mock Exam, Killer.sh 모의 시험을 풀면서 직접 필요한 내용만 북마크로 저장해두었는데, 확실히 시험 보면서 필요한 페이지를 바로 열 수 있어서 도움이 되었다.</p>
<h3 id="json-path-사용법을-잘-익혀두기">JSON Path 사용법을 잘 익혀두기</h3>
<p>JSON Path의 사용법을 잘 익혀두면 시크릿의 데이터를 확인하거나, 네임스페이스 내의 파드가 사용하고 있는 컨테이너 이미지를 확인할 때 아주 유용하게 사용할 수 있다. </p>
<pre><code class="language-bash"># 시크릿의 데이터 확인하기
$ k get secret my-secret -o jsonpath=&#39;{.data}&#39;

# 네임스페이스 내 파드가 사용하고 있는 이미지 목록 확인하기
$ k get pods -n my-namespace -o jsonpath=&#39;{range .items[*]}{&quot;\n&quot;}{.metadata.name}{&quot;:\t&quot;}{range .spec.containers[*]}{.image}{&quot;, &quot;}{end}{end}&#39; |\
sort</code></pre>
<p>사실 EKS 운영을 하면서 JSON Path를 쓰는 경우는 그렇게 많지 않았다. 이번 시험을 준비하면서 JSON Path를 조금만 잘 써도 편해진다는 것을 알게되었고, 시험에서도 물론 잘 썼지만, 앞으로 업무에서도 조금씩 활용을 할 수 있을 것 같다고 생각했다.</p>
<h3 id="killersh-시험은-꼭-풀어보기">killer.sh 시험은 꼭 풀어보기</h3>
<p>이전에 CKA 시험을 볼 때는 killer.sh이 무료 제공되지 않았던 것 같은데, 요즘은 쿠버네티스 자격 시험을 등록하면 killer.sh Simulator 세션이 2개 제공된다. 각 세션은 36시간동안 사용이 가능하고, 36시간 안에는 몇번이고 재시험을 볼 수 있다. 2개 세션의 문제 내용은 같다. </p>
<p>참고로 세션을 시작하기 전에 주의 사항을 보면 &quot;Our simulators are harder than the real exam.&quot;라는 문구가 있는데, 진짜다. Mock Exam 3회독 정도를 하고 자신만만해져서 시험 당일에 가벼운 마음으로 killer.sh 시뮬레이터를 켰다가 너무 어려워서 울 뻔했다. </p>
<p>비록 난이도는 높지만 실제 시험과 유사한 방향성의 문제들이 많기 때문에, 꼭 풀어보는 것이 좋다.</p>
<h3 id="그-외">그 외</h3>
<p>그 외에는 kube-apiserver가 죽는다고 당황하지 말기, 또는 Docker 명령어도 조금 알아두기 정도가 있을 것 같다.</p>
<h2 id="시험-시작부터-종료까지">시험 시작부터 종료까지</h2>
<p>예약한 시간 15분전에 시험 시작 버튼이 활성화되고, 예약 시간 후 15분이 지나도록 시험 시작을 하지 않으면 no-show로 처리되는 듯 하다. </p>
<p>감독관이 시험을 활성화해야 나도 시험을 시작할 수 있기 때문에 15분 전에 들어가봤자 감독관이 늦게오면 오래 기다리기만 해서 더 힘들 뿐이었다. 감독관이 예약 시간보다 13분 늦게 도착하는 바람에 약 30분에 가까운 대기 시간을 끝내고 시험이 시작됐다.</p>
<p>문제는 총 15개였고 시험 시간은 총 2시간이 주어졌다. 각 문제에는 가중치가 표시되어 있는데, 꼭 풀이 과정이 복잡한 문제의 가중치가 높은 것은 아니다. </p>
<p>alias(k=kubectl)나 Auto completion 설정은 이미 되어 있기 때문에 따로 해줄 필요는 없다. </p>
<p>시험 난이도는 CKA보다 어렵긴 했지만, 정신을 잘 차리고, 미리 저장해둔 북마크만 잘 활용한다면 시간 내에 충분히 풀 수 있는 수준이었다. </p>
<h2 id="시험이-끝나고-난-뒤">시험이 끝나고 난 뒤</h2>
<p>시험 결과는 시험 종료 24시간 후에 메일과 Training Portal을 통해 확인할 수 있다. 급한 성격 탓에 시험 종료 20시간 이후부터 결과를 기다리기 시작했고, 22시간 후에 결과를 바로 확인할 수 있었다.</p>
<p>결과는 80점으로 합격이었다.
<img src="https://images.velog.io/images/jay-side-project/post/a6a9ada9-603a-4836-8ad7-4cf6ca884694/image-20211228170112080.png" alt=""></p>
<p>CKS 시험은 쿠버네티스 보안에 대해 완벽하게 이해하기엔 조금 부족하지만, 그래도 어느정도 개념은 잡을 수 있는 시험이었다. </p>
<p>그렇기 때문에, &quot;쿠버네티스 보안.. 이거 맞아?&quot; 라는 질문으로 시작한 자격증 도전기였지만, 질문에 대한 답을 아직 확실하게 찾지는 못했다. 이번 시험 공부를 하면서 배운 내용을 토대로 답을 찾아야 할 것 같다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[번역] docomo의 퍼블릭 클라우드 활용과 CCoE의 역할]]></title>
            <link>https://velog.io/@jay-side-project/docomo%EC%9D%98-%ED%8D%BC%EB%B8%94%EB%A6%AD-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9C-%ED%99%9C%EC%9A%A9%EA%B3%BC-CCoE%EC%9D%98-%EC%97%AD%ED%95%A0</link>
            <guid>https://velog.io/@jay-side-project/docomo%EC%9D%98-%ED%8D%BC%EB%B8%94%EB%A6%AD-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9C-%ED%99%9C%EC%9A%A9%EA%B3%BC-CCoE%EC%9D%98-%EC%97%AD%ED%95%A0</guid>
            <pubDate>Thu, 23 Dec 2021 15:22:00 GMT</pubDate>
            <description><![CDATA[<p>원문 출처: <a href="https://www.nttdocomo.co.jp/corporate/technology/rd/technical_journal/bn/vol29_1/003.html">https://www.nttdocomo.co.jp/corporate/technology/rd/technical_journal/bn/vol29_1/003.html</a></p>
<blockquote>
<p>docomo는 10년 이상 전부터 퍼블릭 클라우드를 사용하여 다양한 서비스를 제공하고 있다. 퍼블릭 클라우드를 활용함에 있어서, CCoE가 중심이 되어 보다 효율적이고 적절하게 활용이 이루어질 수 있도록 활동해오고 있다. 이 글에서는, 그들의 활동과 docomo에 있어서 퍼블릭 클라우드 이용 체제를 최근 클라우드 개발 트렌드와 맞추어 소개한다.</p>
</blockquote>
<h2 id="1-서론">1. 서론</h2>
<p>기업이나 조직에 있어서 퍼블릭 클라우드의 이용이 급속하게 증가하고 있으며, &quot;클라우드 퍼스트&quot;라는 단어로 대표되는 것처럼 퍼블릭 클라우드를 활용한 사업 전개가 일반적인 일이 되어가고 있다. 동시에 많은 기업이나 조직에 있어서 온프레미스에는 없는 퍼블릭 클라우드의 신속성과 유연성을 제대로 활용하여 자사의 비즈니스를 전개, 또는 변혁해 나아갈 필요성이 대두되고 있다. 그러나, 퍼블릭 클라우드의 활용에 있어서는 종래의 온프레미스 형태의 IT 시스템을 구축 또는 운영하는 것과 다른 사고방식이 요구되는 경우가 많고, 원활한 도입이나 활용이 어려운 기업이나 조직도 적지 않다.</p>
<p>일반적으로 퍼블릭 클라우드의 이용에 있어서, 도입 시의 서비스 검증, 보안 대책, 이용 정책 설정, 사내 이용 체제 확립, 스킬 취득, 인재 육성, 빠르게 변화하는 클라우드의 정보 수집이나 노하우 전개 등 많은 과제에 대응해나가야 한다. 퍼블릭 클라우드를 제대로 활용하기 위해서는 기존부터 있던 온프레미스 형태의 IT 시스템의 사고방식과의 다른 점을 인식하고, 변화가 빠른 퍼블릭 클라우드에 적극적으로 따라가는 것이 중요해진다.</p>
<p>docomo에서도 10년이 넘는 기간동안 수많은 서비스에서 퍼블릭 클라우드를 활용하고 있다. 그것을 통해, 앞에서 말한 것과 같은 과제를 마주하고, 더욱 효율적이고 적절하게 퍼블릭 클라우드를 활용하기 위한 활동을 계속 해왔다. 이 글에서는 docomo에서 실시해온 글들의 활동이나 docomo에 있어서 퍼블릭 클라우드 이용 체제를 소개한다.</p>
<h2 id="2-docomo에-있어서-퍼블릭-클라우드의-이용">2. docomo에 있어서 퍼블릭 클라우드의 이용</h2>
<p>2020년 12월 시점에서의 docomo에 있어서 퍼블릭 클라우드의 이용 상황을 설명한다.</p>
<h3 id="21-퍼블릭-클라우드-이용-규모">2.1 퍼블릭 클라우드 이용 규모</h3>
<p>docomo에서는 2009년 경에 연구 개발/검증 목적으로 퍼블릭 클라우드의 이용을 시작했다. 그 후, 이용 범위를 확대하여 2012년부터 대규모 상용 서비스에 퍼블릭 클라우드를 도입했다. 이용 개시 시점부터 매년 이용량은 증가하여, 2020년 12월 시점에서는 900개 이상의 AWS 어카운트, 250개 이상의 GCP 프로젝트, 50개 이상의 Azure 구독을 각각 운영하고 있다. </p>
<h3 id="22-퍼블릭-클라우드-활용-범위">2.2 퍼블릭 클라우드 활용 범위</h3>
<p>docomo에 있어서 퍼블릭 클라우드의 활용 범위는 다양하다. 예를 들어, 웹 서비스, 모바일 애플리케이션의 백엔드 시스템, 데이터 분석 인프라, 기계 학습, 사내 시스템 등 다양한 분야에서 퍼블릭 클라우드를 활용하고 있다.</p>
<h3 id="23-퍼블릭-클라우드의-이용-체제">2.3 퍼블릭 클라우드의 이용 체제</h3>
<p>docomo는 다음 그림1처럼, 퍼블릭 클라우드를 효율적으로 활용할 수 있도록 고려한 이용 체제를 갖추고 있다.</p>
<h4 id="그림1">그림1</h4>
<p><img src="https://images.velog.io/images/jay-side-project/post/4234300d-85f0-4039-bfae-40520fdff495/image-20211223220055788.png" alt="">
docomo의 퍼블릭 클라우드 이용에서 가장 특징적인 점은 명확한 CCoE(Cloud Center of Excellence)가 존재하는 것이다. CCoE란 퍼블릭 클라우드에 관한 다양한 전문지식을 가진 팀으로서, docomo에서는 CCoE를 중심으로 퍼블릭 클라우드 활용을 전개하고 있다.</p>
<blockquote>
<p>CCoE: 기업에 있어서 클라우드 활용을 성공시키기 위해, 베스트 프랙티스 확립이나 필요한 제도, 서버넌스 등을 작성하여 사내에 전파해나가기 위한 전속 팀</p>
</blockquote>
<h2 id="3-docomo-내의-ccoe-활동">3. docomo 내의 CCoE 활동</h2>
<p>docomo의 퍼블릭 클라우드 이용 체제에 있어서 중심적인 역할을 담당하고 있는 CCoE의 상세한 활동 내용에 대해 설명한다.</p>
<h3 id="31-컨설팅-제공">3.1 컨설팅 제공</h3>
<p>퍼블릭 클라우드 이용 시의 지원은 CCoE의 중요한 역할이다. 사내 프로젝트에서 CCoE는 퍼블릭 클라우드 상의 시스템을 구축할 때의 시스템 설계 지원이나 검토, 보안 요건을 충족하기 위한 효율적인 대책 방법의 제시 등을 수행한다. </p>
<p>특히 퍼블릭 클라우드에서는 최초 설계가 이후 비용이나 시스템 운영 사업에 큰 영향을 끼치기 때문에 중요하며, 시스템 설계 시에 지원을 하는 경우가 많다.</p>
<p>또한, 시스템 운영을 시작하고 시스템의 이용자가 증가하면 필연적으로 비용이 증가한다. 이 때, 비용 최적화를 수행하기 위해 비용이 많이 발생하는 원인이나 설계 재검토 등의 지원도 실시하고 있다.</p>
<h3 id="32-클라우드-비용-총괄과-최적화">3.2 클라우드 비용 총괄과 최적화</h3>
<p>일반적으로 퍼블릭 클라우드는 유연한 이용이 가능한 반면 서비스 수나 구입 옵션의 확대에 따라 비용 지불이나 회계 처리 등이 번잡해지기 쉽고, 프로젝트가 늘어날 때 가동하는 컴퓨팅 자원이 크게 증가하는 경우가 있다. 여기서 docomo는 CCoE가 일원적으로 클라우드 사업자와 계약을 하여 일괄로 각 프로젝트에 대한 지불을 총괄하여 처리하는 것으로 각 프로젝트의 부담을 줄이고 있다.</p>
<p>또한 퍼블릭 클라우드 사업자에 따라서는 이용량이 많아질수록 가격이 낮아지는 볼륨 디스카운트 옵션이 있는 경우가 있다. 지불을 한 번에 수행하는 것으로, 볼륨이 확보되기 때문에 사내 전체의 이용료가 일부 절약되는 효과도 있다.</p>
<h3 id="33-최신-정보-수집과-전파">3.3 최신 정보 수집과 전파</h3>
<p>퍼블릭 클라우드는 빠르게 진화하고, 최신 정보를 지속적으로 따라가는 활동을 프로젝트 업무를 맡고 있는 각 프로젝트의 멤버가 하기에는 어려운 경우가 있다. 이 때문에 최신 정보 취득도 CCoE에서 솔선하여 실시하고 있다. 예를 들어, 퍼블릭 클라우드에 관한 기술적인 이벤트에 적극적으로 참가하여 정보 수집이나 발표를 진행하고 있다. 또한 알게된 정보는 노하우로서 가이드라인에 반영하거나, 직접 검증을 하여 사내 프로젝트 멤버에 전파할 수 있도록 하고 있다.</p>
<h3 id="34-클라우드-업무-지원-툴-개발-및-전파">3.4 클라우드 업무 지원 툴 개발 및 전파</h3>
<p>각 프로젝트가 퍼블릭 클라우드를 효율적으로 활용할 수 있도록 다양한 지원 툴을 개발하고, 사내에 전파하고 있다. </p>
<p>클라우드에서는 사업 전개 속도를 향상시킬 수 있는 다양한 기능이 제공되고 있지만, 한편으로는 잘못 사용하면 클라우드의 장애에 따르는 서비스 정지나 설정 오류에 의한 보안 사고를 일으킬 가능성도 있다. 이 때문에, 이용자에게는 올바르게 클라우드를 이용하기 위한 기술 지식이 필요하지만 이용자의 지식 레벨은 각기 다르기 때문에 회사로서는 사원 전체의 기술 지식 수준을 높이는 것이 과제가 된다.</p>
<p>이를 위해 CCoE는 docomo 시점에서의 클라우드 이용 방법을 기재한 가이드라인을 작성하고 있다. 이 가이드라인에 따라, 가령 지식이 많지 않는 이용자라도, 알아둬야 할 최소한의 지식을 단시간에 습득할 수 있게 된다. 가이드라인은 AWS, GCP, Azure에 대응하고 있다. 여기서는 AWS를 대상으로 작성한 가이드라인 일람을 표1로, 가이드라인의 일부 사례를 그림 2로 나타냈다.</p>
<h4 id="표1">표1</h4>
<table>
<thead>
<tr>
<th align="left">No</th>
<th align="left">종류</th>
<th align="left">내용</th>
</tr>
</thead>
<tbody><tr>
<td align="left">1</td>
<td align="left">클라우드 개발 가이드라인</td>
<td align="left">클라우드를 사용하는 경우의 사고방식이나 작법, 개발 플로우에 있어서의 각 단계에서 고려·실시해야 할 지침을 기재, 특히 설계·보안 등은 중점적으로 망라해, 잘못된 사용법을 억제한다.</td>
</tr>
<tr>
<td align="left">2</td>
<td align="left">보안 디자인 패턴</td>
<td align="left">클라우드를 이용한 시스템을 구축함에 있어서, 보안의 고려 누출을 억제하고 ISO/IEC27017에 따른 요건을 미리 준비함으로써 ISO 관리책에 대한 준거성을 높이고 있다. AWS를 사용하여 시스템을 구축할 때 필요한 보안 요구 사항 열거한다.</td>
</tr>
<tr>
<td align="left">3</td>
<td align="left">보안 템플릿</td>
<td align="left">보안 디자인 패턴을 고려한 네트워크 구성이나 네트워크 필터링 기능, 기본 기능을 제공하는 인스턴스군 등을 생성하는 AWS CloudFormation 템플릿을 기재, 보안 대책을 용이하게 실시한다.</td>
</tr>
<tr>
<td align="left">4</td>
<td align="left">IAM 디자인 패턴</td>
<td align="left">AWS 계정 사용 패턴에 맞게 docomo 사내 IAM 정책 설계 베스트 프랙티스를 기재한다.</td>
</tr>
<tr>
<td align="left">5</td>
<td align="left">인시던트 대응 가이드라인</td>
<td align="left">AWS를 이용하는 인터넷에 공개된 서비스 제공 시스템이나 사내 시스템 등에서 사이버 공격 등의 인시던트가 발생한 경우의 대응에 대해 실제로 발생한 사례를 포함하여 기재한다.</td>
</tr>
<tr>
<td align="left">6</td>
<td align="left">비용 최적화 지침</td>
<td align="left">AWS 비용을 관리하는 사람을 위한 비용 파악, 분석 방법, 비용 절감 및 최적화 방법을 기재한다.</td>
</tr>
<tr>
<td align="left">7</td>
<td align="left">시스템 마이그레이션 지침</td>
<td align="left">온 프레미스에서 AWS로의 마이그레이션 기회를 원활하게 수행하기 위해 이전 마이그레이션 사례에서 얻은 지식 등을 기반으로 마이그레이션시 포인트가되는 점과 주의해야 할 점을 설명한다.</td>
</tr>
<tr>
<td align="left">8</td>
<td align="left">공통 인프라화 가이드라인</td>
<td align="left">여러 계정/복수 시스템을 운영하기 시작하면, 운영을 표준화하거나, 운영 시스템을 공통화함으로써 효율화를 도모하면 유효한 경우가 있기 때문에, 클라우드의 특성을 이용함으로써 운영의 효율화를 부드럽게 진행하는 방법을 기재한다.</td>
</tr>
<tr>
<td align="left">9</td>
<td align="left">컨테이너 가이드라인</td>
<td align="left">컨테이너를 서비스 개발/운영에 도입하려고 하는 사람을 위해서, 각 프로젝트에서 효과적, 안전하게 컨테이너 활용을 실천 받는 것을 목적으로, 어떤 툴을 어떻게 이용하는 것이 좋은가 기재한다.</td>
</tr>
<tr>
<td align="left">10</td>
<td align="left">서버리스 가이드라인</td>
<td align="left">AWS상에서 서버리스 시스템을 개발·운영할 때, 어떻게 도입을 진행시켜 나가야 할지, 어떤 서비스를 어떻게 이용하는 것이 좋은지, 각 프로젝트에서 효율적이고 효과적 서버리스를 활용하는 방법을 설명한다.</td>
</tr>
<tr>
<td align="left">11</td>
<td align="left">DevOps 가이드라인</td>
<td align="left">DevOps의 사고방식을 서비스 개발/운영에 도입하려고 하는 사람을 위해서, 어떤 툴을 어떻게 이용하는 것이 좋은지, 각 프로젝트에서 효율적이고 효과적으로 DevOps를 실천 받는 것을 목적으로 한 가이드라인이다.</td>
</tr>
</tbody></table>
<h4 id="그림2">그림2</h4>
<p><img src="https://images.velog.io/images/jay-side-project/post/f0fc28c3-140f-4be9-823a-c07730d93bcf/image-20211223232816822.png" alt="">
또한, 가이드라인 중 하나인 보안 디자인 패턴에서는 클라우드를 사용하여 시스템을 구축할 때 보안을 고려할 수 있도록 정보 보안팀의 보안 체크 항목에 따른 요건(ISO/IEC27017 등)과 클라우드 환경에 있어서의 요건, AWS를 이용한 시스템 구축을 진행할 경우의 요구 사항과 AWS가 제공하는 기능이나 서비스를 함께 기록하여, 보안 체크 항목을 준수할 수 있도록 하고 있다. 시스템 구축 담당자는 보안 체크 항목을 충족시키기 위해 하나 하나 검증할 필요가 없고, 보안 디자인 패턴을 참조하면서 시스템 구축을 실시하면, 자연스럽게 보안 체크 항목을 충족할 수 있게 된다. 보안 디자인 패턴의 일부 예시를 그림3으로 나타냈다.</p>
<h4 id="그림3">그림3</h4>
<p><img src="https://images.velog.io/images/jay-side-project/post/703bbe3c-dda8-4699-a062-6e1f848d490c/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-23%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2011.54.57.png" alt="">
퍼블릭 클라우드에서 새로운 기능이 추가되거나 업데이트가 되는 속도가 빠르기 때문에, 이러한 지원 툴도 빈번하게 업데이트 될 필요가 있다. 이 때문에, CCoE에서는 이러한 툴 개발에 있어서도 애자일 개발을 도입하여, 빈번한 기능 추가나 업데이트에 따라갈 수 있도록 하고 있다.</p>
<h2 id="4-docomo에서의-최신-개발-트렌드">4. docomo에서의 최신 개발 트렌드</h2>
<p>여기서는 docomo의 최신 개발 현장으로부터 서버리스 기술을 적용한 최신 개발 사례를 설명한다.</p>
<h3 id="41-서버리스-기술-등장">4.1 서버리스 기술 등장</h3>
<p>클라우드 세계에서는 지금까지 별개였던 개발과 운영을 분리하지 않고, 이들을 통합하여 생산성을 높이는 소위 말하는 DevOps의 흐름과 함께, 기존의 가상 머신에서 컨테이너 이용을 전제로 한 설계 방식이 보급되었다. 컨테이너화는 개발이나 릴리즈 사이클을 가속시키는 것에는 성공했지만, 기존에 가상 머신을 운영하던 것과 마찬가지로 운영 모니터링이나, 보안을 위한 보수 작업은 필요하다. 컨테이너화 흐름이 진행되는 한편, AWS를 시작으로 퍼블릭 클라우드 사업자는 미들웨어부터 서버의 운영 관리까지를 포함하는 일련의 매니지드 서비스를 &quot;서버리스&quot; 기술로써 이미 제공하기 시작하고 있다. 이는 컨테이너화와는 다른 축으로 발전하고 있는 클라우드 인프라 기술이며 개발자나 운영 관리자는 서버의 존재를 의식하지 않고 인프라의 운영 관리를 모두 클라우드 사업자에게 맡기고, 더 많은 리소스를 비즈니스 로직 개발에 집중할 수 있게 한다. </p>
<h3 id="42-docomo의-서버리스-운영개발-사례">4.2 docomo의 서버리스 운영/개발 사례</h3>
<p>docomo가 2020년 6월에 릴리즈한 docomo 오픈 이노베이션 클라우드의 포탈 사이트는 아래와 같은 React 기반의 일반적인 웹 애플리케이션 시스템이다. (그림4)</p>
<h4 id="그림4">그림4</h4>
<p><img src="https://images.velog.io/images/jay-side-project/post/1a025814-df1d-4148-9042-e18fbc485fb2/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-24%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2012.06.06.png" alt=""></p>
<p>docomo 오픈 이노베이션 클라우드의 개발 시작부터 최초 릴리즈까지의 기간은 4개월, 그리고 운영/보수 인원은 최소한으로 줄인다는 제약이 있었다. 이에, 가능한 한 서버 관리를 AWS에 오프로드하기 위해 AWS Lambda 등을 이용한 서버리스 아키텍처를 전면적으로 채용하여 개발을 진행했다. 그 결과, 개발 기간을 대폭 단축하여 단기간에 릴리즈할 수 있었다.</p>
<p>이 글을 쓰는 시점을 기준으로 운영 개시한 지 1년, 네트워크나 서버 등 인프라르 기인으로 한 장애는 0 건이었다. 가용성에 있어서 서버리스에서는 이중화나 Fault Tolerance가 사전에 빌트인되어있는 혜택을 받고 있다. 운영/보수 인원은 2~3명으로 당초 목표를 달성했다. 이후, 유저 접속 증가에 따른 Scalability 확보가 필요한 국면에서도 서버리스라면 자동으로 대응이 가능하다. 요금도 사용한 만큼만 지불하는 방식이기 때문에 본 프로젝트에서는 비용을 크게 절감할 수 있었다.</p>
<h2 id="5-마지막으로">5. 마지막으로</h2>
<p>이 글에서는 docomo에서의 퍼블릭 클라우드 활용과 CCoE가 하는 역할에 대해 설명했다. 퍼블릭 클라우드 이용은 앞으로도 증가할 것으로 예상되는 가운데, 이를 제대로 이용하고 비즈니스를 성공으로 이끄는 것이 중요하다. 그 때문에 CCoE는 앞으로도 각 프로젝트가 퍼블릭 클라우드를 최대한으로 활용할 수 있도록 지원의 범위를 넓혀가고 싶다.</p>
<p>또한, 서버리스 등 최신 기술을 상용 서비스에 신속하게 도입하는 것은 차세대 이노베이션으로의 도전이기도 하다. 이러한 마인드를 키워나가면서 앞으로도 docomo 사내에서의 개발 효율화를 촉진하고 성공 사례를 늘려가고 싶다고 생각하고 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Terraform State file의 Terraform 버전 변경하기 (AWS 기준)]]></title>
            <link>https://velog.io/@jay-side-project/Terraform-State-file%EC%9D%98-Terraform-%EB%B2%84%EC%A0%84-%EB%B3%80%EA%B2%BD%ED%95%98%EA%B8%B0-AWS-%EA%B8%B0%EC%A4%80</link>
            <guid>https://velog.io/@jay-side-project/Terraform-State-file%EC%9D%98-Terraform-%EB%B2%84%EC%A0%84-%EB%B3%80%EA%B2%BD%ED%95%98%EA%B8%B0-AWS-%EA%B8%B0%EC%A4%80</guid>
            <pubDate>Mon, 06 Dec 2021 16:21:46 GMT</pubDate>
            <description><![CDATA[<p>terraform 명령어를 실행하는 버전과 tfstate 파일에 명시되어 있는 버전 차이로 인해 명령어 실행에 오류가 생기는 경우의 해결방법을 소개한다.</p>
<h2 id="tfstate-file">tfstate file</h2>
<p>terraform plan/apply를 하고 나면 terraform.tfstate라는 파일이 생성된다. 이 파일은 Terraform의 설정 파일로, Terraform을 통해 생성한 리소스의 정보와 Terraform 버전, tfstate 버전 등의 정보가 들어있다.</p>
<pre><code>{
  &quot;version&quot;: 4,
  &quot;terraform_version&quot;: &quot;0.12.20&quot;,
  &quot;serial&quot;: 427,
  &quot;lineage&quot;: &quot;dac9258e-2013-6c16-f250-3538eb4c2bdb&quot;,
  &quot;outputs&quot;: {
    &quot;alb_hostname&quot;: {
      &quot;value&quot;: &quot;ecs-alb.ap-northeast-2.elb.amazonaws.com&quot;,
      &quot;type&quot;: &quot;string&quot;
    }
  },
  &quot;resources&quot;: [
    {
      &quot;mode&quot;: &quot;data&quot;,
      &quot;type&quot;: &quot;aws_iam_role&quot;,
      &quot;name&quot;: &quot;ecs_task_execution_role&quot;,
      &quot;provider&quot;: &quot;provider.aws&quot;,
      ...</code></pre><h2 id="tfstate-file의-terraform-version-변경하기">tfstate file의 Terraform version 변경하기</h2>
<p>tfstate 파일에 적힌 Terraform version이 명령어를 실행한 Terraform version보다 높다면 다음과 같은 메시지가 발생하면서 명령어 실행에 실패한다.</p>
<pre><code>$ terraform plan
Error refreshing state: state snapshot was created by Terraform v0.12.24, which is newer than current v0.12.21; upgrade to Terraform v0.12.24 or greater to work with this state</code></pre><p>tfstate file 수정</p>
<p>terraform_version을 원하는 버전으로 변경한다.</p>
<pre><code>{
  &quot;version&quot;: 4,
  &quot;terraform_version&quot;: &quot;0.12.21&quot;, ## 0.12.24 -&gt; 0.12.21로 변경
  ... </code></pre><p>다시 terraform 명령어를 실행 하면 다음과 같은 메시지가 뜨면서 명령어 실행에 실패한다.</p>
<pre><code>$ terraform plan 
Error refreshing state: state data in S3 does not have the expected content.

This may be caused by unusually long delays in S3 processing a previous state
update.  Please wait for a minute or two and try again. If this problem
persists, and neither S3 nor DynamoDB are experiencing an outage, you may need
to manually verify the remote state and update the Digest value stored in the
DynamoDB table to the following value: &lt;hash 값&gt;</code></pre><p>DynamoDB의 Digest 수정</p>
<p>AWS DynamoDB에 저장되어 있는 terraform lock state 정보와 새로 수정한 tf state 파일의 정보가 일치하지 않아서 발생한 문제인 것으로 보인다.</p>
<p>DyanmoDB에서 Digest 값을 위에서 주어진 &lt;hash 값&gt;으로 변경한 뒤 다시 terraform 명령어를 실행한다.</p>
<pre><code>$ terrafom plan
...

------------------------------------------------------------------------

No changes. Infrastructure is up-to-date.

This means that Terraform did not detect any differences between your
configuration and real physical resources that exist. As a result, no
actions need to be performed.</code></pre><p>정상적으로 실행된 것을 확인할 수 있다.</p>
<h5 id="최초-작성일-20201125">최초 작성일: 2020.11.25</h5>
]]></description>
        </item>
        <item>
            <title><![CDATA[Docker Dangling Image 삭제]]></title>
            <link>https://velog.io/@jay-side-project/Docker-Dangling-Image-%EC%82%AD%EC%A0%9C</link>
            <guid>https://velog.io/@jay-side-project/Docker-Dangling-Image-%EC%82%AD%EC%A0%9C</guid>
            <pubDate>Mon, 06 Dec 2021 16:18:51 GMT</pubDate>
            <description><![CDATA[<p>Docker image 빌드 과정에서 생성되는 dangling image를 삭제하는 방법을 소개한다.</p>
<h2 id="dangling-image란">Dangling Image란</h2>
<p>동일한 태그를 가진 Docker 이미지가 빌드될 경우, 기존에 있던 이미지는 삭제되지는 않고, tag가 none으로 변경된 상태로 남아 있게 된다.</p>
<p>다음은 frontend라는 이름의 Docker image 목록을 조회한 결과이다.</p>
<pre><code>[root@devops ~]# docker images frontend
REPOSITORY                                  TAG                 IMAGE ID            CREATED             SIZE
frontend   latest              dae2841620d8        38 hours ago        31.1MB
frontend   &lt;none&gt;              c213f7380098        2 days ago          31.1MB
frontend   &lt;none&gt;              ca001062a8f1        2 months ago        30.7MB</code></pre><p>가장 최근에 빌드된 이미지를 제외한 다른 이미지의 tag는 none으로 변경된 것을 알 수 있다.</p>
<p>위와 같이 더 이상 컨테이너에 연결되지 않고, 태그가 없어진 이미지를 Dangling image라고 한다.</p>
<p>이러한 dangling image를 그대로 방치하면 파일시스템 용량을 차지하게 되고, Docker 이미지 확인에도 불편함이 있을 수 있다.</p>
<h2 id="dangling-image-조회-및-삭제">Dangling Image 조회 및 삭제</h2>
<p>dangling image의 목록을 확인하는 커맨드는 다음과 같다.</p>
<pre><code>$ docker images -f dangling=true</code></pre><p>-f는 필터를 지정하는 옵션이다. 위 명령에서는 dangling 값이 true인 이미지만을 출력하도록 지정한 것이다.
dangling image를 삭제하는 커맨드는 다음과 같다.</p>
<pre><code>$ docker rmi $(docker images -f &quot;dangling=true&quot; -q)</code></pre><p>-q 옵션을 지정하면, 이미지의 id 값만 출력한다.
dangling 값이 true인 이미지만을 삭제하는 명령이다.</p>
<h2 id="prune-명령어">prune 명령어</h2>
<p>Docker API 1.25 이상부터는 prune 이라는 명령어를 지원하고 있다.</p>
<p>prune 명령은 사용하지 않는 리소스에 대해 정리하는 역할을 한다.</p>
<p>사용법은 다음과 같다.</p>
<h3 id="중지된-모든-컨테이너-삭제">중지된 모든 컨테이너 삭제</h3>
<pre><code>$ docker container prune</code></pre><h3 id="태깅이-되지-않은-모든-이미지dangling-image-삭제">태깅이 되지 않은 모든 이미지(dangling image) 삭제</h3>
<pre><code>$ docker image prune</code></pre><h3 id="사용되지-않는-도커-네트워크-삭제">사용되지 않는 도커 네트워크 삭제</h3>
<pre><code>$ docker network prune</code></pre><h3 id="컨테이너에서-사용하지-않는-모든-도커-볼륨-삭제">컨테이너에서 사용하지 않는 모든 도커 볼륨 삭제</h3>
<pre><code>$ docker volume prune</code></pre><h3 id="모든-리소스-컨테이너-이미지-네트워크-등-중-사용하지-않는-리소스-삭제">모든 리소스 (컨테이너, 이미지, 네트워크 등) 중 사용하지 않는 리소스 삭제</h3>
<pre><code>$ docker system prune -a</code></pre><p>-a 명령을 사용하면 dangling 이미지 이외에도 사용하지 않는 이미지까지 삭제하므로, 주의한다.</p>
<h5 id="최초-작성일-20200512">최초 작성일: 2020.05.12</h5>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Kubernetes] Kubernetes에서 AppArmor 사용하기]]></title>
            <link>https://velog.io/@jay-side-project/Kubernetes-CKS-%EC%A4%80%EB%B9%84%EA%B3%BC%EC%A0%95-Kubernetes%EC%97%90%EC%84%9C-AppArmor-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@jay-side-project/Kubernetes-CKS-%EC%A4%80%EB%B9%84%EA%B3%BC%EC%A0%95-Kubernetes%EC%97%90%EC%84%9C-AppArmor-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</guid>
            <pubDate>Mon, 06 Dec 2021 15:32:09 GMT</pubDate>
            <description><![CDATA[<h2 id="apparmor란">AppArmor란</h2>
<p>AppArmor는 표준 리눅스 사용자와 그룹 기반의 권한을 보완하여, 한정된 리소스 집합으로 프로그램을 제한하는 리눅스 커널 보안 모듈이다. AppArmor는 임의의 애플리케이션에 대해서 잠재적인 공격 범위를 줄이고 더욱 심층적인 방어를 제공하도록 구성할 수 있다. 이 기능은 특정 프로그램이나 컨테이너에서 필요한 리눅스 기능, 네트워크 사용, 파일 권한 등에 대한 접근을 허용하는 프로파일로 구성한다. 각 프로파일은 허용하지 않은 리소스 접근을 차단하는 강제(enforcing) 모드 또는 위반만을 보고하는 불평(complain) 모드로 실행할 수 있다.</p>
<h2 id="쿠버네티스에서-apparmor를-쓰려면">쿠버네티스에서 AppArmor를 쓰려면</h2>
<p>AppArmor를 쿠버네티스에서 사용하려면 다음 조건을 만족해야 한다.</p>
<ul>
<li>쿠버네티스 버전 &gt; 1.4</li>
<li>노드에 AppArmor 커널 모듈 enable되어 있음</li>
<li>노드의 커널에 AppArmor 프로파일이 로드되어 있음</li>
<li>컨테이너 런타임이 AppArmor를 지원함 (docker, containerd 등)</li>
</ul>
<h2 id="filesystem-접근-제한">Filesystem 접근 제한</h2>
<p>예를 들어 한시간동안 sleep을 하는 파드를 생성한다고 가정해보자.</p>
<pre><code>apiVersion: v1
kind: Pod
metadata:
  name: ubuntu-sleeper
spec:
  containers:
  - name: hello
    image: busybox
    command: [&quot;sh&quot;, &quot;-c&quot;, &quot;echo &#39;Sleeping for an hour!&#39; &amp;&amp; sleep 1h&quot;]</code></pre><p>이 파드는 sleep만 하면 되기 때문에, 파일시스템에 대해 쓰기 권한을 가질 필요가 없다.</p>
<p>이 파드가 파일시스템에 쓰기 작업을 하지 못하도록 노드에 다음과 같은 프로파일을 생성한다.</p>
<pre><code>profile apparmor-deny-write flags=(attach_disconnected) {
  file,
  # Deny all file writes.
  deny /** w,
}</code></pre><p>프로파일이 작성되었다면, apparmor_parser 명령어를 사용하여 프로파일을 로드하고, aa-status 명령어를 사용하여 프로파일이 잘 로드되었는지 확인한다. </p>
<pre><code>$ apparmor_parser -q ./apparmor-deny-write
$ aa-status
pparmor module is loaded.
57 profiles are loaded.
20 profiles are in enforce mode.
...
apparmor-deny-write
...</code></pre><p>AppArmor 프로파일은 컨테이너 별로 적용이 가능하다. 
아직은 베타 버전이기 때문에, 컨테이너에 AppArmor 프로파일을 적용하기 위해서는 Annotation을 사용한다.</p>
<pre><code>apiVersion: v1
kind: Pod
metadata:
  name: ubuntu-sleeper
  annotations:
    container.apparmor.security.beta.kubernetes.io/ubuntu-sleeper: localhost/apparmor-deny-write
spec:
  containers:
  - name: hello
    image: busybox
    command: [&quot;sh&quot;, &quot;-c&quot;, &quot;echo &#39;Sleeping for an hour!&#39; &amp;&amp; sleep 1h&quot;]</code></pre><p>이제 파드를 실행시켜서 프로파일이 잘 적용되었는지 확인한다.</p>
<pre><code>$ k apply -f ubuntu-sleeper.yaml
pod/ubuntu-sleeper created

$ k logs ubuntu-sleeper
sleeping for an hour

$ k exec -it ubuntu-sleeper -- touch /tmp/test
touch: cannot touch &#39;/tmp/test/&#39;: Permission denied
command terminated with exit code 1</code></pre><p>touch를 사용해서 파일을 생성하려고 했지만, 의도한 것처럼 실패한 것을 볼 수 있다.
컨테이너의 root 프로세스에 올바른 프로파일이 적용되어 있는지는 proc attr을 확인하여 검증할 수 있다.</p>
<pre><code>$ k exec ubuntu-sleeper cat /proc/1/attr/current</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[Kubernetes] CKS 준비과정 - CKS 준비과정을 준비하기]]></title>
            <link>https://velog.io/@jay-side-project/Kubernetes-CKS-%EC%A4%80%EB%B9%84%EA%B3%BC%EC%A0%95-0-CKS-%EC%A4%80%EB%B9%84%EA%B3%BC%EC%A0%95%EC%9D%84-%EC%A4%80%EB%B9%84%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@jay-side-project/Kubernetes-CKS-%EC%A4%80%EB%B9%84%EA%B3%BC%EC%A0%95-0-CKS-%EC%A4%80%EB%B9%84%EA%B3%BC%EC%A0%95%EC%9D%84-%EC%A4%80%EB%B9%84%ED%95%98%EA%B8%B0</guid>
            <pubDate>Mon, 06 Dec 2021 12:45:49 GMT</pubDate>
            <description><![CDATA[<h1 id="ckscertified-kubernetes-security-specialist란">CKS(Certified Kubernetes Security Specialist)란</h1>
<p>CNCF에서 공인하는 쿠버네티스 보안 전문가 자격증이다.
쿠버네티스 공식 페이지에 따르면 이런 자격증 인증 프로그램이라고 한다. </p>
<blockquote>
<p>공인 쿠버네티스 보안 전문가(CKS) 프로그램은 CKS가 다양한 모범 사례에 대해 능숙하고 자신감을 가지도록 보장합니다. CKS 인증은 빌드, 배포 및 런타임 중에 컨테이너 기반 애플리케이션과 쿠버네티스 플랫폼을 보호하는 기술을 다룹니다.</p>
</blockquote>
<p>CKS 지원자는 CKS에 참여하기 전에 충분한 쿠버네티스 전문 지식을 보유하고 있음을 입증하기 위해 현재 버전의 공인 쿠버네티스 관리자(CKA) 인증을 보유해야 합니다.</p>
<p>CKS의 시험 범위는 이렇다.</p>
<ul>
<li>Cluster Setup 10%</li>
<li>Cluster Hardening 15%</li>
<li>System Hardening 15%</li>
<li>Minimize Microservice Vulnerabilities 20%</li>
<li>Supply Chain Security 20%</li>
<li>Monitoring, Logging and Runtime Security 20%<h1 id="시험을-보게-된-계기">시험을 보게 된 계기</h1>
시험을 결심하게 된 데에는 두 개의 이유가 있었다.<h2 id="쿠버네티스-보안-이거-맞아">쿠버네티스 보안.. 이거 맞아?</h2>
쿠버네티스를 운영하다가 &quot;보안 점검&quot;이라는 장벽에 부딪혔다.
지금까지 운영하던 서버들은 보안 점검이라고 하면 그냥 서버 접속해서 스크립트 돌리고, 결과 보면서 보안 조치 하면 되는 거였는데, 쿠버네티스는 어떻게 해야하지? 하는 생각이 들었다. 
사실, 그와 동시에 쿠버네티스 보안 점검이라면 이전의 서버 보안 점검과는 다르겠지? 하는 기대감도 있었다. </li>
</ul>
<p>하지만 실제로 내가 전달받은 쿠버네티스 보안 점검 방법은 &quot;워커 노드 접속해서 보안 스크립트 돌리세요&quot;였다. 게다가 보안 조치 방법은 &quot;워커 노드에 기존 OS처럼 보안 조치하시고, 백신 설치하세요&quot;라고 했다.</p>
<p>그 순간, &quot;쿠버네티스 보안.. 이렇게 하는 게 진짜 맞나요?&quot;라는 의문이 들었다.</p>
<h2 id="사이버-먼데이-할인">사이버 먼데이 할인</h2>
<p>위의 의문이 들고나서, 바로 CKS 시험을 결제해버렸다. 
Linux Foundation 페이지에서는 이전에 결제한 카드가 저장되어 있어서 어려움 없이 바로 결제가 가능했다. 
다만, 문제는 그 카드가 회사 카드였다는 것이었다. 
난 회사에는 비밀로 혼자만의 연말 버킷리스트의 하나로 시험을 볼 생각이었기 때문에 바로 카드 결제를 취소해달라는 서포트를 올렸다.
Holiday라서 응답이 늦을 수 있다고 해서 이틀정도 기다리다보니 375달러는 너무 비싼가, 괜히 신청했나 등등 후회가 밀려왔다. </p>
<p>하지만 결제 취소 답변과 함께 이렇게나 반가운 소식이 함께 도착했다.
<img src="https://images.velog.io/images/jay-side-project/post/02c9bb92-a058-44bd-b501-5a76ad70b5bb/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-06%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%209.22.32.png" alt=""></p>
<p>사이버 먼데이 할인이 시작된다는 소식이었고, 확인해보니 375달러짜리 시험을 188달러에 볼 수 있었기 때문에, 망설이지 않고 바로 개인 카드로 다시 결제를 해버렸다.</p>
<h1 id="cks-공부-시작하기">CKS 공부 시작하기</h1>
<h2 id="온라인-강의">온라인 강의</h2>
<p>이전에 CKA 공부를 할 때도 <a href="https://kodekloud.com/">Kode Kloud</a>에서 공부했기 때문에, 이번에도 Kode Kloud를 선택했다. </p>
<p>Kode Kloud에서는 각 도메인 별 강의가 끝나면 이렇게 실습 환경을 제공해줘서 어렵지 않게 내용을 따라갈 수 있다.
<img src="https://images.velog.io/images/jay-side-project/post/8000ff64-f96d-4ab2-b193-7779d866c898/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-06%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%209.35.46.png" alt=""></p>
<h2 id="공식문서-둘러보기">공식문서 둘러보기</h2>
<p>CKS 시험을 보면서 접속할 수 있는 공식문서는 CKA보다 조금 더 많다.</p>
<h3 id="kubernetes-documentation">Kubernetes Documentation</h3>
<p><a href="https://kubernetes.io/docs/">https://kubernetes.io/docs/</a> and their subdomains
<a href="https://github.com/kubernetes/">https://github.com/kubernetes/</a> and their subdomains
<a href="https://kubernetes.io/blog/">https://kubernetes.io/blog/</a> and their subdomains</p>
<h3 id="tools">Tools</h3>
<p>Trivy documentation <a href="https://aquasecurity.github.io/trivy/">https://aquasecurity.github.io/trivy/</a>
Sysdig documentation <a href="https://docs.sysdig.com/">https://docs.sysdig.com/</a>
Falco documentation <a href="https://falco.org/docs/">https://falco.org/docs/</a></p>
<h3 id="app-armor">App Armor</h3>
<p> <a href="https://gitlab.com/apparmor/apparmor/-/wikis/Documentation">https://gitlab.com/apparmor/apparmor/-/wikis/Documentation</a></p>
<p>공식문서에 들어갈 수 있도록 허용해준다는 건, 즉 시험에 나올 수 있다는 의미이기 때문에, 어떤 내용이 주로 등장할지 예상해보기 위해 쿠버네티스 공식 문서 중 보안 설정 관련된 부분과, Tools, App Armor의 공식 문서도 함께 둘러보았다.</p>
<p>이제 강의를 들으면서 알게 된 내용, 알아둘 내용, 잊지 말아야 할 내용을 정리해보면서 공부를 하려고 한다.</p>
]]></description>
        </item>
    </channel>
</rss>