[Kubernetes] ๐ Gateway API๋ก HTTPโHTTPS ๋ฆฌ๋ค์ด๋ ํธ (HTTPRoute RequestRedirect)
Gateway API์ ํ์ค ํํฐ RequestRedirect๋ก HTTP๋ฅผ HTTPS๋ก ๋ฆฌ๋ค์ด๋ ํธํ๋ ๋ฐฉ๋ฒ์ ์ ๋ฆฌํฉ๋๋ค. ๋ฆฌ์ค๋ 2๊ฐ+๋ผ์ฐํธ 2๊ฐ ๊ธฐ๋ณธํ๋ถํฐ allowedRoutes๋ก ํ๋ฌธ ๋ ธ์ถ์ ์์ฒ ์ฐจ๋จํ๋ ์ค๋ฌด ํจํด๊น์ง ๋ค๋ฃน๋๋ค.
Gateway API์์ HTTPโHTTPS ๋ฆฌ๋ค์ด๋ ํธ๋ Ingress์ annotation(ssl-redirect)์ด ์๋๋ผ ํ์ค ํํฐ RequestRedirect๋ก ํฉ๋๋ค. ์ด ๊ธ์์๋ HTTP(80)ยทHTTPS(443) ๋ฆฌ์ค๋ 2๊ฐ + HTTPRoute 2๊ฐ๋ก ๊ตฌ์ฑํ๋ ๊ธฐ๋ณธํ๊ณผ, ์ฑ ํ์ด sectionName์ ๋น ๋จ๋ ค๋ ํ๋ฌธ ๋
ธ์ถ์ด ์ ๋๋๋ก allowedRoutes๋ก 80 ๋ฆฌ์ค๋๋ฅผ ์ ๊ทธ๋ ์ค๋ฌด ํจํด, ๊ทธ๋ฆฌ๊ณ โ๊ตฌ์ฑํ๋๋ฐ http๊ฐ ๊ณ์ ๋๋โ ํธ๋ฌ๋ธ์ํ
์ ์ ๋ฆฌํฉ๋๋ค.
์ด ์๋ฆฌ์ฆ๋ ์ฟ ๋ฒ๋คํฐ์ค gRPC ์ฝ์ง์์ ์ถ๋ฐํด HTTP/2ยทTLSยท๋ก๋๋ฐธ๋ฐ์ยทGateway APIยท์ธ์ฆ์๊น์ง ํ์ด๊ฐ๋ ๊ธฐ๋ก์ ๋๋ค. ์์ Ingress โ Gateway API ํธ๊ณผ cert-manager TLS ํธ์ ๋จผ์ ๋ณด๋ฉด ์ดํด๊ฐ ๋น ๋ฆ ๋๋ค.
๐ฏ ํต์ฌ: RequestRedirect ํํฐ
RequestRedirect๋ ํด๋ผ์ด์ธํธ์ 3XX ์๋ต์ ๋๋ ค์ค ๋ค๋ฅธ ์์น๋ก ๋ค์ ์์ฒญํ๊ฒ ํ๋ Gateway API ํ์ค ํํฐ์
๋๋ค. HTTPRoute์ rules[].filters์ type: RequestRedirect๋ฅผ ์ ์ธํ๊ณ , HTTPโHTTPS ์
๊ทธ๋ ์ด๋๋ scheme: https + statusCode: 301์ด ์ ์์
๋๋ค.
1
2
3
4
5
6
rules:
- filters:
- type: RequestRedirect
requestRedirect:
scheme: https
statusCode: 301
๋ฆฌ๋ค์ด๋ ํธ๋ ์ง์ ํ URL ์์๋ง ๋ฐ๊พธ๊ณ ๋๋จธ์ง๋ ๋ณด์กดํฉ๋๋ค. ์๋ฅผ ๋ค์ด GET http://redirect.example/cinnamon ์์ฒญ์ ๋ค์๊ณผ ๊ฐ์ด ์๋ต๋ฉ๋๋ค.
1
2
HTTP/1.1 301 Moved Permanently
location: https://redirect.example/cinnamon
scheme๋ง https๋ก ๋ฐ๋๊ณ host(redirect.example)ยทpath(/cinnamon)๋ ๊ทธ๋๋ก ์ ์ง๋ฉ๋๋ค.
โ ๏ธ
RequestRedirect์URLRewrite๋ ํ rule ์์์ ๋์์ ์ธ ์ ์์ต๋๋ค. RequestRedirect๋ ํด๋ผ์ด์ธํธ์๊ฒ 3XX๋ก โ๋ค์ ์์ฒญํด๋ผโ๋ฅผ ๋๋ ค์ฃผ๋ ๊ฒ์ด๊ณ , URLRewrite๋ ๋ฐฑ์๋๋ก ๋ณด๋ด๊ธฐ ์ ์ ์์ฒญ์ ์กฐ์ฉํ ๋ฐ๊พธ๋ ๊ฒ์ด๋ผ ์ฑ๊ฒฉ์ด ๋ค๋ฆ ๋๋ค.
์ง์ํ๋ ์ํ ์ฝ๋๋?
| ์ฝ๋ | ์๋ฏธ | ๋ฉ๋ชจ |
|---|---|---|
| 301 | ์๊ตฌ ์ด๋ (Moved Permanently) | HTTPโHTTPS ์ ๊ทธ๋ ์ด๋ ๊ถ์ฅ |
| 302 | ์์ (Found) | statusCode ์๋ต ์ ๊ธฐ๋ณธ๊ฐ |
| 303 | See Other | POSTโGET ํจํด |
| 307 | ์์ + ๋ฉ์๋ ๋ณด์กด | Extended ์ง์ |
| 308 | ์๊ตฌ + ๋ฉ์๋ ๋ณด์กด | Extended ์ง์ |
๐ก 307/308๊ณผ path ๋จ์ redirect๋ โExtendedโ ์ง์์ด๋ผ ๊ตฌํ์ฒด(ContourยทIstioยทEnvoy Gateway ๋ฑ)๋ณ๋ก ์ง์ ์ฌ๋ถ๊ฐ ๋ค๋ฆ ๋๋ค. ์ฌ์ฉ ์ conformance ๋ฌธ์๋ก ํ์ธํ์ธ์.
๐งฑ ๊ธฐ๋ณธ ๊ตฌ์ฑ: ๋ฆฌ์ค๋ 2๊ฐ + ๋ผ์ฐํธ 2๊ฐ
HTTPโHTTPS ๋ฆฌ๋ค์ด๋ ํธ์ ๊ธฐ๋ณธํ์ Gateway์ 80ยท443 ๋ฆฌ์ค๋๋ฅผ ๋ชจ๋ ๋๊ณ , HTTPRoute๋ฅผ 2๊ฐ(80=๋ฆฌ๋ค์ด๋ ํธ, 443=๋ฐฑ์๋ ์ ๋ฌ) ๋ง๋๋ ๊ฒ์ ๋๋ค.
1๏ธโฃ Gateway โ HTTPยทHTTPS ๋ฆฌ์ค๋ ๋ ๋ค
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: redirect-gateway
namespace: gateway-system # ํ๋ซํผํ ์์
spec:
gatewayClassName: foo-lb
listeners:
- name: http
protocol: HTTP
port: 80
- name: https
protocol: HTTPS
port: 443
tls:
mode: Terminate
certificateRefs:
- name: redirect-example # TLS Secret (cert-manager๊ฐ ๋ฐ๊ธ)
2๏ธโฃ HTTPRoute โ โ 80 ๋ฆฌ์ค๋์ ๋ถ์ฌ ๋ฆฌ๋ค์ด๋ ํธ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: http-filter-redirect
namespace: gateway-system # 80 ๋ฆฌ์ค๋์ ๋ถ์ด๋ ค๋ฉด Gateway์ ๊ฐ์ ๋ค์์คํ์ด์ค
spec:
parentRefs:
- name: redirect-gateway
sectionName: http # http(80) ๋ฆฌ์ค๋๋ง ์ ํ
hostnames:
- redirect.example
rules:
- filters:
- type: RequestRedirect
requestRedirect:
scheme: https
statusCode: 301
3๏ธโฃ HTTPRoute โก โ 443 ๋ฆฌ์ค๋์ ๋ถ์ฌ ๋ฐฑ์๋๋ก ์ ๋ฌ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: https-route
namespace: team-a # ์ฑ ํ ๋ค์์คํ์ด์ค
labels:
gateway-access: "true" # 443 ๋ฆฌ์ค๋ allowedRoutes selector์ ๋งค์นญ (์๋ ์ฐธ๊ณ )
spec:
parentRefs:
- name: redirect-gateway
namespace: gateway-system # Gateway๊ฐ ๋ค๋ฅธ ๋ค์์คํ์ด์ค๋ผ ๋ช
์
sectionName: https
hostnames:
- redirect.example
rules:
- backendRefs:
- name: example-svc # team-a ์์ Service
port: 80
๐ก ๋ค์์คํ์ด์ค ๋ฐฐ์น ๋ฉ๋ชจ
- Gateway + ๋ฆฌ๋ค์ด๋ ํธ ๋ผ์ฐํธ โ
gateway-system(ํ๋ซํผ). 80 ๋ฆฌ์ค๋๊ฐ ๊ธฐ๋ณธfrom: Same์ด๋ผ ๋ฆฌ๋ค์ด๋ ํธ ๋ผ์ฐํธ๋ ๊ฐ์ ns์ ๋ฌ์ผ ๋ถ์ต๋๋ค.- ๋ฐฑ์๋ ๋ผ์ฐํธ โ
team-a(์ฑ ํ). Gateway๊ฐ ๋ค๋ฅธ ns๋ผparentRefs.namespace๋ฅผ ๋ช ์ํ๊ณ , 443 ๋ฆฌ์ค๋์allowedRoutes๊ฐ ์ด ns๋ฅผ ํ์ฉํด์ผ ํฉ๋๋ค.backendRefs๊ฐ ๋ค๋ฅธ ns์ Service๋ฅผ ๊ฐ๋ฆฌํค๋ฉด ๊ทธ์ชฝ์ ReferenceGrant๊ฐ ํ์ํฉ๋๋ค. ๊ฐ์ ns๋ฉด ๋ถํ์.- ๋ชจ๋ ํ ๋ค์์คํ์ด์ค์ ๋ ๊ฑฐ๋ฉด namespace ํ๊ธฐ๋ ์๋ตํด๋ ๋ฉ๋๋ค(๊ณต์ ๊ฐ์ด๋ ์์ ํํ).
โ ์ ๋ผ์ฐํธ๊ฐ ๊ผญ 2๊ฐ์ฌ์ผ ํ๋?
ํ HTTPRoute์ rules๋ ๊ทธ ๋ผ์ฐํธ๊ฐ ๋ถ์ ๋ชจ๋ ๋ฆฌ์ค๋์ ๋๊ฐ์ด ์ ์ฉ๋๊ธฐ ๋๋ฌธ์
๋๋ค. ๊ทธ๋์ โ80=๋ฆฌ๋ค์ด๋ ํธ / 443=๋ฐฑ์๋ ์ ๋ฌโ์ ํ ๋ผ์ฐํธ ์์์ ๋๋ ์ ์์ต๋๋ค. ์ญํ ๋ณ๋ก ๋ผ์ฐํธ๋ฅผ ๋ถ๋ฆฌํด์ผ ํฉ๋๋ค.
๋ฆฌ๋ค์ด๋ ํธ ๋ผ์ฐํธ๋ ๊ฒ์ดํธ์จ์ด๋น 1๊ฐ๋ก ์ถฉ๋ถํฉ๋๋ค
๋ฆฌ๋ค์ด๋ ํธ ๋ผ์ฐํธ์์ hostnames๋ฅผ ์๋ตํ๋ฉด ๊ทธ 80 ๋ฆฌ์ค๋๋ก ๋ค์ด์ค๋ ๋ชจ๋ ํธ์คํธ์ ์ ์ฉ๋ฉ๋๋ค. ๋ฐ๋ผ์ ์ฑ์ด ์ฌ๋ฌ ๊ฐ์ฌ๋ ๋ฆฌ๋ค์ด๋ ํธ ๋ผ์ฐํธ๋ ํ๋๋ฉด ๋๊ณ , ๋๋จธ์ง๋ ๊ฐ ์ฑ์ 443 ๋ฐฑ์๋ ๋ผ์ฐํธ๋ง ์ถ๊ฐํ๋ฉด ๋ฉ๋๋ค(์ด์ฐจํผ ๋ง๋ค ๊ฒ).
sectionName: https๋ง ๋ฐ์ผ๋ฉด 404, ๋ฆฌ๋ค์ด๋ ํธ๊ฐ ์๋๋๋ค
์ฑ ๋ผ์ฐํธ๋ฅผ 443์๋ง ๊ณ ์ ํ๋ฉด 80์ผ๋ก ์จ ์์ฒญ์ ๋งค์นญ๋๋ ๋ผ์ฐํธ๊ฐ ์์ด 404๊ฐ ๋ฉ๋๋ค(๋ฆฌ๋ค์ด๋ ํธ โ). ๋ธ๋ผ์ฐ์ ๋ก ํ ์คํธํ์ ๋ https๋ก ๋์ด๊ฐ๋ค๋ฉด ๊ทธ๊ฑด ๋ธ๋ผ์ฐ์ ์ https-first ๋์์ผ ๋ฟ, ๊ฒ์ดํธ์จ์ด๊ฐ ๋ฆฌ๋ค์ด๋ ํธํ ๊ฒ ์๋๋๋ค. curlยท๋ชจ๋ฐ์ผ ์ฑ ๋ฑ http ํด๋ผ์ด์ธํธ๋ฅผ ๋ถ๋๋ฝ๊ฒ https๋ก ๋ณด๋ด๋ ค๋ฉด ๋ฆฌ๋ค์ด๋ ํธ ๋ผ์ฐํธ๋ ์ฌ์ ํ ํ์ํฉ๋๋ค.
๐ก๏ธ allowedRoutes๋ก ํ๋ฌธ ๋ ธ์ถ ์์ฒ ์ฐจ๋จ
์ฑ ํ์ด sectionName์ ๋น ๋จ๋ฆฌ๋ฉด ๊ทธ ๋ผ์ฐํธ๊ฐ 80 ๋ฆฌ์ค๋์๋ ๋ฐ์ธ๋ฉ๋ผ ํ๋ฌธ(HTTP)์ผ๋ก ์๋น๋ ์ ์์ต๋๋ค. ๊ฐ๋ณ ๋ผ์ฐํธ์ โ์์โ์ ๊ธฐ๋์ง ๋ง๊ณ , 80 ๋ฆฌ์ค๋๋ฅผ ํ๋ซํผ ์ ์ฉ์ผ๋ก ์ ๊ฐ์ ๋ง๋ ๊ฒ์ด ์์ ํฉ๋๋ค.
sectionName์ด ์์ผ๋ฉด ๋ผ์ฐํธ๋ ํธํ๋๋ ๋ชจ๋ ๋ฆฌ์ค๋(80 ํฌํจ)์ ๋ฐ์ธ๋ฉ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ฉด 80์์ ๋ฐฑ์๋ ๋ผ์ฐํธ๊ฐ ๋ฆฌ๋ค์ด๋ ํธ ๋ผ์ฐํธ๋ณด๋ค ๋ ๊ตฌ์ฒด์ ์ผ๋ก ๋งค์นญ๋์ด ํ๋ฌธ ์๋น์ด ์ผ์ด๋ ์ ์์ต๋๋ค. allowedRoutes๋ก ๋ค์์ฒ๋ผ ์ ๊ธ๋๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
spec:
listeners:
- name: http
port: 80
protocol: HTTP
allowedRoutes:
namespaces:
from: Same # ๊ฒ์ดํธ์จ์ด ๋ค์์คํ์ด์ค(=ํ๋ซํผ ๋ฆฌ๋ค์ด๋ ํธ ๋ผ์ฐํธ)๋ง ํ์ฉ
- name: https
port: 443
protocol: HTTPS
tls:
mode: Terminate
certificateRefs:
- name: redirect-example
allowedRoutes:
namespaces:
from: Selector # ์ฑ ํ ๋ผ์ฐํธ๋ ์ฌ๊ธฐ์๋ง
selector:
matchLabels:
gateway-access: "true"
์ด๋ ๊ฒ ํ๋ฉด ์ฑ ํ์ด sectionName์ ๋น ๋จ๋ ค๋ ๊ทธ ๋ผ์ฐํธ๋ 80์์๋ ๊ฑฐ๋ถ๋๊ณ 443์๋ง ๋ถ์ต๋๋ค. 80์ ํ๋ซํผ ๋ฆฌ๋ค์ด๋ ํธ ๋ผ์ฐํธ๊ฐ ๋
์ ํ๋ฏ๋ก ํ๋ฌธ ๋
ธ์ถ์ด ์์ฒ ์ฐจ๋จ๋ฉ๋๋ค.
๐ง ํธ๋ฌ๋ธ์ํ : ๊ตฌ์ฑํ๋๋ฐ http๊ฐ ๊ณ์ ๋ ๋
์์๋๋ก ํ์ธํฉ๋๋ค.
1๏ธโฃ ๋ฆฌ๋ค์ด๋ ํธ ๋ผ์ฐํธ๊ฐ 80์ ์ง์ง ๋ถ์๋?
1
kubectl describe httproute http-filter-redirect -n gateway-system
status.parents[].conditions์์ Accepted: True์ธ์ง ํ์ธํฉ๋๋ค. ์ ๋ถ๋ ํํ ์์ธ:
allowedRoutes๋ค์์คํ์ด์ค ๋ถ์ผ์น(๊ธฐ๋ณธ๊ฐ์ดSame)sectionName์คํ (http์ธ๋ฐhttps๋ก ์ฐ๋ ๋ฑ)parentRefs.namespace์ค๋ฅhostnames๋ถ์ผ์น
2๏ธโฃ 80์ ๋ฐฑ์๋ ๋ผ์ฐํธ๊ฐ ๋ผ์ด๋ค์๋?
์ฑ ๋ผ์ฐํธ๊ฐ sectionName ์์ด 80์๋ ๋ถ์ผ๋ฉด ๋งค์นญ ์ฐ์ ์์์์ ๋ฐฑ์๋๊ฐ ์ด๊ฒจ ํ๋ฌธ์ผ๋ก ์๋น๋ฉ๋๋ค. โ ์ฑ ๋ผ์ฐํธ์ sectionName: https๋ฅผ ๋ช
์ํ๊ฑฐ๋, ์ allowedRoutes ์ ๊ธ์ ์ ์ฉํฉ๋๋ค.
3๏ธโฃ ์์ฒญ์ด ์ด Gateway๋ฅผ ๊ฑฐ์น๊ธด ํ๋?
์์ ingress-nginx๊ฐ ์์ง 80์ ์๋น์คํ๊ณ ์๊ฑฐ๋, NodePortยทLB๋ก ๋ฐฑ์๋์ ์ง์ ์ ๊ทผํ๊ฑฐ๋, port-forward๋ก ํ
์คํธํ๋ ๊ฒฝ์ฐ Gateway๊ฐ ํธ๋ํฝ ๊ฒฝ๋ก์ ์์ด ๋ฆฌ๋ค์ด๋ ํธ๊ฐ ์ ์ฉ๋ ๋ฆฌ ์์ต๋๋ค.
๋ฆฌ๋ค์ด๋ ํธ ๋์ ํ์ธ์ curl๋ก ํฉ๋๋ค.
1
2
3
curl -I http://redirect.example/cinnamon
# HTTP/1.1 301 Moved Permanently
# location: https://redirect.example/cinnamon
โ ์์ฃผ ๋ฌป๋ ์ง๋ฌธ
Q. Ingress์ ssl-redirect annotation๊ณผ ๋ฌด์์ด ๋ค๋ฅธ๊ฐ์?
Ingress๋ ์ปจํธ๋กค๋ฌ๋ง๋ค nginx.ingress.kubernetes.io/ssl-redirect: "true" ๊ฐ์ ๋ฒค๋ ์ ์ฉ annotation์ผ๋ก ๋ฆฌ๋ค์ด๋ ํธํ์ต๋๋ค. Gateway API๋ ์ด๋ฅผ ํ์ค ํํฐ RequestRedirect๋ก ์ ์ํด ๊ตฌํ์ฒด์ ์๊ด์์ด ๋์ผํ ์คํ์ผ๋ก ๋์ํ๊ฒ ํฉ๋๋ค.
Q. 301๊ณผ 302 ์ค ๋ฌด์์ ์จ์ผ ํ๋์?
HTTPโHTTPS ์๊ตฌ ์ ํ์๋ 301(์๊ตฌ ์ด๋)์ ๊ถ์ฅํฉ๋๋ค. ๋ธ๋ผ์ฐ์ ยท๊ฒ์์์ง์ด ๊ฒฐ๊ณผ๋ฅผ ์บ์ํด ๋ค์๋ถํฐ ๋ฐ๋ก https๋ก ์์ฒญํ๊ธฐ ๋๋ฌธ์
๋๋ค. statusCode๋ฅผ ์๋ตํ๋ฉด ๊ธฐ๋ณธ๊ฐ์ 302(์์)์
๋๋ค.
Q. ๋ฆฌ๋ค์ด๋ ํธ ๋ผ์ฐํธ๋ฅผ ๋นผ๊ณ 443 ๋ผ์ฐํธ๋ง ๋๋ฉด ์ ๋๋์?
๋ธ๋ผ์ฐ์ ๋ https-first ๋์ ๋๋ฌธ์ ์ ๋์ด๊ฐ๋ ๊ฒ์ฒ๋ผ ๋ณด์ด์ง๋ง, 80์ผ๋ก ์ง์ ์จ ์์ฒญ(curlยท๊ตฌํ ํด๋ผ์ด์ธํธยท์ธ๋ถ ์ฐ๋)์ 404๊ฐ ๋ฉ๋๋ค. ๋ถ๋๋ฌ์ด ๋ฆฌ๋ค์ด๋ ํธ๋ฅผ ๋ณด์ฅํ๋ ค๋ฉด 80 ๋ฆฌ์ค๋์ ๋ถ๋ ๋ฆฌ๋ค์ด๋ ํธ ๋ผ์ฐํธ๊ฐ ๋ฐ๋์ ํ์ํฉ๋๋ค.
Q. POST ์์ฒญ๋ ๋ฆฌ๋ค์ด๋ ํธ๋๋์?
301/302๋ ๋ฆฌ๋ค์ด๋ ํธ ์ ๋ฉ์๋๊ฐ GET์ผ๋ก ๋ฐ๋ ์ ์์ต๋๋ค. POST ๋ฑ ๋ฉ์๋๋ฅผ ๋ณด์กดํด์ผ ํ๋ฉด 307/308์ ์ฌ์ฉํด์ผ ํ์ง๋ง, ์ด๋ Extended ์ง์์ด๋ผ ๊ตฌํ์ฒด ์ง์ ์ฌ๋ถ๋ฅผ ๋จผ์ ํ์ธํ์ธ์.
๐ ์ฐธ๊ณ
- HTTP redirects and rewrites (Gateway API ๊ณต์ ๊ฐ์ด๋)
- HTTPRoute API ๋ ํผ๋ฐ์ค
- HTTPRequestRedirectFilter ์คํ
- Cross-Namespace routing (allowedRoutes)
- TLS ์ค์ ๊ฐ์ด๋
- Conformance(์ง์ ๋ ๋ฒจ) ๊ฐ๋
</content> </invoke>