Ingress에 대해 공부한 내용을 정리한 글입니다.
쿠버네티스 공식 홈페이지 - Kubernetes Ingress를 참고하여 진행하였습니다.
또한, 마스터 노드1, 워커노드 2로 실습 진행하였습니다.
🤣🤩😊CKA 자격증 준비 및 쿠버네티스 공부 정리입니다.
클러스터 내부의 오브젝트들을 외부의 클라이언트들에게 노출시켜주는 오브젝트인 ingress에 대해 다뤄보려고 합니다. ingress는 service와 어떻게 다른지, 어떤 방식으로 동작시키는지에 대해 간단히 알아보고 실습을 진행합니다.
service도 클러스터 내부의 자원(pod)에 대해 외부 클라이언트에게 ip와 port를 통한 접근을 제공한다. (L4기능)
L4단의 접근은 각 service에서 ip와 port번호를 노출시키게 됩니다.
ingress를 사용하게 되면, service 앞에 일종의 관문(Gateway)의 역할을 담당하게 되고, 특정 엔드포인트에 접근할 때 포트번호와 일치하는 service에 연결해주게 됩니다.
- Ingress는 외부에서 연결 가능한 URL을 서비스에 제공하고, 트래픽 부하를 분산하고, SSL/TLS를 종료하고, 이름 기반 가상 호스팅을 제공하도록 구성될 수 있습니다.
- Ingress는 임의의 포트나 프로토콜을 노출하지 않습니다. HTTP 및 HTTPS 이외의 서비스를 인터넷에 노출하는 경우 일반적으로
Service.Type=NodePort
또는Service.Type=LoadBalancer
유형의 서비스를 사용합니다
Ingress를 충족하려면 Ingress 컨트롤러가 있어야 합니다 . Ingress 리소스를 생성하는 것만으로는 효과가 없습니다.
Ingress는 라우팅의 내용을 명세하는 것이고, 직접적인 ingress의 동작은 ingress controller가 진행하게 됩니다.
kube-controller-manager
ingress controller는 클러스터에서 자동으로 시작되지 않습니다.따라서 추가로 provider들의 ingress controller 등을 연결하여 사용하게 됩니다.
쿠버네티스 - ingress controllers
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: minimal-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx-example
rules:
- http:
paths:
- path: /testpath
pathType: Prefix
backend:
service:
name: test
port:
number: 80
rewrite-target 주석
: annotation은 특정 리소스에 사용자가 원하는 특정행동을 하도록 만들기 위해 사용됩니다. rewrite-target은 인그레스에 정의된 경로로 들어오는 요청을 설정된 경로로 전달합니다.
위의 예시에서는 path값인 /testpath로 들어오는 모든 요청을 test이름의 service의 /로 전달하겠다는 의미입니다.
/testpath/test -> test
/testpath/test/foo -> /test/foo
/testpath -> /
ingressClassName
: ingress controller가 한 클러스터 내에서 여러개가 존재할 때, 어떤 ingress controller를 사용할 지 ingres class 리소스를 생성해서 정의할 수 있습니다. volume에서 배웠던 storageClass라고 생각하시면 되겠습니다.
spec.rules
와 spec.http
사이에 spec.host
: 어떤 hostName으로 ingress에 접근할 것인지 명세. 비어있으면 hostName이 아닌, ip와 엔드포인트로 접근하겠다는 뜻입니다.
path
: 엔드포인트를 의미합니다.
pathType
: 엔드포인트의 필터링 기준
prefix
: /를 기준으로 접두사 기준 filtering을 하게 된다. 예를 들어 /foo/bbb, /foo/bbb/, /foo/bbb/abc 모두Exact
: 정확히 path값이 일치하는 값만 통과시킨다.ImplementationSpectific
: IngressClass에서 정의한 값을 따라서 routing이 되는 방식으로, 아무 설정 안했을 때 default로 동작한다. IngressClass의 정의에 따라서 달라질 수 있다.apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: name-virtual-host-ingress
spec:
rules:
- host: foo.bar.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service1
port:
number: 80
- host: bar.foo.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service2
port:
number: 80
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: simple-fanout-example
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /foo
pathType: Prefix
backend:
service:
name: service1
port:
number: 4200
- path: /bar
pathType: Prefix
backend:
service:
name: service2
port:
number: 8080
전반적인 ingress에 대한 내용에 대해 알아보았고, 실제로 실습을 진행해보겠습니다.
현재 bare-metal의 상태이므로 loadbalancer의 경우를 사용할 수 없습니다.
MetalLB라는 온프레미스 환경에서 loadbalancer를 지원하는 서드파티도 존재하지만, 이번에는 다루지 않겠습니다.
제 클러스터 환경 구성의 경우, VM으로 쿠버네티스가 설치되어있기 때문에, bare-metal 환경에 일치합니다. 따라서 가이드에 나온 bare-metal설치법을 따르겠습니다.
설치가 완료되고, ingress-nginx-controller라는 서비스가 생성되었습니다.
위의 내용 중, fan-out ingress를 생성해보겠습니다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: simple-fanout-example
namespace: ingress-nginx
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: foo.bar.com
http:
paths:
- path: /foo
pathType: Prefix
backend:
service:
name: service1
port:
number: 80
- path: /bar
pathType: Prefix
backend:
service:
name: service2
port:
number: 80
ingressClassName
에는 nginx-ingress controller를 사용하기 때문에 nginx로 명세를 합니다.foo.bar.com의 호스트 네임의 /foo, /bar의 엔드포인트로 접근할 때 연결해줄 service도 생성하겠습니다.
ingressClassName을 nginx로 연결해주고, ingress를 생성하면, 노드에 ingress가 생성됩니다.
ingress-nginx라는 이름의 namespace의 service, deployment들입니다. nodePort형태로 서비스들을 지정해두었고, ingress로 service들을 바인딩 해주었으니,
ingress controller(80번 포트의 서비스로 연결: nodeport번호) -> 80번 포트로 접근을 받은 서비스는 노드(nodePort로 할당된 port)로 접근
curl 명령어로 foo.bar.com:(ingress controller nodePort번호)로 접근하겠습니다.
하지만, nameServer에 등록되어 있지 않기 때문에, /etc/hosts에 등록을 해주어야 합니다.. nodePort형식이기 때문에, worker node 어느 ip를 사용해도 가능합니다.
위처럼 ip에 대한 domainName을 명세하고 진행해보면..
$ curl foo.bar.com:32652 --> 접근 실패
$ curl foo.bar.com:32652/foo --> 접근 가능
이를 통해, ingress에 명세된 것처럼 엔드포인트에 접근했을 때, service로 접근이 가능해지는 것을 확인했습니다.
이번에는 두 번째 예시인, hostName 기반 ingress를 실습해보겠습니다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: name-virtual-host-ingress
namespace: ingress-nginx
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: foo.bar.com
http:
paths:
- path: /foo
pathType: Prefix
backend:
service:
name: service1
port:
number: 80
- host: bar.foo.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service2
port:
number: 80
마찬가지로, bar.foo.com의 도메인도 /etc/hosts에 등록해줍니다.
service1,2를 수정해서 다른 service로 로드밸런싱이 잘 되는지 확인할 수 있지만, 넘어가도록 하겠습니다.
방법) pod의 컨테이너로 직접 접근해서 nginx의 인덱스페이지를 수정하기
포스팅이 길어져서 ssl, tls를 사용하는 ingress를 다뤄보지 못했지만, 언제가는 꼭 진행하도록 하겠습니다.. 온프레미스의 환경에서 nginx-ingress controller를 사용해보고 ingress의 작동을 실습해보았습니다.
ingress를 통해 경로기반, 호스트기반 라우팅이 가능하였고, 단순히 nodePort를 통한 service구성보다는, ingress를 따로 구성하여 service를 관리하는 것이 보안적으로, 기능적으로 효과적이라는 것도 알 수 있었습니다.