본문 바로가기

About/Kubernetes

[k8s] 인그레스(Ingress)

 

인그레스(Ingress)

인그레스(Ingress)는 주로 클러스터 외부에서 안에 있는 파드에 접근할 때 사용하는 방법입니다. 서비스와의 차이점은 주로 L7 영역의 통신을 담당해서 처리한다는 것입니다. 

인그레스는 클러스터 외부에서 안으로 접근하는 요청들을 어떻게 처리할지 정의해둔 규칙에 대한 모음입니다. 클러스터 외부에서 접근해야 할 URL을 사용할 수 있도록 하고, 트래픽 로드밸런싱, SSL 인증서 처리, 도메인 기반 가상 호스팅도 제공합니다. 인그레스 자체는 이런 규칙들을 정의해둔 자원이고, 실제로 동작시키는 것은 인그레스 컨트롤러(Ingress Controller)입니다.

Kubenetes Ingerss-nginx

클라우드 서비스(AWS EKS 등..)를 사용하면 별다른 설정없이 자체 로드밸런서 서비스와 연동해서 인그레스를 사용할 수 있습니다. 클라우드 서비스를 사용하지 않고 직접 쿠버네티스 클러스터를 구축해서 사용한다면 인그레스 컨트롤러를 직접 인그레스와 연동해야 합니다. 이 때 가장 많이 사용하는 도구는 쿠버네티스에서 제공하는 ingress-nginx 입니다.
(ingress-nginx 외에 HAProxy, Envoy, Kong 등 소프트웨어 프록시를 이용한 인그레스 컨트롤러도 있으며, Citrix, F5 같은 로드밸런서 장비 회사에서 자사의 로드밸런서를 이용할 수 있도록 만든 인그레스 컨트롤러도 있습니다.)

ingress-nginx 컨트롤러는 인그레스에서 설정한 내용을 nginx 환경 설정으로 변경하여 nginx에 적용합니다.

인그레스 설정 예시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
apiVersion: networking.k8s.io/v1
kind: Ingress
 
# Ingress 설정 
metadata:
  name: test
  annotations: 
    nginx.ingress.kubernetes.io/rewrite-target: / #  Ingress-nginx에서 '/'로 리다이렉트
 
spec:
  rules:
  - host: "foo.bar.com" # foo.bar.com 주소에 대한 처리
    http:
      paths:
      - pathType: Prefix # Prefix/Exact/ImplementationsSpecific
        path: "/foos1" # foo.bar.com/foos1 주소에 대한 처리
        backend:
          # foo.bar.com/foos1 주소에 대한 요청을 s1 서비스의 80번 포트로 전송
          service:
            name: s1 
            port: 
              number: 80
 
      - pathType: Prefix 
        path: "/bars2" # foo.bar.com/bars2 주소에 대한 처리
        backend:
          # foo.bar.com/bars 주소에 대한 요청을 s2 서비스의 80번 포트로 전송
          service:
            name: s2
            port: 
              number: 80
 
  - host: "*.foo.com"
    http:
       paths:
        # *.foo.com의 모든 요청을 s2 서비스의 80번 포트로 전송
        - pathType: Prefix
          path: "/"
          backend:
             service:
                name: s2
                port: 
                  number: 80
cs

 

Ingress-nginx 컨트롤러를 사용하므로 .metadata.annotaions의 하위 필드에 nginx.ingress.kubernetes.io/rewrite-target를 키로 / 를 값으로 설정합니다. "/" 경로로 리다이렉트하라는 의미입니다. 또한 Ingress-nginx 컨트롤러가 클러스터에 설치되어 있어야합니다. Ingress-nginx 설치는 다음 사이트를 참고하세요.

https://kubernetes.github.io/ingress-nginx/deploy/

 

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

.spec.rules 필드에서 어떤 규칙을 사용할지 지정할 수 있습니다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
spec:
  rules:
  - host: foo.bar.com # foo.bar.com 주소에 대한 처리
    http:
      paths:
      - pathType: Prefix # Prefix/Exact/ImplementationsSpecific
        path: "/foos1" # foo.bar.com/foos1 주소에 대한 처리
        backend:
          # foo.bar.com/foos1 주소에 대한 요청을 s1 서비스의 80번 포트로 전송
          service:
            name: s1 
            port: 
              number: 80
cs

 

위의 spec에서 .spec.rules[].host 의 필드가 foo.bar.com 입니다. foo.bar.com의 주소로 요청이 들어오면 다음에 설정하는 규칙에 따라 처리합니다. 

.spec.rules[].http.paths[]. 필드는 HTTP 요청이 어떤 경로로 들어오는지 지정합니다. 위의 예시에서 /foos1 경로로 지정했으며 pathTypePrefix이므로 foo.com/foos1으로 들어오는 요청을 처리합니다.

.spec.rules[].http.backend 필드에 위에서 지정한 요청에 어떻게 처리할 것인지 지정합니다. 위의 예시에서는 .backend.service: s1, .backend.service.port.number: 80 이므로 s1이라는 서비스의 80번 포트로 보내도록 설정하였습니다.

