쿠버네티스 네트워킹

컨테이너 네트워크 모델

쿠버네티스는 컨테이너화된 애플리케이션을 배포하고 관리하기 위한 오픈 소스 컨테이너 오케스트레이션 플랫폼이다. 이를 통해 여러 개의 컨테이너가 클러스터 상에서 효율적으로 통신하고 네트워크 리소스를 공유할 수 있다. 

1. 파드 (Pod)

쿠버네티스의 가장 작은 배포 단위인 파드는 하나 이상의 컨테이너 그룹을 포함 한다. 파드 내의 컨테이너들은 동일한 네트워크 네임스페이스와 IP 주소를 공유 한다. 즉, 파드 내의 컨테이너들은 로컬 호스트처럼 서로 통신할 수 있다.

2. 서비스 (Service)

서비스는 파드 집합에 대한 안정적인 네트워크 엔드포인트를 제공하는 추상화 이다. 서비스는 일정한 IP 주소와 포트를 가지며, 클러스터 내부 또는 외부에서 접근 가능한 엔드포인트로서 동작 한다. 서비스를 통해 다른 파드나 서비스와 통신할 수 있다.

3. 서비스 디스커버리 (Service Discovery)

서비스 디스커버리는 클라이언트 애플리케이션이 서비스를 찾고 접근할 수 있는 기능을 제공 한다. Kubernetes는 DNS(Domain Name System)를 사용하여 서비스를 검색하고 해석 한다. 클라이언트는 서비스 이름을 사용하여 해당 서비스에 연결할 수 있다.

4. 클러스터 내부 통신

쿠버네티스는 클러스터 내의 파드는 기본적으로 같은 네트워크에 속하므로 서로의 IP 주소를 직접 사용하여 통신할 수 있다. 이는 로컬 호스트에서 실행되는 컨테이너들 사이의 통신과 유사한 방식이다. 파드 간 통신은 내부 IP 주소를 사용하며, 네트워크 리소스는 클러스터 내에서 공유 된다.

5. 클러스터 외부 통신

클러스터 외부에서 파드에 접근하려면 서비스를 통해 노출해야 한다. 쿠버네티스는 로드 밸런서(Load Balancer), 노드 포트(NodePort), 인그레스(Ingress) 등 다양한 방법을 제공하여 클러스터 외부로 트래픽을 노출할 수 있다.

6. 네트워크 정책 (Network Policies)

쿠버네티스는 네트워크 정책을 통해 파드 간의 통신을 제한하고 제어할 수 있는 기능을 제공 한다. 네트워크 정책은 파드의 네트워크 트래픽을 제어하는 규칙을 정의하며, 보안 및 네트워크 분리를 위해 사용 된다.

Pod 네트워킹

  1. Pod IP 주소 할당
  2. Pod 간 통신

서비스 네트워킹

Deployment를 통해 생성된 파드의 IP를 통해서 직접 접근할 수도 있지만, 파드가 재생성될 경우 경우 IP가 영속적이지 않기 때문에 변경될 수 있다는 점을 유의해야 한다. 여러 개의 Deployment를 하나의 완벽한 애플리케이션으로 연동하려면 파드 IP가 아닌 서로를 발견할 수 있는 방법이 필요하다.

서비스는 여러 개의 팟에 쉽게 접근할 수 있도록 도메인 이름을 부여하고, 로드 밸런서 기능을 수행하여 파드를 외부로 노출시켜준다.
서비스는 Cluster IP, NodePort, LoadBalancer 이렇게 3가지 타입이 있다.

먼저 ClusterIP의 대한 얘기 해보겠다.

image.png

예시:

apiVersion: v1
kind: Service
metadata:
  name: hostname-svc-clusterip
spec:
  ports:
    - name: web-port
      port: 8080
      targetPort: 80
  selector:
    app: webserver
  type: ClusterIP

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hostname-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: webserver
  template:
    metadata:
      name: my-webserver
      labels:
        app: webserver
    spec:
      containers:
        - name: my-webserver
          image: waji97/test:v1
          ports:
            - containerPort: 80

