mobile background
NGINX Ingress/Gateway Fabric 에서 구현가능한 기술 / 사용사례 소개 61
프로필 이미지
관리자
2025-01-17
조회 19

유효한 SSL/TLS 인증서는 현대 애플리케이션 환경의 핵심 요구 사항입니다. 안타깝게도 애플리케이션을 배포할 때 인증서(또는 인증서) 갱신을 관리하는 것은 종종 뒷전으로 밀려납니다. 인증서는 수명이 제한되어 있으며 DigiCert 인증서의 경우 약 13개월 에서 Let's Encrypt 인증서의 경우 90일 까지 다양합니다 . 안전한 액세스를 유지하려면 이러한 인증서는 만료되기 전에 갱신/재발급해야 합니다. 대부분 운영팀의 업무량이 많기 때문에 인증서 갱신이 간과되는 경우가 종종 있으며, 인증서가 만료 날짜에 가까워지거나 더 나쁜 경우 만료되면 혼란이 발생합니다.

이렇게 될 필요는 없습니다. 약간의 계획과 준비로 인증서 관리를 자동화하고 간소화할 수 있습니다. 여기서는 세 가지 기술을 사용하는 Kubernetes 솔루션을 살펴보겠습니다.

  • Jetstack의 인증 관리자
  • Let’s Encrypt
  • NGINX Ingress 컨트롤러

이 블로그에서는 엔드포인트에 고유하고 자동으로 갱신되고 업데이트된 인증서를 제공하여 인증서 관리를 간소화하는 방법을 알아봅니다.


Kubernetes 환경의 인증서

기술적인 세부 사항을 살펴보기 전에 용어를 정의해야 합니다. "TLS 인증서"라는 용어는 Ingress 컨트롤러에서 HTTPS 연결을 활성화하는 데 필요한 두 가지 구성 요소를 말합니다.

  • 인증서
  • 개인 키

인증서와 개인 키는 모두 Let's Encrypt 에서 발급합니다 . TLS 인증서가 작동하는 방식에 대한 전체 설명은 DigiCert의 게시물 How TLS/SSL Certificates Work를 참조하세요 .

쿠버네티스에서 이 두 구성 요소는 Secrets 로 저장됩니다. NGINX Ingress Controller 및 cert-manager 와 같은 쿠버네티스 워크로드는 이러한 Secrets를 쓰고 읽을 수 있으며, 쿠버네티스 설치에 액세스할 수 있는 사용자도 이를 관리할 수 있습니다.


cert-manager 소개

cert -manager 프로젝트는 Kubernetes 및 OpenShift와 함께 작동하는 인증서 컨트롤러입니다. Kubernetes에 배포하면 cert-manager는 Ingress 컨트롤러에 필요한 인증서를 자동으로 발급하고 유효하고 최신 상태인지 확인합니다. 또한 인증서의 만료 날짜를 추적하고 구성된 시간 간격으로 갱신을 시도합니다. 수많은 공개 및 비공개 발급자와 함께 작동하지만 Let's Encrypt와의 통합을 보여드리겠습니다.

Cert Manager 다이어그램


두 가지 도전 유형

Let's Encrypt를 사용하면 모든 인증서 관리가 자동으로 처리됩니다. 이는 많은 편의성을 제공하지만, 다음과 같은 문제도 제기합니다. 이 서비스는 사용자가 문제의 정규화된 도메인 이름(FQDN)을 소유하고 있는지 어떻게 보장합니까?

이 문제는 챌린지를 사용하여 해결되는데 , 챌린지는 특정 도메인의 DNS 레코드에 액세스할 수 있는 사람만 제공할 수 있는 확인 요청에 답해야 합니다. 챌린지는 다음 두 가지 형태 중 하나를 취합니다.

  1. HTTP-01 : 이 챌린지는 인증서를 발급하는 FQDN에 대한 DNS 레코드가 있으면 답변할 수 있습니다. 예를 들어, 서버가 IP www.xxx.yyy.zzz 에 있고 FQDN이 cert.example.com인 경우 챌린지 메커니즘은 www.xxx.yyy.zzz 의 서버에 토큰을 노출하고 Let's Encrypt 서버는 cert.example.com을 통해 해당 토큰에 도달하려고 시도합니다. 성공하면 챌린지가 통과되고 인증서가 발급됩니다.

     

    HTTP-01은 DNS 공급자에 직접 액세스할 필요가 없으므로 인증서를 생성하는 가장 간단한 방법입니다. 이 유형의 챌린지는 항상 포트 80(HTTP)을 통해 수행됩니다. HTTP-01 챌린지를 사용할 때 cert-manager는 Ingress 컨트롤러를 활용하여 챌린지 토큰을 제공합니다.

HTTP 01 다이어그램

  1. DNS-01 : 이 챌린지는 토큰이 있는 DNS TXT 레코드를 생성한 다음 발급자가 이를 확인합니다. 토큰이 인식되면 해당 도메인의 소유권을 증명한 것이며 이제 해당 레코드에 대한 인증서를 발급할 수 있습니다. HTTP-01 챌린지와 달리 DNS-01 챌린지를 사용할 때 FQDN은 서버의 IP 주소로 확인할 필요가 없습니다(존재하지 않아도 됩니다). 또한 DNS-01은 포트 80이 차단된 경우에 사용할 수 있습니다. 이러한 사용 편의성의 단점은 cert-manager 설치에 API 토큰을 통해 DNS 인프라에 대한 액세스를 제공해야 한다는 필요성입니다.

DNS 01 다이어그램


인그레스 컨트롤러

Ingress 컨트롤러는 클러스터 외부에서 트래픽을 가져오고, 내부 Pod (하나 이상의 컨테이너 그룹)로 로드 밸런싱하고, 이탈 트래픽을 관리하는 Kubernetes용 전문 서비스입니다. 또한 Ingress 컨트롤러는 Kubernetes API를 통해 제어되며 Pod가 추가, 제거 또는 실패할 때 로드 밸런싱 구성을 모니터링하고 업데이트합니다.

Ingress 컨트롤러에 대해 자세히 알아보려면 다음 블로그를 읽어보세요.

  • 쿠버네티스 네트워킹 101
  • Ingress 컨트롤러 선택 가이드, 4부: NGINX Ingress 컨트롤러 옵션

아래 예에서는 F5 NGINX가 개발하고 유지 관리하는 NGINX Ingress Controller를 사용하겠습니다.


인증서 관리 예제

이러한 예에서는 테스트할 수 있는 작동하는 Kubernetes 설치가 있고 설치가 외부 IP 주소(Kubernetes LoadBalancer 개체)를 할당할 수 있다고 가정합니다. 또한 포트 80과 포트 443(HTTP-01 챌린지 사용 시) 또는 포트 443(DNS-01 챌린지 사용 시)에서 트래픽을 수신할 수 있다고 가정합니다. 이러한 예는 Mac OS X를 사용하여 설명하지만 Linux 또는 WSL에서도 사용할 수 있습니다.

또한 A 레코드를 조정할 수 있는 DNS 공급자와 FQDN이 필요합니다. HTTP-01 챌린지를 사용하는 경우 A 레코드를 추가하는 기능만 있으면 됩니다(또는 사용자를 위해 추가되도록 하면 됩니다). DNS-01 챌린지를 사용하는 경우 지원되는 DNS 공급자 또는 지원되는 웹훅 공급자 에 대한 API 액세스가 필요합니다 .


NGINX Ingress Controller 배포

가장 쉬운 방법은 Helm을 통해 배포하는 것입니다 . 이 배포를 통해 Kubernetes Ingress와 NGINX Virtual Server CRD를 모두 사용할 수 있습니다.

  1. NGINX 저장소를 추가합니다.
  2. $ helm repo add nginx-stable https://helm.nginx.com/stable  "nginx-stable" has been added to your repositories 
  3. 저장소를 업데이트합니다.
  4. $ helm repo update  Hang tight while we grab the latest from your chart repositories...
      ...Successfully got an update from the "nginx-stable" chart repository
      Update Complete. ⎈Happy Helming!⎈ 
  5. Ingress 컨트롤러를 배포합니다.
  6. $ helm install nginx-kic nginx-stable/nginx-ingress \  --namespace nginx-ingress  --set controller.enableCustomResources=true \ 
      --create-namespace  --set controller.enableCertManager=true 
      NAME: nginx-kic
      LAST DEPLOYED: Thu Sep  1 15:58:15 2022
      NAMESPACE: nginx-ingress
      STATUS: deployed
      REVISION: 1
      TEST SUITE: None
      NOTES:
      The NGINX Ingress Controller has been installed. 
  7. 배포를 확인하고 Ingress 컨트롤러에 대한 egress의 IP 주소를 검색합니다. 유효한 IP 주소 없이는 계속할 수 없습니다.
  8. $ kubectl get deployments --namespace nginx-ingress  NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
      nginx-kic-nginx-ingress   1/1     1            1           23s
      $ kubectl get services --namespace nginx-ingress
      NAME                      TYPE           CLUSTER-IP      EXTERNAL-IP    PORT(S)                      AGE
      nginx-kic-nginx-ingress   LoadBalancer   10.128.60.190   www.xxx.yyy.zzz   80:31526/TCP,443:32058/TCP   30s 


DNS A 레코드 추가

여기서의 프로세스는 귀하의 DNS 공급자에 따라 달라집니다. 이 DNS 이름은 Let's Encrypt 서버에서 확인할 수 있어야 하며, 레코드가 전파될 때까지 기다려야 작동할 수 있습니다. 이에 대한 자세한 내용은 SiteGround 문서 DNS 전파란 무엇이며 왜 그렇게 오래 걸리는가? 를 참조하세요.

선택한 FQDN을 확인할 수 있으면 다음 단계로 넘어갈 준비가 된 것입니다.

$ host cert.example.com  cert.example.com has address www.xxx.yyy.zzz


cert-manager 배포

다음 단계는 cert-manager의 최신 버전을 배포하는 것입니다. 다시 말하지만, 우리는 배포에 Helm을 사용할 것입니다.

  1. Helm 저장소를 추가합니다.
  2. $ helm repo add jetstack https://charts.jetstack.io  "jetstack" has been added to your repositories 
  3. 저장소를 업데이트합니다.
  4. $ helm repo update  Hang tight while we grab the latest from your chart repositories...
      ...Successfully got an update from the "nginx-stable" chart repository
      ...Successfully got an update from the "jetstack" chart repository
      Update Complete. ⎈Happy Helming!⎈ 
  5. cert-manager를 배포합니다.
  6. $ helm install cert-manager jetstack/cert-manager \  --namespace cert-manager --create-namespace \
      --version v1.9.1  --set installCRDs=true 
      NAME: cert-manager
      LAST DEPLOYED: Thu Sep  1 16:01:52 2022 
      NAMESPACE: cert-manager
      STATUS: deployed
      REVISION: 1 
      TEST SUITE: None
      NOTES:
      cert-manager v1.9.1 has been deployed successfully!
    In order to begin issuing certificates, you will need to set up a ClusterIssuer or Issuer resource (for example, by creating a 'letsencrypt-staging' issuer).
    More information on the different types of issuers and how to configure them can be found in our documentation:
    https://cert-manager.io/docs/configuration/
    For information on how to configure cert-manager to automatically provision Certificates for Ingress resources, take a look at the `ingress-shim` documentation:
    https://cert-manager.io/docs/usage/ingress/
  7. 배포를 검증합니다.
  8. $ kubectl get deployments --namespace cert-manager  NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
      cert-manager              1/1     1            1           4m30s
      cert-manager-cainjector   1/1     1            1           4m30s
      cert-manager-webhook      1/1     1            1           4m30s 


NGINX Cafe 예제 배포

우리는 NGINX Cafe 예제를 사용하여 백엔드 배포 및 서비스를 제공할 것입니다. 이것은 NGINX에서 제공하는 설명서 내에서 사용되는 일반적인 예제입니다. 우리는 이것의 일부로 Ingress를 배포하지 않을 것입니다.

  1. NGINX Ingress GitHub 프로젝트를 복제합니다.
  2. $ git clone https://github.com/nginxinc/kubernetes-ingress.git  Cloning into 'kubernetes-ingress'...
      remote: Enumerating objects: 44979, done.
      remote: Counting objects: 100% (172/172), done.
      remote: Compressing objects: 100% (108/108), done.
      remote: Total 44979 (delta 87), reused 120 (delta 63), pack-reused 44807
      Receiving objects: 100% (44979/44979), 60.27 MiB | 27.33 MiB/s, done.
      Resolving deltas: 100% (26508/26508), done. 
  3. 예제 디렉토리로 변경합니다. 이 디렉토리에는 Ingress 컨트롤러의 다양한 구성을 보여주는 여러 예제가 들어 있습니다. 우리는 complete-example 디렉토리에 제공된 예제를 사용하고 있습니다.
  4. $ cd ./kubernetes-ingress/examples/ingress-resources/complete-example 
  5. NGINX Cafe 예제를 배포합니다.
  6. $ kubectl apply -f ./cafe.yaml
      deployment.apps/coffee created
      service/coffee-svc created
      deployment.apps/tea created
      service/tea-svc created
  7. get 명령을 사용하여 배포 및 서비스를 검증합니다 . Pod가 , 서비스가 로 표시되는지 kubectl확인해야 합니다 . 아래 예는 찾고 있는 것의 대표적인 샘플을 보여줍니다. 이 서비스는 NGINX Cafe 예와 동일한 네임스페이스(기본값)에서 실행되는 시스템 서비스입니다.READYrunningkubernetes
  8. $ kubectl get deployments,services  --namespace default  NAME                     READY   UP-TO-DATE   AVAILABLE   AGE
      deployment.apps/coffee   2/2     2            2           69s
      deployment.apps/tea      3/3     3            3           68s
    NAME                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
      service/coffee-svc   ClusterIP   10.128.154.225   <none>        80/TCP    68s
      service/kubernetes   ClusterIP   10.128.0.1       <none>        443/TCP   29m
        service/tea-svc      ClusterIP   10.128.96.145    <none>        80/TCP    68s 


ClusterIssuer 배포

cert-manager 내에서 ClusterIssuer를 사용하여 인증서를 발급할 수 있습니다. 이는 모든 네임스페이스에서 참조할 수 있고 정의된 인증서 발급 기관이 있는 모든 인증서 요청에서 사용할 수 있는 클러스터 범위 개체입니다. 이 예에서 Let's Encrypt 인증서에 대한 모든 인증서 요청은 이 ClusterIssuer에서 처리할 수 있습니다.

선택한 챌린지 유형에 대한 ClusterIssuer를 배포합니다. 이 게시물의 범위를 벗어나지만 ClusterIssuer에서 여러 개의 리졸버(선택자 필드에 따라 선택)를 지정할 수 있는 고급 구성 옵션 이 있습니다.


ACME 챌린지 기본 사항

ACME(Automated Certificate Management Environment) 프로토콜은 도메인 이름을 소유하고 있으므로 Let's Encrypt 인증서를 발급받을 수 있는지 확인하는 데 사용됩니다. 이 챌린지의 경우 전달해야 하는 매개변수는 다음과 같습니다.

  • metadata.name : Kubernetes 설치 내에서 고유해야 하는 ClusterIssuer 이름입니다. 이 이름은 나중에 인증서를 발급할 때 예제에서 사용됩니다.
  • spec.acme.email : 이것은 인증서를 생성하기 위해 Let's Encrypt에 등록하는 이메일 주소입니다. 이것은 귀하의 이메일이어야 합니다.
  • spec.acme.privateKeySecretRef : 개인 키를 저장하는 데 사용할 Kubernetes 비밀의 이름입니다.
  • spec.acme.solvers : 그대로 두어야 합니다. 여기에는 사용하는 챌린지 유형(ACME에서 부르는 대로 솔버)(HTTP-01 또는 DNS-01)과 이를 적용할 Ingress 클래스(이 경우 nginx)가 기록됩니다.


HTTP-01 사용

이 예제에서는 HTTP-01 챌린지를 사용하여 도메인 소유권을 증명하고 인증서를 수신하기 위해 ClusterIssuer를 설정하는 방법을 보여줍니다.

  1. HTTP-01을 사용하여 챌린지를 위한 ClusterIssuer를 생성합니다.
  2. $ cat << EOF | kubectl apply -f   apiVersion: cert-manager.io/v1
      kind: ClusterIssuer
      metadata:
        name: prod-issuer
      spec:
        acme:
          email: example@example.com
          server: https://acme-v02.api.letsencrypt.org/directory
          privateKeySecretRef:
            name: prod-issuer-account-key
          solvers:
          - http01:
             ingress:
               class: nginx
      EOF
      clusterissuer.cert-manager.io/prod-issuer created 
  3. ClusterIssuer를 검증합니다(준비 완료로 표시되어야 함).
  4. $ kubectl get clusterissuer  NAME          READY   AGE
        prod-issuer   True    34s 


DNS-01 사용

이 예제에서는 DNS-01 챌린지를 사용하여 도메인 소유권을 인증하는 ClusterIssuer를 설정하는 방법을 보여줍니다. DNS 공급자에 따라 토큰을 저장하기 위해 Kubernetes Secret을 사용해야 할 가능성이 높습니다. 이 예제에서는 Cloudflare를 사용합니다 . namespace 사용에 유의하세요. cert-manager 네임스페이스에 배포된 cert-manager 애플리케이션은 Secret에 액세스할 수 있어야 합니다.

이 예시에서는 계정에서 만들 수 있는 Cloudflare API 토큰이 필요합니다 . 이는 아래의 <API Token> 줄에 입력해야 합니다. Cloudflare를 사용하지 않는 경우 공급자의 설명서를 따라야 합니다 .

  1. API 토큰에 대한 비밀을 생성합니다.
  2. $ cat << EOF | kubectl apply -f   apiVersion: v1
      kind: Secret
      metadata:
        name: cloudflare-api-token-secret
        namespace: cert-manager
      type: Opaque
      stringData:
        api-token: <API Token> 
      EOF 
  3. DNS-01을 사용하여 발급자를 생성합니다.
  4. $ cat << EOF | kubectl apply -f   apiVersion: cert-manager.io/v1
      kind: ClusterIssuer
      metadata:
        name: prod-issuer
      spec:
        acme:
          email: example@example.com
          server: https://acme-v02.api.letsencrypt.org/directory
          privateKeySecretRef:
            name: prod-issuer-account-key
          solvers:
            - dns01:
                cloudflare:
                  apiTokenSecretRef:
                    name: cloudflare-api-token-secret
                    key: api-token
      EOF 
  5. 발급자를 확인합니다(준비 완료로 표시되어야 함).
  6. $ kubectl get clusterissuer  NAME          READY   AGE
        prod-issuer   True    31m 


Ingress 배포

이것이 우리가 구축해 온 지점입니다. 즉, 애플리케이션에 Ingress 리소스를 배포하는 것입니다. 이렇게 하면 트래픽이 이전에 배포한 NGINX Cafe 애플리케이션으로 라우팅됩니다.


Kubernetes Ingress 사용

표준 Kubernetes Ingress 리소스를 사용하는 경우 다음 배포 YAML을 사용하여 Ingress를 구성하고 인증서를 요청합니다.

apiVersion: networking.k8s.io/v1   kind: Ingress 
  metadata: 
    name: cafe-ingress 
    annotations: 
      cert-manager.io/cluster-issuer: prod-issuer 
      acme.cert-manager.io/http01-edit-in-place: "true" 
  spec: 
    ingressClassName: nginx 
    tls: 
    - hosts: 
      - cert.example.com 
      secretName: cafe-secret 
    rules: 
    - host: cert.example.com 
      http: 
        paths: 
        - path: /tea 
          pathType: Prefix 
          backend: 
            service: 
              name: tea-svc 
              port: 
                number: 80 
        - path: /coffee 
          pathType: Prefix 
          backend: 
            service: 
              name: coffee-svc 
              port: 
number: 80 

매니페스트의 몇 가지 주요 부분을 검토해 보는 것이 좋습니다.

  • 호출되는 API는 표준 Kubernetes Ingress입니다.
  • 이 구성의 핵심 부분은 "true"로 metadata.annotations설정하는 곳 입니다 acme.cert-manager.io/http01-edit-in-place. 이 값은 필수이며 챌린지가 제공되는 방식을 조정합니다. 자세한 내용은 지원되는 주석 문서를 참조하세요. 이는 마스터/미니언 설정을 사용하여 처리할 수도 있습니다 .
  • 이는 spec.ingressClassName우리가 설치하여 사용할 NGINX Ingress 컨트롤러를 말합니다.
  • Kubernetes spec.tls.secretSecret 리소스는 Let's Encrypt에서 인증서가 발급될 때 반환되는 인증서 키를 저장합니다.
  • 우리의 호스트 이름은 및 cert.example.com에 대해 지정됩니다 . 이것은 우리의 ClusterIssuer가 인증서를 발급한 호스트 이름입니다.spec.tls.hostsspec.rules.host
  • 이 spec.rules.http섹션은 경로와 해당 경로에서 요청을 처리할 백엔드 서비스를 정의합니다. 예를 들어, .에 대한 트래픽은 /tea.의 포트 80으로 전송됩니다 tea-svc.
  1. 설치에 맞게 위의 매니페스트를 수정하세요. 최소한 spec.rules.host및 spec.tls.hosts값을 변경하는 것이 포함되지만 구성의 모든 매개변수를 검토해야 합니다.
  2. 매니페스트를 적용합니다.
  3. $  kubectl apply -f ./cafe-virtual-server.yaml  virtualserver.k8s.nginx.org/cafe created 
  4. 인증서가 발급될 때까지 기다리세요. READY 필드에 대한 "True" 값을 찾고 있습니다.
  5. $ kubectl get certificates  NAME                                      READY   SECRET        AGE
      certificate.cert-manager.io/cafe-secret   True    cafe-secret   37m 


NGINX 가상 서버/가상 경로 사용

NGINX CRD를 사용하는 경우 다음 배포 YAML을 사용하여 Ingress를 구성해야 합니다.

  apiVersion: k8s.nginx.org/v1 
  kind: VirtualServer 
  metadata: 
    name: cafe 
  spec: 
    host: cert.example.com 
    tls: 
      secret: cafe-secret 
      cert-manager: 
        cluster-issuer: prod-issuer 
    upstreams: 
      - name: tea 
        service: tea-svc 
        port: 80 
      - name: coffee 
        service: coffee-svc 
        port: 80 
    routes: 
      - path: /tea 
        action: 
          pass: tea 
      - path: /coffee 
        action: 
          pass: coffee

