본문 바로가기

(4)

SpringBoot Application + ECS 배포

ECS를 선택한 이유 최근에 물리치료 스터디를 진행하고있다. 이 스터디를 원활하게 도와줄 수 있는 서비스를 만들고 싶어져서 개인적인 토이프로젝트를 진행하고있다. 엄밀한 의미의 CI / CD는 아니지만 코드가 main 브랜치에 푸쉬됐을 때, 자동으로 배포되는 환경은 만들어두고 싶어 서버 인프라를 구성하게 되었다. 고전적인 방식으로 EC2 인스턴스를 띄워두고 배포 쉘 스크립트를 작성하여 깃 웹훅을 통해서 메인 브랜치에 푸쉬가 발생했을 때, 쉘 스크립트가 실행되도록 트리거를 방식도 있고 또 Jenkins나 CodeDeploy 툴을 이용한 방식도 있지만 전자처럼 직접 EC2 인스턴스로 접속하여 리눅스환경에서의 작업(리눅스도 공부를 하기는 해야할거 같은데 언제하지... 🫠)을 하는 것이 싫었고 후자는 배포를 위한..

쿠버네티스 소개

컨테이너 원래부터 리눅스는 프로세스별로 자원을 격리해서 사용하는 cgroup과 특정 디렉터리로 권한을 제한하는 chroot 등으로 격리 환경을 구축할 수 있다. 여기에 디스크의 파일 변경 사항을 레이어 형태로 저장하는 파일 시스템을 합해 컨테이너라는 개념이 탄생했다. 그리고 도커는 앞에서 언급한 기능들을 모아서 컨테이너를 손쉽게 사용할 수 있도록 한 것으로 주목받았다. 기존에는 가상화나 클라우드 컴퓨팅을 설명할 때는 가상 머신(VM)을 많이 언급했었지만 컨테이너가 널리 알려지면서 컨테이너에 많은 관심이 쏠리기 시작했다. 컨테이너에는 호스트 운영체제 위에 도커가 있고 바로 애플리케이션이 위치하는반면 가상 머신은 하이퍼바이저 위에 가상 머신마다 게스트 운영체제가 있고 그 위에 앱이 위치한다. 즉, 컨테이너가..

리눅스 환경구성 기초

이번 포스팅은 Tacademy의 리눅스 환경구성 기초 강의를 수강하고 요약한 내용입니다. 리눅스 소개 👋🏻 우리에게 컴퓨터는 ? 리눅스와 관련된 키워드 터미널, 쉘스크립트 등 외계언어들이 가득하다! 리눅스, 편안하게 쓸 수 없을까? 리눅스는 왜 어려운걸까? GUI vs CLI 이 두가지로 볼 수 있다. GUI (Graphical User Interface) 한 화면에 많은 정보를 담을 수 있다 눈으로 보고 대상을 선택 가능하다 But, 만약 한 화면에서 다양한 일을 하게된다면...? CLI (Command-Line Interface) 눈에 보이는 거라곤 고작 터미널 하나 뭔가 하고 싶지만 몰라서 할 수가 없다 But, 까막눈이면 몰라도, 숙련자에겐..? 리눅스를 잘 다루는 것? 리눅스 환경에서 파일, 프..

[MySQL] - JOIN의 종류와 사용예제

http://blog.naver.com/PostView.nhn?blogId=pjok1122&logNo=221542171040&parentCategoryNo=&categoryNo=21&viewDate=&isShowPopularPosts=true&from=search [MySQL] Inner Join(내부 조인)과 Outer Join(외부 조인) 조인에는 생각보다 다양한 조인이 존재합니다. 그 중에서 제일 대표적인 두 가지만 살펴보도록 합시다.​1.... blog.naver.com http://www.sqlprogram.com/Basics/sql-join.aspx 테이블 JOIN - SQL 프로그래밍 배우기 (Learn SQL Programming) 테이블 조인 (JOIN) SELECT문은 하나 이상의 테이..

Infra

SpringBoot Application + ECS 배포

728x90

ECS를 선택한 이유

최근에 물리치료 스터디를 진행하고있다. 이 스터디를 원활하게 도와줄 수 있는 서비스를 만들고 싶어져서 개인적인 토이프로젝트를 진행하고있다. 엄밀한 의미의 CI / CD는 아니지만 코드가 main 브랜치에 푸쉬됐을 때, 자동으로 배포되는 환경은 만들어두고 싶어 서버 인프라를 구성하게 되었다. 

고전적인 방식으로 EC2 인스턴스를 띄워두고  배포 쉘 스크립트를 작성하여 깃 웹훅을 통해서 메인 브랜치에 푸쉬가 발생했을 때, 쉘 스크립트가 실행되도록 트리거를 방식도 있고 또 Jenkins나 CodeDeploy 툴을 이용한 방식도 있지만 전자처럼 직접 EC2 인스턴스로 접속하여 리눅스환경에서의 작업(리눅스도 공부를 하기는 해야할거 같은데 언제하지... 🫠)을 하는 것이 싫었고 후자는 배포를 위한 별도의 인스턴스를 띄어야하기 때문에 결국 별도의 비용💸이 들어가기 때문에 이 또한 꺼려졌다. 