생성된 서비스는 쿠버네티스 내부에서만 사용할 수 있는 고유 IP(Cluster IP)를 할당 받는데, 6번 줄에 있는 ports:는 해당 IP의 어떤 포트를 사용해서 접근 가능한지 기입한다. 똑같은 필드에 있는 targetPort는 접근할 파드가 사용하고 있는 포트 번호를 나타낸다. 10번 줄에 있는 selector는 이 서비스에서 어떤 라벨을 가지는 파드에 접근할 수 있게 만들 것인지를 나타낸다. 이렇게 설정을 하면, 내부적으로 파드의 IP가 변경되어도 서비스를 통해 접근하게 되므로 상관없어질 것이다. Cluster IP는 외부에서 접근할 수가 없다.

이번에는 NodePort 타입이다

image.png

예시:

apiVersion: v1
kind: Service
metadata:
  name: hostname-svc-nodeport
spec:
  ports:
    - name: web-port
      port: 8080
      targetPort: 80
  selector:
    app: webserver
  type: NodePort

Manifest파일 형태는 거의 동일 하지만 마지막에 type:필드만 NodePort로 바뀐다. Cluster IP 타입일 때에는 단순히 파드에 연결해주는 것이었다. NodePort는 외부에서 어떤 노드든 간에 해당 노드의 IP에 접근하고 NodePort의 포트번호로 접근하기만 하면 해당 파드로 연결을 해준다. 포트는 30000 ~ 32767 중 랜덤으로 지정된다. 


마지막에 있는 LoadBalancer 타입은 노드포트에 접근하게끔 로드밸런싱을 해주는 타입인데 클라우드 플랫폼 환경에서 주로 사용가능 하다. 예를 들어 AWS 클라우드 플랫폼에서 로드 밸런서 서비스를 지정 해주면, AWS상 로드밸런서가 자동 생성 된고 로드 밸런서 역할을 수행 한다(AWS EKS 클러스터가 설정 되어 있는 과정에서만). 그 외 Baremetal 환경에서는 오픈소스 Load Balancer인 MetalLB를 사용하여 쿠버네티스 클러스터에 Load Balancer를 별도로 구축 가능 하다. MetalLB는 간단하게 로드 밸런서 기능을 해주는 파드를 생성 해준다.

image.png

MetalLB에 대한 기본 정보-

기본적인 MetalLB의 동작 흐름:

BGP모드는 Border Gateway Protocol의 약자로 인터넷에서 라우팅 정보를 교환하고 관리하기 위해 사용 된다
ARP는 IP 주소와 MAC 주소 간의 매핑을 수행하는 네트워크 프로토콜이다

예시:

vi app.yaml

# 로드 밸런서 YAML 파일
apiVersion: v1
kind: Service
metadata:
  name: nginx-loadbalancer
spec:
  ports:
    - name: web-port
      port: 80
      targetPort: 8080
  selector:
    app: webserver
  type: LoadBalancer
  
---
# 웹 사이트 배포 YAML 파일
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 8080


이렇게 YAML 파일을 적용 시킨 후 결과를 확인 하면

# YAML 파일 적용
kubectl apply -f app.yaml

# 모든 리소스 확인
kubectl get all
NAME                                    READY   STATUS    RESTARTS   AGE
pod/nginx-deployment-6f67db9747-l8shl   1/1     Running   0          6s
pod/nginx-deployment-6f67db9747-tcc8k   1/1     Running   0          6s

NAME                         TYPE           CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
service/kubernetes           ClusterIP      10.233.0.1    <none>        443/TCP        24h
service/nginx-loadbalancer   LoadBalancer   10.233.8.88   <pending>     80:31810/TCP   6s


현재 VM을 사용 하여 예시를 사용 하였기 때문에 로드 밸런서가 실제로 생성 되지 않는다. 그렇기 떄문에 EXTERNAL-IP도 아직 <pending> 상태이고 on-premise 환경에서 사용되는 로드 밸런서인 MetalLB를 사용 해야 한다. MetalLB를 설치 하는 방식은 Helm 차트, 매니페스트 파일 그리고 Kubespray로 통해 할 수 있다.

참고용 MetalLB installation 페이지 링크: https://metallb.universe.tf/installation/

공식 사이트에 나와있는 매니페스트 파일 방식으로 L2모드 설치를 진행 해 보았다. L2 모드는 대부분의 경우, 프로토콜 특정 구성이 필요하지 않으며, IP 주소만 필요하고 쉽게 구성 할 수 있다.

