고가용성 앱을 위한 자동 복구 사용


본 대화형 튜토리얼에서는 자동 복구 기능을 사용하여 Compute Engine에서 가용성이 높은 앱을 빌드하는 방법을 보여줍니다.

가용성이 높은 앱은 지연 시간 및 다운타임이 최소화된 클라이언트를 제공하도록 설계됩니다. 앱이 다운되거나 중단되면 가용성이 저해됩니다. 이 경우 앱의 클라이언트는 높은 지연 시간 또는 다운타임을 경험할 수 있습니다.

자동 복구를 사용하면 장애가 발생한 앱을 자동으로 다시 시작할 수 있습니다. 이 기능은 실패한 인스턴스를 즉시 감지하여 자동으로 다시 만들므로 클라이언트에게 서비스를 다시 제공할 수 있습니다. 자동 복구 기능을 사용하면 더 이상 실패 후에 앱 서비스를 직접 복구할 필요가 없습니다.

목표

  • 상태 확인 및 자동 복구 정책 구성
  • 관리형 인스턴스 그룹에서 데모 웹 서비스 설정
  • 상태 확인 실패 시뮬레이션 및 자동 복구 프로세스 확인

비용

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

  • Compute Engine

시작하기 전에

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

    Google Cloud Console의 프로젝트 선택기 페이지에서 Google Cloud 프로젝트를 선택하거나 만듭니다.

    프로젝트 선택기로 이동

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

    Compute Engine API 사용 설정

    API 사용 설정

    Google Cloud Console의 프로젝트 선택기 페이지에서 Google Cloud 프로젝트를 선택하거나 만듭니다.

    프로젝트 선택기로 이동

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

    Compute Engine API 사용 설정

    API 사용 설정

명령줄 작업을 더 선호할 경우에는 Google Cloud CLI를 설치합니다.

  • Google Cloud CLI를 설치합니다.
  • gcloud CLI를 초기화하려면 다음 명령어를 실행합니다.

    gcloud init

앱 아키텍처

앱에는 다음과 같은 Compute Engine 구성요소가 포함됩니다.

  • 상태 확인: 자동 복구 기능에서 실패한 VM 인스턴스를 감지하는 데 사용하는 HTTP 상태 확인 정책
  • 방화벽 규칙: Google Cloud 방화벽 규칙을 사용하면 인스턴스의 트래픽을 허용 또는 거부할 수 있습니다.
  • 관리형 인스턴스 그룹: 같은 데모 웹 서비스를 실행하는 인스턴스 그룹
  • 인스턴스 템플릿: 인스턴스 그룹의 각 인스턴스를 만들 때 사용하는 템플릿

상태 확인 및 인스턴스 그룹의 시스템 아키텍처

상태 확인이 데모 웹 서비스를 프로브하는 방법

상태 확인은 HTTP(S), SSL, TCP 같은 지정된 프로토콜을 사용하여 인스턴스에 프로브 요청을 전송합니다. 자세한 내용은 상태 확인 작동 방식상태 확인 카테고리, 프로토콜, 포트 문서를 참조하세요.

이 튜토리얼의 상태 확인은 포트 80에서 HTTP 경로 /health를 프로브하는 HTTP 상태 확인입니다. HTTP 상태 확인의 경우 경로가 HTTP 200 (OK) 응답을 반환하는 경우에만 프로브 요청이 전달됩니다. 이 튜토리얼에서는 정상일 때 /health 응답을 반환하고 비정상일 때 HTTP 200 (OK) 응답을 반환하기 위해 데모 웹 서버가 경로 HTTP 500 (Internal Server Error)를 정의합니다. 자세한 내용은 HTTP, HTTPS, HTTP/2의 성공 기준을 참조하세요.

상태 확인 만들기

자동 복구를 설정하려면 커스텀 상태 확인을 만들고 네트워크 방화벽을 구성하여 상태 확인 프로브를 허용합니다. 리전 또는 전역 상태 점검을 사용할 수 있습니다. 리전별 상태 점검은 리전 간 종속 항목을 줄이고 데이터 상주를 달성하는 데 도움이 됩니다. 전역 상태 점검은 여러 리전의 MIG에 동일한 상태 점검을 사용하려는 경우에 편리합니다. 이 튜토리얼에서는 전역 상태 점검을 만듭니다.

콘솔

  1. 상태 확인을 만듭니다.

    1. Google Cloud Console에서 상태 확인 페이지로 이동합니다.

      상태 점검으로 이동

    2. 상태 점검 만들기를 클릭합니다.

    3. 이름 필드에 autohealer-check를 입력합니다.

    4. 범위Global로 설정합니다. 자동 복구의 경우 리전 또는 전역 상태 점검 중 하나를 사용할 수 있습니다.

    5. 프로토콜에서 HTTP를 선택합니다.

    6. 요청 경로/health로 설정합니다. 이는 상태 확인이 사용하는 HTTP 경로를 나타냅니다. 이 튜토리얼에서는 정상일 때 /health 응답을 반환하고 비정상일 때 HTTP 200 (OK) 응답을 반환하기 위해 데모 웹 서버가 경로 HTTP 500 (Internal Server Error)를 정의합니다.

    7. 다음과 같이 상태 기준을 설정합니다.

      1. 확인 간격10으로 설정합니다. 이는 한 프로브의 시작부터 다른 프로브의 시작까지의 시간을 정의합니다.
      2. 제한 시간5로 설정합니다. 이는 Google Cloud가 프로브에 대한 응답을 대기하는 시간을 정의합니다. 이 값은 확인 간격보다 작거나 같아야 합니다.
      3. 정상 기준2로 설정합니다. 이는 인스턴스가 정상으로 간주되도록 하기 위해 성공해야 하는 순차적 프로브의 수를 정의합니다.
      4. 비정상 기준3로 설정합니다. 이는 인스턴스가 비정상으로 간주되도록 하기 위해 실패해야 하는 순차적 프로브의 수를 정의합니다.
    8. 하단에서 만들기를 클릭합니다.

  2. 방화벽 규칙을 만들어 상태 확인 프로브가 HTTP 요청을 수행하도록 허용합니다.

    1. Google Cloud Console에서 방화벽 규칙 만들기 페이지로 이동합니다.

      방화벽 규칙 만들기로 이동

    2. 이름default-allow-http-health-check를 입력합니다.

    3. 네트워크에서 default를 선택합니다.

    4. 타겟에서 All instances in the network를 선택합니다.

    5. 소스 필터에서 IP ranges를 선택합니다.

    6. 소스 IP 범위130.211.0.0/2235.191.0.0/16을 입력합니다.

    7. 프로토콜 및 포트에서 tcp를 선택하고 80를 입력합니다.

    8. 만들기를 클릭합니다.

gcloud

  1. health-checks create http 명령어를 사용하여 전역 상태 점검을 만듭니다.

    gcloud compute health-checks create http autohealer-check \
        --global \
        --check-interval 10 \
        --timeout 5 \
        --healthy-threshold 2 \
        --unhealthy-threshold 3 \
        --request-path "/health"
    
    • check-interval은 한 프로브의 시작에서 다음 프로브의 시작까지의 시간을 정의합니다.
    • timeout은 Google Cloud가 프로브에 대한 응답을 대기하는 시간을 정의합니다. 이 값은 확인 간격보다 작거나 같아야 합니다.
    • healthy-threshold는 인스턴스가 정상으로 간주되도록 하기 위해 성공해야 하는 순차적 프로브의 수를 정의합니다.
    • unhealthy-threshold는 인스턴스가 비정상으로 간주되도록 하기 위해 실패해야 하는 순차적 프로브의 수를 정의합니다.
    • request-path는 상태 확인이 사용하는 HTTP 경로를 나타냅니다. 이 튜토리얼에서는 정상일 때 HTTP 200 (OK) 응답을 반환하고 비정상일 때 HTTP 500 (Internal Server Error) 응답을 반환하기 위해 데모 웹 서버가 경로 /health를 정의합니다.
  2. 방화벽 규칙을 만들어 상태 확인 프로브가 HTTP 요청을 수행하도록 허용합니다.

    gcloud compute firewall-rules create default-allow-http-health-check \
        --network default \
        --allow tcp:80 \
        --source-ranges 130.211.0.0/22,35.191.0.0/16
    

유용한 자동 복구 상태 확인의 핵심 기능

자동 복구에 사용되는 상태 확인은 인스턴스를 사전에 삭제하고 다시 만들지 않도록 보수적이어야 합니다. 자동 복구 상태 확인이 지나치게 공격적인 경우 자동 복구 기능은 사용량이 많은 인스턴스를 실패한 인스턴스로 오인하고 불필요하게 다시 시작하여 가용성을 저하시킬 수 있습니다.

  • unhealthy-threshold: 1보다 커야 합니다. 이 값을 3 이상으로 설정하는 것이 좋습니다. 이렇게 하면 네트워크 패킷 손실과 같이 드물게 발생하는 실패로부터 보호됩니다.
  • healthy-threshold: 대부분의 앱에서 값이 2면 충분합니다.
  • timeout: 이 시간 값은 넉넉하게 설정합니다(예상되는 응답 시간의 5배 이상). 이렇게 하면 사용량이 많은 인스턴스 또는 느린 네트워크 연결과 같은 예상치 못한 지연으로부터 보호됩니다.
  • check-interval: 이 값은 1초와 제한 시간 두 배 사이여야 합니다(너무 길지도, 너무 짧지도 않은 시간). 값이 너무 길면 실패한 인스턴스가 신속하게 포착되지 않습니다. 값이 너무 짧으면 매 초 전송되는 많은 수의 상태 확인 프로브로 인해 인스턴스와 네트워크의 사용량이 과도하게 많은 것으로 측정될 수 있습니다.

웹 서비스 설정

이 가이드에서는 GitHub에 저장된 웹 앱을 사용합니다. 앱이 구현된 방법을 자세히 알아보려면 GoogleCloudPlatform/python-docs-samples GitHub 저장소를 참조하세요.

데모 웹 서비스를 설정하려면 시작 시 데모 웹 서버를 실행하는 인스턴스 템플릿을 만듭니다. 그런 다음 이 인스턴스 템플릿을 사용하여 관리형 인스턴스 그룹을 배포하고 자동 복구 기능을 사용 설정합니다.

콘솔

  1. 인스턴스 템플릿을 만듭니다. 데모 웹 서버를 시작하는 시작 스크립트를 추가합니다.

    1. Google Cloud Console에서 인스턴스 템플릿 페이지로 이동합니다.

      인스턴스 템플릿으로 이동

    2. 인스턴스 템플릿 만들기를 클릭합니다.

    3. 이름webserver-template로 설정합니다.

    4. 머신 구성에서 micro(e2-micro)를 선택합니다.

    5. 방화벽에서 HTTP 트래픽 허용 체크박스를 선택합니다.

    6. 관리, 보안, 디스크, 네트워킹, 단독 테넌시를 클릭하여 고급 설정을 표시합니다. 여러 탭이 표시됩니다.

    7. 관리 탭에서 자동화를 찾고 다음 시작 스크립트를 입력합니다.

      sudo apt update && sudo apt -y install git gunicorn3 python3-pip
      git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git
      cd python-docs-samples/compute/managed-instances/demo
      sudo pip3 install -r requirements.txt
      sudo gunicorn3 --bind 0.0.0.0:80 app:app --daemon
      

    8. 만들기를 클릭합니다.

  2. 웹 서버를 관리형 인스턴스 그룹으로 배포합니다.

    1. Google Cloud Console에서 인스턴스 그룹 페이지로 이동합니다.

      인스턴스 그룹으로 이동

    2. 인스턴스 그룹 만들기를 클릭합니다.

    3. 이름webserver-group로 설정합니다.

    4. 리전에서 europe-west1를 선택합니다.

    5. 영역에서 europe-west1-b를 선택합니다.

    6. 인스턴스 템플릿에서 webserver-template을 선택합니다.

    7. 자동 확장에서 자동 확장 안함을 선택합니다.

    8. 인스턴스 수3로 설정합니다.

    9. 상태 확인에서 autohealer-check를 선택합니다.

    10. 초기 지연90로 설정합니다.

    11. 만들기를 클릭합니다.

  3. 웹 서버에 대한 HTTP 요청을 허용하는 방화벽 규칙을 만듭니다.

    1. Google Cloud Console에서 방화벽 규칙 만들기 페이지로 이동합니다.

      방화벽 규칙 만들기로 이동

    2. 이름default-allow-http를 입력합니다.

    3. 네트워크에서 default를 선택합니다.

    4. 타겟에서 Specified target tags를 선택합니다.

    5. 타겟 태그 http-server를 입력합니다.

    6. 소스 필터에서 IP ranges를 선택합니다.

    7. 소스 IP 범위0.0.0.0/0을 입력합니다.

    8. 프로토콜 및 포트에서 tcp를 선택하고 80를 입력합니다.

    9. 만들기를 클릭합니다.

