Redis 및 PHP로 방명록 만들기

이 가이드는 GKE를 사용하여 간단한 다중 계층 웹 애플리케이션을 빌드하는 방법을 보여줍니다. 가이드 애플리케이션은 방문자가 로그에 텍스트를 입력하고 마지막으로 로깅된 항목 몇 개를 볼 수 있는 방명록입니다.

이 가이드에서는 부하 분산기를 사용하여 외부 IP에서 방명록 웹 서비스를 설정하는 방법과 단일 마스터 및 여러 작업자로 구성된 Redis 클러스터를 실행하는 방법을 보여줍니다.

이 예시에서는 여러 가지 GKE의 중요 개념을 자세하게 설명합니다.

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

목표

GKE에서 방명록 애플리케이션을 배포하고 실행하려면 다음을 수행해야 합니다.

  1. Redis 마스터 설정
  2. Redis 작업자 설정
  3. 방명록 웹 프런트엔드 설정
  4. 방명록 웹사이트 방문
  5. 방명록 웹 프런트엔드 확장

시작하기 전에

다음 단계에 따라 Kubernetes Engine API를 사용 설정합니다.
  1. Google Cloud Console에서 Kubernetes Engine 페이지로 이동합니다.
  2. 프로젝트를 만들거나 선택합니다.
  3. API 및 관련 서비스가 사용 설정될 때까지 기다립니다. 몇 분 정도 걸릴 수 있습니다.
  4. Google 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_ENGINE_ZONE]

구성 파일 다운로드

Kubernetes 예시 GitHub 저장소로 이동하여 이 가이드에서 사용되는 구성 파일을 다운로드합니다.

GKE 클러스터 만들기

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

노드가 2개인 guestbook이라는 컨테이너 클러스터를 만듭니다.

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

다음 명령어를 사용하여 프로젝트의 클러스터를 나열하거나 단일 클러스터 세부정보를 가져올 수 있습니다.

gcloud container clusters list
    gcloud container clusters describe guestbook

1단계: Redis 마스터 설정

방명록 애플리케이션은 Redis를 사용하여 데이터를 저장합니다. 방명록 애플리케이션은 Redis 마스터 인스턴스에 데이터를 쓰고 여러 Redis 작업자(슬레이브) 인스턴스에서 데이터를 읽습니다. 첫 번째 단계는 Redis 마스터를 배포하는 것입니다.

redis-master-deployment라는 매니페스트 파일을 사용하여 Redis 마스터를 배포합니다. 이 매니페스트 파일은 단일 복제본 Redis 마스터 Pod를 실행하는 배포 컨트롤러를 지정합니다.

apiVersion: apps/v1 #  for k8s versions before 1.9.0 use apps/v1beta2  and before 1.8.0 use extensions/v1beta1
    kind: Deployment
    metadata:
      name: redis-master
    spec:
      selector:
        matchLabels:
          app: redis
          role: master
          tier: backend
      replicas: 1
      template:
        metadata:
          labels:
            app: redis
            role: master
            tier: backend
        spec:
          containers:
          - name: master
            image: k8s.gcr.io/redis:e2e  # or just image: redis
            resources:
              requests:
                cpu: 100m
                memory: 100Mi
            ports:
            - containerPort: 6379
    

Redis 마스터를 배포하려면 다음 명령어를 실행합니다.

kubectl create -f redis-master-deployment.yaml

Redis 마스터 Pod가 kubectl get pods를 실행하고 있는지 확인합니다.

    kubectl get pods
    
출력:
    NAME                           READY     STATUS    RESTARTS   AGE
    redis-master-343230949-qfvrq   1/1       Running   0          43s
    

이전 명령어의 출력에서 Pod 이름을 복사하고 다음 명령어를 실행하여 Redis 마스터 Pod의 로그를 살펴보세요.

    kubectl logs -f [POD_NAME]
    

redis-master 서비스 만들기

방명록 애플리케이션은 데이터를 쓰기 위해 Redis 마스터와 통신해야 합니다. Redis 마스터 Pod로 트래픽을 프록시하려면 서비스를 만들어야 합니다.

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