먼저 Jenkins, CodeDeploy와 같은 툴은 github에서 제공하는 Github Action을 통해서 충분히 대체할 수 있기에 큰 고민없이 Github Action을 사용하기로 결정했다. 그리고 전자의 문제점도 문제지만 한번 인프라 구성을 한 이후에는 별도로 인프라 관리를 할 필요가 없도록 구성하고 싶은 마음이 컸기에 이런 니즈를 충족해줄 서비스를 찾게되었고 AWS의 BeanstalkECS 서비스 이 두 가지로 범위가 좁혀지게되었다. 나는 조금 더 친숙하기도했고, 또한 오케스트레이션을 해주는 ECS가 마음에 들어서 ECS를 선택하게 되었다. 

 

1. SpringBoot Application 준비

예제 코드 저장소: https://github.com/Rok93/physical-therapy

 

GitHub - Rok93/physical-therapy: 물리치료 스터디 관리 API

물리치료 스터디 관리 API. Contribute to Rok93/physical-therapy development by creating an account on GitHub.

github.com

스프링부트 프로젝트에서는 미리 준비해두면 좋을만한 포인트가 있는데, 

1. 배포할 서비스 모듈의 jar 파일 이름을 직접 지정하기

tasks.bootJar {
    enabled = true
    archiveFileName = "app-api.jar"
    mainClass.set("physicaltherapy.AppApiSpringApplicationKt")
}

2. health check API 만들기

@RestController
class HealthCheckController }{

@GetMapping("/health")
fun checkHealth(): String = "OK"

}

 

이정도면 SpringBoot Application은 준비가 끝난 듯하다.
(당연히 로컬에서 실행했을 때, 정상적으로 서버가 뜨는지 정도는 확인해야한다)

2. Github Action 배포 스크립트 작성

배포할 코드 저장소에 들어가면 상단에 Actions 탭이 있고 이 탭을 누르게되면, (아직 만든 workflow가 없다면) 지금과 같은 창이 나온다!
나는 ECS에 배포할 것이기 때문에 ECS라고 검색하여 나오는 confiure를 클릭해준다.

클릭해보면 기본적으로 ECS 배포를 할 때, 필요한 스크립트 틀을 제공해준다. 
나는 (Kotlin) SpringBoot 애플리케이션을 빌드해야하니 Java 설치가 필요하니 JDK 설치 잡을 추가해준다.

템플릿의 상단에 보면 아래와 같은 환경변수가 존재하는데, 이 값들을 추후 생성하는 ECR, ECS, ECS Service, ECS Task 등을 생성하여 이 값을 채워주면 된다. (주석으로 순서를 매겨놨는데 나중에 AWS에서 서비스를 각각 만들고나서 한번에 매칭해줘도 되고, 아니면 지금 미리 이름만 정해두는 것도 괜찮을 것 같다)

env:
  AWS_REGION: ap-northeast-2                  # 서울 REGION 
  ECR_REPOSITORY: MY_ECR_REPOSITORY           # 1.AWS ECR 이름 
  ECS_SERVICE: MY_ECS_SERVICE                 # 5.AWS의 ECS 클러스터의 SERVICE 이름 
  ECS_CLUSTER: MY_ECS_CLUSTER                 # 4.AWS ECS 클러스터 이름
  ECS_TASK_DEFINITION: MY_ECS_TASK_DEFINITION # 3.정의한 ECS TASK 이름
                                               # file, e.g. .aws/task-definition.json
  CONTAINER_NAME: MY_CONTAINER_NAME           # 2.ECR의 컨테이너 이름

(3. ECS_TASK_DEFINITION이 조금 헷갈리는데, 이 부분은 주석 내용을 참고해보면, TASK 이름을 정의하는 것이 아니라 Task를 정의한 json 파일명을 넣어야하는 것으로  보인다. 🤔  이 부분에서 조금 삽질을 해서, 나의 경우에는 ECS_TASK 이름으로 TASK의 task-definition.json 파일을 먼저 다운로드한 뒤, 가져와서 직접 넣어주는 방식으로 우회했다. 

대략적인 배포 흐름을 살펴보면(deploy job의 step 순서) 아래와 같다.

1) github action에 체크아웃 -> 2) aws 접근권한 확인 -> 3) ECR 로그인 -> 4) docker image build & ECR에 push
 ->  5) ECS Task에 push한 image로 채우는 작업 -> 6) 새로 정의한 ECS Task 배포 

아마 단일 모듈(모노 모듈?)인 일반적인 애플리케이션이라면 제공해준 템플릿에서 JDK 설치 부분만 추가하면 배포 스크립트가 다 작성된게 아닐까 싶다.  하지만 나의 경우에는 멀티 모듈 프로젝트이다보니 4번 부분에서 일부 내용을 수정했었다.

멀티모듈 프로젝트의 배포스크립트 예제가 궁금하다면 👉  멀티모듈 프로젝트 배포 스크립트 예제

이 정도면 배포 스크립트 작성도 끝이난 듯하다.

3. AWS ECR 생성

AWS 검색창에서 ECR을 검색해서 private 리포지토리로 이동하고, 우측 상단에 리포지토리 생성 버튼을 누른다.

설정을 해준다.
(태그 변경 불가능 기능은 초기 배포설정할 때는 활성화하지 말자... 첫 배포환경 구축할 때는 동일한 태그로 배포할 일이 생각보다 많았었는데, 괜히 이 설정을 ON 해둬서, 다시 풀어줘야했던 귀찮은 상황이있었다)

4. ECS Task 생성

