해당 내용은 책 <컨테이너 인프라 환경 구축을 위한 쿠버네티스/도커>에 나오는 내용이며 이는 개인적으로 공부하기 위해서 게시하는 글임을 알립니다.



피곤한데 커피 한잔만 마시고 시작해보자..











사용 목적별로 연결하는 인그레스


노드포트 서비스는 포트를 중복 사용할 수 없어서 1개의 노드포트에 1개의 디플로이먼트만 적용된다. 여러 개의 디플로이먼트가 있을 때 그 수만큼 노드포트 서비스를 구동하기 위해서는 인그레스를 사용한다. 인그레스(Ingress)는 고유한 주소를 제공해 사용 목적에 따라 다른 응답을 제공할 수 있고 트래픽에 대한 L4/L7 로드밸런서와 보안 인증서를 처리하는 기능을 제공한다.


인그레스를 사용하려면 인그레스 컨트롤러가 필요하다. 다양한 인그레스 컨트롤러가 있지만, 여기서는 쿠버네티스에서 프로젝트로 지원하는 NGINX 인그레스 컨트롤러(NGINX Ingress controller)로 구성해 본다. 여기서는 NGINX 인그레스 컨트롤러가 다음 단계로 동작한다.


사용자는 노드마다 설정된 노드포트를 통해 노드포트 서비스로 접속한다
NGINX 인그레스 컨트롤러는 사용자의 접속 경로에 따라 적합한 클러스터 IP 서비스로 경로를 제공한다
클러스터 IP 서비스는 사용자를 해당 파드로 연결해 준다


인그레스 컨트롤러는 파드와 직접 통신할 수 없어서 노드포트 또는 로드밸런서 서비스와 연동되어야 한다. 그래서 노드포트로 이를 연동했다.


인그레스 컨트롤러의 궁극적인 목적은 사용자가 접속하는 경로에 따라 다른 결괏값을 제공하는 것이다.


  1. 테스트용으로 디플로이먼트 2개(in-hname-pod, in-ip-pod))를 배포한다.


kubectl create deployment in-hname-pod --image=sysnet4admin/echo-hname
kubectl create deployment in-ip-pod --image=sysnet4admin/echo-ip



  1. 배포된 노드의 상태를 확인한다.



  1. NGINX 인그레스 컨트롤러를 설치한다. 여기에는 많은 종류의 오브젝트 스펙이 포함된다. 설치되는 요소들은 NGINX 인그레스 컨트롤러 서비스를 제공하기 위해 미리 지정돼 있다.


kubectl apply -f ~/_Book_k8sInfra/ch3/3.3.2/ingress-nginx.yaml



  1. NGINX 인그레스 컨트롤러의 파드가 배포됐는지 확인한다. NGINX 인그레스 컨트롤러는 default 네임스페이스가 아닌 ingress-nginx 네임스페이스에 속하므로 -n ingress-nginx 옵션을 추가해야 한다. 여기서 -nnamespace의 약어로, default 외의 네임스페이스를 확인할 때 사용하는 옵션이다. 파드뿐만 아니라 서비스를 확인할 때도 동일한 옵션을 준다.
kubectl get pods -n ingress-nginx



인그레스를 위한 설정 파일은 다음과 같다. 이 파일은 들어오는 주소 값과 포트에 따라 노출된 서비스를 연결하는 역할을 설정한다. 외부에서 주소 값과 노드포트를 가지고 들어오는 것은 hname-svc-default 서비스와 연결된 파드로 넘기고, 외부에서 들어오는 주소 값, 노드포트와 함께 뒤에 /ip를 추가한 주소 값은 ip-svc 서비스와 연결된 파드로 접속하게 설정했다.

먼저 ingress-config.yaml를 살펴보자


ingress-config.yaml

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: ingress-nginx
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
    - http:
        paths:
          - path:
            backend:
              serviceName: hname-svc-default
              servicePort: 80
          - path: /ip
            backend:
              serviceName: ip-svc
              servicePort: 80
          - path: /your-directory
            backend:
              serviceName: your-svc
              servicePort: 80


하나 하나 알아가보자

ingress-config.yaml

#사용할 api 버젼을 명시한다.
apiVersion: networking.k8s.io/v1beta1

#어떤 종류의 오브젝트를 생성하고자 하는지 명시한다.
kind: Ingress