Redis 마스터의 서비스 리소스를 설명하는 redis-master-service.yaml 매니페스트 파일을 살펴보세요.

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

이 매니페스트 파일은 일련의 라벨 선택기가 있는 redis-master라는 서비스를 만듭니다. 이러한 라벨은 이전 단계에서 배포된 일련의 라벨과 일치합니다. 따라서 이 서비스는 1단계에서 만든 Redis 마스터 Pod로 네트워크 트래픽을 라우팅합니다.

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

다음을 실행하여 Redis 마스터의 서비스를 시작합니다.

    kubectl create -f redis-master-service.yaml
    

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

    kubectl get service
    
출력:
    NAME           CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
    kubernetes     10.51.240.1     <none>        443/TCP    42s
    redis-master   10.51.242.233   <none>        6379/TCP   12s
    

2단계: Redis 작업자 설정

Redis 마스터가 단일 Pod라도 Redis 작업자 복제본을 여러 개 추가하여 가용성을 높이고 트래픽 수요를 충족할 수 있습니다.

Redis 작업자 Pod의 배포를 설명하는 redis-slave-deployment.yaml 매니페스트 파일을 살펴보세요.

apiVersion: apps/v1 #  for k8s versions before 1.9.0 use apps/v1beta2  and before 1.8.0 use extensions/v1beta1
    kind: Deployment
    metadata:
      name: redis-slave
    spec:
      selector:
        matchLabels:
          app: redis
          role: slave
          tier: backend
      replicas: 2
      template:
        metadata:
          labels:
            app: redis
            role: slave
            tier: backend
        spec:
          containers:
          - name: slave
            image: gcr.io/google_samples/gb-redisslave:v1
            resources:
              requests:
                cpu: 100m
                memory: 100Mi
            env:
            - name: GET_HOSTS_FROM
              value: dns
              # If your cluster config does not include a dns service, then to
              # instead access an environment variable to find the master
              # service's host, comment out the 'value: dns' line above, and
              # uncomment the line below:
              # value: env
            ports:
            - containerPort: 6379
    

배포는 매니페스트 파일에서 선언된 구성을 달성해야 합니다. 예를 들어 이 매니페스트 파일은 Redis 작업자에 대한 2개의 복제본을 정의합니다. 실행 중인 복제본이 없다면 배포는 컨테이너 클러스터에서 2개의 복제본을 시작합니다. 실행 중인 복제본이 셋 이상이면 지정된 구성을 충족하기 위해 일부 복제본을 종료합니다.

이 경우, 배포 객체는 2개의 복제본을 지정합니다. Redis 작업자 배포를 만들려면 다음을 실행하세요.

    kubectl create -f redis-slave-deployment.yaml
    

pod 목록을 쿼리하여 2개의 Redis 작업자 복제본이 실행되고 있는지 확인합니다.

    kubectl get pods
    
출력:
    NAME                           READY     STATUS    RESTARTS   AGE
    redis-master-343230949-qfvrq   1/1       Running   0          17m
    redis-slave-132015689-dp23k    1/1       Running   0          2s
    redis-slave-132015689-xq9v0    1/1       Running   0          2s
    

redis-slave 서비스 만들기

방명록 애플리케이션은 데이터를 읽기 위해 Redis 작업자와 통신해야 합니다. Redis 작업자 검색을 가능하게 만들려면 서비스를 설정해야 합니다. 서비스는 Pod 모음에 투명한 부하 분산을 제공합니다.

redis-slave-service.yaml은 Redis 작업자의 서비스 구성을 정의합니다.

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

이 파일은 포트 6379에서 실행되는 redis-slave라는 서비스를 정의합니다. 서비스의 selector 필드는 이전 단계에서 만든 Redis 작업자 Pod와 일치합니다.

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

    kubectl create -f redis-slave-service.yaml
    

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

    kubectl get service
    
출력:
    NAME           CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
    kubernetes     10.51.240.1     <none>        443/TCP    1m
    redis-master   10.51.242.233   <none>        6379/TCP   49s
    redis-slave    10.51.247.238   <none>        6379/TCP   3s
    

3단계: 방명록 웹 프런트엔드 설정

