서비스

이지우·2023년 5월 5일
0

쿠버네티스

목록 보기
7/9

외부 사용자가 파드를 이용하는 방법

서비스 : 외부에서 쿠버네티스 클러스터에 접속하는 방법

📌 노드포트

노드포트(NodePort) 서비스 : 외부에서 쿠버네티스 클러스터의 내부에 접속하는 가장 쉬은 방법

노드포트 서비스 구성

노드포트 서비스 설정
-> 모든 워커 노드의 특정 포트(노드포트)를 엶
-> 여기로 오는 모든 요청을 노드포트 서비스로 전달
-> 해당 업무를 처리할 수 있는 파드로 요청 전달


💻 노트포드 서비스로 외부에서 접속하기

  1. 디플로이먼트로 파드 생성
    kubectl create deployment np-pods --image=sysnet4admin/echo-hname

  2. 파드 확인
    kubectl get pods

  3. 노드포트 서비스 생성 (이미 정의된 오브젝트 스펙 이용)
    kubectl create -f ~/_Book_k8sInfra/ch3/3.3.1/nodeport.yaml

# <nodeport.yaml>
apiVersion: v1
kind: Service
metadata:
  name: np-svc
spec:
  selector:
    app: np-pods 
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 30000
  type: NodePort

-> 기존 파드 구조에서 kind가 Service로 바뀜
-> spec에 컨테이너에 대한 정보가 없음
-> 서비스 타입을 NodePort로 지정

  1. 노드포트 서비스로 생성한 np-svc 서비스 확인
    kubectl get services
    -> 노드포트의 포트 번호가 30000번으로 지정됨
    -> CLUSTER-IP는 클러스터의 내부에서 사용되는 IP (자동 지정됨)

  2. 워커 노드 IP 확인
    kubectl get nodes -o wide

  3. 호스트 PC에 웹 브라우저를 띄우고 워커 노드 IP와 노드포트의 포트 번호로 접속해 외부에서 접근되는지 확인 (화면에 파드 이름이 표시되는지)
    -> 파드가 하나라서 이름은 모두 동일하게 나옴


💻 부하 분산 테스트 (오브젝트 스펙 파일로)

디플로이먼트로 생성된 파드 1개에 접속하고 있다가 파드가 3개로 증가하면 부하가 분산되는가?

  1. 호스트 PC에서 파워셸 명령 창을 띄우고 명령 실행
    (반복적으로 192.168.1.101:30000에 접속해 접속한 파드 이름을 화면에 표시 -> 파드가 1개에서 3개로 늘어나는 시점 관찰하기 위함)
    $i=0; while($true)
    {
    % { %i++; write-host -NoNewline "$i $_" }
    (Invoke-RestMethod "http://192.168.1.101:30000")-replace '\n', " "
    }
    -> 호스트 이름 순서대로 출력됨

  2. 마스터 노드에서 파드를 3개로 증가
    kubectl scale deployment np-pods --replicas=3

  3. 배포된 파드 확인
    kubectl get pods

  4. 파드 이름에 배포된 파드 3개가 돌아가면서 표시되는지 확인
    (부하 분산이 되는지)
    -> 노드포트의 오브젝트 스펙에 np-pods와 디플로이먼트 이름이 동일하면 같은 파드로 간주하여 외부에서 추적해서 접속됨

추적 방법은 이름 외에도 많음


💻 expose로 노드포트 서비스 생성

  1. 서비스로 내보낼 디플로이먼트를 np-pods로 지정
    서비스 이름: np-svc-v2, 타입: NodePort(대소문자 구분!)
    연결 포트: 80
    kubectl expose deployment np-pods --type=NodePort --name=np-svc-v2 --port=80

  2. 서비스 확인
    kubectl get services
    노드포트의 포트 번호를 지정할 수 없음 -> 임의 지정

  3. 호스트 PC에서 웹 브라우저로 포트 번호에 접속하여 배포된 파드 중 하나의 이름이 표시되는지 확인

  4. 디플로이먼트와 서비스 삭제
    kubectl delete deployment np-pods
    kubectl delete services np-svc
    kubectl delete services np-svc-v2


📌 인그레스

노드포트 서비스는 포트를 중복으로 사용할 수 없음
-> 1개의 노드포트에 1개의 디플로이먼트 적용

인그레스
: 고유한 주소를 제공해 사용 목적에 따라 다른 응답 제공
: 트래픽에 대한 L4/L7 로드밸런서와 보안 인증서 처리 기능 제공

