「시작하세요! 도커/쿠버네티스」 학습 정리 - 05장 ~ 06장.

toto9602·2024년 1월 27일
0

Docker 공부하기

목록 보기
7/10

용찬호. 「 시작하세요! 도커/쿠버네티스」. 위키북스 를 읽으며, 학습한 내용을 정리하는 글입니다.
→ 본문의 내용은 모두 책의 내용에 대한 직/간접적 인용임을 밝힙니다.

05장. 쿠버네티스 설치

5.1 쿠버네티스 설치 환경의 종류

[ 개발 용도의 쿠버네티스 설치 ]

  • Minikube
  • Docker for Mac/Windows에 내장된 쿠버네티스

[ 서비스 테스트 또는 운영 용도의 쿠버네티스 설치 ]

  • kops
  • kubespray
  • kubeadm
  • EKS, GKE 등의 매니지드 서비스

5.3 개발 용도의 쿠버네티스 설치

5.3.1 Docker for Mac / Windows에서 쿠버네티스 사용

→ Preference -> Enable Kubernetes 클릭!

kubectl version --short 명령어 입력하여
쿠버네티스 정상 설치 확인!

5.3.2 Minikube로 쿠버네티스 설치

Minikube는 로컬에서 가상 머신이나 도커 엔진을 통해 쿠버네티스를 사용할 수 있는 환경을 제공

→ Minikube는 가상 머신 또는 도커를 통해 쿠버네티스를 설치하기 때문에, 버추얼 박스 또는 도커 엔진이 미리 설치되어 있어야 한다.

[ 기본 설정을 이용해 버추얼 박스로 minikube 설치 ]
1. 버추얼박스 설치

  • apt-get install virtualbox -> 가상화 도구 설치 (in Linux!)
  1. minikube, kubectl 내려받기
minikube \
https://storage.googleapis.com/minikube/releases/v1.4.0/minikube-linux-amd64 && \
chmod +x minikube && \
sudo mv minikube /usr/local/bin/
  1. minikube 가상 머신 설치
minikube start

5.4 여러 서버로 구성된 쿠버네티스 클러스터 설치

5.4.1 kubeadm으로 쿠버네티스 설치

  • 일반적인 서버 클러스터 환경에서도 쿠버네티스를 쉽게 설치 가능한 kubeadm
  • 쿠버네티스 커뮤니티에서 권장하는 설치 방법 중 하나
  • Minikube 및 kubespray 같은 설치 도구도 내부적으로는 kubeadm을 사용함
  • 온프레미스 환경, 클라우드 인프라 환경에 상관없이 일반적인 리눅스 서버라면 모두 사용 가능!

[ example ]

kube-master1 172.30.0.100
kube-worker1 172.31.0.101
kube-worker2 172.31.0.102
kube-worker3 172.31.0.103

1. 쿠버네티스 저장소 추가

  • 쿠버네티스 설치할 모든 노드에서 이하를 실행하여, 쿠버네티스 저장소를 추가!
    curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpt | apt-key add -
    
    cat <<EOR > /etc/apt/sources.list.d/kubernetes.list
    2. kubeadm 설치
  • 도커를 설치
     wget -q0- get.docker.com | sh
  • 쿠버네티스에 필요한 패키지를 설치
    apt-get install -y kubelet kubeadm kubectl kubernetes-cni

3. 쿠버네티스 클러스터 초기화

  • 마스터 노드로 사용할 호스트에서 다음 명령어로 클러스터를 초기화!

    kubeadm init --apiserver-advertise-address 172.31.0.100 \ --pod-network-cidr=192.168.0.0/16
  • apiserver-advertise-address 옵션의 인자에, 다른 노드가 마서트에게 접근할 수 있는 IP 주소를 환경에 맞게 입력

    • kube-master01 호스트에 접근할 수 있는 IP 주소가 172.31.0.100인 경우!
  • --pod-network-cidr 은 쿠버네티스에서 사용할 컨테이너의 네트워크 대역이며, 각 서버의 네트워크 대역과 중복되지 않게 설정 필요!

→ Your Kubernetes control-plane has initialized successfully!
메시지 확인~!
→ 중간에 표시되는 명령어 3줄을 복사하여 마스터 노드에서 실행함!

