0부터 시작하는 AWS 공부 - EKS 활용하기 - Nginx Ingress 설치 및 활용

Jaehong Lee·2023년 4월 12일
2
post-thumbnail

Ingress에 대한 지식은 아래 링크를 참고하자

https://velog.io/@lijahong/0%EB%B6%80%ED%84%B0-%EC%8B%9C%EC%9E%91%ED%95%98%EB%8A%94-Kubernetes-%EA%B3%B5%EB%B6%80-Service-Ingress-metallb-%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90#ingress-%EB%9E%80


1. Nginx Ingress 설치

Ingress는 간단하게 말하면, 외부에서 들어온 트래픽을 Ingress에 정의한 라우팅 규칙에 따라 클러스터 내부의 Service로 라우팅 시켜주는 것이다

참고 : https://kubernetes.github.io/ingress-nginx/deploy/#network-load-balancer-nlb

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.7.0/deploy/static/provider/aws/deploy.yaml
  • Nginx Ingress Controller를 설치하자. Nginx Ingress Controller는 Cluster 상에 여러개 배치할 수 있지만, 이번에는 하나만 배치할 것이다
  • 웹 상에 올라와있는 deploy.yaml을 이용하여 배포하는 형식이다
namespace/ingress-nginx created
serviceaccount/ingress-nginx created
serviceaccount/ingress-nginx-admission created
role.rbac.authorization.k8s.io/ingress-nginx created
role.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrole.rbac.authorization.k8s.io/ingress-nginx created
clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created
rolebinding.rbac.authorization.k8s.io/ingress-nginx created
rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
configmap/ingress-nginx-controller created
service/ingress-nginx-controller created
service/ingress-nginx-controller-admission created
deployment.apps/ingress-nginx-controller created
job.batch/ingress-nginx-admission-create created
job.batch/ingress-nginx-admission-patch created
ingressclass.networking.k8s.io/nginx unchanged
validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created
  • 배포 과정을 살펴보자. ingress-nginx가 설치 및 동작하기 위한 리소스들이 같이 생성된다
  • namespace, SA, Role, RoleBinding, ClusterRole, ClusterRoleBinding, configmap, controller service, controller deploy 등 필요한 리소스가 모두 배포된다

하나의 클러스터에 여러 개의 Ingress Controller를 배포할 수 있으며, 동일한 Ingress Controller를 배포할 수 있다. 허나, 동일한 Ingress Controller를 여러개 배포할 경우, 배포되는 리소스의 Name이나 Label 같은 설정들을 모두 다르게 설정해야 한다

  • 이런 상황에서 Ingress를 배포할 때, Ingress를 참조할 Ingress Controller를 지정해야 한다. Ingress의 annotations의 kubernetes.io/ingress.class에 대한 Value를 통해 Ingress Controller를 지정한다
  • 하지만 보통 하나의 클러스터에 여러 개의 Ingress Controller를 배포하진 않고, 하나의 Ingress Controller만 사용한다
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.7.0/deploy/static/provider/aws/deploy.yaml

cat deploy.yaml
  • deploy.yaml에 대한 상세 내용은 yaml 파일을 다운 받아 확인할 수 있다
[ec2-user@ip-192-168-11-50 work]$ kubectl get svc -n ingress-nginx
NAME                                 TYPE           CLUSTER-IP      EXTERNAL-IP                                                                          PORT(S)                      AGE
ingress-nginx-controller             LoadBalancer   10.100.165.76   *******************.elb.ap-northeast-2.amazonaws.com   80:31009/TCP,443:30944/TCP   3m37s
ingress-nginx-controller-admission   ClusterIP      10.100.95.152   <none>                                                                               443/TCP                      3m37s
  • 배포를 실행하면, Nginx-ingress-controller 앞에 LoadBalancer 서비스가 배포된다
  • AmazonEKSClusterPolicy 정책을 통해 EKS에 LB 서비스가 배포되면, 자동으로 ELB가 생성되어 연결된다

  • deploy.yaml 에서 Service 내용을 살펴보면, NLB가 배포되도록 설정되있다

  • 실제 NLB가 배포된 것을 확인할 수 있다. 해당 NLB는 Internetfacing 이므로 Public Subnet 두 곳에 배치되었다

  • 해당 주소로 접속하면, 아직 ingress, svc, deployment와 같은 연결될 요소들을 배포하지 않았으므로, nginx 404 오류 메세지가 출력된다