다시 한번, 매니페스트의 몇 가지 핵심 부분을 검토해 보는 것이 좋습니다.

  • 호출되는 API는 VirtualServer 리소스에 대한 NGINX 전용 k8s.nginx.org/v1입니다.
  • Kubernetes spec.tls.secretSecret 리소스는 Let's Encrypt에서 인증서가 발급될 때 반환되는 인증서 키를 저장합니다.
  • 의 호스트 이름이 cert.example.com지정되었습니다 spec.host. 이것은 ClusterIssuer가 인증서를 발급한 호스트 이름입니다.
  • 해당 spec.upstreams값은 포트를 포함한 백엔드 서비스를 가리킵니다.
  • 이는 spec.routes경로와 해당 경로에 도달했을 때 수행해야 할 작업을 모두 정의합니다.
  1. 설치에 맞게 위의 매니페스트를 수정하세요. 최소한 값을 변경하는 것이 포함되지만 spec.host구성의 모든 매개변수를 검토해야 합니다.
  2. 매니페스트를 적용합니다.
  3. $  kubectl apply -f ./cafe-virtual-server.yaml  virtualserver.k8s.nginx.org/cafe created
  4. 인증서가 발급될 때까지 기다리세요. 유효 상태가 표시되어야 합니다.
  5. $ kubectl get VirtualServers  NAME   STATE   HOST                    IP             PORTS      AGE
      cafe   Valid   cert.example.com   www.xxx.yyy.zzz   [80,443]   51m 

인증서 보기

Kubernetes API를 통해 인증서를 볼 수 있습니다. 여기에는 인증서의 크기 및 연관된 개인 키를 포함한 인증서에 대한 세부 정보가 표시됩니다.

$ kubectl describe secret cafe-secret  Name:         cafe-secret
  Namespace:    default
  Labels:       <none>
  Annotations:  cert-manager.io/alt-names: cert.example.com
                cert-manager.io/certificate-name: cafe-secret
                cert-manager.io/common-name: cert.example.com
                cert-manager.io/ip-sans:
                cert-manager.io/issuer-group:
                cert-manager.io/issuer-kind: ClusterIssuer
                cert-manager.io/issuer-name: prod-issuer
                cert-manager.io/uri-sans:Type:  kubernetes.io/tlsData
  ====
  tls.crt:  5607 bytes
  tls.key:  1675 bytes 

실제 인증서와 키를 보고 싶다면 다음 명령을 실행하면 됩니다. (참고: 이는 Kubernetes Secrets의 약점을 보여줍니다. 즉, 필요한 액세스 권한이 있는 사람은 누구나 읽을 수 있습니다.)

$ kubectl get secret cafe-secret -o yaml


Ingress 테스트

인증서를 테스트합니다. 여기서는 원하는 방법을 사용할 수 있습니다. 아래 예에서는 cURL을 사용합니다 . 성공은 서버 이름, 서버의 내부 주소, 날짜, 선택한 URI(경로)(커피 또는 차) 및 요청 ID를 포함하는 이전에 표시된 것과 유사한 블록으로 표시됩니다. 실패는 HTTP 오류 코드의 형태를 띠며, 대부분 400 또는 301입니다.

$ curl https://cert.example.com/tea
  Server address: 10.2.0.6:8080
  Server name: tea-5c457db9-l4pvq
  Date: 02/Sep/2022:15:21:06 +0000
  URI: /tea
  Request ID: d736db9f696423c6212ffc70cd7ebecf
  $ curl https://cert.example.com/coffee
  Server address: 10.2.2.6:8080
  Server name: coffee-7c86d7d67c-kjddk
  Date: 02/Sep/2022:15:21:10 +0000
  URI: /coffee
Request ID: 4ea3aa1c87d2f1d80a706dde91f31d54 


인증서 갱신

처음에 우리는 이 접근 방식이 인증서 갱신을 관리할 필요성을 없앨 것이라고 약속했습니다. 하지만 아직 그 방법을 설명하지 못했습니다. 왜 그럴까요? 이는 cert-manager의 핵심 내장 부분이기 때문입니다. 이 자동 프로세스에서 cert-manager가 인증서가 없거나 만료되었거나 만료까지 15일 이내이거나 사용자가 CLI를 통해 새 인증서를 요청하는 경우 새 인증서가 자동으로 요청됩니다 . 이보다 더 쉬운 일은 없습니다.



위 내용과 같이 NGINX Ingress Controller 를 활용하여 Demo 가 필요하시면 하단의 전문가에게 상담받기 버튼을 클릭해주세요


전문가에게 상담받기


프로필 이미지
관리자
2025-01-17
조회 1

사이버 보안 공격의 정교함과 수는 기하급수적으로 증가하고 있으며, 온프레미스, 하이브리드 및 멀티 클라우드 Kubernetes 환경에 배포된 앱에 대한 상당한 노출 위험을 발생시키고 있습니다. 기존 보안 모델은 경계 기반이며, 환경의 보안 경계 내에 위치하는 경우 사용자가 신뢰할 수 있고(그리고 사용자 간의 통신이 안전하다고) 가정합니다. 오늘날의 분산 환경에서 경계 내부의 안전 지대라는 개념은 더 이상 존재하지 않습니다. 환경 "내부"에서 발생하는 통신은 외부 위협만큼 위험할 수 있습니다.

이 블로그에서는 Kubernetes 인프라를 보호하기 위해 Zero Trust 모델을 도입하는 이점과 NGINX가 보안 태세를 개선하는 데 어떻게 도움이 될 수 있는지 알아봅니다.


제로 트러스트란 무엇인가요?

Zero Trust 는 위치가 아닌 신원에 기반한 보안 모델입니다. 이는 요청자가 사내, 원격 또는 클라우드에 있는 것처럼 보이는지 여부에 관계없이 애플리케이션, 데이터 및 장치에 대한 액세스 요청이 공격일 수 있다고 가정합니다.

Zero Trust의 세 가지 핵심 원칙(절대 신뢰하지 말고, 항상 확인하고, 지속적으로 모니터링)을 구현하기 위해 모든 사용자, 서비스, 애플리케이션 및 기기는 지속적으로 인증 및 권한 부여 증명을 제시해야 합니다. 시간 제한 권한은 동적 액세스 정책과 최소 권한 기준에 따라 부여됩니다.

모든 통신은 암호화되고 모든 당사자를 인증하고 동적 액세스 정책에 따라 권한을 부여하는 정책 결정/시행 지점(PDP/PEP)을 통해 라우팅됩니다. 또한 감사, 모니터링, 보고 및 자동화 기능이 보안 위험을 분석, 평가 및 완화하기 위해 마련되어 있습니다.

제로 트러스트 다이어그램


Zero Trust가 보안 태세를 개선하는 방법

Zero Trust는 여러 가지 방법으로 보안 태세를 개선합니다.

  • 승인되지 않은 활동을 자동으로 차단합니다
  • 노출된 공격 표면을 줄이기 위해 액세스 제어를 시행합니다.
  • 행동 이상 및 침해 지표 감지
  • 액세스 시간을 제한하는 실시간 최소 권한 정책을 정의합니다.
  • 진행 중인 공격을 차단하기 위해 지속적으로 신원을 인증하고 검증합니다.

Zero Trust는 Kubernetes 환경에서 실행되는 최신 클라우드 네이티브 앱에 특히 중요합니다. 느슨하게 결합되고 이식 가능한 분산 앱과 서비스는 컨테이너화되어 위치 기반 보안이 옵션이 아닌 하이브리드, 멀티 클라우드 환경에서 실행됩니다. 보안은 필연적으로 ID 및 권한의 지속적인 검증, 종단 간 암호화 및 모니터링에 달려 있습니다.


제로 트러스트 보안을 달성하는 방법

Zero Trust 원칙을 충족하려면 Kubernetes 환경에서 사용자, 애플리케이션, 서비스에 대한 인증, 권한 부여, 액세스 제어, 정책, 암호화, 모니터링, 감사와 같은 중요한 보안 기능을 제공해야 합니다.

이를 달성할 수 있는 한 가지 가능한 방법은 앱 자체에 보안을 구축하는 것입니다. 그러나 이는 개발자가 신뢰 설정 및 확인, 사용자 ID 및 인증서 관리, 모든 통신 암호화 및 복호화 등을 위한 여러 보안 절차를 구현해야 함을 의미합니다. 또한 TLS 및 Single Sign‑on(SSO)과 같은 타사 기술을 이해하고 통합해야 합니다. 이 모든 것이 이미 복잡한 Kubernetes 배포에 복잡성을 더할 뿐만 아니라 개발자가 집중해야 하는(그리고 원하는!) 것, 즉 앱의 비즈니스 기능을 최적화하는 데 방해가 됩니다.

당황하지 마세요. 더 나은 방법이 있습니다. 보안 및 기타 비기능적 요구 사항을 Kubernetes 인프라로 오프로드하세요! Ingress 컨트롤러 및 서비스 메시와 같은 Kubernetes 클러스터용 연결 도구는 사용자 또는 다른 앱이나 서비스에서 시작된 모든 앱 및 서비스 간 통신을 위한 PDP 및 PEP를 제공할 수 있습니다. 즉, 핵심 비즈니스 전문 지식과 기능에 집중하면서 앱을 더 빠르고 쉽게 제공할 수 있습니다.


F5 NGINX가 어떻게 도움이 될 수 있는지

다음 다이어그램에서 알 수 있듯이, 안전한 Kubernetes 연결을 위한 NGINX 솔루션에는 온프레미스, 하이브리드, 멀티 클라우드 등 모든 환경에서 사용자, 분산 애플리케이션, 마이크로서비스, API를 규모에 맞게, 종단 간 성공적으로 보호하는 데 필요한 모든 인프라 독립적 인 구성 요소와 도구가 포함되어 있습니다. 세계에서 가장 인기 있는 데이터 플레인으로 구동되는 이 솔루션은 다음을 결합합니다.

  •  Kubernetes용 Ingress 컨트롤러이자 타사 ID 및 SSO 공급자와 통합되는 PDP/PEP인 NGINX Ingress Controller . NGINX Plus를 기반으로 하는 NGINX Ingress Controller는 고급 연결, 모니터링 및 가시성, 인증 및 SSO를 처리하고 API 게이트웨이 역할을 합니다.
  • NGINX Service Mesh는  가볍고 턴키 방식의 개발자 친화적 서비스 메시로 Kubernetes 클러스터 내에서 서비스 연결을 보호합니다. 각 Kubernetes 서비스와 함께 배치된 PDP/PEP 역할을 하는 엔터프라이즈급 사이드카는 NGINX Plus를 기반으로 합니다.
  •  F5의 시장을 선도하는 보안 기술을 기반으로 구축된 최신 앱과 API의 전체적인 보호를 위한 NGINX App Protect . 배포 시나리오의 유연성과 최적의 리소스 활용을 위해 모듈식 접근 방식을 사용합니다.
    • NGINX App Protect WAF – OWASP Top 10을 보호하고 PCI DDS 규정 준수를 제공하는 강력하고 가벼운 WAF
    • NGINX App Protect DoS  – 클라우드와 아키텍처 전반에 걸쳐 일관되고 적응적인 보호를 제공하는 동작형 DoS 탐지 및 완화

제로 트러스트 다이어그램 2

NGINX 솔루션을 사용하면 다음이 가능합니다.

  • 릴리스 속도를 늦추거나 성능을 저하시키지 않고 분산 환경 전반에 강력한 보안 제어를 통합합니다.
  • 지속적인 인증, 신원 검증, 동작 이상 감지를 통해 진행 중인 공격을 자동으로 차단합니다.
  • 여러 팀에 걸쳐 실시간 최소 권한 정책, 세분화된 액세스 제어, 종단 간 암호화 및 거버넌스를 구현합니다.
  • 통합적이고 강력한 WAF 및 앱 수준 DoS 방어 기능을 통해 코드에서 고객에게 앱을 안전하게 제공하세요.
  • 세부적인 실시간 및 과거 지표를 통해 Kubernetes 환경의 보안 태세를 지속적으로 평가하고 개선합니다.
  • 기술 통합을 통해 보안 사용자-서비스 및 서비스-서비스 간 통신 의 배포 및 관리를 간소화합니다.


NGINX로 포괄적인 Zero Trust 보안 구현

조직이 확장됨에 따라 앱의 기능에 국한되지 않은 요구 사항(예: Zero Trust 보안 기능)을 애플리케이션 계층에서 오프로드하는 것이 중요해집니다. 위에서 설명한 대로 이를 통해 개발자는 앱 전체에서 보안 로직을 빌드, 유지 관리 및 복제하는 부담에서 벗어날 수 있습니다. 대신 플랫폼 수준에서 보안 기술을 쉽게 활용할 수 있습니다. NGINX는 NGINX Ingress Controller를 사용하여 클러스터 가장자리에서 Kubernetes에 대한 중앙 집중식 보안 정책 시행을 제공하고 NGINX Service Mesh를 사용하여 클러스터 내에서 Kubernetes에 대한 중앙 집중식 보안 정책 시행을 제공합니다. 앱 보안 요구 사항에 따라 가장자리 또는 클러스터 내에 배포된 NGINX App Protect WAF 및 DoS를 사용하여 정교한 사이버 공격으로부터 고급 애플리케이션 보호 기능을 추가할 수 있습니다.

Kubernetes 배포에 포괄적인 Zero Trust 보안을 구현하는 데 필요한 기능이 NGINX 솔루션에 어떻게 포함되어 있는지 자세히 살펴보겠습니다.


인증 및 권한 부여

Zero Trust 보안의 핵심 원칙 중 하나는 모든 기기, 사용자, 서비스 및 요청이 인증되고 승인된다는 것입니다. 인증은 신원을 확인하는 프로세스입니다. 즉, 통신에 참여하는 각 당사자가 주장하는 대로인지 확인하는 프로세스입니다. 승인은 당사자가 리소스 또는 기능에 대한 액세스 권한이 있는지 확인하는 프로세스입니다.

이 원칙을 해결하기 위해 NGINX 솔루션은 HTTP 기본 인증 , JSON 웹 토큰(JWT) , Okta 및 Azure Active Directory(AD)와 같은 ID 공급자와의 통합을 통한 OpenID Connect를 포함하여 인증 및 권한 부여를 구현하기 위한 여러 옵션을 제공합니다. NGINX 솔루션은 또한 서비스에 보안 ID를 발급합니다(애플리케이션 사용자에게 인증서 형태의 ID가 발급되는 것과 매우 유사). 이를 통해 Kubernetes 클러스터에서 작업을 수행하도록 인증 및 권한 부여를 받을 수 있습니다. 워크로드 ID를 처리하는 것 외에도 NGINX 솔루션은 PKI(공개 키 인프라) 및 인증 기관과의 기본 제공 통합을 통해 인증서 관리를 자동화합니다.

NGINX Ingress Controller는 이미 클러스터에 들어오는 모든 요청을 면밀히 조사하여 적절한 서비스로 라우팅하기 때문에 중앙에서 사용자를 인증하고 권한을 부여하는 데 가장 효율적인 위치이며, 일부 시나리오에서는 서비스를 인증하는 데도 가장 효율적인 위치입니다.

자세한 내용은 블로그에서 Okta와 NGINX Ingress Controller를 사용하여 Kubernetes에 대한 OpenID Connect 인증 구현을 읽어보세요.


데이터 암호화 및 무결성

또 다른 Zero Trust 원칙은 모든 통신이 보안되어야 한다는 것입니다. 즉, 참여자가 어디에 있든 기밀성과 무결성이 유지되어야 합니다. 데이터는 승인되지 않은 당사자가 읽거나 전송 중에 수정되어서는 안 됩니다. 이 원칙을 충족하기 위해 NGINX 솔루션은 사용자-서비스 통신에는 SSL/TLS 암호화를 사용하고 서비스-서비스 통신 에는 상호 TLS(mTLS) 인증 및 암호화를 사용합니다 .

앱 아키텍처가 Kubernetes 클러스터 내에서 서비스 간 통신을 포함하지 않는 경우 NGINX Ingress Controller가 데이터 무결성 요구 사항을 충족하기에 충분할 수 있습니다. 두 가지 기본 옵션이 있습니다.

 

  • TLS Passthrough를 사용하면 NGINX Ingress Controller는 SSL/TLS로 암호화된 연결을 서비스에 직접 라우팅하여 암호를 해독하거나 SSL/TLS 인증서나 키에 액세스할 필요가 없습니다.
  • SSL/TLS 종료를 사용하면 NGINX Ingress Controller가 역방향 프록시 역할을 하여 요청자와의 TLS 연결을 종료한 다음 mTLS 또는 서비스 측 SSL/TLS를 사용하여 Kubernetes 서비스(백엔드 및 업스트림 서버)에 대한 새로운 연결을 암호화합니다.

아키텍처에 클러스터 내에서 서비스 간 통신이 포함되는 경우 데이터 무결성을 위해 NGINX Ingress Controller와 NGINX Service Mesh가 모두 필요합니다. NGINX Service Mesh는 특정 서비스만 서로 통신할 수 있도록 보장하고 mTLS를 사용하여 이를 인증하고 통신을 암호화합니다. NGINX Service Mesh를 사용하여 mTLS를 "제로 터치" 방식으로 구현할 수 있으므로 개발자는 인증서를 사용하여 애플리케이션을 개조하거나 상호 인증이 수행되고 있다는 것을 알 필요가 없습니다.

Kubernetes 클러스터에서 통신을 보호하는 방법에 대한 자세한 내용은 블로그의 NGINX 서비스 메시의 mTLS 아키텍처를 참조하세요.


접근 제어 및 접근 정책

액세스 제어는 Zero Trust 모델의 또 다른 중요한 요소입니다. Kubernetes는 역할 기반 액세스 제어(RBAC)를 사용하여 다양한 사용자에게 제공되는 리소스와 작업을 규제합니다. 이는 사용자 또는 사용자 그룹이 클러스터의 Kubernetes 객체 또는 네임스페이스와 상호 작용할 수 있는 방법을 결정합니다.

NGINX Kubernetes 연결 솔루션은 조직의 보안 정책과 쉽게 일치할 수 있도록 RBAC를 지원합니다. RBAC를 사용하면 사용자는 IT 티켓을 제출하고 처리될 때까지 기다리지 않고도 업무를 수행하는 데 필요한 기능에 대한 게이트형 액세스를 얻을 수 있습니다. RBAC가 없으면 사용자는 필요하지 않거나 권한이 없는 권한을 얻을 수 있으며, 권한이 오용되면 취약성이 발생할 수 있습니다.

NGINX Ingress Controller로 RBAC를 구성하면 조직의 애플리케이션 개발 및 제공 환경에서 다양한 역할에 맞게 권한을 조정하여 여러 사람과 팀의 액세스를 제어할 수 있습니다. 세분화된 액세스 관리 도구를 통해 여러 팀에서 셀프 서비스와 거버넌스를 수행할 수 있습니다.

NGINX Ingress Controller로 RBAC를 활용하는 방법을 알아보려면 DevNetwork, NGINX Ingress Controller를 사용한 고급 Kubernetes 배포에 대한 웨비나를 시청하세요 . 13:50부터 전문가가 보안, 셀프서비스 및 멀티테넌시를 위해 RBAC와 리소스 할당을 활용하는 방법을 설명합니다.


관찰 가능성

감사, 모니터링, 로깅, 추적 및 보고는 Zero Trust 환경에서 핵심 요소입니다. Kubernetes 애플리케이션 인프라의 상태에 대해 더 많은 정보를 수집하고 더 효과적으로 상관 관계를 분석하고 평가할수록 보안 태세를 강화할 수 있습니다.

아마도 Kubernetes 배포에서 모니터링 도구를 이미 사용하고 있을 것이고, 또 다른 도구가 필요하지 않을 것입니다. 클러스터 내부에서 무슨 일이 일어나고 있는지 전체적으로 파악할 수 있도록, JSON을 허용하고 OpenTelemetry , Grafana 및 Prometheus 와 같은 인기 있는 도구와 미리 빌드된 통합을 제공하는 모든 타사 도구에 메트릭을 쉽게 내보낼 수 있도록 NGINX Plus API 를 계측했습니다. 심층 추적을 통해 앱 연결에 대한 타겟팅된 통찰력을 얻을 수 있으므로 요청이 종단 간에 처리되는 방식을 이해할 수 있습니다 . NGINX Ingress Controller는 클러스터와 외부 클라이언트 간의 연결에 대한 통찰력을 제공하는 반면, NGINX Service Mesh는 클러스터 내의 컨테이너화된 마이크로서비스 기반 앱과 서비스 간의 연결을 다룹니다.


WAF 및 DoS 보호

NGINX App Protect를 사용하면 OWASP Top 10 및 Layer 7 서비스 거부(DoS) 공격 과 같은 위협으로부터 분산 애플리케이션을 보호하여 보안을 더욱 강화할 수 있습니다 . 엔드투엔드 NGINX 보안 연결 솔루션 의 필수 구성 요소인 NGINX App Protect는 기본적인 시그니처를 훨씬 넘어서 가장 진보된 위협으로부터 민첩하고 앱 중심의 보안을 제공합니다. F5의 선도적이고 신뢰할 수 있는 보안 전문 지식을 활용하며 릴리스 속도와 성능을 저하시키지 않습니다. 보안 원격 측정을 타사 분석 및 가시성 솔루션으로 쉽게 전달할 수 있으며, 높은 신뢰도 시그니처와 자동화된 동작 분석으로 거짓 양성을 줄입니다.

NGINX App Protect의 모듈식 설계는 필요에 따라 동일하거나 다른 인스턴스에 WAF와 DoS 보호 중 하나 또는 둘 다를 배포할 수 있음을 의미합니다. 예를 들어, 클러스터 가장자리에 NGINX Ingress Controller를 사용하여 배포하기로 결정할 수 있으며, 이는 전체 단일 클러스터에서 일관된 세분화된 보호를 제공하는 데 이상적입니다. 대신 클러스터의 여러 앱에 대한 앱별 정책이 필요한 경우 서비스 또는 포드 수준에서 WAF 및/또는 DoS 보호를 배포할 수 있습니다.