→ 마지막에 출력된 명령어인 kubeadm join... 은 마스터를 제외한 노드인 워커 노드에서 실행한다.
4. 컨테이너 네트워크 애드온 설치

  • 쿠버네티스 컨테이너 간 통신을 위해 flannel, weaveNet 등 여러 오버레이 네트워크의 사용이 가능
  • 본 예제는 calico를 기준으로 함!
kubectl apply -f https://docs.projectcalico.org/v3.8/manifests/calico.yml
  • 설치가 정상적으로 완료됐는지 확인 차, 아래 명령어로 쿠버네티스 핵심 컴포넌트의 실행 목록을 확인
    • kubectl get pods --namespace kube-system
    • calico-kube-controllers, kube-scheduler 등 확인!

5.4.2 kops로 AWS에서 쿠버네티스 설치

kops는 클라우드 플랫폼에서 쉽게 쿠버네티스 설치를 할 수 있게 하는 도구

→ AWS, GCP 등의 클라우드 플랫폼에서 설치를 지원
→ 2019년 10월을 기준으로 kops는 AWS만을 공식 지원!

1. kops 및 kubectl 실행 바이너리 내려받기

wget -O kops https://github.com/kubernetes/kops/releases/download/1.12.3/kops-linux-amd64

chmod _x ./kops

sudo mv ./kops /usr/local/bin

wget -O kubectl \
http://storage.googleapis.com/kubernetes-release/release/v1.14.0/bin/linux/amd64/kubectl

chmod +x kubectl

sudo mv kubectl /sr/local/bin

2. AWS 사용자 생성, 정책 연결 및 AWS CLI 설정

  • kops는 서버 인스턴스, 네트워크 리소스 등과 같은 인프라를 자동으로 생성하기 위해 aws CLI와 AWS 접근 정보를 사용함.
  • 이를 위해, aws CLI를 설치한 다음, 적절한 역할이 부여된 사용자의 비밀 키와 접근 키를 aws CLI에 설정 필요

3. S3 버킷에 쿠버네티스 클러스터의 설정 정보 저장

  • kops는 쿠버네티스의 설정 정보를 S3 버킷에 저장하므로, kops가 사용할 S3 버킷을 미리 생성해 둬야 함.
# 버킷 생성
aws s3api create-bucket \
	--bucket alicek106-k8s-bucket \
    --create-bucket-configuration LocaationConstraint=ap-northeast-2
    
# S3 버킷의 버저닝을 기록
aws s3api put-bucket-versioning
	--bucket alicek106-k8s-bucket \
    --versioning-configuration Status=Enabled
  • 쿠버네티스의 클러스터 이름과 S3 버킷 이름을 셸 환경 변수로 설정
    export NAME=mycluster.k8s.local
    export KOPS_STATE_STORE=s3://alicek106-k8s-bucket
  • 쿠버네티스를 설치할 EC2 인스턴스에 배포될 SSH 키 생성
    ssh-keygen -t rsa -N "" -f ./id_rsa
  • 클러스터의 설정 파일을 생성
    kops create cluster \
    --zones ap-northeast-2a \
    --networking calico \
    --ssh-public-key ./id_rsa.pub \
    $NAME

4. 쿠버네티스 클러스터 옵션 변경

  • 워커 노드의 옵션 수정

    kops edit ig nodes --name $NAME
  • 노드의 개수는 maxSize와 minSize를 수정해 변경하며, 워커의 CPU와 메모리 크기는 인스턴스 타입을 수정해 변경한다.

    apiVersion: kops/v1alpha2
    kind: InstanceGroup
    
    spec:
    	image: kope.io/k8s-1.11-debian-stretch-amd64-hvm-ebs-2018-08-17
      machineType: t2.medium
      maxSize: 3
      minSize: 3
  • 마스터 노드의 설정을 변경!

    kops edit ig master-ap-northeast-2a --name $NAME
    apiVersion: kops/v1alpha2
    kind: InstanceGroup
    
    spec:
    	image: kope.io/k8s-1.11-debian-stretch-amd64-hvm-ebs-2018-08-17
      machineType: t2.medium
      maxSize: 1

    5. 쿠버네티스 클러스터 생성

  • 아래 명령어를 입력하면 kops가 자동으로 서버 인스턴스, 네트워크 리소스 등을 생성해 쿠버네티스를 설치!

