<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>devvoo.log</title>
        <link>https://velog.io/</link>
        <description>Cloud DevOps Engineer; 루트 노드를 향하여!</description>
        <lastBuildDate>Thu, 26 Dec 2024 07:05:46 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>devvoo.log</title>
            <url>https://velog.velcdn.com/images/root-devvoo/profile/f8b22756-5b10-422c-bc39-600998228aed/image.JPG</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. devvoo.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/root-devvoo" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[크리스마스 CKA 시험 응시 후 합격 후기]]></title>
            <link>https://velog.io/@root-devvoo/%ED%81%AC%EB%A6%AC%EC%8A%A4%EB%A7%88%EC%8A%A4-CKA-%EC%8B%9C%ED%97%98-%EC%9D%91%EC%8B%9C-%ED%9B%84-%ED%95%A9%EA%B2%A9-%ED%9B%84%EA%B8%B0</link>
            <guid>https://velog.io/@root-devvoo/%ED%81%AC%EB%A6%AC%EC%8A%A4%EB%A7%88%EC%8A%A4-CKA-%EC%8B%9C%ED%97%98-%EC%9D%91%EC%8B%9C-%ED%9B%84-%ED%95%A9%EA%B2%A9-%ED%9B%84%EA%B8%B0</guid>
            <pubDate>Thu, 26 Dec 2024 07:05:46 GMT</pubDate>
            <description><![CDATA[<h1 id="cka">CKA</h1>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/315f273c-0e85-4c4f-b73a-b01692ad41b5/image.png" alt=""></p>
<p>작년 여름에 재직했던 회사에서 쿠버네티스로 모든 서비스를 마이그레이션 할 계획을 수립하고 있었다.
회사에 기술적으로 기여하고 싶었던 나는, 쿠버네티스의 기본 동작원리를 보다 깊게 이해하기 위해서,
유명한 강의인 &#39;Udemy&#39;에 올라와있는 &quot;Certified Kubernetes Administrator (CKA) with Practice Tests&quot; 강의를 구매했고, 짬짬이 공부하겠다고 마음 먹었다.
강의는 CKA를 먼저 딴 동료가 추천해줘서 알게 되었고, 저렴할 때 사야한다는 생각으로 질렀었다.</p>
<blockquote>
<p>공부하는 김에 CKA 시험봐서 따면 더 좋고~ </p>
</blockquote>
<p>뭐 이런 느낌으로?</p>
<p>재작년에 DevOps 엔지니어 직무를 준비해보는 것으로 마음먹고,
K-Digital Training 과정으로 쿠버네티스 관련 과정을 하나 더 수료하긴 했지만,
&quot;제대로 배운 것 같지 않다&quot;는 생각에 항상 부족함을 느껴왔었다.</p>
<blockquote>
<p>제대로 알고 쓰고 있는걸까?</p>
</blockquote>
<p>그래서, &quot;하나를 알더라도 제대로 알자&quot;는 생각으로 엄청 천천히 일일히 Notion에 정리를 해가며, 틈틈이 공부를 하고 있었다.</p>
<p>그러던 중, 올해 이직 후, 경제 및 IT시장 상황이 지속적으로 어려워져
불현듯, 재직 중임에도 스스로에 대해 위기감을 느꼈고,
마침 이번 달 초, 지금 재직 중인 회사 대표님과 잠깐 면담할 시간이 있었는데,
내년에 있을 쿠버네티스 관련 대형 프로젝트를 준비하신다는 얘기를 듣게 되었다.
그 얘길 듣자마자 시험을 무조건 올해 안에 1번은 꼭 보는 것으로 결단하고, 전략을 바꾸게 되었다.</p>
<blockquote>
<ul>
<li>Udemy에서 학습이 남은 파트들은 연습문제 위주로 풀이, 잘 모르는 내용만 강의 보기.</li>
</ul>
</blockquote>
<ul>
<li>Lightning Lab 문제랑 Mock Exam 1, 2, 3 각각 풀고 오답노트 작성하고, 최소 2-3번 풀이 후 정리.</li>
</ul>
<blockquote>
<p>마침, 내가 시험 응시를 결심했을 때가 Cyber Monday 기간이어서, 50% 할인 코드를 적용해 신청했다.
(한화 약 27만원 정도) (할인을 해도 비싸긴 하지만, 어쩔수가 없다. 감사해야지...)</p>
</blockquote>
<hr>
<p>그 사이에 같은 회사 수석님이 CKA를 따셨고, 자극을 정말 많이 받았다.
CKA 시험은 온라인으로 미리 날짜를 정하여 보게 되는데, 시험 응시환경 조건이 까다로워서 스터디카페에서 응시하는 방법 밖에 없어보였다.</p>
<h1 id="시험-장소">시험 장소</h1>
<p>날짜를 정하기 전에 집 주변에 스터디룸이 있는 스터디카페를 찾아봤다. (정말 많이 없더라)
한 10개 정도 찾아봤을까?
마침, IT기업 출신이신 사장님이 하시는 스터디카페를 발견했다.
스터디룸도 있었고, 가격도 나쁘지 않아보였다.</p>
<blockquote>
<p>IT기업 출신이라면 이런 IT자격증 시험도 염두하고, 스터디카페와 스터디룸을 구성해놓지 않았을까?</p>
</blockquote>
<p>주말에 사전답사를 가보았다.
심플하게 하얀 벽에 충전기 꽂기 편한 콘센트, 책상, 수납탁자, 투명한 화이트보드만 딱 있었고, 
시험보는데 오해의 소지가 있어 걸리거나 할 것도 없어보였다.</p>
<blockquote>
<p>천안, 아산 분이면 <u><em>워크앤티 스터디카페</em></u> 추천 👍 (광고 아님)
(나는 탕정점에서 봤는데, 불당점도 비슷하다고 한다.)</p>
</blockquote>
<h1 id="시험일정-정하기">시험일정 정하기</h1>
<p>CKA 시험 신청하고, My Portal에 들어가보면, 시험 스케줄을 잡을 수 있다.
나는 일정 상 연차를 쓸 수는 없어서, 날짜들을 보니 한국시간으로 12월 25일에도 응시가 가능하더라!
많은 시간들 중에 오전 9시를 선택했다.
크리스마스 날 오전에 시험을 보고 집으로 돌아가는 길에,
아내랑 먹을 크리스마스 케익을 픽업해서 집으로 돌아가겠다는 계획으로 날짜를 정했다.</p>
<p>그리고, 스터디룸은 응시 전 주변 환경점검, 시험이 늦어질 수도 있다는 점을 고려해서 아침 8시부터 정오까지 예약을 해놨다.</p>
<h1 id="시험-직전">시험 직전</h1>
<p>모든게 순조로울 줄 알았지만...
시험을 일주일 남겨놓고, 아내가 A형독감에 걸렸다.
철저하게 건강 관리를 하며 준비했다.</p>
<blockquote>
<p>독감에 걸리지 않기 위해서 귀가 너무 아팠지만, 잘 때도 마스크를 끼고 잤다.</p>
</blockquote>
<h2 id="시험-d-2">시험 D-2</h2>
<p>Udemy강의 Mock Exam 1, 2, 3을 세번째로 풀었고, 대부분의 모든 문제의 정답을 맞췄다.
어렵거나 헷갈리는 문제는 오답 정리하고 다시 풀어서 익숙해지게 만들었다.</p>
<h2 id="시험-d-1">시험 D-1</h2>
<p>시험을 신청했을 때 왔던 메일을 통해 <code>killer.sh</code> 문제를 한번 시험 PSI Bridge 환경 적응을 겸하여 풀어봤다.
풀기 어렵다고 들었는데, 1시간동안 6문제를 풀었고 그 중에 3문제를 맞췄다.
결국 시간이 관건이겠다는 생각이 들었다.</p>
<p>그리고, 메일로 따라왔던 튜토리얼 테스트도 한번 진행해봤다.</p>
<blockquote>
<p>맥북을 사용해서 시험을 응시하고자 하는 사람은 이 과정이 필수적이라고 본다.
PSI Bridge 환경에서 시험 보기 전에 강제 종료시켜야 하는 프로세스들이 있는데, 종료가 잘 안되는 프로세스들이 있으므로, 이 연습이 반드시 필요하다고 생각된다.
결국, 나는 불안해서 맥에 배치해놓은 위젯을 다 날리고 시험이 끝난 후, 다시 셋팅했다.</p>
</blockquote>
<blockquote>
<p>참, 당연히 그냥 손으로 푼 문제도 있지만, 쿠버네티스 공식 문서를 보면서 푼 문제도 있다.
한쪽에는 터미널, 한쪽에는 쿠버네티스 공식문서가 열려있는 Firefox 창을 적당히 잘 배치해놓자.
나 같은 경우에는 mousepad 메모장도 함께 잘 활용하는 연습을 해서, 수월하게 문제를 푸는데 도움을 받았다.
(application 실행 창에서 pad라고 검색하면 나옴)</p>
</blockquote>
<p>Udemy강의의 Mock Exam 1, 2, 3에서 취약한 문제를 다시 돌려보며 정리했다.</p>
<p>그리고, 다음 날 아침 시험을 위해 한번 더 스터디룸 예약이 잘 되어있는지 확인했고,
신분 확인용 여권, 맥북 &amp; 충전기, 무선 마우스, 마우스 패드, 키보드, 허브, 팜레스트
그리고, 혹시 몰라 문에 &#39;시험 응시중&#39; 이라고 문에 써붙일 2장의 종이와 스카치 테이프를 백팩에 챙겼다.</p>
<h1 id="시험-당일">시험 당일</h1>
<p>7시쯤 기상해서 물 한 컵만 마시고, 그 이후에 아무것도 먹지 않았다.
시험에 영향을 줄까봐 습관적으로 아침에 복용하는 유산균도 먹지 않았다.</p>
<p>스터디룸에 도착해서 다 준비해놓고,
시험 30분 전인 8시 30분부터 약 30분동안 꽤 꼼꼼하게 주변 환경 검사가 진행됐다.
노트북에 위치한 카메라를 이용해서</p>
<ul>
<li>스터디룸 전체 스캔</li>
<li>책상 전체, 책상 밑 스캔</li>
<li>키보드, 마우스 패드 전체 스캔</li>
<li>휴지: (책상 위에 올려놔도 되냐고 물어보고 카메라로 감독관이 스캔 후 허락이 되어 올려놓음)</li>
<li>폰: (미리 꺼놓고 가방에 넣어놔서 그렇게 말했더니 따로 검사를 진행하지는 않았다)</li>
</ul>
<p>예상보다 조금 빠르게 환경 체크가 끝났고, 스케줄 잡았던 9시보다는 조금 빨리 시험이 시작되었다.</p>
<h2 id="시험-문제">시험 문제</h2>
<p>기억 나는대로 유형을 적어보자면,</p>
<ul>
<li>PV 생성</li>
<li>PVC 생성</li>
<li>Multi Container Pod 생성</li>
<li>etcd backup &amp; restore</li>
<li>Sidecar Container 생성</li>
<li>Pod 내 ERROR 로그 찾기</li>
<li>Ready 상태 노드 개수 파악 (Taint 걸려있는 노드 제외)</li>
<li>Ingress 생성</li>
<li>업그레이드 (kubeadm, kubelet, kubectl)</li>
<li>Network Policy 생성</li>
<li>serviceaccount 생성 후 clusterrole, clusterrolebinding 연결</li>
<li>deployment scale out 문제</li>
<li>CPU 리소스 많이 사용하고 있는 Node 파악</li>
<li>특정 노드 drain</li>
</ul>
<p>이러한 문제들이었다.</p>
<p>거의 Udemy강의 내 Mock Exam 문제들과 비슷했다.
역시나, 2시간이라는 시간이 넉넉한 시간이 아니었다.
그리고, 문제를 빨리 이해를 못해서 포기한 문제가 2문제였다.
(다시 보면 이해가 되려나?)</p>
<p>100점은 못맞더라도, 내심 합격을 확신하고 나오긴 했지만,
특히 밤에, 잠을 조금 설쳤다. 😅</p>
<h1 id="합격">합격</h1>
<p>아침 9시 5분이 되었는데도 깜깜 무소식이었다가, 시간이 조금 더 지나니까 메일 알림이 왔다.
어떤 블로그에서 메일이 하나만 날아오면 불합격이고, 메일이 여러 개 날아오면 합격이라고 했는데 그 말이 맞긴 한 것 같다.
나는 첫 메일 알림 내용이 &#39;Congratulations!&#39; 인 것을 보고 합격 사실을 바로 인지하게 되었다.</p>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/3945269d-5251-4e24-9162-7cb0eab59a6e/image.png" alt=""></p>
<figcaption style="text-align:center; font-size:15px; color:#808080; margin-top:40px">
    푸쉬 알림이 없어져서 메일 캡처화면으로 대체 😅
</figcaption>

<p><img src="https://velog.velcdn.com/images/root-devvoo/post/b0c231f0-3798-4e8c-b700-9420ea27fb67/image.jpeg" alt=""></p>
<figcaption style="text-align:center; font-size:15px; color:#808080; margin-top:40px">
    🎄 크리스마스에 CKA 자격증이라니
</figcaption>

<p><img src="https://velog.velcdn.com/images/root-devvoo/post/34c1d7b9-75dd-400a-a10f-46b0a2c4cff1/image.png" alt=""></p>
<p>66점 커트에서 73점으로 합격했다.
100점을 목표로 한 것도 아니었지만, 사실 이 점수를 보고 새삼 감사함을 느끼기도 했는데,
시험 시간이 다 끝나기 3분 전쯤에 약간 검토할 여유가 있어서, 문제를 하나하나 검토를 하고 있었다.
근데, 한 문제에서 어처구니 없는 실수를 한게 발견됐다.</p>
<blockquote>
<p>이게 빠르게 해결하고 넘기려다보니 연습문제 풀이하면서, 자주 썼던 value 값을 주고 자원을 생성했는데,  문제의 요구사항이랑 전혀 다른 내용이었다.</p>
</blockquote>
<p>빠르게 그 실수를 다시 고치고나서 동시에 시험이 끝났는데, 그 실수를 발견하지 못했다면 결과가 어찌 됐을지 모르겠다는 생각을 하니, 감사하지 않을 수가 없다.</p>
<blockquote>
<p>이래서 검토가 참 중요하다. 아무리 시간이 없어도...!</p>
</blockquote>
<p>요즘, 나라가 경제적으로 어렵고, 시장 상황도 안좋은데・・・ 
좋은 자극제가 되었다.
여기서 안주하지 않고, 만족하지 말고, 더욱 성장해야 하겠다.</p>
<p>다음 자격증은 아마 aws 관련 자격증을 준비해서, 도전하지 않을까 싶다.</p>
<p>화이팅 💪🔥</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[문과 출신 엔지니어 2024년 1회 정보처리기사 실기 합격 후기 (Feat. 수제비)]]></title>
            <link>https://velog.io/@root-devvoo/%EB%AC%B8%EA%B3%BC-%EC%B6%9C%EC%8B%A0-%EC%97%94%EC%A7%80%EB%8B%88%EC%96%B4-2024%EB%85%84-1%ED%9A%8C-%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-%EC%8B%A4%EA%B8%B0-%ED%95%A9%EA%B2%A9-%ED%9B%84%EA%B8%B0-Feat.-%EC%88%98%EC%A0%9C%EB%B9%84</link>
            <guid>https://velog.io/@root-devvoo/%EB%AC%B8%EA%B3%BC-%EC%B6%9C%EC%8B%A0-%EC%97%94%EC%A7%80%EB%8B%88%EC%96%B4-2024%EB%85%84-1%ED%9A%8C-%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-%EC%8B%A4%EA%B8%B0-%ED%95%A9%EA%B2%A9-%ED%9B%84%EA%B8%B0-Feat.-%EC%88%98%EC%A0%9C%EB%B9%84</guid>
            <pubDate>Tue, 18 Jun 2024 09:25:09 GMT</pubDate>
            <description><![CDATA[<pre><code>💡 내돈내산 개인추천, 광고는 당연히 1도 없음</code></pre><p><img src="https://velog.velcdn.com/images/root-devvoo/post/07dff483-99ec-475a-9d04-ef0e766e05b2/image.jpg" alt=""></p>
<p>정보처리기사 실기 드디어! 합격했다. (점수는 69점 휴...)
사실 가채점한대로 점수가 나올지 안나올지 긴가민가 했던 부분이 있어서 어젯밤부터 마음을 많이 졸였다.</p>
<p>2022년에 정보처리기사 필기합격을 1트만에 한 후, 22년 3회에 난이도 체감을 위해서 준비 하나도 안된 상태에서 실기시험을 응시했었는데, 그때 당연히 대부분의 문제를 풀지도 못한 채로 시험장을 나왔고, &quot;열심히 공부해서 응시해야 합격할까 말까 하겠다&quot;는 생각을 되게 많이 했다.</p>
<blockquote>
<p>2022년 필기시험 때는 개발자로 일하고 있었을 때라, 시험 전 1주일동안 틈 날 때마다 최신 기출부터 문제은행을 계속 반복해서 풀었고 한 번에 합격했다.
(문제은행 링크: <a href="https://www.comcbt.com/xe/gscomcbt">https://www.comcbt.com/xe/gscomcbt</a>)</p>
</blockquote>
<blockquote>
<p>2020년 이후 개정된 정보처리기사 실기 시험은 문제 난이도가 계속해서 올라가고 있다.
개정 전인 예전 정보처리기사 실기 시험 난이도랑은 완전 다르다. 방심하다 쓴 맛을 보게 될 것이다. 🤯</p>
</blockquote>
<p>그 후에는 대기업 인턴 과정과 현업에서 근무를 하게 되어 당장 앞에 닥친 과제나 업무들에 집중하느라 정보처리기사 실기 공부에 신경 쓸 시간이 부족했다.</p>
<p>그리고 필기시험 면제 유효기간이 임박해오고 있는 걸 인지하고, 포기를 할까 고민하던 와중에 마침 공부할 수 있는 시간적 여유가 다소 생기게 되었고, 동네 이웃인 대학 선배가 &quot;이번에 시험보면 진짜 합격할 것 같은데 준비해서 시험 꼭 보는게 어때?&quot; 라고 얘기해주셨다.</p>
<p>그리고, 그때가 마침 네이버 수제비 카페 8주 스터디가 시작되기 며칠 전이라 8주 스터디 스케줄을 그대로 따라서 &quot;결과와 상관없이 후회없이 공부해보기&quot;를 다짐하게 되었다.</p>
<p>2022년때 사서 갖고있던 수제비 실기 책 2권과 더불어서, 바로 인터넷으로 2024년 수제비 FINAL 실전 모의고사 책을 주문하여 빠른 배송을 받았다.</p>
<blockquote>
<p>여담으로, 책이 도착하자마자 포장을 뜯었는데, 소방자격증 관련 책이 와서 심히 당황했고, 다다음날 재발송된 책을 받았다. (어느 서점이라곤 말하지 않겠다)</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/38c8c466-0054-4bc6-997b-72a952f34f04/image.png" alt=""></p>
<p>그리고, 이렇게 8주동안 평일에는 하루도 빼놓지 않고 정 안되는 날에는 최소 1-2시간 만이라도 스터디를 진행하거나 비교적 여유로운 날에 몰아서 정해진 분량을 공부했다.
그냥 형식적으로 글만 올린게 아니라 2주 정도는 2022년 기본서와 인터넷을 동원하여 이론 공부하면서 Daily 문제를 풀고 오답노트를 작성하며 학습했고,
나머지 6주 정도는 Daily 문제를 포함하여 2024년 FINAL 실전 모의고사 책 문제들과 최신 기출문제부터 역으로 풀고, 오답노트를 작성하였고, 모르는 이론은 어떻게든 찾아서 노트에 필기하면서 머릿속에 집어넣었다.</p>
<blockquote>
<p>새 무지 공책 2권을 다 썼다.</p>
</blockquote>
<blockquote>
<p>C, Java, Python 등의 프로그래밍 문제는 답이 이상하다고 의심되면 직접 코드를 쳐서 코드 실행 순서나 결과값을 확인했다. (의심은 했으나 잘못된 답은 하나도 없었다)
(웹 컴파일 ide 추천 링크: <a href="https://pythontutor.com/visualize.html#mode=edit">https://pythontutor.com/visualize.html#mode=edit</a>
<a href="https://ideone.com/">https://ideone.com/</a>)</p>
</blockquote>
<p>중간중간에 심적으로 걱정이 되거나 지칠 때도 있었는데, 수제비 카페 쌤들이 바쁘신 와중에도 매일같이 달아주시는 자극, 응원, 격려의 글과 댓글들이 정말 힘이 많이 되었다.</p>
<blockquote>
<p>주변 사람들한테는 방해될까봐 묵묵히 공부하는 컨셉으로 지냈음</p>
</blockquote>
<p>시험 직전에는 족보 문제와 수제비 카페 내에서 자체적으로 실시하는 시험 직전 모의고사 문제를 풀었는데, 생각보다 결과가 안좋아서 걱정이 많았었다. 시험 직전에 두음쌤이 항상 올려주시는 [시험 전 마음가짐] 이라는 글이 도움이 많이 되었다.
그 글을 보고 마음을 다시 가다듬고, 시험이 가까운 모교에서 예정되었던 연유로 실기시험 직전 날 밤 11시 55분까지 족보문제 인강도 보고, 오답노트 쓰면서 머릿속에 엄청 상기시켰다.</p>
<p>시험 때, 단순 사칙 연산용 계산기를 무조건 챙겨가서 실전에서 유용하게 써먹으려고 공부하는 기간동안 내내 생각했었는데, 전날 밤까지 공부하는 바람에 계산기를 챙기는 것을 멍청하게 까먹었고 시험장에 챙겨가지 못했다. 시험장에 들어가서야 내가 계산기를 챙기지 않았다는 사실을 알아버렸다.</p>
<blockquote>
<p>시험보면서도 느꼈지만, 계산기가 있으면 빠른 문제풀이와 시간 단축에 정말 많이 도움이 될 것 같다.</p>
</blockquote>
<p>결국, 이렇게 (필기시험 면제 유효기간 마지막) + (실기 응시 2트 만) 에 정보처리기사 실기시험에서 합격을 하게 되었다.</p>
<p>내 주변에 현업에 계시는 대학 선후배 및 전 직장 팀장님 &amp; 동료들, 친구들, 네이버 수제비 카페 선생님들 덕분에 후회없이 준비해서 좋은 결과를 얻게되어 너무 감사하다. 🙏</p>
<p>수제비 정처기 실기 기본서와 모의고사 책들, 족보문제, 인강, 시험 직전 자체 모의고사 문제, Daily 문제 등등 모두 정말 강추한다.</p>
<blockquote>
<p>각자 공부 스타일이 다르겠지만, 나는 수제비 책들과 더불어서 이론 내용과 오답에 대한 노트를 쓰면서 공부하는 방법이 좋은 결과를 얻는데 정말 좋은 전략이었다고 생각한다.</p>
</blockquote>
<blockquote>
<p>나는 인강을 구매하지 않았지만, 스터디 덕에 얻은 족보문제 풀이 인강만 봐도 인강 퀄리티가 너무 좋다는게 느껴졌다.
CS 공부가 많이 안되어있는 응시자라면 인강을 보면서 준비하는 것도 좋은 것 같다. (돈을 더 투자하긴 해야됨)</p>
</blockquote>
<p>정처기 응시 예정에 있으신 분들은 여러 방법을 총동원해서 후회없이 준비해보시길 바란다!</p>
<p>포기하지않고, 열심히 준비해서 도전하면 좋은 결과 있을거라고 생각한다.</p>
<blockquote>
<p>프로그래밍 문제(C, Java, Python)와 SQL 문제의 공략이 정말 중요하다. 수제비 카페에도 많은 후기와 공략법이 있으니 참고해보는 것도 좋을 것 같다.</p>
</blockquote>
<p><strong>수제비 카페 링크</strong>
<a href="https://cafe.naver.com/soojebi">https://cafe.naver.com/soojebi</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[oh-my-posh 오류 해결방법]]></title>
            <link>https://velog.io/@root-devvoo/oh-my-posh-%EC%98%A4%EB%A5%98-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@root-devvoo/oh-my-posh-%EC%98%A4%EB%A5%98-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Tue, 04 Jun 2024 06:12:55 GMT</pubDate>
            <description><![CDATA[<pre><code>💡 Windows PowerShell을 oh-my-zsh처럼 예쁘게 꾸며주는 &#39;oh-my-posh&#39; 라는게 있다. 
   새 컴퓨터에 &#39;oh-my-posh&#39; 를 적용하다가 내 경우에 발생한 오류 해결방법을 작성해본다.</code></pre><hr>
<p>oh-my-posh를 영구적으로 파워쉘을 실행하자마자 사용하도록 적용시키기 위해</p>
<pre><code class="language-powershell">notepad $PROFILE</code></pre>
<p>위 명령어로 <code>Microsoft.PowerShell_profile.ps1</code> 파일 편집을 해주었다.</p>
<h1 id="microsoftpowershell_profileps1-파일-편집-내용"><code>Microsoft.PowerShell_profile.ps1</code> 파일 편집 내용</h1>
<pre><code>oh-my-posh init pwsh | Invoke-Expression</code></pre><p>경로를 못찾는다는 오류가 나오면 파일이 없다는 것이므로 <code>echo $PROFILE</code> 명령어로 경로 지정이 어떻게 되어있는지 확인해보았다.</p>
<p>내 경우 <code>$PROFILE</code> 변수가 담고 있는 경로는 <code>C:\Users\ThinkBook\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1</code>이고 해당 경로에 폴더 및 파일을 같은 이름으로 만들어준다.</p>
<p>그리고, 파워쉘을 다시 실행시키면 적용된다고 했는데…</p>
<h2 id="unauthorizedaccess-오류-발생"><code>UnauthorizedAccess</code> 오류 발생</h2>
<pre><code class="language-powershell">...

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : SecurityError: (:) [], PSSecurityException
    + FullyQualifiedErrorId : UnauthorizedAccess</code></pre>
<p>그런데 갑자기 파워쉘에서 위와 같은 오류가 발생했다.</p>
<h3 id="해결">해결</h3>
<p>파워쉘을 관리자 권한으로 다시 열고, 아래 명령을 실행 시켜 준 다음 다시 파워쉘을 실행시켰다.</p>
<pre><code class="language-powershell">Set-ExecutionPolicy -ExecutionPolicy RemoteSigned</code></pre>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/a04af78e-05cb-4ce1-8b1e-52681f56805e/image.png" alt=""></p>
<p>위 이미지에 나타나듯이 잘된다.</p>
<h1 id="oh-my-posh-테마-적용">oh-my-posh 테마 적용</h1>
<p>나는 iterm2 테마를 적용하였다.</p>
<h2 id="microsoftpowershell_profileps1-파일-편집-내용-1"><code>Microsoft.PowerShell_profile.ps1</code> 파일 편집 내용</h2>
<pre><code>oh-my-posh init pwsh --config &quot;https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/iterm2.omp.json&quot; | Invoke-Expression</code></pre><p>위 내용을 한 줄 더 추가해줬다.</p>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/63fa8f57-30ec-4b8c-81c5-6ff3bf150450/image.png" alt=""></p>
<p>최종적으로 위와 같은 형태로 저장했다.</p>
<p>그리고 다시 윈도우 터미널에서 파워쉘을 켰더니…</p>
<h2 id="get-psreadlinekeyhandler-오류-발생"><code>Get-PSReadLineKeyHandler</code> 오류 발생</h2>
<pre><code>Get-PSReadLineKeyHandler : 매개 변수 이름 &#39;Key&#39;과(와) 일치하는 매개 변수를 찾을 수 없습니다.

...</code></pre><p>파워쉘에서 이런 오류가 떴다.</p>
<h3 id="해결-1">해결</h3>
<p>관리자 권한으로 파워쉘을 다시 실행시킨 후,</p>
<pre><code class="language-powershell">Install-Module PsReadLine -Force</code></pre>
<p>위 명령어를 실행시켰다.</p>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/954566fe-3c16-4d38-a3ad-8dbd84be6681/image.png" alt=""></p>
<p>테마 적용이 잘되어 윈도우 터미널에서 파워쉘을 실행시켰을 때 위와 같이 잘 나오고 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[External Secrets Operator를 통한 Node기반 Amazon EKS 클러스터 Pod 내 AWS Secrets Manager 데이터를 환경변수로 주입]]></title>
            <link>https://velog.io/@root-devvoo/External-Secrets-Operator%EB%A5%BC-%ED%86%B5%ED%95%9C-Node%EA%B8%B0%EB%B0%98-Amazon-EKS-%ED%81%B4%EB%9F%AC%EC%8A%A4%ED%84%B0-Pod-%EB%82%B4-AWS-Secrets-Manager-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A5%BC-%ED%99%98%EA%B2%BD%EB%B3%80%EC%88%98%EB%A1%9C-%EC%A3%BC%EC%9E%85</link>
            <guid>https://velog.io/@root-devvoo/External-Secrets-Operator%EB%A5%BC-%ED%86%B5%ED%95%9C-Node%EA%B8%B0%EB%B0%98-Amazon-EKS-%ED%81%B4%EB%9F%AC%EC%8A%A4%ED%84%B0-Pod-%EB%82%B4-AWS-Secrets-Manager-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A5%BC-%ED%99%98%EA%B2%BD%EB%B3%80%EC%88%98%EB%A1%9C-%EC%A3%BC%EC%9E%85</guid>
            <pubDate>Wed, 29 May 2024 01:57:20 GMT</pubDate>
            <description><![CDATA[<h1 id="aws-secrets-manager-데이터-형태-예시">AWS Secrets Manager 데이터 형태 예시</h1>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/eb4f033c-d978-4871-a990-dbef8f69d16b/image.png" alt=""></p>
<p><code>common-secret</code> 데이터 형태는 아래와 같은 구조</p>
<pre><code>&quot;app&quot;: {
    &quot;DB&quot;: {
          &quot;HOST&quot;: &quot;xxx.xxxx.xxxx&quot;,
        &quot;PASSWORD&quot; : &quot;****&quot;
    },
    &quot;KAFKA_BROKERS&quot;: &quot;kkk.xxxx.xxxxx&quot;
},

...
</code></pre><h1 id="helm으로-external-secret-install">Helm으로 External Secret Install</h1>
<pre><code class="language-bash">$ helm repo add external-secrets https://charts.external-secrets.io

$ helm install external-secrets \
       external-secrets/external-secrets \
       -n external-secrets \
       --create-namespace \
       --set installCRDs=true \
       --set webhook.port=9443</code></pre>
<h1 id="parameter-store-연동">Parameter Store 연동</h1>
<h2 id="secret-store-생성">Secret Store 생성</h2>
<p><code>dev-secretstore.yaml</code></p>
<pre><code class="language-yaml">apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: dev-secretstore
  namespace: kube-system
spec:
  provider:
    aws:
      service: SecretsManager
      region: ap-northeast-2
      auth:
        jwt:
          serviceAccountRef:
            name: eks-sa-role # Secret Manager 접근 권한을 들고 있는 Service Account Role 이름 명시</code></pre>
<h2 id="external-secret-생성">External Secret 생성</h2>
<p><code>dev-externalsecret.yaml</code></p>
<pre><code class="language-yaml">apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: dev-externalsecret
  namespace: kube-system
spec:
  refreshInterval: 1m
  secretStoreRef:
    name: dev-secretstore # 위에서 생성한 Secret Store 이름 명시
    kind: SecretStore
  target:
    name: app-secret # 클러스터 내 생성할 secret 이름
    creationPolicy: Owner
  data:
  - secretKey: DB_HOST
    remoteRef:
      key: &quot;common-secret&quot; # 값 가져올 AWS Secret Manager Name 명시
      property: app.DB.HOST # 3중첩 # xxx.xxxx.xxxx
  - secretKey: KAFKA_BROKERS
    remoteRef:
      key: &quot;common-secret&quot;
      property: app.KAFKA_BROKERS # 2중첩 # kkk.xxxx.xxxxx</code></pre>
<h2 id="해당-값을-deploymentpod에-환경변수-주입">해당 값을 deployment(Pod)에 환경변수 주입</h2>
<p><code>app-admin-deployment.yaml</code> 파일</p>
<pre><code class="language-yaml">apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-deployment
  namespace: kube-system
spec:
  replicas: 1
  selector:
    matchLabels:
      app: app-deployment
  template:
    metadata:
      labels:
        app: app-deployment
    spec:
      containers:
      - name: app-deployment
        image: [AccountID].dkr.ecr.ap-northeast-2.amazonaws.com/develop/[ImageName]:latest
        # envFrom:
        #   - configMapRef: 
        #       name: env-configmap
        ## 여기부터
        env:
          - name: DB_HOST # 컨테이너 내에 등록될 환경변수의 이름
            valueFrom:
              secretKeyRef:
                name: app-secret # 참조할 클러스터 내 Secret Name
                key: DB_HOST # Secret 내에 명시된 참조할 키 Name
                optional: false # 환경변수가 제대로 주입이 안될 경우 컨테이너 생성이 안되게 함
          - name: KAFKA_BROKERS
            valueFrom:
              secretKeyRef:
                name: app-secret
                key: KAFKA_BROKERS
                optional: false
        ########################################################################
        ports:
        - containerPort: 3000</code></pre>
<h1 id="참고">참고</h1>
<h2 id="링크">링크</h2>
<p><a href="https://external-secrets.io/latest/provider/aws-secrets-manager/">https://external-secrets.io/latest/provider/aws-secrets-manager/</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[External Secrets를 이용한 Amazon EKS(Fargate) 클러스터 Pod내 SSM Parameter Store 데이터 환경변수 주입 방법]]></title>
            <link>https://velog.io/@root-devvoo/External-Secrets%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-Amazon-EKSFargate-%ED%81%B4%EB%9F%AC%EC%8A%A4%ED%84%B0-Pod%EB%82%B4-SSM-Parameter-Store-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%99%98%EA%B2%BD%EB%B3%80%EC%88%98-%EC%A3%BC%EC%9E%85-%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@root-devvoo/External-Secrets%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-Amazon-EKSFargate-%ED%81%B4%EB%9F%AC%EC%8A%A4%ED%84%B0-Pod%EB%82%B4-SSM-Parameter-Store-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%99%98%EA%B2%BD%EB%B3%80%EC%88%98-%EC%A3%BC%EC%9E%85-%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Tue, 28 May 2024 03:22:15 GMT</pubDate>
            <description><![CDATA[<h1 id="aws-ssm-parameter-store-값-환경변수-주입방법">AWS SSM Parameter Store 값 환경변수 주입방법</h1>
<h2 id="helm으로-external-secrets-install">Helm으로 External Secrets Install</h2>
<pre><code class="language-bash">$ helm repo add external-secrets https://charts.external-secrets.io

$ helm install external-secrets \
       external-secrets/external-secrets \
       -n external-secrets \
       --create-namespace \
       --set installCRDs=true \
       --set webhook.port=9443</code></pre>
<p>위 명령어 실행 후 확인</p>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/9aaa1bec-e57f-48fd-90fb-1c898999009a/image.png" alt=""></p>
<p><code>external-secrets</code>, <code>external-secrets-cert-controller</code>, <code>external-secrets-webhook</code> 총 세 종류의 파드가 정상적으로 확인되어야한다.</p>
<h2 id="eks-service-account에-iam-policy-설정">EKS Service Account에 IAM Policy 설정</h2>
<p>미리 생성해놓은 <code>victor-eks-fargate-svc-role</code>에 아래와 같이 설정해주었다.</p>
<img src="https://velog.velcdn.com/images/root-devvoo/post/4f793a39-3dc5-4049-bdad-36715963cff3/image.png" width=70% height=70%>

<h2 id="parameter-store-연동">Parameter Store 연동</h2>
<h3 id="secret-store-생성">Secret Store 생성</h3>
<p><code>victor-secretstore.yaml</code>내용</p>
<pre><code class="language-yaml">apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: victor-parameterstore
  namespace: kube-system # namespace는 당연히 모두 같아야 함.
spec:
  provider:
    aws:
      service: ParameterStore
      region: ap-northeast-2
      auth:
        jwt:
          serviceAccountRef: # 인증에 사용할 IAM Service Account 정보 정의
            name: victor-eks-fargate-svc-role-sa </code></pre>
<p>apply 해준다.</p>
<pre><code class="language-bash">$ kubectl apply -f victor-secretstore.yaml</code></pre>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/e67eac22-9ffa-4646-acd5-ae089408b0b6/image.png" alt=""></p>
<p>Valid 상태가 되면 잘 된것이다.</p>
<h3 id="external-secret-생성">External Secret 생성</h3>
<p>현재 AWS SSM 파라미터 스토어에 저장되어있는 test-key 파라미터의 값을 사용할 것이다.</p>
<img src="https://velog.velcdn.com/images/root-devvoo/post/bd9f1ab8-d265-4311-aa86-ab7a8ae62916/image.png" width=70% height=70%>

<p><code>victor-externalsecret.yaml</code> 내용</p>
<pre><code class="language-yaml">apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: victor-externalsecret
  namespace: kube-system
spec:
  secretStoreRef: # 위에서 생성한 SecretStore 정보 정의
    name: victor-parameterstore
    kind: SecretStore
  target:
    name: victor-k8s-secret # EKS 클러스터 내에 만들어질 secret name 정의
  data:
  - secretKey: test-key # secret 내 key name 정의
    remoteRef:
      key: test-key # 클러스터 내에서 쓸 AWS SSM Parameter store데이터의 key name 명시</code></pre>
<p>apply 해준다.</p>
<pre><code class="language-bash">$ kubectl apply -f victor-externalsecret.yaml</code></pre>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/80964fd4-2e9e-4314-b165-01f23fe864bf/image.png" alt=""></p>
<p>apply 후 확인해보니 SecretSynced 상태이고</p>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/dab89004-a8da-4a71-88c4-8d91c5bc90a3/image.png" alt=""></p>
<p>EKS 클러스터 내 secret에 방금 yaml파일 target 내 지정한 이름으로 잘 생성이 되어있다.</p>
<h2 id="해당-값을-deployment에-환경변수-주입">해당 값을 deployment에 환경변수 주입</h2>
<p>deployment 파일 수정</p>
<pre><code class="language-yaml">apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-deployment
  namespace: kube-system
spec:
  replicas: 1
  selector:
    matchLabels:
      app: app-deployment
  template:
    metadata:
      labels:
        app: app-deployment
    spec:
      containers:
      - name: app-deployment
        image: # 비공개
        envFrom:
          - configMapRef:
              name: env-configmap
        # 이 아래부분 부터
        env:
          - name: TEST_KEY # 컨테이너 내에서 등록될 환경변수의 이름
            valueFrom:
              secretKeyRef:
                name: victor-k8s-secret # secret의 이름
                key: test-key # secret data에 명시된 키
                optional: false # 환경변수가 제대로 주입이 안될 경우 컨테이너 생성이 안되게 함
        ########################################################################
        ports:
        - containerPort: 3000</code></pre>
<p>그리고, apply 해준다.</p>
<pre><code class="language-bash">$ kubectl apply -f app-deployment.yaml</code></pre>
<p>배포된 deployment(pod)에 Shell로 접속해서 환경변수로 주입이 잘 되어있는지 확인해보자.</p>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/d3da1c3d-3d55-4875-8a52-4f023970d771/image.png" alt=""></p>
<p>잘 확인된다.</p>
<h2 id="부록-aws-ssm-parameter-store-값-환경변수-주입방법-json-형식">[부록] AWS SSM Parameter Store 값 환경변수 주입방법 (JSON 형식)</h2>
<blockquote>
<p><strong>참고</strong>: Parameter Store에 저장되어있는 중첩되있는 값들이나 array들도 gjson 문법으로 액세스가 가능하다. (<a href="https://github.com/tidwall/gjson/blob/master/SYNTAX.md">https://github.com/tidwall/gjson/blob/master/SYNTAX.md</a>)</p>
</blockquote>
<img src="https://velog.velcdn.com/images/root-devvoo/post/cfff8b80-7fcb-49fa-88b7-050a1e0807cd/image.png" width=50% height=50%>

<p>AWS SSM Parameter Store에 위와 같은 JSON 및 array 형태의 키와 값을 저장해줬다.</p>
<h3 id="secret-store-생성-1">Secret Store 생성</h3>
<p><code>victor-secretstore.yaml</code>내용</p>
<pre><code class="language-yaml">apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: victor-parameterstore
  namespace: kube-system
spec:
  provider:
    aws:
      service: ParameterStore
      region: ap-northeast-2
      auth:
        jwt:
          serviceAccountRef:
            name: victor-eks-fargate-svc-role-sa # 인증에 사용할 IAM Service Account 정보 정의</code></pre>
<p>apply 해준다.</p>
<pre><code class="language-bash">$ kubectl apply -f victor-secretstore.yaml</code></pre>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/88461ed1-d258-43f6-a245-e142f19a8696/image.png" alt=""></p>
<p>Valid 상태 확인</p>
<h3 id="external-secret-생성-1">External Secret 생성</h3>
<p><code>victor-externalsecret.yaml</code> 내용</p>
<pre><code class="language-yaml">apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: victor-externalsecret
  namespace: kube-system
spec:
  refreshInterval: 1m # 1분마다 refresh해서 Parameter store 값 업데이트해서 가져옴
  secretStoreRef: # 위에서 생성한 SecretStore 정보 정의
    name: victor-parameterstore
    kind: SecretStore
  target:
    name: victor-k8s-secret-db # EKS 클러스터 내에 만들어질 secret name 정의
  data:
  - secretKey: account-id # secret 내 key name 정의
    remoteRef:
      key: victor-secret-db # EKS 클러스터로 가져올 AWS SSM Parameter store 데이터의 key name 명시
      property: account.id # root

  - secretKey: account-password
    remoteRef:
      key: victor-secret-db
      property: account.password # root1234

  - secretKey: endpoint-url-0
    remoteRef:
      key: victor-secret-db
      property: endpoints.0.url # test01.com

  - secretKey: endpoint-tag-0
    remoteRef:
      key: victor-secret-db
      property: endpoints.0.tag # test01</code></pre>
<p>apply 해준다.</p>
<pre><code class="language-bash">$ kubectl apply -f victor-externalsecret.yaml</code></pre>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/c3b8970e-96c1-4d35-930a-ebac9c2eaf80/image.png" alt=""></p>
<p>apply 후 <code>kubectl get externalsecret -n kube-system</code> 명령어로 확인해보니 SecretSynced 상태이고</p>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/e7039b5d-0921-4fea-8a48-d54ea8cf3ffe/image.png" alt=""></p>
<p>EKS 클러스터 내 secret에 방금 yaml파일 target 내 지정한 이름으로 잘 생성이 되어있다.</p>
<h3 id="해당-값을-deployment에-환경변수-주입-1">해당 값을 deployment에 환경변수 주입</h3>
<p>deployment 파일 수정</p>
<pre><code class="language-yaml">apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-deployment
  namespace: kube-system
spec:
  replicas: 1
  selector:
    matchLabels:
      app: app-deployment
  template:
    metadata:
      labels:
        app: app-deployment
    spec:
      containers:
      - name: app-deployment
        image: # 비공개
        envFrom:
          - configMapRef:
              name: env-configmap
        env: # 여기 아래부터
          - name: DB_ID # 컨테이너 내에서 등록될 환경변수의 이름
            valueFrom:
              secretKeyRef:
                name: victor-k8s-secret-db # secret의 이름
                key: account-id # secret data에 명시된 키
                optional: false # 환경변수가 제대로 주입이 안될 경우 컨테이너 생성이 안되게 함
          - name: DB_PASSWORD
            valueFrom:
              secretKeyRef:
                name: victor-k8s-secret-db
                key: account-password
                optional: false
          - name: DB_ENDPOINT_URL_0
            valueFrom:
              secretKeyRef:
                name: victor-k8s-secret-db
                key: endpoint-url-0
                optional: false
          - name: DB_ENDPOINT_TAG_0
            valueFrom:
              secretKeyRef:
                name: victor-k8s-secret-db
                key: endpoint-tag-0
                optional: false            
        ###########################################################################
        ports:
        - containerPort: 3000</code></pre>
<p>그리고, apply 해준다.</p>
<pre><code class="language-bash">$ kubectl apply -f app-admin-deployment.yaml</code></pre>
<p>배포된 deployment(pod)에 Shell로 접속해서 환경변수로 주입이 잘 되어있는지 확인해보자.</p>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/edc6331a-3212-4655-87f8-f13c46c4e643/image.png" alt=""></p>
<p>잘 확인된다.</p>
<blockquote>
<p>💡 참고
AWS SSM Parameter Store에서 데이터 값 변경이 일어난 경우, EKS 클러스터 내 secret에서 refresh되어 업데이트가 됐다 하더라도 해당 deployment(pod)가 재기동 되어야지 환경변수도 업데이트 된다.</p>
</blockquote>
<h1 id="eks-secret-값을-aws-ssm-parameter-store에-push하기">EKS Secret 값을 AWS SSM Parameter Store에 push하기</h1>
<h2 id="다른-이름의-secret-store-생성">다른 이름의 Secret Store 생성</h2>
<p><code>victor-secretstore-aws.yaml</code></p>
<pre><code class="language-yaml">apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: aws-parameterstore # name만 다르게 해줌
  namespace: kube-system
spec:
  provider:
    aws:
      service: ParameterStore
      region: ap-northeast-2
      auth:
        jwt:
          serviceAccountRef:
            name: victor-eks-fargate-svc-role-sa</code></pre>
<p>apply</p>
<pre><code class="language-bash">$ kubectl apply -f victor-secretstore-aws.yaml</code></pre>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/a006ebf8-7879-4249-b9cc-3fcb7c3b51d2/image.png" alt=""></p>
<p>Secret Store가 잘 생성되었다.</p>
<h2 id="push-secret-생성">Push Secret 생성</h2>
<p><code>victor-pushsecret.yaml</code></p>
<pre><code class="language-yaml">apiVersion: external-secrets.io/v1alpha1
kind: PushSecret
metadata:
  name: victor-pushsecret # Customisable
  namespace: kube-system # Same of the SecretStores
spec:
  refreshInterval: 10s # Refresh interval for which push secret will reconcile
  secretStoreRefs: # A list of secret stores to push secrets to
    - name: aws-parameterstore
      kind: SecretStore
  selector:
    secret:
      name: victor-k8s-secret # Source Kubernetes secret to be pushed
  data:
    - match:
        secretKey: test-key # Source Kubernetes secret key to be pushed
        remoteRef:
          remoteKey: test-key-2 # Remote reference (where the secret is going to be pushed)</code></pre>
<p>위 내용으로 apply</p>
<pre><code class="language-bash">$ kubectl apply -f victor-pushsecret.yaml</code></pre>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/9ad6c56d-2a22-495a-a90f-a2a28fa686a7/image.png" alt=""></p>
<p>위와 같이 Synced 상태이면 잘 된 것이다.</p>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/6ea5af00-b7c3-4795-b6eb-8cf173b4a8e9/image.png" alt=""></p>
<p>그리고, AWS SSM Parameter Store에 test-key-2라는 이름으로 EKS 클러스터 시크릿 내 test-key 의 값이 push 된 것을 확인할 수 있다.</p>
<h1 id="참고-링크">참고 링크</h1>
<h2 id="fargate-기반-클러스터에서-aws-ssm-parameter-store-값-사용-관련">Fargate 기반 클러스터에서 AWS SSM Parameter Store 값 사용 관련</h2>
<hr>
<p><a href="https://aws.amazon.com/ko/blogs/containers/leverage-aws-secrets-stores-from-eks-fargate-with-external-secrets-operator/">https://aws.amazon.com/ko/blogs/containers/leverage-aws-secrets-stores-from-eks-fargate-with-external-secrets-operator/</a></p>
<p><a href="https://external-secrets.io/latest/">https://external-secrets.io/latest/</a></p>
<p><a href="https://external-secrets.io/latest/provider/aws-parameter-store/">https://external-secrets.io/latest/provider/aws-parameter-store/</a></p>
<p><a href="https://eminalemdar.medium.com/reversing-the-workflow-with-external-secrets-operators-push-secret-feature-f2a64f3db748">https://eminalemdar.medium.com/reversing-the-workflow-with-external-secrets-operators-push-secret-feature-f2a64f3db748</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[쉘 스크립트에서 ’ ’, ” ”, ` ` 및 괄호 기능과 차이점]]></title>
            <link>https://velog.io/@root-devvoo/%EC%89%98-%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%97%90%EC%84%9C-%EB%94%B0%EC%98%B4%ED%91%9C-%EC%8C%8D%EB%94%B0%EC%98%B4%ED%91%9C-%EB%B0%B1%ED%8B%B1-%EB%B0%8F-%EA%B4%84%ED%98%B8-%EA%B8%B0%EB%8A%A5%EA%B3%BC-%EC%B0%A8%EC%9D%B4%EC%A0%90</link>
            <guid>https://velog.io/@root-devvoo/%EC%89%98-%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%97%90%EC%84%9C-%EB%94%B0%EC%98%B4%ED%91%9C-%EC%8C%8D%EB%94%B0%EC%98%B4%ED%91%9C-%EB%B0%B1%ED%8B%B1-%EB%B0%8F-%EA%B4%84%ED%98%B8-%EA%B8%B0%EB%8A%A5%EA%B3%BC-%EC%B0%A8%EC%9D%B4%EC%A0%90</guid>
            <pubDate>Tue, 28 May 2024 01:33:38 GMT</pubDate>
            <description><![CDATA[<ul>
<li><p><strong>따옴표 <code>&#39; &#39;</code></strong></p>
<ul>
<li>따옴표로 감싸진 문자열은 문자열 그대로 유지되어 출력된다. (Bash 변수 사용 불가능)</li>
<li>따옴표에서는 특수기호 이스케이핑을 해주지 않아도 문자 그 자체로 출력이 가능하다.</li>
</ul>
</li>
<li><p><strong>쌍따옴표 <code>&quot; &quot;</code></strong></p>
<ul>
<li>쌍따옴표로 감싸진 문자열 내에서는 Bash에서 선언한 변수사용이 가능하다.</li>
</ul>
</li>
<li><p>*<em>백틱 <code>` `</code> *</em></p>
<ul>
<li><p>리눅스 쉘에서 백틱은 <code>$()</code>와 함께 명령어 대체(command subtitution)로 분류되는 표현식이다. 백틱 또는 <code>$()</code>괄호 안에 기술하는 명령어를 하위 쉘이 실행하고 그 출력 결과를 문자열로 대체하여 준다.</p>
  <img src="https://velog.velcdn.com/images/root-devvoo/post/c4a90a32-3146-4179-be34-7b8e362cc9f1/image.png" width=50% height=50%>


</li>
</ul>
</li>
</ul>
<pre><code>- 권장 사항
    - 백틱은 오래된 표현법으로 중첩되는 괄호나 이스케이프 문자 관련하여 혼란이 있을 수 있으므로 달러괄호 `$()` 표현이 권장된다.
        참고1: [Bash scripting: Moving from backtick operator to $ parentheses](https://www.redhat.com/sysadmin/backtick-operator-vs-parens)
        참고2: [What&#39;s the difference between $(stuff) and `stuff`?](https://unix.stackexchange.com/questions/5778/whats-the-difference-between-stuff-and-stuff)

- 주의할 점
    - 명령어 대체는 현재 환경 기준으로 하위 쉘을 통해 수행되므로 만약 둘러싸고 있는 명령이 원격이나 다른 환경에서 실행된다면 서로 다른 환경에서 실행될 수 있다는 점을 유의해야 한다.

        &lt;img src=&quot;https://velog.velcdn.com/images/root-devvoo/post/bc2e9012-b441-4132-91f6-7066cb9ee8aa/image.png&quot; width=50% height=50%&gt;

        &lt;img src=&quot;https://velog.velcdn.com/images/root-devvoo/post/b26c6fcd-f413-4e36-84f2-dbf3064ac2c6/image.png&quot; width=50% height=50%&gt;

        ```
        # xargs는 주어진 입력으로 다른 명령어를 실행하도록 도와줌.
        # -I : -I 옵션 뒤에 replace-str을 정의하고 replace-str가 모두 xargs에 전달된 인수로 대체됨
        ```</code></pre><blockquote>
<pre><code>📝 출처: https://shanta.tistory.com/18
        https://jjeongil.tistory.com/1574</code></pre></blockquote>
<p>```</p>
<h1 id="따옴표-를-사용해야-할-때">따옴표(<code>‘ ’</code>)를 사용해야 할 때</h1>
<ul>
<li>문자열 그 자체가 존중되고 싶을 때</li>
<li>특수문자가 많이 포함된 문자열의 경우, 백슬래시(<code>\</code>)를 사용해가며 일일이 Escaping을 해주기 귀찮을 때</li>
</ul>
<h1 id="쌍따옴표-를-사용해야-할-때">쌍따옴표(<code>“ ”</code>)를 사용해야 할 때</h1>
<ul>
<li>문자열 내에 Bash 변수를 삽입해 새로운 문자열을 동적으로 만들어 내야 할 때</li>
<li><code>\n</code>, <code>\t</code>, <code>\a</code>와 같이 이스케이프 코드를 삽입해야 할 때</li>
</ul>
<hr>
<h1 id="---정리"><code>[]</code> <code>()</code> <code>{}</code> 정리</h1>
<ul>
<li><p><code>[]</code>: 배열 인덱스, 테스트 조건을 정의</p>
<blockquote>
<p>(와일드 카드) <code>[ ]</code>: 문자 범위 지정하는 특수문자, <code>[]</code>괄호 안에 포함된 문자 중 하나를 나타냄</p>
</blockquote>
<ul>
<li><code>[[]]</code>: 기본적으로 단일 대괄호와 동일한 기능을 수행하지만 bash 내장</li>
</ul>
</li>
<li><p><code>()</code>: 함수 인수의 시작과 끝, 서브 쉘 작성, 배열 초기화</p>
<ul>
<li>스크립트의 다른 곳에서는 소괄호 안 서브 쉘에 들어있는 변수를 볼 수 없음</li>
<li>소괄호 안의 명령어들은 현재 쉘 환경과는 별도의 서브 쉘 환경에서 실행된다.</li>
<li>예를 들어, <code>(명령어1; 명령어2)</code>는 <code>명령어1</code>과 <code>명령어2</code>를 서브 쉘에서 실행</li>
</ul>
</li>
<li><p><code>{}</code>: 명령 블록의 시작과 끝, 각종 변수의 존재범위도 연관됨, 매개변수 확장, 반복되는 문자열 목록 작성, 변수를 명확하게 식별</p>
<ul>
<li>중괄호 안의 명령어들은 현재 쉘 환경에서 실행된다.</li>
<li>예를 들어, <code>{ 명령어1; 명령어2; }</code>는 <code>명령어1</code>과 <code>명령어2</code>를 같은 쉘 환경에서 실행</li>
</ul>
</li>
</ul>
<blockquote>
<p>📝 출처: <a href="https://coding-chobo.tistory.com/54">https://coding-chobo.tistory.com/54</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[AWS CodePipeline 알림을 위한 AWS Chatbot + Slack 연결]]></title>
            <link>https://velog.io/@root-devvoo/AWS-CodePipeline-%EC%95%8C%EB%A6%BC%EC%9D%84-%EC%9C%84%ED%95%9C-AWS-Chatbot-Slack-%EC%97%B0%EA%B2%B0</link>
            <guid>https://velog.io/@root-devvoo/AWS-CodePipeline-%EC%95%8C%EB%A6%BC%EC%9D%84-%EC%9C%84%ED%95%9C-AWS-Chatbot-Slack-%EC%97%B0%EA%B2%B0</guid>
            <pubDate>Sun, 26 May 2024 02:00:02 GMT</pubDate>
            <description><![CDATA[<h1 id="aws-chatbot-구성">AWS Chatbot 구성</h1>
<p>AWS 관리 콘솔로 로그인 후, AWS Chatbot 서비스 선택하고, 아래와 같이 구성된 클라이언트가 있으면 선택,
없으면 새 클라이언트를 구성하자.</p>
<img src=https://velog.velcdn.com/images/root-devvoo/post/f4154008-b224-425a-94d6-7f1cb0b03f4c/image.png width=70% height= 70%>

<p>(내 경우는 클라이언트가 이미 있기 때문에 있는거 클릭함)</p>
<br>

<p>[새 채널 구성] 클릭</p>
<img src=https://velog.velcdn.com/images/root-devvoo/post/d06943be-41ae-4c18-8a36-9506fc468173/image.png width=50% height= 50%>

<img src=https://velog.velcdn.com/images/root-devvoo/post/f73fb899-de67-4d2f-8397-c19d79a9eafb/image.png width=70% height= 70%>

<p>awsbot은 DM 지원을 안하기 때문에, 테스트용 슬랙 비공개 채널을 따로 파서 그 채널 ID를 넣어줬다. 채널 ID는 친절하게 안내문에 적혀있는대로 진행해서 넣으면 된다.</p>
<img src=https://velog.velcdn.com/images/root-devvoo/post/d8e3dec9-e019-47c3-89a1-e299f773c53d/image.png width=70% height= 70%>

<p>권한은 위와 같이 설정해주고</p>
<img src=https://velog.velcdn.com/images/root-devvoo/post/19446803-14a1-4f1e-86d3-2d8562490930/image.png width=50% height= 50%>

<p>이 부분은 비워놓고, 저장을 눌러준다.
<br></p>
<p>슬랙 비공개 방에 들어가서</p>
<img src=https://velog.velcdn.com/images/root-devvoo/post/cb1415b2-a864-4fdc-aa9e-7197b5de0586/image.png width=70% height= 70%>

<p>위와 같이 <code>/invite @aws</code> 를 입력해서 보내주면, bot이 초대가 된다.
(여기선 awsbot 앱이 이미 추가가 되어있는 상태여서 바로 진행했지만, 앱 추가하는거 전제되어야함)</p>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/03b02e41-8e9d-4230-aa1c-2f53a3ed0def/image.png" alt=""></p>
<p>추가가 잘 되었다면 위와 같은 메시지가 출력된다.</p>
<h1 id="aws-codepipeline-알림-설정">AWS CodePipeline 알림 설정</h1>
<p>CodePipeline 서비스에 들어가서, 파이프라인을 들어가주자.</p>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/56052c15-eb0c-4cac-a590-dedebffb6804/image.png" alt=""></p>
<p>해당 알림을 설정할 파이프라인을 클릭한다.
<br></p>
<p>알림 드롭박스를 클릭 후, [알림 규칙 생성] 을 클릭한다.</p>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/a10ef1e0-404f-4e7c-ad20-dfbdb69bbfff/image.png" alt=""></p>
<br>

<p>이름 설정과 알림을 트리거하는 이벤트를 설정해준다.</p>
<img src=https://velog.velcdn.com/images/root-devvoo/post/03f6fd1a-24bb-4573-8a01-2eb983e4a869/image.png width=70% height= 70%>

<br>

<p>그리고, AWS Chatbot에 아까 구성했던 클라이언트를 선택해주고, [submit]해준다.</p>
<img src=https://velog.velcdn.com/images/root-devvoo/post/064e07a4-4c5b-4d08-8ab8-39df3e851c53/image.png width=70% height= 70%>

<br>

<p>AWS Chatbot으로 돌아와서 구성한 클라이언트로 다시 들어가면</p>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/d138bbb4-885b-43c9-8b06-88b7e943844d/image.png" alt=""></p>
<p>위와 같이 SNS 주제로 등록된 것을 확인할 수 있고,</p>
<h1 id="테스트-및-확인">테스트 및 확인</h1>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/1cc489a5-e7e5-4a2c-ab7f-08dd35e45f8e/image.png" alt=""></p>
<p>[테스트 메시지 전송] 버튼을 클릭했을 때</p>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/e6157299-9eb7-4eed-b7b5-a13b05f68a9e/image.png" alt=""></p>
<p>Slack 채널에서 AWS bot으로부터 이와 같은 메시지가 수신된 것이 확인된다면 잘 연결된 것이다.</p>
<br>

<p>그리고, AWS CodePipeline의 알림 설정에 따라, 파이프라인이 시작하고 성공적으로 마쳤을 때 Slack Channel로 아래와 같이 알람이 오는 것을 확인할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/f26547b6-9a37-41c6-8aea-03d0c265b174/image.png" alt=""></p>
<hr>
<h1 id="참고">참고</h1>
<p><a href="https://minjii-ya.tistory.com/43">https://minjii-ya.tistory.com/43</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[AWS CloudWatch를 통한 프로세스 모니터링 및 재시작 적용]]></title>
            <link>https://velog.io/@root-devvoo/AWS-CloudWatch%EB%A5%BC-%ED%86%B5%ED%95%9C-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EB%AA%A8%EB%8B%88%ED%84%B0%EB%A7%81-%EB%B0%8F-%EC%9E%AC%EC%8B%9C%EC%9E%91-%EC%A0%81%EC%9A%A9</link>
            <guid>https://velog.io/@root-devvoo/AWS-CloudWatch%EB%A5%BC-%ED%86%B5%ED%95%9C-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EB%AA%A8%EB%8B%88%ED%84%B0%EB%A7%81-%EB%B0%8F-%EC%9E%AC%EC%8B%9C%EC%9E%91-%EC%A0%81%EC%9A%A9</guid>
            <pubDate>Wed, 22 May 2024 03:48:42 GMT</pubDate>
            <description><![CDATA[<h1 id="amazon-ec2-인스턴스에-통합-cloudwatch-agent와-ssm-agent-설치">Amazon EC2 인스턴스에 통합 CloudWatch Agent와 SSM Agent 설치</h1>
<h2 id="iam-역할">IAM 역할</h2>
<p>먼저 EC2 인스턴스에서 CloudWatch Agent를 실행하기 위해서는 EC2 인스턴스의 IAM 역할에 정책 CloudWatchAgentServerPolicy에 대한 권한이 필요하다. 추가로 Agent가 CloudWatch Logs에 로그를 전송하고 Agent가 이러한 로그 그룹에 대한 보존 정책을 설정할 수 있도록 하려면 IAM 역할에 logs:PutRetentionPolicy 권한을 부여해야한다.</p>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/39fa16e5-dda9-488f-862a-306c60735e3f/image.png" alt=""></p>
<p>우리는 EC2에 연결된 <code>x</code>라는 역할에 CloudWatchFullAccess 권한을 주었다.
(역할 이름은 Naming 하기 나름이라 <code>x</code>라는 임의의 이름을 명시함)</p>
<h2 id="cloudwatch-agent">CloudWatch Agent</h2>
<ol>
<li>CloudWatch Agent 다운로드 (EC2 인스턴스 내에서)</li>
</ol>
<pre><code>sudo apt-get install amazon-cloudwatch-agent</code></pre><h1 id="amazon-sns-주제-생성">Amazon SNS 주제 생성</h1>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/5d99e5a8-bd78-44b0-a7bd-ad69b0668a43/image.png" alt=""></p>
<p>위와 같은 네이밍으로 표준 형태로 생성해준다. (down, up)</p>
<h1 id="aws-lambda-함수-생성-및-코드-작성">AWS Lambda 함수 생성 및 코드 작성</h1>
<p>Lambda 함수 생성 시 함수에 대한 권한을 정의하는 IAM 역할이 필요하다. 기본적으로 Lambda는 Amazon CloudWatch Logs에 로그를 업로드할 수 있는 권한을 가진 실행 역할을 생성하며, 이 기본 역할은 나중에 트리거를 추가할 때 사용자 지정이 가능하다.</p>
<img src="https://velog.velcdn.com/images/root-devvoo/post/aabf410a-2ed7-4b2c-b9da-02762502958f/image.png" width="50%" height="50%">

<p>우리는 lambda-fullaccess로 역할을 지정해주었다.</p>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/cbe80278-ca19-49ea-ac75-25aea17a925f/image.png" alt=""></p>
<p>lambda-fullaccess 역할에는 위와 같이 권한 정책들이 세팅 되어있지만,</p>
<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;logs:CreateLogGroup&quot;,
            &quot;Resource&quot;: &quot;arn:aws:logs:ap-northeast-2:[Accound ID]:*&quot;
        },
        {
            &quot;Effect&quot;: &quot;Allow&quot;,
            &quot;Action&quot;: [
                &quot;logs:CreateLogStream&quot;,
                &quot;logs:PutLogEvents&quot;
            ],
            &quot;Resource&quot;: [
                &quot;arn:aws:logs:ap-northeast-2:[Account ID]:log-group:/aws/lambda/[lambda Name]:*&quot;
            ]
        }
    ]
}</code></pre>
<p>필요한 정책 권한은 위와 같다는 것을 참고하자.</p>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/a9ad4d4f-b7ab-4dc2-9693-1210c728c108/image.png" alt=""></p>
<p>위 이미지와 같이 x-monitoring이라는 이름으로 Python 3.9 기반의 Lambda 함수를 생성하였다.</p>
<p>그리고 생성한 함수에 코드를 아래와 같이 정의해주고, <code>Deploy</code> 했는데,</p>
<pre><code class="language-bash">import json
import boto3
import requests

def lambda_handler(event, context):
    # TODO implement

    message = event[&#39;Records&#39;][0][&#39;Sns&#39;][&#39;Message&#39;]
    message = json.loads(message)
    servicename = message[&#39;AlarmDescription&#39;]
    topic_arn = event[&#39;Records&#39;][0][&#39;Sns&#39;][&#39;TopicArn&#39;]

    for dimension in message[&#39;Trigger&#39;][&#39;Dimensions&#39;]:
        if dimension[&#39;name&#39;] == &#39;InstanceId&#39;:
            instanceid = dimension[&#39;value&#39;]

    print(&quot;instance id:&quot;, instanceid)
    print(&quot;service name:&quot;, servicename)

    if &quot;down&quot; in topic_arn:
        # Node Down시 슬랙 발송
        command = &quot;sudo systemctl restart [프로세스명].service&quot;
        ssm_client = boto3.client(&#39;ssm&#39;)
        response = ssm_client.send_command(
            InstanceIds=[instanceid],
            DocumentName=&quot;AWS-RunShellScript&quot;,
            Parameters={
                &#39;commands&#39;: [command]
            },
        )

        # 슬랙 메시지 전송
        payload = {
            &quot;channel&quot;: &quot;[Slack 채널명]&quot;,
            &quot;username&quot;: &quot;[채널에서 사용할 Slack bot 이름]&quot;,
            &quot;text&quot;: servicename + &quot; 노드가 중지 되었습니다. 노드를 기동하겠습니다.&quot;,
            &quot;icon_emoji&quot;: &quot;:robot_face:&quot;,
            &quot;attachments&quot;: [
                {
                    &quot;color&quot;: &quot;#FF0000&quot;,
                    &quot;fields&quot;: [
                        {
                            &quot;title&quot;: &quot;재기동 진행중&quot;,
                            &quot;value&quot;: &quot;대상: &quot; + servicename,
                        }
                    ]
                }
            ]
        }
    elif &quot;up&quot; in topic_arn:
        # Node Up시 슬랙 발송
        payload = {
            &quot;channel&quot;: &quot;[Slack 채널명]&quot;,
            &quot;username&quot;: &quot;[채널에서 사용할 Slack bot 이름]&quot;,
            &quot;text&quot;: servicename + &quot; 노드가 기동 되었습니다.&quot;,
            &quot;icon_emoji&quot;: &quot;:robot_face:&quot;,
            &quot;attachments&quot;: [
                {
                    &quot;color&quot;: &quot;#00FF00&quot;,
                    &quot;fields&quot;: [
                        {
                            &quot;title&quot;: &quot;재기동 완료&quot;,
                            &quot;value&quot;: &quot;대상: &quot; + servicename,
                        }
                    ]
                }
            ]
        }

    webhook_url = &quot;https://hooks.slack.com/services/[비공개]/[비공개]/[비공개]&quot;

    requests.post(
        webhook_url, data=json.dumps(payload),
        headers={&#39;Content-Type&#39;: &#39;application/json&#39;},
    )

    return {
        &#39;statusCode&#39;: 200
    }</code></pre>
<h2 id="참고-코드-작성-관련">참고: 코드 작성 관련</h2>
<p>처음에 아래와 같이 Lambda 함수 내 코드를 정의하고 Deploy해서 실행되게 한 후,</p>
<pre><code class="language-python">import json

def lambda_handler(event, context):
    # 전체 이벤트 데이터 출력
    print(json.dumps(event))

    return {
        &quot;statusCode&quot;: 200,
        &quot;body&quot;: json.dumps(&quot;SNS event data printed&quot;)
    }</code></pre>
<img src="https://velog.velcdn.com/images/root-devvoo/post/5ff594a7-6bf4-4a9a-b5dc-8dfe9419fa92/image.png" width="70%" height="70%">


<p>위와 같이 AWS CloudWatch 콘솔에서 쿼리를 실행하여</p>
<pre><code class="language-json">필드                               값
@ingestionTime                   1692339271137
@log                           [AWSAccountId]:/aws/lambda/x-monitoring
@logStream                     2023/08/18/[$LATEST]6dbc7bd76f844dd397d06b7625c79fa1
@message                       {&quot;Records&quot;: [{&quot;EventSource&quot;: &quot;aws:sns&quot;, &quot;EventVersion&quot;: &quot;1.0&quot;, &quot;EventSubscriptionArn&quot;: &quot;arn:aws:sns:ap-northeast-2:[AWSAccountId]:[SNS Topic name(down)]:[비공개]&quot;, &quot;Sns&quot;: {&quot;Type&quot;: &quot;Notification&quot;, &quot;MessageId&quot;: &quot;[비공개]&quot;, &quot;TopicArn&quot;: &quot;arn:aws:sns:ap-northeast-2:[AWSAccountId]:[SNS Topic name(down)]&quot;, &quot;Subject&quot;: &quot;ALARM: \&quot;[경보 이름]\&quot; in Asia Pacific (Seoul)&quot;, &quot;Message&quot;: &quot;{\&quot;AlarmName\&quot;:\&quot;[경보 이름]\&quot;,\&quot;AlarmDescription\&quot;:\&quot;**## [메시지 내용]\uac00 \uc911\uc9c0 \ub418\uc5c8\uc2b5\ub2c8\ub2e4.**\&quot;,\&quot;AWSAccountId\&quot;:\&quot;[비공개]\&quot;,\&quot;AlarmConfigurationUpdatedTimestamp\&quot;:\&quot;2023-08-18T06:04:23.696+0000\&quot;,\&quot;NewStateValue\&quot;:\&quot;ALARM\&quot;,\&quot;NewStateReason\&quot;:\&quot;Threshold Crossed: 1 out of the last 1 datapoints [0.0 (18/08/23 06:13:00)] was less than or equal to the threshold (0.0) (minimum 1 datapoint for OK -&gt; ALARM transition).\&quot;,\&quot;StateChangeTime\&quot;:\&quot;2023-08-18T06:14:29.779+0000\&quot;,\&quot;Region\&quot;:\&quot;Asia Pacific (Seoul)\&quot;,\&quot;AlarmArn\&quot;:\&quot;arn:aws:cloudwatch:ap-northeast-2:[AWSAccountId]:alarm:[경보 이름]\&quot;,\&quot;OldStateValue\&quot;:\&quot;OK\&quot;,\&quot;OKActions\&quot;:[\&quot;arn:aws:sns:ap-northeast-2:[AWSAccountId]:[SNS Topic name(up)]\&quot;],\&quot;AlarmActions\&quot;:[\&quot;arn:aws:sns:ap-northeast-2:[AWSAccountId]:[SNS Topic name(up)]\&quot;],\&quot;InsufficientDataActions\&quot;:[],\&quot;Trigger\&quot;:{\&quot;MetricName\&quot;:\&quot;procstat_lookup_pid_count\&quot;,\&quot;Namespace\&quot;:\&quot;CWAgent\&quot;,\&quot;StatisticType\&quot;:\&quot;Statistic\&quot;,\&quot;Statistic\&quot;:\&quot;SUM\&quot;,\&quot;Unit\&quot;:null,\&quot;Dimensions\&quot;:[{\&quot;value\&quot;:\&quot;[비공개]\&quot;,\&quot;name\&quot;:\&quot;InstanceId\&quot;},{\&quot;value\&quot;:\&quot;[비공개]\&quot;,\&quot;name\&quot;:\&quot;pattern\&quot;},{\&quot;value\&quot;:\&quot;native\&quot;,\&quot;name\&quot;:\&quot;pid_finder\&quot;}],\&quot;Period\&quot;:60,\&quot;EvaluationPeriods\&quot;:1,\&quot;DatapointsToAlarm\&quot;:1,\&quot;ComparisonOperator\&quot;:\&quot;LessThanOrEqualToThreshold\&quot;,\&quot;Threshold\&quot;:0.0,\&quot;TreatMissingData\&quot;:\&quot;missing\&quot;,\&quot;EvaluateLowSampleCountPercentile\&quot;:\&quot;\&quot;}}&quot;, &quot;Timestamp&quot;: &quot;2023-08-18T06:14:29.821Z&quot;, &quot;SignatureVersion&quot;: &quot;1&quot;, &quot;Signature&quot;: &quot;[비공개]&quot;, &quot;SigningCertUrl&quot;: &quot;https://sns.ap-northeast-2.amazonaws.com/SimpleNotificationService-[비공개].pem&quot;, &quot;UnsubscribeUrl&quot;: &quot;https://sns.ap-northeast-2.amazonaws.com/?Action=Unsubscribe&amp;SubscriptionArn=arn:aws:sns:ap-northeast-2:[AWSAccountId]:x-monitoring:[비공개]&quot;, &quot;MessageAttributes&quot;: {}}}]}
@timestamp                     1692339270275
Records.0.EventSource          aws:sns
Records.0.EventSubscriptionArn arn:aws:sns:ap-northeast-2:[AWSAccountId]:[SNS Topic name]:[비공개]
Records.0.EventVersion           1.0
Records.0.Sns.Message           {&quot;AlarmName&quot;:&quot;[경보 이름]&quot;,&quot;AlarmDescription&quot;:&quot;**## [메시지 내용]**&quot;,&quot;AWSAccountId&quot;:&quot;[비공개]&quot;,&quot;AlarmConfigurationUpdatedTimestamp&quot;:&quot;2023-08-18T06:04:23.696+0000&quot;,&quot;NewStateValue&quot;:&quot;ALARM&quot;,&quot;NewStateReason&quot;:&quot;Threshold Crossed: 1 out of the last 1 datapoints [0.0 (18/08/23 06:13:00)] was less than or equal to the threshold (0.0) (minimum 1 datapoint for OK -&gt; ALARM transition).&quot;,&quot;StateChangeTime&quot;:&quot;2023-08-18T06:14:29.779+0000&quot;,&quot;Region&quot;:&quot;Asia Pacific (Seoul)&quot;,&quot;AlarmArn&quot;:&quot;arn:aws:cloudwatch:ap-northeast-2:[AWSAccountId]:alarm:[경보 이름]&quot;,&quot;OldStateValue&quot;:&quot;OK&quot;,&quot;OKActions&quot;:[&quot;arn:aws:sns:ap-northeast-2:[AWSAccountId]:[SNS Topic name(up)]&quot;],&quot;AlarmActions&quot;:[&quot;arn:aws:sns:ap-northeast-2:[AWSAccountId]:[SNS Topic name(down)]&quot;],&quot;InsufficientDataActions&quot;:[],&quot;Trigger&quot;:{&quot;MetricName&quot;:&quot;procstat_lookup_pid_count&quot;,&quot;Namespace&quot;:&quot;CWAgent&quot;,&quot;StatisticType&quot;:&quot;Statistic&quot;,&quot;Statistic&quot;:&quot;SUM&quot;,&quot;Unit&quot;:null,&quot;Dimensions&quot;:[{&quot;value&quot;:&quot;[비공개]&quot;,&quot;name&quot;:&quot;InstanceId&quot;},{&quot;value&quot;:&quot;[비공개]&quot;,&quot;name&quot;:&quot;pattern&quot;},{&quot;value&quot;:&quot;native&quot;,&quot;name&quot;:&quot;pid_finder&quot;}],&quot;Period&quot;:60,&quot;EvaluationPeriods&quot;:1,&quot;DatapointsToAlarm&quot;:1,&quot;ComparisonOperator&quot;:&quot;LessThanOrEqualToThreshold&quot;,&quot;Threshold&quot;:0.0,&quot;TreatMissingData&quot;:&quot;missing&quot;,&quot;EvaluateLowSampleCountPercentile&quot;:&quot;&quot;}}
Records.0.Sns.MessageId           [비공개]
Records.0.Sns.Signature           [비공개]
Records.0.Sns.SignatureVersion 1
Records.0.Sns.SigningCertUrl   https://sns.ap-northeast-2.amazonaws.com/SimpleNotificationService-[비공개].pem
Records.0.Sns.Subject           ALARM: &quot;[경보 이름]&quot; in Asia Pacific (Seoul)
Records.0.Sns.Timestamp           2023-08-18T06:14:29.821Z
Records.0.Sns.TopicArn           arn:aws:sns:ap-northeast-2:[AWSAccountId]:[SNS Topic name(down)]
Records.0.Sns.Type               Notification
Records.0.Sns.UnsubscribeUrl   https://sns.ap-northeast-2.amazonaws.com/?Action=Unsubscribe&amp;SubscriptionArn=arn:aws:sns:ap-northeast-2:[비공개]:[SNS Topic name(down)]:[비공개]</code></pre>
<p>위와 같은 형태로 찍힌 로그 중 Records 데이터 값을 바탕으로 코드를 작성해주었던 것이다. 
(안맞는 내용이 있을 수도 있으니 형태가 이렇다는 것 정도만 참고)</p>
<hr>
<p>그리고, requests 라이브러리를 import 하기 위해</p>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/d793b2d8-78d8-44f2-a22c-4af7394b18b8/image.png" alt=""></p>
<p>lambda 계층도 위와 같이 지정해주었는데,</p>
<img src="https://velog.velcdn.com/images/root-devvoo/post/4ec65a92-291e-4bd4-ab1b-113c9c3e7cf8/image.png" width="50%" height="50%">

<h2 id="참고-계층-생성">참고: 계층 생성</h2>
<img src="https://velog.velcdn.com/images/root-devvoo/post/26fd7817-2e0e-4d41-acb2-0f85a5385424/image.png" width="50%" height="50%">

<p>pip로 로컬에서 request 라이브러리를 다운받고, zip으로 묶은 후 업로드 버튼으로 업로드 해주고, 생성한다.</p>
<pre><code class="language-bash">pip3 install requests==2.28.2 -t python</code></pre>
<blockquote>
<p>똑같이 Python 3.9 기반으로 다운 받아야 함!</p>
</blockquote>
<h1 id="cloudwatch-알람-생성">CloudWatch 알람 생성</h1>
<p>EC2 기반 노드 내에서 <code>/opt/aws/amazon-cloudwatch-agent/bin/config.json</code> 파일을 아래와 같이 작성해준다.</p>
<pre><code class="language-json">{
    &quot;agent&quot;: {
        &quot;metrics_collection_interval&quot;: 60,
        &quot;run_as_user&quot;: &quot;root&quot;
    },
    &quot;metrics&quot;: {
        &quot;append_dimensions&quot;: {
            &quot;InstanceId&quot;: &quot;${aws:InstanceId}&quot;
        },
        &quot;metrics_collected&quot;: {
            &quot;procstat&quot;: [
                {
                    &quot;pattern&quot;: &quot;org.hyperledger.besu.Besu&quot;, # 모니터링할 프로세스 정의
                    &quot;measurement&quot;: [
                        &quot;pid_count&quot;
                    ]
                }
            ]
        }
    }
}</code></pre>
<p>그리고, AWS CloudWatch 콘솔에서 1분 동안 특정 인스턴스의 프로세스의 실행 수의 합계가 0보다 작거나 같을 때, 자동으로 알람이 발생하도록 지표 및 조건을 지정하여 경보를 생성한다.</p>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/a072bd7f-2bb2-48a1-9db8-8ce87d3f645b/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/33e521e8-8aa0-4cbd-bcde-021cac8d667c/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/d025f9bf-4f47-4e8d-9442-a36a25437c7c/image.png" alt=""></p>
<img src="https://velog.velcdn.com/images/root-devvoo/post/99750d27-02e2-409c-9370-0c2e67b75e0a/image.png" width="50%" height="50%">

<img src="https://velog.velcdn.com/images/root-devvoo/post/39e332f9-915e-43b4-a2ad-b2a036cd0fbf/image.png" width="50%" height="50%">

<p>CloudWatch 알람이 발생한 경우 및 프로세스가 정상 상태로 변경된 경우 위에서 생성한 SNS 주제로 해당 알림을 전송하도록 연결했다.</p>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/c109cd05-56aa-41f6-9626-d4a769b0fa38/image.png" alt=""></p>
<p>아래와 같이 생성이 완료되었다.</p>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/221da228-9c59-4908-b326-6875a49cc1cd/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/250473c9-df57-4e08-ab08-0fdec38d939d/image.png" alt=""></p>
<h1 id="aws-lambda-트리거-추가">AWS Lambda 트리거 추가</h1>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/f773b4b9-0172-43ac-9271-edf7deb2d980/image.png" alt=""></p>
<p>위와 같이 먼저 생성했던 SNS 주제들로 트리거를 추가해주었다.</p>
<h1 id="테스트-결과">테스트 결과</h1>
<p><img src="https://velog.velcdn.com/images/root-devvoo/post/49ba8e48-8309-4ae1-8fa1-3b6f93c93eee/image.png" alt=""></p>
<p>위 이미지에 표시한 것과 같이 특정 인스턴스의 besu 프로세스가 모두 다운되어 1분 동안 프로세스의 실행 수의 합계가 0인 경우 ‘경보 상태’가 되어 CloudWatch 알람이 발생하게 된다.</p>
<img src="https://velog.velcdn.com/images/root-devvoo/post/14f66608-d63e-47e2-ae5c-d304c6892719/image.png" width="50%" height="50%">

<p>또 Lambda 코드에 정의한 Slack 채널로 알람에 대한 메시지가 전송되며, 프로세스를 재기동하고, 상태가 정상으로 변경된 경우에도 아래와 같이 메시지가 전송된다.</p>
<img src="https://velog.velcdn.com/images/root-devvoo/post/85b4ba8d-595c-4b33-993c-176a3a60d17c/image.png" width="50%" height="50%">]]></description>
        </item>
        <item>
            <title><![CDATA[oh-my-zsh 업데이트 에러 해결]]></title>
            <link>https://velog.io/@root-devvoo/oh-my-zsh-%EC%97%85%EB%8D%B0%EC%9D%B4%ED%8A%B8-%EC%97%90%EB%9F%AC-%ED%95%B4%EA%B2%B0</link>
            <guid>https://velog.io/@root-devvoo/oh-my-zsh-%EC%97%85%EB%8D%B0%EC%9D%B4%ED%8A%B8-%EC%97%90%EB%9F%AC-%ED%95%B4%EA%B2%B0</guid>
            <pubDate>Tue, 21 May 2024 08:39:47 GMT</pubDate>
            <description><![CDATA[<p>나 같은 경우에는 <code>_docker</code>파일에서 충돌이 났는데, 내가 건드리거나 수정한 적은 딱히 없는 파일이었다.</p>
<p>git의 <code>stash</code>를 이용해서 이 문제를 해결할 수 있었다.</p>
<h1 id="stash">stash</h1>
<p><code>stash</code>는 마무리하지 않은 작업을 잠시 스택에 저장할 수 있도록 하는 명령어다.
이를 통해 아직 완료하지 않은 일을 커밋하지 않고 나중에 다시 꺼내와 마무리할 수 있다.
<img src=https://velog.velcdn.com/images/root-devvoo/post/7a0bebe2-c655-4ddf-8c97-22e2a1f6b081/image.png width="50%" height="50%"></p>
<h2 id="자주-쓰는-stash-명령어">자주 쓰는 stash 명령어</h2>
<pre><code class="language-bash"># stash 생성
$ git stash

# stash 목록 확인
$ git stash list

# stash 작업 가져오기
$ git stash apply [stash 이름]

# stash 제거
$ git stash drop [stash 이름]

# stash 작업 가져오기 &amp; 제거
$ git stash pop

# stash 되돌리기
$ git stash show -p [stash 이름] | git apply -R</code></pre>
<h1 id="해결">해결</h1>
<p><code>stash</code>를 이용하여 <code>oh-my-zsh</code>업데이트 문제를 해결한 명령어는 다음과 같다.</p>
<pre><code class="language-bash"># stash 생성
$ git stash

# stash 이름 확인 (stash@{0})
$ git stash list

# oh-my-zsh 업데이트
$ omz update

# stash 적용
$ git stash apply stash@{0}

# stash 제거
$ git stash drop stash@{0}</code></pre>
]]></description>
        </item>
    </channel>
</rss>