Docker&Kubernetes 스터디 - 1

배채윤·2023년 4월 17일
0
post-thumbnail

Docker & K8s 스터디 요약 자료

01장. 도커란?

가상화라는 건 왜 나왔는가?

한정된 리소스를 논리적으로 나눠서 효율적으로 사용하고자 하는 니즈가 있었음.

  • 1964년 IBM에서 system/360을 출시.
    -> 멀티 태스킹이 가능해짐
    -> 신뢰성을 이유로 제대로 활용을 못함.

  • 가상화의 등장
    -> 하나의 물리 서버에서 여러 가지 서비스를 독립적으로 운영 가능해짐

  • cpu 스케줄링
    -> CPU 이용률, 처리 시간, 대기 시간.. 등등을 고려하여 스케줄링을 함
    -> Load balancing vs Processor Affinity
    프로세서에 균등하게 일을 분배 vs 균등하게 분배는 안되지만 캐싱 메모리 활용 가능

가상머신의 한계

  • 일반 호스트에 비해 성능 손실 발생함
    물리 머신 - host os - hypervisor - guestos - 어플피케이션까지의 단계를 거치기 때문
  • 이미지 크기가 큼
    guest os 를 위한 lib, 커널까지 포함됨

Docker 컨테이너 원리

아래 리눅스 자체 기능을 이용해서 프로세스 단위의 격리 환경을 만듦.

  • chroot : 프로세스의 루트 디렉터리를 변경하는 리눅스 시스템콜/명령어
  • cgroups : 프로세스들의 자원의 사용(CPU, 메모리, 디스크 입출력, 네트워크 등)을 제한하고 격리시키는 리눅스 커널 기능
  • namespace :동일한 시스템에서 별개의 독립된 공간을 격리된 환경에서 운영하는 가상화 기술

chroot

  • 탈옥이 가능하다. -> Pivot root로 해결 가능(root 마운트 포인트 자체를 바꿔서 루트 디렉토리를 변경하는 거라 아예 탈옥이 불가능)
  • 완전한 격리가 불가능하다. (Host의 filesystems, network 등에 접근 가능) -> namespace로 해결 가능
  • root 권한 사용 가능하다. -> namespaces 로 해결 가능
  • host의 자원을 무제한으로 사용할 수 있다. -> cgroups

Namespace

  • Mount namespaces: 디스크 마운트 지점과 파일 시스템의 격리를 제공
  • UTS namespaces: 호스트 이름 격리
  • IPC namespaces: 다른 네임스페이스 프로세스 간에는 통신을 못하게 함
  • PID namespaces: 프로세스 ID 번호 공산을 분리
  • Net namespaces: ip 주소, 라우팅 테이블, 터널, 방화벽 등 자체 리소스가 있음.
  • User namespaces: user, group, 권한 등 분리 가능

Cgroups

Hierarchy 기반으로 자원을 묶어줌.
CPU, MEM 등의 자원을 그룹별로 몇%씩 사용할지 지정할 수 있음.

Docker를 사용해야 하는 이유

  • 컨테이너 진영의 표준이기 때문
    • 컨테이너로는 OpenVZ, LXC, CRI-O 등 많음. docker가 사실상 컨테이너 진영에서 표준
    • 도커 런타임인 containerd는 CRI 표준에 맞춰져 있음.
  • 어플리케이션 개발과 배포의 용이성
    • 격리되어 있어서 컨테이너 내부에서 수많은 SW를 설치하고 수정해도 host OS에는 영향이 없음.
    • 개발 환경에서 작업을 마친 후 운영 환경에 배포하고자 한다면 도커 이미지로 전달하기만 하면 별도 설치 필요 없이 동일하게 복제 가능
    • 커널을 포함하고 있지 않아 이미지 크기가 크지 않음.
    • 내로잘 방지(내 로컬에선 잘되는데요..)
  • 어플리케이션 독립성과 확장성
    • 모놀리식 아키텍처: 서비스 기능이 복잡해지고 거대해질 수록 sw의 확장성/유연성이 줄어듦
    • MSA: 빠른 대응, 각 모듈 관리가 쉬워짐.
      -> 컨테이너는 수초내로 구성이 가능하고 여러 모듈에 독립된 환경을 제공해주기 때문에 MSA에서 많이 사용하고 있는 기술

Docker을 이용한 MSA 예시

  • 웹서비스에 부하 발생 -> 웹 서버 컨테이너만을 동적으로 늘려서 분산
  • 웹 서버와 DB 이미지 버전을 독립적으로 관리
  • 보통 직접 MSA를 구현하진 않음.
    -> 도커 스웜, 쿠버네티스 등 컨테이너 오케스트레이션 플랫폼 사용

