K8S | Service服務發現

服務發現與負載均衡。

一、背景

在微服務架構中,這裏以開發環境「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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章