본문 바로가기
도커&쿠버네티스

[도커/쿠버네티스] 8장 인그레스

by bzerome240 2022. 2. 28.

인그레스(Ingress)

: 외부에서 서버로 유입되는 트래픽

: 외부 요청을 어떻게 처리할 것인지 네트워크 7계층 레벨에서 정의하는 쿠버네티스 오브젝트

  • 인그레스 네트워크: 인그레스 트래픽을 처리하기 위한 네트워크

 

인그레스 기본 기능

  • 외부 요청의 라우팅: 특정 경로로 들어온 요청을 어떠한 서비스로 전달할지 정의하는 라우팅 규칙 설정 가능
  • 가상 호스트 기반의 요청 처리: 같은 IP에 대해 다른 도메인 이름으로 요청이 도착했을 때 어떻게 처리할 것인지 정의
  • SSL/TLS보안 연결 처리: 여러 개의 서비스로 요청을 라우팅할 때 보안연결을 위한 인증서를 쉽게 적용 가능

 

인그레스의 요청을 처리할 서버로 뭇엇을 선택하느냐에 따라 기능이 달라진다.

 


인그레스를 사용하는 이유?

 

애플리케이션이 3개의 디플로이먼트로 생성돼있다고 가정하고, 각 디플로이먼트를 외부에 노출해야한다면?

-> 일반적으로는 NodePort 또는 LoadBalancer 타입의 서비스 3개를 생성해야한다고 생각

-> But 각 서비스마다 SSL/TLS 보안 연결, 라우팅을 구현하려면 각 서비스와 디플로이먼트에 일일이 설정해야함

-> 인그레스 오브젝트를 사용하면 URL 엔드포인트를 단 하나만 생성하여 번거로움 해결 가능

 

https://subicura.com/k8s/guide/ingress.html#ingress-%E1%84%86%E1%85%A1%E1%86%AB%E1%84%83%E1%85%B3%E1%86%AF%E1%84%80%E1%85%B5

  • 클라이언트 -> URL 요청이 들어오면 인그레스에서 규칙에 따라 처리 -> 적절한 디플로이먼트 포드로 전달
  • 라우팅 정의, 보안 연결은 디플로이먼트나 서비스가 아니라 인그레스에 의해 수행!

 

인그레스의 핵심은 외부 요청에대한 처리 규칙을 편리하게 관리 가능하다는 것

 


 

 

인그레스 생성 YAML

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: ingress-example
  annotations:                                   # [4]
    nginx.ingress.kubernetes.io/rewrite-target: /
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
  - host: alicek106.example.com                  # [1]
    http:
      paths:
      - path: /echo-hostname                     # [2]
        backend:
          serviceName: hostname-service          # [3]
          servicePort: 80
  • [1] host: 해당 도메인 이름으로 접근하는 요청에 대해서 처리 규칙을 적용한다.
    • ex) alicek106.example.com  도메인으로 접근 하는 요청만 처리
  • [2] path: 해당 경로에 들어온 요청을 어느 서비스로 전달할 것인지 정의
    • ex) /echo=hostame 경로의 요청을 backend에 정의된 서비스로 전달
  • [3] serviceName, servicePort: path로 들어온 요청이 전달될 서비스와 포트
    • ex) /echo=hostame 경로의 요청을 hostname-service 서비스의 80포트로 전달한다
  • [4] annotations (주석): 
    • nginx.ingress.kubernetes.io/rewrite-target: nginx 인그레스 컨트롤러에서만 사용 가능한 기능으로, 들어온 요청을 설정된 경로로 전달한다
      • ex) nginx 인그레스 컨트롤러로 /echo-hostname 으로 접근하면 hostname-service의 / 경로로 전달된다
      • ex) /echo-hostname/alice/bob 이라는 경로로 요청을 보내도 /로 전달된다
    • kubernetes.io/ingress.class: 인그레스 규칙을 어떤 인그레스 컨트롤러에 적용할 것인지를 의미
      • ex) 인그레스 컨트롤러로 nginx를 사용한다

 

 

인그레스 생성 후 인그레스 목록 확인하기

kubectl get ingress

 


 

But, YAML 파일로 인그레스를 생성했다해도, 단순한 규칙을 정의한 오브젝트에 불과하다.

