k8s ingress 설정하기

최준호·2022년 12월 20일
0

molu

목록 보기
3/3
post-thumbnail

참고 쿠버네티스 안내서

📗 ingress 만들기

ingress는 msa에서 gateway의 역할을 대신해주는 녀석이다. 기존에 SpringCloud를 사용할 때에 비해 훨씬 간단하게 적용할 수 있는 느낌이다.

📄 minikube에 ingress 추가

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를 사용하여 두개의 서비스를 분리하여 요청해보자

📗 Spring Application 만들기

기존에 사용하던 소스를 이미지로 2개로 나누어 버전별로 요청시켜보려고 한다.

📄 Controller 수정

@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

📄 k8s yaml 작성

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를 사용하여 나눠보자!

📄 ingress 설정

✅ host 기반 라우팅

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만 변경되어 사용되고 있음을 확인할 수 있다.

✅ uri 기반 라우팅

참고 naver cloud ingress 활용

하지만 하나의 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이 없기 때문이다...

그래서 소스를 좀 수정하자!

✅ Spring 소스 수정 및 docker image push

@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에 따라 다르게 응답할 수 있게 되었다.

profile
코딩을 깔끔하게 하고 싶어하는 초보 개발자 (편하게 글을 쓰기위해 반말체를 사용하고 있습니다! 양해 부탁드려요!) 현재 KakaoVX 근무중입니다!

0개의 댓글