반응형

목차

  1. 인그레스
    1. Ingress가 필요한 이유
    2. Ingress 리소스 생성
    3. Ingress로 서비스 엑세스
    4. Ingress 동작 방식
    5. 하나의 Ingress로 여러 서비스 노출
  2. TLS
    1. 하나의 Ingress로 여러 서비스 노출
    2.  TLS?

Ingress
Ingress가 필요한 이유

로드밸런서 서비스는 자신의 공용 IP 주소를 가진 로드밸런서가 필요하지만, Ingress는 한 IP 주소로 수십 개의 서비스에 접근이 가능하도록 지원해줍니다. 클라이언트가 HTTP 요청을 Ingress에 보낼 때, 요청한 호스트와 경로에 따라 요청을 전달할 서비스가 결정됩니다. 이는 다음 그림을 참고할 수 있습니다.

 

Ingress는 네트워크 스택의 애플리케이션 계층(HTTP, OSI 7계층 중 7계층에 해당)에서 작동하며 서비스가 할 수 없는 쿠키 기반 세션 어피니티 등과 같은 기능을 제공할 수 있습니다.

 

Ingress 오브젝트가 제공하는 기능을 살펴보기 전에 Ingress 리소스를 작동시키려면 클러스터에 Ingress 컨트롤러를 실행해야 합니다. 쿠버네티스 환경마다 다른 컨트롤러 구현을 사용할 수 있지만 일부는 기본 컨트롤러를 전혀 제공하지 않습니다.

 

예를 들어 구글 쿠버네티스 엔진은 구글 클라우드 플랫폼의 고유한 HTTP 로드 밸런싱 기능을 사용해 Ingress 기능을 제공합니다. 초기에 minikube는 기본 Ingress 컨트롤러를 제공하지 않았지만 이제 Ingress 기능을 시험해볼 수 잇는 애드온을 제공합니다.


Ingress 리소스 생성

클러스터에서 Ingress 컨트롤러가 실행 중인 것을 확인했다면 이제 Ingress 리소스를 만들 수 있습니다. 다음 예제는 Ingress에 대한 YAML 매니페스트를 보여줍니다.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: kubia
spec:
  rules:
  - host: kubia.example.com                >  Ingress는 kubia.example.com 도메인 이름을 서비스에 매핑합니다.
    http:
    paths:
    - path: /                                            >  모든 요청은 kubia-nodeport 서비스 포트인 80으로 전달됩니다.
      backend:
        serviceName: kubia-nodeport
        servicePort: 80

Host kubia.examle.com으로 요청되는 Ingress 컨트롤러에 수신된 모든 HTTP 요청을 포트 80의 kubia-nodeport 서비스로 전송하도록 하는 Ingress 규칙을 정의한 것입니다. 참고로 GKE와 같은 클라우드 공급자의 Ingress 컨트롤러는 Ingress가 노드포트 서비스를 가리킬 것을 요구합니다. 하지만 그것이 쿠버네티스 자체의 요구 사항은 아닙니다.


Ingress로 서비스 엑세스

http://kubia.example.com 서비스에 액세스하려면 도메인 이름이 Ingress 컨트롤러의 IP와 매핑되도록 확인해야 합니다.

 

Ingress의 IP 주소 를 확인하려면 Ingress 목록을 확인해야 합니다. kubectl get ingresses 명령어로 목록을 확인할 수 있습니다. 만약 클라우드에서 실행하는 경우 Ingress 컨트롤러가 뒷단에서 로드밸런서를 프로비저닝하기 때문에 주소가 표시되는데 시간이 조금 걸릴 수 있습니다. 명령어 결과가 출력되면 IP는 ADDRESS 열에 표시됩니다.

 

Ingress 컨트롤러가 구성된 호스트의 IP를 Ingress 엔드포인트로 지정할 수 있는데, 방금 설명한 방법으로 IP를 알고 나면 kubia.example.com을 해당 IP로 확인하도록 DNS 서버를 구성하거나, 다음 줄을 /etc/hosts에 추가하여 지정할 수 있습니다.

 

이제 Ingress로 파드에 엑세스하기 위한 모든 것이 설정됐으므로 브라우저 또는 curl을 통해 http://kubia.example.com 서비스에 엑세스할 수 있습니다.


Ingress 동작 방식