-> Pod, ReplicaSet, Deployment, Service와 달리 별도의 컨트롤러를 설치해야 한다.

-> 인그레스 컨트롤러라는 특수 서버에 적용해야만 규칙을 사용할 수 있다.

-> 인그레스 컨트롤러의 서버는 외부 요청을 받아들이며, 인그레스 규칙을 로드해 사용한다.

 

 

인그레스 사용 방법 순서

1. 공식 깃허브에서 제공되는 YAML 파일로 Nginx 인그레스 컨트롤러 생성

2. Nginx 인그레스 컨트롤러를 외부로 노출하기 위한 서비스 생성

3. 요청 처리 규칙을 정의하는 인그레스 오브젝트 생성

4. Nginx 인그레스 컨트롤러로 들어온 요청은 인그레스 규칙에 따라 적절한 서비스로 전달

 

 

인그레스 컨트롤러의 구조

https://blog.naver.com/alice_k106/221502890249

 

인그레스 컨트롤러 서버의 종류

  • Nginx 웹서버 인그레스 컨트롤러 (쉽고 간단, 대표적으로 사용됨)
  • Kong 
  • GKE

 

Nginx 웹서버 인그레스 컨트롤러 설치

  • 쿠버네티스에서 공식적으로 개발되고 있기때문에 공식 깃허브 저장소에서 직접 내려받을 수 있다.

 

AWS NLB(Network Load Balancer) 생성

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.1/deploy/static/provider/aws/deploy.yaml
  • 다양한 리소스를 한번에 생성한다 ex) 네임스페이스, 디플로이먼트, 컨피그맵
  • ingress-nginx 네임스페이스의 포드, 디플로이먼트 확인하면 Nginx웹서버가 생성돼있다.
  • 외부에서 컨트롤러에 접근하기 위한 서비스도 생성돼있다. (AWS에서 생성하면 자동으로 로드밸런서 타입으로 생성된다.)

 

인그레스 컨트롤러 포드에 접근하기 위한 서비스 생성

https://blog.naver.com/alice_k106/221502890249

 

 

NodePort 타입의 서비스 생성 YMAL

  • 가상머신 환경
  • 각 노드의 랜덤한 포트로 Nginx 인그레스 컨트롤러에 접근 가능
apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: ingress-nginx
  name: ingress-nginx-controller-nodeport
  namespace: ingress-nginx
spec:
  ports:
  - name: http
    nodePort: 31000
    port: 80
    protocol: TCP
    targetPort: http
  - name: https
    nodePort: 32000
    port: 443
    protocol: TCP
    targetPort: https
  selector:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
  type: NodePort

 

 

여기까지

인그레스, Nginx 인그레스 컨트롤러, Nginx 포드에 접근하기 위한 서비스 준비 완료!

인그레스 요청이 들어갈 테스트용 디플로이먼트, 서비스 생성하면 테스트 준비 완료!

 


Nginx 인그레스 컨트롤러로 요청하기

 

1)

 

/echo-hostname 으로 요청 전송하기 (AWS 사용시에는 DNS 이름으로 접근)

$ curl a20~2.elb.amazonaws.com/echo-hostname

But 인그레스 생성 시 도메인이름을 다른걸로 지정했기 때문에 해당 요청은 404 뜬다. 

 

2)

AWS에서 임의의 DNS를 LoadBalancer 타입의 서비스에 할당받았다면,

이미 생성된 인그레스 리소스의 정보에서 host 항목을 직접 로드 밸런서의 DNS로 수정하기

$ kubectl edit ingress ingress-example

 

3)

다시 DNS 이름으로 접근하면 인그레스 컨트롤러가 해당 요청 처리 가능

$ curl a20~2.elb.amazonaws.com/echo-hostname

 


 

 

인그레스 컨트롤러는 항상 인그레스 리소스에 대해 Watch API를 사용한다.

Whatch는 리소스에 생성, 삭제, 수정 등의 이벤트가 발생했을 때 알려주는 쿠버네티스 기능

ex) kubectl get pods -w : 포드에 변화가 생기면 콘솔에 표시

 


Bypass

: 서비스를 거치지 않고 포드로 직접 요청을 전달하기 때문에 Nginx 인그레스 컨트롤러는 서비스에 의해 생성된 엔드포인트로 요청을 직접 전달한다.

 

 

엔드포인트 확인하기