kops update cluster --yes $NAME
  • kops validate cluster 명령어로 쿠버네티스 설치 진행 상황 확인
  • kubectl get nodes 로 노드의 목록, 쿠버네티스 버전을 출력해 정상 설치 확인!

6장. 쿠버네티스 시작하기

쿠버네티스를 시작하기 전에

  • 모든 리소스는 오브젝트 형태로 관리됩니다.
    • 컨테이너의 집합(Pods), 컨테이너의 집합을 관리하는 컨트롤러(Replica Set), 사용자(Service Account), 노드(Node) 등도 하나의 오브젝트로 사용 가능!
    • kubectl api-resources 명령어로 쿠버네티스에서 사용 가능한 오브젝트 확인 가능!
  • 쿠버네티스는 명령어로도 사용할 수 있지만, YAML 파일을 더 많이 사용함!
    • kubectl 명령어로 쿠버네티스 사용 가능!
    • 쿠버네티스도 YAML 파일로 컨테이너 리소스를 생성, 삭제할 수 있음.
    • 컨테이너뿐만 아니라, 거의 모든 리소스 오브젝트에 YAML 파일이 사용될 수 있음!
    • 쿠버네티스에서 실제로 서비스를 배포할 때도, 여러 개의 YAML 파일을 정의해 쿠버네티스에 적용시키는 방식으로 동작!
  • 쿠버네티스는 여러 개의 컴포넌트로 구성돼 있습니다.
    • 쿠버네티스 노드의 역할은 크게 마스터와 워커로 구분
    • 마스터 노드는 쿠버네티스가 제대로 동작할 수 있게 클러스터를 관리하며, 워커 노드에는 애플리케이션 컨테이너가 생성된다!
    • 가령, 마스터 노드에서는 API 서버(kube-apiserver), 컨트롤러 매니저(kube-controller-manager), 스케줄러(kube-scheduler) DNS 서버(coreDNS) 등이 실행!
    • 모든 노드에서는 오버레이 네트워크 구성을 위해 프락시(kube-proxy)와 네트워크 플러그인(calico, flannel 등...)이 실행!

컴포넌트들은 기본적으로 도커 컨테이너로서 실행된다!
→ 쿠버네티스 클러스트 구성을 위해 kubelet이라는 에이전트가 모든 노드에서 실행!
= 컨테이너의 생성, 삭제뿐만 아니라 마스터와 워커 노드 간의 통신 역할을 담당하는 중요한 에이전트이다!

6.2 포드(Pod) : 컨테이너를 다루는 기본 단위

6.2.1 포드 사용하기

  • 쿠버네티스에서는 컨테이너 애플리케이션의 기본 단위를 포드(Pod)라고 부른다!
  • 포드는 1개 이상의 컨테이너로 구성된 컨테이너의 집합
    • 도커 엔진에서 기본 단위가 도커 컨테이너이고, 스웜 모드에서 기본 단위가 여러 개의 컨테이너로 구성된 서비스(Service)
    • 비슷한 맥락으로, 쿠버네티스에서 컨테이너 애플리케이션을 배포하기 위한 기본 단위로 포드라는 개념을 사용
    • 1개의 포드에서 1개의 컨테이너가 존재할 수도 있고, 여러 개의 컨테이너가 존재할 수도 있다.

ex) Nginx 컨테이너로 구성된 포드

apiVersion: v1
kind: Pod
metadata:
	name: my-nginx-pod
spec:
	containers:
    - name: my-nginx-container
      image: nginx:latest
      ports:
      - containerPort: 80
      protocol: TCP
  • apiVersion : YAML 파일에서 정의한 오브젝트의 API 버전
  • kind : 리소스의 종류. 위의 YAML 파일에서 생성하려고 하는 것이 포드이므로 Pod를 입력
  • metadata : 라벨, 주석(Annotation), 이름 등과 같은 리소스의 부가 정보 입력
  • spec : 리소스를 생성하기 위한 자세한 정보를 입력
    • 위 예시에서는 포드에서 실행될 컨테이너 정보를 정의하는 containers 항목을 작성하고, 하위 항목인 image에서 사용할 도커 이미지 지정
    • name 항목에 컨테이너의 이름, ports 항목에서는 Nginx 컨테이너가 사용할 포트인 80

