728x90
반응형

이 게시물에서는 AWS LightsailGitHub Actions를 이용하여 간단한 CI/CD 파이프라인을 구축하는 방법을 설명합니다. 이를 통해 코드가 masterstaging 브랜치에 푸시될 때마다 Lightsail 서버에 자동으로 배포되도록 설정합니다.

1. .github/workflows/deploy.yml 작성

먼저 GitHub Actions에서 사용할 워크플로우 파일을 작성합니다. 이 파일은 GitHub 리포지토리의 .github/workflows/ 경로에 생성하며, 배포 작업을 정의하는 데 사용됩니다.

name: Deploy to Server

on:
  push:
    branches:
      - master

jobs:
  deploy
    runs-on: ubuntu-latest

    steps:
      - name: Check out the code
        uses: actions/checkout@v2

      - name: Set up SSH
        uses: webfactory/ssh-agent@v0.5.3
        with:
          ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}

      - name: Deploy to Master Server
        env:
          LIGHTSAIL_HOST: ${{ secrets.LIGHTSAIL_HOST }}
          LIGHTSAIL_USER: ${{ secrets.LIGHTSAIL_USER }}
        run: |
          ssh -o StrictHostKeyChecking=no $LIGHTSAIL_USER@$LIGHTSAIL_HOST << 'EOF'
            cd ~/<project-name>
            git pull origin master
            yarn install
            yarn build
            yarn start
          EOF

위의 YAML 파일은 masterstaging 브랜치에 각각 배포 작업을 정의하고 있습니다.

2. GitHub Actions 키 생성 및 Lightsail에 등록

  • GitHub Actions에서 사용할 SSH 키를 생성합니다. 다음 명령어를 사용해 키를 생성합니다.

    ssh-keygen -t rsa -b 4096 -C "github-actions@yourproject"
  • 생성된 공개 키(id_rsa.pub)를 Lightsail 서버~/.ssh/authorized_keys에 추가합니다.

    echo [public key string] >> ~/.ssh/authorized_keys
  • 개인 키(id_rsa)는 GitHub Repository의 Secrets에 등록합니다. (SSH_PRIVATE_KEY 등으로 지정)

3. Lightsail에 폴더 생성 및 Git 초기화

  • Lightsail 서버에 배포할 프로젝트 폴더를 생성하고 Git 초기화를 합니다.

    mkdir ~/<project-name>
    cd ~/<project-name>
    git init

4. Lightsail에서 Deploy Key 생성 및 GitHub에 등록

  • Deploy Key를 생성하여 GitHub에 등록합니다.

    ssh-keygen -t rsa -b 4096 -C "deploy-key@yourproject"
  • 생성된 공개 키 (deploy-key.pub)를 GitHub의 Deploy Keys로 등록합니다. 이 키는 리포지토리에 대한 읽기 권한을 가집니다.

5. 프로젝트 최초 Pull 및 known_hosts 등록

  • Lightsail 서버의 프로젝트 폴더에서 GitHub에서 리포지토리를 최초로 클론하고, known_hosts 파일에 GitHub 서버 정보를 등록합니다.

    git remote add origin git@github.com:username/repository.git
    git pull origin master

6. Yarn 및 PM2 설치

  • Lightsail 서버에서 YarnPM2를 설치하여 Node.js 애플리케이션을 배포합니다.

    yarn global add pm2
  • pm2 설정 파일 ecosystem.config.json 예제 입니다.

{
  "apps": [
    {
      "name": "club-match-api",
      "script": "./dist/main.js",
      "ignore_watch": ["node_modules", "src"],
      "instances": 1,
      "autorestart": true,
      "watch": false,
      "max_memory_restart": "1G",
      "env": {
        "PORT": 3000,
        "NODE_ENV": "development"
      },
    }
  ]
}
  • yarn start 명령어 (in package.json)
"start": "pm2 restart ecosystem.config.json",

7. GitHub Actions를 통한 자동 배포

  • GitHub Actions에서 작성한 deploy.yml 파일에 따라, 서버로 연결하여 최신 코드를 가져오고 yarn을 통해 빌드하고 PM2로 프로덕션 서버를 시작합니다.

마무리

이와 같이 설정하면 GitHub의 master 브랜치에 코드가 푸시될 때마다 자동으로 Lightsail 서버에 배포됩니다. 이를 통해 코드 업데이트를 간편하게 적용하고, CI/CD를 통해 지속적으로 서비스를 개선할 수 있습니다.

반응형
728x90
반응형

이번 포스팅에서는 최종적으로 EKS에 애플리케이션을 배포해보겠습니다. EBS CSI Driver 설치, ECR Repository 생성, Docker 이미지 빌드 및 배포, k8s 적용 및 구동 확인 순서로 진행하겠습니다.

1. EBS CSI Driver 설치

이 명령어들은 AWS EBS CSI 드라이버를 Kubernetes 클러스터에 설치하고 설정하는 데 사용됩니다. 각 명령어는 Helm을 사용하여 드라이버를 설치하고 설정하며, Kubernetes의 스토리지 관리를 위한 프로비저닝 작업을 수행할 수 있게 해줍니다. Helm 차트는 Kubernetes 애플리케이션을 배포하고 관리할 수 있는 패키지

  • Helm 차트 리포지토리를 추가:
helm repo add aws-ebs-csi-driver https://kubernetes-sigs.github.io/aws-ebs-csi-driver
  • Helm 차트 업데이트:
helm repo update
  • Helm을 사용하여 aws-ebs-csi-driver라는 이름으로 AWS EBS CSI 드라이버를 설치:
  • --namespace kube-system은 Kubernetes의 특정 네임스페이스(kube-system)에 드라이버를 설치하도록 지정하는 옵션입니다.
helm install aws-ebs-csi-driver aws-ebs-csi-driver/aws-ebs-csi-driver --namespace kube-system

2. ECR Repository 생성

ECR(Amazon Elastic Container Registry)은 Docker 이미지를 저장하고 관리할 수 있는 AWS의 서비스입니다. 이 포스팅 시리즈에서는 ECR을 사용하겠습니다. 다른 저장소(Docker hub, GCR, GHCR, ACR 등)를 사용하셔도 무방합니다.

  • Repository 이름을 정하고 생성합니다.

3. Docker 이미지 빌드 및 배포

aws ecr get-login-password --region <region> | docker login --username AWS --password-stdin <your-aws-account-id>.dkr.ecr.<region>.amazonaws.com
  • Docker 이미지 빌드하기:
docker build --platform linux/amd64 -t nestjs-mariadb-eks-boilerplate:latest .
  • AWS ECR을 위한 Docker 이미지 태그:
docker tag nestjs-mariadb-eks-boilerplate:latest <your-aws-account-id>.dkr.ecr.<region>.amazonaws.com/<repository-name>:latest
  • Docker 이미지 push:
