서비스 및 인그레스 만들기

이 문서에서는 Google Distributed Cloud용 사용자, 하이브리드 또는 독립형 클러스터에서 Kubernetes 인그레스 객체를 만드는 방법을 보여줍니다. 인그레스는 각각 포드 집합과 연결된 서비스 하나 이상과 연결됩니다.

배포 만들기

배포를 만들려면 다음 단계를 따르세요.

  1. 배포 매니페스트를 만듭니다.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: hello-deployment
    spec:
      selector:
        matchLabels:
          greeting: hello
      replicas: 3
      template:
        metadata:
          labels:
            greeting: hello
        spec:
          containers:
          - name: hello-world
            image: "gcr.io/google-samples/hello-app:2.0"
            env:
            - name: "PORT"
              value: "50000"
          - name: hello-kubernetes
            image: "gcr.io/google-samples/node-hello:1.0"
            env:
            - name: "PORT"
              value: "8080"
    

    이 실습을 진행하면서 배포 매니페스트에 대해 알아야 할 중요한 사항은 다음과 같습니다.

    • 배포에 속한 각 pod에는 greeting: hello 라벨이 있습니다.

    • 각 pod에는 2개의 컨테이너가 있습니다.

    • env 필드는 hello-app 컨테이너가 TCP 포트 50000에서 리슨하고 node-hello 컨테이너가 TCP 포트 8080에서 리슨하는 것을 지정합니다. hello-app의 경우 소스 코드를 보면 PORT 환경 변수의 효과를 확인할 수 있습니다.

  2. 이름이 hello-deployment.yaml인 파일에 매니페스트를 복사합니다.

  3. 배포를 만듭니다.

    kubectl apply --kubeconfig CLUSTER_KUBECONFIG -f hello-deployment.yaml
    

    CLUSTER_KUBECONFIG를 클러스터의 kubeconfig 파일 이름으로 바꿉니다.

서비스에 배포 노출

클라이언트가 배포의 포드로 요청을 보내는 안정적인 방법을 제공하려면 서비스를 만드세요.

  1. 클러스터 내부 클라이언트에 배포를 노출하는 서비스 매니페스트를 만듭니다.

    apiVersion: v1
    kind: Service
    metadata:
      name: hello-service
    spec:
      type: ClusterIP
      selector:
        greeting: hello
      ports:
      - name: world-port
        protocol: TCP
        port: 60000
        targetPort: 50000
      - name: kubernetes-port
        protocol: TCP
        port: 60001
        targetPort: 8080
    
  2. 이름이 hello-service.yaml인 파일에 매니페스트를 복사합니다.

  3. 서비스 만들기:

    kubectl apply --kubeconfig CLUSTER_KUBECONFIG -f hello-service.yaml
    

    CLUSTER_KUBECONFIG를 클러스터의 kubeconfig 파일 이름으로 바꿉니다.

  4. 서비스를 확인합니다.

    kubectl --kubeconfig CLUSTER_KUBECONFIG get service hello-service --output yaml
    

    서비스에 제공된 clusterIP의 값이 출력에 표시됩니다. 예를 들면 다음과 같습니다.

    apiVersion: v1
    kind: Service
    metadata:
      annotations:
        ...
    spec:
      clusterIP: 10.96.14.249
      clusterIPs:
      - 10.96.14.249
      ipFamilies:
      - IPv4
      ipFamilyPolicy: SingleStack
      ports:
      - name: world-port
        port: 60000
        protocol: TCP
        targetPort: 50000
      - name: kubernetes-port
        port: 60001
        protocol: TCP
        targetPort: 8080
      selector:
        greeting: hello
      sessionAffinity: None
      type: ClusterIP
    status:
      loadBalancer: {}
    

    위 출력에서 ports 필드는 이름이 각각 world-portkubernetes-portServicePort 객체의 배열입니다. 서비스 필드에 대한 자세한 내용은 Kubernetes 문서의 ServiceSpec을 참조하세요.

    클라이언트에서 서비스를 호출할 수 있는 방법은 다음과 같습니다.

    • world-port 사용: 클러스터 노드 중 하나에서 실행되는 클라이언트가 port (예: 10.96.14.249:60000)의 clusterIP에 요청을 전송합니다. 인그레스 컨트롤러는 targetPort (예: POD_IP_ADDRESS:50000, 여기서 POD_IP_ADDRESS은 구성원 포드의 IP 주소)의 구성원 포드로 요청을 전달합니다.

    • kubernetes-port 사용: 클러스터 노드 중 하나에서 실행되는 클라이언트가 port(10.96.14.249:60001)의 clusterIP에 요청을 전송합니다. 인그레스 컨트롤러는 targetPort (POD_IP_ADDRESS:8080)의 멤버 포드로 요청을 전달합니다.