진짜루다가 Docker가 가상머신보다 좋은가?

  • 컨테이너가 가볍다 -> 경량 하이퍼바이저도 많음
  • Docker는 배포가 편하다. -> 가상머신도 이미지 만들어서 배포하면 되고 배포 스크립트로 만들어도 됨.
  • msa에 유리하다 -> 클라우드 환경에서 가상머신도 msa 관리 관리함.
  • Docker를 사용해야 하는 이유?
    가볍다~ 배포가 편하다? 그것도 맞지만 이미지가 가장 큰 이점.
    아래 02 도커엔진 - 이미지 에서 자세히 보자.

02장. 도커 엔진

도커 사용해보기

컨테이너로 사용할 디스크 마운트

$ df -h
$ sudo fdisk -l
$ sudo fdisk /dev/sdb
$ sudo mkfs.ext4 /dev/sdb1
$ sudo mkdir -p /mnt/storage
$ sudo e2label /dev/sdb1 node_disk
$ sudo blkid
$ sudo vi /etc/fstab
$ cat /ect/fstab
  LABEL=cloudimg-rootfs   /        ext4   discard,errors=remount-ro       0 1
  LABEL=UEFI      /boot/efi       vfat    umask=0077      0 1
  LABEL=node_disk /mnt/storage    ext3    default 0 0
       
$ sudo mount -a
$ df -h
$ sudo chmod 777 /mnt/storage
$ mkdir -p /mnt/storage/docker
$ mkdir -p /mnt/storage/containerd

DOCKER 설치

$ sudo apt-get update
$ sudo apt-get install     ca-certificates     curl     gnupg
$ sudo install -m 0755 -d /etc/apt/keyrings
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
$ sudo chmod a+r /etc/apt/keyrings/docker.gpg
$ echo   "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" |   sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

DOCKER 데몬 서비스 만들기

$ sudo vi /etc/docker/daemon.json
{
        "data-root": "/mnt/storage/docker",
        "storage-driver": "overlay2"
}
$ sudo mkdir -p /etc/systemd/system/docker.service.d
$ sudo systemctl daemon-reload
$ sudo systemctl restart docker
$ systemctl status docker

아래 경로에 잘 쌓이고 있으면 정상

$ sudo ls /mnt/storage/docker/
buildkit  containers  engine-id  image  network  overlay2  plugins  runtimes  swarm  tmp  volumes

DOCKER 명령어 간략하게

  • pull: 허브에서 이미지 다운받음
  • create: 컨테이너 생성
  • start: 컨테이너 실행
  • attach: 컨테이너 접속
  • run == pull - create - start - attach
    컨테이너 생성/실행 명령어 로컬 도커 엔진에 없으면 도커 허브에서 자동으로 이미지를 내려 받음.
  • -i -t: 상호 입출력을 가능하게 하는 옵션
  • -d : 입출력 x
  • stop: 컨테이너 정지
  • rm: 컨테이너 삭제
  • container prune: 컨테이너 전부 삭제
  $ sudo docker run -i -t ubuntu:18.04
  Status: Downloaded newer image for ubuntu:18.04
  root@0c1c667dd261:/#  --> container id 12자리
  $ sudo docker ps -a
  CONTAINER ID   IMAGE          COMMAND       CREATED         STATUS                       PORTS     NAMES
  0c1c667dd261   ubuntu:18.04   "/bin/bash"   5 minutes ago   Exited (130) 4 seconds ago             wonderful_clarke
  $ sudo docker inspect wonderful_clarke
  $ sudo docker pull centos:7
  $ sudo docker images
  REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
  ubuntu       18.04     3941d3b032a8   5 weeks ago     63.1MB
  centos       7         eeb6ee3f44bd   19 months ago   204MB
  $ sudo docker inspect centos:7
  $ sudo docker create -it --name mydocker centos:7
  b8dafdf26aecadc3e1ec5ab8cff0b5991c781d2792ea0a76880242c03f89fbd6
  $ sudo docker start mydocker
  $ sudo docker attach mydocker # 컨테이너 접속
  [root@b8dafdf26aec /]# --> ^Q 입력 --> 컨테이너 종료하지 않고 접속만 해제

도커 이미지와 컨테이너

alicek106/ubuntu:22:04 == 저장소/이미지이름:태그

  • 도커는 레이어 이미지 구조를 갖고 있음.
  • 레이어는 추가될 떄마다 위에 쌓임
  • 새컨테이너를 만들 때 underlying layers 위에 writable layer를 추가
    -> container layer라 부르기도 함.
  • 실행 중인 컨테이너의 모든 변경 사항은 이 thin writable container layer에 기록
  • 공유하고 있는 layer는 새로 빌드나 배포를 할 필요가 없음. (속도 up)

