ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 쿠버네티스 (2)
    DevOps 2023. 5. 9. 03:14

     

    이전 글에서 Controller 의 개념까지 알아봤습니다. 이번 글에서는 Service 의 개념부터 그 외 기능까지 마무리 하도록 하겠습니다.

    혹시 이전 글을 읽지 않으셨다면 참고해주시면 감사하겠습니다.

     

    쿠버네티스 (1)

    회사에서 쿠버네티스를 도입하며 지금까지 미뤄두었던 쿠버네티스에 대한 학습이 필요했기 때문에 이번 기회에 쿠버네티스를 사용하는데 필요한 기본적인 개념들에 대해 공부했습니다. 이번

    jinmook.tistory.com

     

    1. 실습 환경 구성 방법

    2. 쿠버네티스 기본

    3. Pod

    4. Controller

    5. Service

    6. Ingress

    7. 그 외 기능 (Label, ConfigMap, Secret)

     

     


     

    5. Service

    • 동일한 서비스를 제공하는 Pod 그룹의 단일 진입점을 제공합니다.
    • 서비스는 기본적으로 자신의 클러스터 IP를 가지고 있고 이 서비스를 pod에 연결하면 서비스의 아이피로 파드에 접근이 가능합니다.
      • pod에도 자신의 클러스터 IP를 가지고 있는데, pod의 경우는 언제든지 죽을 수 있고 재생성될 수 있기 때문에 ip는 가변젹으로 재생성되면서 변하게 됩니다.
      • 따라서 pod의 IP가 아닌 서비스 IP 를 이용해서 pod에 접근해야 합니다.
      • 즉, 특정 파드에 일관된 아이피를 통한 접근을 가능하게 하기 때문에 서비스를 사용합니다.

     

     

     

    • Service 4가지 타입을 지원합니다.
      1. ClusterIP : Pod 그룹의 단일 진입점(Virtual IP) 생성 → 내부에서만 접속 가능
      2. NodePort : ClusterIP가 생성된 후 모든 worker node에 외부에서 접속 가능한 포트가 예약
      3. LoadBalancer : 클라우드 인프라스트럭처(AWS, Azure, GCP…)나 오픈스택 클라우드에 적용
      4. ExternalName : 클러스터 안에서 외부에 접속 시 사용할 도메인을 등록해서 사용, 클러스터 도메인이 실제 외부 도메인으로 치환되어 동작

     

    결국 동일한 기능을 하는 어플리케이션 파드, 예를 들어 backend api 어플리케이션을 갖는 pod가 여러 개라면 각 pod들은 모두 서로 다른 ip를 갖게될 것입니다. 따라서 궁극적으로 backend api에 어플리케이션에 접근하기 위한 단 하나의 ClusterIP인 단일 진입점을 제공하는 것이 Service라고 이해하면 좀 더 쉬울 것 같습니다.

     

    지금부터 각 타입에 대해 좀 더 자세히 알아보겠습니다.

     

    [ ClusterIP ]

    • selector의 label과 동일한 pod들을 그룹으로 묶어 단일 진입점을 생성해줍니다.
    • 클러스터 내부에서만 사용가능합니다.
    apiVersion: v1
    kind: Service
    metadata:
      name: clusterip-service
    spec:
      type: ClusterIP
      clusterIP: 10.100.100.100
      selector:
        app: webui
      ports:
        - protocol: TCP
          port: 80
          targetPort: 80
    

     

    port 옵션은 서비스가 생성할 port 입니다. targetPort는 서비스가 접근할 pod의 port 입니다.

     

    아래 사진은 위 yaml 파일을 실행했을 때 EndPoints로 5개의 nginx pod들이 연결되어 있는 것을 확인할 수 있습니다.

     

     

    [ NodePort ]

    • ClusterIP는 클러스터 내부에서만 접근할 수 있습니다.
    • NodePort를 통해 클러스터 외부에서 접근할 수 있습니다.
    • 모든 노드를 대상으로 외부 접속 가능한 포트를 예약해줍니다.
    • ClusterIP를 생성 후 NodePort를 예약하는 구조입니다.
    apiVersion: v1
    kind: Service
    metadata:
      name: nodeport-service
    spec:
      type: NodePort
      clusterIP: 10.100.100.200
      selector:
        app: webui
      ports:
        - protocol: TCP
          port: 80
          targetPort: 80
          nodePort: 30080
    
    • 위 yaml 파일을 실행하고 로컬 pc에서 특정 node ip의 30200 포트로 연결을 시도하면 정상적인 응답을 받을 수 있습니다.

     

    위 사진에서 외부 클라이언트에서 각 노드에 생성된 pod에 접근하고 싶을 때 특정 노드(Node1, Node2 상관없이)의 NodePort인 30080 포트로 접근을 하게되면 ClusterIP로 전송되며 이때 Service를 통해 랜덤한 Pod로 요청이 전달되는 구조입니다.

     

    즉, NodePort를 이용해 클러스터 외부에서 각 Pod에 접근할 수 있게 되는 것입니다.

     

     

    [ LoadBalancer ]

    • public 클라우드(AWS, Azure, GCP 등)에서 운영가능
    • LoadBalancer를 자동으로 구성 요청
    • NodePort를 예약 후 해당 nodeport로 외부 접근을 허용합니다.
    apiVersion: v1
    kind: Service
    metadata:
      name: loadbalancer-service
    spec:
      type: LoadBalancer
      selector:
        app: webui
      ports:
        - protocol: TCP
          port: 80
          targetPort: 80
    

     

    결국 LoadBalancer가 각 노드의 NodePort에 대한 로드밸런싱 역할을 진행하게 됩니다.

    참고로 현재 직장에서 TB에 쿠버네티스 클러스터를 구축할 때 클라우드가 아닌 온프레미스 환경이었기 때문에 haproxy를 이용해 LoadBalancer와 비슷한 역할을 하도록 설정했습니다.

     

     

    [ ExternalName ]

    • ExternalName은 외부 서비스를 쿠버네티스 내부에서 호출하고자할때 사용할 수 있습니다.
    • cluster 내의 pod 들은 클러스터 IP 대역 밖의 서비스를 호출하고자 하면, 복잡한 설정이 필요합니다.
    • 특히 AWS, GCP와 같은 클라우드 환경을 사용할 경우 데이터베이스나, 클라우드에서 제공되는 외부 서비스를 사용하고자 할 경우 쿠버네티스 클러스터 밖이기 때문에 호출이 어려운 경우가 있는데, 이를 쉽게 해결할 수 있는 방법이 ExternalName 입니다.
    apiVersion: v1
    kind: Service
    metadata:
      name: externalname-svc
    spec:
      type: ExternalName
      externalName: google.com
    
    • 특정 pod에 들어가서 curl externalname-svc 를 호출하게 되면 google.com 의 페이지가 확인되는 것을 알 수 있습니다.

     

    아래 블로그를 통해 ExternalName에 대해 좀 더 자세히 확인할 수 있습니다.

     

    [k8s] Service - ExternalName 사용하기

    쿠버네티스에서 ExternalName 유형의 서비스는 일반적인 셀렉터에 대한 서비스가 아니라 DNS 이름에 대한 서비스에 매핑합니다. ExternalName 서비스 생성 다음은 ExternalName 타입의 서비스를 설정하는

    kimjingo.tistory.com

     

     

    [ Kubernetes Headless 서비스 ]

    • ClusterIP가 없는 서비스로 단일 진입점이 필요없을 때 사용합니다.
    • Headless Service로 묶인 pod들은 각각 아래와 같은 고정된 DNS를 가집니다.

     

    [pod-name].[svc].[namespace].svc.cluster.local

     

    • 사실 Headless Service가 없더라도 pod는 기본적으로 아래와 같은 DNS를 가집니다.

     

    [pod-ip-address].[namespace].pod.cluster.local

     

    하지만 DNS에 pod의 ip 주소가 포함되어 있기 때문에 사실상 고정된 DNS가 아닙니다.

    이때 StatefulSet의 경우 고정된 pod 이름을 가지므로 Headless Service와 같이 사용하게 되면 고정된 DNS를 가진다고 할 수 있습니다.

    즉, Headless Service와 StatefulSet을 이용해서 Service를 통해 수행되던 로드밸런싱이나 proxy를 사용하지 않고 고정된 DNS를 생성할 수 있습니다.

     

    아래 yaml 설정 파일에서 type 속성은 ClusterIP이지만 IP를 None으로 설정해주면 헤드리스 서비스입니다. 만약 IP를 설정하지 않는다면 랜덤 ClusterIP가 설정됩니다.

    apiVersion: v1
    kind: Service
    metadata:
      name: headless-srvice
    spec:
      type: ClusterIP
      clusterIP: None
      selector:
        app: webui
      ports:
        - protocol: TCP
          port: 80
          targetPort: 80
    

     

    • Headless Service와 StatefulSet 실습을 해볼 수 있는 블로그 자료입니다.
     

    Kubernetes의 Statefulset 실습

    Kubernetes의 StatefulSet을 이해하기 위해 Headless 서비스가 무엇인지 왜 필요한지 실습해보고 Mysql 예제를 공부해보자.

    velog.io

     

     


     

    6. Ingress

    • HTTP나 HTTPS를 통해 클러스터 내부의 서비스를 외부로 노출시켜줍니다.
    • Ingress의 기능은 아래와 같습니다.
      • Service에 대한 외부 URL을 제공
      • 트래픽을 로드밸런싱
      • SSL 인증서 처리
      • Virtual hosting을 지정

     

     

    kubernetes가 제공해주는 인그레스 컨트롤러가 있는데 프로젝트로서는 AWS, GCE, nginx 인그레스 컨트롤러를 지원합니다. 아래 페이지를 통해 설치 방법을 확인할 수 있습니다.

    참고로 저는 가상 머신 환경에서 실습했기 때문에 Nginx Ingress에서 Bare-metal을 이용해서 설치를 진행했습니다.

     

     

    Installation Guide - Ingress-Nginx Controller

    Installation Guide There are multiple ways to install the Ingress-Nginx Controller: with Helm, using the project repository chart; with kubectl apply, using YAML manifests; with specific addons (e.g. for minikube or MicroK8s). On most Kubernetes clusters,

    kubernetes.github.io

     

    ingress-nginx controller를 설치하게 되면 네임스페이스, 서비스, deployment 등이 생성됩니다.

     

     

    아래는 ingress rule 설정 파일이며 로드밸런싱 역할을 수행합니다.

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: marvel-ingress
    spec:
      rules:
        - http:
            paths:
            - path: /
              pathType: Prefix
              backend:
                service: 
                  name: marvel-service
                  port:
                    number: 80
            - path: /pay
              pathType: Prefix
              backend:
                service:
                  name: pay-service
                  port:
                    number: 80

     

     


     

    7. 그 외 기능

    [ Label ]

    • node를 포함하여 pod, deployment 등 모든 리소스에 할당 가능합니다.
    • Selector를 이용해서 특정 리소스를 선택할 수 있습니다.
    • key-value 쌍으로 적용합니다.

     

    참고로 아래 사진은 Label과 Selector 구문 예시 입니다.

     

    node에도 label을 설정할 수 있습니다. 이를 통해 특정 노드를 선택해서 pod를 배치할 수 있습니다.

    아래 예시는 만약 gpu가 존재하고 disk가 ssd인 node에 pod를 띄우는 예시입니다.

    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-nodeselector
    spec:
      nodeSelector:
        gpu: "true"
        disk: ssd
      containers:
        - name: nginx
          image: nginx:1.14
          ports:
            - containerPort: 80
    

    위 사진을 살펴보면 node1, node2의 DISK, GPU 라벨이 있는 것을 확인할 수 있습니다. 즉, 라벨을 통해 노드의 특징을 나타낼 수 있다는 것을 알 수 있습니다.

    이때 위 yaml 파일 설정을 적용하게 되면 gpu가 true 이며 disk가 ssd인 node1에 해당 pod이 띄워지는 것을 확인할 수 있는 사진입니다.

     

    Label을 통한 카나리 배포

    • 카나리 업데이트 → 기존 버전에 새로운 버전을 하나씩 집어 넣는 방법
    • 구버전과 신버전 pod를 모두 구성한 뒤, 트래픽의 양을 조절하여 테스트를 진행한 다음 교체하는 방식
    • 기존 버전을 유지한 채로 일부 버전만 신규 버전으로 올려서 신규 버전에 버그나 이상이 없는지 확인합니다.
    카나리배포 : 예를들어 이전버전 80%, 새버전 20%와 같이 기준을 정해 새버전과 기존버전을 함께 동작시켜 전체 운영환경 모니터링, 서비스 동작 모니터링등을 하는 것입니다. 신버전 TEST하기 위해 사용합니다.

     

     

    위 사진에서 Label 을 이용해 카나리 배포를 진행할 수 있는데 단계별로 설명해보겠습니다.

     

    1. 가장 먼저 stable 버전의 Deployment가 2개의 replicas 를 갖고 띄워져 있는 상태입니다.

     

    2. 다음으로 각 pod들의 단일진입점인 Service를 설정해주는데 이때 app=mainui 라벨을 선택하게 설정해줍니다.

     

    3. 이후 canary 버전 즉, 업데이트할 버전을 1개의 replicas를 갖고 띄웁니다. 이때 app=mainui를 갖기 때문에 서비스를 통해 일부 요청은 canary 버전으로 전달되게 되는것을 알 수 있습니다.

     

    4. 전체 서비스에 문제가 없다면 canary 버전의 replicas 숫자를 변경하며 테스트하며 점차 stable 버전의 replicas를 줄여주며 테스트를 하게 되면서 canary 배포가 진행됩니다.

     

     

     [ ConfigMap ]

    • 컨테이너 구성 정보를 한곳에 모아서 관리해줍니다.
    • ConfigMap 커멘드를 통해 생성하는 방법
      • 파일을 통해 생성할 수 있는데 --from-file=파일명 옵션을 통해 생성 가능합니다. 이때 key값은 파일명이 되고 value가 파일의 내용이 됩니다.
      • 추가로 --from-file=mydata=파일명 옵션으로 작성하면 key가 파일명이 아닌 mydata가 되고 value가 파일의 내용이 됩니다.
      • 특정 디렉토리 아래에서는 /config.dir/ 디렉토리에 있는 모든 파일들을 ConfigMap에 저장하는 방법도 가능합니다.

     

     

    아래 공식문서를 통해 ConfigMap 예시를 좀 더 자세히 확인할 수 있습니다.

     

    ConfigMaps

    A ConfigMap is an API object used to store non-confidential data in key-value pairs. Pods can consume ConfigMaps as environment variables, command-line arguments, or as configuration files in a volume. A ConfigMap allows you to decouple environment-specifi

    kubernetes.io

     

    [ kubernetes Secret ]

    • 위에서 본 ConfigMap과 비슷하게 컨테이너 구성 정보를 한곳에 모아서 관리해줍니다.
    • Secret : 컨테이너가 사용하는 password, auth token, ssh key와 같은 중요한 정보를 저장하고 민감한 구성정보를 base64로 인코딩해서 한 곳에 모아서 관리해줍니다.
    • 민감하지 않은 일반 설정파일은 ConfigMap을 사용하고, 민감한 데이터는 secret을 사용합니다.
    • pod를 띄울 때는 해당 secret들이 디코딩 되어서 입력되게 됩니다.

     

     

    아래 공식문서를 통해 Secret 예시를 좀 더 자세히 확인할 수 있습니다.

     

     

    Secrets

    A Secret is an object that contains a small amount of sensitive data such as a password, a token, or a key. Such information might otherwise be put in a Pod specification or in a container image. Using a Secret means that you don't need to include confiden

    kubernetes.io

     

     

    마지막으로 이번에는 제대로 정리하지 못한 퍼시스턴트 볼륨에 대해서도 한번 학습해보시면 도움이 될것 같아서 참고할만한 블로그 공유합니다.

     

     

    [Kubernetes] 쿠버네티스 볼륨 개념 1편 (emptryDir, hostPath)

    볼륨을 사용해야하는 이유? 컨테이너 특성 상 어떠한 문제가 발생하여 컨테이너가 삭제 된다면 데이터도 같이 삭제 됩니다. 웹 소스 파일의 경우 이미지에 들어있어 삭제 되더라도 상관 없겠지

    nirsa.tistory.com

     

     

    퍼시스턴트 볼륨

    이 페이지에서는 쿠버네티스의 퍼시스턴트 볼륨 에 대해 설명한다. 볼륨에 대해 익숙해지는 것을 추천한다. 소개 스토리지 관리는 컴퓨트 인스턴스 관리와는 별개의 문제다. 퍼시스턴트볼륨 서

    kubernetes.io

     

     


    [ 글을 마무리하며...]

    이번에 큰 맘 먹고 쿠버네티스에 관해 학습을 했는데 개인적으로 네트워크 부분이 가장 어렵다고 느꼈습니다. CNI부터 시작해서 각 컨테이너들이 어떻게 서로 작동하는지 연결되는지 등등, 사실 도커랑 비슷하겠지 정도의 생각을 갖고 처음 학습을 시작했는데 생각했던 것보다 훨씬 복잡해서 추후에 네트워크 관련해서는 개인적인 학습이 좀 더 필요하다고 많이 느꼈습니다.

     

    사실 가장 아쉬운 점은 현재 팀에서 진행하는 프로젝트는 쿠버네티스 환경에서 서비스가 이루어지고 있지 않기 때문에 이번에 경험만 잠깐 해보고 실무에서 사용해볼 기회가 없다는 점인데... 그래도 일단 한번 쭉 정리해봤으니 이후에 언젠가 쿠버네티스를 사용하는 환경이 된다면 좀 더 빠르게 적응할 수 있지 않을까 라는 소박한 기대를 하며 정리를 했습니다.

     

    개인적으로 공부하고 정리한 내용이다보니 틀린 내용이 있을수도 있습니다. 정확한 정보를 전달하면 좋겠지만 아직은 실력이 부족해서 정확한 정보보다는 쿠버네티스가 이런거구나 하는 느낌으로 편하게 읽어주시면 감사하겠습니다.

     

    마지막으로 이전 글에서 유튜브 강의를 듣고 학습했다고 했는데 정말 좋은 강의를 무료로 공개해주셔서 다시한번 너무나 감사하고 이후에 쿠버네티스를 좀 더 제대로 활용하게 된다면 추가 강의도 학습할 예정입니다. 처음 쿠버네티스를 공부하시는 분들이라면 한번쯤 들어보면서 공부하는 것을 개인적으로 추천하면서 마무리하도록 하겠습니다. 감사합니다.

     

     

     

    'DevOps' 카테고리의 다른 글

    쿠버네티스 (1)  (0) 2023.05.02

    댓글

Designed by Tistory.