→ YAML 파일은 kubectl apply -f 명령어로 쿠버네티스에 생성한다.
= 새로운 포드 생성!

kubectl apply -f nginx-pod.yaml
  • 현재 이 포드는, 외부에서 접근 가능하도록 노출된 상태가 아니다.
kubectl describe pods my-nginx-pod

→ docker run 명령어에서 -p 옵션 없이 실행한 것과 유사!

  • 클러스터의 노드 중 하나에 접속하여, Nginx 포드의 IP로 HTTP 요청을 전송하여 Nginx 포드가 정상 실행 중인 것을 알 수 있다.

  • docker exec와 비슷하게, kubectl exec 명령어로 포드의 컨테이너에 명령어 전달이 가능하다.

kubectl exec -it my-nginx-pod bash
  • 쿠버네티스에서도 kubectl logs 명령어로 포드의 로그를 확인할 수 있다.

6.2.2 포드 vs. 도커 컨테이너

→ 여기까지만 놓고 보면, 포드는 docker run으로 생성한 단일 nginx 컨테이너와 유사하다?

  • 포드는 컨테이너 IP 주소를 갖고 있어 쿠버네티스 클러스터 내부에서 접근이 가능
  • kubectl exec 명령어로 포드 컨테이너 내부로 들어갈 수도 있음
  • kubectl logs 명령어로 포드의 로그 확인도 가능!

→ 그렇다면 쿠버네티스는 왜, '도커 컨테이너'가 아니라 '포드'라는 새로운 개념을 사용하는가?

→ 여러 리눅스 네임스페이스(namespace)를 공유하는 여러 컨테이너들을 추상화된 집합으로 사용하기 위함-!

→ 이 설명을 조금 더 자세히 알아보자-!

  • 대부분 쿠버네티스의 컨테이너 애플리케이션은 1개의 컨테이너로 포드를 구성해 사용한다.
  • 그러나, 포드는 반드시 1개의 컨테이너로 구성해야 하는 것은 아니다!
    [ cf. Nginx 포드에 새로운 우분투 컨테이너를 추가하기 ]
apiVersion: v1
kind: Pod
metadata:
	name: my-nginx-pod
spec:
	containers:
    - name: my-nginx-container
      image: nginx:latest
      ports:
      - containerPort: 80
      	protocol: TCP 
     
   - name: ubuntu-sidecar-container
     image: alicek106/rr-test:curl
     command: ["tail"]
     args: ["-f", "/dev/null"] # 컨테이너가 종료되지 않도록 유지   
  • cf. YAML에서 대시(-)를 사용하는 항목은 여러 개의 항목을 정의할 수 있음을 의미!
kubectl apply -f nginx-pod-with-ubuntu.yml # 적용
kubectl exec -it my-nginx-pod -c ubuntu-sidecar-container bash # 특정 컨테이너에서 배시 셸 실행 
  • 우분투 컨테이너에서 Nginx 서버를 실행하고 있지 않지만, 로컬호스트에서 Nginx 서버로 접근이 가능!
    • 포드 내의 컨테이너들이 네트워크 네임스페이스 등과 같은 리눅스 네임스페이스를 공유해 사용하기 때문-!

6.2.3 완전한 애플리케이션으로서의 포드

하나의 포드는 하나의 완전한 애플리케이션이다.

  • 포드의 주 컨테이너와 더불어, 기능 확장을 위한 추가 컨테이너를 함께 포드에 포함시킬 수 있다.
    • 포드에 정의된 부가적인 컨테이너를 사이드카(sidecar) 컨테이너라고 함!
    • 사이드카 컨테이너는 포드 내의 다른 컨테이너와 네트워크 환경 등을 공유
    • 따라서, 포드에 포함된 컨테이너들은 모두 같은 워커 노드에서 실행됨

