1장 도커 복습과 Hello, Kubernetes

1.1 도커복습

알아야 할 도커지식

  • 컨테이너 설계
  • 파일 작성법
  • 이미지 빌드
  • 레지스트리로 이미지 푸시

1.1.1 도커 컨테이너란?

  • 컨테이너는 도커 이미지를 기반으로 실행되는 프로세스
  • 환경의 영향을 받지 않아 이식성이 높다

1.1.2 도커 컨테이너 설계

  • 1 컨테이너당 1 프로세스
  • 변경 불가능한 인프라(Immutable Infrastructure) 이미지로 생성한다.
  • 경량의 도커 이미지로 생성한다.
  • 실행 계정은 root 이외의 사용자로 한다.

1 컨테이너당 1 프로세스

  • 관례임으로 안지키면 도커의 에코시스템과 맞지않아 관리가 힘들어짐.

변경 불가능한 인프라(Immutable Infrastructure) 이미지로 생성

  • 컨테이너 기동 후에 외부 실행 바이너리, 또는 외부 패키지를 설치하면 컨테이너 실행 결과가 달라질 수 있음.
  • 관련 리소스를 가능한 이미지에 포함시켜 최대한 일관된 결과를 보장

경량의 도커 이미지로 생성한다.

  • 도커 이미지가 무거우면 (다운로드를 통해 이미지를 가져오기 때문에) 배포가 느려짐.
  • 빌드 단계에서만 사용되는 패키지를 제거, 경량 배포판(알파인, scratch) 이미지를 사용, 도커 빌드 레이어 수를 줄이는 등등의 방법 있음.

실행 계정은 root 이외의 사용자로 한다.

  • 보안사고 예방

1.1.3 도커 파일 작성법

image

  • FROM에서는 기반이 되는 도커 이미지를 지정
  • COPY 명령으로 빌드할 머신에 있는 파일을 컨테이너에 복사
  • RUN 명령은 빌드 시에 컨테이너에서 명령어를 실행
  • ENTRYPOINT 명령과 CMD 명령은 컨테이너가 기동할 때 실행하는 명령어
  • ENTRYPOINT에 기본적으로 바꿀 필요가 없는 부분을 정의
  • CMD에 기본값 인수 등을 정의

image image

1.1.4 도커 이미지 빌드

  • docker image build 명령어를 사용
  • -t 옵션으로 이미지의 이름과 태그를 지정
  • 태그는 버전을 지정하는 것이 일반적
멀티 스테이지 빌드

