Fn Project를 사용하여 Python으로 작성된 기능을 이동해보십시오.

개요



이 항목에서는 OSS의 FaaS 서버인 "Fn Project"를 사용하여 Python의 함수를 이동하는 패턴을 다룹니다.

아래 그림과 같이 Python의 곱셈 함수를 Fn 서버에 배포하고 이동합니다.



가정 독자


  • Fn Project에서 Python 프로그램 아직 스스로 움직이지 않은 분

  • 「Fn Project를 사용해 JavaScript로 쓴 function을 Node로 움직여 본다」의 파이썬 버전에 관심이 있다면

  • 준비



    Fn Project를 이동할 때까지는 다른 항목"OCI의 Micro Instance에서 CentOS에 Fn Project 서버를 설치해보십시오"을 참조하십시오.

    이 항목에서 필자는 OCI의 Micro Instance에서 작업합니다.

    파이썬으로 function 이동



    작업의 기본 흐름은 Introduction to Fn with Python에 쓰여진 것을 따르고 있습니다.

    Fn의 앱



    또 다른 항목 「Fn Project를 사용해 JavaScript로 쓴 function을 Node로 움직여 본다」에서 fn create app에서 fn에 "calc-fn-app"앱을 만들고있는 것에 Function을 추가하는 형태를 취합니다.

    등록



    /multiply라는 위치에 Python으로 함수를 하나 만들기 위해 fn init를 실행합니다.
    $ fn init --runtime python --trigger http multiply
    Creating function at: ./multiply
    Function boilerplate generated.
    func.yaml created.
    

    아래와 같은 세 개의 파일이 있습니다.
    $ ls
    func.py  func.yaml  requirements.txt
    

    코드 변경



    아래와 같이 입력값의 left와 right를 곱하여 반환하는 함수로 다시 씁니다.
    import io
    import json
    from decimal import *
    
    from fdk import response
    
    
    def handler(ctx, data: io.BytesIO=None):
        value = Decimal('NaN')
        try:
            body = json.loads(data.getvalue())
            left = Decimal(body.get('left'))
            right = Decimal(body.get('right'))
            value = left * right
        except (Exception, ValueError) as ex:
            print(str(ex))
    
        return response.Response(
            ctx, response_data=json.dumps(
                {"result": str(value)}),
            headers={"Content-Type": "application/json"}
        )
    

    앱 배포 -w로 작업 디렉토리를 지정하여 등록하고 있습니다.
    fn --verbose deploy --app calc-fn-app --local -w /home/opc/calc-fn-app/multiply
    

    첫회 실행시에는 다음과 같은 흐름이 되는 것 같습니다.
    $ fn --verbose deploy --app calc-fn-app --local -w /home/opc/calc-fn-app/multiply
    Deploying multiply to app: calc-fn-app
    Bumped to version 0.0.2
    Building image fndemouser/multiply:0.0.2
    FN_REGISTRY:  fndemouser
    Current Context:  default
    Sending build context to Docker daemon  6.144kB
    Step 1/12 : FROM fnproject/python:3.6-dev as build-stage
    3.6-dev: Pulling from fnproject/python
    80369df48736: Pull complete
    aaba0609d543: Pull complete
    a97b990f94a5: Pull complete
    af4a941e5376: Pull complete
    709c35256bb6: Pull complete
    3c3deb8445b4: Pull complete
    Digest: sha256:8ac8c28a68fd0442b9ddcdf6a41f30230482d72d1024cafca06c9f1ac0bd821c
    Status: Downloaded newer image for fnproject/python:3.6-dev
     ---> c5dbe9a0175b
    Step 2/12 : WORKDIR /function
     ---> Running in f7aaa0e58f7a
    Removing intermediate container f7aaa0e58f7a
     ---> 697f68e69e7c
    Step 3/12 : ADD requirements.txt /function/
     ---> c4472f73a275
    Step 4/12 : RUN pip3 install --target /python/  --no-cache --no-cache-dir -r requirements.txt &&                         rm -fr ~/.cache/pip /tmp* requirements.txt func.yaml Dockerfile .venv
     ---> Running in 4f758b74080b
    Collecting fdk
      Downloading https://files.pythonhosted.org/packages/1d/b8/41b81bf76766f7e810627728647a8076626070a6e1d01a18a8ed16bd3d3f/fdk-0.1.12-py3-none-any.whl (46kB)
    Collecting iso8601==0.1.12
      Downloading https://files.pythonhosted.org/packages/ef/57/7162609dab394d38bbc7077b7ba0a6f10fb09d8b7701ea56fa1edc0c4345/iso8601-0.1.12-py2.py3-none-any.whl
    Collecting httptools>=0.0.10
      Downloading https://files.pythonhosted.org/packages/1b/03/215969db11abe8741e9c266a4cbe803a372bd86dd35fa0084c4df6d4bd00/httptools-0.0.13.tar.gz (104kB)
    Collecting pbr!=2.1.0,>=2.0.0
      Downloading https://files.pythonhosted.org/packages/7a/db/a968fd7beb9fe06901c1841cb25c9ccb666ca1b9a19b114d1bbedf1126fc/pbr-5.4.4-py2.py3-none-any.whl (110kB)
    Collecting pytest==4.0.1
      Downloading https://files.pythonhosted.org/packages/81/27/d4302e4e00497448081120f65029696070806bc8e649b83f644de006d710/pytest-4.0.1-py2.py3-none-any.whl (217kB)
    Collecting pytest-asyncio==0.9.0
      Downloading https://files.pythonhosted.org/packages/33/7f/2ed9f460872ebcc62d30afad167673ca10df36ff56a6f6df2f1d3671adc8/pytest_asyncio-0.9.0-py3-none-any.whl
    Collecting py>=1.5.0
      Downloading https://files.pythonhosted.org/packages/99/8d/21e1767c009211a62a8e3067280bfce76e89c9f876180308515942304d2d/py-1.8.1-py2.py3-none-any.whl (83kB)
    Collecting pluggy>=0.7
      Downloading https://files.pythonhosted.org/packages/a0/28/85c7aa31b80d150b772fbe4a229487bc6644da9ccb7e427dd8cc60cb8a62/pluggy-0.13.1-py2.py3-none-any.whl
    Collecting attrs>=17.4.0
      Downloading https://files.pythonhosted.org/packages/a2/db/4313ab3be961f7a763066401fb77f7748373b6094076ae2bda2806988af6/attrs-19.3.0-py2.py3-none-any.whl
    Collecting setuptools
      Downloading https://files.pythonhosted.org/packages/a7/c5/6c1acea1b4ea88b86b03280f3fde1efa04fefecd4e7d2af13e602661cde4/setuptools-45.1.0-py3-none-any.whl (583kB)
    Collecting more-itertools>=4.0.0
      Downloading https://files.pythonhosted.org/packages/72/96/4297306cc270eef1e3461da034a3bebe7c84eff052326b130824e98fc3fb/more_itertools-8.2.0-py3-none-any.whl (43kB)
    Collecting six>=1.10.0
      Downloading https://files.pythonhosted.org/packages/65/eb/1f97cb97bfc2390a276969c6fae16075da282f5058082d4cb10c6c5c1dba/six-1.14.0-py2.py3-none-any.whl
    Collecting atomicwrites>=1.0
      Downloading https://files.pythonhosted.org/packages/52/90/6155aa926f43f2b2a22b01be7241be3bfd1ceaf7d0b3267213e8127d41f4/atomicwrites-1.3.0-py2.py3-none-any.whl
    Collecting importlib-metadata>=0.12; python_version < "3.8"
      Downloading https://files.pythonhosted.org/packages/8b/03/a00d504808808912751e64ccf414be53c29cad620e3de2421135fcae3025/importlib_metadata-1.5.0-py2.py3-none-any.whl
    Collecting zipp>=0.5
      Downloading https://files.pythonhosted.org/packages/be/69/4ac28bf238f287f1677f41392e24d2c4ffafcf11648c23824f5f62ef6ccb/zipp-2.1.0-py3-none-any.whl
    Building wheels for collected packages: httptools
      Building wheel for httptools (setup.py): started
      Building wheel for httptools (setup.py): finished with status 'done'
      Created wheel for httptools: filename=httptools-0.0.13-cp36-cp36m-linux_x86_64.whl size=217310 sha256=51eb19168c0639662416a8ad83b9df7d7ceb8eb14a58ce3bec5ffe3ab3b07a7f
      Stored in directory: /tmp/pip-ephem-wheel-cache-pwxrmfa5/wheels/e8/3e/2e/013f99b42efc25cf3589730cf380738e46b1e5edaf2f78d525
    Successfully built httptools
    Installing collected packages: iso8601, httptools, pbr, py, zipp, importlib-metadata, pluggy, attrs, setuptools, more-itertools, six, atomicwrites, pytest, pytest-asyncio, fdk
    Successfully installed atomicwrites-1.3.0 attrs-19.3.0 fdk-0.1.12 httptools-0.0.13 importlib-metadata-1.5.0 iso8601-0.1.12 more-itertools-8.2.0 pbr-5.4.4 pluggy-0.13.1 py-1.8.1 pytest-4.0.1 pytest-asyncio-0.9.0 setuptools-45.1.0 six-1.14.0 zipp-2.1.0
    WARNING: You are using pip version 19.3.1; however, version 20.0.2 is available.
    You should consider upgrading via the 'pip install --upgrade pip' command.
    Removing intermediate container 4f758b74080b
     ---> 5246c18d4e6f
    Step 5/12 : ADD . /function/
     ---> c6181bb33bd1
    Step 6/12 : RUN rm -fr /function/.pip_cache
     ---> Running in 695fe059e692
    Removing intermediate container 695fe059e692
     ---> 5ea69eaafc3a
    Step 7/12 : FROM fnproject/python:3.6
    3.6: Pulling from fnproject/python
    80369df48736: Already exists
    aaba0609d543: Already exists
    a97b990f94a5: Already exists
    af4a941e5376: Already exists
    709c35256bb6: Already exists
    671870542c6c: Pull complete
    936a6f40830a: Pull complete
    Digest: sha256:3b438ba11405bba0f6e1e8d8819c9b8be38249da7253491f3cf9f7e5ed6c0ec6
    Status: Downloaded newer image for fnproject/python:3.6
     ---> e8e10863d7cd
    Step 8/12 : WORKDIR /function
     ---> Running in ddbc794f4bd9
    Removing intermediate container ddbc794f4bd9
     ---> 4e3bed62a7f5
    Step 9/12 : COPY --from=build-stage /python /python
     ---> b1c7d4fd7598
    Step 10/12 : COPY --from=build-stage /function /function
     ---> 87446e069bd2
    Step 11/12 : ENV PYTHONPATH=/function:/python
     ---> Running in af075fbcae2c
    Removing intermediate container af075fbcae2c
     ---> 98a9f515e7e0
    Step 12/12 : ENTRYPOINT ["/python/bin/fdk", "/function/func.py", "handler"]
     ---> Running in 555033ab1e55
    Removing intermediate container 555033ab1e55
     ---> 9942a3d98858
    Successfully built 9942a3d98858
    Successfully tagged fndemouser/multiply:0.0.2
    
    Updating function multiply using image fndemouser/multiply:0.0.2...
    Successfully created function: multiply with fndemouser/multiply:0.0.2
    Successfully created trigger: multiply
    Trigger Endpoint: http://127.0.0.1:18080/t/calc-fn-app/multiply
    
    

    fn 명령으로 확인합니다. (다른 엔트리로 plus, minus를 만들고 있습니다)
    $ fn list fn calc-fn-app
    NAME            IMAGE                           ID
    multiply        fndemouser/multiply:0.0.2       01E086F2D6NG8G00GZJ000001E
    plus            fndemouser/plus:0.0.2           01E0393FDCNG8G00GZJ000000E
    subtract        fndemouser/subtract:0.0.3       01E05KAKGENG8G00GZJ0000013
    

    Docker 명령으로 확인하면 해당 컨테이너의 이미지가 만들어졌음을 알 수 있습니다.
    $ docker images | grep multiply
    fndemouser/multiply   0.0.2               9942a3d98858        About a minute ago   175MB
    

    실행



    등록시의 말미에 있던 URL에 curl로 액세스 해 봅니다.
    $ curl -d '{"left":"2", "right":"4"}' http://127.0.0.1:18080/t/calc-fn-app/multiply
    {"result": "8"}
    

    2*4의 결과인 8이 반환되고 있습니다.

    결론



    이 항목에서는 Fn project를 사용하여 Python에서 작성한 function을 움직이는 것을 다루었습니다.

    이 항목에서 사용한 코드는 htps : // 기주 b. 이 m / hrkt / 또는 lc-f- p / re / s / g / 0.0.3 태그에 저장됩니다.

    보충: 외부 라이브러리



    이 항목에서는 외부 라이브러리를 사용하지 않았지만 requirements.txt에 나열되어 pip를 사용할 수 있습니다.

    보충: 이 항목을 작성할 때



    이 항목을 작성할 때 OCI의 마이크로 인스턴스에 다음과 같은 상황을 만들고 노트북에서 클라우드 측으로 ssh로 원격으로 연결하여 작업했습니다.
  • ssh 앞에 화면에서 여러 장의 창을 올려 놓고 작업하십시오
  • VS Code를 WEB로 움직여 "cdr / code-server와 OCI의 Always Free Micro 인스턴스에서 VS Code를 실행해보십시오."
  • Fn 프로젝트 서버도 거기에서 움직입니다
  • 코드는 GitHub에
  • 좋은 웹페이지 즐겨찾기