【问题标题】:How can I access a local FastAPI service with deployed with Skaffold?如何访问使用 Skaffold 部署的本地 FastAPI 服务?
【发布时间】:2021-03-26 11:01:35
【问题描述】:

到目前为止,我使用 docker 和 docker-compose 在本地开发 Python 应用程序。现在我想更改我的开发工作流程,使用skaffolddocker 作为构建器,使用kubectl 作为部署器,使用minikube 管理本地kubernetes 集群。

假设我有这个用于 FastAPI 的基于 docker 的 hello world:

项目结构:

app/app.py
Dockerfile

app/app.py

from typing import Optional

from fastapi import FastAPI

app = FastAPI()


@app.get("/")
def read_root():
    return {"Hello": "World"}

@app.get("/items/{item_id}")
def read_item(item_id: int, q: Optional[str] = None):
    return {"item_id": item_id, "q": q}

Dockerfile:

FROM tiangolo/uvicorn-gunicorn-fastapi:python3.7

COPY ./app /app

如果我运行docker build -t hello-fastapi .docker run -p 80:80 hello-fastapi,我可以通过0.0.0.0localhost 访问该服务。我在这里跳过docker-compose 的事情,因为这并不重要。脚手架设置。

要使用skaffold,我有完全相同的项目结构和内容,但我添加了 skaffold + kubectl 特定的东西(skaffold.yamldeployment.yaml):

项目结构:

app/app.py
k8s/deployment.yaml
Dockerfile
skaffold.yaml

k8s/deployment.yaml

apiVersion: v1
kind: Service
metadata:
  name: fastapi-service
  labels:
    app: fastapi-service
spec:
  clusterIP: None
  ports:
    - port: 80
      name: fastapi-service
  selector:
    app: fastapi-service
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: fastapi-service
  labels:
    app: fastapi-service
spec:
  replicas: 1
  selector:
    matchLabels:
      app: fastapi-service
  template:
    metadata:
      labels:
        app: fastapi-service
    spec:
      containers:
      - name: fastapi-service
        image: fastapi-service
        ports:
        - containerPort: 80

skaffold.yaml

apiVersion: skaffold/v2beta10
kind: Config
build:
  artifacts:
  - image: fastapi-image
