Ingress 란
HTTP나 HTTPS를 통하여 클러스터 내부의 서비스를 외부로 노출시키는 것이다. 트래픽 라우팅은 ingress resource 를 통해서 제어된다.
internet
|
[Ingress]
--|--|--
[Service]
Ingress 는 다음의 일을 할 수 있다.
- Service 에 외부 URL을 제공한다.
- 트래픽을 로드밸런싱 한다.
- SSL/TLS를 terminate 한다.
- virtual hosting을 지정한다.
Ingress 는 임의로 포트나 프로토콜을 노출시키지 않는다. HTTP 및 HTTPS 이외의 서비스를 인터넷에 노출 시키면 일반적으로 Service.Type = NodePort 또는 Service.Type = LoadBalancer 유형의 서비스가 사용된다.
Ingress 와 Service 의 차이
Service 애플리케이션의 endpoint를 추상화 한 것이 Service 이다. 애플리케이션은 Pod에서 동작하고, 여러 Pod 들은 Service 로 추상화 되어 제공된다.
Ingress Service 들을 외부로 노출시킬때 Ingress 를 쓴다. 여러 Service 들은 Ingress 로 추상화 되어 제공된다.
Ingress Coltroller
Ingress 로 환경을 설정하고 실제로 일은 Ingress Controller가 수행한다. 그래서 Ingress 리소스를 사용하기 위해서는 클러스터에서 ingress controller 가 수행되고 있어야 한다. 다른 타입의 컨트롤러와 다르게 ingress controller는 kube-controller-manager의 부분으로 속해있다. ingress controller는 자동으로 시작하지는 않는다.
현재 Kubernetes에서 공식적으로 제공하는 Ingress Controller 는 다음의 플랫폼에 배포되어 있다.
- ingress-gce : Google Compute Engine 용. GCE를 이용하면 자동으로 사용됨
- ingress-nginx : 직접 설치해서 사용할 수 있는 ingress controller (https://kubernetes.github.io/ingress-nginx/)
아키텍처
아래의 순서대로 수행을 하면 다음과 같은 아키텍처가 된다.
ingress-nginx 배포
다음의 명령어로 ingress-nginx 를 사용할 수 있다.
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml
namespace "ingress-nginx" created
configmap "nginx-configuration" created
configmap "tcp-services" created
configmap "udp-services" created
serviceaccount "nginx-ingress-serviceaccount" created
clusterrole.rbac.authorization.k8s.io "nginx-ingress-clusterrole" created
role.rbac.authorization.k8s.io "nginx-ingress-role" created
rolebinding.rbac.authorization.k8s.io "nginx-ingress-role-nisa-binding" created
clusterrolebinding.rbac.authorization.k8s.io "nginx-ingress-clusterrole-nisa-binding" created
deployment.apps "nginx-ingress-controller" created
위와같이 명령을 하면 ingress-nginx 라는 namesapce가 생기고, 이 namespance에 ingress controller를 배포하게 된다.
$ kubectl get namespace
NAME STATUS AGE
default Active 62d
ingress-nginx Active 10m
kube-public Active 62d
kube-system Active 62d
그리고 ingress-nginx라는 namespace에 어떤 pod 이 동작하는지 볼 수 있다.
$ kubectl get pods -n ingress-nginx
NAME READY STATUS RESTARTS AGE
nginx-ingress-controller-6df4d8b446-6q76s 1/1 Running 0 9m
Helm 을 이용한 배포
helm 을 이용하여 ingress-nginx를 배포할 수 있다.
helm install stable/nginx-ingress --name my-nginx
ingress-nginx 노출하기
배포된 ingress-nginx를 Service로 배포한다.
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/cloud-generic.yaml
service "ingress-nginx" created
잘 배포되었는지 체크한다.
$ kubectl get service -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx LoadBalancer 10.96.229.129 129.213.74.19 80:32594/TCP,443:31073/TCP 4m
내용의 EXTERNAL-IP 로 호출을 해 보면 잘 동작함을 알 수 있다.
$ curl 129.213.74.19
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>openresty/1.15.8.1</center>
</body>
</html>
아직까지는 호출될 애플리케이션이 없어서 오류가 나온다.
TLS Secret 생성
$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginxsvc/O=nginxsvc"
Generating a 2048 bit RSA private key
........................................................+++
........................................................................................+++
writing new private key to 'tls.key'
-----
$ kubectl create secret tls tls-secret --key tls.key --cert tls.crt
secret "tls-secret" created
애플리케이션 배포
테스트로 사용할 애플리케이션을 배포한다.
애플리케이션은 nginx 를 사용하도록 한다. 아래는 이를 위한 myapp.yaml 파일이다. replicas를 3으로 두어 3개의 Pod을 생성하고 80포트로 리슨하는 애플리케이션이다. Service 는 8088 포트로 리슨하며 Pod의 80 포트로 연결이 된다.
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: myapp
labels:
app: myapp
spec:
replicas: 3
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: myapp-svc
spec:
selector:
app: myapp
ports:
- port: 8088
targetPort: 80
type: ClusterIP
myapp.yaml 을 사용하여 애플리케이션을 생성한다. Deployment 의 이름은 myapp 이며, Service의 이름은 myapp-svc 이다.
$ kubectl create -f myapp.yaml
deployment.apps "myapp" created
service "myapp-svc" created
Ingress 사용
해당 서비스는 ClusterIP 로 서비스 되고 있다.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: myapp-ing
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
tls:
- secretName: tls-secret
rules:
- http:
paths:
- backend:
serviceName: myapp-svc
servicePort: 8088
8088포트로 서비스 되고 있는 myapp-svc 를 호출하는 백엔드를 가지는 myapp-ing 라는 이름의 Ingress 서비스를 생성한다.
@ kubectl create -f myapp-ingress.yaml
ingress.extensions "myapp-ing" created
이전에 ingress-nginx 를 노출시키고 난 EXTERNAL-IP인 129.213.74.19를 통해서 호출해 본다.
$ curl http://129.213.74.19
<html>
<head><title>308 Permanent Redirect</title></head>
<body>
<center><h1>308 Permanent Redirect</h1></center>
<hr><center>openresty/1.15.8.1</center>
</body>
</html>
SSL 때문에 위와 같은 메시지가 나온다. 그래서 curl에서 옵션을 준다.
- i 옵션 : Include protocol headers in the output (H/F)
- k 옵션 : not verify the SSL certificates.
- L 옵션 : automatically folow the location header
$ curl -ikL http://129.213.74.19
HTTP/1.1 308 Permanent Redirect
Via: 1.1 10.188.53.7 (McAfee Web Gateway 7.8.2.7.0.28225)
Date: Fri, 19 Jul 2019 07:33:20 GMT
Server: openresty/1.15.8.1
Location: https://129.213.74.19/
Connection: Keep-Alive
Content-Type: text/html
Content-Length: 177
HTTP/2 200
server: openresty/1.15.8.1
date: Fri, 19 Jul 2019 07:33:21 GMT
content-type: text/html
content-length: 612
vary: Accept-Encoding
last-modified: Tue, 25 Jun 2019 12:19:45 GMT
etag: "5d121161-264"
accept-ranges: bytes
strict-transport-security: max-age=15724800; includeSubDomains
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
웹브라우저로 접속하면 다음과 같이 나온다.
동작하는 상태를 체크해 본다.
kubectl get pods --all-namespaces -l app.kubernetes.io/name=ingress-nginx --watch
추가
배포된 ingress-nginx를 사용하기 위해서 환경별로 필요한 항목이 있다.
- minikube
minikube addon enable ingress
Docker for Mac
version 18.06.0-ce 버젼부터 Docker for Mac 에서 Kubernetes가 사용 가능하다.
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/cloud-generic.yaml
- Oracle - OKE (Docker for Mac 와 동일)
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/cloud-generic.yaml
- Google - GKE (Docker for Mac 와 동일)
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/cloud-generic.yaml
- Azure (Docker for Mac 와 동일)
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/cloud-generic.yaml
- AWS AWS에서는 Elastic Load Balancer(ELB)가 Type=LoadBalancer 의 Service 뒤에 NGINX Ingress Controller 로 사용되고 있다. L4 및 L7울 사용할 수 있다.
- Layer 4 : 80 포트와 443 포트용으로 TCP 프로토콜로 리슨한다.
- Layer 7 : 80 포트와 terminate TLS용으로 HTTP 프로토콜로 리슨한다.
LayerELB를 사용하기 위해서 다음의 명령을 수행한다.
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/aws/service-l4.yaml kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/aws/patch-configmap-l4.yaml
- Bere-metal NodePort를 사용한다.
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/baremetal/service-nodeport.yaml
참고
- https://kubernetes.github.io/ingress-nginx/deploy/
- https://github.com/kubernetes/ingress-nginx/blob/master/README.md
- https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/multiple-ingress.md#multiple-ingress-controllers
- https://github.com/kubernetes/ingress-gce/blob/master/docs/faq/README.md#how-do-i-run-multiple-ingress-controllers-in-the-same-cluster
- https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/#additional-controllers
- https://docs.cloud.oracle.com/iaas/Content/ContEng/Tasks/contengsettingupingresscontroller.htm