2. ingress-nginx-controller-admission

참고 : https://stackoverflow.com/questions/68385378/ingress-nginx-controller-admission-what-does-it-do-why-is-it-there

[ec2-user@ip-192-168-11-50 work]$ kubectl get svc -n ingress-nginx
NAME                                 TYPE           CLUSTER-IP      EXTERNAL-IP                                                                          PORT(S)                      AGE
ingress-nginx-controller             LoadBalancer   10.100.165.76   *******************.elb.ap-northeast-2.amazonaws.com   80:31009/TCP,443:30944/TCP   3m37s
ingress-nginx-controller-admission   ClusterIP      10.100.95.152   <none>                                                                               443/TCP                      3m37s

우리가 외부에서 접속할 LB SVC는 ingress-nginx-controller이다. 그렇다면, ingress-nginx-controller-admission은 무엇일까?

  • ingress-nginx-controller-admission은 ingress-nginx에 포함된 검증 web-hook을 위한 서비스이다. 해당 서비스를 제거하면, web-hook 구성을 제거하지 않는 한, Ingress 객체를 생성하거나 수정할 수 없다

Ingress Controller는 동기화 루프 패턴을 사용하여 작동한다. 동기화 루프 패턴으로 인해 발생하는 문제점을 방지하기 위해, 유효성 검사 Webhook 서비스인 ingress-nginx-controller-admission을 노출한다

  • 이를 통해 수신 개체에 대한 유효성을 보장할 수 있다

Webhook

  • WEB PAGE나 WEB APP에서 발생하는 특정 이벤트를 커스컴 Callback으로 변환해주는 방법. 쉽게 말해 서버에 특정 이벤트가 발생했을 때, 클라이언트를 호출하는 방식이다
  • EndPoint에서 Event가 발생하면, 이에 대해 자동으로 다른 WEB이나 APP으로 수신하는 형태로 Reverse API, WEB Callback, HTTP PUSH API라고 불리기도 한다

3. Ingress.yaml 배포

참고 : https://velog.io/@jihwankim94/Kubernetes-Ingress-%EB%9E%80-ozmlmzf8

우리는 http://nlb.주소/hong1 ~ hong3로 접속하면, Ingress 규칙을 통해 url 경로인 hong1 ~ hong3을 확인하여, 각 경로에 맞는 서비스로 트래픽이 라우팅되게 설정할 것이다

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: hong-ingress
  namespace: hongspace # 네임스페이스 hongspace 지정
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$1
    kubernetes.io/ingress.class: "nginx" # 사용할 Ingress Controller
spec:
  rules:
  - http:
      paths:
        - path: /hong1
          pathType: Prefix
          backend:
            service:
              name: hong-svc1 # 트래픽을 라우팅할 서비스
              port:
                number: 80
        - path: /hong2
          pathType: Prefix
          backend:
            service:
              name: hong-svc2
              port:
                number: 80
        - path: /hong3
          pathType: Prefix
          backend:
            service:
              name: hong-svc3
              port:
                number: 80
  • ingress.yaml 내용은 위와 같다. 우리는 3 개의 svc와 연결한다. Namespace는 사용자의 Namespace로 지정하자
  • kubernetes.io/ingress.class는 Ingress를 참조할 Ingress Controller를 지정하는 것이다. 우리는 Nginx Ingress Controller를 사용하기에 해당 Controller를 가리키는 값인 nginx를 써야 한다
  • rewrite-target 은 접속할 디렉토리를 지정한다. / 로 되어있으면, 기본 디렉토리이기에 /usr/share/nginx/html 디렉토리를 가리킨다
  • rule은 ingress 규칙을 정의한다. 프로토콜은 http이며, path는 url 경로를 의미한다
  • Path Type은 Ingress 경로 유형으로 아래와 같은 설정이 가능하다
    • ImplementationSpecific: 경로 유형의 일치 여부는 IngressClass에 따라 달라진다. 이를 구현할 때 별도 pathType으로 처리하거나, Prefix 또는 Exact 경로 유형과 같이 동일하게 처리할 수 있다.
    • Exact: URL 경로의 대소문자를 엄격하게 지킨다
    • Prefix: URL 경로의 접두사를 /를 기준으로 분리한 값과 일치시킨다. 일치는 대소문자를 구분하고, 요소별로 경로 요소에 대해 수행한다. 모든 p가 요청 경로의 요소별 접두사가 p인 경우 요청은 p 경로에 일치한다