docker push <your-aws-account-id>.dkr.ecr.<region>.amazonaws.com/<repository-name>:latest

4. k8s 적용 및 구동 확인 명령어

  • k8s manifests 적용:
kubectl apply -f k8s/
  • Pod 상태 확인:
kubectl get pods
kubectl describe pod <pod-name>
  • 클러스터 상태 확인:
aws eks describe-cluster --name <cluster-name>
  • 노드 상태 확인:
kubectl get nodes
  • PVC 상태 확인:
kubectl get pvc
  • 네임스페이스 kube-system에 속한 서비스 상태 확인:
kubectl get pods -n kube-system
  • 로그 확인:
kubectl logs <pod-name>
반응형
728x90
반응형

이번 포스팅에서는 EKS 클러스터에서 실제 애플리케이션이 실행되는 노드 그룹을 생성합니다.

1. 노드 그룹 구성

노드 그룹에 관한 기본적인 내용을 정의합니다. 노드 그룹 이름과 IAM 역할을 지정해줍니다. IAM이 없다면 IAM 콘솔에서 역할 생성 버튼으로 이동하여 기본 설정 그대로 진행해서 노드 IAM을 생성해줍시다. 저의 경우 아래의 정책으로 생성하였습니다.

  • AmazonEBSCSIDriverPolicy
  • AmazonEC2ContainerRegistryReadOnly (기본)
  • AmazonEC2FullAccess
  • AmazonEKS_CNI_Policy (기본)
  • AmazonEKSWorkerNodePolicy (기본)

  • 시작 템플릿 (Launch Template):
    • 설명: 시작 템플릿은 EC2 인스턴스를 생성할 때 사용할 사전 정의된 설정 집합입니다. 여기에는 AMI ID, 인스턴스 유형, 키 페어, 보안 그룹, 사용자 데이터, 블록 스토리지 구성 등이 포함됩니다.
    • 이점: 시작 템플릿을 사용하면 일관된 인스턴스 구성을 보장하고, 복잡한 설정을 쉽게 반복해서 적용할 수 있습니다. 특히, 다양한 사용자 지정 설정을 포함시킬 때 유용합니다.
    • 사용: EKS 노드 그룹을 구성할 때, 특정 요구사항에 맞춰 미리 준비된 시작 템플릿을 선택하여 EC2 인스턴스를 일관되게 생성할 수 있습니다.
  • 레이블 (Label):
    • 설명: 레이블은 쿠버네티스 노드에 할당되는 키-값 쌍으로, 클러스터 내에서 특정 노드를 식별하거나, 특정 워크로드를 특정 노드에서 실행되도록 지정하는 데 사용됩니다.
    • 이점: 레이블을 사용하면 파드가 특정 조건을 만족하는 노드에만 배치되도록 스케줄링할 수 있습니다. 예를 들어, env=production과 같은 레이블을 사용해 프로덕션 환경용 워크로드를 프로덕션 노드에서만 실행되도록 설정할 수 있습니다.
    • 사용: 노드 그룹 구성 단계에서 노드에 레이블을 지정하면, 클러스터 내에서 파드를 배포할 때 이 레이블을 기준으로 노드를 선택할 수 있습니다.
  • 테인트 (Taint):
    • 설명: 테인트는 특정 파드가 해당 노드에 스케줄링되지 않도록 제한하는 메커니즘입니다. 테인트는 노드에 설정되며, 파드는 특정 톨러레이션(Toleration)이 설정된 경우에만 그 노드에 스케줄링될 수 있습니다.
    • 이점: 테인트를 사용하면 특정 노드를 특정 유형의 파드에만 사용할 수 있게 제어할 수 있습니다. 예를 들어, 중요한 작업만 처리하는 노드를 설정할 때 유용합니다.
    • 사용: 노드 그룹 구성 시 테인트를 설정하여, 의도하지 않은 파드가 해당 노드에서 실행되지 않도록 제어할 수 있습니다. 이로써 특정 파드의 성능 또는 보안을 보장할 수 있습니다.

요약:

  • 시작 템플릿은 노드 그룹의 인스턴스 구성을 일관되게 관리하는 도구입니다.
  • 레이블은 파드를 특정 노드에 배치하기 위해 노드에 할당하는 메타데이터입니다.
  • 테인트는 특정 파드만 해당 노드에 배치되도록 제한하는 설정입니다.

2. 컴퓨팅 및 조정 구성 설정

EKS 노드 그룹의 컴퓨팅 리소스를 구성하고, 클러스터의 확장성과 자동 조정(오토스케일링) 관련 설정을 정의합니다.

  • On-Demand 용량 (On-Demand Capacity):
    • 설명: On-Demand 인스턴스는 사용자가 필요할 때 EC2 인스턴스를 생성하고, 사용한 만큼 시간당 비용을 지불하는 방식입니다.
    • 이점: On-Demand 인스턴스는 가용성이 높고, 언제든지 생성할 수 있어 안정적인 서비스 운영을 보장합니다. 인스턴스가 필요할 때 언제든지 추가하거나 제거할 수 있으며, 예측 가능한 비용 구조를 제공합니다.
    • 사용 사례: 예측 가능하고 안정적인 컴퓨팅 리소스가 필요한 워크로드에 적합합니다. 예를 들어, 프로덕션 환경이나 긴급히 확장이 필요한 서비스에 유용합니다.
  • Spot 용량 (Spot Capacity):
    • 설명: Spot 인스턴스는 AWS에서 미사용 EC2 인스턴스를 경매 방식으로 저렴하게 구매할 수 있는 옵션입니다. Spot 인스턴스는 On-Demand 인스턴스 대비 최대 90% 저렴할 수 있습니다.
    • 이점: 비용 절감 효과가 크며, 대규모의 일시적인 컴퓨팅 파워가 필요한 워크로드에 매우 유용합니다. 가격 변동에 따라 리소스를 동적으로 확장하거나 축소할 수 있습니다.
    • 주의사항: Spot 인스턴스는 AWS에서 더 이상 인스턴스를 제공할 수 없게 되면(예: 수요 증가로 인해) 언제든지 회수될 수 있습니다. 따라서, 회수에 대비한 내구성 있는 애플리케이션 설계가 필요합니다.
    • 사용 사례: 비즈니스 크리티컬하지 않거나, 일괄 처리 작업, 데이터 분석, 테스트 및 개발 환경 등에서 사용하기 적합합니다. 비용 절감이 중요한 경우에 활용됩니다.

만약 기본적으로 실행하려는 노드가 2개라면, 원하는 크기를 2, 최소 크기를 2, 최대 크기를 3 이상으로 설정하고, 최대 사용 불가 노드 수를 1로 설정합니다.

