從 Google Kubernetes Engine 連線至 Cloud SQL

本頁面說明如何設定連線,從 Google Kubernetes Engine (GKE) 中執行的應用程式連線至 Cloud SQL 執行個體。

如要瞭解如何逐步執行已連結至 Cloud SQL 的 Google Kubernetes Engine 範例網頁應用程式,請參閱從 Google Kubernetes Engine 連線的快速入門指南

Cloud SQL 是全代管資料庫服務,可協助您在雲端中設定、維護及管理關聯式資料庫。

Google Kubernetes Engine 可讓您輕鬆自動部署、管理 Kubernetes 及調度所需資源。

關於將 Google Kubernetes Engine 連線至 Cloud SQL

如要從 Google Kubernetes Engine 中執行的應用程式存取 Cloud SQL 執行個體,您可以使用 Cloud SQL Auth Proxy (搭配公開或私人 IP),也可以直接使用私人 IP 位址連線。

即使使用私人 IP,我們仍建議您使用 Cloud SQL 驗證 Proxy 連線至 Cloud SQL。這是因為 Cloud SQL Auth Proxy 會使用 IAM 提供強大的加密和驗證機制,有助於確保資料庫安全。

資料庫連線會耗用伺服器與連線中應用程式的資源,因此請務必使用合適的連線管理做法,以便將應用程式耗用的資源降到最低,同時降低超過 Cloud SQL 連線限制的可能性。詳情請參閱「管理資料庫連線」。

事前準備

如要連線至 Cloud SQL,您必須具備下列項目:

  • GKE 叢集,已安裝 kubectl 指令列工具並設為與叢集通訊。

    如需開始使用 GKE 的說明,請參閱「將應用程式部署至 GKE 叢集」。

    如要使用私人 IP 進行連線,GKE 叢集必須是原生 VPC,且與 Cloud SQL 執行個體使用相同的虛擬私有雲 (VPC) 網路進行對等連線。

  • 已建立的執行個體。

    如需建立 Cloud SQL 執行個體的說明,請參閱建立執行個體一文。

  • 執行個體上設有 MySQL 使用者帳戶。

    您的應用程式會使用此帳戶連線至資料庫。如需建立使用者帳戶的說明,請參閱建立使用者

關於 Kubernetes Secret

在 Kubernetes 中,密鑰是將設定詳細資料傳遞至應用程式的安全方式。您可以建立密鑰,其中包含資料庫名稱、使用者和密碼等詳細資料,這些資料可以以環境變數的形式插入應用程式。

視連線類型而定,Secrets 可用於多種情況:

  • 資料庫憑證 Secret 包含您以何人身分連線的資料庫使用者名稱,以及該使用者的資料庫密碼。
  • 如果要連線至 Cloud SQL 驗證 Proxy,您可以使用密碼保管服務帳戶的憑證檔案。
  • 如果使用私人 IP 連線,您可以使用密碼指定 Cloud SQL 執行個體的私人 IP 位址。

如需使用密鑰的完整範例,請參閱本頁後續所提及的 GitHub 存放區。

建立 Secret 物件

  1. 您可以使用 kubectl create secret 指令建立 Secret 物件。

    如要建立資料庫憑證密鑰,請按照下列步驟操作:

    kubectl create secret generic <YOUR-DB-SECRET> \
      --from-literal=username=<YOUR-DATABASE-USER> \
      --from-literal=password=<YOUR-DATABASE-PASSWORD> \
      --from-literal=database=<YOUR-DATABASE-NAME>
    
  2. 建立後,您可以在 Google Cloud 控制台的 Google Kubernetes Engine 頁面「Configuration」部分查看這些物件。

使用 Cloud SQL 驗證 Proxy 連線至 Cloud SQL

