K8S | Service服務發(fā)現(xiàn)
一、背景
在微服務架構中,這里以開發(fā)環(huán)境「Dev」為基礎來描述,在K8S集群中通常會開放:路由網(wǎng)關、注冊中心、配置中心等相關服務,可以被集群外部訪問;
圖片
對于測試「Tes」環(huán)境或者生產(chǎn)「Pro」環(huán)境,出于安全或者環(huán)境隔離性來考慮,在正常情況下只會開放網(wǎng)關服務,而「注冊、配置」中心并不會對外暴露;
對于架構中的其它業(yè)務服務一般不會對外開放,在K8S集群內(nèi)部服務間是可以正常通信的,對于「Dev」環(huán)境來說,研發(fā)會使用「注冊、配置」中心,網(wǎng)關是系統(tǒng)的訪問入口;
在K8S集群中,通過Service組件,可以快速簡單的實現(xiàn)服務發(fā)現(xiàn)和負載均衡;
二、Service組件
1、簡介
在K8S集群中是通過Pod組件來部署應用服務,Deployment組件實現(xiàn)Pod編排管理,Service組件實現(xiàn)應用的訪問;
圖片
【Pod】自身的特點是臨時的,使用過后直接拋棄的實體,這樣在Pod創(chuàng)建和銷毀的狀態(tài)中,會導致IP地址發(fā)生變化,即無法使用固定的IP進行應用訪問;
【Deployment】控制器通過管理ReplicaSet間接實現(xiàn)Pod管理,比如發(fā)布方式,更新和回滾策略,維持Pod副本數(shù)量,對應用進行快速的編排,但是并沒有涉及應用的訪問;
【Service】是將運行在一個或一組Pod上的網(wǎng)絡應用程序公開為網(wǎng)絡服務的方法,可以在不修改現(xiàn)有應用程序的情況下,使用服務發(fā)現(xiàn)機制訪問到該應用;
基于Pod、Deployment、Service三個組件的協(xié)作,同一個應用的部署腳本可以在開發(fā)、測試、生產(chǎn)不同環(huán)境中復用;
2、基礎語法
這里提供一個簡單的【Service】語法做參考;
圖片
需要注意的是:在該腳本中沒有指定服務類型即ServiceType,默認采用的是ClusterIP,通過集群的內(nèi)部IP暴露服務,選擇該值時服務只能夠在集群內(nèi)部訪問;
三、內(nèi)部服務發(fā)現(xiàn)
1、Pod創(chuàng)建
基于【Deployment】組件,創(chuàng)建「auto-serve」應用;
apiVersion: apps/v1
kind: Deployment
metadata:
name: serve-deployment
labels:
app: auto-serve
spec:
replicas: 1
selector:
matchLabels:
app: auto-serve
template:
metadata:
labels:
app: auto-serve
spec:
containers:
- name: auto-serve
image: auto-serve:latest
imagePullPolicy: Never
ports:
- containerPort: 8082
name: auto-serve-port
執(zhí)行創(chuàng)建命令
kubectl apply -f serve-deployment.yaml
2、Service創(chuàng)建
簡單的腳本文件:app-service.yaml;
apiVersion: v1
kind: Service
metadata:
name: app-service
spec:
selector:
app: auto-serve
ports:
- name: app-service-port
protocol: TCP
port: 8082
targetPort: auto-serve-port
創(chuàng)建【Service】
kubectl apply -f app-service.yaml
查看【Service】,可以使用命令行或者界面;
kubectl describe svc app-service
圖片
刪除【Service】
kubectl delete -f app-service.yaml
3、內(nèi)部訪問
在上面已經(jīng)說明,當Type不指定時采用的是ClusterIP,只能在集群內(nèi)部訪問,集群外部的網(wǎng)絡是無法訪問的;
在【auto-client】服務中提供一段訪問【auto-serve】接口的代碼,并制作鏡像【auto-client:3.3.3】,完成部署后查看日志打??;
@Component
public class HttpServiceJob {
private static final Logger LOG = LoggerFactory.getLogger(HttpServiceJob.class.getName()) ;
private static final String SERVER_NAME = "http://app-service:8082/serve";
private static final String SERVER_IP = "http://10.103.252.94:8082/serve";
/**
* 每30秒執(zhí)行一次
*/
@Scheduled(fixedDelay = 30000)
public void systemDate () {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setReadTimeout(3000);
factory.setConnectTimeout(6000);
RestTemplate restTemplate = new RestTemplate(factory);
try {
Map<String, String> paramMap = new HashMap<>();
String result = restTemplate.getForObject(SERVER_NAME, String.class, paramMap);
LOG.info("service-name-resp::::" + result);
} catch (Exception e) {
e.printStackTrace();
}
try {
Map<String, String> paramMap = new HashMap<>();
String result = restTemplate.getForObject(SERVER_IP, String.class, paramMap);
LOG.info("service-ip-resp::::" + result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
在代碼中通過服務名:端口和IP:端口都可以正常訪問,在Pod中查看兩個應用的日志,請求和響應都正常;
圖片
四、外部服務發(fā)現(xiàn)
1、NodePort類型
指定類型為NodePort的腳本:app-np-service.yaml;
apiVersion: v1
kind: Service
metadata:
name: app-np-service
spec:
type: NodePort
selector:
app: auto-serve
ports:
- protocol: TCP
port: 8082
targetPort: 8082
nodePort: 30010
創(chuàng)建【Service】
kubectl apply -f app-np-service.yaml
使用NodePort類型,K8S控制平面會在指定的范圍內(nèi)分配端口,如果需要特定的端口號可以指定nodePort字段中的值,但是該類型需要自己設置負載均衡解決方案;
2、LoadBalancer類型
指定類型為LoadBalancer的腳本:app-lb-service.yaml;
apiVersion: v1
kind: Service
metadata:
name: app-lb-service
spec:
type: LoadBalancer
selector:
app: auto-serve
ports:
- protocol: TCP
port: 8082
targetPort: 8082
創(chuàng)建【Service】
kubectl apply -f app-lb-service.yaml
查看【Service】
在查看「app-lb-service」時,值得注意一下Endpoints的字段屬性,這里就是Pod選擇器選中的Pod;
kubectl get svc app-lb-service -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
app-lb-service LoadBalancer 10.111.65.220 localhost 8082:30636/TCP 6m49s app=auto-serve
kubectl describe svc app-lb-service
Name: app-lb-service
Namespace: default
Labels: <none>
Annotations: <none>
Selector: app=auto-serve
Type: LoadBalancer
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.111.65.220
IPs: 10.111.65.220
LoadBalancer Ingress: localhost
Port: <unset> 8082/TCP
TargetPort: 8082/TCP
NodePort: <unset> 30636/TCP
Endpoints: 10.1.0.160:8082,10.1.0.161:8082,10.1.0.162:8082
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>
kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
serve-deployment-f6f6c5bbd-9qvgr 1/1 Running 0 39m 10.1.0.162 docker-desktop
serve-deployment-f6f6c5bbd-w7nj2 1/1 Running 0 39m 10.1.0.161 docker-desktop
serve-deployment-f6f6c5bbd-x7v4d 1/1 Running 0 39m 10.1.0.160 docker-desktop
圖片
五、參考源碼
文檔倉庫:
https://gitee.com/cicadasmile/butte-java-note
腳本倉庫:
https://gitee.com/cicadasmile/butte-auto-parent