WAF와 DoS 보호 기능을 구축하는 방법에 대한 자세한 내용은 블로그에서 보다 안전한 앱을 위해 보안 도구를 좌측으로 전환을 읽어보세요.


Kubernetes를 위한 NGINX Zero Trust 보안 솔루션 시작하기

Kubernetes 여정의 시작에 있는 사용자이든 오랫동안 Kubernetes를 운영 환경에서 사용해 온 고급 사용자이든, NGINX는 사용자의 요구 사항을 충족하고 보안 태세를 개선하는 데 필요한 포괄적인 도구와 빌딩 블록 세트를 제공합니다




위 내용과 같이 NGINX Ingress Controller 를 활용하여 Demo 가 필요하시면 하단의 전문가에게 상담받기 버튼을 클릭해주세요



전문가에게 상담받기


프로필 이미지
관리자
2025-01-17
조회 7


조직이 확장됨에 따라 Kubernetes의 개발 및 운영 워크플로는 더욱 복잡해집니다. 각 팀이 자체 클러스터를 갖는 것보다 팀이 Kubernetes 클러스터와 리소스를 공유하는 것이 일반적으로 더 비용 효율적이며 더 안전할 수 있습니다. 그러나 팀이 안전하고 보안적인 방식으로 리소스를 공유하지 않거나 해커가 구성을 악용하는 경우 배포에 심각한 손상이 발생할 수 있습니다.

네트워크 및 리소스 수준에서의 멀티 테넌시 관행과 네임스페이스 격리는 팀이 Kubernetes 리소스를 안전하게 공유하는 데 도움이 됩니다. 또한 테넌트별로 애플리케이션을 격리하여 침해 규모를 크게 줄일 수도 있습니다. 이 방법은 특정 팀이 소유한 애플리케이션의 하위 섹션만 손상될 수 있고 다른 기능을 제공하는 시스템은 그대로 유지되므로 복원력을 높이는 데 도움이 됩니다.

NGINX Ingress Controller는 여러 멀티 테넌시 모델을 지원하지만, 우리는 두 가지 주요 패턴을 봅니다. 인프라 서비스 공급자 패턴은 일반적으로 물리적 격리가 있는 여러 NGINX Ingress Controller 배포를 포함하는 반면, 엔터프라이즈 패턴은 일반적으로 네임스페이스 격리가 있는 공유 NGINX Ingress Controller 배포를 사용합니다. 이 섹션에서는 엔터프라이즈 패턴을 심층적으로 살펴봅니다. 여러 NGINX Ingress Controller를 실행하는 방법에 대한 자세한 내용은 설명서를 참조 하세요 .


NGINX Ingress Controller를 사용한 위임

NGINX Ingress Controller는 표준 Kubernetes Ingress 리소스와 사용자 지정 NGINX Ingress 리소스를 모두 지원하여 보다 정교한 트래픽 관리와 여러 팀에 대한 구성 제어 위임을 모두 가능하게 합니다. 사용자 지정 리소스는 VirtualServer, VirtualServerRoute , GlobalConfiguration , TransportServer 및 Policy 입니다 .

NGINX Ingress Controller를 사용하면 클러스터 관리자는 VirtualServer 리소스를 사용하여 외부 트래픽을 백엔드 애플리케이션으로 라우팅하는 Ingress 도메인(호스트 이름) 규칙을 프로비저닝하고 VirtualServerRoute 리소스를 사용하여 특정 URL의 관리를 애플리케이션 소유자와 DevOps 팀에 위임할 수 있습니다.

Kubernetes 클러스터에서 다중 테넌시를 구현할 때 선택할 수 있는 두 가지 모델이 있습니다. 전체 셀프 서비스 및 제한된 셀프 서비스입니다 .


전체 셀프 서비스 구현

전체 셀프 서비스 모델에서 관리자는 NGINX Ingress Controller 구성의 일상적인 변경에 관여하지 않습니다. 관리자는 NGINX Ingress Controller와 배포를 외부에 노출하는 Kubernetes Service를 배포하는 것에만 책임이 있습니다 . 그런 다음 개발자는 관리자를 포함하지 않고 할당된 네임스페이스 내에서 애플리케이션을 배포합니다. 개발자는 TLS 비밀을 관리하고, 도메인 이름에 대한 부하 분산 구성을 정의하고, VirtualServer 또는 표준 Ingress 리소스를 생성하여 애플리케이션을 노출할 책임이 있습니다.

이 모델을 설명하기 위해 다음 다이어그램에 나와 있는 것처럼 두 개의 하위 도메인 과 를 사용하여 샘플 bookinfo 애플리케이션(원래 Istio에서 생성)을 복제합니다. 관리자가 네임스페이스(녹색으로 강조 표시됨)에 NGINX Ingress Controller를 설치하고 배포하면 DevA(분홍색) 팀과 DevB(보라색) 팀이 자체 VirtualServer 리소스를 만들고 네임스페이스( 각각 및 ) 내에서 격리된 애플리케이션을 배포합니다 .a.bookinfo.comb.bookinfo.comnginx-ingressAB

DevA 팀과 DevB 팀은 도메인에 대한 Ingress 규칙을 설정하여 외부 연결을 해당 애플리케이션으로 라우팅합니다.

a.bookinfo.comTeam DevA는 네임스페이스 의 도메인  에 대한 애플리케이션을 노출하기 위해 다음 VirtualServer 리소스 개체를 적용합니다 A.



apiVersion: k8s.nginx.org/v1

kind: VirtualServer

metadata:

  name: bookinfo

  namespace: A

spec:

  host: a.bookinfo.com

  upstreams:

  - name: productpageA

    service: productpageA

    port: 9080

  routes:

  - path: /

    action:

      pass: productpageA
view rawfull-self-service-vs-a.yaml hosted with ❤ by GitHub


b.bookinfo.com마찬가지로, DevB 팀은 네임스페이스 의 도메인  에 대한 애플리케이션을 노출하기 위해 다음 VirtualServer 리소스를 적용합니다 B.



apiVersion: k8s.nginx.org/v1

kind: VirtualServer

metadata:

  name: bookinfo

  namespace: B

spec:

  host: b.bookinfo.com

  upstreams:

  - name: productpageB

    service: productpageB

    port: 9080

  routes:

  - path: /

    action:

      pass: productpageB
view rawfull-self-service-vs-b.yaml hosted with ❤ by GitHub


제한된 셀프 서비스 구현

제한된 셀프 서비스 모델에서 관리자는 클러스터에 들어오는 트래픽을 적절한 네임스페이스로 라우팅하도록 VirtualServer 리소스를 구성하지만, 네임스페이스의 애플리케이션 구성을 담당 개발 팀에 위임합니다. 이러한 각 팀은 VirtualServer 리소스에서 인스턴스화된 애플리케이션 하위 경로에 대해서만 책임을 지고 VirtualServerRoute 리소스를 사용하여 트래픽 규칙을 정의하고 네임스페이스 내에서 애플리케이션 하위 경로를 노출합니다.

관리자가 VirtualServer 리소스를 구성하지만 애플리케이션 구성을 개발 팀에 위임하여 트래픽 규칙을 정의하고 애플리케이션 하위 경로를 노출하는 Kubernetes 클러스터의 제한된 셀프 서비스 토폴로지 다이어그램

다이어그램에 표시된 것처럼 클러스터 관리자는 nginx-ingress네임스페이스(녹색으로 강조 표시됨)에 NGINX Ingress Controller를 설치 및 배포하고 VirtualServerRoute 리소스 정의를 참조하는 경로 기반 규칙을 설정하는 VirtualServer 리소스를 정의합니다.

/productpage-A이 VirtualServer 리소스 정의는 두 개의 하위 경로에 대한 VirtualServerRoute 리소스 정의를 참조하는 두 개의 경로 기반 규칙을 설정합니다 /productpage-B.



apiVersion: k8s.nginx.org/v1

kind: VirtualServer

metadata:

  name: example

spec:

  host: bookinfo.example.com

  routes:

  - path: /productpage-A

    route: A/ingress 

  - path: /productpage-B

    route: B/ingress
view rawrestricted-self-service-vs.yaml hosted with ❤ by GitHub


네임스페이스AB 의 앱을 담당하는 개발자 팀은 VirtualServerRoute 리소스를 정의하여 네임스페이스 내의 애플리케이션 하위 경로를 노출합니다. 팀은 네임스페이스별로 격리 되고 관리자가 프로비저닝한 VirtualServer 리소스에서 설정한 애플리케이션 하위 경로를 배포하는 것으로 제한됩니다.

  • Team DevA(다이어그램의 분홍색)는 관리자가 설정한 애플리케이션 하위 경로 규칙을 노출하기 위해 다음 VirtualServerRoute 리소스를 적용합니다 /productpage-A.



    apiVersion: k8s.nginx.org/v1

    kind: VirtualServerRoute

    metadata:

      name: ingress 

      namespace: A

    spec:

      host: bookinfo.example.com

      upstreams:

      - name: productpageA

        service: productpageA-svc

        port: 9080

      subroutes:

      - path: /productpage-A 

        action:

          pass: productpageA
    view rawrestricted-self-service-vsr-a.yaml hosted with ❤ by GitHub


  • Team DevB(보라색)는 관리자가 설정한 애플리케이션 하위 경로 규칙을 노출하기 위해 다음 VirtualServerRoute 리소스를 적용합니다 /productpage-B.



    apiVersion: k8s.nginx.org/v1

    kind: VirtualServerRoute

    metadata:

      name: ingress 

      namespace: B

    spec:

      host: bookinfo.example.com

      upstreams:

      - name: productpageB

        service: productpageB-svc

        port: 9080

      subroutes:

      - path: /productpage-B 

        action:

          pass: productpageB
    view rawrestricted-self-service-vsr-b.yaml hosted with ❤ by GitHub


VirtualServer 및 VirtualServerRoute 리소스에서 구성할 수 있는 기능에 대한 자세한 내용은 NGINX Ingress Controller 설명서를 참조하세요 .

참고: 병합 가능한 Ingress 유형을 사용하여 크로스 네임스페이스 라우팅을 구성할 수 있지만 제한된 셀프 서비스 위임 모델에서는 이 접근 방식에 VirtualServer 및 VirtualServerRoute 리소스와 비교할 때 세 가지 단점이 있습니다.

  1. 보안성이 낮습니다.
  2. Kubernetes 배포가 점점 더 크고 복잡해짐에 따라 병합 가능한 Ingress 유형은 개발자가 네임스페이스 내에서 호스트 이름에 대한 Ingress 규칙을 설정하는 것을 방해하지 않기 때문에 실수로 수정될 가능성이 커집니다.
  3. VirtualServer 및 VirtualServerRoute 리소스와 달리 병합 가능한 Ingress 유형은 기본("마스터") Ingress 리소스가 "미니언" Ingress 리소스의 경로를 제어할 수 있도록 하지 않습니다.


제한된 셀프 서비스 모델에서 Kubernetes RBAC 활용

Kubernetes 역할 기반 액세스 제어(RBAC)를 사용하면 사용자에게 할당된 역할에 따라 네임스페이스 및 NGINX Ingress 리소스에 대한 사용자 액세스를 규제할 수 있습니다.

예를 들어, 제한된 셀프 서비스 모델에서 특별한 권한이 있는 관리자만 VirtualServer 리소스에 안전하게 액세스할 수 있습니다. 해당 리소스는 Kubernetes 클러스터의 진입점을 정의하기 때문에 오용하면 시스템 전체가 중단될 수 있습니다.

개발자는 VirtualServerRoute 리소스를 사용하여 자신이 소유한 애플리케이션 경로에 대한 Ingress 규칙을 구성하므로 관리자는 개발자가 해당 리소스만 만들 수 있도록 하는 RBAC 정책을 설정합니다. 개발자 액세스를 더욱 규제해야 하는 경우 해당 권한을 특정 네임스페이스로 제한할 수도 있습니다.

완전한 셀프 서비스 모델에서 개발자는 VirtualServer 리소스에 안전하게 액세스할 수 있지만, 관리자가 해당 권한을 특정 네임스페이스로 제한할 수도 있습니다.

RBAC 권한 부여에 대한 자세한 내용은 Kubernetes 설명서를 참조하세요 .


정책 추가

NGINX 정책 리소스는 분산 팀이 멀티 테넌시 배포에서 Kubernetes를 구성할 수 있도록 하는 또 다른 도구입니다. 정책 리소스는 OAuth 및 OpenID Connect  (OIDC)를 사용한 인증, 속도 제한 및 웹 애플리케이션 방화벽(WAF)과 같은 기능을 활성화합니다. 정책 리소스는 VirtualServer 및 VirtualServerRoute 리소스에서 참조되어 Ingress 구성에서 적용됩니다.

예를 들어, 클러스터에서 ID 관리를 담당하는 팀은  Okta를 OIDC ID 공급자(IdP)로 사용하여 다음과 같이 JSON 웹 토큰 (JWT) 또는 OIDC 정책을 정의할 수 있습니다.



apiVersion: k8s.nginx.org/v1

kind: Policy

metadata:

  name: okta-oidc-policy

  spec:

    oidc:

      clientID: <client_id>

      clientSecret: okta-oidc-secret

      authEndpoint: https://<your_okta_domain>/oauth2/v1/authorize

      tokenEndpoint: https://<your_okta_domain>/oauth2/v1/token

      jwksURI: https://<your_okta_domain>/oauth2/v1/keys
view rawoidc-policy.yaml hosted with ❤ by GitHub


NetOps 및 DevOps 팀은 이 예와 같이 VirtualServer 또는 VirtualServerRoute 리소스를 사용하여 해당 정책을 참조할 수 있습니다.



apiVersion: k8s.nginx.org/v1

kind: VirtualServer

metadata:

  name: bookinfo-vs

spec:

  host: bookinfo.example.com

  tls:

    secret: bookinfo-secret

  upstreams:

  - name: backend

    service: productpage

    port: 9080

  routes:

  - path: /

    policies:

    - name: okta-oidc-policy

    action:

      pass: backend
view rawoidc-vs.yaml hosted with ❤ by GitHub


NGINX Policy, VirtualServer 및 VirtualServerRoute 리소스를 함께 사용하면 관리자가 구성을 다른 팀에 쉽게 위임할 수 있는 분산 구성 아키텍처가 가능합니다. 팀은 네임스페이스 전반에 걸쳐 모듈을 조립하고 안전하고 확장 가능하며 관리하기 쉬운 방식으로 정교한 사용 사례로 NGINX Ingress Controller를 구성할 수 있습니다.

관리자가 특정 기능의 구성을 다양한 팀에 위임하는 다중 테넌트 Kubernetes 클러스터의 다이어그램



위 내용과 같이 NGINX Ingress Controller 를 활용하여 Demo 가 필요하시면 하단의 전문가에게 상담받기 버튼을 클릭해주세요



전문가에게 상담받기

프로필 이미지
관리자
2025-01-17
조회 7


NGINX Ingress Controller는 HTTP 트래픽과 함께 TCP 및 UDP 트래픽의 부하를 분산하므로 다음을 포함하여 해당 프로토콜을 기반으로 하는 다양한 앱과 유틸리티의 트래픽을 관리하는 데 사용할 수 있습니다.

  • MySQL, LDAP 및 MQTT  – 많은 인기 있는 애플리케이션에서 사용되는 TCP 기반 앱
  • DNS, syslog 및 RADIUS  – 에지 장치 및 비트랜잭션 애플리케이션에서 사용되는 UDP 기반 유틸리티

NGINX Ingress Controller를 사용한 TCP 및 UDP 로드 밸런싱은 다음과 같은 상황에서 Kubernetes 애플리케이션에 네트워크 트래픽을 분산하는 데도 효과적인 솔루션입니다.

  • NGINX Ingress Controller가 아닌 엔드투엔드 암호화(EE2E)를 사용하고 애플리케이션이 암호화 및 복호화를 처리하도록 합니다.
  • TCP 또는 UDP 기반 애플리케이션의 경우 고성능 로드 밸런싱이 필요합니다.
  • 기존 네트워크(TCP/UDP) 로드 밸런서를 Kubernetes 환경으로 마이그레이션할 때 변경 사항을 최소화하려고 합니다.

NGINX Ingress Controller에는 TCP/UDP 부하 분산을 지원하는 두 개의 NGINX Ingress 리소스가 함께 제공됩니다.

  • GlobalConfiguration 리소스는 일반적으로 클러스터 관리자가 DevOps 팀에서 사용할 수 있는 TCP/UDP 포트( listeners)를 지정하는 데 사용됩니다. 각 NGINX Ingress Controller 배포에는 GlobalConfiguration 리소스가 하나만 있을 수 있습니다.
  • TransportServer 리소스는 일반적으로 DevOps 팀이 애플리케이션에 대한 TCP/UDP 부하 분산을 구성하는 데 사용됩니다. NGINX Ingress Controller는 관리자가 GlobalConfiguration 리소스에서 인스턴스화한 포트에서만 수신합니다. 이를 통해 포트 간 충돌을 방지하고 DevOps 팀이 관리자가 미리 결정한 안전한 포트만 공개 외부 서비스에 노출하도록 하여 보안 계층을 추가로 제공합니다.


다음 다이어그램은 GlobalConfiguration 및 TransportServer 리소스에 대한 샘플 사용 사례를 보여줍니다. gc.yaml 에서 클러스터 관리자는 GlobalConfiguration 리소스에서 TCP 및 UDP 리스너를 정의합니다. ts.yaml 에서 DevOps 엔지니어는 MySQL 배포로 트래픽을 라우팅하는 TransportServer 리소스에서 TCP 리스너를 참조합니다.

GlobalConfiguration 및 TransportServer 리소스에 대한 사용 사례의 토폴로지 다이어그램

gc.yaml 의 GlobalConfiguration 리소스는 두 개의 리스너를 정의합니다. syslog 서비스에 연결하기 위한 포트 514의 UDP 리스너와 MySQL 서비스에 연결하기 위한 포트 5353의 TCP 리스너입니다.



apiVersion: k8s.nginx.org/v1alpha1

kind: GlobalConfiguration 

metadata:

  name: nginx-configuration

  namespace: nginx-ingress

spec: 

  listeners:

  - name: syslog-udp

    port: 541

    protocol: UDP

  - name: mysql-tcp 

    port: 5353 

    protocol: TCP
view rawgc.yaml hosted with ❤ by GitHub


ts.yaml 의 TransportServer 리소스의 6~8행은 gc.yaml 에 이름( mysql-tcp) 으로 정의된 TCP 리스너를 참조하고 , 9~14행은 TCP 트래픽을 업스트림으로 보내는 라우팅 규칙을 정의합니다 mysql-db.



apiVersion: k8s.nginx.org/v1alpha1

kind: TransportServer

metadata:

  name: mysql-tcp

spec:

  listener:

    name: mysql-tcp 

    protocol: TCP

upstreams:

- name: mysql-db 

  service: mysql 

  port: 3306

action:

  pass: mysql-db
view rawts.yaml hosted with ❤ by GitHub


rawdata_content_schema이 예에서 DevOps 엔지니어는 MySQL 클라이언트를 사용하여 구성이 제대로 작동하는지 확인합니다. 이는 MySQL 배포 내 데이터베이스 의 테이블 목록이 포함된 출력을 통해 확인됩니다 .

$ echo “SHOW TABLES” | mysql –h <external_IP_address> -P <port> -u <user> –p rawdata_content_schema Enter Password: <password>
Tables_in_rawdata_content_schema
authors
posts

UDP 트래픽을 위한 TransportServer 리소스는 비슷하게 구성됩니다. 전체 예제는 GitHub의 NGINX Ingress Controller repo에서 Basic TCP/UDP Load Balancing을 참조하세요. 고급 NGINX 사용자는 repo의 Support for TCP/UDP Load Balancingstream-snippets 예제 에서 볼 수 있듯이 ConfigMap 키를 사용하여 기본 NGINX 구성으로 TransportServer 리소스를 확장할 수 있습니다 .



위 내용과 같이 NGINX Ingress Controller 를 활용하여 Demo 가 필요하시면 하단의 전문가에게 상담받기 버튼을 클릭해주세요



전문가에게 상담받기

프로필 이미지
관리자
2025-01-17
조회 1

2021년 8월 Sprint 2.0에서 NGINX Modern Applications Reference Architecture  (MARA)를 공개했을 때 우리는 디자인 목표를 솔직하게 밝혔습니다. 우리는 Kubernetes에서 실행되고 보안, 확장성, 안정성, 모니터링 및 내성을 지원하도록 설계된 최신 애플리케이션 아키텍처의 예를 만들고 싶었습니다. 이 프로젝트는 시간 소모적인 통합 노력 없이 기능적 구성 요소를 결합하는 "플러그 앤 플레이" 방식으로 다양한 인프라에 배포할 수 있어야 했습니다.

Sprint 이후 몇 달 동안 우리는 로드맵을 추진해 왔습니다. 다른 프로젝트와 마찬가지로 우리는 성공과 실패를 겪었고, MARA에 성공 사례를 녹여냈으며, 배운 교훈 목록도 계속 늘렸습니다. 이러한 문제를 문서화하고 이러한 교훈을 염두에 두고 설계함으로써 다른 사람들이 같은 문제에 부딪히지 않도록 할 수 있기를 바랍니다.

우리는 최근 MARA 버전 1.0.0 으로 이정표에 도달했습니다 . 이 버전은 프로젝트 디렉토리를 재구성하고 환경을 인스턴스화하고 파괴하는 프로세스를 변경합니다. 중복된 코드를 제거하고, 향후 추가 사항을 쉽게 수용할 수 있는 디렉토리 구조를 만들고, 관리 스크립트를 표준화했습니다. 이 버전은 MARA의 역사에서 중요한 지점을 나타내므로, 우리는 잠시 멈추어 커뮤니티에 진행 상황을 보고하고, 더 중요한 교훈 중 일부라고 생각되는 것을 기록하고, 앞으로의 로드맵에 대한 정보를 제공하고자 했습니다.

NGINX Modern Apps Reference Architecture 버전 1.0.0에 대한 토폴로지 다이어그램


원격 측정 – 메트릭, 로깅 및 추적

