Deploy Streamlit using Kubernetes
Introduction
所以,你有一个很棒的应用,你想开始与其他人分享它,你该怎么做?你有几个选择。首先,你想在哪里运行你的Streamlit应用,以及你想如何访问它?
- 在您的企业网络上 - 大多数企业网络对外部世界是封闭的。您通常使用VPN登录到您的企业网络并访问那里的资源。出于安全原因,您可以在企业网络中的服务器上运行您的Streamlit应用程序,以确保只有公司内部的人员可以访问它。
- 在云端 - 如果您希望从公司网络外部访问您的Streamlit应用程序,或者与家庭网络或笔记本电脑外部的人员共享您的应用程序,您可能会选择此选项。在这种情况下,这将取决于您的主机提供商。我们有来自Heroku、AWS和其他提供商的社区提交的指南。
无论您决定在哪里部署您的应用程序,您首先需要将其容器化。本指南将引导您使用Kubernetes部署您的应用程序。如果您更喜欢使用Docker,请参阅使用Docker部署Streamlit。
Prerequisites
Install Docker Engine
如果您还没有这样做,请在您的服务器上安装Docker。Docker 提供了许多 Linux 发行版的 .deb
和 .rpm
包,包括:
通过运行hello-world
Docker 镜像来验证 Docker Engine 是否正确安装:
sudo docker run hello-world
提示
按照Docker官方的Linux安装后步骤以非root用户身份运行Docker,这样你就不必在docker
命令前加上sudo
。
Install the gcloud CLI
在本指南中,我们将使用Kubernetes编排Docker容器,并在Google Container Registry (GCR)上托管Docker镜像。由于GCR是Google支持的Docker注册表,我们需要将gcloud
注册为Docker凭证助手。
按照官方文档安装gcloud CLI并初始化它。
Create a Docker container
我们需要创建一个包含所有依赖项和应用程序代码的docker容器。下面你可以看到入口点,即容器启动时运行的命令,以及Dockerfile的定义。
Create an entrypoint script
创建一个包含以下内容的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}
Create a 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 virtualenv ${VIRTUAL_ENV}
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
所示。
Build a Docker image
将上述文件(run.sh
和 Dockerfile
)放在同一个文件夹中并构建 Docker 镜像:
docker build --platform linux/amd64 -t gcr.io/$GCP_PROJECT_ID/k8s-streamlit:test .
重要
将上述命令中的$GCP_PROJECT_ID
替换为您的Google Cloud项目名称。
Upload the Docker image to a container registry
下一步是将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
Create a Kubernetes deployment
在这一步,你将需要:
- 运行Kubernetes服务
- 您可以为其生成TLS证书的自定义域名
- DNS服务,您可以在其中配置自定义域名以指向应用程序IP
由于图像已在上一步上传到容器注册表,我们可以使用以下配置在Kubernetes中运行它。
Install and run Kubernetes
确保您的Kubernetes客户端,kubectl
,已安装并在您的机器上运行。
Configure a Google OAuth Client and oauth2-proxy
要配置Google OAuth客户端,请参阅Google Auth Provider。配置oauth2-proxy以使用所需的OAuth Provider Configuration,并在配置映射中更新oath2-proxy配置。
以下配置包含一个处理与Google认证的ouath2-proxy sidecar容器。您可以从oauth2-proxy repository了解更多信息。
Create a Kubernetes configuration file
创建一个名为 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
Set up TLS support
由于您正在使用Google身份验证,您需要设置TLS支持。请参阅TLS配置了解如何操作。
Verify the deployment
一旦部署和服务创建完成,我们需要等待几分钟,直到公共IP地址可用。我们可以通过运行以下命令来检查何时准备就绪:
kubectl get service streamlit-service -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
分配公网IP后,您需要在DNS服务中配置一个指向上述IP地址的A记录
。
还有问题吗?
我们的 论坛 充满了有用的信息和Streamlit专家。