ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [kubernetes] 쿠버네티스 시작하기
    Software Development/기타 2022. 5. 30. 23:00

    '시작하세요! 도커/쿠버네티스' 읽고 정리한 내용을 적습니다.

     

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

    모든 리소스는 오브젝트 형태로 관리

    k8s는 대부분의 리소스를 '오브젝트'라고 불리는 형태로 관리.

    쿠버네티스는 명령어로도 사용할 수 있지만, YAML 파일을 더 많이 사용

    kubetcl이라는 명령어로 k8s를 사용할 수 있음. kubetcl로 대부분의 작업을 실행할 수 있음.

    YAML파일로 컨테이너뿐만 아니라 모든 리소스 오브젝트들에 사용될 수 있음.

    실제 서비스 배포시에 YAML 파일을 정의해 k8s에 적용시키는 방식으로 동작.

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

    컨테이너 애플리케이션을 구동하기 위해서는 Pod, replica-set, service, deployment등의 오브젝트가 있는데, 가장 기초가 되는 게 Pod

    6.2.1 포드 사용하기

    포드는 1개 이상의 컨테이너로 구성된 컨테이너의 집합.

    도커 엔진의 기본 단위 - 도커 컨테이너

    스웜 모드의 기본 단위 - 서비스

    k8s의 기본 단위 - Pod

    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 버전. 오브젝트의 종류 및 개발 성숙도에 따라 apiVersion의 설정값이 달라질 수 있음.
    • kind: 리소스의 종류
    • metadata: 라벨, 주석, 이름 등과 같은 리소스의 부가 정보
    • spec: 리소스를 생성하기 위한 자세한 정보를 입력

    k8s 생성 명령어: kubectl apply -f <nginx-pod.yaml>

    오르젝트 목록 확인 명령어: kubectl get <pods>

    생성된 리소스의 자세한 정보: kubetcl describe pods <my-nginx-pod>

     

    포드의 IP는 외부에서 접근할 수 있는 것이 아님. k8s 외부 또는 내부에서 포드에 접근하려면 서비스(service)라고 하는 k8s 오브젝트를 따로 생성해야 함.

     

    docker exec 명령어와 비슷하게 kubectl exec 명령으로 포드의 컨테이너에 명령어를 전달할 수 있음.

     

    docker logs 명령어를 사용했던 것처럼 k8s도 kubectl logs 명령어로 포드의 로그를 확인할 수 있음.

     

    오브젝트 삭제 명령어: kubectl delete -f <nginx-pod.yaml>

    6.2.2 포드 vs 도커 컨테이너

    k8s가 포드를 사용하는 이유: 여러 리눅스 네임스페이스를 공유하는 여러 컨테이너들을 추상화된 집합으로 사용하기 위해서.

    같은 포드 내의 컨테이너는 네트워크 네임스페이스를 공유하기도 하며, 다른 네임스페이스를 공유.

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

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

    Nginx의 설정 파일 변경사항을 갱신해주는 리로드 프로세스나 로그를 수집해주는 프로세스는 Nginx 컨테이너와 함께 실행돼야 할 수 있음. 포드에 정의된 부가적인 컨테이너를 사이드카 컨테이너라고 명칭하며, 포드 내의 다른 컨테이너와 네트워크 환경 등을 공유.

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

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

    포드는 여러개의 컨테이너를 추상화해 하나의 애플리케이션으로 동작하도록 만드는 컨테이너 묶음.

    YAML에 포드만 정의해 생성하게 되면 이 포드의 생애 주기는 어떻게 될까?

    YAML 파일에 포드만 정의해 생성할 경우 해당 포드는 오직 k8s 사용자에 의해 관리. 실제로 외부 사용자의 요청을 처리해야 하는 마이크로 서비스 구조의 포드라면 이러한 방식을 사용하기 어려움. 스웜 모드처럼 MS에서는 여러 개의 동일한 컨테이너를 생성한 뒤 외부 요청이 각 컨테이너에 적절히 분배될 수 있어야 함.

     

    k8s에서는 기본 단위가 포드이기 때문에 동일한 여러 개의 포드를 생성해 외부 요청을 각 포드에 분배하는 방식을 사용.

    동일 포드를 여러개 생성하는 것을 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
    • spec.replicas: 동일한 포드를 몇 개 유지시킬 것인지 설정.
    • spec.template 아래의 내용들: 포드를 생성할 때 사용할 템플릿을 정의. 포드를 사용했던 내용을 동일하게 리플리카셋에도 정의함으로써 어떠한 포드를 어떻게 생성할 것인지 명시.

    kubectl apply -f <replicaset-nginx.yaml>로 생성.

     

    만일 포드의 개수를 늘려 4개의 포드가 실행되게 하려면, 이미 생성된 리플리카셋을 삭제하고 다시 생성할 필요는 없음. k8s에서는 이미 생성된 리소스의 속성을 변경하는 기능을 제공.

    kubectl apply -f <replicaset-nginx.yaml>로 생성.

    6.3.3 리플리카셋의 동작 원리

    리플리카셋과 포드는 라벨 셀렉터를 통해 느슨한 결합을 유지함.

    라벨은 포드 등의 k8s 리소스를 분류할 때 유용하게 사용할 수 있는 메타데이터.

    라벨은 k8s 리소스의 부가적인 정보를 표현할 수 있을 뿐만 아니라, 서로 다른 오브젝트가 서로를 찾아야 할 때 사용. spec.selector.matchLabel에 정의된 라벨을 통해 생성해야 하는 포드를 찾음.

    리플리카셋의 목적은 '일정 개수의 포드를 유지하는 것'

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

    6.4.1 디플로이먼트 사용하기

    운영 환경에서 리플리카셋을 YAML 파일에서 사용하는 경우는 거의 없음. 배부분은 리플리카셋과 포드의 정보를 정의하는 디플로이먼트라는 이름의 오브젝트를 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 디플로이먼트를 사용하는 이유

    애플리케이션의 업데이트와 배포를 더욱 편하게 만들기 위해서 사용. 디플로이먼트는 컨테이너 애플리케이션을 배포하고 관리하는 역할을 담당.

    디플로이먼트는 포드의 정보가 변경되어 업데이트가 발생했을 때, 이전의 정보를 리비전으로서 보존.

    디플로이먼트에서 생성된 포드의 이미지를 변경할 때는 kubectl set image 명령어를 사용할 수 있습니다. 

    --record=true 옵션으로 디플로이먼트를 변경하면 변경 사항을 디플로이먼트에 기록함으로써 해당 버전의 리플리카셋을 보존.

    디플로이먼트를 사용하면 리플리카셋의 리비전 관리뿐만 아니라 다양한 포드의 롤링 업데이트 정책을 사용할 수 있다는 장점.

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

    도커 컨테이너는 -p(publish) 옵션으로 컨테이너를 외부로 노출할 수 있음. 오버레이 네트워크나 도커 사용자 정의 네트워크, docker run --link 옵션으로 컨테이너들이 서로를 이름으로 접근할 수 있음.

    k8s는 디플로이먼트를 생성할 때 포드를 외부로 노출하지 않으며, 디플로이먼트의 YAML 파일에는 단지 포드의 애플리케이션이 사용할 내부 포트만 정의.

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

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

    6.5.1 서비스의 종류

    • ClusterIP 타입: k8s 내부에서만 포드들에 접근할 때 사용. k8s 클러스터 내부에서만 사용되는 포드에 적합.
    • NodePort 타입: 포드에 접근할 수 있는 포트를 클러스터의 모든 노드에 동일하게 개방. 외부에서 포드에 접근할 수 있는 서비스 타입.
    • LoadBalancer 타입: NodePort 타입과 마찬가지로 외부에서 포드에 접근할 수 있는 서비스 타입. 일반적으로 AWS, GCP 등과 같은 클라우드 플랫폼 환경에서만 사용.

    포드를 내부에서만 접근하고 싶다면 ClusterIP.

    외부에서도 포드에 접근하고 싶다면 NodePort.

    실제 운영 환경에서는 LoadBalancer.

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

    apiVersion: v1
    kind: Service
    metadata:
      name: hostname-svc-clusterip
    spec:
      ports:
        - name: web-port
          port: 8080
          targetPort: 80
      selector:
        app: webserver
      type: ClusterIP
    • spec.selector: 이 서비스에서 어떠한 라벨을 가지는 포드에 접근할 수 있게 만들 것인지 결정. 예시에서는 app: webserver라는 라벨을 가지는 포드들의 집합에 접근할 수 있는 서비스를 생성.
    • spec.ports.port: 쿠버네티스 배수에서만 사용할 수 있는 고유한 IP를 할당.
    • spec.ports.targetPort: 접근 대상이 된 포드들이 내부적으로 사용하고 있는 포트를 입력.
    • spec.type: 서비스의 타입.

    kubectl apply -f <hostname-svs-clusterip.yaml>

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

    NodePort는 모든 노드의 특정 포트를 개방해 서비스에 접근하는 방식.

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

    도메인 이름과 IP를 할당받기 때문에 NodePort보다 더욱 쉽게 포드에 접근할 수 있음.

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

    LoadBalancer 타입의 서비스를 사용하면 외부로부터 들어온 요청은 각 노드 중 하나로 보내지며, 그 노드에서 다시 포드 중 하나로 전달. NodePort 타입을 사용했을 때도 각 노드로 들어오는 요청은 다시 포드 중 하나로 전달.

    이는 네트워크 홉이 한 단계 더 발생하게 됨. 그리고 노드 간의 리다이렉트가 발생하게 되어 트래픽의 출발지 주소가 바뀌는 SNAT가 발생하게 되고, 이로 인해 클라이언트의 IP 주소 또한 보존되지 않는다는 단점이 있음.

    LoadBalancer를 Local로 설정하면 포드가 생성된 노드에서만 포드로 접근할 수 있으며, 로컬 노드에 위치한 포드 중 하나로 요청이 전달. 추가적인 네트워크 홉과 전달되는 요청의 클라이언트 IP 또한 보존.

    대신 요청이 고르게 분산되지 않을 수 있으며, 이는 자원 활용률 측면에서 바람직하지 않을 수 있음.

    6.5.6 요청을 외부로 리다이렉트하는 서비스: ExternalName

    k8s를 외부 시스템과 연동해야 할 때는 ExternalName 타입의 서비스를 사용.

    댓글

Designed by Tistory.