AWS 검색 창에서 ECS Task 로 검색한다.
작업 정의 목록으로 들어간다.

새 태스크 정의 생성을 한다.

설정을 추가해준다. 
Task의 이름을 입력해주고, 태스크의 역할(= 없음) 및 태스크 실행 역할(ecaTaskExecutionRole)을 지정해준다.

ECS Service가 최초 배포시 배포한 태스크가 정상적으로 실행되지 않는다면, 몇번 더 배포를 시도하다가 자연스럽게 Service가 중지된다. (여러번의 삽질끝에 알게됐다. 🫠)

우리는 아직 우리가 만든 스프링 애플리케이션을 도커 이미지로 만들어서 ECR에 푸쉬하지 않았다 그래서 일단 돌아가는 어떤 도커 이미지든지 간에 태스크에 등록해서 ECS Service 생성 시, 이 태스크를 오케스트레이션 할 때, 정상적으로 배포가 완료되도록 해야만 한다. (그래야 ECS Service가 계속해서 유지된다)

ECR에 수동으로 도커 이미지를 빌드&푸시하는 방법은 아래와 같다.
(ECR의 특정 리포지토리로 들어가면 우측 상단에 푸시 명령 보기 버튼을 누르면, 본인 리포지토리에 맞는 명령어를 아래와 같이 알려준다!   하나하나 타이핑하지말고 복붙하자 😆)

5. ECS Cluster 생성

AWS 검색 창에서 ECS를 검색하여 Elastic Container Service 서비스로 접근한다.

클러스터 생성 버튼을 누른다.

설정을 추가해준다. 
클러스터 이름(배포스크립트 환경변수 4번)과 VPC(VPC는 첫번째것만 남겨놨다) 설정을 해준다.
(인프라는 fargate로 설정한다  ⚠️ 요금이 부과된다)

6. ECS Service 생성

주의할점: ECS Service가 계속 유지될 수 있도록 꼭 살려야한다!

위의 내용을 몰라서 삽질을 많이했었다. 
제대로 배포가 되지 않으면 서비스가 자동으로 중단된다. 
꼭 pull 받았을 때, 정상적으로 실행되는 도커 이미지를 태스크에 지정해줘야한다. 

5에서 생성한 ECS Cluster에 들어가면 하단에 서비스 생성을 할 수 있는 버튼이 있다. 눌러주자!

ECS Service 설정을 해준다.

보안 그룹 설정

보안 그룹쪽은 나도 블로그 글들을 참고해보면서, 따라한 부분인데 이 부분은 잘 모르고 설정했다. 
보안쪽은 사실 잘 모르겠어서, 혹시나 이 글을 따라서 배포를 하고 계신분이 계시다면 이 부분은 꼭 의심과 함께 더 알아보고 진행하면 좋을 것 같다. 

AWS 공식문서에서 ECS는 Anywhere가 고급 보안 기능을 갖추고 있다고 하는데.... 위처럼 설정하는게 고급 보안이 되고 있는지는 확실치 않다. 

이제 로드밸런서 설정해줄건데, 로드밸런서를 설정하는 이유는 깃헙 액션의 플로우를 통해서 배포가 일어날 때마다 매번 신규 태스크가 뜨게되는데, 그 때마다 인스턴스의 host 주소가 계속 바뀌는 문제가 있었다. 탄련적 IP를 이용해서 배포되는 IP를 고정시키려고했는데, 공식문서에는 아래와 같이 말하고있다.

고정 IP 주소 또는 탄력적 IP 주소는 Fargate 태스크에 직접 추가할 수 없습니다. Fargate 태스크에서 고정 IP 또는 탄력적 IP를 사용하려면 먼저 Network Load Balancer를 사용하여 Fargate 서비스를 생성해야 합니다. 그런 다음, 태스크의 탄력적 IP 주소를 로드 밸런서에 연결할 수 있습니다.

따라서 로드밸런서를 생성해서 설정할 것이다. 
헌데, 나의 경우에는 ECS Service를 생성하는 창에서 새 로드밸런서 등록을 하니까 오류가 발생했다.
에러로그도 매우 불친절해서 원인을 알 수가 없었다.

결국 로드밸런서를 직접 생성해주고, 기존 로드밸런서를 가지고와서 설정하는 방식으로 우회했다.
AWS 검색창에서 EC2 콘솔로 이동하면 좌측 메뉴에 로드 밸런싱 탭이 있다.

먼저 대상 그룹부터 먼저 생성한다.

이 때, 별 다른 설정은 필요없지만 대상 유형 선택에서 IP 주소를 선택하는 것이 중요하다.

그 이유는 아래와 같다.

⚠️ 중요
서비스 태스크의 정의가 awsvpc 네트워크 모드(Fargate 시작 유형에 필수)를 사용할 경우 대상 유형으로 IP 주소(IP addresses)를 선택해야 합니다. awsvpc 네트워크 모드를 사용하는 태스크는 Amazon EC2 인스턴스가 아닌 탄력적 네트워크 인터페이스와 연결되기 때문입니다.

출처: https://docs.aws.amazon.com/ko_kr/AmazonECS/latest/userguide/create-application-load-balancer.html

참고로 fargate를 사용하면 네트워크 모드가 자동으로 awsvpc로 지정되기 때문에 이 설정이 중요하다.
(설정하지 않으면 서비스 생성 오류가 발생한다)