gcloud

  1. 인스턴스 템플릿을 만듭니다. 데모 웹 서버를 시작하는 시작 스크립트를 추가합니다.

    gcloud compute instance-templates create webserver-template \
        --machine-type e2-micro \
        --tags http-server \
        --metadata startup-script='
      sudo apt update && sudo apt -y install git gunicorn3 python3-pip
      git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git
      cd python-docs-samples/compute/managed-instances/demo
      sudo pip3 install -r requirements.txt
      sudo gunicorn3 --bind 0.0.0.0:80 app:app --daemon'
    
  2. 인스턴스 그룹을 만듭니다.

    gcloud compute instance-groups managed create webserver-group \
        --zone europe-west1-b \
        --template webserver-template \
        --size 3 \
        --health-check autohealer-check \
        --initial-delay 90
    
  3. 웹 서버에 대한 HTTP 요청을 허용하는 방화벽 규칙을 만듭니다.

    gcloud compute firewall-rules create default-allow-http \
        --network default \
        --allow tcp:80 \
        --target-tags http-server
    

상태 확인 실패 시뮬레이션

상태 확인 실패를 시뮬레이션하기 위해 데모 웹 서버는 강제로 상태 확인 실패를 만드는 방법을 제공합니다.

콘솔

  1. 웹 서버 인스턴스로 이동합니다.

    1. Google Cloud 콘솔에서 VM 인스턴스 페이지로 이동합니다.

      VM 인스턴스로 이동

    2. 외부 IP 열에서 webserver-group 인스턴스의 IP 주소를 클릭합니다. 웹 브라우저에 새 탭이 열립니다. 요청이 타임아웃되거나 웹 페이지를 사용할 수 없는 경우 서버가 설정을 완료할 때까지 1분 동안 기다렸다가 다시 시도하세요.

    데모 웹 서버는 다음과 유사한 페이지를 표시합니다.

    녹색 상태 버튼 및 파란색 작업 버튼을 보여주는 데모 웹페이지

  2. 데모 웹페이지에서 비정상으로 설정을 클릭합니다.

    이렇게 하면 웹 서버가 상태 확인에 실패합니다. 즉, 웹 서버는 /health 경로가 HTTP 500 (Internal Server Error)을 반환하도록 합니다. 상태 확인 버튼을 빠르게 클릭하여 직접 확인할 수 있습니다(자동 복구 기능이 인스턴스 재부팅을 시작하면 작동이 중지됨).

  3. 자동 복구 기능이 작동할 때까지 기다립니다.

    1. Google Cloud 콘솔에서 VM 인스턴스 페이지로 이동합니다.

      VM 인스턴스로 이동

    2. 웹 서버 인스턴스의 상태가 변경될 때까지 기다립니다. 인스턴스 이름 옆의 녹색 체크표시가 회색 사각형으로 변경됩니다. 이는 자동 복구 기능이 비정상 인스턴스의 재부팅을 시작했음을 나타냅니다.

    3. 페이지 상단의 새로고침을 주기적으로 클릭하여 최신 상태를 가져옵니다.

    4. 회색 사각형이 인스턴스가 정상 상태임을 나타내는 녹색 체크마크로 다시 변경되면 자동 복구 프로세스가 완료된 것입니다.

