서비스를 사용하여 애플리케이션 노출

이 페이지에서는 Google Kubernetes Engine(GKE) 클러스터에서 Kubernetes 서비스를 만드는 방법을 보여줍니다. 서비스 개념 설명 및 여러 가지 서비스 유형 설명은 서비스를 참조하세요.

소개

서비스의 개념은 일련의 포드 엔드포인트를 단일 리소스로 그룹화하는 것입니다. 그룹화는 여러 방법으로 구성할 수 있습니다. 기본적으로는 클러스터 내부의 클라이언트가 서비스에서 포드에 연락하기 위해 사용할 수 있는 안정적인 클러스터 IP 주소를 사용합니다. 클라이언트는 안정적인 IP 주소로 요청을 전송하고, 요청이 서비스에 있는 포드 중 하나로 라우팅됩니다.

서비스의 5가지 유형은 다음과 같습니다.

  • ClusterIP(기본값)
  • NodePort
  • LoadBalancer
  • ExternalName
  • Headless

Autopilot 클러스터는 기본적으로 공개됩니다. 비공개 Autopilot 클러스터를 선택할 경우 DockerHub에서 이미지를 가져올 때와 같이 아웃바운드 인터넷 연결을 위해 Cloud NAT를 구성해야 합니다.

이 문서에는 몇 가지 연습이 포함되어 있습니다. 각 연습에서는 서비스를 만들어서 배포를 만들고 포드를 노출합니다. 그런 후 서비스에 HTTP 요청을 전송합니다.

시작하기 전에

시작하기 전에 다음 태스크를 수행했는지 확인합니다.

  • Google Kubernetes Engine API를 사용 설정합니다.
  • Google Kubernetes Engine API 사용 설정
  • 이 태스크에 Google Cloud CLI를 사용하려면 gcloud CLI를 설치한 후 초기화합니다. 이전에 gcloud CLI를 설치한 경우 gcloud components update를 실행하여 최신 버전을 가져옵니다.
* GKE 클러스터 만들기

ClusterIP 유형의 서비스 만들기

이 섹션에서는 ClusterIP 유형의 서비스를 만듭니다.

kubectl apply

배포 매니페스트는 다음과 같습니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment
spec:
  selector:
    matchLabels:
      app: metrics
      department: sales
  replicas: 3
  template:
    metadata:
      labels:
        app: metrics
        department: sales
    spec:
      containers:
      - name: hello
        image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0"

my-deployment.yaml 파일에 매니페스트를 복사하고 배포를 만듭니다.

kubectl apply -f my-deployment.yaml

3개의 포드가 실행 중인지 확인합니다.

kubectl get pods

출력에는 실행 중인 3개의 포드가 표시됩니다.

NAME                            READY   STATUS    RESTARTS   AGE
my-deployment-dbd86c8c4-h5wsf   1/1     Running   0          7s
my-deployment-dbd86c8c4-qfw22   1/1     Running   0          7s
my-deployment-dbd86c8c4-wt4s6   1/1     Running   0          7s

ClusterIP 유형 서비스의 매니페스트는 다음과 같습니다.

apiVersion: v1
kind: Service
metadata:
  name: my-cip-service
spec:
  type: ClusterIP
  # Uncomment the below line to create a Headless Service
  # clusterIP: None
  selector:
    app: metrics
    department: sales
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080

이 서비스에는 2개의 라벨을 지정하는 선택기가 있습니다.

  • app: metrics
  • department: sales

이전에 생성한 배포의 각 포드에는 다음 두 개의 라벨이 포함됩니다. 따라서 배포에 있는 포드가 이 서비스의 구성원이 됩니다.

매니페스트를 my-cip-service.yaml 파일에 복사하고 서비스를 만듭니다.

kubectl apply -f my-cip-service.yaml

Kubernetes가 안정적인 내부 주소를 서비스에 할당할 때까지 기다린 후 서비스를 확인합니다.

kubectl get service my-cip-service --output yaml

출력에 clusterIP의 값이 표시됩니다.

spec:
  clusterIP: 10.59.241.241

나중을 위해 clusterIP 값을 기록해 둡니다.

콘솔