kubectl apply -f ingress.yaml
  • 배포하자

4. Deployment & ClusterIP 배포

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hong-deploy1
  namespace: hongspace
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hongdeploy1
  template:
    metadata:
      labels:
        app: hongdeploy1
    spec:
      containers:
      - name: hongtainer1
        image: nginx
        ports:
          - containerPort: 80
---

apiVersion: v1
kind: Service
metadata:
  namespace: hongspace
  name: hong-svc1
spec:
  ports:
  - name: hong-svc-port
    port: 80
    targetPort: 80
  selector:
    app: hongdeploy1
  • nginx 기본 이미지를 이용하여 사용자의 Namespace에 Deployment를 배포하자
  • 해당 Deployment와 연결할 ClusterIP 서비스도 배포하자
  • 단, 서비스의 이름은 위의 Ingress에서 설정한 서비스의 이름과 동일하게 해야 한다 ( hong-svc1 )
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hong-deploy2
  namespace: hongspace
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hongdeploy2
  template:
    metadata:
      labels:
        app: hongdeploy2
    spec:
      containers:
      - name: hongtainer2
        image: nginx
        ports:
          - containerPort: 80
---

apiVersion: v1
kind: Service
metadata:
  namespace: hongspace
  name: hong-svc2
spec:
  ports:
  - name: hong-svc-port2
    port: 80
    targetPort: 80
  selector:
    app: hongdeploy2
  • 다른 2 개의 Deployment도 label과 name만 바꿔주면 된다
kubectl apply -f deploy.yaml
kubectl apply -f deploy2.yaml
kubectl apply -f deploy3.yaml
  • 배포하자

5. 구축한 구조

  • 구축한 구조는 위와 같다

트래픽이 전달되는 과정은 아래와 같다

  1. 사용자가 NLB DNS 주소에 접속
  2. 트래픽이 IGW를 거쳐 NLB( == Ingress LB )에 도달
  3. Ingress LB에 트래픽이 들어오면, Ingress Controller는 Ingress에 정의한 경로 규칙을 토대로 트래픽을 적합한 SVC에 전달
  4. SVC는 트래픽을 POD에 전달

6. 결과 확인

구축한 결과를 확인하자

[ec2-user@ip-192-168-11-50 work]$ kubectl get svc -n hongspace
NAME        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
hong-svc1   ClusterIP   10.100.141.158   <none>        80/TCP    27m
hong-svc2   ClusterIP   10.100.69.89     <none>        80/TCP    23m
hong-svc3   ClusterIP   10.100.42.254    <none>        80/TCP    23m
[ec2-user@ip-192-168-11-50 work]$ kubectl get deploy -n hongspace
NAME           READY   UP-TO-DATE   AVAILABLE   AGE
hong-deploy1   3/3     3            3           27m
hong-deploy2   3/3     3            3           23m
hong-deploy3   3/3     3            3           23m
[ec2-user@ip-192-168-11-50 work]$ kubectl get ingress -n hongspace
NAME           CLASS    HOSTS   ADDRESS                                                                              PORTS   AGE
hong-ingress   <none>   *       *************.elb.ap-northeast-2.amazonaws.com   80      23m
  • ingress, svc, deploy가 잘 배포됬는지 확인하자

  • 각 url 별로 잘 접속된다

  • 설정하지 않는 url은 404가 출력된다

  • 기본 dns 주소에 대해서도 설정하지 않았기에 404가 출력된다. 해당 경로에 대해 설정하려면, path를 / 로 설정하면 된다

잘 접속된다!!!

profile
멋진 엔지니어가 될 때까지

0개의 댓글