예제: PHP/Redis 게스트북 배포하기

예제: PHP/Redis 게스트북 배포하기 (Example: Deploying PHP Guestbook application with Redis)

이 튜토리얼에서는 간단한 다중 계층 웹 애플리케이션을 구축하고 배포하는 방법을 보여줘요. 결과물은 '게스트북(guestbook)' 애플리케이션입니다. 두 개의 구성요소가 있습니다:

  • PHP 기반의, Redis 백엔드가 있는 웹 프런트엔드
  • 함께 동작하는 두 개의 Redis 인스턴스로 구성된 Redis 클러스터

출처: 문서

본문

목표 (Objectives)

  • Redis 마스터를 시작합니다.
  • Redis 마스터의 팔로워(복제본)를 시작합니다.
  • 게스트북 프런트엔드를 시작합니다.
  • 프런트엔드 Service를 노출하고 확인합니다.

시작하기 전에 (Before you begin)

쿠버네티스 클러스터가 필요하며, kubectl 명령줄 도구가 클러스터와 통신하도록 구성되어 있어야 합니다. kubectl이 설치되어 있는지 확인하세요.

Redis 마스터 배포 (Deploying the Redis master)

게스트북 애플리케이션은 Redis를 사용해 데이터를 저장합니다. 배포할 첫 번째 구성요소는 Redis 마스터입니다.

목표:

  • Redis 마스터 Deployment를 만듭니다.
  • redis-master라는 이름의 Service를 만들어, Redis 인스턴스가 프런트엔드와 통신할 수 있게 합니다.

Redis 마스터 만들기

게스트북 앱은 데이터 저장을 위해 Redis 7을 사용합니다. Redis 인스턴스가 실행되는 Redis 마스터 Deployment를 만듭니다.

다음 Deployment 구성 파일을 적용합니다:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-master
  labels:
    app: redis
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis
      role: master
      tier: backend
  template:
    metadata:
      labels:
        app: redis
        role: master
        tier: backend
    spec:
      containers:
      - name: master
        image: redis:7.0.5
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
        ports:
        - containerPort: 6379
kubectl apply -f https://k8s.io/examples/application/guestbook/redis-master-deployment.yaml

Deployment를 만들고, pod가 준비되었는지 확인합니다:

kubectl get pods -l app=redis,role=master

출력은 pod가 준비된 것을 보여줍니다:

NAME                            READY     STATUS    RESTARTS   AGE
redis-master-7db7f6579f-2x64c   1/1       Running   0          11s

Deployment을 통해 생성된 ReplicaSet의 상태를 확인합니다:

kubectl get rs

출력은 ReplicaSet이 생성되었음을 보여줍니다:

NAME                          DESIRED   CURRENT   READY   AGE
redis-master-7db7f6579f       1         1         1       23s

Redis 마스터 Service 만들기

게스트북 애플리케이션은 데이터를 쓸 Redis 마스터에 접근해야 합니다. Service를 만들어 트래픽을 Redis 마스터 파드로 전달합니다. Service는 Redis 마스터에 대한 추상화된 라우팅입니다.

다음 Service 구성 파일을 적용합니다:

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
kubectl apply -f https://k8s.io/examples/application/guestbook/redis-master-service.yaml

다음 명령으로 Service를 확인합니다:

kubectl get service

출력은 redis-master Service가 있는 것을 보여줍니다:

NAME           TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
kubernetes     ClusterIP   10.96.0.1    <none>        443/TCP    1m
redis-master   ClusterIP   10.96.110.3  <none>        6379/TCP   76s

Redis 팔로워(복제본) 배포

게스트북 애플리케이션에 더 부하가 걸리면 Redis 마스터보다 더 많은 Redis 복제본을 사용합니다(또는 redis와 관련된 쿠버네티스 구성 요소들 중에서).

아래 목표:

  • Redis 팔로워(복제본) Deployment를 만듭니다.
  • redis-follower라는 이름의 Service를 만들어, 프런트엔드가 Redis 팔로워 인스턴스로 데이터를 읽을 수 있게 합니다.

Redis 팔로워 만들기

Redis 마스터는 단일 파드입니다. 팔로워를 추가해 확장할 수 있게 하고, 네트워크 부하를 분산하려면 다음 설정을 해야 합니다.

다음 Deployment 구성 파일을 적용합니다:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-follower
  labels:
    app: redis
spec:
  replicas: 2
  selector:
    matchLabels:
      app: redis
      role: follower
      tier: backend
  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
kubectl apply -f https://k8s.io/examples/application/guestbook/redis-follower-deployment.yaml

Deployment를 만들고, 두 개의 팔로워가 준비되었는지 확인합니다:

kubectl get pods -l app=redis,role=follower

출력은 두 개의 팔로워가 준비되었음을 보여줍니다:

NAME                             READY     STATUS    RESTARTS   AGE
redis-follower-765d5f7d7d-6lg85  1/1       Running   0          23s
redis-follower-765d5f7d7d-8zvlv  1/1       Running   0          23s

Deployment을 통해 생성된 ReplicaSet의 상태를 확인합니다:

kubectl get rs

출력은 ReplicaSet이 생성되었음을 보여줍니다:

NAME                           DESIRED   CURRENT   READY   AGE
redis-follower-765d5f7d7d      2         2         2       40s
redis-master-7db7f6579f        1         1         1       85s

Redis 팔로워 Service 만들기

게스트북 앱은 Redis 팔로워에서 데이터를 읽어야 합니다. 데이터를 읽도록 Redis 팔로워에 Service를 만들어야 합니다. Service는 Redis 팔로워에 대한 추상화된 라우팅입니다.

팔로워들이 redis-follower라는 이름의 Service에 노출되어 프런트엔드가 데이터를 읽을 수 있게 합니다.

다음 Service 구성 파일을 적용합니다:

apiVersion: v1
kind: Service
metadata:
  name: redis-follower
  labels:
    app: redis
    role: follower
    tier: backend
spec:
  ports:
    - port: 6379
  selector:
    app: redis
    role: follower
    tier: backend
kubectl apply -f https://k8s.io/examples/application/guestbook/redis-follower-service.yaml

Service를 확인합니다:

kubectl get service

출력은 redis-follower Service가 있는 것을 보여줍니다:

NAME             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
kubernetes       ClusterIP   10.96.0.1       <none>        443/TCP    3m
redis-follower   ClusterIP   10.96.99.137    <none>        6379/TCP   64s
redis-master     ClusterIP   10.96.110.3     <none>        6379/TCP   2m

게스트북 웹 프런트엔드 배포

게스트북 앱은 이제 웹 프런트엔드를 배포해 사용자가 볼 수 있게 할 준비가 되었습니다. 프런트엔드는 데이터를 저장하기 위해 작성할 Redis 마스터와, 데이터를 읽을 Redis 팔로워에 접근하는 PHP 기반 웹 서버입니다.

아래 목표:

  • 프런트엔드 Deployment를 만듭니다.
  • 프런트엔드를 외부에 노출하기 위해 NodePort형의 frontend Service를 만듭니다.

이 튜토리얼에서는 프런트엔드를 NodePort Service로 노출합니다. 프런트엔드는 클라우드 공급자에 따라 LoadBalancer Service로도 노출할 수 있습니다.

참고: 프런트엔드 Deployment는 기본적으로 3개의 웹 UI 복제본(파드)을 만들도록 확장되어 있습니다. 각 파드는 사용자 접근을 위해 하나의 복제본을 사용합니다. 자세한 내용은 예제를 참조하세요.

프런트엔드 만들기

다음 Deployment 구성 파일을 적용합니다:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
  labels:
    app: guestbook
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
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
        env:
        - name: GET_HOSTS_FROM
          value: dns
        ports:
        - containerPort: 80
kubectl apply -f https://k8s.io/examples/application/guestbook/frontend-deployment.yaml

Deployment를 만들고, 세 개의 프런트엔드 파드가 준비되었는지 확인합니다:

kubectl get pods -l app=guestbook

출력은 세 개의 프런트엔드 파드가 준비되었음을 보여줍니다:

NAME                        READY     STATUS    RESTARTS   AGE
frontend-7567795657-4xzzq   1/1       Running   0          25s
frontend-7567795657-bszrq   1/1       Running   0          25s
frontend-7567795657-lw2sw   1/1       Running   0          25s

Deployment을 통해 생성된 ReplicaSet의 상태를 확인합니다:

kubectl get rs

출력은 ReplicaSet이 생성되었음을 보여줍니다:

NAME                    DESIRED   CURRENT   READY   AGE
frontend-7567795657     3         3         3       38s
redis-follower-765d5f7d7d  2      2         2       3m
redis-master-7db7f6579f   1      1         1       4m

프런트엔드 Service 만들기

Frontend Service는 그 트래픽을 게스트북 프런트엔드 파드로 전달하는 네트워크 경로를 제공합니다. 이 Service는 NodePort 형식입니다.

