Go中来自Kubernetes的Cloud SQL连接-错误403:权限不足

时间:2018-08-08 15:38:29

标签: go kubernetes google-cloud-platform google-cloud-sql

我需要使用Go从Kubernetes容器连接到Google Cloud SQL。

我一直认真地遵循以下指南: https://cloud.google.com/sql/docs/mysql/connect-kubernetes-engine https://cloud.google.com/sql/docs/mysql/connect-external-app#go

这是我的 Kubernetes部署Yaml 文件:

---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: my-service
  labels:
    app: my-service
spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 10%
      maxSurge: 10%
  replicas: 1
  template:
    metadata:
      labels:
        app: my-service
    spec:
      imagePullSecrets:
      - name: regsecret
      containers:
      - name: my-service
        image: my-image
        imagePullPolicy: IfNotPresent
        env:
          - name: DB_INSTANCE
            value: "my-project-id:europe-west1:uk"
          - name: DB_USERNAME
            valueFrom:
              secretKeyRef:
                name: cloudsql-db-credentials
                key: username
          - name: DB_PASSWORD
            valueFrom:
              secretKeyRef:
                name: cloudsql-db-credentials
                key: password
      - name: cloudsql-proxy
        image: gcr.io/cloudsql-docker/gce-proxy:1.11
        command: ["/cloud_sql_proxy",
                  "-instances=my-project-id:europe-west1:uk=tcp:3306",
                  "-credential_file=/secrets/cloudsql/credentials.json"]
        volumeMounts:
          - name: cloudsql-instance-credentials
            mountPath: /secrets/cloudsql
            readOnly: true
      volumes:
        - name: cloudsql-instance-credentials
          secret:
            secretName: cloudsql-instance-credentials

这是我尝试使用 Go 进行连接:

import (
    "github.com/GoogleCloudPlatform/cloudsql-proxy/proxy/dialers/mysql"
    "github.com/spf13/viper"
    "log"
)

func Connect() {
    cfg := mysql.Cfg(
        viper.GetString("DB_INSTANCE"),
        viper.GetString("DB_USERNAME"),
        viper.GetString("DB_PASSWORD"))
    cfg.DBName = "my-db-name"

    db, err := mysql.DialCfg(cfg)
    if err != nil {
        log.Fatalf("Failed to create the Cloud SQL client: %v", err)
    }
}

不幸的是,运行此代码会导致:

2018/08/08 15:19:45 Failed to create the Cloud SQL client: ensure that the Cloud SQL API is enabled for your project (https://console.cloud.google.com/flows/enableapi?apiid=sqladmin). Error during createEphemeral for my-project-id:europe-west1:uk: googleapi: Error 403: Insufficient Permission, insufficientPermissions

我可以确认该数据库显然存在于Cloud SQL中,确实已启用 Cloud SQL API ,以及我用来生成凭据的服务帐户(如上面的链接所述)确实附加了 Cloud SQL Client 角色(我也曾尝试过Cloud SQL Admin甚至项目所有者,但都没有成功)。

我想念什么?

编辑:

通过将我的Go代码更新为以下内容来修复:

dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s",
    viper.GetString("DB_USERNAME"),
    viper.GetString("DB_PASSWORD"),
    "127.0.0.1:3306",
    "my-db-name")
db, err := sql.Open("mysql", dsn)
if err != nil {
    log.Fatalf("Failed to create the Cloud SQL client: %v", err)
}

感谢@DazWilkin的提示。

1 个答案:

答案 0 :(得分:1)

我知道您已经解决了您的问题,但是想为其他阅读此主题的人提供另一种选择。

有两种方法可以连接到实例: 1:通过TCP连接:您已经有了该解决方案,this page向您显示了详细信息。由于云SQL代理容器与您的应用容器在同一容器上运行,因此您的主机应指向localhost。 2:Unix套接字:

您还应该能够通过以下代码(details here)进行连接:

import (
       "database/sql"
        _ "github.com/go-sql-driver/mysql"
)

dsn := fmt.Sprintf("%s:%s@unix(/cloudsql/%s)/%s",
       dbUser,
       dbPassword,
       INSTANCE_CONNECTION_NAME,
       dbName)
db, err := sql.Open("mysql", dsn)

您可能必须通过以下步骤从您的deployment.yaml文件中删除=tcp:3306部分。