인그레스 구성요소

인그레스와 관련된 몇 가지 클러스터 구성요소는 다음과 같습니다.

  • istio-ingress 배포. 인그레스 프록시입니다. 인그레스 프록시는 인그레스 객체에 지정된 규칙에 따라 트래픽을 내부 서비스로 전달합니다.

  • istio-ingress 서비스. 이 서비스는 istio-ingress 배포를 노출합니다.

  • istiod 배포. 인그레스 컨트롤러입니다. 인그레스 컨트롤러는 인그레스 객체 생성을 감시하고 그에 따라 인그레스 프록시를 구성합니다.

이러한 모든 Istio 클러스터 내 구성요소는 gke-system 네임스페이스에 설치됩니다. 이 네임스페이스는 전체 Istio/Cloud Service Mesh 설치와 충돌하지 않습니다.

인그레스 만들기

다음 단계에 따라 인그레스를 만듭니다.

  1. 인그레스 매니페스트를 만듭니다.

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: my-ingress
    spec:
      rules:
      - http:
          paths:
          - path: /greet-the-world
            pathType: Exact
            backend:
              service:
                name: hello-service
                port:
                  number: 60000
          - path: /greet-kubernetes
            pathType: Exact
            backend:
              service:
                name: hello-service
                port:
                  number: 60001
    
  2. 이름이 my-ingress.yaml인 파일에 매니페스트를 복사합니다.

  3. 인그레스를 만듭니다.

    kubectl apply --kubeconfig CLUSTER_KUBECONFIG -f my-ingress.yaml
    

사용자 클러스터를 만들 때 클러스터 구성 파일에서 loadbalancer.ingressVIP 값을 지정합니다. 이 IP 주소는 클러스터 부하 분산기에서 구성됩니다. 인그레스를 만들면 외부 IP 주소와 동일한 이 VIP가 인그레스에 지정됩니다.

클라이언트가 사용자 클러스터 인그레스 VIP로 요청을 전송하면 요청이 부하 분산기로 라우팅됩니다. 부하 분산기는 istio-ingress 서비스를 사용하여 사용자 클러스터에서 실행되는 인그레스 프록시로 요청을 전달합니다. 인그레스 프록시는 요청 URL의 경로에 따라 요청을 다른 백엔드로 전달합니다.

/greet-the-world 경로

인그레스 매니페스트에서 /greet-the-world 경로가 serviceName: hello-serviceservicePort: 60000과 연결되어 있음을 나타내는 규칙을 확인할 수 있습니다. 60000은 hello-service 서비스의 world-port 섹션에 있는 port 값입니다.

- name: world-port
    port: 60000
    protocol: TCP
    targetPort: 50000

인그레스 서비스는 요청을 clusterIP:50000으로 전달합니다. 그런 다음 요청은 hello-service 서비스의 구성원 포드 중 하나로 이동합니다. 해당 포드의 포트 50000에서 리슨하는 컨테이너에 Hello World! 메시지가 표시됩니다.

/greet-kubernetes 경로

인그레스 매니페스트에서 /greet-kubernetes 경로가 serviceName: hello-serviceservicePort: 60001과 연결되어 있음을 나타내는 규칙을 확인할 수 있습니다. 60001은 hello-service 서비스의 kubernetes-port 섹션에 있는 port 값입니다

- name: kubernetes-port
    port: 60001
    protocol: TCP
    targetPort: 8080

인그레스 서비스는 요청을 clusterIP: 8080으로 전달합니다. 그런 다음 요청은 hello-service 서비스의 구성원 포드 중 하나로 이동합니다. 해당 포드의 포트 8080에서 리슨하는 컨테이너에 Hello Kubernetes! 메시지가 표시됩니다.

