Redis 및 PHP를 사용하여 다중 계층 웹 애플리케이션 만들기


이 튜토리얼에서는 Google Kubernetes Engine(GKE)을 사용하여 다중 계층 웹 애플리케이션을 빌드하는 방법을 보여줍니다.

이 튜토리얼에서는 다음 작업을 수행합니다.

  • 외부 IP 주소 및 부하 분산기로 웹 애플리케이션을 설정합니다.
  • 단일 마스터(리더) 및 여러 복제본(팔로어)으로 Redis 클러스터를 만듭니다.

이 예시에서는 다음 Kubernetes 개념을 설명합니다.

  • YAML 매니페스트 파일을 사용하는 선언적 구성
  • 복제된 포드 집합의 구성을 결정하는 Kubernetes 리소스인 배포
  • 포드 집합의 내부 및 외부 부하 분산기를 만들기 위한 서비스

목표

GKE에서 애플리케이션을 배포하고 실행하려면 다음 안내를 따르세요.

  1. Redis 리더 설정
  2. Redis 팔로어 2개 설정
  3. 웹 프런트엔드 설정
  4. 웹사이트 방문
  5. 웹 프런트엔드 확장

다음 다이어그램에서는 이러한 목표를 완료하여 생성하는 클러스터 아키텍처의 개요를 보여줍니다.

GKE 클러스터 아키텍처

비용

이 문서에서는 비용이 청구될 수 있는 다음과 같은 Google Cloud 구성요소를 사용합니다.

프로젝트 사용량을 기준으로 예상 비용을 산출하려면 가격 계산기를 사용하세요. Google Cloud를 처음 사용하는 사용자는 무료 체험판을 사용할 수 있습니다.

이 문서에 설명된 태스크를 완료했으면 만든 리소스를 삭제하여 청구가 계속되는 것을 방지할 수 있습니다. 자세한 내용은 삭제를 참조하세요.

시작하기 전에

Cloud Shell에는 kubectlgcloud CLI 등 이 튜토리얼에 필요한 소프트웨어가 사전 설치되어 있습니다. Cloud Shell을 사용하지 않는 경우에는 gcloud CLI를 설치해야 합니다.

  1. Google Cloud 계정에 로그인합니다. Google Cloud를 처음 사용하는 경우 계정을 만들고 Google 제품의 실제 성능을 평가해 보세요. 신규 고객에게는 워크로드를 실행, 테스트, 배포하는 데 사용할 수 있는 $300의 무료 크레딧이 제공됩니다.
  2. Google Cloud CLI를 설치합니다.
  3. gcloud CLI를 초기화하려면 다음 명령어를 실행합니다.

    gcloud init
  4. Google Cloud 프로젝트를 만들거나 선택합니다.

    • Google Cloud 프로젝트를 만듭니다.

      gcloud projects create PROJECT_ID

      PROJECT_ID를 만들려는 Google Cloud 프로젝트의 이름으로 바꿉니다.

    • 만든 Google Cloud 프로젝트를 선택합니다.

      gcloud config set project PROJECT_ID

      PROJECT_ID를 Google Cloud 프로젝트 이름으로 바꿉니다.

  5. Google Cloud 프로젝트에 결제가 사용 설정되어 있는지 확인합니다.

  6. GKE API를 사용 설정합니다.

    gcloud services enable container.googleapis.com
  7. Google Cloud CLI를 설치합니다.
  8. gcloud CLI를 초기화하려면 다음 명령어를 실행합니다.

    gcloud init
  9. Google Cloud 프로젝트를 만들거나 선택합니다.

    • Google Cloud 프로젝트를 만듭니다.

      gcloud projects create PROJECT_ID

      PROJECT_ID를 만들려는 Google Cloud 프로젝트의 이름으로 바꿉니다.

    • 만든 Google Cloud 프로젝트를 선택합니다.

      gcloud config set project PROJECT_ID

      PROJECT_ID를 Google Cloud 프로젝트 이름으로 바꿉니다.

  10. Google Cloud 프로젝트에 결제가 사용 설정되어 있는지 확인합니다.

  11. GKE API를 사용 설정합니다.

    gcloud services enable container.googleapis.com

환경 준비

환경을 설정하려면 다음 단계를 수행합니다.

  1. 환경 변수를 설정합니다.

    export PROJECT_ID=PROJECT_ID
    export COMPUTE_LOCATION=COMPUTE_LOCATION
    

    다음을 바꿉니다.

  2. GitHub 저장소를 클론합니다.

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
    
  3. 작업 디렉터리로 변경합니다.

    cd kubernetes-engine-samples/quickstarts/guestbook/
    