대상그룹 설정은 끝났고 이어서 좌측 메뉴에서 로드밸런서 탭으로 들어가서 로드 밸런서를 생성한다.

그림상으로는 하나만 픽했지만 최소 2개를 지정해야하니, 적당히 나머지 하나도 지정하면 된다.

포트는 80 으로 그대로 두고, 대상 그룹은 방금전 단계에서 생성했던 대상 그룹을 지정한다.

이렇게 설정이 끝나고 나면, 서비스를 생성한다. 

정상적으로 배포된 상태라면 서비스 상태는 위와 같아야한다.

서비스를 클릭해서 들어간 뒤, 태스크 탭을 눌러보면 현재 배포된 태스크를 확인할 수 있다. 
정상적으로 배포된 상태이고 health check 응답도 잘 떨어졌다면, 태스크 상태는 '정상'으로 나와야한다.

ECS 서비스의 네트워크 탭을 누르면 연결된 로드밸런서의 DNS 주소를 알 수 있다.

로드밸런서 DNS로 health check API를 요청해보니, 응답이 잘 떨어지는 것을 확인했다.

마치며...

인프라는 역시 어렵다. 인프라는 나한테 너무 막연하게 느껴지는 분야다보니, 인프라 초기 설정할 때는 겁이 덜컥 나는 편인데, 이번에 삽질하면서 조금은 친숙해진 듯하다. 다음에 또 인프라 작업할 일 있으면, 시간이 좀 걸려서그렇지 어떻게든 할 수는 있겠다는 자신감도 조금 생겼다. 

728x90

'Infra' 카테고리의 다른 글

쿠버네티스 소개  (0) 2022.12.03
리눅스 환경구성 기초  (0) 2020.10.22
Infra

쿠버네티스 소개

728x90

컨테이너 

원래부터 리눅스는 프로세스별로 자원을 격리해서 사용하는 cgroup과 특정 디렉터리로 권한을 제한하는 chroot 등으로 격리 환경을 구축할 수 있다. 여기에 디스크의 파일 변경 사항을 레이어 형태로 저장하는 파일 시스템을 합해 컨테이너라는 개념이 탄생했다. 

그리고 도커는 앞에서 언급한 기능들을 모아서 컨테이너를 손쉽게 사용할 수 있도록 한 것으로 주목받았다. 

기존에는 가상화나 클라우드 컴퓨팅을 설명할 때는 가상 머신(VM)을 많이 언급했었지만 컨테이너가 널리 알려지면서 컨테이너에 많은 관심이 쏠리기 시작했다. 

왼쪽: 컨테이너 / 오른쪽: 가상머신  구조

컨테이너에는 호스트 운영체제 위에 도커가 있고 바로 애플리케이션이 위치하는반면 가상 머신은 하이퍼바이저 위에 가상 머신마다 게스트 운영체제가 있고 그 위에 앱이 위치한다. 즉, 컨테이너가 구조상 레이어가 더 간단하므로 가상 머신보다 성능을 높이기 쉽다

컨테이너가 등장하기 전에는 호스트에도 개발 환경에 필요한 설정을 똑같이 해야만했다. 이 과정에서 여러 가지 장애 요소가 많이 발생해서 어려움이 있기도 했다. 이런 불편한 점을 컨테이너와 오케스트레이션 시스템을 함께 사용하면 쉽게 해결할 수 있고 또 앱을 배포하고 관리하기가 더 편하고 강력해진다. 

컨테이너 오케스트레이션 시스템 

도커가 컨테이너를 사용하기 편하게 만들면서 애플리케이션 개발 과정 전체에 혁신을 가져왔다. 컨테이너를 이용하면 개발 환경과 운영 환경의 차이 때문에 일어나는 많은 장애를 막을 수 있다. 개발 환경에서 실행했던 컨테이너를 컨테이너 런타임(ex. 도커)만 있다면 실제 서버 어디에서든지 실행할 수 있기 때문이다. 하지만 컨테이너만으로는 실제 상용 서비스를 운영하기에는 부족하다. 이런 부족함을 컨테이너 오케스트레이션 시스템이 채워줄 수 있다. 

일반적으로 실제 상용 서비스를 운영할 때는 서버를 여러대 띄어놓고 사용한다. 그 이유는 서버의 단일 장애점을 방지하여 서버 하나에 장애가 발생해도 그 장애 때문에 전체 서비스에 영향이 가지 않도록하기 위함이다. 이런 상용 서비스 구성에서 컨테이너만 단독으로 사용한다면 컨테이너 이미지를 만들고 여러 대 서버에 컨테이너를 배포하는 전체 과정을 수동으로 제어해야한다. 그리고 장애가 발생하면 해당 서버의 컨테이너를 다른 서버로 옮기는 등의 작업도 직접해야 한다. 

하지만 컨테이너 오케스트레이션  시스템을 사용하면 수동으로 제어하는 부분 모두를 자동화하므로 시스템 운영이 훨씬 수월해진다. 

쿠버네티스의 구조로 보는 컨테이너 오케스트레이션 시스템

컨테이너 오케스트레이션 시스템으로 상용 서비스에 사용할 서버들을 클러스터로 구성하면, 서버 1대든 100대든 컨테이너를 한 번의 명령으로 자동 배포할 수 있다. 그리고 사용 중인 클러스터 일부에 장애가 발생하면 오케스트레이션 시스템은 알아서 장애가 발생한 서버에 있는 컨테이너들을 정상 운영 중인 다른 서버로 옮겨서 실행시킵니다. 장애가 발생한 서버로 향하는 트래픽도 자동으로 중지시키고 새로 옮긴 컨테이너로 보낸다.  

