참고
쿠버네티스 안내서
ingress는 msa에서 gateway의 역할을 대신해주는 녀석이다. 기존에 SpringCloud를 사용할 때에 비해 훨씬 간단하게 적용할 수 있는 느낌이다.
minikube ip
를 입력하여 minikube가 할당받은 내부 ip를 확인해보자
minikube addons enable ingress
minikube에 ingress를 추가하고
kubectl -n ingress-nginx get pod
명령어를 통해 실행을 확인해볼 수 있다.
minikube service ingress-nginx-controller -n ingress-nginx --url
docker를 사용한다면 다음과 같이 입력하여 ingress 요청해야할 url 확인할 수 있다.
이렇게 2개의 url이 노출되는데 첫번째로 요청해보면 된다.
그후에 나의 경우에는 http://127.0.0.1:35757/healthz
로 요청하면 다음과 같이 네트워크 값이 정상으로 반환된다.
이제 ingress 세팅은 모두 끝났다. 실제로 ingress를 사용하여 두개의 서비스를 분리하여 요청해보자
기존에 사용하던 소스를 이미지로 2개로 나누어 버전별로 요청시켜보려고 한다.
@RestController
public class HelloController {
@GetMapping("/test")
public Mono<ResponseEntity<TempDto>> test(){
return Mono.just(ResponseEntity.ok(
TempDto.builder()
.name("juno! v2")
.build()));
}
}
controller에 v2를 붙여서 수정하고 build까지 진행한다.
그후 2.0 버전으로 docker hub에 올려준다.
docker build --tag ililil9482/test:2.0 .
docker push ililil9482/test:2.0
test2-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: test2
labels:
app: test2
spec:
replicas: 1
selector:
matchLabels:
app: test2
template:
metadata:
labels:
app: test2
spec:
containers:
- name: test2
image: ililil9482/test:2.0
imagePullPolicy: Always
ports:
- containerPort: 8080
test2-service.yaml
apiVersion: v1
kind: Service
metadata:
name: test2
namespace: default
labels:
app: test2
spec:
selector:
app: test2
ports:
- protocol: TCP
port: 8080
nodePort: 30001
type: NodePort
kubectl apply -f test2-deployment.yaml
kubectl apply -f test2-service.yaml
test 2.0 버전으로 새롭게 pod를 생성하여 service까지 정의해주었다.
minikube service test2
그후에 동일하게 실행해주면
다음과 같이 확인할 수 있다.
이제 두개의 이미지 버전을 생성했으니 ingree를 사용하여 나눠보자!
test.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test
spec:
rules:
- host: v1.test.127.0.0.1.sslip.io
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: test
port:
number: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: test
labels:
app: test
spec:
replicas: 1
selector:
matchLabels:
app: test
template:
metadata:
labels:
app: test
spec:
containers:
- name: test
image: ililil9482/test:1.0
imagePullPolicy: Always
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: test
namespace: default
labels:
app: test
spec:
selector:
app: test
ports:
- protocol: TCP
port: 8080
nodePort: 30000
type: NodePort
test2.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test2
spec:
rules:
- host: v2.test.127.0.0.1.sslip.io
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: test2
port:
number: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: test2
labels:
app: test2
spec:
replicas: 1
selector:
matchLabels:
app: test2
template:
metadata:
labels:
app: test2
spec:
containers:
- name: test2
image: ililil9482/test:2.0
imagePullPolicy: Always
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: test2
namespace: default
labels:
app: test2
spec:
selector:
app: test2
ports:
- protocol: TCP
port: 8080
nodePort: 30001
type: NodePort
하나의 파일에 ingress, deployment, service 모두 정의해서 사용도 가능하다.
kubectl apply -f test.yml,test2.yml
다음과 같이 하나의 명령어로 모두 적용 가능!
모두 적용 후에 이제 ingress를 통해서 서버가 작동하는지 확인해보자.
minikube service ingress-nginx-controller -n ingress-nginx --url
명령어를 통해
다음과 같이 포트번호를 확인하고
http://v1.test.127.0.0.1.sslip.io:39273/test
http://v2.test.127.0.0.1.sslip.io:39273/test
두개의 url로 요청했을 때 각 api의 반환을 하나의 요청을 통해 host만 변경되어 사용되고 있음을 확인할 수 있다.
하지만 하나의 host 요청에서 path에 따라 다른 기능을 제공하고 싶을 수도 있다. 그럴때를 대비하여 k8s에서는 해당 기능을 제공한다.
test.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test
spec:
rules:
- http:
paths:
- path: /v1
pathType: Prefix
backend:
service:
name: test
port:
number: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: test
labels:
app: test
spec:
replicas: 1
selector:
matchLabels:
app: test
template:
metadata:
labels:
app: test
spec:
containers:
- name: test
image: ililil9482/test:1.0
imagePullPolicy: Always
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: test
namespace: default
labels:
app: test
spec:
selector:
app: test
ports:
- protocol: TCP
port: 8080
nodePort: 30000
type: NodePort
test2.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test2
spec:
rules:
- http:
paths:
- path: /v2
pathType: Prefix
backend:
service:
name: test2
port:
number: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: test2
labels:
app: test2
spec:
replicas: 1
selector:
matchLabels:
app: test2
template:
metadata:
labels:
app: test2
spec:
containers:
- name: test2
image: ililil9482/test:2.0
imagePullPolicy: Always
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: test2
namespace: default
labels:
app: test2
spec:
selector:
app: test2
ports:
- protocol: TCP
port: 8080
nodePort: 30001
type: NodePort
kubectl apply -f test.yml, test2.yml
다음과 같이 적용하면 된다.
그런데 다음과 같이 모두 에러페이지가 뜬다... 이유가 뭘까? url은 수정되었지만 실제 java 소스에서는 /v1/test라는 url이 없기 때문이다...
그래서 소스를 좀 수정하자!
@RestController
@RequestMapping("/v1")
public class HelloController {
@GetMapping("/test")
public Mono<ResponseEntity<TempDto>> test(){
return Mono.just(ResponseEntity.ok(
TempDto.builder()
.name("juno! v1")
.build()));
}
}
@RestController
@RequestMapping("/v2")
public class HelloController {
@GetMapping("/test")
public Mono<ResponseEntity<TempDto>> test(){
return Mono.just(ResponseEntity.ok(
TempDto.builder()
.name("juno! v2")
.build()));
}
}
소스는 다음과 같이 수정한 뒤
docker build --tag ililil9482/test:1.0 .
docker build --tag ililil9482/test:2.0 .
docker push ililil9482/test:1.0
docker push ililil9482/test:2.0
명령어를 통해 각각 push 해주었다.
그리고 다시
kubectl apply -f test.yml,test2.yml
명령어를 입력해주면 적용이 완료되고
minikube service ingress-nginx-controller -n ingress-nginx --url
다시 실행해주자!
이제 다음과 같이
http://127.0.0.1:33053/v1/test
http://127.0.0.1:33053/v2/test
에서 같은 host를 갖고 uri에 따라 다르게 응답할 수 있게 되었다.