GKE + CloudSQL MYSQL实例上的Wordpress部署-MySQL连接错误:(2002)连接被拒绝

时间:2020-08-16 20:33:58

标签: mysql kubernetes google-cloud-platform google-kubernetes-engine google-cloud-sql

我正在尝试完成以下教程,以在GKE上部署Wordpress: https://cloud.google.com/kubernetes-engine/docs/tutorials/persistent-disk

我已经使用terraform来配置gcp资源,而不是本教程建议的gcp。这是导致CrashLoopBackOff状态的部署。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: wordpress
  labels:
    app: wordpress
spec:
  replicas: 1
  selector:
    matchLabels:
      app: wordpress
  template:
    metadata:
      labels:
        app: wordpress
    spec:
      containers:
        - image: wordpress
          name: wordpress
          env:
          - name: WORDPRESS_DB_HOST
            value: 127.0.0.1:3306
          # These secrets are required to start the pod.
          - name: WORDPRESS_DB_USER
            valueFrom:
              secretKeyRef:
                name: cloudsql-db-credentials
                key: username
          - name: WORDPRESS_DB_PASSWORD
            valueFrom:
              secretKeyRef:
                name: cloudsql-db-credentials
                key: password
          ports:
            - containerPort: 80
              name: wordpress
          volumeMounts:
            - name: wordpress-persistent-storage
              mountPath: /var/www/html
        # Change archtek-wordpress:us-west1:archtek-wordpress-postgres-instance here to include your GCP
        # project, the region of your Cloud SQL instance and the name
        # of your Cloud SQL instance. The format is
        # ::
        - name: cloudsql-proxy
          image: gcr.io/cloudsql-docker/gce-proxy:1.11
          command: ["/cloud_sql_proxy",
                    "-instances=archtek-wordpress:us-west1:archtek-wordpress-mysql-instance=tcp:3306",
                    # If running on a VPC, the Cloud SQL proxy can connect via Private IP. See:
                    # https://cloud.google.com/sql/docs/mysql/private-ip for more info.
                    # "-ip_address_types=PRIVATE",
                    "-credential_file=/secrets/cloudsql/key.json"]
          securityContext:
            runAsUser: 2  # non-root user
            allowPrivilegeEscalation: false
          volumeMounts:
            - name: cloudsql-instance-credentials
              mountPath: /secrets/cloudsql
              readOnly: true
          imagePullPolicy: Always
      volumes:
        - name: wordpress-persistent-storage
          persistentVolumeClaim:
            claimName: wordpress-volumeclaim
        - name: cloudsql-instance-credentials
          secret:
            secretName: cloudsql-instance-credentials

当我描述吊舱时,我在日志中看到以下内容:

wordpress-54c68dbf59-5djfx wordpress MySQL Connection Error: (2002) Connection refused

要排除凭据无效的想法,我使用了用于创建cloudsql-db-credentials(在部署yaml中引用的k8s机密)的用户名和密码,然后运行了该密码。

$: gcloud sql connect archtek-wordpress-mysql-instance -u wordpress

我可以连接,没问题。但是我发现我也无法做到这一点:

$: mysql -u wordpress -p'$CLOUD_SQL_PASSWORD' \                                                                    ()
    -h 35.197.7.98       -P 3306 \
    -D archtek-wordpress:us-west1:archtek-wordpress-mysql-instance -v

返回:

ERROR 2003 (HY000): Can't connect to MySQL server on '35.197.7.98' (60)

我知道,当使用gcloud客户端连接到cloudsql数据库时,它会在身份验证之前的5分钟内将IP列入白名单,这也许可以解释为什么mysql客户端无法身份验证的原因。但是,我不确定这个理由是否可以支持我在集群中的部署。是否也需要将白名单列入cloudsql以接受身份验证请求?

这是用于配置cloudsql实例的terraform文件:

resource "google_sql_database_instance" "postgres" {
  name             = "archtek-wordpress-mysql-instance"
  database_version = "MYSQL_5_7"
  settings {
    tier              = "db-f1-micro"
    availability_type = "ZONAL"
  }
}

