CloudNet@ 가시다님이 진행하는 쿠버네티스 네트워크 스터디 KANS 3기 내용을 정리한 글입니다.
Ingress
기존의 쿠버네티스에 존재하던 NodePort 및 LoadBalancer의 경우 단순한 로드밸런서 외에는 아무런 기능을 하지 못했다. 이러한 한계점을 보완하고자 나온 것이 Ingress이다. 하지만 이 Ingress에는 단점이 많이 존재함으로 만약 처음 공부하고 계신 분이라면 Gateway API를 먼저 알아보는 것을 추천한다. Ingress도 한계점이 많아 새롭게 만들어진것이 Gateway API이다. 그래서 심지어 Ingress에는 더 이상 기능이 추가 되지 않는다.
기본적으로 쿠버네티스에서 만들어진 서비스라는 객체는 L4레이어에서 동작하는 로드밸런서라고 생각하면 좋을 것 같다. 하지만 Ingress는 L7레이어에서 동작하며 HTTP, HTTPS에 대한 통신을 처리하는 것으로 알고있다. Path기반의 라우팅이나 Host기반의 라우팅을 지원하며 카나리 배포 또한 가능하다.
Ingress Nginx
nginx가 F5라는 회사에 인수가 되었는데 그 이후에 Ingress Nginx도 F5에서 운영이 되다가 Kubernetes로 넘어오게 되었다. 그래서 helm차트를 찾다보면 Nginx가 만들었다고나오는 Ingress들이 보이는데 이것은 F5가 관리하던것으로 아마 일반적으로 알려진 Ingress Nginx와는 조금 다르다고 한다. 그러니 주의
https://github.com/kubernetes/ingress-nginx
GitHub - kubernetes/ingress-nginx: Ingress NGINX Controller for Kubernetes
Ingress NGINX Controller for Kubernetes. Contribute to kubernetes/ingress-nginx development by creating an account on GitHub.
github.com
설치하기
<참고> 테스트 환경은 orbstack의 기본 쿠버네티스를 사용했습니다.
설치는 Helm차트를 이용해서 진행하고자 합니다.
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
레포를 추가 완료했다면 Ingress를 설치할 네임스페이스도 생성합니다.
kubectl create ns ingress
설치하는 버전은 글 작성 기준으로 최신의 헬름차트 버전인 4.11.2를 사용했습니다.
helm install ingress-nginx ingress-nginx/ingress-nginx --namespace ingress --version 4.11.2
이렇게 설치하고 나면 컨트롤러와 서비스가 생성이 된다.
그리고 Ingress에 연결할 default ingress class도 생성이 된다.
Ingress Nginx에도 상태를 확인할수있는 Health Check 경로가 존재합니다.
curl -s -o /dev/null -w "%{http_code}" http://198.19.249.2/healthz
200 정상응답으로 설치에 성공했습니다.
Ingress Nginx의 기능
테스트를 위한 환경 구축 방법입니다.
총 3개의 서비스를 구성할 예정입니다.
첫번째
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy1-websrv
spec:
replicas: 1
selector:
matchLabels:
app: websrv
template:
metadata:
labels:
app: websrv
spec:
containers:
- name: pod-web
image: nginx
---
apiVersion: v1
kind: Service
metadata:
name: svc1-web
spec:
ports:
- name: web-port
port: 9001
targetPort: 80
selector:
app: websrv
type: ClusterIP
두번째
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy2-guestsrv
spec:
replicas: 2
selector:
matchLabels:
app: guestsrv
template:
metadata:
labels:
app: guestsrv
spec:
containers:
- name: pod-guest
image: gcr.io/google-samples/kubernetes-bootcamp:v1
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: svc2-guest
spec:
ports:
- name: guest-port
port: 9002
targetPort: 8080
selector:
app: guestsrv
type: NodePort
세번 째
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy3-adminsrv
spec:
replicas: 3
selector:
matchLabels:
app: adminsrv
template:
metadata:
labels:
app: adminsrv
spec:
containers:
- name: pod-admin
image: k8s.gcr.io/echoserver:1.5
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: svc3-admin
spec:
ports:
- name: admin-port
port: 9003
targetPort: 8080
selector:
app: adminsrv
Host 기반 라우팅
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-1
annotations:
# 기본은 라우팅이 RR방식인데 IP-Hash 방식으로도 변경가능합니다.
nginx.ingress.kubernetes.io/upstream-hash-by: "true"
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: svc1-web
port:
number: 80
- path: /guest
pathType: Prefix
backend:
service:
name: svc2-guest
port:
number: 8080
- path: /admin
pathType: Prefix
backend:
service:
name: svc3-admin
port:
number: 8080
Canary 업그레이드
나중에 Canary 업그레이드 방법에 대해 문서를 작성해 보고 싶지만, 여기서는 간단하게 설명해 보겠습니다. Canary 업그레이드는 일부 트래픽을 먼저 새로 업그레이드된 버전으로 보내어 이상 여부를 확인한 뒤, 문제가 없으면 전체 시스템에 적용하는 방식입니다. 만약 문제가 생기면, 즉시 롤백하여 서비스의 안정성을 확보할 수 있습니다.
Canary라는 단어가 붙은 이유는 광부들이 광산 내 유해 가스(일산화탄소 등)를 탐지하기 위해 민감한 생명체인 카나리아를 먼저 내려보내서 가스가 있는지 확인했던 것처럼, Canary 배포 방식도 시스템 전체에 영향을 주기 전에 소규모 트래픽이나 일부 사용자에게만 먼저 새로운 버전을 배포해 안전성을 확인하는 것을 의미합니다.
테스트 용 환경 구축하기
apiVersion: apps/v1
kind: Deployment
metadata:
name: dp-v1
spec:
replicas: 3
selector:
matchLabels:
app: svc-v1
template:
metadata:
labels:
app: svc-v1
spec:
containers:
- name: pod-v1
image: k8s.gcr.io/echoserver:1.5
ports:
- containerPort: 8080
terminationGracePeriodSeconds: 0
---
apiVersion: v1
kind: Service
metadata:
name: svc-v1
spec:
ports:
- name: web-port
port: 9001
targetPort: 8080
selector:
app: svc-v1
업그레이드 용 설정
apiVersion: apps/v1
kind: Deployment
metadata:
name: dp-v2
spec:
replicas: 3
selector:
matchLabels:
app: svc-v2
template:
metadata:
labels:
app: svc-v2
spec:
containers:
- name: pod-v2
image: k8s.gcr.io/echoserver:1.6
ports:
- containerPort: 8080
terminationGracePeriodSeconds: 0
---
apiVersion: v1
kind: Service
metadata:
name: svc-v2
spec:
ports:
- name: web-port
port: 9001
targetPort: 8080
selector:
app: svc-v2
기존에 운영중이던 Ingress가 이렇게 구성되어있다고 합시다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-canary-v1
spec:
ingressClassName: nginx
rules:
- host: kans.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: svc-v1
port:
number: 8080
신규 v2 버전에 트래픽을 일부 보내고 싶다면 새로운 Ingress를 생성해야합니다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-canary-v2
annotations:
nginx.ingress.kubernetes.io/canary: "true" # Canary 트래픽을 설정하는 주석. 트래픽의 일부만 이 리소스로 라우팅.
nginx.ingress.kubernetes.io/canary-weight: "10" # Canary 트래픽의 비율을 설정. 10%의 트래픽을 이 Ingress로 라우팅
spec:
ingressClassName: nginx
rules:
- host: kans.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: svc-v2
port:
number: 8080
HTTPS 처리 (TLS 종료, TLS PassThorugh, SSL Redirect)
TLS 터미네이션은 클라이언트와 서버 간 암호화된 TLS 연결을 네트워크 경계 지점(예: 로드 밸런서, 프록시)에서 해제하는 방식입니다. 클라이언트에서 보낸 암호화된 요청을 해당 지점에서 복호화한 뒤, 서버로는 평문으로 전달하며, 서버 응답 시에도 다시 암호화하여 클라이언트로 전송됩니다.
Ingress Nginx에서는 TLS설정으로 TLS종료 처리를 합니다. TLS 종료와는 반대로 오히려그냥 넘어가는 설정도 있는데
이 설정의 경우 annotations에 nginx.ingress.kubernetes.io/ssl-passthrough 설정을 하면 됩니다. Nginx에서 TLS 통신을 복호화 할 수 없기 때문에 헤더를 삽입하거나 그외의 기능들을 사용할 수 없습니다.
그 외에도 http로 들어온 요청을 https로 강제로 리다이렉트도 시킬 수 있습니다. nginx.ingress.kubernetes.io/ssl-redirect: 'true' 값을 동일하게 annotations에 넣어줄 경우 http로 들어온 요청을 https로 다시 요청하게 합니다.
XFF(X-Forwarded-For)와 XFP(X-Forwarded-Proto) 헤더
이전 포스팅(2024.09.26 - [K8S/network] - Proxy Protocol: Client IP를 유지하는 방법)에서 Proxy Protocol을 통해 L4 레이어에서 클라이언트 IP를 유지하는 방법을 다뤘습니다. 그렇다면 L4가 아닌 L7 레이어에서 클라이언트 IP를 유지하려면 어떻게 해야 할까요? 이 경우, 헤더를 사용하면 가능합니다.
X-Forwarded-For 헤더는 네트워크 장비나 서버 등에서 송신지 IP 주소가 변경되는 상황에서, 원래 클라이언트의 IP 주소를 기록하는 역할을 합니다. 즉, 원본 송신지 IP를 유지하는 방법입니다. 여러 장비를 거치게 되면 X-Forwarded-For 값에는 여러 IP가 추가됩니다. 이 헤더의 값은 새로운 장비를 지날 때마다 추가되므로, 맨 첫 번째 IP가 사용자의 IP를 나타냅니다. 예를 들어, "X-Forwarded-For: 10.140.1.4, 40.1.22.9"라는 IP 정보가 들어온다면 10.140.1.4가 클라이언트의 IP입니다.
클라이언트 IP 유지 외에도, 요청 시 사용된 프로토콜 정보를 저장할 수 있습니다. 이를 위한 헤더가 X-Forwarded-Proto입니다. 이 헤더는 원래의 프로토콜 정보를 기록합니다. 예를 들어, SSL 오프로딩 환경에서 서버는 클라이언트가 처음 요청할 때 사용한 프로토콜(HTTP/HTTPS)을 이 헤더를 통해 확인할 수 있습니다.
'K8S > 🔥 network study🔥' 카테고리의 다른 글
[네떡스터디🔥kans] Istio Gateway API (0) | 2024.10.07 |
---|---|
[네떡스터디🔥kans] Gateway API (0) | 2024.10.07 |
[네떡스터디🔥kans] 쿠버네티스 서비스 이해하기 - kube-proxy IPVS 모드 (0) | 2024.09.30 |
[네떡스터디🔥kans] 쿠버네티스 서비스 이해하기 - External IP (0) | 2024.09.22 |
[네떡스터디🔥kans] 쿠버네티스 서비스 이해하기 - LoadBalancer(metallb) (0) | 2024.09.22 |