Deploy Streamlit using Kubernetes

所以,你有一个很棒的应用,你想开始与其他人分享它,你该怎么做?你有几个选择。首先,你想在哪里运行你的Streamlit应用,以及你想如何访问它?

  • 在您的企业网络上 - 大多数企业网络对外部世界是封闭的。您通常使用VPN登录到您的企业网络并访问那里的资源。出于安全原因,您可以在企业网络中的服务器上运行您的Streamlit应用程序,以确保只有公司内部的人员可以访问它。
  • 在云端 - 如果您希望从公司网络外部访问您的Streamlit应用程序,或者与家庭网络或笔记本电脑外部的人员共享您的应用程序,您可能会选择此选项。在这种情况下,这将取决于您的主机提供商。我们有来自Heroku、AWS和其他提供商的社区提交的指南

无论您决定在哪里部署您的应用程序,您首先需要将其容器化。本指南将引导您使用Kubernetes部署您的应用程序。如果您更喜欢使用Docker,请参阅使用Docker部署Streamlit

  1. 安装 Docker 引擎
  2. 安装 gcloud CLI

如果您还没有这样做,请在您的服务器上安装Docker。Docker 提供了许多 Linux 发行版的 .deb.rpm 包,包括:

通过运行hello-world Docker 镜像来验证 Docker Engine 是否正确安装:

sudo docker run hello-world
star

提示

按照Docker官方的Linux安装后步骤以非root用户身份运行Docker,这样你就不必在docker命令前加上sudo

在本指南中,我们将使用Kubernetes编排Docker容器,并在Google Container Registry (GCR)上托管Docker镜像。由于GCR是Google支持的Docker注册表,我们需要将gcloud注册为Docker凭证助手。

按照官方文档安装gcloud CLI并初始化它。

我们需要创建一个包含所有依赖项和应用程序代码的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}

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 virtualenv ${VIRTUAL_ENV} RUN . ${VIRTUAL_ENV}/bin/activate && pip install -r app/requirements.txt EXPOSE 8501 COPY run.sh /home/appuser ENTRYPOINT ["./run.sh"]
priority_high

重要

开发流程中所述,对于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 所示。

将上述文件(run.shDockerfile)放在同一个文件夹中并构建 Docker 镜像:

docker build --platform linux/amd64 -t gcr.io/$GCP_PROJECT_ID/k8s-streamlit:test .
priority_high

重要

将上述命令中的$GCP_PROJECT_ID替换为您的Google Cloud项目名称。

下一步是将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服务
  • 您可以为其生成TLS证书的自定义域名
  • DNS服务,您可以在其中配置自定义域名以指向应用程序IP

由于图像已在上一步上传到容器注册表,我们可以使用以下配置在Kubernetes中运行它。

确保您的Kubernetes客户端kubectl,已安装并在您的机器上运行。

要配置Google OAuth客户端,请参阅Google Auth Provider。配置oauth2-proxy以使用所需的OAuth Provider Configuration,并在配置映射中更新oath2-proxy配置。

以下配置包含一个处理与Google认证的ouath2-proxy sidecar容器。您可以从oauth2-proxy repository了解更多信息。

创建一个名为 k8s-streamlit.yamlYAML 配置文件

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
priority_high

重要

虽然上述配置可以逐字复制,但您需要自己配置oauth2-proxy并使用正确的GOOGLE_CLIENT_IDGOOGLE_CLIENT_IDGCP_PROJECT_IDREDIRECT_URL

现在使用kubectl create命令从Kubernetes中的文件创建配置:

kubctl create -f k8s-streamlit.yaml

由于您正在使用Google身份验证,您需要设置TLS支持。请参阅TLS配置了解如何操作。

一旦部署和服务创建完成,我们需要等待几分钟,直到公共IP地址可用。我们可以通过运行以下命令来检查何时准备就绪:

kubectl get service streamlit-service -o jsonpath='{.status.loadBalancer.ingress[0].ip}'

分配公网IP后,您需要在DNS服务中配置一个指向上述IP地址的A记录

forum

还有问题吗?

我们的 论坛 充满了有用的信息和Streamlit专家。