Kubernetes 1.13.3 部署电商微服务实战:安装包与详细文档笔记
2026/9/23 16:33:52 网站建设 项目流程

简介:这份资源面向具备一定容器与 Linux 基础的云计算运维人员及微服务开发者,围绕 k8s 1.13.3 版本,提供一套电商微服务在 Kubernetes 上落地的实战案例资料,帮助读者理解从环境搭建到服务编排的完整流程。压缩包共 6 个文件,约 950.8MB,包含 gz 与 tar 格式的安装包(如 JDK、Maven、微服务镜像及 ingress-controller 组件)、一份 yaml 编排清单,以及一份 docx 详细文档笔记,覆盖依赖准备、镜像导入与资源配置等环节。目前已有 223 人学习下载。资料中的文档笔记对部署步骤、组件作用与常见问题做了整理,yaml 文件可直接参考或改造用于自己的集群,配合安装包能较快复现一套可运行的电商微服务环境,适合作为 k8s 入门到进阶的练手项目,也便于在面试或实际运维中对照排查部署问题。

1. k8s 1.13.3 部署电商微服务:一套能跑起来的实战路径

2019 年前后,大量中小团队手里跑的还是 k8s 1.13.3 这个版本,电商业务又刚好在往微服务拆。这个组合放到今天看有点旧,但它的价值恰恰在于“旧”——组件依赖少、镜像体积小、单机也能把整套链路跑通,非常适合拿来吃透 Kubernetes 部署微服务的完整流程。标题里的“安装包和详细文档笔记整理”,本质是把一套可复现的部署方案固化下来:从集群初始化、镜像准备、微服务拆分,到 Service、Ingress、配置与存储的落地。它适合两类人:一是刚学 k8s、想找一个真实业务场景练手的工程师;二是手上真有老集群、需要把电商微服务迁上去的运维和开发。下面按“集群怎么搭 → 微服务怎么拆 → 怎么部署 → 坑在哪 → 怎么验证”的顺序讲透。

2. 集群与镜像准备:把 k8s 1.13.3 的地基打稳

2.1 为什么这个版本要锁死组件版本

k8s 1.13.3 属于 1.13 分支的补丁版本,API 还是apps/v1为主,extensions/v1beta1的 Deployment 已经废弃但部分资源仍在用。这个版本对容器运行时只认 Docker,kubeletkubeadm的版本必须严格对齐,否则kubeadm init阶段就会因为版本偏差直接报错退出。我一般会把三个节点的系统统一成 CentOS 7.6 或 Ubuntu 18.04,内核 4.x,关闭 swap,因为 1.13 的 kubelet 对 swap 的容忍度很低,开着 swap 会出现 Pod 反复重启的玄学问题。

组件版本建议这样锁:

组件版本说明
kubeadm / kubelet / kubectl1.13.3三者必须一致
Docker18.06.1-ce1.13 官方验证过的运行时
flannelv0.10.0网络插件,配置简单
etcd3.2.24kubeadm 内置,无需单独装

2.2 用 kubeadm 初始化单 master 集群

单节点或一主两从是练手最稳的形态。先在所有节点装好 Docker 和 kubelet,然后在 master 上执行初始化。下面这段是初始化配置文件,比纯命令行更好维护:

# kubeadm-config.yaml apiVersion: kubeadm.k8s.io/v1beta1 kind: InitConfiguration localAPIEndpoint: advertiseAddress: 192.168.1.10 # master 内网 IP bindPort: 6443 --- apiVersion: kubeadm.k8s.io/v1beta1 kind: ClusterConfiguration kubernetesVersion: v1.13.3 imageRepository: registry.aliyuncs.com/google_containers # 国内拉镜像更稳 networking: podSubnet: 10.244.0.0/16 # 必须和 flannel 网段一致

执行初始化:

