GKE Private Cluster Connect to CloudSQL by Internal IP
採用 all private 方式使用 GKE 與 CloudSQL,需留意 GKE Control Plane 與使用 kubectl 使用者連線端是否 peering。
Scenario
須規劃並留意以下網段並避免 overlap,造成連線上的問題。
- GKE
- Control Plane
- Node
- Pod
- Service
- CloudSQL
實做方式
- private cluster 使用完全封閉式,須透過內網跳板 VM 才可連接
- 連入跳板 VM 時,環境變數須再重貼一次,才可取得 cluster credential
- 建立一個具有 mysqlclient 的 pod 進行連線測試
建立 GKE private cluster and network
- 使用指令方式建立 VPC 網路與 GKE private cluster
- 記得將以下環境變數進行調整
1export NETWORK_NAME="ricky-private-gke"2export SUBNET_NAME="subnet-us-east"3export PROJECT_ID="YOUR_PROJECT_ID"4export REGION="us-east4"5export ZONE="us-east4-c"6export GKE_CLUSTER_NAME="ricky-nat-test-cluster"7export BASTION_VM_NAME="ricky-bastion"8export ROUTER_NAME="ricky-nat-router"9export DB_NAME="ricky-mysql"10export DB_IP_RANGE="10.0.101.0"11export DB_IP_PREFIX="24"12export CP_IP_RANGE="10.0.100.0/28"13export NODE_IP_RANGE="10.0.1.0/24"14export POD_IP_RANGE="10.1.0.0/16"15export SERVICE_IP_RANGE="10.2.0.0/24"16
17# create network18gcloud compute networks create ${NETWORK_NAME} --subnet-mode custom19gcloud compute networks subnets create ${SUBNET_NAME} \20 --network ${NETWORK_NAME} \21 --region ${REGION} \22 --range ${NODE_IP_RANGE} \23 --secondary-range my-pods=${POD_IP_RANGE},my-services=${SERVICE_IP_RANGE} \24 --enable-private-ip-google-access25
26gcloud compute firewall-rules create allow-ssh \27 --network ${NETWORK_NAME} \28 --source-ranges 35.235.240.0/20 \29 --allow tcp:2230
31
32gcloud compute addresses create google-managed-services-${NETWORK_NAME} \33--global \34--purpose=VPC_PEERING \35--addresses=${DB_IP_RANGE} \36--prefix-length=${DB_IP_PREFIX} \37--network=projects/${PROJECT_ID}/global/networks/${NETWORK_NAME}38
39gcloud services vpc-peerings connect \40--service=servicenetworking.googleapis.com \41--ranges=google-managed-services-${NETWORK_NAME} \42--network=${NETWORK_NAME} \43--project=${PROJECT_ID}44
45
46# create private cluster47gcloud container clusters create ${GKE_CLUSTER_NAME} \48 --zone ${ZONE} \49 --cluster-version "latest" \50 --machine-type "n2-standard-2" \51 --disk-type "pd-standard" \52 --disk-size "100" \53 --scopes "https://www.googleapis.com/auth/compute","https://www.googleapis.com/auth/devstorage.read_only","https://www.googleapis.com/auth/logging.write","https://www.googleapis.com/auth/monitoring","https://www.googleapis.com/auth/servicecontrol","https://www.googleapis.com/auth/service.management.readonly","https://www.googleapis.com/auth/trace.append" \54 --num-nodes "1" \55 --enable-private-nodes \56 --enable-private-endpoint \57 --master-ipv4-cidr ${CP_IP_RANGE} \58 --enable-ip-alias \59 --network ${NETWORK_NAME} \60 --subnetwork ${SUBNET_NAME} \61 --max-nodes-per-pool "110" \62 --enable-master-authorized-networks \63 --addons HorizontalPodAutoscaling,HttpLoadBalancing \64 --enable-autoupgrade \65 --enable-autorepair \66 --cluster-secondary-range-name my-pods \67 --services-secondary-range-name my-services \68 --enable-network-policy69
70# create bastion71gcloud compute instances create ${BASTION_VM_NAME} \72 --project=${PROJECT_ID} \73 --zone=${ZONE} \74 --machine-type=e2-micro \75 --network-interface=network-tier=PREMIUM,stack-type=IPV4_ONLY,subnet=${SUBNET_NAME} \76 --maintenance-policy=MIGRATE \77 --provisioning-model=STANDARD \78 --create-disk=auto-delete=yes,boot=yes,device-name=ricky-bastion,image=projects/ubuntu-os-cloud/global/images/ubuntu-2204-jammy-v20230616,mode=rw,size=10,type=projects/${PROJECT_ID}/zones/${ZONE}/diskTypes/pd-balanced \79 --no-shielded-secure-boot \80 --shielded-vtpm \81 --shielded-integrity-monitoring \82 --labels=goog-ec-src=vm_add-gcloud \83 --reservation-affinity=any84
85
86# add bastion ip to GKE control plane allowlist (for external ip only)87export BASTION_IP=$(gcloud compute instances describe ${BASTION_VM_NAME} --zone ${ZONE} --format='get(networkInterfaces[0].networkIP)')88
89gcloud container clusters update ${GKE_CLUSTER_NAME} --zone=${ZONE} \90 --enable-master-authorized-networks \91 --master-authorized-networks ${BASTION_IP}/32設定跳板機
安裝必要套件,會需要等待 5 分鐘左右
1gcloud compute ssh ${BASTION_VM_NAME} --zone ${ZONE} --tunnel-through-iap -- "sudo snap remove google-cloud-cli && \2sudo apt-get update && \3sudo apt-get install apt-transport-https ca-certificates gnupg curl -y && \4curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /usr/share/keyrings/cloud.google.gpg && \5echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list && \6sudo apt-get update && sudo apt-get install google-cloud-cli kubectl google-cloud-cli-gke-gcloud-auth-plugin -y"登入跳板機的 gcloud 帳號
1gcloud compute ssh ${BASTION_VM_NAME} --zone ${ZONE} --tunnel-through-iap -- "gcloud auth login"建立 CloudSQL
使用以下指令建立 CloudSQL,password 部分可依照需求調整
1gcloud beta sql instances create ${DB_NAME} \2--database-version=MYSQL_8_0 \3--tier db-f1-micro \4--region=${REGION} \5--network ${NETWORK_NAME} \6--no-assign-ip \7--allocated-ip-range-name google-managed-services-${NETWORK_NAME} \8--storage-size 109
10gcloud sql users set-password root \11--host=% \12--instance ${DB_NAME} \13--password 1qaz2wsx連線測試
使用 mysql-client 進行連測試
1gcloud compute ssh ${BASTION_VM_NAME} --zone ${ZONE} --tunnel-through-iap2kubectl run mysqlclient --image imega/mysql-client -- sleep 864003DB_IP=$(gcloud sql instances describe ricky-mysql --format='value(ipAddresses[0].ipAddress)')4kubectl exec mysqlclient -- mysql --host=${DB_IP} --user=root --password=1qaz2wsx --execute='show databases;'5# 移除 pod6kubectl delete po mysqlclient預期結果,會出現目前所有的資料庫
1Database2information_schema3mysql4performance_schema5sys