GKE 클러스터 만들기

Autopilot 또는 표준 GKE 클러스터를 만듭니다.

Autopilot

gcloud container clusters create-auto guestbook \
    --location=${COMPUTE_LOCATION} \

스탠더드

gcloud container clusters create guestbook \
    --location=${COMPUTE_LOCATION} \
    --num-nodes=4

클러스터에 연결

클러스터와 통신하도록 kubectl을 구성합니다.

gcloud container clusters get-credentials guestbook \
    --location=${COMPUTE_LOCATION}

Redis 리더 설정

이 애플리케이션은 Redis를 사용하여 데이터를 저장합니다. 이 애플리케이션은 Redis 리더 인스턴스에 데이터를 쓰고 여러 Redis 팔로어 인스턴스에서 데이터를 읽습니다.

  1. 다음 매니페스트에서는 단일 복제본 Redis 리더 포드를 실행하는 Kubernetes 배포를 설명합니다.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: redis-leader
      labels:
        app: redis
        role: leader
        tier: backend
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: redis
      template:
        metadata:
          labels:
            app: redis
            role: leader
            tier: backend
        spec:
          containers:
          - name: leader
            image: "docker.io/redis:6.0.5"
            resources:
              requests:
                cpu: 100m
                memory: 100Mi
            ports:
            - containerPort: 6379

    매니페스트를 클러스터에 적용합니다.

    kubectl apply -f redis-leader-deployment.yaml
    
  2. Redis 리더 포드가 실행 중인지 확인합니다.

    kubectl get pods
    

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

    NAME                           READY     STATUS    RESTARTS   AGE
    redis-leader-343230949-qfvrq   1/1       Running   0          43s
    

    STATUSPending에서 Running으로 변경되는 데 몇 분 정도 걸릴 수 있습니다.

Redis 리더 서비스 만들기

웹 애플리케이션은 데이터를 쓰기 위해 Redis 리더와 통신해야 합니다. 서비스를 만들어 트래픽을 Redis 리더 포드로 프록시 처리할 수 있습니다.

서비스는 논리적 포드 집합과 포드에 대한 액세스를 사용 설정하는 정책을 정의하는 Kubernetes 추상화입니다. 서비스를 만들 때는 포드 라벨을 기준으로 어떤 포드를 프록시 처리할지 설명합니다.

  1. 다음 매니페스트에서는 Redis 리더에 대한 서비스를 설명합니다.

    apiVersion: v1
    kind: Service
    metadata:
      name: redis-leader
      labels:
        app: redis
        role: leader
        tier: backend
    spec:
      ports:
      - port: 6379
        targetPort: 6379
      selector:
        app: redis
        role: leader
        tier: backend

    이 매니페스트에는 라벨 선택기 집합이 포함됩니다. 이러한 라벨은 이전 단계에서 배포된 라벨 집합과 일치합니다. 따라서 이 서비스는 이전 단계에서 만든 Redis 리더 포드로 네트워크 트래픽을 라우팅합니다.

    매니페스트의 ports 섹션은 단일 포트 매핑을 선언합니다. 이 서비스는 port: 6379의 트래픽을 지정된 selector 라벨과 일치하는 컨테이너의 targetPort: 6379로 라우팅합니다. 트래픽을 배포로 라우팅하려면 배포에서 사용되는 containerPorttargetPort와 일치해야 합니다.

    매니페스트를 클러스터에 적용합니다.

    kubectl apply -f redis-leader-service.yaml
    
  2. GKE에서 서비스를 만들었는지 확인합니다.

    kubectl get service
    

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

    NAME           CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
    kubernetes     10.51.240.1     <none>        443/TCP    42s
    redis-leader   10.51.242.233   <none>        6379/TCP   12s
    

Redis 팔로어 설정