kubeadm init --config kubeadm-config.yaml --ignore-preflight-errors=Swap mkdir -p $HOME/.kube cp -i /etc/kubernetes/admin.conf $HOME/.kube/config kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/v0.10.0/Documentation/kube-flannel.yml

advertiseAddress填 master 的真实内网 IP,填错会导致 node 注册不上。podSubnet一旦定了就不要改,flannel 的 ConfigMap 里网段必须和它一致,否则跨节点 Pod 通信直接断。--ignore-preflight-errors=Swap是临时绕过 swap 检查,生产环境还是老老实实关掉 swap。初始化完成后用kubectl get nodes确认状态是 Ready,如果一直是 NotReady,八成是 flannel 没起来,用kubectl get pods -n kube-system看具体哪个 Pod 在 CrashLoopBackOff。

2.3 镜像准备与私有仓库

电商微服务的镜像通常有十几个,直接走公网拉取在集群里会非常慢。常见做法是在本地或一台跳板机上起一个 registry,把镜像统一推上去,再让 kubelet 从内网拉。给 Docker 配置私有仓库信任:

# /etc/docker/daemon.json { "insecure-registries": ["192.168.1.20:5000"], "exec-opts": ["native.cgroupdriver=systemd"] }

native.cgroupdriver=systemd这一项在 1.13 上很关键,Docker 默认用 cgroupfs,和 kubelet 的 systemd 驱动不一致时,节点资源统计会出错,严重时 Pod 起不来。改完systemctl daemon-reload && systemctl restart docker。镜像命名统一成192.168.1.20:5000/ecommerce/order-service:1.0.0这种格式,后面写 Deployment 时直接引用,省得每个 yaml 里再改地址。

3. 电商微服务拆分与部署清单设计

3.1 按业务边界拆成哪几个服务

电商系统拆微服务,最忌讳一上来就按技术分层拆。我一般按业务能力切:用户服务、商品服务、订单服务、库存服务、支付服务、网关。每个服务独立镜像、独立 Deployment、独立 Service。服务之间用 ClusterIP 的 Service 名做 DNS 调用,比如订单服务调库存,直接写http://inventory-service:8080,kube-dns 会解析到对应 Pod。这样拆的好处是每个服务能单独扩缩容,订单高峰时只扩订单和库存,不用整个系统一起加机器。

拆分时要注意数据库边界。订单库和库存库最好物理分开,至少逻辑上分库,否则一个服务的慢查询会把另一个拖死。配置方面,每个服务的数据库连接、Redis 地址、MQ 地址都通过 ConfigMap 注入,敏感信息走 Secret,不要硬编码在镜像里。

3.2 一个可复用的 Deployment 模板

下面以订单服务为例,给出 Deployment 加 Service 的完整 yaml。这个模板改改镜像名和端口就能套到其他服务上:

apiVersion: apps/v1 kind: Deployment metadata: name: order-service namespace: ecommerce spec: replicas: 2 selector: matchLabels: app: order-service template: metadata: labels: app: order-service spec: containers: - name: order-service image: 192.168.1.20:5000/ecommerce/order-service:1.0.0 ports: - containerPort: 8080 envFrom: - configMapRef: name: order-config - secretRef: name: order-secret resources: requests: cpu: 250m memory: 512Mi limits: cpu: 500m memory: 1Gi readinessProbe: httpGet: path: /actuator/health port: 8080 initialDelaySeconds: 30 periodSeconds: 10 --- apiVersion: v1 kind: Service metadata: name: order-service namespace: ecommerce spec: selector: app: order-service ports: - port: 8080 targetPort: 8080 type: ClusterIP

replicas: 2是起步值,单副本在滚动更新时会有短暂不可用。resources的 requests 和 limits 必须写,1.13 的调度器靠 requests 算资源,不写的话所有 Pod 都往一个节点挤。readinessProbe指向 Spring Boot 的 health 端点,没就绪的 Pod 不会被挂到 Service 后面,这是滚动更新不丢请求的关键。envFrom把 ConfigMap 和 Secret 里的键值对整体注入成环境变量,改配置不用重新打镜像。