따라서 위의 spec은 요청된 url이 foo.bar.com/foos1 으로 시작하면 s1 서비스의 80번 포트로 전송하라라는 의미입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
spec:
  rules:
  
  ...
 
  - host: "*.foo.com"
    http:
       paths:
        # *.foo.com의 모든 요청을 s2 서비스의 80번 포트로 전송
        - pathType: Prefix
          path: "/"
          backend:
             service:
                name: s2
                port: 
                  number: 80
cs

 

.spec.rules[].host 필드를 위와 같이 "*.foo.com" 으로 설정하면 .foo.com으로 끝나는 모든 요청에 대해 모두 처리할 수 있습니다. ex) foo.foo.com. bar.foo.com

이제 예시를 ingress_basic.yaml 파일로 저장한 후 kubectl 명령어를 이용하여 클러스터에 적용합니다. 그리고 나서 kubectl describe ingress [인그레스이름] 명령어를 실행하면 인그레스의 자세한 내용을 확인할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@k8s-master ingerss]# kubectl apply -f ingress_basic.yaml
ingress.networking.k8s.io/test created
 
[root@k8s-master ingerss]# kubectl describe ingress test
Name:             test
Namespace:        default
Address:          
Default backend:  default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
Rules:
  Host         Path  Backends
  ----         ----  --------
  foo.bar.com  
               /foos1   s1:80 (<error: endpoints "s1" not found>)
               /bars2   s2:80 (<error: endpoints "s2" not found>)
  *.foo.com    
               /   s2:80 (<error: endpoints "s2" not found>)
Annotations:   nginx.ingress.kubernetes.io/rewrite-target: /
Events:        <none>
cs

결과의 Rules 필드를 살펴보면 위에서 명시한대로 설정된 것을 확인할 수 있습니다. (위의 예시에서 서비스 s1, s2를 정의하지 않아 s1, s2 서비스가 없다라는 에러도 확인할 수 있습니다.)

또한 Default backend는 현재 default-http-backend로 설정되어 있는데, DefaultBackend는 규칙이 없는 모든 트래픽을 모두 전송하는 백엔드 입니다. 일반적으로 인그레스 컨트롤러의 구성옵션입니다.

 

(추가)인그레스 경로 유형, spec.rules[].http.paths[].pathType

1
2
3
4
5
6
7
8
9
10
11
12
13
spec:
  rules:
  - host: "foo.bar.com" # foo.bar.com 주소에 대한 처리
    http:
      paths:
      - pathType: Prefix # Prefix/Exact/ImplementationsSpecific
        path: "/foos1" # foo.bar.com/foos1 주소에 대한 처리
        backend:
          # foo.bar.com/foos1 주소에 대한 요청을 s1 서비스의 80번 포트로 전송
          service:
            name: s1 
            port: 
              number: 80
cs

 

위 예시의 6번 줄처럼 Ingress path 설정 시 spec.rules[].http.paths[].pathType 필드에서 경로 유형을 지정해야합니다. 지원하는 경로 유형은 세 가지가 있습니다.

경로 유형 설명
ImplementationSpecific 이 경로 유형의 일치 여부는 IngressClass에 따라 달라진다. 이를 구현할 때 별도 pathType 으로 처리하거나, Prefix 또는 Exact 경로 유형과 같이 동일하게 처리할 수 있다.
Exact URL 경로의 대소문자를 엄격하게 지킨다.
Prefix  URL 경로의 접두사를 / 를 기준으로 분리한 값과 일치시킨다. 일치는 대소문자를 구분하고, 요소별로 경로 요소에 대해 수행한다. 모든 p 가 요청 경로의 요소별 접두사가 p 인 경우 요청은 p 경로에 일치한다.

경로 유형에 따른 일치 여부는 다음 예제를 참고하세요.

종류  경로 요청 경로 일치 여부
Prefix / (모든 경로)
Exact /foo /foo
Exact /foo /bar 아니오
Exact /foo /foo/ 아니오
Exact /foo/ /foo 아니오
Prefix /foo /foo, /foo/
Prefix /foo/ /foo, /foo/
Prefix /aaa/bb /aaa/bbb 아니오
Prefix /aaa/bbb /aaa/bbb
Prefix /aaa/bbb/ /aaa/bbb 예, 마지막 슬래시 무시함
Prefix /aaa/bbb /aaa/bbb/ 예, 마지막 슬래시 일치함
Prefix /aaa/bbb /aaa/bbb/ccc 예, 하위 경로 일치함
Prefix /aaa/bbb /aaa/bbbxyz 아니오, 문자열 접두사 일치하지 않음
Prefix /, /aaa /aaa/ccc 예, /aaa 접두사 일치함
Prefix /, /aaa, /aaa/bbb /aaa/bbb 예, /aaa/bbb 접두사 일치함
Prefix /, /aaa, /aaa/bbb /ccc 예, / 접두사 일치함
Prefix /aaa /ccc 아니오, 기본 백엔드 사용함
Mixed /foo (Prefix), /foo (Exact) /foo 예, Exact 선호함

 

 


이처럼 인그레스를 사용하면 클러스터 외부에서 오는 요청에 대해 다양한 방식으로 처리할 수 있습니다.

쿠버네티스의 인그레스에 대하여 알아보았습니다.

참고