배포 만들기

  1. Google Cloud 콘솔에서 워크로드 페이지로 이동합니다.

    워크로드로 이동

  2. 배포를 클릭합니다.

  3. 컨테이너 지정에서 기존 컨테이너 이미지를 선택합니다.

  4. 이미지 경로에 대해 us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0을 입력합니다.

  5. 완료를 클릭한 후 계속을 클릭합니다.

  6. 구성에서 애플리케이션 이름my-deployment를 입력합니다.

  7. 라벨에서 다음 라벨을 만듭니다.

    • 키: app값: metrics
    • 키: department값: sales
  8. 클러스터에서 배포를 만들려는 클러스터를 선택합니다.

  9. 배포를 클릭합니다.

  10. 배포가 준비되면 배포 세부정보 페이지가 열립니다. 관리형 포드에서 배포에 하나 이상의 실행 중인 포드가 있는지 확인할 수 있습니다.

배포를 노출하기 위한 서비스 만들기

  1. 배포 세부정보 페이지에서 작업 > 노출을 클릭합니다.
  2. 노출 대화상자의 포트 매핑에서 다음 값을 설정합니다.

    • 포트: 80
    • 대상 포트: 8080
    • 프로토콜: TCP
  3. 서비스 유형 드롭다운 목록에서 클러스터 IP를 선택합니다.

  4. 노출을 클릭합니다.

  5. 서비스가 준비되었으면 서비스 세부정보 페이지가 열리고 서비스 세부정보를 확인할 수 있습니다. 클러스터 IP에서 Kubernetes가 서비스에 할당한 IP 주소를 기록해 둡니다. 이것은 내부 클라이언트가 서비스 호출을 위해 사용할 수 있는 IP 주소입니다.

서비스 액세스

실행 중인 포드를 나열합니다.

kubectl get pods

출력에서 my-deployment로 시작하는 포드 이름을 복사합니다.

NAME                            READY   STATUS    RESTARTS   AGE
my-deployment-dbd86c8c4-h5wsf   1/1     Running   0          2m51s

실행 중인 컨테이너 중 하나에 셸로 들어갑니다.

kubectl exec -it POD_NAME -- sh

POD_NAMEmy-deployment에 있는 포드 중 하나의 이름으로 바꿉니다.

셸에서 curl을 설치합니다.

apk add --no-cache curl

컨테이너에서 클러스터 IP 주소 및 포트 80을 사용하여 서비스에 요청을 수행합니다. 80은 서비스의 port 필드 값입니다. 이것은 서비스의 클라이언트로 사용하는 포트입니다.

curl CLUSTER_IP:80

CLUSTER_IP를 서비스의 clusterIP 값으로 바꿉니다.

요청은 TCP 포트 8080의 구성원 포드 중 하나로 전달되며, 이는 targetPort 필드의 값입니다. 서비스의 각 구성원 포드에는 포트 8080으로 수신 대기하는 컨테이너가 있어야 합니다.

응답에 hello-app의 출력이 표시됩니다.

Hello, world!
Version: 2.0.0
Hostname: my-deployment-dbd86c8c4-h5wsf

컨테이너의 셸에서 나오려면 exit를 입력합니다.

NodePort 유형의 서비스 만들기

이 섹션에서는 NodePort 유형의 서비스를 만듭니다.

kubectl apply

배포 매니페스트는 다음과 같습니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment-50000
spec:
  selector:
    matchLabels:
      app: metrics
      department: engineering
  replicas: 3
  template:
    metadata:
      labels:
        app: metrics
        department: engineering
    spec:
      containers:
      - name: hello
        image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0"
        env:
        - name: "PORT"
          value: "50000"

매니페스트에서 env 객체를 확인합니다. env 객체는 실행 중인 컨테이너의 PORT 환경 변수가 50000 값을 갖도록 지정합니다. hello-app 애플리케이션은 PORT 환경 변수가 지정한 포트에서 수신 대기합니다. 따라서 이 연습에서는 컨테이너가 포트 50000에서 수신 대기하도록 지정합니다.

my-deployment-50000.yaml 파일에 매니페스트를 복사하고 배포를 만듭니다.

kubectl apply -f my-deployment-50000.yaml