인그레스 테스트

  1. /greet-the-world 경로를 사용하여 인그레스를 테스트합니다.

    curl CLUSTER_INGRESS_VIP/greet-the-world
    

    CLUSTER_INGRESS_VIP를 인그레스의 외부 IP 주소로 바꿉니다.

    출력에 Hello, world! 메시지가 표시됩니다.

    Hello, world!
    Version: 2.0.0
    Hostname: ...
    
  2. /greet-kubernetes 경로를 사용하여 인그레스를 테스트합니다.

    curl CLUSTER_INGRESS_VIP/greet-kubernetes
    

    출력에 Hello, Kubernetes! 메시지가 표시됩니다.

    Hello Kubernetes!
    

번들 인그레스 사용 중지

Google Distributed Cloud와 함께 번들로 제공되는 인그레스 기능은 인그레스 기능만 지원합니다. Istio 또는 Cloud Service Mesh와 통합할 수 있습니다. 이러한 제품은 상호 전송 계층 보안 (mTLS), 서비스 간 인증 관리 기능, 워크로드 관측 가능성과 같이 모든 기능을 갖춘 서비스 메시의 추가 이점을 제공합니다. Istio 또는 Cloud Service Mesh와 통합하는 경우 번들 인그레스 기능을 사용 중지하는 것이 좋습니다.

클러스터 구성 파일의 spec.clusterNetwork.bundledIngress 필드를 사용하여 번들 인그레스를 사용 설정하거나 중지할 수 있습니다. 이 필드는 버전 1.13.0 이상 클러스터에서만 사용할 수 있습니다. bundledIngress 필드의 기본값은 true이며 생성된 클러스터 구성 파일에 없습니다. 이 필드는 변경 가능하며 버전 1.13.0 이상의 클러스터를 만들거나 업데이트할 때 변경할 수 있습니다.

  • 번들 인그레스 기능을 사용 중지하려면 클러스터 구성 파일의 clusterNetwork 섹션에 bundledIngress 필드를 추가하고 다음 예와 같이 값을 false로 설정합니다.

    apiVersion: v1
    kind: Namespace
    metadata:
      name: cluster-hybrid-basic
    ---
    apiVersion: baremetal.cluster.gke.io/v1
    kind: Cluster
    metadata:
      name: hybrid-basic
      namespace: cluster-hybrid-basic
    spec:
      type: hybrid
      profile: default
      anthosBareMetalVersion: 1.13.0
      gkeConnect:
        projectID: project-fleet
      controlPlane:
        nodePoolSpec:
          nodes:
          - address: 10.200.0.2
      clusterNetwork:
        bundledIngress: false
        pods:
          cidrBlocks:
          - 192.168.0.0/16
        services:
          cidrBlocks:
          - 10.96.0.0/20
    ...
    

인그레스에 HTTPS 설정

클라이언트의 HTTPS 요청을 수락하려면 인그레스 프록시에 인증서가 있어야 인그레스 프록시가 클라이언트에게 ID를 증명할 수 있습니다. 또한 이 프록시에 비공개 키가 있어야 HTTPS 핸드셰이크를 완료할 수 있습니다.

다음 예시에서 이러한 항목이 사용됩니다.

  • 인그레스 프록시: HTTPS 핸드셰이크에 참여한 후 hello-service 서비스의 구성원 포드에 패킷을 전달합니다.

  • hello-service 서비스의 도메인: 예시 조직의 altostrat.com

다음 단계를 따르세요.

  1. 루트 인증서와 비공개 키를 만듭니다. 이 예시에서는 루트 CA 예시 조직에서 root.ca.example.com의 루트 인증 기관을 사용합니다.

    openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj \
        '/O=Root CA Example Inc./CN=root.ca.example.com' -keyout root-ca.key \
        -out root-ca.crt
    
  2. 인증서 서명 요청을 만듭니다.

     openssl req -out server.csr -newkey rsa:2048 -nodes -keyout server.key -subj \
         "/CN=altostrat.com/O=Example Org"
    
  3. 인그레스 프록시에 대해 서빙 인증서를 만듭니다.

    openssl x509 -req -days 365 -CA root-ca.crt -CAkey root-ca.key -set_serial 0 \
        -in server.csr -out server.crt
    

    이제 다음 인증서 및 키가 생성되었습니다.

    • root-ca.crt: 루트 CA의 인증서
    • root-ca.key: 루트 CA의 비공개 키
    • server.crt: 인그레스 프록시에 대한 제공 인증서
    • server.key: 인그레스 프록시의 비공개 키
  4. 서빙 인증서 및 키가 포함된 Kubernetes 보안 비밀을 만듭니다.

    kubectl create secret tls example-server-creds --key=server.key --cert=server.crt \
        --namespace gke-system
    

    결과 보안 비밀은 이름이 example-server-creds로 지정됩니다.