쿠버네티스

쿠버네티스(kubernetes)는 배의 조타수란 그리스 단어에서 유래했다. 
또한 2014년 구글 내부에서 사용하던 컨테이너 오케스트레이션 시스템 보그(borg)를 오픈 소스 소프트웨어로 공개한 것이고 10년 이상 대규모 시스템을 운영해오면서 쌓은 노하우를 녹인 것이기도하다. 쿠버네시트는 k와 s사이의 글자 개수가 8개이므로 k8s라고도 표기한다.

구글은 리눅스 재단과 협업해서 클라우드 네이티브 컴퓨팅 재단(Cloud Native Computing Foundation)을 만들고 쿠버네티스를 기부했다. 그 이후로 쿠버네티스는 커뮤니티의 힘으로 더 많은 성장을 이뤘다. 

AWS에서도 쿠버네티스 관리형 서비스인 EKS(Amazon Elastic Kubernetes Service)를 출시했다. 

쿠버네티스의 특징 

쿠버네티스가 많은 인기를 얻은 이유는 사용하기 간편한 선언적 API, 처음 쿠버네티스를 사용할 때의 손쉬운 접근성, 강력한 커뮤니티 등이 있다. 

선언적 API 

쿠버네티스의 가장 큰 설계 원칙은 API가 '선언적'(declarative)이라는 것이다. 컨테이너가 어떤 상태이길 원하는지만 쿠버네티스에 설정하면 지속해서 컨테이너 상태를 확인한다. 그리고 설정한 상태가 아니라면 그것에 맞게 맞춘다는 개념이다. 

쿠버네티스의 '선언적' 특징

쿠버네티스의 이런 '선언적' 특징을 이용하면 원하는 상태만 쿠버네티스에 정의해 유지할 수 있으므로 관리 비용이 많이 준다. 

사용자가 설정한 명령이 없어지는 것 등을 염려하지 않아도 된다. 쿠버네티스를 사용하면 이런 문제를 걱정하지 않아도 된다. 클러스터가 동작 중이라면 항상 원하는 상태로 자동 복구를 하기 때문이다. 

이 때문에 쿠버네티스에서 사용하는 컴포넌트들의 구현 또한 단순하다. 또한 컴포넌트를 여러 개 실행해둘 수 있으므로 단일 장애점(Single Point Of Failure, SPOF)이 없다. 

하지만 '선언적' 특징 때문에 때로 불편한 점도 생긴다. 컨테이너가 몇 개 실행되어야 한다거나 앱이 없어야 할 때는 설정하기 쉽지만, 앱 재시작 같은 단순한 작업은 쿠버네티스에서 할 수 없다. 앱 재시작은 쿠버네티스 시스템 내부 동작으로 사용자가 제어할 수 없기 때문이다. 

쿠버네티스 입장에서는 같은 설정, 즉 기존 설정과 비교했을 때 변경 사항이 없는 앱은 재시작하지 않아도 된다고 생각한다. 하지만 앱 재시작 기능을 넣어달라는 사용자 요청이 많아지면서 쿠버네티스 CLI인 kubectl 1.15부터는 디플로이먼트, 스테이트풀세트, 데몬세트에 재시작 기능이 추가됐다. 쿠버네티스 컴포넌트들의 선언적 특징을 그대로지만, kubectl이 직접 애너테이션을 변경하면서 재시작 동작을 제어하는 방식으로 바뀌었다. 

워크로드 분리 

쿠버네티스를 사용하면 분산 시스템을 개발하고 어떻게 실행할지에 관한 고민을 많이 덜어준다. 분산 시스템을 개발할 때는 분산된 프로세스 각각이 잘 실행되는지, 이상이 생겼을 때는 어떻게 처리해야 하는지 등 시스템 안전성에 관한 고민을 많이 해야한다. 이때 쿠버네티스는 운영체제처럼 분산된 프로세스의 관리를 추상화하는 레이어가 되므로 시스템 운영에 관한 고민을 많이 덜어 준다. 이 때문에 최근에 쿠버네티스를 클라우드의 리눅스라고 말하는 상황도 생기고 있다. 

어디서나 실행 가능

쿠버네티스가 지금처럼 인기를 얻게 된 주요 원인 중 하나는 어디서나 실행할 수 있다는 점이다. 개인 컴퓨터에 쿠버네티스를 설치해서 사용해 볼 수 있고, 여러 대 서버에 설치해서 사용할 수 있다. 퍼블릭 클라우드에서도 쿠버네티스를 실행할 수 있고, 단순한 테스트라면 쿠버네티스 설치 없이도 웹에서도 사용해볼 수 있다. 즉, 처음 쿠버네티스를 접하려는 사람이 접근하기 쉬워 많은 사용자가 모이는 원동력이 되었다. 

커뮤니티

활성화된 커뮤니티 또한 쿠버네티스의 큰 장점이다. 

728x90

'Infra' 카테고리의 다른 글

SpringBoot Application + ECS 배포  (0) 2023.08.20
리눅스 환경구성 기초  (0) 2020.10.22
Infra

리눅스 환경구성 기초

728x90

