在 Istio 服務網格內連線外部 MySQL 資料庫

2023-06-15 09:00:29

為了方便理解,以 Istio 官方提供的 Bookinfo 應用範例為例,利用 ratings 服務外部 MySQL 資料庫。

Bookinfo應用的架構圖如下:

其中,包含四個單獨的微服務:

  • productpage:呼叫 detailsreviews 兩個服務,用來生成頁面。
  • details:包含了書籍的資訊。
  • reviews:包含了書籍相關的評論。它還會呼叫 ratings 微服務。
  • rating:包含了由書籍評價組成的評級資訊。

其中,reviews 服務有 3 個版本:

  • v1 版本不會呼叫 ratings 服務。
  • v2 版本會呼叫 ratings 服務,並使用 1 到 5 個黑色星形圖示來顯示評分資訊。
  • v3 版本會呼叫 ratings 服務,並使用 1 到 5 個紅色星形圖示來顯示評分資訊。

準備 MySQL 資料庫

建立一個名為 test 資料庫,執行以下SQL建立表和資料:

DROP TABLE IF EXISTS `ratings`;
CREATE TABLE `ratings`  (
  `ReviewID` int(11) NOT NULL,
  `Rating` int(11) NULL DEFAULT 0,
  PRIMARY KEY (`ReviewID`) USING BTREE
) ENGINE = InnoDB;

INSERT INTO ratings (ReviewID, Rating) VALUES (1, 2);
INSERT INTO ratings (ReviewID, Rating) VALUES (2, 4);

建立ServiceEntry

執行以下命令建立ServiceEntry:

kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: mysqldb
spec:
  hosts:
  - mysqldb.svc.remote
  ports:
  - number: 3306
    name: mysql
    protocol: MySQL
  location: MESH_EXTERNAL
  resolution: STATIC
  endpoints:
  - address: 192.168.1.116
    ports:
      mysql: 3306
EOF

其中,192.168.1.116是 MySQL 資料庫的IP,3306是 MySQL 資料庫的埠。

建立ratings服務

首先,執行以下命令,獲取密碼的Base64編碼:

echo -n 'OneMoreSociety' | base64

其中,OneMoreSociety是連線 MySQL 資料庫的密碼。

然後,執行以下命令,建立 ratings 服務:

kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
  name: mysql-credentials
type: Opaque
data:
  dbpasswd: T25lTW9yZVNvY2lldHk=
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ratings-v2-mysql
  labels:
    app: ratings
    version: v2-mysql
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ratings
      version: v2-mysql
  template:
    metadata:
      labels:
        app: ratings
        version: v2-mysql
    spec:
      containers:
      - name: ratings
        image: docker.io/istio/examples-bookinfo-ratings-v2:1.16.2
        imagePullPolicy: IfNotPresent
        env:
          - name: DB_TYPE
            value: "mysql"
          - name: MYSQL_DB_HOST
            value: mysqldb.svc.remote
          - name: MYSQL_DB_PORT
            value: "3306"
          - name: MYSQL_DB_USER
            value: root
          - name: MYSQL_DB_PASSWORD
            valueFrom:
              secretKeyRef:
                name: mysql-credentials
                key: dbpasswd
        ports:
        - containerPort: 9080
        securityContext:
          runAsUser: 1000
EOF

其中,T25lTW9yZVNvY2lldHk=是連線 MySQL 資料庫的密碼的Base64編碼。

修改路由規則

執行以下命令,把對 reviews 服務的呼叫全部路由到 v2 版本上:

kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
  - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v2
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: reviews
spec:
  host: reviews
  subsets:
    - labels:
        version: v1
      name: v1
    - labels:
        version: v2
      name: v2
    - labels:
        version: v3
      name: v3
EOF

執行以下命令,把對 ratings 服務的呼叫全部路由到 v2-mysql 版本上:

kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: ratings
spec:
  hosts:
  - ratings
  http:
  - route:
    - destination:
        host: ratings
        subset: v2-mysql
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: ratings
spec:
  host: ratings
  subsets:
    - labels:
        version: v1
      name: v1
    - labels:
        version: v2-mysql
      name: v2-mysql
EOF

效果

存取 productpage 頁面,可以看到 Reviewer1 顯示2星, Reviewer2 顯示4星,和資料庫中的資料一致,如下圖:

在Kiali中也可以看到對應的拓撲結構,如下圖:

文章持續更新,微信搜尋「萬貓學社」第一時間閱讀,關注後回覆「電子書」,免費獲取12本Java必讀技術書籍。

流量轉移

存取 MySQL 資料庫時,所有流量都路由到v1版本,具體設定如下:

kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: mysqldb
spec:
  hosts:
  - mysqldb.svc.remote
  ports:
  - number: 3306
    name: tcp
    protocol: TCP
  location: MESH_EXTERNAL
  resolution: STATIC
  endpoints:
  - address: 192.168.1.116
    ports:
      tcp: 3306
    labels:
      version: v1
  - address: 192.168.1.118
    ports:
      tcp: 3306
    labels:
      version: v2
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: mysqldb
spec:
  hosts:
  - mysqldb.svc.remote
  tcp:
  - route:
    - destination:
        host: mysqldb.svc.remote
        subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: mysqldb
spec:
  host: mysqldb.svc.remote
  subsets:
    - labels:
        version: v1
      name: v1
    - labels:
        version: v2
      name: v2
EOF

存取 MySQL 資料庫時,把50%流量轉移到v2版本,具體設定如下:

kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: mysqldb
spec:
  hosts:
  - mysqldb.svc.remote
  tcp:
  - route:
    - destination:
        host: mysqldb.svc.remote
        subset: v1
      weight: 50
    - destination:
        host: mysqldb.svc.remote
        subset: v2
      weight: 50
EOF

存取 MySQL 資料庫時,所有流量都路由到v2版本,具體設定如下:

kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: mysqldb
spec:
  hosts:
  - mysqldb.svc.remote
  tcp:
  - route:
    - destination:
        host: mysqldb.svc.remote
        subset: v2
EOF

最後,感謝你這麼帥,還給我點贊

微信公眾號:萬貓學社

微信掃描二維條碼

關注後回覆「電子書」

獲取12本Java必讀技術書籍