방명록의 Redis 스토리지가 실행되고 있으니 이제 방명록 웹 서버를 시작합니다. Redis 작업자와 마찬가지로 이것도 배포로 관리되는 복제된 애플리케이션입니다.

이 가이드는 단순한 PHP 프런트엔드를 사용합니다. 요청이 읽기인지 쓰기인지에 따라 Redis 작업자 서비스나 마스터 서비스와 통신하도록 구성되어 있습니다. 단순한 JSON 인터페이스를 노출하고 jQuery-Ajax 기반 UX를 제공합니다.

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

apiVersion: apps/v1 #  for k8s versions before 1.9.0 use apps/v1beta2  and before 1.8.0 use extensions/v1beta1
    kind: Deployment
    metadata:
      name: frontend
    spec:
      selector:
        matchLabels:
          app: guestbook
          tier: frontend
      replicas: 3
      template:
        metadata:
          labels:
            app: guestbook
            tier: frontend
        spec:
          containers:
          - name: php-redis
            image: gcr.io/google-samples/gb-frontend:v4
            resources:
              requests:
                cpu: 100m
                memory: 100Mi
            env:
            - name: GET_HOSTS_FROM
              value: dns
              # If your cluster config does not include a dns service, then to
              # instead access environment variables to find service host
              # info, comment out the 'value: dns' line above, and uncomment the
              # line below:
              # value: env
            ports:
            - containerPort: 80
    

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

    kubectl create -f frontend-deployment.yaml
    

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

    kubectl get pods -l app=guestbook -l tier=frontend
    
출력:
    NAME                      READY     STATUS    RESTARTS   AGE
    frontend-88237173-5p257   1/1       Running   0          40s
    frontend-88237173-84036   1/1       Running   0          40s
    frontend-88237173-j3rvr   1/1       Running   0          40s
    

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

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

서비스 기본 유형이 ClusterIP이므로 이전 단계에서 만든 redis-slaveredis-master 서비스는 컨테이너 클러스터 내에서만 액세스할 수 있습니다. ClusterIP는 서비스가 가리키는 Pod 모음에 단일 IP 주소를 제공합니다. 이 IP 주소는 클러스터 내에서만 액세스할 수 있습니다.

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

apiVersion: v1
    kind: Service
    metadata:
      name: frontend
      labels:
        app: guestbook
        tier: frontend
    spec:
      # comment or delete the following line if you want to use a LoadBalancer
      type: NodePort
      # if your cluster supports it, uncomment the following to automatically create
      # an external load-balanced IP for the frontend service.
      # type: LoadBalancer
      ports:
      - port: 80
      selector:
        app: guestbook
        tier: frontend
    

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

서비스를 만들려면 먼저 frontend-service.yaml 파일에서 다음 줄의 주석 처리를 삭제합니다.

type: LoadBalancer

그런 후 다음을 실행하여 서비스를 만듭니다.

    kubectl create -f frontend-service.yaml
    

4단계: 방명록 웹사이트 방문

방명록 서비스에 액세스하려면 다음 명령어를 실행하여 방금 설정한 서비스의 외부 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에서 실행되는 방명록

수고하셨습니다. 몇 가지 방명록 항목을 추가해 보세요.

5단계: 웹 프런트엔드 확장

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

다음을 실행하여 frontend Pod 수를 5개로 확장합니다.

    kubectl scale deployment frontend --replicas=5
    

이제 배포 구성은 복제본 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-master-343230949-qfvrq   1/1       Running   0          54m
    redis-slave-132015689-dp23k    1/1       Running   0          37m
    redis-slave-132015689-xq9v0    1/1       Running   0          37m
    

다시 잘 알려지지 않은 사이트가 되면 같은 방법으로 웹 서버 Pod의 수를 줄일 수 있습니다.

삭제

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

6단계: 삭제

이 가이드를 완료한 후에는 계정에 원치 않는 비용이 발생하지 않도록 다음 단계에 따라 다음과 같은 리소스를 삭제합니다.

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

    kubectl delete service frontend

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

    gcloud compute forwarding-rules list

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

    gcloud container clusters delete guestbook

다음 단계