使用 Kubernetes 部署 Streamlit
简介
你有一个很棒的应用,想开始与其他人分享,该怎么办?你有几种选择。首先,你想在哪里运行你的 Streamlit 应用,以及如何访问它?
- 在你的公司网络上 - 大多数公司网络对外部世界是封闭的。你通常使用 VPN 登录公司网络并访问其中的资源。出于安全原因,你可以在公司网络中的服务器上运行 Streamlit 应用,以确保只有公司内部人员可以访问它。
- 在云端 - 如果你想从公司网络外部访问你的 Streamlit 应用,或者与家庭网络或笔记本电脑外部的人分享你的应用,你可能会选择这个选项。在这种情况下,将取决于你的托管服务提供商。我们有来自 Heroku、AWS 和其他提供商的社区贡献指南。
无论你决定在哪里部署你的应用,你首先需要将其容器化。本指南将引导你使用 Kubernetes 部署你的应用。如果你喜欢 Docker,请参阅使用 Docker 部署 Streamlit。
先决条件
安装 Docker Engine
如果你还没有这样做,请在你的服务器上安装Docker。Docker 为许多 Linux 发行版提供了 .deb
和 .rpm
包,包括
通过运行 hello-world
Docker 镜像来验证 Docker Engine 是否已正确安装
sudo docker run hello-world
提示
遵循 Docker 官方的Linux 安装后步骤,以非 root 用户身份运行 Docker,这样你就无需在 docker
命令前加上 sudo
。
安装 gcloud CLI
在本指南中,我们将使用 Kubernetes 编排 Docker 容器,并将 Docker 镜像托管在 Google Container Registry (GCR) 上。由于 GCR 是 Google 支持的 Docker 注册表,我们需要将 gcloud
注册为 Docker 凭据助手。
遵循官方文档安装 gcloud CLI 并进行初始化。
创建一个 Docker 容器
我们需要创建一个包含所有依赖项和应用程序代码的 Docker 容器。您可以在下面看到入口点(即容器启动时运行的命令)和 Dockerfile 定义。
创建一个入口点脚本
创建一个包含以下内容的 run.sh
脚本
#!/bin/bash APP_PID= stopRunningProcess() { # Based on https://linuxconfig.org/how-to-propagate-a-signal-to-child-processes-from-a-bash-script if test ! "${APP_PID}" = '' && ps -p ${APP_PID} > /dev/null ; then > /proc/1/fd/1 echo "Stopping ${COMMAND_PATH} which is running with process ID ${APP_PID}" kill -TERM ${APP_PID} > /proc/1/fd/1 echo "Waiting for ${COMMAND_PATH} to process SIGTERM signal" wait ${APP_PID} > /proc/1/fd/1 echo "All processes have stopped running" else > /proc/1/fd/1 echo "${COMMAND_PATH} was not started when the signal was sent or it has already been stopped" fi } trap stopRunningProcess EXIT TERM source ${VIRTUAL_ENV}/bin/activate streamlit run ${HOME}/app/streamlit_app.py & APP_ID=${!} wait ${APP_ID}
创建一个 Dockerfile
Docker 通过读取 Dockerfile
中的指令来构建镜像。Dockerfile
是一个文本文件,包含用户可以在命令行中调用来组装镜像的所有命令。在 Dockerfile 参考中了解更多信息。docker build
命令从 Dockerfile
构建镜像。docker run 命令首先在指定的镜像上创建一个容器,然后使用指定的命令启动它。
这是一个示例 Dockerfile
,你可以将其添加到你的目录的根目录。
FROM python:3.9-slim RUN groupadd --gid 1000 appuser \ && useradd --uid 1000 --gid 1000 -ms /bin/bash appuser RUN pip3 install --no-cache-dir --upgrade \ pip \ virtualenv RUN apt-get update && apt-get install -y \ build-essential \ software-properties-common \ git USER appuser WORKDIR /home/appuser RUN git clone https://github.com/streamlit/streamlit-example.git app ENV VIRTUAL_ENV=/home/appuser/venv RUN . ${VIRTUAL_ENV}/bin/activate && pip install -r app/requirements.txt EXPOSE 8501 COPY run.sh /home/appuser ENTRYPOINT ["./run.sh"]
重要
正如开发流程中所述,对于 Streamlit 1.10.0 及更高版本,Streamlit 应用无法从 Linux 发行版的根目录运行。你的主脚本应该位于根目录以外的目录中。如果你尝试从根目录运行 Streamlit 应用,Streamlit 将抛出 FileNotFoundError: [Errno 2] No such file or directory
错误。有关更多信息,请参阅 GitHub 问题#5239。
如果你使用的是 Streamlit 1.10.0 或更高版本,你必须将 WORKDIR
设置为根目录以外的目录。例如,你可以将 WORKDIR
设置为 /home/appuser
,如上面的示例 Dockerfile
所示。
构建 Docker 镜像
将上述文件(run.sh
和 Dockerfile
)放在同一文件夹中并构建 Docker 镜像
docker build --platform linux/amd64 -t gcr.io/$GCP_PROJECT_ID/k8s-streamlit:test .
重要
将上述命令中的 $GCP_PROJECT_ID
替换为你的 Google Cloud 项目名称。
将 Docker 镜像上传到容器注册表
下一步是将 Docker 镜像上传到容器注册表。在此示例中,我们将使用Google Container Registry (GCR)。首先启用 Container Registry API。登录 Google Cloud,导航到你的项目中的Container Registry,然后点击启用。
现在我们可以从上一步构建 Docker 镜像并将其推送到我们项目的 GCR。请务必将 docker push 命令中的 $GCP_PROJECT_ID
替换为你的项目名称
gcloud auth configure-docker docker push gcr.io/$GCP_PROJECT_ID/k8s-streamlit:test
创建一个 Kubernetes 部署
在此步骤中,你需要一个
- 正在运行的 Kubernetes 服务
- 可为其生成 TLS 证书的自定义域名
- 可配置自定义域名指向应用程序 IP 的 DNS 服务
由于镜像已在上一步上传到容器注册表,我们可以使用以下配置在 Kubernetes 中运行它。
安装并运行 Kubernetes
确保你的Kubernetes 客户端 kubectl
已安装并在你的机器上运行。
配置 Google OAuth 客户端和 oauth2-proxy
要配置 Google OAuth 客户端,请参阅Google Auth Provider。配置 oauth2-proxy 使用所需的OAuth Provider Configuration,并在 config map 中更新 oauth2-proxy 配置。
以下配置包含一个 oauth2-proxy sidecar 容器,它处理与 Google 的认证。你可以从oauth2-proxy repository中了解更多信息。
创建一个 Kubernetes 配置文件
创建一个名为 k8s-streamlit.yaml
的YAML配置文件
apiVersion: v1 kind: ConfigMap metadata: name: streamlit-configmap data: oauth2-proxy.cfg: |- http_address = "0.0.0.0:4180" upstreams = ["http://127.0.0.1:8501/"] email_domains = ["*"] client_id = "<GOOGLE_CLIENT_ID>" client_secret = "<GOOGLE_CLIENT_SECRET>" cookie_secret = "<16, 24, or 32 bytes>" redirect_url = <REDIRECT_URL> --- apiVersion: apps/v1 kind: Deployment metadata: name: streamlit-deployment labels: app: streamlit spec: replicas: 1 selector: matchLabels: app: streamlit template: metadata: labels: app: streamlit spec: containers: - name: oauth2-proxy image: quay.io/oauth2-proxy/oauth2-proxy:v7.2.0 args: ["--config", "/etc/oauth2-proxy/oauth2-proxy.cfg"] ports: - containerPort: 4180 livenessProbe: httpGet: path: /ping port: 4180 scheme: HTTP readinessProbe: httpGet: path: /ping port: 4180 scheme: HTTP volumeMounts: - mountPath: "/etc/oauth2-proxy" name: oauth2-config - name: streamlit image: gcr.io/GCP_PROJECT_ID/k8s-streamlit:test imagePullPolicy: Always ports: - containerPort: 8501 livenessProbe: httpGet: path: /_stcore/health port: 8501 scheme: HTTP timeoutSeconds: 1 readinessProbe: httpGet: path: /_stcore/health port: 8501 scheme: HTTP timeoutSeconds: 1 resources: limits: cpu: 1 memory: 2Gi requests: cpu: 100m memory: 745Mi volumes: - name: oauth2-config configMap: name: streamlit-configmap --- apiVersion: v1 kind: Service metadata: name: streamlit-service spec: type: LoadBalancer selector: app: streamlit ports: - name: streamlit-port protocol: TCP port: 80 targetPort: 4180
重要
虽然上述配置可以照搬,但你需要自己配置 oauth2-proxy
并使用正确的 GOOGLE_CLIENT_ID
、GOOGLE_CLIENT_ID
、GCP_PROJECT_ID
和 REDIRECT_URL
。
现在使用 kubectl create
命令在 Kubernetes 中从文件创建配置
kubctl create -f k8s-streamlit.yaml
设置 TLS 支持
由于你正在使用 Google 认证,你需要设置 TLS 支持。请在TLS Configuration中了解具体方法。
验证部署
部署和服务创建后,我们需要等待几分钟,以便公共 IP 地址可用。我们可以通过运行以下命令检查何时准备就绪
kubectl get service streamlit-service -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
分配公共 IP 后,你需要在 DNS 服务中配置一个指向上述 IP 地址的 A record
。
还有问题吗?
我们的 论坛 提供了许多有用的信息和 Streamlit 专家。