image

  • 여러 컨테이너 이미지를 사용해 빌드하고 결과물만 실행용 컨테이너 이미지에 복사
  • 이미지가 경량화되고 보안측면도 더 나음.
  • 빌드킷(https://github.com/moby/buildkit) 등으로 빌드 의존 관계를 자동 파악해 병렬 처리하는 것도 가능

1.1.5 이미지 레이어 통합과 이미지 축소화

  • 다이브(https://github.com/wagoodman/dive)로 레이어의 용량 소비를 조사 가능함.
  • docker image build 시 --squash옵션을 사용하면 한 개의 레이어로 통합 (아직 실험적 experimental 기능)

1.1.6 도커 레지스트리로 이미지 업로드

  • 레지스트리는 도커 이미지를 보관하는 저장소 서버
  • 되도록 비공식 이미지 보단 공식 이미지를 사용할 것을 권장

image

1.1.7 컨테이너 기동

  • 쿠버네티스를 사용하면 직접 도커 명령어를 사용하지 않음

image

2장 왜 쿠버네티스가 필요할까?

2.1 쿠버네티스란?

  • 애플리케이션의 배포, 확장 등을 관리하는 것을 자동화하기 위한 플랫폼
  • 도커(단독으로)는 여러 도커 호스트를 동시에 동작, 통합 관리하는 기능을 제공하지 않음

2.2 쿠버네티스의 역사

  • 구글이 내부적으로 사용하던 컨테이너 클러스터 관리 도구 Borg에서 파생된 오픈 소스
  • 리눅스 재단 산하의 클라우드 네이티브 컴퓨팅 파운데이션(CNCF)으로 이관
  • 사실상 표준이 된 배경에는 대형 클라우드 사업자(구글, 애저, 아마존등)가 쿠버네티스 관리형 서비스를 제공한다는 점 때문

2.3 쿠버네티스를 사용하면 무엇을 할 수 있을까?

  • 여러 쿠버네티스 노드 관리
  • 컨테이너 스케줄링
  • 롤링 업데이트
  • 스케일링/오토 스케일링
  • 컨테이너 모니터링
  • 자동화된 복구
  • 서비스 디스커버리
  • 로드 밸런싱
  • 데이터 관리
  • 워크로드 관리
  • 로그 관리
  • 선언적 코드를 사용한 관리
  • 그 외 에코시스템과의 연계 및 확장

2.3.1 선언적 코드를 사용한 관리(IaC)

YAML, JSON 형식으로 작성한 선언적 코드(매니페스트)로 리소스를 관리

2.3.2 스케일링/오토 스케일링

같은 이미지 기반의 컨테이너 수를 자동으로 늘리거나 줄여 부하를 분산함

2.3.3 스케줄링

어피니티, 안티어피니티(https://kubernetes.io/ko/docs/concepts/scheduling-eviction/assign-pod-node/#%EC%96%B4%ED%94%BC%EB%8B%88%ED%8B%B0-affinity-%EC%99%80-%EC%95%88%ED%8B%B0-%EC%96%B4%ED%94%BC%EB%8B%88%ED%8B%B0-anti-affinity)을 사용해 워크로드 특징이나 노드 성능을 기준으로 컨테이너를 어느 노드에 배치할 것인지 제어 가능.

2.3.4 리소스 관리

  • (따로 스케줄링 설정이 없으면) 노드의 CPU나 메모리의 여유 리소스 상태에 따라 자동 스케줄링
  • 리소스 상태에 따라 자동적으로 클러스터에 노드 추가나 삭제도 가능

2.3.5 자동화된 복구

  • 컨테이너 프로세스 정지를 감지하면 자동 재배포
  • 노드가 제거되도 컨테이너를 다른 노드로 자동 복구함

2.3.6 로드 밸런싱과 서비스 디스커버리

  • 로드 밸런서 기능(서비스, 인그레스)을 제공
  • 컨테이너의 확장, 업데이트, 또는 장애가 발생했을 때 필요한 엔드 포인트 서비스 변경 작업(컨테이너 등록, 삭제, 분리등)을 자동 수행
  • 서비스 디스커버리 기능으로 복수의 서비스간 연계가 쉬움. (마이크로 서비스 구축 용이)

2.3.7 데이터 관리

  • 내부 백엔드 데이터 스토어로 etcd 사용
  • 안전하고 이중화된 상태로 중앙 집중 관리

2.4 정리

쿠버네티스를 사용하면 컨테이너의 이동성과 경량화를 활용한 빠른 개발과 전체 시스템의 배포 자동화를 구현할 수 있다.

3장 쿠버네티스 환경 선택

생략합니다. 나중에 여유 있으면 하겠음

4장 API 리소스와 kubectl

4.1 이 책을 읽기 위한 준비

  • CLI 도구인 kubectl을 설치
  • 쿠버네티스 클러스터 생성

4.2 쿠버네티스 기초

  • 쿠버네티스는 k8s 마스터와 k8s 노드로 구성
  • k8s 마스터는 API 엔드포인트 제공, 컨테이너 스케줄링, 스케일링 등을 담당
  • k8s 노드는 컨테이너를 기동시키는 노드
  • kubectl이 매니페스트 파일(YAML,JSON)을 바탕으로 쿠버네티스 마스터에 리소스를 등록

4.3 쿠버네티스와 리소스

4.3.1 워크로드 API 카테고리

컨테이너를 기동하기 위해 사용되는 리소스. 내부적으로 사용하는 것외 사용자가 직접 관리할 수 있는 것은 아래 8가지.

  • 파드(Pod)
  • 레플리케이션 컨트롤러(ReplicationController)
  • 레플리카셋(ReplicaSet)
  • 디플로이먼트(Deployment)
  • 데몬셋(DaemonSet)
  • 스테이트풀셋(StatefulSet)
  • 잡(Job)
  • 크론잡(CronJob)

4.3.2 서비스 API 카테고리

서비스 디스커버리와 클러스터 외부 접속이 가능한 엔드포인트 제공하는 리소스.

  • 서비스
    • ClusterIP
    • ExternalIP(ClusterIP의 한 종류)
    • NodePort
    • LoadBalancer
    • Headless(None)
    • ExternalName
    • None-Selector
  • 인그레스

4.3.3 컨피그 & 스토리지 API 카테고리

설정과 기밀 데이터를 컨테이너에 담거나 영구 볼륨을 제공하는 리소스.

  • 시크릿(Secret)
  • 컨피그맵(ConfigMap)
  • 영구 볼륨 클레임(PersistentVolumeClaim)

4.3.4 클러스터 API 카테고리

클러스터 동작(보안 관련 설정이나 정책, 클러스터 관리성을 향상시키는 기능)을 정의하는 리소스.

  • 노드(Node)
  • 네임스페이스(Namespace)
  • 영구 볼륨(PersistentVolume)
  • 리소스 쿼터(ResourceQuota)
  • 서비스 어카운트(ServiceAccount)
  • 롤(Role)
  • 클러스터 롤(ClusterRole)
  • 롤바인딩(RoleBinding)
  • 클러스터롤바인딩(ClusterRoleBinding)
  • 네트워크 정책(NetworkPolicy)

4.3.5 메타데이터 API 카테고리

내부의 다른 리소스 동작을 제어하기 위한 리소스.

  • LimitRange
  • HorizontalPodAutoscaler(HPA)
  • PodDisruptionBudget(PDB)
  • 커스텀 리소스 데피니션(CustomResourceDefinition)

4.4 네임스페이스로 가상적인 클러스터 분리

  • 네임스페이스는 가상적인 쿠버네티스 클러스터 분리 기능
  • 하나의 클러스터를 여러 팀에서 사용하거나 서비스/스테이징/개발 환경으로 구분하는 경우 사용
  • 클러스터를 (여러 팀에서) 공용으로 사용하지 않고 시스템이 단순하면 기본 네임스페이스만 사용하는 것도 괜찮음.

저자 추천

아래 3가지 이유로 저자는 서비스/스테이징/개발 환경으로 나누는 용도 보단 마이크로서비스를 개발하는 팀 단위로 나눌 것을 추천.

  • 클러스터 장애시 모든 환경에서 장애가 나는 것을 격리, 차단할 수 있음.
  • 매니페스트 파일 재사용성이 떨어짐. (같은 리소스임에도 prod 매니페스트랑 dev 매니페스트로 나뉨)
  • 위와 같은 이유로 같은 리소스의 서비스 주소가 달라짐. (ex, SERVICE.prod.svc.cluster.local과 SERVICE.dev.svc.cluster.local)

4.5 커맨드 라인 인터페이스(CLI) 도구 kubectl

image

CLI 도구인 kubectl을 사용해 마스터의 API 요청을 보내 클러스터를 조작

4.5.1 인증 정보와 컨텍스트(config)

image

  • 쿠버네티스 마스터와 통신할 때 필요한 접속 대상의 서버, 인증 정보.
  • clusters, users, contexts 3가지 정보로 구성
  • clusters는 접속 대상 클러스터 정보
  • users는 사용자 인증 정보
  • contexts는 사용할 cluster와 user, 네임스페이스 조합.
  • 조합된 컨텍스트를 전환해, 여러 환경을 여러 권한으로 조작 가능

image image image

4.5.2 kubectx/kubens를 사용한 전환

kubectx/kubens(https://github.com/ahmetb/kubectx) 사용하면 컨텍스트, 네임스페이스 전환이 kubectl 명령어를 사용하는 것 보다 편리함.

image image

4.5.3 매니페스트와 리소스 생성/삭제/갱신

  • 리소스를 생성할 때는 kubectl create 명령어
  • 생성한 파드는 kubectl get pods 명령어로 확인 가능
  • 삭제할 때는 kubectl delete 명령어
  • --wait 옵션은 리소스 처리가 끝나고 명령어가 종료됨. (기본은 명령어가 비동기로 실행, 기다리지 않는다)
  • 즉시 강제 삭제는 --force 옵션
  • 리소스 업데이트는 kubectl apply 명령어
  • 기존 리소스가 없을 때 kubectl apply는 kubectl create와 동일
  • kubectl create 따로 사용하는 것 보단 kubectl apply로 통일하는 것이 편리
  • (특정 리소스 경우) 최초 생성 후에 kubectl apply로 변경할 수 없는 필드도 존재함.

4.5.4 리소스 생성에도 kubectl apply를 사용해야 하는 이유

  1. kubectl apply에 create 기능이 포함되어 있어서 애초 구분이 불필요.
  2. k8s는 필드삭제를 이전 매니페스트와 적용될 다음 매니페스트를 비교해 정하는데 create는 이전 매니페스트 정보를 저장하지 않아서 필드 삭제가 누락될 수 있음.

image image

4.5.5 Server-side apply

  • 클라이언트(kubectl)에서 변경사항을 계산해 요청을 보내기 때문에 (Client-side apply) 여러 사용자가 동시에 같은 필드를 변경하는 경우 경합 현상이 발생.
  • kubectl 이름을 기록하고 서버 측에서 변경 사항을 계산, 충돌 감지하는 기능 (Server-side apply) 도입
  • 충돌 감지만 제공할 뿐, 해결은 사용자가 직접 해야함.
  • --server-side 옵션을 사용
  • 동일한 kubectl일지라도 강제로 --field-manager 옵션을 통해 kubectl 이름을 바꿔 충돌감지가 가능함.

개인생각 노트: 충돌 해결을 직접해야 하기 때문에 여러 사용자가 동일한 리소스를 관리해야 한다면 매니페스트에 대한 버전 관리가 필요해보임 (argocd?)

image

4.5.6 파드 재기동

  • rollout restart로 디플로이먼트 등의 리소스와 연결되어 있는 모든 파드를 재기동.
  • 단독 파드에서는 사용할 수 없음.

개인생각 노트: 롤 아웃이 레플리카셋과 같은 여러 팟 그룹을 swap하면서 이뤄지기 때문에 단독 팟보다 더 높은 추상화 리소스가 요구되는 것 아닌가하는?

image

4.5.7 generateName으로 임의의 이름을 가진 리소스 생성

  • kubectl create로 리소스 생성시, generateName 값에 난수를 붙여 팟 이름을 자동생성
  • kubectl apply에서는 사용할 수 없음.

개인생각 노트: apply에서 사용할 수 없는 이윤 아마 본래 기존 리소스를 수정하는 기능이니깐 매번 새로 난수 이름 생성하는 내용을 허용하게 되면 본래 기능이 무의미해지기 때문인듯?

4.5.8 리소스 상태 체크와 대기(wait)

  • kubectl wait 명령어는 리소스가 지정한 상태가 될 때까지 대기함.
  • --for옵션 뒤에 상태 지정
  • --timeout 옵션으로 최대 대기 시간 지정 (기본은 30초)
  • 리소스 대신 매니페스트 파일이 대상이 될 때, (매니페스트의) 모든 리소스가 같은 상태가 될 때 까지 대기함.

4.5.9 매니페스트 파일 설계

하나의 매니페스트 파일에 여러 리소스를 정의

  • 파드를 기동하는 워크로드 리소스와 외부에 공개하는 서비스 리소스를 묶어 하나의 매니페스트 파일로 정의하는 것이 일반적
  • 실행 순서를 정확하게 지켜야 하거나 리소스 간의 결합도를 높일 때 하나로 정의
  • 공통으로 사용되는 리소스(컨피그맵, 시크릿)는 별도 매니페스트로 분리
  • 위에서부터 정의된 리소스 순서대로 적용됨.
  • 중간에 문법 에러등으로 중단 시, 이후 리소스는 적용되지 않음.

여러 매니페스트 파일을 동시에 적용

  • kubectl apply 실행 시, 디렉토리 지정 가능
  • 파일명 순으로 적용 (순서를 지켜야하면 파일명 앞에 실행순서 넘버링)
  • -R 옵션은 하위 디렉토리의 매니페스트 파일까지 재귀적으로 적용됨.
  • 문법 에러등으로 중단 시, 중단된 파일의 이후 리소스는 마찬가지 적용되지 않으나 다른 매니페스트는 적용함.

매니페스트 파일 설계 방침

  • 많이 쓰이는 3가지 패턴
    • 규모가 크지 않을 경우 디렉토리 하나로 관리하는 패턴
    • 서브시스템, 부서별, 내부정책에 따른 그루핑등으로 나눠 관리하는 패턴
    • 마이크로서비스 별로 나눠 관리하는 패턴 (서비스간 적용순서를 제어하기 어려움)
  • 개발 팀의 구성(조직별로 변경 가능한 범위등)을 고려하는 것도 중요
    • 개발 조직도와 매니페스트 관리구조가 서로 유사하게 구성됨.

image image image

4.5.10 어노테이션과 레이블

어노테이션

레이블

4.5.11 Alpha Prune을 사용한 리소스 삭제: -prune 옵션

4.5.12 편집기로 편집: edit

4.5.13 리소스 일부 정보 업데이트: set

4.5.14 로컬 매니페스트와 쿠버네티스 등록 정보 비교 출력: diff

4.5.15 사용 가능한 리소스 종류의 목록 가져오기: api-resources

4.5.16 리소스 정보 가져오기: get

4.5.17 리소스 상세 정보 가져오기: describe

4.5.18 실제 리소스 사용량 확인: top

4.5.19 컨테이너에서 명령어 실행: exec

4.5.20 Alpha 파드에 디버깅용 임시 컨테이너 추가: debug

4.5.21 로컬 머신에서 파드로 포트 포워딩: port-forward

4.5.22 컨테이너 로그 확인: logs

4.5.23 스턴을 사용한 로그 확인

4.5.24 컨테이너와 로컬 머신 간의 파일 복사: cp

4.5.26 kubectl에서 디버깅

4.5.27 kubectl의 기타 팁

4.6 정리