이렇게 설정하면 AWS는 롤링 업데이트(Rolling Update) 방식을 사용하여 노드 그룹을 업데이트합니다:

  • 노드 추가: 업데이트를 시작할 때, AWS는 클러스터의 가용성을 유지하기 위해 최대 노드 수에 따라 새로운 노드를 추가합니다. 이로 인해 노드 수가 일시적으로 증가합니다.
  • 파드 재배치: 기존 노드 중 하나를 업데이트할 때, 그 노드에서 실행 중이던 파드(애플리케이션)를 새로 추가된 노드로 자동으로 이동시킵니다.
  • 노드 업데이트: 파드가 다른 노드로 이동한 후, 기존 노드가 업데이트됩니다.
  • 노드 제거: 업데이트가 완료되면 클러스터는 다시 원하는 크기(2개)에 맞게 노드 수를 조정하여, 추가된 노드를 제거합니다.

롤링 업데이트 방식은 클러스터의 노드들을 순차적으로 업데이트하는 방식으로, 업데이트 도중에도 서비스의 가용성을 유지할 수 있습니다. 각 노드를 하나씩 업데이트하면서, 파드를 다른 노드로 재배치하여 다운타임을 최소화합니다. 이 과정은 자동으로 이루어지며, 클러스터의 가용성을 유지하면서 노드 그룹을 효율적으로 업데이트할 수 있도록 도와줍니다.

3. 네트워킹 지정

노드에 대한 원격 액세스 허용은 유연한 운영을 위해 허용으로 설정합니다.

4. 검토 및 생성

앞서 설정한 내용들을 다시 확인 후 생성합니다.

5. CLI에서 노드 그룹 생성 확인

노드 목록 확인:

kubectl get nodes

노드 상세 정보 확인:

kubectl describe node <node-name>

Pod 배포 확인:

  • 노드 그룹이 정상적으로 작동하는지 확인하기 위해, 기본 네임스페이스나 kube-system 네임스페이스에서 실행 중인 파드들을 확인해 볼 수 있습니다.
kubectl get pods -o wide --all-namespaces

AWS CLI로 노드 그룹 상태 확인:

aws eks describe-nodegroup --cluster-name <cluster-name> --nodegroup-name <node-group-name>
반응형
728x90
반응형

AWS EKS 클러스터를 설정하고 애플리케이션을 배포하는 과정에서 필수적인 단계들을 정리했습니다. 전체 과정은 클러스터 생성부터 노드그룹 설정, ECR에 이미지 푸시, 그리고 EBS 스토리지 자동 프로비저닝까지의 과정을 다룹니다. 이번 포스팅에서는 EKS 클러스터 생성 과정을 다룹니다.

1. 클러스터 구성

EKS 클러스터는 애플리케이션을 배포하고 관리할 수 있는 Kubernetes 클러스터를 AWS에서 제공하는 서비스입니다. 클러스터를 생성하는 과정은 아래와 같습니다.

 

  • 클러스터 이름을 입력합니다. 저의 경우 <product-name>-staging 으로 하였습니다.
  • 클러스터의 Controll Plane이 AWS 리소스를 관리할 수 있도록 적절한 IAM 을 지정합니다. 없다면 오른쪽 하단의 IAM 콘솔에서 역할 생성 버튼으로 새로운 IAM 역할을 생성합니다.

 

그 외에는 기본설정을 그대로 두고 다음으로 진행합니다.

2. 네트워킹 지정

EKS 클러스터 생성 시 네트워킹 지정 단계는 클러스터가 사용하는 네트워크 환경을 설정하는 중요한 과정입니다. 이 단계에서는 클러스터의 VPC, 서브넷, 및 관련 네트워크 설정을 지정하게 됩니다

 

 

  • VPC (Virtual Private Cloud) 선택:
    • EKS 클러스터는 Amazon VPC에서 실행되며, 이 단계에서 클러스터가 사용할 VPC를 지정해야 합니다.
    • 기존 VPC를 선택하거나, 필요에 따라 새로운 VPC를 생성할 수 있습니다.
  • 서브넷 지정:
    • VPC 내에서 클러스터가 사용할 서브넷을 선택합니다.
    • 일반적으로 퍼블릭 서브넷과 프라이빗 서브넷을 모두 선택하여 워커 노드와 로드밸런서가 적절히 분리되도록 설정합니다.
    • 최소 두 개 이상의 서브넷을 선택해야 하며, 고가용성을 위해 서로 다른 가용 영역(AZ)에 있는 서브넷을 지정하는 것이 좋습니다.
  • 클러스터 보안 그룹(Security Groups):
    • EKS 클러스터와 관련된 네트워크 트래픽을 제어하는 보안 그룹을 지정합니다.
    • 기본적으로 EKS는 클러스터 생성 시 필요에 따라 보안 그룹을 자동으로 생성하지만, 필요한 경우 사용자가 직접 지정할 수도 있습니다.
  • 클러스터 엔드포인트 액세스:
    • 클러스터가 퍼블릭 서브넷을 사용하여 인터넷에 접근할지, 혹은 프라이빗 서브넷을 통해 NAT 게이트웨이를 통해 간접적으로 접근할지를 설정합니다.
    • 워커 노드가 외부 네트워크와 통신해야 한다면, 이 설정이 중요합니다.

3. 관찰성 구성

쿠버네티스 클러스터에서 관찰성(Observability) 구성을 통해 클러스터의 상태와 성능을 모니터링하고 문제를 진단할 수 있습니다.

  • Prometheus는 시스템의 전체적인 메트릭 정보(예: CPU 사용량, 메모리 사용량, 요청 처리 시간 등)를 모니터링하는 역할을 합니다.
  • 컨트롤 플레인 로깅(Control Plane Logging)은 쿠버네티스 클러스터의 컨트롤 플레인에서 발생하는 이벤트와 활동을 로깅하는 기능입니다. 컨트롤 플레인은 쿠버네티스 클러스터의 핵심 관리 컴포넌트들(kube-apiserver, etcd, kube-scheduler, kube-controller-manager 등)을 포함하며, 이들의 동작을 로깅하는 것은 클러스터의 운영 및 문제 해결에 매우 중요합니다.
  • 위 두 항목은 운영에 있어서 중요하지만 이 문서에서는 가이드의 목적이기에 활성화하지 않았습니다.

4. 추가 기능 선택

