Python 런타임

Python 런타임은 애플리케이션 코드 및 종속 항목을 설치한 후 가변형 환경에서 해당 애플리케이션을 실행하는 소프트웨어 스택입니다.

Python 버전

Python 3.12는 buildpacks을 사용합니다. 지원되는 Python 버전의 전체 목록과 해당 Ubuntu 버전은 런타임 지원 일정을 참조하세요.

지원되는 Python 버전을 사용하려면 다음을 수행해야 합니다.

  • app.yaml 파일에 runtime_configoperating_system 설정을 포함하여 운영체제를 지정합니다.

  • gcloud CLI 버전 420.0.0 이상을 설치합니다. gcloud components update 명령어를 실행하여 CLI 도구를 업데이트할 수 있습니다. 설치된 버전을 보려면 gcloud version 명령어를 실행합니다.

  • 선택사항으로 app.yaml 파일에 runtime_version 설정을 포함하여 런타임 버전을 지정할 수 있습니다. runtime_version 설정이 지정되지 않으면 기본적으로 최신 Python 버전이 사용됩니다.

예시

  • Ubuntu 22에서 Python 3.12를 지정하려면 다음을 실행합니다.

    runtime: python
    env: flex
    entrypoint: gunicorn -b :$PORT main:app
    
    runtime_config:
        operating_system: "ubuntu22"
        runtime_version: "3.12"
    
  • Ubuntu 22에서 지원되는 최신 Python 버전을 지정하려면 다음을 실행합니다.

      runtime: python
      env: flex
      entrypoint: gunicorn -b :$PORT main:app
    
      runtime_config:
          operating_system: "ubuntu22"
    

자세한 내용은 app.yaml 참조 페이지를 확인하세요.

이전 런타임 버전

Python 버전 3.7 이하의 경우 애플리케이션의 app.yaml 파일에서 runtime_configpython_version 설정을 사용하여 버전을 지정합니다.

예시

runtime: python
env: flex
entrypoint: gunicorn -b :$PORT main:app

runtime_config:
    python_version: 3.7

Python 버전 3.7 이하에서는 runtime_config 또는 python_version이 생략된 경우 기본 인터프리터가 Python 2.7.12입니다. 예를 들어 app.yaml 파일에 runtime: python을 지정하여 기본 런타임을 사용할 수 있습니다.

runtime: python
env: flex

자세한 내용은 app.yaml 참조 페이지를 확인하세요.

각 버전 설정에 배포된 인터프리터는 다음 표에 나와 있습니다.

python_version 설정 배포된 인터프리터 런타임 ID app.yaml 예시
2(기본) 2.7.12 python2 runtime_config:
python_version: 2
3.4 3.4.8 python34 runtime_config:
python_version: 3.4
3.5 3.5.9 python35 runtime_config:
python_version: 3.5
3 또는 3.6 3.6.10 python36 runtime_config:
python_version: 3
3.7 3.7.9 python37 runtime_config:
python_version: 3.7

기타 Python 런타임 지원

지원되지 않는 Python 버전을 사용해야 하는 경우 커스텀 런타임을 만들고 필요한 Python 버전의 유효한 기본 이미지를 선택하면 됩니다.

Google에서 제공하는 기본 이미지나 Docker Python 기본 이미지커스텀 런타임 빌드를 참고하세요.

Cloud Run용 App Engine 앱을 컨테이너화하기 위한 자세한 내용은 마이그레이션 가이드를 참조하세요.

종속 항목

런타임에서는 애플리케이션 소스 디렉터리에서 requirements.txt 파일을 찾아 pip를 사용해 애플리케이션을 시작하기 전에 종속 항목을 설치합니다. 패키지 선언 및 관리에 대한 자세한 내용은 Python 라이브러리 사용을 참조하세요.

앱에 비공개 종속 항목이 필요하면 적합한 패키지를 설치할 Python 런타임을 기준으로 커스텀 런타임을 사용해야 합니다.

애플리케이션 시작

런타임은 app.yaml 파일에 정의된 entrypoint를 사용하여 애플리케이션을 시작합니다. 이 entrypoint에서 환경 변수 PORT로 정의된 포트에서 HTTP 요청에 응답하는 프로세스를 시작합니다.

대부분의 웹 애플리케이션은 Gunicorn, uWSGI, Waitress 같은 WSGI 서버를 사용합니다.

이러한 서버 중 하나를 사용하려면 먼저 애플리케이션의 requirements.txt에 종속 항목으로 추가해야 합니다. Flask 애플리케이션에 gunicorn을 사용하는 경우 애플리케이션의 Python 버전이 gunicorn호환되는지 확인합니다.

런타임은 entrypoint가 호출되기 전에 모든 종속 항목이 설치되도록 보장합니다.

Flask==2.0.2
gunicorn==20.1.0

Flask 애플리케이션에 gunicorn을 사용하는 entrypoint의 예:

entrypoint: gunicorn -b :$PORT main:app

Django 애플리케이션에 gunicorn을 사용하는 entrypoint의 예시:

entrypoint: gunicorn -b :$PORT mydjangoapp:wsgi

권장되는 WSGI 서버는 Gunicorn이지만 다른 WSGI 서버를 사용해도 무방합니다. Flask에 uWSGI를 사용하는 진입점의 예를 들면 다음과 같습니다.

entrypoint: uwsgi --http :$PORT --wsgi-file main.py --callable app

WSGI 서버 없이 요청을 처리할 수 있는 애플리케이션에서는 Python 스크립트만 실행하면 됩니다.

entrypoint: python main.py

위에 제시된 기본 entrypoint 예시는 시작점으로 사용하기 위한 것이며 사용자의 웹 애플리케이션에서 작동할 수도 있습니다. 하지만 대부분의 애플리케이션은 WSGI 서버를 추가로 구성해야 합니다. entrypoint에서 모든 설정을 지정하는 대신 app.yaml 파일이 위치한 프로젝트 루트 디렉터리에 gunicorn.conf.py 파일을 생성하고 entrypoint에서 다음과 같이 지정합니다.

entrypoint: gunicorn -c gunicorn.conf.py -b :$PORT main:app

Gunicorn 문서에서 Gunicorn의 모든 구성 값을 확인할 수 있습니다.

작업자

Gunicorn은 요청을 처리하기 위해 작업자를 사용합니다. 기본적으로 Gunicorn은 동기 작업자를 사용합니다. 이 작업자 클래스는 모든 웹 애플리케이션과 호환되지만 각 작업자는 한 번에 하나의 요청만 처리할 수 있습니다. 기본적으로 gunicorn은 이러한 작업자 중 하나만 사용합니다. 따라서 인스턴스가 제대로 활용되지 못하여 고부하 시 애플리케이션의 지연 시간이 증가하는 경우가 생길 수 있습니다.

작업자 수는 인스턴스 CPU 코어 수의 2~4배에 1을 더한 수로 설정할 것을 권장합니다. gunicorn.conf.py에서 다음과 같이 지정할 수 있습니다.

import multiprocessing

workers = multiprocessing.cpu_count() * 2 + 1

또한 대부분 I/O 바운드인 일부 웹 애플리케이션은 다른 작업자 클래스를 사용하여 성능을 개선할 수 있습니다. 작업자 클래스에 gevent나 tornado 같은 추가 종속 항목이 필요하다면 애플리케이션의 requirements.txt에 이러한 종속 항목을 선언해야 합니다.

HTTPS 및 전달 프록시

App Engine은 부하 분산기에서 HTTPS 연결을 종료하고 요청을 애플리케이션에 전달합니다. 대부분의 애플리케이션은 요청이 HTTPS를 통해 전송되었는지 여부를 알 필요는 없지만, 이 정보가 필요한 애플리케이션은 gunicorn.conf.py에서 App Engine 프록시를 신뢰하도록 Gunicorn을 구성해야 합니다.

forwarded_allow_ips = '*'
secure_scheme_headers = {'X-FORWARDED-PROTO': 'https'}

이제 Gunicorn은 대부분의 웹 프레임워크가 요청의 표시로 사용하게 될 'https'로 설정된 wsgi.url_scheme이 안전하다는 것을 확신하게 됩니다. WSGI 서버 또는 프레임워크에서 이를 지원하지 않는 경우 X-Forwarded-Proto 헤더의 값을 수동으로 확인하세요.

일부 애플리케이션은 사용자 IP 주소도 확인해야 합니다. 사용자 IP 주소는 X-Forwarded-For 헤더에서 제공됩니다.

gunicorn.conf.pysecure_scheme_headers 설정은 X-FORWARDED-PROTO와 같이 대문자여야 하지만, 코드에서 읽을 수 있는 헤더는 X-Forwarded-Proto와 같이 대소 문자를 혼용합니다.

런타임 확장

가변형 환경 Python 런타임은 커스텀 런타임을 만드는 데 사용할 수 있습니다. 자세한 내용은 Python 맞춤설정을 참조하세요.

환경 변수

런타임 환경에서 설정되는 환경 변수는 다음과 같습니다.

환경 변수 설명
GAE_INSTANCE 현재 인스턴스의 이름입니다.
GAE_MEMORY_MB 애플리케이션 프로세스에서 사용할 수 있는 메모리 양입니다.
GAE_SERVICE 애플리케이션의 app.yaml 파일에 지정된 서비스 이름이거나 서비스 이름이 지정되지 않은 경우 default로 설정됩니다.
GAE_VERSION 현재 애플리케이션의 버전 라벨입니다.
GOOGLE_CLOUD_PROJECT 애플리케이션과 연결된 프로젝트 ID로, Google Cloud 콘솔에 표시됩니다.
PORT HTTP 요청을 수신할 포트

app.yaml 파일에서 추가 환경 변수를 설정할 수 있습니다.

메타데이터 서버

애플리케이션의 각 인스턴스에서 Compute Engine 메타데이터 서버를 사용해 호스트 이름, 외부 IP 주소, 인스턴스 ID, 커스텀 메타데이터, 서비스 계정 정보 등의 인스턴스 관련 정보를 쿼리할 수 있습니다. App Engine에서는 인스턴스별로 커스텀 메타데이터를 설정할 수 없지만 프로젝트 차원의 커스텀 메타데이터를 설정해 App Engine 및 Compute Engine 인스턴스에서 읽는 것은 가능합니다.

이 예시 함수는 메타데이터 서버를 사용해 인스턴스의 외부 IP 주소를 가져옵니다.

METADATA_NETWORK_INTERFACE_URL = (
    "http://metadata/computeMetadata/v1/instance/network-interfaces/0/"
    "access-configs/0/external-ip"
)


def get_external_ip():
    """Gets the instance's external IP address from the Compute Engine metadata
    server.

    If the metadata server is unavailable, it assumes that the application is running locally.

    Returns:
        The instance's external IP address, or the string 'localhost' if the IP address
        is not available.
    """
    try:
        r = requests.get(
            METADATA_NETWORK_INTERFACE_URL,
            headers={"Metadata-Flavor": "Google"},
            timeout=2,
        )
        return r.text
    except requests.RequestException:
        logging.info("Metadata server could not be reached, assuming local.")
        return "localhost"