다음 그림은 클라이언트가 Ingress 컨트롤러로 파드에 연결하는 방식을 보여줍니다. 클라이언트는 먼저 kubia.example.com의 DNS 조회를 수행했으며 DNS 서버(또는 로컬 운영 체제)가 Ingress 컨트롤러의 IP를 반환합니다. 그런 다음 클라이언트는 HTTTP 요청을 Ingress 컨트롤러로 전송하고 host 해더에서 kubia.example.com을 지정합니다. 컨트롤러는 해당 해더에서 클라이언트가 액세스하려는 서비스를 결정하고 서비스와 관려된 엔드포인트 오브젝트로 파드 IP를 조회한 다음 클라이언트 요청을 파드에 전달합니다.

 

보다시피 Ingress 컨트롤러는 요청을 서비스로 전달하지 않습니다. 파드를 선택하는 데만 사용합니다. 모두는 아니지만 대부분의 컨트롤러는 이와 같이 동작합니다.


하나의 Ingress로 여러 서비스 노출

Ingress 스펙을 자세히 보면 규칙과 경로가 모두 배열이므로 여러 항목을 가질 수 있습니다. Ingress는 다음에서 볼 수 있듯이 여러 호스트와 경로를 여러 서비스에 매핑할 수있습니다.

 

1. 동일한 호스트의 다른 경로로 여러 서비스 매핑

다음 예제에 표시된 것처럼 동일한 호스트의 여러 경로를 다른 서비스에 매핑할 수 있습니다.

...
  - host: kubia.example.com
    http:
      paths:                                 >  kubia.example.com/kubia으로의 요청은 kubia 서비스로 라우팅됩니다.
        - path: /kubia
          backend:
            serviceName: kubia
            servicePort: 80
        - path: /bar                        >  kubia.example.com/bar로의 요청은 bar 서비스로 라우팅됩니다.
          backend:
            serviceName: bar
            serviceProt: 

이 경우 요청은 URL의 경로에 따라 두 개의 다른 섯비스로 전송됩니다. 따라서 클라이언트는 단일 IP 주소(Ingress 컨트롤러의 IP 주소)로 두 개의 서비스에 도달할 수 있습니다.

 

2. 서로 다른 호스트로 서로 다른 서비스 매핑하기

다음 예제와 같이 경로 대신 HTTP 요청의 호스트를 기반으로 서로 다른 서비스를 매핑할 수 있습니다.

spec:
  rules:
  - host: foo.example.com               >  foo.example.com으로의 요청은 서비스 foo로 라우팅됩니다.
    http:
      paths:
      - path: /
        backend:
          serviceName: foo
          serviceProt: 80
  - host: bar.example.com                >  bar.example.com으로의 요청은 서비스 bar로 라우팅됩니다.
    http:
      paths:
      - path: /
        backend:
          serviceName: bar
          serviceProt: 80

컨트롤러가 수신한 요청은 요청의 호스트 헤더(웹 서버에서 가상 호스트가 처리되는 방식)에 따라 서비스 foo 또는 bar로 전달됩니다. DNS는 foo.example.com과 bar.example.com 도메인 이름을 모두 Ingress 컨트롤러의 IP 주소로 지정해야 합니다.


TLS
TLS 트레픽을 처리하도록 Ingress 구성
Ingress를 위한 TLS 인증서 생성

클라이언트가 Ingress 컨트롤러에 대한 TLS 연결을 하면 컨트롤러는 TLS 연결을 종료합니다. 클라이언트와 컨트롤러 간의 통신은 암호화되지만 컨트롤러와 백엔드 파드 간의 통신은 암호화되지 않습니다. 파드에서 실행 중인 애플리케이션은 TLS를 지원할 필요가 없습니다.

 

예를 들어 파드가 웹 서버를 실행하는 경우 HTTP 트래픽만 허용하고 Ingress 컨트롤러가 TLS와 관련된 모든 것을 처리하도록 할 수 있습니다. 컨트롤러가 그렇게 하려면 인증서와 개인 키를 Ingress에 첨부해야 합니다. 이 두개는 시크릿 이라는 쿠버네티스 리소스에 저장하면 Ingress 매니페스트에서 참조합니다. 이 시크릿은 다음에 자세히 다뤄보도록 하겠습니다.

 

다음 명령어를 사용해 키와 시크릿을 만들 수 있습니다.

키 생성
openssl genrsa -out tls.key 2048

