티스토리 뷰
안녕하세요. Kubernetes Advanced Networking Study(=KANS) 3기 모임에서 스터디한 내용을 정리했습니다. 해당 글에서는 k8s중 Ingress에 대해 자세히 알아보겠습니다.
실습 환경 구성
- VPC 1개(퍼블릭 서브넷 2개), EC2 인스턴스 4대 (Ubuntu 22.04 LTS, t3.medium - vCPU 2 , Mem 4)
# YAML 파일 다운로드
curl -O https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/kans/kans-6w.yaml
# CloudFormation 스택 배포
# aws cloudformation deploy --template-file kans-1w.yaml --stack-name mylab --parameter-overrides KeyName=<My SSH Keyname> SgIngressSshCidr=<My Home Public IP Address>/32 --region ap-northeast-2
예시) aws cloudformation deploy --template-file kans-6w.yaml --stack-name mylab --parameter-overrides KeyName=kp-hayley SgIngressSshCidr=$(curl -s ipinfo.io/ip)/32 --region ap-northeast-2
## Tip. 인스턴스 타입 변경 : MyInstanceType=t3.xlarge (vCPU 4, Mem 16)
예시) aws cloudformation deploy --template-file kans-6w.yaml --stack-name mylab --parameter-overrides MyInstanceType=t3.xlarge KeyName=kp-hayley SgIngressSshCidr=$(curl -s ipinfo.io/ip)/32 --region ap-northeast-2
# CloudFormation 스택 배포 완료 후 작업용 EC2 IP 출력
aws cloudformation describe-stacks --stack-name mylab --query 'Stacks[*].Outputs[0].OutputValue' --output text --region ap-northeast-2
# [모니터링] CloudFormation 스택 상태 : 생성 완료 확인
while true; do
date
AWS_PAGER="" aws cloudformation list-stacks \
--stack-status-filter CREATE_IN_PROGRESS CREATE_COMPLETE CREATE_FAILED DELETE_IN_PROGRESS DELETE_FAILED \
--query "StackSummaries[*].{StackName:StackName, StackStatus:StackStatus}" \
--output table
sleep 1
done
# EC2 SSH 접속 : 바로 접속하지 말고, 3~5분 정도 후에 접속 할 것
ssh -i ~/.ssh/kp-hayley.pem ubuntu@$(aws cloudformation describe-stacks --stack-name mylab --query 'Stacks[*].Outputs[0].OutputValue' --output text --region ap-northeast-2)
...
(⎈|default:N/A) root@k3s-s:~# <- kubeps 가 나오지 않을 경우 ssh logout 후 다시 ssh 접속 할 것!
k3s : Lightweight Kubernetes. Easy to install, half the memory, all in a binary of less than 100 MB - Docs
- rancher 회사에서 IoT 및 edge computing 디바이스 위에서도 동작할 수 있도록 만들어진 경량 k8s
- 설치가 쉽다, 가볍다(etcd, cloud manager 등 무거운 컴포넌트 제거)
k3s 기본 정보 확인
- k8s v1.30.x → 현재 ingress-nginx controller 이 1.30.x 까지 버전 호환 테스트 완료 임 (‘24.10.6 일 기준)
# Install k3s-server
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC=" --disable=traefik" sh -s - server --token kanstoken --cluster-cidr "172.16.0.0/16" --service-cidr "10.10.200.0/24" --write-kubeconfig-mode 644
# Install k3s-agent
curl -sfL https://get.k3s.io | K3S_URL=https://192.168.10.10:6443 K3S_TOKEN=kanstoken sh -s -
# 노드 확인
kubectl get node -owide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
k3s-s Ready control-plane,master 23m v1.30.5+k3s1 192.168.10.10 <none> Ubuntu 22.04.5 LTS 6.8.0-1015-aws containerd://1.7.21-k3s2
k3s-w1 Ready <none> 23m v1.30.5+k3s1 192.168.10.101 <none> Ubuntu 22.04.5 LTS 6.8.0-1015-aws containerd://1.7.21-k3s2
k3s-w2 Ready <none> 23m v1.30.5+k3s1 192.168.10.102 <none> Ubuntu 22.04.5 LTS 6.8.0-1015-aws containerd://1.7.21-k3s2
k3s-w3 Ready <none> 23m v1.30.5+k3s1 192.168.10.103 <none> Ubuntu 22.04.5 LTS 6.8.0-1015-aws containerd://1.7.21-k3s2
# kubecolor alias 로 kc 설정 되어 있음
kc describe node k3s-s # Taints 없음
kc describe node k3s-w1
# 파드 확인
kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-7b98449c4-jmhgk 1/1 Running 0 21m
local-path-provisioner-6795b5f9d8-w6h8s 1/1 Running 0 21m
metrics-server-cdcc87586-m4ndt 1/1 Running 0 21m
#
kubectl top node
kubectl top pod -A --sort-by='cpu'
kubectl top pod -A --sort-by='memory'
kubectl get storageclass
# config 정보(위치) 확인
kubectl get pod -v=6
I1006 13:04:02.858105 4325 loader.go:395] Config loaded from file: /etc/rancher/k3s/k3s.yaml
I1006 13:04:02.872677 4325 round_trippers.go:553] GET https://127.0.0.1:6443/api/v1/namespaces/default/pods?limit=500 200 OK in 5 milliseconds
No resources found in default namespace.
cat /etc/rancher/k3s/k3s.yaml
export | grep KUBECONFIG
# 네트워크 정보 확인 : flannel CNI(vxlan mode), podCIDR
ip -c addr
ip -c route
cat /run/flannel/subnet.env
kubectl get nodes -o jsonpath='{.items[*].spec.podCIDR}' ;echo
kubectl describe node | grep -A3 Annotations
brctl show
# 서비스와 엔드포인트 확인
kubectl get svc,ep -A
# iptables 정보 확인
iptables -t filter -S
iptables -t nat -S
iptables -t mangle -S
# tcp listen 포트 정보 확인
ss -tnlp
Ingress
클러스터 내부의 서비스(ClusterIP, NodePort, Loadbalancer)를 외부로 노출(HTTP/HTTPS) - Web Proxy 역할
- Ingress is frozen. New features are being added to the Gateway API.
Nginx 인그레스 컨트롤러 설치
- Ingress : 클러스터 내부의 HTTP/HTTPS 서비스를 외부로 노출(expose) - 링크
- Ingress Controller : 인그레스의 실제 동작 구현은 인그레스 컨트롤러(Nginx, Kong 등)가 처리 - 링크
- Ingress NGINX Controller for Kubernetes - Home , Github
Ingress-Nginx 컨트롤러 생성
# 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) 실습 및 통신 흐름 확인
- 컨트롤플레인 노드에 인그레스 컨트롤러(Nginx) 파드를 생성, NodePort 로 외부에 노출
- 인그레스 정책 설정 : Host/Path routing, 실습의 편리를 위해서 도메인 없이 IP로 접속 설정 가능
sv1-pod.yaml
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
svc2-pod.yaml
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
svc3-pod.yaml
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
디플로이먼트와 서비스 생성 후 확인
# 모니터링
watch -d 'kubectl get ingress,svc,ep,pod -owide'
# 생성
kubectl taint nodes k3s-s role=controlplane:NoSchedule
curl -s -O https://raw.githubusercontent.com/gasida/NDKS/main/7/svc1-pod.yaml
curl -s -O https://raw.githubusercontent.com/gasida/NDKS/main/7/svc2-pod.yaml
curl -s -O https://raw.githubusercontent.com/gasida/NDKS/main/7/svc3-pod.yaml
kubectl apply -f svc1-pod.yaml,svc2-pod.yaml,svc3-pod.yaml
# 확인 : svc1, svc3 은 ClusterIP 로 클러스터 외부에서는 접속할 수 없다 >> Ingress 는 연결 가능!
kubectl get pod,svc,ep
인그레스(정책) 생성
ingress1.yaml
cat <<EOT> ingress1.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-1
annotations:
#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
EOT
인그레스 생성 및 확인
# 모니터링
watch -d 'kubectl get ingress,svc,ep,pod -owide'
# 생성
kubectl apply -f ingress1.yaml
# 확인
kubectl get ingress
kc describe ingress ingress-1
...
Rules:
Host Path Backends
---- ---- --------
*
/ svc1-web:80 ()
/guest svc2-guest:8080 ()
/admin svc3-admin:8080 ()
...
# 설정이 반영된 nginx conf 파일 확인
kubectl exec deploy/ingress-nginx-controller -n ingress -it -- cat /etc/nginx/nginx.conf
kubectl exec deploy/ingress-nginx-controller -n ingress -it -- cat /etc/nginx/nginx.conf | grep 'location /' -A5
location /guest/ {
set $namespace "default";
set $ingress_name "ingress-1";
set $service_name "svc2-guest";
set $service_port "8080";
--
location /admin/ {
set $namespace "default";
set $ingress_name "ingress-1";
set $service_name "svc3-admin";
set $service_port "8080";
--
location / {
set $namespace "default";
set $ingress_name "ingress-1";
set $service_name "svc1-web";
set $service_port "80";
--
...
인그레스를 통한 내부 접속
Nginx 인그레스 컨트롤러를 통한 접속(HTTP 인입) 경로 : 인그레스 컨트롤러 파드에서 서비스 파드의 IP로 직접 연결
인그레스(Nginx 인그레스 컨트롤러)를 통한 접속(HTTP 인입) 확인
- HTTP 부하분산 & PATH 기반 라우팅, 애플리케이션 파드에 연결된 서비스는 Bypass
#
kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress-1 nginx * 10.10.200.24 80 3m44s
kubectl describe ingress ingress-1 | sed -n "5, \$p"
Rules:
Host Path Backends
---- ---- --------
* / svc1-web:80 ()
/guest svc2-guest:8080 ()
/admin svc3-admin:8080 ()
# 접속 로그 확인 : kubetail 설치되어 있음 - 출력되는 nginx 의 로그의 IP 확인
kubetail -n ingress -l app.kubernetes.io/component=controller
-------------------------------
# 자신의 집 PC에서 인그레스를 통한 접속 : 각각
echo -e "Ingress1 sv1-web URL = http://$(curl -s ipinfo.io/ip):30080"
echo -e "Ingress1 sv2-guest URL = http://$(curl -s ipinfo.io/ip):30080/guest"
echo -e "Ingress1 sv3-admin URL = http://$(curl -s ipinfo.io/ip):30080/admin"
# svc1-web 접속
MYIP=<EC2 공인 IP>
MYIP=13.124.93.150
curl -s $MYIP:30080
# svvc2-guest 접속
curl -s $MYIP:30080/guest
curl -s $MYIP:30080/guest
for i in {1..100}; do curl -s $MYIP:30080/guest ; done | sort | uniq -c | sort -nr
# svc3-admin 접속 > 기본적으로 Nginx 는 라운드로빈 부하분산 알고리즘을 사용 >> Client_address 와 XFF 주소는 어떤 주소인가요?
curl -s $MYIP:30080/admin
curl -s $MYIP:30080/admin | egrep '(client_address|x-forwarded-for)'
for i in {1..100}; do curl -s $MYIP:30080/admin | grep Hostname ; done | sort | uniq -c | sort -nr
# (옵션) 디플로이먼트의 파드 갯수를 증가/감소 설정 후 접속 테스트 해보자
* X-Forwarded-For 헤더 : X-Forwarded-For 헤더는 송신지 IP 주소가 변환되는 환경(장비, 서버, 솔루션 등)에서, 변환 전 송신지(클라이언트) IP 주소를 저장하는 헤더
* X-Forwarded-Proto 헤더 : X-Forwarded-Proto 헤더는 변환 전 프로토콜을 저장
노드에서 아래 패킷 캡처 확인 : flannel vxlan, 파드 간 통신 시 IP 정보 확인
#
ngrep -tW byline -d ens5 '' udp port 8472 or tcp port 80
#
tcpdump -i ens5 udp port 8472 -nn
# vethY는 각자 k3s-s 의 가장 마지막 veth 를 지정
tcpdump -i vethY tcp port 80 or tcp port 443 -nn
tcpdump -i vethY tcp port 8080 -w /tmp/ingress-nginx.pcap
# 자신의 PC에서 k3s-s EC2 공인 IP로 pcap 다운로드
scp ubuntu@<k3s-s EC2 공인 IP>:/tmp/ingress-nginx.pcap ~/Downloads
scp ubuntu@43.202.1.177:/tmp/ingress-nginx.pcap ~/Downloads
Nginx 파드가 endpoint 정보 등을 모니터링 가능한 이유
- ClusterRole과 Role(엔드포인트 list, watch)를 바인딩된 서비스 어카운트를 파드가 사용
# (옵션) Nginx 파드가 endpoint 정보 등을 모니터링 가능한 이유 : 클러스터롤과 롤(엔드포인트 list, watch)를 바인딩된 서비스 어카운트를 파드가 사용!
kubectl describe clusterrole ingress -n ingress | egrep '(Verbs|endpoints)'
[root@k8s-m:~/yaml (ctx-k8s:default)]# kubectl describe clusterrole ingress-nginx -n ingress-nginx | egrep '(Verbs|endpoints)'
Resources Non-Resource URLs Resource Names Verbs
endpoints [] [] [list watch]
kubectl describe roles ingress-nginx -n ingress | egrep '(Verbs|endpoints)'
[root@k8s-m:~/yaml (ctx-k8s:default)]# kubectl describe roles ingress-nginx -n ingress-nginx | egrep '(Verbs|endpoints)'
Resources Non-Resource URLs Resource Names Verbs
endpoints [] [] [get list watch]
(참고) AWS Ingress (ALB) 모드
- IP 모드 : nginx ingress controller 동작과 유사하게 AWS LoadBalancer Controller 파드가 kube api 를 통해서 파드의 IP를 제공받아서 AWS ALB 에 타켓(파드 IP)를 설정
참고자료
K8S Docs - Ingress , GatewayAPI , Setup-Nginx_Ingress
'IT > Container&k8s' 카테고리의 다른 글
K8S Service Mesh Istio (6) | 2024.10.20 |
---|---|
K8s Gateway API (0) | 2024.10.13 |
K8S IPVS Proxy 모드 (3) | 2024.10.05 |
K8S Service : LoadBalancer(MetalLB) (2) | 2024.10.05 |
K8S Service : NodePort (1) | 2024.09.29 |
- Total
- Today
- Yesterday
- k8s calico
- AWS
- 혼공챌린지
- OS
- PYTHON
- IaC
- handson
- SDWAN
- S3
- cloud
- 파이썬
- 혼공단
- 국제 개발 협력
- 도서
- VPN
- k8s
- cni
- gcp serverless
- operator
- NW
- security
- 혼공파
- terraform
- NFT
- EKS
- AI
- controltower
- GKE
- k8s cni
- GCP
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |