1漓踢、說明
在K8s Paas平臺搭建SpringCloud微服務框架牵署,進行微服務開發(fā)。網(wǎng)關采用Zuul1喧半、服務注冊與發(fā)現(xiàn)采用Eureka奴迅。鏈路跟蹤與日志采集采用Skywalking。Skywalking日志采集是Skywalking8.5.0版本之后的功能挺据,Skywalking日志采集采用服務工程主動推送的方式取具,與logback集成,可以滿足中小型系統(tǒng)的日志采集和分析扁耐,數(shù)據(jù)庫可選用elasticsearch者填,能保證良好的搜索性能。
新建一個k8s命名空間進行實驗:
Yaml:
apiVersion: v1
kind: Namespace
metadata:
??? name: sclouds
??? labels:
?????? name: sclouds
設置默認命名空間:
kubectl config set-context $(kubectl config current-context) --namespace=sclouds
2做葵、Eureka容器集群
2.1.StatefulSet占哟、Headless Service
Eureka搭建容器集群,需要依賴k8s的statefulset組件酿矢。Eureka-server的每個實例需要相互同步狀態(tài)榨乎。
StatefulSet是為了解決有狀態(tài)服務的問題(對應Deployments和ReplicaSets是為無狀態(tài)服務而設計),其應用場景包括
穩(wěn)定的持久化存儲瘫筐,即Pod重新調度后還是能訪問到相同的持久化數(shù)據(jù)蜜暑,基于PVC來實現(xiàn)。
穩(wěn)定的網(wǎng)絡標志策肝,即Pod重新調度后其PodName和HostName不變肛捍,基于Headless Service(即沒有Cluster IP的Service)來實現(xiàn)。
有序部署之众,有序擴展拙毫,即Pod是有順序的,在部署或者擴展的時候要依據(jù)定義的順序依次依次進行(即從0到N-1棺禾,在下一個Pod運行之前所有之前的Pod必須都是Running和Ready狀態(tài))缀蹄,有序收縮,有序刪除(即從N-1到0)膘婶。
使用StatefulSet缺前,StatefulSet中每個Pod的DNS就是固定的,格式為
??? statefulSetName-{0..N-1}.serviceName.namespace.svc.cluster.local
serviceName為Headless Service的名字0..N-1為Pod所在的序號悬襟,從0開始到N-1statefulSetName為StatefulSet的名字namespace為服務所在的namespace衅码,Headless Service和StatefulSet必須在相同的namespacecluster.local為Cluster Domain
2.2.Ecureka Springboot鏡像
集群由兩個ecureka服務組成,服務工程基于Springboot開發(fā)脊岳,打包成jar包逝段,最后打包成docker鏡像在k8s上部署筛璧。
Sprinboot版本:2.6.2
SpringCloud版本:2021.0.1
pom.xml設置,引入spring-cloud-starter-netflix-eureka-server:
引入spring-boot-starter-web惹恃、spring-cloud-starter-netflix-eureka-server
? ? <dependencies>
? ? ? ? <dependency>
? ? ? ? ? ? <groupId>org.springframework.boot</groupId>
? ? ? ? ? ? <artifactId>spring-boot-starter-web</artifactId>
? ? ? ? </dependency>
? ? ? ? <dependency>
? ? ? ? ? ? <groupId>org.springframework.cloud</groupId>
? ? ? ? ? ? <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
? ? ? ? </dependency>
? ? ? ? <dependency>
? ? ? ? ? ? <groupId>org.springframework.boot</groupId>
? ? ? ? ? ? <artifactId>spring-boot-starter-test</artifactId>
? ? ? ? ? ? <scope>test</scope>
? ? ? ? </dependency>
? ? </dependencies>
? ? <dependencyManagement>
? ? ? ? <dependencies>
? ? ? ? ? ? <dependency>
? ? ? ? ? ? ? ? <groupId>org.springframework.cloud</groupId>
? ? ? ? ? ? ? ? <artifactId>spring-cloud-dependencies</artifactId>
? ? ? ? ? ? ? ? <version>${spring-cloud.version}</version>
? ? ? ? ? ? ? ? <type>pom</type>
? ? ? ? ? ? ? ? <scope>import</scope>
? ? ? ? ? ? </dependency>
? ? ? ? </dependencies>
</dependencyManagement>
application.properties屬性設置:
spring.application.name=register-server
server.port=8000
management.server.port=8001
eureka.instance.leaseRenewalIntervalInSeconds=10
eureka.instance.leaseExpirationDurationInSeconds=30
eureka.instance.hostname=${MY_POD_NAME}.register-server
eureka.instance.prefer-ip-address=true
eureka.client.fetch-registry=true
eureka.client.register-with-eureka=true
eureka.client.service-url.defaultZone=http://register-server-0.register-server:8000/eureka/,http://register-server-1.register-server:8000/eureka/
eureka.client.service-url.registryFetchIntervalSeconds=10
eureka.client.service-url.disable-delta=true
eureka.server.evictionIntervalTimerInMs=4000
eureka.server.enable-self-preservation=false
Dockfile:
FROM java:8
VOLUME /tmp
ADD eurekaclu-0.0.1-SNAPSHOT.jar /eurekaclu-0.0.1-SNAPSHOT.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/eurekaclu-0.0.1-SNAPSHOT.jar"]
2.3.k8s service服務暴露
使用2.2的鏡像部署statefulset夭谤。Service關聯(lián)暴露服務。為了方便訪問巫糙,設置成nodePort類型朗儒,暴露外網(wǎng)端口。
statefulset:
apiVersion: apps/v1
kind: StatefulSet
metadata:
? name: register-server
? labels:
? ? service: register-server
spec:
? replicas: 2
? serviceName: register-server
? selector:
? ? matchLabels:
? ? ? service: register-server
? template:
? ? metadata:
? ? ? labels:
? ? ? ? service: register-server
? ? ? annotations:
? ? ? ? service: register-server
? ? spec:
? ? ? containers:
? ? ? ? - name: register-server
? ? ? ? ? image: dw/eurekaclu-2
? ? ? ? ? imagePullPolicy: IfNotPresent
? ? ? ? ? env:
? ? ? ? ? - name: MY_POD_NAME
? ? ? ? ? ? valueFrom:
? ? ? ? ? ? ? fieldRef:
? ? ? ? ? ? ? ? fieldPath: metadata.name
? ? ? ? ? ports:
? ? ? ? ? ? - name: http
? ? ? ? ? ? ? containerPort: 8000
? ? ? ? ? ? ? protocol: TCP
? ? ? ? ? readinessProbe:
? ? ? ? ? ? httpGet:
? ? ? ? ? ? ? path: /actuator/health
? ? ? ? ? ? ? port: 8001
? ? ? ? ? ? ? scheme: HTTP
? ? ? ? ? ? failureThreshold: 3
? ? ? ? ? ? initialDelaySeconds: 60
? ? ? ? ? ? periodSeconds: 10
? ? ? ? ? ? successThreshold: 1
? ? ? ? ? ? timeoutSeconds: 10
? ? ? ? ? resources:
? ? ? ? ? ? limits:
? ? ? ? ? ? ? # cpu: 100m
? ? ? ? ? ? ? memory: 1Gi
? ? ? ? ? ? requests:
? ? ? ? ? ? ? ? # cpu: 100m
? ? ? ? ? ? ? memory: 1Gi
? ? ? ? ? volumeMounts:
? ? ? ? ? - mountPath: /Charts
? ? ? ? ? ? name: data
? ? ? volumes:
? ? ? - name: data
? podManagementPolicy: "Parallel"
Service:
apiVersion: v1
kind: Service
metadata:
? name: register-server
? labels:
? ? service: register-server
spec:
? type: NodePort
? ports:
? ? - port: 8000
? ? ? targetPort: 8000
? ? ? protocol: TCP
? ? ? name: http
? ? ? nodePort: 30111
? selector:
? ? service: register-server
依次應用statefulset参淹、service醉锄,部署兩個statefulset:
這樣可以得到兩個ecurka-server的集群內(nèi)url,和2.2節(jié)的屬性設置對應:
register-server-0.register-server:8000
register-server-1.register-server:8000
導出nodePort浙值,瀏覽器登錄驗證:
3.Zuul1容器集群
Zuul1是springcloud早期的服務網(wǎng)關恳不,這里使用舊一點的穩(wěn)定版本。
3.1.zuul1 springboot
Zuul也要注冊到eureka开呐,需要引入eureka-client和netflix-zuul烟勋。服務注冊ecureka使用上一章搭建的集群,根據(jù)k8s服務url規(guī)則筐付,ecureka服務的url為http://register-server.sclouds.svc.cluster.local:8000/eureka/卵惦,k8s服務進行負載分發(fā)到兩個stateful實例
Springboot版本:2.1.8
SpringCloud版本:Greenwich.SR2
Pom.xml:
<dependency>
? ? <groupId>org.springframework.cloud</groupId>
? ? <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
? ? <groupId>org.springframework.cloud</groupId>
? ? <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
application.properties:
server.port=7005
spring.application.name=springboot-zuul-server
eureka.client.serviceUrl.defaultZone=http://register-server.sclouds.svc.cluster.local:8000/eureka/
zuul.stripPrefix=false
zuul.ignored-services="*"
zuul.routes.api-a.path=/ribbon/**
zuul.routes.api-a.serviceId=springboot-eureka-client
zuul.routes.api-a.strip-prefix=false
ribbon.eureka.enabled=true
eureka.instance.prefer-ip-address=true
注:這里設置一個路由規(guī)則,路由到springboot-eureka-client微服務(下文有例子)
Dockerfile:
FROM java:8
VOLUME /tmp
ADD ecurkazuul-0.0.1-SNAPSHOT.jar /ecurkazuul-0.0.1-SNAPSHOT.jar
ADD skagent /skagent
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/ecurkazuul-0.0.1-SNAPSHOT.jar"]
3.2.k8s service
Zuul集群實例不需要互相同步狀態(tài)瓦戚,部署Deployment即可沮尿。Service進行服務暴露負載
Yaml:
apiVersion: v1
kind: Service
metadata:
? name: ecurka-zuul
? namespace: sclouds
? labels:
? ? verison: "1.0.0"
? ? env: "test"
spec:
? type: NodePort
? selector:
? ? app: ecurka-zuul
? ? release: master
? ports:
? ? ? - name: http
? ? ? ? port: 7005
? ? ? ? targetPort: 7005
? ? ? ? nodePort: 30112
---
apiVersion: apps/v1
kind: Deployment
metadata:
? name: ecurka-zuul
? namespace: sclouds
? labels:
? ? verison: "1.0.0"
? ? env: "test"
spec:
? replicas: 2
? selector:
? ? matchLabels:
? ? ? app: ecurka-zuul
? ? ? release: master
? template:
? ? metadata:
? ? ? labels:
? ? ? ? app: ecurka-zuul
? ? ? ? release: master
? ? spec:
? ? ? containers:
? ? ? ? - name: ecurka-zuul
? ? ? ? ? image: dw/ecurka-zuul
? ? ? ? ? imagePullPolicy: IfNotPresent
? ? ? ? ? ports:
? ? ? ? ? ? - name: http
? ? ? ? ? ? ? containerPort: 7005
應用service,部署兩個pod實例:
登錄ecureka较解,看到有兩個zuul服務實例在運行:
4畜疾、SkyWalking
這里簡單介紹一下Windows單機部署
4.1.軟件版本
Skywalking 8.7.0
下載地址:https://skywalking.apache.org/downloads/
Elasticsearch 6.8.23
下載地址:https://www.elastic.co/cn/downloads/past-releases/elasticsearch-6-8-23
本文選擇Elasticsearch 作為skywalking的數(shù)據(jù)庫,skywalking與el的版本需要對應印衔,如果使用Elasticsearch7啡捶,需要下載es后綴的skywalking版本。
4.2.elasticsearch
elasticsearch.yml修改:
4.3.Skywalking
分為兩個服務当编,后臺信息收集服務oap届慈,前端門戶ui(skywalking-webapp)
?OAP后臺服務
config:application.yml
?UI門戶工程
webapp.yml徒溪,如果端口被占用忿偷,可修改默認端口
4.4.服務啟動
啟動Elasticsearch
執(zhí)行elasticsearch.bat,默認占用9200端口
啟動skywalking
執(zhí)行startup.bat臊泌,或者分別執(zhí)行oapService.bat鲤桥、webappService.bat,默認占用11800,12800,8080端口渠概。
4.5.Springboot工程接入
Skywalking對于Java工程是非侵入的茶凳,通過探針進行接口探測嫂拴,數(shù)據(jù)上報。只需要在啟動后臺服務時贮喧,加入啟動參數(shù)筒狠,指定Skywalking agent依賴包以及oap服務Url,idea中可在工程啟動配置中配置箱沦,有兩個屬性需要注意辩恼,skywalking.agent.service_name是skywalking中顯示的服務名稱,不同服務需要區(qū)分谓形。skywalking.collector.backend_service灶伊,是skywalking服務端的地址,要根據(jù)實際情況修改寒跳。本文中聘萨,skywalking沒有部署到k8s中,寫的是skywalking部署主機的地址童太。
參考:
-javaagent:J:\tmppro\demo\skagent\skywalking-agent.jar -Dskywalking.agent.service_name=DemoHelloService -Dskywalking.collector.backend_service=192.168.76.54:11800
HTTP調用米辐,Skywalking前端觀測
4.6.springboot服務docker鏡像打包修改
拷貝skywalking agent依賴到docker鏡像打包目錄
修改Dockerfile,加入加粗字體部分:
FROM java:8
VOLUME /tmp
ADD ecurkaclient-0.0.1-SNAPSHOT.jar /ecurkaclient-0.0.1-SNAPSHOT.jar
ADD skagent /skagent
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-javaagent:/skagent/skywalking-agent.jar","-Dskywalking.agent.service_name=EurekaClient","-Dskywalking.collector.backend_service=192.168.76.54:11800","-jar","/ecurkaclient-0.0.1-SNAPSHOT.jar"]
5书释、服務實例
5.1.springboot鏡像
Java代碼儡循,設置兩個url作為服務實驗:
package com.example.ecurkaclient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
? ? private static final Logger log = LoggerFactory.getLogger(TestController.class);
? ? @RequestMapping(value = "/hello", method = RequestMethod.GET)
? ? public ResponseX testHello() {
? ? ? ? ResponseX x = new ResponseX();
? ? ? ? x.setMsg("hello-x");
? ? ? ? log.info("######################################\n" + "hello");
? ? ? ? return x;
? ? }
? ? @RequestMapping(value = "/helloworld", method = RequestMethod.GET)
? ? public ResponseX testHellox() {
? ? ? ? ResponseX x = new ResponseX();
? ? ? ? x.setMsg("hello-world-x");
? ? ? ? log.info("######################################\n" + "hello-world");
? ? ? ? return x;
? ? }
}
application.properties:
server.port=7004
spring.application.name=springboot-eureka-client
eureka.client.serviceUrl.defaultZone=http://register-server.sclouds.svc.cluster.local:8000/eureka/
eureka.instance.prefer-ip-address=true
注:spring.application.name和前面zuul網(wǎng)關設置的zuul.routes.api-a.serviceId要對應。Zuul網(wǎng)關根據(jù)服務名稱進行路由征冷。
Dockerfile打包鏡像:
FROM java:8
VOLUME /tmp
ADD ecurkaclient-0.0.1-SNAPSHOT.jar /ecurkaclient-0.0.1-SNAPSHOT.jar
ADD skagent /skagent
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-javaagent:/skagent/skywalking-agent.jar","-Dskywalking.agent.service_name=EurekaClient","-Dskywalking.collector.backend_service=192.168.76.54:11800","-jar","/ecurkaclient-0.0.1-SNAPSHOT.jar"]
5.2.k8s service
Yaml:
apiVersion: v1
kind: Service
metadata:
? name: ecurka-client
? namespace: sclouds
? labels:
? ? verison: "1.0.0"
? ? env: "test"
spec:
? selector:
? ? app: ecurka-client
? ? release: master
? ports:
? ? ? - name: http
? ? ? ? port: 7004
? ? ? ? targetPort: 7004
---
apiVersion: apps/v1
kind: Deployment
metadata:
? name: ecurka-client
? namespace: sclouds
? labels:
? ? verison: "1.0.0"
? ? env: "test"
spec:
? replicas: 2
? selector:
? ? matchLabels:
? ? ? app: ecurka-client
? ? ? release: master
? template:
? ? metadata:
? ? ? labels:
? ? ? ? app: ecurka-client
? ? ? ? release: master
? ? spec:
? ? ? containers:
? ? ? ? - name: ecurka-client
? ? ? ? ? image: dw/ecurka-client
? ? ? ? ? imagePullPolicy: IfNotPresent
? ? ? ? ? ports:
? ? ? ? ? ? - name: http
? ? ? ? ? ? ? containerPort: 7004
6择膝、日志采集(SkyWalking)
logback設置GRPCLogClientAppender,設置日志級別:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
? ? <appender name="msystem-log" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">
? ? ? ? <!-- 日志輸出編碼 -->
? ? ? ? <encoder>
? ? ? ? ? ? <!--格式化輸出:%d表示日期检激,%thread表示線程名肴捉,%-5level:級別從左顯示5個字符寬度%msg:日志消息,%n是換行符-->
? ? ? ? ? ? <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
? ? ? ? </encoder>
? ? </appender>
? ? <root level="info">
? ? ? ? <appender-ref ref="msystem-log"/>
? ? </root>
</configuration>
完成上述配置叔收,日志就會上傳到skywalking
log.info("######################################\n" + "hello-world");