服務發現與負載均衡。
一、背景
在微服務架構中,這裏以開發環境「Dev」爲基礎來描述,在K8S集羣中通常會開放:路由網關、註冊中心、配置中心等相關服務,可以被集羣外部訪問;
對於測試「Tes」環境或者生產「Pro」環境,出於安全或者環境隔離性來考慮,在正常情況下只會開放網關服務,而「註冊、配置」中心並不會對外暴露;
對於架構中的其它業務服務一般不會對外開放,在K8S集羣內部服務間是可以正常通信的,對於「Dev」環境來說,研發會使用「註冊、配置」中心,網關是系統的訪問入口;
在K8S集羣中,通過Service組件,可以快速簡單的實現服務發現和負載均衡;
二、Service組件
1、簡介
在K8S集羣中是通過Pod組件來部署應用服務,Deployment組件實現Pod編排管理,Service組件實現應用的訪問;
【Pod】自身的特點是臨時的,使用過後直接拋棄的實體,這樣在Pod創建和銷燬的狀態中,會導致IP地址發生變化,即無法使用固定的IP進行應用訪問;
【Deployment】控制器通過管理ReplicaSet間接實現Pod管理,比如發佈方式,更新和回滾策略,維持Pod副本數量,對應用進行快速的編排,但是並沒有涉及應用的訪問;
【Service】是將運行在一個或一組Pod上的網絡應用程序公開爲網絡服務的方法,可以在不修改現有應用程序的情況下,使用服務發現機制訪問到該應用;
基於Pod、Deployment、Service三個組件的協作,同一個應用的部署腳本可以在開發、測試、生產不同環境中複用;
2、基礎語法
這裏提供一個簡單的【Service】語法做參考;
需要注意的是:在該腳本中沒有指定服務類型即ServiceType
,默認採用的是ClusterIP
,通過集羣的內部IP暴露服務,選擇該值時服務只能夠在集羣內部訪問;
三、內部服務發現
1、Pod創建
基於【Deployment】組件,創建「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
執行創建命令
kubectl apply -f serve-deployment.yaml
2、Service創建
簡單的腳本文件: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
創建【Service】
kubectl apply -f app-service.yaml
查看【Service】,可以使用命令行或者界面;
kubectl describe svc app-service
刪除【Service】
kubectl delete -f app-service.yaml
3、內部訪問
在上面已經說明,當Type
不指定時採用的是ClusterIP
,只能在集羣內部訪問,集羣外部的網絡是無法訪問的;
在【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秒執行一次
*/
@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中查看兩個應用的日誌,請求和響應都正常;
四、外部服務發現
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
創建【Service】
kubectl apply -f app-np-service.yaml
使用NodePort
類型,K8S控制平面會在指定的範圍內分配端口,如果需要特定的端口號可以指定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
創建【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