반응형
250x250
Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

샘오리_개발노트

도커 & 쿠버네티스 이해하기 본문

카테고리 없음

도커 & 쿠버네티스 이해하기

샘오리 2024. 2. 28. 09:53
728x90
반응형

 

도커(Docker)란?

도커를 한 문장으로 요약하면

개발자가 만든 코드가 어느 환경에서도 작동할 수 있게 도와주는 오픈소스이다.

 

그런데 왜 굳이 Docker일까?

 

영어로 된 대부분의 기술 용어들은 이름에서 그 뜻을 쉽게 유추할 수 있다.

이를 이해하고 넘어가야 Docker 의 개념을 빠르게 받아들일 수 있다.

 

Dock은 부두이다.

Docker는 자연스럽게 부두 노동자가 된다.

부두 노동자들은 부두에서 선박에 물건을 선적하고 양하하는, 하역작업자들이다.

이 부두 노동자들의 도움으로 물건이 선박에 실렸다가 내려지는 것이다.

현대에는 대부분의 물건들이 컨테이너라는 공간에 보관되고 운반 된다.

컨테이너는 왜 쓰는 걸까?

일정한 규격이 있어 싣고 내리기 편하며

독립적이면서도 튼튼하기 때문에 외부 환경에 영향을 거의 받지 않는다.

그래서 궁극적으로 보관된 물건이 온전한 상태로 도착지에 배송된다.

도커의 컨테이너가 바로 이 개념을 착안한 것이다.

일정한 규격 덕에 명령어 하나로 쉽게 올렸다가 내릴 수 있고.

독립적이기 때문에 OS 에 영향을 받지 않으며

그래서 궁극적으로 운영 환경에 소스 코드를 배포했을 때 온전하게 작동한다.

 

개발자가 개발 환경에서 소스 코드라는 물건을 만들고

운영 환경으로 소스 코드를 배포할 때

어떠한 외부 환경에도 영향을 받지 않고 기존 상태 그대로 운반되길 원하기 때문에

컨테이너라는 독립적인 공간에 보관하는 것이고

그 컨테이너들을 무사히 하역해줄 도커의 도움을 받는 것이다.

이게 왜 중요하냐면

개발 환경에서는 문제가 없는데 운영 환경에서 문제가 생기는 경우가 자주 발생하기 때문이다.

이러한 문제를 해결하기 위해서 전통적으로

하이퍼바이저(Hypervisor)기반의 가상머신을 많이 사용했다

가상머신이란?

가상머신은 독립적이고 작은 컴퓨터라고 볼 수 있다.

각각 게스트 O/S가 있으며 하이퍼바이저 위에서 작동한다.

*하이퍼바이저란? 가상 머신을 생성하고 구동하는 소프트웨어

도커와 차이점은?

Guest OS의 유무이다.

VM에는 위에서 언급한 Guest OS가 깔린다.

하지만 도커의 컨테이너는 애플리케이션을 구동하는데

필요한 모든 패키지만 있으면 Guest OS 없이 컨테이너를 구동 시킬 수 있다.

이게 가능한 이유는 Host OS에서 커널을 공유 받기 때문이라고 한다.

 

커널이란?

영어로 Kernel은 씨앗의 알맹이와 같이 어떤 것의 핵심을 뜻한다.

IT 분야에서도 이 개념과 연관 지어 운영체제의 핵심 프로그램을 일컫는데

더 자세히는 컴퓨터 자원들을 관리하는 인터페이스이다.

 

 

커널은 운영체제 중 항상 메모리에 올라가 있는 운영체제의 핵심 부분으로써 하드웨어와 응용 프로그램 사이에서 인터페이스를 제공하는 역할을 하며 컴퓨터 자원들을 관리한다.

 

그래서 결론은 도커가 더 빠르고 가볍다고 볼 수 있다.

그렇다면 도커 컨테이는 장점만 있는걸까?

도커의 단점

  1. 전염성