배포 및 서비스 만들기

이 가이드의 HTTP 부분에서 배포와 서비스를 만든 경우 이를 그대로 둡니다. 만들지 않았으면 HTTP에 설명된 단계에 따라 지금 만듭니다.

인그레스 만들기

HTTPS용 인그레스를 만드는 것은 HTTP용 인그레스를 만드는 것과 비슷하지만 HTTPS용 인그레스 사양에는 호스트와 보안 비밀을 지정하는 tls 섹션이 포함됩니다. tls 섹션의 hostsrules 섹션의 host와 명시적으로 일치해야 합니다.

백엔드 서비스가 별도의 네임스페이스에 있는 경우 인그레스와 동일한 네임스페이스에 ExternalName 유형의 서비스를 만들어 트래픽을 백엔드 서비스로 라우팅해야 합니다.

HTTPS 또는 HTTP용 인그레스를 만드는 전체 단계는 매니페스트 파일에서 구성하는 내용을 제외하고 동일합니다.

  1. 이 문서의 이전에 HTTP 부분에서 인그레스를 만든 경우 계속하기 전에 해당 인그레스를 삭제합니다.

    kubectl --kubeconfig CLUSTER_KUBECONFIG delete ingress my-ingress
    
  2. 이전에 만든 서비스의 트래픽을 처리하려면 tls 섹션이 있는 새 인그레스 매니페스트를 만듭니다.

    tls 구성을 사용하면 클라이언트와 인그레스 프록시 간에 HTTPS가 사용 설정됩니다.

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: my-ingress-2
    spec:
      tls:
      - hosts:
        - altostrat.com
        secretName: example-server-creds
      rules:
      - host: altostrat.com
        http:
          paths:
          - path: /greet-the-world
            pathType: Exact
            backend:
              service:
                name: hello-service
                port:
                  number: 60000
          - path: /greet-kubernetes
            pathType: Exact
            backend:
              service:
                name: hello-service
                port:
                  number: 60001
    
  3. 매니페스트를 my-ingress-2.yaml이라는 파일에 저장하고 인그레스를 만듭니다.

    kubectl apply --kubeconfig CLUSTER_KUBECONFIG -f my-ingress-2.yaml
    
  4. 다음과 같이 테스트하여 인그레스가 생성되었고 제대로 작동하는지 확인합니다.

    • /greet-the-world 경로를 테스트합니다.

      curl -v --resolve altostrat.com:443:CLUSTER_INGRESS_VIP \
          https://altostrat.com/greet-the-world \
          --cacert root-ca.crt
      

      출력:

      Hello, world!
      Version: 2.0.0
      Hostname: hello-deployment-5ff7f68854-wqzp7
      
    • /greet-kubernetes 경로를 테스트합니다.

      curl -v --resolve altostrat.com:443:CLUSTER_INGRESS_VIP \
          https://altostrat.com/greet-kubernetes --cacert root-ca.crt
      

      출력:

      Hello Kubernetes!
      

LoadBalancer 서비스 만들기

클러스터 외부에 워크로드를 노출하는 또 다른 방법으로 LoadBalancer 유형의 서비스가 있습니다. LoadBalancer 유형의 서비스를 만드는 방법에 대한 안내 및 예시는 애플리케이션 배포에서 LoadBalancer 유형의 서비스 만들기를 참고하세요.

삭제

  1. 인그레스를 삭제합니다.

    kubectl --kubeconfig CLUSTER_KUBECONFIG delete ingress INGRESS_NAME
    

    INGRESS_NAMEmy-ingress 또는 my-ingress-2와 같은 인그레스 이름으로 바꿉니다.

  2. 서비스를 삭제합니다.

    kubectl --kubeconfig CLUSTER_KUBECONFIG delete service hello-service
    
  3. 배포를 삭제합니다.

    kubectl --kubeconfig CLUSTER_KUBECONFIG delete deployment hello-deployment
    
  4. LoadBalancer 서비스를 삭제합니다.

    kubectl --kubeconfig CLUSTER_KUBECONFIG delete service service-does-not-use-nodeports