Redis 리더가 단일 포드라도 Redis 팔로어 즉, 복제본을 여러 개 추가하여 가용성을 높이고 트래픽 수요를 충족할 수 있습니다.

  1. 다음 매니페스트는 Redis 팔로어 포드에 대한 배포를 설명합니다.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: redis-follower
      labels:
        app: redis
        role: follower
        tier: backend
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: redis
      template:
        metadata:
          labels:
            app: redis
            role: follower
            tier: backend
        spec:
          containers:
          - name: follower
            image: us-docker.pkg.dev/google-samples/containers/gke/gb-redis-follower:v2
            resources:
              requests:
                cpu: 100m
                memory: 100Mi
            ports:
            - containerPort: 6379
  2. 매니페스트를 클러스터에 적용합니다.

    kubectl apply -f redis-follower-deployment.yaml
    
  3. 2개의 Redis 팔로어 복제본이 실행 중인지 확인합니다.

    kubectl get pods
    

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

    NAME                              READY   STATUS    RESTARTS   AGE
    redis-follower-76588f55b7-bnsq6   1/1     Running   0          27s
    redis-follower-76588f55b7-qvtws   1/1     Running   0          27s
    redis-leader-dd446dc55-kl7nl      1/1     Running   0          119s
    

    STATUSPending에서 Running으로 변경되는 데 몇 분 정도 걸릴 수 있습니다.

Redis 팔로어 서비스 만들기

웹 애플리케이션은 데이터를 읽기 위해 Redis 팔로어와 통신해야 합니다. Redis 팔로어를 검색할 수 있도록 하려면 서비스를 설정해야 합니다.

  1. 다음 매니페스트에서는 Redis 팔로어를 위한 서비스를 설명합니다.

    apiVersion: v1
    kind: Service
    metadata:
      name: redis-follower
      labels:
        app: redis
        role: follower
        tier: backend
    spec:
      ports:
        # the port that this service should serve on
      - port: 6379
      selector:
        app: redis
        role: follower
        tier: backend

    이 매니페스트에서는 포트 6379에서 실행되는 포트를 지정합니다. 서비스의 selector 필드는 이전 단계에서 만든 Redis 팔로어 포드와 일치합니다.

    매니페스트를 클러스터에 적용합니다.

    kubectl apply -f redis-follower-service.yaml
    
  2. GKE에서 서비스를 생성했는지 확인합니다.

    kubectl get service
    

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

    NAME           CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
    kubernetes     10.51.240.1     <none>        443/TCP    1m
    redis-leader   10.51.242.233   <none>        6379/TCP   49s
    redis-follower 10.51.247.238   <none>        6379/TCP   3s
    

애플리케이션 웹 프런트엔드 설정

이제 애플리케이션에 Redis 스토리지가 준비되었으므로 웹 서버를 시작합니다. Redis 팔로어와 마찬가지로 프런트엔드는 Kubernetes 배포를 사용하여 배포됩니다.

웹 애플리케이션은 요청이 읽기인지 쓰기인지에 따라 Redis 팔로어 또는 리더 서비스와 통신하도록 구성된 PHP 프런트엔드를 사용합니다. 프런트엔드는 JSON 인터페이스를 노출하고 jQuery-Ajax 기반 UX를 제공합니다.

  1. 다음 매니페스트에서는 웹 서버 배포를 설명합니다.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: frontend
    spec:
      replicas: 3
      selector:
        matchLabels:
            app: guestbook
            tier: frontend
      template:
        metadata:
          labels:
            app: guestbook
            tier: frontend
        spec:
          containers:
          - name: php-redis
            image: us-docker.pkg.dev/google-samples/containers/gke/gb-frontend:v5
            env:
            - name: GET_HOSTS_FROM
              value: "dns"
            resources:
              requests:
                cpu: 100m
                memory: 100Mi
            ports:
            - containerPort: 80

    매니페스트 파일은 환경 변수 GET_HOSTS_FROM=dns를 지정합니다. 웹 프런트엔드 애플리케이션에 구성을 제공하면 프런트엔드 애플리케이션은 호스트 이름 redis-followerredis-leader를 사용하여 DNS 조회를 수행합니다. DNS 조회는 이전 단계에서 만든 서비스의 IP 주소를 찾습니다. 이 개념을 DNS 서비스 검색이라고 합니다.

    매니페스트를 클러스터에 적용합니다.

    kubectl apply -f frontend-deployment.yaml
    
  2. 복제본이 실행 중인지 확인합니다.

    kubectl get pods -l app=guestbook -l tier=frontend
    

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

    NAME                        READY   STATUS    RESTARTS   AGE
    frontend-7b78458576-8kp8s   1/1     Running   0          37s
    frontend-7b78458576-gg86q   1/1     Running   0          37s
    frontend-7b78458576-hz87g   1/1     Running   0          37s
    

외부 IP 주소에 프런트엔드 노출

현재 구성에서 서비스 기본 유형이 ClusterIP이므로 이전 단계에서 만든 redis-followerredis-leader 서비스는 GKE 클러스터 내에서만 액세스할 수 있습니다.

