1. 컨테이너란?
- 애플리케이션 레벨에서 필요한 소스 코드, 라이브러리 등 모든 파일을 하나의 런타임 환경으로 패키징하는 기술.
- namespace
- 컨테이너에 대한 격리 rPcmd wprhd
- cgroup
- 애플리케이션을 특정 리소스 사용 세트로 제한.
- 컨테이너의 장점
- 표준화에 따른 이식성: OS 플랫폼, 클라우드 간 이식 가능
- 경량화 및 민첩성: 일반 가상화에 비해 가벼워 더 빠른 빌드 가능
- 신속한 확장성: 같은 인프라에 더 많은 컨테이너 지원 가능. 신속한 스케일링 또한 가능.
- 애자일한 프로젝트 운영에 잘 맞음
- 신속한 출시 주기, 통합 및 파이프라인의 글로벌 자동화, 팀 간의 긴밀한 협업을 통해 소프트웨어 제품을 지속적으로 개선하는 프로세스를 구성하는 데 필요한 이점을 모두 갖추고 있음.
2. Docker란?
- 컨테이너 가상실행 환경을 제공해주는 대표적인 오픈소스 플랫폼.
- Image
- 컨테이너를 정의하는 읽기 전용 템플릿
- reusable함.
- immutable함.
- Dockerfile
- 도커 이미지를 생성하기 위한 명세서
- 컨테이너에 이미지를 설치하기 위해 필요한 각종 명령어나 설정들이 들어 있음.
- 이미지의 레이어
- 기존의 이미지 내용들이 레이어화되어 추가되는 형태.
- 이 레이어 방식 때문에 이미지의 수정이 있어도 경량화가 유지될 수 있음.
- 도커 레지스트리와 허브
- 도커 허브에 기본적으로 이미지를 올리고 내려받아 쓰고 할 수 있다.
- AWS 같은 경우 ECR이라는 레지스트리에 이미지를 등록해서 쓸 수 있다.
2020년 이후 쿠버 1.20 이상에서 도커 지원중단 이슈
쿠버는 CRI(container runtime interface)를 통해 컨테이너 런타임과 통신함. 도커는 해당 인터페이스를 지원하지 않아 DockerShim을 이용해서 억지로 호환되게 하고 있었음.
이게 오버헤드를 일으키는 문제가 있어서 containerd, cri-o를 사용하면 CRI 이슈가 해결이 되기 때문에 docker대신 위와 같은 다른 컨테이너 런타임을 이용하면 해결이 됨.
하지만 개발자 입장에서는 도커 이미지를 생성하고 사용해도 됨.
쿠버 운영자가 런타임을 다른 걸로 조정해줘야 함.
→ 클러스터를 수동으로 작성해서 사용하는 게 아니고 EKS 등의 클라우드에서 지원해주는 클러스터 생성툴을 사용하면 아무 문제가 없음.
주요 도커 명령어
도커 허브에서 이미지 가져오기
docker search nginx docker search nginx --filter stars=100 결과 NAME DESCRIPTION STARS OFFICIAL AUTOMATED nginx Official build of Nginx. 19230 [OK] nginxinc/nginx-unprivileged Unprivileged NGINX Dockerfiles 133 nginxproxy/nginx-proxy Automated Nginx reverse proxy for docker con… 115 nginxproxy/acme-companion Automated ACME SSL certificate generation fo… 126 bitnami/nginx Bitnami nginx Docker Image 177 [OK] ubuntu/nginx Nginx, a high-performance reverse proxy & we… 103
서치 후 가져오기
docker image pull ubuntu docker image pull nginx 버전을 명시하지 않으면 기본적으로 :latest 로 가져온다.
도커 이미지 실행하기
docker run nginx
실행 컨테이너 상태 보기
docker ps
실행 시 포트 설정하기
docker run -p 8080:80 nginx
running 되지 않는 컨테이너 상태까지 보기
docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 28e87ebdbb3b ubuntu "/bin/bash" 23 seconds ago Exited (0) 22 seconds ago serene_thompson 97ec539256e7 nginx "/docker-entrypoint.…" 59 seconds ago Exited (0) 35 seconds ago mystifying_lumiere 7db4b3a9e209 nginx "/docker-entrypoint.…" 2 minutes ago Exited (0) About a minute ago youthful_cohen ... 대신 다 보여주는 옵션 docker ps --no-trunc -a
우분투 이미지는 run ubuntu해도 실행이 안 된다. ubuntu 이미지에는 task가 없기 때문에 올라오자마자 할 일이 없어서 그냥 바로 내려간 것이다.
-it 옵션: 컨테이너를 종료하지 않은 채로 컨테이너에 명령을 전달할 때 사용
docker run -it --name test-ubuntu ubuntu docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d507cda8c13b ubuntu "/bin/bash" 20 seconds ago Up 20 seconds test-ubuntu
위와 같이 -it 옵션을 붙이면 bash 셀이 실행중이라 바로 꺼지지 않고 남아있는 것을 알 수 있다.
-d 옵션: 컨테이너를 백그라운드로 돌리는 옵션
docker run -it -d --name test2-ubuntu ubuntu
응답으로 컨테이너 ID가 출력된다.
도커 컨테이너 중지 및 삭제
docker stop 컨테이너ID ps -a 해도 안나오도록 컨테이너 관리에서도 없애버리는 것. docker rm 컨테이너ID
터미널에서 진행한 내용도 도커 데스크탑에서 확인이 가능하다.
로그 확인하기
docker logs 컨테이너ID 스트리밍하기 docker logs -f 컨테이너ID
직접 이미지 만들어 보기
Dockerfile 작성
FROM
- 기반 이미지 지정(최대한 가벼운 alpine 같은걸로 지정하는 게 보통)
MAINTAINER
- 이미지 관리자 정보 표시 (요즘은 LABEL을 더 많이 사용)
LABEL
- 이미지의 메타데이터 지정
USER
- 명령어 실행 계정
WORKDIR
- 명령어를 실행할 작업 디렉터리 지정
RUN
- 컨테이너 안에서 명령어를 실행
EXPOSE
- 컨테이너 실행시 Listen할 포트 지정
ADD
- 로컬 파일을 이미지에 추가
COPY
- 로컬 디렉터리에서 읽어들인 컨텍스트로부터 이미지에 파일을 복사
CMD
- 컨테이너 기동시 실행할 명령어 인수
ENTRYPOINT
- 컨테이너 기동시 실행할 명령어 (CMD를 오버라이드함.)
# Start with a base image containing Java runtime FROM adoptopenjdk/openjdk15:alpine-jre # Add Author info LABEL maintainer="hyeonhyeop.lee@wefunding.com" # Add a volume to /tmp VOLUME /tmp # Make port 8080 available to the world outside this container EXPOSE 8080 # The application's jar file ARG JAR_FILE=api/build/libs/api-0.0.1-SNAPSHOT.jar # Add the application's jar to the container ADD ${JAR_FILE} seoul-api-local.jar # Run the jar file ENTRYPOINT ["java","-jar","-Dspring.profiles.active=dev","/seoul-api-local.jar"]
docker image build -t 이미지이름 .
도커 이미지를 도커 헙에 올리기
docker push
쿠버네티스 구축 환경
로컬 환경
- 물리머신 내에서 구축. 테스트, 스터디용
- Minicube
- Docker Desktop for Mac/Windows
- Manual 구축 with tool
- 도구를 이용해서 원하는 곳에 클러스터를 구축
- kubeadm, kops, Rancher…
- 관리형 k8s 서비스 (CSP 제공)
- AWS EKS
- GCP GKE
- Azure AKS
- 나는 NKS(NHN k8s service)
minikube
- 쿠버네티스를 로컬에서 실행할 수 있는 도구
- 단일 노드 all in one 구성으로 이중화가 보장되지 않기 때문에 상용에서 사용 불가
- 로컬 가상 머신에 쿠버를 구성하기 때문에 하이퍼바이저 설치 필요
- kubectl 사용
kubectl
- k8s 클러스터와 통신하기 위한 CLI 도구
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/arm64/kubectl"
로 설치한다. 애플 실리콘 기준.
바이너리 실행 가능 권한 추가
chomod +x ./kubectl
바로 실행가능하도록 위치 변경
sudo mv ./kubectl /usr/local/bin/kubectl sudo chown root: /usr/local/bin/kubectl
설치 잘 되었는지 확인
kubectl version --client --output=yaml clientVersion: buildDate: "2023-10-18T11:42:52Z" compiler: gc gitCommit: a8a1abc25cad87333840cd7d54be2efaf31a3177 gitTreeState: clean gitVersion: v1.28.3 goVersion: go1.20.10 major: "1" minor: "28" platform: darwin/arm64 kustomizeVersion: v5.0.4-0.20230601165947-6ce0bf390ce3
brew install을 이용해도 됨.
자동완성 활성화 & alias 등록 (zsh 기준)
source <(kubectl completion zsh) alias k=kubectl compdef __start_kubectl k
이렇게 하면 k로 kubectl을 대신해서 쓸 수 있다.
minikube 설치
brew install minikube
$ minikube start 😄 Darwin 13.3.1 (arm64) 의 minikube v1.32.0 ✨ 자동적으로 docker 드라이버가 선택되었습니다 📌 Using Docker Desktop driver with root privileges 👍 minikube 클러스터의 minikube 컨트롤 플레인 노드를 시작하는 중 🚜 베이스 이미지를 다운받는 중 ... 💾 쿠버네티스 v1.28.3 을 다운로드 중 ... > preloaded-images-k8s-v18-v1...: 341.16 MiB / 341.16 MiB 100.00% 6.63 Mi > gcr.io/k8s-minikube/kicbase...: 410.58 MiB / 410.58 MiB 100.00% 5.62 Mi 🔥 Creating docker container (CPUs=2, Memory=4000MB) ... 🐳 쿠버네티스 v1.28.3 을 Docker 24.0.7 런타임으로 설치하는 중 ▪ 인증서 및 키를 생성하는 중 ... ▪ 컨트롤 플레인이 부팅... ▪ RBAC 규칙을 구성하는 중 ... 🔗 Configuring bridge CNI (Container Networking Interface) ... 🔎 Kubernetes 구성 요소를 확인... ▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5 🌟 애드온 활성화 : storage-provisioner, default-storageclass 🏄 끝났습니다! kubectl이 "minikube" 클러스터와 "default" 네임스페이스를 기본적으로 사용하도록 구성되었습니다. docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 5c99149028dc gcr.io/k8s-minikube/kicbase:v0.0.42 "/usr/local/bin/entr…" 52 seconds ago Up 51 seconds 127.0.0.1:57794->22/tcp, 127.0.0.1:57795->2376/tcp, 127.0.0.1:57797->5000/tcp, 127.0.0.1:57798->8443/tcp, 127.0.0.1:57796->32443/tcp minikube
미니큐브가 도커 기반으로 실행되었기 때문에 도커 컨테이너 위에 쿠버네티스를 설치한 것이다.
kubeconfig
클러스터 인증 정보와 컨텍스트
- kubectl이 kubenetes와 통신할 때 필요한 접속 대상의 서버정보, 인증 정보 등을 정의
- current-context가 어디인지 아는 게 중요하다.
- dev, prod, QA 등 목적에 따라 클러스터를 따로 가져가는 게 보통이기 때문이다.
k config current-context minikube k config get-contexts CURRENT NAME CLUSTER AUTHINFO NAMESPACE * minikube minikube minikube default
클러스터 탐색하기
k get node NAME STATUS ROLES AGE VERSION minikube Ready control-plane 6m36s v1.28.3
all-in-one node이기 때문에 한 개만 뜨는 게 맞다.
k get ns NAME STATUS AGE default Active 7m7s kube-node-lease Active 7m7s kube-public Active 7m7s kube-system Active 7m7s
k get pod -A NAMESPACE NAME READY STATUS RESTARTS AGE kube-system coredns-5dd5756b68-bw9sh 1/1 Running 0 7m15s kube-system etcd-minikube 1/1 Running 0 7m28s kube-system kube-apiserver-minikube 1/1 Running 0 7m27s kube-system kube-controller-manager-minikube 1/1 Running 0 7m27s kube-system kube-proxy-qfd2s 1/1 Running 0 7m16s kube-system kube-scheduler-minikube 1/1 Running 0 7m27s kube-system storage-provisioner 1/1 Running 1 (6m44s ago) 7m27s
k get all -A NAMESPACE NAME READY STATUS RESTARTS AGE kube-system pod/coredns-5dd5756b68-bw9sh 1/1 Running 0 7m58s kube-system pod/etcd-minikube 1/1 Running 0 8m11s kube-system pod/kube-apiserver-minikube 1/1 Running 0 8m10s kube-system pod/kube-controller-manager-minikube 1/1 Running 0 8m10s kube-system pod/kube-proxy-qfd2s 1/1 Running 0 7m59s kube-system pod/kube-scheduler-minikube 1/1 Running 0 8m10s kube-system pod/storage-provisioner 1/1 Running 1 (7m27s ago) 8m10s NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE default service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 8m12s kube-system service/kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 8m11s NAMESPACE NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE kube-system daemonset.apps/kube-proxy 1 1 1 1 1 kubernetes.io/os=linux 8m11s NAMESPACE NAME READY UP-TO-DATE AVAILABLE AGE kube-system deployment.apps/coredns 1/1 1 1 8m11s NAMESPACE NAME DESIRED CURRENT READY AGE kube-system replicaset.apps/coredns-5dd5756b68 1 1 1 7m58s
pod 띄워보기
- pod: 앱을 띄우기 위한 최소 단위. 이 위에 컨테이너를 띄우게 된다.
도커 허브에서 nginx 이미지를 가져와서 쿠버 환경위에 nginx 용으로 pod 생성하기
k run nginx --image=nginx pod/nginx created
pod 상세 정보 확인하기
k describe pod nginx Name: nginx Namespace: default Priority: 0 Service Account: default Node: minikube/192.168.49.2 Start Time: Wed, 15 Nov 2023 16:41:40 +0900 Labels: run=nginx Annotations: <none> Status: Running IP: 10.244.0.3 IPs: IP: 10.244.0.3 Containers: nginx: Container ID: docker://d28cb87ec0f29ac39bbc6f5b02d9c481638d4d33abdb8d9c45236aa68a3c4afd Image: nginx Image ID: docker-pullable://nginx@sha256:86e53c4c16a6a276b204b0fd3a8143d86547c967dc8258b3d47c3a21bb68d3c6 Port: <none> Host Port: <none> State: Running Started: Wed, 15 Nov 2023 16:41:51 +0900 Ready: True Restart Count: 0 Environment: <none> Mounts: /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-rbttp (ro) Conditions: Type Status Initialized True Ready True ContainersReady True PodScheduled True Volumes: kube-api-access-rbttp: Type: Projected (a volume that contains injected data from multiple sources) TokenExpirationSeconds: 3607 ConfigMapName: kube-root-ca.crt ConfigMapOptional: <nil> DownwardAPI: true QoS Class: BestEffort Node-Selectors: <none> Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s node.kubernetes.io/unreachable:NoExecute op=Exists for 300s Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 62s default-scheduler Successfully assigned default/nginx to minikube Normal Pulling 62s kubelet Pulling image "nginx" Normal Pulled 51s kubelet Successfully pulled image "nginx" in 10.87s (10.87s including waiting) Normal Created 51s kubelet Created container nginx Normal Started 51s kubelet Started container nginx
minikube dashboard (대시보드 GUI 생성)
하지만 브라우저를 통해 봐야하기 때문에 보안 이슈 때문에 안쓰는 것을 권장한다.
pod 삭제
k delete pod nginx
kubectl cheat sheet
minikube 정지
minikube stop minikube status minikube delete
etcd
- 쿠버네티스에서 필요한 모든 데이터를 key-value 형태로 저장하는 데이터베이스
- etcd가 다운되면 모든 컴포넌트가 미아가 되기 때문에 가용성이 매우 중요 → 보통 삼중화
- 클러스터링하여 분산 실행하는 RSM (Replicated State Machine) 구조
etcd 팟 확인해보기
k describe pod etcd-minikube -n kube-system Name: etcd-minikube Namespace: kube-system Priority: 2000001000 Priority Class Name: system-node-critical Node: minikube/192.168.49.2 Start Time: Wed, 15 Nov 2023 16:32:15 +0900 Labels: component=etcd tier=control-plane Annotations: kubeadm.kubernetes.io/etcd.advertise-client-urls: https://192.168.49.2:2379 kubernetes.io/config.hash: 9aac5b5c8815def09a2ef9e37b89da55 kubernetes.io/config.mirror: 9aac5b5c8815def09a2ef9e37b89da55 kubernetes.io/config.seen: 2023-11-15T07:32:08.459732678Z kubernetes.io/config.source: file Status: Running SeccompProfile: RuntimeDefault IP: 192.168.49.2 IPs: IP: 192.168.49.2 Controlled By: Node/minikube Containers: etcd: Container ID: docker://6a4c52d5a6a94989f76faa4c2145f29d0601e985514fce6a3c9cfd93f48a6301 Image: registry.k8s.io/etcd:3.5.9-0 Image ID: docker-pullable://registry.k8s.io/etcd@sha256:e013d0d5e4e25d00c61a7ff839927a1f36479678f11e49502b53a5e0b14f10c3 Port: <none> Host Port: <none> Command: etcd --advertise-client-urls=https://192.168.49.2:2379 --cert-file=/var/lib/minikube/certs/etcd/server.crt --client-cert-auth=true --data-dir=/var/lib/minikube/etcd --experimental-initial-corrupt-check=true --experimental-watch-progress-notify-interval=5s --initial-advertise-peer-urls=https://192.168.49.2:2380 --initial-cluster=minikube=https://192.168.49.2:2380 --key-file=/var/lib/minikube/certs/etcd/server.key --listen-client-urls=https://127.0.0.1:2379,https://192.168.49.2:2379 --listen-metrics-urls=http://127.0.0.1:2381 --listen-peer-urls=https://192.168.49.2:2380 --name=minikube --peer-cert-file=/var/lib/minikube/certs/etcd/peer.crt --peer-client-cert-auth=true --peer-key-file=/var/lib/minikube/certs/etcd/peer.key --peer-trusted-ca-file=/var/lib/minikube/certs/etcd/ca.crt --proxy-refresh-interval=70000 --snapshot-count=10000 --trusted-ca-file=/var/lib/minikube/certs/etcd/ca.crt State: Running Started: Wed, 15 Nov 2023 16:32:09 +0900 Ready: True Restart Count: 0 Requests: cpu: 100m memory: 100Mi Liveness: http-get http://127.0.0.1:2381/health%3Fexclude=NOSPACE&serializable=true delay=10s timeout=15s period=10s #success=1 #failure=8 Startup: http-get http://127.0.0.1:2381/health%3Fserializable=false delay=10s timeout=15s period=10s #success=1 #failure=24 Environment: <none> Mounts: /var/lib/minikube/certs/etcd from etcd-certs (rw) /var/lib/minikube/etcd from etcd-data (rw) Conditions: Type Status Initialized True Ready True ContainersReady True PodScheduled True Volumes: etcd-certs: Type: HostPath (bare host directory volume) Path: /var/lib/minikube/certs/etcd HostPathType: DirectoryOrCreate etcd-data: Type: HostPath (bare host directory volume) Path: /var/lib/minikube/etcd HostPathType: DirectoryOrCreate QoS Class: Burstable Node-Selectors: <none> Tolerations: :NoExecute op=Exists Events: <none>
ETCHctl
- ETCD를 다루기 위한 유틸리티
- api version 2와 3가 있음. (기본적으로는 v2를 사용)
- ETCDCTL이 ETCD API Server에 인증할 수 있도록 인증서 파일 경로 지정 필요
Kube-apiserver
- 쿠버네티스 API를 제공하는 핵심 구성 요소
- 쿠버네티스 프론트 앤드로서 클러스터로 온 요청의 유효성을 검증
- 다른 컴포넌트 간 통신을 중재
- kubectl 유틸리티가 접근하는 주체
Kube-Scheduler
- 클러스터 안에서 자원 할당이 가능한 노드 중 알맞은 노드를 선택하는 역할
- Label / Selector /. Affinity / Taint /Toleration 기능과 함께 동작
pod 스케줄링의 필요성
- 머신러닝 워크로드를 돌리는 특정 pod는 GPU가 탑재된 node에서만 돌아야 한다.
- consumer들은 네트워크 intensive 하므로 전용 node group을 쓰고 싶다.
- 팀별로 node를 나눠서 사용하고 싶다. 등
pod 스케줄링 분류
- 사용자가 특정 노드에 pod을 배치하고 싶을 때 - Affinity, Selector
- 관리자가 특정 노드에는 pod가 배치되는 것을 막고 싶을 때 - Taints, Tolerations
Taints and Toleration
- 어떤 pod가 어떤 node에 스케줄링 될 수 있는지를 제한함.
- 예를 들어 control node에는 pod가 스케줄링되지 않도록 taint가 되어있음.
Taints: node가 가지게 되는 성격
Toleration: pod가 가지게 되는 taint에 대한 toleration
Labels and Selector (Affinity)
- NodeSelector
- 노드에는 라벨을 할당하고 pod에는 nodeSelector 필드를 추가하여 특정 노드에서 구동되도록 함.
- 다만, NodeSelector는 여러 값을 할당하거나 not 예외처리를 하거나 하는 등을 하기는 어려움.
- NodeAffinity
- 여러 advanced 할당을 할 수 있는 만큼 문법이 다소 복잡.