카테고리 없음

쿠버네티스 기본 오브젝트 Ingress

ㅈ현 2022. 6. 30. 14:53

Ingress는 클러스터로 들어오는 http 트래픽을 관리해주는 쿠버네티스 오브젝트다. Ingress 는 로드밸런싱, TLS 종료, 가상 호스팅 등 서비스를 제공해주게 된다.

 

 

인그레스(Ingress)

FEATURE STATE: Kubernetes v1.19 [stable] 클러스터 내의 서비스에 대한 외부 접근을 관리하는 API 오브젝트이며, 일반적으로 HTTP를 관리함. 인그레스는 부하 분산, SSL 종료, 명칭 기반의 가상 호스팅을 제공

kubernetes.io

Ingress 리소스는 트래픽 처리를 위한 하나의 규칙이며 이 규칙을 동작시켜 주는것이 Ingress Controller다. 

이러한 Ingress Controller가 실질적으로 http 트래픽을 관리 해주게 되며, 이 관리 규칙이 Ingress 리소스 인것이다.

 

Ingress Controller에는 많은 종류들이 있지만 여기서는 Nginx Ingress Controller에 대해 살펴본다.

 

인그레스 컨트롤러

인그레스 리소스가 작동하려면, 클러스터는 실행 중인 인그레스 컨트롤러가 반드시 필요하다. kube-controller-manager 바이너리의 일부로 실행되는 컨트롤러의 다른 타입과 달리 인그레스 컨트롤러

kubernetes.io

 

GitHub - kubernetes/ingress-nginx: NGINX Ingress Controller for Kubernetes

NGINX Ingress Controller for Kubernetes. Contribute to kubernetes/ingress-nginx development by creating an account on GitHub.

github.com

 

 

Ingress Controller 설치

Nginx Ingress Controller 설치는 다음 링크를 참조해 진행한다.

https://kubernetes.github.io/ingress-nginx/deploy/#bare-metal-clusters

 

Installation Guide - NGINX Ingress Controller

Installation Guide There are multiple ways to install the NGINX ingress 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

 

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.2.0/deploy/static/provider/baremetal/deploy.yaml

위 yml 파일을 그대로 사용하지 않고 약간 수정하여 사용하기 위해 kubectl apply 명령 대신 wget 명령을 통해 파일을 받아온다.

wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.2.0/deploy/static/provider/baremetal/deploy.yaml

해당 파일은 Ingress Controller를 위한 파일로써 이번 포스팅에서는 해당 파일을 약간 수정하여 사용한다.

해당 파일을 열어보면 다음과 같이 되어있다.

 

deploy.yaml

해당 파일에는 Namespace에 대한 설정과, ServiceAccount, Role, NodePort에 대한 설정들이 들어있다.

여기서 기본으로 ingress-nginx로 되어있는 Namespace를 바꿔 사용할 것이다.

 

우선 7줄에 있는 Namespace의 이름을 바꿔준다.

이후 다음 명령을 통해 해당 파일 내에서 사용하는 모든 namespace를 바꿔준다.

sed -i 's/namespace: ingress-nginx/namespace: {some_namespace}/g' deploy.yaml

 

이후 아래 명령을 통해 Ingress Controller를 생성한다.

kubectl create -f deploy.yaml

 

이후 아래 명령을 통해 생성한 Ingress Controller를 확인할 수 있다.

kubectl get po -n {설정한 ns}

ingress controller pod

kubectl get svc -n {설정한 namespace}

NodePort로 설정된 nginx-controller를 확인할 수 있다. (외부 포트는 32206)

 

이 Ingress Controller는 클러스터내 어떠한 노드를 통해서도 접근할 수 있다.

즉 현재 master, worker1, worker2 노드가 운영중이고 어떠한 노드의 IP든 32206 포트로 접근하기만 하면 해당 Ingress Controller로 접근이 가능하다.

 

네임스페이스 변경

네임 스페이스를 위에서 설정한 Ingress Controller가 사용되는 네임스페이스로 변경해야한다.

현재는 아마 default namespace로 되어있을 것이다.

kubectl config set-context --current --namespace {namespace name}

위 명령을 통해 사용중인 네임스페이스를 변경한다.

 

Ingress 리소스 생성

이제 Ingress Controller가 사용할 Ingress 규칙을 만들어 준다.

 

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: madpt-ingress
  annotations:
    kubernetes.io/ingress.class: nginx
    ingressclass.kubernetes.io/is-default-class: "true"

