[DEV] 11주차. Docker & K8s (5)
1. Docker 정리
Docker를 실제 production 환경에서 사용할 때 유념할 점
- Docker Volumes
- Host volume은 보통 개발 시 소스코드를 바로 container 안으로 마운트하기 위해 사용
- Production에서는 named volumes를 사용해야 함
- Docker container는 read-only로 사용
- 내용을 바꿔야 한다면 실행 중인 컨테이너를 수정하지 말 것
- 항상 이미지를 새로 빌드하고 다시 컨테이너를 새로 실행
- 자동화가 중요해짐: CI/CD 프로세스
- 다수의 Docker container들을 다수의 호스트에서 실행 필요
- 용량 문제와 Fail-over (fail-tolerant)
Docker를 개인 생산성 향상을 위해 사용
- 개발 시 필요한 모듈을 Docker 이미지로 받아와서 컨테이너로 실행
-
여러 소프트웨어를 연동해서 개발 시 이들을 docker-compose로 설정
- 장점
- 일관된 방식으로 소프트웨어 설치 (문서화하고 매뉴얼하게 설치할 필요 X)
- 분리된 충돌없는 환경에서 소프트웨어 설치/실행
2. 서버 관리의 어려움
- 관리해야 하는 서버의 수가 늘어나면
- 어느 서버에 문제가 있는지
- 어느 서비스가 문제를 갖고 있는지
- 이런 문제들을 얼마나 빨리 알고 해결할 수 있을지
- 새로 들어온 사람이나 주니어를 잘 온보딩하려면?
- 문제들은 밤낮없이 연휴에도 발생
해결방안
- 문서화
- 지금 서비스 상황과 셋업 방법 문서화
- 다양한 문제 발생시 해결 방법 문서화
- 단점
- 문서를 현재 상황에 맞게 업데이트 하는 것이 매우 번거로움
- 또한, 상황에 따라 의미가 없는 경우도 많음
- 또한, 몇백대의 서버를 일일히 관리하고 명령을 실행하는 것은 거의 불가능
- 코드
- Infrastructure As Code: DevOps 엔지니어가 꼭 알아야 하는 기술
- 문서보다는 코드로 관리
- 대화형 명령보다는 자동화된 스크립트로 해결
- 다수의 서버들에 명령을 대신 실행해줌
- 다양한 툴들이 존재
- Chef
- Puppet
- Ansible
- Terraform
- 단점
- Learning curve가 높음
- 설치시 소프트웨어 충돌 문제에는 크게 도움이 되지 않음
- Virtual Machine
- 소프트웨어 충돌 해결을 위해 VM 사용
- 한 물리 서버에 다수의 VM을 올리고, 서비스별로 VM을 하나씩 할당
- 단점
- VM이 전반적으로 리소스 소비가 크고 느림
- 결정적으로 특정 VM 벤더 혹은 클라우드에 종속되어 버림 (Lock-in)
- 소프트웨어 충돌 해결을 위해 VM 사용
- Docker
- 모든 소프트웨어를 Docker Image로 만들면 어디에서든 동작
- 기본적으로 리눅스 환경에 최적
- VM에 비해 리소스 낭비도 적고 실행 시간도 빠름
- 오픈소스 -> 클라우드나 특정 업체 Lock-in 이슈도 없음
- 거의 단점이 없지만, container 수가 늘어나면서 관리가 힘들다는 점이 부각됨
- 모든 소프트웨어를 Docker Image로 만들면 어디에서든 동작
Docker
- 서비스 배포의 기본이 됨
- 빌드 프로세스 출력물은 Docker Image가 되고 있음
- Github에서 빌드 프로세스를 보면 docker image를 만들고, 이를 내부 Registry에 등록하는 것이 일반적
- 그러다보니 다수의 Docker Image들을 더 많은 수의 Docker Container로 실행, 관리하는 것이 필요해짐
- 모든 것의 컨테이너화 -> Containerization이라고 부름
Docker 서비스 배포 과정
- Docker Image를 기준으로 프로세스가 만들어짐
- 컨테이너의 수가 기하급수적으로 늘어난다면 컨테이너를 효율적으로 관리할 수 있는 도구가 필요!
- 다수의 컨테이너를 동시에 관리
- 놀고 있는 서버나 너무 바쁜 서버를 어떻게 알아낼지?
- 마이크로서비스의 등장으로 인한 서비스 수 증가로 어떤 서비스들이 있는지 쉽게 찾을 수 있는 방법 필요
- 모니터링을 어떻게 할 것인지
- 특정 서비스의 컨테이너 수를 탄력적으로 어떻게 운영할 것인지
마이크로서비스
- 웹 서비스를 다수의 작은 서비스들로 구현하는 방식
- 각 서비스들은 팀 단위로 원하는 언어/기술로 개발하는 자율성을 가짐
- 각 서비스들은 계약관계로 지켜야하는 책임이 있고, 서비스 정보를 등록해야 함
- Service Registry
- 특징
- Decentralization (탈중앙화)
- Modularity (모듈화)
- Domain driven desgin
- Focus on empowering teams
3. Container Orchestration
-
다수의 container들을 관리하기 위한 도구
- 한 클러스터 안에 다양한 서비스들이 공존 (DB, Web Service, Backend, …)
- 자원 요청을 받아 마스터가 자원 할당
- 다양한 기능 제공 (배포, 스케일링, 네트워크, 인사이트 등)
소프트웨어 배포
- 서비스 이미지를 Container로 배포
- 이상이 감지되면 이전 안정 버전으로 롤백
- v1에서 v2로 배포되는 경우 문제가 생기면 v1으로 롤백
- 컨테이너의 수가 많을수록 큰 이슈가 됨
- DevOps 팀 관점에서 보면 가장 중요한 기능
스케일링
- 특정 서비스의 Container 수를 쉽게 늘리고 줄이는 것
- 이때 서버의 utilization도 고려
- 너무 바쁘거나 놀고있는 서버가 없도록
네트워크
- 서비스가 다수의 컨테이너로 나눠지면서 이들을 대표하는 Load Balancer를 만들어주어야 함
- 서비스들 간에 서로를 쉽게 찾을 수 있어야 함
- 서비스 디스커버리
인사이트
- 노드/컨테이너 문제시 해결
- 서버 2의 F가 다운되면 이를 서버 3에 재실행
- F 로드밸런서 정보도 알맞게 수정
- Logging/Analytics 등의 기능 제공
- 외부 서비스 plug and play
- 전체 서비스 분석
- 시각화
- 문제 분석
4. K8s
- 컨테이너 기반 서비스 배포/스케일/관리 자동화를 해주는 오픈소스 프레임워크
- 클라우드나 on-prem 모두 동작
- 어느 컨테이너든 가능하지만 주로 Docker Container들이 대상이 됨
- 물리서버나 가상서버 위에서 모두 동작
- 지금은 Cloud Native Computing Foundation이라는 비영리 단체에서 운영
- 클라우드 환경에서 어떻게 소프트웨어를 배포하는 것이 효율적일까
- 컨테이너, 서비스메시, 마이크로서비스, API, DevOps, On-demand Infra
- 클라우드 환경에서 어떻게 소프트웨어를 배포하는 것이 효율적일까
- 가장 많이 사용되는 컨테이너 오케스트레이션 시스템
- 모든 글로벌 클라우드 업체들이 지원: EKS, AKS, GKE
- 확장성이 좋아 다양한 환경에서 사용됨
- ML: Kubeflow
- CI/CD: Tekton
- Service Mesh: Istio
- Serverless: Kubeless
- 다수의 서버에 컨테이너 기반 프로그램을 실행하고 관리
- 컨테이너 기반 프로그램 == Docker Container
- 보통 Docker와 K8s는 같이 사용됨
- Pod: 같은 디스크와 네트워크를 공유하는 하나 이상의 컨테이너들의 집합
기본 구조 - 마스터 노드
- 노드: 물리서버 / 가상서버
- 클러스터: 하나 이상의 노드의 집합
- 마스터는 클러스터를 관리해주는 역할
기본 구조 - K8s 프로세스들
- Master 안에는 여러 프로세스들이 돌고 있음
- API Server (Container로 동작): kube-apiserver
- Entrypoint of K8s cluster
- Web UI, CLI (kubectl), API
- Scheduler
- Pods 생성과 할당 (노드들의 utilization 고려)
- Controller Manager
- 전체 상황을 모니터링하고 fault tolerance 보장
- Master는 High Availability가 중요함
- etcd
- K8s 환경 설정 정보가 저장되는 key/value 스토어로 백업됨
- API Server (Container로 동작): kube-apiserver
- Controller runtime
- 대부분 Docker가 사용됨
Pod
- K8s 사용자가 사용하는 가장 작은 빌딩 블록
- K8s에서 컨테이너를 바로 다루지 않음
- 하나의 Pod는 보통 하나의 Container로 구성
- 하나보다 많은 경우에는 보통 helper container가 같이 사용됨
- 같은 Pod 안에서는 디스크와 네트워크가 공유됨
- Fail-over를 위해서 replicas를 지정하는 것이 일반적
- 다양한 방법으로 복제본 유지
- Pod는 네트워크 주소를 갖는 self-contained server
YAML 환경 설정 예시
apiVersion: apps/v1
kind: Pod
# POD, Service, ReplicaSet, Deployment ..
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
Pod 생성 예
kubectl create -f pod-definition.yml
kubectl get pods
kubectl describe pod nginx
kubectl run nginx --image nginx