Service로 프론트엔드를 백엔드에 연결하기

Service로 프론트엔드를 백엔드에 연결하기 (Connect a Frontend to a Backend Using Services)

이 태스크는 프론트엔드백엔드 마이크로서비스를 만드는 방법을 보여줘요. 백엔드 마이크로서비스는 "hello" 인사(greeter)예요. 프론트엔드는 nginx와 쿠버네티스 Service 객체를 사용해 백엔드를 노출해요.

출처: 문서

본문

목표 (Objectives)

  • Deployment 객체로 샘플 hello 백엔드 마이크로서비스를 만들고 실행해요.
  • Service 객체를 사용해 백엔드 마이크로서비스의 여러 레플리카에 트래픽을 보내요.
  • 역시 Deployment 객체로 nginx 프론트엔드 마이크로서비스를 만들고 실행해요.
  • 프론트엔드 마이크로서비스가 백엔드 마이크로서비스에 트래픽을 보내도록 구성해요.
  • type=LoadBalancer 의 Service 객체를 사용해 프론트엔드 마이크로서비스를 클러스터 밖에 노출해요.

시작하기 전에 (Before you begin)

이 태스크는 외부 로드 밸런서가 있는 Service를 사용하며, 이는 지원되는 환경이 필요해요. 환경이 이를 지원하지 않는다면 NodePort 유형의 Service를 대신 사용할 수 있어요.

Deployment로 백엔드 만들기

백엔드는 간단한 hello 인사 마이크로서비스예요. 백엔드 Deployment의 구성 파일은 다음과 같아요:

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend
spec:
  selector:
    matchLabels:
      app: hello
      tier: backend
      track: stable
  replicas: 3
  template:
    metadata:
      labels:
        app: hello
        tier: backend
        track: stable
    spec:
      containers:
        - name: hello
          image: "gcr.io/google-samples/hello-go-gke:1.0"
          ports:
            - name: http
              containerPort: 80
...

백엔드 Deployment를 만들어요:

kubectl apply -f https://k8s.io/examples/service/access/backend-deployment.yaml

백엔드 Deployment에 대한 정보를 봐요:

kubectl describe deployment backend

출력은 다음과 비슷해요:

Name:                           backend
Namespace:                      default
CreationTimestamp:              Mon, 24 Oct 2016 14:21:02 -0700
Labels:                         app=hello
                                tier=backend
                                track=stable
Annotations:                    deployment.kubernetes.io/revision=1
Selector:                       app=hello,tier=backend,track=stable
Replicas:                       3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType:                   RollingUpdate
MinReadySeconds:                0
RollingUpdateStrategy:          1 max unavailable, 1 max surge
Pod Template:
  Labels:       app=hello
                tier=backend
                track=stable
  Containers:
   hello:
    Image:              "gcr.io/google-samples/hello-go-gke:1.0"
    Port:               80/TCP
    Environment:        <none>
    Mounts:             <none>
  Volumes:              <none>
Conditions:
  Type          Status  Reason
  ----          ------  ------
  Available     True    MinimumReplicasAvailable
  Progressing   True    NewReplicaSetAvailable
OldReplicaSets:                 <none>
NewReplicaSet:                  hello-3621623197 (3/3 replicas created)
Events:
...

hello Service 객체 만들기

프론트엔드에서 백엔드로 요청을 보내는 핵심은 백엔드 Service예요. Service는 영구 IP 주소와 DNS 이름 항목을 만들어 백엔드 마이크로서비스가 항상 도달될 수 있게 해요. Service는 셀렉터를 사용해 트래픽을 라우팅할 파드를 찾아요.

먼저 Service 구성 파일을 살펴봐요:

---
apiVersion: v1
kind: Service
metadata:
  name: hello
spec:
  selector:
    app: hello
    tier: backend
  ports:
  - protocol: TCP
    port: 80
    targetPort: http
...

구성 파일에서 hello 라는 Service가 app: hellotier: backend 라벨을 가진 파드에 트래픽을 라우팅하는 것을 볼 수 있어요.

백엔드 Service를 만들어요:

kubectl apply -f https://k8s.io/examples/service/access/backend-service.yaml

이 시점에서 hello 애플리케이션의 레플리카 3개를 실행하는 backend Deployment가 있고, 그 파드에 트래픽을 라우팅할 수 있는 Service가 있어요. 하지만 이 서비스는 클러스터 밖에서는 사용할 수 없고 해석되지도 않아요.