이번 포스팅은 Tacademy의 리눅스 환경구성 기초 강의를 수강하고 요약한 내용입니다.

리눅스 소개 👋🏻

우리에게 컴퓨터는 ?

리눅스와 관련된 키워드

터미널, 쉘스크립트 등 외계언어들이 가득하다!

리눅스, 편안하게 쓸 수 없을까?

리눅스는 왜 어려운걸까?

GUI vs CLI 이 두가지로 볼 수 있다.

GUI (Graphical User Interface)

  • 한 화면에 많은 정보를 담을 수 있다
  • 눈으로 보고 대상을 선택 가능하다
  • But, 만약 한 화면에서 다양한 일을 하게된다면...?

CLI (Command-Line Interface)

  • 눈에 보이는 거라곤 고작 터미널 하나
  • 뭔가 하고 싶지만 몰라서 할 수가 없다
  • But, 까막눈이면 몰라도, 숙련자에겐..?

리눅스를 잘 다루는 것?

리눅스 환경에서 파일, 프로그램을 얼마나 잘 다루는가? + CLI 환경이 얼마나 익숙한가?

리눅스란?

  • 리눅스 커널을 사용하는 Unix 계열 운영체제
  • 대규모 오픈소스 프로젝트 by 리누즈 토르발스

커널? 운영체제?

보통 커널의 종류에 따라 ~~ 계열이라 불린다. Linux Kernel을 쓰게 된다면 리눅스계열이라 불린다.

이 말고도 엄청나게 많다.

Linux 시작

주의! 본 과정은 AWS EC2 서버에서 실습이 진행된다.

이미 이전에 AWS EC2 서버를 만든적이 있어, 튜토리얼을 따라 진행하지는 않았다. 추가적으로 Window의 경우 터미널 사용을 위해서 Putty 프로그램이나 OpenSSH Client를 사용해야한다. (맥의 경우 그냥 터미널을 사용하면 된다!)

사전 지식

  • SSH (Secure Shell): 원격으로 다른 컴퓨터에 연결할 수 있도록 해주는 프로그램 (+ 보완연결)
  • Port: 목적지(Host)의 프로세스에 연결하기 위한 구분 123.234.345.456:3434

리눅스 활용 (리눅스 기본 명령어 및 활용법)

정리중... (추후 링크 첨부)

리눅스 이해 (계정과 권한, SUDO, PATH)

Tool 역할
apt-get 필요한 패키지, 프로그램을 설치 할 수 있는 패키지 관리 도구
htop top을 좀 더 예쁘게 꾸며서 보여준다
nohup 내 스크립트가 터미널을 끄더라도 계속 실행시키고 싶을 때 &와 함께 백그라운드로 실행
screen(tmux) nohup을 통해 백그라운드로 가버린 프로세스는 다시 볼 수 없지만 Screen을 띄워서 실행하면, 해당 세션을 다시 복원할 수 있다

계정과 권한

권한 변경

권한 변경에 숫자가 3개인데, 각 숫자는 앞에서부터 Owner, Group, Others 에 대한 권한이다. (각 숫자는 이진법을 의미하는 것이고 권한 부여는 표에 적혀있는 대로이다)

chmod뿐만아니라 chown 이라는 명령어로 파일의 owner를 변경할 수도 있다!

소유자의 권한, 그룹의 권한, 소유자가 아닌 사람의 권한을 구분 한다. ('보안')

Sudo ?

Root 사용자라는 것은 모든 권한을 가진 Super 관리자이다.

But Root 계정은 너무 강력하다보니 남용하면 안된다!

시스템의 중요한 부분을 변경하거나 업데이트해야 할 때, Root 계정 접속을 남발하면 귀찮기도 하고, 보안상 좋지 않기 때문에 일시적으로 Root의 권한을 위임 받을 수 있는 방법이 "sudo" 이다. (지정된 그룹에서만 sudo를 쓸 수 있다)

환경 변수 $PATH

터미널에 echo $PATH 명령어 입력시

디렉토리 용도 사용권한
/bin 기본적인 명령어 일반 사용자
/sbin 시스템 관리를 위한 명령어 슈퍼유저(root)
/usr/bin /bin에 있는 명령을 제외한 기본적인 명령어 일반 사용자
/usr/sbin /sbin에 있는 명령을 제외한 시스템 관리를 위한 명령어 슈퍼유저(root)

프로그램을 실행할 때 자동으로 참조하는 절대경로의 모음 왼쪾으로 갈수록 우선순위가 높으며, 발견 즉시 바로 실행 됨!

다른 환경 변수

터미널에 export 명령어 입력시

  • 프로그램을 실행할 때 자동으로 참조하는 절대경로의 모음
  • export 명령어로 환경변수를 추가 (일시적)

쉘 스크립트 기본

쉘 스크립트를 왜 쓸까?

반복적이고, 똑같은 작업이 너무 귀찮으니, 자동으로 해버리자!

셔뱅 (Shabang)

#!{인터프리터 위치}
  • 셸 스크립트 시작할 때 맨 처음에 기입
  • 아무것도 아닌 것 같지만, 스크립트를 해석하는 인터프리터를 지정하는 것!
  • ex) #!/usr/bin/python3

작성한 셸 스크립트 실행하는 법 (2가지 방법)

첫번째 방법

bash {파일명}

이렇게 실행할 경우, 쉘 스크립터에서 '인터프리터'를 지정하지 않아도 가능하다! (실행할 때, 직접 지정했기 때문이다)