포드에 정의된 여러 개의 컨테이너는 하나의 완전한 애플리케이션으로서 동작한다.
→ 이게 도커 컨테이너와 쿠버네티스 포드의 차이점!

6.3 레플리카셋(Replica Set) : 일정 개수의 포드를 유지하는 컨트롤러

6.3.1 레플리카셋을 사용하는 이유

쿠버네티스의 기본 단위인 포드는 여러 개의 컨테이너를 추상화해, 하나의 애플리케이션으로 동작하도록 만드는 컨테이너 묶음

  • 다만, YAML 파일에 포드만 정의해 생성할 경우, 해당 포드는 쿠버네티스 사용자에 의해서만 관리됨
  • 이에 따르는 여러 한계를 해결해주는 레플리카셋이라는 쿠버네티스 오브젝트를 함께 사용한다!
    • 레플리카셋은 정해진 수의 동일한 포드가 항상 실행되도록 관리
    • 노드 장애 등의 이유로 포드를 사용할 수 없다면 다른 노드에서 포드를 다시 생성

6.3.2 레플리카셋 사용하기

apiVersion: apps/v1     # 레플리카셋 정의
kind: ReplicaSet
metadata:
	name: replicaset-nginx
spec:
	replicas: 3  # 동일한 포드를 몇 개 유지할지 설정
    selector:                          
    	matchLabels:                   
        	app: my-nginx-pods-label       
    template:                # 포드 생성시 사용할 템플릿 정의
    	metadata:
        	name: my-nginx-pod
            labels:
            	app: my-nginx-pods-label
        spec:
        	containers:
            - name: nginx
              image: nginx:latest
              ports:
              - containerPort: 80

6.3.3 레플리카셋의 동작 원리

  • 실제로 레플리카셋은 포드와 연결돼 있지 않음

    • 느슨한 연결(Loosely coupled) 유지 중
    • 이러한 느슨한 연결은 포드와 레플리카셋의 정의 중 라벨 셀렉터(label selector)를 이용해 이뤄진다.
  • 포드 생성시, metadata 항목에서는 리소스의 고유 이름, 라벨 등 부가적인 정보를 설정할 수 있었다.

    • 라벨은 포드 등의 쿠버네티스 리소스 분류시 유용한 메타데이터!
  • 라벨은 서로 다른 오브젝트가 서로를 찾아야 할 때도 쓰인다.

    • 가령, 레플리카셋은 spec.selector.matchLabel에 정의된 라벨을 통해 생성해야 하는 포드를 찾는다.
    • 즉, app: my-nginx-pods-label 라벨을 가지는 포드의 개수가 replicas 항목에 정의된 3개와 일치하지 않으면, 포드를 정의하는 포드 템플릿 항목으로 포드를 생성함.

레플리카셋의 목적은 '포드를 생성하는 것'이 아니라 '일정 개수의 포드를 유지하는 것'이다.

+) 레플리카셋의 selector.matchLabel 항목처럼, 두 리소스 간의 라벨을 일치시킴으로써 쿠버네티스의 기능을 사용하는 경우가 많다!

6.4 디플로이먼트(Deployment) : 레플리카셋, 포드의 배포를 관리

6.4.1 디플로이먼트 사용하기

  • 실제 쿠버네티스 운영 환경에서 레플리카셋을 YAML 파일에서 사용하는 경우는 거의 없다..
  • 레플리카셋과 포드의 정보를 정의하는 디플로이먼트(Deployment)라는 이름의 오브젝트를 YAML 파일에 정의해 사용함!
  • 디플로이먼트는 레플리카셋의 상위 오브젝트이므로, 디플로이먼트를 생성하면 해당 디플로이먼트에 대응하는 레플리카셋도 함께 생성된다!
apiVersion: apps/v1
kind: Deployment
metadata:
	name: my-nginx-deployment
spec:
	replicas: 3
    selector: 
    	matchLabels: 
        	app: my-nginx
    template:
    	metadata:
        	name: my-nginx-pod
            labels: 
            	app: my-nginx
        spec:
        	containers:
            - name: nginx
              image: nginx:1.10
              ports:
              - containerPort: 80            

6.4.2 디플로이먼트를 사용하는 이유

