NodePort로 외부에 서비스 노출하기

4riend·2024년 4월 21일
1

CodeMind 프로젝트

목록 보기
15/20
post-thumbnail

eks cluster 내 서비스를 pod로 띄웠다면 외부에서 접속을 허용해야 한다.
오늘은 AWS EKS Cluster에서 NodePort로 접속하는 과정을 공유한다 🔥🔥🔥


시작 전

클러스터내 노드를 만들 땐 private하게 만든다고 한다.
public한 접근은 모두 비용이 되기도 하고 보안적으로도 접근을 막아두는게 좋기 때문이다.

따로 pod에 접근을 하고 싶다면 보통 ingress rule을 통해 host로 접근하는 것이 일반적이라고 한다.

하지만 NodePort와 LoadBalancer 모두 상황에 따라 쓰인다고 하니 실습을 하는 것도 좋다 생각한다👍

멘토님께서 겪으신 NodePort의 이용사례는 '클러스터 내에 있는 pod에 접근하기 위한 외부 LB를 개발할 때 쓰였다'고 한다.


서비스 배포

난 2개의 서비스 pod를 띄울 것이다.

streamlit-svc.yaml

apiVersion: v1
kind: Service
metadata:
  name: streamlit-svc
spec:
  selector:
    app: streamlit
  ports:
    - protocol: TCP
      port: 8501
      targetPort: 8501

---
apiVersion: apps/v1
kind: Deployment
	metadata:
  name: streamlit-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: streamlit
  template:
    metadata:
      labels:
        app: streamlit
    spec:
      containers:
      - name: streamlit
        image: 211125418324.dkr.ecr.ap-northeast-2.amazonaws.com/webservice:latest
        ports:
        - containerPort: 8501
        env:
        - name: AUTH0_APP_URL
          value: "http://3.35.196.184:30002" # 노드의 public IP:auth0 NodePort
        volumeMounts:
        - name: aws-credentials-volume
          mountPath: "/root/.aws"
          readOnly: true
      volumes:
      - name: aws-credentials-volume
        secret:
          secretName: aws-credentials

혹시나 aws 내 자원을 이용하는 경우 credentials 주입도 필수다.

kubectl create secret generic aws-credentials --from-file=credentials=/home/ec2-user/.aws/credentials

auth0-svc.yaml

apiVersion: v1
kind: Service
metadata:
  name: auth0-svc
spec:
  selector:
    app: auth0
  ports:
    - protocol: TCP
      port: 3000
      targetPort: 3000

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: auth0-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: auth0
  template:
    metadata:
      labels:
        app: auth0
    spec:
      containers:
      - name: auth0
        image: 211125418324.dkr.ecr.ap-northeast-2.amazonaws.com/auth0:latest
        ports:
        - containerPort: 3000
        env:
        - name: STREAMLIT_APP_URL
          value: "http://3.35.196.184:30001" # 노드의 public IP:streamlit NodePort

각각의 서비스를 배포하자 ✔

kubectl apply -f streamlit-svc.yaml -f auth0-svc.yaml

NodePort 배포

서비스에 대해 각각의 NodePort를 만들자

streamlit-np.yaml

apiVersion: v1
kind: Service
metadata:
  name: streamlit-np
spec:
  type: NodePort
  selector:
    app: streamlit # 간혹 streamlit-svc 라고 적을 수 있습니다. (주의하세요)
  ports:
    - protocol: TCP
      port: 8501
      targetPort: 8501
      nodePort: 30001

auth0-np.yaml

apiVersion: v1
kind: Service
metadata:
  name: auth0-np
spec:
  type: NodePort
  selector:
    app: auth0 # 간혹 auth0-svc 라고 적을 수 있습니다. (주의하세요)
  ports:
    - protocol: TCP
      port: 3000
      targetPort: 3000
      nodePort: 30002

각각의 NodePort를 배포하자 ✔

kubectl apply -f streamlit-np.yaml -f auth0-np.yaml

조회 및 결과

배포된 서비스는 다음과 같이 조회할 수 있다.

$ kubectl get svc
NAME            TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
auth0-svc       ClusterIP   10.100.60.37     <none>        3000/TCP         12s
kubernetes      ClusterIP   10.100.0.1       <none>        443/TCP          10h
streamlit-np    NodePort    10.100.30.59     <none>        8501:30001/TCP   27m
streamlit-svc   ClusterIP   10.100.136.229   <none>        8501/TCP         5m44s

(몇 일 전에 기록해뒀던 것을 velog에 작성하다보니 auth0-np가 잘린 기록 밖에 없었다🤣)

그리고 노드를 조회하자

$ kubectl get nodes -o wide
NAME                                               STATUS   ROLES    AGE    VERSION               INTERNAL-IP     EXTERNAL-IP    OS-IMAGE         KERNEL-VERSION                  CONTAINER-RUNTIME
ip-192-168-35-49.ap-northeast-2.compute.internal   Ready    <none>   109m   v1.28.5-eks-5e0fdde   192.168.35.49   3.36.110.252   Amazon Linux 2   5.10.213-201.855.amzn2.x86_64   containerd://1.7.11

EXTERNAL-IP 와 NodePort(30001)을 통해 streamlit pod에 접근할 수 있게 된다.

EXTERNAL-IP가 없어요

이때 만약 EXTERNAL-IP가 없다면 여러분이 노드 그룹을 생성할 때 private 설정을 해서 그런 것이다.
따로 노드를 public하게 변경하거나 기존 노드를 삭제하고 public한 노드를 생성하는 것도 방법이 될 수 있다 👍

GCP를 사용한다면?

노드에 접속하기 전 GCP 사용시 방화벽 해제 후 노드로 직접 접속 해야함

  • 우리가 만든 네트워크가 VPC로 감싸져있기 때문에 방화벽을 열어줘야 함
  • 공인 IP를 갖고 있지만 방화벽을 열지 않으면 접근이 불가능 😢

예시 명령어

  • 허용하는 정책을 만들게 되는데 30001 포트를 열겠다고 정의한 것
$ gcloud compute firewall-rules create http-go-svc-rule --allow=tcp:30001
Creating firewall...working..Created [https://www.googleapis.com/compute/v1/projects/kimgun95-2024-02-13/global/firewalls/http-go-svc-rule].
Creating firewall...done.                                                                      
NAME: http-go-svc-rule
NETWORK: default
DIRECTION: INGRESS
PRIORITY: 1000
ALLOW: tcp:30001
DENY: 
DISABLED: False
profile
날씨의 아이, 진격의 거인, 로스트 아크, Java Spring

0개의 댓글