두번째 방법
(먼저 일반문서인 쉘스크립트를 실행파일로 변경하는 작업을 진행한다!)

chmod 7xx {파일명}

권한을 7xx로 주는 이유는, 나에게 모든 권한을 부여하겠다는 뜻이다. (그룹이나 다른 사용자들에게는 상황에 맞게 권한을 부여하면 된다)

권한을 부여한 뒤에, ls 명령어로 파일을 조회해보면, 이전과는 다르게 해당 파일이 다른색상으로 변경된다!

실행 방법

./{파일명}

그리고 바로 실행을 하면 될 것 같지만, 안된다! 그 이유는 현재 위치가 쉘 스크립트가 위치한 파일이 아니기 때문이다(실행이 된다면, 이미 파일위치로 경로를 설정한 상태이다!).

변수 (Variable)

  • 선언은 VAR=?
  • 사용은 $VAR
  • 특수한 경우 ${VAR}
  • 매개변수 $0, $1 ..., $*, $@
#!/bin/bash

MY_VAR=13
string=12312abcva312

echo "MY_VAR" $MY_VAR
echo "string" $string
echo "file_name:" $0
echo "first:" $1
echo "second:" $2
echo "all:" $*

echo ${string:1}
echo ${string:0:5}

echo `expr 1+2`
echo `expr 1 + 2`
echo $((1+2))
echo $((1 + 2))

산술 덧셈을 추가 처리가 필요하다.
입력 매개변수는 기본적으로 스트링

조건문, 비교 연산자

  • if then ~ elif then ~ fi
  • 정수 -eq, -ne, -gt, -lt, -ge, -le
  • 문자열 ==. !=, -z, -n
#!/bin/bash

echo "What Number?"

number=3

if [ $1 == $number ]
then 
    echo "Correct!"

elif[ $1 != $number ]
then 
    echo "Retry .."
fi

정수와 문자열의 비교방식이 다르다.
괄호를 2개를 넣는다거나[[]], 문자열로 인식되도록 변환하는 방법이 있다.

반복문

  • while 조건에 만족한다면
  • for wlwjdehls qjadnl dksdptj
  • break, continue, exit로 제어
#!/bin/bash

count=$(($1))

echo "loop" $count
while [ $count -gt 0 ]
do
    echo $count 
    count=$(( $count - 1 ))
done

echo "parameters:"
for a in $*
do
    echo $a
done

어떤 명령어나 흐름을 반복하고 싶을 때

스크립트 작성시 유의사항

  1. Space가 필요한 곳은 확실히 넣어줘야 한다.
  2. 중간에 에러가 나더라도 계속 진행
  3. 엔터 잘못 쳤다가... 전부 날려먹을 수도 있다.

(변수 입력시 VAR=2 와 같이 전부 붙여써야한다.. 추가적으로 rm -rf 쓸때는 조심 또 조심하자)
앞에 실행이 다 안되더라도 계속 실행이 되버리기 때문에, 더더욱 조심해야한다!

728x90

'Infra' 카테고리의 다른 글

SpringBoot Application + ECS 배포  (0) 2023.08.20
쿠버네티스 소개  (0) 2022.12.03
Infra/DataBase

[MySQL] - JOIN의 종류와 사용예제

728x90

http://blog.naver.com/PostView.nhn?blogId=pjok1122&logNo=221542171040&parentCategoryNo=&categoryNo=21&viewDate=&isShowPopularPosts=true&from=search

 

[MySQL] Inner Join(내부 조인)과 Outer Join(외부 조인)

조인에는 생각보다 다양한 조인이 존재합니다. 그 중에서 제일 대표적인 두 가지만 살펴보도록 합시다.​1....

blog.naver.com

http://www.sqlprogram.com/Basics/sql-join.aspx

 

테이블 JOIN - SQL 프로그래밍 배우기 (Learn SQL Programming)

테이블 조인 (JOIN) SELECT문은 하나 이상의 테이블로부터 데이타를 가져올 수 있다. 복수의 테이블로부터 데이타를 가져오기 위해서는, FROM절 뒤에 복수의 테이블을 나열하면 된다. 이때, 테이블들이 서로 연관을 맺고 이들로부터 특정 조건의 레코드셋들을 선별하게 되는데, 이를 테이블 조인이라 한다. 테이블 조인에는 Cross Join, Inner Join, Outer Join 등이 있으며, Cross Join은 테이블A의 모든 레코드들에 대해 테이

www.sqlprogram.com

위 글들을 참고하였습니다. 

