Redis 및 PHP로 방명록 만들기

이 가이드에서는 Google Kubernetes Engine(GKE)을 사용하여 다중 계층 웹 애플리케이션을 빌드하는 방법을 보여줍니다. 이 가이드 애플리케이션은 방문자가 로그에 텍스트를 입력하고 최근에 기록된 몇 개 항목을 볼 수 있는 방명록입니다.

이 가이드에서는 부하 분산기를 사용하여 외부 IP에서 방명록 웹 서비스를 설정하는 방법과 단일 마스터(리더) 및 여러 복제본(팔로어)으로 구성된 Redis 클러스터를 실행하는 방법을 보여줍니다.

이 예에서는 여러 가지 GKE의 중요 개념을 상세히 설명합니다.

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

목표

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

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

시작하기 전에

다음 단계에 따라 Kubernetes Engine API를 사용 설정합니다.
  1. Google Cloud Console에서 Kubernetes Engine 페이지로 이동합니다.
  2. 프로젝트를 만들거나 선택합니다.
  3. API 및 관련 서비스가 사용 설정될 때까지 기다립니다. 몇 분 정도 걸릴 수 있습니다.
  4. Cloud 프로젝트에 결제가 사용 설정되어 있는지 확인합니다. 프로젝트에 결제가 사용 설정되어 있는지 확인하는 방법을 알아보세요.

이 가이드에 사용된 다음 명령줄 도구를 설치합니다.

  • gcloud는 Kubernetes Engine 클러스터를 만들고 삭제하는 데 사용됩니다. gcloudGoogle Cloud SDK에 포함되어 있습니다.
  • kubectl은 Kubernetes Engine에서 사용되는 클러스터 조정 시스템인 Kubernetes를 관리하는 데 사용됩니다. gcloud를 사용하여 kubectl을 설치할 수 있습니다.
    gcloud components install kubectl

gcloud 명령줄 도구의 기본값 설정

gcloud 명령줄 도구에 프로젝트 IDCompute Engine 영역 옵션을 입력하는 시간을 절약하려면 기본값을 설정하면 됩니다.
gcloud config set project project-id
gcloud config set compute/zone compute-zone

GKE 클러스터 만들기

첫 번째 단계는 방명록 애플리케이션과 Redis 서비스를 실행할 GKE 클러스터를 만드는 것입니다.

guestbook이라는 GKE 클러스터를 만듭니다.

gcloud container clusters create guestbook --num-nodes=4

다음 명령어를 사용하여 프로젝트에서 실행 중인 클러스터를 나열할 수 있습니다.

gcloud container clusters list
gcloud container clusters describe guestbook

Redis 리더 설정

방명록 애플리케이션은 Redis를 사용하여 데이터를 저장합니다. 애플리케이션은 Redis 리더 인스턴스에 데이터를 쓰고 여러 Redis 팔로어 인스턴스에서 데이터를 읽습니다. 첫 번째 단계는 Redis 리더를 배포하는 것입니다.

먼저 샘플 매니페스트를 클론합니다.

git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
cd kubernetes-engine-samples/guestbook
git checkout abbb383

redis-leader-deployment라는 매니페스트 파일을 사용하여 Redis 리더를 배포합니다. 이 매니페스트 파일은 단일 복제본 Redis 리더 Pod를 실행하는 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

다음 명령어를 실행하여 Redis 리더를 배포합니다.

kubectl apply -f redis-leader-deployment.yaml

Redis 리더 Pod가 실행 중인지 확인합니다.

kubectl get pods
결과:
NAME                           READY     STATUS    RESTARTS   AGE
redis-leader-343230949-qfvrq   1/1       Running   0          43s

다음 명령어를 실행하여 Redis 리더 pod의 로그를 살펴보세요.

kubectl logs deployment/redis-leader

결과:

1:M 24 Jun 2020 14:48:20.917 * Ready to accept connections

Redis 리더 서비스 만들기

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

서비스는 논리적 pod 집합과 이 집합에 액세스하는 정책을 정의하는 Kubernetes 추상화를 의미합니다. 이 서비스는 트래픽을 하나 이상의 pod로 프록시하는 사실상 이름이 지정된 부하 분산기입니다. 서비스를 설정할 때 pod 라벨을 기준으로 프록시할 pod를 설명합니다.

Redis 리더의 서비스 리소스를 설명하는 redis-leader-service.yaml 매니페스트 파일을 확인합니다.

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-leader라는 서비스를 만듭니다. 이러한 라벨은 이전 단계에서 배포된 라벨 집합과 일치합니다. 따라서 이 서비스는 이전 단계에서 만든 Redis 리더 pod로 네트워크 트래픽을 라우팅합니다.

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

다음을 실행하여 Redis 리더 서비스를 시작합니다.

kubectl apply -f redis-leader-service.yaml

서비스가 만들어졌는지 확인합니다.

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 리더가 단일 pod라도 Redis 팔로어 즉, 복제본을 여러 개 추가하여 가용성을 높이고 트래픽 수요를 충족할 수 있습니다.

Redis 팔로어 pod의 배포를 설명하는 redis-follower-deployment.yaml 매니페스트 파일을 확인합니다.

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: gcr.io/google_samples/gb-redis-follower:v2
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
        ports:
        - containerPort: 6379