3.3 用 Ingress 暴露网关

集群内部走 ClusterIP,对外只暴露一个网关服务。1.13 时代 Ingress 还是extensions/v1beta1,写法如下:

apiVersion: extensions/v1beta1 kind: Ingress metadata: name: ecommerce-gateway namespace: ecommerce annotations: nginx.ingress.kubernetes.io/rewrite-target: / spec: rules: - host: shop.example.com http: paths: - path: / backend: serviceName: gateway-service servicePort: 8080

host换成你自己的域名或 hosts 里配的假域名。rewrite-target在路径转发时很有用,网关内部路由和外部路径不一致时靠它对齐。Ingress controller 需要单独部署,1.13 上常用 nginx-ingress 的 0.22 左右版本,装好后kubectl get pods -n ingress-nginx确认 Running,再用kubectl get ingress -n ecommerce看 ADDRESS 有没有分配出来。

4. 配置、存储与滚动更新:让微服务真正可用

4.1 ConfigMap 和 Secret 的正确用法

配置外置是微服务的基本功。ConfigMap 存非敏感配置,Secret 存密码和密钥。创建方式有两种,命令行和 yaml。我倾向用 yaml 管理,方便进版本库:

kubectl create configmap order-config \ --from-literal=DB_HOST=mysql-service \ --from-literal=REDIS_HOST=redis-service \ -n ecommerce kubectl create secret generic order-secret \ --from-literal=DB_PASSWORD=yourpassword \ -n ecommerce

--from-literal适合少量键值,配置多的时候用--from-file挂整个配置文件。Secret 默认是 base64 编码不是加密,集群里谁能读 Secret 谁就能拿到明文,所以 RBAC 要收紧。改完 ConfigMap 后,已经运行的 Pod 不会自动加载新值,要么重启 Pod,要么用 sidecar 做热加载,这一点在 1.13 上没有原生支持,别指望改完就生效。

4.2 有状态服务用 PV 和 PVC

MySQL、Redis 这类有状态服务不能像无状态服务那样随便漂。1.13 上动态存储供给还不普及,常见做法是手动建 PV 再让 PVC 绑定:

apiVersion: v1 kind: PersistentVolume metadata: name: mysql-pv spec: capacity: storage: 20Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain hostPath: path: /data/mysql --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: mysql-pvc namespace: ecommerce spec: accessModes: - ReadWriteOnce resources: requests: storage: 20Gi

hostPath只适合单节点练手,多节点必须换成 NFS 或云盘。persistentVolumeReclaimPolicy: Retain是后悔药,删 PVC 时数据不会被一起清掉。MySQL 的 Deployment 里把mysql-pvc挂到/var/lib/mysql,Pod 重建后数据还在。注意 hostPath 的目录权限,MySQL 容器里是 mysql 用户,宿主机目录属主不对会启动失败,报错通常是Permission denied

4.3 滚动更新参数怎么调

电商服务更新不能停服,靠的是 Deployment 的滚动更新策略。默认maxUnavailable是 25%,副本少的时候这个值会导致更新期间可用 Pod 不够。我一般显式设置:

spec: strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 0 maxSurge: 1

maxUnavailable: 0保证更新过程中可用副本数不低于期望值,maxSurge: 1允许临时多起一个 Pod。这样更新时先起新 Pod,就绪后再杀旧 Pod,全程服务不断。配合 readinessProbe 的initialDelaySeconds,给应用留足启动时间,否则新 Pod 还没起来就被判定失败,更新会卡住。用kubectl rollout status deployment/order-service -n ecommerce观察更新进度,kubectl rollout undo可以回滚到上一版。

5. 部署电商微服务时最容易翻车的几个点

5.1 Pod 一直 Pending,事件里写 Insufficient cpu