현재 진행중인 프로젝트에서 테이블을 3개, 4개 join하라는 요구조건이 있었다. SQL로 간단한 CRUD 정도만 진행하다보니 join의 개념을 잊고있었다. (또 이렇게 되새김질 하는 것 아니겠는가? 부디 이번에는 오랫동안 기억에 남기를 바란다

테이블 조인(Table Join)

SELECT문은 하나 이상의 테이블로부터 데이터를 가져올 수 있다. 복수의 테이블로부터 데이타를 가져오기 위해서는, FROM절 뒤에 복수의 테이블을 나열하면 된다. 이때, 테이블들이 서로 연관을 맺고 이들로부터 특정 조건의 레코드셋들을 선별하게 되는데, 이를 테이블 조인이라 한다. 테이블 조인에는 Cross Join, Inner Join, Outer Join 등이 있으며, Cross Join테이블A의 모든 레코드들에 대해 테이블B의 모든 레코드가 맴핑되는 것으로, 테이블A에 10개 레코드가 있고, 테이블 B에 5개 있다면, 총 10 x 5 = 50개의 레코드를 출력한다. Inner Join테이블A의 특정 컬럼값테이블B의 지정 컬럼값일치하는 레코드만을 선별하는 경우에 사용된다. Outer JoinInner Join과 마찬가지로 조인 조건을 만족하는 레코드들을 출력하지만, 추가로 일치하지 않는 레코드들도 함께 출력해 준다.

 

Inner Join

Inner Join은 복수 테이블들이 조인 조건을 모두 만족하는 레코드들만 선별하는 조인이다.
아래와 같이 두가지 방법으로 표현할 수 있다. 

(1) Inner Join...On 문
FROM TabA INNER JOIN TabB ON TabA.Col = TabB.Col

(2) FROM...WHERE절에서 조인 조건식 사용
FROM TabA,TabB WHERE TabA.Col = TabB.Col

 

예제

더보기

-- Orders 테이블과 OrderDetails 테이블을
-- Order ID로 조인한 예
-- 두 테이블에 동일 컬럼이 있는 경우
-- 테이블명을 명시적으로 사용한다.
SELECT Orders.ID, OrderDetails.*
FROM Orders INNER JOIN OrderDetails
ON Orders.ID = OrderDetails.ID
WHERE Orders.OrderDate >= '1/1/2012'

-- 테이블 Alias를 사용하여
-- 위의 문장을 간략히 다음처럼 표시
SELECT o.ID, d.*
FROM Orders o INNER JOIN OrderDetails d
ON o.ID = d.ID
WHERE o.OrderDate >= '1/1/2012'

 

Cross Join

Cross Join은 복수 테이블의 모든 레코드를 M x N 식으로 모두 출력하는 것으로, 만약 테이블A가 10개의 레코드가 있고, 테이블B가 5개의 레코드가 있다면, 10 x 5 레코드 즉 총 50개의 조합을 출력한다. Cross Join은 특별한 조인 조건을 지정하지 않고, 복수 테이블명을 FROM절에 나열하면 된다. (이해가 쉽다고 판단하여 따로 예제는 안들겠다)

SELECT * FROM Class, Score

 

Outer Join

복수 테이블에 모든 조인 조건이 만족되지 않더라도 한 테이블의 모든 데이터는 출력되게 하려면 Outer Join을 사용한다. 매칭 데이터가 없는 부분은 NULL로 표시될 것이다. Outer Join은 모든 데이터를 출력하는 테이블의 위치에 따라 Left Outer Join, Right Outer Join, 그리도 양쪽 테이블의 모든 데이터가 기본적으로 출력되는 Full Outer Join이 있다.

예제

더보기

-- City명은 매출여부와 상관없이
-- 출력. 매출없는 경우 합계란은 NULL
--
SELECT c.Name, SUM(s.Total) '합계'
FROM City c LEFT OUTER JOIN Sales s
ON c.Code = s.CityCode
GROUP BY c.Name


-- Outer Join 결과 예 --

Name                 합계
-------------------  -----------
서울                   264
부산                   238
대전                   232
제주                   NULL

 

Self Join

(위에서 언급하지는 않았지만 이런 Join도 존재한다)
Self Join이란 FROM절에 하나의 테이블을 Table Alias를 통하여 두번 참조한 후, 자신의 테이블을 마치 다른 테이블인 것 처럼 조인하는 것이다. 아래 예제는 Self Join을 통해 Emp 테이블에서 Boss가 Kim인 모든 종업원을 출력하는 예이다.

예제

더보기

SELECT e.EmpID, e.Name, b.Name AS Boss
FROM Emp e, Emp b 
WHERE e.MgrId = b.EmpId
AND b.Name = 'Kim'

 

 

3개 이상의 Table을 Join 해야할 경우 (다중 테이블 join)

SELECT ST.STADIUM_NAME, SC.STADIUM_ID, SCHE_DATE, HT.TEAM_NAME, AT.TEAM_NAME, HOME_SCORE, AWAY_SCORE 
FROM SCHEDULE SC 
        JOIN STADIUM ST 
                ON SC.STADIUM_ID = ST.STADIUM_ID 
        JOIN TEAM HT 
                ON SC.HOMETEAM_ID = HT.TEAM_ID 
        JOIN TEAM AT 
                ON SC.AWAYTEAM_ID = AT.TEAM_ID 
WHERE HOME_SCORE >= AWAY_SCORE +3

(테이블에 대한 구체적인 소개는 따로 안하겠다. 그냥 3개의 테이블(SCHEDULE, STADIUM, TEAM)이 있다는 사실만 파악하면 된다 마지막에 self join을 써서 같은 테이블을 사용했다)

 

원래 WHERE 조건절로 각 테이블을 연결시켜주는 column의 동등 조건을 나열하면서 (수동적인) join을 진행하려고 하였는데... 지나가면서 본 내용중에 성능적인면에서 WHERE로 join 결과를 만들어 내는 것은 조회 횟수가 많기 때문에(결국 모든 데이터를 조회 해야하기 때문이라고 했던 것 같다) 성능적인 측면에서 join이 더 좋다고 했던 것 같다. (나를 너무 신뢰하지는 말아줬으면 한다) 

728x90