<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>js_moon.log</title>
        <link>https://velog.io/</link>
        <description>Devops, AWS infra</description>
        <lastBuildDate>Sun, 25 Jun 2023 10:42:41 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>js_moon.log</title>
            <url>https://velog.velcdn.com/images/js_moon/profile/9e61d5bb-5ae6-4687-83f7-943f741c56b0/image.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. js_moon.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/js_moon" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Keda]]></title>
            <link>https://velog.io/@js_moon/Keda</link>
            <guid>https://velog.io/@js_moon/Keda</guid>
            <pubDate>Sun, 25 Jun 2023 10:42:41 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>Keda 공식 홈페이지</p>
<p><a href="https://keda.sh/">KEDA</a></p>
</blockquote>
<blockquote>
<p>Keda 구성 시 참고 주소</p>
<p><a href="https://keda.sh/docs/2.8/concepts/scaling-deployments/">KEDA | Scaling Deployments, StatefulSets &amp; Custom Resources</a></p>
</blockquote>
<blockquote>
<p><span style="color:indianred">과연 kubernetes에서 제공해주는 기본 hpa 말고 개발환경에 맞는 pod 오토스케일링은 안되는 걸까? 라는 호기심으로 시작하여 알아보니 prometheus와 연동하여 prometheus의 지표를 사용하여 오토스케일링 하는 방법이 있어 적용하는 과정입니다 !</span></p>
</blockquote>
<h3 id="keda란">Keda란?</h3>
<ul>
<li>Kubernetes 이벤트 기반 기반 자동 확장 솔루션입니다.</li>
<li><strong>K</strong>ubernetes-based <strong>E</strong>vent <strong>D</strong>riven <strong>A</strong>utoscaler</li>
<li>모든 K8S에 설치할 수 있으며 HPA(Horizontal Pod Autoscaler)와 같은 표준 쿠버네티스 구성 요소와 함께 작동 할 수 있습니다.</li>
<li>Kubernetes 클러스터에 KEDA를 설치하면 두 개의 컨테이너가 실행 됩니다.<ul>
<li>Keda-operator<ul>
<li>배포, 상태 저장 집합 또는 롤아웃을 0에서 이벤트 없이 0으로 확장하는 것 ( 사용 X )</li>
</ul>
</li>
<li>keda-operator-metrics-apiserver</li>
</ul>
</li>
<li>KEDA는 큐 길이 또는 스트림 지연과 같은 풍부한 이벤트 데이터를 HPA에 노출하여 스케일 아웃을 유도하는 Kubernetes 메트릭 서버 역할을 합니다.</li>
<li>메트릭 제공은 두번째 컨테이너인 keda-operator-metrics-apiserver의 기본 역할입니다.</li>
<li>CNCF 제단과 MS의 공동 개발</li>
</ul>
<h3 id="keda-특징">Keda 특징</h3>
<ul>
<li>간편한 자동 확장<ul>
<li>Kubernetes의 모든 워크로드에 풍부한 확장성 제공 무리</li>
</ul>
</li>
<li>이벤트 기반<ul>
<li>이벤트 기반 애플리케이션을 지능적으로 확장</li>
</ul>
</li>
<li>내장 스케일러<ul>
<li>다양한 클라우드 플랫폼, 데이터베이스, 메시징 시스템, 원격 측정 시스템, CICD 등을 위한 50개 이상의 내장 스케일러 카탈로그</li>
</ul>
</li>
<li>여러 워크로드 유형<ul>
<li>/scale 하위 리소스가 있는 배포, 작업 및 사용자 지정 리소스와 같은 다양한 워크로드 유형 지원</li>
</ul>
</li>
<li>환경 영향 감소<ul>
<li>워크로드 스케줄링 및 0으로 확장을 최적화하여 지속 가능한 플랫폼 구축</li>
</ul>
</li>
<li>확장 가능<ul>
<li>직접 가져오거나 커뮤니티에서 관리하는 스케일러 사용</li>
</ul>
</li>
<li>공급업체 불가지론<ul>
<li>다양한 클라우드 제공업체 및 제품 전반에 걸친 트리거 지원</li>
</ul>
</li>
<li>Azure,aws 기능 지원</li>
</ul>
<p>KEDA 기반으로 확장 할 수 있는 이벤트 소스 중 Prometheus랑 연동하여 스케일</p>
<p>ex) Facade API, node.js 등 CPU와 Memory 지표를 가지고 스케일이 어려운 상황이므로 Prometheus랑 연동하여 스케일</p>
<h3 id="사용목적">사용목적</h3>
<ul>
<li>AWS 환경에서 낮은 버전의 Kubernetesd에서의 오토스케일링 문제 해결을 위한 Keda 서비스 도입</li>
<li><span style="color:indianred"></span></li>
<li>오토스크일링을 더욱더 세분화해서 하기위해서</li>
<li>프로매태우스랑 Keda와 연동하여 생성</li>
<li>node.js 개발 특성상 CPU,Memory 등 리소스들을 효율적으로 사용하기 때문에 기존 kubernetes에서 지원하는 horizon 지표인 cpu, memory 등으로 스케일링 불가</li>
<li>prometheus 지표를 활용하여 효율적인 오토스케일링을 위한 작업</li>
</ul>
<h3 id="설치">설치</h3>
<ul>
<li>설치는 helm을 이용하여 keda 설치</li>
</ul>
<blockquote>
<p>helm 설치 가이드</p>
<p><a href="https://helm.sh/ko/docs/intro/install/">헬름 설치하기</a></p>
</blockquote>
<h3 id="helm으로-설치">helm으로 설치</h3>
<pre><code class="language-jsx">~~helm 설치 (mac-os)

$ brew install helm~~

스크립트로 helm 설치

$ curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
$ chmod 700 get_helm.sh
$ ./get_helm.sh

$ helm repo add kedacore https://kedacore.github.io/charts
$ helm repo update

~~# keda를 설치할 namespace 생성
$ kubectl create namespace keda 
$ helm install keda kedacore/keda --namespace keda~~

keda 삭제 시 주의사항

scaleobject를 제외하고 패키지만 삭제 시 불필요한 scaleobject들이 남아있어 리소스를 먼저 삭제 후
keda 삭제

for i in $(kubectl get scaledobjects -oname);
do kubectl patch $i -p &#39;{&quot;metadata&quot;:{&quot;finalizers&quot;:null}}&#39; --type=merge
done

for i in $(kubectl get scaledjobs -oname);
do kubectl patch $i -p &#39;{&quot;metadata&quot;:{&quot;finalizers&quot;:null}}&#39; --type=merge
done</code></pre>
<p>Keda-helm-repo 받기</p>
<pre><code class="language-jsx">$ helm pull keda kedacore/keda
$ tar xvf ~
$ cd keda</code></pre>
<p>Prometheus의 매트릭을 이용하는 scale 예시 yaml</p>
<pre><code class="language-jsx">apiVersion: v1
kind: Secret
metadata:
  name: keda-prom-secret
  namespace: default
data:
  username: &quot;dXNlcm5hbWUK&quot; # Must be base64
  password: &quot;cGFzc3dvcmQK&quot; # Must be base64
---
apiVersion: keda.sh/v1alpha1
kind: TriggerAuthentication
metadata:
  name: keda-prom-creds
  namespace: default
spec:
  secretTargetRef:
    - parameter: username 
      name: keda-prom-secret
      key: username
    - parameter: password
      name: keda-prom-secret
      key: password
---
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: facade-api
  namespace: ns
spec:
  pollingInterval: 60
  minReplicaCount: 1
  maxReplicaCount: 10
  scaleTargetRef:
    name: facade-api
  triggers:
    - type: prometheus
      metadata:
        serverAddress:
        metricName: http_requests_total
        threshold: &#39;60&#39;
        query: max(nodejs_active_handles_total{app_kubernetes_io_name=~&quot;facade-api&quot;})
#              sum(rate(http_requests_total{deployment=&quot;my-deployment&quot;}[2m]))
#        authModes: &quot;basic&quot;
#      authenticationRef:
#        name: keda-prom-creds</code></pre>
<h3 id="매개변수-목록">매개변수 목록</h3>
<ul>
<li>serverAddress<ul>
<li>프로메테우스의 주소</li>
</ul>
</li>
<li>metricName<ul>
<li><a href="http://external.metrics.k8s.io">external.metrics.k8s.io</a> API에서 메트릭을 식별하기 위한 이름. 둘 이상의 트리거를 사용하는 경우 모두 metricName이 고유해야함</li>
</ul>
</li>
<li>query<ul>
<li>실행할 쿼리</li>
</ul>
</li>
<li>threshold<ul>
<li>확장을 시작할 값 (소수점 설정도 가능)</li>
</ul>
</li>
<li>activationThreshold<ul>
<li>스케일러를 활성화하기 위한 목표 값</li>
</ul>
</li>
<li>pollingInterval<ul>
<li>각 트리거를 확인하는 간격. 기본으로 default 30초마다 모든 sclaedobject에서 각 트리거 소스를 확인</li>
<li>현재 구조상 짧은 시간에 급격하게 오르는 스파이크 현상에 대비하여 pollingInterval을 설정하여 불필요한 오토스케일링 작업을 방지</li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/js_moon/post/b0acf92f-21b7-49ac-a371-e71ed7d54dfd/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/js_moon/post/a3ff3c14-53be-4afd-a1c2-7b9369141777/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/js_moon/post/cd84a28d-bc27-415f-94c3-cc0cc3825572/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/js_moon/post/c69d52b0-9782-4dc0-b77f-99e712bf58ac/image.png" alt=""></p>
<h3 id="실제-사용할-코드">실제 사용할 코드</h3>
<pre><code class="language-jsx">apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: api
  namespace: [오토스케일을 설정하고 싶은 리소스가 존재하는 ns에 설정]