애플리케이션의 업데이트와 배포를 더욱 편하게 만들기 위함!

  • 애플리케이션을 업데이트할 때 레플리카셋의 변경 사항을 저장하는 리비전을 남겨, 롤백을 가능하게 하거나
  • 무중단 서비스를 위해 포드의 롤링 업데이트 전략을 지정하기도 한다!

[ ex. 포드의 이미지 버전을 nginx:1.11로 변경하기 ]

kubectl set image deployment my-nginx-deployment nginx=nginx:1.11 --record

→ 이렇게 실행하면, 레플리카셋의 목록이 2개가 된다!
→ 디플로이먼트는 포드의 정보를 업데이트함으로써 새로운 레플리카셋과 포드를 생성했음에도 불구하고, 이전 버전의 레플리카셋을 삭제하지 않고 남겨둔다.

6.5 서비스(Service) : 포드를 연결하고 외부에 노출

  • 도커 컨테이너와 마찬가지로 포드의 IP는 영속적이지 않아, 변할 수 있음.

  • 여러 개의 디플로이먼트를 하나의 완벽한 애플리케이션으로 연동하려면 포드 IP가 아닌, 서로를 발견(Discovery)할 수 있는 방법이 필요!

  • 쿠버네티스는 디플로이먼트를 생성할 대 포드를 외부로 노출하지 않으며,
    디플로이먼트의 YAML 파일에는 단지 포드의 애플리케이션이 사용할 내부 포트만 정의

    • 이 포트를 외부로 노출해 사용자들이 접근하거나, 다른 디플로이먼트의 포드들으 내부적응로 접근하려면 서비스(Service)라고 부르는 별도의 쿠버네티스 오브젝트를 생성해야 한다!

[ 서비스 주요 기능 ]

  • 여러 개의 포드에 접근할 수 있도록 고유한 도메인 이름 부여
  • 여러 개의 포드에 접근할 때, 요청을 분산하는 로드밸런서 기능 수행
  • 클라우드 플랫폼의 로드 밸런서, 클러스터 노드의 포트 등을 통해 포드를 외부로 노출

6.5.1 서비스(Service)의 종류

  • 쿠버네티스의 서비스는 포드에 어떻게 접근할 것이냐에 따라 종류가 여러 개로 세분화되어 있음.
  • 주로 사용하는 서비스 타입은 크게 3가지다!
    • ClusterIP 타입 : 쿠버네티스 내부에서만 포드들에 접근할 때 사용. 외부로 포드를 노출하지 않기 대문에, 쿠버네티스 클러스터 내부에서만 사용되는 포드에 적합
    • NodePort 타입 : 포드에 접근할 수 있는 포트를 클러스터의 모든 노드에 동일하게 개방. 따라서, 외부에서 포드에 접근할 수 있는 서비스타입!
    • LoadBalancer 타입 : 클라우드 플랫폼에서 제공하는 로드 밸런서를 동적으로 프로비저닝해 포드에 연결. NodePort 타입과 마찬가지고 외부에서 포드에 접근이 가능!

6.5.2 ClusterIP 타입의 서비스 - 쿠버네티스 내부에서만 포드에 접근하기

apiVersion: v1
kind: Service
metadata:
	name: hostname-svc-clusterip
spec: 
	ports:
    	- name: web-port
          port: 8080 # 서비스의 IP에 접근할 때 사용할 포트를 설정
          targetPort: 80 # selector 항목에서 정의한 라벨에 의해 접근 대상이 된 포드들이 내부적으로 사용 중인 포트
    selector: # 이 서비스에서 어떠한 라벨을 갖는 포드에 접근할 수 있게 할 것인가
    	app: webserver
     type: ClusterIP   
  1. 특정 라벨을 가지는 포드를 서비스와 연결하기 위해 서비스의 YAML 파일에 selector 항목을 정의
  2. 포드에 접근할 때 사용하는 포트(포드에 설정된 containerPort)를 YAML 파일의 targetPort 항목에 정의
  3. 서비스를 생성할 때, YAML 파일의 port 항목에 8080을 명시해 서비스의 Cluster IP와 8080 포트로 접근할 수 있게 설정
  4. kubectl apply -f 명령어로 ClusterIP 타입의 서비스가 생성되면, 서비스는 쿠버네티스 클러스터 내부에서만 사용할 수 있는 고유한 내부 IP를 할당받음.
  5. 쿠버네티스 클러스터에서 서비스의 내부 IP 또는 서비스 이름으로 포드에 접근할 수 있음.