프론트엔드 만들기

이제 백엔드가 실행 중이므로, 클러스터 밖에서 접근할 수 있고 요청을 프록시해 백엔드에 연결하는 프론트엔드를 만들 수 있어요.

프론트엔드는 백엔드 Service에 부여된 DNS 이름을 사용해 백엔드 워커 파드에 요청을 보내요. DNS 이름은 examples/service/access/backend-service.yaml 구성 파일의 name 필드 값인 hello 예요.

프론트엔드 Deployment의 파드는 hello 백엔드 Service에 요청을 프록시하도록 구성된 nginx 이미지를 실행해요. nginx 구성 파일은 다음과 같아요:

# The identifier Backend is internal to nginx, and used to name this specific upstream
upstream Backend {
    # hello is the internal DNS name used by the backend Service inside Kubernetes
    server hello;
}
server {
listen 80;
location / {
    # The following statement will proxy traffic to the upstream named Backend
    proxy_pass http://Backend;
}
}

백엔드와 비슷하게 프론트엔드에도 Deployment와 Service가 있어요. 백엔드와 프론트엔드 서비스 사이의 중요한 차이점은 프론트엔드 Service의 구성이 type: LoadBalancer 라는 점이에요. 이는 Service가 클라우드 제공자가 프로비저닝한 로드 밸런서를 사용하고 클러스터 밖에서 접근 가능하다는 뜻이에요.

---
apiVersion: v1
kind: Service
metadata:
  name: frontend
spec:
  selector:
    app: hello
    tier: frontend
  ports:
  - protocol: "TCP"
    port: 80
    targetPort: 80
  type: LoadBalancer
...
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
spec:
  selector:
    matchLabels:
      app: hello
      tier: frontend
      track: stable
  replicas: 1
  template:
    metadata:
      labels:
        app: hello
        tier: frontend
        track: stable
    spec:
      containers:
        - name: nginx
          image: "gcr.io/google-samples/hello-frontend:1.0"
          lifecycle:
            preStop:
              exec:
                command: ["/usr/sbin/nginx","-s","quit"]
...

프론트엔드 Deployment와 Service를 만들어요:

kubectl apply -f https://k8s.io/examples/service/access/frontend-deployment.yaml
kubectl apply -f https://k8s.io/examples/service/access/frontend-service.yaml

출력은 두 리소스 모두 생성됐음을 확인해요:

deployment.apps/frontend created
service/frontend created

참고:

프론트엔드 Service와 상호 작용하기

type LoadBalancer의 Service를 만들었다면 이 명령으로 외부 IP를 찾을 수 있어요:

kubectl get service frontend --watch

이것은 frontend Service의 구성을 표시하고 변경 사항을 지켜봐요. 처음에는 외부 IP가 <pending> 으로 나열돼요:

NAME       TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)  AGE
frontend   LoadBalancer   10.51.252.116   <pending>     80/TCP   10s

외부 IP가 프로비저닝되는 즉시 구성이 EXTERNAL-IP 표제 아래에 새 IP를 포함하도록 업데이트돼요:

NAME       TYPE           CLUSTER-IP      EXTERNAL-IP        PORT(S)  AGE
frontend   LoadBalancer   10.51.252.116   XXX.XXX.XXX.XXX    80/TCP   1m

그 IP는 이제 클러스터 밖에서 frontend 서비스와 상호 작용하는 데 사용할 수 있어요.

프론트엔드를 통해 트래픽 보내기

프론트엔드와 백엔드가 이제 연결됐어요. 프론트엔드 Service의 외부 IP에 curl 명령을 사용해 엔드포인트를 칠 수 있어요.

curl http://${EXTERNAL_IP} # replace this with the EXTERNAL-IP you saw earlier

출력은 백엔드가 생성한 메시지를 보여줘요:

{"message":"Hello"}

정리 (Cleaning up)

Service를 삭제하려면 다음 명령을 입력해요:

kubectl delete services frontend backend

백엔드와 프론트엔드 애플리케이션을 실행하는 Deployment, ReplicaSet, 파드를 삭제하려면 다음 명령을 입력해요:

kubectl delete deployment frontend backend

더 알아보기 (Learn more)