클러스터에 기본적으로 제공되는 기능 외에 추가적으로 활성화할 수 있는 기능들을 선택하는 단계입니다. 추가 기능이라고 되어있긴 하지만 사실상 필수인 기능들이 기본적으로 선택되어 있습니다.

  • CoreDNS:
    • 기능: CoreDNS는 클러스터 내에서 서비스 이름을 IP 주소로 해석하는 DNS 서버입니다.
    • 필수 이유: 클러스터에서 파드 간의 네트워크 통신이나 서비스 검색이 제대로 동작하려면 DNS 해석이 필수적입니다. CoreDNS가 이를 담당하므로, 일반적으로 필수적으로 선택해야 합니다.
  • kube-proxy:
    • 기능: kube-proxy는 쿠버네티스 클러스터 내에서 네트워크 프록시 역할을 하며, 각 노드의 네트워크 규칙을 관리하여 파드 간의 트래픽을 라우팅합니다.
    • 필수 이유: 클러스터 내에서 파드 간의 네트워크 통신이 가능하도록 하는 핵심 컴포넌트로, 이 기능이 없으면 클러스터의 네트워킹이 제대로 동작하지 않습니다.
  • Amazon VPC CNI:
    • 기능: Amazon VPC CNI 플러그인은 EKS에서 파드에 AWS VPC 내의 IP 주소를 할당하여 네트워킹을 처리합니다.
    • 필수 이유: 이 플러그인을 통해 클러스터의 파드들이 VPC 네트워크 상에서 원활하게 통신할 수 있게 됩니다. AWS 네트워킹과 밀접하게 연동되는 필수적인 기능입니다.
  • Amazon EKS Pod Identity 에이전트:
    • 기능: 이 에이전트는 Kubernetes의 서비스 계정과 AWS IAM 역할 간의 매핑을 관리하여, 파드가 IAM 역할을 사용해 AWS 리소스에 접근할 수 있도록 합니다 (IRSA 기능).
    • 필수 이유: 특정 워크로드가 AWS 리소스에 접근할 때 보안 및 관리 편의를 제공하기 위해 필요한 기능입니다. 특히, IAM 역할을 통해 안전하게 AWS 리소스에 접근할 수 있게 합니다.

5. 선택한 추가 기능 설정 구성

  • 앞서 선택한 추가 기능에 대한 설정을 구성합니다. 기본 설정을 그대로 사용하겠습니다.

6. 검토 및 생성

앞의 단계들에서 설정한 내용들을 검토 후 생성합니다.

반응형
728x90
반응형

Kubernetes와 Minikube를 사용하면서 자주 사용하는 명령어들과 유용한 옵션들을 정리한 문서입니다.


Minikube 명령어

Minikube 시작 및 중지

  • 클러스터 시작
  minikube start  
Minikube 클러스터를 시작합니다. 기본적으로 Minikube VM을 생성하고 Kubernetes를 설정합니다.
  • 클러스터 중지
  minikube stop

Minikube 상태 확인

  • 클러스터 상태 확인
  minikube status

Minikube IP 확인

  • 클러스터 IP 확인
  minikube ip

Minikube 대시보드

  • 대시보드 실행
  minikube dashboard
Minikube의 Kubernetes 대시보드를 실행합니다. 브라우저에서 Kubernetes 클러스터를 시각적으로 관리할 수 있습니다.

Minikube 서비스 접근

  • 서비스 URL 확인 및 브라우저 열기
  minikube service [SERVICE_NAME]
  1. 서비스 URL 생성: 지정된 서비스에 대한 접근 URL을 생성합니다.

  2. 브라우저 열기: 기본 브라우저에서 해당 URL을 자동으로 엽니다.

  3. 포트 포워딩 설정: 필요한 경우, 로컬 호스트와 Minikube 클러스터 간의 포트 포워딩을 설정하여 서비스에 접근할 수 있도록 합니다.

    이 명령어는 주로 개발과 테스트 용도로 사용되며, 로컬 환경에서 서비스를 빠르게 확인하고 접근하는 데 유용합니다.

Minikube 터널링

  • 터널링 시작
  minikube tunnel
  1. LoadBalancer 지원: LoadBalancer 타입의 서비스를 클러스터 외부에 노출합니다.

  2. External IP 할당: 서비스에 외부 IP를 할당하여, 클러스터 외부에서 접근할 수 있도록 합니다.

  3. 권한 요구: sudo 권한을 요구할 수 있습니다, 특히 80, 443과 같은 특권 포트를 사용할 때.

    LoadBalancer 타입의 서비스를 외부에 노출하기 위한 터널링을 시작합니다.

특징 minikube service minikube tunnel
목적 특정 서비스를 빠르게 브라우저에서 접근 LoadBalancer 서비스를 클러스터 외부에 노출
브라우저 자동 열기 아니오
포트 포워딩 필요에 따라 설정 예, 외부 IP 할당을 통해
권한 요구 아니오 예, sudo 권한 요구 가능
주요 사용 사례 개발 및 테스트 용도로 서비스 빠르게 확인 로컬 환경에서 LoadBalancer 서비스 테스트

사용 시나리오

  • minikube service: 특정 서비스를 브라우저에서 빠르게 접근하고 테스트하고자 할 때 사용합니다. 개발 및 테스트 환경에서 유용합니다.
  • minikube tunnel: LoadBalancer 서비스를 외부에 노출시켜야 할 때 사용합니다. 클라우드 환경에서의 배포를 로컬에서 테스트할 때 유용합니다.

Minikube 클러스터 삭제

  • 클러스터 삭제
  minikube delete

Kubectl 명령어

Kubectl 설정

  • 현재 컨텍스트 확인
  kubectl config current-context
  • 컨텍스트 목록 확인
  kubectl config get-contexts
  • 컨텍스트 변경
  kubectl config use-context [CONTEXT_NAME]

리소스 조회

  • 모든 네임스페이스의 모든 리소스 조회
  kubectl get all --all-namespaces
  • 특정 리소스 조회
  kubectl get [RESOURCE_TYPE]
특정 리소스 타입을 조회합니다. 예를 들어, Pod, Service, Deployment 등이 있습니다.
  kubectl get pods
  kubectl get services
  kubectl get deployments
  • 리소스 상세 조회
  kubectl describe [RESOURCE_TYPE] [RESOURCE_NAME]
특정 리소스의 상세 정보를 조회합니다.
  kubectl describe pod [POD_NAME]

리소스 관리

  • 리소스 생성

    kubectl apply -f [FILE_NAME].yaml

    YAML 파일을 사용하여 리소스를 생성하거나 업데이트합니다.

로그 및 디버깅

  • Pod 로그 조회
  kubectl logs [POD_NAME]
-f 옵션을 사용하면 실시간 로그를 조회합니다.

Pod 접근

  • Pod에 명령어 실행
  kubectl exec -it [POD_NAME] -- [COMMAND]
특정 Pod에서 명령어를 실행합니다. 예를 들어, 셸을 실행할 수 있습니다.
  kubectl exec -it [POD_NAME] -- /bin/bash