#이름 문자열, UID, 그리고 선택적인 네임스페이스를 포함하여
#오브젝트를 유일하게 구분지어 줄 데이터이다.
#서비스 이름(name)은 ingress-nginx이다.
metadata:
  name: ingress-nginx

  #쿠버네티스 어노테이션을 사용하여 임의의 비-식별 메타데이터를 오브젝트에 첨부할 수 있다.
  #도구 및 라이브러리와 같은 클라이언트는 이 메타데이터를 검색할 수 있다.
  annotations:
    #nginx.ingress.kubernetes.io을 Prefix로 하는 Annotation은 Nginx를 위한 것이다
    #이 Prefix는 Nginx의 YAML 파일에서 확인할 수 있는 실행 옵션에 설정되어 있다.
    #이는 곧 Ingress의 규칙 또는 설정을 적용할 Nginx Ingress Controller를 선택적으로
    #사용할 수 있다는 것을 의미한다.
    #nginx.ingress.kubernetes.io/rewrite-target는 트래픽을 리디렉션해야 하는 대상 URI이다. 즉
    #rule의 path에 지정된 경로를 해당 주석에 설정된 경로로 Redirect 한다. 여기선 /로 Redirect한다.
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  #규칙 지정
  rules:
    #http에 대한 프로토콜 및 포트 지정이다
    - http:
        paths:
          #기본 경로 규칙이다.
          #외부에서 주소 값과 노드포트를 가지고 들어오는 것은
          #hname-svc-default 서비스와 연결된 파드로 넘긴다.
          - path:

            backend:
              #나중에 expose 명령으로 디플로이먼트 (in-hname-pod)를 서비스로 노출할 것이다.
              #expose할 때 이름이 hname-svc-default를 가지게 한다.
              #연결되는 서비스와 포트를 명시
              serviceName: hname-svc-default
              servicePort: 80

            #기본 경로에 ip라는 이름의 경로 추가
            #외부에서 주소 값과 노트포트와 함께 뒤에 /ip를 추가한 주소 값은
            #ip-svc 서비스와 연결된 파드로 접속하게 설정했다.
          - path: /ip

            backend:
              #나중에 expose 명령으로 디플로이먼트 (in-hname-pod)를 서비스로 노출할 것이다.
              #expose할 때 이름이 ip-svc를 가지게 한다.
              #연결되는 서비스와 포트를 명시
              serviceName: ip-svc
              servicePort: 80

            #기본 경로에 your-directory 경로 추가
          - path: /your-directory

            #연결되는 서비스와 포트
            backend:
              serviceName: your-svc
              servicePort: 80

[사진 참고]


제대로 생성되었는지 확인하기 위해서는 -n 옵션을 사용해야 한다. 네임스페이스가 다르기 때문이다.

kubectl get pods -n ingress-nginx



  1. 설정을 적용한다.
kubectl apply -f ~/_Book_k8sInfra/ch3/3.3.2/ingress-config.yaml



  1. 인그레스 설정 파일이 제대로 등록됐는지 확인한다.


kubectl get ingress



  1. **kubectl get ingress -o yaml을 실행해 인그레스에 요청한 내용이 확실하게 적용됐는지 확인한다. 이 명령은 인그레스에 적용된 내용을 야믈 형식으로 출력해 적용된 내용을 확인할 수 있다. 우리가 적용한 내용 외에 시스템에서 자동으로 생성하는 것까지 모두 확인할 수 있으므로 이 명령을 응용하면 오브젝트 스펙 파일을 만드는 데 도움이 된다.



  1. NGINX 인그레스 컨트롤러 생성과 인그레스 설정을 완료했다. 이제 외부에서 NGINX 인그레스 컨트롤러에 접속할 수 있게 노드포트 서비스로 NGINX 인그레스 컨트롤러를 외부에 노출한다.



적용하는 코드를 살펴보자.

ingress.yaml

apiVersion: v1
kind: Service
metadata:
  name: nginx-ingress-controller
  namespace: ingress-nginx
spec:
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 30100
    - name: https
      protocol: TCP
      port: 443
      targetPort: 443
      nodePort: 30101
  selector:
    app.kubernetes.io/name: ingress-nginx
  type: NodePort


한 줄 한 줄 살펴보자.

ingress.yaml

#apiVersion: API 버전을 명시한다
#이 오브젝트를 생성하기 위해 사용하고 있는 쿠버네티스 API 버전이 어떤 것인지
#명시한다.
apiVersion: v1

