单Ubuntu VM搭建K8s集群部署Angular+Express+Mongo应用方案
Ubuntu虚拟机K8s集群搭建实操指南(Angular+Express+MongoDB栈)
集群前置准备
- 虚拟机配置:至少分配2核CPU、4G内存、50G系统盘,网卡设置为桥接模式,确保虚拟机和实验室内网其他机器在同一网段,可直接通过内网IP互通
- 系统配置:提前关闭swap,执行
sudo swapoff -a && sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab,配置内网NTP时间同步,避免后续SSO token校验、数据库交互出时间差问题 - 集群选型:实验室小规模场景优先用k3s,资源占用仅为原生K8s的30%左右,自带containerd运行时和Flannel网络插件,安装完即可用,省去kubeadm部署的大量排错成本。安装时添加
--tls-san 你的虚拟机内网IP --node-ip 你的虚拟机内网IP参数,确保内网访问apiserver证书可信、节点流量走内网网卡。 - 安装完成后将k3s生成的kubeconfig拷贝到用户目录,执行
kubectl get nodes验证节点状态为Ready即可开始部署应用。
第一步:创建隔离命名空间
执行命令创建独立命名空间,避免和集群系统资源混用:
kubectl create namespace lab-app
第二步:创建MongoDB持久化存储
k3s自带local-path存储类,无需额外部署存储服务,直接创建PVC即可满足本地持久化需求:
# mongo-pvc.yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: mongo-pvc namespace: lab-app spec: accessModes: - ReadWriteOnce resources: requests: storage: 20Gi # 按实际数据量调整 storageClassName: local-path
执行kubectl apply -f mongo-pvc.yaml完成创建。
第三步:创建敏感信息Secret
禁止将数据库密码、SSO密钥等敏感信息明文写在Deployment配置中,先创建Secret统一存储:
kubectl create secret generic lab-app-secrets -n lab-app \ --from-literal=mongo-root-password=你设置的MongoDB管理员密码 \ --from-literal=sso-client-secret=你的组织SSO客户端密钥
第四步:核心业务资源Manifest
共包含3个Deployment、3个Service,其中数据库服务仅集群内可访问,前端、API服务通过NodePort暴露,可直接通过虚拟机内网IP访问。
MongoDB 部署+集群内Service
# mongo-deploy-svc.yaml apiVersion: apps/v1 kind: Deployment metadata: name: mongo namespace: lab-app spec: replicas: 1 selector: matchLabels: app: mongo template: metadata: labels: app: mongo spec: containers: - name: mongo image: mongo:6.0 ports: - containerPort: 27017 env: - name: MONGO_INITDB_ROOT_USERNAME value: "admin" - name: MONGO_INITDB_ROOT_PASSWORD valueFrom: secretKeyRef: name: lab-app-secrets key: mongo-root-password volumeMounts: - name: mongo-data mountPath: /data/db resources: # 资源限制,避免占满整机资源 requests: cpu: "500m" memory: "1Gi" limits: cpu: "1" memory: "2Gi" volumes: - name: mongo-data persistentVolumeClaim: claimName: mongo-pvc --- apiVersion: v1 kind: Service metadata: name: mongo-svc namespace: lab-app spec: type: ClusterIP # 仅集群内访问,不对外暴露 selector: app: mongo ports: - port: 27017 targetPort: 27017
Express API 部署+NodePort Service
# express-deploy-svc.yaml apiVersion: apps/v1 kind: Deployment metadata: name: express-api namespace: lab-app spec: replicas: 2 # 按需调整副本数 selector: matchLabels: app: express-api template: metadata: labels: app: express-api spec: containers: - name: express-api image: 你的Express业务镜像地址:版本号 # 替换为自己打包的镜像 ports: - containerPort: 3000 env: - name: MONGO_URI value: "mongodb://admin:$(MONGO_PASSWORD)@mongo-svc:27017/你的业务库名?authSource=admin" - name: MONGO_PASSWORD valueFrom: secretKeyRef: name: lab-app-secrets key: mongo-root-password - name: SSO_CLIENT_SECRET valueFrom: secretKeyRef: name: lab-app-secrets key: sso-client-secret - name: SSO_ENTRY value: "你的组织SSO登录地址" - name: SSO_CALLBACK value: "http://你的虚拟机内网IP:30100/api/auth/callback" resources: requests: cpu: "200m" memory: "512Mi" limits: cpu: "500m" memory: "1Gi" --- apiVersion: v1 kind: Service metadata: name: express-api-svc namespace: lab-app spec: type: NodePort selector: app: express-api ports: - port: 3000 targetPort: 3000 nodePort: 30100 # 固定端口,内网通过IP:30100访问API
Angular前端 部署+NodePort Service
注意:Angular代码打包时,需要将API请求基地址配置为http://你的虚拟机内网IP:30100/api,避免前端请求跨域或地址错误
# angular-deploy-svc.yaml apiVersion: apps/v1 kind: Deployment metadata: name: angular-frontend namespace: lab-app spec: replicas: 2 selector: matchLabels: app: angular-frontend template: metadata: labels: app: angular-frontend spec: containers: - name: angular-frontend image: 你的Angular前端镜像地址:版本号 # 替换为自己打包的镜像,用nginx托管静态文件即可 ports: - containerPort: 80 resources: requests: cpu: "100m" memory: "128Mi" limits: cpu: "200m" memory: "256Mi" --- apiVersion: v1 kind: Service metadata: name: angular-frontend-svc namespace: lab-app spec: type: NodePort selector: app: angular-frontend ports: - port: 80 targetPort: 80 nodePort: 30080 # 固定端口,内网通过IP:30080访问前端页面
第五步:拉起所有资源
将所有yaml文件放在同一目录,执行命令一键部署:
kubectl apply -f .
执行kubectl get pods -n lab-app查看所有Pod状态,全部为Running后,即可在内网任意机器通过http://你的虚拟机内网IP:30080访问前端页面。
SSO对接说明
实验室场景不需要部署集群级SSO组件,直接在Express服务层集成即可:
- 按你用的组织SSO协议(一般是OIDC2.0、CAS2.0)引入对应SDK,回调地址和Service里配置的30100端口回调路径保持一致,且和SSO后台登记的回调地址完全匹配(包括http/https前缀、端口,不能有偏差)
- 登录态建议用HttpOnly Cookie存储,配置跨域规则时将前端地址
http://你的虚拟机内网IP:30080加入允许源列表,Cookie的SameSite属性设置为Lax,避免跨站请求无法携带Cookie - 如果SSO需要证书校验,将证书文件创建为Secret挂载到Express容器,不要把证书明文打进镜像。
部署注意事项
- 网络连通性排查:如果内网无法访问30080、30100端口,先检查Ubuntu的ufw防火墙是否开放对应端口,执行
sudo ufw allow 30080/tcp && sudo ufw allow 30100/tcp放通端口,同时确认实验室上层交换机没有做端口隔离 - 镜像拉取问题:如果用私有镜像仓库,需要先创建镜像拉取Secret配置到Deployment的
imagePullSecrets字段;如果是本地打包的镜像,导出为tar包后用ctr -n k8s.io images import 镜像包.tar导入到k3s的containerd运行时即可 - 数据备份:MongoDB的数据默认存在k3s节点的
/var/lib/rancher/k3s/storage目录下,定期备份对应PVC的目录,不要随意删除PVC资源,避免数据丢失 - 日志排查:服务启动失败时优先用
kubectl logs -n lab-app Pod名看容器日志,镜像路径错误、环境变量配置不对、数据库连接串错误是最常见的启动失败原因 - 后续扩容:如果后续服务访问量变大,直接调整对应Deployment的replicas副本数即可,Service会自动做流量负载,不需要额外配置
- 安全配置:实验室环境也不要把数据库、SSO密钥这类配置明文提交到代码仓库,Secret资源可以单独备份,不要和业务代码存在同一个仓库
内容的提问来源于stack exchange,提问作者user14068266
相关产品推荐
相关产品推荐