L2 모드는 워커 노드의 네트워크 인터페이스의 IP를 할당할 필요가 없다. 이 모드는 로컬 네트워크에서 ARP 요청에 직접 응답하여 클라이언트에게 기계의 MAC 주소를 제공 하는 모드다.

 

제일 먼저, strictARP 모드를 활성화 해야 한다. 

마스터 노드에서, 

kubectl edit configmap -n kube-system kube-proxy

 

vim editor 처럼 파일 수정이 가능 하다. 파일 속에서 41번째 줄에 있는 값을 변경 해준다.

# 기본으로 false
strictARP: true

 

그 후 저장 후 파일에서 나온다. MetalLB설치 할 준비는 끝났으나 이제 바로 매니페스트 파일을 적용 시켜 주면 된다

# 공식 사이트 Installation에 나온 링크
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.10/config/manifests/metallb-native.yaml

namespace/metallb-system configured
customresourcedefinition.apiextensions.k8s.io/addresspools.metallb.io created
customresourcedefinition.apiextensions.k8s.io/bfdprofiles.metallb.io created
customresourcedefinition.apiextensions.k8s.io/bgpadvertisements.metallb.io created
customresourcedefinition.apiextensions.k8s.io/bgppeers.metallb.io created
customresourcedefinition.apiextensions.k8s.io/communities.metallb.io created
customresourcedefinition.apiextensions.k8s.io/ipaddresspools.metallb.io created
customresourcedefinition.apiextensions.k8s.io/l2advertisements.metallb.io created
serviceaccount/controller unchanged
serviceaccount/speaker unchanged
role.rbac.authorization.k8s.io/controller configured
role.rbac.authorization.k8s.io/pod-lister configured
clusterrole.rbac.authorization.k8s.io/metallb-system:controller configured
clusterrole.rbac.authorization.k8s.io/metallb-system:speaker configured
rolebinding.rbac.authorization.k8s.io/controller configured
rolebinding.rbac.authorization.k8s.io/pod-lister configured
clusterrolebinding.rbac.authorization.k8s.io/metallb-system:controller unchanged
clusterrolebinding.rbac.authorization.k8s.io/metallb-system:speaker unchanged
configmap/metallb-excludel2 created
secret/webhook-server-cert created
service/webhook-service created
deployment.apps/controller configured
daemonset.apps/speaker configured
validatingwebhookconfiguration.admissionregistration.k8s.io/metallb-webhook-configuration created

이렇게 매니페스트를 적용 하게 되면 자동으로 MetalLB의 모든 필요 요소들이 자동으로 설치가 된다.

 

확인을 하기 위해 metallb-system namespace을 보면, controller과 speaker들이 보일 것이다

# 확인 하기 위해 새로 생성 된 metallb 네임 스페이스 리소스들 보기
kubectl get all -n metallb-system
NAME                              READY   STATUS    RESTARTS   AGE
pod/controller-5fd797fbf7-r28s6   0/1     Running   0          17s
pod/controller-bdf98b979-pp7dp    1/1     Running   0          80s
pod/speaker-2hx68                 1/1     Running   0          80s
pod/speaker-p2nh4                 1/1     Running   0          80s
pod/speaker-r95cx                 0/1     Running   0          17s

NAME                      TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/webhook-service   ClusterIP   10.233.32.213   <none>        443/TCP   17s

NAME                     DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
daemonset.apps/speaker   3         3         2       1            2           kubernetes.io/os=linux   80s

NAME                         READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/controller   1/1     1            1           80s

 

초기 설치는 끝났으나 바로 사용 가능 하지는 않다. 사용하기 위해 먼저 초기 설정을 해 줘야 한다.

참고용 MetalLB Configuration 링크: https://metallb.universe.tf/configuration/

먼저 IP 풀을 지정 해 줘야 한다.

# IP 풀 설정을 위해 매니페스트 파일 생성
vi metallb-config.yaml

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: first-pool
  namespace: metallb-system
spec:
  addresses:
  - 192.168.1.40-192.168.1.50             # IP 주소 풀 할당
  
---

apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: metal
  namespace: metallb-system
spec:
  ipAddressPools:
  - first-pool

 

매니페스트 파일 저장 후 적용을 한다

kubectl apply -f metallb-config.yaml
ipaddresspool.metallb.io/first-pool created
l2advertisement.metallb.io/metal created

 