네임스페이스 관리

  • 네임스페이스 목록 조회
  kubectl get namespaces
  • 네임스페이스 생성
  kubectl create namespace [NAMESPACE_NAME]
  • 네임스페이스 삭제
  kubectl delete namespace [NAMESPACE_NAME]

자주 사용하는 옵션

  • -n [NAMESPACE]: 특정 네임스페이스에서 명령어를 실행합니다.
  kubectl get pods -n [NAMESPACE]
  • -o wide: 출력 형식을 넓게 설정하여 더 많은 정보를 표시합니다.
  kubectl get pods -o wide
  • --all-namespaces: 모든 네임스페이스에서 리소스를 조회합니다.
  kubectl get all --all-namespaces
  • -f [FILE_NAME]: YAML 파일을 사용하여 리소스를 관리합니다.
  kubectl apply -f [FILE_NAME].yaml
  • -l [LABEL_SELECTOR]: 특정 라벨을 가진 리소스를 조회합니다.
  kubectl get pods -l [LABEL_SELECTOR]
반응형
728x90
반응형

Kubernetes 오브젝트

Kubernetes는 다양한 오브젝트를 사용하여 애플리케이션을 배포하고 관리합니다. 주요 오브젝트에는 Pod, Service, Deployment, ConfigMap, Secret, PersistentVolumeClaim(PVC) 등이 있습니다.

1. Pod

Pod는 Kubernetes에서 가장 작은 배포 단위로, 하나 이상의 컨테이너를 포함합니다.

2. Service

Service는 Pod에 대한 네트워크 접근을 추상화하여, 로드 밸런싱과 서비스 디스커버리를 제공합니다. 주요 타입에는 ClusterIP, NodePort, LoadBalancer가 있습니다.

  • ClusterIP: 기본 서비스 타입으로, 클러스터 내부에서만 접근할 수 있는 가상의 IP 주소를 할당받습니다.
  • NodePort: 클러스터 외부에서 각 노드의 특정 포트를 통해 접근할 수 있습니다.
  • LoadBalancer: 클라우드 제공자의 로드 밸런서를 통해 외부에서 접근할 수 있습니다.

3. Deployment

Deployment는 Pod와 ReplicaSet을 관리하여, 애플리케이션의 배포와 업데이트를 간소화합니다.

4. ConfigMap

ConfigMap은 애플리케이션 설정을 외부에서 관리할 수 있도록 도와줍니다.

5. Secret

Secret은 민감한 정보를 안전하게 저장하고 전달하는 데 사용됩니다.

6. PersistentVolumeClaim (PVC)

PVC는 스토리지 리소스를 요청하는 오브젝트로, Pod가 데이터를 영구적으로 저장할 수 있도록 합니다.


Minikube를 사용한 로컬 예제

이 섹션에서는 Minikube를 사용하여 로컬 환경에서 Kubernetes 오브젝트를 실행하는 예시 코드를 제공합니다.

1. 환경 설정

먼저, Minikube를 시작합니다:

minikube start

Minikube 클러스터의 Docker 데몬을 사용하도록 환경 변수를 설정합니다:

eval $(minikube -p minikube docker-env)

2. Docker 이미지 빌드

프로젝트 디렉토리에서 Docker 이미지를 빌드합니다:

docker build -t my-nestjs-image:latest .

3. 예시 코드

Dockerfile
## [1. Build Stage]
# Use an official Node.js runtime as a parent image
FROM node:20.9.0 AS builder

# Set the working directory
WORKDIR /app

# Bundle app source
COPY package*.json ./
COPY yarn.lock ./

# Install Node.js dependencies
RUN yarn install

# Copy all files from the current directory to the working directory (/app)
COPY . .

# Build application
RUN yarn build

## [2. Runtime Stage]
# Use an official Node.js as runtime image
FROM node:20.9.0

# Set the working directory
WORKDIR /app

# Copy the application build from the previous stage
COPY --from=builder /app .

# Expose application's port
EXPOSE ${PORT}

# Start application
CMD yarn start:prod
app-env-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-env-configmap
data:
  NODE_ENV: "local" # .env 파일의 내용에 따라 추가
app-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nest-minikube-study
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-nest-minikube-study
  template:
    metadata:
      labels:
        app: my-nest-minikube-study
    spec:
      containers:
      - name: my-nest-minikube-study
        image: my-nestjs-image:latest
        imagePullPolicy: Never
        env:
        - name: NODE_ENV
            valueFrom:
                configMapKeyRef:
                    name: app-env-configmap
                    key: NODE_ENV
        ports:
        - containerPort: 3000
  • apiVersion: 오브젝트의 API 버전을 정의합니다. apps/v1은 Deployment 오브젝트의 버전입니다.
  • kind: 생성할 Kubernetes 리소스의 종류를 정의합니다. 여기서는 Deployment입니다.
  • metadata: 오브젝트의 메타데이터를 정의합니다. name 필드에는 오브젝트의 이름이 지정됩니다.
  • spec: 오브젝트의 스펙(구체적인 설정)을 정의합니다.
    • replicas: 실행할 Pod의 복제본 수를 정의합니다.
    • selector: 이 Deployment가 관리하는 Pod를 선택하는 라벨입니다.
    • template: Pod 템플릿을 정의합니다.
      • metadata.labels: 생성된 Pod에 적용할 라벨을 정의합니다.
      • spec.containers: 컨테이너 목록을 정의합니다.
        • name: 컨테이너의 이름입니다.
        • image: 컨테이너 이미지입니다.
        • imagePullPolicy: 이미지를 외부에서 가져오지 않도록 설정합니다.
        • ports: 컨테이너에서 사용하는 포트를 정의합니다.
app-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: my-nest-minikube-study-service
spec:
  selector:
    app: my-nest-minikube-study
  ports:
    - protocol: TCP
      port: 80
      targetPort: 3000
  type: LoadBalancer
  • apiVersion: 오브젝트의 API 버전을 정의합니다. v1은 Service 오브젝트의 버전입니다.
  • kind: 생성할 Kubernetes 리소스의 종류를 정의합니다. 여기서는 Service입니다.
  • metadata: 오브젝트의 메타데이터를 정의합니다. name 필드에는 오브젝트의 이름이 지정됩니다.
  • spec: 오브젝트의 스펙(구체적인 설정)을 정의합니다.
    • selector: 이 Service가 연결할 Pod를 선택하는 라벨입니다.
    • ports: 서비스 포트 설정을 정의합니다.
      • protocol: 사용할 프로토콜입니다. 여기서는 TCP입니다.
      • port: 서비스의 포트입니다.
      • targetPort: Pod의 포트입니다.
    • type: 서비스 타입을 정의합니다. 여기서는 LoadBalancer입니다.
