Helm 部署 nginx 和 fastapi 本地镜像服务

FastAPI web服务

目录结构:

1
2
3
4
5
6
.
├── app
│   ├── __init__.py
│   └── main.py
├── app.Dockerfile
└── requirements.txt

app服务

创建一个fastapi服务,实现生成短链接的接口, 实现参考如何生成短链?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
from typing import Union

from fastapi import FastAPI
from pydantic import BaseModel

import mmh3
import random

class URL(BaseModel):
    long_url: str
    short_url: str | None = None

app = FastAPI()

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


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

@app.get("/short/code")
async def short_code():
    hash = random.randint(1, ((1<<32)-1))
    code = to_base62(hash)
    return {"code": code}

@app.post("/short/url")
async def short_url(url: URL):
    hash = mmh3.hash(url.long_url, signed=False) # returns a 32-bit unsigned int
    url.short_url = to_base62(hash)
    return url

BASE62 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
async def to_base62(hash: int):
    code = ''
    while hash > 0:
        code += BASE62[hash % 62]
        hash //= 62
    return code

requirements.txt

app/main.py 服务依赖文件

1
2
3
4
fastapi==0.111.0
pydantic==2.7.1
uvicorn==0.29.0
mmh3==4.1.0

Dockerfile文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
FROM python:3.12.3

WORKDIR /code

COPY ./requirements.txt /code/requirements.txt

RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt

COPY ./app /code/app

CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8080"]

构建Docker镜像

构建app服务镜像

1
docker build -t fastapi_shortcode:v0.1 -f app.Dockerfile .

构建完成后,查看本地镜像

1
2
3
4
5
docker images
REPOSITORY                         TAG                   IMAGE ID       CREATED              SIZE
fastapi_shortcode                  v0.1                  b5a184cd5f41   About a minute ago   1.09GB
python                             3.12.3                12e5ab9d51c8   6 weeks ago          1.02GB

运行镜像

1
2
docker run -d --name fastapi_shortcode -p 8080:8080 fastapi_shortcode:v0.1
6742784e41c6ed59d738d492862cb437b97264e82fdc5ddf39231a394d4c338b

查看运行镜像状态

1
2
3
docker ps
CONTAINER ID   IMAGE                             COMMAND                   CREATED         STATUS         PORTS                                       NAMES
6742784e41c6   fastapi_shortcode:v0.1            "uvicorn app.main:ap…"   26 seconds ago   Up 25 seconds   0.0.0.0:8080->8080/tcp, :::8080->8080/tcp   fastapi_shortcode

查看镜像运行日志

1
2
3
4
5
6
7
docker logs -f 6742784e41c6
INFO:     Started server process [1]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:8080 (Press CTRL+C to quit)
INFO:     172.17.0.1:49386 - "GET / HTTP/1.1" 200 OK
INFO:     172.17.0.1:49386 - "GET /favicon.ico HTTP/1.1" 404 Not Found

接口测试

Swagger UI: http://localhost:8080/docs#

  1. 验证服务接口
1
2
3
4
5
6
7
8
curl -i http://localhost:8080/
HTTP/1.1 200 OK
date: Sat, 25 May 2024 14:06:21 GMT
server: uvicorn
content-length: 17
content-type: application/json

{"Hello":"World"}%
  1. 随机生成短链接code
1
2
3
4
5
6
7
8
curl -i http://localhost:8080/short/code
HTTP/1.1 200 OK
date: Sat, 25 May 2024 15:12:29 GMT
server: uvicorn
content-length: 17
content-type: application/json

{"code":"L5xZu2"}%
  1. 生成长链接对应的短链接code
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
curl -X 'POST' \
  'http://localhost:8080/short/url' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "long_url": "https://google.com",
  "short_url": ""
}'

{
  "long_url": "https://google.com",
  "short_url": "zTgQx3"
}

helm部署fastapi app

使用helm来安装fastapi app,并使用nginx ingress来做反向代理。

helm 版本

1
2
3
~ helm version
version.BuildInfo{Version:"v3.14.4", GitCommit:"81c902a123462fd4052bc5e9aa9c513c4c8fc142", GitTreeState:"clean", GoVersion:"go1.22.2"}

helm 仓库

1
2
3
4
5
helm repo list
NAME    URL
piaohua https://piaohua.github.io/helm-charts/
bitnami https://charts.bitnami.com/bitnami

仓库中搜索nginx镜像

1
2
3
4
5
6
helm search repo nginx
NAME                                    CHART VERSION   APP VERSION     DESCRIPTION
bitnami/nginx                           16.0.6          1.25.5          NGINX Open Source is a web server that can be a...
bitnami/nginx-ingress-controller        11.1.1          1.10.1          NGINX Ingress Controller is an Ingress controll...
bitnami/nginx-intel                     2.1.15          0.4.9           DEPRECATED NGINX Open Source for Intel is a lig...

创建一个新的Helm chart目录结构:

1
helm create fastapi-short-code

配置values.yaml后,打包应用

1
2
helm package fastapi-short-code --debug
Successfully packaged chart and saved it to: /Users/piao/data/golang/helm-charts/fastapi-short-code-0.1.0.tgz