spec:
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx-service
            port:
              number: 80
      - path: /test1
        pathType: Prefix
        backend:
          service:
            name: nginx-service2
            port:
              number: 80
      - path: /test2
        pathType: Prefix
        backend:
          service:
            name: nginx-service3
            port:
              number: 80

위의 예시는 간단하게 3개의 path를 라우팅 해주는 Ingress 룰이다.

 

 

/ 로 들어오는 요청들은 nginx-service라는 서비스로 보내주게 되고

/test1로 들어오는 요청들은 nginx-service2라는 서비스로 보내주게 되고

/test2로 들어오는 요청들은 nginx-service3라는 서비스로 보내주게 된다.

 

실제 서비스를 만들어 테스트를 해보자.

3개의 nginx-service를 만들어서 각각 하나의 pod를 endpoint로 할당해줬다.

 

3개의 pod
3개의 service

 

이제 각 end point들에게 attach를 해서 접속을 확인해 본다.

kubectl attach {pod name}

 

이제 각 path로 요청을 넣게되면

/ 로 요청
/test1 로 요청
/test2로 요청

 

당연히 각 pod에서는 /test1, /test2에 대한 대응이 안되어 있으므로 오류 페이지가 날라오지만, 요청이 각 서비스로 나뉘어 들어간다는것은 알 수 있다.

 

 

rewrite

 

GitHub - kubernetes/ingress-nginx: NGINX Ingress Controller for Kubernetes

NGINX Ingress Controller for Kubernetes. Contribute to kubernetes/ingress-nginx development by creating an account on GitHub.

github.com

ingress는 요청이 들어오는 경로를 rewrite하여 새로운 경로를 만들 수 있다.

위의 예시에선 /test1, /test2 경로로 나뉘어 서비스를 제공했다. 요청으로 들어온 url이 /test1, test2냐에 따라 제공할 서비스를 다르게 구분한 것이다.

 

하지만 우리는 다음과 같은 구분또한 하고싶을 수 있다.

 

/test1/{something}/{something}...

/test2/{something}/{something}...

 

즉 요청하게 될 root path가 test1, test2냐에 따라 제공되는 서비스를 다르게 하는것이다.

 

이때는

nginx.ingress.kubernetes.io/rewrite-target

라는 어노테이션을 사용한다.

 

 

만약 위 예시처럼 동작하게 하는 서비스를 제공하고자 한다면, 아래와 같이 yml 파일을 작성한다.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: test-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
    ingressclass.kubernetes.io/is-default-class: "true"
    kubernetes.io/ingress.class: "nginx"

spec:
  rules:
  - http:
      paths:
      - path: /test1(/|$)(.*)
        pathType: Prefix 
        backend:
          service:
            name: test1-service
            port:
              number: 8080
              
      - path: /test2(/|$)(.*)
        pathType: Prefix 
        backend:
          service:
            name: test2-service
            port:
              number: 8080

 

 

example

클라이언트는 /test1/foo/bar 라는 경로로 http 요청을 하게 된다.

 

이 요청은 rule에 따라 test1-service로 가게될 것이다. 

하지만 요청 그대로 /test1/foo/bar 경로에 대한 요청이 가는것이 아닌  /foo/bar 요청이 가게 된다. 

만약 /test1/bar/foo 라는 경로로 요청이 들어오게 되어도 rewrite를 통해 /bar/foo 요청이 test1-service로 전달되게 된다.

실제 요청경로 Service로 전달될 경로
/test1/foo/bar /foo/bar
/test2/foo/ /foo

 

내가 사용한 예시로는, 이미 서버 개발이 완료된 시점에, 정책상 get, post요청을 나눠야 할 일이 생겼다.

 

서버 소스코드를 건들지 않고, 클라이언트쪽 소스코드만 수정하여 문제를 해결해야 하는 상황이였다.

 

이때 클라이언트측에서 요청하게 될 경로에  /get, /post를 추가하여 요청을 진행했다.

즉 /account/login 이라는 요청의 경우 /post/account/login 이라는 요청으로만 바꿔준 것이다.

 

이후 ingress의 rewrite 기능을 사용하여 클라이언트측으로부터 들어온 /post/account/login이라는 요청은 /account/login이라는 요청으로 바뀌어 서버측 변경 없이 서비스를 제공해주었다.