mariadb-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mariadb-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mariadb
  template:
    metadata:
      labels:
        app: mariadb
    spec:
      containers:
      - name: mariadb
        image: mariadb
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mariadb-secret
              key: password
        - name: MYSQL_DATABASE
          value: mydb
        - name: MYSQL_USER
          value: user
        - name: MYSQL_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mariadb-secret
              key: password
        ports:
        - containerPort: 3306
        volumeMounts:
        - mountPath: /var/lib/mysql
          name: mariadb-storage
      volumes:
      - name: mariadb-storage
        persistentVolumeClaim:
          claimName: mariadb-pvc
  • apiVersion: 오브젝트의 API 버전을 정의합니다. apps/v1은 Deployment 오브젝트의 버전입니다.
  • kind: 생성할 Kubernetes 리소스의 종류를 정의합니다. 여기서는 Deployment입니다.
  • metadata: 오브젝트의 메타데이터를 정의합니다. name 필드에는 오브젝트의 이름이 지정됩니다.
  • spec: 오브젝트의 스펙(구체적인 설정)을 정의합니다.
    • replicas: 실행할 Pod의 복제본 수를 정의합니다.
    • selector: 이 Deployment가 관리하는 Pod를 선택하는 라벨입니다.
    • template: Pod 템플릿을 정의합니다.
      • metadata.labels: 생성된 Pod에 적용할 라벨을 정의합니다.
      • spec.containers: 컨테이너 목록을 정의합니다.
        • name: 컨테이너의 이름입니다.
        • image: 컨테이너 이미지입니다.
        • env: 환경 변수를 정의합니다.
          • name: 환경 변수 이름입니다.
          • valueFrom: Secret에서 값을 가져옵니다.
        • ports: 컨테이너에서 사용하는 포트를 정의합니다.
        • volumeMounts: 컨테이너에 볼륨을 마운트합니다.
          • mountPath: 컨테이너 내의 마운트 경로입니다.
          • name: 볼륨의 이름입니다.
      • volumes: Pod에 사용할 볼륨을 정의합니다.
        • name: 볼륨의 이름입니다.
        • persistentVolumeClaim: PVC를 참조합니다.
          • claimName: 참조할 PVC의 이름입니다.
mariadb-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: mariadb-service
spec:
  selector:
    app: mariadb
  ports:
    - protocol: TCP
      port: 3306
  type: ClusterIP
  • apiVersion: 오브젝트의 API 버전을 정의합니다. v1은 Service 오브젝트의 버전입니다.
  • kind: 생성할 Kubernetes 리소스의 종류를 정의합니다. 여기서는 Service입니다.
  • metadata: 오브젝트의 메타데이터를 정의합니다. name 필드에는 오브젝트의 이름이 지정됩니다.
  • spec: 오브젝트의 스펙(구체적인 설정)을 정의합니다.
    • selector: 이 Service가 연결할 Pod를 선택하는 라벨입니다.
    • ports: 서비스 포트 설정을 정의합니다.
      • protocol: 사용할 프로토콜입니다. 여기서는 TCP입니다.
      • port: 서비스의 포트입니다.
    • type: 서비스 타입을 정의합니다. 여기서는 ClusterIP입니다.
mariadb-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: mariadb-secret
type: Opaque
data:
  password: cGFzc3dvcmQ=  # "password"의 base64 인코딩 값
  • apiVersion: 오브젝트의 API 버전을 정의합니다. v1은 Secret 오브젝트의 버전입니다.
  • kind: 생성할 Kubernetes 리소스의 종류를 정의합니다. 여기서는 Secret입니다.
  • metadata: 오브젝트의 메타데이터를 정의합니다. name 필드에는 오브젝트의 이름이 지정됩니다.
  • type: Secret의 타입을 정의합니다. Opaque는 일반적인 키-값 쌍을 저장할 때 사용됩니다.
  • data: Secret에 저장할 데이터를 정의합니다. Base64로 인코딩된 값을 사용합니다.
mariadb-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mariadb-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  • apiVersion: 오브젝트의 API 버전을 정의합니다. v1은 PVC 오브젝트의 버전입니다.
  • kind: 생성할 Kubernetes 리소스의 종류를 정의합니다. 여기서는 PersistentVolumeClaim입니다.
  • metadata: 오브젝트의 메타데이터를 정의합니다. name 필드에는 오브젝트의 이름이 지정됩니다.
  • spec: 오브젝트의 스펙(구체적인 설정)을 정의합니다.
    • accessModes: 접근 모드를 정의합니다. ReadWriteOnce는 하나의 노드에서 읽고 쓸 수 있음을 의미합니다.
    • resources.requests.storage: 요청하는 스토리지의 크기입니다. 이 예제에서는 1GiB를 요청합니다.

4. 매니페스트 파일 적용

다음 명령어를 사용하여 매니페스트 파일을 적용합니다:

kubectl apply -f app-env-configmap.yaml
kubectl apply -f mariadb-secret.yaml
kubectl apply -f mariadb-pvc.yaml
kubectl apply -f mariadb-deployment.yaml
kubectl apply -f mariadb-service.yaml
kubectl apply -f app-service.yaml
kubectl apply -f app-deployment.yaml

5. 애플리케이션 상태확인

kubectl get pods
kubectl get services

6. Minikube 터널링

minikube tunnel 명령어를 사용하여 LoadBalancer 서비스를 외부에 노출합니다:

minikube tunnel

7. 서비스 접근

브라우저 또는 curl 명령어를 사용하여 서비스에 접근합니다:

curl http://127.0.0.1:80

구조 다이어그램

Minikube 내에서 Kubernetes 클러스터가 어떻게 구성되고 동작하는지를 시각적으로 이해하기 위해, 아래와 같은 구조 다이어그램을 참고할 수 있습니다.

+------------------+
| Docker Desktop   |
|  +--------------+|
|  | Minikube     ||
|  |  (Container) ||
|  +--------------+|
|      (K8s Cluster)|
|  +------------------+  +------------------+|
|  | Pod               |  | Pod               ||
|  |  - Container      |  |  - Container      ||
|  +------------------+  +------------------+|
|  +------------------+  +------------------+|
|  | Service           |  | Service           ||
|  +------------------+  +------------------+|
+------------------+
반응형
728x90
반응형

Kubernetes는 컨테이너화된 애플리케이션의 배포, 확장 및 운영을 자동화하는 오픈 소스 플랫폼입니다. 이 문서에서는 Kubernetes의 기본 구성 요소와 이들 간의 상호작용을 설명합니다.


기본 구성 요소

kubectl