MARA의 핵심 기여자들은 대규모로 소프트웨어를 실행한 경험이 있으며 운영, 엔지니어링 및 관리 관점에서 서비스를 제공하는 데 필요한 사항을 이해합니다. 그들은 애플리케이션이 제대로 작동하지 않고 문제가 무엇인지 정확히 파악할 수 있는 쉬운 방법이 없을 때 느끼는 침울함을 알고 있습니다. DevOps 세계에 떠도는 인용문은 이 문제를 간결하게 요약합니다. "마이크로서비스 디버깅은 일련의 살인 미스터리를 푸는 것과 같습니다."

이를 염두에 두고, 우리는 단기 로드맵에서 관찰 가능성 추가를 최우선 순위로 삼았습니다. 이 맥락에서 관찰 가능성에는 로그 관리, 메트릭 및 추적 데이터가 포함됩니다. 그러나 데이터 수집만으로는 충분하지 않습니다. 데이터를 파헤치고 환경에서 무슨 일이 일어나고 있는지에 대한 의미 있는 결정을 내릴 수 있어야 합니다.

추적 옵션에 대한 우리의 탐색은 원격 측정 데이터, 로그, 메트릭 및 추적의 전체 범위를 지원하기 때문에 OpenTelemetry  (OTEL)로 이어졌습니다. 우리는 OTEL 에이전트가 모든 추적 데이터를 수집, 처리 및 중복 제거한 다음 OTEL 수집기에 전달하여 집계하고 내보내는 구현을 구상했으며, 워크플로 끝에 시각화 시스템을 사용하여 데이터를 사용 가능하게 만들었습니다. 이 접근 방식은 사용자에게 데이터를 표시하고 분석하기 위한 가장 광범위한 선택권을 제공하는 동시에 OTEL 표준을 활용하여 초기 단계(수집, 집계 등)를 간소화합니다.

우리는 두 단계로 구현을 구축했습니다.

  1. 환경에서 OTEL 수집기를 관리하기 위해 Kubernetes용 OpenTelemetry Operator를 배포합니다 .

  2. Bank of Sirius 애플리케이션을 도구화하여 추적 및 메트릭을 방출합니다.

MARA의 원래 버전은 로깅을 위해 Filebeat 와 함께 Elasticsearch를 사용했고, Grafana Loki 로 대체하는 것을 고려했지만 , 당장은 원래의 선택을 유지하기로 했습니다. 지표 측면에서, 우리는 처음에 사용했던 맞춤형 Prometheus 구성을 커뮤니티에서 유지 관리하는 kube-prometheus-stack Helm 차트로 대체하여 Prometheus 와 Grafana 에 기반한 원래 배포를 수정해야 한다는 것을 깨달았습니다. 이 차트는 Grafana, 노드 내보내기 , Kubernetes 환경을 관리하는 데 적합한 일련의 미리 구성된 대시보드 및 스크래핑 대상을 포함한 완전한 Prometheus 환경을 구성합니다. 여기에 F5 NGINX Ingress Controller 와 Bank of Sirius 애플리케이션 에 대한 몇 가지 추가 대시보드를 추가했습니다 .

이는 OTEL을 구현하는 데 필요한 엄청난 양의 작업에 대한 간략한 요약일 뿐입니다. 다른 사람들이 같은 가파른 학습 곡선을 오르는 수고를 덜어주기 위해, 저희는 블로그의 Integrating OpenTelemetry into the Modern Apps Reference Architecture – A Progress Report 에서 전체 프로세스를 문서화했습니다 .


배포 옵션 – Kubeconfig

MARA의 초기 버전에서 우리는 배포 환경으로 Amazon Elastic Kubernetes Service  (EKS)를 선택했습니다. 그 이후로 많은 사용자가 비용상의 이유로 랩이나 워크스테이션과 같이 리소스가 덜 필요한 "로컬" 환경에서 MARA를 실행하고 싶다고 말했습니다. 이식성은 원래 프로젝트의 핵심 목표였고(지금도 그렇습니다) 이것이 우리가 그것을 달성할 수 있다는 것을 증명할 기회였습니다. 작업을 더 쉽게 하기 위해 우리는 최소 요구 사항을 충족하는 모든 Kubernetes 클러스터에서 실행할 수 있는 배포 절차를 설계하기로 결정했습니다.

첫 번째 단계로, 우리는 Kubernetes 클러스터와 통신하기 위해 kubeconfig 파일을 읽는 새로운 Pulumi 프로젝트를 MARA에 추가했습니다. 이 프로젝트는 Pulumi Kubernetes 프로젝트와 인프라 프로젝트(후자의 예로는 AWS와 Digital Ocean 프로젝트) 사이에 있습니다. 실제적으로 kubeconfig 프로젝트를 만들면 새로운 인프라 프로젝트를 통합하는 데 대한 장벽이 낮아집니다. 인프라 프로젝트가 kubeconfig 파일, 클러스터 이름, 클러스터 컨텍스트를 kubeconfig 프로젝트에 전달할 수 있다면 MARA 배포 절차의 나머지 부분은 원활하게 작동합니다.

테스트를 위해 K3s , Canonical MicroK8s , minikube를 포함하여 CPU와 메모리 요구 사항이 작은 설치하기 쉬운 Kubernetes 배포판을 여러 개 사용했습니다. 배포판은 모두 2개의 CPU 와 16GB RAM이 있는 Ubuntu 21.10을 실행하는 가상 머신(VM)에 배포되었습니다 . 또한 모든 배포판은 영구 볼륨과 Kubernetes LoadBalancer 지원을 제공하도록 구성되었습니다.

이 프로세스에서 가장 어려운 부분은 프로젝트의 일부인 맞춤형 NGINX Ingress Controller에 사용되는 개인 레지스트리로 작업하는 것이었습니다. (Mara를 배포할 때는 NGINX Open Source 또는 NGINX Plus 기반의 표준 NGINX Ingress Controller와 이 맞춤형 NGINX Ingress Controller를 사용할 수 있습니다.) 우리는 더 플랫폼 독립적인 접근 방식을 위해 레지스트리 로직을 Amazon Elastic Container Registry  (ECR)에서 분리해야 한다는 것을 발견했고, 이 작업은 현재 진행 중입니다. 또한 이그레스 주소의 호스트 이름을 가져오는 로직이 AWS Elastic Load Balancing  (ELB)에 매우 특화되어 있고 다른 사용 사례에 적용하기 위해 다시 작성해야 한다는 것을 깨달았습니다.

MARA 관리 스크립트와 Pulumi 프로젝트는 현재 위에 설명된 문제를 해결하기 위해 몇 가지 특정 논리를 사용합니다. 지금으로서는 Kubernetes 구성 기반 배포는 공식 NGINX 레지스트리의 NGINX Ingress Controller(NGINX Open Source 또는 NGINX Plus 기반)를 사용해야 합니다.

클라우드 기반 배포에 필요한 리소스를 제공하지 않는 로컬 배포를 수용하기 위해 MARA 구성 파일에 여러 튜닝 매개변수를 추가했습니다. 대부분의 매개변수는 Elastic Stack 의 다양한 구성 요소에 대해 요청된 복제본 수와 관련이 있습니다 . 테스트가 진행됨에 따라 배포 환경의 리소스 제약 조건에 따라 MARA를 미세 조정하기 위한 추가 매개변수가 있을 것입니다.

이러한 변경 사항을 적용하면 K3s, MicroK8s 및 Minikube에 성공적으로 배포할 수 있으며 Azure Kubernetes Service  (AKS), Digital Ocean , Google Kubernetes Engine , Linode 및 Rancher's Harvester 에서 로직을 성공적으로 테스트했습니다 . 자세한 내용은 MARA Provider Status 페이지 와 블로그의 MARA: Now Running on a Workstation Near You를 참조하세요.


파트너와의 협력

저희 파트너들은 MARA와의 협력에 대해 매우 수용적이고 지지적이었습니다. 그들 중 많은 사람들이 이 프로젝트에 대해 자세히 알아보고, 자사 제품에 이를 어떻게 활용할 수 있는지, 심지어 기능을 어떻게 추가할 수 있는지 문의해왔습니다.

우리는 MARA의 핵심 부분으로 Pulumi를 선택했는데 , 사용하기 쉽고 Python을 지원하기 때문입니다. Python은 매우 인기 있는 언어이기 때문에 MARA 코드를 대규모 커뮤니티에서 쉽게 이해할 수 있습니다. 또한 Pulumi의 활기찬 커뮤니티와 프로젝트 참여는 MARA를 통해 이루고자 하는 커뮤니티 참여의 모델이었습니다.

2021년 후반에 우리는 Sumo Logic 과 협력하여 MARA를 NGINX Ingress Controller를 사용한 클라우드 모니터링 솔루션 의 일부로 만들었습니다 . 이것은 MARA가 플러그 가능하다는 우리의 주장을 시험할 기회였습니다. 과제는 MARA에서 Sumo Logic 솔루션을 Grafana, Prometheus, Elastic으로 대체하는 것이었습니다. 우리는 다른 배포에 사용하는 것과 동일한 로직을 사용하여 솔루션을 성공적으로 구축하고 Sumo Logic SaaS에 연결할 뿐만 아니라 환경에서 메트릭을 가져오도록 구성하게 되어 기뻤습니다.

OpenTelemetry와의 작업의 일환으로 Lightstep 과 협업하여 OTEL 수집기를 쉽게 재구성하여 추적 및 메트릭을 Lightstep의 SaaS 오퍼링으로 내보낼 수 있었습니다. 이는 OTEL이 관찰 가능성의 미래라고 굳게 믿기 때문에 더 조사하고 싶은 분야입니다.


지금까지 얻은 교훈

지금까지 우리가 얻은 가장 큰 교훈은 모듈식 접근 방식의 지혜입니다. Sumo Logic과의 작업은 MARA 구성 요소를 성공적으로 혼합하고 일치시킬 수 있음을 보여줍니다. OTEL을 환경에 더욱 완벽하게 통합함에 따라 추가 확인을 기대합니다. 이전에 Elasticsearch를 Grafana Loki로 로그 관리 환경으로 대체하는 것을 고려하고 있다고 언급했는데, 이는 스택의 리소스 사용량을 줄이기 때문입니다. 그럼에도 불구하고 모든 것을 마이크로서비스로 만들어 극단적인 방향으로 가는 것보다는 "실용적인 모듈성"을 옹호합니다. 예를 들어, 많은 애플리케이션의 로그를 처리할 수 있는 전문화된 서비스를 갖는 것이 합리적이지만 로그 수집, 저장 및 시각화를 위해 별도의 마이크로서비스가 필요하다는 것은 덜 분명합니다.

또한 관련 매개변수를 생략하는 것보다 구성에 명시적으로 포함시켜 기본값을 설정하는 것이 도움이 된다는 것을 알게 되었습니다. 이는 관리자에게 두 가지 면에서 편리합니다. 기본값을 기억할 필요가 없고 구성의 올바른 위치에 올바른 구문으로 이미 나타나는 매개변수를 수정하기만 하면 쉽게 변경할 수 있습니다.

우리가 얻은 또 다른 고통스러운 교훈은 일부 솔루션이 최고이기 때문이 아니라 설치하기 가장 쉽거나 튜토리얼이 가장 좋기 때문에 인기가 있다는 것입니다. 이것이 설계 과정에서 가정에 의문을 제기하고 동료와 상의하는 것이 매우 중요한 이유입니다. 개방적인 의사소통 문화는 문제를 일찍 식별하고 해결하는 데 큰 도움이 됩니다.

그럼에도 불구하고, 우리는 여러 차례에 걸쳐 작동했지만 우리를 궁지에 몰거나 다른 문제를 일으킨 로직을 구현했습니다. 예를 들어, Pulumi를 통해 애플리케이션을 배포하기 시작했을 때, 우리는 ConfigMaps 에 YAML 매니페스트를 사용하여 Pulumi 변환을 통해 변수를 업데이트했습니다. 이는 효과가 있었지만, 여러 가지 이유로 이상적이지 않았습니다. 그 중 가장 중요한 이유는 유지 관리성이었습니다. 다음 반복에서 우리는 kube2pulumi를 사용하여 매니페스트를 Pulumi 코드로 변환하여 ConfigMaps를 빌드하는 데 사용할 수 있도록 함으로써 코드의 가독성과 유지 관리성을 개선했습니다 .

또 다른 교훈은 병합이 배포 YAML에 잘못된 설정을 삽입했을 때 시작되었습니다. 우리는 YAML의 큰 부분을 다시 작성하고 신중하게 검토하여 코드가 구문적으로 올바르고 원하는 대로 작동하는지 확인해야 했는데, 이는 좌절스럽고 시간이 많이 걸리는 과정이었습니다. 향후 문제를 피하기 위해 이제 GitHub 푸시 프로세스 중에 일반 YAML과 Kubernetes 특정 린팅 및 검증을 모두 자동화 했습니다 .

마지막으로, 처음부터 우리의 목표는 메인라인 브랜치가 항상 실행 가능하도록 하는 것이었습니다. 새로운 프로젝트를 체크아웃하고 메인라인에서 관리자가 도입한 문제를 해결해야 할 때는 좌절스럽습니다. 안타깝게도, 우리는 이 부분에서 몇 번 실패했는데, 여기에는 Bank of Sirius 하위 모듈의 예도 포함됩니다.

  • 우리는 실수로 URL 스킴을 ssh:// 에서 https:// 로 바꾸는 것을 잊었습니다 . 이것은 우리에게 문제가 되지 않았습니다. 왜냐하면 우리 모두가 sshGitHub에 연결하곤 했기 때문입니다. 그러나 GitHub의 SSH 키가 없는 사용자는 하위 모듈을 초기화하려고 했을 때 오류 메시지에 휩싸였습니다.
  • 관리 스크립트의 한 릴리스에는 모든 사람의 컴퓨터에 설치되어 있기 때문에 우리 컴퓨터에도 설치되어 있을 것이라고 잘못 가정한 공통 패키지에 대한 종속성이 있었습니다.
  • 우리는 시작 로직을 다시 작성하는 동안 하위 모듈 소스에 대한 검사를 넣는 것을 잊었습니다. 하위 모듈에는 Bank of Sirius를 배포하는 데 필요한 매니페스트가 포함되어 있으며, 불행히도 이러한 매니페스트를 사용할 수 없을 때 발생하는 오류와 경고는 우리가 근본 원인을 발견하기 전에 이상한 동작을 디버깅하는 며칠간의 오디세이를 시작하기에 충분히 모호했습니다.


다음은 무엇인가

저희는 향후 몇 달 동안 NGINX Ingress Controller 빌드 리팩토링, 레지스트리 푸시, Ingress 호스트 이름/IP 주소 로직을 포함한 대규모 개발을 계획하고 있습니다.

MARA의 모든 스탠드업에서 우리가 알아차린 한 가지는 NGINX Ingress Controller에서 스캔과 공격이 얼마나 빨리 발생하는지입니다. 이로 인해 NGINX Ingress Controller를 NGINX App Protect WAF와 함께 MARA에 통합하기 시작했습니다. 여기에는 App Protect에서 생성된 로깅을 가장 잘 관리하는 방법을 결정하는 과제와 기회가 함께 제공됩니다.

앞으로 몇 달 동안 우리가 할 또 다른 변경 사항은 모든 모듈이 Pulumi와 Kubernetes가 아닌 Kubernetes에서 비밀을 가져오는 것입니다. 즉, 모든 모듈이 공통 비밀 저장소를 사용하고 관리자가 비밀을 채우는 방법을 제어할 수 있습니다. 사용자가 선택한 저장소에서 비밀을 읽고 해당 Kubernetes 비밀을 만드는 새 모듈을 작성하고 있습니다.

MARA는 현재 Bank of Sirius를 포크한 원래 Bank of Anthos 앱과 함께 제공되는 Locust 기반 도구 의 업그레이드되고 약간 수정된 버전인 부하 생성 도구를 포함합니다 . 우리가 작성 중인 새로운 테스트 도구인 Cicada Swarm은 부하를 생성할 뿐만 아니라 메트릭이 설정한 임계값을 초과할 때 추적하고 보고하므로 클라우드에서 소프트웨어 제품의 빠른 성능 테스트를 위한 프레임워크가 됩니다. 병렬화 기술을 사용하여 필요한 신뢰 수준, 더 높은 정밀도 및 사용자 정의 가능한 회귀 분석을 통해 CI/CD 파이프라인에서 빌드의 성공 또는 실패를 판별하는 테스트 결과를 제공합니다.

마지막으로, 부하 테스트에 대해 언급하려면 부하 테스트의 영향을 측정하는 방법에 대해 이야기해야 하는데, 이는 원격 측정으로 돌아갑니다. 우리는 OpenTelemetry의 잠재력에 대해 기대하고 있으며, 곧 더 포괄적인 구현을 구현할 수 있기를 바랍니다. 전체 구현이 없더라도, 우리의 목표는 테스트를 실행하고, 영향을 측정하고, 데이터가 알려주는 내용에 대한 운영 결정을 내리는 것입니다.



위 내용과 같이 NGINX Ingress Controller 를 활용하여 Demo 가 필요하시면 하단의 전문가에게 상담받기 버튼을 클릭해주세요



전문가에게 상담받기

프로필 이미지
관리자
2025-01-17
조회 2


NGINX Modern Apps Reference Architecture (MARA) 프로젝트를 시작했을 때 , 우리는 이미 플랫폼에 익숙했고 부서 예산으로 비용을 지불할 수 있었기 때문에 AWS를 IaaS 공급자로 선택했습니다. 물론 모든 사람이 같은 경험이나 예산을 가지고 있는 것은 아니며, 여러분 중 많은 분들이 K3s , Canonical MicroK8s , minikube  와 같은 Kubernetes 배포판을 사용하여 로컬에서(랩 기반 환경 또는 워크스테이션에서) MARA를 실행할 수 있는 옵션을 제공해 달라고 요청했습니다 .

여러분의 의견을 듣고, 오늘 MicroK8s에서 MARA를 테스트 했으며, 여러분이 직접 배포할 수 있도록 지침을 제공하게 되어 기쁩니다!

워크스테이션에서 실행되는 NGINX Modern Apps Reference Architecture의 토폴로지를 보여주는 다이어그램

왜 우리는 테스트를 위해 MicroK8s를 선택했을까요? 그것은 MARA에 필요한 DNS, 스토리지, 이탈 기능을 낮은 메모리 Foot-Print로 배포하기 쉬운 모델로 제공하기 때문입니다. MicroK8s를 사용하면 테스트 시나리오를 쉽고 반복적으로 반복하여 합리적인 수준의 성능을 제공하는 배포에 대한 최소 요구 사항을 결정할 수 있습니다.

이 작업이 다른 Kubernetes 배포판의 테스트를 용이하게 할 것으로 기대합니다. 다양한 배포판의 현재 상태에 대한 정보는 GitHub repo를 참조하세요 . 목록에 포함시키고 싶은 선호하는 배포판이 있으면 포크하고 테스트하고 풀 리퀘스트를 생성하세요!


리소스 제약 처리

MARA를 로컬로 실행하는 데 가장 큰 제약은 메모리와 CPU입니다. 예비 테스트 중에 메모리 고갈과 관련된 문제의 대부분이 Elasticsearch와 관련이 있다는 것을 발견했습니다. Kibana는 매우 적은 양의 메모리( 16GB 미만 )가 있는 구성에서는 거의 사용할 수 없습니다. 이 문제를 해결하기 위해 MARA 구성 파일에 전체 Elasticsearch 배포에 일반적으로 있는 중복 보호 기능을 제거하는 설정을 제공했습니다. 이로 인해 실패 모드 수가 늘어나지만 리소스가 제한된 환경에서는 필요한 트레이드오프 입니다.

CPU에 대한 제약은 샘플 Bank of Sirius 애플리케이션 에 부과되는 부하량과 직접 연결됩니다 . MARA 배포에는 Bank of Sirius에 부하를 생성하는 Locust가 포함되어 있으며 , 사용자 수와 새 사용자의 생성 속도에 대한 사용자 제어 설정이 있습니다.

Bank of Sirius의 부하를 늘리면 나머지 시스템에도 영향을 미칩니다. 사용자 Response 속도가 너무 높으면 MARA 성능이 저하되어 구성 요소가 충돌하거나 멈출 가능성이 높습니다. 이러한 동작을 일으키는 값은 사용 가능한 CPU에 따라 다르지만 요구 사항 에 지정된 용량 이상을 사용하여 최대 64명의 사용자와 한 번에 16명의 사용자로 생성된 부하를 처리할 수 있는 배포를 기대할 수 있습니다.

MicroK8s에 MARA 배포

이제 배경 지식을 갖추었으니, MicroK8s에서 MARA를 선보일 준비가 되었습니다!

요구 사항

  • root최소한 Ubuntu 20.04(Focal) 이상 을 실행하는 시스템(베어메탈 Linux 서버, 가상화 또는 클라우드)에 액세스 :

    • 20GB 디스크
    • 16GB 메모리
    • 4개의 CPU와 동일
  • MARA에 필요한 모든 라이브러리와 바이너리가 있는 로컬 시스템의 Python 3 가상 환경. Python 3이 아직 설치되지 않았다면 다음 명령을 실행합니다.

    $  sudo apt update$  sudo apt install -y python3-venv
  • MicroK8s의 통합 MetalLB 로드 밸런서가 NGINX Ingress Controller egress에 할당할 최소 하나의 무료 IPv4 주소 . 로컬호스트를 통해 Bank of Sirius 애플리케이션에 액세스하는 경우 사용 가능한 개인 ( RFC 1918 호환) 주소가 허용됩니다. 예를 들어 네트워크가 192.168.100.0/24인 경우 10.10.10.10과 같은 주소를 사용할 수 있습니다.

  • Pulumi 계정과 액세스 토큰. 아직 없다면 Deploy MARA 의 1단계 에서 만들게 됩니다 .

    Pulumi에서는 상태 파일을 S3 호환 객체 저장소나 로컬 파일 시스템에 저장할 수 있지만 MARA에서는 작성 시점에 이를 지원하지 않습니다. 이 제한은 MARA 또는 Pulumi의 향후 릴리스에서 제거될 예정입니다.

