일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 29 | 30 |
- Kafka
- Zeppelin
- 자바
- 예제
- login
- 간단
- gradle
- Redis
- Docker
- 설정
- fastcampus
- SpringBoot
- redash
- vue
- Mac
- 레디스
- 자동
- ec2
- spring
- EMR
- java
- 머신러닝
- Cluster
- hive
- 젠킨스
- Jenkins
- 로그인
- config
- aws
- 클러스터
- Today
- Total
코알못
[kubernetes] Ingress 소개 및 실습 본문
LoadBalance를 사용하면 Service External IP를 기억해야하며 하나면 괜찮지만 여러개일때 모두 기억하기 어렵다.
이때 사용하는것이 Ingress로 트래픽을 서비스로 분산하기 위한 라우팅 규칙 모음이다!
host 헤더나 path를 통해 서비스를 구분하고 트래픽 포워딩 할 수 있다.
Ingress는 규칙 집합으로 IngressController 객체의 도움이 필요하며 이는 쿠버네티스가 지원하는 Ingress Controller를 가지고 직접 구성하거나 여러 라이브러리를 사용하여 구성 해야 한다.
어렵기 때문에 클라우드에서 제공해주는 경우가 있으며 우리는 구글 클라우드를 사용하므로 Ingress 사용시 Controller를 자동 구성해주므로 따로 구현할필요가 없다.
Ingress 정의하는 방법은 아래와 같이 apiVersion, kind 를 입력하고
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name:snackbar
...
spec에 포워딩할 부분을 Host + Path 로 정의 한다.
예를 들어 order.fast-snackbar.com/order 의 경우에는 order 서비스의 80포트로 전달 된다.
spec:
rules:
- host: order.fast-snackbar.com # HOST가 일치
http:
paths:
- pathType: Prefix # Path가 /order로 시작
path: /order
backend:
service:
name: order # order 서비스의 80 포트로 포워딩
port:
number: 80
- pathType: Prefix # Path가 /order로 시작
path: /payment
backend:
service:
name: payment # order 서비스의 80 포트로 포워딩
port:
number: 80
defaultBackend: # 위에 정의 되지 않은 호스트+Path 조합의 경우 아래 서비스로 포워딩(fallback)
service:
name: order
port:
number: 80
만약 host가 아닌 path 로만 라우팅하고 싶다면 아래와 같이 host를 빼고 정의 하면 된다.
spec:
rules:
- http:
paths:
- pathType: Prefix # Path가 /order로 시작
path: /order
backend:
service:
name: order # order 서비스의 80 포트로 포워딩
port:
number: 80
- pathType: Prefix # Path가 /order로 시작
path: /payment
backend:
service:
name: payment # order 서비스의 80 포트로 포워딩
port:
number: 80
defaultBackend: # 위에 정의 되지 않은 호스트+Path 조합의 경우 아래 서비스로 포워딩(fallback)
service:
name: order
port:
number: 80
이제 실습을 통해 상세하게 알아보자!
실습전 주의 사항은 여기서 연동 되는 서비스의 경우에는 반드시 NodePort 여야만 수신 가능하다는점을 기억하도록 하자!
Host 헤더 | IP:PORT | URL Path | 결과 | 서비스 매핑 |
order.snackbar.com | IngressAddress:80 | /menus | 메뉴 조회 | order |
/order | 주문 신청 | |||
payment.snackbar.com | /receipt | 영수증 조회 | payment | |
delivery.snackbar.com | / | 시작페이지 조회 | delivery |
위에 정의된 부분 이외에는 home 서비스로 가도록 한다.
우선 order, payment, delivery 에 해당하는 Deployment, Service 를 생성하는 yaml 파일을 만든다.
# service-deployment-for-ingress.yaml
apiVersion: v1
kind: Service
metadata:
name: home
namespace: snackbar
labels:
service: home
project: snackbar
spec:
type: NodePort
selector:
service: home
project: snackbar
ports:
- port: 80
targetPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: order
namespace: snackbar
labels:
service: order
project: snackbar
spec:
type: NodePort
selector:
service: order
project: snackbar
ports:
- port: 80
targetPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: payment
namespace: snackbar
labels:
service: payment
project: snackbar
spec:
type: NodePort
selector:
service: payment
project: snackbar
ports:
- port: 80
targetPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: delivery
namespace: snackbar
labels:
service: delivery
project: snackbar
spec:
type: NodePort
selector:
service: delivery
project: snackbar
ports:
- port: 80
targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: home
namespace: snackbar
labels:
service: home
project: snackbar
spec:
replicas: 1
selector:
matchLabels:
service: home
project: snackbar
template:
metadata:
namespace: snackbar
labels:
service: home
project: snackbar
spec:
containers:
- name: home
image: yoonjeong/home:1.0
ports:
- containerPort: 8080
resources:
limits:
memory: "64Mi"
cpu: "50m"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: order
namespace: snackbar
labels:
service: order
project: snackbar
spec:
replicas: 2
selector:
matchLabels:
service: order
project: snackbar
template:
metadata:
namespace: snackbar
labels:
service: order
project: snackbar
spec:
containers:
- name: order
image: yoonjeong/order:1.0
ports:
- containerPort: 8080
resources:
limits:
memory: "64Mi"
cpu: "50m"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: payment
namespace: snackbar
labels:
service: payment
project: snackbar
spec:
replicas: 2
selector:
matchLabels:
service: payment
project: snackbar
template:
metadata:
namespace: snackbar
labels:
service: payment
project: snackbar
spec:
containers:
- name: payment
image: yoonjeong/payment:1.0
ports:
- containerPort: 8080
resources:
limits:
memory: "64Mi"
cpu: "50m"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: delivery
namespace: snackbar
labels:
service: delivery
project: snackbar
spec:
replicas: 2
selector:
matchLabels:
service: delivery
project: snackbar
template:
metadata:
namespace: snackbar
labels:
service: delivery
project: snackbar
spec:
containers:
- name: delivery
image: yoonjeong/my-app:2.0
ports:
- containerPort: 8080
resources:
limits:
memory: "64Mi"
cpu: "50m"
클러스터에 적용한다.
$ kubectl apply -f service-deployment-for-ingress.yaml
모든 오브젝트를 검색해보면 정상적으로 생성 되었다.
$ kubectl get all -l project=snackbar -n snackbar -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/delivery-68fd5c7497-8bscb 1/1 Running 0 3m54s 10.100.2.56 gke-corin-cluster-default-pool-d2d86113-zy02 <none> <none>
pod/delivery-68fd5c7497-ljhpd 1/1 Running 0 3m54s 10.100.3.72 gke-corin-cluster-default-pool-d2d86113-xq03 <none> <none>
pod/home-5858cfc489-l4gqj 1/1 Running 0 3m57s 10.100.3.69 gke-corin-cluster-default-pool-d2d86113-xq03 <none> <none>
pod/order-7c8cb88558-hxrm7 1/1 Running 0 3m56s 10.100.3.70 gke-corin-cluster-default-pool-d2d86113-xq03 <none> <none>
pod/order-7c8cb88558-tvg9z 1/1 Running 0 3m56s 10.100.2.55 gke-corin-cluster-default-pool-d2d86113-zy02 <none> <none>
pod/payment-79984d47b-d2clm 1/1 Running 0 3m55s 10.100.3.71 gke-corin-cluster-default-pool-d2d86113-xq03 <none> <none>
pod/payment-79984d47b-pnvk4 1/1 Running 0 3m55s 10.100.0.50 gke-corin-cluster-default-pool-d2d86113-w610 <none> <none>
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/delivery NodePort 10.104.3.44 <none> 80:30283/TCP 4m project=snackbar,service=delivery
service/home NodePort 10.104.15.114 <none> 80:32635/TCP 4m4s project=snackbar,service=home
service/order NodePort 10.104.13.251 <none> 80:31273/TCP 4m3s project=snackbar,service=order
service/payment NodePort 10.104.11.140 <none> 80:30783/TCP 4m2s project=snackbar,service=payment
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
deployment.apps/delivery 2/2 2 2 3m57s delivery yoonjeong/my-app:2.0 project=snackbar,service=delivery
deployment.apps/home 1/1 1 1 4m home yoonjeong/home:1.0 project=snackbar,service=home
deployment.apps/order 2/2 2 2 3m59s order yoonjeong/order:1.0 project=snackbar,service=order
deployment.apps/payment 2/2 2 2 3m58s payment yoonjeong/payment:1.0 project=snackbar,service=payment
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
replicaset.apps/delivery-68fd5c7497 2 2 2 3m58s delivery yoonjeong/my-app:2.0 pod-template-hash=68fd5c7497,project=snackbar,service=delivery
replicaset.apps/home-5858cfc489 1 1 1 4m1s home yoonjeong/home:1.0 pod-template-hash=5858cfc489,project=snackbar,service=home
replicaset.apps/order-7c8cb88558 2 2 2 4m order yoonjeong/order:1.0 pod-template-hash=7c8cb88558,project=snackbar,service=order
replicaset.apps/payment-79984d47b 2 2 2 3m59s payment yoonjeong/payment:1.0 pod-template-hash=79984d47b,project=snackbar,service=payment
이제 요청사항에 맞도록 ingress 오브젝트를 만드는 yaml 파일을 작성하며 host+path 로 라우팅 하도록 하고
정의된 요청 이외에는 home 서비스로 갈 수 있도록 defaultBackend에 정의한다.
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: snackbar
namespace: snackbar
labels:
project: snackbar
spec:
defaultBackend:
service:
name: home
port:
number: 80
rules:
- host: order.snackbar.com
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: order
port:
number: 80
- host: payment.snackbar.com
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: payment
port:
number: 80
- host: delivery.snackbar.com
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: delivery
port:
number: 80
클러스터에 적용한다.
$ kubectl apply -f ingress.yaml
ingress.networking.k8s.io/snackbar created
생성한 ingress를 보면 정상적으로 아래 host일 경우 해당 Ingress를 타도록 설정이 정상적으로 되어있다.
Address 할당까지 조금 시간이 걸리므로 기다리면서
$ kubectl get ingress snackbar -n snackbar
NAME CLASS HOSTS ADDRESS PORTS AGE
snackbar <none> order.snackbar.com,payment.snackbar.com,delivery.snackbar.com 80 84s
서비스에 대한 endpoint 를 확인하면 정상적으로 파드가 매핑 되었다.
$ kubectl get endpoints -n snackbar
NAME ENDPOINTS AGE
delivery 10.100.2.56:8080,10.100.3.72:8080 15m
home 10.100.3.69:8080 15m
order 10.100.2.55:8080,10.100.3.70:8080 15m
payment 10.100.0.50:8080,10.100.3.71:8080 15m
이제 Address 할당이 되었으며 IP 할당 완료시 해당 필드가 채워진다.
$ kubectl get ingress snackbar -n snackbar
NAME CLASS HOSTS ADDRESS PORTS AGE
snackbar <none> order.snackbar.com,payment.snackbar.com,delivery.snackbar.com 34.12.12.1 80 4m55s
이제 ingress IP 만 얻어오기 위해서 복사해서 쓸 수 있지만 코드 한줄로 얻어 오기 위해 우선 yaml 로 ingress ip를 얻어 오기 위한 구조를 파악한다.
$ kubectl get ingress snackbar -n snackbar -o yaml
...
..
status:
loadBalancer:
ingress:
- ip: 34.12.12.1
그다음 -o 옵션으로 jsonpath를 주어 위에서 확인한 구조로 ip 에 접근하면 정상적으로 ip만 얻어올 수 있다.
$ kubectl get ingress snackbar -n snackbar -o jsonpath="{.status.loadBalancer.ingress[0].ip}"
34.12.12.1
이제 해당 IP를 가져와 환경변수로 설정하고 정상적으로 설정 되었는지 확인한다.
$ export INGRESS_IP=$(kubectl get ingress snackbar -n snackbar -o jsonpath="{.status.loadBalancer.ingress[0].ip}")
$ echo $INGRESS_IP
34.12.12.1
이제 테스트를 해보자!
아래와 같이 /etc/hosts 파일에 호스트 설정을 하여 도메인으로 호출해도 되나
# /etc/hosts
34.12.12.1 order.snackbar.com
호스트 설정 없이 하는 방법은 아래와 같이 호스트 헤더를 직접 셋팅하여 보내는 방법이다!
테스트를 해보면 정상적으로 order 서비스로 호출 된것을 확인할 수 있다.
$ curl -H "Host: order.snackbar.com" --request GET $INGRESS_IP
Welcome to Snackbar!
Order what you want!
===== Host Info =====
HostIP: 10.100.2.55
HostName: order-7c8cb88558-tvg9z
메뉴를 확인하면 정상적으로 order 서비스와 통신하여 가져온다.
$ curl -H "Host: order.snackbar.com" --request GET $INGRESS_IP/menus
We have 4 snacks!
1. Pizza: 10,000
2. Burger: 5,000
3. Coke: 1,000
4. Juice: 1000
===== Host Info =====
HostIP: 10.100.2.55
HostName: order-7c8cb88558-tvg9z
주문 체크도 해보면 영수증을 정상적으로 얻어올 수 있으며
$ curl -H "Host: order.snackbar.com" --request POST $INGRESS_IP/checkout \
--header 'Content-Type: application/json' \
--data-raw '{
"Pizza": 1,
"Burger": 2,
"Coke": 0,
"Juice": 0
}'
payment 서버에서도 응답이 정상적으로 나온다.
$ curl -H "Host: payment.snackbar.com" --request POST $INGRESS_IP/receipt \
--header 'Content-Type: application/json' \
--data-raw '{
"Pizza": 1,
"Burger": 2,
"Coke": 0,
"Juice": 0
}'
{"orderedMenus":[{"name":"Pizza","count":1,"price":10000},{"name":"Burger","count":2,"price":10000},{"name":"Coke","count":0,"price":0},{"name":"Juice","count":0,"price":0}],"sumOfPrices":20000,"vat":2000,"totalPrice":22000,"host":{"ip":"10.100.0.50","name":"payment-79984d47b-pnvk4"}}
delivery 서비스도 정상적으로 호출 된다.
$ curl -H "Host: delivery.snackbar.com" --request GET $INGRESS_IP
Welcome to Version 2!
===== Host Info =====
HostIP: 10.100.3.72
HostName: delivery-68fd5c7497-ljhpd
정의되지 않은 호스트로 호출하면 정상적으로 home 서비스를 호출하는것을 확인 할 수 있다.
$ curl -H "Host: corin.snackbar.com" --request GET $INGRESS_IP
Welcome to Home!
===== Host Info =====
HostIP: 10.100.3.69
HostName: home-5858cfc489-l4gqj
기존 Ingress 만 제거하여 두번째 실습을 하도록 하자!
$ kubectl delete ingress snackbar -n snackbar
ingress.networking.k8s.io "snackbar" deleted
두번째 실습은 Host+Path 가 아닌 Path 로만 설정하여 라우팅 하도록 해보자!
정의되지 않은 path 로 호출할 경우 home 서비스로
/order 일 경우 order 서비스로
/payment 일 경우 payment 서비스로 이동하도록 아래와 같이 ingress 파일을 작성하며
# ingress-v2.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: snackbar
namespace: snackbar
labels:
project: snackbar
spec:
defaultBackend:
service:
name: home
port:
number: 80
rules:
- http:
paths:
- pathType: Prefix
path: /order
backend:
service:
name: order
port:
number: 80
- pathType: Prefix
path: /payment
backend:
service:
name: payment
port:
number: 80
클러스터에 적용한다.
$ kubectl apply -f ingress-v2.yaml
ingress.networking.k8s.io/snackbar created
호스트 설정 하지 않았으므로 모든 호스트에 대해 해당 ingress가 받아주겠다는 의미이며 아직 IP 할당되지 않았다.
$ kubectl get ingress snackbar -n snackbar
NAME CLASS HOSTS ADDRESS PORTS AGE
snackbar <none> * 80 43s
기다리면 ADDRESS에 할당된 IP가 나온다.
$ kubectl get ingress snackbar -n snackbar
NAME CLASS HOSTS ADDRESS PORTS AGE
snackbar <none> * 34.12.12.1 80 27m
환경 설정에 ingress ip 를 셋팅하고 정상적으로 나오는지 확인한다.
$ export INGRESS_IP=34.12.12.1
$ echo $INGRESS_IP
34.12.12.1
이제 order 서버에 호출 하기 위해서 path 는 /order 까지 적어주며 그 뒤에 path 인 /menus 로 호출하면 정상적으로 데이터가 나온다.
host 설정이 아닌 path 이므로 /order 까지 적어준뒤 내부 통신할 주소를 적어 줘야 하므로 기존 테스트와 url을 다르게 호출해야 한다.
$ curl --request GET $INGRESS_IP/order/menus
We have 4 snacks!
1. Pizza: 10,000
2. Burger: 5,000
3. Coke: 1,000
4. Juice: 1000
===== Host Info =====
HostIP: 10.100.2.55
HostName: order-7c8cb88558-tvg9z
checkout 도 마찬가지로 앞에 /order 를 붙여야 order 서비스로 호출하며
$ curl --request POST $INGRESS_IP/order/checkout \
--header 'Content-Type: application/json' \
--data-raw '{
"Pizza": 1,
"Burger": 2,
"Coke": 0,
"Juice": 0
}'
Received from http://payment/receipt
Server is running on
- HostName: payment-79984d47b-pnvk4
- HostIP: 10.100.0.50
=== Here is Your Receipt! ===
[영수증]
주문한 메뉴
--------------------------
Pizza - 10000원
Burger - 10000원
Coke - 0원
Juice - 0원
--------------------------
주문금액 20000
부가세(10%) 2000
합계 22000
payment 서비스로 호출 하기 위해 /payment 를 붙여준다.
$ curl --request POST $INGRESS_IP/payment/receipt \
--header 'Content-Type: application/json' \
--data-raw '{
"Pizza": 1,
"Burger": 2,
"Coke": 0,
"Juice": 0
}'
{"orderedMenus":[{"name":"Pizza","count":1,"price":10000},{"name":"Burger","count":2,"price":10000},{"name":"Coke","count":0,"price":0},{"name":"Juice","count":0,"price":0}],"sumOfPrices":20000,"vat":2000,"totalPrice":22000,"host":{"ip":"10.100.3.71","name":"payment-79984d47b-d2clm"}}
마지막으로 정의되지 않은 path 로 호출해보면 정상적으로 home 서비스와 통신하는것을 확인 할 수 있다.
$ curl $INGRESS_IP
Welcome to Home!
===== Host Info =====
HostIP: 10.100.3.69
HostName: home-5858cfc489-l4gqj
이제 실습을 마무리하며 모두 제거한다.
$ kubectl delete all -l project=snackbar -n snackbar
pod "delivery-68fd5c7497-8bscb" deleted
pod "delivery-68fd5c7497-ljhpd" deleted
pod "home-5858cfc489-l4gqj" deleted
pod "order-7c8cb88558-hxrm7" deleted
pod "order-7c8cb88558-tvg9z" deleted
pod "payment-79984d47b-d2clm" deleted
pod "payment-79984d47b-pnvk4" deleted
service "delivery" deleted
service "home" deleted
service "order" deleted
service "payment" deleted
deployment.apps "delivery" deleted
deployment.apps "home" deleted
deployment.apps "order" deleted
deployment.apps "payment" deleted
끝!
'ETC' 카테고리의 다른 글
[kubernetes] MapConfig 소개 및 실습 (0) | 2023.06.04 |
---|---|
[kubernetes] Probe(liveness,readiness) 소개 및 실습 (0) | 2023.06.03 |
[kubernetes] Service - LoadBalancer로 Pod 노출 실습 (1) | 2023.05.28 |
[kubernetes] Service - NodePort로 Pod 노출 실습 (0) | 2023.05.28 |
[kubernetes] Service 소개 및 ClusterIP로 Pod 노출 실습 (1) | 2023.05.27 |