테스팅을 위해 이미 배포 되어 있는 웹 사이트의 서비스 타입을 LoadBalancer로 바꿔 보았다

# 웹 사이트 매니페스트 파일
vi my-app.yaml

apiVersion: v1
kind: Service
metadata:
  name: my-app-service
spec:
  type: LoadBalancer    # 전에는 NodePort로 서비스
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80


진행 중인 서비스들 목록을 확인 해보면 이젠 로드 밸런서가 EXTERNAL-IP를 지정 한 IP 풀 안에서 자동으로 부여 하는 것을 확인 할 수 있다

kubectl get svc
NAME             TYPE           CLUSTER-IP      EXTERNAL-IP    PORT(S)        AGE
kubernetes       ClusterIP      10.233.0.1      <none>         443/TCP        27h
my-app-service   LoadBalancer   10.233.11.219   192.168.1.40   80:30208/TCP   25m


본 IP로 들어가서 확인 하면

image.png

Ingress 컨트롤러 & 리소스

인그레스는 외부 요청을 처리하는 방법을 정의하는 오브젝트다. 인그레스는 다양한 기능을 담당한다. 예를 들어, 특정 경로로 들어온 요청을 어떤 서비스로 전달할지 정의하는 라우팅 규칙, 가상 호스트를 기반으로한 요청 처리, SSL/TLS 보안 연결 처리 등을 담당한다.

NodePort나 LoadBalancer를 사용하면 위와 같은 기능을 구현할 수 있지만, NodePort의 개수가 많을 경우 각 서비스에 대해 설정을 별도로 해주어야 하는 번거로움이 있을 수 있다. 하지만 인그레스를 사용하면 한 곳에만 설정을 하면 되기 때문에 편리하다. 인그레스를 통해 요청의 경로와 처리 방식을 중앙에서 관리할 수 있어서 유연성과 효율성을 높일 수 있다. 쉽게 말하면 Ingress를 통해 특정 트래픽을 지정한 서비스 쪽으로 라우팅을 해 줄 수 있다.

image.png


예시:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-example
spec:
  rules:
    - host: example.com
      http:
        paths:
        - pathType: Prefix
          path: /
          backend:
            name: hostname-service       	# 목적지 서비스의 이름과 포트 번호
            port: 80							

여기서 host:는 해당 도메인 이름으로 접근하는 요청에 대해 처리 규칙을 적용 한다는 뜻이다. 그리고 path: 는 해당 경로의 요청을 어떤 서비스로 전달 할 것인지 정의한다. 

인그레스는 요청 처리 규칙을 정의하는 선언적인 오브젝트일 뿐이며, 실제로 외부 요청을 처리하지는 않는다. 인그레스 규칙을 사용하기 위해서는 인그레스 컨트롤러라고 하는 특수한 서버에 적용해야 한다. 인그레스 컨트롤러 서버가 실제로 외부 요청을 받아들이고 인그레스 규칙을 적용한다.


인그레스 설정

클라우드 서비스를 사용하는 경우, 자사의 로드밸런서 서비스와 연동하여 인그레스를 사용할 수 있다. 그러나 자체 클라우드 구축 시에는 보통 Nginx 웹 서버 인그레스 컨트롤러를 사용 한다. 이는 쿠버네티스에서 공식적으로 개발되고 있어서 공식 깃허브 저장소에서 설치를 위한 YAML 파일을 직접 내려받을 수 있다. 그 외에도 Nginx 인그레스 컨트롤러 설치 하는 방식은 많다. Nginx Doc 사이트 참고 해서 설치 가능 하다

Nginx Documentation - Installing Nginx Ingress Controller  

매니페스트 YAML 파일을 이용 하여 설치를 진행 하였다. 

제일 먼저 깃 허브 쿠버네티스 인그레스 파일들을 내려 받는다

git clone https://github.com/nginxinc/kubernetes-ingress.git --branch v3.1.1

# 배포 파일들 위치로 이동
cd kubernetes-ingress/deployments


이제 차례대로 아래 명령어들을 사용하여 Nginx 인그레스 컨트롤러를 배포/설치 준비를 한다

# Namespace 과 서비스 계정 생성
kubectl apply -f common/ns-and-sa.yaml

# 서비스 계정용 cluster role과 cluster role binding 생성
kubectl apply -f rbac/rbac.yaml