kubectl은 Kubernetes 클러스터와 상호작용하기 위한 커맨드라인 툴입니다. 이를 통해 클러스터의 리소스를 관리하고, 애플리케이션을 배포하고, 클러스터 상태를 모니터링할 수 있습니다.

  • 리소스 관리: 생성, 업데이트, 삭제 등.
  • 클러스터 정보 조회: 리소스 목록 조회, 상세 정보 조회 등.
  • 디버깅 및 로깅: 로그 조회, 실시간 로그 스트리밍, 명령어 실행 등.
  • 애플리케이션 배포: 디플로이먼트 생성, 업데이트 등.

Master Node

마스터 노드는 클러스터를 제어하고 관리하는 역할을 합니다. 주요 구성 요소는 다음과 같습니다:

  • API Server (API 서버): 클러스터의 주요 API 엔드포인트로, kubectl과 같은 클라이언트가 클러스터와 상호작용할 수 있게 합니다.
  • Controller Manager (컨트롤러 관리자): 클러스터의 상태를 모니터링하고, 설정된 상태를 유지하도록 다양한 컨트롤러를 실행합니다.
  • Scheduler (스케줄러): 새로운 Pod를 적절한 워커 노드에 배치합니다.
  • ETCD: 클러스터의 상태와 구성 데이터를 저장하는 분산 키-값 저장소입니다.

Worker Node

워커 노드는 실제 애플리케이션이 실행되는 노드입니다. 주요 구성 요소는 다음과 같습니다:

  • Kubelet: 각 워커 노드에서 실행되는 에이전트로, Pod와 컨테이너를 관리합니다.
  • Container Runtime (컨테이너 런타임): 컨테이너를 실행하는 소프트웨어입니다. 예: Docker, containerd.
  • Kube-Proxy: 네트워크 규칙을 관리하고, 클러스터 내의 네트워크 통신을 처리합니다.

Master Node와 Worker Node의 상호작용

Kubernetes 클러스터에서 마스터 노드와 워커 노드는 협력하여 애플리케이션을 배포하고 관리합니다.

  1. kubectl과 API Server 상호작용:

    • 사용자는 kubectl을 통해 클러스터에 명령을 보냅니다.
    • kubectl은 API 서버와 상호작용하여 요청을 전달합니다.
  2. API 서버와 마스터 노드 구성 요소 상호작용:

    • API Server는 요청을 받아 ETCD에 저장하거나 Controller Manager와 Scheduler에게 전달합니다.
    • Controller Manager는 클러스터 상태를 모니터링하고, 설정된 상태로 유지하기 위해 작업을 수행합니다.
    • Scheduler는 새로운 Pod를 생성할 위치를 결정합니다.
  3. 마스터 노드와 워커 노드 상호작용:

    • 마스터 노드의 구성 요소들은 워커 노드의 Kubelet과 상호작용하여 Pod를 생성, 업데이트 및 삭제합니다.
    • Kube-Proxy는 네트워크 트래픽을 관리하고, 클러스터 내의 서비스 간 통신을 처리합니다.

요약

  • kubectl: Kubernetes 클러스터와 상호작용하는 커맨드라인 툴.
  • Master Node: 클러스터 제어 및 관리.
    • API Server: 클러스터의 주요 API 엔드포인트.
    • Controller Manager: 클러스터 상태 모니터링 및 유지.
    • Scheduler: 새로운 Pod 배치.
    • ETCD: 클러스터 상태 저장소.
  • Worker Node: 애플리케이션 실행.
    • Kubelet: Pod 및 컨테이너 관리.
    • Container Runtime: 컨테이너 실행.
    • Kube-Proxy: 네트워크 통신 관리.

Kubernetes의 구성 요소들은 상호작용하여 클러스터를 효율적으로 관리하고 애플리케이션을 안정적으로 배포할 수 있게 합니다. kubectl을 사용하여 클러스터와 상호작용하며, 마스터 노드와 워커 노드는 협력하여 클러스터의 상태를 유지하고, 애플리케이션을 실행합니다.

반응형
728x90
반응형

Docker 이미지

Docker 이미지는 컨테이너를 실행하기 위한 가상 실행 환경의 템플릿입니다. 이미지는 불변의 실행 환경을 제공하며, 애플리케이션과 그 종속성, 설정 파일 등을 포함합니다. 이미지는 여러 레이어로 구성되며, 각 레이어는 Dockerfile의 명령어에 의해 생성됩니다.

Docker 이미지의 주요 개념

  • 레이어 (Layer):
    • Docker 이미지는 여러 레이어로 구성됩니다. 각 레이어는 이미지의 특정 상태를 나타내며, Dockerfile의 각 명령어가 새로운 레이어를 생성합니다.
    • 레이어는 캐시되어서, 동일한 레이어를 여러 이미지에서 재사용할 수 있습니다.
  • Dockerfile:
    • Docker 이미지를 정의하는 파일입니다. Dockerfile에는 이미지 생성 과정에서 실행될 명령어들이 포함되어 있습니다.
  • 레지스트리 (Registry):
    • 이미지를 저장하고 배포하는 중앙 저장소입니다. Docker Hub, AWS ECR, Google Container Registry 등이 있습니다.
    • 이미지를 레지스트리에 푸시(push)하고, 다른 환경에서 풀(pull)하여 사용할 수 있습니다.

Docker 컨테이너

Docker 컨테이너는 이미지를 기반으로 생성된 실행 가능한 인스턴스입니다. 컨테이너는 이미지의 실행 가능한 인스턴스로, 애플리케이션을 실제로 실행하는 환경입니다. 컨테이너는 호스트 운영 체제의 커널을 공유하면서도, 독립된 파일 시스템, 네트워크 인터페이스, 프로세스 공간을 가집니다.

Docker 컨테이너와 가상 머신의 차이점

  • 아키텍처:
    • 가상 머신 (VM):
      • 하이퍼바이저(VMware, Hyper-V, KVM 등)를 사용하여 물리적 하드웨어 위에 다수의 독립적인 가상 운영 체제를 실행합니다.
      • 각 가상 머신은 자체 운영 체제(OS), 가상 하드웨어(CPU, 메모리, 네트워크 인터페이스 등)를 포함합니다.
    • 컨테이너:
      • 컨테이너 엔진(Docker, containerd, CRI-O 등)을 사용하여 호스트 운영 체제의 커널을 공유합니다.
      • 각 컨테이너는 애플리케이션과 그 종속성만 포함하며, 독립된 파일 시스템, 네트워크, 프로세스 공간을 가집니다.
  • 자원 사용:
    • 가상 머신:
      • 각 가상 머신은 전체 운영 체제를 실행하므로 더 많은 자원을 소비합니다.
      • 하이퍼바이저를 통해 가상 하드웨어를 에뮬레이션하므로, 자원 오버헤드가 발생합니다.
    • 컨테이너:
      • 컨테이너는 호스트 운영 체제의 커널을 공유하므로, 훨씬 적은 자원을 사용합니다.
      • 경량 프로세스 격리 방식으로 동작하므로, 오버헤드가 거의 없습니다.
  • 속도 및 효율성:
    • 가상 머신:
      • 부팅 시간이 길며, 운영 체제 부팅 과정이 필요합니다.
      • 이미지 크기가 크고, 디스크 I/O가 더 많이 필요합니다.
    • 컨테이너:
      • 빠른 시작과 종료가 가능하며, 애플리케이션 실행 속도가 빠릅니다.
      • 이미지 크기가 작고, 디스크 I/O가 적습니다.