现象是kubectl get pods显示 Pending,kubectl describe pod的 Events 里报0/3 nodes are available: Insufficient cpu。原因是 Deployment 里 requests 设得太大,或者节点上已有 Pod 占满了可分配资源。解决方法是先看kubectl describe node里的 Allocated resources,把不合理的 requests 调小,或者给集群加节点。1.13 的调度器不会自动压缩,requests 写多少就占多少。

5.2 Service 能 ping 通但访问超时

现象是集群内curl service-name:port卡住,Pod 本身是 Running。原因多半是 targetPort 和容器实际监听端口不一致,或者 readinessProbe 没通过导致 Endpoints 为空。用kubectl get endpoints order-service -n ecommerce看有没有后端地址,空的就说明探针没过。检查容器里应用是不是真的监听在containerPort上,Spring Boot 默认 8080,改过端口的话 yaml 里要同步改。

5.3 镜像拉取报 ImagePullBackOff

现象是 Pod 起不来,describe 里写Failed to pull image。原因是私有仓库没配信任,或者镜像 tag 写错。先在节点上手动docker pull一次,能拉下来再排查 kubelet。1.13 的 kubelet 读的是/etc/docker/daemon.json里的 insecure-registries,改完要重启 docker 和 kubelet。另外镜像名里的仓库地址必须和 daemon.json 里配的一致,少个端口号都会失败。

5.4 跨节点 Pod 通信不通

现象是同节点 Pod 能通,跨节点就不行。原因是 flannel 没起来或者网段冲突。kubectl get pods -n kube-system看 flannel 的 Pod 是否 Running,kubectl logs看有没有报错。还要确认podSubnet和 flannel ConfigMap 里的Network一致,以及节点之间 8285/8472 端口没被防火墙拦。云服务器上安全组也要放行这些端口,血泪经验是安全组问题最容易被忽略。

5.5 滚动更新卡住不结束

现象是kubectl rollout status一直不返回,新 Pod 起不来旧 Pod 也不杀。原因是 readinessProbe 一直失败,新 Pod 永远不就绪。先kubectl describe pod看探针的失败信息,再进容器curl localhost:8080/actuator/health确认应用状态。initialDelaySeconds设太短也会导致这个问题,Java 应用启动慢,给到 30 到 60 秒比较稳。

6. 验证部署是否真的可用:从命令到压测

部署完不算完,得验证。第一步看整体状态:

kubectl get pods,svc,ingress -n ecommerce kubectl get endpoints -n ecommerce

所有 Pod 是 Running,Endpoints 里每个 Service 都有对应 IP,Ingress 有 ADDRESS,这是基本盘。第二步从集群内发请求,起一个临时 Pod 做 curl:

kubectl run curl-test --image=radial/busyboxplus:curl -it --rm -- sh # 进入后执行 curl http://order-service:8080/actuator/health curl http://gateway-service:8080/api/products

能返回 JSON 说明服务间调用链路通了。第三步从集群外验证 Ingress,在 hosts 里把shop.example.com指到任意节点 IP,浏览器或 curl 访问,能看到网关返回的内容就说明对外暴露成功。

进阶一点,用kubectl scale deployment order-service --replicas=4 -n ecommerce手动扩容,观察新 Pod 是否自动挂到 Service 后面,kubectl get endpoints的地址数量应该跟着变。再模拟一次滚动更新,改镜像 tag 后kubectl apply,同时用while true; do curl -s -o /dev/null -w "%{http_code}\n" http://shop.example.com/api/orders; sleep 0.5; done持续打请求,观察有没有 5xx。全程没有错误码,说明滚动更新策略和探针配置是有效的。

我自己的习惯是每次部署完必做这三步验证,尤其是 Endpoints 那一步,很多“服务起不来”的问题其实卡在探针上,看一眼 Endpoints 就能定位。k8s 1.13.3 虽然老,但把这一套跑通,后面换任何版本都是换汤不换药。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询