gcloud

  1. 인스턴스 그룹의 상태를 모니터링합니다. (모니터링을 마치면 Ctrl+C를 눌러 중지합니다.)

    while : ; do \
        gcloud compute instance-groups managed list-instances webserver-group \
        --zone europe-west1-b \
        ; done
    
    NAME                 ZONE            STATUS   ACTION  INSTANCE_TEMPLATE   VERSION_NAME  LAST_ERROR
    webserver-group-d5tz  europe-west1-b  RUNNING  NONE    webserver-template
    webserver-group-q6t9  europe-west1-b  RUNNING  NONE    webserver-template
    webserver-group-tbpj  europe-west1-b  RUNNING  NONE    webserver-template
    

    STAGING 같이 인스턴스에 RUNNING이 아닌 상태가 표시되는 경우 인스턴스가 설정을 완료할 때까지 1분 동안 기다렸다가 다시 시도하세요.

  2. 설치된 Google Cloud CLI를 사용해서 새 Cloud Shell 세션을 엽니다.

  3. 웹 서버 인스턴스의 주소를 가져옵니다.

    gcloud compute instances list --filter webserver-group
    

    EXTERNAL_IP 열에서 웹 서버 인스턴스의 IP 주소를 복사하여 로컬 bash 변수로 저장합니다.

    export IP_ADDRESS=EXTERNAL_IP_ADDRESS
    
  4. 웹 서버가 설정을 완료했는지 확인합니다. 서버가 HTTP 200 OK 응답을 합니다.

    curl --head $IP_ADDRESS/health
    
    HTTP/1.1 200 OK
    Server: gunicorn/19.6.0
    ...
    

    Connection refused 오류가 발생하면 서버가 설정을 완료할 때까지 1분 동안 기다렸다가 다시 시도하세요.

  5. 웹 서버를 비정상 상태로 설정합니다.

    curl $IP_ADDRESS/makeUnhealthy > /dev/null
    

    이렇게 하면 웹 서버가 상태 확인에 실패합니다. 즉, 웹 서버는 /health 경로가 HTTP 500 INTERNAL SERVER ERROR을 반환하도록 합니다. /health을 빠르게 요청하여 직접 확인할 수 있습니다(자동 복구 기능이 인스턴스 재부팅을 시작하면 작동이 중지됨).

    curl --head $IP_ADDRESS/health
    
    HTTP/1.1 500 INTERNAL SERVER ERROR
    Server: gunicorn/19.6.0
    ...
    
  6. 첫 번째 셸 세션으로 돌아가서 인스턴스 그룹을 모니터링하고 자동 복구 기능이 작동할 때까지 기다립니다.

    1. 자동 복구 프로세스가 시작되면 STATUS 열과 ACTION 열이 업데이트되어 자동 복구 기능이 비정상 인스턴스의 재부팅을 시작했음을 나타냅니다.

      NAME                 ZONE            STATUS    ACTION      INSTANCE_TEMPLATE   VERSION_NAME  LAST_ERROR
      webserver-group-d5tz  europe-west1-b  RUNNING   NONE        webserver-template
      webserver-group-q6t9  europe-west1-b  RUNNING   NONE        webserver-template
      webserver-group-tbpj  europe-west1-b  STOPPING  RECREATING  webserver-template
      
    2. 인스턴스가 STATUSRUNNING을, ACTIONNONE을 보고하여 인스턴스가 성공적으로 다시 시작되었음을 나타내면 자동 복구 프로세스가 완료된 것입니다.

      NAME                 ZONE            STATUS   ACTION  INSTANCE_TEMPLATE   VERSION_NAME  LAST_ERROR
      webserver-group-d5tz  europe-west1-b  RUNNING  NONE    webserver-template
      webserver-group-q6t9  europe-west1-b  RUNNING  NONE    webserver-template
      webserver-group-tbpj  europe-west1-b  RUNNING  NONE    webserver-template
      
    3. 인스턴스 그룹 모니터링을 마치면 Ctrl+C를 눌러 중지합니다.

