作者:小樹扎根兒
郵箱:zjg_num01@163.com
一、從運維角度看微服務:
1.1 微服務的特點:
- 服務組件化:每個微服務獨立開發、部署,可以有效避免因單個微服務的變更引起整個系統重新部署的情況。
- 技術棧靈活:約定通信方式,使得服務本身功能實現對技術棧要求不再敏感。
- 獨立部署:每個微服務獨立部署,加速部署速度,方便擴展。
- 擴展性強:每個微服務可以部署多個,並且有負載均衡能力。
- 獨立數據:每個微服務有獨立的基本組件,例如:數據庫、緩存等。
1.2 微服務的不足:
- 溝通成本:微服務相比於傳統單體應用開發團隊溝通成本更大。
- 數據一致性:每個微服務都有自己獨立的數據存儲,可能會造成數據的不一致。
- 運維成本:微服務部署會涉及更多的組件,對運維的部署、監控、更新都帶來更大的挑戰。
- 內部架構復雜性:微服務本身就會帶來架構的復雜性,如:服務之間的耦合性設計、分布式事務等。
1.3 單體架構 vs 微服務:
-
單體架構:
- 單體架構的優勢:
易於部署;
易於測試;
- 單體架構的不足:
代碼臃腫,難以維護;
構建、部署時間成本大;
新人上手難;
-
微服務架構:
1.4 Java微服務框架:
- Spring Boot
- Spring Cloud / Spring Cloud Alibaba
- Dubbo
二、在K8S平台部署微服務需要考慮的問題:
-
微服務架構圖:
-
項目遷移到K8S平台的流程:
-
制作鏡像:
鏡像分為三層:
基礎鏡像:centos、ubuntu ... 純凈系統;
運行環境:基礎鏡像 + 運行環境(如:jdk、php ....);
項目鏡像:基礎鏡像 + 運行環境 + 應用程序代碼;
-
控制器管理Pod:
K8S包括以下幾種控制器:
Deployment:無狀態部署;
StatefulSet:有狀態部署;
DaemonSet:守護進程部署;
Job & CronJob:批處理;
-
通過Service暴露應用:
Service定義了Pod的邏輯集合和訪問這個集合的策略;
Service的引入是為了解決Pod的動態變化,提供服務發現和負載均衡。
-
通過Ingress對外發布應用:
Ingress:
通過Service關聯Pod;
基於域名訪問;
通過Ingress Controller實現Pod的負載均衡;
-
日志/監控:
主流方案:
FileBeat + ELK
Prometheus + Grafana
-
-
傳統部署與K8S部署的區別:
-
傳統方式部署項目:
-
K8S方式部署項目:
-
三、在K8S平台部署Spring Cloud微服務項目:
1、熟悉Spring Cloud微服務項目:
-
K8S服務器部署清單:
角色 IP 組件 k8s-master 192.168.1.90 kube-apiserver、kube-controller、kube-scheduler、docker、etcd K8s-node1 192.168.1.91 kubelet、kube-proxy、docker、etcd K8s-node2 192.168.1.92 kubelet、kube-proxy、docker、etcd -
Spring Cloud微服務項目地址:https://github.com/xiaoshuzhagen/simple-microservice
-
Spring Cloud微服務使用到的組件如下:
2、通過二進制包方式部署Consul:
-
Consul服務器部署清單:
角色 IP 組件 Consul Node 192.168.1.90 consul server(master)、 consul client Consul Node 192.168.1.91 consul server(follower)、consul client Consul Node 192.168.1.92 consul server(follower)、consul client
3、構建項目鏡像並推送到鏡像倉庫:
-
編寫微服務
Dockerfile:# 基礎鏡像,如果本地沒有,會從遠程倉庫拉取 FROM openjdk:11 # 鏡像的制作人 MAINTAINER zjg_num01@163.com # 定義環境變量 ENV JAVA_OPTS="$JAVA_OPTS" # 聲明容器應該打開的端口並沒有實際將端口啟用 EXPOSE 6010 # 拷貝本地文件到鏡像中 COPY ./target/gateway-service.jar ./ # 指定容器啟動時要執行的命令,但如果存在CMD命令,CMD命令中的參數會被附加到ENTRYPOIN指令的后面 ENTRYPOINT ["java","-jar","./gateway-service.jar","$JAVA_OPTS"] -
通過
maven命令構建微服務:mvn clean package -Dmaven.test.skip=true -
將
jar包構建成docker鏡像並推送到鏡像倉庫中:docker build -t gateway-service . # -f : 可以指定要使用的Dockerfile路徑. # -m : 可以設置內存最大值. # -t : 可以指定鏡像名稱及版本. # . : 指定構建鏡像的上下文路徑,docker build 會將這個路徑下所有的文件都打包上傳給Docker引擎. -
將微服務鏡像推送到鏡像倉庫中:
docker login http://192.168.1.90:6666 docker push http://192.168.1.90:6666/simple-microservice/gateway-service:v1.0 # simple-microservice:表示鏡像倉庫中的項目名稱,把鏡像打到指定的項目下. # gateway-service: 表示鏡像名稱. # v1.0:表示鏡像版本.
4、K8S部署Spring Cloud項目:
1、服務編排:
-
編寫微服務需要k8s編排的
yaml文件:apiVersion: apps/v1 kind: Deployment metadata: name: product-service namespace: simple-microservice spec: replicas: 2 selector: matchLabels: project: simple-microservice app: product-service template: metadata: labels: project: simple-microservice app: product-service spec: imagePullSecrets: - name: registry-pull-secert containers: - name: product-service image: 192.168.1.90:7777/simple-microservice/product-service:v1.0 imagePullPolicy: Always ports: - protocol: tcp containerPort: 8888 resources: requests: cpu: 0.5 memory: 256Mi readinessProbe: tcpSocket: port: 8888 initialDelaySeconds: 60 periodSeconds: 10 livenessProbe: tcpSocket: port: 8888 initialDelaySeconds: 60 periodSeconds: 10 -
部署微服務:
kubectl apply -f product-service.yaml -
資源限制問題:
雖然微服務運行的Pod已經進行了資源限制,如:最大使用1G內存,但Pod中的jvm並不會感知到資源限制問題,jvm
運行時如果資源不夠會繼續申請物理資源,此時,Pod檢測到使用的物理資源已經超出自身限制的最大可用戶資源,
會將Java進程kill掉,從而Java程序會拋出OOM。
-
jdk 1.8之前的版本:
服務編排的
yaml中指定環境變量:
Dockfile中引用服務編排yaml中定義的環境變量:

-
jdk 1.9以上的版本不存在這個問題。
-