# Nginx 컨트롤러 설정을 위해 configMap 설정 적용
kubectl apply -f common/nginx-config.yaml

# IngressClass 리소스 생성 (없으면 Nginx 컨트롤러 실행 불가)
kubectl apply -f common/ingress-class.yaml

# 사용자 지정 리소스들 생성
kubectl apply -f common/crds/k8s.nginx.org_virtualservers.yaml
kubectl apply -f common/crds/k8s.nginx.org_virtualserverroutes.yaml
kubectl apply -f common/crds/k8s.nginx.org_transportservers.yaml
kubectl apply -f common/crds/k8s.nginx.org_policies.yaml

## 기본적으로 VirtualServer, VirtualServerRoute, TransportServer 및 Policy에 대한 사용자 지정 리소스 정의를 생성해야 한다
## 그렇지 않으면 인그레스 컨트롤러 파드가 준비 상태가 되지 않는다.

# 그 외 인그레스 컨트롤러의 TCP나 UDP 로드 밸런싱을 사용하고 싶다면
kubectl apply -f common/crds/k8s.nginx.org_globalconfigurations.yaml


마지막으로 인그레스 컨트롤러 배포/설치를 진행 한다

# 기본적으로 아래 파일을 그대로 실행 하면 1 replica 인그레스 컨트롤러 파드를 생성 한다
kubectl apply -f deployment/nginx-ingress.yaml

# 마지막 단계로 loadbalancer 서비스를 통해 인그레스 컨트롤러 접근 허용을 위해
kubectl apply -f service/loadbalancer.yaml


## 선택적으로 NodePort 서비스를 통해서도 인그레스 컨트롤러 접근 가능 하다
kubectl create -f service/nodeport.yaml


설치 후 결과 확인

kubectl get all -n nginx-ingress
NAME                                READY   STATUS    RESTARTS   AGE
pod/nginx-ingress-bcd99bfb9-w6kn7   1/1     Running   0          152m

NAME                    TYPE           CLUSTER-IP    EXTERNAL-IP    PORT(S)                      AGE
service/nginx-ingress   LoadBalancer   10.233.3.51   192.168.1.40   80:30276/TCP,443:30815/TCP   150m

NAME                            READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-ingress   1/1     1            1           152m

NAME                                      DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-ingress-bcd99bfb9   1         1         1       152m


이렇게 Ingress 컨트롤러는 배포가 완료 되었다. External-IP를 통해 접속이 가능 하지만 아직 아무 서비스가 링크 되어 있지 않기 때문에 아래와 같은 화면이 보인다.

image.png

컨트롤러를 다른 서비스와 활용 하기 위해 Ingress 리소스를 생성 해야 한다. 

인그레스 컨트롤러는 쿠버네티스 클러스터의 외부 트래픽을 관리하기 위한 역할을 수행 한다.  클러스터 외부에서 내부 서비스로의 트래픽 라우팅을 처리하고, 로드 밸런싱, SSL 인증서 관리 등의 기능을 제공한다.

그리고 인그레스 리소스는 인그레스 컨트롤러에 대한 구성을 정의하는 쿠버네티스 리소스이다. 인그레스 리소스는 어떤 경로로 어떤 서비스에 트래픽을 전달 할지를 정의하며, 이를 통해 클러스터 외부에서 서비스로의 트래픽을 관리할 수 있다.

테스팅을 위해 2개의 웹 사이트 서비스를 생성 하여 인그레스 리소스 설정을 통해 특정 호스트에 따라 트래픽을 전달 하겠다.

# 1번째 웹 사이트
vi my-app.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: my-app
          image: waji97/ecommerce:v2                      
          ports:
            - containerPort: 8000
---
apiVersion: v1
kind: Service
metadata:
  name: my-app-service
spec:
  type: ClusterIP
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8000
:wq

      
# 2번째 웹 사이트
vi my-app2.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: my-app
          image: waji97/django:v2                       
          ports:
            - containerPort: 8000
---
apiVersion: v1
kind: Service
metadata:
  name: my-app-service
spec:
  type: ClusterIP
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8000
      
:wq


두 개의 서비스 및 Deployment 완료 후 확인

# 1번째 웹 사이트
vi my-app.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: my-app
          image: waji97/ecommerce:v2                      
          ports:
            - containerPort: 8000