3개의 포드가 실행 중인지 확인합니다.

kubectl get pods

NodePort 유형 서비스의 매니페스트는 다음과 같습니다.

apiVersion: v1
kind: Service
metadata:
  name: my-np-service
spec:
  type: NodePort
  selector:
    app: metrics
    department: engineering
  ports:
  - protocol: TCP
    port: 80
    targetPort: 50000

매니페스트를 my-np-service.yaml 파일에 복사하고 서비스를 만듭니다.

kubectl apply -f my-np-service.yaml

서비스를 확인합니다.

kubectl get service my-np-service --output yaml

출력에 nodePort 값이 표시됩니다.

...
  spec:
    ...
    ports:
    - nodePort: 30876
      port: 80
      protocol: TCP
      targetPort: 50000
    selector:
      app: metrics
      department: engineering
    sessionAffinity: None
    type: NodePort
...

노드 포트에서 TCP 트래픽을 허용하도록 방화벽 규칙을 만듭니다.

gcloud compute firewall-rules create test-node-port \
    --allow tcp:NODE_PORT

NODE_PORT를 서비스의 nodePort 필드 값으로 바꿉니다.

콘솔

배포 만들기

  1. Google Cloud 콘솔에서 워크로드 페이지로 이동합니다.

    워크로드로 이동

  2. 배포를 클릭합니다.

  3. 컨테이너 지정에서 기존 컨테이너 이미지를 선택합니다.

  4. 이미지 경로에 대해 us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0을 입력합니다.

  5. 환경 변수 추가를 클릭합니다.

  6. PORT를 입력하고 50000을 입력합니다.

  7. 완료를 클릭한 후 계속을 클릭합니다.

  8. 구성에서 애플리케이션 이름my-deployment-50000를 입력합니다.

  9. 라벨에서 다음 라벨을 만듭니다.

    • 키: app값: metrics
    • 키: department값: engineering
  10. 클러스터에서 배포를 만들려는 클러스터를 선택합니다.

  11. 배포를 클릭합니다.

  12. 배포가 준비되면 배포 세부정보 페이지가 열립니다. 관리형 포드에서 배포에 하나 이상의 실행 중인 포드가 있는지 확인할 수 있습니다.

배포를 노출하기 위한 서비스 만들기

  1. 배포 세부정보 페이지에서 작업 > 노출을 클릭합니다.
  2. 노출 대화상자의 포트 매핑에서 다음 값을 설정합니다.

    • 포트: 80
    • 대상 포트: 50000
    • 프로토콜: TCP
  3. 서비스 유형 드롭다운 목록에서 노드 포트를 선택합니다.

  4. 노출을 클릭합니다.

  5. 서비스가 준비되었으면 서비스 세부정보 페이지가 열리고 서비스 세부정보를 확인할 수 있습니다. 포트에서 Kubernetes가 서비스에 할당한 노드 포트를 기록해 둡니다.

노드 포트의 방화벽 규칙 만들기

  1. Google Cloud 콘솔에서 방화벽 정책 페이지로 이동합니다.

    방화벽 정책으로 이동

  2. 방화벽 규칙 만들기를 클릭합니다.

  3. 이름test-node-port를 입력합니다.

  4. 대상 드롭다운 목록에서 네트워크의 모든 인스턴스를 선택합니다.

  5. 소스 IPv4 범위0.0.0.0/0을 입력합니다.

  6. 프로토콜 및 포트에서 지정된 프로토콜 및 포트를 선택합니다.

  7. tcp 체크박스를 선택하고 기록한 노드 포트 값을 입력합니다.

  8. 만들기를 클릭합니다.

노드 IP 주소 가져오기

노드 중 하나의 외부 IP 주소를 찾습니다.

kubectl get nodes --output wide

출력은 다음과 비슷합니다.

NAME          STATUS    ROLES     AGE    VERSION        EXTERNAL-IP
gke-svc-...   Ready     none      1h     v1.9.7-gke.6   203.0.113.1

모든 클러스터가 노드에 대해 외부 IP 주소를 갖지는 않습니다. 예를 들어 비공개 클러스터의 노드에는 외부 IP 주소가 없습니다.

서비스 액세스