#어떤 종류의 오브젝트를 생성하고자 하는지 명시한다.
kind: Service

#이름 문자열, UID, 그리고 선택적인 네임스페이스를 포함하여
#오브젝트를 유일하게 구분지어 줄 데이터이다.
#서비스 이름(name)은 nginx-ingress-controller.

metadata:
  name: nginx-ingress-controller

  #NGINX 인그레스 컨트롤러가 위치하는 네임스페이스를
  #ingress-nginx로 한다.
  namespace: ingress-nginx

spec:
  ports:
    - name: http
      protocol: TCP

      #http를 처리하기 위해 30100번 포트로 들어온 요청을
      #80번 포트로 넘긴다.
      port: 80
      #내부에 있는 컨테이너를 연결해주기 위하여 80포트를 사용하는 것이다.
      targetPort: 80
      nodePort: 30100

    - name: https
      protocol: TCP

      #https를 처리하기 위해 30101번 포트로 들어온 것을
      #443번 포트로 넘긴다.
      port: 443
      #내부에 있는 컨테이너를 연결해주기 위하여 443포트를 사용하는 것이다.
      targetPort: 443
      nodePort: 30101

      #NGINX 인그레스 컨트롤러의 요구 사항에 따라
      #셀렉터를 ingress-nginx로 지정한다.
      #즉 ingress-nginx라는 이름을 통해서 통신할 ingress 컨트롤러를 확인한다.
      #위의 ingress-config.yaml에서 metadata.name이 ingress-nginx이다.
  selector:
    app.kubernetes.io/name: ingress-nginx

  #서비스 타입을 설정
  type: NodePort


  1. 노드포트 서비스로 생성된 NGINX 인그레스 컨트롤러(nginx-ingress-controller)를 확인한다. 이때도 -n ingress-nginx(ingress.yaml를 작성할 때 metadata.namespace를 ingress-nginx로 위치하게 했음)로 네임스페이스를 지정해야만 내용을 확인할 수 있다.


kubectl get services -n ingress-nginx



  1. expose 명령으로 디플로이먼트(in-hname-pod, in-ip-pod)도 서비스로 노출한다. 외부와 통신하기 위해 클러스터 내부에서만 사용하는 파드를 클러스터 외부에 노출할 수 있는 구역으로 옮기는 것이다.


kubectl expose deployment in-hname-pod --name=hname-svc-default --port=80,443

kubectl expose deployment in-ip-pod --name=ip-svc --port=80,443



  1. 생성된 서비스를 점검해 디플로이먼트들이 서비스에 정상적으로 노출되는지 확인한다. 새로 생성된 서비스는 default 네임스페이스에 있으므로 -n 옵션으로 네임스페이스를 지정하지 않아도 된다.


kubectl get services



  1. 이제 호스트 노트북(또는 PC)에서 웹 브라우저를 띄우고 192.168.1.101:30100에 접속해 외부에서 접속되는 경로에 따라 다르게 작동하는지 확인한다. 이때 워커 노드 IP는 192.168.1.101이 아닌 102 또는 103을 사용해도 무방하다. 파드 이름이 웹 브라우저에 표시되는지도 확인한다.



  1. 이번에는 경로를 바꿔서 192.168.1.101:30100 뒤에 /ip를 추가해 본다.



  1. https://192.168.1.101:30101으로 접속해 HTTP 연결이 아닌 HTTPS 연결도 정상적으로 작동하는지 확인한다. 30101HTTPS의 포트인 443번으로 변환해 접속된다.





https 접속할 때 그냥 ip:port 만 적으면 애라 사진과 같이 나올 수 있다. 이럴 땐 https://ip:port 이렇게 적는다.



브라우저에 따라 경고 메시지가 뜰경우 고급 > 주소(안전하지 않음)(으)로 이동을 클릭하면 접속된다.


디플로이먼트와 서비스 및 NGINX 인그레스 컨트롤러와 관련된 내용 삭제

kubectl delete deployment in-hname-pod
kubectl delete deployment in-ip-pod
kubectl delete services hname-svc-default
kubectl delete services ip-svc

kubectl delete -f ~/_Book_k8sInfra/ch3/3.3.2/ingress-nginx.yaml
kubectl delete -f ~/_Book_k8sInfra/ch3/3.3.2/ingess-config.yaml

YoungKyonYou

Integration of Knowledge