Ingress는 외부로부터 서버 내부로 유입되는 네트워크 트래픽을, egress는 서버 내부에서 외부로 나가는 트래픽을 의미한다.
쿠버네티스에도 Ingress라고 하는 리소스 오브젝트가 존재한다. 쿠버네티스의 Ingress는 외부에서 쿠버네티스 클러스터 내부로 들어오는 네트워크 요청 즉, Ingress 트래픽을 어떻게 처리할지 정의한다. 쉽게 말하자면, Ingress는 외부에서 쿠버네티스에서 실행 중인 Deployment와 Service에 접근하기 위한, 일종의 관문(Gateway) 같은 역할을 담당한다. Ingress를 사용하지 않았다고 가정했을 떄, 외부 요청을 처리할 수 있는 선택지는 NodePort, ExternalIP 등이 있다. 그러나 이러한 방법들은 일반적으로 Layer 4(TCP,UDP)에서의 요청을 처리하며, 네트워크 요청에 대한 세부적인 처리 로직을 구현하기는 아무래도 한계가 있다.
쿠버네티스의 Ingress는 Layer 7에서의 요청을 처리할 수 있다. 외부 요청을 어떻게 처리할 것인지를 정의하는 집합인 Ingress를 정의한 뒤, Ingress Controller라고 부르는 특별한 웹 서버에 적용함으로써 추상화된 단계에서 서비스 처리 로직을 정의할 수 있다.
서비스를 외부로 노출시켜 제공해야 한다면 Ingress를 사용하는 것이 바람직하다. Ingress 요청을 처리하기 위한 Service는 일반적으로 클라우드 플랫폼에서 제공되는 Load Balancer 타입의 Service를 사용한다.
쿠버네티스에서 Ingress를 사용하기 위해서는 두 가지가 필요하다. 첫 번째는 YAML 파일에서 [kind:Ingress]로 정의되는 Ingress Object이고, 두 번째는 Ingress 규칙이 적용될 Ingress Controller이다.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: alicek106.com
http:
paths:
- path: /api/hostname-service
backend:
serviceName: hostname-service
servicePort: 80
Ingress를 정의하는 위 yaml
파일은 매우 간단하다.
host
: 지정된 값을 호스트 명으로 접근하는 네트워크 요청에 대해서 Ingress 규칙을 적용http
: http 프로토콜을 통해path
: 해당 경로로 접근하는 요청을serviceName
: 해당 이름의 service의servicePort
: 해당 포트 번호로 전달하라는 뜻위의 yaml
파일로부터 Ingress를 생성해도 아무 일도 일어나지 않는다. Ingress는 단지 Ingress 규칙을 정의하는 선언적인 오브젝트일 뿐, 외부 요청을 받아들이는 실제 서버가 아니기 때문이다. Ingress는 Ingress Controller라고 하는 특수한 서버 컨테이너에 적용되어야만 Ingress에 적용된 규칙이 활성화된다. 즉, Ingress Controller가 외부로부터 네트워크 요청을 수신했을 때, Ingress 규칙에 기반해 이 요청을 어떻게 처리할지를 결정한다.
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
Ingress-nginx 컨트롤러를 사용하므로 .metadata.annotations의 하위 필드에 nginx.ingress.kubernetes.io/rewrite-target을 키로 /를 값으로 설정한다. "/" 경로로 리다이렉트 하라는 의미이다. 또한 Ingress-nginx 컨트롤러가 클러스터에 설치되어 있어야 한다.
.spec.rules
필드에서 어떤 규칙을 사용할지 지정할 수 있다.
위의 spec에서 .spec.rules[].host
의 필드가 foo.bar.com
이다. foo.bar.com
의 주소로 요청이 들어오면 다음에 설정하는 규칙에 따라 처리한다.
.spec.rules[].http.paths[]
필드는 HTTP 요청이 어떤 경로로 들어오는지 지정한다. 위의 예시에서 /foos1
경로로 지정했으며 pathType이 Prefix이므로 foo.com/foos1
으로 들어오는 요청을 처리한다.
.spec.rules[].http.backend
필드에 위에서 지정한 요청에 어떻게 처리할 것인지를 지정한다. 위의 예시에서는 s1이라는 서비스의 80 포트로 보내도록 설정하였다.
즉, 요청된 url이 foo.bar.com/foos1으로 시작하면 s1 서비스의 80번 포트로 전송하라 라는 의미이다.
이제 ingress_basic.yml 파일로 저장한 후 kubectl 명령어를 이용하여 클러스터에 적용한다. 그리고 나서 kubectl describe ingress [인그레스 이름]
명령어 실행 시 인그레스의 자세한 내용을 확인할 수 있다.
인그레스 경로 유형
ImplementationSpecific
: 이 경로 유형의 일치 여부는 IngressClass에 따라 달라진다. 이를 구현할 때 별도 pathType으로 처리하거나, Prefix 또는 Exact 경로 유형과 같이 동일하게 처리할 수 있다.Exact
: URL 경로의 대소문자를 엄격하게 지킨다.Prefix
: URL 경로의 접두사를 /를 기준으로 분리한 값과 일치시킨다. 일치는 대소문자를 구분하고, 요소별로 경로 요소에 대해 수행한다. 모든 p가 요청 경로의 요소별 접두사가 p인 경우 요청은 p 경로에 일치한다.