MicroK8s 설치 및 구성

  1. MicroK8s 설치:

    $ sudo snap install microk8s --classicmicrok8s (1.23/stable) v1.23.3 from Canonical✓ installed
  2. 명령을 실행하는 데 필요한 권한을 설정합니다 microk8s. 의 경우 시스템에 대한 권한이 <username>있는 계정을 대체합니다 .root

    $ sudo usermod -a -G microk8s <username>$ sudo chown -f -R <username> ~/.kube
    $ newgrp microk8s
  3. 새로운 권한이 적용되도록 루트 권한이 있는 계정에서 로그아웃했다가 다시 로그인하세요.

  4. DNS , 스토리지 , MetalLB 에 대한 MicroK8s 애드온을 활성화합니다 .

    프롬프트에서 다음 중 하나를 나타내는 형식의 IP 주소 범위를 지정하세요.X.X.X.X‑X.X.X.Y

    • 개인 IP 주소의 실제 범위(예: 192.168.100.100-192.168.100.110아래에 사용된 값)
    • 단일 개인 IP 주소(예: 192.168.100.100-192.168.100.100)
  5. $ microk8s enable dns storage metallbEnabling DNS
    Applying manifest
    ...
    Restarting kubelet
    DNS is enabled
    Enabling default storage class
    ...
    Storage will be available soon
    Enabling MetalLB
    Enter each IP address range delimited by comma (e.g. '10.64.140.43-10.64.140.49,192.168.0.105-192.168.0.111'): 192.168.100.100-192.168.100.110
    Applying Metallb manifest
    ...
    MetalLB is enabled
  6. MicroK8s가 실행 중인지 확인하세요:

    $ microk8s statusmicrok8s is running
    high-availability: no
      datastore master nodes: 127.0.0.1:19001
      datastore standby nodes: none
    addons:
      enabled:
        dns           # CoreDNS
        ha-cluster    # Configure high availability on the current node
        metallb       # Loadbalancer for your Kubernetes cluster
        storage       # Storage class; allocates storage from host directory
    ...
  7. 대부분의 유틸리티가 찾을 것으로 예상하는 파일( ~/.kube/config )에 MicroK8s 구성을 로드하고 디렉토리 및 파일에 권장되는 권한을 설정합니다.

    $ microk8s config > ~/.kube/config$ sudo chmod 0644 ~/.kube/config

MARA Repo 복제 및 MicroK8s 클러스터 설정

  1. MARA 저장소를 복제하고 Bank of Sirius 하위 모듈을 초기화합니다.

    $ git clone https://github.com/nginxinc/kic-reference-architectures.git$ cd kic-reference-architectures/
    $ git submodule update --init --recursive --remote
  2. 복제된 MARA 리포의 루트 디렉토리에서 작업합니다(이전 단계에서 해당 디렉토리를 변경했습니다). MicroK8s 클러스터에 대한 Python 가상 환경을 설정합니다.

    $ ./bin/setup_venv.sh

    이 명령은 긴 추적을 생성합니다. 오류가 있는 경우 MARA GitHub repo의 알려진 문제/주의 사항 섹션에서 제안 사항을 확인하세요.

  3. Python 가상 환경을 활성화합니다. 이 명령은 PATH가상 환경을 사용하도록 사용자 및 기타 환경 변수를 설정합니다.

    $ source ./pulumi/python/venv/bin/activate
  4. MicroK8s 클러스터가 MARA 배포에 맞게 올바르게 구성되었는지 확인하세요.

    $ ./bin/testcap.sh
    This script will perform testing on the current kubernetes installation using the currently active kubernetes configuration and context.
    Any failures should be investigated, as they will indicate that the installation does not meet the minimum set of capabilities required to run MARA.
    
    ...
    ==============================================================
    | All tests passed! This system meets the basic requirements |
    | to deploy MARA.                                            |
    ==============================================================


MARA 배치

이 섹션에서 MARA를 배포하는 데 사용되는 스크립트 start.sh는 배포가 성공하기 위해 추가 작업이 필요한 옵션을 수용합니다. 단순성을 위해 여기서는 다음과 같은 기본 배포를 가정합니다.

  • 다른 지원되는 배포 옵션 중 하나가 아닌 kubeconfig 파일을 사용합니다. 다른 옵션에 대한 자세한 내용은 GitHub repo의 시작 가이드를 참조하세요.
  • 우리가 MARA를 테스트한 NGINX 오픈 소스의 최신 버전을 사용합니다(반드시 최신 버전일 필요는 없습니다).
  • NGINX Open Source 기반의 NGINX Ingress Controller를 사용합니다. NGINX Plus 기반의 NGINX Ingress Controller를 사용하려면 Kubernetes 클러스터의 F5 Docker 레지스트리에서 NGINX Plus 기반 이미지를 사용해야 합니다. 자세한 내용은 아래 3단계NOTICE! 의 첫 번째를 참조하세요.
  • 단일 표준 Kubernetes 컨텍스트를 사용합니다. NOTICE!3단계의 두 번째를 참조하세요.

MicroK8s 클러스터에 MARA 배포:

  1. 스크립트를 실행합니다 start.sh.

    아직 Pulumi를 사용하도록 워크스테이션을 구성하지 않은 경우 Pulumi에 로그인하라는 메시지가 표시되고(필요한 경우 계정 생성) Pulumi 계정과 연결된 API 토큰을 입력하라는 메시지가 표시됩니다.

    $ ./bin/start.shAdding to [/home/ubuntu/kic-reference-architectures/bin/venv/bin] to PATH
    Manage your Pulumi stacks by logging in.
    Run `pulumi login --help` for alternative login options.
    Enter your access token from https://app.pulumi.com/account/tokens
        or hit <ENTER> to log in using your browser            : <token>
    
    Please read the documentation for more details.
  2. 배포 유형을 선택하고 k프롬프트에 입력하여 kubeconfig 파일로 배포를 빌드합니다. makeDocker가 설치되지 않았다는 경고는 무시합니다. 대신 배포는 레지스트리의 NGINX Ingress Controller 이미지를 사용합니다.

    Type a for AWS, k for kubeconfig? k
    Calling kubeconfig startup script
    make is not installed - it must be installed if you intend to build NGINX Kubernetes Ingress Controller from source.
    docker is not installed - it must be installed if you intend to build NGINX Kubernetes Ingress Controller from source.

  3. 프롬프트에서 생성할 Pulumi 스택의 이름을 지정합니다(여기서는 mara). Pulumi 계정 내에서 고유해야 합니다.

    Enter the name of the Pulumi stack to use in all projects: maraSubmodule source found
    Configuring all Pulumi projects to use the stack: mara
    Created stack 'mara'
    
    NOTICE! Currently the deployment via kubeconfig only supports pulling images from the registry! A JWT is required in order to access the NGINX Plus repository. This should be placed in a file in the extras directory in the root, in a file named jwt.token
    
    See https://docs.nginx.com/nginx-ingress-controller/installation/using-the-jwt-token-docker-secret/ for more details and examples.
    
    No JWT found; writing placeholder manifest
    
    NOTICE! When using a kubeconfig file you need to ensure that your environment is configured to connect to Kubernetes properly. If you have multiple kubernetes contexts (or custom contexts) you may need to remove them and replace them with a simple ~/.kube/config file. This will be addressed in a future release.
  4. 프롬프트에서 kubeconfig 파일의 전체 경로와 클러스터 이름을 지정합니다. 여기에 있습니다 ./home/<username>/.kube/configmicrok8s-cluster

    Provide an absolute path to your kubeconfig filevalue: /home/<username>/.kube/config
    Provide your clustername
    value: microk8s-cluster
    Attempting to connect to kubernetes cluster
  5. 다음 프롬프트에서 클러스터의 정규화된 도메인 이름(FQDN)을 지정합니다. 스크립트는 FQDN을 두 가지 목적으로 사용합니다. NGINX Ingress Controller를 구성하고 자체 서명된 인증서를 만드는 것입니다(두 번째 용도는 값이 IP 주소가 될 수 없음을 의미합니다). 다른 FQDN을 대체하는 경우 mara.example.com다음 단계에서도 사용해야 합니다.

  6. Create a fqdn for your deploymentvalue: mara.example.com
  7. Grafana 관리자 비밀번호를 지정하세요:

    Create a password for the grafana admin user; this password will be used to access the Grafana dashboardThis should be an alphanumeric string without any shell special characters; it is presented in plain text due to current limitations with Pulumi secrets. You will need this password to access the Grafana dashboard.
    value: <password>
  8. 설치 과정의 흔적이 나타나며 각 단계에 대한 다음 정보가 표시됩니다.

    • 단계에서 수행되는 주요 작업을 설명하는 배너(예: LogstoreElasticsearch 배포 시작을 알림)
    • Pulumi가 수행할 작업 목록
    • 각 Pulumi 작업에 대한 실시간 상태 표시기
    • 예를 들어 Pulumi 및 MARA에서 생성된 진단은 정의된 호스트 이름 및 IP 주소입니다.
    • 영향을 받는 자원의 수
    • 경과 시간
  9. 마지막 단계(Bank of Sirius의 경우)가 완료되면 추적에서는 MetalLB가 NGINX Ingress Controller에 할당한 IP 주소(여기 192.168.100.100)와 배포를 위해 선택한 FQDN(여기 mara.example.com)을 배포에 대한 기타 정보와 함께 보고합니다.

    The startup process has finished successfully
    Next Steps:
    1. Map the IP address (192.168.100.100) of your Ingress Controller with your FQDN (mara.example.com).
    2. Use the ./bin/test-forward.sh program to establish tunnels you can use to connect to the management tools.
    3. Use kubectl, k9s, or the Kubernetes dashboard to explore your deployment.
    
    To review your configuration options, including the passwords defined, you can access the pulumi secrets via the following commands:
    
    Main Configuration: pulumi config -C /jenkins/workspace/jaytest/bin/../pulumi/python/config
    
    Bank of Sirius (Example Application) Configuration: pulumi config -C /jenkins/workspace/jaytest/bin/../pulumi/python/kubernetes/applications/sirius
    
    K8 Loadbalancer IP: kubectl get services --namespace nginx-ingress
    
    Please see the documentation in the github repository for more information
  10. 이전 단계에서 보고된 FQDN과 IP 주소 간의 매핑을 FQDN을 확인하는 데 사용하는 도구(로컬 /etc/hosts 파일 또는 DNS 서버 등)에서 만듭니다 .

  11. MARA 배포에 대한 요청이 성공했는지 확인합니다. 자체 서명된 인증서를 수락하도록 -k옵션을 포함합니다 curl. 인증서에 대한 자세한 정보를 표시하려면 옵션 을 추가합니다 -v.

    $ curl  -k -I https://mara.example.comHTTP/1.1 200 OK
    Server: nginx/1.21.5
    Date: Day, DD Mon YYYY hh:mm:ss TZ
    Content-Type: text/html; charset=utf-8
    Content-Length: 7016
    Connection: keep-alive
  12. 브라우저에서 https://mara.example.com 으로 이동하여 Bank of Sirius 웹사이트를 표시합니다. 이 글을 쓰는 시점에서 많은 브라우저(Firefox 및 Safari 포함)에서는 자체 서명 인증서를 사용하여 사이트에 대한 경고를 안전하게 클릭할 수 있습니다. Chrome을 사용하지 않는 것이 좋습니다. 최근 보안 변경으로 인해 사이트에 액세스하는 것이 금지될 가능성이 높습니다.

  13. 스크립트를 실행하여 test-forward.shKubernetes 포트 포워딩을 설정하여 MARA 관리 제품군( Elasticsearch , Grafana , Kibana , Locust , Prometheus )의 도구에 액세스할 수 있습니다 . 스크립트는 적절한 서비스 이름을 결정하고 kubectl명령을 실행하여 로컬 포트로 전달합니다.

    참고: 포트 포워딩이 제대로 작동하려면 브라우저가 이 명령을 실행하는 명령 셸과 동일한 시스템에서 실행 중이어야 합니다. 그렇지 않은 경우(예: 가상화 환경을 사용하는 경우) 명령은 성공한 것처럼 보이지만 포트 포워딩은 실제로 작동하지 않습니다. 자세한 내용은 GitHub 리포지토리에서 MARA의 관리 도구 액세스를 참조하세요.

    $ ./bin/test-forward.shConnections Details
    ====================================
    Kibana:        http://localhost:5601
    Grafana:       http://localhost:3000
    Locust:        http://localhost:8089
    Prometheus:    http://localhost:9090
    Elasticsearch: http://localhost:9200
    ====================================
    
    Issue Ctrl-C to Exit

요약

그게 다입니다! 이 지침을 따르면 약 20분 이내에 사용자 환경에서 작동하는 MARA 배포가 실행됩니다. 이 시점에서 다른 Kubernetes 애플리케이션과 마찬가지로 Bank of Sirius 애플리케이션과 상호 작용할 수 있습니다. 시작하기에 좋은 방법은 내장된 관찰 도구를 사용하여 Locust로 다양한 양의 부하를 생성할 때 환경이 어떻게 작동하는지 테스트하는 것입니다.

우리의 목표는 가능한 한 많은 Kubernetes 사용자에게 MARA를 최대한 유용하게 만드는 것입니다. 일부 구성 요소에 대한 선택 사항이 마음에 들지 않으신가요? 구성 요소를 대체하고 공유하고 싶으시다면 풀 리퀘스트를 여는 것을 권장합니다. 또한, 우리의 repo의 Issues and Discussions 페이지 에서 생각을 공유하고 질문을 해주세요. 의심스러운 가정에 대한 질문도 포함됩니다.



위 내용과 같이 NGINX Ingress Controller 를 활용하여 Demo 가 필요하시면 하단의 전문가에게 상담받기 버튼을 클릭해주세요



전문가에게 상담받기

프로필 이미지
관리자
2025-01-17
조회 5

NGINX에서는 지난 몇 년 동안 애플리케이션을 진정으로 현대적이고 적응적으로 만들어야 할 필요성에 대해 논의해 왔습니다 . 즉, 이식성, 클라우드 네이티브, 복원성, 확장성 및 업데이트 용이성을 갖춰야 합니다. 최근에는 현대적 앱의 생성과 제공을 용이하게 하는 두 가지 개념이 대두되었습니다. 첫 번째는 Platform Ops 로, 기업 수준의 플랫폼 팀이 개발 및 DevOps 팀이 업무를 수행하는 데 필요한 모든 도구를 큐레이션, 유지 관리, 연결 및 보안합니다. 두 번째는 Shifting Left로 , 개발 라이프사이클의 초기 단계에서 프로덕션 등급 보안, 네트워킹 및 모니터링을 애플리케이션에 통합하는 것을 의미합니다. 개발자는 이전에 ITOps에 속했던 기능에 대한 책임이 더 커지지만 동시에 해당 기능을 구현하는 방법에 대한 선택권과 독립성이 더 커집니다.

좋은 말처럼 들리지만, 실제로 Platform Ops를 구현하고 인프라와 운영 툴링을 "좌측으로 이동"하는 것은 어렵습니다. 우선, 점점 더 많은 앱이 컨테이너화된 환경에서 고도로 분산된 방식으로 배포되고 있으며, 증가하는 수의 Kubernetes 오케스트레이션 엔진 중 하나를 사용하고 있습니다. 또한 기업은 클라우드 간 및 클라우드와 온프레미스 환경 간의 차이에 얽매이지 않고 여러 환경에 앱을 배포하고자 합니다.

현대 앱을 위한 "황금 이미지"

당연히 그렇듯이, 우리의 고객과 커뮤니티는 직면한 과제에 대한 도움을 계속 요청합니다. 그들은 모든 좋은 것을 원하지만, 보안, 네트워킹, 관찰 가능성 및 성능 모니터링, 확장 등 모든 부분을 하나로 모으려면 실제 작업이 필요합니다. 프로덕션 환경에 충분히 견고한 결과 플랫폼을 만들려면 더 많은 작업이 필요합니다. 그들은 "단일 리포에서 실행할 수 있는 최신 앱에 대한 '골든 이미지'가 없는 이유는 무엇일까?"라고 궁금해합니다.

좋은 질문이고, 우리는 좋은 답을 내는 것을 우리만의 과제로 삼았습니다. 첫째, 우리는 질문을 더 구체적으로 재구성했습니다. 우리는 고객과 커뮤니티가 다음과 같은 질문을 하고 있다고 생각합니다. "다양한 소프트웨어 제품을 더욱 응집력 있는 전체로 통합하고, 스택을 조정하여 올바른 구성과 설정을 확정하고, 작업과 수고를 덜어줄 수 있나요? 그리고 기본 서비스와 기능의 차이로 인해 주요 구성을 변경하지 않고도 다양한 클라우드에서 애플리케이션을 실행하기 쉽게 만들어줄 수 있나요?"

우리는 이러한 질문을 전체 커뮤니티에 유익한 것으로 진정으로 해결하는 솔루션을 봅니다. 수백 개의 기업과 모든 주요 클라우드 공급업체의 파트너뿐만 아니라 진정으로 제로섬이 아닌 승리입니다. 이상적으로는 솔루션이 "장난감"이 아니라 견고하고 테스트되었으며 Kubernetes 환경에서 실행되는 라이브 프로덕션 애플리케이션에 배포할 준비가 된 코드입니다. 그리고 솔직히 말해서, 우리는 누구나 GitHub에서 바로 우리의 작업을 훔칠 수 있기를 바랍니다.

요점은, 오늘 NGINX Sprint 2.0 에서 우리는 솔루션 출시를 발표합니다. 모던 앱 레퍼런스 아키텍처 (MARA)의 첫 번째 반복, 모던 앱을 위한 오픈 소스 아키텍처 및 배포 모델입니다. 여러분이 좋아하고, 사용하고, 훔치고, 더 나은 방법으로 개선하거나 사용자 지정하기 위해 수정하거나 포크하기를 바랍니다. 이 게시물은 우리가 무엇을 만들고 어떻게 작동하는지 살펴봅니다.


현대적 적응형 애플리케이션 정의

먼저, 이상적인 현대적이고 적응적인 애플리케이션을 정의해 보겠습니다. 마이크로서비스로 구성되고, 컨테이너화되고, 클라우드 네이티브 디자인 원칙(느슨하게 결합되고, 확장하기 쉽고, 인프라에 묶이지 않음)을 준수할 수 있지만 반드시 그럴 필요는 없습니다. 현대 애플리케이션의 정신의 일부는 인프라 추상화를 활용하도록 특별히 설계하는 것입니다. 이 정의는 간단하지만 모든 참조 아키텍처에 대한 기본 템플릿을 확립하기 때문에 중요합니다.

최신 애플리케이션 아키텍처의 핵심 요소로는 이식성, 확장성, 복원성, 민첩성이 있습니다.

  • 이동성  – 다양한 유형의 기기와 인프라, 퍼블릭 클라우드와 온프레미스에 애플리케이션을 쉽게 배포할 수 있습니다.
  • 확장성  – 앱은 전 세계 어디에서나 수요의 급증이나 감소에 맞춰 신속하고 원활하게 확장하거나 축소할 수 있습니다.
  • 복원성  – 앱은 다양한 가용성 지역, 클라우드 또는 데이터 센터에 있는 새로 구동된 클러스터나 가상 환경으로 우아하게 장애 조치(failover)할 수 있습니다.
  • 민첩성  – 앱은 자동화된 CI/CD 파이프라인을 통해 빠르게 업데이트될 수 있습니다. 최신 앱의 경우 이는 더 빠른 코드 속도와 더 빈번한 코드 푸시를 의미합니다.

참조 아키텍처 설계

우리는 최신 앱 정의와 배포 패턴의 기본 요구 사항을 충족하는 플랫폼을 만들고 싶었습니다. 기술적 목표 외에도 최신 앱 디자인 원칙을 설명하고 커뮤니티가 Kubernetes에서 배포하도록 장려하고 싶었습니다. 그리고 물론, 개발자, DevOps 및 Platform Ops 팀이 놀고, 수정하고, 개선할 수 있는 "훔칠 수 있는" 코드를 제공하고 싶었습니다. 간단히 말해서, 우리는 다음을 제공하고 싶었습니다.

  • 장난감이 아닌 쉽게 배포 가능하고 프로덕션에 적합한 Kubernetes 아키텍처
  • Kubernetes에서 파트너 제품이 작동하는 방식을 강조하는 플랫폼
  • Kubernetes Ingress 컨트롤러를 쉽게 빌드하고 배포할 수 있는 푸시 버튼
  • 향후 제품 및 제휴 통합을 위한 테스트 환경
  • 플러그형 배포 프레임워크
  • 발견 및 채택을 단순화하는 오픈 소스 코드의 단일 리포

플랫폼의 첫 번째 버전을 위해 내린 디자인과 파트너십 선택 사항은 다음과 같습니다(다음 버전에 대한 계획은 버전 2의 Many More Integrations and More Flexibility 참조 ). 우리는 레퍼런스 앱을 파트너에게 포괄적으로 만드는 것이 파트너와 커뮤니티 참여를 촉진하는 데 중요하다고 굳게 믿습니다.

  • 오픈 소스 개발 – https://github.com/nginxinc/kic-reference-architectures/ ; NGINX/F5 커뮤니티와 협력하여 리포를 구축했습니다.
  • 배포 대상 – Amazon Elastic Kubernetes Service (EKS)
  • Infrastructure-as-Code 자동화 – Python 및 Pulumi 는 거의 모든 인기 있는 코딩 언어에서 Terraform 레시피 및 자동화 스크립트를 허용합니다.
  • Ingress Controller 이미지 – 구독자를 위해 사전 빌드된 NGINX Plus , DockerHub에서 사전 빌드된 NGINX Open Source , 소스에서 빌드된 두 버전
  • 로그 관리(저장 및 분석) – Elastic , 사용자들에게 매우 인기가 많기 때문에
  • 성능 모니터링 및 대시보드 – Prometheus 및 Grafana
  • 지속적인 개발(CD) – Spinnaker
  • TLS – 인증서 관리자
  • 데모 애플리케이션 – Google Bank of Anthos

코드가 배포되는 방법

샘플 애플리케이션을 설치하고 배포하려면 시작 스크립트를 호출하는 단일 명령을 실행하고 다음 Pulumi 프로젝트가 표시된 순서대로 실행됩니다. 각 프로젝트 이름은 리포지토리의 루트 디렉토리를 기준으로 디렉토리 이름에 매핑됩니다 . 자세한 내용은 README를 참조하세요 .

