목표:
1. ingress 에 대해 알아보자.
2. ingress를 통한 통신 흐름을 알아보자.
3. ingress의 각 기능들을 알아보자.
인그레스(Ingress) 소개
인그레스란?
클러스터 내부의 서비스(ClusterIP, NodePort, Loadbalancer)를 외부로 노출(HTTP/HTTPS) - Web Proxy 역할
- 7계층 HTTP/HTTPS를 이해함 - URL,Hostname, path 기반 라우팅 가능
- 추상화된 API 오브젝트로 이를 통해 클러스터 내부의 svc에 external 접근을 가능하게 함 , 특히 HTTP
- 로드밸런싱 , SSL 종료 , 카나리 업그레이드
- 하지만 ingress frozen 앞으로는 Gateway API만 개발될 예정
Ingress-Controller란?
외부에서 인그레스로 접속 시 Nginx 인그레스 컨트롤러 파드로 인입되고, 이후 애플리케이션 파드의 IP로 직접 통신
Ingress-Controller 설치 방식도 여러개?
- NodePort 사용
- MetalLB 사용
- Via the host network 사용
- Using a self-provisioned edge 사용
- External IPs 사용
Ingress-Controller 설치 방식( NodePort )
- 간편한 테스트를 위해서 NodePort 타입(externalTrafficPolicy: Local) 설정
- 노드 포트 형태로 설치
# Ingress-Nginx 컨트롤러 생성
cat <<EOT> ingress-nginx-values.yaml
controller:
service:
type: NodePort
nodePorts:
http: 30080
https: 30443
nodeSelector:
kubernetes.io/hostname: "k3s-s"
metrics:
enabled: true
serviceMonitor:
enabled: true
EOT
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
kubectl create ns ingress
helm install ingress-nginx ingress-nginx/ingress-nginx -f ingress-nginx-values.yaml --namespace ingress --version 4.11.2
# 확인
kubectl get all -n ingress
kc describe svc -n ingress ingress-nginx-controller
# externalTrafficPolicy 설정
kubectl patch svc -n ingress ingress-nginx-controller -p '{"spec":{"externalTrafficPolicy": "Local"}}'
# 기본 nginx conf 파일 확인
kc describe cm -n ingress ingress-nginx-controller
kubectl exec deploy/ingress-nginx-controller -n ingress -it -- cat /etc/nginx/nginx.conf
# 관련된 정보 확인 : 포드(Nginx 서버), 서비스, 디플로이먼트, 리플리카셋, 컨피그맵, 롤, 클러스터롤, 서비스 어카운트 등
kubectl get all,sa,cm,secret,roles -n ingress
kc describe clusterroles ingress-nginx
kubectl get pod,svc,ep -n ingress -o wide -l app.kubernetes.io/component=controller
# 버전 정보 확인
POD_NAMESPACE=ingress
POD_NAME=$(kubectl get pods -n $POD_NAMESPACE -l app.kubernetes.io/name=ingress-nginx --field-selector=status.phase=Running -o name)
kubectl exec $POD_NAME -n $POD_NAMESPACE -- /nginx-ingress-controller --version
인그레스(Ingress) 를 통한 통신 흐름
인그레스 통신흐름
1. nodeport로 인그레스 컨트롤러 배포
2. 인그레스 정책 설정: Host/Path Routing (실습의 편의를 위해서 도메인 없이 IP로 접속 설정)
- 서비스 1 생성
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
- 서비스 2 생성
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
- 서비스 2 / 디플로이 생성
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
- ingress 설정 확인
- 외부 클라이언트 통신
- 클라이언트 ( 내 노트북 공유기 IP ) 에서 호출
- 클라이언트 IP가 보존된것을 확인 ( SNAT 안됨 ) - externalTrafficPolicy: local
- svc3-admin 접속 > 기본적으로 Nginx 는 라운드로빈 부하분산 알고리즘을 사용
- Client_address 와 XFF 주소는 어떤 주소인가요?
- Client_address : ingress- controller pod IP
- XFF 주소 : SK Telecome IP가 찍힘 ( whois 118.235.6.43 ) 으로 확인 가능
IP 주소 118.235.6.43는 SK Telecom의 공인 IP 주소입니다. 이 IP 주소는 SK Telecom이 보유한 IP 대역 중 하나로, 그 사용자는 SK Telecom의 네트워크를 통해 인터넷에 연결된 기기일 수 있습니다. .
whois 명령을 통해 이 IP 주소가 SK Telecom에 할당된 범위에 속하는지를 확인한 것처럼, 이 IP는 SK Telecom의 인터넷 서비스나 그와 관련된 네트워크 장비에 사용될 가능성이 큽니다. 공인 IP는 인터넷에 직접 노출된 IP로, 사용자가 특정 인터넷 서비스 제공자를 통해 네트워크에 접속할 때 해당 네트워크의 공인 IP가 나타나게 됩니다.
따라서 이 IP 주소는 SK Telecom을 통해 인터넷에 연결된 클라이언트 혹은 서버의 IP 주소로 이해할 수 있습니다
인그레스 특징
1. Host / Path 기반의 라우팅
인그레스 룰 생성
- ingress.yaml
cat <<EOT> ingress2.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-2
spec:
ingressClassName: nginx
rules:
- host: kans.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: svc3-admin
port:
number: 8080
- host: "*.kans.com"
http:
paths:
- path: /echo
pathType: Prefix
backend:
service:
name: svc3-admin
port:
number: 8080
EOT
- 자기 도메인으로 변경
# 터미널1
watch -d 'kubectl get ingresses,svc,ep,pod -owide'
# 도메인 변경
MYDOMAIN1=<각자 자신의 닉네임의 도메인> 예시) gasida.com
MYDOMAIN1=gasida.com
sed -i "s/kans.com/$MYDOMAIN1/g" ingress2.yaml
# 생성
kubectl apply -f ingress2.yaml,svc3-pod.yaml
# 확인
kubectl get ingress
kubectl describe ingress ingress-2
kubectl describe ingress ingress-2 | sed -n "5, \$p"
Rules:
Host Path Backends
---- ---- --------
kans.com / svc3-admin:8080 ()
*.kans.com /echo svc3-admin:8080 ()
...
- 배포
# 로그 모니터링
kubetail -n ingress -l app.kubernetes.io/component=controller
# (옵션) ingress nginx 파드 vethY 에서 패킷 캡처 후 확인 해 볼 것
------------
# 자신의 PC 에서 접속 테스트
# svc3-admin 접속 > 결과 확인 : 왜 접속이 되지 않는가? HTTP 헤더에 Host 필드를 잘 확인해보자!
curl $MYIP:30080 -v
curl $MYIP:30080/echo -v
curl $MYIP:30080/echo -v
* Trying [64:ff9b::2bca:484]:30080...
* Connected to 43.202.4.132 (64:ff9b::2bca:484) port 30080
> GET /echo HTTP/1.1
> Host: 43.202.4.132:30080
> User-Agent: curl/8.7.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 404 Not Found
< Date: Thu, 10 Oct 2024 23:26:40 GMT
< Content-Type: text/html
< Content-Length: 153
< Connection: keep-alive
# mypc에서 접속을 위한 설정
## /etc/hosts 수정 : 도메인 이름으로 접속하기 위해서 변수 지정
## 윈도우 C:\Windows\System32\drivers\etc\hosts
## 맥 sudo vim /etc/hosts
MYDOMAIN1=<각자 자신의 닉네임의 도메인>
MYDOMAIN2=<test.각자 자신의 닉네임의 도메인>
MYDOMAIN1=koo.com
MYDOMAIN2=test.koo.com
echo $MYIP $MYDOMAIN1 $MYDOMAIN2
echo "$MYIP $MYDOMAIN1" | sudo tee -a /etc/hosts
echo "$MYIP $MYDOMAIN2" | sudo tee -a /etc/hosts
cat /etc/hosts | grep $MYDOMAIN1
# svc3-admin 접속 > 결과 확인
curl $MYDOMAIN1:30080 -v
curl $MYDOMAIN1:30080/admin
curl $MYDOMAIN1:30080/echo
curl $MYDOMAIN1:30080/echo/1
curl $MYDOMAIN2:30080 -v
curl $MYDOMAIN2:30080/admin
curl $MYDOMAIN2:30080/echo
curl $MYDOMAIN2:30080/echo/1
curl $MYDOMAIN2:30080/echo/1/2
## (옵션) /etc/hosts 파일 변경 없이 접속 방안
curl -H "host: $MYDOMAIN1" $MYIP:30080
- ingress host routing 되는 부분을 확인 할수 있음. test.koo.com으로 접근하는것은 ingress-controller에 404 에러로 표시됨
2. Canary + Bluegreen 배포
Blue-Green 전략은 2쌍의 서비스를 띄워 놓고 트래픽을 돌리는 전략 - 롤백이 쉽고 업데이트 소요 시간을 줄일수 있음 , 다만 서버를 2쌍을 띄워야 하는 리소스 적 문제가 있음
Canary 전략은 트래픽 제어를 통해 신서버로 조금씩 트래픽을 흘려 검증 과정을 거친 후 배포하는 전략
(⎈|default:N/A) root@k3s-s:~/canary# cat <<EOT> canary-svc1-pod.yaml
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
EOT
(⎈|default:N/A) root@k3s-s:~/canary# cat <<EOT> canary-svc2-pod.yaml
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
EOT
(⎈|default:N/A) root@k3s-s:~/canary# ls
canary-svc1-pod.yaml canary-svc2-pod.yaml
(⎈|default:N/A) root@k3s-s:~/canary# kubectl apply -f canary-svc1-pod.yaml,canary-svc2-pod.yaml
deployment.apps/dp-v1 created
service/svc-v1 created
deployment.apps/dp-v2 created
service/svc-v2 created
(⎈|default:N/A) root@k3s-s:~/canary# cat <<EOT> canary-ingress1.yaml
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
EOT
(⎈|default:N/A) root@k3s-s:~/canary# cat <<EOT> canary-ingress2.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-canary-v2
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "10"
spec:
ingressClassName: nginx
rules:
- host: kans.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: svc-v2
port:
number: 8080
EOT
(⎈|default:N/A) root@k3s-s:~/canary# MYDOMAIN1=koo.com
(⎈|default:N/A) root@k3s-s:~/canary# sed -i "s/kans.com/$MYDOMAIN1/g" canary-ingress1.yaml
sed -i "s/kans.com/$MYDOMAIN1/g" canary-ingress2.yaml
(⎈|default:N/A) root@k3s-s:~/canary#
- 배포
# 터미널1
watch -d 'kubectl get ingress,svc,ep'
# 도메인 변경
MYDOMAIN1=<각자 자신의 닉네임의 도메인> 예시) gasida.com
sed -i "s/kans.com/$MYDOMAIN1/g" canary-ingress1.yaml
sed -i "s/kans.com/$MYDOMAIN1/g" canary-ingress2.yaml
# 생성
kubectl apply -f canary-ingress1.yaml,canary-ingress2.yaml
# 로그 모니터링
kubetail -n ingress -l app.kubernetes.io/component=controller
# 접속 테스트
curl -s $MYDOMAIN1:30080
curl -s $MYDOMAIN1:30080 | grep nginx
# 접속 시 v1 v2 버전별 비율이 어떻게 되나요? 왜 이렇게 되나요?
for i in {1..100}; do curl -s $MYDOMAIN1:30080 | grep nginx ; done | sort | uniq -c | sort -nr
for i in {1..1000}; do curl -s $MYDOMAIN1:30080 | grep nginx ; done | sort | uniq -c | sort -nr
while true; do curl -s --connect-timeout 1 $MYDOMAIN1:30080 | grep Hostname ; echo "--------------" ; date "+%Y-%m-%d %H:%M:%S" ; sleep 1; done
# 비율 조정 >> 개발 배포 버전 전략에 유용하다!
kubectl annotate --overwrite ingress ingress-canary-v2 nginx.ingress.kubernetes.io/canary-weight=50
# 접속 테스트
for i in {1..100}; do curl -s $MYDOMAIN1:30080 | grep nginx ; done | sort | uniq -c | sort -nr
for i in {1..1000}; do curl -s $MYDOMAIN1:30080 | grep nginx ; done | sort | uniq -c | sort -nr
# (옵션) 비율 조정 << 어떻게 비율이 조정될까요?
kubectl annotate --overwrite ingress ingress-canary-v2 nginx.ingress.kubernetes.io/canary-weight=100
for i in {1..100}; do curl -s $MYDOMAIN1:30080 | grep nginx ; done | sort | uniq -c | sort -nr
# (옵션) 비율 조정 << 어떻게 비율이 조정될까요?
kubectl annotate --overwrite ingress ingress-canary-v2 nginx.ingress.kubernetes.io/canary-weight=0
for i in {1..100}; do curl -s $MYDOMAIN1:30080 | grep nginx ; done | sort | uniq -c | sort -nr
3. SSL Termination
cat <<EOT> ssl-termination-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: https
spec:
ingressClassName: nginx
tls:
- hosts:
- kans.com
secretName: secret-https
rules:
- host: kans.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: svc-https
port:
number: 8080
EOT
cat <<EOT> tls-ingress1.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-https
labels:
app: https
spec:
containers:
- name: container
image: k8s.gcr.io/echoserver:1.6
terminationGracePeriodSeconds: 0
---
apiVersion: v1
kind: Service
metadata:
name: svc-https
spec:
selector:
app: https
ports:
- port: 8080
EOT
# 서비스와 파드 생성
curl -s -O https://raw.githubusercontent.com/gasida/NDKS/main/7/svc-pod.yaml
kubectl apply -f svc-pod.yaml
# 도메인 변경
MYDOMAIN1=<각자 자신의 닉네임의 도메인> 예시) gasida.com
MYDOMAIN1=kans.com
echo $MYDOMAIN1
sed -i "s/kans.com/$MYDOMAIN1/g" ssl-termination-ingress.yaml
# 인그레스 생성
kubectl apply -f ssl-termination-ingress.yaml
# 인증서 생성
# openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=dkos.com/O=dkos.com"mkdir key && cd key
MYDOMAIN1=kans.com
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=$MYDOMAIN1/O=$MYDOMAIN1"
tree
# Secret 생성
kubectl create secret tls secret-https --key tls.key --cert tls.crt
# Secret 확인
kubectl get secrets secret-https
kubectl get secrets secret-https -o yaml
-------------------
# 자신의 PC 에서 접속 확인 : PC 웹브라우저
# 접속 확인 : -k 는 https 접속 시 : 접속 포트 정보 확인
curl -Lk https://$MYDOMAIN1:30443
## (옵션) /etc/hosts 파일 변경 없이 접속 방안
curl -Lk -H "host: $MYDOMAIN1" https://$MYDOMAIN1:30443
curl -Lk https://$MYDOMAIN1:30443
Hostname: pod-https
Pod Information:
-no pod information available-
Server values:
server_version=nginx: 1.13.1 - lua: 10008
Request Information:
client_address=172.16.0.5
method=GET
real path=/
query=
request_version=1.1
request_uri=http://koo.com:8080/
Request Headers:
accept=*/*
host=koo.com:30443
user-agent=curl/8.7.1
x-forwarded-for=211.234.196.67
x-forwarded-host=koo.com:30443
x-forwarded-port=443
x-forwarded-proto=https
x-forwarded-scheme=https
x-real-ip=211.234.196.67
x-request-id=920edc2da4a13f97c60d6b02953acf7a
x-scheme=https
Request Body:
-no body in request-
'컨테이너 > 쿠버네티스 네트워크' 카테고리의 다른 글
[KANS] 쿠버네티스 네트워크 (13) Service Mesh : istio (0) | 2024.10.17 |
---|---|
[KANS] 쿠버네티스 네트워크 (12) Gateway API (0) | 2024.10.12 |
[KANS] 쿠버네티스 네트워크 (10) Service : LoadBalancer (0) | 2024.10.03 |
[KANS] 쿠버네티스 네트워크 (9) Service : ClusterIP, NodePort (0) | 2024.09.23 |
[KANS] 쿠버네티스 네트워크 (8) Calico Mode / eBPF (1) | 2024.09.17 |