<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>joshua_s.log</title>
        <link>https://velog.io/</link>
        <description>devops engineer가 되기 위해</description>
        <lastBuildDate>Sun, 18 Jun 2023 23:51:18 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>joshua_s.log</title>
            <url>https://velog.velcdn.com/images/joshua_s/profile/33f45a17-a356-49d0-8045-41f64a6cc6ed/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. joshua_s.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/joshua_s" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[k8s]AKS Jenkins CICD 구축(4)]]></title>
            <link>https://velog.io/@joshua_s/k8sAKS-Jenkins-CICD-%EA%B5%AC%EC%B6%953</link>
            <guid>https://velog.io/@joshua_s/k8sAKS-Jenkins-CICD-%EA%B5%AC%EC%B6%953</guid>
            <pubDate>Sun, 18 Jun 2023 23:51:18 GMT</pubDate>
            <description><![CDATA[<h2 id="intro">Intro</h2>
<p>AKS에 thanos와 prometheus, grafana를 사용하여 모니터링 시스템을 구축하였습니다. 이 내용에서 추가적으로 cicd를 구축해보는 것이 이번 내용입니다. <a href="https://velog.io/@joshua_s/k8sAKS-%EB%AA%A8%EB%8B%88%ED%84%B0%EB%A7%81-%EC%84%9C%EB%B2%84-%EA%B5%AC%EC%B6%953">이전글</a>과 연동하셔도 상관 없으며 따로 구축하셔도 무방한 내용입니다. Azure CLI에 대한 코드도 적어두었습니다. 해당 코드는 vscode에서 powershell로 Azure cli를 사용하고 있습니다. </p>
<h2 id="사전-구축-내용">사전 구축 내용</h2>
<p>만약 이미 aks 리소스가 존재한다면 VM(ubuntu)만 한개 생성해주시면 됩니다.</p>
<p>가장 먼저 Azure cli를 사용하기 위하여 login을 합니다. 해당 ID에 여러개의 구독을 가지고 있거나 여러 테넌트에 등록된 계정이라면 구성을 원하는 구독을 세팅하는 작업이 필요합니다.</p>
<pre><code># use azure cli  
az login

# default subscription check
az group list --output table

# subscription setting
az account set --subscription &quot;Subscription ID&quot;
</code></pre><p>구독이 설정 되었다면 이후에 jenkins용 vm과 aks를 생성합니다. 이전에 말씀드린 것과 같이 VScode에서 powershell로 azure-cli를 사용중입니다. 또한 아래 작업중에는 ACR 생성 및 ACR로 접근하기 위해 AKS 클러스터에 ACR Role을 할당하는 작업이 들어가 있습니다. 해당 내용은 #Generate acr과 #connect aks to acr (role) 부분이니 참고해주시기 바랍니다. <strong>이 작업을 수행하지 않으면 image에 에러가 나오게 됩니다.</strong></p>
<pre><code># Variable
$aksrg=&quot;rg-krc-dev-aks01&quot;
$aksvnet01=&quot;vnet-krc-dev-aks01&quot;
$akssnet01=&quot;snet-krc-dev-aks01&quot;
$akscluster=&quot;aks-krc-dev-app01&quot;
$aksnodepool=&quot;nokrcdaks01&quot;
$aksnoderg=&quot;rg-krc-dev-node01&quot;
$vmsnet01=&quot;snet-krc-dev-vm01&quot;
$vmnsg01=&quot;nsg-krc-dev-vm01&quot;
$vmpip01=&quot;pip01-krc-dev-jenkins01&quot;
$vmnic01=&quot;nic01-krc-dev-jenkins01&quot;
$vmosdisk=&quot;osdisk-krc-dev-jenkis01&quot;
$vmname=&quot;vmkrcdevjenkins&quot;
$vmusername=&quot;azureuser&quot;
$vmpassword=&quot;Password1234&quot;

# config resource group
az group list --output table

# create resource group, virtual network, subnet
az group create -n $aksrg --location koreacentral
az network vnet create -g $aksrg -n $aksvnet01 --subnet-name $akssnet01 --address-prefixes &quot;10.0.0.0/16&quot; --subnet-prefixes &quot;10.0.0.0/24&quot; 
az network vnet subnet create -g $aksrg --vnet-name $aksvnet01 -n $vmsnet01 --address-prefixes &quot;10.0.1.0/24&quot;

# nsg create for vm 
az network nsg create -g $aksrg -n $vmnsg01
az network nsg rule create -g $aksrg --nsg-name $vmnsg01 -n nsgsr-vm-ssh --destination-port-ranges 22 --access Allow --priority 100 --description &quot;ssh&quot; 
az network nsg rule create -g $aksrg --nsg-name $vmnsg01 -n nsgsr-vm-http --destination-port-ranges 80 --access Allow --priority 200 --description &quot;http&quot; 
az network nsg rule create -g $aksrg --nsg-name $vmnsg01 -n nsgsr-vm-jenkins --destination-port-ranges 8080 --access Allow --priority 300 --description &quot;jenkins&quot; 
az network nsg rule create -g $aksrg --nsg-name $vmnsg01 -n nsgsr-vm-go --destination-port-ranges 9000 --access Allow --priority 400 --description &quot;when i make my project, i use this port for golang&quot; 
# connect nsg to subnet
az network vnet subnet update -g $aksrg -n $vmsnet01 --vnet-name $aksvnet01 --network-security-group $vmnsg01

# create vm with pip
az network public-ip create --name $vmpip01  -g $aksrg --sku Standard
az network nic create -g $aksrg -n $vmnic01 --vnet-name $aksvnet01 --subnet $vmsnet01 --private-ip-address 10.0.1.4 --location koreacentral --public-ip-address $vmpip01
az vm create -g $aksrg --name $vmname --image UbuntuLTS --admin-username $vmusername --admin-password $vmpassword --size Standard_D2S_v5 --os-disk-name $vmosdisk --os-disk-size-gb 30 --os-disk-caching ReadWrite --storage-sku StandardSSD_LRS --nics $vmnic01

# Generate aks using azurecni
az aks create --resource-group $aksrg --name $akscluster --network-plugin azure --nodepool-name $aksnodepool --node-vm-size standard_d2s_v5 --node-count 1 --vnet-subnet-id $(az network vnet subnet list --resource-group $aksrg --vnet-name $aksvnet01 --query &quot;[0].id&quot; --output tsv) --node-resource-group $aksnoderg --docker-bridge-address 172.17.0.1/16 --dns-service-ip 10.2.0.10 --service-cidr 10.2.0.0/24 --generate-ssh-keys

# Generate acr
az acr create --name k8scicdacrtest01 -g $aksrg --sku Basic --admin-enabled true

# connect aks to acr (role)
az aks update -n $akscluster -g $aksrg --attach-acr $(az acr list --resource-group $aksrg --query &quot;[0].id&quot; --output tsv)

# connect cluster
az aks get-credentials --resource-group $aksrg --name $akscluster

# config connection
kubectl get nodes
</code></pre><p><strong>jenkins용 vm를 생성하는 이유는 기존에 jenkins 내부에 플러그인들이 2024-02-29에 사라질 예정입니다. 이에 대안으로 Azure에서 Azure-cli 사용을 권장하고 있습니다. 자세한 내용은 <a href="https://learn.microsoft.com/en-us/azure/developer/jenkins/plug-ins-for-azure">링크</a>를 확인해주세요</strong></p>
<h2 id="virtual-machine">Virtual machine</h2>
<p>기본적으로 VM에서 jenkins의 서비스를 실행시키기 위해서는 다운로드 받아야 되는 것들이 존재합니다. 기본적인 요소들은 같지만 언어는 사용하는 사람에 따라 다르니 해당 부분은 직접 설치해주시기 바랍니다. 참고로 ubuntu 22.04버전을 사용중입니다. </p>
<h3 id="1-azure-cli-설치">1. Azure-cli 설치</h3>
<p>jenkins 플러그인의 대체로 Azure-cli를 권장하므로 이를 다운로드 받아 사용해야 합니다. </p>
<pre><code>sudo apt-get install ca-certificates curl apt-transport-https lsb-release gnupg -y
sudo mkdir -p /etc/apt/keyrings
curl -sLS https://packages.microsoft.com/keys/microsoft.asc |
    gpg --dearmor |
    sudo tee /etc/apt/keyrings/microsoft.gpg &gt; /dev/null
sudo chmod go+r /etc/apt/keyrings/microsoft.gpg
AZ_REPO=$(lsb_release -cs)
echo &quot;deb [arch=`dpkg --print-architecture` signed-by=/etc/apt/keyrings/microsoft.gpg] https://packages.microsoft.com/repos/azure-cli/ $AZ_REPO main&quot; |
    sudo tee /etc/apt/sources.list.d/azure-cli.list
sudo apt-get update
sudo apt-get install azure-cli -y</code></pre><h3 id="2-jenkins-설치">2. jenkins 설치</h3>
<pre><code>sudo apt install openjdk-11-jre -y
curl -fsSL https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key | sudo tee /usr/share/keyrings/jenkins-keyring.asc &gt; /dev/null
echo &#39;deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] https://pkg.jenkins.io/debian-stable binary/&#39; | sudo tee /etc/apt/sources.list.d/jenkins.list &gt; /dev/null
sudo apt-get update &amp;&amp; sudo apt-get install jenkins -y
sudo service jenkins restart
sudo systemctl status jenkins.service</code></pre><h3 id="3-docker-설치">3. docker 설치</h3>
<pre><code>sudo apt-get install apt-transport-https ca-certificates curl software-properties-common -y
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo apt-key fingerprint 0EBFCD88
sudo add-apt-repository &quot;deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable&quot;
sudo apt-get update
sudo apt-get install docker-ce -y
sudo systemctl status docker.service</code></pre><h3 id="4-kubernetes-설치-및-인증">4. kubernetes 설치 및 인증</h3>
<p>쿠버네티스의 경우 kubectl을 사용하기 위해 필요합니다.
간단하게 설치가 가능합니다. 이때도 구독 확인 필수</p>
<pre><code>az login
sudo az aks install-cli
az aks get-credentials --resource-group rg-krc-dev-aks01 --name aks-krc-dev-app01</code></pre><h3 id="선택5-언어-설치">(선택)5. 언어 설치</h3>
<p>ubuntu에서 Golang을 설치하는 과정입니다. 최신버전은 <a href="https://go.dev/dl/">링크</a>를 확인해주시기 바랍니다</p>
<pre><code>wget https://go.dev/dl/go1.20.5.linux-amd64.tar.gz
sudo tar -xvf go1.20.5.linux-amd64.tar.gz -C /usr/local

# .profile 수정
vi ~/.profile

#마지막 부분에 추가
export GOROOT=/usr/local/go
export GOPATH=$HOME/go
export PATH=$GOPATH/bin:$GOROOT/bin:$PATH

# 환경 변수 적용 
. ~/.profile

# 설치 확인
go version
-- go version go1.20.5 linux/amd64 과 같이 버전이 출력되면 완료

# test 용 ping pong
mkdir -p ~/go/main
cd ~/go/main

vi main.go
-- 아래 코드 입력 간단한 ping pong 예제
package main

import(
        &quot;net/http&quot;
        &quot;github.com/gin-gonic/gin&quot;
)

func main() {
        r := gin.Default()
        r.GET(&quot;ping&quot;, func(c *gin.Context){
                c.JSON(http.StatusOK, gin.H{
                        &quot;message&quot;:&quot;pong&quot;,
                })
        })
        r.Run(&quot;:9000&quot;)
}

---
go mod init main.go
go mod tidy
go run main.go</code></pre><p>공인ip주소:9000/ping으로 접근 후 아래 사진과 같이 나오면 완료
<img src="https://velog.velcdn.com/images/joshua_s/post/f76f35c4-45b2-41da-bdd8-5787c861eb32/image.png" alt="">
혹시 공인 ip 주소가 기억 나지 않는경우</p>
<pre><code>curl ifconfig.me</code></pre><h3 id="6-kube-파일-소유권-변경">6. kube 파일 소유권 변경</h3>
<p>.kube파일과 docker를 젠킨스로 소유자 및 소유 그룹 변경을 실시합니다.</p>
<pre><code>sudo usermod -aG docker jenkins;
sudo usermod -aG docker azureuser;
sudo touch /var/lib/jenkins/jenkins.install.InstallUtil.lastExecVersion;
sudo service jenkins restart;
sudo cp -R ~/.kube /var/lib/jenkins/
sudo chmod 755 /var/lib/jenkins/
sudo chown -R jenkins:jenkins /var/lib/jenkins</code></pre><h2 id="jenkins-설정">jenkins 설정</h2>
<p>공인ip:8080으로 접근하면 jenkins의 초기 화면이 나오는데 initialPassword를 통하여 진입합니다.</p>
<pre><code>sudo cat /var/lib/jenkins/secrets/initialAdminPassword
</code></pre><p>Select plugins to install 클릭 후 github 선택, install
<img src="https://velog.velcdn.com/images/joshua_s/post/e3c7108a-a540-48c8-90e9-b15a6c5d9c9a/image.png" alt="">
영겁의 시간을 기다립니다...
<img src="https://velog.velcdn.com/images/joshua_s/post/8f23f927-7a71-45a6-ad2f-5802decf9803/image.png" alt="">
계정을 설정합니다.
<img src="https://velog.velcdn.com/images/joshua_s/post/ffb7ab84-ffbb-4e0d-a91c-7a95f80434ac/image.png" alt="">
freestyle로 프로젝트 생성
<img src="https://velog.velcdn.com/images/joshua_s/post/f387a3bb-27a0-40e4-bad1-d3fac160cf0d/image.png" alt="">
생성 이후 관리 -&gt; system 에서 아래쪽에 Global properties가 존재합니다. 이 부분에 ACR의 주소를 등록시켜줍니다. acr의 주소는 &quot;acr생성시작성된이름.azureacr.io&quot;입니다. </p>
<blockquote>
<p>만약 기억이 나지 않는다면 콘솔로 접근하여 확인하시거나
az acr list -g $aksrg  를 입력하여 확인하시기 바랍니다.</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/joshua_s/post/d6174c8a-634e-401e-9b64-17275592b8dd/image.png" alt=""></p>
<p>이후 jenkins의 자격증명을 위해 acr의 서비스 주체를 생성합니다.</p>
<pre><code>az ad sp create-for-rbac
-- 입력시 아래와 같은 결과물이 나오는데 메모필수
{
  &quot;appId&quot;: &quot;&quot;,
  &quot;displayName&quot;: &quot;&quot;,
  &quot;password&quot;: &quot;&quot;,
  &quot;tenant&quot;: &quot;&quot;
}
--
$ACR_ID=$(az acr show --resource-group $aksrg --name k8scicdacrtest01 --query &quot;id&quot; --output tsv)
az role assignment create --assignee &quot;appId값 입력&quot; --role Contributor --scope $ACR_ID
</code></pre><p>여기까지 진행하면 jenkins의 ACR 접근을 위한 RBAC이 생성됩니다.
이제 jenkins에 해당 id를 등록시킵니다.
관리 -&gt; Credentials -&gt; System -&gt; Global credentials (unrestricted)로 들어가 새로운 자격증명을 생성합니다. 여기서 Username은 appId이며 Password는 서비스 주체의 password입니다. 이 내용은 위에서 메모한 내용을 기반으로 합니다. ID는 acr-credentials와 같이 적당히 적으시면 됩니다.</p>
<p><img src="https://velog.velcdn.com/images/joshua_s/post/4f83957c-8793-45cd-8706-fb5b64cdb991/image.png" alt=""></p>
<p>github로 이동하셔서 Personal access Token을 생성합니다.
<img src="https://velog.velcdn.com/images/joshua_s/post/13fccdfd-9cc9-42f1-90ab-99cd16e833d3/image.png" alt=""></p>
<p>생성하며 나온 내용 또한 jenkins에 등록시킵니다
<img src="https://velog.velcdn.com/images/joshua_s/post/2dd9e3ff-bb08-4547-8e63-e2584e49af06/image.png" alt=""></p>
<p>등록 이후 github에서 webhook으로 등록시킵니다. 
<img src="https://velog.velcdn.com/images/joshua_s/post/86e1bfb4-6718-4a02-9581-e1957c26b8d1/image.png" alt=""></p>
<h3 id="작업-구성">작업 구성</h3>
<p>jenkins의 credencial까지 등록을 완료하였다면 이제 실제 작업을 구성할 차례입니다. 이전에 freestyle로 생성한 프로젝트에서 구성작업을 실시합니다. github 주소 및 등록된 credential을 적용합니다.
<img src="https://velog.velcdn.com/images/joshua_s/post/44463b0c-38f3-4f81-8004-0341d40ebb51/image.png" alt="">
<img src="https://velog.velcdn.com/images/joshua_s/post/733f2db9-460e-4fc4-80cd-362b8fc94781/image.png" alt="">
<img src="https://velog.velcdn.com/images/joshua_s/post/0ecd5e23-91f0-4b31-b6a9-10da1c712940/image.png" alt=""></p>
<p>Build Steps을 추가합니다.</p>
<pre><code>WEB_IMAGE_NAME=&quot;${ACR_SERVER}/ping:${BUILD_NUMBER}&quot;
docker build -t $WEB_IMAGE_NAME ./ping
docker login ${ACR_SERVER} -u ${ACR_ID} -p ${ACR_PASSWORD}
docker push $WEB_IMAGE_NAME</code></pre><pre><code># Update kubernetes deployment with new image.
WEB_IMAGE_NAME=&quot;${ACR_SERVER}/ping:${BUILD_NUMBER}&quot;
kubectl set image deployment/ping ping=$WEB_IMAGE_NAME</code></pre><p>-- 빌드 이전에 aks cluster에 deployment를 배포하여야 합니다. 
필자는 deployment의 이름을 ping으로 설정하였기 때문에 build step에 deployment/ping의 이미지를 변경하는 것으로 설정을 해두었습니다. 이 부분은 각자에 맞게 설정하면 되겠습니다.</p>
<h3 id="pingdeployment">ping/deployment</h3>
<p>아래는 필자의 간단한 ping.yaml의 간단한 예제를 적어두었습니다. 이를 이용하여 이미지를 변경하는 형식으로 진행되는 cicd입니다.</p>
<pre><code>---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ping
spec:
  replicas: 4
  selector:
    matchLabels:
      app: ping
  template:
    metadata:
      labels:
        app: ping
    spec:
      containers:
      - name: ping
        image: aak1009/pingpong:latest
        ports:
        - containerPort: 9000
        resources:
         requests:
           memory: &quot;64Mi&quot;
           cpu: &quot;125m&quot;
         limits:
           memory: &quot;128Mi&quot;
           cpu: &quot;250m&quot;
---
apiVersion: v1
kind: Service
metadata:
  name: ping
spec:
  type: LoadBalancer
  ports:
  - port: 9000
  selector:
    app: ping</code></pre><p>k8s에서는 Pod 교체 전략을 변경할 수 있습니다. 여기서 교체전략은 Rolling Update와 Recreate 2개의 값이 존재하며 RollingUpdate는 Pod를 하나씩 죽이고 새로 띄우면서 순차적으로 교체하는 방식이고 Recreate는 기존 파드를 모두 삭제한 이후 새로운 파드를 생성하는 방식입니다. k8s deployment의 기본 속성은 RollingUpdate이므로 따로 명시하지 않았습니다.
만약 이를 명시한다면 아래와 같은 yaml파일과 같이 지정하면 됩니다.</p>
<pre><code>apiVersion: apps/v1
kind: Deployment
metadata:
  name: ping
spec:
  replicas: 4
  strategy:
      type: RollingUpdate
    rollingUpdate:
        maxUnvailable: 2
        maxSurge: 4 
... 이하생략</code></pre><p>여기서 maxUnvailable은 롤링 업데이트 시 동시에 삭제할 수 있는 파드의 최대 개수를 의미하고, maxSurge 는 동시에 생성될 수 있는 파드의 최대 값을 의미합니다. (기본 25%)
빠르게 업데이트 하는 것도 중요하지만 이후에 벌어질 이펙트를 대비하여 적절한 값을 주는 것이 중요합니다. 이제 이 yaml파일을 이용하여 pod와 svc를 배포하고 빌드를 하시면 됩니다.
<img src="https://velog.velcdn.com/images/joshua_s/post/21f67471-68f0-4263-8014-20b05f56e268/image.png" alt=""></p>
<h3 id="build">build</h3>
<p>젠킨스로 이동하여 지금 빌드를 누르면 해당 파일을 빌드할 수 있습니다.
<img src="https://velog.velcdn.com/images/joshua_s/post/1e093447-f8b2-4d11-a759-931c179be325/image.png" alt="">
빌드를 실행시키게 되면 Build History가 생기면서 성공과 실패를 확인 할 수 있습니다.
<img src="https://velog.velcdn.com/images/joshua_s/post/c526f3b0-3ab2-42bd-99f3-c91d9c542a4b/image.png" alt="">
<img src="https://velog.velcdn.com/images/joshua_s/post/fe4a3aa0-2642-412e-9f5b-1044e2eb2e0c/image.png" alt="">
값이 잘 변경됨을 확인 할 수 있었습니다.
이전에 webhook을 등록시켰다면 로컬에서 git으로 main브런치를 이용하여 push하게 되면 github에서 webhook으로 젠킨스에게 해당 내용을 보내게 되고 자동으로 빌드를 하게됨을 볼 수 있습니다. 
<img src="https://velog.velcdn.com/images/joshua_s/post/83017e8d-fec2-4e40-bdb3-67ab92888149/image.png" alt="">
<img src="https://velog.velcdn.com/images/joshua_s/post/dcbbd74d-b9c0-45e0-bcbc-f00c439529f5/image.png" alt="">
<img src="https://velog.velcdn.com/images/joshua_s/post/9040a708-783b-4132-a68f-70581dbee3e7/image.png" alt="">
<img src="https://velog.velcdn.com/images/joshua_s/post/c06daba8-8472-4fb0-8521-69e0eb8acbd4/image.png" alt=""></p>
<p>물론 git의 브랜치를 변경하여 테스트를 진행해도 빌드 진행으로 이어지지 않는 것을 확인할 수 있습니다. git의 브랜치에 대한 명령어는 다음과 같습니다.</p>
<pre><code>브랜치 생성
git branch 이름
브랜치 확인
git branch
브랜치 변경
git checkout 브랜치이름</code></pre><p>URL에 get 요청으로 Rollingupdate를 볼 수도 있습니다.
<img src="https://velog.velcdn.com/images/joshua_s/post/5a881605-45d1-4939-a143-799593c35bd8/image.png" alt=""></p>
<h2 id="마무리">마무리</h2>
<p>마지막으로 해당 내용의 과정을 설명하면 깃헙으로 push -&gt; github에서 웹 훅을 젠킨스에게 전달 -&gt; 젠킨스에서 브랜치 확인 및 빌드시작(도커 이미지를 acr에 저장후 aks의 이미지 변경)</p>
<p>지금까지 사용한 모든 리소스를 삭제하며 마무리합시다.</p>
<pre><code>az group delete -g &quot;그룹이름&quot;</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[k8s]AKS 모니터링 서버 구축(3)]]></title>
            <link>https://velog.io/@joshua_s/k8sAKS-%EB%AA%A8%EB%8B%88%ED%84%B0%EB%A7%81-%EC%84%9C%EB%B2%84-%EA%B5%AC%EC%B6%953</link>
            <guid>https://velog.io/@joshua_s/k8sAKS-%EB%AA%A8%EB%8B%88%ED%84%B0%EB%A7%81-%EC%84%9C%EB%B2%84-%EA%B5%AC%EC%B6%953</guid>
            <pubDate>Mon, 27 Feb 2023 06:35:15 GMT</pubDate>
            <description><![CDATA[<h2 id="사전구축">사전구축</h2>
<p>이전 <a href="https://velog.io/@joshua_s/k8sAKS-front-back-%EC%84%9C%EB%B2%84-%EA%B5%AC%EC%B6%952">AKS front + back 서버 구축(2)</a>을 마친 이후에 작업을 진행해도 되지만 굳이 안해도 상관없는 내용입니다. AKS 클러스터 생성과 노드 확인후 credentials을 얻은 후에 노드를 확인했다고 한다면 큰 문제 없이 진행될 것입니다. 
현재 window환경에서 작업 중입니다.</p>
<h2 id="구축">구축</h2>
<p>모니터링 시스템을 구축하기 앞서 먼저 helm을 설치해야 합니다. 윈도우 pc의 경우 helm을 설치하기 위해 패키지 매니저인 chocolatey를 설치한 이후 kubernetes-helm을 인스톨 하는 방식으로 진행합니다.</p>
<pre><code>helm설치
1. PowerShell 관리자 모드 실행

2. Get-ExecutionPolicy  (만약 Restricted라면 AllSigned나 Bypass로 설정)
2.2. Set-ExecutionPolicy AllSignedSet-ExecutionPolicy Bypass -Scope Process

3. Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString(&#39;https://community.chocolatey.org/install.ps1&#39;))

4. choco</code></pre><p>설치 완료후 choco를 입력했을 경우 아래와 같이 나오면 성공입니다. 만약 이상이 생긴다면 <a href="https://docs.chocolatey.org/en-us/choco/setup">chocolatey의 공식 홈페이지</a>로 이동하여 설치 방법을 다시 확인하시면 됩니다.
<img src="https://velog.velcdn.com/images/joshua_s/post/3a95165d-6e90-44a6-bced-aa316c3c6785/image.png" alt="">
이후 choco를 이용하여 helm을 설치합니다.</p>
<pre><code>helm 설치

choco install kubernetes-helm

helm version</code></pre><p>설치 완료 이후 helm version을 이용하여 설치를 확인합니다.
<img src="https://velog.velcdn.com/images/joshua_s/post/3faaeb5e-a462-41de-a70e-e713c44ee9fd/image.png" alt="">
위와같이 version 정보가 출력되면 설치가 완료된 상태입니다.</p>
<p>이제 간단한 모니터링 시스템을 구축하시면 됩니다. 모니터링 시스템은 prometheus와 grafana를 이용하게 됩니다.</p>
<pre><code>Prometheus 및 Grafana용 Helm 저장소 추가
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts

helm 업데이트
helm repo update

aks에 그라파나, 프로메테우스 배포
helm install prometheus prometheus-community/kube-prometheus-stack --namespace monitoring --create-namespace

설치 확인 
kubectl get all -n monitoring
</code></pre><p>prometheus의 helm 차트가 궁금하신 분은 <a href="https://github.com/prometheus-community/helm-charts/tree/main/charts">prometheus-community/helm-chars</a>에서 확인이 가능합니다.
<img src="https://velog.velcdn.com/images/joshua_s/post/69635842-3e0f-49d6-8e25-423f70ab483a/image.png" alt=""></p>
<p>위와 같이 나오면 성공입니다. 이제 prometheus와 grafana로 접속하여 확인하도록 합니다.</p>
<pre><code>그라파나 접근
kubectl port-forward svc/prometheus-grafana -n monitoring 4000:80 # (localhost 로 접근가능)

- id : admin / passwd : prom-operator
이후 데시보드 확인

prometheus 접근
kubectl port-forward svc/prometheus-kube-prometheus-prometheus -n monitoring 4001:9090 #(localhost 로 접근가능)
</code></pre><p>localhost로 접근하여 아이디 비밀번호를 입력후 dashboards로 가게될 경우 아래와 같은 모습을 볼 수 있습니다.
<img src="https://velog.velcdn.com/images/joshua_s/post/c7c15cad-ecb0-4272-9abb-f90e861133bf/image.png" alt=""></p>
<p>Namespace(Pods)를 확인하게 될경우 pod들의 메트릭 값을 볼 수 있습니다.
<img src="https://velog.velcdn.com/images/joshua_s/post/747b8407-f85d-43f8-8176-f1c6ffddb4e7/image.png" alt="">
부하를 걸어 확인해봅시다. 
<img src="https://velog.velcdn.com/images/joshua_s/post/c4e1fb88-1e66-4c43-a323-d96043270921/image.png" alt="">
아주 잘 동작함을 볼 수 있었습니다.</p>
<h2 id="정리">정리</h2>
<p>prometheus에 접속하는 방법도 동일하게 port-forwarding으로 진행이 가능하며 해당 prometheus에서 alert도 설정이 가능하게 되어 있습니다. 하지만 보기 쉽게 설정되어 있는 것이 grafana이다 보니 grafana로 대부분을 확인을 하였습니다. 또한 prometheus는 더 공부가 필요한 부분이 있기 때문에 더 공부 후에 따로 추가하도록 하겠습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[k8s]AKS front + back 서버 구축(2)]]></title>
            <link>https://velog.io/@joshua_s/k8sAKS-front-back-%EC%84%9C%EB%B2%84-%EA%B5%AC%EC%B6%952</link>
            <guid>https://velog.io/@joshua_s/k8sAKS-front-back-%EC%84%9C%EB%B2%84-%EA%B5%AC%EC%B6%952</guid>
            <pubDate>Fri, 24 Feb 2023 07:16:46 GMT</pubDate>
            <description><![CDATA[<h2 id="사전-구축">사전 구축</h2>
<p>AKS 클러스터 구축 - 이전 자료를 확인하여 주시기 바랍니다. <a href="https://velog.io/@joshua_s/k8s-AKS-%EA%B8%B0%EB%B3%B8-%EA%B5%AC%EC%B6%951">링크</a></p>
<p>frontend (react) - 저는 프론트 엔드로 react를 선택하였고 nginx를 이용할 예정입니다. github에 있는 crud를 간단하게 구축해놓은 소스를 이용하여 조금 수정하여 사용하였습니다. 출처는 <a href="https://github.com/olinations/crud-starter-frontend">링크</a>를 참조해 주시기 바랍니다</p>
<p>backend server (go) - gin-gonic과 gorm을 이용한 백엔드 서버를 구축하여 crud api server를 구축하여 사용하였습니다.</p>
<p>DB (Azure Database for mysql) </p>
<h2 id="구축">구축</h2>
<p>가장 먼저 해야할 내용은 front와 back 서버를 docker image로 만드는 것입니다. 이를 위해 Dockerfile을 생성합니다.</p>
<pre><code>#Go server Dockerfile

FROM golang:1.18-alpine

WORKDIR /app

COPY . ./

RUN go mod download
RUN go build -o /goserver

EXPOSE 8081

CMD [ &quot;/goserver&quot; ]</code></pre><p>프론트 엔드는 먼저 nginx.conf파일과 .env.production 파일을 생성하고 적용한 후에 Docker image로 만드는 작업을 진행하였습니다. .env.production은 package.json과 같은 위치에 두었습니다. </p>
<pre><code>.env.production file

REACT_APP_URL=/api</code></pre><p>그리고 이를 적용하기 위해 env-cmd를 이용하여 package.json에 적용하는 방식으로 진행하였습니다. env-cmd는 npm으로 설치하였습니다.
<img src="https://velog.velcdn.com/images/joshua_s/post/5b3a1d1a-13ac-4d94-85e7-5ac8a8e5b8a6/image.png" alt=""></p>
<p>또한 GET 호출을 하는 부분에 URL을 아래 사진과 같이 변경하였습니다. 이렇게 하면 /api/crud로 호출이 진행되게 됩니다.
<img src="https://velog.velcdn.com/images/joshua_s/post/ada286ef-6019-4d6a-8ace-39e3d972a516/image.png" alt=""></p>
<p>이제 nginx.conf 파일을 생성합니다. 저는 ./conf/nginx.conf 위치에 두었습니다. 아래 backend:8081 부분은 후에 service를 생성할 때 지정할 svc의 이름과 포트번호 입니다. 또한 /api 부분의 rewrite를 통하여 /api 부분을 제거한 이후 부분으로 백서버와 소통이 진행되게 됩니다. 따라서 실제로 백엔드로 전달되는 부분은 /crud로 진행되게 됩니다.</p>
<pre><code>upstream backend {
    server backend:8081;
}

server {
    listen 80;
    server_name frontend;

    location / {
        root /usr/share/nginx/html;
        index index.html index.htm;
        try_files $uri /index.html;
    }

    location /api {
        rewrite ^/api(.*)$ $1?$args break;
        proxy_pass http://backend;
    }
}</code></pre><p>이제 프론트에 대한 Dockerfile을 생성합니다.</p>
<pre><code>FROM node:16.18-alpine as builder

WORKDIR /app

COPY . ./

RUN npm i

RUN npm run build

FROM nginx

COPY conf/nginx.conf /etc/nginx/conf.d/default.conf

COPY --from=builder /app/build/. /usr/share/nginx/html
</code></pre><p>각각의 Dockerfile을 생성하였다면 docker build 명령어를 이용하여 빌드를 진행합니다. 이후 docker hub로 push까지 진행하였습니다.</p>
<pre><code>docker build -t DockerHubId/이름:태그 Dockerfile위치
docker push DockerHubId/이름:태그</code></pre><p>이제 kubernetes에 배포하기 위한 yaml 파일을 생성합니다.
배포해야할 내용은 deployment 2개와 service 2개입니다. 
먼저 web server에 대한 deployment 파일입니다.
아래와 같이 replicas로 pod의 수를 결정할 수 있으며 memory와 cpu도 제한할 수 있습니다.</p>
<pre><code>---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
spec:
  replicas: 3
  selector:
    matchLabels:
      app: frontend
      version: v1
  template:
    metadata:
      labels:
        app: frontend
        version: v1
    spec:
      containers:
      - name: frontend
        image: DockerID/name:tag
        ports:
        - containerPort: 80
        resources:
         requests:
           memory: &quot;64Mi&quot;
           cpu: &quot;125m&quot;
         limits:
           memory: &quot;128Mi&quot;
           cpu: &quot;250m&quot;

</code></pre><p>이후 service.yaml파일을 생성합니다. 서비스는 NodePort, LB, clusterip등으로 구성이 가능하며 default는 clusterip입니다. azure의 서비스를 같이 이용하기 위해 LB로 생성하였고 이 서비스를 apply하게 되면 azure에 LB가 생성되게 됩니다. </p>
<pre><code>apiVersion: v1
kind: Service
metadata:
  name: frontend
spec:
  type: LoadBalancer
  ports:
  - port: 80
  selector:
    app: frontend
    version: v1</code></pre><p>이어서 api서버의 yaml파일입니다. yaml파일은 Deployment와 service를 함께 배포할 수 있으며 service의 annotations를 이용하여 internalLB도 생성이 가능합니다.</p>
<pre><code>---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: backend
  template:
    metadata:
      labels:
        app: backend
    spec:
      containers:
      - name: backend
        image: Dockerhubid/name:tag
        ports:
        - containerPort: 8081
          name: app
---
apiVersion: v1
kind: Service
metadata:
  name: backend
  annotations:
    service.beta.kubernetes.io/azure-load-balancer-internal: &quot;true&quot;
spec: 
  type: LoadBalancer
  ports:
  - port: 8081
  selector:
    app: backend
</code></pre><p>이제 kubectl 명령어로 배포를 진행합니다. 먼저 연결이 되어있는지 확인하기 위해서 node를 확인합니다.</p>
<p><img src="https://velog.velcdn.com/images/joshua_s/post/a3f3893f-2719-48c6-b9dd-75a6a2b9f005/image.png" alt=""></p>
<p>노드가 확인이 된다면 apply를 통하여 배포를 진행합니다.</p>
<pre><code>kubectl apply -f yaml파일
</code></pre><p>모든 파일을 배포하였다면 get 명령어를 통하여 배포 상태를 확인합니다.</p>
<pre><code>kubectl get svc
kubectl get po -o wide
kubectl describe po pod이름</code></pre><p><img src="https://velog.velcdn.com/images/joshua_s/post/d32bee43-d3ed-4b0f-be17-138281b68af4/image.png" alt="">
배포 내용을 보시면 해당 external ip가 생성이 됩니다. 해당 external ip로 접근을 해보면 정상적으로 동작하는 것을 확인할 수 있습니다.
<img src="https://velog.velcdn.com/images/joshua_s/post/c60660f2-e8e8-43a6-99a8-034dfc56488a/image.png" alt="">
물론 콘솔에서도 LB와 k8s의 리소스들에 대한 확인이 가능합니다.</p>
<h2 id="에러">에러</h2>
<p>react를 처음으로 사용하는 것이다보니 여러 문제가 있었는데 그 중 가장 어려웠던 부분이 proxy에 대한 부분이였습니다. 기존에는 package.json에 proxy로 적용을 하여 진행하였었는데 build를 진행하면서 package.json에 대한 proxy가 적용이 되지 않는 것을 모르고 있었습니다. 그래서 npm의 http-middleware를 적용해 보거나 내부에 소통을 확인, request url을 변경, goserver의 문제인것인가 싶어서 goserver의 내용을 변경해보는 등 여러모로 많은 시도를 했었고 모든 시도는 실패하였습니다. 이후 더 찾아보면서 해결 방법을 발견하여 진행하여 성공하였습니다. 성공을 하긴 했지만 이 방법이 가장 좋은 해답인지는 확신하지 못하는 상태입니다.</p>
<h2 id="리소스-제거">리소스 제거</h2>
<p>저번과 마찬가지로 az group delete를 이용하여 리소스 그룹을 제거하거나 kubectl delete -f yaml파일이름 을 이용하여 pod를 제거하거나 여러가지 방법이 있습니다. 
<del>귀찮으니 그룹을 날립니다</del></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[k8s] AKS 기본 구축(1)]]></title>
            <link>https://velog.io/@joshua_s/k8s-AKS-%EA%B8%B0%EB%B3%B8-%EA%B5%AC%EC%B6%951</link>
            <guid>https://velog.io/@joshua_s/k8s-AKS-%EA%B8%B0%EB%B3%B8-%EA%B5%AC%EC%B6%951</guid>
            <pubDate>Thu, 23 Feb 2023 07:10:46 GMT</pubDate>
            <description><![CDATA[<h2 id="k8s-vs-aks">k8s VS AKS</h2>
<p>AKS는 Azure kubernetes service의 약자로 managed Kubernetes입니다.
그렇다면 managed와 일반 쿠버네티스의 차이점이 무엇일까요?</p>
<ul>
<li><p>non-managed k8s는 기본적으로 사용자들이 직접 관리를 해야합니다. 서버를 생성하여 마스터 노드와 워커 노드를 구분하고 각각에 k8s 소프트웨어 패키지를 생성하여 연결하는 등 여러가지 작업을 진행해야 사용 가능한 k8s가 완성이 됩니다. 이전 <a href="https://velog.io/@joshua_s/%EC%BF%A0%EB%B2%84%EB%84%A4%ED%8B%B0%EC%8A%A4-%ED%85%8C%EC%8A%A4%ED%8A%B8-%ED%99%98%EA%B2%BD%EA%B5%AC%EC%B6%95">쿠버네티스 테스트 환경 구축</a>을 보시면 해야할 작업들이 생각보다 많다는 것을 알 수 있습니다. 또한 관리적인 측면을 보자면 만약 노드를 늘려야 할 경우가 발생할 수 있는데 자동화를 해놓았으면 다행이지만 만약 아니라고 하면 새로운 워커노드를 생성하여 연결하는 작업들을 해줘야 합니다. 정기적인 업데이트 역시 수동으로 진행해야 하며 모든 유지 관리 작업은 수동으로 수행해야 합니다.</p>
</li>
<li><p>managed k8s는 공급자가 제공하거나 공급자를 통해 구성하는 k8s를 말합니다. 일반적으로 AWS의 EKS, Azure의 AKS, GCP의 GKE가 있습니다. 해당 리소스를 사용하게 되면 클릭 몇번 혹은 명령어 몇줄로 k8s를 세팅할 수 있습니다. 또한 밴더사의 서비스들을 연결하여 사용할 수 있기 때문에 이부분 또한 장점으로 보인다. 관리적인 측면을 봐도 Auto Scailing Group(ASG)가 있기 때문에 노드의 수를 증가하는 부분도 이상이 없으며 업데이트 또한 수월하게 진행할 수 있다. 기본적으로 노드에 대한 모니터링이 세팅 없이 가능하다는 부분도 장점중 하나이다.</p>
</li>
</ul>
<h2 id="aks-구축">AKS 구축</h2>
<p>AKS를 구축하기 앞서 콘솔이 아닌 Azure cli를 이용하여 구축을 진행합니다. 또한 k8s 기본 cni인 kubelet이 아닌 Azure cni를 이용하여 구축을 진행합니다. </p>
<pre><code>az 로그인
az login

구독 확인 
az account list

구독 변경
az account set --subscription 구독id

리소스 그룹 생성
az group create --name k8stest --location koreacentral

vnet snet 생성
az network vnet create --resource-group k8stest --name k8stestvnet --address-prefixes &quot;10.0.0.0/16&quot; --subnet-name &quot;k8ssnet&quot; --subnet-prefixes &quot;10.0.0.0/24&quot;

Azure cni를 이용한 k8s 클러스터 생성
az aks create --resource-group k8stest --name 3tierCluster --network-plugin azure --node-vm-size standard_d2s_v5 --node-count 1 --vnet-subnet-id $(az network vnet subnet list --resource-group k8stest --vnet-name k8stestvnet --query &quot;[0].id&quot; --output tsv) --docker-bridge-address 172.17.0.1/16 --dns-service-ip 10.2.0.10 --service-cidr 10.2.0.0/24 --generate-ssh-keys

kubectl 설치
az aks install-cli

클러스터 연결
az aks get-credentials --resource-group k8stest --name 3tierCluster

클러스터 연결 확인
kubectl get nodes

</code></pre><p>모든 코드를 입력하게 될경우 위와 같은 결과를 출력할 수 있습니다. 또한 콘솔로 들어가면 잘 생성된 모습과 MC_로 시작하는 k8s nodepool이 있는 Resource group을 확인할 수 있습니다.</p>
<h2 id="결론">결론</h2>
<p>간단하게 Managed k8s와 기본 k8s의 차이를 구분하고 AKS의 간단한 구축 방법을 이해하였습니다.
리소스 삭제는 아래 코드로 간단하게 가능합니다
<strong>(리소스 그룹을 삭제하는 코드입니다. 리소스 그룹 내에 모든 리소스가 삭제됩니다)</strong></p>
<pre><code>az group delete -g k8stest</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[Azure VS AWS 비교]]></title>
            <link>https://velog.io/@joshua_s/Azure-VS-AWS-%EB%B9%84%EA%B5%90</link>
            <guid>https://velog.io/@joshua_s/Azure-VS-AWS-%EB%B9%84%EA%B5%90</guid>
            <pubDate>Thu, 23 Feb 2023 02:28:48 GMT</pubDate>
            <description><![CDATA[<h2 id="소개">소개</h2>
<p>AWS 클라우드 엔지니어로서 회사를 다니다가 Azure 회사로 이직을 하면서 그동안 느꼈던 내용을 위주로 작성을 해보았습니다. 특정 클라우드가 더 낫다고 생각하는 것 보다 이런 점이 다르다 라는 것으로 봐주시면 좋을 것 같습니다. Azure와 AWS 두개의 클라우드 모두 장단점이 존재하며 궁극적으로 조직의 특정 요구 사항과 사용 목적에 따라 클라우드를 선택하는 것이 중요하다고 생각합니다.</p>
<p><strong>반박시 반박하신 분이 정답이라고 생각하시고 넘어가주세요..</strong></p>
<h2 id="계층구조">계층구조</h2>
<p><img src="https://velog.velcdn.com/images/joshua_s/post/d721183c-97b1-4453-90a0-919fb4b3280d/image.png" alt="">
AWS와 Azure 간에 계층 구조가 서로 다릅니다. 또한 에저에서는 기본적으로 테넌트 밑에 구독이 생기는 구조로 이루어져 있으며 AWS에서는 Organization은 선택입니다. 또한 AWS에도 Resource group이 있지만 이 RG는 태그와 cloudformation 기반이며 리소스들을 관리하기 편하게 묶어주는 역활만 하기 때문에 리소스를 모두 생성하고 RG를 생성해도 문제가 없으며 삭제해도 리소스에 영향을 끼치지 않지만 Azure에서는 RG내부에 리소스를 생성하며 이 RG를 삭제하면 내부에 있는 모든 리소스가 삭제되기 때문에 구조가 다른 느낌입니다.</p>
<h2 id="resource-name">Resource Name</h2>
<p><img src="https://velog.velcdn.com/images/joshua_s/post/a0ec8ef6-3164-453a-8854-341af633cdb7/image.png" alt="">
많이 사용하는 Azure와 AWS의 리소스의 이름을 비교한 표입니다. 각각 하나의 리소스 내부에서 모든 부분을 설정할 수 있는 내용들이 존재하며 가장 큰 차이점이라고 생각하는 부분은 LB에 대한 부분이라고 생각합니다. Azure에서는 7계층 - Application Gateway, 4계층 - Load Balancer라고 불리며 AWS에서는 각각 ALB, NLB로 분류됩니다. </p>
<h2 id="network">Network</h2>
<p>AWS에서 네트워크 설정을 할때 VPC를 생성하고 Subnet과 Route table을 생성하며 IGW를 생성해서 Route table에 연결해 주어 IGW가 연결된 Route table의 경우 퍼블릭 서브넷에 연결해 주고 IGW를 연결하지 않은 Route table의 경우는 Private Subnet에 연결해여 각각 Public Subnet과 Private 서브넷을 구성하게 되는데 Azure에서는 기본적인 Vnet을 생성후 Subnet을 생성하여 이용하며 따로 퍼블릭과 프라이빗을 구분하지 않습니다. 또한 Private Subnet에 있는 EC2가 외부와 통신하기 위해서는 NAT Gateway를 사용하여 Route table에 연결하여 이용하지만 Azure에서는 LB의 sNAT기능이 있기 때문에 따로 NAT를 연결할 필요가 없으며 LB를 이용하지 않으면 NAT gateway를 사용합니다. 신기한 부분은 Azure에서 명시적 아웃바운드 연결이 없는 경우 기본 아웃바운드 ip가 붙게되어 외부로 소통이 가능합니다. 이 ip는 고객의 소유가 아니며 변경될 수 있고 종속성에 대해 문제가 발생할 수 있으므로 명시적 아웃바운드를 연결(NAT or LB)을 하는 것이 권장됩니다. 자세한 사항은 <a href="https://learn.microsoft.com/ko-kr/azure/virtual-network/ip-services/default-outbound-access#when-is-default-outbound-access-provided">docs</a>를 참조하시면 됩니다.</p>
<h2 id="nameing-rule">Nameing rule</h2>
<p>기본적으로 AWS와 Azure의 리소스 Naming에 대한 부분은 매우 큰 차이가 있습니다. AWS는 태그 기반이며 Azure는 ID 기반입니다. 따라서 AWS는 엔드 포인트를 갖는 경우를 제외한 거의 대부분의 리소스는 UTF-8기준 256자를 지원하며 이름을 변경 가능합니다. 하지만 Azure는 리소스의 이름이 ID 로 사용되기 때문에 리소스 마다 제한사항이 다릅니다. vNET의 경우 2~64글자, 영숫자, 밑줄 마침표 및 하이픈을 사용 가능합니다. 리소스의 이름을 바꾸는 것은 거의 대부분이 불가능하여 만들 당시에 오탈자가 발생하면 삭제후 다시 생성해야 합니다. 리소스에 대한 제한 사항은 <a href="https://learn.microsoft.com/ko-kr/azure/azure-resource-manager/management/resource-name-rules">docs</a>를 통해 확인이 가능합니다.</p>
<h2 id="결론">결론</h2>
<p>Azure와 AWS는 많은 차이점이 존재합니다. AWS 엔지니어를 하다 Azure를 하게 되면서 경험을 통해 이해하기 어려운 점을 위주로 정리를 하였습니다. 더욱 많은 내용을 알고 싶으시면 직접 경험을 해보시거나 <a href="https://learn.microsoft.com/ko-kr/azure/architecture/aws-professional/">링크</a>를 확인하시면서 보시면 좋을 것 같습니다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코멘토 실무PT 후기 챌린지_ Golang 강의 4주차 후기]]]></title>
            <link>https://velog.io/@joshua_s/%EC%BD%94%EB%A9%98%ED%86%A0-%EC%8B%A4%EB%AC%B4PT-%ED%9B%84%EA%B8%B0-%EC%B1%8C%EB%A6%B0%EC%A7%80-Golang-%EA%B0%95%EC%9D%98-4%EC%A3%BC%EC%B0%A8-%ED%9B%84%EA%B8%B0</link>
            <guid>https://velog.io/@joshua_s/%EC%BD%94%EB%A9%98%ED%86%A0-%EC%8B%A4%EB%AC%B4PT-%ED%9B%84%EA%B8%B0-%EC%B1%8C%EB%A6%B0%EC%A7%80-Golang-%EA%B0%95%EC%9D%98-4%EC%A3%BC%EC%B0%A8-%ED%9B%84%EA%B8%B0</guid>
            <pubDate>Mon, 09 Jan 2023 07:51:17 GMT</pubDate>
            <description><![CDATA[<h2 id="4주차-교육내용">4주차 교육내용</h2>
<p>Docker 소개</p>
<ul>
<li>Docker container 개념</li>
</ul>
<p>Docker 사용</p>
<ul>
<li>Docker 명령어</li>
<li>Docker로 DB 사용하기</li>
</ul>
<p>Docker 배포</p>
<ul>
<li>Docker를 활용한 어플리케이션 배포</li>
</ul>
<h3 id="docker-소개">Docker 소개</h3>
<p>docker는 리눅스의 프로세스 격리 기술들을 활용하여 컨테이너로 실행하고 관리하는 오픈소스 프로젝트 입니다.
docker container는 일종의 소프트웨어 실행에 필요한 모든 것을 포함하는 완전한 파일 시스템 안에 포함시킵니다. 여기에는 코드, 런타임, 시스템 도구, 시스템 라이브러리 등 서버에 설치되는 모든 것입니다.
따라서 실행되는 환경에 상관없이 언제나 동일하게 동작하는 것을 보증합니다.</p>
<h3 id="docker-명령어">Docker 명령어</h3>
<p><strong>1. docker images</strong>
현재 호스트 pc에 다운로드 되어있는 이미지 출력</p>
<p><strong>2. docker ps</strong>
실행중인 컨테이너의 목록 확인
-a 옵션을 추가하면 이전에 종료되었던 컨테이너들을 포함하여 목록을 확인</p>
<p><strong>3. docker build</strong>
docker build -t 이름:태그 Dockerfile위치
docker image를 생성</p>
<p><strong>4. docker rmi</strong>
docker image 삭제</p>
<p><strong>5. docker rm</strong>
docker container 삭제
모든 컨테이너를 삭제하려면
docker rm -f $(docker ps -aq)</p>
<p><strong>6. docker inspect</strong>
docker object의 정보를 확인</p>
<p><strong>7. docker logs</strong>
docker container의 로그를 확인</p>
<p><strong>8. docker top</strong>
실행중인 도커의 프로세스를 확인</p>
<p><strong>9. docker tag</strong>
도커 이미지의 테그를 변경</p>
<p><strong>10. docker exec</strong>
실행중인 도커 컨테이너 내부로 진입하기 위한 명령어</p>
<h3 id="docker로-db-사용">Docker로 DB 사용</h3>
<p>mysql혹은 mariadb의 도커 이미지를 사용하여 db를 생성하는 명령어입니다.</p>
<blockquote>
<p>docker run -d -p 3306:3306 -v $(pwd)/volume:/var/lib/mysql --name mariadb --env MARIADB_USER=username --env MARIADB_PASSWORD=password -- MARIADB_ROOT_PASSWORD=password mariadb:latest</p>
</blockquote>
<p>저장되는 볼륨과 mariadb의 유저 정보 및 루트 패스워드를 설정하여 진입하기 위한 방법입니다.</p>
<h3 id="golang-dockerfile">golang Dockerfile</h3>
<blockquote>
<p>FROM golang:1.18-alpine
WORKDIR /app
COPY . ./
RUN go mod download
RUN go build -o /goserver
EXPOSE 8081
CMD [ &quot;/goserver&quot; ]</p>
</blockquote>
<p>goserver라는 이름으로 빌드 후 해당이름으로 실행합니다.
이제 docker build 명령어를 통하여 go server를 빌드 합니다</p>
<blockquote>
<p> docker build -t goserver .</p>
</blockquote>
<p>빌드가 완료되었다면 docker run 명령어로 실행합니다</p>
<blockquote>
<p>docker run -d -p 8081:8081 goserver</p>
</blockquote>
<p>빌드가 성공하였다면 docker ps 명령어로 확인합니다
<img src="https://velog.velcdn.com/images/joshua_s/post/0d47f4c0-1db5-40d1-bc90-6074834b12c6/image.png" alt="">
잘 생성됨을 확인하였습니다.</p>
<h3 id="코멘토-리뷰">코멘토 리뷰</h3>
<p>4주간의 짧다고 한다면 짧은 시간동안 자신이 얼마나 노력했는지가 가장 중요한 것 같다. 또한 멘토님을 어떻게 이용하였느냐로 코멘토에 대한 모든 리뷰가 갈릴 것 같다. 현업자이신 멘토님을 통해 얻을 수 있는 많은 지식을 얻은 것 같다. 선택은 본인의 몫입니다.</p>
<p>링크 : <a href="https://bit.ly/3D9XCOz">https://bit.ly/3D9XCOz</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코멘토 실무PT 후기 챌린지_ Golang 강의 3주차 후기]]]></title>
            <link>https://velog.io/@joshua_s/%EC%BD%94%EB%A9%98%ED%86%A0-%EC%8B%A4%EB%AC%B4PT-%ED%9B%84%EA%B8%B0-%EC%B1%8C%EB%A6%B0%EC%A7%80-Golang-%EA%B0%95%EC%9D%98-3%EC%A3%BC%EC%B0%A8-%ED%9B%84%EA%B8%B0</link>
            <guid>https://velog.io/@joshua_s/%EC%BD%94%EB%A9%98%ED%86%A0-%EC%8B%A4%EB%AC%B4PT-%ED%9B%84%EA%B8%B0-%EC%B1%8C%EB%A6%B0%EC%A7%80-Golang-%EA%B0%95%EC%9D%98-3%EC%A3%BC%EC%B0%A8-%ED%9B%84%EA%B8%B0</guid>
            <pubDate>Thu, 05 Jan 2023 09:19:41 GMT</pubDate>
            <description><![CDATA[<h2 id="3주차-교육내용">3주차 교육내용</h2>
<ul>
<li>CORS 개념</li>
<li>Gin 설정</li>
<li>DB docker로 실행하기</li>
<li>Client 로 확인하기</li>
<li>DB 연동(Gorm)</li>
<li>Front-end 개발 산출물을 이용한 Back-end 개발</li>
</ul>
<h3 id="cors">CORS</h3>
<p>Cross-origin resource sharing의 약자로 Origin이 다른 웹 애플리케이션 간 리소스를 공유할 수 있도록 브라우저에게 알려주는 체제입니다.
브라우저가 보안상의 이유로 Origin이 다른 웹 서버에 리소스를 요청하는 것을 막는다.</p>
<pre><code># gin-gonic에서의 cors
import &quot;github.com/gin-contrib/cors

func main() {
  router := gin.Default()
  config := cors.DefaultConfig()
  config.AllowOrigins = []string{&quot;http://localhost:3000&quot;}
  router.Use(cors.New(config))
  router.Run()
}
</code></pre><h3 id="db-docker로-실행하기">DB docker로 실행하기</h3>
<ul>
<li>Docker란 : 리눅스의 응용 프로그램들을 프로세스 격리 기술들을 사용해 컨테이너로 실행하고 관리하는 오픈 소스 프로젝트이다.</li>
</ul>
<pre><code>#도커 설치
sudo apt-get update
sudo apt-get install \
    openssh-server \
    vim \
    tree \
    ca-certificates \
    curl \
    gnupg \
    lsb-release -y

sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

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

sudo apt-get update

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin</code></pre><p>도커를 설치한 후 아래와 같은 코드를 입력해 DB를 Docker로 실행하면 mariaDB가 생성된다.</p>
<pre><code>docker run -d -p (내부 포트번호):(외부 포트번호) --name (컨테이너 이름) --env MARIADB_USER=(유저이름) --env MARIADB_PASSWORD=(패스워드) --env MARIADB_ROOT_PASSWORD=(root 패스워드) --env MARIADB_DATABASE=(DB 이름) mariadb:latest
</code></pre><h3 id="내부로-진입하여-확인">내부로 진입하여 확인</h3>
<pre><code>docker exec -i -t (컨테이너이름) /bin/bash</code></pre><p>혹은</p>
<pre><code>#클라이언트 설치
sudo apt-get install mariadb-client

#client를 이용하여 로그인
mysql -h (host ip) --port (포트번호) -u (유저이름) -p </code></pre><h3 id="gorm으로-db-연동">GORM으로 DB 연동</h3>
<pre><code># GORM 설치
go get -u gorm.io/gorm
</code></pre><pre><code>package main

import (
    &quot;fmt&quot;

    &quot;github.com/pkg/errors&quot;
    &quot;gorm.io/driver/mysql&quot;
    &quot;gorm.io/gorm&quot;
)

type Board struct {
    ID       uint   `gorm:&quot;primarykey;autoIncrement&quot; json:&quot;id&quot;`
    Email    string `json:&quot;email&quot;`
    First    string `json:&quot;first&quot;`
    Hobby    string `json:&quot;hobby&quot;`
    Last     string `json:&quot;last&quot;`
    Location string `json:&quot;location&quot;`
    Phone    string `json:&quot;phone&quot;`
}

type DBHandler struct {
    gDB *gorm.DB
}

func main() {

    dbHandler, err := NewAndConnectGorm(&quot;(MariaDBusername):(Password)@tcp((ip))/(dbname)?charset=utf8mb4&amp;parseTime=True&amp;loc=Local&amp;tls=true&quot;)
    if err != nil {
        fmt.Printf(&quot;%+v\n&quot;, err)
    }
    a, _ := dbHandler.GetBoradList()
    fmt.Println(a)
}

func NewAndConnectGorm(dsn string) (*DBHandler, error) {
    gormDB, err := gorm.Open(mysql.Open(dsn), &amp;gorm.Config{})
    gormDB.AutoMigrate(Board{})
    dbHandler := &amp;DBHandler{
        gDB: gormDB,
    }

    return dbHandler, err
}

func (h *DBHandler) GetBoradList() ([]Board, error) {
    boardList := []Board{}
    result := h.gDB.Find(&amp;boardList)

    return boardList, errors.Wrap(result.Error, &quot;db handler error2&quot;)
}
</code></pre><p>해당 DB로부터 값을 가져와서 출력해주는 코드입니다.</p>
<h3 id="오픈소스-프론트엔드-게시판을-이용하여-게시판-개발">오픈소스 프론트엔드 게시판을 이용하여 게시판 개발</h3>
<p>이번 과제는 오픈 소스 프론트 엔드 게시판을 이용하여 게시판이 동작하도록 백엔드 부분을 개발하는 내용이였습니다. <img src="https://velog.velcdn.com/images/joshua_s/post/6167508f-6c54-4ca1-8595-390da37a1edb/image.png" alt="">
많은 문제가 있었고 react를 처음으로 접하여 조금 어려움이 있었지만 개발에는 성공하였습니다! 
<img src="https://velog.velcdn.com/images/joshua_s/post/7057dff4-f922-491e-922a-b3d787106a35/image.png" alt=""></p>
<h3 id="후기">후기</h3>
<p>devops로 성장하고 싶은 생각에 golang을 공부하기로 마음을 먹었지만 어떤 부분을 공부해야할지 감이 전혀 안잡혔는데 이번 과제들을 통하여 어느정도 프로젝트에 대한 감이 잡히는 것 같았습니다. 다음 주차가 마지막 이지만 지금까지도 많은 내용을 배운 느낌을 받았습니다.</p>
<p>코멘토 : <a href="https://bit.ly/3D9XCOz">https://bit.ly/3D9XCOz</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코멘토 실무PT 후기 챌린지_ Golang 강의 2주차 후기]]]></title>
            <link>https://velog.io/@joshua_s/%EC%BD%94%EB%A9%98%ED%86%A0-%EC%8B%A4%EB%AC%B4PT-%ED%9B%84%EA%B8%B0-%EC%B1%8C%EB%A6%B0%EC%A7%80-Golang-%EA%B0%95%EC%9D%98-2%EC%A3%BC%EC%B0%A8-%ED%9B%84%EA%B8%B0</link>
            <guid>https://velog.io/@joshua_s/%EC%BD%94%EB%A9%98%ED%86%A0-%EC%8B%A4%EB%AC%B4PT-%ED%9B%84%EA%B8%B0-%EC%B1%8C%EB%A6%B0%EC%A7%80-Golang-%EA%B0%95%EC%9D%98-2%EC%A3%BC%EC%B0%A8-%ED%9B%84%EA%B8%B0</guid>
            <pubDate>Thu, 29 Dec 2022 01:06:40 GMT</pubDate>
            <description><![CDATA[<h2 id="2주차-교육">2주차 교육</h2>
<p>2주차 교육 내용은 go의 웹 프레임워크 중 하나인 gin-gonic에 대한 내용을 가지고 교육을 진행하였습니다. gin-gonic을 이용하여 Image Restful API를 만들어 Postman으로 테스트를 진행하였습니다. </p>
<h3 id="http-method">http Method</h3>
<ol>
<li>GET : 존재하는 자원에 대한 요청</li>
<li>POST : 새로운 자원을 생성</li>
<li>PUT : 존재하는 자원에 대한 변경</li>
<li>DELETE : 존재하는 자원에 대한 삭제</li>
</ol>
<h3 id="gin을-이용하여-ping-보내는-방법">gin을 이용하여 ping 보내는 방법</h3>
<pre><code>r := gin.Default()
    r.GET(&quot;/ping&quot;, func(c *gin.Context) {
        c.JSON(http.StatusOK, gin.H{
            &quot;message&quot;: &quot;pong&quot;,
        })
    })</code></pre><h3 id="binding">Binding</h3>
<ul>
<li>Binding을 하기 앞서 태그로 바인딩할 대상을 지정할 수 있다.<pre><code>type RequestURI struct {
  ImageId string `uri:&quot;id&quot;`
}
</code></pre></li>
</ul>
<p>type RequestFile struct {
    File string <code>json:&quot;image&quot;</code>
    No   string <code>json:&quot;no&quot;</code>
}</p>
<p>type Response struct {
    Res string <code>json:&quot;res&quot;</code>
}</p>
<pre><code>
- 이후에 위에서 정한 태그를 바탕으로 각각의 태그에 맞게 바인딩을 시도한다. 종류 : ShouldBind, ShouldBindJSON, ShouldBindXML, ShouldBindQuery, ShouldBindYAML, ShouldBindHeader
</code></pre><p>if err := c.ShouldBindJSON(&amp;req); err != nil { //먼저 json으로 바인딩 type = string
        fmt.Println(err)
        c.JSON(http.StatusBadRequest, Response{Res: &quot;binding error&quot;})
        return
    }</p>
<p>if err := c.ShouldBindUri(&amp;reqURI); err != nil { //:id 바인딩
        fmt.Println(err)
        c.JSON(http.StatusBadRequest, Response{Res: &quot;binding error&quot;})
        return
    }</p>
<pre><code>

### []byte 변환
이번 강의 과제에서 base64로 변환되어 들어오는 이미지를 업로드 하기 위해 아래와 같이 나눈 후 base64, 이후 부분을 byte로 변환후 업로드 시켰다. 초기에는 강의대로 바로 saveuploadfile을 이용하여 업로드 하면 되는 줄 알았지만 base64로 변환된 코드라는 점을 간과하여 실패를 했었다. 이후 멘토님에게 조언을 구한 후 해당 부분을 바로 수정할 수 있었다. 강의에 참여하는 인원수가 적고 이런식으로 바로바로 조언을 구하며 수정을 할 수 있는게 코멘토의 아주 큰 장점으로 생각된다.
![](https://velog.velcdn.com/images/joshua_s/post/651fc86c-e36d-4088-bdf9-9309ab813d9b/image.png)
</code></pre><p>//코드
data, errBase := base64.RawStdEncoding.DecodeString(strings.Split(req.File, &quot;base64,&quot;)[1]) // :&quot;base64, 부분으로 나눈 후 []byte로 변환&quot;
    if errBase != nil {
        fmt.Println(errBase)
        c.JSON(http.StatusBadRequest, Response{Res: &quot;byte conversion error&quot;})
        return
    }</p>
<pre><code>
### 이번 강의를 통하여 얻은 부분
- 해당 프래임 워크속 함수들을 이해하기 위한 방법 :
ctrl + 클릭을 통하여 해당 함수가 어떤 구조로 이루어져 있는지 확인하면서 코드를 작성할 수 있어짐!
![](https://velog.velcdn.com/images/joshua_s/post/7d85e023-77fc-4361-b8b8-6398f32fb215/image.png)
![](https://velog.velcdn.com/images/joshua_s/post/8bceadea-8d4f-4b54-ba5a-2db48d50f1f8/image.png)
위에 사진과 같이 해당 함수로 이동하여 확인할 수 있다는 것을 알았다.... 
해당 부분을 이용하여 여러 프레임 워크를 이용하여 혼자서도 어느정도 코드를 짤 수 있게 된 것이 가장 큰 부분인 것 같다.
코멘토 : https://bit.ly/3D9XCOz

</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[코멘토 실무PT 후기 챌린지_ Golang 강의 1주차 후기]]]></title>
            <link>https://velog.io/@joshua_s/%EC%BD%94%EB%A9%98%ED%86%A0-%EC%8B%A4%EB%AC%B4PT-%ED%9B%84%EA%B8%B0-%EC%B1%8C%EB%A6%B0%EC%A7%80-Golang-%EA%B0%95%EC%9D%98-1%EC%A3%BC%EC%B0%A8-%ED%9B%84%EA%B8%B0</link>
            <guid>https://velog.io/@joshua_s/%EC%BD%94%EB%A9%98%ED%86%A0-%EC%8B%A4%EB%AC%B4PT-%ED%9B%84%EA%B8%B0-%EC%B1%8C%EB%A6%B0%EC%A7%80-Golang-%EA%B0%95%EC%9D%98-1%EC%A3%BC%EC%B0%A8-%ED%9B%84%EA%B8%B0</guid>
            <pubDate>Mon, 19 Dec 2022 04:28:19 GMT</pubDate>
            <description><![CDATA[<h3 id="실무-pt를-하게된-이유">실무 PT를 하게된 이유</h3>
<p>클라우드 엔지니어에서 devops로의 전환을 위하여 여러 언어를 찍어먹어 보고 있었고 그러던 와중 같이 일하는 선임이 Golang에 대해 열심히 영업을 하시고 실무에서 자주 사용되는 k8s의 경우도 Golang으로 짠 프로그램인 것을 알게되고 이제 나도 언어 한가지를 좀 딥하게 공부해보고자 하는 생각으로 공부를 시작하게 되었다.</p>
<p>먼저는 <a href="https://youtu.be/KBdz5c-0t1w">tucker의 go언어 강의</a>를 들으며 개념에 대한 공부를 몇번 반복해서 익힌 후 이제 어떤 프로젝트를 진행해 봐야할까? 실제 실무에서는 어떤 식으로 사용하는 언어일까? 라는 고민을 하던중에 코멘토라는 곳에서 실무자가 PT를 해주는 강의가 있는 것을 보고 신청하게 되었다.</p>
<h3 id="강의-내용">강의 내용</h3>
<p>1주차 강의의 경우 기본적인 문법에 대한 내용이 많았다. 멘토분이 준비한 자료와 golang.site를 통하여 기초 문법 중 실무에서 사용하는 것을 위주로 강의가 진행 되었다. 기초 문법을 공부하고 오지 않았다면 강의를 따라가기 매우 힘들었을 것으로 생각된다. 에초에 기초 강의를 끝낸 사람들에게 하는 강의라는 생각이 더 강하긴 하다. 고루틴과 sync, mutex에 대한 부분과 각자 다른 환경이여서 환경을 맞추기위해 ubuntu에 go를 설치하는 방법등을 배우고 과제를 해결함으로 개념에 대한 부분을 더 확실하게 하는 느낌이였다.</p>
<h3 id="과제">과제</h3>
<p>과제는 1~10억 까지 덧샘, 환율 정보를 10회 가져와서 channel에 push하고 해당 값의 평균값을 출력하는 내용이다. </p>
<p>1~10억 sumation
<img src="https://velog.velcdn.com/images/joshua_s/post/32773535-6d49-461b-87e7-f592f31920cc/image.png" alt="">
환율
<img src="https://velog.velcdn.com/images/joshua_s/post/0f8ea7ce-b681-4c99-95c4-f256a7f42e76/image.png" alt=""></p>
<p>go routin을 이용하여 해당 내용을 짜긴 했지만 더 go스럽게 코드를 짤 수 있는 방법이 있지 않을까? 라는 고민을 하며 환율에 대한 부분을 조금씩 수정해보고 있는데 처음에는 환율을 가져오는 go routin의 갯수를 늘렸다고 한다면 두번째는 환율을 가져오는 루틴과 값의 결과를 출력하는 부분에 루틴을 주어 환율 정보를 가져오면서 chan에 값이 입력되면 결과를 바로 계산하는 방법으로 코드를 변경하고 있다. 이런 과제가 있고 더 go스럽게 작성하려는 생각을 가지다 보니 개념에 대한 부분이 더 확실하게 정착되는 것 같다.</p>
<h3 id="후기">후기</h3>
<p>아직 1주 밖에 되지 않았지만 초반에 갈피를 잡는 부분에 있어서는 도움이 많이 될 것 같다. 아직 시작이니깐... </p>
<h3 id="코멘토-주소">코멘토 주소</h3>
<p>실무자가 강의하는 강의가 많으니 필요하시면 보시길
<a href="https://bit.ly/3D9XCOz">https://bit.ly/3D9XCOz</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[쿠버네티스 테스트 환경구축]]></title>
            <link>https://velog.io/@joshua_s/%EC%BF%A0%EB%B2%84%EB%84%A4%ED%8B%B0%EC%8A%A4-%ED%85%8C%EC%8A%A4%ED%8A%B8-%ED%99%98%EA%B2%BD%EA%B5%AC%EC%B6%95</link>
            <guid>https://velog.io/@joshua_s/%EC%BF%A0%EB%B2%84%EB%84%A4%ED%8B%B0%EC%8A%A4-%ED%85%8C%EC%8A%A4%ED%8A%B8-%ED%99%98%EA%B2%BD%EA%B5%AC%EC%B6%95</guid>
            <pubDate>Tue, 02 Aug 2022 07:37:08 GMT</pubDate>
            <description><![CDATA[<h2 id="쿠버네티스-환경">쿠버네티스 환경</h2>
<ol>
<li>ubuntu 20.04</li>
<li>vmware workstation16</li>
</ol>
<h2 id="vm에-가상환경-세팅">vm에 가상환경 세팅</h2>
<p>세팅할때 기본적으로 ram 4GB이상 2코어 이상으로 세팅하는게 편합니다. </p>
<p>우분투 os를 설치 한 후 네트워크 세팅을 먼저 실시합니다.
네트워크 세팅은 설정으로 들어가서 고정 ip를 입력합니다.
<img src="https://velog.velcdn.com/images/joshua_s/post/df115929-ca08-457f-a8eb-2dd86076ae8e/image.png" alt="">
<img src="https://velog.velcdn.com/images/joshua_s/post/6c65bbd4-48dc-43d1-a807-f4c5d988d2a1/image.png" alt=""></p>
<p>고정 ip 설정이 완료되었다면 /etc/hosts와 /etc/hostname을 변경합니다.</p>
<pre><code>sudo vi /etc/hosts

sudo vi /etc/hostname</code></pre><p>이 두개를 변경하는데 기본적인 것은 node와 소통을 위한 부분입니다. </p>
<p>hosts
<img src="https://velog.velcdn.com/images/joshua_s/post/42150f79-223c-4d4d-a647-1ad88ddfaba2/image.png" alt=""></p>
<p>hostname
<img src="https://velog.velcdn.com/images/joshua_s/post/2754c691-fe62-4a4c-be21-4f6047aa4b83/image.png" alt=""></p>
<p>두가지의 설정이 완료되었다면 아래의 코드를 실행시킵니다.</p>
<pre><code>sudo apt-get update
sudo apt-get install \
    openssh-server \
    vim \
    tree \
    ca-certificates \
    curl \
    gnupg \
    lsb-release -y

sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

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

sudo apt-get update

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin</code></pre><p>위에 코드들은 기본적인 설정에 필요한 파일이랑 docker를 설치하는 과정입니다. 자세한 사항은 <a href="https://docs.docker.com/engine/install/ubuntu/">docs</a>를 확인하세요</p>
<pre><code>sudo systemctl status docker
sudo docker run hello-world</code></pre><p>설치가 완료되었다면 상기의 명령어로 도커를 실행이 되는지 확인하시고 docker rm 명령어로 테스트 파일를 지워줍니다.</p>
<p>이후에 vm의 클론 기능을 이용하여 node를 만들어줍니다. 이때 시스템을 종료하시고 클론을 하셔야합니다.
<img src="https://velog.velcdn.com/images/joshua_s/post/0dae267b-89aa-4d8c-a6ad-b785c088d119/image.png" alt=""></p>
<p>node를 만든 후에 각 노드에 맞게 네트워크 설정을 해줍니다.
저는 각각 130,131,132로 마스터, 노드1, 노드2를 만들었습니다.
위에서 진행한 대로 hosts와 hostname을 확인하시고 모든 설정이 끝났다면 메모리 절약을 위해 멀티유저 모드로 전환합니다.</p>
<pre><code>sudo systemctl set-default multi-user.target</code></pre><p>컴퓨터의 성능에 맞게 노드의 메모리도 줄여줍니다.
<img src="https://velog.velcdn.com/images/joshua_s/post/4dfe61c6-e72e-4806-9833-f7ae1d8e31fe/image.png" alt=""></p>
<p>putty로 각각에 접근하여 ping test를 진행합니다.
<img src="https://velog.velcdn.com/images/joshua_s/post/16ba7303-a637-4e1e-9d96-47ea8880332e/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/joshua_s/post/b7f8ad0a-c878-4ec0-aea0-f76684314b88/image.png" alt="">
정상적으로 수신하는 것을 확인할 수 있습니다.
이제 본격적으로 쿠버네티스를 설치할 시간입니다.
쿠버네티스는 기본적으로 <a href="https://kubernetes.io/ko/docs/setup/production-environment/tools/kubeadm/install-kubeadm/">공식 홈페이지</a>에 설치 방법에 대한 가이드가 있습니다. 달라지는 경우도 있기 때문에 <a href="https://kubernetes.io/ko/docs/setup/production-environment/tools/kubeadm/install-kubeadm/">공식 홈페이지</a>를 참조하는 것이 바람직합니다.
각 노드와 마스터에 아래의 코드를 실행시켜 쿠버네티스를 설치한다.</p>
<pre><code>sudo swapoff -a &amp;&amp; sudo sed -i &#39;/swap/s/^/#/&#39; /etc/fstab

cat &lt;&lt;EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

sudo modprobe overlay
sudo modprobe br_netfilter

cat &lt;&lt;EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF

sudo sysctl --system
sudo ufw disable

sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl
sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
echo &quot;deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main&quot; | sudo tee /etc/apt/sources.list.d/kubernetes.list

sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

sudo systemctl daemon-reload
sudo systemctl restart kubelet
</code></pre><p>마스터 노드는 아래의 코드를 추가로 실행시킨다.</p>
<pre><code>sudo rm /etc/containerd/config.toml
sudo systemctl restart containerd
sudo kubeadm init
</code></pre><p>최종적으로는  kubeadm join 192.168.146.130:6443 --token zx3x0p.prkjwuigxlva8jqj <br>        --discovery-token-ca-cert-hash sha256:ad2ee7cb9bf4378db184a79ed033711ddb9baf9e105142aaf3dfbcda9c08a81d
이것과 비슷하게 토큰이 생긴다. </p>
<p>아래의 코드를 실행시켜 모든 사용자가 kube 명령어를 사용할 수 있게 한다.</p>
<pre><code>mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
</code></pre><p>또한 pod간 네트워크 통신을 위해 weave net works 설치한다.</p>
<pre><code>kubectl apply -f &quot;https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d &#39;\n&#39;)&quot;
</code></pre><p>이제 노드로 이동하여서 아까 나온 토큰을 등록해주며 마스터와 연결한다.</p>
<pre><code>sudo rm /etc/containerd/config.toml
sudo kubeadm join 192.168.146.130:6443 --token zx3x0p.prkjwuigxlva8jqj \
        --discovery-token-ca-cert-hash sha256:ad2ee7cb9bf4378db184a79ed033711ddb9baf9e105142aaf3dfbcda9c08a81d
</code></pre><p>마스터로 이동하여 노드들의 상태를 확인한다.</p>
<pre><code>kubectl get nodes -o wide</code></pre><p>또한 bash에서 kubectl 명령어를 더 쉽게 사용하기 위해 tab키로 자동완성기능을 추가한다.</p>
<pre><code>source &lt;(kubectl completion bash)
echo &quot;source &lt;(kubectl completion bash)&quot; &gt;&gt; ~/.bashrc</code></pre><p>이제 쿠버네티스의 기본적인 설정이 완료되었다</p>
<pre><code>kubectl run nginx --image=nginx:1.14 --port=80
kubectl get pods -o wide</code></pre><p>여러가지 실행 명령어를 이용하여 테스트를 진행해보면 됩니다.
<img src="https://velog.velcdn.com/images/joshua_s/post/4bf7ce9a-cff4-47b3-baeb-406236d010e6/image.png" alt=""></p>
<h2 id="마무리">마무리</h2>
<p>k8s의 기본적인 부분과 명령어들을 익혀 후에 EKS를 활용 및 관리할 수 있도록!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Prometheus, Grafana를 이용한 EC2 시각화]]></title>
            <link>https://velog.io/@joshua_s/Prometheus-Grafana%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-EC2-%EC%8B%9C%EA%B0%81%ED%99%94</link>
            <guid>https://velog.io/@joshua_s/Prometheus-Grafana%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-EC2-%EC%8B%9C%EA%B0%81%ED%99%94</guid>
            <pubDate>Tue, 02 Aug 2022 07:09:12 GMT</pubDate>
            <description><![CDATA[<h2 id="개념정리">개념정리</h2>
<p>프로메테우스를 이용하면 EC2 내부에 깔려있는 mysql이나 apach와 같은 서비스들의 사용량 체크와 EC2자체의 메모리, 볼륨, CPU와 같은 것들을 확인할 수 있기 때문에 프로메테우스로 모니터링 시스템을 구축해보도록 하겠다.</p>
<h2 id="환경">환경</h2>
<ul>
<li>ubuntu 20.04</li>
<li>EC2</li>
<li>mysql </li>
<li>apach</li>
<li>prometheus</li>
<li>grafana</li>
</ul>
<h2 id="실행">실행</h2>
<p>먼저 EC2를 열어준 뒤 EC2의 내부로 진입한다. 내부로 진입한 EC2에 필요한 요소들을 설치해준다.</p>
<pre><code>sudo apt-get update
wget https://github.com/prometheus/prometheus/releases/download/v2.37.0/prometheus-2.37.0.linux-amd64.tar.gz

wget https://github.com/prometheus/mysqld_exporter/releases/download/v0.14.0/mysqld_exporter-0.14.0.linux-amd64.tar.gz

wget https://github.com/prometheus/node_exporter/releases/download/v1.3.1/node_exporter-1.3.1.linux-amd64.tar.gz

wget https://github.com/Lusitaniae/apache_exporter/releases/download/v0.11.0/apache_exporter-0.11.0.linux-amd64.tar.gz</code></pre><p>각각 prometheus와 exporter들입니다.
필요한 정보는 프로메테우스 공식 홈페이지와 원하는 exporter를 다운로드 받으시면 됩니다.</p>
<p>각각의 폴더의 압축을 풉니다.</p>
<pre><code>tar xf apache_exporter-0.11.0.linux-amd64.tar.gz
tar xf mysqld_exporter-0.14.0.linux-amd64.tar.gz
tar xf node_exporter-1.3.1.linux-amd64.tar.gz
tar xf prometheus-2.37.0.linux-amd64.tar.gz
</code></pre><p>이제 프로메테우스가 위치할 장소를 만들어주고 그 위치로 파일을 옮겨줍니다.</p>
<pre><code>sudo mkdir -p /etc/prometheus
sudo mv prometheus console_libraries prometheus.yml consoles /etc/prometheus
</code></pre><p>프로메테우스의 유저 및 그룹을 시스템에 생성한다. 계정으로 로그인을 하지 않을거기 때문에 nologin으로 설정한다.</p>
<pre><code>sudo groupadd --system prometheus
sudo useradd --system -s /usr/sbin/nologin -g prometheus prometheus</code></pre><p>프로메테우스 유저와 그룹을 생성하였으니 이제 /etc/prometheus의 폴더와 내부 소유권들을 변경한다.</p>
<pre><code>sudo chown prometheus:prometheus /etc/prometheus -R
ll</code></pre><p>이제 프로메테우스가 시스템의 서비스로 운영될 수 있도록 systemd에 등록한다. 등록시 루트 계정으로 접근하여야 합니다.</p>
<pre><code>su -
cd /etc/systemd/system
vi prometheus.service

[Unit]
Description=Prometheus
Wants=network-online.target
After=network-online.target

[Service]
User=prometheus
restart=on-failure
ExecStart=/etc/prometheus/prometheus \
        --config.file=/etc/prometheus/prometheus.yml \
        --storage.tsdb.path=/var/lib/prometheus \
        --web.console.templates=/etc/prometheus/console \
        --web.console.libraries=/etc/prometheus/console_libraries \
        --web.listen-address=0.0.0.0:9090 \
        --web.external-url=

[Install]
WantedBy=multi-user.target</code></pre><p>이제 storage파일이 적용되어 있는 /var/lib/prometheus 폴더를 생성하고 권한을 prometheus로 변경해준다.</p>
<pre><code>sudo mkdir -p /var/lib/prometheus
sudo chown prometheus:prometheus /var/lib/prometheus</code></pre><p>이제 prometheus.service 적용을 위해 리로드를 해주고 status를 확인한다.</p>
<pre><code>sudo systemctl daemon-reload
sudo systemctl status prometheus.service

sudo journalctl -xe
</code></pre><p>만일 문제가 발생하였다면 가장 밑에 있는 코드인 journalctl -xe로 확인하고 문제를 해결한다.
이제 ip로 접근하여 보면 prometheus가 잘 동작중인 것을 확인할 수 있다.
<img src="https://velog.velcdn.com/images/joshua_s/post/7448b131-5aeb-4c08-a86a-6ce3e97b3c04/image.png" alt=""></p>
<p>이제 exporter들을 설정하여 프로메테우스가 mysql과 node, apach로 부터 정보를 가져오도록 설정한다.</p>
<pre><code>mkdir -p /etc/prometheus/exporters
cd /home/ubuntu/node_exporter-1.3.1.linux-amd64
sudo mv node_exporter /etc/prometheus/exporters/
sudo chown prometheus:prometheus /etc/prometheus/exporters/ -R
</code></pre><p>이제 다시 systemd에 등록해준다.</p>
<pre><code>cd /etc/systemd/system
cp prometheus.service node-exporter.service
vi node-exporter.service

[Unit]
Description=Prometheus - node_exporter
Wants=network-online.target
After=network-online.target

[Service]
User=prometheus
restart=on-failure
ExecStart=/etc/prometheus/exporters/node_exporter 

[Install]
WantedBy=multi-user.target

</code></pre><p>다시 데몬 리로드 시키고 node_exporter을 확인한다.</p>
<pre><code>sudo systemctl daemon-reload
sudo systemctl restart node-exporter.service
sudo systemctl status node-exporter.service</code></pre><p>실제로 실행정보를 확인하려면 node_exporter의 포트 번호를 변경하지 않았다면 9100번으로 접근이 가능하다.
<img src="https://velog.velcdn.com/images/joshua_s/post/5242c6b3-0b82-4f7b-ab77-9c50bc801606/image.png" alt=""></p>
<p>이제 프로메테우스에 등록을 해주면 됩니다. 아래의 코드를 아래의 사진과 같이 추가해주시면 됩니다.</p>
<pre><code>vi /etc/prometheus/prometheus.yml

  - job_name: &quot;node_exporter&quot;
    static_configs:
      - targets: [&quot;localhost:9100&quot;]</code></pre><p><img src="https://velog.velcdn.com/images/joshua_s/post/1bf90a4f-0f29-456e-bcec-aceb3ab7feaa/image.png" alt="">
이제 프로메테우스를 재시작하고 확인해주시면됩니다.</p>
<pre><code>systemctl restart prometheus.service</code></pre><p><img src="https://velog.velcdn.com/images/joshua_s/post/2ae5c125-6f69-43b8-8e19-904b3794448a/image.png" alt=""></p>
<p>같은 방식으로 apach와 mysql을 등록시켜주시면 됩니다.
이제 그라파나를 설치하고 프로메테우스와 연결해봅시다.
그라파나 다운로드는 <a href="https://grafana.com/docs/grafana/latest/setup-grafana/installation/debian/">홈페이지</a>에서 확인 가능합니다.</p>
<pre><code>sudo apt-get install -y apt-transport-https
sudo apt-get install -y software-properties-common wget
wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add -
echo &quot;deb https://packages.grafana.com/oss/deb stable main&quot; | sudo tee -a /etc/apt/sources.list.d/grafana.list
sudo apt-get update
sudo apt-get install grafana
sudo systemctl enable grafana-server.service
sudo systemctl start grafana-server.service
sudo systemctl status grafana-server.service
</code></pre><p>그라파나의 설치가 완료되었다. 이제 3000번 포트로 접근하게 되면 그라파나에 들어가는 것을 확인할 수 있다. 
<img src="https://velog.velcdn.com/images/joshua_s/post/99ebf77d-7bf4-42e7-a3b0-a4d9289c1c74/image.png" alt="">
초기 아이디/비밀번호는 admin/admin 이다.</p>
<p><img src="https://velog.velcdn.com/images/joshua_s/post/eb004871-6cd1-45a5-a66c-e56ff547c0f6/image.png" alt=""></p>
<p>config - datasources - add datasources 로 이동한 뒤 url만 localhost:9090으로 변경한 뒤 test를 진행하면 테스트를 성공한 것을 확인할 수 있다.
<img src="https://velog.velcdn.com/images/joshua_s/post/6a410915-70af-4a73-9246-4b9af0644349/image.png" alt="">
<img src="https://velog.velcdn.com/images/joshua_s/post/14f3fac7-01d6-453c-a814-10308cb50d26/image.png" alt=""></p>
<p>이제 데쉬보드를 꾸며주면 되는데 저는 그라파나 공식 홈페이지에 대쉬보드 올려놓은 것을 import 시켜주어 꾸미기로 했습니다.
<img src="https://velog.velcdn.com/images/joshua_s/post/c7b3516d-8858-4d37-856b-20d2c014ef81/image.png" alt="">
<img src="https://velog.velcdn.com/images/joshua_s/post/8a3ed858-b829-4204-b2e2-369d785ac8a1/image.png" alt="">
<img src="https://velog.velcdn.com/images/joshua_s/post/003282c0-3fb3-42c6-a297-324ef50963a3/image.png" alt="">
<img src="https://velog.velcdn.com/images/joshua_s/post/527beeb2-3c29-4d01-8893-e9a6718dfb01/image.png" alt=""></p>
<p>끝</p>
<h2 id="마무리">마무리</h2>
<p>필요한 포트는 aws 인바운드 포트를 알아서 열어주셔야 합니다. 또한 port번호는 변경하는 것이 보안상 좋습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[EKS CI/CD 환경구축 (2)]]></title>
            <link>https://velog.io/@joshua_s/EKS-CICD-%ED%99%98%EA%B2%BD%EA%B5%AC%EC%B6%95-2</link>
            <guid>https://velog.io/@joshua_s/EKS-CICD-%ED%99%98%EA%B2%BD%EA%B5%AC%EC%B6%95-2</guid>
            <pubDate>Tue, 21 Jun 2022 07:12:10 GMT</pubDate>
            <description><![CDATA[<h2 id="환경">환경</h2>
<p>Github, jenkins, argoCD를 사용하여 CI/CD 환경의 EKS 구축을 진행한다. 
CI의 경우 Github -&gt; jenkins -&gt; AWS ECR로 진행되며
CD의 경우 argoCD -&gt; AWS EKS로 진행된다.
필자의 구성 환경은 vmware-ubuntu-docker에서 진행할 예정이다.
<a href="https://velog.io/@joshua_s/EKS-CICD-%ED%99%98%EA%B2%BD%EA%B5%AC%EC%B6%95-1">이전 내용을 참조하세요</a></p>
<h2 id="eks">EKS</h2>
<p>EKS는 Kubernetes를 실행하는 데 사용할 수 있는 관리형 서비스이다. kubernetes 제어 플레인 또는 노드를 설치, 작동, 유지 관리할 필요가 없다. 또한 오픈소스 Kubernetes 소프트웨어의 최신 버전을 실행하므로 모든 즉 기존에 사용중인 플러그인과 도구들을 사용할 수 있다. EKS에서 실행된느 애플리케이션은 IDC에서 실행중이든 퍼블릭 클라우드에서 실행중이든 상관없이 모든 표준 K8s환경에서 실행되는 앱과 완벽하게 호환된다. 즉 필요한 코드를 수정하지 않고 쉽게 EKS로 마이그레이션이 가능하다.
자세한 설명은 <a href="https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/what-is-eks.html">Docs</a>를 확인하자</p>
<h2 id="eks-server">EKS Server</h2>
<p>EKS를 시작하기 앞서서 먼저 서버를 생성해야 한다. EKS 서버는 VM으로 해도 상관없지만 필자는 EC2를 이용하여서 EKS 전용 서버를 생성하였다.</p>
<blockquote>
<p>EKS server instance 정보
OS : amazon Linux2 5.10
인스턴스 유형 : t3.small</p>
</blockquote>
<p>저는 인스턴스 정보와 같이 진행하였지만 다른 OS혹은 인스턴스 유형을 선택하여 진행하여도 상관 없습니다.
EKS 서버 인스턴스가 시작되면 ssh를 통하여 접속한 후 AWS CLI를 삭제합니다. 이는 초기에 AWS cli 1버전이 깔려있기 때문에 이 버전을 AWS CLI 2로 업그레이드 하기 위하여 진행하는 것입니다. 버전 확인은 아래의 코드로 확인할 수 있습니다.</p>
<pre><code>aws --version</code></pre><p>제거 방법은 아래와 같습니다</p>
<pre><code>sudo yum remove awscli</code></pre><p>이후에 아래의 코드로 AWS CLI버전 2를 다운로드 합니다.</p>
<pre><code>curl &quot;https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip&quot; -o &quot;awscliv2.zip&quot;
unzip awscliv2.zip
sudo ./aws/install</code></pre><p>설치가 완료되었다면 버전을 확인합니다.</p>
<pre><code>/usr/local/bin/aws --version</code></pre><p>이제 eksctl을 설치합니다. 설치방법은 <a href="https://docs.aws.amazon.com/ko_kr/ko_kr/eks/latest/userguide/eksctl.html">docs</a>를 참조하시면 됩니다.</p>
<pre><code>curl --silent --location &quot;https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz&quot; | tar xz -C /tmp
sudo mv /tmp/eksctl /usr/local/bin
eksctl version</code></pre><p>버전이 정상적으로 나온다면 설치가 완료된 것입니다.
이제 kubectl을 설치합니다.</p>
<pre><code>curl -o kubectl https://amazon-eks.s3.us-west-2.amazonaws.com/1.21.2/2021-07-05/bin/linux/amd64/kubectl
chmod +x ./kubectl
mkdir -p $HOME/bin &amp;&amp; cp ./kubectl $HOME/bin/kubectl &amp;&amp; export PATH=$PATH:$HOME/bin
echo &#39;export PATH=$PATH:$HOME/bin&#39; &gt;&gt; ~/.bashrc
kubectl version --short --client</code></pre><p>마찬가지로 완료가 된다면 client버전이 정상적으로 나오게 됩니다.
이제 aws configure 명령어를 이용하여 키를 등록합니다. 만약 계정의 Access key와 Secret key가 없다면 IAM user를 새로 만드는 것을 추천합니다. IAM user생성시 programmatic access를 꼭 체크하셔야 합니다.</p>
<pre><code>aws configure</code></pre><p>aws configure를 입력하게 된다면 아래 이미지와 같이 나오게 되는데 이때 region name은 원하는 리전을 입력하시면 됩니다. 서울 리전의 경우 ap-northeast-2입니다.
<img src="https://velog.velcdn.com/images/joshua_s/post/2a655d1a-48d4-431c-9ca0-b59e7a8c7832/image.png" alt="">
리전을 확인하는 방법은 이름 console에서 계정옆에 서울 혹은 글로벌로 되어있는 부분에 나와있습니다.
<img src="https://velog.velcdn.com/images/joshua_s/post/270a258d-9e12-4bf0-ac2c-8e1ef9545242/image.png" alt="">
이렇게 하면 관리서버에 계정을 등록하는 부분까지 완료된 상태입니다. 이제 eksctl을 사용하여서 클러스터와 node를 생성하면 됩니다. 제가 사용한 명령어는 아래와 같습니다.</p>
<pre><code>eksctl create cluster \
--name k8s-argocd \
--region ap-northeast-2 \
--with-oidc \
--ssh-access \
--ssh-public-key my-key \
--nodes 2 \
--node-type t3.small \
--node-volume-size=8 \
--managed</code></pre><p>여기서 ssh-public-key 부분에 my-key는 본인 키의 이름으로 수정하셔야 합니다. 또한 더 많은 옵션들을 확인하고 싶다면 eksctl create cluster --help 를 이용하시거나 [링크] (<a href="https://github.com/weaveworks/eksctl/tree/main/examples)%EB%A5%BC">https://github.com/weaveworks/eksctl/tree/main/examples)를</a> 확인하시면 더 다양한 예제를 볼 수 있습니다.
eks클러스터 생성은 20분 정도 소요되며 생성되고 있는 정보를 확인하고 싶다면 cloudformation에 들어가서 이벤트를 확인하시면 볼 수 있습니다.
<img src="https://velog.velcdn.com/images/joshua_s/post/b6c4466a-256e-4323-a9a6-2de1946e5c06/image.png" alt=""></p>
<h2 id="eks-argocd">EKS argocd</h2>
<p>argo cd를 설치하여 eks server에 적용한다.</p>
<pre><code>kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/v2.0.4/manifests/install.yaml
sudo curl --silent --location -o /usr/local/bin/argocd https://github.com/argoproj/argo-cd/releases/download/v2.0.4/argocd-linux-amd64
sudo chmod +x /usr/local/bin/argocd
kubectl patch svc argocd-server -n argocd -p &#39;{&quot;spec&quot;: {&quot;type&quot;: &quot;LoadBalancer&quot;}}&#39;</code></pre><p>기본적으로 argocd-server는 공개적으로 노출하지 않지만 테스트 진행상황을 확인하기 위하여 Argo cd를 로드밸런서를 사용하여 사용할 수 있도록 설정한 것이다. ELB를 통하여 접근하기 까지 시간은 대략 2분정도 기다려야한다.</p>
<pre><code>export ARGO_PWD=`kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath=&quot;{.data.password}&quot; | base64 -d`</code></pre><p>위 코드를 입력하면 argocd의 초기 비밀번호와 이름이 자동으로 생성된다.
<img src="https://velog.velcdn.com/images/joshua_s/post/0f31bb10-626a-4e9d-b426-8b3b94ff94a2/image.png" alt="">
ArgoCD는 로드벨런서의 dns주소를 입력해서 접근한다.
username은 admin이고 
password는 echo $ARGO_PWD 명령어를 이용하여 확인하면 된다.
<img src="https://velog.velcdn.com/images/joshua_s/post/675d9da5-dc20-4082-9d92-4efc2704f89b/image.png" alt="">
<img src="https://velog.velcdn.com/images/joshua_s/post/c805643f-5105-4bb9-88bf-b8116005260f/image.png" alt=""></p>
<p>ArgoCD 접근까지 완료 되었다. 이제 jenkins와 연결만 하면 CI/CD가 완료된다. Manage &gt; repositories 에 들어가서 github url 설정을 합니다. 이 설정은 connect repo using https를 클릭한 후 git repo url을 입력해주고 connect를 연결하였을때 successful이 뜨면 성공입니다.
이후에 메인 화면에 new app을 클릭하고 manifest 파일이 수정되면 저동 배포를 위하여 automatic으로 설정합니다
repository URL 부분에 깃 repo주소를 넣어주고 path부분에 kustomization.yaml파일이 있는 path를 넣어주면 됩니다.
kustomization 파일이 없다고 한다면 만들어서 넣으면 되는데 이 파일은 <a href="https://kubernetes.io/ko/docs/tasks/manage-kubernetes-objects/kustomization/">공식 홈페이지</a>를 참조하면 됩니다. </p>
<h2 id="테스트">테스트</h2>
<p>jenkins에서 bulid now를 클릭하게 되면 ecr에서 태그가 업데이트 되게되고 argocd의 app을 확인하면 새로운 pod가 배포되는 것을 확인 할 수 있습니다. </p>
<h2 id="정리">정리</h2>
<pre><code>kubectl delete pod --all
eksctl delete cluster --name cluster-name
</code></pre><p>이후에 ecr과 eks managed용 ec2를 삭제하면 끝입니다.</p>
<h2 id="사진이-안올라가요-그래서-중간부터-짤림ㅠ">사진이 안올라가요.... 그래서 중간부터 짤림...ㅠ</h2>
<p>하... 다했는데 사진 왜 안올라가 이게 외않되...?</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Lambda를 이용하여 EC2 정기적 중지, 시작]]></title>
            <link>https://velog.io/@joshua_s/Lambda%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%98%EC%97%AC-EC2-%EC%A0%95%EA%B8%B0%EC%A0%81-%EC%A4%91%EC%A7%80-%EC%8B%9C%EC%9E%91</link>
            <guid>https://velog.io/@joshua_s/Lambda%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%98%EC%97%AC-EC2-%EC%A0%95%EA%B8%B0%EC%A0%81-%EC%A4%91%EC%A7%80-%EC%8B%9C%EC%9E%91</guid>
            <pubDate>Mon, 02 May 2022 07:06:10 GMT</pubDate>
            <description><![CDATA[<h2 id="ec2-인스턴스를-정기적으로-시작중지">EC2 인스턴스를 정기적으로 시작,중지</h2>
<p>AWS는 기본적으로 Pay per use이기 떄문에 사용하지 않는 인스턴스는 중지 시키는 것이 좋다. 하지만 이를 신경쓰는 것은 6시에 칼같이 퇴근을 하고 싶은 나의 입장에서는 너무 힘든 일이다. 따라서 미리 구축을 해놓고 퇴근시간에 알아서 정지되도록 구축하려고 한다.</p>
<h2 id="iam-role">IAM Role</h2>
<p>먼저 IAM Role을 생성한다. 사용 사례는 Lambda로 적용한뒤 생성하면 된다. 또한 권한도 나중에 부여할 것이기 때문에 권한을 넣지 않고 이름만 부여해주고 바로 생성을 하면 된다.
<img src="https://velog.velcdn.com/images/joshua_s/post/7f897cc2-0873-4d3d-8f8a-5891712a3f34/image.png" alt="">
역활을 생성하였으면 이제 역활에 권한을 부여해줄 차례이다. 방금만든 Role로 이동한뒤 권한 추가에 인라인 정책 생성으로 이동한다
<img src="https://velog.velcdn.com/images/joshua_s/post/e4b8f5e7-a74f-4df3-9f57-945adcef7c87/image.png" alt="">
정책 생성에서 Json으로 변환한 뒤 다음과 같은 코드를 입력하면 된다.<img src="https://velog.velcdn.com/images/joshua_s/post/4217a7dd-4e7c-4ac6-8554-ce59be68e729/image.png" alt=""></p>
<pre><code>{
    &quot;Version&quot;: &quot;2012-10-17&quot;,
    &quot;Statement&quot;: [
        {
            &quot;Effect&quot;: &quot;Allow&quot;,
            &quot;Action&quot;: [
                &quot;logs:CreateLogGroup&quot;,
                &quot;logs:CreateLogStream&quot;,
                &quot;logs:PutLogEvents&quot;
            ],
            &quot;Resource&quot;: &quot;arn:aws:logs:*:*:*&quot;
        },
        {
            &quot;Effect&quot;: &quot;Allow&quot;,
            &quot;Action&quot;: [
                &quot;ec2:Start*&quot;,
                &quot;ec2:Stop*&quot;
            ],
            &quot;Resource&quot;: &quot;*&quot;
        }
    ]
}</code></pre><p>이후 정책 검토를 누르고 정책의 이름을 지정해주면 된다. 이렇게 하면 IAM Role은 끝이다.</p>
<h2 id="lambda">Lambda</h2>
<p>Lambda로 이동한뒤 함수 -&gt; 함수 생성을 해준다. 그런 뒤에 이름을 지정하고 권한을 선택해준다. 또한 언어는 python으로 할 것이기 때문에 python을 지정해준다. 
<img src="https://velog.velcdn.com/images/joshua_s/post/1d29b7f2-fc76-4fa9-8f12-e1e65ad23c67/image.png" alt="">
함수가 생성되었으면 구성 -&gt; 일반구성으로 가서 제한 시간을 30초로 늘려주도록 하겠다.
<img src="https://velog.velcdn.com/images/joshua_s/post/1c7ac955-a768-4aa1-a64b-719dc1c74f92/image.png" alt="">
이후에 코드로 이동한 뒤 python 스크립트를 넣어주면 끝이다.
<img src="https://velog.velcdn.com/images/joshua_s/post/db562ac8-d2eb-409c-8d8b-2e68cf523992/image.png" alt=""></p>
<pre><code>import boto3
region = &#39;본인 리전&#39;
instances = [&#39;EC2 인스턴스 ID&#39;]

ec2 = boto3.client(&#39;ec2&#39;, region_name=region)
def lambda_handler(event, context):
    if event[&#39;action&#39;] == &quot;start&quot;:
        ec2.start_instances(InstanceIds=instances, DryRun = False)
        print(&quot;instances start success&quot;)
    elif event[&#39;action&#39;] == &quot;stop&quot;:
        ec2.stop_instances(InstanceIds=instances, DryRun = False)
        print(&quot;instances stop success&quot;)</code></pre><p>리전이랑 인스턴스 부분만 수정하면 된다. 코드에 대한 이야기를 잠깐 하자면 대충 보기만해도 action:start라는 내용이 들어오면 EC2가 실행되고 action:stop이 들어오면 EC2가 중지되는 것을 알 수 있다 이를 바탕으로 간단한 테스트를 진행해보자. Deploy를 한 후에 test를 눌러 테스트 이벤트를 구성한다. 위에서 말한 것과 같이 action:start or action:stop만 있으면된다. <img src="https://velog.velcdn.com/images/joshua_s/post/7f10f9e2-7146-4ad6-ac5a-4300de295c8d/image.png" alt="">
이제 테스트를 진행하면 아주 잘 동작하는 것을 확인 할 수 있다.</p>
<h2 id="eventbridge">EventBridge</h2>
<p>원래 Cloudwatch에서 규칙을 지정해주던거 같은데 EventBridge라는 이름으로 옮겨진것 같다.. 먼저 EC2 Start부터 만들겠다. EventBridge에 가서 규칙 -&gt; 규칙생성을 클릭한다. 그 후에 이름을 입력해주고 규칙 유형은 일정으로 변경한다. 
<img src="https://velog.velcdn.com/images/joshua_s/post/9f6e7fc7-1ad8-4bb6-913e-ff7218088a2a/image.png" alt="">
이제 cron을 지정해주면 되는데 필자는 09시부터 18시까지로 진행할 것이기 때문에 
(0 0 ? * MON-FRI *)로 지정해주었다. 참고로 그리니치 평균시 기준이기 때문에 -9를 해줘야 한국과 시간이 일치한다. 잘 모르겠으면 현지시간대로 선택한 뒤 시간을 계속 바꿔보자.
<img src="https://velog.velcdn.com/images/joshua_s/post/44ddea3e-76a3-4e90-b436-0daa24c92567/image.png" alt="">
대상을 선택해주면 되는데 대상 = Lambda 그리고 함수는 방금 만든 Lambda함수, 추가설정에서 대상 입력 구성을 Json으로 변경한 뒤 Json을 만들어 준다. 이후에 대상을 검토하고 생성을 해주면 된다.
<img src="https://velog.velcdn.com/images/joshua_s/post/c53a69a3-5841-4e3f-84da-2831b6d2ee85/image.png" alt="">
같은 방법으로 Stop도 만들어주면 된다.
<img src="https://velog.velcdn.com/images/joshua_s/post/bad84d46-feea-4c3e-8fdd-f6e0e8580f51/image.png" alt="">
18시 퇴근 기준으로 시간은 9로 지정해주면 된다.
<img src="https://velog.velcdn.com/images/joshua_s/post/d69c7514-27f3-4700-9fde-cb5b80ac0523/image.png" alt="">
action은 방금과 반대로 &quot;action&quot; : &quot;stop&quot;으로 지정해주면 된다.
<img src="https://velog.velcdn.com/images/joshua_s/post/c46252f7-91be-4fe0-a76c-4d2b02347481/image.png" alt="">
이제 모든 것을 검토한 뒤 생성을 눌러주면 끝이난다.</p>
<h2 id="끝">끝</h2>
<p>이제 모든 구성이 끝났으므로 퇴근하기전에 EC2를 중지시키는 귀찮은 일은 안해도 된다. 퇴근하고 EC2를 껏나? 라는 생각에 AWS를 접속해보지 않아도 된다. 이제 자유로운 몸이 되었다.<del>그러니 10분 전에 퇴근하자</del></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[AWS CI/CD (2)]]></title>
            <link>https://velog.io/@joshua_s/AWS-CICD-2</link>
            <guid>https://velog.io/@joshua_s/AWS-CICD-2</guid>
            <pubDate>Tue, 26 Apr 2022 07:37:27 GMT</pubDate>
            <description><![CDATA[<p><a href="https://velog.io/@joshua_s/AWS-CICD-1">AWS CI/CD(1)에 이어서 진행되는 내용입니다.</a></p>
<h2 id="4-codebuild">4. CodeBuild</h2>
<p>CodeBuild를 선택하고 프로젝트를 생성한다. 소스를 CodeCommit을 선택하고 자신이 만든 레포지토리를 연결해준후 브랜치를 선택한다.<img src="https://velog.velcdn.com/images/joshua_s/post/ff493267-7369-4c8f-a178-6a9fd8315261/image.png" alt="">
환경에서 운영체제를 선택한 후에 운영체제의 버전을 선택한다. 
<img src="https://velog.velcdn.com/images/joshua_s/post/2f7fc70b-0ed6-41ec-80c0-9f668c43656d/image.png" alt=""></p>
<p>이후 IAM Role을 선택해야 하는데 만약 없다고 하면 새 서비스 역활을 선택하여 역활을 생성해주면 된다.
<img src="https://velog.velcdn.com/images/joshua_s/post/b27d4420-a6ec-4052-8a97-4baf0e9e578f/image.png" alt="">
VPC와 서브넷은 따로 설정하지 않아도 된다. 후에 Buildspec을 설정해주어야 하는데 이 Buildspec은 모두 설정한 후에 따로 넣어주려고 한다.
<img src="https://velog.velcdn.com/images/joshua_s/post/ddce8f5d-14f3-477c-adc7-c96c2bc4eb59/image.png" alt="">
이제 빌드 생성하기를 누르면 빌드가 생성된다. 빌드 프로젝트 -&gt; 방금 만든 프로젝트 -&gt; 편집 -&gt; Buildspec으로 이동한다.
<img src="https://velog.velcdn.com/images/joshua_s/post/1f5db466-2e57-4bce-b43b-fde2ea169aec/image.png" alt="">
이제 Buildspec을 넣어주면 되는데 이 내용은 파일로 만들어서 하여도 상관없지만 직접 입력으로 진행하겠다.</p>
<pre><code>version: 0.2

phases:
  pre_build:
    commands:
      - echo Build Dev prepare on `date`
  build:
    commands:
      - echo Build Dev started on `date`
  post_build:
    commands:
      - echo Build Dev completed on `date`
      - mkdir zip
      - mv ./dist ./zip/dist
      - cp appspec.yml ./zip/
      - cd zip
      - zip -r myapp.zip ./*
      - buildDateTime=$(date +%Y%m%d_%H%M%S)
      - aws s3 cp myapp.zip &quot;s3://testjoshuabu/test/&quot;
      - echo &quot;path=s3://testjoshuabu/test/myapp.zip&quot;

artifacts:
  files:
    - dist
    - appspec.yml</code></pre><p>YAML파일 형식으로 작성하면 되며 간단하게 설명한다면 모든 파일을 zip폴더로 이동한 후 zip으로 묶어서 버킷에 업로드한다는 내용이다. <a href="https://docs.aws.amazon.com/ko_kr/codebuild/latest/userguide/build-spec-ref.html">자세한 사항은 여기를 참고하자.</a>
또한 appspec.yml파일은 CodeDeploy에서 사용되며 이 파일은 미리 만들어 놓았다. 이 코드는 다음과 같다.</p>
<pre><code>version: 0.0
os: linux
files:
  - source: dist
    destination: /var/www/html
</code></pre><p>따로 무언가를 할 필요가 있지 않아서 파일 위치만 지정하였다. 이 내용도 <a href="https://docs.aws.amazon.com/ko_kr/codedeploy/latest/userguide/reference-appspec-file.html">자세한 사항은 Docs를 확인하자.</a></p>
<p>이제 빌드를 진행하여 보자! 빌드 시작을 누르면 빌드가 진행된다.
<img src="https://velog.velcdn.com/images/joshua_s/post/6e49b671-1f76-45bc-ab20-6f22c7015417/image.png" alt="">
<img src="https://velog.velcdn.com/images/joshua_s/post/a0276977-59c7-482c-9044-fb63c22a4aee/image.png" alt=""></p>
<h2 id="5-codedeploy">5. CodeDeploy</h2>
<p>이제 CodeDeploy를 생성한다. 컴퓨팅 플랫폼은 EC2로 지정한다.
<img src="https://velog.velcdn.com/images/joshua_s/post/93901e6e-6246-4e9b-9e87-0b6f938706e3/image.png" alt="">
IAM을 생성한다. IAM은 EC2로 진행하면된다.
<img src="https://velog.velcdn.com/images/joshua_s/post/c7fbf33e-1255-4dcd-a32a-c5ec9a8a5153/image.png" alt="">
Role은 AWSCodeDeployRole과 아래의 Json을 넣어주면된다.</p>
<pre><code>{
    &quot;Version&quot;: &quot;2012-10-17&quot;,
    &quot;Statement&quot;: [
        {
            &quot;Sid&quot;: &quot;EC2InstanceManagement&quot;,
            &quot;Effect&quot;: &quot;Allow&quot;,
            &quot;Action&quot;: [
                &quot;ec2:CreateTags&quot;,
                &quot;ec2:RunInstances&quot;
            ],
            &quot;Resource&quot;: &quot;*&quot;
        },
        {
            &quot;Sid&quot;: &quot;EC2InstanceProfileManagement&quot;,
            &quot;Effect&quot;: &quot;Allow&quot;,
            &quot;Action&quot;: [
                &quot;iam:PassRole&quot;
            ],
            &quot;Resource&quot;: &quot;*&quot;,
            &quot;Condition&quot;: {
                &quot;StringLike&quot;: {
                    &quot;iam:PassedToService&quot;: &quot;ec2.amazonaws.com*&quot;
                }
            }
        }
    ]
}</code></pre><p>배포 그룹생성을 누르고 배포 그룹을 입력한 뒤 서비스 역활에 방금 만든 따끈따끈한 IAM Role을 넣어준다. 배포방법은 블루/그린으로 할것이며 <a href="https://docs.aws.amazon.com/codedeploy/latest/userguide/welcome.html?icmpid=docs_acd_console#welcome-deployment-overview">자세한 사항은 docs를 확인하자</a>
<img src="https://velog.velcdn.com/images/joshua_s/post/5cce8245-b369-4209-8de3-1ff7c376ce6e/image.png" alt="">
나머지 조건들도 입력해준다. ALB와 AutoScailing은 만든 것을 넣어주면 된다.
<img src="https://velog.velcdn.com/images/joshua_s/post/e9d3cc52-4b94-400c-802d-13e2aaf1cbf7/image.png" alt="">
이제 배포를 생성하면 됩니다. 배포생성을 클릭하고 zip위치를 개정위치에 넣어주면된다.
<img src="https://velog.velcdn.com/images/joshua_s/post/04064f4f-b3c9-4e22-b5a7-f960aceb9908/image.png" alt="">
추가 배포 동작 설정에서 콘텐츠 덮어쓰기를 하여서 나중에 다시 배포를 눌렀을때 덮어써질수 있도록 하자.
<img src="https://velog.velcdn.com/images/joshua_s/post/334103de-e12f-45e4-8061-7efd78281e5c/image.png" alt="">
배포 만들기를 누르면 자동적으로 배포가 실행된다.! 이제 기다리자... 조금 오래 걸린다...
혹시 모를 에러를 위해 에러를 확인하는 방법을 말하자면 배포 수명주기 이벤트에 보면 view events라는 것이 있다. 클릭하여 들어가면 거기에 어디서 실패하였는지, 어떤 에러가 발생하였는지 나와있다. 확인하며 docs와 google, 또는 서포터를 통하여 문제를 해결하면 된다. <del>크게 건든게 없어서 문제가 발생할지 모르겠지만...</del></p>
<h2 id="6-codepipeline">6. CodePipeline</h2>
<p>이제 마지막으로 codepipeline만 하면 모든 CI/CD는 종료된다. codepipeline으로 이동한 후 이름을 입력하고 사용자 지정위치로 버킷설정한다. <img src="https://velog.velcdn.com/images/joshua_s/post/29bbc2c5-93e7-4644-a122-b2d5d1a2ac10/image.png" alt="">
소스 공급자는 이전에 완료했던 codecommit이며 나머지 내용도 이전과 동일하게 선택한 뒤 넘어간다. <img src="https://velog.velcdn.com/images/joshua_s/post/321afd3f-3048-4a17-8784-9eca23db6a01/image.png" alt="">
빌드는 codebuild이며 프로젝트 이름도 이전에 설정해두었다.
<img src="https://velog.velcdn.com/images/joshua_s/post/1868eddc-d02a-467c-aff2-279a5f881334/image.png" alt="">
배포공급자도 마찬가지로 진행하면 된다.
<img src="https://velog.velcdn.com/images/joshua_s/post/97b5bd82-3bf2-4f83-9aa4-f49d499af66e/image.png" alt="">
확인하고 파이프라인 생성을 누르면 바로 한번 진행이 시작되고 커밋이 들어올 때마다 파이프라인이 동작하게 된다. 바로 되는것이 싫다고 한다면 후에 code commit에 브런치를 추가하여 특정 브런치가 커밋한 순간 파이프라인이 진행하도록 하거나 먼저 test deploy로 진행하도록 설정한 후 test deploy에서 문제가 없다고 한다면 실 서버에 적용하는 방식으로 진행하면 상당한 부분이 해결될 것으로 생각된다. </p>
<h2 id="대충-완료했다는-내용">대충 완료했다는 내용</h2>
<p><img src="https://velog.velcdn.com/images/joshua_s/post/01cb46db-6745-4d92-a08f-370855f546ce/image.png" alt=""></p>
<p>사용한 뒤 삭제를 생활화 합시다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[AWS CI/CD (1)]]></title>
            <link>https://velog.io/@joshua_s/AWS-CICD-1</link>
            <guid>https://velog.io/@joshua_s/AWS-CICD-1</guid>
            <pubDate>Tue, 26 Apr 2022 02:20:54 GMT</pubDate>
            <description><![CDATA[<h2 id="aws의-서비스들을-활용하여-cicd를-구축">AWS의 서비스들을 활용하여 CI/CD를 구축</h2>
<p>AWS의 서비스들을 활용하여 CICD를 구현려고 한다. 여기서 CI/CD란 지속적인 통합과 지속적인 배포를 의미한다. 다시 말해서 코드 변경이 있을 때마다 사용자가 정의한 프로세스 모델에 따라 코드를 빌드, 테스트, 배포하는 시스템을 만드는 것이다.
빠른 요약은 다음과 같다.</p>
<blockquote>
<ol>
<li>EC2에 설정을 마친후 AMI로 만들기</li>
<li>S3 생성</li>
<li>Codecommit</li>
<li>codebuild</li>
<li>codedeploy</li>
<li>codepipeline</li>
</ol>
</blockquote>
<h2 id="1-ec2-설정">1. EC2 설정</h2>
<p>EC2를 만든 후 codedeploy를 위한 에이전트를 설치한다. 필자는 ubuntu 18.04버전으로 진행한다.
<img src="https://velog.velcdn.com/images/joshua_s/post/d58560f0-a3c8-4918-9aa5-8ca9aa18e0d2/image.png" alt="">
인스턴스 유형은 t3.micro로 진행했으며 네트워크는 퍼블릭으로 설정해 놓았고 보안그룹은 SSH와 HTTP, HTTPS 이렇게 3개만 허용한 보안그룹으로 만들었다. 마지막으로 사용자 데이터에 아래와 같은 코드를 삽입하였다.</p>
<pre><code>#!/bin/bash
apt-get update -y
apt-get install nginx -y
apt-get install git -y
apt-get install aws-cli
apt-get install nodejs-dev node-gyp libssl1.0-dev -y
apt-get install npm -y
apt-get install unzip -y
apt install ruby -y
apt install wget -y
cd /home/ubuntu
wget https://aws-codedeploy-ap-northeast-2.s3.ap-northeast-2.amazonaws.com/latest/install
chmod +x ./install
./install auto
cd /etc/nginx/sites-available
cat &lt;&lt;EOF &gt;  test.conf 
server {
    listen 80 default_server;
    listen [::]:80 default_server;

    root /var/www/html/dist;
    index index.html index.htm;
    server_name _;
}
EOF
ln -s /etc/nginx/sites-available/test.conf /etc/nginx/sites-enabled
rm /etc/nginx/sites-enabled/default
service nginx restart</code></pre><p>위 코드는 필자가 테스트 할때 쓰는 코드들이며 이 서비스를 이용하는데 필요 없는 것도 존재합니다. <del>(귀차니즘)</del>
apt get install ruby부터 ./install auto부분까지가 deploy Agent를 설치하는 내용입니다. 이렇게 만든 인스턴스를 이미지화하여야 한다. <img src="https://velog.velcdn.com/images/joshua_s/post/4bf01dff-50d1-4ee6-85f5-1a4e8bcd8c9a/image.png" alt="">
이미지를 생성한 후에 시작 템플릿으로 이동한 후 시작합니다.
<img src="https://velog.velcdn.com/images/joshua_s/post/9cec5bd4-804e-4b0c-bb8c-52f62fbb8b84/image.png" alt="">
적당한 이름을 입력하고 Auto Scaling 지침을 적용한다.
<img src="https://velog.velcdn.com/images/joshua_s/post/78e3dbc0-38bd-49fe-bf1d-f70c33bf1b35/image.png" alt="">
어플리케이션 및 OS 이미지 부분에 아까 만들어둔 AMI이미지를 선택한다.
<img src="https://velog.velcdn.com/images/joshua_s/post/29bc65f7-dd94-470d-8273-495069214676/image.png" alt="">
인스턴스 유형을 선택하고 키페어를 적용한 뒤 서브넷은 AutoScailing에서 선택할 예정이다. 보안그룹은 본인이 필요한 내용으로 생성하시면 됩니다. 마지막으로 IAM Role을 부여한다. 만약 없다면 만들면 됩니다. IAM Role에는 다음과 같은 정책이 부여되어 있어야 한다.
<img src="https://velog.velcdn.com/images/joshua_s/post/04dfb220-afce-4629-a9a5-f50f8dad3555/image.png" alt="">
여기까지 입력하고 탬플릿을 생성하면 된다.</p>
<p>이제 AutoScailing으로 이동한 뒤 AutoScailing 그룹 생성을 클릭한다. 이름을 입력하고 시작 템플릿에 방금 만들어둔 것을 적용한다.<img src="https://velog.velcdn.com/images/joshua_s/post/a8342baf-49b4-4e64-ab74-1726318a37c8/image.png" alt="">
본인의 VPC를 적용한 뒤에 서브넷을 설정한다. 다음으로는 로드밸런서를 연결한다. 기존 로드밸런서가 있다면 바로 적용하면 되지만 없다고 한다면 새 로드밸런서에 연결을 클릭해서 만들어둔다. <img src="https://velog.velcdn.com/images/joshua_s/post/1ce5fde0-d3a2-4dc4-bd46-8c8d42e07036/image.png" alt="">
마지막으로 그룹 크기를 적당히 설정해서 넘어간다. </p>
<p><img src="https://velog.velcdn.com/images/joshua_s/post/e526d811-efe2-4717-828e-41ca127c94c1/image.png" alt="">
여기까지 하면 EC2에서 할 모든 것이 끝났다.</p>
<h2 id="2-s3-버킷-생성">2. S3 버킷 생성</h2>
<p>S3 버킷생성은 간단하다. S3로 이동한 뒤 버킷생성, 버킷 이름을 입력해준 뒤 버킷을 생성하면 끝이다. 퍼블릭 액세스 설정은 차단으로 해놓아도 문제가 없다. 따라서 보안을 위해 차단으로 해두자.
<img src="https://velog.velcdn.com/images/joshua_s/post/6dea314f-97b3-43ec-a385-8b5836e68247/image.png" alt=""></p>
<h2 id="3-codecommit-설정">3. Codecommit 설정</h2>
<p>Codecommit으로 이동한 뒤 리포지토리 생성을 클릭하고 리포지토리 이름을 설정하고 생성을 누른다. <img src="https://velog.velcdn.com/images/joshua_s/post/c05a6573-fa9e-4ebc-822c-ec06ef391b9b/image.png" alt="">
이후에 연결단계에서 보이는 순서대로 진행하면 되는데 기본적으로 pc에 git이 설치되어 있어야한다.
<img src="https://velog.velcdn.com/images/joshua_s/post/2c8a17c5-e8dd-460b-88e6-24048807c0d2/image.png" alt="">
git이 설치되어 있다는 가정하에 3단계로 넘어가보겠다.
iam으로 이동한뒤에 액세스관리에 사용자, 지금 사용중인 계정을 클릭하면 아래와 같은 화면을 볼 수 있다.
<img src="https://velog.velcdn.com/images/joshua_s/post/f493810d-ce52-4ece-8132-996ed6fec9f4/image.png" alt="">
여기서 보안 증명으로 이동한뒤 밑으로 내리면 AWS CodeCommit에 대한 HTTPS Git 자격 증명이라는 것을 볼 수 있다. 여기서 자격증명 생성을 클릭하고 Download Credentials를 클릭하면 git에 대한 Access ID와 passwd를 얻을 수 있다.
<img src="https://velog.velcdn.com/images/joshua_s/post/07aded40-1888-46ba-9b13-fd10193bb483/image.png" alt="">
이제 다시 codecommit으로 돌아와서 3단계 리포지토리 복제분을 보면 git clone 부분을 볼 수 있다. 그 내용을 복사한다.
<img src="https://velog.velcdn.com/images/joshua_s/post/fc6d33aa-e386-450a-a861-81e5000ac497/image.png" alt="">
소스들이 있는 폴더를 연후에 git bash를 실행시키고 그 위치에 복사한 명령어를 실행시키키면 git 자격증명이 나온다. 해당 증명이 나오면 아까 다운로드 받아둔 credential.csv 파일을 연후에 ID와 passwd를 복사하여 붙여넣는다.
<img src="https://velog.velcdn.com/images/joshua_s/post/b2339745-4711-4bbb-a019-f3f17981311a/image.png" alt="">
이제 git 명령어를 이용하여 커밋이 뒤는지 확인하면 된다. 참고로 git clone을 하면 repo에 해당하는 폴더가 생성되는데 그 폴더에 올리고자 하는 파일 넣어야된다.</p>
<pre><code>git add .
git commit -m &quot;내용&quot;
git push origin master</code></pre><p><img src="https://velog.velcdn.com/images/joshua_s/post/abcdafb9-cef5-4fc3-bc14-8fce22aceb70/image.png" alt="">
이렇게 push가 완료되면 codecommit에 코드로 들어가보면 push한 폴더, 파일들이 나온다. 이렇게 되면 codecommit은 종료되었다.
<img src="https://velog.velcdn.com/images/joshua_s/post/9df29c5c-3e7e-4400-91e1-1446f56c1f55/image.png" alt=""></p>
<h2 id="이후의-내용은-다음편에-계속">이후의 내용은 다음편에 계속...</h2>
]]></description>
        </item>
        <item>
            <title><![CDATA[EKS CI/CD 환경구축 (1)]]></title>
            <link>https://velog.io/@joshua_s/EKS-CICD-%ED%99%98%EA%B2%BD%EA%B5%AC%EC%B6%95-1</link>
            <guid>https://velog.io/@joshua_s/EKS-CICD-%ED%99%98%EA%B2%BD%EA%B5%AC%EC%B6%95-1</guid>
            <pubDate>Tue, 12 Apr 2022 04:23:17 GMT</pubDate>
            <description><![CDATA[<h2 id="환경">환경</h2>
<p>Github, jenkins, argoCD를 사용하여 CI/CD 환경의 EKS 구축을 진행한다. 
CI의 경우 Github -&gt; jenkins -&gt; AWS ECR로 진행되며
CD의 경우 argoCD -&gt; AWS EKS로 진행된다.
필자의 구성 환경은 vmware-ubuntu-docker에서 진행할 예정이다.</p>
<h2 id="ci-구축">CI 구축</h2>
<h3 id="1-jenkins-설치">1. Jenkins 설치</h3>
<p>도커로 jenkins를 다운로드 한다.</p>
<pre><code>sudo docker run -itd --name jenkins -p 8080:8080 -p 50000:50000 -v /docker/jenkins:/var/jenkins_home -v /var/run/docker.sock:/var/run/docker.sock -e TZ=Asia/Seoul -u root jenkins/jenkins:latest</code></pre><p><img src="https://images.velog.io/images/joshua_s/post/ae9c561d-ed8c-4ba5-b355-0222a1b57947/image.png" alt=""></p>
<h3 id="2-jenkins-container에-docker-kustomize-설치">2. Jenkins container에 docker, kustomize 설치</h3>
<ul>
<li>Docker: docker in docker를 위하여 필요하다.(하지만 docker 측에서 보안때문에 권하지 않는다.)</li>
<li>Kustomize: 쿠버네티스 구성을 사용자 정의화하는 도구</li>
</ul>
<pre><code># docker 시작 명령어, 종료 명령어
docker start (컨테이너 이름 or ID 앞부분)
docker stop (컨테이너 이름 or ID 앞부분)

# Jenkins container 접속 명령어  
docker exec -it jenkins bash 

# docker 설치 명령어  
curl -fsSL get.docker.com -o get-docker.sh 
sh get-docker.sh 

# 확인 명령어 
docker ps 

# kustomize 설치 명령어  
curl -s &quot;https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh&quot;  | bash 
mv kustomize /usr/local/bin 
kustomize version </code></pre><p><img src="https://images.velog.io/images/joshua_s/post/27c6eb1c-f67a-4339-b1e9-711e7187c88f/image.png" alt="">
여기까지가 kustomize 까지 설치를 완료한 것이다.</p>
<h3 id="3-ecr-생성">3. ECR 생성</h3>
<p>AWS ECR &gt; 레포지토리 생성을 클릭한 뒤 프라이빗으로 생성한다.</p>
<p><img src="https://images.velog.io/images/joshua_s/post/c1793c0d-014c-4dd0-8a9a-054e1d0506b0/image.png" alt=""></p>
<p>생성을 완료했다면 생성된 레포지토리의 URL을 복사한다.</p>
<h3 id="4-jenkins-환경구성">4. Jenkins 환경구성</h3>
<p>Jenkins의 환경 구성을 위하여 Sever IP:8080으로 접속한다.
jenkins의 초기 비밀번호는 cat 명령어로 찾으면 된다. 필자의 경우 /var/jenkins_home/secrets/initialAdminPassword의 경로에 있었다.</p>
<pre><code>cat /var/jenkins_home/secrets/initialAdminPassword</code></pre><p>이제 Jenkins의 화면이 나오면 데쉬보드 -&gt; jenkins 관리 -&gt; 플러그인 메니저에서 docker-build-step, docker plugin, docker pipeline, AWS ECR을 다운로드한다.
<img src="https://images.velog.io/images/joshua_s/post/c2f079e7-ca03-43d2-826e-21cd633b41ab/image.png" alt="">
<img src="https://images.velog.io/images/joshua_s/post/ac1f3f1e-71cc-495f-a8e7-7d89aa1027a9/image.png" alt=""></p>
<p>이제 Jenkins에서 사용할 인증정보를 등록한다.
데쉬보드 -&gt; jenkins 관리 -&gt; manage Credentials로 이동한다.
<img src="https://images.velog.io/images/joshua_s/post/cc3ee1d6-2ec8-47ca-aa9a-f977cfbfa2f5/image.png" alt="">
global을 클릭하고 왼쪽에 add Credentials를 클릭하면 아래와 같은 화면이 출력된다.
<img src="https://images.velog.io/images/joshua_s/post/be703ce1-a9ac-4114-957a-4ec23d57fe14/image.png" alt="">
kind를 AWS Credentials로 변경하고 ID는 임의로 지정하면 된다. Access key, secret key는 ECR 정책이 있는 AWS IAM의 액세스 키와 시크릿 키를 입력하면 된다.</p>
<p>이 작업을 한번 더 하는데 이번엔 github에 접근하기 위한 자격증명이다. </p>
<pre><code>- kind : Username with password
- Username : github name
- password : github password
- ID : 임의 지정하면 된다.</code></pre><h3 id="5-jenkinsfile">5. Jenkinsfile</h3>
<p>Jenkinsfile을 작성한다. VScode를 열고 파일의 이름을 Jenkinsfile이라 부여한다. 이후 작성하는 방법은 <a href="https://www.jenkins.io/doc/book/pipeline/#pipeline-syntax-overview">공식문서</a>를 참고하면 좋을 것 같다.</p>
<pre><code>node {   
     // git 연동
     stage(&#39;Clone repository&#39;) { 
         checkout scm
     }     

     // 도커 이미지 build
     stage(&#39;Build image&#39;) { 
         app = docker.build(&quot;YOUR ECR URL&quot;)
     }

     // ecr repo 에 도커 이미지 push 
     stage(&#39;Push image&#39;) {  
         sh &#39;rm -f ~/.dockercfg ~/.docker/config.json || true&#39;

         docker.withRegistry(&#39;YOUR_REGISTRY&#39;, &#39;YOUR_CREDENTIAL&#39;){
             app.push(&quot;${env.BUILD_NUMBER}&quot;)
         }         
     }

     // updated docker image 태그를 git push 
     stage(&#39;Deploy&#39;) { 
         // 사전 준비
         sh(&quot;&quot;&quot;
            git config --global user.name &quot;Your Name&quot;
            git config --global user.email &quot;you@example.com&quot;
            git checkout -B master
         &quot;&quot;&quot;)
      withCredentials([usernamePassword(credentialsId: &#39;github-signin&#39;, usernameVariable: &#39;GIT_USERNAME&#39;, passwordVariable: &#39;GIT_PASSWORD&#39;)]) {   
            sh(&quot;&quot;&quot;
               #!/usr/bin/env bash
               git config --local credential.helper &quot;!f() { echo username=\\$GIT_USERNAME; echo password=\\$GIT_PASSWORD; }; f&quot;
               cd prod &amp;&amp; kustomize edit set image ECR주소:${BUILD_NUMBER}
               git add kustomization.yaml
               git status
               git commit -m &quot;update the image tag&quot;
               git push origin HEAD:master
            &quot;&quot;&quot;)   


     }

}</code></pre><p>이런식으로 코드를 작성하여 파일을 생성하였다. 다른 필요한 부분이 있으면 공식 문서나 구글링을 통하여 추가하도록 하자.</p>
<h3 id="6-dockerfile">6. Dockerfile</h3>
<pre><code>FROM ubuntu:18.04

RUN ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime

RUN apt upgrade -y &amp;&amp; apt-get update -y &amp;&amp; apt-get install nginx -y

RUN echo &quot;/ndaemon off;&quot; &gt;&gt; /etc/nginx/nginx.conf

CMD [&quot;nginx&quot;]

EXPOSE 80</code></pre><p>도커 파일은 아주 간단한 nginx를 실행시키는 파일로 구성하였습니다.</p>
<h3 id="7-github-repo-생성-및-jenkins-연동">7. github repo 생성 및 jenkins 연동</h3>
<p>github으로 이동한 뒤 레포지토리를 생성하고 제일 상위 파일에 Dockerfile을 올린다. git 명령어 정리는 나중에 하도록 하겠다.
<img src="https://velog.velcdn.com/images/joshua_s/post/b261bba5-e590-4623-87fa-8859484434e9/image.png" alt="">
github에 올렸으면 이제 Jenkins로 이동한다.
새로운 items 생성에서 pipeline을 선택한다
<img src="https://velog.velcdn.com/images/joshua_s/post/8f6b8b05-ebdb-4f30-a69b-2e7acc5b38ae/image.png" alt="">
Advance Project Options로 이동한뒤 Definiton을 SCM으로 변경한후 SCM은 git 그리고 밑에 GIT 레포지토리 URL과 미리 만들어둔 Credentials을 선택해준다.
<img src="https://velog.velcdn.com/images/joshua_s/post/b74cf7ef-be5b-4ce5-8e62-9397def5b8da/image.png" alt="">
이후에 git에 설정해둔 branch와 Jenkinsfile의 위치를 지정해주면 끝이다.
<img src="https://velog.velcdn.com/images/joshua_s/post/889ab5db-40a3-4c63-a76b-e32bc15830ec/image.png" alt=""></p>
<h3 id="8-확인">8. 확인</h3>
<p>확인할떄는 Bulid Now를 클릭하면 자동으로 빌드가 된다.
<img src="https://velog.velcdn.com/images/joshua_s/post/d2747bac-aedd-4ce4-8ead-7f1209e973a8/image.png" alt="">
<img src="https://velog.velcdn.com/images/joshua_s/post/6a9f1c96-4939-4768-a4b5-c5898b3ce482/image.png" alt=""></p>
<p>이렇게 하면 Ci는 끝난다 이제 CD까지 하면 CiCD가 완성된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[AWS DMS를 이용한 마이그레이션 서비스]]></title>
            <link>https://velog.io/@joshua_s/AWS-DMS%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EB%A7%88%EC%9D%B4%EA%B7%B8%EB%A0%88%EC%9D%B4%EC%85%98-%EC%84%9C%EB%B9%84%EC%8A%A4</link>
            <guid>https://velog.io/@joshua_s/AWS-DMS%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EB%A7%88%EC%9D%B4%EA%B7%B8%EB%A0%88%EC%9D%B4%EC%85%98-%EC%84%9C%EB%B9%84%EC%8A%A4</guid>
            <pubDate>Thu, 31 Mar 2022 07:51:43 GMT</pubDate>
            <description><![CDATA[<h2 id="개념정리">개념정리</h2>
<p>DMS : 데이터베이스 마이그레이션 서비스의 약자로 온프레미스의 데이터 베이스를 클라우드 환경으로 이동하는 서비스이다. AWS SCT를 사용하여 다른 데이터베이스 엔진으로 마이그레이션도 가능하다. 또한 지속적인 변경사항을 복제하여 소스와 타겟을 동기화 시킬 수 있다.</p>
<h2 id="소스db-생성">소스DB 생성</h2>
<p>온프레미스를 가정하기 위하여 EC2 인스턴스 한개를 생성하겠습니다. 인스턴스의 OS는 ubuntu 18.04를 선택하였으며 t2.micro의 크기를 이용하였습니다. subnet은 퍼블릭이 가능한 서브넷으로 구성하고 퍼블릭 IP 자동할당은 활성화를 해두시면 됩니다. 보안그룹은 22, 3306포트를 열어두시면 됩니다. 22는 보안성을 위하여 내 IP만 허용하시 것을 추천합니다.
<img src="https://images.velog.io/images/joshua_s/post/d07dbb9d-6f18-4e29-8905-4e41e74f8c6f/image.png" alt="">
인스턴스 한개가 생성되었습니다.
putty를 이용하여 인스턴스에 접근을 하겠습니다.
EC2를 이용하여 우분투를 생성하였으면 login 아이디는 ubuntu입니다.
<img src="https://images.velog.io/images/joshua_s/post/13304c1f-da51-451f-bbc8-f89f7f1fa66e/image.png" alt="">
이제 mysql과 pip3를 다운로드 하고 pip3로 pymysql을 다운로드합니다. pymysql은 후에 검증을 위해 python을 이용할 예정이기 때문에 다운로드 받는 것입니다. 필요하지 않으시면 다운로드 하지 않으셔도 됩니다.</p>
<pre><code>sudo apt update -y
sudo apt-get install -y mysql-server python3-pip
sudo pip3 install pymysql
sudo ufw allow 3306</code></pre><p>ufw allow 3306은 3306의 포트를 열어둔 것입니다.
이제 DB유저를 생성, DB생성, table생성을 해야합니다.
mysql은 root의 초기 비밀번호가 없으므로 엔터치시고 넘어가시면 됩니다. 저는 간단하게 테이블을 구성했습니다.</p>
<pre><code>sudo mysql -u root -p
create user &#39;test&#39;@&#39;%&#39; identified by &#39;test&#39;;
grant all privileges on *.* to &#39;test&#39;@&#39;%&#39;;
FLUSH PRIVILEGES;
create database testdb;
use testdb;

CREATE TABLE member_table (
 NAME    VARCHAR(20),
 AGE     INT,
 PRIMARY KEY(AGE)
) ENGINE=MYISAM CHARSET=utf8;
</code></pre><p>이제 데이터 베이스의 내부를 채울 시간입니다. 그 전에 앞서서 python 스크립트를 저장할 폴더를 만듭니다.</p>
<pre><code>mkdir script
cd script
vi sc.py</code></pre><p>vi로 진입을 하셨으면 인서트 모드로 전환후 내용을 채울 간단한 스크립트를 적어넣습니다.</p>
<pre><code>import pymysql
import time


jh_db = pymysql.connect(
    user=&quot;test&quot;, 
    passwd=&quot;test&quot;, 
    host=&quot;127.0.0.1&quot;, 
    db=&quot;testdb&quot;, 
    port=3306,
    charset=&#39;utf8&#39;
)

cursor = jh_db.cursor(pymysql.cursors.DictCursor)

def insertsql():
    sql_query = &quot;&quot;&quot;INSERT INTO member_table(NAME, AGE) VALUES (%s, %s)&quot;&quot;&quot;
    i = 0
    while i &lt; 100:
        i = i + 1
        cursor.execute(sql_query,(&#39;jh&#39;+str(i), i))
        jh_db.commit()
        time.sleep(1)
    jh_db.close()


if __name__ == &quot;__main__&quot;:
    insertsql()
</code></pre><p>이후에 파이썬 스크립트를 동작 시킵니다. python 파일의 내용은 본인이 편하신 방법으로 수정하시면 됩니다.</p>
<pre><code>sudo python3 sc.py</code></pre><p>참고로 위에 작성된 파이썬 파일은 1초마다 동작하며 jh0, 0부터 100까지 내용을 채우게 됩니다. 다 동작되기까지 시간이 걸리므로 중간에 취소하셔도 상관없습니다. 이제 내용을 확인합니다.</p>
<pre><code>sudo mysql -u test -p
use testdb;
select * from member_table;</code></pre><p><img src="https://images.velog.io/images/joshua_s/post/0d938aff-872a-409f-88d8-c5bc59d04e76/image.png" alt="">
이러한 결과를 얻을 수 있게됩니다.
이제 mysql의 외부 접속을 허용을 시켜야합니다. mysql에서 나와서 mysqld.cnf파일을 수정합니다. 참고로 저는 mysql 5.7버전입니다.</p>
<pre><code>cd /etc/mysql/mysql.conf.d
vi mysqld.cnf

bind-address 부분을 주석처리 </code></pre><p><img src="https://images.velog.io/images/joshua_s/post/9b8361c5-d856-497f-9e4a-83546428ae50/image.png" alt="">
이제 서비스를 다시 시작합니다.</p>
<pre><code>sudo systemctl restart mysql.service</code></pre><p>이렇게 하면 소스의 작업은 끝나게 됩니다.</p>
<h2 id="타겟-db생성">타겟 DB생성</h2>
<p>RDS에서 DB를 생성합니다.
<img src="https://images.velog.io/images/joshua_s/post/ecd3b818-421c-4181-ba2c-325955534d33/image.png" alt="">
엔진은 mysql이며 버전은 맞추는 것이 좋지만 이번에 저는 다르게 할 예정입니다.
<img src="https://images.velog.io/images/joshua_s/post/c23e443b-ca37-4cdf-a05e-6ecd5b6d6c6a/image.png" alt="">
이후에 내용대로 쭉 진행하시면 되는데 DB의 VPC가 없으신 분은 만드시면 됩니다. 또한 퍼블릭으로 진행할 것이기 때문에 퍼블릭 액세스를 허용해두셔야 합니다. 이렇게 하고 DB 생성을 누르시면 DB 생성은 끝납니다. </p>
<h2 id="dms">DMS</h2>
<p>복제 인스턴스를 생성합니다. 내용이 어렵지 않으니 그냥 보고 입력하시면 됩니다.
<img src="https://images.velog.io/images/joshua_s/post/e625b816-2aea-409f-8a43-d04f67beb0c4/image.png" alt=""></p>
<p>엔드포인트를 만듭니다. 엔드포인트는 소스와 타겟 이 두개를 만드셔야 합니다.
<img src="https://images.velog.io/images/joshua_s/post/9f2e394c-f7d2-46ab-b548-16226db4221c/image.png" alt="">
사용자 이름과 암호는 db계정을 적으시면 됩니다. 이후 생성을 누르시면 끝납니다. 다시 엔드포인트 생성을 누르시고 대상 엔드포인트, RDS선택을 누르시면 대부분의 정보가 기입되어 있습니다. 활용하시면 됩니다. 마찬가지로 입력하시고 생성누르시면 완료입니다. 이제 타겟 db의 연결테스트를 실시합니다 
<img src="https://images.velog.io/images/joshua_s/post/97d3b29f-5cde-4601-9b18-6cddb9b0a48b/image.png" alt="">
이름 누르시고 연결에 연결 테스트 하시면 됩니다.
<img src="https://images.velog.io/images/joshua_s/post/c8919bfd-1afc-4d81-a4d5-b226d937d470/image.png" alt="">
이렇게 나오면 성공한 것입니다. 
마찬가지로 소스도 테스트 해줍니다.
<img src="https://images.velog.io/images/joshua_s/post/206e9e6c-8a07-4159-ac2e-87dec6421ee2/image.png" alt="">
성공이 나왔습니다. 이제 마이그레이션 테스크로 이동하여 테스크를 생성한뒤 입력방식에 맞게 입력하시면 됩니다.
<img src="https://images.velog.io/images/joshua_s/post/d8bc4975-2d66-42d5-bfb6-f979a291d788/image.png" alt="">
테스크 설정에서 필요한 고급테스크 설정을 누르시면 예외적용을 할 수 있습니다. 참고하셔서 하시면 됩니다.
<img src="https://images.velog.io/images/joshua_s/post/0254089b-7a5c-4b3f-97a3-4cc4792f3cd8/image.png" alt="">
테이블 매핑에서 선택규칙 추가를 누르시고 스키마 입력을 누르시면 스키마 이름이 나옵니다. 이스키마 이름은 db를 적으셔도 되고 와일드카드인 %를 적으셔도 되는데 %를 적으시면 DB의 모든 내용들이 옮겨지기 때문에 필요한 내용만 필터로 추가하셔서 입력하시면됩니다. 반대로 필요없는 부분을 추가하셔서 작업을 제외로 바꾸시면 그 부분을 제외하고 나머지 부분을 마이그레이션 할 수 있습니다. 참고하시면 됩니다. 
<img src="https://images.velog.io/images/joshua_s/post/24117be0-a678-4c83-b775-0180f400a5ec/image.png" alt="">
테스크 생성을 누르시고 생성이 완료되면 테스크가 진행될 것입니다. 이후에 RDS로 접근하셔서 내용을 확인하시면 DB의 내용이 일치할 것입니다.</p>
<h3 id="테스크-진행시-오류-메시지-대처방법">테스크 진행시 오류 메시지 대처방법</h3>
<p>이 내용은 지속적 복제모드를 선택했을때 발생했던 문제와 그 해결에 대해 적어놓은 것이다.</p>
<p><img src="https://images.velog.io/images/joshua_s/post/863b30d3-158f-4fe5-a516-16230dd637de/image.png" alt="">
이런 실패 메시지로 나온 경우이다. 내용을 요약하자면 binary logging을 활성화 시켜야 된다는 내용이다. </p>
<p>해결책 </p>
<ol>
<li>바이너리 로그를 활성화 시킨다.<pre><code>cd /etc/mysql
vi my.cnf
</code></pre></li>
</ol>
<p>[mysqld]
log-bin
server-id=1</p>
<pre><code>아래 부분을 추가시켜주면 된다.
</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[ubuntu에 Docker 설치]]></title>
            <link>https://velog.io/@joshua_s/ubuntu%EC%97%90-Docker-%EC%84%A4%EC%B9%98</link>
            <guid>https://velog.io/@joshua_s/ubuntu%EC%97%90-Docker-%EC%84%A4%EC%B9%98</guid>
            <pubDate>Thu, 17 Mar 2022 05:33:58 GMT</pubDate>
            <description><![CDATA[<h3 id="ssh설치">ssh설치</h3>
<p>굳이 할 필요는 없지만 편의를 위하여 필자는 ssh를 설치한 후에 모든 작업을 진행하였다.</p>
<pre><code>sudo apt-get install openssh-server
sudo vi /etc/ssh/sshd_config</code></pre><p>ssh포트를 열기(적당히 기억할 수 있는 4~5자리 정도의 값으로 입력해도 된다.
<img src="https://images.velog.io/images/joshua_s/post/57384e77-3997-4836-9ac8-0c1e0503ffc3/image.png" alt=""></p>
<pre><code>sudo service ssh start 
sudo service ssh status
sudo ufw enable
sudo ufw allow 포트번호</code></pre><p>이후에 hostnme -I 명령어로 아이피를 확인한 후 putty와 같은 터미널 에뮬레이터로 접속하면 된다.</p>
<h3 id="docker-설치">docker 설치</h3>
<p>먼저 패키지들을 설치한다.</p>
<pre><code>sudo apt-get update
sudo apt-get install \
    ca-certificates \
    curl \
    gnupg \
    lsb-release</code></pre><p>이후에 공식 GPC키를 추가한다.</p>
<pre><code>curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg</code></pre><p>아래 명령어로 저장소를 설정한다.</p>
<pre><code>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</code></pre><p>도커 엔진을 설치한다.</p>
<pre><code>sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io</code></pre><blockquote>
<ul>
<li>만약 특정 엔진을 설치하려면 apt-cache madison docker-ce로 버전을 확인하고  sudo apt-get install docker-ce=<VERSION_STRING> docker-ce-cli=<VERSION_STRING> containerd.io 버전을 입력하면 된다.</li>
</ul>
</blockquote>
<p>도커가 제대로 설치 되었는지 확인하기 위해 hello-world 이미지를 실행하여 본다.</p>
<blockquote>
<p>sudo docker run hello-world</p>
</blockquote>
<p><img src="https://images.velog.io/images/joshua_s/post/0b7f1137-a4a3-448a-9dca-24290363e470/image.png" alt=""></p>
<p>설치가 완료 되었다.</p>
<h3 id="docker-엔진-제거">Docker 엔진 제거</h3>
<p>Docker 엔진 cli 및 containerd 패키지를 제거한다.</p>
<blockquote>
<p>sudo apt-get purge docker-ce docker-ce-cli containerd.io</p>
</blockquote>
<p>호스트의 이미지, 컨테이너, 볼륨 또는 사용자 지정 구성 파일은 자동으로 제거되지 않습니다. 모든 이미지, 컨테이너 및 볼륨을 삭제하려면 다음의 코드를 입력해야한다.</p>
<pre><code>sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd</code></pre><h3 id="수고하셨습니다">수고하셨습니다.</h3>
<blockquote>
<p><a href="https://docs.docker.com/engine/install/ubuntu/">https://docs.docker.com/engine/install/ubuntu/</a>
도커 docs에 나와있는 우분투에 설치하는 방법으로 진행하였다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Grafana를 활용하여 EC2 메모리 모니터링]]></title>
            <link>https://velog.io/@joshua_s/Grafana%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%98%EC%97%AC-EC2-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EB%AA%A8%EB%8B%88%ED%84%B0%EB%A7%81</link>
            <guid>https://velog.io/@joshua_s/Grafana%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%98%EC%97%AC-EC2-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EB%AA%A8%EB%8B%88%ED%84%B0%EB%A7%81</guid>
            <pubDate>Thu, 17 Mar 2022 04:16:49 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><a href="https://velog.io/@joshua_s/CloudWatch-Agent%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC-EC2-%EB%AA%A8%EB%8B%88%ED%84%B0%EB%A7%812">https://velog.io/@joshua_s/CloudWatch-Agent를-사용하여-EC2-모니터링2</a></p>
</blockquote>
<p>위 내용과 이어지는 내용입니다.
참고사항 : 필자는 amazon linux2를 사용중 입니다.</p>
<h3 id="1-db설정">1. DB설정</h3>
<p>mysql을 설치한 후 DB생성, 권한부여를 한다.</p>
<pre><code>sudo yum update -y 
sudo yum install -y mariadb-server 
sudo systemctl enable mariadb 
sudo systemctl start mariadb 
sudo mysql_secure_installation
mysql -u root -p
CREATE DATABASE grafana CHARACTER SET UTF8 COLLATE UTF8_BIN;
CREATE USER &#39;grafana&#39;@&#39;%&#39; IDENTIFIED BY &#39;password&#39;;
GRANT ALL PRIVILEGES ON grafana.* TO &#39;grafana&#39;@&#39;%&#39;;
quit;</code></pre><p>CREATE USER 코드에서 password는 자신이 적으면 됩니다.
필자는 test용도로 password로 입력했습니다.
<img src="https://images.velog.io/images/joshua_s/post/11384179-abc3-4cea-bcd0-2280880fe290/image.png" alt=""></p>
<h3 id="2-grafana설치-및-설정">2. Grafana설치 및 설정</h3>
<p>대상 EC2인스턴스에 ssh로 연결한다. 
<img src="https://images.velog.io/images/joshua_s/post/a6a3bdde-6153-47fc-8911-e3922b247e4a/image.png" alt="">
ec2 업데이트를 하고 그라파나 다운로드 할 위치를 알 수 있도록 YUM저장소를 추가한다.</p>
<pre><code>sudo yum update -y
sudo vi /etc/yum.repos.d/grafana.repo</code></pre><p>grafana.repo의 설정은 다음과 같다.</p>
<pre><code>[grafana]
name=grafana
baseurl=https://packages.grafana.com/oss/rpm
repo_gpgcheck=1
enabled=1
gpgcheck=1
gpgkey=https://packages.grafana.com/gpg.key
sslverify=1
sslcacert=/etc/pki/tls/certs/ca-bundle.crt</code></pre><p>그라파나를 설치한다.</p>
<pre><code>sudo yum repolist
sudo yum install -y grafana</code></pre><p>새 설정을 로드하고 그라파나 서버를 시작, 부팅시 자동적으로 시작될 수 있도록 설정한다.</p>
<pre><code>sudo systemctl daemon-reload
sudo systemctl start grafana-server
sudo systemctl status grafana-server
sudo systemctl enable grafana-server.service</code></pre><p>그라파나 구성파일 grafana.ini을 편집한다.
<code>vi /etc/grafana/grafana.ini</code></p>
<p>데이터 베이스와 세션을 다음과 같이 구성한다. </p>
<pre><code>[database]
type = mysql
host = 127.0.0.1:3306
name = grafana
user = grafana
password = your-password
[session]
provider = mysql
provider_config = `grafana:your-password@tcp(127.0.0.1:3306)/grafana`</code></pre><p><img src="https://images.velog.io/images/joshua_s/post/05766636-e2d1-480c-98c0-930b4383d905/image.png" alt="">
그라파나 서비스를 시작한다.
<code>sudo servic grafana-server start</code>
<img src="https://images.velog.io/images/joshua_s/post/c825d93b-4ade-4f62-82cf-8d508b3b6c15/image.png" alt=""></p>
<h3 id="3-인바운드-룰-추가">3. 인바운드 룰 추가</h3>
<p>해당 EC2의 보안그룹으로 이동한 후에 인바운드룰에 tcp 3000번을 추가한다. <img src="https://images.velog.io/images/joshua_s/post/c050323e-e6e7-4a12-a9a5-1c25f702d642/image.png" alt=""></p>
<h3 id="4-그라파나-접속후-설정">4. 그라파나 접속후 설정</h3>
<p>해당 EC2의 공인 IP:3000으로 접속한다.
초기 아이디와 비밀번호는 admin/admin이다.
<img src="https://images.velog.io/images/joshua_s/post/5c385bd7-678d-4eb2-bcfb-67c7c0258bda/image.png" alt=""></p>
<p>Configuration - Data Sources - add data source로 이동한다.
<img src="https://images.velog.io/images/joshua_s/post/31cc0995-2913-42ce-b5ee-b101ad89667c/image.png" alt=""></p>
<p>cloudwatch를 검색한 후 추가한다.
<img src="https://images.velog.io/images/joshua_s/post/184fa36b-5f40-44ed-b41c-3868ae6392af/image.png" alt=""></p>
<p>Authentication Provider - Access &amp; secret key로 변경 후 액세스 키, 시크릿 엑세스키, 기본 지역, 사용자 지정 메트릭스(필자는 test로 지정했다)를 설정한다.
<img src="https://images.velog.io/images/joshua_s/post/08c8e5f9-5baf-4480-a7cd-1b1179688261/image.png" alt=""></p>
<p>이제 저장 및 테스트를 진행하면 설정이 완료된다.
<img src="https://images.velog.io/images/joshua_s/post/753da170-935f-44c3-8797-2a6aea71d35f/image.png" alt=""></p>
<p>대시보드를 구성하고 빈 패널을 추가한다.
<img src="https://images.velog.io/images/joshua_s/post/64720c17-fa81-47e5-b97b-1b94f37b7062/image.png" alt="">
<img src="https://images.velog.io/images/joshua_s/post/5816a706-e1d0-40f8-851b-ec3e738b27df/image.png" alt=""></p>
<p>쿼리의 세부 정보를 채운다.
1- Query Mode — CloudWatch 지표
2- Region — 메트릭스의 위치 (제 경우에는 ap-northeast-2)
3- Namespace — 사용자의 네임 스페이스 (필자는 test)
4- Metric Name: 출력하기 원하는 메트릭스의 이름
5- Stats: 평균
6- Dimensions: 아래 사진과 같이 설정
<img src="https://images.velog.io/images/joshua_s/post/117ebb70-79d7-4bcc-9cb4-3cfea5801446/image.png" alt="">
<img src="https://images.velog.io/images/joshua_s/post/9544ec08-6cf2-4091-b3b6-ae13d8e5fd34/image.png" alt="">
<img src="https://images.velog.io/images/joshua_s/post/c66b2b45-d165-4753-a5ef-a1492f2d3d72/image.png" alt=""></p>
<p>이제 적용을 누르면 완료된 화면을 볼 수 있다.
<img src="https://images.velog.io/images/joshua_s/post/1511fe4f-a2db-4682-98c4-87cce6087ff5/image.png" alt=""></p>
<p>그래프 모양을 변경하여 보기 편한 방식으로 설정하여 진행하면 됩니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CloudWatch Agent를 사용하여 EC2 모니터링(2)]]></title>
            <link>https://velog.io/@joshua_s/CloudWatch-Agent%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC-EC2-%EB%AA%A8%EB%8B%88%ED%84%B0%EB%A7%812</link>
            <guid>https://velog.io/@joshua_s/CloudWatch-Agent%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC-EC2-%EB%AA%A8%EB%8B%88%ED%84%B0%EB%A7%812</guid>
            <pubDate>Wed, 16 Mar 2022 05:00:38 GMT</pubDate>
            <description><![CDATA[<h3 id="1-ec2-iam-설정등등">1. EC2 IAM 설정등등</h3>
<blockquote>
<p><a href="https://velog.io/@joshua_s/CloudWatch-Agent%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC-EC2-%EB%AA%A8%EB%8B%88%ED%84%B0%EB%A7%81">https://velog.io/@joshua_s/CloudWatch-Agent를-사용하여-EC2-모니터링</a></p>
</blockquote>
<p>위 링크에서 4번까지는 동일하게 진행하면 된다.</p>
<h3 id="2-파라미터-스토어">2. 파라미터 스토어</h3>
<p>Systems Manger -&gt; 애플리케이션 관리 -&gt; 파라미터 스토어 -&gt; 파라미터 생성
<img src="https://images.velog.io/images/joshua_s/post/ad3e5f81-b9b4-4dbe-8b87-c6eff75aec12/image.png" alt="">
<img src="https://images.velog.io/images/joshua_s/post/f6ff924a-9a31-4cfe-a097-c2e4ab6bdd60/image.png" alt=""></p>
<p>파라미터 이름 설정, 필자는 test로 진행하였다.
<img src="https://images.velog.io/images/joshua_s/post/0e4eec4d-3ec4-4653-8cf0-56ca7fdf1368/image.png" alt="">
값에 지정하는 내용이 중요한데 필자는 메모리 사용량과 disk 사용량을 지정하여 진행하였다. 또한 namespace설정으로 cloudwatch 지표에 나오는 이름도 변경이 가능하다. </p>
<pre><code>{
    &quot;agent&quot;: {
        &quot;metrics_collection_interval&quot;: 60,
        &quot;run_as_user&quot;: &quot;cwagent&quot;
    },
    &quot;metrics&quot;: {
        &quot;metrics_collected&quot;: {
            &quot;disk&quot;: {
                &quot;measurement&quot;: [
                    {
                    &quot;name&quot;: &quot;disk_used_percent&quot;,
                    &quot;rename&quot;: &quot;DiskSpaceUtilization&quot;,
                    &quot;unit&quot;: &quot;Percent&quot;
                    }
                ],
                &quot;metrics_collection_interval&quot;: 60,
                &quot;resources&quot;: [
                    &quot;*&quot;
                ]
            },
            &quot;mem&quot;: {
                &quot;measurement&quot;: [
                    {
                        &quot;name&quot;: &quot;mem_used_percent&quot;,
                        &quot;rename&quot;: &quot;MemoryUtilization&quot;,
                        &quot;unit&quot;: &quot;Percent&quot;
                    }
                ],
                &quot;metrics_collection_interval&quot;: 60
            }
        },
        &quot;namespace&quot;: &quot;test&quot;
    }
}</code></pre><p>필자는 위와 같이 적용을 하였다. 자세한 사항은 AWS 공식문서를 참고하기 바란다. <a href="https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-Agent-Configuration-File-Details.html">https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-Agent-Configuration-File-Details.html</a>
<img src="https://images.velog.io/images/joshua_s/post/c9d1b08e-7a43-43d7-a3b6-6673aa83c2fe/image.png" alt="">
값에 내용을 입력한 후 파라미터 생성을 클릭하면 완료가 된다.</p>
<h3 id="3-파라미터-스토어에-등록한-명령-실행">3. 파라미터 스토어에 등록한 명령 실행</h3>
<p>Systems Manger -&gt; 노드관리 -&gt; 명령실행으로 이동하여 명령실행을 누른 후 명령 문서를 지정한다. 명령문서는 AmazonCloudWatch-ManageAgent이다. 
<img src="https://images.velog.io/images/joshua_s/post/84118163-98f4-430f-88be-fc73f6468055/image.png" alt="">
이후 명령 파라미터에 Optional Configuration Location에 아까전에 파라미터 스토어에 등록한 파라미터 이름을 입력하면 된다. 필자의 경우 test이다.<img src="https://images.velog.io/images/joshua_s/post/71ce752b-42d1-44c1-a3c7-a2017fe3881d/image.png" alt="">
이후 수동으로 인스턴스 선택, IAM Role을 적용한 인스턴스를 클릭한다. <img src="https://images.velog.io/images/joshua_s/post/da69781c-d6c9-4336-8ce3-1bc3126e72e4/image.png" alt="">
이후 실행을 누르면 명령이 실행된다.</p>
<h3 id="4-cloudwatch-지표확인">4. CloudWatch 지표확인</h3>
<p>몇분이 지나면 CloudWatch에 지표가 등록이 되는데 이 내용을 확인하면 된다.<img src="https://images.velog.io/images/joshua_s/post/fcaaf86e-faa4-47b1-9645-b4d1e5e7d85d/image.png" alt=""></p>
<h3 id="목적">목적</h3>
<p>이 내용을 하는 목적은 ec2는 기본적으로 모니터링이 가능하지만 메모리를 모니터링 할 수 없다. 따라서 이를 적용함으로써 메모리도 모니터링이 가능하도록 만들 수 있다. 또한 이를 발전시키면 그라파나와 같은 모니터링 오픈소스에 적용하여 이용할 수 있다. 이후에 이 내용을 가지고 진행하도록 하겠다.</p>
]]></description>
        </item>
    </channel>
</rss>