spec:
  pollingInterval: 60 # 초 단위
  minReplicaCount: 1
  maxReplicaCount: 10
  scaleTargetRef:
    name: facade-api
  triggers:
    - type: prometheus
      metadata:
        serverAddress: http://prometheus.[prometheus가 설치된 ns].svc.cluster.local:9090
        metricName: nodejs_active_handles_total
        threshold: &#39;60&#39;
        query: max(nodejs_active_handles_total{app_kubernetes_io_name=~&quot;facade-api&quot;})
# sum(rate(http_requests_total{deployment=&quot;my-deployment&quot;}[2m]))
#        authModes: &quot;basic&quot;
#      authenticationRef:
#        name: keda-prom-creds
---
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: web
  namespace: [오토스케일을 설정하고 싶은 리소스가 존재하는 ns에 설정]
spec:
  pollingInterval: 60
  minReplicaCount: 2
  maxReplicaCount: 10
  scaleTargetRef:
    name: web
  triggers:
    - type: prometheus
      metadata:
        serverAddress: http://prometheus.[prometheus가 설치된 ns].svc.cluster.local:9090
        metricName: nodejs_active_handles_total_web
        threshold: &#39;40&#39;
        query: max(nodejs_active_handles_total{app_kubernetes_io_name=~&quot;web&quot;})</code></pre>
<h3 id="측정항목의-쿼리-값">측정항목의 쿼리 값</h3>
<pre><code class="language-jsx">kubectl get --raw &quot;/apis/external.metrics.k8s.io/v1beta1/namespaces/YOUR_NAMESPACE/YOUR_METRIC_NAME&quot;
kubectl get --raw &quot;/apis/external.metrics.k8s.io/v1beta1/namespaces/[namespace]/nodejs_active_handles_total_web&quot;

여러 ScaledObject가 동일한 메트릭 이름을 가질 때 메트릭을 얻는 방법
kubectl get scaledobject SCALEDOBJECT_NAME -n NAMESPACE -o jsonpath={.metadata.labels}
kubectl get scaledobject web -n NAMESPACE -o jsonpath={.metadata.labels}
kubectl get scaledobject facade-api -n NAMESPACE -o jsonpath={.metadata.labels}

kubectl get --raw &quot;/apis/external.metrics.k8s.io/v1beta1/namespaces/sample-ns/s1-rabbitmq-queueName2?labelSelector=scaledobject.keda.sh%2Fname%3D{ScaledObjectName}&quot;

Facade
kubectl get --raw &quot;/apis/external.metrics.k8s.io/v1beta1/namespaces/[namespace]/s0-prometheus-nodejs_active_handles_total?labelSelector=scaledobject.keda.sh%2Fname%3Dfacade-api&quot;

Web 
kubectl get --raw &quot;/apis/external.metrics.k8s.io/v1beta1/namespaces/[namespace]/s0-prometheus-nodejs_active_handles_total_web?labelSelector=scaledobject.keda.sh%2Fname%3Dweb&quot;</code></pre>
<h3 id="1차-test">1차 TEST</h3>
<p>TEST - 방법</p>
<p>부하TEST를 하기에는 추가적인 비용이 발생하므로 threshold의 값을 임의로 낮추어서 test 진행</p>
<ul>
<li>threshold: 40 → threshold: 3</li>
</ul>
<p>TEST part.1 - 순서</p>
<ol>
<li><p>threshold: 40 → threshold: 3</p>
<p> <img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/60b1c361-b265-4dc2-b2bd-42cfe85c5818/Untitled.png" alt="Untitled"></p>
<p> <img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/f195783d-fba1-45d7-937d-84f7e904b4fa/Untitled.png" alt="Untitled"></p>
</li>
<li><p>interval이 걸려 있으므로 1분 대기</p>
</li>
<li><p>5/3 hpa가 동작 (1분 소요)</p>
<p> <img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/f195783d-fba1-45d7-937d-84f7e904b4fa/Untitled.png" alt="Untitled"></p>
</li>
<li><p>deployment 상태도 1</p>
<p> <img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/6b9d10c8-253f-42f3-b38f-f0a186c157bc/Untitled.png" alt="Untitled"></p>
</li>
<li><p>5/3 이므로 hpa 스케일링 시작</p>
</li>
<li><p>deploy에서 pod 개수가 순차적으로 증가하는 모습</p>
<p> <img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/6cef0e12-679d-47cd-b3b3-11ce581f091d/Untitled.png" alt="Untitled"></p>
<p> <img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/01df554b-1083-4ebb-867c-2d21fc9e9161/Untitled.png" alt="Untitled"></p>
</li>
<li><p>web의 pod 수가 [1 → 2] , [2 → 3] 증가 후 hpa에서 자원들이 안정화 된 모습 - 1667m/3</p>
<p> <img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/a97581d4-69e7-4b4e-bf29-b238d2353fcd/Untitled.png" alt="Untitled"></p>
</li>
<li><p>threshold: 3 → threshold: 40으로 늘려 준 뒤</p>
<p> <img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/ff403a10-616f-42a4-8b1e-851bf5e665ac/Untitled.png" alt="Untitled"></p>
<p> 정상적으로 pod들도 내려간 모습</p>
</li>
</ol>
<h3 id="2차-test">2차 TEST</h3>
<pre><code class="language-jsx">apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: web 
  namespace: [오토스케일을 설정하고 싶은 리소스가 존재하는 ns에 설정]
spec:
  pollingInterval: 60
  minReplicaCount: 1 
  maxReplicaCount: 10
  scaleTargetRef:
    name: web 
  triggers:
    - type: prometheus 
      metadata:
        serverAddress: http://prometheus.[prometheus가 설치된 ns].svc.cluster.local:9090 
        metricName: nodejs_active_handles_total_web 
        threshold: &#39;20&#39; # 수치를 낮춰서 진행
        query: max(nodejs_active_handles_total{app_kubernetes_io_name=~&quot;web&quot;}) 
#sum(rate(http_requests_total{deployment=&quot;my-deployment&quot;}[2m]))
#        authModes: &quot;basic&quot;
#      authenticationRef:
#        name: keda-prom-creds</code></pre>
<p>TEST part.2 - 순서</p>
<ol>
<li><p>threshold: 40 → threshold: 20</p>
<ul>
<li><p>MINPODS → 1</p>
</li>
<li><p>MAXPODS → 10</p>
<p><img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/60b1c361-b265-4dc2-b2bd-42cfe85c5818/Untitled.png" alt="Untitled"></p>
<p><img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/700a402e-4006-4a4c-bd7e-197f3ac30938/Untitled.png" alt="Untitled"></p>
</li>
</ul>
</li>
<li><p>interval이 걸려 있으므로 1분 대기</p>
</li>
<li><p>ngrinder를 활용하여 부하진행</p>
<p> <img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/4a1f9ca2-ba7b-467a-ad07-194ec98ef91d/Untitled.png" alt="Untitled"></p>
<ul>
<li>nGrinder configuration<ul>
<li>Agent: 8</li>
<li>Vuser per agent: 20</li>
<li>Script: frontend/main_stress.groovy</li>
<li>Target Host: [target-url]</li>
<li>Duration: 00:02:00 (HH:MM:SS)</li>
</ul>
</li>
</ul>
</li>
<li><p>5/20 hpa가 동작 (1분 소요)</p>
<p> <img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/700a402e-4006-4a4c-bd7e-197f3ac30938/Untitled.png" alt="Untitled"></p>
</li>
<li><p>deployment 상태도 1</p>
<p> <img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/6b9d10c8-253f-42f3-b38f-f0a186c157bc/Untitled.png" alt="Untitled"></p>
</li>
<li><p>209/20 이므로 hpa 스케일링 시작</p>
<p> <img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/c20e7f9b-3be1-4903-ba16-0e54a4927e99/Untitled.png" alt="Untitled"></p>
<p> <img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/42421f41-24c2-4786-9f6b-41ef6630c9b1/Untitled.png" alt="kubectl get hpa -n [namespace] -w 시 web의 TARGETS = 209
 prometheus = 209
 동일한 쿼리 사용 확인"></p>
<p> kubectl get hpa -n [namespace] -w 시 web의 TARGETS = 209
 prometheus = 209
 동일한 쿼리 사용 확인</p>