UFS(Union File System)

  • 서로 다른 파일 시스템에 대해서 union mount 를 구현하는 linux용 file system 서비스
  • branch의 파일과 디렉토리를 투명하게 overlay하여 일관된 단일 file system을 형성
    ** 투명하다?: 유저가 내부적인 상세 로직을 몰라도 사용하는 데 어려움이 없다는 뜻

OverlayFS2

  • 두 개의 디렉토리를 계층화하고 단일 디렉토리로 제공 -> layer
  • 레이어를 통합하는 과정 -> union mount
  • 하위 디렉토리: lowerdir / 상위 디렉토리: uppderdir
  • unified view: merged라는 자체 디렉토리를 통해 노출

도커 컨테이너 다뤄보기

실습

여러 컨테이너를 연결해서 서비스 구축해보기

도커 볼륨

  • 이미지, 컨테이너
    도커 이미지로 컨테이너를 생성하면 이미지는 읽기 전용이 되고
    컨테이너의 변경사항만 별도 저장하여 각 컨테이너 정보를 보전한다.
    이미지에는 mysql 실행하는 데 필요한 애플리페이션 파일
    컨테이너에는 워드프레스에서 쓰는 게시글 등 db운용하면서 쌓이는 데이터

  • 컨테이너 레이어의 단점.

    • 컨테이너가 사라지면 운용 데이터도 사라짐
    • 이미지로 빌드시 너무나 많은 변경사항이 일어났기 때문에 레이어가 과도하게 쌓임

    -> 컨테이너 데이터를 영속적으로 관리하기 위한 방법으로 볼륨을 활용해볼 수 있음.

  • 볼륨 활용하기

    • 호스트와 볼륨 공유

      $ sudo docker run -d \
      --name wordpressdb_hostvolume \
      -e MYSQL_ROOT_PASSWORD=password \
      -e MYSQL_DATABASE=wordpress \
      -v ~/wordpress_db:/var/lib/mysql \ # [호스트 공유 디렉토리]:[컨테이너 공유 디렉토리]
      mysql:5.7

      ~/wordpress_db:/var/lib/mysql 이 둘은 동기화 되는 개념이 아니라 그냥 같은 디렉토리임.

    • -v 옵션으로 볼륨을 사용하는 다른 컨테이너와 볼륨을 공유

    • docker volume 명령어

도커 네트워크

  • 인터페이스 종류

    • eth0: 공인 or 내부 ip가 할당되어 실제로 외부와 통신할 수 있는 호스트의 네트워크 인터페이스
    • veth~: 각 컨테이너의 eth0과 연결.
    • docker0: 각 veth 인터페이스와 바인딩돼 호스트의 eth0과 연결.
    LDCC@instance-node-1:~$ ifconfig
    docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
            inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
            inet6 fe80::42:20ff:feb1:9b78  prefixlen 64  scopeid 0x20<link>
    ...
    ens4: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1460
            inet 10.178.0.5  netmask 255.255.255.255  broadcast 0.0.0.0
    ...
    lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
            inet 127.0.0.1  netmask 255.0.0.0
    ...
    
    veth2d31241: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
            inet6 fe80::34b2:8ff:fedb:d897  prefixlen 64  scopeid 0x20<link>
    ...
    vethd7140a9: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
            inet6 fe80::1879:46ff:fe19:5dd8  prefixlen 64  scopeid 0x20<link>
    ...

  • 드라이버 종류

    • 브릿지 네트워크: docker0이 아닌 사용자 정의 브리지를 새로 생성하여 각 컨테이너에 연결하는 네트워크 구조
    • 호스트 네트워크: 호스트 네트워크 환경 그대로 사용 -> 포트 포워딩 없이 바로 서비스 가능
    • 논 네트워크: 네트워크 x
    • 컨테이너 네트워크: 다른 컨테이너의 네트워크 네임스페이스 환경을 공유할 수 있음.

이미지 배포

# 이미지 생성
$ docker run -it --name --name commit_container1 ubuntu:14.04
$ docker commit commit_container1 my-ubuntu:0.0

# docker hub에 업로드하기 위해 이미지 태그 추가
$ docker tag my-ubuntu:0.0 dchecheb/my-ubuntu:0.0
$ docker tag my-ubuntu:0.0 asia-northeast3-docker.pkg.dev/${PROJECT_ID}/mygcr/my-ubuntu:0.0

Docker File 만들기

FROM ubuntu:14.04

LABEL maintainer "geoffyoon <geofff.yoon@gmail.com>"
LABEL "purpose"="practice"