vpc - Defines and installs VPC and subnets to use with EKS  └─eks - Deploys EKS
    └─ecr - Configures ECR for use in EKS cluster
      └─kic-image-build - Builds new NGINX Ingress Controller image
        └─kic-image-push - Pushes image built in previous step to ECR
          └─kic-helm-chart - Deploys NGINX Ingress Controller to EKS 
                             cluster
            └─logstore - Deploys Elastic log store to EKS cluster
              └─logagent - Deploys Elastic (filebeat) logging agent to 
                           EKS cluster
               └─certmgr - Deploys cert-manager.io Helm chart to EKS 
                           cluster
                 └─anthos - Deploys Bank of Anthos application to EKS 
                            cluster

버전 2에서는 더 많은 통합과 더 큰 유연성이 제공됩니다.

저희는 초기 노력이 Kubernetes 환경에 필요한 모든 통합을 제공하지 못할 수 있다는 점을 알고 있습니다. Platform Ops는 스마트하지만 무제한적인 선택에 관한 것입니다. Platform Ops, DevOps 및 개발자 팀이 새로운 참조 플랫폼을 시도하고 잠재적으로 채택하기 쉽도록 단기적으로 다음을 포함한 많은 개선 사항을 계획하고 있습니다.

  • Digital Ocean, OpenShift, Rancher, vSphere 및 기타 Kubernetes 환경을 구축하세요.
  • NGINX Controller와 통합하여 NGINX Plus Ingress Controller를 관리하고 모니터링합니다.

    [ 편집기  – NGINX Controller는 이제 F5 NGINX Management Suite 입니다 .]

  • NGINX App Protect 에 대한 기본 구성 제공
  • BIG‑IP , 클라우드 서비스 , Volterra 와 같은 F5 제품 및 서비스와 통합
  • NGINX Service Mesh 및 Istio 기반 Aspen Mesh 와 통합
  • Terraform 및 기타 자동화 도구 와 기본적으로 통합
  • 다른 CI/CD 옵션 지원
  • 인프라 및 애플리케이션 서비스에 대해 별도 또는 여러 클러스터를 배포합니다.

저희는 저희의 작업이 다른 참조 플랫폼의 프레임워크가 되고 모든 유형의 차별화된 현대적 애플리케이션을 구축하기 위한 "도용 가능한" 시작점이 되기를 바랍니다. Kubernetes는 현대적 애플리케이션을 구축하고 Platforms Ops와 Shift‑left 문화를 강화하는 데 매우 강력한 메커니즘이기 때문에 참조 아키텍처가 더 광범위하고 플러그인이 가능할수록 더 좋습니다. 저희는 여러분, 커뮤니티가 저희 작업에 대해 어떻게 생각하는지, 그리고 더 중요한 것은 여러분이 그것으로 무엇을 구축하는지 보고 싶습니다.



위 내용과 같이 NGINX Ingress Controller 를 활용하여 Demo 가 필요하시면 하단의 전문가에게 상담받기 버튼을 클릭해주세요



전문가에게 상담받기

프로필 이미지
관리자
2025-01-17
조회 16


최근 몇 개의 블로그 게시물에서 애플리케이션을 마이크로서비스의 집합으로 개발 및 배포하는 

4계층 애플리케이션 아키텍처를 채택하는 것이 중요한 이유를 설명한 바 있습니다. 

10년 전에도 잘 작동했던 개발 프로세스와 애플리케이션 아키텍처를 계속 사용한다면 

점점 더 많은 앱 중에서 선택할 수 있는 모바일 사용자의 관심을 사로잡고 유지할 수 없다는 사실이 점점 더 분명해지고 있습니다.

마이크로서비스 아키텍처로 전환하면 기업들은 시장에서 흥미로운 기회를 창출할 수 있습니다. 


시스템 설계자와 개발자에게는 고객에게 혁신적인 새로운 웹 경험을 제공할 때 전례 없는 수준의 제어와 속도를 약속합니다. 

하지만 이렇게 숨 가쁜 속도에서는 오류가 발생할 여지가 많지 않은 것처럼 느껴질 수 있습니다. 

현실에서는 앱 개발과 배포를 중단할 수 없으므로 이를 위한 프로세스를 재구축해야 합니다. 

미래의 성공이 마이크로서비스 아키텍처로의 전환에 달려 있다는 것을 알고 있지만 

실제로는 어떻게 해야 할까요?


다행히도 마이크로서비스의 여러 얼리어답터들이 공개 코드뿐만 아니라 

컨퍼런스 프레젠테이션과 블로그 게시물을 통해 

오픈 소스 정신에 입각하여 전문 지식을 아낌없이 공유하고 있습니다. 

Netflix가 대표적인 예입니다. 웹 엔지니어링 디렉터와 클라우드 아키텍트를 역임한

 Adrian Cockcroft는 100명의 엔지니어가 모놀리식 DVD 대여 애플리케이션을 제작하는 

기존 개발 모델에서 매일 수백만 명의 Netflix 고객에게 디지털 엔터테인먼트를 스트리밍하는 

수백 개의 마이크로서비스 엔드투엔드 개발을 담당하는 여러 소규모 팀이 함께 일하는 

마이크로서비스 아키텍처로 전환하는 과정을 감독했습니다. 

현재 배터리 벤처스의 기술 펠로우인 콕크로프트는 마이크로서비스 및 클라우드 네이티브 아키텍처의 저명한 전도사이며 

NGINX 기술 자문위원회에서 활동하고 있습니다.

2부로 구성된 블로그 게시물 시리즈에서는 작년 10월에 열린 첫 번째 연례 NGINX 컨퍼런스와 

몇 달 전 실리콘밸리 마이크로서비스 밋업에서 콕크로프트가 발표한 두 강연의 주요 내용을 소개합니다. 

(전체 동영상 녹화본도 시청할 가치가 있습니다.)

  • 이 게시물에서는 마이크로서비스 아키텍처를 정의하고 설계를 위한 몇 가지 모범 사례를 설명합니다.
  • 넷플릭스에서 마이크로서비스 도입하기: 
  • 팀 및 프로세스 설계를 위한 교훈에서는 소프트웨어 개발을 위해 새로운 사고방식을 채택하고 
  • 이를 중심으로 팀을 재구성하는 이유와 방법에 대해 설명합니다.


마이크로서비스 아키텍처란 무엇인가요?

콕크로프트는 마이크로서비스 아키텍처를 경계가 있는 느슨하게 결합된 요소로 구성된 서비스 지향 아키텍처로 정의합니다.

<느슨하게 결합되어 있다는 것은 서비스를 독립적으로 업데이트할 수 있고, 한 서비스를 업데이트해도 

다른 서비스를 변경할 필요가 없다는 것을 의미합니다. 

소규모의 전문화된 서비스가 여러 개 있지만 함께 업데이트해야 하는 경우

느슨하게 결합되어 있지 않으므로 마이크로 서비스가 아닙니다. 

마이크로서비스 아키텍처로 전환할 때 사람들이 간과하기 쉬운 결합 유형 중 하나는 데이터베이스 결합으로, 

모든 서비스가 동일한 데이터베이스에 연결되고 서비스를 업데이트하려면 스키마를 변경해야 합니다. 


데이터베이스를 분할하고 비정규화해야 합니다.

바운드 컨텍스트라는 개념은 Eric Evans의 도메인 중심 설계라는 책에서 유래했습니다. 

컨텍스트가 올바르게 바인딩된 마이크로서비스는 소프트웨어 개발 목적에 따라 독립적입니다. 

마이크로서비스와 그 동료는 API를 통해 엄격하게 상호 작용하므로 

데이터 구조, 데이터베이스 스키마 또는 기타 객체의 내부 표현을 공유하지 않으므로 

동료의 내부에 대해 전혀 몰라도 마이크로서비스의 코드를 이해하고 업데이트할 수 있습니다.

인터넷용 애플리케이션을 개발해 본 적이 있다면 이름만 다르지 실제로는 이러한 개념에 이미 익숙할 것입니다. 


대부분의 모바일 앱은 사용자가 앱의 컨텍스트 내에서 

Facebook에서 공유하고, Google 지도에서 길을 찾고, Foursquare에서 레스토랑을 찾는 등의 

작업을 수행할 수 있도록 꽤 많은 백엔드 서비스와 통신합니다. 

모바일 앱이 이러한 서비스와 긴밀하게 연결되어 있다면 

업데이트를 릴리스하기 전에 모든 개발 팀과 상의하여 변경 사항으로 인해 서비스가 중단되지 않는지 확인해야 합니다.


마이크로서비스 아키텍처로 작업할 때는 인터넷 백엔드와 같은 다른 내부 개발 팀을 

마이크로서비스가 API를 통해 상호 작용하는 외부 서비스로 생각하면 됩니다. 

마이크로서비스 간에 일반적으로 이해되는 '계약'은 API가 안정적이고 앞으로 호환된다는 것입니다. 

Google 지도 API가 사용자에게 피해를 주는 방식으로 경고 없이 변경되는 것이 허용되지 않는 것처럼,

 API는 발전할 수 있지만 이전 버전과 호환성을 유지해야 합니다.


마이크로서비스 아키텍처 설계를 위한 모범 사례

콕크로프트는 넷플릭스에서 클라우드 아키텍트로서 자신의 역할은 아키텍처를 제어하는 것이 아니라 

넷플릭스 엔지니어들이 아키텍처를 구축하면서 떠오른 아키텍처를 발견하고 공식화하는 것이라고 설명합니다. 

넷플릭스 개발팀은 마이크로서비스 아키텍처를 설계하고 구현하기 위한 몇 가지 모범 사례를 확립했습니다.

각 마이크로서비스에 대해 별도의 데이터 저장소 만들기

여러 마이크로서비스에서 동일한 백엔드 데이터 저장소를 사용하지 마세요. 

각 마이크로서비스의 팀이 해당 서비스에 가장 적합한 데이터베이스를 선택하도록 해야 합니다. 

게다가 단일 데이터 저장소를 사용하면 서로 다른 팀에서 작성한 마이크로서비스가 작업 중복을 줄인다는 명목으로 

데이터베이스 구조를 공유하기가 너무 쉽습니다. 


결국 한 팀이 데이터베이스 구조를 업데이트하면 해당 구조를 사용하는 

다른 서비스도 함께 변경해야 하는 상황이 발생하게 됩니다.

데이터를 분리하면 별도의 저장 시스템이 더 쉽게 동기화되지 않거나 일관성이 없어지고 

외래 키가 예기치 않게 변경될 수 있기 때문에 데이터 관리가 더 복잡해질 수 있습니다. 

불일치를 찾아 수정하려면 백그라운드에서 작동하여 마스터 데이터 관리(MDM)를 수행하는 도구를 추가해야 합니다. 

예를 들어, 가입자 ID를 저장하는 모든 데이터베이스를 검사하여 

모든 데이터베이스에 동일한 ID가 존재하는지(한 데이터베이스에 누락되거나 여분의 ID가 없는지) 확인할 수 있습니다. 

직접 도구를 작성하거나 도구를 구입할 수 있습니다. 

많은 상용 관계형 데이터베이스 관리 시스템(RDBMS)이 이러한 종류의 검사를 수행하지만, 

일반적으로 결합에 너무 많은 요구 사항을 부과하므로 확장되지 않습니다.


코드의 성숙도를 비슷한 수준으로 유지

마이크로서비스의 모든 코드를 비슷한 수준의 성숙도와 안정성으로 유지하세요. 

즉, 잘 작동하는 배포된 마이크로서비스에서 일부 코드를 추가하거나 다시 작성해야 하는 경우 

일반적으로 가장 좋은 방법은 기존 마이크로서비스는 그대로 두고 

새 코드 또는 변경된 코드에 대한 새 마이크로서비스를 만드는 것입니다. 


[편집자; - 이를 불변 인프라 원칙이라고도 합니다.] 

이렇게 하면 기존 마이크로서비스에 장애나 성능 저하가 발생할 위험 없이 새 코드가 버그가 없고 

최대한 효율적이 될 때까지 반복적으로 배포하고 테스트할 수 있습니다. 

새 마이크로서비스가 기존 마이크로서비스만큼 안정적이면 

두 마이크로서비스가 실제로 하나의 기능을 함께 수행하거나 

결합을 통해 다른 효율성이 있는 경우 다시 병합할 수 있습니다. 

하지만 콕크로프트의 경험에 따르면 마이크로서비스가 너무 커져서 분리해야 한다는 사실을 깨닫는 경우가 훨씬 더 흔합니다.


각 마이크로서비스에 대해 별도의 빌드 수행

각 마이크로서비스에 대해 별도의 빌드를 수행하여 

리포지토리에서 해당 리비전 레벨에 맞는 컴포넌트 파일을 가져올 수 있도록 하세요. 

이로 인해 여러 마이크로서비스가 비슷한 파일 집합을 가져오지만 

서로 다른 리비전 레벨에서 가져오는 상황이 발생하기도 합니다. 

이 경우 이전 파일 버전을 폐기하여 코드베이스를 정리하기가 더 어려워질 수 있지만

(리비전이 더 이상 사용되지 않는지 더 주의 깊게 확인해야 하므로), 

새 마이크로서비스를 구축하면서 새 파일을 추가하는 것이 더 쉬워진다는 점을 감안하면 감수할 수 있는 절충안이 될 수 있습니다. 

새로운 마이크로서비스, 파일 또는 함수를 도입하는 것이 위험하지 않고 쉽기를 바라는 의도적인 비대칭성입니다.


컨테이너에 배포

컨테이너에 마이크로서비스를 배포하는 것이 중요한 이유는 하나의 도구만 있으면 

모든 것을 배포할 수 있기 때문입니다. 마이크로서비스가 컨테이너에 있는 한, 도구는 배포 방법을 알고 있습니다. 

컨테이너가 무엇이든 상관없습니다. 그렇긴 하지만 Docker는 컨테이너의 사실상 표준으로 빠르게 자리 잡은 것 같습니다.


서버를 상태 비저장 상태로 취급

서버, 특히 고객 대면 코드를 실행하는 서버는 그룹의 상호 교환 가능한 멤버로 취급하세요. 

서버는 모두 동일한 기능을 수행하므로 개별적으로 신경 쓸 필요가 없습니다. 

필요한 작업량을 생산하기에 충분한 개수만 있으면 되고, 자동 스케일링을 사용하여 숫자를 위아래로 조정할 수 있습니다. 

한 서버가 작동을 멈추면 자동으로 다른 서버로 대체됩니다. 

특수 기능을 수행하기 위해 개별 서버에 의존하는 '눈송이' 시스템은 피하세요.

콕크로프트의 비유를 빌리자면 서버를 애완동물이 아닌 가축처럼 생각해야 한다는 것입니다. 


특수한 기능을 수행하는 기계가 있고 이름만 들어도 알 수 있고, 

그 기계가 고장 나면 모두가 슬퍼한다면 그 기계는 애완동물과 같이 소중해집니다.

대신 서버를 젖소통처럼 생각해야 합니다.

여러분은  몇 갤런의 우유가 나오는지를 신경씁니다. 

어느 날 평소보다 우유가 적게 나오는 것을 발견하면 어떤 젖소가 잘 생산되지 않는지 알아내어 교체합니다.



NGINX를 기반으로 구축된 넷플릭스 전송 아키텍처

넷플릭스는 NGINX 오픈 소스의 오랜 사용자였으며 2011년 통합 이후 NGINX의 첫 번째 고객이 되었습니다. 

실제로 넷플릭스는 전송 인프라의 핵심으로 세계 최대 규모의 콘텐츠 전송 네트워크(CDN) 중 

하나인 Open Connect의 핵심으로 NGINX를 선택했습니다. 


초당 수천, 때로는 수백만 건의 요청을 처리할 수 있는 NGINX와 NGINX;Plus는 

고성능 HTTP 전송을 위한 최적의 솔루션으로 넷플릭스와 같은 기업이 

매일 수백만 명의 고객에게 고품질 디지털 경험을 제공할 수 있도록 지원합니다.


nginx.conf 2014, 2014년 10월

마이크로서비스로 마이그레이션, 2부
실리콘밸리 마이크로서비스 밋업, 2014년 8월


마이크로서비스로 마이그레이션, 2부
실리콘밸리 마이크로서비스 밋업, 2014년 8월




위 내용과 같이 NGINX Ingress Controller 를 활용하여 Demo 가 필요하시면 하단의 전문가에게 상담받기 버튼을 클릭해주세요.


전문가에게 상담받기

프로필 이미지
관리자
2025-01-16
조회 5


편집자 - 이제 7부로 구성된 이 시리즈 기사가 완성되었습니다.

  1. 마이크로서비스 소개
  2. 마이크로서비스 구축하기: API 게이트웨이 사용
  3. 마이크로서비스 구축하기: 마이크로서비스 아키텍처의 프로세스 간 통신(이 문서)
  4. 마이크로서비스 아키텍처에서의 서비스 검색
  5. 마이크로서비스를 위한 이벤트 중심 데이터 관리
  6. 마이크로서비스 배포 전략 선택
  7. 모놀리스를 마이크로서비스로 리팩토링

또한 전체 문서와 NGINX를 사용하여 마이크로서비스를 구현하는 방법에 대한 정보를 전자책으로 다운로드할 수도 있습니다

 - 마이크로서비스: 설계부터 배포까지. 또한 새로운 마이크로서비스 솔루션 페이지도 살펴보세요.


이 글은 마이크로서비스 아키텍처로 애플리케이션을 구축하는 방법에 대한 시리즈의 세 번째 글입니다. 

첫 번째 문서에서는 마이크로서비스 아키텍처 패턴을 소개하고 이를 모놀리식 아키텍처 패턴과 비교하며 

마이크로서비스 사용의 장점과 단점에 대해 논의합니다. 


두 번째 글에서는 애플리케이션의 클라이언트가 API 게이트웨이라는 중개자를 통해 마이크로서비스와 통신하는 방법에 대해 설명합니다.

이 문서에서는 시스템 내의 서비스들이 서로 통신하는 방법을 살펴봅니다. 

네 번째 글에서는 서비스 검색과 밀접한 관련이 있는 문제를 살펴봅니다.

소개

모놀리식 애플리케이션에서 구성 요소는 언어 수준의 메서드나 함수 호출을 통해 서로를 호출합니다. 

이와 대조적으로 마이크로서비스 기반 애플리케이션은 여러 컴퓨터에서 실행되는 분산 시스템입니다. 

각 서비스 인스턴스는 일반적으로 하나의 프로세스입니다.

따라서 다음 다이어그램에서 볼 수 있듯이 서비스는 프로세스 간 통신(IPC) 메커니즘을 사용하여 상호 작용해야 합니다.


In a microservices application, the services need an inter-process communication (IPC) mechanism (whereas modules in a monolith can call routines)

나중에 구체적인 IPC 기술을 살펴보겠지만, 먼저 다양한 디자인 문제를 살펴보겠습니다.

상호 작용 스타일

서비스에 대한 IPC 메커니즘을 선택할 때는 먼저 서비스 상호 작용 방식을 고려하는 것이 유용합니다. 

클라이언트⇔서비스 상호 작용 스타일은 다양합니다. 

두 가지 차원으로 분류할 수 있습니다. 

첫 번째 차원은 상호 작용이 일대일인지 일대다인지 여부입니다:

  • 일대일 - 각 클라이언트 요청이 정확히 하나의 서비스 인스턴스에 의해 처리됩니다.
  • 일대다 - 각 요청이 여러 서비스 인스턴스에 의해 처리됩니다.

두 번째 차원은 상호 작용이 동기식인지 비동기식인지 여부입니다:

  • 동기식 - 클라이언트는 서비스에서 적시에 응답을 기대하며 기다리는 동안 차단할 수도 있습니다.
  • 비동기식 - 클라이언트가 응답을 기다리는 동안 차단하지 않으며 응답이 있는 경우 반드시 즉시 전송되지 않습니다.

다음 표는 다양한 상호 작용 스타일을 보여줍니다.


 
동기식
요청/응답
 - 
비동기
알림
게시/구독
요청/비동기 응답
게시/비동기 응답


일대일 상호작용에는 다음과 같은 종류가 있습니다:


요청/응답 - 클라이언트가 서비스에 요청을 하고 응답을 기다립니다.
클라이언트는 응답이 적시에 도착하기를 기대합니다.
스레드 기반 애플리케이션에서는 요청을 하는 스레드가 대기하는 동안 차단될 수도 있습니다.

알림(단방향 요청이라고도 함)- 클라이언트가 서비스에 요청을 보냈지만 응답이 예상되거나 전송되지 않은 경우입니다.
요청/비동기 응답 - 클라이언트가 서비스에 요청을 보내면 비동기적으로 응답합니다. 
클라이언트는 대기하는 동안 차단되지 않으며 응답이 한동안 도착하지 않을 수 있다는 가정 하에 설계되었습니다.


일대다 상호 작용에는 다음과 같은 종류가 있습니다:

  • 게시/구독 - 클라이언트가 알림 메시지를 게시하면 0개 이상의 관심 서비스에서 이를 소비합니다.
  • 응답 게시/비동기화 - 클라이언트가 요청 메시지를 게시한 다음 관심 있는 서비스의 응답을 일정 시간 동안 기다립니다.


각 서비스는 일반적으로 이러한 상호 작용 스타일을 조합하여 사용합니다. 

일부 서비스의 경우 단일 IPC 메커니즘으로 충분합니다. 

다른 서비스에서는 여러 IPC 메커니즘을 조합하여 사용해야 할 수도 있습니다. 

다음 다이어그램은 사용자가 차량 호출을 요청할 때 택시 호출 애플리케이션의 서비스가 상호 작용하는 방식을 보여줍니다.




서비스는 알림, 요청/응답, 게시/구독의 조합을 사용합니다. 

예를 들어, 승객의 스마트폰이 트립 관리 서비스에 알림을 전송하여 픽업을 요청합니다. 

여행 관리 서비스는 요청/응답을 사용하여 승객 서비스를 호출하여 승객의 계정이 활성화되어 있는지 확인합니다. 


그런 다음 여행 관리 서비스는 여행을 생성하고 게시/구독을 사용하여 

사용 가능한 드라이버를 찾는 Dispatcher를 비롯한 다른 서비스에 알립니다.

