서론
Ingress가 무엇인지, 어떻게 사용하고 어떻게 생성하는지에 대해서 알아보자.
Ingress vs External Service
간단한 my-app파드와 파드를 연결해주는 my-app서비스를 생각해보자.
external-service는 사용자가 브라우저를 통해서 보낸 요청을 받아서 알맞은 파드로 전달해주는 역할을 한다.
사용자가 서비스에 접근하기 위해서는 클러스터에 접근하기 위한 클러스터 IP와 서비스가 열어놓은 포트 그리고 HTTP 프로토콜을 사용할 수 있다. 이러한 방식은 특정 케이스에 대해서 테스트하기 매우 빠르고 편리하다는 장점이 있다.
하지만 이는 배포 단계에서는 좋지 못하다. 배포 단계에서는 도메인 명으로 API 통신을 하는 것이 보안적 측면에서 중요하다. 이를 가능하게 해주는 쿠버네티스 컴포넌트가 바로 Ingress이다.
External-service대신에 Ingress를 사용하면 Internal-service를 사용하게 된다. 그리고 my-app 애플리케이션은 IP와 포트번호를 통해서 외부에 노출되지 않는다.
이제 브라우저를 통해서 요청을 받으면 가장 먼저 my-app-Ingress가 요청을 받게 된다. 그리고 Internal-service로 요청을 전달하고, Internal-service는 알맞은 파드로 요청을 전달한다.
External-service를 생성하는 YAML 파일
# myapp-external-service.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-external-service
spec:
selector:
app: myapp
type: LoadBalancer
ports:
- protocol: TCP
port: 8080
targetPort: 8080
nodePort: 35010
spec.type의 LoadBalancer는 service에 external IP를 부여해 External-service로 만들어 준다.
spec.ports의 nodePort는 사용자가 myapp 서비스에 접근하기 위해서 사용하는 포트를 의미한다.(35010)
서비스를 생성하기 위한 파일에 명시적으로 externalIP를 설정해줄 수도 있고, 포트번호를 세부적으로 설정해줄 수도 있다.
Ingress를 생성하는 YAML 파일
# myapp-ingress.yaml
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: myapp-ingress
spec:
rules:
- host: myapp.com
http:
paths:
- backend:
serviceName: myapp-internal-service
servicePort: 8080
service를 만드는 yaml파일과 꽤 다르다.
kind는 Ingress로 설정한다.
spec은 rules를 설정하는데, 이를 Routing rules라고 한다.
host로 설정된 도메인으로 들어오는 모든 요청은 internal-service로 전달된다.
사용자가 http://myapp.com 으로 접속을 시도하면 Internal-service로 리다이렉트된다.
그리고 myapp.com/api... 같은 세부적인 요청들은 paths 부분에서 개별적인 처리가 가능하다.
중요한 점은 spec.host 아래의 http는 유저가 브라우저에서 요청할 때의 도메인 앞에 붙는 http:// 부분을 의미하는것이 아니다. internal-service로 요청을 보내기위한 프로토콜로 http를 사용한다는 뜻이다.
Ingress와 Internal-service 설정
# myapp-internal-service.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-internal-service
spec:
selector:
app: myapp
ports:
- protocol: TCP
port: 8080
targetPort: 8080
External-service와 다르게 Loadbalancer 설정도 필요없고, nodePort 설정도 필요없다.
# myapp-ingress.yaml
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: myapp-ingress
spec:
rules:
- host: myapp.com
http:
paths:
- backend:
serviceName: myapp-internal-service
servicePort: 8080
backend의 serviceName은 internal-service의 이름과 동일하게 맞춰준다.
그리고 servicePort와 internal-service의 port를 동일하게 맞춰준다.
host에는 유효한 도메인 주소를 입력한다.
도메인 명을 사용할 entrypoint가 있는 Node의 IP주소와 연결해준다.
만약 쿠버네티스 클러스터 외부의 다른 서버의 entrypoint를 사용한다해도 동일한 방법으로 host를 연결할 수 있다.
클러스터에 Ingress를 설정하는 방법
클러스터 내부에 하나의 파드 또는 여러개의 파드 묶음으로 이루어진 Ingress Controller가 Ingress 규칙을 적용하고 실행한다.
일반적으로 Ingress를 만드는 yaml파일 내부의 kind에 적힌 Ingress는 클러스터의 Ingress 컴포넌트가 맞지만, Ingress Controller는 클러스터 내부에서 Ingress를 구현하기 위해서 추가적으로 생성된다.
Ingress Controller는 Ingress의 규칙을 수행하고 Redirection을 관리한다.
그리고 클러스터로 들어오는 요청은 모두 Ingress Controller Pod를 통해서 들어오게 되므로 Ingress Controller는 하나의 endpoint가 된다.
Ingress를 설치하고 구현하기 위해서는 많은 third-party 구현체 중 하나를 설치해야 한다.
주로 K8s Nginx Ingress Controller를 사용한다.
만약 AWS, GCP 같은 클라우드 서비스 업체에서 가상 머신을 빌려서 서버를 구축하는 경우를 생각해 보자.
서버를 구축하면 클라우드 서비스에서 자체 제공하는 LoadBalancer를 사용할 수 있다.
이런 경우 외부의 요청은 먼저 클라우드의 LoadBalancer가 받아들인다. 그리고 LoadBalancer는 노드에서 구현된 Ingress Controller Pod로 요청을 Redirect한다.
이는 요청이 전달되는 여러 흐름 중 일부일 뿐이고, 흐름은 개인이 설계하기 나름이다.
클라우드 LoadBalancer가 주는 이점은 우리가 직접 loadbalancer를 구현할 필요가 없다는 점이다.
클라우드를 통해서 네트워크 요청을 받는 경우도 있겠지만 자신만의 물리서버를 직접 구축해서 사용하는 경우를 Bare Metal Server라고 한다.
베어메탈 서버란?
최근 IT 인프라 전체를 클라우드로 이전하는 ‘클라우드 올인’ 기업들이 늘어나고 있죠.
하지만 데이터베이스와 같은 성능이나 운영환경에 민감한 부분은 선뜻 클라우드를 도입할 수 없어 일부 기업들은 물리 서버에 구축하는 ‘하이브리드 클라우드’ 전략을 취하기도 했습니다.
만약 ‘클라우드 올인’, ‘하이브리드 클라우드’ 중 어떤 방식으로 IT 인프라를 구축하는 게 적합한지 고민 중이라면, 베어메탈 서버(Bare Metal Server)를 대안으로써 고려해볼 수 있습니다.
‘베어메탈(Bare Metal)’이란 용어는 원래 하드웨어 상에 어떤 소프트웨어도 설치되어 있지 않은 상태를 뜻합니다. 즉, 베어메탈 서버는 가상화를 위한 하이퍼바이저 OS 없이 물리 서버를 그대로 제공하는 것을 말합니다. 따라서 하드웨어에 대한 직접 제어 및 OS 설정까지 가능합니다.
특히 가상화로 인한 불필요한 성능 저하가 없어 고성능을 발휘하는 데에 유리합니다. 이런 특징들을 보면 베어메탈 서비스는 결국 서버호스팅과 같지만, 베어메탈 서버는 직접 물리 서버를 구매하고 설치하는 것이 아니라 클라우드 가상 서버와 동일하게 클라우드 환경에 신속하게 배치하고 사용할 수 있다는 점에서 다릅니다.
https://library.gabia.com/contents/infrahosting/9300/
Minikube에서 Ingress 설정하기
먼저 Minikube에 Ingress Controller를 설치한다.
minikube addons enable ingress
위 명령어는 자동으로 K8s Nginx Ingress Controller를 구현해 준다.
물론 다른 써드파티 Ingress를 설치해서 사용할 수도 있다.
kubectl get pods -n ingress-nginx
제대로 설치되었다면 위와 같이 나오면 정상이다. nginx ingress controller가 실행중임을 나타낸다.
Minikube의 Dashboard를 브라우저에 띄워보자.
kubectl get all -n kubernetes-dashboard
이미 Internal-service로 kubenetes-dashboard 서비스가 생성되어 있음을 볼 수 있다. 이는 Minikube에서만 기본적으로 가지고 있는 서비스이다.
위 정보를 참고해서 Ingress 설정파일을 만들어 보자.
# dashboard-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: dashboard-ingress # Ingress 이름 설정
namespace: kubernetes-dashboard # service의 파드의 것과 동일한 namespace로 설정
spec:
rules: # Ingress 규칙
- host: dashboard.com # 도메인 명
http: # Internal-service로 향하는 요청을 http 프로토콜을 사용
paths:
- path: / # 모든 경로 요청 허용
pathType: Prefix
backend:
service:
name: kubernetes-dashboard
port:
number: 80
최소한의 Ingress 설정파일 예제이다.
참조
동영상의 파일을 그대로 따라하면 오류가 날 수 있다.
Ingress를 생성하자.
kubectl apply -f dashboard-ingress.yaml
kubectl get ingress -n kubernetes-dashboard
아직 ADDRESS가 할당되지 않은 모습이다. 시간이 약간 지나고 다시 kubectl get ingress -n kubernetes-dashboard 명령을 입력해보면 아래와 같이 ADDRESS가 할당되었음을 볼 수 있다.
ADDRESS를 클립보드에 복사하고 아래 명령어를 쳐서 host 관련 문서를 열어보자.
sudo vi /etx/hosts
127.0.0.1 ubuntu 아래에 <YOUR Ingress ADDRESS> dashboard.com 을 입력한다.
서버의 192.168.49.2 IP와 dashboard.com 도메인이 서로 매핑되었다.
curl http://dashboard.com
VM 내부에서 curl 명령을 입력하면 위와 같이 dashboard에 접속됨을 확인할 수 있다.
VM 내부에서 돌아가는 dashboard를 호스트 컴퓨터에서 보고 싶다면 아래 포스팅을 보면 된다.
개인적으로 정말 힘들게 찾아낸 방법이다ㅜ
Ingress 실제 사용 예시
myapp이라는 호스트명을 가진 서비스가 analytics라는 서비스를 제공함과 동시에 shopping이라는 서비스를 제공한다. 그리고 두 서비스는 MSA구조를 통해 서비스된다고 가정하자.
클라이언트 입장에서는 analytics 서비스를 이용하고 싶으면 /analytics 로 요청을 보내면 되고, shopping 서비스를 이용하고 싶으면 /shopping 으로 요청을 보내면 된다.
요청이 전달되는 과정의 제일 앞부분에 k8s Ingress가 존재한다.
요청의 URL에 따라 요청을 알맞은 서비스로 전달해준다.
위 그림의 yaml 파일의 spec.rules.http.paths 에서 세부적인 설정을 모두 할 수 있음을 볼 수 있다.
URL로 요청을 구분하는 것 외에, sub도메인을 설정해서 요청을 분산시키는 방법도 있다.
analytics 서비스를 이용하기 위해서는 analytics.myapp.com 으로 요청을 보내면 되고, shopping 서비스를 이용하기 위해서는 shopping.myapp.com 으로 요청을 보내면 된다.
Ingress TLS 인증서 적용
Ingress에 https를 적용하는건 매우 간단한 일이다.
기존의 spec.rules 대신에 spec.tls 라고 적어주면 된다.
그리고 tls를 적용하려면 당연히 인증서 키가 필요한데, 이는 secret 컴포넌트로 생성할 수 있다.
그리고 생성한 secret을 secretName과 연동해서 참조한다면 tls 인증을 사용해 https를 적용할 수 있다.
출처 : https://www.youtube.com/watch?v=X48VuDVv0do
번역 : 나
Chapter : K8s Ingress explained
'DevOps > Kubernetes' 카테고리의 다른 글
[Kubernetes] No Ingressclass resource with name nginx found 문제 해결하기 (Helm stable repo) (0) | 2022.03.31 |
---|---|
[kubernetes] #10 쿠버네티스 영속성 데이터와 볼륨 (0) | 2022.03.14 |
[kubernetes] VirtualBox의 Minikube Service 노출시키기 (0) | 2022.03.09 |
[kubernetes] #8 네임스페이스를 통해 컴포넌트 구성하기 (0) | 2022.03.06 |
[kubernetes] #7 Demo 프로젝트: MongoDB + MongoExpress (0) | 2022.03.03 |