RUN apt-get update
RUN apt-get install apache2 -y
ADD lotto.html /var/www/html
WORKDIR /var/www/html
RUN ["/bin/bash","-c","echo hello >> test.html"]
EXPOSE 80
CMD apachectl -DFOREGROUND
  • FROM: 생성할 이미지의 베이스 이미지
  • LABEL: 이미지의 메타데이터를 추가, 키-벨류 형태로 저장
  • RUN: 이미지를 만들기 위해 컨테이너 내부에서 명령어를 실행
  • ADD: 파일을 이미지에 추가.
  • WORKDIR: 명령어를 실행할 디렉토리 == cd
  • EXPOSE: 노출할 포트 지정. 바인딩은 X
  • CMD: 컨테이너가 시작할 때 실행할 명령어 설정

멀티스테이지 빌드

이미지 용량을 줄여서 빌드 & 배포하기 위해 사용함.
하나의 Docker File 안에 여러 개의 FROM 이미지를 정의함으로써 빌드 완료 시 최종적으로 생성될 이미지 크기를 줄임.

FROM golang
ADD main.go /root
WORKDIR /root
RUN go build -o /root/mainApp /root/main.go

FROM alpine:latest
WORKDIR /root
COPY --from=0 /root/mainApp .
CMD ["./mainApp"]

도커 컴포즈 사용하기

  • 여러 개 컨테이너가 하나의 애플리케이션으로 동작할 때 이를 테스트하려면 각 컨테이너를 하나씩 생성해야 함.
  • Run 명령을 여러번 쓰면 되지만 각 컨테이너의 헬스체크를 하면서 하기 번거로움
  • 여러 개 컨테이너를 하나의 서비스로 정의해서 컨테이너를 묶어서 관리할 수 있다면?! good~
  • 컨테이너를 이용한 서비스 개발과 CI를 위해 여러 개 컨테이너를 하나의 프로젝트로서 다룰 수 있는 작업 환경 제공
  • 여러 개 컨테이너의 옵션과 환경을 정의한 파일을 읽어 컨테이너를 순차적으로 생성
  • 서비스의 컨테이너 수를 유동적으로 조절할 수 있음
  • 각 컨테이너의 의존성, 네트워크, 볼륨 등을 함께 정의할 수 있음

아래 명령 2번을

$ docker run -d --name mysql \
alicek106/composetest:mysql \
mysqld

$ docker run -d -p 80:80 \
--link mysql:db --name web \
alicek106/composetest:web \
apachectl -DFOREGROUND

컴포즈로 하나로 묶을 수 있음.

version: '3.0' 	-- 파일 포멧 버전(1.2, 2.1, 3.0 ...)
services:		-- 생성될 컨테이너들을 묶어 놓은 단위
  web:			-- 생성될 서비스 이름
    image: alicek106/composetest:web	-- 컨테이너 생성할 때 쓰일 이미지 이름 설정
    ports:
      - "80:80"
    links:	-- 다른 서비스의 컨테이너에 대한 네트워크 링크를 정의
      - mysql:db
    command: apachectl -DFOREGROUND
  mysql:		-- 생성될 서비스 이름
    image: alicek106/composetest:mysql
    command: mysqld
  • 컴포즈 파일로 서비스 실행하기
$ docker compose up -d
$ docker compose ps # 생성된 컨테이너 확인 
NAME                    IMAGE                         COMMAND             SERVICE             CREATED              STATUS              PORTS
first_compose-mysql-1   alicek106/composetest:mysql   "mysqld"            mysql               About a minute ago   Up 59 second

컨테이너 이름:
[프로젝트명]-[서비스명]-[서비스 내에서의 컨테이너 번호] = first_compose-mysql-1

  • 컴포즈 관련 기타 명령어 사용해보기
$ docker compose up --scale mysql=3 -d # 같은 서비스에 컨테이너를 3개까지 늘림
$ docker compose down # 프로젝트 삭제
$ docker compose -p myproject up -d # 같은 yaml로 프로젝트 여러 개 생성 가능
$ docker compose -p myproject down # 프로젝트 이름 지정해서 삭제

도커 데몬

도커의 구조는 아래 2가지로 나뉜다.

  • 서버: 실제로 컨테이너를 생성하고 실행하며 이비지를 관리하는 주체. -> dockerd 프로세스로 동작
    -> 도커 프로세스가 실행되어 서버로서 입력 받을 준비가 된 상태를 도커 데몬이라고 함.
  • 클라이언트: 도커 CLI. 도커 데몬이 API입력을 받아 엔진의 기능을 수행하게 함.
profile
새로운 기술을 테스트하고 적용해보는 걸 좋아하는 서버 개발자

0개의 댓글