1 个答案:

答案 0 :(得分:2)

在尝试从/* 1 */ { "_id" : ObjectId("5f4c93478ac8f4f9d79151bd"), "property" : "prop_1", "created" : ISODate("2020-01-01T22:00:00.000Z") } 群集进行外部连接时遇到的错误:

ERROR 2003(HY000):无法连接到'35 .197.7.98'(60)上的MySQL服务器

这是因为您所连接的站点(IP)没有被授权这样做。使用:

  • GKE

允许在5分钟内连接到$ gcloud sql connect ...实例。

SQL中使用CloudSQL proxy时,无需授权您要连接的网络。

您可以在GKE中看到授权部分。

此外,您还可以查看Pod(GCP -> SQL -> Instance -> Connectionswordpress)的日志,以确定哪个Pod引起了问题(cloudsql-proxy除外):

  • $ kubectl describe

有关$ kubectl logs POD_NAME -c wordpressCloudSQL的更多参考:


假设您在github页面上使用sql-proxy文件为CloudSQL实例创建了用户,则可能是失败的原因。负责创建用户.tf的部分的主机参数错误(下面的示例已编辑):

wordpress

我无法使用以下参数连接到服务器:resource "google_sql_user" "users" { name = "wordpress" instance = google_sql_database_instance.postgres.name # host = "*" <- BAD host = "%" # <- GOOD password = random_password.password.result } 。将其从host = "*"更改为"*"解决了我的问题。


我设法创建了"%"文件,这些文件与官方.tf指南中的部分类似:

将Terraform连接到GKE项目的指南:

使用的文件:

  • GCP
  • main.tf-创建一个vpc.tf(基于评论中链接的github)
  • VPC-在新的gke.tf
  • 中创建一个GKE集群
  • VPC-创建一个mysql.tf实例和一个用户CloudSQL
  • wordpress-为pvc.tf部署创建PVC
  • Wordpress-创建一个sa.tf并将其绑定到访问ServiceAccount实例所需的权限
  • CloudSQL-为上方secret.tf创建密钥,并为ServiceAccountKubernetes吊舱创建Wordpress机密
  • CloudSQL-创建将运行deployment.tfWordpress
  • 的部署

每次添加新文件时(按上述顺序),我都会执行以下命令:

  • cloudsql-proxy
  • $ terraform init

$ terraform apply

main.tf

provider "google" { project = "ENTER-YOUR-PROJECT-ID" region = "europe-west3" zone = "europe-west3-c" } variable project { type = string default = "ENTER-YOUR-PROJECT-ID" } variable zone { type = string default = "europe-west3-c" } variable region { type = string default = "europe-west3" }

vpc.tf

resource "google_compute_network" "terraform-network" { name = "terraform-network" auto_create_subnetworks = "false" } resource "google_compute_subnetwork" "terraform-subnet" { name = "terraform-subnet" region = var.region network = google_compute_network.terraform-network.name ip_cidr_range = "10.0.0.0/24" }

gke.tf

我也跑了:

  • resource "google_container_cluster" "gke-terraform" { name = "gke-terraform" location = var.zone initial_node_count = 1 network = google_compute_network.terraform-network.name subnetwork = google_compute_subnetwork.terraform-subnet.name }

$ gcloud container clusters get-credentials gke-terraform --zone=europe-west3-c

mysql.tf

resource "google_sql_database_instance" "cloudsql" { name = "cloudsql-terraform" database_version = "MYSQL_5_7" settings { tier = "db-f1-micro" availability_type = "ZONAL" } } data "google_sql_database_instance" "cloudsql" { name = "cloudsql-terraform" } resource "random_password" "wordpress-cloudsql-password" { length = 18 special = true override_special = "_%@" } resource "local_file" "password-file" { content = random_password.wordpress-cloudsql-password.result filename = "./password-file" } resource "google_sql_user" "cloudsql-wordpress-user" { name = "wordpress" instance = google_sql_database_instance.cloudsql.name host = "%" password = random_password.wordpress-cloudsql-password.result }

pvc.tf

resource "google_compute_disk" "terraform-pd" { name = "terraform-disk" type = "pd-standard" zone = "europe-west3-c" } resource "kubernetes_persistent_volume" "terraform-pv" { metadata { name = "wordpress-pv" } spec { capacity = { storage = "10Gi" } storage_class_name = "standard" access_modes = ["ReadWriteOnce"] persistent_volume_source { gce_persistent_disk { pd_name = google_compute_disk.terraform-pd.name } } } } resource "kubernetes_persistent_volume_claim" "terraform-pvc" { metadata { name = "wordpress-pvc" } spec { access_modes = ["ReadWriteOnce"] storage_class_name = "standard" resources { requests = { storage = "10Gi" } } volume_name = kubernetes_persistent_volume.terraform-pv.metadata.0.name } }

sa.tf

resource "google_service_account" "cloudsql-proxy-terraform" { account_id = "cloudsql-proxy-terraform" display_name = "cloudsql-proxy-terraform" } data "google_service_account" "cloudsql-proxy-terraform" { account_id = "cloudsql-proxy-terraform" } resource "google_project_iam_binding" "cloudsql-proxy-binding" { project = var.project role = "roles/cloudsql.client" members = [ "serviceAccount:${google_service_account.cloudsql-proxy-terraform.email}", ] }

secret.tf

resource "google_service_account_key" "cloudsql-proxy-key" { service_account_id = google_service_account.cloudsql-proxy-terraform.name } resource "kubernetes_secret" "cloudsql-instance-credentials-terraform" { metadata { name = "cloudsql-instance-credentials-terraform" } data = { "key.json" = base64decode(google_service_account_key.cloudsql-proxy-key.private_key) } } resource "kubernetes_secret" "cloudsql-db-credentials-terraform" { metadata { name = "cloudsql-db-credentials-terraform" } data = { "username" = "wordpress" "password" = random_password.wordpress-cloudsql-password.result } }

deployment.tf

在检查资源是否正确创建(resource "kubernetes_deployment" "wordpress-deployment" { metadata { name = "wordpress-deployment" labels = { app = "wordpress" } } spec { replicas = 1 selector { match_labels = { app = "wordpress" } } template { metadata { labels = { app = "wordpress" } } spec { container { image = "wordpress" name = "wordpress" env { name = "WORDPRESS_DB_HOST" value = "127.0.0.1:3306" } env { name = "WORDPRESS_DB_USER" value_from { secret_key_ref { name = kubernetes_secret.cloudsql-db-credentials-terraform.metadata.0.name key = "username" } } } env { name = "WORDPRESS_DB_PASSWORD" value_from { secret_key_ref { name = kubernetes_secret.cloudsql-db-credentials-terraform.metadata.0.name key = "password" } } } port { name = "http" container_port = 80 protocol = "TCP" } volume_mount { mount_path = "/var/www/html" name = "wordpress-persistent-storage" } } container { image = "gcr.io/cloudsql-docker/gce-proxy:1.11" name = "cloudsql-proxy" command = ["/cloud_sql_proxy", "-instances=${google_sql_database_instance.cloudsql.connection_name}=tcp:3306", "-credential_file=/secrets/cloudsql/key.json"] security_context { run_as_user = 2 allow_privilege_escalation = "false" } volume_mount { mount_path = "/secrets/cloudsql" name = "cloudsql-instance-credentials-terraform" read_only = "true" } } volume { name = "wordpress-persistent-storage" persistent_volume_claim { claim_name = "wordpress-pvc" } } volume { name = "cloudsql-instance-credentials-terraform" secret { secret_name = "cloudsql-instance-credentials-terraform" } } } } } } )之后,可以使用以下内容公开$ kubectl logs POD_NAME -c CONTAINER_NAME

  • Wordpress