Docker 볼륨

Docker 볼륨은 컨테이너와 호스트 시스템 간의 데이터 공유를 위해 사용되는 디렉토리입니다. 볼륨을 사용하면 컨테이너가 중지되거나 제거되더라도 데이터가 유지되며, 여러 컨테이너 간에 데이터를 공유할 수 있습니다.

Docker 볼륨의 주요 개념

  • 지속성 (Persistence):
    • 컨테이너는 기본적으로 비휘발성 저장소를 사용하지 않으므로, 컨테이너가 중지되거나 제거되면 그 안의 데이터도 사라집니다.
    • 볼륨을 사용하면 컨테이너가 중지되거나 제거되더라도 데이터가 유지됩니다.
  • 데이터 공유:
    • 여러 컨테이너가 동일한 볼륨을 마운트하면, 데이터가 컨테이너 간에 공유될 수 있습니다.
  • 데이터 분리:
    • 볼륨을 사용하여 애플리케이션의 데이터와 애플리케이션 자체를 분리할 수 있습니다. 이는 데이터 백업, 복구, 이관 등을 더 쉽게 합니다.

로컬 개발 환경과 스테이징 및 프로덕션 환경에서의 설정

  • 로컬 개발 환경:
    • 바인드 마운트를 사용하여 호스트 시스템의 소스 코드가 컨테이너에 실시간으로 반영되도록 설정합니다.
    • 빠른 피드백 루프와 개발 생산성을 높이는 데 중점을 둡니다.

Docker Compose 예시 (로컬 개발 환경):

version: '3.1'

services:
  app:
    image: node:14
    working_dir: /app
    volumes:
      - .:/app
      - /app/node_modules
    ports:
      - '3000:3000'
    command: npm run dev
    environment:
      - NODE_ENV=development
      - DATABASE_HOST=db
      - DATABASE_USER=user
      - DATABASE_PASSWORD=password
      - DATABASE_NAME=mydb
    depends_on:
      - db

  db:
    image: mariadb
    environment:
      MYSQL_ROOT_PASSWORD: example
      MYSQL_DATABASE: mydb
      MYSQL_USER: user
      MYSQL_PASSWORD: password
    volumes:
      - db-data:/var/lib/mysql

volumes:
  db-data:
  • 스테이징 및 프로덕션 환경:
    • 바인드 마운트를 사용하지 않고, 빌드된 이미지를 사용하여 컨테이너를 실행합니다.
    • 코드 변경 사항이 철저하게 테스트되고 검증된 후에 배포합니다.
    • 데이터베이스 데이터의 지속성을 보장하기 위해 데이터 볼륨을 사용합니다.

Docker Compose 예시 (스테이징/프로덕션 환경):

version: '3.1'

services:
  app:
    image: my-node-app:latest
    ports:
      - '3000:3000'
    environment:
      - NODE_ENV=production
      - DATABASE_HOST=db
      - DATABASE_USER=user
      - DATABASE_PASSWORD=password
      - DATABASE_NAME=mydb
    depends_on:
      - db

  db:
    image: mariadb
    environment:
      MYSQL_ROOT_PASSWORD: example
      MYSQL_DATABASE: mydb
      MYSQL_USER: user
      MYSQL_PASSWORD: password
    volumes:
      - db-data:/var/lib/mysql

volumes:
  db-data:

요약

  • Docker 이미지는 컨테이너를 실행하기 위한 불변의 템플릿입니다.
  • Docker 컨테이너는 이미지를 기반으로 생성된 실행 가능한 인스턴스로, 애플리케이션을 실제로 실행하는 환경입니다.
  • Docker 볼륨은 컨테이너와 호스트 시스템 간의 데이터 공유를 위해 사용되며, 데이터의 지속성을 보장합니다.
  • 로컬 개발 환경에서는 바인드 마운트를 사용하여 실시간 코드 반영이 가능하도록 설정하고, 스테이징 및 프로덕션 환경에서는 안정성과 일관성을 위해 빌드된 이미지를 사용하여 배포합니다.
반응형
728x90
반응형

구조

  • Github Webhook -> Jenkins Server (Lightsail) -> Test Server (Lightsail)
  • Jenkins Server에서 파이프라인 스크립트를 통해 SSH Agent를 이용하여 Test Server에 SSH 접속

과정

1. Jenkins 설치

  • Lightsail에 Jenkins 설치 (자바 설치 필요)

2. Github Webhook 설정

  • Payload URL: http://<Jenkins-URL>/github-webhook/

3. SSH 키 생성 및 복사

  • Jenkins Server에서 Test Server로 SSH 접속을 위한 키 발급
ssh-keygen
  • 발급된 공개키를 Test Server로 복사
echo <public_key_string> >> ~/.ssh/authorized_keys

4. Jenkins 설정

4.1. Credential 등록

  • Github Access Token: Jenkins의 Username with password 유형으로 등록
  • SSH 키: SSH Username with private key 유형으로 Jenkins Server에서 발급한 개인키 등록
  • .env 파일: Secret file 유형으로 등록

4.2. 플러그인 설치

  • SSH Agent 플러그인 설치

4.3. 파이프라인 등록

  • Github 프로젝트

    • Project URL 등록
    • GitHub hook trigger for GITScm polling 체크
  • 파이프라인

    • Pipeline script from SCM
    • SCM: Git
    • Repository URL: Git 프로젝트 주소 등록
    • Credentials: 등록한 Github Access Token 선택
    • Script path: Jenkinsfile (실행 스크립트가 작성된 Jenkins 파일)
pipeline {
    agent any

    stages {
        stage('Running commands') {
            steps {
                script {
                    sshagent(['<test-server-ssh-private-key>']) {
                        withCredentials([file(credentialsId: 'env-file', variable: 'ENV_FILE')]) {
                            sh "scp -o StrictHostKeyChecking=no $ENV_FILE bitnami@<test-server-url>:workspace/<project-name>/.env"
                            sh "ssh -o StrictHostKeyChecking=no bitnami@<test-server-url> 'cd workspace/<project-name> && git pull && sudo docker compose up -d --build'"
                        }
                    }
                }
            }
        }
    }
}
반응형