使用 Cloud SQL 驗證 Proxy 連線時,Cloud SQL 驗證 Proxy 會使用 sidecar 容器模式新增至 Pod。Cloud SQL 驗證 Proxy 容器與應用程式位於相同的 Pod 中,可讓應用程式使用 localhost 連線至 Cloud SQL 驗證 Proxy,進而提升安全性和效能。

如要進一步瞭解 Cloud SQL 驗證 Proxy,請參閱「關於 Cloud SQL 驗證 Proxy」一文。如要進一步瞭解如何使用 Pod,請參閱 Kubernetes 說明文件中的「Pod 總覽」一節。

如要使用 Cloud SQL 驗證 Proxy 連線,您需要:

  1. Cloud SQL 執行個體的執行個體連線名稱。

    您可以前往 Google Cloud 主控台的「Cloud SQL Instance details」(Cloud SQL 執行個體詳細資料) 頁面,或是使用 gcloud sql instances describe INSTANCE_ID 指令取得執行個體連線名稱。

  2. 具有 Cloud SQL 執行個體適當權限的服務帳戶相關聯的金鑰檔案所在位置。

    詳情請參閱「建立服務帳戶」一文。

  3. Cloud SQL Admin API 已啟用。

    Enable the API

將服務帳戶提供給 Cloud SQL 驗證 Proxy

在 Google Kubernetes Engine 中執行 Cloud SQL 驗證 Proxy 的第一步,是建立代表應用程式的 Google 服務帳戶 (GSA)。建議您為每個應用程式建立專屬的服務帳戶,而非在所有地方都使用相同的服務帳戶。這個模式可讓您針對個別應用程式限制權限,因此更安全。

應用程式的服務帳戶必須符合下列條件:

  • 屬於已啟用 Cloud SQL Admin API 的專案
  • 已針對包含要連線的執行個體的專案,授予 Cloud SQL 用戶端 IAM 角色 (或同等角色)
  • 如果您使用私人 IP 進行連線,則必須使用與 Cloud SQL 執行個體位於相同 VPC 的 VPC 原生 GKE 叢集

您必須設定 GKE,為 Cloud SQL 驗證 Proxy 提供服務帳戶。建議您使用以下兩種方式: 工作負載身分服務帳戶金鑰檔案

Workload Identity

如果您使用 Google Kubernetes Engine,建議使用 GKE 的 Workload Identity 功能。您可以使用這個方法將 Kubernetes 服務帳戶 (KSA) 繫結至 Google 服務帳戶 (GSA)。應用程式就能使用相符的 KSA 存取 GSA。

Google 服務帳戶 (GSA) 是代表您在 Google Cloud 中的應用程式的 IAM 身分。同樣地,Kubernetes 服務帳戶 (KSA) 是代表您在 Google Kubernetes Engine 叢集中的應用程式身分。

Workload Identity 會將 KSA 繫結至 GSA,因此當 KSA 與 Google Cloud 互動時,任何部署都會以 GSA 的身分進行驗證。

  1. 為叢集啟用 Workload Identity
  2. 通常,每個應用程式都有專屬的 ID,由 KSA 和 GSA 組合表示。執行 kubectl apply -f service-account.yaml,為應用程式建立 KSA:

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: <YOUR-KSA-NAME> # TODO(developer): replace these values
  3. 請在 YOUR-GSA-NAMEYOUR-KSA-NAME 之間啟用 IAM 繫結:

    gcloud iam service-accounts add-iam-policy-binding \
    --role="roles/iam.workloadIdentityUser" \
    --member="serviceAccount:YOUR-GOOGLE-CLOUD-PROJECT.svc.id.goog[YOUR-K8S-NAMESPACE/YOUR-KSA-NAME]" \
    YOUR-GSA-NAME@YOUR-GOOGLE-CLOUD-PROJECT.iam.gserviceaccount.com
  4. 將註解新增至 YOUR-KSA-NAME,完成繫結:

    kubectl annotate serviceaccount \
    YOUR-KSA-NAME \
    iam.gke.io/gcp-service-account=YOUR-GSA-NAME@YOUR-GOOGLE-CLOUD-PROJECT.iam.gserviceaccount.com
  5. 最後,請務必指定 k8s 物件的服務帳戶。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: <YOUR-DEPLOYMENT-NAME>
    spec:
      selector:
        matchLabels:
          app: <YOUR-APPLICATION-NAME>
      template:
        metadata:
          labels:
            app: <YOUR-APPLICATION-NAME>
        spec:
          serviceAccountName: <YOUR-KSA-NAME>

服務帳戶金鑰檔案

或者,如果您無法使用工作負載身分,建議您將服務帳戶金鑰檔案掛載至 Cloud SQL 驗證 Proxy Pod,並使用 --credentials-file 標記。

  1. 為服務帳戶金鑰建立憑證檔案:

    gcloud iam service-accounts keys create ~/key.json \
    --iam-account=YOUR-SA-NAME@project-id.iam.gserviceaccount.com
  2. 將服務帳戶金鑰轉換為 k8s 密鑰

    kubectl create secret generic YOUR-SA-SECRET \
    --from-file=service_account.json=~/key.json
  3. 將密鑰掛接為 k8s 物件的 spec: 底下的磁碟區:

    volumes:
      - name: <YOUR-SA-SECRET-VOLUME>
        secret:
          secretName: <YOUR-SA-SECRET>
  4. 請按照下一節的操作說明,從 Cloud SQL 驗證 Proxy 的 Pod 存取磁碟區。

以邊車模式執行 Cloud SQL 驗證 Proxy

建議您在 sidecar 模式中執行 Cloud SQL 驗證 Proxy (做為與應用程式共用 Pod 的額外容器)。我們建議您採用這種做法,而非執行為獨立服務,原因如下:

  • 避免 SQL 流量在本機上曝光;Cloud SQL 驗證 Proxy 會為傳出連線提供加密功能,但您必須限制傳入連線的曝光程度。
  • 避免單點故障:每個應用程式對資料庫的存取權皆獨立於其他應用程式,因此更具彈性。
  • 限制 Cloud SQL 驗證 Proxy 的存取權,讓您可以為每個應用程式使用 IAM 權限,而非將資料庫公開給整個叢集。
  • 可讓您更精準地設定資源要求範圍。由於 Cloud SQL 驗證 Proxy 會以線性方式消耗資源,因此您可以透過這種模式,更精準地設定資源要求範圍,並在應用程式擴充時,要求相應的資源。

  • 將 Cloud SQL 驗證 Proxy 新增至 initContainers 底下的 Pod 設定:

    initContainers:
      - name: cloud-sql-proxy
        restartPolicy: Always
        # It is recommended to use the latest version of the Cloud SQL Auth Proxy
        # Make sure to update on a regular schedule!
        image: gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.14.1
        args:
          # If connecting from a VPC-native GKE cluster, you can use the
          # following flag to have the proxy connect over private IP
          # - "--private-ip"
    
          # If you are not connecting with Automatic IAM, you can delete
          # the following flag.
          - "--auto-iam-authn"
    
          # Enable structured logging with LogEntry format:
          - "--structured-logs"
    
          # Replace DB_PORT with the port the proxy should listen on
          - "--port=<DB_PORT>"
          - "<INSTANCE_CONNECTION_NAME>"
    
        securityContext:
          # The default Cloud SQL Auth Proxy image runs as the
          # "nonroot" user and group (uid: 65532) by default.
          runAsNonRoot: true
        # You should use resource requests/limits as a best practice to prevent
        # pods from consuming too many resources and affecting the execution of
        # other pods. You should adjust the following values based on what your
        # application needs. For details, see
        # https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
        resources:
          requests:
            # The proxy's memory use scales linearly with the number of active
            # connections. Fewer open connections will use less memory. Adjust
            # this value based on your application's requirements.
            memory: "2Gi"
            # The proxy's CPU use scales linearly with the amount of IO between
            # the database and the application. Adjust this value based on your
            # application's requirements.
            cpu: "1"

    如果您使用服務帳戶金鑰,請指定您的機密磁碟區,並在指令中加入 --credentials-file 標記:

      # This flag specifies where the service account key can be found
      - "--credentials-file=/secrets/service_account.json"
    securityContext:
      # The default Cloud SQL Auth Proxy image runs as the
      # "nonroot" user and group (uid: 65532) by default.
      runAsNonRoot: true
    volumeMounts:
      - name: <YOUR-SA-SECRET-VOLUME>
        mountPath: /secrets/
        readOnly: true
  • 如果您使用IAM 資料庫驗證,請使用 --auto-iam-authn 標記啟動 Cloud SQL Auth Proxy。
  • 最後,請將應用程式設定為使用 127.0.0.1 連線至您在指令部分指定的 DB_PORT