이 연습을 얼마든지 반복해도 됩니다. 다음 팁을 참조하세요.

  • 모든 인스턴스를 한 번에 비정상으로 설정하는 경우 어떻게 될까요? 동시 실패 중의 자동 복구 동작에 대한 자세한 내용은 자동 복구 동작을 참조하세요.

  • 인스턴스를 최대한 빠르게 복구하기 위해 상태 확인 구성을 업데이트할 수 있나요? (실제로는 이 튜토리얼에서 설명한 대로 보수적인 값을 사용하도록 상태 확인 매개변수를 설정해야 합니다. 그렇지 않으면 실제 문제가 없는 경우에도 인스턴스가 잘못 삭제되고 다시 시작될 위험이 있습니다.)

  • 인스턴스 그룹에 initial delay 구성 설정이 있습니다. 이 데모 웹 서버에 필요한 최소 지연 시간을 확인할 수 있나요? (실제로는 인스턴스가 부팅되고 앱 요청을 처리하기 시작하는 데 걸리는 시간보다 지연 시간을 약간 더 길게(10~20%) 설정해야 합니다. 그렇지 않으면 인스턴스가 자동 복구 부팅 루프에서 멈출 위험이 있습니다.)

자동 복구 기록 보기(선택사항)

자동 복구 작업의 기록을 보려면 다음 gcloud 명령어를 사용하세요.

gcloud compute operations list --filter='operationType~compute.instances.repair.*'

자세한 내용은 이전 자동 복구 작업 보기를 참조하세요.

삭제

튜토리얼을 완료한 후에는 만든 리소스를 삭제하여 할당량 사용을 중지하고 요금이 청구되지 않도록 할 수 있습니다. 다음 섹션은 이러한 리소스를 삭제하거나 사용 중지하는 방법을 설명합니다.

이 튜토리얼용으로 별도의 프로젝트를 만든 경우 전체 프로젝트를 삭제합니다. 그렇지 않고 프로젝트에 유지하려는 리소스가 있는 경우 이 튜토리얼에서 만든 특정 리소스만 삭제합니다.

프로젝트 삭제

  1. Google Cloud 콘솔에서 리소스 관리 페이지로 이동합니다.

    리소스 관리로 이동

  2. 프로젝트 목록에서 삭제할 프로젝트를 선택하고 삭제를 클릭합니다.
  3. 대화상자에서 프로젝트 ID를 입력한 후 종료를 클릭하여 프로젝트를 삭제합니다.

특정 리소스 삭제

이 튜토리얼에 사용된 프로젝트를 삭제할 수 없는 경우 가이드 리소스를 개별적으로 삭제합니다.

인스턴스 그룹 삭제

콘솔

  1. Google Cloud 콘솔에서 인스턴스 그룹 페이지로 이동합니다.

    인스턴스 그룹으로 이동

  2. webserver-group 인스턴스 그룹의 체크박스를 클릭합니다.
  3. 인스턴스 그룹을 삭제하려면 삭제를 클릭합니다.

gcloud

gcloud compute instance-groups managed delete webserver-group --zone europe-west1-b -q

인스턴스 템플릿 삭제

콘솔

  1. Google Cloud Console에서 인스턴스 템플릿 페이지로 이동합니다.

    인스턴스 템플릿으로 이동

  2. 인스턴스 템플릿 옆의 체크박스를 클릭합니다.

  3. 페이지 상단에 있는 삭제를 클릭합니다. 새 창에서 삭제를 클릭하여 삭제를 확인합니다.

gcloud

gcloud compute instance-templates delete webserver-template -q

상태 확인 삭제

콘솔

  1. Google Cloud Console에서 상태 확인 페이지로 이동합니다.

    상태 확인으로 이동

  2. 상태 확인 옆의 체크박스를 클릭합니다.

  3. 페이지 상단에 있는 삭제를 클릭합니다. 새 창에서 삭제를 클릭하여 삭제를 확인합니다.

gcloud

gcloud compute health-checks delete autohealer-check -q

방화벽 규칙 삭제

콘솔

  1. Google Cloud Console에서 방화벽 규칙 페이지로 이동합니다.

    방화벽 규칙으로 이동

  2. default-allow-httpdefault-allow-http-health-check 방화벽 규칙 옆의 체크박스를 클릭합니다.

  3. 페이지 상단에 있는 삭제를 클릭합니다. 새 창에서 삭제를 클릭하여 삭제를 확인합니다.

gcloud

gcloud compute firewall-rules delete default-allow-http default-allow-http-health-check -q

다음 단계