Ingress
개요
Make your HTTP (or HTTPS) network service available using a protocol-aware configuration mechanism, that understands web concepts like URIs, hostnames, paths, and more. The Ingress concept lets you map traffic to different backends based on rules you define via the Kubernetes API.[1]
HTTP 서비스를 프로토콜 기반 설정 매커니즘을 통해 uri, 호스이름, 경로 등을 활용하며 조금 더 유연하게 조작할 수 있다.
인그레스의 기본 컨셉은 쿠버네티스 api를 통해 트래픽을 규칙 기반으로 여러 백엔드로 보낼 수 있게 하고자 하는 것이다.
뭔가 설명이 자연스럽지는 않은데, 아무튼 http 통신을 할 때 경로나 각종 정보를 통해 유연하게 서비스를 관리할 수 있도록 도와주는 오브젝트이다.
가령 SSL 터미네이션, 로드 밸런싱, 이름 기반 호스팅 등을 할 수 있다.
가령 example.com
으로 서비스를 하고 싶은데, /auth
경로로 가면 로그인 관련 페이지를 호출하고 싶고 /doc
으로 가면 문서 페이지를 띄우고 싶은 것이다.
그러나 두 페이지는 다른 어플리케이션으로 서비스되고 싶다면, 이럴 때 경로를 기반으로 라우팅할 수 있게 해주는 게 바로 인그레스다!
흔히 L7 기반 로드 밸런서라고들 한다.
틀린 말은 아니긴 한데.. 그렇다고 서비스 / 인그레스를 그저 4.RESOURCE/KNOWLEDGE/AWS/AWS의 로드밸런서 타입 정도의 L4 / L7로 대치시켜 이해하면 곤란하다.
아래에서 세부 원리를 보자.
현재 이 오브젝트의 개발은 중단되었다.
이 후속자로서 Gateway API가 활발히 개발되는 중이다.
막상 공부해보니 느끼는 건데, 이거 진짜 개불편해서 중단될 만하다.
기능
이 녀석의 기능은 http로 할 수 있는 것들에 특화돼있다.
- 경로 기반 라우팅(fanout)
- 하나의 입력에서 여러 개의 출력을 내는 것을 fanout이라 하는 모양인데, 이걸 http에서도 사용하는 모양이다.
- 위에서 말한 예시, 경로 기반으로 라우팅을 하는 것을 말한다.
- 이름 기반 가상 호스팅
- 위와 다르게
f.host.com
과b.host.com
을 다르게 라우팅하는, 호스팅 이름 기반으로 라우팅을 하는 것을 말한다.
- 위와 다르게
- TLS
- https로 연결하는 것도 처리할 수 있다.
- 이렇게 들어온 트래픽을 백엔드로 보낼 때는 복호화를 시켜 플레인 텍스트로 보내는 기능도 있다.
사실 이 정도가 필드를 통해서 할 수 있는 인그레스의 전부다..
생각보다 뭐가 별로 없는 것 같은데, 대신 커스텀 어노테이션을 붙여서 기능들을 제공하는 컨트롤러들이 더러 있다.
동작 원리
인그레스는 http 트래픽을 받아서 라우팅 규칙에 따라 지정한 서비스로 트래픽을 흘려보낸다.
그러나 사실 인그레스가 그 자체로 트래픽을 받아내는 역할을 할 수 있는 것은 아니다.
그림에서 보다시피, 인그레스는 인그레스로 보낼 트래픽을 관리할 [[#인그레스 클래스]](사진에서 load balancer)가 뒷단에서 동작하고 있다.
그리고 그 클래스의 도움으로 인그레스는 트래픽을 받아 자신에게 설정된 규칙에 따라 뒷단의 서비스로 트래픽을 보내게 된다.
인그레스 클래스는 사실 NodePort, 혹은 LoadBalancer 타입의 서비스를 또 내부적으로 가지고 있다.
이 인그레스, 인그레스 클래스를 동작시키는 컨트롤러는 기본 kube-controller-manager에 포함되어 있지 않다.[2]
그러므로 우리가 직접 클러스터에 설치해서 써야 한다.
컨트롤러마다 지원하는 기능, 설정들이 다양해서 이를 고려해서 선택해주면 된다.
양식 작성법
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: minimal-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx-example
rules:
- host: "foo.bar.com"
http:
paths:
- path: /testpath
pathType: Prefix
backend:
service:
name: test
port:
number: 80
이것은 가장 대중적인 nginx-ingress에서 하는 설정이다.
어노테이션의 경우에는 인그레스 컨트롤러마다 정말 세팅이 달라서 이 차이를 알아야 한다.
스펙에 기본적으로 사용할 [[#인그레스 클래스]]를 지정한다.
이 놈이 인그레스 컨트롤러랑 연결되는 설정 오브젝트이다.
그리고 규칙들을 리스트로 쓰게 되는데, 어떤 경로가 일치하면 지정한 서비스로 흘려보내는 방식이다.
참고로 이 문서에서 백엔드라고 하면 서비스나, 서비스처럼 트래픽을 받을 오브젝트를 나타낸다.
defaultBackend
defaultBackend:
resource:
apiGroup: k8s.example.com
kind: StorageBucket
name: static-assets
인그레스에 지정한 모든 규칙에 맞지 않는 트래픽은 여기에서 처리된다.
보통은 인그레스 컨트롤러 쪽에다 하게 되는 설정이고, 인그레스에다 일일히 필드를 작성하지는 않는다.
다만 인그레스를 만들면서 아래의 .spec.rules
를 안 만들거라면, 이걸 무조건 명시해야 한다.
rules
.spec.rules
에 원하는 조건 규칙을 리스트로 넣으면 된다.
규칙들은 다음의 정보를 담으면 된다.
- 호스트
example.org
라던가 하는 처리할 호스트 이름.- 이 값이 없으면 그냥 클러스터로 들어오는 모든 ip에 대해 처리가 될 것이다.
- 경로
/testpath
와 같은 경로를.spec.rules[].http.paths
에 리스트로 넣어준다.
- 서비스
- 각 경로마다 그 경로에 원하는 서비스의 이름과 포트를 쓰면 된다.
지금부터 각 부분을 상세하게 털어보자.
host
호스트 헤더로 들어가는 부분.
*.foo.com
처럼 와일드카드처리를 할 수도 있다.
와일드카드는 하나의 라벨만 처리할 수 있기 때문에, a.b.foo.com
이나 foo.com
은 처리하지 못한다.
paths
경로들을 리스트로 넣어주고, 이 하위 필드로 backend를 명시하여 연결할 서비스를 지정한다.
경로에는 세가지 타입이 있으며, 이걸 명시하지 않으면 검증 오류가 발생한다.
- Prefix
- /로 분리되는 url 경로를 기반으로 매칭하는 가장 기본값이라 보면 된다.
- 이 타입일 때
/test
라고 한다면,/test/*
,/test/
도 매칭된다. - 하위 경로도 매칭시켜주며 끝에 붙은 슬래쉬도 신경 안쓰고 매칭한다.
- Exact
- 정확하게 명시된 경로만을 처리한다.
- 이 타입일 때
/test
라고 한다면,/test
로 들어온 것만 처리한다. - 이때
/test/
도 처리되지 않으니 유의하자!
- ImplementationSpecific
- 인그레스 클래스가 매칭을 담당한다.
- 궁극적으로는 Prefix와 Exact의 조합으로 이뤄진 어떤 방식이 될 것이다.
만약 Prefix와 Exact가 겹치는 경로로 들어올 때는 Exact가 우선된다.
그리고 여러 개의 Prefix에 부합하는 경로로 들어온다면 더 길게 설정된 Prefix가 우선된다.
paths[].backend
기본적으로 여기에 서비스를 적어주면 된다.
backend:
resource:
apiGroup: k8s.example.com
kind: StorageBucket
name: icon-assets
이런 식으로 서비스가 아니라 resource라는 필드를 넣을 수도 있다.
서비스가 아닌 오브젝트를 명시해 넣는 방식인데, 흔히 4.RESOURCE/KNOWLEDGE/개념/스토리지#Object Storage가 클러스터에 있을 때 활용한다.
그냥 서비스를 넣는다면 서비스 이름과 포트 이름을 넣어주면 된다.
양식이 참 불편하게 생겼다고 생각한다..
tls
443 포트로 들어오는 요청에 대해 tls 관련 기능을 할 때 사용하는 필드이다.
이걸 사용하면 https로 들어오는 요청을 인그레스 단에서 처리한 후 플레인 텍스트로 백엔드에 넘겨준다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tls-example-ingress
spec:
tls:
- hosts:
- https-example.foo.com
secretName: testsecret-tls
rules:
- host: https-example.foo.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: service1
port:
number: 80
사용방법은 그렇게 어렵지는 않다.
hosts에 rules에서 나온 모든 호스트를 나열한다.
apiVersion: v1
kind: Secret
metadata:
name: testsecret-tls
namespace: default
data:
tls.crt: {base64로 인코딩된 인증서}
tls.key: {base64로 인코딩된 키}
type: kubernetes.io/tls
그리고 secreteName 필드에 키로 사용할 위와 같은 Secret을 넣어주면 된다.
웃긴 게 무조건 443으로 와야지만 처리할 수 있는데.. 이렇게 제한적이니 Gateway API가 나왔나 싶다.
또 컨트롤러마다 작동하는 게 천지차이라고 한다.
인그레스 클래스
위에서 말했듯 관리자는 클러스터에 아무 컨트롤러를 갖다 박아서 쓰면 된다.
(물론 각각이 어떤 기능을 가지고 있는지는 잘 알아야겠지)
그리고 각 컨트롤러를 사용할 때 다양한 설정을 추가하고 싶을 수 있다.
이를 위해 존재하는 것이 인그레스 클래스이며, 이 놈이 인그레스가 돌아가게 하는 설정 파일처럼 동작한다.
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: external-lb
annotation: {
"ingressclass.kubernetes.io/is-default-class": "true",
}
spec:
controller: example.com/ingress-controller
parameters:
apiGroup: k8s.example.com
kind: IngressParameters
name: external-lb
기본적인 예시로, .spec.controller
필드로 원하는 컨트롤러를 지정해주면 된다.
.spec.parameters
필드에서 각종 설정을 넣을 수 있는데, 이 오브젝트는 컨트롤러에서 지정한 양식에 맞춰서 만들어서 넣어주면 된다.
위의 어노테이션을 걸어두면 기본 인그레스 클래스가 된다.
참고로 이 어노테이션이 여러 개 클러스터에 있다면 이 설정이 무시돼버려서 클래스가 없는 인그레스를 만들면 에러가 날 것이다.
전역 설정
인그레스 클래스 자체는 무조건 클러스터 전역으로 사용되는 오브젝트로, 네임스페이스에 종속되지 않는다.
그러나 .spec.parameters.scope=Namespace
를 통해 특정 네임스페이스에서만 사용가능한 클래스로 만들어버릴 수는 있다.
당연히 .spec.parameters.namespace
도 지정해줘야 할 것이다!
설정하지 않는다면 Cluster 전역으로 설정된다.
관련 문서
이름 | noteType | created |
---|---|---|
Ingress | knowledge | 2025-01-06 |