---
apiVersion: v1
kind: Service
metadata:
  name: my-app-service
spec:
  type: ClusterIP
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8000
:wq

      
# 2번째 웹 사이트
vi my-app2.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app2
spec:
  replicas: 2
  selector:
    matchLabels:
      app: my-app2
  template:
    metadata:
      labels:
        app: my-app2
    spec:
      containers:
        - name: my-app2
          image: waji97/django:v2                       
          ports:
            - containerPort: 8000
---
apiVersion: v1
kind: Service
metadata:
  name: my-app2-service
spec:
  type: ClusterIP
  selector:
    app: my-app2
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8000
      
:wq


# 적용 하기
kubectl apply -f my-app.yaml
deployment.apps/my-app created
service/my-app-service created

kubectl apply -f my-app2.yaml
deployment.apps/my-app2 created
service/my-app2-service created

# 현재 서비스과 Deployment들 확인 하기
NAME                           READY   STATUS    RESTARTS   AGE
pod/my-app-7d7b9b8d94-92qwc    1/1     Running   0          3m48s
pod/my-app-7d7b9b8d94-xhlvd    1/1     Running   0          3m45s
pod/my-app2-764587cdfc-fc7df   1/1     Running   0          3m54s
pod/my-app2-764587cdfc-l9h85   1/1     Running   0          3m54s

NAME                      TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/kubernetes        ClusterIP   10.233.0.1      <none>        443/TCP   2d
service/my-app-service    ClusterIP   10.233.46.112   <none>        80/TCP    169m
service/my-app2-service   ClusterIP   10.233.27.197   <none>        80/TCP    3m54s


이제 Ingress 리소스를 지정 해주는 작업을 한다

# YAML 매니페스트 파일을 생성 한다
vi ingress.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
    kubernetes.io/ssl-redirect: "false"
spec:
  rules:
  - host: myapp.ingtest.com 
    http:
      paths:
      - pathType: Prefix
        path: /									
        backend:
          service:
            name: my-app-service
            port: 
              number: 80
  - host: myapp2.ingtest.com
    http:
      paths:
      - pathType: Prefix
        path: /
        backend:
          service:
            name: my-app2-service
            port: 
              number: 80
              
:wq

# 위 파일을 적용
kubectl apply -f ingres.yaml 
ingress.networking.k8s.io/my-ingress created

# 생성 된 리소스 확인
kubectl get ingress
NAME         CLASS    HOSTS                                  ADDRESS   PORTS   AGE
my-ingress   <none>   myapp.ingtest.com,myapp2.ingtest.com             80      169m


이제 두 웹 사이트가 정상 적으로 작동 하고 있는지 및 Ingress가 적용이 되었는지를 확인 하기 위해 DNS 주소들에게 접속을 한다.

접속 전에 접속 하는 PC의 'hosts' 파일에 IP주소 to DNS 주소 핑을 해 줘야 한다. 그런 이유는 보통 쿠버네티스에서 인그레스 리소스를 정의할 때, 일반적으로 클러스터 외부에서 애플리케이션에 접근하기 위해 사용할 DNS 호스트 이름을 포함한다. 그러나 기본적으로 로컬 PC의 DNS Resolver는 해당 호스트 이름과 클러스터 내의 해당 IP 주소 간의 매핑을 인식하지 못할 수 있다. 로컬 PC의 'hosts' 파일에 항목을 추가함으로써, 호스트 이름과 IP 주소 간의 수동 매핑을 생성 하면 로컬 PC에서 호스트 이름을 로컬로 해석할 수 있으며 외부 DNS 해석에 의존하지 않는다.

Window 속 'hosts' 파일 경로
C:\Windows\System32\drivers\etc\hosts

Linux 속 'hosts' 파일 경로
/etc/hosts


'hosts' 파일 속 IP 매핑 후 모습

.
.
192.168.90.73 host.docker.internal
192.168.90.73 gateway.docker.internal

# 인그레스 컨트롤러의 서비스 External-IP와 매핑
192.168.1.40 myapp.ingtest.com
192.168.1.40 myapp2.ingtest.com


웹 사이트 접속 결과:

myapp.ingtest.com

image.png


myapp2.ingtest.com

image.png


//SSL 추가 및 더 디테일 한 YAML 파일 설명 그리고 /myapp /myapp2 형태의 분리 작업 남음