브라우저의 주소 표시줄에 다음을 입력합니다.

NODE_IP_ADDRESS:NODE_PORT

다음을 바꿉니다.

  • NODE_IP_ADDRESS는 이전 작업에서 서비스를 만들 때 찾은 노드 중 하나의 외부 IP 주소입니다.
  • NODE_PORT: 노드 포트 값입니다.

출력은 다음과 비슷합니다.

Hello, world!
Version: 2.0.0
Hostname: my-deployment-50000-6fb75d85c9-g8c4f

LoadBalancer 유형의 서비스 만들기

이 섹션에서는 LoadBalancer 유형의 서비스를 만듭니다.

kubectl apply

배포 매니페스트는 다음과 같습니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment-50001
spec:
  selector:
    matchLabels:
      app: products
      department: sales
  replicas: 3
  template:
    metadata:
      labels:
        app: products
        department: sales
    spec:
      containers:
      - name: hello
        image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0"
        env:
        - name: "PORT"
          value: "50001"

이 배포의 컨테이너는 포트 50001에서 리슨합니다.

my-deployment-50001.yaml 파일에 매니페스트를 복사하고 배포를 만듭니다.

kubectl apply -f my-deployment-50001.yaml

3개의 포드가 실행 중인지 확인합니다.

kubectl get pods

LoadBalancer 유형 서비스의 매니페스트는 다음과 같습니다.

apiVersion: v1
kind: Service
metadata:
  name: my-lb-service
spec:
  type: LoadBalancer
  selector:
    app: products
    department: sales
  ports:
  - protocol: TCP
    port: 60000
    targetPort: 50001

my-lb-service.yaml,라는 파일에 매니페스트를 복사하고 서비스를 만듭니다.

kubectl apply -f my-lb-service.yaml

LoadBalancer 유형의 서비스를 만들면 Google Cloud 컨트롤러가 작동하여 외부 패스 스루 네트워크 부하 분산기를 구성합니다. 컨트롤러가 외부 패스 스루 네트워크 부하 분산기를 구성하고 안정적인 IP 주소를 생성할 때까지 1분 정도 기다립니다.

서비스를 확인합니다.

kubectl get service my-lb-service --output yaml

출력에서 loadBalancer:ingress 아래에 안정적인 외부 IP 주소가 표시됩니다.

...
spec:
  ...
  ports:
  - ...
    port: 60000
    protocol: TCP
    targetPort: 50001
  selector:
    app: products
    department: sales
  sessionAffinity: None
  type: LoadBalancer
status:
  loadBalancer:
    ingress:
    - ip: 203.0.113.10

콘솔

배포 만들기

  1. Google Cloud 콘솔에서 워크로드 페이지로 이동합니다.

    워크로드로 이동

  2. 배포를 클릭합니다.

  3. 컨테이너 지정에서 기존 컨테이너 이미지를 선택합니다.

  4. 이미지 경로에 대해 us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0을 입력합니다.

  5. 환경 변수 추가를 클릭합니다.

  6. PORT를 입력하고 50001을 입력합니다.

  7. 완료를 클릭한 후 계속을 클릭합니다.

  8. 구성에서 애플리케이션 이름my-deployment-50001를 입력합니다.

  9. 라벨에서 다음 라벨을 만듭니다.

    • 키: app값: products
    • 키: department값: sales
  10. 클러스터에서 배포를 만들려는 클러스터를 선택합니다.

  11. 배포를 클릭합니다.

  12. 배포가 준비되면 배포 세부정보 페이지가 열립니다. 관리형 포드에서 배포에 하나 이상의 실행 중인 포드가 있는지 확인할 수 있습니다.

배포를 노출하기 위한 서비스 만들기

  1. 배포 세부정보 페이지에서 작업 > 노출을 클릭합니다.
  2. 노출 대화상자의 포트 매핑에서 다음 값을 설정합니다.

    • 포트: 60000
    • 대상 포트: 50001
    • 프로토콜: TCP
  3. 서비스 유형 드롭다운 목록에서 부하 분산기를 선택합니다.

  4. 노출을 클릭합니다.

  5. 서비스가 준비되었으면 서비스 세부정보 페이지가 열리고 서비스 세부정보를 확인할 수 있습니다. 부하 분산기에서 부하 분산기의 외부 IP 주소를 기록해 둡니다.