이제 상호작용 스타일을 살펴보았으니 API를 정의하는 방법을 살펴보겠습니다.

API 정의하기

서비스의 API는 서비스와 클라이언트 간의 계약입니다. 

어떤 IPC 메커니즘을 선택하든 일종의 인터페이스 정의 언어(IDL)를 사용하여 서비스의 API를 정확하게 정의하는 것이 중요합니다. 

서비스를 정의할 때 API 우선 접근 방식을 사용하는 것이 좋다는 주장도 있습니다.


인터페이스 정의를 작성하고 클라이언트 개발자와 함께 검토하는 것으로 서비스 개발을 시작합니다. 

API 정의에 대한 반복 작업을 거친 후에야 서비스를 구현할 수 있습니다. 


이 설계를 미리 수행하면 클라이언트의 요구 사항을 충족하는 서비스를 구축할 가능성이 높아집니다.

이 글의 뒷부분에서 살펴보겠지만 API 정의의 성격은 사용 중인 IPC 메커니즘에 따라 달라집니다. 


메시징을 사용하는 경우 API는 메시지 채널과 메시지 유형으로 구성됩니다. 

HTTP를 사용하는 경우 API는 URL과 요청 및 응답 형식으로 구성됩니다. 

나중에 몇 가지 IDL에 대해 더 자세히 설명하겠습니다.

진화하는 API


서비스의 API는 시간이 지남에 따라 항상 변합니다. 

모놀리식 애플리케이션에서는 일반적으로 API를 변경하고 모든 호출자를 업데이트하는 것이 간단합니다. 

마이크로서비스 기반 애플리케이션에서는 API의 모든 소비자가 동일한 애플리케이션의 다른 서비스라고 하더라도 훨씬 더 어렵습니다. 

일반적으로 모든 클라이언트를 서비스와 함께 강제로 업그레이드할 수는 없습니다. 


또한 서비스의 이전 버전과 새 버전이 동시에 실행되도록 서비스의 새 버전을 점진적으로 배포할 수도 있습니다. 

이러한 문제를 처리하기 위한 전략을 세우는 것이 중요합니다.

API 변경을 처리하는 방법은 변경의 규모에 따라 다릅니다. 

일부 변경 사항은 경미하며 이전 버전과 역호환됩니다. 

예를 들어 요청이나 응답에 속성을 추가할 수 있습니다. 


클라이언트와 서비스가 강건성 원칙을 준수하도록 설계하는 것이 좋습니다. 

이전 API를 사용하는 클라이언트는 새 버전의 서비스에서 계속 작업해야 합니다. 

서비스에서는 누락된 요청 속성에 대한 기본값을 제공하며 클라이언트는 추가 응답 속성을 무시합니다. 

API를 쉽게 발전시킬 수 있는 IPC 메커니즘과 메시징 형식을 사용하는 것이 중요합니다.


하지만 때로는 호환되지 않는 API를 크게 변경해야 하는 경우도 있습니다. 

클라이언트가 즉시 업그레이드하도록 강제할 수 없으므로 서비스에서 일정 기간 동안 이전 버전의 API를 지원해야 합니다. 

REST와 같은 HTTP 기반 메커니즘을 사용하는 경우 URL에 버전 번호를 포함시키는 것도 한 가지 방법입니다. 

각 서비스 인스턴스는 여러 버전을 동시에 처리할 수 있습니다. 

또는 각각 특정 버전을 처리하는 다른 인스턴스를 배포할 수도 있습니다.

부분 장애 처리하기

API 게이트웨이에 대한 이전 문서인 .htmla<.htmla< 에서 언급했듯이 

분산 시스템에서는 부분 장애의 위험이 항상 존재합니다. 

클라이언트와 서비스는 별개의 프로세스이므로 서비스가 클라이언트의 요청에 적시에 응답하지 못할 수 있습니다. 

장애 또는 유지보수로 인해 서비스가 다운될 수 있습니다. 

또는 서비스가 과부하되어 요청에 매우 느리게 응답하고 있을 수 있습니다.

예를 들어 해당 문서의 제품 세부 정보 시나리오를 생각해 보세요. 

추천 서비스가 응답하지 않는다고 가정해 봅시다. 

클라이언트를 순진하게 구현하면 응답을 기다리며 무기한 차단될 수 있습니다. 

이는 사용자 경험을 저하시킬 뿐만 아니라 많은 애플리케이션에서 스레드와 같은 귀중한 리소스를 소모하게 됩니다. 

결국 다음 그림과 같이 런타임에 스레드가 부족하여 응답하지 않게 됩니다.


A microservices app must be designed to handle partial failures, or else the runtime might run out of threads when clients block waiting for an unresponsive service

이 문제를 방지하려면 부분적인 장애를 처리하도록 서비스를 설계하는 것이 필수적입니다.

넷플릭스에서 설명하는 에 따라 접근하는 것이 좋습니다. 

부분 장애를 처리하기 위한 전략은 다음과 같습니다:

  • 네트워크 타임아웃 - 무한정 차단하지 말고 응답을 기다릴 때는 항상 타임아웃을 사용하세요. 
  • 타임아웃을 사용하면 리소스가 무한정 묶이지 않습니다.
  • 미결 요청 수 제한하기 - 클라이언트가 특정 서비스에 대해 가질 수 있는 미결 요청 수에 상한선을 설정합니다. 
  • 한도에 도달한 경우 추가 요청을 하는 것은 무의미하며 이러한 시도는 즉시 실패해야 합니다.
  • 서킷 차단기 패턴 - 성공 및 실패 요청 횟수를 추적합니다. 오류율이 구성된 임계값을 초과하면 회로 차단기를 트립하여 
  • 추가 시도가 즉시 실패하도록 합니다. 많은 수의 요청이 실패하는 경우 서비스를 사용할 수 없으며 
  • 요청을 보내는 것이 무의미하다는 의미입니다. 
  • 시간 초과 기간이 지나면 클라이언트는 다시 시도하고 성공하면 회로 차단기를 닫아야 합니다.
  • 폴백 제공 - 요청이 실패할 때 폴백 로직을 수행합니다. 
  • 예를 들어 캐시된 데이터 또는 빈 추천 세트와 같은 기본값을 반환합니다.

넷플릭스 Hystrix는 이러한 패턴과 기타 패턴을 구현하는 오픈 소스 라이브러리입니다. 

JVM을 사용하는 경우 Hystrix 사용을 반드시 고려해야 합니다. 

또한, JVM이 아닌 환경에서 실행하는 경우 동등한 라이브러리를 사용해야 합니다.

IPC 기술

선택할 수 있는 다양한 IPC 기술이 있습니다. 

서비스는 HTTP 기반 REST 또는 Thrift와 같은 동기식 요청/응답 기반 통신 메커니즘을 사용할 수 있습니다. 

또는 AMQP나 STOMP와 같은 비동기 메시지 기반 통신 메커니즘을 사용할 수도 있습니다. 

다양한 메시지 형식도 있습니다. 

서비스는 JSON 또는 XML과 같이 사람이 읽을 수 있는 텍스트 기반 형식을 사용할 수 있습니다. 

또는 Avro나 프로토콜 버퍼와 같은 이진 형식(더 효율적)을 사용할 수도 있습니다. 

나중에 동기식 IPC 메커니즘에 대해 살펴보겠지만 먼저 비동기식 IPC 메커니즘에 대해 알아보겠습니다.


비동기 메시지 기반 통신

메시징을 사용할 때 프로세스는 비동기적으로 메시지를 교환하여 통신합니다. 

클라이언트는 서비스에 메시지를 전송하여 요청을 합니다. 


서비스에서 응답이 예상되면 클라이언트에 별도의 메시지를 다시 전송하여 응답합니다. 

통신은 비동기식이기 때문에 클라이언트는 응답 대기를 차단하지 않습니다. 

대신 클라이언트는 응답이 즉시 수신되지 않을 것을 가정하여 작성됩니다.

메시지는 헤더(보낸 사람 등의 메타데이터)와 메시지 본문으로 구성됩니다. 


메시지는 채널을 통해 교환됩니다. 채널에 메시지를 보낼 수 있는 프로듀서의 수는 제한이 없습니다. 

마찬가지로 채널에서 메시지를 받는 소비자도 얼마든지 가능합니다. 

채널에는 point-to-point와 publish-subscribe의 두 가지 종류가 있습니다. 

지점 간 채널은 채널에서 읽고 있는 소비자 중 정확히 한 명에게 메시지를 전달합니다. 


서비스는 앞서 설명한 일대일 상호 작용 스타일에 지점 간 채널을 사용합니다. 

게시-구독 채널은 연결된 모든 소비자에게 각 메시지를 전달합니다. 

서비스는 위에서 설명한 일대다 상호 작용 스타일에 게시-구독 채널을 사용합니다.

다음 다이어그램은 택시 호출 애플리케이션에서 게시-구독 채널을 사용하는 방법을 보여줍니다.



Microservices in taxi-hailing application use publish-subscribe channels for communication between dispatcher and other services

트립 관리 서비스는 게시-구독 채널에 트립 생성 메시지를 작성하여 디스패처와 같은 관심 있는 서비스에 새 트립에 대해 알립니다. 

디스패처는 사용 가능한 드라이버를 찾아 다른 서비스에 드라이버 제안 메시지를 게시-구독 채널에 작성하여 알립니다.

선택할 수 있는 메시징 시스템은 여러 가지가 있습니다. 다양한 프로그래밍 언어를 지원하는 시스템을 선택해야 합니다. 

일부 메시징 시스템은 AMQP 및 STOMP와 같은 표준 프로토콜을 지원합니다. 

다른 메시징 시스템에는 독점적이지만 문서화된 프로토콜이 있습니다. 

RabbitMQ, 아파치 및 카프카, 아파치 및 액티브MQ, NSQ 등 수많은 오픈 소스 메시징 시스템 중에서 선택할 수 있습니다. 

높은 수준에서는 모두 어떤 형태의 메시지와 채널을 지원합니다. 

모두 안정적이고 성능이 뛰어나며 확장성을 갖추기 위해 노력합니다. 

그러나 각 브로커의 메시징 모델 세부 사항에는 상당한 차이가 있습니다.


메시징을 사용하면 많은 장점이 있습니다:


클라이언트와 서비스 분리 - 클라이언트는 적절한 채널에 메시지를 보내기만 하면 요청을 할 수 있습니다. 
클라이언트는 서비스 인스턴스를 전혀 알지 못합니다. 
서비스 인스턴스의 위치를 확인하기 위해 검색 메커니즘을 사용할 필요가 없습니다.

메시지 버퍼링 - HTTP와 같은 동기식 요청/응답 프로토콜의 경우 클라이언트와 서비스 모두 교환이 진행되는 동안 사용할 수 있어야 합니다. 
이와 달리 메시지 브로커는 채널에 쓰여진 메시지를 소비자가 처리할 수 있을 때까지 대기열에 대기시킵니다. 
예를 들어, 온라인 스토어는 주문 처리 시스템이 느리거나 사용할 수 없는 경우에도 
고객의 주문을 받을 수 있습니다. 주문 메시지가 대기열에 대기하기만 하면 됩니다.

유연한 클라이언트-서비스 상호 작용 - 메시징은 앞서 설명한 모든 상호 작용 스타일을 지원합니다.

명시적 프로세스 간 통신 - RPC 기반 메커니즘은 원격 서비스 호출을 로컬 서비스 호출과 동일하게 보이게 하려고 시도합니다
그러나 물리 법칙과 부분적인 실패 가능성으로 인해 실제로는 상당히 다릅니다.
메시징은 이러한 차이를 매우 명확하게 보여주기 때문에 개발자가 보안에 대한 잘못된 인식을 갖지 않도록 합니다.

하지만 메시징 사용에는 몇 가지 단점도 있습니다:

- 추가적인 운영 복잡성 - 메시징 시스템은 설치, 구성 및 운영해야 하는 또 다른 시스템 구성 요소입니다.
메시지 브로커의 가용성이 높아야 하며, 그렇지 않으면 시스템 안정성에 영향을 미칩니다.

- 요청/응답 기반 상호 작용 구현의 복잡성 - 요청/응답 스타일 상호 작용을 구현하려면 약간의 작업이 필요합니다.
각 요청 메시지에는 응답 채널 식별자와 상관관계 식별자가 포함되어야 합니다.
서비스는 상관관계 ID가 포함된 응답 메시지를 회신 채널에 씁니다.
클라이언트는 상관관계 ID를 사용하여 응답을 요청과 일치시킵니다.
요청/응답을 직접 지원하는 IPC 메커니즘을 사용하는 것이 더 쉬운 경우가 많습니다. 메시징 기반 IPC 사용에 대해 살펴봤으니 이제 요청/응답 기반 IPC에 대해 살펴보겠습니다.


동기식 요청/응답 IPC

동기식 요청/응답 기반 IPC 메커니즘을 사용하는 경우 클라이언트는 서비스에 요청을 보냅니다. 

서비스는 요청을 처리하고 응답을 다시 보냅니다. 

많은 클라이언트에서 요청을 만드는 스레드는 응답을 기다리는 동안 차단됩니다. 

다른 클라이언트는 선물 또는 Rx Observables로 캡슐화된 비동기 이벤트 중심 클라이언트 코드를 사용할 수도 있습니다. 

그러나 메시징을 사용할 때와 달리 클라이언트는 응답이 적시에 도착할 것이라고 가정합니다. 

선택할 수 있는 프로토콜은 다양합니다. 널리 사용되는 두 가지 프로토콜은 REST와 중고품입니다. 

먼저 REST에 대해 살펴보겠습니다.

REST

오늘날에는 RESTful 스타일로 API를 개발하는 것이 유행입니다. 

REST는 (거의 항상) HTTP를 사용하는 IPC 메커니즘입니다. 

REST의 핵심 개념은 리소스이며, 일반적으로 고객이나 제품과 같은 비즈니스 개체 또는 비즈니스 개체 모음을 나타냅니다. 

REST는 URL을 사용하여 참조되는 리소스를 조작하기 위해 HTTP 동사를 사용합니다. 

예를 들어, GET 요청은 리소스의 표현을 반환하며, 이는 XML 문서 또는 JSON 객체의 형태일 수 있습니다. 

POST 요청은 새 리소스를 생성하고 PUT 요청은 리소스를 업데이트합니다. 

REST의 창시자인 Roy 필딩의 말을 인용하면 다음과 같습니다:


"REST는 전체적으로 적용될 때 구성 요소 상호 작용의 확장성, 인터페이스의 일반성, 구성 요소의 독립적인 배포, 상호 작용 지연 시간을 줄이고 보안을 강화하며 레거시 시스템을 캡슐화하기 위한 중개 구성 요소를 강조하는 일련의 아키텍처 제약 조건을 제공합니다."

다음 다이어그램은 택시 호출 애플리케이션에서 REST를 사용할 수 있는 방법 중 하나를 보여줍니다.


In microservices-based taxi-hailing app, passenger smartphone sends POST request, which trip management microservice converts to GET request to passenger-verification microservice

승객의 스마트폰이 여행 관리 서비스의 POST 리소스에 /trips 요청을 하여 여행을 요청합니다. 

이 서비스는 승객에 대한 정보를 요청하는 GET 요청을 승객 관리 서비스로 전송하여 요청을 처리합니다. 

승객이 여행을 생성할 권한이 있는지 확인한 후, 여행 관리 서비스는 여행을 생성하고 스마트폰에 201 응답을 반환합니다.

많은 개발자가 자신의 HTTP 기반 API가 RESTful이라고 주장합니다. 

하지만 Fielding이 이 블로그 게시물에서 설명한 것처럼 실제로는 모두 그런 것은 아닙니다. 

Leonard Richardson(관계 없음)은 다음 단계로 구성된 매우 유용한 rest 성숙도 모델을 정의합니다.

  • 레벨 0 - 레벨 0 API의 클라이언트는 유일한 URL 엔드포인트에 HTTP POST 요청을 보내 서비스를 호출합니다. 
  • 각 요청은 수행할 작업, 작업 대상(예: 비즈니스 개체) 및 모든 매개변수를 지정합니다.
  • 레벨 1 - 레벨 1 API는 리소스라는 개념을 지원합니다. 리소스에 대한 작업을 수행하려면 
  • 클라이언트는 수행할 작업과 매개 변수를 지정하는 POST 요청을 합니다.
  • 레벨 2 - 레벨 2 API는 HTTP 동사를 사용하여 작업을 수행합니다: GET은 검색, POST는 생성, PUT는 업데이트에 사용됩니다. 요청 쿼리 매개변수와 본문(있는 경우)은 작업의 매개변수를 지정합니다. 이를 통해 서비스는 GET 요청에 대한 캐싱과 같은 웹 인프라를 활용할 수 있습니다.
  • 레벨 3 - 레벨 3 API의 설계는 끔찍한 이름의 HATEOAS(Hypertext As The Engine Of Application State) 원칙을 기반으로 합니다. 기본 개념은 GET 요청에 의해 반환되는 리소스의 표현에 해당 리소스에서 허용되는 작업을 수행하기 위한 링크가 포함되어 있다는 것입니다. 예를 들어, 클라이언트는 주문을 검색하기 위해 전송된 GET 요청에 대한 응답으로 반환된 주문 표현의 링크를 사용하여 주문을 취소할 수 있습니다. HATEOAS의 이점에는 더 이상 URL을 클라이언트 코드에 하드 와이어할 필요가 없다는 점이 포함됩니다. 또 다른 장점은 리소스의 표현에 허용되는 작업에 대한 링크가 포함되어 있기 때문에 클라이언트가 현재 상태의 리소스에 대해 어떤 작업을 수행할 수 있는지 추측할 필요가 없다는 것입니다.

HTTP 기반 프로토콜을 사용하면 많은 이점이 있습니다:

  • HTTP는 간단하고 친숙합니다.
  • 브라우저 내에서 Postman과 같은 확장 프로그램을 사용하거나 
  • 명령줄에서 curl(JSON 또는 다른 텍스트 형식이 사용된다는 가정 하에)를 사용하여 HTTP API를 테스트할 수 있습니다.
  • 요청/응답 스타일의 통신을 직접 지원합니다.
  • 물론 HTTP는 방화벽 친화적입니다.
  • 중간 브로커가 필요하지 않으므로 시스템 아키텍처가 간소화됩니다.

HTTP 사용에는 몇 가지 단점이 있습니다:

  • 요청/응답 방식의 상호작용만 직접적으로 지원한다는 점입니다. 알림에 HTTP를 사용할 수 있지만 서버는 항상 HTTP 응답을 보내야 합니다.
  • 클라이언트와 서비스는 메시지를 버퍼링하는 중개자 없이 직접 통신하기 때문에 교환이 진행되는 동안 둘 다 실행 중이어야 합니다.
  • 클라이언트는 각 서비스 인스턴스의 위치(즉, URL)를 알고 있어야 합니다. API 게이트웨이에 대한 이전 문서 에 설명된 대로 이는 최신 애플리케이션에서 사소한 문제가 아닙니다. 클라이언트는 서비스 인스턴스를 찾기 위해 서비스 검색 메커니즘을 사용해야 합니다.

개발자 커뮤니티는 최근 RESTful API를 위한 인터페이스 정의 언어의 가치를 재발견했습니다. 

RAML 및 Swagger 등 몇 가지 옵션이 있습니다. 

Swagger와 같은 일부 IDL을 사용하면 요청 및 응답 메시지의 형식을 정의할 수 있습니다. 

RAML과 같은 다른 IDL은 JSON 스키마와 같은 별도의 사양을 사용해야 합니다. 

API를 설명할 뿐만 아니라 IDL에는 일반적으로 인터페이스 정의에서 클라이언트 스텁과 서버 골격을 생성하는 도구가 있습니다.

중고품

아파치 중고품는 REST의 흥미로운 대안입니다. 크로스 언어 RPC 클라이언트와 서버를 작성하기 위한 프레임워크입니다. 

Thrift는 API를 정의하기 위한 C 스타일 IDL을 제공합니다. 

Thrift 컴파일러를 사용해 클라이언트 측 스텁과 서버 측 스켈레톤을 생성할 수 있습니다. 

컴파일러는 C++, Java, Python, PHP, Ruby, Erlang, Node.js 등 다양한 언어에 대한 코드를 생성합니다.

중고품 인터페이스는 하나 이상의 서비스로 구성됩니다. 서비스 정의는 Java 인터페이스와 유사합니다. 

강력한 타입의 메서드 모음입니다. 중고품 메서드는 (무효일 수 있는) 값을 반환하거나 단방향으로 정의할 수 있습니다. 

값을 반환하는 메서드는 요청/응답 스타일의 상호작용을 구현합니다. 클라이언트는 응답을 기다리며 예외를 발생시킬 수 있습니다. 

단방향 메서드는 상호 작용의 알림 스타일에 해당합니다. 

서버가 응답을 보내지 않습니다.

중고품은 다양한 메시지 형식을 지원합니다: JSON, 바이너리, 압축 바이너리. 

바이너리는 디코딩 속도가 빠르기 때문에 JSON보다 효율적입니다. 

그리고 이름에서 알 수 있듯이 압축 바이너리는 공간 효율적인 형식입니다.

물론 JSON은 인간과 브라우저 친화적입니다. 

또한 Thrift는 원시 TCP와 HTTP를 포함한 전송 프로토콜을 선택할 수 있습니다. 

원시 TCP가 HTTP보다 더 효율적일 가능성이 높습니다. 하지만 HTTP는 방화벽, 브라우저, 인간 친화적입니다.

메시지 형식

HTTP와 중고품에 대해 살펴봤으니 이제 메시지 형식에 대해 살펴봅시다. 

메시징 시스템이나 REST를 사용하는 경우 메시지 형식을 선택할 수 있습니다. 

Thrift와 같은 다른 IPC 메커니즘은 소수의 메시지 형식만 지원할 수도 있습니다. 


어떤 경우든 언어 간 메시지 형식을 사용하는 것이 중요합니다. 

현재 단일 언어로 마이크로서비스를 작성하고 있더라도 향후에는 다른 언어를 사용할 가능성이 높습니다.

메시지 형식에는 텍스트와 바이너리의 두 가지 주요 유형이 있습니다. 

텍스트 기반 형식의 예로는 JSON과 XML이 있습니다. 


