Hyper-V 관리자에 들어감 - 시작 > Windows 관리 도구 > Hyper-V 관리자를 클릭함
Hyper-V 관리자 하위의 컴퓨터 이름 부분에서 우클릭 후 '가상 스위치 관리자'를 클릭함
외부를 선택하고 가상 스위치 만들기 버튼을 클릭함 - 외부는 가상 컴퓨터에서 인터넷을 이용할 때 사용함
다음과 같이 지정한 후 확인을 클릭함 - 이름 : 가상 스위치로 사용할 이름으로 임의로 지정 - 외부 네트워크 옵션 선택 - 또한 사용 중인 PC(혹은 노트북)에서도 인터넷 연결이 필요하다면 '관리 운영 체제에서 네트워크 어댑터를 공유할 수 있도록 허용'을 체크해야 함 - 이때 컴퓨터의 네트워크가 랜 케이블로 연결되어 있는 환경(Wi-Fi 이용 환경)이 아니라면 가상 스위치가 생성되지 않을 수 있음
쿠버네티스를 설치할 가상 컴퓨터를 생성함 - 컴퓨터 이름에서 마우스 오른쪽 버튼을 클릭 - 새로 만들기 > 가상 컴퓨터를 클릭
가상 컴퓨터를 만들기 위한 설정이 단계별로 진행됨 1. 다음 버튼 클릭 2. 가상 컴퓨터의 이름, 가상 컴퓨터가 저장될 위치를 지정한 후 다음 클릭 3. 우분투는 모두 64비트만 사용할 예정이므로 옵션에서 2세대를 선택한 후 다음 클릭 4. 메모리를 4096(4GB)로 지정한 후 다음 클릭. 사용 중인 컴퓨터의 메모리 용량에 따라 지정 5. 앞에서 생성해 두었던 External 스위치를 선택한 후 다음 클릭 6. 기본 상태에서 '가상 하드 디스크 만들기'의 '크기'만 80으로 변경하고 다음을 클릭함 7. 앞에서 받았던 우분투 이미지 파일의 위치를 지정한 후 다음 클릭 8. 구성 정보를 보여줌. 마침을 클릭함
가상 컴퓨터를 시작하려면 보안 설정을 해야함 - master라는 이름의 가상 컴퓨터에서 마우스 오른쪽 버튼을 클릭하고 설정을 클릭함 - 왼쪽 보안 메뉴를 선택한 후 오른쪽의 보안 부팅 사용 옵션을 해제함
설정의 왼쪽 메뉴에서 프로세서를 선택한 후 '가상 프로세서 수'를 2로 변경한 후 확인 클릭함
master에 마우스 우클릭 후 시작을 선택해 만들어진 가상 컴퓨터를 시작함
master를 더블클릭함 - 새로운 창이 뜨면서 다음과 같이 우분투 설치 화면이 나타남 - 한국어로 설치를 진행하면 오류가 발생할 수 있으므로 영문으로 진행함 - Install Ubuntu를 클릭함
키보드에 대한 설정으로 다음 그림과 같이 설정한 후 Continue를 클릭함
설치 옵션, OS 설치 방법, 가상 컴퓨터의 디스크 정보를 보여주는 화면. 기본 상태에서 Continue를 클릭
시간 정보를 설정함. Seoul을 선택하고 Continue 클릭
컴퓨터에 대한 사용자 정보를 입력함 - 맨 처음 우분투에 접근할 때 자동으로 로그인하기 위해 Log in automatically를 선택한 후 Continue를 클릭함 - 이후 우분투 설치를 진행함 (보통 10분 정도 소요됨)
설치를 마치면 Restart Now를 클릭함
최초 로그인 화면은 다음과 같음. - 최초 로그인 화면은 버전에 따라 다를 수 있음 - 온라인 계정을 입력하라는 화면으로 변경 없이 오른쪽 상단의 Skip을 클릭함
설치 정보를 우분투에 보낼 것인지 묻는 화면 - No, don't send system info를 선택하고 오른쪽 상단의 Next를 클릭
위치 서비스는 비활성화 하고 Next 버튼 클릭
준비가 완료됨. 오른쪽 상단의 Done을 클릭함
초기 설정이 끝나면 우분투를 업데이트할 건지 물어봄 - 필수 과정은 아님
오른쪽 상단의 트리(네트워크) 아이콘을 클릭한 후 Settings를 클릭함 - 쿠버네티스를 설치하기 위해 몇 가지 설정 정보를 변경해야 함 - master라는 이름으로 생성된 가상 컴퓨터는 재부팅될 때마다 IP가 변경되는 특성이 있음 - 따라서 고정으로 할당된 IP를 사용하도록 다음 작업을 진행함
Wired에서 옵션 버튼을 클릭하고, 다음과 같이 Details 탭의 내용을 기록해 둠
IPv4 항목에 앞에서 저장해 둔 내용들을 기입함. 수정 이후 Apply 버튼을 클릭함
컴퓨터에서 우분투에 접속하기 위한 설정을 함. 왼쪽 하단의 시작 버튼을 클릭한 후 Terminal을 선택
다음은 Terminal(터미널)이 실행된 화면
SSH 접속을 위해 다음 명령어를 실행함 - 'Do you want to continue?'라는 메시지가 보인다면 y를 입력함 sudo apt-get install openssh-server
사용 가능한 포트를 확인하기 위해 net-tools 툴을 설치함 sudo apt install net-tools
22번 포트를 사용할 수 있는지 확인 - 22번 포트는 우분투가 설치된 컴퓨터에 접근할 때 사용 - 22번 포트가 LISTEN 상태인 것을 확인할 수 있음 netstat -ntl
'worker1'이라는 이름으로 가상 컴퓨터를 하나 더 생성한 후 동일한 과정을 진행함 - 과정은 동일함 (위의 6번부터 다시 보면됨)
우분투에서 쿠버네티스 설치하기
- WSL을 이용한 쿠버네티스 설치에서는 마스터와 워커 노드를 구분해서 설치하지 않았지만, kubeadm을 이용할 때에는 마스터와 워커 노드를 구분해 설치함
- 마스터 노드에서는 클러스터를 설치하기 위해 kubeadm init 명령어를 실행하고, 워커 노드에서는 마스터 노드에서 생성된 클러스터에 조인하기 위해 kubeadm join 명령어를 실행함
방금 다운로드한 putty.msi 파일을 더블클릭한 후 설치함 - 기능은 기본 상태로 두고 Install을 클릭함
푸티를 실행해 마스터 노드에 접속함 - 시작>실행을 클릭한 후 putty를 입력하고 확인을 클릭함
우분투의 터미널(terminal)에서 다음 명령어를 실행하여 접속할 IP를 확인함 - inet의 주소를 확인하면 됨 ifconfig
Host Name 항목에 앞에서 확인한 IP주소를 입력한 후 Open을 클릭함 - 접속하려는 우분투가 안전한지를 묻는 창이 뜸 Accept를 클릭함
사용자와 패스워드를 묻는 화면이 나타남 - 우분투를 생성할 때 만든 사용자 계정으로 로그인함
PuTTY 접속 과정을 worker1 노드에서도 동일하게 진행해서 워커 노드에도 접속함
다음 명령어로 패키지를 최신 상태로 업데이트함 sudo su - # root 사용자로 변경 sudo apt-get update && sudo apt-get upgrade # 리눅스를 최신 상태로 업데이트
패키지 관리자가 https를 통해 데이터와 패키지에 접근할 수 있도록 apt-transport-https와 curl을 설치함 - curl : URL로 데이터를 전송할 때 사용 - apt-transport-https : apt가 https를 통해 리포지터리에 접속하기 위해 사용함 sudo apt install apt-transport-https curl
sudo su - # root 사용자로 변경
sudo apt-get update && sudo apt-get upgrade # 리눅스를 최신 상태로 업데이트
sudo apt install apt-transport-https curl
쿠버네티스 설치 과정 1. br_netfilter 모듈 활성화 2. 스왑 메모리 비활성화 하기 3. 도커(엔진 및 런타임) 설치 4. 쿠버네티스 설치하기
br_netfilter 모듈 활성화
# br_netfilter 모듈 로드
sudo modprobe br_netfilter
# 부팅 시 br_netfilter 모듈 자동 로드 설정
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF
# iptables 필터링 활성화 설정
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
# sysctl 설정 적용
sudo sysctl --system
스왑 메모리 비활성하기 - kubelet이 제대로 작동하려면 스왑 메모리를 비활성화 해야함 - 두 번째로 실행한 명령어는 시스템이 재부팅되어도 스왑 메모리가 비활성화되도록 유지시킴 스왑 메모리 : 물리 메모리가 부족할 경우를 대비해서 만들어 놓은 공간
sudo swapoff -a
sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
도커(엔진 및 런타임) 설치
sudo apt install docker.io
sudo systemctl start docker
sudo systemctl enable docker # 재부팅 후에도 서비스가 자동으로 시작되도록 설정
sudo systemctl status docker # 도커 서비스 상태 확인
- 일반 사용자 계정의 경우 권한 문제로 작업에 제약이 있을 수 있으므로 권한을 설정함
sudo usermod -aG docker $USER
- 도커가 정상적으로 설치되었는지 hello-world를 이용해 확인함 cgroup 드라이버 설정 - 쿠버네티스에서는 도커의 cgroup 관리를 위해 systemd를 사용하도록 변경해야 함 - 변경하지 않으면 클러스터 설치 과정에서 오류가 발생할 수 있음 1. docker info 명령어로 도커 설치 정보를 확인함
2. 다음 명령어는 cgroup driver가 systemd가 아닌 경우에만 실행 - 코드를 입력한 후에는 차례대로 esc, :wq!, enter를 입력하고 빠져나옴 vi /etc/docker/daemon.json
sudo mkdir -p /etc/systemd/system/docker.service.d
sudo systemctl daemon-reload # .service 파일을 변경하면 데몬을 다시 로드해야 함
sudo systemctl restart docker # 도커 서비스 재시작
쿠버네티스 설치하기 - 쿠버네티스를 사용하려면 기본적으로 kubelet, kubeadm, kubectl, kubernetes-cni 패키지가 필요함 - 각 패키지 역할은 아래의 표와 같음
구분
역할
kubelet
클러스터의 각 노드에서 실행되는 에이전트로 파드 및 컨테이너의 생성/실행 등과 같은 작업 수행
kubeadm
쿠버네티스의 클러스터를 구축하기 위해 사용
kubectl
클러스터와 통신하는 명령어라인 인터페이스
kubernetes-cni
컨테이너가 데이터를 교환하고 통신할 수 있도록 컨테이너 내에서 네트워킹을 가능하게 함
# apt 업데이트
sudo apt-get update
# 필수 패키지 설치
sudo apt-get install -y apt-transport-https ca-certificates curl gnupg
#keyrings 디렉토리 생성
sudo mkdir -p /etc/apt/keyrings
#개인키 다운로드
curl -fsSLo /etc/apt/keyrings/kubernetes-archive-keyring.gpg https://dl.k8s.io/apt/doc/apt-key.gpg
#쿠버네티스 레포지토리 추가
sudo apt-add-repository "deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] http://apt.kubernetes.io/ kubernetes-xenial main"
# 저장소 추가되었기 때문에 apt 업데이트
sudo apt-get update
# 쿠버네티스 패키지 설치
sudo apt-get install -y kubelet kubeadm kubectl
# 쿠버네티스 패키지 버전 고정
sudo apt-mark hold kubelet kubeadm kubectl
# 쿠버네티스 설치 버전 조회
kubelet --version
kubeadm version
kubectl version
# kubelet service 확인
sudo systemctl status kubelet.service
*쿠버네티스 패키지 설치 중 Unable to locate package ~ 에러 발생
# 구글 클라우드의 공개 사이닝 키를 다운로드 한다.
curl -fsSL https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-archive-keyring.gpg
# 쿠버네티스 apt 리포지터리를 추가한다.
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.28/deb/ /" | sudo tee /etc/apt/sources.list.d/kubernetes.list
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
# apt 패키지 색인을 업데이트하고, kubelet, kubeadm, kubectl을 설치하고 해당 버전을 고정한다.
sudo apt-get update
마스터 노드 설정하기 - 마스터 노드는 클러스터를 생성하는 것이 중요함 - 클러스터는 마스터와 워커 노드를 하나의 관리 단위로 묶는 역할을 함 - kubeadm init : 쿠버네티스 클러스터 생성 - pod-network-cidr : 파드 네트워크의 IP 주소 범위 - apiserver-advertise-address : 수신 대기 중임을 알릴 IP 주소 (API 서버의 IP 주소)로 마스터 노드의 IP를 설정
# Kubernetes 클러스터 초기화 (특정 Pod 네트워크 CIDR 및 API 서버 광고 주소 지정)
sudo kubeadm init --pod-network-cidr=10.244.0.0/16 --apiserver-advertise-address=192.168.0.2
# 이후 kubeadm join과 관련된 내용이 나온다면 따로 메모해두기!
# kubectl이 Kubernetes 클러스터와 상호작용할 수 있도록 .kube 디렉토리 생성
mkdir -p $HOME/.kube
# 관리자 인증 파일을 kubectl에 필요한 config 파일로 복사
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
# 사용자 권한으로 config 파일의 소유자 변경 (현재 사용자에게 읽기/쓰기 권한 부여)
sudo chown $(id -u):$(id -g) $HOME/.kube/config
# 설치 확인
kubectl get nodes
네트워크 설정하기 - 서로 다른 노드에 떠 있는 파드 간의 통신 혹은 외부와의 통신을 위해서는 CNI 플러그인이 필요함 - 여기서는 플라넬 CNI 플러그인을 사용함
- 플라넬 CNI 플러그인이 정상적으로 설치되면 다음 명령어를 입력해 CoreDNS 파드가 실행 중(running)인지 확인함. CoreDNS 파드가 실행 중이어야 파드들의 네트워크 통신이 가능함
kubectl get pods --all-namespaces
워커 노드 설정하기 - 워커 노드는 마스터 노드에 생성된 클러스터에 조인하기 위해 kubeadm join 명령어를 실행함 - 마스터 노드에서 클러스터 설치 결과로 보여 준 명령어를 수정없이 그대로 사용하면 됨 - 실행 결과 마지막에 'Run kubectl get nodes' on the control-plane to see this node join the cluster' 라는 문구가 나타나면 정상적으로 설치된 것
+ 마스터 노드에서 쿠버네티 클러스터에 등록된 노드들의 상태를 보여주는 명령으로 확인해보기
kubectl get nodes
2. 쿠버네티스 사용하기
01. YAML 파일 알아보기
- 쿠버네티스 환경에서 오브젝트(디플로이먼트, 파드 등)를 어떻게 배포할 것인지 정의할 필요가 있음
- 이때 쿠번티스는 매니페스트라는 파일로 정의를 내림
- 매니페스트(manifest) : 쿠버네티스의 오브젝트를 생성하기 위한 메타 정보를 yaml이나 json으로 기술한 파일
- 매니페스트를 작성했다는 말은 곧 yaml 파일을 작성했다는 뜻으로 이해해도 됨 - 전체적으로 yaml 파일에는 생성할 오브젝트나 컴포넌트 유형, 이름 등이 포함됨 - yaml 파일을 문법에 맞게 작성했는지 확인할 수 있는 사이트도 있음. 다음 사이트에서 매니페스트를 작성하면 문법에 맞는지 확인할 수 있음 (https://onlineyamltools.com/validate-yaml)
yaml 파일 규칙 - 하나의 블록에 속하는 엔트리(entry)마다 '-'를 붙임 - 키-값 매핑은 ':'으로 구분함 - 문서의 시작과 끝에 '---'을 삽입할 수 있음. 대체로 여러 개의 오브젝트를 정의할 때 사용하고 하나의 리소스만 정의할 때는 사용하지 않는 경우도 많음 - 키와 값 사이에 공백이 있어야 함 - 주석은 '#'으로 처리함 - 들여쓰기는 tab이 아닌 space를 이용함
yaml 파일의 구조 - 숫자, 불린(참, 거짓), 문자 사용 가능 - 하위 엔트리를 표현할 때에는 들여쓰기 - 리스트 형태의 값을 가질 때 '-'로 구분 - 다중 값을 표현할 때 '[ ]'으로 표현 - Yaml 파일의 구조를 맵(map) 혹은 디렉터리, 해시, 오브젝트라고도 함
02. 파드 생성하고 관리하기
- 하나의 파드에 여러 개의 컨테이너가 포함되어 있는 구조를 사이드카(sidecar) 패턴이라고 함 - 사이드카는 기본 기능을 하는 컨테이너(ex: 쇼핑몰 웹 사이트)와 부가 기능을 하는 컨테이너(ex: 쇼핑몰 웹 사이트에서 발생하는 로그)가 결합한 것 - 이런식으로 컨테이너의 기능을 확장하기 위해 파드 내부에 컨테이너를 여러 개 구성할 수 있음
파드 생성하기
- 파드는 create 또는 apply 명령어를 사용해 생성
- kubectl create : 클러스터에 새로운 리소스를 생성
- kubectl apply : create와 replace (생성된 오브젝트를 삭제하고 새로운 오브젝트를 생성)의 혼합
스테이트리스와 스테이트풀 - 스테이트리스(stateless, 상태가 없는) : 사용자가 애플리케이션을 사용할 때 상태나 세션을 저장해 둘 필요가 없는 애플리케이션에서 사용함 - 스테이트풀(stateful) : 사용자가 애플리케이션을 사용할 때 상태나 세션을 별도의 데이터베이스에 저장해야 하는 애플리케이션에서 사용. 상태나 세션을 저장해야 하는 애플리케이션으로는 상품을 장바구니에 담고 구매하는 쇼핑몰, 금융 거래 사이트 등이 있음
- 디플로이먼트가 생성되었는지 확인하기 위해 kubectl get deployment명령어를 사용함
- 디플로이먼트의 추가적인 정보를 얻으려면 -o wide 옵션을 사용하면 됨
kubectl get deployment
실행 결과의 의미
READY : 레플리카의 개수
UP-TO-DATE : 최신 상태로 업데이트된 레플리카의 개수
AVAILABLE : 사용 가능한 레플리카의 개수
AGE : 파드가 실행되고 있는 지속 시간
실행 결과의 의미
CONTAINERS: 파드에 포함된 컨테이너의 개수
IMAGES: 파드 생성에 사용된 이미지
SELECTOR: yaml 파일의 셀렉터를 의미(yaml 파일의 셀렉터는 라벨이 app=my-httpd인 파드만을 선택해서 서비스를 하겠다는 의미)
- 디플로이먼트로 생성된 파드를 확인함. 파드 이름 혹은 상태를 확인하려면 kubectl get pod 명령어를 사용함
- 파드 역시 상세한 정보를 확인하려면 -o wide 옵션을 사용하면 됨
kubectl get pod
실행 결과의 의미
IP : 파드에 할당된 IP
NODE : 파드가 실행되고 있는 노드
NOMINATED NODE: 예약된 노드의 이름 (실습에선 예약된 노드 없으므로 none)
READINESS GATES : 파드 상태 정보로 사용자가 수정할 수 있음. 예를 들어 running, pending 상태가 기본이지만 creating 같은 좀 더 상세한 정보를 원한다면 READINESS GATES를 다음과 같이 설정하면 됨 ex) Type Status Initialized True ContainersReady True PodScheduled True
- curl 명령어를 이용해 httpd 웹 서버에 IP로 접속해봄
- curl은 웹 서버로부터 콘텐츠를 가져올 때 사용하는 리눅스 명령어
- 파드에 할당된 IP를 확인한 후 접속하면 됨
- 'It works!'라는 결과가 출력되었다면 웹 서비스가 정상적으로 동작하고 있다는 의미
curl 10.244.5.2:80
파드 수정하기
- 생성된 디플로이먼트나 파드의 속성을 변경하고 싶다면 kubectl edit 명령어를 이용함
사용된 명령어의 의미 - kubectl exec : 실행 중인 파드에 접속 - -it i : 컨테이너에 대화형 셸(shell)을 생성 t : 대화형 터미널을 도커 컨테이너에 연결 - my-httpd-7547bdb59f-dr6sj : 접속할 파드의 이름 - -- /bin/bash : 셸의 절대 경로
파드의 로그를 확인하는 명령어 - 주로 파드가 정상적으로 만들어지지 않거나, 정상적으로 만들어졌더라도 실행 중에 문제가 생긴다면 로그를 살핌
kubectl logs my-httpd-7547bdb59f-dr6sj
(다음 실습 전 kubectl delete deployment 명령어로 생성된 디플로이먼트 삭제하기)
03. 디플로이먼트와 서비스 사용하기
- 디플로이먼트는 쿠버네티스에서 상태가 없는(stateless) 애플리케이션을 배포할 때 사용함
- 디플로이먼트는 레플리카셋의 상위 개념으로서 파드의 개수를 유지할 뿐만 아니라 배포 작업을 좀 더 세분화해 관리할 수 있게 해줌
apiVersion : apps/v1
kind : Deployment
metadata :
name : rolling
spec :
replicas : 3
template :
metadata :
labels :
app : rolling
spec :
containers :
- name : rolling
image : myimage
ports :
- containerPort : 8080
롤링(rolling) 업데이트 - 새 버전의 애플리케이션(파드)을 배포할 때 새 버전의 애플리케이션은 하나씩 늘려가고 기존 버전의 애플리케이션은 하나씩 줄여나가는 방식 - 쿠버네티스에서 사용하는 표준 배포 방식 - 새로운 버전(V2)으로 배포된 파드에 문제가 발생하면 다시 이전 버전(V1)의 파드로 서비스를 대체할 수 있어서 상당히 안정적인 배포 방식 - 업데이트가 느리게 진행된다는 단점이 있음
spec :
replicas : 3
# 롤링 업데이트 부분 추가
strategy :
type : RollingUpdate
rollingUpdate :
maxSurge : 25%
maxUnavailable : 25%
# # #
template :
. . .
명령어의 의미 - maxSurge : 업데이트 중에 만들 수 있는 파드의 최대 개수 - maxUnavailable : 업데이트 중에 사용할 수 없는 파드의 개수, 0보다 큰 정수를 지정할 수 있고 실습과 같이 퍼센트로 지정할 수도 있음
재생성(recreate) 업데이트 - 재생성 업데이트는 모든 이전 버전(V1)의 파드를 모두 한 번에 종료하고 새 버전(V2)의 파드로 일괄적으로 교체하는 방식 - 빠르게 교체할 수 있지만 새로운 버전의 파드에 문제가 발생하면 대처가 늦어질 수 있다는 단점이 있음
블루/그린(blue/green) 업데이트 - 애플리케이션의 이전 버전(블루, V1 파드)과 새 버전(그린, V2 파드)이 동시에 운영됨 - 하지만 서비스 목적으로 접속할 수 있는 것은 새 버전의 파드만 가능하며 이전 버전의 파드는 테스트 목적으로만 접속할 수 있음 - 따라서 새로운 버전의 파드에 문제가 발생했을 때 빠르게 대응할 수 있으며 안정적으로 배포할 수 있음 - 많은 파드가 필요하므로 그만큼 많은 자원(CPU, 메모리)이 필요하다는 단점이 있음
apiVersion : apps/v1
kind : Service
metadata :
name : bluegreen
spec :
selector :
app : bluegreen
version : v1.0.0 # 트래픽이 신규 버전의 애플리케이션으로 변경되는 시점에 버전 업데이트
. . .
카나리(canary) 업데이트 - 블루/그린과 비슷하지만 더 진보적인 단계적 접근 방식 - 주로 애플리케이션의 몇몇 새로운 기능을 테스트할 때 사용됨 - 두 개의 버전을 모두 배포하지만 새 버전에는 조금씩 트래픽을 증가시켜(ex: 처음엔 5% 트래픽 → 50% 트래픽 흘려보냄) 새로운 기능들을 테스트함 - 기능 테스트가 끝나고 새 버전에 문제가 없다고 판단하면 이전 버전은 모두 종료시키고 새 버전으로만 서비스함 - 카나리 매니페스트도 블루/그린과 유사함
- 파드와 디플로이먼트의 가장 큰 차이점은 '버전 관리'
- 파드는 단순히 관련성이 있는 컨테이너가 하나의 파드에 포함되어 있는지가 중요함
- 디플로이먼트는 파드(혹은 컨테이너)의 버전 관리가 중요하다고 볼 수 있음
파드
디플로이먼트
- 단일 컨테이너 또는 관련 컨테이너들의 그룹(묶음)
- 쿠버네티스에서 사용되는 용어로 파드의 원하는 동작이나 특성을 정의하는 파일 - 각 파드의 상태를 모니터링 - 개발과 운영 환경에서 사용하기에 적합
디플로이먼트와 서비스 사용하기
- 디플로이먼트는 파드 배포에 관한 객체
- 단순히 파드를 배포하는 것뿐만 아니라 몇 개의 파드를 실행할지 결정하는 것도 디플로이먼트
- 기본적으로 파드는 같은 노드에 떠 있는 파드끼리만 통신할 수 있음. 따라서 다수의 노드에 떠 있는 파드 간의 통신이나 외부와의 통신을 위해서는 CNI 플러그인이 필요함
- 하지만 CNI 플러그인만 설치했다고 외부와 통신할 수 있는건 아님
- 파드에 위치한 서비스(이용자 편의를 위한 기능)를 외부에서 접속하려면 서비스(쿠버네티스의 서비스)를 이용해야함
디플로이먼트와 서비스를 이용한 외부 접속 순서 1. 디플로이먼트를 이용해 파드를 배포함 - 몇 개의 파드를 배포(레플리카셋)할지 결정하는 것 역시 디플로이먼트에서 지정함 - 파드가 배포되었다는 의미는 파드를 통해 서비스(ex: 소셜커머스)를 하겠다는 것 - 그러려면 해당 파드가 외부에서 접속할 수 있어야하는데, 그 역할을 하는 것이 서비스 2. 서비스를 외부에 노출함 3. 외부에서 파드에 접속 가능
구현 방법 - nginx 이미지를 이용해 디플로이먼트를 생성함
nginx-deploy.yaml 파일을 생성하여 작성함 - nginx는 공개된 이미지이면서 눈으로 바로 테스트해 볼 수 있는 장점이 있음
apiVersion : apps/v1
kind : Deployment
metadata : # 디플로이먼트 정보
name : nginx-deploy # nginx-deploy라는 이름의 디플로이먼트 생성
labels :
app : nginx # 디플로이먼트 레이블 설정
spec :
replicas : 2 # 2개의 파드 생성
selector : # 디플로이먼트가 관리할 파드를 선택
matchLabels :
app : nginx # 디플로이먼트는 nginx 레이블을 갖는 파드를 선택해 관리
template : # template에 정의된 내용에 따라 파드를 생성
metadata :
labels :
app : nginx # 생성될 파드의 레이블
spec : # 컨테이너에 대한 정보
containers :
- name : nginx
image : nginx:1.7.9 # 1.7.9 버전의 nginx 이미지 가져오기
ports :
- containerPort : 80
- 이 매니페스트는 nginx 이미지를 이용해 nginx-deploy이란 이름의 파드를 생성하겠다는 의미- 디플로이먼트 → 파드 → 컨테이너 순서로 이동하면서 상세한 정보들을 정의함 - .spec.template.metadata.label의 설정과 .spec.selector.matchLabels의 설정이 같아야 함, 두 개의 설정은 동일한 레이블 값이어야 함 - 모두 작성하면 esc → :wq! → enter 를 차례대로 입력해 빠져나옴
작성한 yaml 파일을 실행함
kubectl apply -f nginx-deploy.yaml
배포한 디플로이먼트 상태와 파드 상태를 확인함
디플로이먼트 상태 확인 - READY에서 2/2의 결과가 출력되었는데, 이것은 nginx-deploy.yaml 파일에서 replicas를 2로 지정했기 때문 - 2개의 파드가 생성되었다는 의미
kubectl get deployments
파드 상태 확인 - kubectl get pod에서 pod를 짧게 po라고 입력해도 인식함 - 디플로이먼트 이름으로 파드가 생성되었는데 뒤에 숫자와 문자들이 결합된 이유는 파드들을 구분하기 위함
kubectl get pod
디플로이먼트, 레플리카셋, 파드의 이름 형태 replicas = 3으로 지정 디플로이먼트 이름 : deploy ↓ 레플리카셋 이름 : deploy-48e15e ←임의로 생성 ↓ 파드 1 이름 : deploy-48e15e-f5e48←임의로 생성 파드 2 이름 : deploy-48e15e-e54eg←임의로 생성 파드 3 이름 : deploy-48e15e-h8gr8←임의로 생성
외부로 접속할 수 있도록 서비스를 생성함 - nginx-svc.yaml 파일을 생성하고 내용을 작성함
apiVersion : v1
kind : Service
metadata :
name : nginx-svc # 서비스 이름
labels :
app : nginx
spec :
type : NodePort # 노드포트를 이용해서 서비스(service)를 외부에 노출시킴
ports :
- port : 8080
nodePort : 31472
targetPort : 80
selector :
app : nginx # 서비스(service)를 nginx 레이블을 갖는 파드와 연결
- 모두 작성 후 esc → :wq! → enter를 차례대로 입력해 빠져나옴 - 작성한 yaml 파일을 kubectl apply 명령어로 실행함
kubectl apply -f nginx-svc.yaml
- 생성된 nginx-svc 서비스의 상태 정보를 확인
kubectl get svc
외부 접속을 확인함 - 노드포트를 이용해 서비스를 외부에 노출시켰기 때문에 노드(호스트)의 IP에 31472포트를 붙여서 접속할 수 있음
04. 레플리카셋 사용하기
- 레플리카셋은 일정한 개수의 동일한 파드가 항상 실행되도록 관리함
- 이러한 기능이 필요한 이유는 서비스의 지속성 때문임
- 노드의 하드웨어에서 발생하는 장애 등의 이유로 파드를 사용할 수 없을 때 다른 노드에서 파드를 다시 생성해서 사용자에게 중단 없는 서비스를 제공할 수 있음
매니페스트를 정의하는 replicaset.yaml을 작성함 - replicaset.yaml에서는 단순히 몇 개의 파드를 배포할지를 결정함
apiVersion : apps/v1
kind : ReplicaSet
metadata :
name : 3-replicaset # 레플리카 이름
spec :
template :
metadata :
name : 3-replicaset
labels :
app : 3-replicaset
spec :
containers :
- name : 3-replicaset
image : nginx
ports :
- containerPort : 80
replicas : 3 # 3개의 파드 생성
selector :
matchLabels :
app : 3-replicaset
앞에서 정의한 yaml 파일을 실행해 레플리카셋을 생성
kubectl apply -f replicaset.yaml
생성된 레플리카셋과 파드의 상태를 알아봄 - 여러 정보를 한 번에 보고 싶다면 다음과 같이 ,를 이용함
kubectl get replicaset,pods
- 매니페스트에서 지정한 것과 같이 3개의 파드가 생성됨 - 생성된 파드가 모두 running 상태
파드 하나를 삭제함 - 3개의 파드 중 제일 위에 있는 파드를 삭제함
kubectl delete pod 3-replicaset-62tdr
다시 레플리카셋과 파드 정보를 확인함 - 삭제되었다는 결과를 받았지만, 여전히 3개의 파드가 떠 있음 - 기존 62tdr인 파드는 삭제되었지만, 새로운 파드가 생성된 것 - 레플리카셋은 파드가 삭제되어도 지정된 숫자만큼 파드의 개수를 유지하는 역할을 함
- 레플리카셋이 특정 개수의 파드를 유지할 때 사용하는 것이라면, 데몬셋은 모든 노드에 파드를 배포할 때 사용함
- 데몬셋은 모든 노드에 필요한 모니터링 용도로 많이 사용됨
파일 생성하고 매니페스트 작성 - 데몬셋은 주로 모니터링 용도로 사용 - 파드 역시 프로메테우스(prometheus)라는 모니터링 용도의 이미지를 이용해 파드를 배포 - kind 부분에 리소스 유형을 DaemonSet으로 지정
apiVersion : apps/v1
kind : DaemonSet # 데몬셋 배포
metadata :
name : prometheus-daemonset
spec :
selector :
matchLabels:
tier : monitoring # 사용자 정의 레이블로 모니터링 용도로 사용될 것임을 지정
name : prometheus-exporter
template :
metadata :
labels :
tier : monitoring # 모니터링 용도
name : prometheus-exporter
spec :
containers:
- name : prometheus
image : prom/node-exporter
ports :
- containerPort : 80
매니페스트를 적용해 데몬셋 생성
kubectl apply -f daemonsets.yaml
데몬셋 정보 확인 - 생성된 데몬셋에 대한 정보를 자세히 확인함 - 파드의 상세 정보는 다음 두 가지 방법으로 확인할 수 있음 kubectl get pod -o wide : 모든 리소스에 대한 상세 정보를 보여줌 kubectl describe 파드명/디플로이먼트명 : 파드명/디플로이먼트명으로 지정된 오브젝트에 대한 상세 정보를 보여줌 - 두 가지 방법 중 kubectl describe 명령어를 이용해 확인 - 1대의 워커 노드를 사용하고 있으므로 1개의 파드가 배포됨, 워커 노드를 2대로 구성했다면 2개의 파드가 배포될 것
kubectl describe daemonset/prometheus-daemonset
배포된 파드 리스트 확인 - 1대의 워커 노드에 파드가 생성된 것을 확인할 수 있음
생성했던 데몬셋 삭제 - 다음 명령은 데몬셋뿐만 아니라 파드도 함께 삭제됨
kubectl delete -f daemonsets.yaml
06. 크론잡 사용하기
잡(Jobs)의 두 가지 유형
잡 (Job) - 혹은 Run-to-Completion이라고도 불림 - 하나 이상의 파드가 특정한 파드의 정상적인 상태를 유지할 수 있도록 관리 - 노드(혹은 시스템)에 문제가 발생해서 특정 파드에 문제가 발생하면 정상적인 서비스를 유지하도록 새로운 파드를 다시 만드는 역할
크론잡 (CronJob) - 어떤 액션을 얼마나 자주 발생시킬지는 매니페스트에서 지정 - 특정 시기에 주기적으로 발생시키기 때문에 애플리케이션이나 데이터를 백업해야 할 때 주로 사용함
- 실습은 쿠버네티스 공식 홈페이지에도 게시되어 있는 busybox(최소한의 기능만 있는 리눅스) 이미지를 사용함
cronjob.yaml 파일을 생성하고 매니페스트 작성함 - 다른 매니페스트와 다르게 schedule(얼마나 자주), command(어떤 행동을 수행) 부분이 추가되어 있음 - 이 매니페스트는 busybox 이미지를 통해 파드를 생성하고, 생성된 파드는 1분 단위(schedule)로 date; echo Hello from the Kubernetes cluster 메시지를 출력(command)하는 크론잡
apiVersion: batch/v1
kind: CronJob # 크론잡 생성
metadata:
name: hello
spec:
schedule: "*/1 * * * *" # 스케줄 지정
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox
imagePullPolicy: IfNotPresent # 데스크톱/서버에 이미지가 없을 때에만 내려받음
command: # 스케줄에 따라 다음의 명령을 실행
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
restartPolicy: OnFailure # 컨테이너에서 실행된 프로세스가 실패할 때에만 다시 시작
작성한 yaml 파일을 kubectl apply 명령어로 실행
kubectl create -f cronjob.yaml # 크론잡 생성
매니페스트에서 작성한 스케줄의 의미 schedule : "*/1 * * * *" 첫 번째 필드 : 분(0~59) 두 번째 필드 : 시간(0~23) 세 번째 필드 : 일(0~31) 네 번째 필드 : 월(1~12) 다섯 번째 필드 : 주(0~6), 일요일은 0으로 표현 → 1분 단위로 스케줄을 실행하겠다는 의미
크론잡의 상태를 확인 - 확인 결과 LAST SCHEDULE 상태가 47s로 출력됨 - 즉, 스케줄을 47초 전에 실행했다는 의미 - 경우에 따라 <none>으로 출력될 수도 있음. 시간이 좀 지나면 숫자로 바뀜 - kubectl get crongob -w 명령어를 실행하면 1분 단위로 크론잡 실행되고 있는 것을 확인할 수 있음 - 주기적으로 크론잡이 계속 실행(ACTIVE=1)되고 있음
파드의 변화를 확인 - 주기적으로 파드가 생성되고 삭제되는 과정(Pending, ContainerCreating, Completed, Terminating)이 반복되고 있음을 확인할 수 있음 - 파드가 Completed되었다는 것은 스케줄에 따라 명령어 수행이 완료되었음을 의미함 - 상태를 확인했다면 ctrl + c로 해당 명령어를 종료시킴
생성된 크론잡은 kubectl delete 명령어로 삭제함
kubectl delete cronjob hello
07. CoreDNS 알아보기
- DNS : 사람이 이해하기 쉬운 도메인과 컴퓨터가 이해하는 IP 주소 간의 변환을 해주는 서비스
- 사람이 모든 서비스의 IP를 기억할 수는 없으므로 DNS 같은 서비스가 필요함
- CoreDNS : 쿠버네티스에서 사용하는 DNS, 클러스터를 지속적으로 모니터링하며 새로운 서비스나 파드가 생성되면 DNS를 업데이트함 - kubeadm으로 설치하면 CoreDNS가 기본으로 설치됨
CoreDNS에 대해 알아보기
CoreDNS로 사용되는 파드 확인하기
kubectl get po -n kube-system -l k8s-app=kube-dns
- CoreDNS로 사용되는 파드를 확인하면 두 개의 파드로 구성되어 있음 - 이 두 개의 파드에 대한 서비스는 kube-system 네임스페이스에서 kube-dns라는 이름으로 실행됨
kube-dns라는 서비스를 확인하기
kubectl get svc -n kube-system -l k8s-app=kube-dns
- kube-dns는 TCP와 UDP 모두 53 포트를 사용함, 일반적으로 DNS는 53포트를 사용함
CoreDNS의 내용을 담고 있는 Corefile 정보를 확인하기
kubectl describe cm -n kube-system coredns
- cm은 ConfigMap의 약어 - Corefile은 CoreDNS의 구성 파일로서 어떤 서버가 어떤 포트와 프로토콜을 수신하는지에 대한 내용들이 기록되어 있음
Corefile의 출력 내용 - errors : 에러가 발생하면 stdout에 그 내용을 기록함. 즉, 에러가 발생하면 사용자에게 그 내용을 출력해 알려주겠다는 의미 - health : CoreDNS에 대한 상태를 확인하는 부분으로, http://localhost:8080/health를 통해 CoreDNS 상태를 확인할 수 있음 - ready : DNS 서비스를 할 준비가 되었다면 200 OK가 반환됨 - kubernetes : CoreDNS가 쿠버네티스의 서비스 및 파드의 IP를 기반으로 DNS 질의에 응답을 함 - prometheus : 지정된 포트(9153)로 프로메테우스의 메트릭 정보를 확인할 수 있음
CoreDNS가 어떻게 사용되는지 확인 - 파드를 하나 생성하고 /etc/resolv.conf(리눅스에서 DNS 역할을 함) 파일의 내용을 살펴봄
kubectl run -it --rm \
busybox \
--image=busybox \
--restart=Never \
-- cat /etc/resolv.conf # /etc/resolv.conf 파일 확인
- 파드가 생성될 때 kubelet은 /etc/resolv.conf 파일에 CoreDNS를 가리키는 IP 주소를 네임서버(nameserver)로 등록한다는 것을 확인할 수 있음 - 이처럼 resolv.conf 파일에 등록된 네임서버를 이용해 도메인을 IP로 변경할 수 있음
resolv.conf에 등록된 결과의 의미 - nameserver : CoreDNS의 IP 주소 - search : DNS에 질의하는 부분으로 도메인 주소를 표시 - ndots : 도메인에 포함될 '.'의 최소 개수 (ex, www.a.com에서 '.'의 개수)
08. 컨피그맵과 시크릿 알아보기
- 컨피그맵(ConfigMap)은 환경 변수 같은 값을 도커 이미지에 포함시키지 않고 별도로 분리해서 관리하는 방법을 제공함
옵션의 의미 - map-name : 컨피그맵 이름 - data-source : 컨피그맵을 포함하는 파일 또는 디렉터리의 경로 - arguments : 컨피그맵을 생성하는 방법을 지정 - 파일로 생성 : 파일/디렉터리(--from-file), 환경 파일(--from-env-file) - 문자로 생성 : 리터럴 값(--from-literal)