NGINX 인그레스 컨트롤러 작동 단계

  1. 사용자는 노드마다 설정된 노드포트를 통해 노드포트 서비스로 접속
    노드포트 서비스는NGINX 인그레스 컨트롤러로 구성함

  2. NGINX 인그레스 컨트롤러가 사용자 접속 경로에 따라 적합한 클러스터 IP 서비스로 경로 제공

  3. 클러스터 IP 서비스가 사용자를 해당 파드로 연결

인그레스 컨트롤러는 파드와 직접 통신할 수 없음!
-> 노드포트 or 로드밸런서 서비스와 연동해서 통신

💻 인그레스 컨트롤러 구성

  1. 테스트용 디플로이먼트 2개 배포
    kubectl create deployment in-hname-pod --image=sysnet4admin/echo-hname
    kubectl create deployment in-ip-pod --image=sysnet4admin/echo-ip

  2. 파드 상태 확인
    kubectl get pods

  3. NGINX 인그레스 컨트롤러 설치
    kubectl apply -f ~/_Book_k8sInfra/ch3/3.3.2/ingress-nginx.yaml

  4. NGINX 인그레스 컨트롤러의 파드가 배포됐는지 확인
    default 네임스페이스가 아닌 ingress-nginx 네임스페이스에 속함
    -> -n ingress-nginx 옵션 추가해야함
    kubectl get pods -n ingress-nginx
    -n : namespace의 약어, default 외의 네임스페이스 확인할 때 사용
    파드, 서비스 확인할 때 동일한 옵션

  5. 경로와 작동을 정의해 사용자 요구 사항에 맞게 설정 (파일로)
    kubectl apply -f ~/_Book_k8sInfra/ch3/3.3.2/ingress-config.yaml

# <ingress-config.yaml>
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: ingress-nginx
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - http:
      paths:
      - path:
        backend:
          serviceName: hname-svc-default
          servicePort: 80
      - path: /ip
        backend:
          serviceName: ip-svc
          servicePort: 80
      - path: /your-directory
        backend:
          serviceName: your-svc
          servicePort: 80

-> 들어오는 주소 값과 포트에 따라 노출된 서비스를 연결하는 역할을 설정
-> 외부에서 주소 값과 노드포트를 가지고 들어오면 hname-svc-default 서비스와 연결된 파드로 넘김
-> 외부에서 들어오는 주소 값, 노드포트와 함께 뒤에 /ip를 추가한 주소 값은 ip-svc 서비스와 연결된 파드로 접속

  1. 인그레스 설정 파일 등록 확인
    kubectl get ingress

  2. 인그레스에 요청한 내용이 적용됐는지 확인
    kubectl get ingress -o yaml
    -> 인그레스에 적용된 내용을 야믈 형식으로 출력
    -> 적용한 내용 외에 시스템에서 자동으로 생성하는 것까지 확인 가능

  3. 외부에서 NGINX 인그레스 컨트롤러에 접속할 수 있게 노드포트 서비스로 외부에 노출
    kubectl apply -f ~/_Book_k8sInfra/ch3/3.3.2/ingress.yaml

# <ingress.yaml>
apiVersion: v1
kind: Service
metadata:
  name: nginx-ingress-controller
  namespace: ingress-nginx # 네임스페이스를 ingress-nginx로 지정