Docker는 커널을 공유하기에 호스트 서버의 문제가 모든 컨테이너에 영향을 미친다.

  1. 리눅스 Only

커널 기술은 리눅스 기반의 기술이기 때문에 리눅스 용 소프트웨어만 지원한다. 한마디로 리눅스가 아닌 맥이나 윈도우를 쓰게 되면 어짜피 Docker for mac 이나 Docker for Window 같은 가상 머신을 써야한다.

  1. 비용

도커를 제대로 배우려면 알아야 하는 게 많아서 러닝 커브가 높은 반면 비즈니스의 규모가 작거나 테스트 용도여서 컨테이너의 수가 적을 경우 VM과 성능 차이가 미미하다.

이러한 한계가 있음에도 장점이 이를 상쇄하기에 많은 사람들이 도커를 찾고 있는게 아닌가 싶다.

 


도커 사용하기

도커 명령어

- docker image bulid -t 이미지:태그 Dockerfile경로

		: 도커 파일로 이미지 빌드하기(만들기

- docker image pull 레파지토리:태그
		
		: 도커 이미지 내려받기(도커 허브 같은 곳에서)

- docker image push 레파지토리:태그

		: 도커 이미지 올리기 (도커 허브 같은 곳으로)
- docker images
    
    : 전체 도커 이미지 목록 확인
    
- docker ps
    
    : 실행중인 컨테이너 목록 확인
    
- docker ps -a
    
    : 전체 컨테이너 목록 확인
    
- docker start 컨테이너ID
    
    : 컨테이너 시작
    
- docker attach 컨테이너ID
    
    : 컨테이너 접속(진입)
    
- docker stop 컨테이너ID
    
    : 컨테이너 멈춤
    
- docker run 컨테이너ID
    
    : 컨테이너 생성 및 시작
    
- docker run -it 컨테이너ID
    
    : 컨테이너 생성 및 시작 및 접속(진입)
    
- docker rm 컨테이너ID
    
    : 컨테이너 삭제
    
- docker exec -it 컨테이너ID /bin/bash
    
    : 실행되고 있던 컨테이너 접속
    
- exit
    
    : 컨테이너 빠져나오기

도커 파일 만들기

도커 파일을 만들고 빌드를 하면 이미지가 생성된다.

그리고 이미지를 Run 하면 컨테이너로 올라간다.

가장 첫번 째 단계인 도커 파일을 어떻게 만드는지 살펴보자.

도커 파일에서 사용할 수 있는 설정은 아래와 같다.

FROM
베이스 이미지(Base Image) 지정

MAINTAINER
이미지를 생성한 사람의 이름 및 정보

LABEL
Key-value 형식으로 작성된 메타 데이터

RUN
컨테이너 빌드를 위한 실행 Commands

COPY
컨테이너 빌드시 호스트 파일을 복사

ADD
컨테이너 빌드시 호스트의 (tar,url)을 복사

WORKDIR
컨테이너 빌드시 명령이 실행될 작업 디렉토리

ENV
환경 변수

USER
명령 및 컨테이너 실행시 적용할 유저설정 ( 기본: root )

VOLUME
컨테이너 내의 특정 디렉토리를 컨테이너 외부 경로에 마운트

EXPOSE
컨테이너 동작 시 외부에서 사용할 포트 지정

CMD
컨테이너 동작 시 자동으로 실행할 서비스 및 스크립트 지정

ENTRYPOINT
CMD와 함께 사용하면서 Command 지정 시 사용

 

ENTRYPOINT와 CMD의 차이는?
ENTRYPOINT는 도커 파일에 적힌대로만 실행 == 일반적인 명령어로는 오버라이딩 불가
*--entrypoint flag 명령어를 쓰면 오버라이딩이 가능하긴 하다.

CMD는 일반적인 명령어의 파라미터로 오버라이딩 가능

예: 
도커파일에 3000번 포트를 열어놓고 실행할 때는 열린 포트를 5000번으로 바꾼다.

CMD ["--server.port=**3000**"]

docker build -t java-server .
docker run -dit -p 8080:5000 java-server

그럼 확장성을 고려해서 CMD가 더 좋은것 아닌가? 싶지만 각각의 특성을 고려해서
요즘은 둘을 같이 쓰는 것이 추세라고 한다.

예:
항상 ping이라는 명령어를 실행시키라는 ENTRYPOINT와
기본값을 google 도메인으로 잡은 CMD.

ENTRYPOINT ["ping"]
CMD ["google.com"]

이제 도커를 실행시키면 구글의 핑이 찍히겠다.
하지만 확장성을 고려해서 추후에 CMD에 적힌 값을 네이버로 오버라이딩 하게 되면
도커파일을 수정하지 않고도 네이버의 핑이 찍히는 것이다.

Ubuntu 기반의 Docker샘플 파일을 바로 보도록 하자

# 베이스 이미지 가져오기

FROM ubuntu:16.04

# 패키지 설치하는 명령어 돌리기

RUN \\

apt-get update && \\

apt-get -y upgrade && \\

apt-get install -y apache2 && \\

# 아파치 서버에 내용 좀 추가해보기

RUN echo "This is a test docker" > /var/www/html/index.html

# 설정파일 복사하기

COPY data/httpd.conf /etc/apache2/httpd.conf

# 도커가 켜진 후 실행할 명령어 적기

ENTRYPOINT ["ping"]

CMD ["google.com"]

도커 파일을 설정하고 빌드하면 Image가 되고

도커 명령어로 해당 이미지를 실행하면 컨테이너로 올라가는 것 까지 알겠다.

하지만 일반적인 시스템은 단일 컨테이너로 구동이 되지 않는다. 여러 컨테이너들이 서로 의존성 있게 구성되어있는데 이들을 한꺼번에 설정하고 실행할 수 있는 도구가 없을까? 해서 만들어진 도구가 Docker Compose 이다.

도커 컴포즈(Docker Compose)란?

도커 컴포즈는 여러 개의 도커 컨테이너를 정의하고 실행하기 위한 도구로

현재는 도커를 사용하는 대부분의 개발자들이 필수적으로 사용하고 있는 도구이다.

도커 컴포즈 사용하기

아래는 ELK 관련 도커 컴포즈 설정파일이다.

아래에서 볼 수 있듯 서비스라는 곳에 실행하고 싶은 컨테이너들을 적고 각각 어떤 설정으로 실행할지 적는다.

context에서 경로 설정해주고,

볼륨에서 마운트 해주고,

Port 에서 포트 포워딩 해주면서,

environment에서 환경 변수 파일에서 지정한 변수 받고,

네트워크 설정을 해주는등 여러 설정을 해줄 수 있다.

version: '3.7'

services:

  setup:
    profiles:
      - setup
    build:
      context: setup/
      args:
        ELASTIC_VERSION: ${ELASTIC_VERSION}
    init: true
    volumes:
      - ./setup/entrypoint.sh:/entrypoint.sh:ro,Z
      - ./setup/lib.sh:/lib.sh:ro,Z
      - ./setup/roles:/roles:ro,Z
    environment:
      ELASTIC_PASSWORD: ${ELASTIC_PASSWORD:-}
      LOGSTASH_INTERNAL_PASSWORD: ${LOGSTASH_INTERNAL_PASSWORD:-}
      KIBANA_SYSTEM_PASSWORD: ${KIBANA_SYSTEM_PASSWORD:-}
      METRICBEAT_INTERNAL_PASSWORD: ${METRICBEAT_INTERNAL_PASSWORD:-}
      FILEBEAT_INTERNAL_PASSWORD: ${FILEBEAT_INTERNAL_PASSWORD:-}
      HEARTBEAT_INTERNAL_PASSWORD: ${HEARTBEAT_INTERNAL_PASSWORD:-}
      MONITORING_INTERNAL_PASSWORD: ${MONITORING_INTERNAL_PASSWORD:-}
      BEATS_SYSTEM_PASSWORD: ${BEATS_SYSTEM_PASSWORD:-}
    networks:
      - elk
    depends_on:
      - elasticsearch

  elasticsearch:
    build:
      context: elasticsearch/
      args:
        ELASTIC_VERSION: ${ELASTIC_VERSION}
    volumes:
      - ./elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml:ro,Z
      - elasticsearch:/usr/share/elasticsearch/data:Z
    ports:
      - 9200:9200
      - 9300:9300
    environment:
      node.name: elasticsearch
      ES_JAVA_OPTS: -Xms512m -Xmx512m
      ELASTIC_PASSWORD: ${ELASTIC_PASSWORD:-}
      discovery.type: single-node
    networks:
      - elk
    restart: unless-stopped

...
...
...

networks:
  elk:
    driver: bridge

volumes:
  elasticsearch:

그리고 해당 yaml.file을 실행할 수 있는 명령어는 아래와 같다.

도커 컴포즈 명령어

# 도커 컴포즈 컨테이너들을 백그라운드로 띄우기
$ docker-compose up -d
 
# 도커 컴포즈 컨테이너들을 포어그라운드로 띄우기
$ docker-compose up
 
# 도커 컴포즈 컨테이너들을 내리기
$ docker-compose down
 
# 도커 컴포즈 컨테이너들을 다시 시작하기
$ docker-compose restart
 
# 도커 컴포즈 컨테이너들의 로그를 계속해서 읽기
$ docker-compose logs -f
 
# 도커 컴포즈 컨테이너들의 상태 확인
$ docker-compose ps
 
# 도커 컴포즈 설정을 확인
$ docker-compose config
 
# 다른 경로에 있는 도커 컴포즈 파일 사용
$ docker-compose -f /app/docker-compose.yml up
# 여러개의 도커 컴포즈 설정 파일을 사용. 
$ docker-compose -f docker-compose.yml -f docker-compose-test.yml up

쿠버네티스(Kubernetes)란?

쿠버네티스는 컨테이너 오케스트레이션(Container Orchestration) 도구이다.

오케스트라에는 여러 연주자들이 있고 이들을 지휘하는 지휘자가 있다.

Kubernetes는 지휘자이다.

컨테이너 오케스트레이션 이라는 이름에 걸맞게 연주자들 대신 컨테이너를 지휘한다.

그리고 이 Kubernetes는 컨트롤러라고 하는 매니저가 존재한다.

Controller란?

Pod 를 관찰하여 관리자가 선언한 Pod의 개수를 보장해주는 기능

Controller의 두 가지 대표적인 역할

  1. Auto Healing • Pod 에 문제가 생겼을 경우 자동으로 복구하는 기능
  2. Auto Scaling • Pod의 리소스가 부족할 때 Pod을 추가적으로 생성하는 기능

Pod란?

영어로 Pod는 작은 무리를 뜻이다. 고래 떼를 부를 때도 사용된다.

도커 컨테이너의 마스코트가 고래인 만큼 해당 용어를 택한 것으로 풀이된다.

아무튼 이 Kubernetes의Pod는 Kubernetes에서 가장 작은 컴퓨팅 단위인데 1개 이상의 리눅스 컨테이너 무리를 뜻한다.

오토 스케일링(Auto Scaling)을 자주 쓰는 이유

이유는 바로 트래픽을 유동적으로 대처할 수 있기 때문이다.

예를 들어 블랙 프라이데이 같은 시즌에 쇼핑몰 사이트의 접속자가 폭주한다면

원활한 서비스를 위해 리소스를 자동으로 늘리고,

다시 여유로운 상황이 되면 불필요한 리소스를 줄이는 것을 예로 들 수 있다.

주로 사용되는 오토 스케일링의 방법으로는 Horizontal Pod Autoscaler (HPA) 가 있다.

 

Horizontal Pod Autoscaler (HPA)가 동작하는 원리는?

Pod 에서 CPU나 메모리와 같은 리소스 지표들을 메트릭으로 서버에 저장하고

이 지표들이 지정해놓은 임계점(메트릭)을 지나면 Pod의 수를 늘려서 스케일링을 한다.

정확히 말하면 HPA는 메트릭을 모니터링하고, 

실제로 Pod의 수를 늘리거나 줄이는 것은 Deployment 와 ReplicaSet에 의해 가능하다.

아래는 샘플 HPA 설정 파일이다.

apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: gs-spring-boot-docker-hpa
spec:
  maxReplicas: 10
  minReplicas: 1
  scaleTargetRef:
    apiVersion: apps/v1beta2
    kind: Deployment
    name: gs-spring-boot-docker-deployment
  targetCPUUtilizationPercentage: 50

여기서 눈여겨 봐야하는 것은 크게 3가지 이다.

  • maxReplicas: Pod의 최대 개수
  • minReplicas: Pod의 최소 개수
  • targetCPUUtilizationPercentage: CPU 사용률 (임계치)
  • targetCPUUtilizationPercentage: 50

위 설정 파일 대로라면 CPU의 사용률이 50%를 넘어간 순간 오토 스케일링을 발동하는 것이다.

그렇게 되면 최대 10개의 pod가 만들어질 수 있다 = maxReplicas: 10

Deployment 와 ReplicaSet이란?

Replica Set은 Pod의 숫자를 보장해주는 Controller 이다.

Replica Set을 이용하면 Pod의 숫자가 보장되기 때문에 관리자가 원하는 애플리케이션을 안정적으로 배포할 수 있다.

하지만, 시간이 흐르게 되면 해당 애플리케이션의 버전을 올려서 배포 해야 하는 경우가 생기게 되는데, Replica Set은 이런 업데이트에 관한 기능이 없다. 이를 해결하기 위해 Deployment가 나왔다.

이 Deployment는 Replica Set과 별개의 기법이 아니라 Replica Set을 상위에서 제어하는데 기본적으로 무중단 배포(Rolling Update)를 제공하는 오브젝트 이기도 하다.

Deployment를 사용하려면 yaml 파일에 설정해주면 된다. 아래는 공식 홈페이지의 샘플이다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

 

이 yaml 파일에서도 볼 수 있듯

kind: Deployment

Deployment를 사용한다고 선언해주고

 

spec: replicas: 3

replicas에 pod를 몇 개나 복제할지 정한다.

 

그리고 정해둔

spec: replicas: 3 개수는

Deployment에 의해 제어되기 때문에 문제가 생겨서 꺼지거나 삭제가 되었다 하더라도 복구를 통해서 pod의 개수는 3개로 유지된다.

 

여기서 HPA를 통해 더 많은 리소스가 필요하다고 판단되면 오토 스케일링을 통해 이 Replica Set의 개수가 늘어나든가 줄어드는 것이다. 그래서 HPA 를 사용한다면 Deployment 에서 Replicas의 개수를 지정해주지 않아도 된다.

쿠버네티스 명령어

아래 명령어들은 Kubernetes에서 자주 사용되는 명령어로

아주 기초적인 영어 동사들로 한눈에 그 의미 파악이 가능한 특징이 있다.

create 리소스 생성
apply 리소스 생성/업데이트
get 리소스 목록 조회
describe 리소스 상세 상태 조회
delete 리소스 제거
logs 컨테이너 로그 확인
exec 컨테이너 진입/명령어 전달
config kubectl 설정 관리

Docker와 마찬가지로 Kubernetes 또한 yaml 설정 파일을 실행시키는 구조인데

yaml파일을 아래 명령어로 쉽게 실행시킬 수 있다 = 리소스 생성/선언

kubectl apply -f 파일명 또는 URL

선언된 리소스 목록은 get으로 볼 수 있고 삭제는 delete로 컨테이너 진입은 exec 명령어로 할 수 있다.

 

728x90
반응형
Comments