$ kubectl get endpoints

 

 


 

nginx.ingress.kubernetes.io/rewrite-target 주석 세부 설명

  • Nginx의 캡처 그룹(요청 경로를 변수로 사용)과 함께 사용될때 유용하다
  • (.*) 라는 정규표현식을 통해 /echo-hostname/ 뒤에 오는 경로를 얻고, 이 값을 rewite-target 에서 사용
  • ex) /etcho-hostname/color/red 로 요청이 들어오면 서비스의 /color/red 로 전달된다
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: ingress-example
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2 # path의 (.*) 에서 획득한 경로로 전달합니다.
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
  - host: <여러분이 Nginx 컨트롤러에 접근하기 위한 도메인 이름을 입력합니다>
  #- host: a2cbfefcfbcfd48f8b4c15039fbb6d0a-1976179327.ap-northeast-2.elb.amazonaws.com
    http:
      paths:
      - path: /echo-hostname(/|$)(.*)          # (.*) 을 통해 경로를 얻습니다.
        backend:
          serviceName: hostname-service
          servicePort: 80

 

 

이 밖에도 Nginx 인그레스 컨트롤러에서 사용할 수 있는 주석이 많다. annotation 목록 확인하기

  • ex) app-root: 루트경로로 접근했을 때 특정 path로 리다이렉트
  • ex) ssl-redirect: SSL 리다이렉트

쿠버네티스의 장점은 뒤쪽에 있는 디플로이먼트, 서비스가 아닌
앞쪽에 있는 인그레스 컨트롤러에서 편리하게 SSL/TLS 보안 연결을 설정할 수 있다는 것

 

 

직접 서명한 루트 인증서를 통해 Nginx 인그레스 컨트롤러에 적용하는 방법 순서

 

1) 인증서와 비밀키 생성

  • /CN=<public DNS 이름>
  • tls.key 이름의 비밀키와 tls.crt 이름의 인증서가 생성된다.
$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout tls.key -out tls.crt -subj "/CN=alicek106.example.com/O=alicek106

 

2) tls타입, tls-secret 이름의 시크릿 생성

kubectl create secret tls tls-secret --key tls.key --cert tls.crt

 

3) 인그레스 설정에 TLS 옵션을 적용한 YAML

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: ingress-example
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    kubernetes.io/ingress.class: "nginx"
spec:
  tls:
  - hosts:
    - alicek106.example.com            # 여러분의 도메인 이름을 입력해야 합니다.
    secretName: tls-secret
  rules:
  - host: alicek106.example.com          # 여러분의 도메인 이름을 입력해야 합니다.
    http:
      paths:
      - path: /echo-hostname
        backend:
          serviceName: hostname-service
          servicePort: 80
  • spec.tls.hosts: 보안연결을 적용할 도메인 이름
  • spec.tls.secretName: 시크릿 이름
  • ex) alicek106.example.com 도메인으로 접근하는 요청에 대해 tls-secret 의 인증서로 보안 연결을 수립하겠다는 것을 의미

 

4) 인그레스 생성 후 https 로 요청하기

  • [-k]: 신뢰할 수 없는 인증서로 보안 연결을 하기 위함
curl https://alicek106.example.com/echo-hostname -k

* 인증서를 통해 보안 연결을 설정하면 http로 요청해도 https로 리다이텍트할 수 있다.

 


 

간단한 기능을 테스트하는 용도라면 기본 옵션 설정으로도 충분
But 실제 운영 환경에서는 여러 옵션의 커스터마이징이 필요하다

 

 

* 하나의 쿠버네티스 클러스터에서 여러개의 인그레스 컨트롤러를 사용할 수 있다.

* 인그레스 규칙을 선택적으로 적용할 수 있다.

 

 

깃허브에서 제공되는 Nginx 인그레스 컨트롤러 YAML 수정하여 사용하기

1) YAML 파일에 --ingress-class=alicek106-nginx 옵션 추가

2) 인그레스 생성 시 인그레스 컨트롤러 이름을 nginx가 아니라 alicek106-nginxfh 설정해줘야 정상 로드 가능

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: ingress-example
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    kubernetes.io/ingress.class: "alicek106-nginx"

 


 

리소스 정리하기

kubectl delete -f ./

 

 

 

 

 

728x90
반응형

댓글