spec:
  ports:
  # http를 처리하기 위한 30100번 포트 요청은 80번 포트로 넘김
  - name: http
    protocol: TCP
    port: 80
    targetPort: 80
    nodePort: 30100
  # http를 처리하기 위한 30101번 포트 요청은 443번 포트로 넘김
  - name: https
    protocol: TCP
    port: 443
    targetPort: 443
    nodePort: 30101
  selector: # 요구 사항에 따라 셀렉터를 ingress-nginx로 지정
    app.kubernetes.io/name: ingress-nginx 
  type: NodePort

  1. 노드포트 서비스로 생성된 인그레스 컨트롤러 확인
    (네인스페이스 지정해야함!)
    kubectl get services -n ingress-nginx

  2. 디플로이먼트도 서비스로 노출 (외부와 통신하기 위해 클러스터 외부에 노출할 수 있는 구역으로 옮김)
    kubectl expose deployment in-hname-pod --name=hname-svc-defaul --port=80, 443
    kubectl expose deployment in-ip-pod --name=ip-svc --port=80, 443

  3. 서비스 점검으로 디플로이먼트들이 서비스에 정상적으로 노출되는지 확인 (새로 생성된 서비스는 default에 있어서 네임스페이스 지정 안해도 됨)
    kubectl get services

  4. 호스트 PC 웹 브라우저에서 192.168.1.101:30100 접속하여 파드 이름이 표시되는지 확인 (101, 102, 103 중에 하나 사용)

  5. 경로 뒤에 /ip 추가하여 요청 방법과 파드 ip가 표시되는지 확인

  6. https://192.168.1.101:30101 접속하여 https 연결도 잘 되는지, 파드 이름 표시되는지 확인
    (경고 메시지 뜨면 고급>주소(안전하지 않음)로 이동 클릭)

  7. https://192.168.1.101:30101/ip 에서도 요청 방법과 파드 IP가 표시되는지 확인

  8. 테스트 끝 / 서비스 삭제
    kubectl delete deployment in-hname-pod
    kubectl delete deployment in-ip-pod
    kubectl delete services hname-svc-default
    kubectl delete services ip-svc

  9. NGINX 인그레스 컨트롤러 관련 내용 삭제
    kubectl delete -f ~/_Book_k8sInfra/ch3/3.3.2/ingress-nginx.yaml


📌 클라우드에서 로드밸런서 구성

로드밸런서 : 간단한 구조로 파드를 외부에 노출하고 부하를 분산

로드밸런서를 사용하려면 로드밸런서를 이미 구현해 둔 서비스업체의 도움을 받아 외부에 구현해야 함

클라우드에서 제공하는 쿠버네티스를 사용하고 있으면 선언만 하면 사용할 수 있음
-> 로드밸런서 서비스가 생성되고 외부와 통신할 수 있는 ip가 부여되고 외부와 통신할 수 있으며 부하도 분산됨


📌 온프레미스에서 로드밸런서 (MetallLB)

MetalLB : 로드밸런서 서비스를 받아주는 구성을 지원

온프레미스에서 로드밸런서를 사용하려면 내부에서 서비스를 받아주는 구성이 있어야함

베어메탈(bare metal, 운영 체제가 설치되지 않은 하드웨어)로 구성된 쿠버네티스에서도 로드밸런서를 사용할 수 있게 함

🔎 MetalLB 구성도

  • MetalLB 컨트롤러
    : 작동 방식(Protocol)을 정의하고 EXTERNAL-IP를 부여해 관리함

  • MetalLB 스피커(speaker)
    : 정해진 작동 방식(L2/ARP, L3/BGP)에 따라 경로를 만들 수 있게 네트워크 정보를 수집해 각 파드의 경로 제공
    : L2는 스피커 중에서 리더를 선출해서 총괄하게 함

💻 로드밸런서 서비스 구성

  1. 디플로이먼트를 이용해 2종류 파드 생성하고 3개로 늘려 노드당 1개씩 파드 배포
    kubectl create deployment lb-hname-pods --image=sysnet4admin/echo-hname
    kubectl scale deployment lb-hname-pods --replicas=3
    kubectl create deployment lb-ip-pods --image=sysnet4admin/echo-ip
    kubectl scale deployment lb-ip=pods --replicas=3

  2. 2종류 파드 총 6개 배포 확인
    kubectl get pods

  3. 사전에 정의된 오브젝트 스펙으로 MetalLB 구성
    kubectl apply -f ~/_Book_k8sInfra/ch3/3.3.4/metallb.yaml
    -> MetalLB에 필요한 요소 모두 설치됨
    -> 독립적인 네임스페이스(metallb-system) 만들어짐

  4. MetalLB 파드 5개(controller 1, speaker 4)인지, IP, 상태 확인
    kubectl get pods -n metallb-system -o wide

  5. ConfigMap 오브젝트 사용하여 MetalLB 설정 적용
    kubectl apply -f ~/_Book_k8sInfra/ch3/3.3.4/metallb-l2config.yaml