서비스 액세스

GKE가 부하 분산기를 구성할 때까지 몇 분 정도 기다립니다.

브라우저의 주소 표시줄에 다음을 입력합니다.

LOAD_BALANCER_ADDRESS:60000

LOAD_BALANCER_ADDRESS를 부하 분산기의 외부 IP 주소로 바꿉니다.

응답에 hello-app의 출력이 표시됩니다.

Hello, world!
Version: 2.0.0
Hostname: my-deployment-50001-68bb7dfb4b-prvct

서비스의 port 값은 임의적입니다. 앞의 예시에서 port 값 60000을 사용하여 이를 보여줍니다.

ExternalName 유형의 서비스 만들기

이 섹션에서는 ExternalName 유형의 서비스를 만듭니다.

ExternalName 유형의 서비스는 외부 DNS 이름에 대한 내부 별칭을 제공합니다. 내부 클라이언트는 내부 DNS 이름을 사용하여 요청을 수행하고, 요청이 외부 이름으로 리디렉션됩니다.

ExternalName 유형 서비스의 매니페스트는 다음과 같습니다.

apiVersion: v1
kind: Service
metadata:
  name: my-xn-service
spec:
  type: ExternalName
  externalName: example.com

이전 예시에서 DNS 이름은 my-xn-service.default.svc.cluster.local입니다. 내부 클라이언트가 my-xn-service.default.svc.cluster.local에 요청을 전송하면 요청이 example.com으로 리디렉션됩니다.

kubectl expose를 사용하여 서비스 만들기

서비스 매니페스트를 작성하는 대신 kubectl expose를 사용하여 서비스를 만들어 배포를 노출할 수 있습니다.

이 주제의 앞 부분에 표시된 my-deployment를 노출하기 위해서는 다음 명령어를 입력할 수 있습니다.

kubectl expose deployment my-deployment --name my-cip-service \
    --type ClusterIP --protocol TCP --port 80 --target-port 8080

이 주제의 앞 부분에 표시된 my-deployment-50000을 노출하기 위해서는 다음 명령어를 입력할 수 있습니다.

kubectl expose deployment my-deployment-50000 --name my-np-service \
    --type NodePort --protocol TCP --port 80 --target-port 50000

이 주제의 앞 부분에 표시된 my-deployment-50001을 노출하기 위해서는 다음 명령어를 입력할 수 있습니다.

kubectl expose deployment my-deployment-50001 --name my-lb-service \
    --type LoadBalancer --port 60000 --target-port 50001

삭제

이 페이지의 연습을 완료한 후에는 다음 단계에 따라 자신의 계정에 원치 않는 비용이 발생하지 않도록 리소스를 삭제합니다.

kubectl apply

서비스 삭제

kubectl delete services my-cip-service my-np-service my-lb-service

배포 삭제

kubectl delete deployments my-deployment my-deployment-50000 my-deployment-50001

방화벽 규칙 삭제

gcloud compute firewall-rules delete test-node-port

콘솔

서비스 삭제

  1. Google Cloud 콘솔의 서비스 페이지로 이동합니다.

    서비스로 이동

  2. 이 연습에서 만든 서비스를 선택하고 삭제를 클릭합니다.

  3. 확인 메시지가 나타나면 삭제를 클릭합니다.

배포 삭제

  1. Google Cloud 콘솔에서 워크로드 페이지로 이동합니다.

    워크로드로 이동

  2. 이 연습에서 만든 배포를 선택한 후 삭제를 클릭합니다.

  3. 확인 메시지가 표시되면 선택한 배포와 연관된 수평형 포드 자동 확장 처리 삭제 체크박스를 선택하고 삭제를 클릭합니다.

방화벽 규칙 삭제

  1. Google Cloud 콘솔에서 방화벽 정책 페이지로 이동합니다.

    방화벽 정책으로 이동

  2. test-node-port 체크박스를 선택한 후 삭제를 클릭합니다.

  3. 확인 메시지가 나타나면 삭제를 클릭합니다.

다음 단계