文章

LLM 加持下生成 Kubernetes YAML 文件探索

需求

以下适合使用Kubernetes工具管理容器化应用,如果你使用Docker工具管理,可跳过。

部署一些主流的应用,如:MySQL、Redis、Jenkins等,都可以使用Helm等package工具进行快速的部署到K8S环境中。

在我上一篇文章《快速搭建本地大语言模型和知识库》中,关于 AnythingLLM 的部署中,官方只提供了 Docker 的部署方式,如何快速地将其部署到 K8S 环境中,并统一管理起来。

如下是大致的流程:

image-20240328143148777

注意:这里可以灵活的根据自己的需求,调整你的Prompt,来部署满足个人需求的 K8S Manifests Yaml文件。

使用 LLM 生成初稿

ChatGPT 4

Inputs:

 请将如下docker命令脚本转换成Kubernetes Yaml文件,至少需要包含deployment、service以及pvc等文件,如下是docker运行脚本:
 export STORAGE_LOCATION=$HOME/Documents/data/anythingllm && \
 mkdir -p $STORAGE_LOCATION && \
 touch "$STORAGE_LOCATION/.env" && \
 docker run -d -p 3001:3001 \
 --cap-add SYS_ADMIN \
 -v ${STORAGE_LOCATION}:/app/server/storage \
 -v ${STORAGE_LOCATION}/.env:/app/server/.env \
 -e STORAGE_DIR="/app/server/storage" \
 mintplexlabs/anythingllm

Outputs:

这是一个基本的转换,你可能需要根据你的实际需求进行调整。请注意,Kubernetes并不直接支持Docker的--cap-add选项,因此我省略了这一部分。

以下是一个基本的Kubernetes YAML文件示例,包含了Deployment、Service和PersistentVolumeClaim。

 apiVersion: v1
 kind: PersistentVolumeClaim
 metadata:
   name: storage-pvc
 spec:
   accessModes:
     - ReadWriteOnce
   resources:
     requests:
       storage: 1Gi
 ​
 ---
 apiVersion: apps/v1
 kind: Deployment
 metadata:
   name: anythingllm-deployment
 spec:
   replicas: 1
   selector:
     matchLabels:
       app: anythingllm
   template:
     metadata:
       labels:
         app: anythingllm
     spec:
       containers:
       - name: anythingllm
         image: mintplexlabs/anythingllm
         ports:
         - containerPort: 3001
         env:
         - name: STORAGE_DIR
           value: "/app/server/storage"
         volumeMounts:
         - name: storage-volume
           mountPath: /app/server/storage
       volumes:
       - name: storage-volume
         persistentVolumeClaim:
           claimName: storage-pvc
 ​
 ---
 apiVersion: v1
 kind: Service
 metadata:
   name: anythingllm-service
 spec:
   selector:
     app: anythingllm
   ports:
     - protocol: TCP
       port: 80
       targetPort: 3001

这个YAML文件首先定义了一个PersistentVolumeClaim,然后定义了一个Deployment,其中包含了一个容器,这个容器使用了之前定义的PersistentVolumeClaim作为存储卷。最后,定义了一个Service,用于暴露Deployment。

注意,这个YAML文件假设你的Kubernetes集群有一个默认的StorageClass。如果没有,你可能需要定义一个PersistentVolume来满足PersistentVolumeClaim的需求。

此外,这个YAML文件没有处理.env文件,因为Kubernetes通常使用ConfigMap或Secret来处理这种情况。你可能需要创建一个ConfigMap或Secret,并将其挂载到容器中的/app/server/.env。

本地模型 codellama 7b

Inputs:

 Please convert the following docker command script into a Kubernetes Yaml file, including at least deployment, service and pvc files. The following is the docker run script. export STORAGE_LOCATION=$HOME/Documents/data/anythingllm &&
 mkdir -p $STORAGE_LOCATION &&
 touch “$STORAGE_LOCATION/.env” &&
 docker run -d -p 3001:3001
 –cap-add SYS_ADMIN
 -v ${STORAGE_LOCATION}:/app/server/storage
 -v ${STORAGE_LOCATION}/.env:/app/server/.env
 -e STORAGE_DIR=“/app/server/storage”
 mintplexlabs/anythingllm

Outputs:

Here is a sample Kubernetes YAML file that includes the deployment, service, and PVC (Persistent Volume Claim) files for the provided Docker command script:

 # Deployment.yaml
 apiVersion: apps/v1
 kind: Deployment
 metadata:
   name: anythingllm-deployment
 spec:
   replicas: 1
   selector:
     matchLabels:
       app: anythingllm
   template:
     metadata:
       labels:
         app: anythingllm
     spec:
       containers:
       - name: anythingllm
         image: mintplexlabs/anythingllm
         ports:
         - containerPort: 3001
         volumeMounts:
         - name: storage-volume
           mountPath: /app/server/storage
         - name: env-volume
           mountPath: /app/server/.env
         securityContext:
           capabilities:
             add:
               - SYS_ADMIN
       volumes:
       - name: storage-volume
         persistentVolumeClaim:
           claimName: anythingllm-pvc
       - name: env-volume
         configMap:
           name: anythingllm-env
 ​
 # Service.yaml
 apiVersion: v1
 kind: Service
 metadata:
   name: anythingllm-service
 spec:
   selector:
     app: anythingllm
   ports:
   - protocol: TCP
     port: 3001
     targetPort: 3001
 ​
 # PersistentVolumeClaim.yaml
 apiVersion: v1
 kind: PersistentVolumeClaim
 metadata:
   name: anythingllm-pvc
 spec:
   accessModes:
     - ReadWriteOnce
   resources:
     requests:
       storage: 1Gi

Note that this is just a sample YAML file, and you may need to modify it based on your specific use case. Additionally, you will need to create a ConfigMap with the name "anythingllm-env" that contains the ".env" file content.

文言一心

Inputs:

同 ChatGPT 4。

Outputs:

要将Docker命令转换为Kubernetes YAML文件,我们需要定义DeploymentService以及PersistentVolumeClaim (PVC)资源。以下是根据你提供的Docker命令转换的Kubernetes YAML文件示例:

PersistentVolumeClaim (PVC) YAML 文件 (pvc.yaml):

 apiVersion: v1
 kind: PersistentVolumeClaim
 metadata:
   name: anythingllm-storage
 spec:
   accessModes:
     - ReadWriteOnce
   storageClassName: standard # 请根据你的集群环境设置合适的存储类名
   resources:
     requests:
       storage: 1Gi # 你可以根据需要调整存储大小

Deployment YAML 文件 (deployment.yaml):

 apiVersion: apps/v1
 kind: Deployment
 metadata:
   name: anythingllm-deployment
 spec:
   replicas: 1
   selector:
     matchLabels:
       app: anythingllm
   template:
     metadata:
       labels:
         app: anythingllm
     spec:
       containers:
         - name: anythingllm
           image: mintplexlabs/anythingllm
           imagePullPolicy: IfNotPresent
           ports:
             - containerPort: 3001
           env:
             - name: STORAGE_DIR
               value: "/app/server/storage"
           volumeMounts:
             - name: storage-volume
               mountPath: /app/server/storage
             - name: env-volume
               mountPath: /app/server/.env
               subPath: .env
       volumes:
         - name: storage-volume
           persistentVolumeClaim:
             claimName: anythingllm-storage
         - name: env-volume
           emptyDir: {} # 假设.env文件为空或者可以由容器内创建,这里使用emptyDir
       securityContext:
         capabilities:
           add: ["SYS_ADMIN"]

Service YAML 文件 (service.yaml):

 apiVersion: v1
 kind: Service
 metadata:
   name: anythingllm-service
 spec:
   selector:
     app: anythingllm
   ports:
     - protocol: TCP
       port: 3001
       targetPort: 3001
   type: NodePort # 假设你希望服务可以从集群外部访问,使用NodePort;如果仅在集群内部使用,可以使用ClusterIP

注意:

  1. 上面的PVC配置假定你的Kubernetes集群有一个名为standard的存储类。你需要根据实际的存储类名称替换standard

  2. 对于.env文件的挂载,这里我使用了emptyDir,因为.env文件在Docker命令中只是被创建了一个空文件。如果.env文件包含特定的配置,你需要以某种方式将其内容注入到容器中(例如通过ConfigMap或者Secret)。

  3. SYS_ADMIN权限的使用可能具有安全风险,并可能不被集群管理员允许。如果可能,最好避免使用SYS_ADMIN权限,或者与集群管理员讨论如何安全地提供所需的功能。

  4. 在实际部署之前,请确保你的Kubernetes集群已配置好网络插件,且可以访问mintplexlabs/anythingllm镜像。

  5. 请根据你的实际环境调整YAML文件中的资源请求、存储类、端口类型等。

  6. 在部署之前,你还需要先创建PVC (kubectl apply -f pvc.yaml),然后再创建Deployment和Service。

请根据你的具体需求和环境对上述YAML文件进行相应的调整。

人工微调

因为是本地进行部署,对volumes和securityContext元素进行调整。

调整后的 test.yaml 文件如下:

 apiVersion: apps/v1
 kind: Deployment
 metadata:
   name:  anythingllm
   namespace: aigc
   labels:
     app:  anythingllm
 spec:
   selector:
     matchLabels:
       app: anythingllm
   replicas: 1
   template:
     metadata:
       labels:
         app:  anythingllm
     spec:
       containers:
       - name:  anythingllm
         image:  mintplexlabs/anythingllm:latest
         imagePullPolicy: IfNotPresent
         securityContext:
           capabilities:
             add:
               - SYS_ADMIN
         ports:
         - containerPort:  3001
           name:  anythingllm
         env:  
         - name: STORAGE_DIR  
           value: "/app/server/storage"
         volumeMounts:
         - name: storage-dir
           mountPath: /app/server/storage
         - name: env-file
           mountPath: /app/server/.env
       volumes:
         - name: storage-dir
           hostPath:
             path: /Users/eric/anythingllm/
             type: DirectoryOrCreate
         - name: env-file
           hostPath:
             path: /Users/eric/anythingllm/.env
             type: FileOrCreate
 ​
 ---
 ​
 apiVersion: v1
 kind: Service
 metadata:
   name: anythingllm
   namespace: aigc
 spec:
   selector:
     app: anythingllm
   type: ClusterIP
   ports:
   - name: anythingllm
     port: 3001
     targetPort: 3001     

执行如下命令执行成功后,即可通过http://localhost:3001访问,并且通过Kubernetes来管理pod。

 kubectl create namespace aigc
 kubectl apply -f test.yaml
 kubectl port-forward service/anythingllm 3001:3001 -n aigc

往往有时通过 LLM 生成的 Yaml 脚本是有问题或者不符合 K8S version版本的,这里介绍如何通过工具进行快速调整:

  1. K8S 官网(https://kubernetes.io/docs/concepts)和 kubectl explain

 kubectl explain deployment.spec.template.spec.containers
  1. VS Code 插件:YamlKubernetes Templates

输入 k8s 会自动弹出如下模板:

image-20240328162926067

选择 k8sDeployment 后,会帮你生成如下:

   apiVersion: apps/v1
 kind: Deployment
 metadata:
   name:  MYAPP
   namespace: default
   labels:
     app:  MYAPP
 spec:
   selector:
     matchLabels:
       app: MYAPP
   replicas: 1
   strategy:
     rollingUpdate:
       maxSurge: 25%
       maxUnavailable: 25%
     type: RollingUpdate
   template:
     metadata:
       labels:
         app:  MYAPP
     spec:
       # initContainers:
         # Init containers are exactly like regular containers, except:
           # - Init containers always run to completion.
           # - Each init container must complete successfully before the next one starts.
       containers:
       - name:  MYAPP
         image:  MYAPP:latest
         resources:
           requests:
             cpu: 100m
             memory: 100Mi
           limits:
             cpu: 100m
             memory: 100Mi
         livenessProbe:
           tcpSocket:
             port: 80
           initialDelaySeconds: 5
           timeoutSeconds: 5
           successThreshold: 1
           failureThreshold: 3
           periodSeconds: 10
         readinessProbe:
           httpGet:
             path: /_status/healthz
             port: 80
           initialDelaySeconds: 5
           timeoutSeconds: 2
           successThreshold: 1
           failureThreshold: 3
           periodSeconds: 10
         env:
         - name: DB_HOST
           valueFrom:
             configMapKeyRef:
               name: MYAPP
               key: DB_HOST
         ports:
         - containerPort:  80
           name:  MYAPP
         volumeMounts:
         - name: localtime
           mountPath: /etc/localtime
       volumes:
         - name: localtime
           hostPath:
             path: /usr/share/zoneinfo/Asia/Shanghai
       restartPolicy: Always

以上就能够快速地准备好 k8s manifest 文件,并将其部署和验证。当然 LLM 和 Kubernetes Templates 插件生成的都是基础的文件,一些高级的参数配置还需要参考官网。

License:  CC BY 4.0