# <metallb-l2config.yaml>
apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    address-pools:
    - name: nginx-ip-range
      protocol: layer2
      addresses:
      - 192.168.1.11-192.168.1.13

  1. ConfigMap 생성 확인
    kubectl get configmap -n metallb-system

  2. MetalLB 설정 적용 확인
    kubectl get configmap -n metallb-system -o yaml

  3. 디플로이먼트를 로드밸런서 서비스로 노출
    kubectl expose deploymnet lb-hname-pods --type=LoadBalancer --name=lb-hname-svc --port=80
    kubectl expose deploymnet lb-ip-pods --type=LoadBalancer --name=lb-ip-svc --port=80

  4. 로드밸런서 서비스별로 CLUSTER-IP, EXTERNAL-IP가 잘 적용됐는지, EXTERNAL-IP에 ConfigMap을 통한 IP가 잘 부여됐는지 확인
    kubectl get servies

  5. EXTERNAL-IP 작동 확인위해 호스트 PC 브라우저로 lb-hname-svc의 EXTERNAL-IP로 접속 후 파드 이름이 표시되는지 확인

  6. lb-ip-svc의 EXTERNAL-IP로 접속 후 요청 방법과 IP가 표시되는지 확인

  7. 파워셸 명령 창에 스크립트 실행
    $i=0; while($true)
    {
    % { $i++; write-host -NoNewline "$i $_" }
    (Invoike-RestMethod "http://[lb-hname-svc의 EXTERNAL-IP]")-replace '\n', " "
    }

  1. 파드 6개로 늘림
    kubectl scale deployment lb-hname-pods --replicas=6

  2. 늘어난 파드도 EXTERNAL-IP 접근되는지 확인

  3. MetalLB 설정 제외 나머지 삭제
    코드 스킵


HPA

HPA(Horizontal Pod Autoscaler)
사용자가 갑자기 늘어 파드가 감당할 수 없게되어 서비스 불가되는 경우를 대비해 부하량에 따라 디플로이먼트의 파드 수를 유동적으로 관리하는 기능

  1. 디플로이먼트 1개 생성
    kubectl create deployment hpa-hname-pods --image=sysnet4admin/echo-hname

  2. hpa-hname-pods를 로드밸런서 서비스로 설정
    (앞에서 MetalLB 구성 했음)
    kubectl expose deployment hpa-hname-pods --type=LoadBalancer --name=hpa-hname-svc --port=80

  3. 로드밸런서 서비스 IP 확인
    kubectl get services

  4. HPA 작동하기 위해 파드 자원 어느 정도 사용되는지 파악
    (부하 확인)
    kubectl top pods
    -> 자원 요청 설정 없다고 에러 발생

-> HPA가 자원 요청할 때 메트릭 서버를 통해 계측값을 전달받음
-> 메트릭 서버가 없어서 에러 발생!

  1. 메트릭 서버 생성
    kubectl create -f ~/_Book_k8sInfra/ch3/3.3.5/metrics-server.yaml

  2. 메트릭 서버 설정 후 ④ 결과 제대로 확인
    -> 부하 없어서 CPU, MEMORY 값이 매우 낮음

  3. 파드에 부하가 걸리기 전에 scale이 실행되게 수정
    kubectl edit deployment hpa-hname-pods
    resources: {} 에서 {} 부분 수정
    resources:
    requests:
    cpu: "10m" -> 파드의 CPU 0.01 사용을 기준으로 파드 증설
    limits:
    cpu: "50m" -> CPU 사용 제한 0.05 (순간적인 부하 대비)

  4. 스펙이 변경되고 새로운 파드 생성됐는지 확인
    kubectl top pods

  5. autoscale 설정하여 특정 조건이 만족되면 자동으로 scale 수행
    kubectl autoscale deployment hpa-hname-pods --min=1 --max=30 --cpu-percent=50
    -> CPU 사용량이 50% 넘으면 autoscale

  6. 왼: 마스터 노드 창 2개, 오: 파워셸
    마스터 노드 1 : watch kubectl top pods
    마스터 노드 2 : watch kubectl get pods
    watch: 2초에 한 번씩 자동으로 상태 확인

  7. HPA 테스트 위해 파워셸에 반복문 실행
    로드밸런서 테스트 코드와 동일
    -> 마스터 노드 1 창에서 부하량 감지하는지 확인

  8. 마스터 노드 2 창에서 파드 새로 생성되는지 확인

  9. 부하 분산으로 생성된 파드의 부하량 증가하는지 확인

  10. 안정적인 상태가 되는지 확인하고 파워셸 창 종료

  11. 부하가 없어지면 autoscale 최소 조건인 파드 1개로 돌아가기 위해 파드가 종료되는지 확인

  12. 파드 모두 종료되고 1개 남게되는지 확인

  13. 디플로이먼트, 서비스, 메트릭 서버 삭제
    코드 생략

profile
노력형 인간

0개의 댓글