NodePort Service는 각 노드의 포트에 프런트엔드를 노출합니다.

다음 Service 구성 파일을 적용합니다:

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
kubectl apply -f https://k8s.io/examples/application/guestbook/frontend-service.yaml

Service를 확인합니다:

kubectl get services

출력은 frontend Service가 있는 것을 보여줍니다:

NAME             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
frontend         NodePort    10.96.211.225   <none>        80:31753/TCP   36s
kubernetes       ClusterIP   10.96.0.1       <none>        443/TCP        5m
redis-follower   ClusterIP   10.96.99.137    <none>        6379/TCP       3m
redis-master     ClusterIP   10.96.110.3     <none>        6379/TCP       4m

guestbook 및 Redis 사전 구성 확인

웹 UI가 guestbook 애플리케이션을 표시할 준비가 되었는지 확인합니다:

  • 모든 서비스와 앱을 확인합니다
kubectl get pods,svc -l app=redis

출력은 앱이 실행 중임을 보여줍니다:

NAME                              READY   STATUS    RESTARTS   AGE
pod/redis-follower-765d5f7d7d-6lg85   1/1 Running   0          92s
pod/redis-follower-765d5f7d7d-8zvlv   1/1 Running   0          92s
pod/redis-master-7db7f6579f-2x64c   1/1 Running   0          2m

NAME                      TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
service/redis-follower   ClusterIP   10.96.99.137    <none>        6379/TCP   4m
service/redis-master     ClusterIP   10.96.110.3     <none>        6379/TCP   5m
  • 프런트엔드 파드와 Service를 확인합니다
kubectl get pods,svc -l app=guestbook

출력은 앱이 실행 중임을 보여줍니다:

NAME                             READY   STATUS    RESTARTS   AGE
pod/frontend-7567795657-4xzzq   1/1     Running   0          2m
pod/frontend-7567795657-bszrq   1/1     Running   0          2m
pod/frontend-7567795657-lw2sw    1/1     Running   0          2m

NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
service/frontend     NodePort    10.96.211.225   <none>        80:31753/TCP   2m

guestbook 확인하기 (Verify the guestbook)

게스트북 애플리케이션이 준비되었는지 확인합니다:

  • 프런트엔드 Service의 NodePort(예: 31753)를 얻습니다.
kubectl get service frontend

출력은 NodePort를 보여줍니다:

NAME       TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
frontend   NodePort   10.96.211.225   <none>        80:31753/TCP   4m

NodePort로 볼륨 마운트

이 튜토리얼 코드에서는 NodePort가 80:31753/TCP로 설정되어 있습니다. 브라우저에서 웹 UI를 열어 게스트북 애플리케이션을 확인합니다. 예를 들어 브라우저에서 http://<your-cluster-node-ip>:31753을 엽니다.

참고: 클러스터가 클라우드 플랫폼에서 실행 중이면 클라우드 UI에서 MINIKUBE_IP에 해당하는 노드의 IP를 확인할 수 있습니다.

다음과 같은 웹 UI가 표시됩니다:

  • guestbook 메시지를 추가하고 제출합니다.
  • 데이터가 저장된 Redis 팔로워나 마스터에 요청이 전달되는 것을 확인합니다.

cleanup (Cleaning up)

Deployment와 Service의 리소스를 정리하고, 게스트북 애플리케이션과 redis를 삭제합니다.

  • guestbook frontend Deployment와 Service를 삭제합니다:
kubectl delete deployment frontend
kubectl delete service frontend
  • redis master Deployment와 Service를 삭제합니다:
kubectl delete deployment redis-master
kubectl delete service redis-master
  • redis follower(복제본) Deployment와 Service를 삭제합니다:
kubectl delete deployment redis-follower
kubectl delete service redis-follower

Persistent Volumes에 대한 자세한 내용은 Persistent Volumes를 참조하세요.

언제 데이터가 삭제되고 언제 유지되는지 확인:

kubectl get persistentvolumes

출력은 persistent volume이 없음을 보여줍니다:

No resources found

데이터 한계는 persistent volume이 없음을 보여줍니다. 데이터는 앱과 파드가 삭제되는 순간 클러스터 밖의 영구 스토리지로 옮겨지지 않고 삭제됩니다.

더 알아보기 (Learn more)

  • Pod 및 Deployment의 개념을 배워보세요.
  • Service 및 로드 밸런싱에 대해 자세히 알아보세요.
  • 애플리케이션의 확장과 다운타임을 최소화하는 방법을 배워보세요.