打包后安装启动应用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
helm install shortcode fastapi-short-code-0.1.0.tgz
NAME: shortcode
LAST DEPLOYED: Sun May 26 17:40:19 2024
NAMESPACE: default
STATUS: deployed
REVISION: 1
NOTES:
1. Get the application URL by running these commands
  http:///

部署成功后,查看启动服务

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
kubectl get pods,rc,svc,deployment -o wide -n default
NAME                                                READY   STATUS    RESTARTS   AGE   IP          NODE               NOMINATED NODE   READINESS GATES
pod/shortcode-fastapi-short-code-78546fd569-6x8qk   1/1     Running   0          15m   10.42.0.8   colima-helm-test   <none>           <none>

NAME                                   TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE   SELECTOR
service/kubernetes                     ClusterIP   10.43.0.1      <none>        443/TCP    20d   <none>
service/shortcode-fastapi-short-code   ClusterIP   10.43.229.27   <none>        8080/TCP   15m   app.kubernetes.io/instance=shortcode,app.kubernetes.io/name=fastapi-short-code

NAME                                           READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS           IMAGES                   SELECTOR
deployment.apps/shortcode-fastapi-short-code   1/1     1            1           15m   fastapi-short-code   fastapi_shortcode:v0.1   app.kubernetes.io/instance=shortcode,app.kubernetes.io/name=fastapi-short-code

helm应用查看

1
2
3
~ helm ls
NAME            NAMESPACE       REVISION        UPDATED                                 STATUS          CHART                           APP VERSION
shortcode       default         1               2024-05-26 17:40:19.987909 +0800 CST    deployed        fastapi-short-code-0.1.0        1.16.0

部署失败场景

部署出现如下错误

1
2
Error: INSTALLATION FAILED: 1 error occurred:
        * Ingress.extensions "shortcode" is invalid: spec.rules[0].host: Invalid value: "0.0.0.0": must be a DNS name, not an IP address

是因为values.yaml中host配置错误,host只能配置为域名,不能是ip,或者配置为空

第二种错误场景如下:

1
Error: INSTALLATION FAILED: non-absolute URLs should be in form of repo_name/path_to_chart, got: shortcode-0.1.0.tgz

这是因为应用名称已经存在,可以用命令helm -n default ls -a查看,

如果已经存在,可以用命令helm -n default delete shortcode删除。

nginx部署

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
 ~ helm install nginx-fastapi fastapi-short-code-nginx-0.1.0.tgz
NAME: nginx-fastapi
LAST DEPLOYED: Sun May 26 17:59:04 2024
NAMESPACE: default
STATUS: deployed
REVISION: 1
NOTES:
1. Get the application URL by running these commands:
     NOTE: It may take a few minutes for the LoadBalancer IP to be available.
           You can watch the status of by running 'kubectl get --namespace default svc -w nginx-fastapi-fastapi-short-code-nginx'
  export SERVICE_IP=$(kubectl get svc --namespace default nginx-fastapi-fastapi-short-code-nginx --template "{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}")
  echo http://$SERVICE_IP:80

部署成功后查看服务状态

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
➜  ~ kubectl get pods,rc,svc,deployment -o wide -n default
NAME                                                          READY   STATUS    RESTARTS      AGE   IP           NODE               NOMINATED NODE   READINESS GATES
pod/shortcode-fastapi-short-code-78546fd569-6x8qk             1/1     Running   0             19m   10.42.0.8    colima-helm-test   <none>           <none>
pod/nginx-fastapi-fastapi-short-code-nginx-66cf6785dd-dcffz   0/1     Running   1 (29s ago)   60s   10.42.0.10   colima-helm-test   <none>           <none>

NAME                                             TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE   SELECTOR
service/kubernetes                               ClusterIP      10.43.0.1      <none>        443/TCP        20d   <none>
service/shortcode-fastapi-short-code             ClusterIP      10.43.229.27   <none>        8080/TCP       19m   app.kubernetes.io/instance=shortcode,app.kubernetes.io/name=fastapi-short-code
service/nginx-fastapi-fastapi-short-code-nginx   LoadBalancer   10.43.56.241   192.168.5.3   80:30726/TCP   62s   app.kubernetes.io/instance=nginx-fastapi,app.kubernetes.io/name=fastapi-short-code-nginx

NAME                                                     READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS                 IMAGES                              SELECTOR
deployment.apps/shortcode-fastapi-short-code             1/1     1            1           19m   fastapi-short-code         fastapi_shortcode:v0.1              app.kubernetes.io/instance=shortcode,app.kubernetes.io/name=fastapi-short-code
deployment.apps/nginx-fastapi-fastapi-short-code-nginx   0/1     1            0           62s   fastapi-short-code-nginx   bitnami/nginx:1.25.5-debian-12-r0   app.kubernetes.io/instance=nginx-fastapi,app.kubernetes.io/name=fastapi-short-code-nginx

helm应用查看

1
2
3
4
5
➜  ~ helm ls
NAME            NAMESPACE       REVISION        UPDATED                                 STATUS          CHART                           APP VERSION
nginx-fastapi   default         1               2024-05-26 17:59:04.017599 +0800 CST    deployed        fastapi-short-code-nginx-0.1.0  1.16.0
shortcode       default         1               2024-05-26 17:40:19.987909 +0800 CST    deployed        fastapi-short-code-0.1.0        1.16.0

参考