deploy:
  kubectl:
    manifests:
      - k8s/*

如果我运行 skaffold dev 一切似乎都很好:

Listing files to watch...
 - fastapi-service
Generating tags...
 - fastapi-service -> fastapi-service:latest
Some taggers failed. Rerun with -vdebug for errors.
Checking cache...
 - fastapi-service: Found Locally
Tags used in deployment:
 - fastapi-service -> fastapi-service:17659a877904d862184d7cc5966596d46b0765f1995f7abc958db4b3f98b8a35
Starting deploy...
 - service/fastapi-service created
 - deployment.apps/fastapi-service created
Waiting for deployments to stabilize...
 - deployment/fastapi-service is ready.
Deployments stabilized in 2.165700782s
Press Ctrl+C to exit
Watching for changes...
[fastapi-service] Checking for script in /app/prestart.sh
[fastapi-service] Running script /app/prestart.sh
[fastapi-service] Running inside /app/prestart.sh, you could add migrations to this file, e.g.:
[fastapi-service] 
[fastapi-service] #! /usr/bin/env bash
[fastapi-service] 
[fastapi-service] # Let the DB start
[fastapi-service] sleep 10;
[fastapi-service] # Run migrations
[fastapi-service] alembic upgrade head
[fastapi-service] 
[fastapi-service] [2020-12-15 19:02:57 +0000] [1] [INFO] Starting gunicorn 20.0.4
[fastapi-service] [2020-12-15 19:02:57 +0000] [1] [INFO] Listening at: http://0.0.0.0:80 (1)
[fastapi-service] [2020-12-15 19:02:57 +0000] [1] [INFO] Using worker: uvicorn.workers.UvicornWorker
[fastapi-service] [2020-12-15 19:02:57 +0000] [8] [INFO] Booting worker with pid: 8
...

但是我无法通过我的网络浏览器访问该服务。如何通过例如从本地计算机访问服务网络浏览器?

编辑

根据minikube service list服务fastapi-service存在:

|----------------------|---------------------------|--------------|-----|
|      NAMESPACE       |           NAME            | TARGET PORT  | URL |
|----------------------|---------------------------|--------------|-----|
| default              | fastapi-service           | No node port |
| default              | kubernetes                | No node port |
| kube-system          | kube-dns                  | No node port |
| kubernetes-dashboard | dashboard-metrics-scraper | No node port |
| kubernetes-dashboard | kubernetes-dashboard      | No node port |
|----------------------|---------------------------|--------------|-----|

但我无法通过curl $(minikube service fastapi-service --url)访问它:

curl: (3) Failed to convert ???? to ACE; string contains a disallowed character

curl: (6) Could not resolve host: service
curl: (6) Could not resolve host: default
curl: (6) Could not resolve host: has
curl: (6) Could not resolve host: no
curl: (6) Could not resolve host: node
curl: (6) Could not resolve host: port

这可能与 Unable to get ClusterIP service url from minikube 有关。如果我将deployment.yaml 更改为

apiVersion: v1
kind: Service
metadata:
  name: fastapi-service
  labels:
    app: fastapi-service
spec:
  type: NodePort
  ports:
    - targetPort: 80
      port: 80
  selector:
    app: fastapi-service
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: fastapi-service
  labels:
    app: fastapi-service
spec:
  replicas: 1
  selector:
    matchLabels:
      app: fastapi-service
  template:
    metadata:
      labels:
        app: fastapi-service
    spec:
      containers:
      - name: fastapi-service
        image: fastapi-service
        ports:
        - containerPort: 80

通过curl $(minikube service fastapi-service --url)访问服务成功:

{"message":"Hello world! From FastAPI running on Uvicorn with Gunicorn. Using Python 3.7"}

但是我无法通过网络浏览器访问该服务。

【问题讨论】:

    标签: python kubernetes fastapi skaffold


    【解决方案1】:

    可以使用minikube service list获取服务的IP和端口:

    |----------------------|---------------------------|--------------|---------------------------|
    |      NAMESPACE       |           NAME            | TARGET PORT  |            URL            |
    |----------------------|---------------------------|--------------|---------------------------|
    | default              | fastapi-service           |           80 | http://192.168.49.2:32205 |
    | default              | kubernetes                | No node port |
    | kube-system          | kube-dns                  | No node port |
    | kubernetes-dashboard | dashboard-metrics-scraper | No node port |
    | kubernetes-dashboard | kubernetes-dashboard      | No node port |
    |----------------------|---------------------------|--------------|---------------------------|
    

    【讨论】:

      【解决方案2】:

      使用 Skaffold --port-forward 启用服务的自动端口转发和用户定义的端口转发。

      Skaffold 通常会尽可能选择靠近远程端口的本地端口。但由于端口 80 是受保护的端口,Skaffold 将选择不同的本地端口。您可以显式configure a port forward your skaffold.yaml 指定本地端口。如果您稍后添加其他服务,使用用户定义的端口转发可以帮助避免潜在的混乱。

      apiVersion: skaffold/v2beta10
      kind: Config
      build:
        artifacts:
        - image: fastapi-service
      deploy:
        kubectl:
          manifests:
            - k8s/*
      portForward:
        - resourceType: deployment
          resourceName: fastapi-service
          port: 80
          localPort: 9000
      

      而不是运行 skaffold dev 运行 skaffold dev --port-forward。现在您可以通过localhost:9000访问该服务。

      也可以使用kubectl port-forward手动转发端口; Skaffold 使用相同的功能来实现其端口转发。

      【讨论】:

        猜你喜欢
        • 2022-08-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-13
        相关资源
        最近更新 更多