개요
등장 배경
전통적인 배포 시대
- 초기 조직은 애플리케이션을
물리 서버
에서 실행했었다. 한 물리 서버에서 여러 애플리케이션의 리소스 한계를 정의할 방법이 없었기에, 리소스 할당의 문제가 발생했다. - 예를 들어 물리 서버 하나에서 여러 애플리케이션을 실행하면, 리소스 전부를 차지하는 애플리케이션 인스턴스가 있을 수 있고, 결과적으로 다른 애플리케이션의 성능이 저하될 수 있었다. 이에 대한 해결책은 물리적인 서버를 여러 개 두는 것이지만, 각 리소스가 충분히 활용되지 않는다는 점에서 확장 가능하지 않았으므로,
물리 서버를 유지하는 데 많은 비용이 소모
되었다.
가상화된 배포 시대
- 가상화 기술의 등장 → 단일 물리 서버의 CPU에서 여러 가상 시스템을 실행 가능해졌다.
- 가상화를 사용하면 VM 간에 애플리케이션을 격리하고 애플리케이션의 정보를 다른 애플리케이션에서 자유롭게 액세스 할 수 없으므로, 일정 수준의 보안성을 제공할 수 있다.
가상화를 사용하면 물리 서버에서 리소스를 보다 효율적으로 활용
할 수 있으며, 쉽게 애플리케이션을 추가하거나 업데이트할 수 있고 하드웨어 비용을 절감할 수 있어 더 나은 확장성 및 고가용성을 제공 할 수 있다. 가상화를 통해 일련의 물리 리소스를 폐기 가능한 가성머신으로 구성된 클러스터로 만들 수 있다. 이를 통해, 모든 컨테이너는 하나의 물리 인스턴스(또는 VM) 위에서 실행된다면, 해당 인스턴스가 죽었을 때 그 위의 모든 컨테이너도 같이 죽는다는 한계를 극복할 수 있다.
컨테이너 개발 시대
- 컨테이너는 VM과 유사하지만 격리 속성을 완화하여
애플리케이션 간에 운영체제를 공유
한다. 그러므로 컨테이너는 가볍다고 여겨진다. VM과 마찬가지로 컨테이너에는 자체 파일 시스템, CPU 점유율, 메모리, 프로세스 공간 등이 있다. 기본 인프라와의 종속성을 끊었기 때문에, 클라우드나 OS 배포판에 모두 이식할 수 있다.
컨테이너 개발의 장점
- 기민한 애플리케이션 생성과 배포의 편리함
- VM 이미지를 사용하는 것에 비해 컨테이너 이미지 생성이 보다 쉽고 효율적임.
- 지속적인 개발, 통합 및 배포 가능
- 안정적이고 주기적으로 컨테이너 이미지를 빌드해서 배포할 수 있고 (이미지의 불변성 덕에) 빠르고 효율적으로 롤백할 수 있음.
- 개발과 운영의 관심사 분리 가능
- 배포 시점이 아닌 빌드/릴리즈 시점에 애플리케이션 컨테이너 이미지를 만들기 때문에, 애플리케이션이 인프라스트럭쳐에서 분리된다.
- 가시성
- OS 수준의 정보와 메트릭에 머무르지 않고, 애플리케이션의 헬스와 그 밖의 시그널을 볼 수 있다.
- 개발, 테스팅 및 운영 환경에 걸친 일관성 보장
- 랩탑에서도 클라우드에서와 동일하게 구동된다.
- 클라우드 및 OS 배포판 간 이식성
- Ubuntu, RHEL, CoreOS, 온-프레미스, 주요 퍼블릭 클라우드와 어디에서든 구동된다.
- 애플리케이션 중심 관리 가능
- 가상 하드웨어 상에서 OS를 실행하는 수준에서 논리적인 리소스를 사용하는 OS 상에서 추상화 수준이 높아진다.
- 느슨하게 커플되고, 분산되고, 유연하며, 자유로운 마이크로서비스 가능
- 애플리케이션은 단일 목적의 머신에서 모놀리식 스택으로 구동되지 않고 보다 작고 독립적인 단위로 쪼개져서 동적으로 배포되고 관리될 수 있다.
- 자원 사용량: 리소스 사용량이 고효율, 고집적.
Docker
Container
- 정의
- 외부 환경으로부터 격리된 프로세스를 말한다.
- 한 컴퓨팅 환경에서 다른 컴퓨팅 환경으로 빠르고 안정적으로 실행될 수 있도록 코드와 모든 종속성을 패키지화한 것을 말한다. → 플랫폼 종속성이 제거된 상태이다.
- 가상화 기술
- 프로세서, 메모리, 스토리지 등 물리적 컴퓨팅 자원들을 소프트웨어 형태로 시뮬레이션하는 가상 환경을 말한다.
- 하나의 물리적 시스템을 다수의 가상 컴퓨터로 분할할 수 있다.
- 컴퓨터 자원을 더욱 효율적으로 사용하기 위해 사용하며, 주로 클라우드 컴퓨팅 시 사용된다.
- 컨테이너와 가상 머신과의 비교
- Container
- 공통점
- 컨테이너도 가상화 기술의 하나이다.
- 차이점
- 주로 OS를 가상화하는 VM (e.g - Ubuntu Desktop)
- 윈도우 운영체제에서도 리눅스 운영체제를 실행할 수 있다.
- 컨테이너는 VM과 유사하지만 격리 속성을 완화하여
애플리케이션 간에 운영체제를 공유
한다.- 호스트 OS 위에 게스트 OS 전체를 가상화하여 사용 할 수 있다.
- 주로 OS를 가상화하는 VM (e.g - Ubuntu Desktop)
- 공통점
- Container
Docker
- Docker
- 컨테이너 기술을 사용하기 쉽게 서비스화 한 것이다.
- 다양한 프로그램, 실행 환경을 컨테이너로 추상화하고 동일한 인터페이스를 제공하여 프로그램의 배포 및 관리를 단순하게 해준다.
- 특징
- 높은 확장성
- OS 환경, 클라우드 벤더 등에 종속적이지 않기 때문에 Docker만 설치되어 있으면 컨테이너 사용이 가능하다. 따라서 쉽고 빠르게 서버 환경을 구축할 수 있다.
- 표준화 가능
- Java, Python, Nodejs 등 서로 다른 App들을 동일한 방식으로 실행 가능하다. 즉, 이종 기술들을 동일한 인터페이스로 배포하고 관리할 수 있다.
- 재현 가능한 이미지
- Docker는 가상화 플랫폼이다. 기존의 가상머신 이미지는 재현이 어렵다.
- 그러나 Docker 이미지는 Dockerfile이라는 파일에 이미지가 어떻게 만들어지는지 기술되어 있으므로 100% 재현이 가능하다.
- 높은 확장성
관련 용어
- 이미지
- 컨테이너 실행에 필요한 파일과 설정 값 등을 포함하고 있는 것을 말한다.
- 컨테이너는
이미지를 실행한 상태
이고 같은 이미지에서 여러개의 컨테이너를 생성할 수 있다.- 컨테이너가 프로세스라면, 이미지는 프로그램.
- 도커 이미지는 Docker hub에 등록하거나 Docker Registry 저장소를 직접 만들어 관리 가능하다.
- Docker Registry = Github 같은 원격 저장소
- 이미지와 컨테이너
- 이미지는 컨테이너 실행을 위한 모든 정보를 가지고 있으므로 의존성 파일을 컴파일하고 애플리케이션을 설치할 필요가 없다.
- 만약 새로운 서버가 추가되면, 미리 만들어놓은 이미지를 다운받고 컨테이너를 생성만 하면 된다. 또한 한 서버에 여러 개의 컨테이너를 실행할 수 있고 수십, 수백, 수천대의 서버도 동일하게 생성 가능하다.
- Dockerfile
- 정의
- DockerImage를 생성하기 위한 스크립트(설정파일) 여러가지 명령어를 토대로 Dockerfile을 작성한 후 빌드하면, Docker는 Dockerfile에 나열된 명령문을 차례대로 수행하며 DockerImage를 생성해준다.
- 예시
- JDK 11을 설치하고 컨테이너가 빌드된 .jar 파일을 실행하는 경우
- 정의
FROM adoptopenjdk/openjdk11
ARG JAR_FILE=build/libs/*.jar
COPY ${JAR_FILE} app.jar ENTRYPOINT ["java","-jar","/app.jar"]
- 도커 컴포즈
- 서비스 설계와 구축이 용이한 스크립트를 작성하여 도커를 더 쉽게 사용하게 한다. 도커 컴포즈를 사용하면 여러 컨테이너를 하나의 서비스로 실행하거나 다른 컨테이너를 동시에 생성할 수 있다. 도커 콤퍼즈의 사용 순서는 다음과 같다.
- 파일 생성 : docker-compose.yml
- 파일 유효성 확인 : docker-compose config
- 시작 : docker-compose up
- 예시
- 서비스 설계와 구축이 용이한 스크립트를 작성하여 도커를 더 쉽게 사용하게 한다. 도커 컴포즈를 사용하면 여러 컨테이너를 하나의 서비스로 실행하거나 다른 컨테이너를 동시에 생성할 수 있다. 도커 콤퍼즈의 사용 순서는 다음과 같다.
version: "3"
services:
web: # Nginx 컨테이너
image: nginx
ports:
- "8080:80"
volumes:
- /etc/nginx/:/etc/nginx/
# 로컬 EC2의 /etc/nginx/ 디렉토리를 컨테이너의 /etc/nginx/에 마운트
spring: # Spring Boot 애플리케이션 컨테이너
build: .
ports:
- "8080:8080"
volumes:
- ./:/root/
# 현재 디렉토리를 컨테이너 내부의 /root/ 디렉토리에 마운트
- 도커 컴포즈와 Dockerfile
- 요약하면, 컨테이너 이미지를 생성하기 위해 Dockerfile을 사용하고, 해당 이미지의 인스턴스를 컨테이너로 배포하기 위해 Docker Composition을 사용한다.
Docker 실습
- 순서
- 로컬에서 실행하는 경우
- 도커 이미지 빌드
# Dockerfile 파일이 있는 디렉토리 기준. 마지막의 . 이 상대주소 docker build -t {이미지명} . docker build -f Dockerfile -t [이미지 이름:이미지 버전] [Dockerfile의 경로] # M1의 경우 docker build -f Dockerfile -t [이미지 이름:이미지 버전] [Dockerfile의 경로] --platform linux/amd64
docker create {옵션} {이미지명}:{태그} # 예: docker create -it python
- 도커 이미지 실행
docker run {이미지명}:{태그} # 예: docker -it run python:3
- 도커 이미지 빌드
- docker hub에서 받아와 실행하는 경우
- 로그인
docker login -u ${{ secrets.USERNAME }} -p ${{ secrets.PASSWORD }}
- 빌드
docker build -t 이미지명 .
- push & pull
docker push 이미지명
docker pull 이미지명
- 실행
docker run {이미지명}:{태그}
- 로그인
- 로컬에서 실행하는 경우
Kubernetes
개요
- 정의
- 컨테이너 오케스트레이션 도구로, 사실상
컨테이너 오케스트레이션의 표준
처럼 자리잡고 있다.
- 컨테이너 오케스트레이션 도구로, 사실상
- 특징
- Immutable Infrastructure
- 한번 구축한 인프라는 수정하지 않고 바로 파기하며,
원하는 상태를 만들어서 새로운 환경을 구축
한다. 이는 클라우드 환경이므로 가능하다.
- 한번 구축한 인프라는 수정하지 않고 바로 파기하며,
- Declarative Configuration
- Kubernetes는
선언적으로 상태를 명시
할 수 있다. 원하는 상태를 만들기 위해 명령어를 하나씩 차지 않고, 단지 원하는 상태를 기술하여 Kubernetes에 적용할 수 있다.
- Kubernetes는
- Self Healing
- 장애가 발생했을 때,
사람의 개입을 최소화하여 자동으로 복구
할 수 있어야 한다. 시스템이 되어 있어야 하는 상태를 항상 감시하며, 원하는 상태와 다를 경우에 자동으로 복구한다.
- 장애가 발생했을 때,
- Immutable Infrastructure
역할 : Container Orchestration
- 정의
- 다수의 컨테이너를 쉽고 자동적으로 제어/관리하기 위해 생겨난 기법을 말한다.
- 역할
- 쿠버네티스는 분산 시스템을 탄력적으로 실행하기 위한 프레임 워크를 제공한다.
애플리케이션의 확장과 장애 조치를 처리하고, 배포 패턴 등을 제공
한다. 예를 들어, 쿠버네티스는 시스템의 카나리아 배포를 쉽게 관리할 수 있다.- 서비스 디스커버리와 로드 밸런싱
- 쿠버네티스는 DNS 이름을 사용하거나 자체 IP 주소를 사용하여 컨테이너를 노출할 수 있다. 컨테이너에 대한 트래픽이 많으면, 쿠버네티스는 네트워크 트래픽을 로드밸런싱하고 배포하여 배포가 안정적으로 이루어질 수 있다.
- 스토리지 오케스트레이션
- 쿠버네티스를 사용하면 로컬 저장소, 공용 클라우드 공급자 등과 같이 원하는 저장소 시스템을 자동으로 탑재할 수 있다
- 자동화된 롤아웃과 롤백
- 쿠버네티스를 사용하여
배포된 컨테이너의 원하는 상태를 서술할 수 있으며 현재 상태를 원하는 상태로 설정한 속도에 따라 변경
할 수 있다. 예를 들어, 쿠버네티스를 자동화해서 배포용 새 컨테이너를 만들고, 기존 컨테이너를 제거하고, 모든 리소스를 새 컨테이너에 적용할 수 있다.
- 쿠버네티스를 사용하여
- 자동화된 빈 패킹(bin packing)
- 컨테이너화된 작업을 실행하는데 사용할 수 있는 쿠버네티스 클러스터 노드를 제공한다. 각 컨테이너가 필요로 하는 CPU와 메모리(RAM)를 쿠버네티스에게 지시한다. 쿠버네티스는 컨테이너를 노드에 맞추어서 리소스를 가장 잘 사용할 수 있도록 해준다.
- 자동화된 복구(self-healing)
- 쿠버네티스는
실패한 컨테이너를 다시 시작
하고,컨테이너를 교체
하며, '사용자 정의 상태 검사'에 응답하지 않는 컨테이너를 죽이고, 서비스 준비가 끝날 때까지 그러한 과정을 클라이언트에 보여주지 않는다.
- 쿠버네티스는
- 시크릿과 구성 관리
- 쿠버네티스를 사용하면 암호, OAuth 토큰 및
SSH 키와 같은 중요한 정보를 저장하고 관리
할 수 있다. 컨테이너 이미지를 재구성하지 않고 스택 구성에 시크릿을 노출하지 않고도 시크릿 및 애플리케이션 구성을 배포 및 업데이트할 수 있다.
- 쿠버네티스를 사용하면 암호, OAuth 토큰 및
- 서비스 디스커버리와 로드 밸런싱
- 쿠버네티스는 분산 시스템을 탄력적으로 실행하기 위한 프레임 워크를 제공한다.
- 구조
- 특징
- Master에 API 서버와 상태 저장소를 두고 각 서버의 에이전트와 통신하는 구조이다.
- 컨테이너가 위치한 곳이 노드이고 컨테이너는 pod라는 단위로 노드에 배포된다.
- 마스터는
kubectl을 통해 클라이언트와 통신
한다.
- 구성
- 마스터
- 마스터는 클러스터를 관리하는 역할을 한다.
- 노드의 상황을 파악하고 컨테이너를 어떤 노드에서 가동할지 선택한다.
- etcd라는 분산 저장소를 사용해 클러스터의 정보를 저장한다.
- API 서버
- 모든 요청을 처리하는 마스터의 핵심이다.
- 모든 컴포넌트들은 API 서버를 통해서 커뮤니케이션 한다.
- 아무나 들어오면 안되기 때문에 인증 및 인가 기능 또한 보유하고 있다.
- 스케쥴러
컨테이너를 어떤 노드에서 가동할지 결정하는 컴포넌트
이다. 따라서 CPU/Memory 가용 수준 파악이 필요하다.
- 컨트롤러 매니저
- 컨트롤러 매니저는 K8s 클러스터의 상태를 감시한다.
- 되어 있어야 한 시스템을 감시하고, 다를 경우 같아지도록 조치한다. 여러 개의 컨트롤러 매니저가 존재할 수 있다.
- 분산 데이터 저장소 etcd
- etcd는 분산 key-value 저장소로, 클러스터의 모든 설정과 데이터를 저장한다.
- 클러스터의 모든 데이터를 가지고 있기 때문에 가용성이 매우 중요하고 마스터에서 분리하여 독자적으로 구축 가능하다.
- 노드
컨테이너가 가동되는 서버
로, 다수의 노드로 클러스터를 구성한다. 클라우드의 경우, 가상머신이 노드가 된다.
- kubelet
- 실제로 컨테이너를 생성하는 주체로, 마스터로부터 생성 요청을 받으면 컨테이너를 생성한다. 컨테이너의 상태를 감시하는 역할도 수행하며, 이 상태를 API 서버로 전송한다.
- kube proxy
- 각 노드에서 실행되는
네트워크 프록시
다. - 노드의 네트워크 규칙을 유지 및 관리하고 내부 네트워크 세션이나 클러스터 바깥에서 컨테이너로 네트워크 통신을 할 수 있도록 해준다.
- 각 노드에서 실행되는
- Pod
배포할 수 있는 가장 작은 단위
로, 한 개 이상의 컨테이너와 스토리지, 네트워크 속성을 가진다.- 여기에 속한 컨테이너는 스토리지와 네트워크를 공유하고 서로 localhost로 접근할 수 있으며, 컨테이너를 하나만 사용하는 경우에도 반드시 이걸 통해 관리해야 한다.
- 마스터
- Kubernetes Objects
- 대규모 분산환경에 필요한 공통 요소들을 추상화한 것이다.
- 컨테이너 자체, 애플리케이션 배포나 추상 방식, 네트워크 등을 쿠버네티스에서 사용할 수 있도록 추상화한다. 이렇게 추상화 한 것들을 Object라고 통칭하며, 다양한 오브젝트들이 존재한다.
- Application 및 배포 : Pod, ReplicaSet, Deployment, DaemonSet, StatefulSet ..
- ReplicaSet
동일한 pod를 복제해서 관리하기 위해 사용
하는 것으로, pod를 생성하고 개수를 유지할 때 사용한다.
- Deployment
실제 배포를 진행하는 기본 단위
로, pod나 ReplicaSet 단위로 배포할 수도 있지만 Deployment는 실제 배포를 진행하기 위한 여러가지 기능들을 제공하기 떄문에 기본 단위로 사용된다.
- DaemonSet
클러스터 전체에 Pod를 띄울 때 사용하는 Controller
로, 어플리케이션 수행 방식에 관한 것이다.- 항상 모든 노드에 특정 파드(컨테이너)가 실행되는 것을 보장하며, 새로운 Node가 추가되면 자동으로 Pod가 실행되도록 관리한다.
- StatefulSet
- Kubernetes의 대부분의 Object는 Stateless이다. StatefulSet은 상태를 유지하는 pod를 위한 오브젝트로, Volume을 사용해서 데이터를 저장하고 pod 재가동 시에도 유지가 가능하다.
- ReplicaSet
- 네트워크 : Service, Ingress
- Service
- 네트워크와 관련된 오브젝트로 pod 간 연결 및 pod와 외부 네트워크를 연결하는 역할을 한다. ReplicaSet을 사용해 여러 개의 pod가 복제되어 있을 때, 그 내부를 로드밸런싱하는 역할도 제공한다.
- Ingress
- Ingress는 로드 밸런싱, SSL 종료 및 이름 기반 가상 호스팅을 제공한다.
- Service
- 설정 정보 관리 : ConfigMap, Secrets
- 배치 잡 관리 : Job, CronJob
- Application 및 배포 : Pod, ReplicaSet, Deployment, DaemonSet, StatefulSet ..
- 특징
Manifest 파일
# pods/simple-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
- Kubernetes에서 선언적인 상태 변경을 하기 위한 파일이다. YAML (또는 JSON) 파일로 작성되며, 리소스의 종류와 원하는 상태를 입력한다.
- apiVersion
- Kubernetes API 버젼 정보 기술
- 보통 v1 사용
- kind
- Object의 종류 기술
- pod, service, ingress …
- metadata.name
- Object의 이름을 지정
- 알기 쉽게 지정하는 것이 좋음
- spec
- Object의 상세 정보 기술
- Object의 종류에 따라 정보 상이
- 컨테이너 이름
- 컨테이너 포트 정보
- 환경 변수 등
- status(read-only)
- 시스템에서 관리하는 최신 상태
- apiVersion
참고한 사이트
https://www.docker.com/resources/what-container/
https://kubernetes.io/ko/docs/concepts/overview/
반응형
'Infra' 카테고리의 다른 글
[Infra] Minikube를 활용하여 Kubernetes 핵심 개념을 익혀보자 (0) | 2025.03.25 |
---|---|
간단하게 실습하며 배우는 Kubernetes와 Terraform (1) 로컬 Kubernetes 클러스터에 웹 서버 배포 자동화하기 (0) | 2025.02.08 |
PresignedUrl 활용한 파일 다운로드/업로드 Timeout 에러 및 성능개선기 (4) | 2024.10.22 |
댓글