完整的設定檔範例:

Workload Identity

# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: <YOUR-DEPLOYMENT-NAME>
spec:
  selector:
    matchLabels:
      app: <YOUR-APPLICATION-NAME>
  template:
    metadata:
      labels:
        app: <YOUR-APPLICATION-NAME>
    spec:
      serviceAccountName: <YOUR-KSA-NAME>
      containers:
        - name: <YOUR-APPLICATION-NAME>
          # ... other container configuration
          env:
            - name: DB_USER
              valueFrom:
                secretKeyRef:
                  name: <YOUR-DB-SECRET>
                  key: username
            - name: DB_PASS
              valueFrom:
                secretKeyRef:
                  name: <YOUR-DB-SECRET>
                  key: password
            - name: DB_NAME
              valueFrom:
                secretKeyRef:
                  name: <YOUR-DB-SECRET>
                  key: database
      initContainers:
        - name: cloud-sql-proxy
          restartPolicy: Always
          # It is recommended to use the latest version of the Cloud SQL Auth Proxy
          # Make sure to update on a regular schedule!
          image: gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.14.1
          args:
            # If connecting from a VPC-native GKE cluster, you can use the
            # following flag to have the proxy connect over private IP
            # - "--private-ip"

            # If you are not connecting with Automatic IAM, you can delete
            # the following flag.
            - "--auto-iam-authn"

            # Enable structured logging with LogEntry format:
            - "--structured-logs"

            # Replace DB_PORT with the port the proxy should listen on
            - "--port=<DB_PORT>"
            - "<INSTANCE_CONNECTION_NAME>"

          securityContext:
            # The default Cloud SQL Auth Proxy image runs as the
            # "nonroot" user and group (uid: 65532) by default.
            runAsNonRoot: true
          # You should use resource requests/limits as a best practice to prevent
          # pods from consuming too many resources and affecting the execution of
          # other pods. You should adjust the following values based on what your
          # application needs. For details, see
          # https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
          resources:
            requests:
              # The proxy's memory use scales linearly with the number of active
              # connections. Fewer open connections will use less memory. Adjust
              # this value based on your application's requirements.
              memory: "2Gi"
              # The proxy's CPU use scales linearly with the amount of IO between
              # the database and the application. Adjust this value based on your
              # application's requirements.
              cpu: "1"

服務帳戶金鑰

# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: <YOUR-DEPLOYMENT-NAME>
spec:
  selector:
    matchLabels:
      app: <YOUR-APPLICATION-NAME>
  template:
    metadata:
      labels:
        app: <YOUR-APPLICATION-NAME>
    spec:
      containers:
        - name: <YOUR-APPLICATION-NAME>
          # ... other container configuration
          env:
            - name: DB_USER
              valueFrom:
                secretKeyRef:
                  name: <YOUR-DB-SECRET>
                  key: username
            - name: DB_PASS
              valueFrom:
                secretKeyRef:
                  name: <YOUR-DB-SECRET>
                  key: password
            - name: DB_NAME
              valueFrom:
                secretKeyRef:
                  name: <YOUR-DB-SECRET>
                  key: database
      initContainers:
        - name: cloud-sql-proxy
          restartPolicy: Always
          # It is recommended to use the latest version of the Cloud SQL Auth Proxy
          # Make sure to update on a regular schedule!
          image: gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.14.1
          args:
            # If connecting from a VPC-native GKE cluster, you can use the
            # following flag to have the proxy connect over private IP
            # - "--private-ip"

            # If you are not connecting with Automatic IAM AuthN, you can delete
            # the following flag.
            - "--auto-iam-authn"

            # Enable structured logging with LogEntry format:
            - "--structured-logs"

            # Replace DB_PORT with the port the proxy should listen on
            - "--port=<DB_PORT>"
            - "<INSTANCE_CONNECTION_NAME>"

            # This flag specifies where the service account key can be found
            - "--credentials-file=/secrets/service_account.json"
          securityContext:
            # The default Cloud SQL Auth Proxy image runs as the
            # "nonroot" user and group (uid: 65532) by default.
            runAsNonRoot: true
          volumeMounts:
            - name: <YOUR-SA-SECRET-VOLUME>
              mountPath: /secrets/
              readOnly: true
          # Resource configuration depends on an application's requirements. You
          # should adjust the following values based on what your application
          # needs. For details, see https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
          resources:
            requests:
              # The proxy's memory use scales linearly with the number of active
              # connections. Fewer open connections will use less memory. Adjust
              # this value based on your application's requirements.
              memory: "2Gi"
              # The proxy's CPU use scales linearly with the amount of IO between
              # the database and the application. Adjust this value based on your
              # application's requirements.
              cpu: "1"
      volumes:
        - name: <YOUR-SA-SECRET-VOLUME>
          secret:
            secretName: <YOUR-SA-SECRET>

不使用 Cloud SQL 驗證 Proxy 連線至 Cloud SQL

雖然安全性較低,但您可以使用私人 IP,從VPC 原生 GKE 叢集連線至位於相同 VPC 的 Cloud SQL 執行個體,而無需使用 Cloud SQL 驗證 Proxy。

  1. 使用執行個體的私人 IP 位址建立機密:

    kubectl create secret generic <YOUR-PRIVATE-IP-SECRET> \
        --from-literal=db_host=<YOUR-PRIVATE-IP-ADDRESS>
    
  2. 接著,請務必將密鑰新增至應用程式的容器:

    - name: DB_HOST
      valueFrom:
        secretKeyRef:
          name: <YOUR-PRIVATE-IP-SECRET>
          key: db_host
  3. 最後,請設定應用程式,以便使用 DB_HOST 環境變數中的 IP 位址連線。您必須使用 MySQL 的正確通訊埠:3306

完整的設定檔範例:

私人 IP

# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: <YOUR-DEPLOYMENT-NAME>
spec:
  selector:
    matchLabels:
      app: <YOUR-APPLICATION-NAME>
  template:
    metadata:
      labels:
        app: <YOUR-APPLICATION-NAME>
    spec:
      containers:
      - name: <YOUR-APPLICATION-NAME>
        # ... other container configuration
        env:
        - name: DB_USER
          valueFrom:
            secretKeyRef:
              name: <YOUR-DB-SECRET>
              key: username
        - name: DB_PASS
          valueFrom:
            secretKeyRef:
              name: <YOUR-DB-SECRET>
              key: password
        - name: DB_NAME
          valueFrom:
            secretKeyRef:
              name: <YOUR-DB-SECRET>
              key: database
        - name: DB_HOST
          valueFrom:
            secretKeyRef:
              name: <YOUR-PRIVATE-IP-SECRET>
              key: db_host

疑難排解

需要協助嗎?如需針對 Proxy 進行疑難排解,請參閱「Cloud SQL 驗證 Proxy 連線疑難排解」一文,或造訪 Cloud SQL 支援頁面。

後續步驟