인증서 생성
openssl req -new -x509 -key tls.key -out tls.cret -days 360 -subj

시크릿 생성
kubectl create secret tls tls-secret  --cert=tls.cert --key=tls.key

* 참고
인증서 서명
kubectl cretificate approve <name of the CSR>

개인 키와 인증서는 이제 tls-secret이라는 시크릿에 저장됩니다. Ingress 오브젝트를 업데이트하면 kubia.example.com에 대한 HTTPS 요청도 수락할 수 있습니다. Ingress 매니페스트는 다음과 같이 보일 것입니다.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: kubia
spec:
  tls:
  - hosts:
    - kubia.example.com
    secretName: tls-secret
  rouls:
    - host: kubia.example.com
      http:
        paths:
        - path: /
          backend:
            serviceName: kubia-nodeport
            serviceProt: 80

참고로 Ingress를 삭제하고 다시 만드는 대신 kubectl apply -f 명령어로 위 YAML을 사용하면 파일에 지정된 내용으로 Ingress 리소스가 업데이트됩니다.

 

이제 HTTPS로 Ingress를 통해 서비스에 액세스할 수 있습니다.

curl -k -v https://kubia.example.com/kubia

명령어의 출력에는 애플리케이션의 응답과 Ingress에 구성한 서버 인증서가 표시 됩니다. Ingress 기능에 대한 지원은 Ingress 컨트롤러 구현마다 서로 다르므로 관련 문서에서 지원 내용을 확인할 필요가 있습니다.


TLS?

TLS(Transport Layer Security, 전송 계층 보안)는 클라이언트와 서버 간의 네트워크 통신을 보호하는 데 사용되는 암호화 프로토콜입니다. 쿠버네티스의 맥락에서 TLS는 클러스터 내에서 실행되는 클라이언트와 서비스 간 또는 쿠버네티스 컨트롤 플레인의 서로 다른 구성 요소 간 통신 보안과 관련하여 자주 논의됩니다.

다음은 쿠버네티스에서 TLS가 관련된 몇 가지 예입니다.

  1. 수신 및 TLS:

    Ingress 리소스를 사용하여 외부 트래픽을 쿠버네티스 클러스터 내의 서비스로 라우팅할 때 클라이언트와 Ingress 간의 통신을 암호화하도록 TLS를 구성할 수 있습니다. 이렇게 하면 클라이언트와 서비스 간에 전송되는 데이터가 기밀로 유지되고 도청이나 변조로부터 보호됩니다. Ingress 리소스에서 TLS를 활성화하려면 TLS 인증서와 개인 키가 포함된 TLS 시크릿을 생성한 다음 Ingress 구성에서 이 시크릿을 참조해야 합니다.

  2. 쿠버네티스 API 서버 보안:

    쿠버네티스 API 서버는 쿠버네티스 API를 노출하는 중앙 구성 요소로, 클러스터와 상호 작용하고 클러스터를 관리할 수 있습니다. API 서버와 클라이언트(예: kubectl, 대시보드) 또는 기타 컨트롤 플레인 구성 요소(예: etcd, kubelet) 간의 통신을 보호하는 데 필수적입니다. TLS는 이 통신을 암호화하는 데 사용되어 교환된 데이터가 기밀로 유지되도록 하고 클라이언트는 API 서버의 신뢰성을 확인할 수 있습니다.

  3. 컨트롤 플레인 구성 요소 간의 통신 보안:

    API 서버 외에도 etcd 및 kubelet과 같은 쿠버네티스 컨트롤 플레인의 다른 구성 요소도 TLS를 사용하여 통신을 보호합니다. 예를 들어 쿠버네티스의 데이터 저장소인 etcd는 TLS를 사용하여 etcd 피어 간 및 etcd와 API 서버 간 트래픽을 암호화하여 데이터 기밀성과 무결성을 보장합니다.

  4. 서비스 간 통신 보안:

    경우에 따라 쿠버네티스 클러스터 내의 서비스 간 통신을 보호해야 할 수 있습니다. Istio 또는 Linkerd와 같은 도구를 사용하여 서비스 간 mTLS(상호 TLS)를 자동으로 활성화할 수 있는 서비스 메시를 설정할 수 있습니다. mTLS는 클라이언트와 서버가 서로를 인증하고 통신을 암호화하도록 합니다.
반응형