<p> <img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/5a776755-446d-48ed-a269-45bf59d2fb1a/Untitled.png" alt="kubectl get hpa -n [namespace] -w 시 TARGETS = 97
 prometheus = 97
 동일한 쿼리 사용 확인"></p>
<p> kubectl get hpa -n [namespace] -w 시 TARGETS = 97
 prometheus = 97
 동일한 쿼리 사용 확인</p>
<ul>
<li>정상적으로 부하를 걸기 전 TARGETS 5/20</li>
<li>부하 진행 중 facade-api가 97/60으로 오토스케일링 중 replicas 1 → 2 로 증가</li>
<li>web 209/20 이므로 오토스케일링 증가 replicas 1 → 4 로 증가</li>
</ul>
</li>
<li><p>deploy에서 pod 개수가 순차적으로 증가하는 모습</p>
<p> <img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/ee008d99-589d-4a9f-8809-56063173ff06/Untitled.png" alt="Untitled"></p>
</li>
<li><p>web의 pod 수가 [1 → 10] 증가 후 hpa에서 자원들이 안정화 된 모습 - 500m/20</p>
<ul>
<li><p>동일하게 facade-api도 감소한 모습</p>
<p><img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/4fad9608-72de-4edf-a6c7-afb2c27d7c1a/Untitled.png" alt="Untitled"></p>
</li>
</ul>
</li>
<li><p>test 마무리 부하 test 종료시 5/20 안정적이므로 rplicas가 내려간 모습
interval 1분으로 인하여 1분이 지난 뒤 감소한 모습</p>
<p> <img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/4fad9608-72de-4edf-a6c7-afb2c27d7c1a/Untitled.png" alt="Untitled"></p>
<p> 정상적으로 pod들도 내려간 모습</p>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[Packer 사용]]></title>
            <link>https://velog.io/@js_moon/Packer-%EC%82%AC%EC%9A%A9</link>
            <guid>https://velog.io/@js_moon/Packer-%EC%82%AC%EC%9A%A9</guid>
            <pubDate>Fri, 23 Jun 2023 15:26:45 GMT</pubDate>
            <description><![CDATA[<h3 id="작업-목적">작업 목적</h3>
<ol>
<li>OS 보안취약점을 강화하기 위해 스크립트를 돌려야하지만 EKS에 설정된 Launch Template가 변경되지 않으면 스크립트를 적용해도 오토스케일링이 되면 보안설정들이 날라감</li>
<li>골든이미지를 생성하여 Dev, Production 환경등에서 빠른 배포가 가능하다.</li>
<li>스크립트를 사용하요 버전관리 가능</li>
</ol>
<h3 id="packer-란">Packer 란</h3>
<ul>
<li>Packer는 여러 플랫폼에 대해 동일한 시스템 이미지를 작성하기위한 오픈 소스 도구입니다.</li>
<li>AWS의 AMI, Azure Image, Google Cloud Image 등을 스크립트 파일을 이용해서 생성할 수 있습니다.</li>
<li>패커는 Hashicorp에서 만든 인프라 관리 도구 중 하나이다.</li>
<li>인프라 자동화 도구 중 하나로 다양한 플랫폼에서 사용가능한 이미지를 동적으로 생성할 수 있게 도와준다.</li>
</ul>
<h3 id="packer---builder">Packer - Builder</h3>
<ul>
<li>빌더로 이미지를 생성할 플랫폼을 지정할 수 있다.</li>
<li>AWS, VirtualBox 및 VM웨어와 같은 가상 머신의 이미지, 도커 등 컨테이너 이미지도 생성이 가능하다.</li>
<li>현재 packer에서 지원하는 목록은<ul>
<li>아마존 EC2 AMI</li>
<li>디지털오션</li>
<li>도커</li>
<li>구글 컴퓨트 엔진</li>
<li>오픈스택</li>
<li>패러럴스</li>
<li>QEMU</li>
<li>버추얼박스</li>
<li>VM웨어</li>
<li>Custom</li>
<li>Null</li>
</ul>
</li>
</ul>
<h3 id="packer---provisioner">Packer - Provisioner</h3>
<ul>
<li>이미지를 생성할 때 사용할 빌드 도구를 의미한다.</li>
<li>셸스크립트와 같은 원시적인 방법인 앤서블, 셰프와 같은 도구들도 지원한다.</li>
<li>현재는 셸스크립트를 통해 보안취약점을 해결한 골든이미지를 만드는 작업입니다.</li>
</ul>
<h2 id="packer를-사용하여-aws-ami-만드는-작업순서">Packer를 사용하여 AWS AMI 만드는 작업순서</h2>
<h3 id="1-packer-설치-방법">1. Packer 설치 방법</h3>
<ul>
<li><p>mac 같은 경우 brew로 손쉽게 설치할 수 있습니다.</p>
<pre><code class="language-docker">  $ brew tap hashicorp/tap
  $ brew install hashicorp/tap/packer</code></pre>
</li>
</ul>
<h3 id="2-aws-인증-설정하기">2. AWS 인증 설정하기</h3>
<ul>
<li><p>Packer를 사용하기 위해서는 AWS 인증 정보가 필요하다. 따라서 AWS CLI를 사용하여 인증 정보를 설정한다.</p>
<pre><code class="language-docker">  $ aws configure</code></pre>
</li>
</ul>
<h3 id="3-packer-템플릿-작성하기">3. Packer 템플릿 작성하기</h3>
<ul>
<li><p>Packer는 JSON 또는 HCL을 사용하여 템플릿을 작성한다. 따라서 JSON을 사용하여 템플릿을 작성하는 방법을 소개.</p>
</li>
<li><p>아래는 JSON 방식으로 작성된 template입니다.</p>
<pre><code class="language-docker">  {
    &quot;variables&quot;: {
      &quot;aws_region&quot;: &quot;us-west-2&quot;,
      &quot;ami_name&quot;: &quot;my-ami&quot;,
      &quot;instance_type&quot;: &quot;t2.micro&quot;,
      &quot;ssh_username&quot;: &quot;ubuntu&quot;
    },
    &quot;builders&quot;: [{
      &quot;type&quot;: &quot;amazon-ebs&quot;,
      &quot;region&quot;: &quot;{{user `aws_region`}}&quot;,
      &quot;source_ami_filter&quot;: {
        &quot;filters&quot;: {
          &quot;virtualization-type&quot;: &quot;hvm&quot;,
          &quot;name&quot;: &quot;ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*&quot;,
          &quot;root-device-type&quot;: &quot;ebs&quot;
        },
        &quot;owners&quot;: [&quot;099720109477&quot;],
        &quot;most_recent&quot;: true
      },
      &quot;instance_type&quot;: &quot;{{user `instance_type`}}&quot;,
      &quot;ssh_username&quot;: &quot;{{user `ssh_username`}}&quot;,
      &quot;ami_name&quot;: &quot;{{user `ami_name`}}&quot;,
      &quot;tags&quot;: {
        &quot;Name&quot;: &quot;{{user `ami_name`}}&quot;
      }
    }],
    &quot;provisioners&quot;: [
      {
        &quot;type&quot;: &quot;shell&quot;,
        &quot;inline&quot;: [
          &quot;echo &#39;Hello, World!&#39; &gt; /tmp/hello-world.txt&quot;
        ]
      }
    ]
  }</code></pre>
</li>
<li><p>variables : 변수를 정의</p>
</li>
<li><p>builders : AMI를 만들기 위한 설정을 정의</p>
</li>
<li><p>provisioners : AMI를 생성한 후 실행할 스크립트를 정의</p>
</li>
</ul>
<h3 id="4-packer로-ami-만들기">4. Packer로 AMI 만들기</h3>
<ul>
<li><p>다음 명령어를 사용하여 Packer로 AMI를 만든다.</p>
<pre><code class="language-docker">  $ packer build template.json</code></pre>
</li>
<li><p>template.json 파일을 템플릿으로 사용하여 AMNI를 생성한다.</p>
</li>
</ul>
<h3 id="packer를-사용하여-골든이미지-생성">Packer를 사용하여 골든이미지 생성</h3>
<ol>
<li><p>Template.json 생성</p>
<pre><code class="language-docker"> {
     &quot;variables&quot;: {
       &quot;vpc_id&quot;: &quot;[VPC 이름]&quot;,
       &quot;subnet_id&quot;: &quot;[subnet 지정]&quot;,
       &quot;aws_region&quot;: &quot;ap-northeast-2&quot;,
       &quot;ami_name&quot;: &quot;EKS-Golden-image-1-{{timestamp}}&quot;,
       &quot;instance_type&quot;: &quot;c5.xlarge&quot;,
       &quot;ssh_username&quot;: &quot;ec2-user&quot;,
       &quot;iam_instance_profile&quot;: &quot;[ec2에 할당할 iam 맵핑],
       &quot;source_ami&quot;: &quot;ami-0443a21cb1a8f238e&quot;,
       &quot;aws_session_token&quot;: &quot;{{env `AWS_SESSION_TOKEN`}}&quot;,
       &quot;aws_access_key&quot;: &quot;{{env `AWS_ACCESS_KEY_ID`}}&quot;,
       &quot;aws_secret_key&quot;: &quot;{{env `AWS_SECRET_ACCESS_KEY`}}&quot;
     },
     &quot;builders&quot;: [{
       &quot;type&quot;: &quot;amazon-ebs&quot;,
       &quot;region&quot;: &quot;{{user `aws_region`}}&quot;,
       &quot;vpc_id&quot;: &quot;{{user `vpc_id`}}&quot;,
       &quot;subnet_id&quot;: &quot;{{user `subnet_id`}}&quot;,
       &quot;source_ami&quot;: &quot;{{user `source_ami`}}&quot;,
       &quot;instance_type&quot;: &quot;{{user `instance_type`}}&quot;,
       &quot;ssh_username&quot;: &quot;{{user `ssh_username`}}&quot;,
       &quot;ami_name&quot;: &quot;{{user `ami_name`}}&quot;,
       &quot;iam_instance_profile&quot;: &quot;{{user `iam_instance_profile`}}&quot;,
       &quot;ssh_pty&quot;: true,
       &quot;tags&quot;: {
         &quot;Name&quot;: &quot;{{user `ami_name`}}&quot;
       },
       &quot;communicator&quot;: &quot;ssh&quot;,
       &quot;ssh_interface&quot;: &quot;session_manager&quot;
     }],
     &quot;provisioners&quot;: [
         {
           &quot;type&quot;: &quot;shell&quot;,
           &quot;inline&quot;: [
             &quot;sudo yum update -y&quot;,
             &quot;sudo yum install -y aws-cli&quot;,
             &quot;sudo yum install -y amazon-cloudwatch-agent&quot;,
             &quot;sudo sed -i &#39;s/^PASS_MAX_DAYS\\s\\+[0-9]\\+/PASS_MAX_DAYS   90/g&#39; /etc/login.defs&quot;,
             &quot;sudo sed -i &#39;s/^PASS_MIN_LEN\\s\\+[0-9]\\+/PASS_MIN_LEN   8/g&#39; /etc/login.defs&quot;,
             &quot;sudo sh -c &#39;echo \&quot;password    requisite     pam_cracklib.so try_first_pass retry=3 minlen=8\&quot; &gt;&gt; /etc/pam.d/system-auth&#39;&quot;,
             &quot;sudo sh -c &#39;echo \&quot;password    requisite     pam_cracklib.so try_first_pass retry=3 minlen=8\&quot; &gt;&gt; /etc/pam.d/password-auth&#39;&quot;,
             &quot;sudo sed -i &#39;s/#\\s\\+minlen\\s\\+=\\s\\+[0-9]\\+/minlen = 8/g&#39; /etc/security/pwquality.conf&quot;,
             &quot;sudo chmod 4750 /bin/su&quot;,
             &quot;sudo chown root:wheel /bin/su&quot;,
             &quot;sudo sh -c &#39;echo \&quot;\&quot; &gt; /etc/motd&#39;&quot;,
             &quot;sudo sed -i &#39;s/^#Banner\\s\\+none/Banner none/g&#39; /etc/ssh/sshd_config&quot;,
             &quot;sudo service sshd restart&quot;
           ]
         }
       ]
   }</code></pre>
</li>
<li><p>Packer 명령어</p>
</li>
</ol>
<ul>
<li><p>다음은 Packer에서 자주 사용하는 명령어 목록입니다.</p>
<ul>
<li><p><strong><code>validate</code></strong> : 템플릿 구문 분석을 위한 구문 분석 및 구성 파일 유효성 검사를 실행합니다.</p>
</li>
<li><p><strong><code>build</code></strong> : 이미지 빌드를 시작합니다.</p>
</li>
<li><p><strong><code>inspect</code></strong> : Packer 템플릿 파일의 내용을 검사합니다.</p>
</li>
<li><p><strong><code>fix</code></strong> : Packer 템플릿 파일의 내용을 수정합니다.</p>
</li>
<li><p><strong><code>version</code></strong> : Packer의 버전을 출력합니다.</p>
<p>Packer 명령어는 다음과 같이 사용합니다.</p>
<pre><code class="language-docker">packer validate &lt;filename&gt;   # 파일의 유효성을 검사합니다.
packer build &lt;filename&gt;      # 파일을 빌드합니다.
packer inspect &lt;filename&gt;    # 파일 내용을 검사합니다.
packer fix &lt;filename&gt;        # 파일 내용을 수정합니다.
packer version               # Packer의 버전을 출력합니다.</code></pre>
<pre><code class="language-docker">$ export AWS_ACCESS_KEY_ID=&quot;anaccesskey&quot;
$ export AWS_SECRET_ACCESS_KEY=&quot;asecretkey&quot;
$ export AWS_DEFAULT_REGION=&quot;ap-northeast-2&quot;
$ packer build template.pkr.hcl</code></pre>
<p><img src="https://velog.velcdn.com/images/js_moon/post/fcfcbcca-3537-467e-9f6c-82179e498390/image.png" alt=""></p>
</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[EFK]]></title>
            <link>https://velog.io/@js_moon/EFK</link>
            <guid>https://velog.io/@js_moon/EFK</guid>
            <pubDate>Fri, 23 Jun 2023 14:30:46 GMT</pubDate>
            <description><![CDATA[<h1 id="eks에-efk-모니터링-설치-및-alert-설정">EKS에 efk 모니터링 설치 및 alert 설정</h1>
<h2 id="설치하기">설치하기</h2>
<p>elasticsearch -&gt; 7.10.2
kibana -&gt; 7.10.2
동일한 버전을 사용하여 설치</p>
<h3 id="사전준비">사전준비</h3>
<ul>
<li><p>relaese 정보
<a href="https://github.com/elastic/helm-charts/releases?q=7.10.2&amp;expanded=true">https://github.com/elastic/helm-charts/releases?q=7.10.2&amp;expanded=true</a></p>
</li>
<li><p>7.10.2 version 설치 파일
<a href="https://github.com/elastic/helm-charts/archive/refs/tags/v7.10.2.tar.gz">https://github.com/elastic/helm-charts/archive/refs/tags/v7.10.2.tar.gz</a></p>
</li>
</ul>
<ul>
<li>기존 7.15 버전에서는 alerting 기능을 사용하려면 라이센스 등록이 필요한데 무료로 alerting 기능을 사용할 수 있는 opendistro 라는 부가 플러그인을 설치하여 alerting 기능을 활성화하는 시나리오입니다. 하지만 이 때 opendistro라는 부가 플러그인을 사용하려면 최소 7.10.2 버전까지만 호환이 되기때문에 버전을 다운그레이드해서 사용했습니다.
<a href="https://opendistro.github.io/for-elasticsearch-docs/">https://opendistro.github.io/for-elasticsearch-docs/</a></li>
</ul>
<h3 id="설치-순서">설치 순서</h3>
<ol>
<li>helm 설치</li>
<li>Kibana, Elastic에 대한 init continer 생성 (Plugin 설치)하고 본 Cotnaier에 해당 디렉토리 /usr/share/elasticsearch/plugins 공유</li>
<li>Slack 연동 &amp; 대시보드 구성</li>
</ol>
<p>여기서 initcontainer를 설정안하려면 Dockerfile에서 Dockerhub를 이용하여 이미지를 넣는 방법도 있는데 본 실습에서는 initcontainer에 추가하는 방법입니다.</p>
<blockquote>
<p>우아한형제들 기술블로그를 보고 참고하였습니다.
<a href="https://techblog.woowahan.com/2659/">ELK 셋팅부터 알람까지 | 우아한형제들 기술블로그</a>
<del>나도 가고싶다....</del></p>
</blockquote>
<h4 id="elasticsearch-설치">elasticsearch 설치</h4>
<p>7.10.2 버전의 elasticsearch와 kibana를 설치하고 압축까지 풀어줍니다.</p>
<p>이 과정에서 중요한 부분은 initcontainer를 통해 플러그인들을 볼륨마운트를 시켜줘야 정상적으로 alerting 기능이 정상 수행합니다. 따라서 helm values.yaml 값을 변경해줘야합니다.</p>
<pre><code class="language-yaml">$ cd helm-charts-7.10.2
$ cd elasticsearch

 25 esConfig:
 26   elasticsearch.yml: |
 27     xpack.security.enabled: false</code></pre>
<blockquote>
<p>여기서 xpack을 사용해서 alerting 기능을 사용하려면 라이센스를 구매해야합니다. 
   그래서 false 값을 임의로 넣어줍니다.</p>
</blockquote>
<pre><code class="language-yaml">139 extraVolumes:
140   - name: elastic-plugin
141     emptyDir: {} </code></pre>
<blockquote>
<p>volume을 생성하고</p>
</blockquote>
<pre><code class="language-yaml">142 
143 extraVolumeMounts:
144  - name: elastic-plugin
145    mountPath: /usr/share/elasticsearch/plugins</code></pre>
<blockquote>
<p> volumeMount 경로를 지정해줍니다.</p>
</blockquote>
<pre><code>146 
153   - name: plugin-install
154     image: docker.elastic.co/elasticsearch/elasticsearch:7.10.2
155     command: [&#39;sh&#39;, &#39;-c&#39;, &#39;bin/elasticsearch-plugin install --batch https://d3g5vo6xdbdb9a.cloudfront.net/downloads/elasticsearch-plugins/opendistro-a    lerting/opendistro-alerting-1.13.1.0.zip&#39;]
156     volumeMounts:
157     - name: elastic-plugin
158       mountPath: &quot;/usr/share/elasticsearch/plugins&quot;</code></pre><blockquote>
<p>또한 pod 내에 있는 경로를 지정하여 본 컨테이너와의 연동을 위해 지정해주고
command 라인을 이용하여 opendistro plugin을 성공적으로 다운로드 했을 때 본 컨테이너가
   실행될 수 있도록 설정하였습니다.
혹시 command라인의 뜻을 궁금해하시는 분들이 있는데 opendistro 사이트에 가면 elasticsearch
설치 방법이 나와있습니다.</p>
</blockquote>
<pre><code>

```yaml
$ bin/elasticsearch-plugin install https://d3g5vo6xdbdb9a.cloudfront.net/downloads/elasticsearch-plugins/opendistro-alerting/opendistro-alerting-1.13.1.0.zip
이 명령어를 참조하여 initcontainer command에 넣어준 모습입니다.</code></pre><p>또한 elasticsearch 의 플러그인 공식 Document에서도 활용하여 넣어준 모습입니다.
<img src="https://velog.velcdn.com/images/js_moon/post/020e2340-5922-442d-8bee-d299c8fcecb8/image.png" alt="">
<span style="color:indianred">여기서 중요한 부분은 initcontainer에도 7.10.2의 동일한 이미지가 들어가야 합니다!!</span></p>
<p>따라서 elasticsearch의 설치준비는 끝났습니다.</p>
<pre><code class="language-yaml">$ helm upgrade --install elasticsearch . \
-n logging \
--set volumeClaimTemplate.resources.requests.storage=20Gi \
--set volumeClaimTemplate.storageClassName=default \
--set antiAffinityTopologyKey=elasticsearch \
--set antiAffinity=soft</code></pre>
<p>storage 용량은 20Gi 스토리지클래스 이름은 default로 설정을 하였습니다.</p>
<h4 id="fluentd-설치">fluentd 설치</h4>
<p>Fluentd는 0.3.2의 버전을 사용했습니다. fluentd의 공식 repo에서 가져왔습니다.</p>
<p>또한 시간기반의 로그를 뽑아와야하기때문에 config를 수정해줍니다.</p>
<pre><code class="language-yaml">$ helm upgrade --install fluentd . -n efk

&lt;source&gt;
106       @id fluentd-containers.log
107       @type tail
108       path /var/log/containers/*.log
109       pos_file /var/log/containers.log.pos
110       tag raw.kubernetes.*
111       read_from_head true
112       &lt;parse&gt;
113         @type multi_format
114         &lt;pattern&gt;
115           format json
116           time_key time
117           time_format %Y-%m-%dT%H:%M:%S.%NZ
118           keep_time_key true
119         &lt;/pattern&gt;
120         &lt;pattern&gt;
121           format /^(?&lt;time&gt;.+) (?&lt;stream&gt;stdout|stderr) [^ ]* (?&lt;log&gt;.*)$/
122           time_format %Y-%m-%dT%H:%M:%S.%N%:z
123           keep_time_key true
124         &lt;/pattern&gt;
125       &lt;/parse&gt;
126       emit_unmatched_lines true
127     &lt;/source&gt;

time 부분에 true라고 설정을 해줘야합니다.</code></pre>
<h4 id="kibana-설치">kibana 설치</h4>
<p>Kibana 또한 elasticsearch 7.10.2의 helm-chart에 있습니다. 따라서 설치 방법은 동일합니다.</p>
<p>kibana helm 공식 repo입니다.</p>
<p><a href="https://github.com/elastic/helm-charts/blob/main/kibana/values.yaml#L45">helm-charts/values.yaml at main · elastic/helm-charts</a></p>
<p>HTTPS 통신을 위해 secret을 생성해야합니다.(crt,key 값을 이용하여)</p>
<p>여기서 crt와 key 값은 구하셔서 넣어야 합니다.</p>
<pre><code class="language-yaml">$ kubectl create -n logging secret tls efk-tls-ingress --key private.key --cert certificate.crt</code></pre>
<pre><code class="language-yaml">$ cd helm-charts-7.10.2
$ cd kibana

16 envFrom:
 17  - secretRef:
 18      name: [생성한 secrets 이름]
        -&gt; ingress를 하기위한 secret 등록

89 extraVolumes:
 90  - name: kibana-plugin
 91    emptyDir: {}
     볼륨마운트
 93 extraVolumeMounts:
 94  - name: kibana-plugin
 95    mountPath: /usr/share/kibana/plugins

 97 extraContainers: &quot;&quot;
 98 # - name: dummy-init
 99 #   image: busybox
100 #   command: [&#39;echo&#39;, &#39;hey&#39;]
101 
102 extraInitContainers:
103  - name: plugin-install
104    image: docker.elastic.co/kibana/kibana:7.10.2
105    command: [&#39;sh&#39;, &#39;-c&#39;, &#39;bin/kibana-plugin install https://d3g5vo6xdbdb9a.cloudfront.net/downloads/kibana-plugins/opendistro-alerting/opendistroAlertingKibana-1.13.0.0.zip&#39;]
106    volumeMounts:
107    - name: kibana-plugin
108      mountPath: &quot;/usr/share/kibana/plugins&quot;

ingress:
  enabled: true
  annotations:
     kubernetes.io/ingress.class: nginx
    # kubernetes.io/tls-acme: &quot;true&quot;
  path: /
  hosts:
    - [DNS 주소]
  tls:
    - secretName: [생성한 secrets 이름]
      hosts:
        - [DNS 주소]</code></pre>
<p> elasticsearch에서 설명하듯 비슷한 설정 파일을 가지고 있고 initcontainer를 통해서 플러그인 설치를 진행합니다. 이 때도 volume을 마운트 시켜 플러그인 설치 경로를 지정해 줍니다.</p>
<p> 단, helm-Chart를 보시면 extra항목이 차트에 없기 때문에 추가로 넣어줘야합니다.</p>
<p>template → deployment.yaml 수정</p>
<p><a href="https://github.com/elastic/helm-charts/blob/main/kibana/templates/deployment.yaml">helm-charts/deployment.yaml at main · elastic/helm-charts</a></p>
<pre><code class="language-yaml">53       {{- if .Values.extraVolumes }}
54 {{ toYaml .Values.extraVolumes | indent 8 }}
55       {{- end }}

158         {{- if .Values.extraVolumeMounts }}
159 {{ toYaml .Values.extraVolumeMounts | indent 10 }}
160         {{- end }}</code></pre>
<p> 공식 helm-chart를 보고서 값을 추가해준 모습입니다. 값을 넣지 않으면 플러그인 설치 시 오류가 납니다.</p>
<p> 또한 ingress를 통한 https 통신을 하기위해 secrets 정보를 넣어준 모습이고 ingress 설정한 모습입니다.</p>
<p>  ingress를 생성하였기때문에 ingress controller도 설치를 해야합니다.</p>
<pre><code class="language-yaml">$ helm upgrade --install ingress-nginx ingress-nginx \
--repo https://kubernetes.github.io/ingress-nginx \
--namespace ingress-nginx \
--set controller.replicaCount=2

$ kubectl get ingress

helm upgrade --install kibana . -n logging \
--set service.type=ClusterIP \
--set service.port=5601</code></pre>
<p>command</p>
<pre><code class="language-yaml">$ bin/kibana-plugin install https://d3g5vo6xdbdb9a.cloudfront.net/downloads/kibana-plugins/opendistro-alerting/opendistroAlertingKibana-1.13.0.0.zip

위와 같은 command를 초기화컨테이너에 플러그인 설치를 넣어줍니다</code></pre>
<p><img src="https://velog.velcdn.com/images/js_moon/post/1fc93902-cec7-485f-91f7-47ed7c9fb896/image.png" alt=""></p>
<p><a href="https://opendistro.github.io/for-elasticsearch-docs/docs/kibana/plugins/">Standalone Kibana Plugin Install</a></p>
<p>이제 기본적인 설정은 끝났습니다. ingress에 등록된 HOST를 타고 들어가서 Alerting 기능을 설정하는 모습입니다.</p>
<p>설치 완료.</p>
<hr>
<h2 id="alert-설정">Alert 설정</h2>
<p><img src="https://velog.velcdn.com/images/js_moon/post/55dfabd7-681b-405d-ab96-45bba75f0428/image.png" alt="">
<img src="https://velog.velcdn.com/images/js_moon/post/adf87aa6-e328-43c8-be3f-50187b38eac1/image.png" alt="">
<img src="https://velog.velcdn.com/images/js_moon/post/1803830b-998e-4f3f-829e-44eed655725b/image.png" alt="">
<img src="https://velog.velcdn.com/images/js_moon/post/3f9fa038-5036-451e-95c2-74e1d430e064/image.png" alt=""></p>
<blockquote>
<p>slack으로 보내는 웹훅 주소 추가</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/js_moon/post/c93d21dd-73ee-4083-ba88-58564b59cb0b/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Dokcer 시간대 설정]]></title>
            <link>https://velog.io/@js_moon/Dokcer-%EC%8B%9C%EA%B0%84%EB%8C%80-%EC%84%A4%EC%A0%95</link>
            <guid>https://velog.io/@js_moon/Dokcer-%EC%8B%9C%EA%B0%84%EB%8C%80-%EC%84%A4%EC%A0%95</guid>
            <pubDate>Wed, 21 Jun 2023 14:41:53 GMT</pubDate>
            <description><![CDATA[<hr>
<p>Docker 이미지 사용시 컨테이너의 타임존 트러블 슈팅</p>
<pre><code class="language-jsx">FROM [repository-name]:[tag-num]
ENV TZ=Asia/Seoul
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime &amp;&amp; echo $TZ &gt; /etc/timezone</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Docker 설치]]></title>
            <link>https://velog.io/@js_moon/Docker-%EC%84%A4%EC%B9%98</link>
            <guid>https://velog.io/@js_moon/Docker-%EC%84%A4%EC%B9%98</guid>
            <pubDate>Wed, 21 Jun 2023 14:38:59 GMT</pubDate>
            <description><![CDATA[<hr>
<h3 id="docker-설치">Docker 설치</h3>
<p><a href="https://docs.docker.com/engine/install/ubuntu">Install Docker Engine on Ubuntu</a></p>
<p>docker-install.sh</p>
<pre><code class="language-java">#!/usr/bin/env bash
## INFO: https://docs.docker.com/engine/install/ubuntu/

set -euf -o pipefail

DOCKER_USER=ubuntu

# Install dependencies
sudo apt-get update &amp;&amp; sudo apt-get install -y \
  apt-transport-https \
  ca-certificates \
  curl \
  gnupg \
  lsb-release

# Add Docker’s official GPG key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --yes --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

# Set up the stable repository
echo \
  &quot;deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable&quot; | sudo tee /etc/apt/sources.list.d/docker.list &gt; /dev/null

# Install Docker CE
sudo apt-get update &amp;&amp; sudo apt-get install -y docker-ce docker-ce-cli containerd.io

# Use Docker without root
sudo usermod -aG docker $DOCKER_USER

chmod u+x docker-install.sh</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Helm-Chart 작성]]></title>
            <link>https://velog.io/@js_moon/Helm-Chart-%EC%9E%91%EC%84%B1</link>
            <guid>https://velog.io/@js_moon/Helm-Chart-%EC%9E%91%EC%84%B1</guid>
            <pubDate>Wed, 21 Jun 2023 14:32:58 GMT</pubDate>
            <description><![CDATA[<h1 id="helm-chart-생성">helm-chart 생성</h1>
<hr>
<h3 id="helm의-장점">Helm의 장점</h3>
<ol>
<li><p>쿠버네티스의 다양한 리소스로 구성된 패키지를 관리하는 쿠버네티스 패키지 매니저이다. ( yum, apt와 같음)</p>
</li>
<li><p>helm 차트를 사용하면 복잡한 쿠버네티스 애플리케이션을 쉽고 간단하게 정의할 수 있고 업그레이드가 가능하다.</p>
</li>
<li><p>기존 파일과 내용을 유지한 채 업데이트 가능</p>
</li>
<li><p>원격 repository 등을 통해 애플리케이션을 쉽게 공유할 수 있고 형상관리가 가능하다.</p>
</li>
<li><p>Rollbacks기능을 지원 하므로 간단하게 이전의 버전으로 롤백이 가능하다.</p>
</li>
<li><p>Helm chart 생성 가이드</p>
</li>
</ol>
<pre><code class="language-jsx">$ curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
$ chmod 700 get_helm.sh
$ ./get_helm.sh</code></pre>
<ol>
<li>helm-chart 생성</li>
</ol>
<pre><code class="language-jsx">$ helm create [name]</code></pre>
<p>helm 뼈대가 완성되었으므로 작성을 시작하면 된다!</p>
<p>helm-chart 작성 시 imagepullsecrets에서 syntax 오류가 발생하여 기록 중</p>
<blockquote>
<p>imagepullsecrets - official docs</p>
<p><a href="https://helm.sh/ko/docs/howto/charts_tips_and_tricks/#%EC%9D%B4%EB%AF%B8%EC%A7%80-%ED%92%80-%EC%8B%9C%ED%81%AC%EB%A6%BF-%EC%83%9D%EC%84%B1%ED%95%98%EA%B8%B0">차트 개발 팁과 비법</a></p>
</blockquote>
<pre><code class="language-jsx">imageCredentials:
  registry: quay.io
  username: someone
  password: sillyness

---
helper template
{{- define &quot;imagePullSecret&quot; }}
{{- with .Values.imageCredentials }}
{{- printf &quot;{\&quot;auths\&quot;:{\&quot;%s\&quot;:{\&quot;username\&quot;:\&quot;%s\&quot;,\&quot;password\&quot;:\&quot;%s\&quot;,\&quot;email\&quot;:\&quot;%s\&quot;,\&quot;auth\&quot;:\&quot;%s\&quot;}}}&quot; .registry .username .password .email (printf &quot;%s:%s&quot; .username .password | b64enc) | b64enc }}
{{- end }}
{{- end }}

---

apiVersion: v1
kind: Secret
metadata:
  name: myregistrykey
type: kubernetes.io/dockerconfigjson
data:
  .dockerconfigjson: {{ template &quot;imagePullSecret&quot; . }}</code></pre>
<p>이 방법 말고 다른 방법을 사용하여 해결 했습니다.</p>
<p>helm-chart</p>
<p>template/deployment.yaml</p>
<pre><code class="language-jsx">spec:
    {{- with .Values.imagePullSecrets }}
      imagePullSecrets:
        {{- toYaml . | nindent 8 }}
    {{- end }}</code></pre>
<p>values.yaml</p>
<pre><code class="language-jsx">imagePullSecrets:
  - name: ecr-secrets</code></pre>
<p>간단한 방법으로 imagepullsecrets 오류를 해결했습니다. !</p>
<p>추후에 helm syntax에 대해서 자세하게 정리</p>
<hr>
<h2 id="helm-chart-작성">Helm-chart 작성</h2>
<ul>
<li><p>기본 helm-chart 생성 시</p>
<p>  → Chart.yaml</p>
<p>  → template</p>
<p>  → deployment.yaml</p>
<p>  → hpa.yaml</p>
<p>  → service.yaml </p>
<p>  → 등 다양한 resource.yaml 파일 생성</p>
<p>  → values.yaml</p>
</li>
<li><p>template</p>
<ul>
<li>helm-chart key값들을 정의하는 역할</li>
</ul>
</li>
<li><p>values.yaml</p>
<ul>
<li>기존 template에 있는 key값들의 values들을 설정하는 역할</li>
</ul>
</li>
</ul>
<p>비교하기 쉽게 values.yaml과 template에 있는 yaml들을 비교하면서 설명</p>
<p>values.yaml</p>
<pre><code class="language-jsx">#replicaCount: 1

image:
  repository: [private-repository] 
  pullPolicy: IfNotPresent
  tag: [&quot;tag-num&quot;]

imagePullSecrets: 
  - name : [private-repository-secret]

containers:
  resources:
    limits:
      cpu: 100m
      memory: 200Mi
    requests:
      cpu: 100m
      memory: 200Mi

service:
  type: LoadBalancer
  ip: &quot;&quot; 
  port: 8080

autoscaling:
  enabled: true
  minReplicas: 1
  maxReplicas: 3
  targetCPUUtilizationPercentage: 50
  targetMemoryUtilizationPercentage: 50

nodeSelector: []

tolerations: []

affinity: {}</code></pre>
<p>template → deployment.yaml</p>
<pre><code class="language-jsx">apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}
  labels:
spec:
  selector:
    matchLabels:
      app: {{ .Release.Name }}
  template:
    metadata:
      labels:
        app: {{ .Release.Name }}
    spec:
      containers:
        - name: {{ .Release.Name }}
          image: &quot;{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}&quot;
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          ports:
            - name: {{ .Release.Name }}
              containerPort: 8080
          resources:
            limits:
              memory: {{ .Values.containers.resources.limits.memory }}
              cpu: {{ .Values.containers.resources.limits.cpu }}
            requests:
              memory: {{ .Values.containers.resources.requests.memory }}
              cpu: {{ .Values.containers.resources.requests.cpu }}</code></pre>
<p>예를 들어서 설명을 하면</p>
<pre><code class="language-jsx">resources:
  limits:
    memory: {{ .Values.containers.resources.limits.memory }}
    cpu: {{ .Values.containers.resources.limits.cpu }}
  requests:
    memory: {{ .Values.containers.resources.requests.memory }}
    cpu: {{ .Values.containers.resources.requests.cpu }}
</code></pre>
<p>memory 부분을 보면  “ {{ .Values.containers.resources.limits.memory }}  “</p>
<ul>
<li>노란색 배경의 뜻 : values.yaml에있는</li>
<li>회색 배경의 뜻 : values.yaml에 containers 하위 리소스</li>
<li>파란색 배경의 뜻 : values.yaml에 containers 하위에 있는 resources</li>
<li>빨간색 배경의 뜻 : values.yaml에 containers 하위에 있는 resources의 하위 값</li>
</ul>
<p>따라서 쉽게 생각하면 ‘ . ‘을 기준으로 values.yaml에 하위리소스 라고 보면 됩니다.</p>
<ul>
<li>또한 {{ .Release.Name }} 의 뜻은 배포할 때 이름을 value 값으로 가져와서 추가적으로 넣어 준다는 뜻 입니다.</li>
</ul>
<p>들여쓰기에 항상 주의해 주세요.</p>
<h3 id="helm-chart-if문-설정">helm-chart if문 설정</h3>
<pre><code class="language-jsx">{{- if .Values.autoscaling.enabled }} #만약 values.yaml에서 autoscaling 기능이 enable되어있으면 true, 아니면 false
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: {{ .Release.Name }}
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: {{ .Release.Name }}
  minReplicas: {{ .Values.autoscaling.minReplicas }}
  maxReplicas: {{ .Values.autoscaling.maxReplicas }}
  metrics:
    {{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
    {{- end }}
    {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
    {{- end }}
{{- end }} # if 문 eof</code></pre>
<ul>
<li>if문을 작성시 {{- end }} 를 사용하여 마무리를 지어 줘야함.</li>
<li>{{- if .Values.autoscaling.enabled }} → if문 사용시 values.yaml에서 autoscaling key의 values값이 enabled 시 if문 실행 단, {{- end }} 문까지 ( if 와 end는 helm-chart에서 한쌍으로 이루어짐)</li>
</ul>
<p>helm-chart with, toYaml, nindent 설정</p>
<pre><code class="language-jsx">{{- with .Values.nodeSelector }}
      nodeSelector:
        {{- toYaml . | nindent 8 }}
      {{- end }}
      {{- with .Values.affinity }}
      affinity:
        {{- toYaml . | nindent 8 }}
      {{- end }}
      {{- with .Values.tolerations }}
      tolerations:
        {{- toYaml . | nindent 8 }}
      {{- end }}</code></pre>
<ul>
<li>nindent - 의미하는 바는 들여쓰기를 의미 yaml형식이므로 들여쓰기가 중요한데 helm-chart에서는 nindent로 들여쓰기를 사용함 8은 8칸을 띄어쓰기 하겠다는 의미</li>
<li>toYaml - ‘ toYaml . ’ 은 ‘ . ‘ 현재 yaml을 참조하겠다는 뜻 ‘ . ‘ 대신 다른 yaml을 생성하여 넣을 수 있음</li>
<li>with도 end와 같이 한쌍</li>
</ul>
<p>이 외에도 많은 문법이 있지만 </p>
<ul>
<li>{{ .Values.autoscaling.minReplicas }}</li>
<li>{{ if.~ }} 와 {{- end }} 를 사용하여 간편하고 이해하기 쉽게 생성가능<ul>
<li>개인적으로 위에 2개의 문법을 많이 사용함.</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Gitlab과 Jenkins 연동]]></title>
            <link>https://velog.io/@js_moon/GitlabJenkins-%EC%97%B0%EB%8F%99</link>
            <guid>https://velog.io/@js_moon/GitlabJenkins-%EC%97%B0%EB%8F%99</guid>
            <pubDate>Wed, 21 Jun 2023 14:24:40 GMT</pubDate>
            <description><![CDATA[<h1 id="gitlab--jenkins-연동">Gitlab + Jenkins 연동</h1>
<pre><code class="language-java">Gitlab 서버에 들어가서 Key 생성
$ sudo ssh-keygen
$ cd
$ cd .ssh
$ chmod 700 *</code></pre>
<blockquote>
<p>생성된 키를 Gitlab sshkey 등록</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/js_moon/post/b14adea8-f92f-475b-a600-8ce2ce70b25c/image.png" alt="">
<img src="https://velog.velcdn.com/images/js_moon/post/dcca34b6-1665-42e0-acb1-dc46e7de930e/image.png" alt=""></p>
<h3 id="1-gitlab과-jenkins-프로젝트-별-연동방법">1. Gitlab과 Jenkins 프로젝트 별 연동방법</h3>
<p><img src="https://velog.velcdn.com/images/js_moon/post/fed7738d-8bd8-43e0-9cd3-b25f17c95551/image.png" alt="">
<img src="https://velog.velcdn.com/images/js_moon/post/30f1a8e8-6eaa-431a-b7ef-84b0a05fc5dc/image.png" alt="">
<img src="https://velog.velcdn.com/images/js_moon/post/ea101a15-d088-4fff-95e2-67484a5aaff7/image.png" alt="">
<img src="https://velog.velcdn.com/images/js_moon/post/4c502068-37ef-44f4-8d3b-df300891a27b/image.png" alt="">
<img src="https://velog.velcdn.com/images/js_moon/post/20555908-1210-4924-bce3-f6bab69b9c30/image.png" alt="">
<img src="https://velog.velcdn.com/images/js_moon/post/f019c415-8e49-4506-8b54-1b241e56cef2/image.png" alt="">
Repository URL은 Gitlab
<img src="https://velog.velcdn.com/images/js_moon/post/b40a7bae-7063-4821-a2db-9250e04ef84e/image.png" alt="">
<img src="https://velog.velcdn.com/images/js_moon/post/a4667759-d690-49c4-84cd-e7832f2cbf52/image.png" alt="">
<img src="https://velog.velcdn.com/images/js_moon/post/525a75f4-6e47-4878-994a-ea771f44a0bf/image.png" alt=""></p>
<h3 id="2-웹훅-설정">2. 웹훅 설정</h3>
<p>Secret token을 발급하고 복사한 뒤 Gitlab Webhook 설정
<img src="https://velog.velcdn.com/images/js_moon/post/2df85ac9-1432-4370-a6ff-2077a6c07e9e/image.png" alt="">
<img src="https://velog.velcdn.com/images/js_moon/post/48ad9f04-c339-4dda-95f1-6cfa809d2d00/image.png" alt="">
<img src="https://velog.velcdn.com/images/js_moon/post/2d1cf094-dca1-459e-a688-3b1b3bf7f36d/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[GitLab, Jenkins 설치]]></title>
            <link>https://velog.io/@js_moon/GitLab-Jenkins-%EC%84%A4%EC%B9%98</link>
            <guid>https://velog.io/@js_moon/GitLab-Jenkins-%EC%84%A4%EC%B9%98</guid>
            <pubDate>Wed, 21 Jun 2023 13:20:09 GMT</pubDate>
            <description><![CDATA[<h2 id="jenkins-설치">Jenkins 설치</h2>
<pre><code class="language-java">apt-get update
-&gt; apt-get update

sudo apt-get install -y openjdk-8-jdk
-&gt; openjdk 8 설치 원하는 버전으로 설치가능

wget -q -O - https://pkg.jenkins.io/debian/jenkins-ci.org.key | sudo apt-key add -
OK
-&gt; jenkins 저장소 key 다운로드

echo deb http://pkg.jenkins.io/debian-stable binary/ | sudo tee /etc/apt/source.list.d/jenkins.list

sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys FCEF32E745F2C3D5

sudo apt-get install jenkins
Reading package lists... Done
Building dependency tree
Reading state information... Done
Package jenkins is not available, but is referred to by another package.
This may mean that the package is missing, has been obsoleted, or
is only available from another source

E: Package &#39;jenkins&#39; has no installation candidate

이런 오류가 발생하면

sudo vi /etc/apt/sources.list

deb https://pkg.jenkins.io/debian-stable binary/ -&gt; 추가

sudo apt-get install jenkins

sudo systemctl daemon-reload
sudo systemctl start jenkins
sudo systemctl status jenkins

-------------------------------------------------------</code></pre>
<h2 id="jenkins-삭제">Jenkins 삭제</h2>
<pre><code class="language-java">sudo systemctl stop jenkins
sudo systemctl disable jenkins
sudo yum erase jenkins

sudo rm /etc/init.d/jenkins
sudo rm -rf /var/lib/jenkins
sudo rm -rf /etc/yum.repos.d/jenkins</code></pre>
<h2 id="docker-설치">Docker 설치</h2>
<pre><code class="language-java">sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

sudo add-apt-repository \
&quot;deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable&quot;

sudo apt-get update &amp;&amp; sudo apt-get install docker-ce docker-ce-cli containerd.io

-------------
sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository \
&quot;deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable&quot;
sudo apt-get update &amp;&amp; sudo apt-get install docker-ce docker-ce-cli containerd.io
docker -v
sudo systemctl enable docker &amp;&amp; service docker start
service docker status
</code></pre>
<h2 id="docker-완전-삭제">Docker 완전 삭제</h2>
<pre><code class="language-java">docker ps -a
~
~
docker stop ~
docker rm ~

docker rmi $(docker images -q)

systemctl stop docker.service
systemctl stop containerd.service

yum list installed | grep docker
~
~
~

yum erase ~

cd /var/lib/docker
rm -rf *

cd /var/run
rm docker.sock docker.pid
rm -rf docker</code></pre>
<h2 id="docker-compose">Docker-compose</h2>
<pre><code class="language-java">sudo curl -L &quot;https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)&quot; -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
docker-compose -version</code></pre>
<h2 id="gitlab-설치">Gitlab 설치</h2>
<pre><code class="language-java">curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash
curl 명령어를 이용하여 Gitlab CE 저장소를 우분투 패키지 시스템에 추가한다.

Gitlab CE 설치
우분투 패키지 시스템을 업데이트 하고, apt 명령어를 이용하여 gitlab-ce 패키지를 설치한다.

sudo apt update
sudo apt -y install gitlab-ce

sudo gitlab-ctl reconfigure

sudo cat /etc/gitlab/initial_root_password
a3vxsScmwIZKwGGPwcOs0l30LCs2Ud+VdU8yQVTMQ/A=

/etc/gitlab/gitlab.rb -&gt; gitlab 설정 경로
sudo gitlab-ctl reconfigure
jksudo gitlab-ctl status</code></pre>
<hr>
<p><a href="https://ko.linux-console.net/?p=1603">&quot;Docker를 설치하고 CentOS 및 RHEL 8/7에서 기본 컨테이너 조작 학습-1 부&quot;</a></p>
<h2 id="rhel-→-java-jenkins-gitlab-docker-docker-compose">RHEL → java, jenkins, gitlab, docker, docker-compose</h2>
<pre><code class="language-java">java 설치

sudo yum install -y java-1.8.0-openjdk-devel.x86_64
alternatives --config java</code></pre>
<p><img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/73a5daab-32a5-43f3-8f7c-c86eac84ae4d/Untitled.png" alt="Untitled"></p>
<pre><code class="language-java">docker 설치

yum install -y yum-utils

yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo

yum install https://download.docker.com/linux/centos/7/x86_64/stable/Packages/containerd.io-1.2.6-3.3.el7.x86_64.rpm
yum install docker-ce docker-ce-cli

systemctl enable --now docker
systemctl status docker

sudo chmod 666 /var/run/docker.sock
-&gt; 관리자 권한부여</code></pre>
<p><img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/8e0287b8-3953-4a84-927d-2de3108c2301/Untitled.png" alt="Untitled"></p>
<pre><code class="language-java">docker-compose 설치

sudo curl -L &quot;https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)&quot; -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose --version</code></pre>
<pre><code class="language-java">jenkins 설치

# 젠킨스 stable 버전 설치파일 다운로드
sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo

# 젠킨스 설치 key import
sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key

인터넷이 안되는 경우 인터넷이 되는 같은 운영체제의 VM 생성 후 래포 등록과 키값을 넣어준 뒤
# sudo yumdownload --resolve jenkins

# sudo yumdowonload --resolve git 
-&gt; 젠킨스 서버에도 git 래포 등록시 git 패키지가 없으면 GITHEAD~~~ 라는 오류가 발생함

# 젠킨스 패키지 설치
sudo yum install jenkins -y

sudo systemctl daemon-reload
sudo systemctl start jenkins
sudo systemctl status jenkins

# 젠킨스 설치확인
rpm -qa | grep jenkins

# 젠킨스 비밀번호 확인
docker exec &lt;CONTAINER_NAME&gt; cat /var/jenkins_home/secrets/initialAdminPassword

cat /var/lib/jenkins/secrets/initialAdminPassword</code></pre>
<p><a href="https://about.gitlab.com/install/#centos-7">Download and install GitLab</a></p>
<pre><code class="language-java">Gitlab 설치

sudo yum -y install curl vim policycoreutils python3-policycoreutils
sudo yum -y install postfix
sudo systemctl enable postfix &amp;&amp; sudo systemctl start postfix

curl -s https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | sudo bash
sudo yum install -y gitlab-ce

sudo vi /etc/gitlab/gitlab.rb

Gitlab 삭제
sudo gitlab-ctl uninstall
sudo gitlab-ctl cleanse
sudo gitlab-ctl remove-accounts
sudo dpkg -P gitlab-ce || sudo yum -y remove gitlab-ce

/opt/gitlab
/var/opt/gitlab
/etc/gitlab
/var/log/gitlab
/etc/yum.repos.d/gitlab 관련파일
</code></pre>
<h2 id="rpm으로-수동-설치">RPM으로 수동 설치</h2>
<pre><code class="language-java">1. 기존 도커 삭제
sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine

2. yum-utils 설치
sudo yum install -y yum-utils

3. docker repo 등록
sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo

4. 다운받을 디렉토리 생성 및 압축
mkdir ~/docker
cd ~/docker
yumdownloader --resolve docker-ce
tar cvzf ~/docker.tar.gz *</code></pre>
<h2 id="외부-인터넷과-통신이-안되는-경우">외부 인터넷과 통신이 안되는 경우</h2>
<pre><code class="language-java">$ sudo yum list installed | grep -i [패키지명]
$ sudo yum erase [패키지명]
$ sudo yumdownload --resolve [패키지명]

이 후 받은 파일을 압축하여 설치 대상의 서버에 설치</code></pre>
<ul>
<li>인터넷이 되는 VM을 생성해서 yumdownload를 사용하여 rpm 패키지를 받은 뒤 scp로 파일 전송하는 과정입니다.</li>
</ul>
<h2 id="utf-8-트러블-슈팅">UTF-8 트러블 슈팅</h2>
<pre><code class="language-java">$ sudo yumdownload --resolve langpacks-en glibc-all-langpacks -y
$ localectl set-locale LANG=en_US.UTF-8</code></pre>
<p>로케일 설정을 먼저 해결하고 gitlab을 설치해야지만 gitlab 설치시 오류가 생기지 않고 생성됩니다.</p>
<h2 id="gitlab-설치-1">Gitlab 설치</h2>
<pre><code class="language-java">인터넷이 되는 환경에서 yumdownload 명령어를 사용하여 패키지를 받아옵니다.
또한 https://packages.gitlab.com/gitlab 원하는 버전의 gitlab 버전을 찾아 wget으로 가져온다

wget으로 가져온 gitlab을 설치 대상의 서버에 scp로 파일을 전송한 뒤

$ sudo yum install -y [].rpm
$ sudo vi /etc/gitlab/gitlab.rb
-&gt; gitlab 설정 경로

$ sudo gitlab-ctl reconfigure
-&gt; gitlab 설정 갱신

$ sudo cat /etc/gitlab/initial_root_password
a3vxsScmwIZKwGGPwcOs0l30LCs2Ud+VdU8yQVTMQ/A=

$ sudo vim /etc/gitlab/gitlab.rb
external_URL -&gt; 원하는 값으로 변경</code></pre>
<h2 id="jenkins-설치-1">Jenkins 설치</h2>
<pre><code class="language-java">인터넷이 되는 환경에서 

# 젠킨스 stable 버전 설치파일 다운로드
sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo

# 젠킨스 설치 key import
sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key

설정 후

$ sudo yumdownload --resolve jenkins
$ 받은 jenkins.rpm 파일을 scp로 대상의 서버에 전송
$ sudo yum -y install jenkins.rpm

$ sudo systemctl enable --now jenkins
젠킨스는 Gitlab과 다르게 restart하면 설정값들이 갱신됨

$ cat /var/lib/jenkins/secrets/initialAdminPassword
-&gt; 초기 비밀번호 보는방법

Gitlab과의 pipeline 설정을 위해 git도 위와 같은 방법으로 설치해야함

    또한 인터넷이 안되는 상황이므로 Plugin을 인터넷이 되는 VM에 jenkins와 필요한 plugin을 설치해서
cd /var/liv/jenkins/plugin 경로에서 플러그인을 복사하여 Jenkins 설치 대상 서버에 넣어준다.

또는 jenkins 플러그인을 수동으로 하나하나씩 넣어주는 방법도 있다

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

Jenkins 삭제

sudo systemctl stop jenkins
sudo systemctl disable jenkins
sudo yum erase jenkins

sudo rm /etc/init.d/jenkins
sudo rm -rf /var/lib/jenkins
sudo rm -rf /etc/yum.repos.d/jenkins</code></pre>
<p>또한 private 환경에서는 외부에서 plugin을 받아오지 못해 수동으로 넣어줘야합니다.</p>
<blockquote>
<p>Jenkins-Plugin site</p>
<p><a href="https://plugins.jenkins.io/">Jenkins Plugins</a></p>
</blockquote>
]]></description>
        </item>
    </channel>
</rss>