有个微信小程序的后端服务,原来托管在阿里云上,现在希望做成微服务发布在k8s上。
1.配置 nginx 容器,转发HTTPS 请求(配置有SSL证书)到k8s
docker run -d --name nginx -p 8081:8081 -v /mnt/nginx/conf.d:/etc/nginx/conf.d -v /mnt/nginx/certs:/etc/nginx/certs nginx:alpine
在 /mnt/nginx/certs 目录下放置SSL证书

在 /mnt/nginx/conf.d 目录下放置nginx配置文件

server { listen 8081 ssl; server_name 92it.top www.92it.top; # 同时支持两种域名访问 # 允许最大上传文件大小为 100MB client_max_body_size 100M; client_body_buffer_size 256k; # 代理超时配置 proxy_connect_timeout 120s; # 连接后端服务器的超时时间 proxy_send_timeout 300s; # 向后端服务器发送请求的超时时间 proxy_read_timeout 600s; # 从后端服务器读取响应的超时时间(关键参数) # SSL 证书配置 ssl_certificate /etc/nginx/certs/ssl-cert.pem; ssl_certificate_key /etc/nginx/certs/ssl-cert.key; # 转发所有请求到目标主机 location / { proxy_pass http://123.56.xxx.xxx:30080; 转发所有请求到这个ip地址 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # 可选:保留所有请求头部(包括非标准字段) proxy_pass_request_headers on; } }
2.在k8s 通过 kubectl 命令 做成pv
在 Kubernetes(K8S)里,PV(Persistent Volume,持久卷 )和 PVC(PersistentVolumeClaim,持久卷声明 )是实现容器持久化存储的核心概念,用于解耦存储资源的 “供给” 和 “使用”。
- 定义:PV 是集群里的一块网络存储资源,由管理员创建或通过存储类动态创建,独立于 Pod 存在,可看作集群级别的 “存储资源池” 。
类比:把 PV 想成 “共享硬盘”,提前接入 K8S 集群,供 Pod 按需使用。 - 作用:
- 抽象底层存储细节(不管是云厂商存储、NFS、iSCSI 还是本地存储,对用户统一暴露为 PV )。
- 作为 “公共存储资源”,被多个 Pod 共享或独占,生命周期独立于单个 Pod。
- 关键属性:
- 容量:如
10Gi
,指定存储大小。 - 访问模式:
ReadWriteOnce(RWO)
:只能被单个节点以读写方式挂载。ReadOnlyMany(ROX)
:可被多个节点以只读方式挂载。ReadWriteMany(RWX)
:可被多个节点以读写方式挂载(需存储后端支持,如 NFS )。
- 存储类别(StorageClass):关联存储类,用于动态创建 PV 时选择存储后端。
- 回收策略:PV 释放后如何处理(如
Retain
保留数据、Delete
删除数据、Recycle
清理数据 )。
- 容量:如
# kubectl apply -f persistent-volume.yaml # 无需指定命名空间 apiVersion: v1 kind: PersistentVolume metadata: name: wechat-pv spec: capacity: storage: 1Gi volumeMode: Filesystem accessModes: - ReadWriteMany # 多节点读写 persistentVolumeReclaimPolicy: Retain storageClassName: manual hostPath: path: "/Users/xxx/Documents/k8s/pv/wechat" # 宿主机路径 type: DirectoryOrCreate # 若目录不存在则创建

在这个 PersistentVolume (PV) 配置中,hostPath.path
字段定义的是 宿主机(Kubernetes 节点)上的物理路径,即 PV 实际存储数据的位置。具体来说:
path: "/Users/xxx/Documents/k8s/pv/wechat"
的含义
- 宿主机路径:该路径指向 Kubernetes 节点(运行 Pod 的物理机或虚拟机)上的一个目录。当 Pod 通过 PVC 挂载这个 PV 时,容器内的数据会被实际存储到宿主机的
/data/volumes/my-pv
目录中。 - 数据持久化:即使 Pod 被删除或迁移到其他节点,只要新节点上存在相同的
hostPath
路径,数据就可以被重新挂载,从而实现持久化存储。
在 PersistentVolume(PV)中使用 hostPath
类型时,path
字段是必须指定的,它用于明确宿主机上存储数据的具体位置。
- 核心功能需求:
hostPath
的本质是将宿主机的本地路径映射到 PV,因此必须明确指定宿主机上的目标路径,否则 PV 无法确定数据存储位置。 - 配置合法性:Kubernetes 会校验 PV 配置的完整性,缺少
path
会导致配置无效,无法创建 PV。
在使用 kubectl apply -f pv.yaml
时,不需要指定 namespace
,因为 PersistentVolume (PV) 是集群级资源,不属于任何命名空间。而 PersistentVolumeClaim (PVC) 是命名空间级资源,需要在特定命名空间中创建。
资源类型 | 是否需要指定命名空间 | 原因 |
---|---|---|
PersistentVolume | ❌ 不需要 | 集群级资源,全局可见,不隶属于任何命名空间。 |
PersistentVolumeClaim | ✅ 需要 | 命名空间级资源,必须在某个命名空间中创建,默认在 default 命名空间。 |
PV 与 PVC 的绑定:PVC 只能绑定到访问模式和存储类匹配的 PV,且 PV 的容量必须 ≥ PVC 请求的容量。命名空间不影响绑定逻辑,但 PVC 只能在其所在命名空间内被 Pod 引用。
# 查看所有 PV(无命名空间限制) kubectl get pv # 查看特定命名空间的 PVC kubectl get pvc -n my-namespace
3. kubectl 创建PVC
定义:PVC 是用户对存储资源的 “请求声明”,类似 Pod 对 CPU、内存的资源请求,描述 Pod 对存储的需求(要多大、以什么方式访问 )。
类比:PVC 是 “存储申请单”,用户填 “要 5Gi 存储、读写模式”,K8S 自动匹配 PV 满足需求。
- 作用:
- 解耦 Pod 与具体存储实现(Pod 只需声明 PVC,不用关心底层是 NFS 还是云存储 )。
- 让存储资源 “按需分配”,用户无需提前了解 PV 细节,只需提需求。
- 关键属性:
- 存储容量:如
5Gi
,请求需要的存储大小。 - 访问模式:与 PV 匹配(如
ReadWriteOnce
)。 - 存储类别:指定需要的存储类,用于动态创建 PV(若静态 PV 不足时 )。
- 标签选择器:通过标签匹配特定 PV(精细控制 PV 绑定 )。
- 存储容量:如
- 总结
- PV 是集群里的 “存储资源池”,由管理员维护,抽象底层存储;
- PVC 是用户的 “存储申请单”,描述 Pod 对存储的需求,自动匹配 PV;
- 二者配合实现了 存储资源的解耦、按需分配和动态管理,让 K8S 里的持久化存储更灵活、更易用。
# kubectl apply -f persistent-volume-claim.yaml -n wechat-applet-services apiVersion: v1 kind: PersistentVolumeClaim metadata: name: wechat-pvc spec: accessModes: - ReadWriteMany resources: requests: storage: 1Gi # 请求的存储大小(必须小于等于 PV 的容量) storageClassName: manual # 必须与 PV 的 storageClassName 匹配

ReadWriteOnce
是 Kubernetes 中 PersistentVolume (PV) 和 PersistentVolumeClaim (PVC) 的一种 访问模式(Access Mode),用于定义存储卷的使用限制。具体含义如下:
ReadWriteOnce
的核心定义
- 单节点读写:该卷可以被单个节点以读写方式挂载。
- 独占性:同一时间只能有一个节点(Node)挂载并读写该卷,其他节点无法同时访问。
- Pod 迁移限制:若 Pod 从一个节点迁移到另一个节点,卷会跟随迁移,但原节点将失去访问权限。
Kubernetes 支持三种主要访问模式:
访问模式 | 缩写 | 含义 |
---|---|---|
ReadWriteOnce | RWO | 单节点读写(最常用,适用于多数数据库等需要独占访问的场景)。 |
ReadOnlyMany | ROX | 多节点只读(适用于静态资源共享,如网站静态文件)。 |
ReadWriteMany | RWX | 多节点读写(需存储系统支持,如 NFS、Ceph 等分布式存储)。 |
ReadWriteOnce
的典型场景
- 数据库存储:
- 如 MySQL、PostgreSQL 等数据库需要独占存储,避免多节点同时写入导致数据冲突。
- 本地存储依赖:
- 某些应用依赖特定节点的本地文件系统(如
hostPath
类型的 PV),必须限制在单节点使用。
- 某些应用依赖特定节点的本地文件系统(如
- 云存储卷:
- AWS EBS、GCE PD 等云存储卷本身限制只能挂载到单个实例,对应
ReadWriteOnce
模式。
- AWS EBS、GCE PD 等云存储卷本身限制只能挂载到单个实例,对应
4. kubectl 创建Deployment
# service-wechat-deployment.yaml # kubectl apply -f service-wechat-deployment.yaml -n wechat-applet-services apiVersion: apps/v1 kind: Deployment metadata: name: service-wechat-deployment labels: app: service-wechat spec: replicas: 1 # 创建1个Pod副本 selector: matchLabels: app: service-wechat template: metadata: labels: app: service-wechat spec: containers: - name: service-wechat image: 123.57.xxx.xxx:5001/service-wechat:latest ports: - containerPort: 8081 resources: limits: memory: "512Mi" cpu: "500m" volumeMounts: - name: service-wechat-volume mountPath: "/mnt" # 容器内挂载路径,会把pvc挂到容器 /mnt目录下 imagePullSecrets: - name: docker-registry-secret volumes: - name: service-wechat-volume persistentVolumeClaim: claimName: wechat-pvc # 用到了上面的pvc
在宿主机上可以看到 Pod用到了上面绑定的pv和pvc,这个路径下面有了pod产生的文件。

进到k8s容器里面看一下

5. kubectl 创建Service 通过 nodePort 暴露服务
# wechat-service.yaml # kubectl apply -f wechat-service.yaml -n wechat-applet-services apiVersion: v1 kind: Service metadata: name: wechat-service spec: selector: app: service-wechat ports: - protocol: TCP port: 80 targetPort: 8081 nodePort: 30080 # 指定 NodePort(范围 30000-32767) type: NodePort # 暴露到集群外

在 Kubernetes 的 Service 配置中,port
、targetPort
和 nodePort
是三个关键概念,它们分别对应不同层级的端口映射关系。以下是详细解释:
port:Service 自身的端口(集群内部访问)
- 定义:Service 在集群内部 IP 上暴露的端口,用于集群内其他 Pod 或服务通过该端口访问此 Service。
ports: - protocol: TCP port: 80 # Service 在集群内部的端口为 80
- 作用:当集群内的 Pod 访问
wechat-service:80
时,流量会被 Service 转发到后端 Pod 的targetPort
。
targetPort:后端 Pod 的目标端口
- 定义:Service 转发流量时指向的后端 Pod 的端口,需与 Pod 中容器的端口一致。
ports: - targetPort: 8081 # 转发到 Pod 中容器的 8081 端口
- 作用:假设 Pod 中容器的端口为 8081(如
containerPort: 8081
),则 Service 会将请求从port
转发到 Pod 的targetPort
。
nodePort:节点暴露的端口(集群外部访问)
- 定义:当
type: NodePort
时,Kubernetes 会在集群所有节点上开放一个端口(nodePort
),外部流量可通过节点 IP +nodePort
访问服务。
ports: - nodePort: 30080 # 节点上开放的端口为 30080 type: NodePort
- 作用:外部用户可通过
http://<节点IP>:30080
访问服务,流量会被节点转发到 Service 的port
,再由 Service 转发到 Pod 的targetPort
。 - 端口范围:
nodePort
必须在30000-32767
范围内,若不指定,Kubernetes 会自动分配一个可用端口。
三者的映射关系(以示例配置为例)
外部访问 → 节点 IP:30080(nodePort) ↓ Service 内部 IP:80(port) ↓ 后端 Pod:8081(targetPort)
总结
端口类型 | 作用范围 | 示例值 | 访问场景 |
---|---|---|---|
port | 集群内部 | 80 | 集群内 Pod 通过 服务名:port 访问 |
targetPort | 后端 Pod | 8081 | Service 转发到 Pod 的目标端口 |
nodePort | 集群所有节点 | 30080 | 外部通过 节点IP:nodePort 访问 |
扩展说明
- 为什么需要三层端口?
port
和targetPort
解耦了 Service 与 Pod 的端口依赖(如 Pod 端口变更时,只需修改targetPort
)。nodePort
提供了集群外部访问的统一入口,避免直接暴露 Pod 地址。
- 与 Ingress 的区别
NodePort 适合简单场景,但存在以下限制:- 每个 Service 占用一个节点端口,端口资源有限。
- 无法基于域名、路径进行路由(需 Ingress 实现)。