Redis 팔로어 배포를 만들려면 다음을 실행합니다.

kubectl apply -f redis-follower-deployment.yaml

Pod 목록을 쿼리하여 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

Redis 팔로어 중 하나의 Pod 로그를 가져옵니다.

kubectl logs deployment/redis-follower
출력:
1:M 24 Jun 2020 14:50:43.617 * Background saving terminated with success
1:M 24 Jun 2020 14:50:43.617 * Synchronization with replica 10.12.3.4:6379 succeeded

Redis 팔로어 서비스 만들기

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

redis-follower-service.yaml은 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에서 실행되는 redis-follower라는 서비스를 정의합니다. 서비스의 selector 필드는 이전 단계에서 만든 Redis 팔로어 Pod와 일치합니다.

다음을 실행하여 redis-follower 서비스를 만듭니다.

kubectl apply -f redis-follower-service.yaml

서비스가 만들어졌는지 확인합니다.

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 배포를 사용하여 배포됩니다.

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

방명록 웹 서버의 배포를 설명하는 frontend-deployment.yaml 매니페스트 파일을 살펴보세요.

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: gcr.io/google_samples/gb-frontend:v5
        env:
        - name: GET_HOSTS_FROM
          value: "dns"
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
        ports:
        - containerPort: 80

방명록 웹 프런트엔드 배포를 만들려면 다음을 실행합니다.

kubectl apply -f frontend-deployment.yaml

웹 프런트엔드를 식별하는 라벨 목록을 쿼리하여 3개의 복제본이 실행 중인지 확인합니다.

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

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

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

서비스 기본 유형이 ClusterIP이므로 이전 단계에서 만든 redis-followerredis-leader 서비스는 GKE 클러스터 내에서만 액세스할 수 있습니다. ClusterIP는 서비스가 가리키는 pod 집합에 단일 IP 주소를 제공합니다. 이 IP 주소는 클러스터 내에서만 액세스할 수 있습니다.

하지만 방명록 웹 프런트엔드 서비스는 외부에서 볼 수 있어야 합니다. 즉, 클라이언트가 GKE 클러스터 외부에서 서비스를 요청할 수 있어야 합니다. 이 요청을 처리하려면 서비스 구성에서 요구사항에 따라 type: LoadBalancer 또는 type: NodePort를 지정하면 됩니다. 이 예시에서는 type: LoadBalancer을 사용합니다. 이 구성을 지정하는 frontend-service.yaml 매니페스트 파일은 다음과 같습니다.

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

frontend 서비스가 생성되면 GKE는 부하 분산기와 외부 IP 주소를 만듭니다. 이러한 리소스는 청구 대상입니다. ports 섹션의 포트 선언은 port: 80을 지정하며 targetPort는 지정되지 않습니다. targetPort 속성을 생략하면 기본적으로 port 필드 값이 사용됩니다. 이 경우 이 서비스는 포트 80의 외부 트래픽을 frontend 배포의 컨테이너 포트 80으로 라우팅합니다.

서비스를 만들려면 다음 명령어를 실행합니다.

kubectl apply -f frontend-service.yaml

방명록 웹사이트 방문

방명록 서비스에 액세스하려면 다음 명령어를 실행하여 설정한 서비스의 외부 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 열에서 IP 주소를 복사하고 브라우저에서 페이지를 로드합니다.

GKE에서 실행되는 방명록

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

웹 프런트엔드 확장

방명록 앱이 실행된 지 어느 정도 지나 갑자기 유명해졌다고 가정해 보세요. 프런트엔드에 웹 서버를 추가하는 것이 좋겠다고 결정합니다. 서버가 배포 컨트롤러를 사용하는 서비스로 정의되어 있으므로 이 작업을 손쉽게 수행할 수 있습니다.

다음을 실행하여 frontend pod 수를 확장합니다.

kubectl scale deployment frontend --replicas=5

결과:

deployment.extensions/frontend scaled

이제 복제본 5개가 실행되어야 한다고 지정하도록 배포 구성이 업데이트됩니다. 배포는 구성과 일치하도록 실행 중인 pod 수를 조정합니다. 복제본 수를 확인하려면 다음 명령어를 실행합니다.

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

동일한 명령어를 사용하여 프런트엔드 Pod의 개수를 축소할 수 있습니다.

삭제

이 가이드에서 사용한 리소스 비용이 Google Cloud Platform 계정에 청구되지 않도록 하려면 다음 안내를 따르세요.

  1. 서비스 삭제: 이 단계는 frontend 서비스에 만든 Cloud 부하 분산기의 할당을 취소합니다.

    kubectl delete service frontend

  2. frontend 서비스에 프로비저닝된 부하 분산기가 삭제될 때까지 대기: kubectl delete를 실행하면 부하 분산기가 백그라운드에서 비동기식으로 삭제됩니다. 다음 명령어 출력을 확인하여 부하 분산기가 삭제될 때까지 기다립니다.

    gcloud compute forwarding-rules list

  3. GKE 클러스터 삭제: 이 단계에서는 컴퓨팅 인스턴스, 디스크, 네트워크 리소스와 같이 GKE 클러스터를 구성하는 리소스를 삭제합니다.

    gcloud container clusters delete guestbook

다음 단계