6.5.3 NodePort 타입의 서비스 - 서비스를 이용해 포드를 외부에 노출하기

  • 클러스터 외부에서도 접근 가능
  • 모든 노드(Node)의 특정 포트(Port)를 개방해 서비스에 접근하는 방식
    • 스웜 모드에서 컨테이너를 외부로 노출하는 방식과 비슷하다.
apiVersion: v1
kind: Service
metadata:
	name: hostname-svc-nodeport
spec:
	ports:
      - name: web-port
        port: 8080
        targetPort: 80
    selector:
    	app: webserver
    type: NodePort        
  • NodePort 타입의 서비스인데도, kubectl get service 명령어의 출력에서 CLUSTER-IP 항목에 내부 IP도 할당된다!

  • 이는 NodePort 타입의 서비스가 ClusterIP의 기능을 포함하고 있기 때문!

  • 다만, 실제 운영 환경에서 NodePort로 서비스를 외부에 제공하는 경우는 많지 않다.

    • SSL 인증서 적용, 라우팅 등과 같은 설정을 적용하기 어렵기 때문.
  • 따라서, NodePort 서비스 그 자체를 통해 서비스를 외부로 제공하기보다는 인그레스(Ingress)라고 부르는 쿠버네티스의 오브젝트에서 간접적으로 사용함!

6.5.4 클라우드 플랫폼의 로드 밸런서와 연동하기 - LoadBalancer 타입의 서비스

  • 서비스 생성과 동시에 로드 밸런서를 새롭게 생성해 포드와 연결
  • 로드 밸런서를 동적으로 생성하는 기능을 제공하는 환경에서만 사용할 수 있음.
    • AWS, GCP 등과 같은 클라우드 플랫폼!
apiVersion: v1
kind: Service
metadata:
	name: hostname-svc-lb
spec:
	ports:
      - name: web-port
        port: 80 # 로드밸런서에 접근하기 위한 포트
        targetPort: 80
    selector:
    	app: webserver
     type: LoadBalancer   
  1. LoadBalancer 타입의 서비스가 생성됨과 동시에, 모든 워커 노드는 포드에 접근할 수 있는 랜덤한 포트를 개방한다.
  2. 클라우드 플랫폼에서 생성된 로드 밸런서로 요청이 들어오면, 이 요청은 쿠버네티스의 워커 노드 중 하나로 전달되며, 이때 사용하는 포트는 1번에서 개방된 포트이다.
  3. 워커 노드로 전달된 요청은 포드 중 하나로 전달되어 처리된다.

6.5.5 트래픽의 분배를 결정하는 서비스 속성 : externalTrafficPolicy

  • LoadBalancer 타입의 서비스를 사용하면 외부로부터 들어온 요청은 각 노드 중 하나로 보내지며, 그 노드에서 다시 포드 중 하나로 전달!
kubectl get svc hostname-svc-nodeport -o yaml

→ externalTrafficPolicy의 기본 설정값인 Cluster는 클러스터의 모든 노드에 랜덤한 포트를 개방하는 방식
Local로 설정하면, 포드가 생성된 노드에서만 포드로 접근할 수 있고, 로컬 노드에 위치한 포드 중 하나로 요청이 전달된다!

apiVersion: v1
kind: Service
metadata:
	name: hostname-svc-lb-local
spec:
	externalTrafficPolicy: Local
    ports:
      - name: web-port
        port: 80
        targetPort: 80
    selector:
      app: webserver
    type: LoadBalancer   

각 노드에 포드가 고르지 않게 스케줄링 됐을 때, 요청이 고르게 분산되지 않을 수도 있다.
→ Cluster와 Local 모두 장단점이 있음!

profile
주니어 백엔드 개발자입니다! 조용한 시간에 읽고 쓰는 것을 좋아합니다 :)

0개의 댓글