從 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 Auth Proxy 連線,則可使用 Secret 保存服務帳戶的憑證檔案。
  • 如要使用私人 IP 連線,可以透過 Secret 指定 Cloud SQL 執行個體的私人 IP 位址。

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

建立 Secret 物件

  1. 您可以使用 kubectl create secret 指令建立 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 頁面中,查看「設定」部分中的物件。

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

使用 Cloud SQL 驗證 Proxy 連線時,系統會使用 sidecar 容器模式,將 Cloud SQL 驗證 Proxy 新增至 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 console 的「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 連線,您必須使用 VPC 原生 GKE 叢集,且該叢集與 Cloud SQL 執行個體位於相同的 VPC

您需要設定 GKE,將服務帳戶提供給 Cloud SQL Auth Proxy。建議您採用以下兩種方式: 工作負載身分服務帳戶金鑰檔案

Workload Identity

如果您使用 Google Kubernetes Engine,建議使用 GKE 的工作負載身分功能。這個方法可讓您將 Kubernetes 服務帳戶 (KSA) 繫結至 Google 服務帳戶 (GSA)。應用程式隨後就能使用相符的 KSA 存取 GSA。

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

Workload Identity 會將 KSA 繫結至 GSA,導致任何具有該 KSA 的部署作業在與 Google Cloud 互動時,都會以 GSA 的身分進行驗證。

  1. 為叢集啟用 Workload Identity
  2. 通常每個應用程式都有自己的身分,以 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>

服務帳戶金鑰檔案

如果無法使用 Workload Identity,建議採用以下模式:將服務帳戶金鑰檔案掛接至 Cloud SQL Auth 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 Secret

    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 Auth Proxy 會根據用量線性消耗資源,因此這個模式可讓您更準確地設定資源範圍並要求資源,以配合應用程式的擴充。

  • initContainers 下,將 Cloud SQL 驗證 Proxy 新增至 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 資料庫驗證,請將 IAM 政策繫結新增至服務帳戶。將 Cloud SQL 執行個體使用者 (role/cloudsql.instanceUser) 和 Cloud SQL 用戶端 (role/cloudsql.client) 角色授予 Cloud SQL Auth Proxy 使用的服務帳戶。

  • 如要使用 IAM 資料庫驗證功能自動登入執行個體,請使用 --auto-iam-authn 旗標啟動 Cloud SQL Auth Proxy。

  • 最後,請設定應用程式,使用指令部分指定的 DB_PORT 連線。127.0.0.1

完整的設定檔範例:

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,但不要使用 Cloud SQL 驗證 Proxy

雖然安全性較低,但您可以從虛擬私有雲原生 GKE 叢集連線至相同虛擬私有雲中的 Cloud SQL 執行個體,使用私人 IP 而不透過 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 支援頁面。

後續步驟