이러한 형식의 장점은 사람이 읽을 수 있을 뿐만 아니라 자체적으로 설명할 수 있다는 것입니다. 

JSON에서 객체의 속성은 이름-값 쌍의 컬렉션으로 표현됩니다. 

마찬가지로 XML에서는 속성이 명명된 요소와 값으로 표현됩니다. 

이를 통해 메시지 소비자는 관심 있는 값만 골라내고 나머지는 무시할 수 있습니다. 

따라서 메시지 형식의 사소한 변경 사항도 쉽게 이전 버전과 호환될 수 있습니다.


XML 문서의 구조는 XML 스키마에 의해 지정됩니다. 

시간이 지남에 따라 개발자 커뮤니티는 JSON에도 유사한 메커니즘이 필요하다는 사실을 깨닫게 되었습니다. 

한 가지 옵션은 독립적으로 또는 Swagger와 같은 IDL의 일부로 JSON 스키마를 사용하는 것입니다.

텍스트 기반 메시지 형식을 사용할 때의 단점은 메시지가 장황한 경향이 있다는 것입니다(특히 XML). 


메시지가 자체적으로 설명되기 때문에 모든 메시지에는 값과 함께 속성 이름이 포함됩니다. 

또 다른 단점은 텍스트 구문 분석의 오버헤드입니다. 따라서 바이너리 형식 사용을 고려할 수 있습니다.

선택할 수 있는 바이너리 형식은 여러 가지가 있습니다. 중고품 RPC를 사용하는 경우 바이너리 중고품을 사용할 수 있습니다. 

메시지 형식을 선택할 때 많이 사용되는 옵션으로는 Protocol Buffers와 Apache Avro가 있습니다. 


이 두 형식 모두 메시지 구조를 정의하기 위한 유형화된 IDL을 제공합니다. 

그러나 한 가지 차이점은 프로토콜 버퍼는 태그가 지정된 필드를 사용하는 반면, 

Avro 소비자는 메시지를 해석하기 위해 스키마를 알아야 한다는 점입니다. 

따라서 API 진화는 Avro보다 프로토콜 버퍼를 사용하는 것이 더 쉽습니다. 

이 블로그 게시물은 Thrift, Protocol, Buffers, Avro를 비교한 훌륭한 글입니다.

요약

마이크로서비스는 프로세스 간 통신 메커니즘을 사용하여 통신해야 합니다. 

서비스의 통신 방식을 설계할 때는 서비스 상호 작용 방식, 각 서비스의 API를 지정하는 방법, API를 발전시키는 방법, 

부분 장애를 처리하는 방법 등 다양한 문제를 고려해야 합니다.

 마이크로서비스가 사용할 수 있는 IPC 메커니즘에는 비동기 메시징과 동기 요청/응답의 두 가지 종류가 있습니다. 

시리즈의 다음 글에서는 마이크로서비스 아키텍처에서 서비스 검색 문제를 살펴보겠습니다.

편집자 - 이제 이 7부작 시리즈 기사가 완료되었습니다:



  1. 마이크로서비스 소개
  2. 마이크로서비스 구축하기: API 게이트웨이 사용
  3. 마이크로서비스 구축하기: 마이크로서비스 아키텍처의 프로세스 간 통신(이 문서)
  4. 마이크로서비스 아키텍처에서의 서비스 검색
  5. 마이크로서비스를 위한 이벤트 중심 데이터 관리
  6. 마이크로서비스 배포 전략 선택
  7. 모놀리스를 마이크로서비스로 리팩토링



위 내용과 같이 NGINX Ingress Controller 를 활용하여 Demo 가 필요하시면 하단의 전문가에게 상담받기 버튼을 클릭해주세요


전문가에게 상담받기


'


프로필 이미지
관리자
2025-01-16
조회 7

쿠버네티스는 Google에서 클러스터에서 컨테이너화된 마이크로서비스 기반 애플리케이션을 실행하고 

관리하기 위해 개발한 오픈 소스 시스템입니다. 쿠버네티스를 사용하는 사람들은 

종종 쿠버네티스에서 만든 서비스를 쿠버네티스 클러스터 외부에서 액세스할 수 있도록 해야 합니다.


Kubernetes는 아래의 내장 솔루션을 사용하여 Kubernetes 서비스 노출 에서 

설명한 대로 서비스를 노출하기 위한 내장 솔루션을 제공 하지만 , 

해당 솔루션은 레이어 4 부하 분산 또는 라운드 로빈 HTTP 부하 분산으로 제한됩니다.


이 게시물에서는 클라우드에서 Kubernetes를 실행하든 자체 인프라에서 실행하든 

Kubernetes 서비스를 인터넷에 노출하기 위한 고급 Layer 7 로드 밸런싱 솔루션으로 NGINX Plus를 사용하는 방법을 보여줍니다 .


Kubernetes(포드, 서비스, 복제 컨트롤러 및 레이블)와 실행 중인 Kubernetes 클러스터에 대한 기본적인 이해가 있다고 가정합니다. 

Kubernetes에 대해 자세히 알아보려면 공식 Kubernetes 사용자 가이드를 참조하세요 .

내장 솔루션을 사용하여 Kubernetes 서비스 노출


쿠버네티스는 서비스를 노출하기 위한 여러 옵션을 제공합니다 . 

그 중 두 가지(NodePort와 LoadBalancer)는 특정 유형의 서비스에 해당합니다. 

세 번째 옵션인 Ingress API는 쿠버네티스 릴리스 1.1에서 베타로 제공되었습니다.

노드포트

서비스 유형을 NodePort 로 지정하면 각 Kubernetes 노드에서 동일한 포트에서 서비스를 사용할 수 있습니다. 

서비스를 인터넷에 노출하려면 해당 포트에서 하나 이상의 노드를 노출합니다. 

고가용성을 위해 여러 노드를 노출하고 DNS 기반 로드 밸런싱을 사용하여 

트래픽을 분산하거나 노드를 선택한 로드 밸런서 뒤에 배치할 수 있습니다.

들어오는 트래픽이 포트의 노드에 도달하면 서비스의 포드 간에 로드 밸런싱이 이루어집니다. 

kube-proxy모든 노드에서 실행되는 Kubernetes 네트워크 프록시( )가 수행하는 로드 밸런싱은 TCP/UDP 로드 밸런싱으로 제한됩니다.


로드 밸런서

서비스 유형을 LoadBalancer 로 지정하면 서비스의 Pod 간에 수신 트래픽을 분산하는 클라우드 로드 밸런서가 할당됩니다.

LoadBalancer 솔루션은 특정 클라우드 공급자와 Google Container Engine 에서만 지원되며 

자체 인프라에서 Kubernetes를 실행하는 경우 사용할 수 없습니다. 

또한 Kubernetes에서는 클라우드 로드 밸런서에 세션 지속성이나 

요청 매핑과 같은 고급 기능이 있더라도 라운드 로빈 TCP 로드 밸런싱만 구성할 수 있습니다.


인그레스 API

Ingress 리소스를 생성하면 사용자 지정 URL(예: URL /foo 에서 서비스 A , URL /bar 에서 서비스 B )과 

여러 가상 호스트 이름(예: 한 서비스 그룹의 경우 foo.example.com , 다른 그룹의 경우 bar.example.com )에서 

서비스를 인터넷에 노출할 수 있습니다. 


Ingress 컨트롤러는 Ingress 리소스를 사용하고 외부 로드 밸런서를 설정합니다.

Ingress 컨트롤러는 표준 Kubernetes 배포의 일부가 아닙니다. 

필요에 가장 적합한 컨트롤러를 선택하거나 직접 구현하여 Kubernetes 클러스터에 추가해야 합니다. 


많은 컨트롤러 구현이 곧 나타날 것으로 예상되지만 현재 유일하게 사용 가능한 구현은 

Google Compute Engine HTTP Load Balancer용 컨트롤러로 , 

Google Compute Engine 또는 Google Container Engine 에서 Kubernetes를 실행하는 경우에만 작동합니다. 

Ingress API는 실제 로드 밸런서가 고급 기능을 지원하더라도 라운드 로빈 HTTP 로드 밸런싱만 지원합니다.


이 글을 쓰는 시점에서 Ingress API와 Google Compute Engine HTTP 부하 분산 장치용 컨트롤러는 모두 베타 버전입니다.

업데이트  – NGINX와 NGINX Plus를 위한 NGINX Ingress Controller가 이제 GitHub 저장소 에서 제공됩니다 . 

제품 세부 정보는 NGINX Ingress Controller를 참조하세요 .

위에서 언급한 솔루션은 설정이 간단하고 바로 사용할 수 있지만 

특히 7계층 부하 분산과 관련된 기능을 비롯하여 고급 기능을 제공하지 않습니다.


NGINX Plus로 Kubernetes 서비스 노출

[편집자 - 이 섹션은 원래 여기에서 논의된 별도의 동적 구성 모듈을 대체하고 더 이상 사용되지 않는 NGINX Plus API를 참조하도록 업데이트되었습니다 .]


NGINX Plus를 Kubernetes와 통합하려면 NGINX Plus 구성이 Kubernetes와 동기화되어 

Pod 추가 또는 삭제와 같은 Kubernetes 서비스의 변경 사항을 반영해야 합니다. 

NGINX Open Source를 사용하면 NGINX 구성 파일을 수동으로 수정하고 구성을 다시 로드할 수 있습니다. 

NGINX Plus를 사용하면 구성을 동적으로 업데이트하는 두 가지 방법이 있습니다.


API 사용 - 이 방법은 NGINX Plus API를 사용하여 NGINX Plus 구성에서 
Kubernetes 포드에 대한 항목을 추가 및 제거하고
Kubernetes API를 사용하여 포드의 IP 주소를 검색합니다.
이 방법을 사용하려면 코드를 작성해야 하며 여기서는 자세히 설명하지 않습니다.
자세한 내용은 Kelsey Hightower의 웨비나 Bringing Kubernetes to the Edge with NGINX Plus를 시청하세요 .
여기서 그는 API를 탐색하고 이를 활용하는 애플리케이션을 만듭니다.
DNS 이름을 다시 확인 하여 – 이 방법은 다음 섹션에 설명된 대로 NGINX Plus의 적절한 일회성 구성만 필요합니다.


DNS 기반 재구성 활용

이미 실행 중인 Kubernetes 클러스터와 kubectl클러스터를 관리하는 데 

사용할 수 있는 유틸리티가 있는 호스트가 있다고 가정합니다. 

지침은 클러스터 유형에 대한 Kubernetes 시작 가이드를 참조하세요 . 

또한 NGINX Plus Docker 이미지를 빌드해야 하며, 

지침은 블로그의 Docker를 사용하여 NGINX 및 NGINX Plus 배포 에서 확인할 수 있습니다.

우리가 할 일의 개요는 다음과 같습니다.

  1. 2단계에서 생성한 서비스를 노출하고 부하를 분산하기 위해 NGINX Plus Pod를 구성합니다.
  2. 우리의 서비스로 간단한 웹 애플리케이션을 만들어 보겠습니다.
  3. 서비스를 확장하거나 축소하면서 NGINX Plus가 자동으로 재구성되는 모습을 살펴보세요.


참고 사항: 이 블로그에 설명된 솔루션을 Google Compute Engine에서 실행되는 

Kubernetes 1.0.6 과 로컬 Vagrant 설정(아래에서 사용)으로 테스트했습니다.

명령에서 Kubernetes 설정에 따라 다를 수 있는 값은 기울임꼴로 표시됩니다.


NGINX Plus Pod 구성

우리는 인터넷에 노출된 노드의 Kubernetes 포드에 NGINX Plus를 넣고 있습니다. 

우리의 포드는 우리가 또한 설정하고 있는 복제 컨트롤러에 의해 생성됩니다. 

우리의 Kubernetes 특정 NGINX Plus 구성 파일은 NGINX Plus 포드와 노드 간

공유되는 폴더에 상주하여 유지 관리가 더 간단합니다.

NGINX Plus Pod를 호스팅할 노드 선택


NGINX Plus pod가 실행되는 노드를 지정하기 위해 해당 노드에 레이블을 추가합니다. 

다음을 실행하여 모든 노드 목록을 가져옵니다.

$ kubectl get nodesNAME         LABELS
                              STATUS 10.245.1.3
   Kubernetes.io/hostname=10.245.1.3   Ready 10.245.1.4
   Kubernetes.io/hostname=10.245.1.4   Ready 10.245.1.5
   Kubernetes.io/hostname=10.245.1.5   Ready

첫 번째 노드를 선택하고 다음을 실행하여 레이블을 추가합니다.

$ kubectl label node 10.245.1.3 role=nginxplus

NGINX Plus Pod에 대한 복제 컨트롤러 구성

우리는 NGINX Plus 포드를 직접 생성하지 않고 복제 컨트롤러를 통해 생성합니다. 

nginxplus-rc.yaml 이라는 Kubernetes 선언 파일에서 NGINX Plus 포드에 대한 복제 컨트롤러를 구성합니다 .

  • replicasNGINX Plus Pod가 항상 실행되도록 하려면 Pod 개수를 하나로 설정했습니다 . 
  • Pod에 장애가 발생하면 새로운 Pod로 교체합니다.
  • 필드 에서 nodeSelectorNGINX Plus Pod가 레이블이 지정된 노드에 생성되도록 지정합니다 role: nginxplus.
  • NGINX Plus 컨테이너는 80과 8080이라는 두 개의 포트를 노출하며, 이 두 포트와 노드의 80과 8080 포트 간의 매핑을 설정합니다.
  • NGINX Plus 컨테이너는 노드에 있는 /etc/nginx/conf.d 폴더도 공유합니다. 

아래 NGINX Plus 구성 에서 자세히 설명했듯이,
폴더를 공유하면 컨테이너 이미지를 다시 빌드하지 않고도 NGINX Plus를 재구성할 수 있습니다.
apiVersion: v1kind: ReplicationController
metadata:
  name: webapp-rc
spec:
  replicas: 2
  selector:
    app: webapp
  template:
    metadata:
      labels:
        app: webapp
    spec:
      containers:
      - name: hello
        image: nginxdemos/hello 
        ports:
        - containerPort: 80       

노드에서 NGINX Plus Docker 이미지 사용 가능

위에서 말했듯이, 우리는 이미 NGINX Plus Docker 이미지를 빌드했습니다. 

이제 노드에서 사용할 수 있도록 합니다. 단순성을 위해 개인 Docker 저장소를 사용하지 않고 

이미지를 노드에 수동으로 로드합니다.

Docker 이미지를 빌드한 호스트에서 다음 명령을 실행하여 이미지를 파일에 저장합니다.

$ docker save -o nginxplus.tar nginxplus

nginxplus.tar를 노드로 전송하고 , 노드에서 다음 명령을 실행하여 파일에서 이미지를 로드합니다.

$ docker load -i nginxplus.tar

NGINX Plus 구성

NGINX Plus 컨테이너의 /etc/nginx 폴더에서 NGINX Plus 패키지와 함께 제공되는 기본 주 nginx.conf 구성 파일을 유지합니다. 

기본 파일의 지시문은 /etc/nginx/conf.dinclude 폴더 에서 다른 구성 파일을 읽습니다 . 

NGINX Plus 복제 컨트롤러( nginxplus-rc.yaml ) 의 선언 파일 에 지정된 대로 

NGINX Plus 노드의 /etc/nginx/conf.d 폴더를 컨테이너와 공유합니다. 

공유는 컨테이너에서 직접 폴더를 만든 경우 해야 하는 NGINX Plus Docker 이미지를 다시 빌드하지 않고도 

폴더(노드)에 저장된 구성 파일을 변경할 수 있음을 의미합니다. 

공유 폴더에 Kubernetes 특정 구성 파일( backend.conf )을 넣습니다.

먼저 노드에 /etc/nginx/conf.d 폴더를 만들어 보겠습니다 .

$ sudo mkdir -p /etc/nginx/conf.d

그런 다음 해당 위치에 backend.conf 파일을 만들고 다음 지침을 포함합니다.

  • resolver NGINX Plus가 업스트림 서버를 식별하는 데 사용하는 도메인 이름을 주기적으로 재확인하는 데 사용하는 DNS 서버를 정의합니다(다음 글머리 기호에서 설명하는 블록 server내부의 지시문 ). 이 DNS 서버를 도메인 이름인 kube-dns.kube-system.svc.cluster.localupstream 로 식별합니다 . 이 매개변수는 NGINX Plus에 5초마다 재확인 요청을 보내라고 지시합니다.valid

    (이 지시어에 대한 확인 프로세스는 업스트림 서버의 확인 프로세스와 다릅니다. 이 도메인 이름은 NGINX가 시작되거나 다시 로드될 때만 확인되고, NGINX Plus는 /etc/resolv.conf 파일에 정의된 시스템 DNS 서버를 사용하여 이를 확인합니다.)

  • upstream– 우리가 노출하는 Kubernetes 서비스를 제공하는 서버를 포함하는 백엔드  라는 업스트림 그룹을 만듭니다 . 서버를 개별적으로 나열하는 대신, 단일 server지시문에서 완전히 정규화된 호스트 이름으로 식별합니다. 이 resolve매개변수는 NGINX Plus에 지시문으로 지정된 설정에 따라 런타임에 호스트 이름을 다시 확인하도록 지시합니다 resolver.

    Kubernetes DNS와 NGINX Plus(R10 이상)는 모두 DNS 서비스( SRV) 레코드를 지원하므로 NGINX Plus는 DNS를 통해 업스트림 서버의 포트 번호를 가져올 수 있습니다. serviceNGINX Plus 요청 레코드를 갖도록 매개변수를 포함하여 서비스에서 노출된 포트에 대한 SRV이름( _http)과 프로토콜( )을 지정합니다. 아래 서비스에 대한 복제 컨트롤러 생성 에서 설명한 webapp-svc.yaml_tcp 파일 에 해당 값을 선언합니다 .

    DNS를 사용한 서비스 검색에 대한 자세한 내용은 블로그의 NGINX 및 NGINX Plus에서 DNS를 사용하여 서비스 검색을 참조하세요.

  • server(2회) – 두 개의 가상 서버를 정의합니다.

    • 첫 번째 서버는 포트 80에서 수신하고 /webapp (우리 서비스)에 대한 들어오는 요청을 서비스 인스턴스를 실행하는 포드 간에 로드 밸런싱합니다. 또한 활성 상태 검사를 설정합니다 .

    • 두 번째 서버는 포트 8080에서 수신합니다. 여기서 NGINX Plus의 라이브 활동 모니터링을 설정합니다 .

    • 나중에 NGINX Plus가 제대로 재구성되었는지 확인하는 데 사용합니다.
      [편집자 - 이 두 번째 서버의 구성은 원래 사용되었던 별도의 상태 모듈을 대체하고 더 이상 사용되지 않는 NGINX Plus API를 사용하도록 업데이트되었습니다 .]

resolver kube-dns.kube-system.svc.cluster.local valid=5s; 
upstream backend {
    zone upstream-backend 64k;
    server webapp-svc.default.svc.cluster.local service=_http._tcp resolve; }
 server {
    listen 80;
    status_zone backend-servers;
     location /webapp {
        proxy_pass http://backend;
        health_check;
    }
 }
 server {
    listen 8080;
    root /usr/share/nginx/html;
     location = /dashboard.html { }
     location = / {
        return 302 /dashboard.html;
    }     location /api {
        api write=on;
    }
 }

복제 컨트롤러 생성

이제 다음 명령을 실행하여 복제 컨트롤러를 생성할 준비가 되었습니다.

$ kubectl create -f nginxplus-rc.yaml

NGINX Plus Pod가 생성되었는지 확인하려면 다음을 실행합니다.

$ kubectl get pods
NAME                 READY     STATUS    RESTARTS   AGE
nginxplus-rc-0ts5t   1/1       Running   0          17s

로컬 Vagrant 설정에서 Kubernetes를 실행하고 있으므로 노드의 외부 IP 주소가 10.245.1.3임을 알고 있으며 

이 예제의 나머지 부분에서 해당 주소를 사용할 것입니다. 

클라우드 공급자에서 Kubernetes를 실행하는 경우 다음을 실행하여 노드의 외부 IP 주소를 가져올 수 있습니다.

$ kubectl get nodes node-name -o json | grep -i externalIP -A 1
                "type": "ExternalIP",
                "address": XXX.XXX.XXX.XXX

클라우드에서 실행 중이라면 NGINX Plus 노드가 들어오는 트래픽을 허용하도록 방화벽 규칙을 설정하는 것을 잊지 마세요. 

클라우드 제공자의 설명서를 참조하세요.

NGINX Plus pod가 작동 중인지 확인하려면 노드의 외부 IP 주소(예: http://10.245.1.3:8080/dashboard.html )에서 

포트 8080에서 사용할 수 있는 NGINX Plus 라이브 활동 모니터링 대시보드를 보면 됩니다. 

하지만 이 지점을 살펴보면 아직 서비스를 만들지 않았기 때문에 서비스에 대한 서버가 보이지 않습니다.


Kubernetes 서비스를 생성하기 전의 NGINX Plus 라이브 활동 모니터링 대시보드

간단한 쿠버네티스 서비스 만들기

이제 Kubernetes 서비스를 만들 시간입니다. 저희 서비스는 두 개의 웹 서버로 구성되어 있으며, 

각각은 실행 중인 컨테이너에 대한 정보가 있는 웹 페이지를 제공합니다.

서비스에 대한 복제 컨트롤러 생성

먼저 복제 컨트롤러를 생성하여 Kubernetes가 지정된 수의 웹 서버 복제본(포드)이 클러스터에서 항상 실행되도록 합니다. 

다음은 선언 파일( webapp-rc.yaml )입니다.

apiVersion: v1kind: ReplicationController metadata:  name: webapp-rc spec:  replicas: 2  selector:    app: webapp  template:    metadata:      labels:        app: webapp    spec:      containers:      - name: hello        image: nginxdemos/hello         ports:        - containerPort: 80

컨트롤러는 두 개의 웹 서버로 구성되어 있습니다. 

단일 컨테이너가 있는 포드로 구성된 컨트롤러를 선언하고 포트 80을 노출합니다. 

nginxdemos/hello 이미지는 Docker Hub에서 가져옵니다.

복제 컨트롤러를 생성하려면 다음 명령을 실행합니다.