ClusterIP 서비스는 서비스가 가리키는 포드 집합에 단일 IP 주소를 제공합니다. 이 IP 주소는 클러스터 내에서만 액세스할 수 있습니다.

웹 프런트엔드 서비스를 외부에서 액세스할 수 있도록 하려면 요구사항에 따라 서비스 구성에서 type: LoadBalancer 또는 type: NodePort를 지정할 수 있습니다.

다음 매니페스트에서는 LoadBalancer 유형의 서비스를 설명합니다.

apiVersion: v1
kind: Service
metadata:
  name: frontend
  labels:
    app: guestbook
    tier: frontend
spec:
  type: LoadBalancer
  ports:
    # the port that this service should serve on
  - port: 80
  selector:
    app: guestbook
    tier: frontend

ports 섹션의 포트 선언은 port: 80을 지정하며 targetPort는 지정되지 않습니다. targetPort 속성을 생략하면 기본적으로 port 필드 값이 사용됩니다. 이 경우 이 서비스는 포트 80의 외부 트래픽을 frontend 배포의 컨테이너 포트 80으로 라우팅합니다.

매니페스트를 클러스터에 적용합니다.

kubectl apply -f frontend-service.yaml

frontend 서비스가 생성되면 GKE는 부하 분산기와 외부 IP 주소를 만듭니다. 이러한 리소스는 청구 대상입니다.

애플리케이션 웹사이트 방문

애플리케이션 웹사이트에 액세스하려면 frontend 서비스의 외부 IP 주소를 가져옵니다.

kubectl get service frontend

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

NAME       CLUSTER-IP      EXTERNAL-IP        PORT(S)        AGE
frontend   10.51.242.136   109.197.92.229     80:32372/TCP   1m

부하 분산기를 만드는 동안 EXTERNAL-IP 열에 <pending>이 표시될 수 있습니다. 이 작업은 몇 분 정도 걸릴 수 있습니다. Does not have minimum availability와 같은 오류가 표시되면 몇 분 정도 기다립니다. 이 일시적인 오류는 GKE에서 노드를 다시 생성하여 변경하기 때문에 발생합니다.

IP 주소를 복사하고 브라우저에서 페이지를 엽니다.

GKE에서 실행되는 웹 애플리케이션

메시지를 입력하고 제출을 클릭하여 몇 가지 항목을 추가해 보세요. 입력한 메시지가 프런트엔드에 표시됩니다. 이 메시지는 생성된 서비스를 통해 데이터가 Redis에 성공적으로 추가되었음을 나타냅니다.

웹 프런트엔드 확장

애플리케이션이 실행된 지 어느 정도 지나 갑자기 유명해졌다고 가정해 보세요. 프런트엔드에 웹 서버를 추가하는 것이 좋겠다고 결정합니다. 포드 수를 늘려 이 작업을 수행할 수 있습니다.

  1. frontend 포드 수를 확장합니다.

    kubectl scale deployment frontend --replicas=5
    

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

    deployment.extensions/frontend scaled
    
  2. 실행 중인 복제본 수를 확인합니다.

    kubectl get pods
    

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

    NAME                             READY     STATUS    RESTARTS   AGE
    frontend-88237173-3s3sc          1/1       Running   0          1s
    frontend-88237173-twgvn          1/1       Running   0          1s
    frontend-88237173-5p257          1/1       Running   0          23m
    frontend-88237173-84036          1/1       Running   0          23m
    frontend-88237173-j3rvr          1/1       Running   0          23m
    redis-leader-343230949-qfvrq     1/1       Running   0          54m
    redis-follower-132015689-dp23k   1/1       Running   0          37m
    redis-follower-132015689-xq9v0   1/1       Running   0          37m
    

    51로 바꾼 동일한 명령어를 사용하여 frontend 포드 수를 줄일 수 있습니다.

삭제

이 튜토리얼에서 사용된 리소스 비용이 Google Cloud 계정에 청구되지 않도록 하려면 리소스가 포함된 프로젝트를 삭제하거나 프로젝트를 유지하고 개별 리소스를 삭제하세요.

프로젝트 삭제

    Google Cloud 프로젝트를 삭제합니다.

    gcloud projects delete PROJECT_ID

개별 리소스 삭제

기존 프로젝트를 사용한 경우 삭제하지 않으려면 개별 리소스를 삭제합니다.

  1. frontend 서비스를 삭제합니다.

    kubectl delete service frontend
    
  2. GKE 클러스터를 삭제합니다.

    gcloud container clusters delete guestbook
    

다음 단계