Men-deploy cluster MySQL stateful di GKE


Dokumen ini ditujukan untuk administrator database, arsitek cloud, dan profesional operasi yang tertarik untuk men-deploy topologi MySQL yang sangat tersedia di Google Kubernetes Engine.

Ikuti tutorial ini untuk mempelajari cara men-deploy Cluster InnoDB MySQL dan MySQL InnoDB ClusterSet, selain middleware MySQL Router di cluster GKE Anda, dan cara melakukan upgrade.

Tujuan

Dalam tutorial ini, Anda akan mempelajari cara:

  • Membuat dan men-deploy layanan Kubernetes stateful.
  • Men-deploy Cluster InnoDB MySQL untuk ketersediaan tinggi.
  • Men-deploy middleware Router untuk perutean operasi database.
  • Men-deploy ClusterSet InnoDB MySQL untuk toleransi bencana.
  • Menyimulasikan failover cluster MySQL.
  • Melakukan upgrade versi MySQL.

Bagian berikut menjelaskan arsitektur solusi yang akan Anda buat dalam tutorial ini.

Cluster InnoDB MySQL

Di cluster GKE regional, dengan menggunakan StatefulSet, Anda men-deploy instance database MySQL dengan penamaan dan konfigurasi yang diperlukan untuk membuat Cluster InnoDB MySQL. Untuk memberikan fault tolerance dan ketersediaan tinggi, Anda harus men-deploy tiga Pod instance database. Hal ini memastikan sebagian besar Pod di zona yang berbeda tersedia pada waktu tertentu untuk pemilu primer yang sukses menggunakan protokol konsensus, dan membuat Cluster MySQL InnoDB Anda toleran terhadap kegagalan zona tunggal.

Diagram arsitektur yang menunjukkan hubungan antara aplikasi, Router MySQL, dan Cluster MySQL
Gambar 1: Contoh arsitektur Cluster InnoDB MySQL tunggal

Setelah di-deploy, Anda menetapkan satu Pod sebagai instance utama untuk menyalurkan operasi baca dan tulis. Dua Pod lainnya adalah replika sekunder hanya baca. Jika instance utama mengalami kegagalan infrastruktur, Anda dapat mempromosikan salah satu dari dua Pod replika ini untuk menjadi yang utama.

Dalam namespace terpisah, Anda men-deploy tiga Pod Router MySQL untuk memberikan perutean koneksi guna meningkatkan ketahanan. Alih-alih terhubung langsung ke layanan database, aplikasi Anda terhubung ke Pod Router MySQL. Setiap Pod Router mengetahui status dan tujuan setiap Pod Cluster InnoDB MySQL, dan merutekan operasi aplikasi ke masing-masing Pod yang responsif. Status perutean disimpan dalam cache di Pod Router dan diperbarui dari metadata cluster yang disimpan di setiap node Cluster InnoDB MySQL. Jika terjadi kegagalan instance, Router akan menyesuaikan pemilihan rute koneksi ke instance langsung.

ClusterSet InnoDB MySQL

Anda dapat membuat ClusterSet InnoDB MySQL dari Cluster InnoDB MySQL awal. Dengan demikian, Anda dapat meningkatkan toleransi bencana jika cluster utama tidak lagi tersedia.

Diagram menunjukkan cara Cluster InnoDB MySQL utama dan replika terus disinkronkan melalui replikasi asinkron.
Gambar 2: Contoh arsitektur ClusterSet multi-region yang berisi satu cluster utama dan satu cluster replika

Jika instance utama Cluster InnoDB MySQL tidak lagi tersedia, Anda dapat mempromosikan cluster replika di ClusterSet menjadi utama. Saat menggunakan middleware Router MySQL, aplikasi Anda tidak perlu melacak kondisi instance database utama. Pemilihan rute disesuaikan untuk mengirim koneksi ke cluster primer baru setelah pemilihan dilakukan. Namun, Anda bertanggung jawab untuk memastikan bahwa aplikasi yang terhubung ke middleware Router MySQL Anda mengikuti praktik terbaik untuk ketahanan, sehingga koneksi akan dicoba ulang jika terjadi error selama failover cluster.

Biaya

Dalam dokumen ini, Anda menggunakan komponen Google Cloud yang dapat ditagih berikut:

Untuk membuat perkiraan biaya berdasarkan proyeksi penggunaan Anda, gunakan kalkulator harga. Pengguna baru Google Cloud mungkin memenuhi syarat untuk mendapatkan uji coba gratis.

Setelah menyelesaikan tugas yang dijelaskan dalam dokumen ini, Anda dapat menghindari penagihan berkelanjutan dengan menghapus resource yang Anda buat. Untuk mengetahui informasi selengkapnya, lihat Pembersihan.

Sebelum memulai

Menyiapkan project

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. Di konsol Google Cloud, pada halaman pemilih project, klik Buat project untuk mulai membuat project Google Cloud baru.

    Buka pemilih project

  3. Make sure that billing is enabled for your Google Cloud project.

  4. Aktifkan API GKE.

    Mengaktifkan API

  5. Di konsol Google Cloud, pada halaman pemilih project, klik Buat project untuk mulai membuat project Google Cloud baru.

    Buka pemilih project

  6. Make sure that billing is enabled for your Google Cloud project.

  7. Aktifkan API GKE.

    Mengaktifkan API

Menyiapkan peran

  1. Grant roles to your user account. Run the following command once for each of the following IAM roles: role/storage.objectViewer, role/logging.logWriter, role/artifactregistry.Admin, roles/container.clusterAdmin, role/container.serviceAgent, roles/serviceusage.serviceUsageAdmin, roles/iam.serviceAccountAdmin

    gcloud projects add-iam-policy-binding PROJECT_ID --member="user:USER_IDENTIFIER" --role=ROLE
    • Replace PROJECT_ID with your project ID.
    • Replace USER_IDENTIFIER with the identifier for your user account. For example, user:myemail@example.com.

    • Replace ROLE with each individual role.

Menyiapkan lingkungan Anda

Dalam tutorial ini, Anda akan menggunakan Cloud Shell untuk mengelola resource yang dihosting di Google Cloud. Cloud Shell dilengkapi dengan Docker, kubectl, dan gcloud CLI.

Untuk menggunakan Cloud Shell guna menyiapkan lingkungan Anda:

  1. Menetapkan variabel lingkungan.

    export PROJECT_ID=PROJECT_ID
    export CLUSTER_NAME=gkemulti-west
    export REGION=COMPUTE_REGION
    

    Ganti nilai berikut:

    • PROJECT_ID: project ID Google Cloud Anda.
    • COMPUTE_REGION: region Compute Engine Anda. Untuk tutorial ini, region-nya adalah us-west1. Biasanya, Anda menginginkan wilayah yang dekat dengan Anda.
  2. Tetapkan variabel lingkungan default.

     gcloud config set project PROJECT_ID
     gcloud config set compute/region COMPUTE_REGION
    
  3. Buat clone repositori kode.

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
    
  4. Ubah ke direktori kerja.

    cd kubernetes-engine-samples/databases/gke-stateful-mysql/kubernetes
    

Membuat cluster GKE

Di bagian ini, Anda akan membuat cluster GKE regional. Tidak seperti cluster zona, bidang kontrol cluster regional direplikasi ke beberapa zona, sehingga pemadaman layanan di satu zona tidak membuat bidang kontrol tidak tersedia.

Untuk membuat cluster GKE, ikuti langkah-langkah berikut:

Autopilot

  1. Di Cloud Shell, buat cluster GKE Autopilot di region us-west1.

    gcloud container clusters create-auto $CLUSTER_NAME \
        --region=$REGION
    
  2. Dapatkan kredensial cluster GKE.

    gcloud container clusters get-credentials $CLUSTER_NAME \
      --region=$REGION
    
  3. Deploy Layanan di tiga zona.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: prepare-three-zone-ha
      labels:
        app: prepare-three-zone-ha
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: prepare-three-zone-ha
      template:
        metadata:
          labels:
            app: prepare-three-zone-ha
        spec:
          affinity:
            # Tell Kubernetes to avoid scheduling a replica in a zone where there
            # is already a replica with the label "app: prepare-three-zone-ha"
            podAntiAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
              - labelSelector:
                  matchExpressions:
                  - key: app
                    operator: In
                    values:
                    - prepare-three-zone-ha
                topologyKey: "topology.kubernetes.io/zone"
          containers:
          - name: prepare-three-zone-ha
            image: busybox:latest
            command:
                - "/bin/sh"
                - "-c"
                - "while true; do sleep 3600; done"
            resources:
              limits:
                cpu: "500m"
                ephemeral-storage: "10Mi"
                memory: "0.5Gi"
              requests:
                cpu: "500m"
                ephemeral-storage: "10Mi"
                memory: "0.5Gi"
    kubectl apply -f prepare-for-ha.yaml
    

    Secara default, Autopilot menyediakan sumber daya di dua zona. Deployment yang ditentukan dalam prepare-for-ha.yaml memastikan bahwa Autopilot menyediakan node di tiga zona dalam cluster Anda, dengan menetapkan replicas:3, podAntiAffinity dengan requiredDuringSchedulingIgnoredDuringExecution, dan topologyKey: "topology.kubernetes.io/zone".

  4. Periksa status Deployment.

    kubectl get deployment prepare-three-zone-ha --watch
    

    Jika Anda melihat tiga Pod dalam status siap, batalkan perintah ini dengan CTRL+C. Outputnya mirip dengan hal berikut ini:

    NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
    prepare-three-zone-ha   0/3     3            0           9s
    prepare-three-zone-ha   1/3     3            1           116s
    prepare-three-zone-ha   2/3     3            2           119s
    prepare-three-zone-ha   3/3     3            3           2m16s
    
  5. Jalankan skrip ini untuk memvalidasi bahwa Pod Anda telah di-deploy di tiga zona.

    bash ../scripts/inspect_pod_node.sh default
    

    Setiap baris output sesuai dengan Pod, dan kolom kedua menunjukkan zona cloud. Outputnya mirip dengan hal berikut ini:

    gk3-gkemulti-west1-default-pool-eb354e2d-z6mv us-west1-b prepare-three-zone-ha-7885d77d9c-8f7qb
    gk3-gkemulti-west1-nap-25b73chq-739a9d40-4csr us-west1-c prepare-three-zone-ha-7885d77d9c-98fpn
    gk3-gkemulti-west1-default-pool-160c3578-bmm2 us-west1-a prepare-three-zone-ha-7885d77d9c-phmhj
    

Standar

  1. Di Cloud Shell, buat cluster GKE Standard di region us-west1.

    gcloud container clusters create $CLUSTER_NAME \
      --region=$REGION \
      --machine-type="e2-standard-2" \
      --disk-type="pd-standard" \
      --num-nodes="5"
    
  2. Dapatkan kredensial cluster GKE.

    gcloud container clusters get-credentials $CLUSTER_NAME \
      --region=$REGION
    

Men-deploy StatefulSets MySQL

Di bagian ini, Anda akan men-deploy satu StatefulSet MySQL. Setiap StatefulSet terdiri dari tiga replika MySQL.

Untuk men-deploy StatefulSet MySQL, ikuti langkah-langkah berikut:

  1. Membuat namespace untuk StatefulSet.

    kubectl create namespace mysql1
    
  2. Membuat secret MySQL.

    apiVersion: v1
    kind: Secret
    metadata:
      name: mysql-secret
    type: Opaque
    data:
      password: UGFzc3dvcmQkMTIzNDU2 # Password$123456
      admin-password: UGFzc3dvcmQkMTIzNDU2 # Password$123456
    kubectl apply -n mysql1 -f secret.yaml
    

    Sandi di-deploy dengan setiap Pod, dan digunakan oleh skrip dan perintah pengelolaan untuk Cluster InnoDB MySQL dan deployment ClusterSet dalam tutorial ini.

  3. Membuat StorageClass.

    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: fast-storageclass
    provisioner: pd.csi.storage.gke.io
    volumeBindingMode: WaitForFirstConsumer
    reclaimPolicy: Retain
    allowVolumeExpansion: true
    parameters:
      type: pd-balanced
    kubectl apply -n mysql1 -f storageclass.yaml
    

    Kelas penyimpanan ini menggunakan jenis Persistent Disk pd-balanced yang menyeimbangkan performa dan biaya. Kolom volumeBindingMode disetel ke WaitForFirstConsumer yang berarti GKE menunda penyediaan PersistentVolume hingga Pod dibuat. Setelan ini memastikan bahwa disk disediakan di zona yang sama dengan tempat Pod dijadwalkan.

  4. Men-deploy StatefulSet Pod instance MySQL.

    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: dbc1
      labels:
        app: mysql
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: mysql
      serviceName: mysql
      template:
        metadata:
          labels:
            app: mysql
        spec:
          topologySpreadConstraints:
          - maxSkew: 1
            topologyKey: "topology.kubernetes.io/zone"
            whenUnsatisfiable: DoNotSchedule
            labelSelector:
              matchLabels:
                app: mysql
          affinity:
            podAntiAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
              - labelSelector:
                  matchExpressions:
                  - key: app
                    operator: In
                    values:
                    - mysql
                topologyKey: "kubernetes.io/hostname"
          containers:
          - name: mysql
            image: mysql/mysql-server:8.0.28
            command:
            - /bin/bash
            args:
            - -c
            - >-
              /entrypoint.sh
              --server-id=$((20 +  $(echo $HOSTNAME | grep -o '[^-]*$') + 1))
              --report-host=${HOSTNAME}.mysql.mysql1.svc.cluster.local
              --binlog-checksum=NONE
              --enforce-gtid-consistency=ON
              --gtid-mode=ON
              --default-authentication-plugin=mysql_native_password
            env:
            - name: MYSQL_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mysql-secret
                  key: password
            - name: MYSQL_ADMIN_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mysql-secret
                  key: admin-password
            - name: MYSQL_ROOT_HOST
              value: '%'
            ports:
            - name: mysql
              containerPort: 3306
            - name: mysqlx
              containerPort: 33060
            - name: xcom
              containerPort: 33061
            resources:
              limits:
                cpu: "500m"
                ephemeral-storage: "1Gi"
                memory: "1Gi"
              requests:
                cpu: "500m"
                ephemeral-storage: "1Gi"
                memory: "1Gi"
            volumeMounts:
            - name: mysql
              mountPath: /var/lib/mysql
              subPath: mysql
            readinessProbe:
              exec:
                command:
                - bash
                - "-c"
                - |
                  mysql -h127.0.0.1 -uroot -p$MYSQL_ROOT_PASSWORD -e'SELECT 1'
              initialDelaySeconds: 30
              periodSeconds: 2
              timeoutSeconds: 1
            livenessProbe:
              exec:
                command:
                - bash
                - "-c"
                - |
                  mysqladmin -uroot -p$MYSQL_ROOT_PASSWORD ping
              initialDelaySeconds: 30
              periodSeconds: 10
              timeoutSeconds: 5
      updateStrategy:
        rollingUpdate:
          partition: 0
        type: RollingUpdate
      volumeClaimTemplates:
      - metadata:
          name: mysql
          labels:
            app: mysql
        spec:
          storageClassName: fast-storageclass
          volumeMode: Filesystem
          accessModes:
          - ReadWriteOnce
          resources:
            requests:
              storage: 10Gi
    kubectl apply -n mysql1 -f c1-mysql.yaml
    

    Perintah ini men-deploy StatefulSet yang terdiri dari tiga replika. Dalam tutorial ini, cluster MySQL utama di-deploy di tiga zona pada us-west1. Outputnya mirip dengan hal berikut ini:

    service/mysql created
    statefulset.apps/dbc1 created
    

    Dalam tutorial ini, batas dan permintaan resource ditetapkan ke nilai minimum untuk menghemat biaya. Saat merencanakan beban kerja produksi, pastikan untuk menetapkan nilai ini dengan tepat sesuai kebutuhan organisasi Anda.

  5. Pastikan StatefulSet berhasil dibuat.

    kubectl get statefulset -n mysql1 --watch
    

    Perlu waktu sekitar 10 menit hingga StatefulSet siap.

  6. Jika ketiga pod dalam status siap, keluar dari perintah menggunakan Ctrl+C. Jika Anda melihat error PodUnscheduleable karena CPU atau memori tidak mencukupi, tunggu beberapa menit agar ukuran bidang kontrol diubah untuk mengakomodasi beban kerja yang besar.

    Outputnya mirip dengan hal berikut ini:

    NAME   READY   AGE
    dbc1   1/3     39s
    dbc1   2/3     50s
    dbc1   3/3     73s
    
  7. Untuk memeriksa penempatan Pod di node cluster GKE, jalankan skrip ini:

    bash ../scripts/inspect_pod_node.sh mysql1 mysql
    

    Output menunjukkan nama Pod, nama node GKE, dan zona tempat node disediakan, dan terlihat mirip dengan contoh berikut:

    gke-gkemulti-west-5-default-pool-4bcaca65-jch0 us-west1-b dbc1-0
    gke-gkemulti-west-5-default-pool-1ac6e8b5-ddjx us-west1-c dbc1-1
    gke-gkemulti-west-5-default-pool-1f5baa66-bf8t us-west1-a dbc1-2
    

    Kolom dalam output masing-masing mewakili nama host, zona cloud, dan nama Pod.

    Kebijakan topologySpreadConstraints dalam spesifikasi StatefulSet (c1-mysql.yaml) mengarahkan penjadwal untuk menempatkan Pod secara merata di seluruh domain gagal (topology.kubernetes.io/zone).

    Kebijakan podAntiAffinity menerapkan batasan yang mengharuskan Pod agar tidak ditempatkan pada node cluster GKE yang sama (kubernetes.io/hostname). Untuk Pod instance MySQL, kebijakan ini menyebabkan Pod di-deploy secara merata di ketiga zona dalam region Google Cloud. Penempatan ini memungkinkan ketersediaan tinggi Cluster InnoDB MySQL dengan menempatkan setiap instance database di domain kegagalan yang terpisah.

Menyiapkan Cluster InnoDB MySQL utama

Untuk mengonfigurasi Cluster InnoDB MySQL, ikuti langkah-langkah berikut:

  1. Di terminal Cloud Shell, tetapkan konfigurasi replikasi grup untuk instance MySQL yang akan ditambahkan ke cluster Anda.

    bash ../scripts/c1-clustersetup.sh
    
    POD_ORDINAL_START=${1:-0}
    POD_ORDINAL_END=${2:-2}
    for i in $(seq ${POD_ORDINAL_START} ${POD_ORDINAL_END}); do
      echo "Configuring pod mysql1/dbc1-${i}"
      cat <<'  EOF' | kubectl -n mysql1 exec -i dbc1-${i} -- bash -c 'mysql -uroot -proot --password=${MYSQL_ROOT_PASSWORD}'
    INSTALL PLUGIN group_replication SONAME 'group_replication.so';
    RESET PERSIST IF EXISTS group_replication_ip_allowlist;
    RESET PERSIST IF EXISTS binlog_transaction_dependency_tracking;
    SET @@PERSIST.group_replication_ip_allowlist = 'mysql.mysql1.svc.cluster.local';
    SET @@PERSIST.binlog_transaction_dependency_tracking = 'WRITESET';
      EOF
    done

    Skrip ini akan terhubung dari jarak jauh ke masing-masing dari tiga instance MySQL untuk menetapkan dan mempertahankan variabel lingkungan berikut:

    • group_replication_ip_allowlist: memungkinkan instance dalam cluster terhubung ke instance mana pun dalam grup.
    • binlog_transaction_dependency_tracking='WRITESET': memungkinkan transaksi paralel yang tidak akan bertentangan.

    Di MySQL versi yang lebih lama dari 8.0.22, gunakan group_replication_ip_whitelist, bukan group_replication_ip_allowlist.

  2. Buka terminal kedua agar Anda tidak perlu membuat shell untuk setiap Pod.

  3. Menghubungkan ke MySQL Shell di Pod dbc1-0.

    kubectl -n mysql1 exec -it dbc1-0 -- \
        /bin/bash \
        -c 'mysqlsh --uri="root:$MYSQL_ROOT_PASSWORD@dbc1-0.mysql.mysql1.svc.cluster.local"'
    
  4. Memverifikasi daftar replikasi grup MySQL yang diizinkan untuk terhubung ke instance lain.

    \sql SELECT @@group_replication_ip_allowlist;
    

    Outputnya mirip dengan hal berikut ini:

    +----------------------------------+
    | @@group_replication_ip_allowlist |
    +----------------------------------+
    | mysql.mysql1.svc.cluster.local   |
    +----------------------------------+
    
  5. Pastikan bahwa server-id bersifat unik pada setiap instance.

    \sql SELECT @@server_id;
    

    Outputnya mirip dengan hal berikut ini:

    +-------------+
    | @@server_id |
    +-------------+
    |          21 |
    +-------------+
    
  6. Konfigurasikan setiap instance untuk penggunaan Cluster InnoDB MySQL dan buat akun administrator di setiap instance.

    \js
    dba.configureInstance('root@dbc1-0.mysql.mysql1.svc.cluster.local', {password: os.getenv("MYSQL_ROOT_PASSWORD"),clusterAdmin: 'icadmin', clusterAdminPassword: os.getenv("MYSQL_ADMIN_PASSWORD")});
    dba.configureInstance('root@dbc1-1.mysql.mysql1.svc.cluster.local', {password: os.getenv("MYSQL_ROOT_PASSWORD"),clusterAdmin: 'icadmin', clusterAdminPassword: os.getenv("MYSQL_ADMIN_PASSWORD")});
    dba.configureInstance('root@dbc1-2.mysql.mysql1.svc.cluster.local', {password: os.getenv("MYSQL_ROOT_PASSWORD"),clusterAdmin: 'icadmin', clusterAdminPassword: os.getenv("MYSQL_ADMIN_PASSWORD")});
    

    Semua instance harus memiliki nama pengguna dan sandi yang sama agar Cluster InnoDB MySQL dapat berfungsi dengan baik. Setiap perintah menghasilkan output yang mirip dengan berikut ini:

    ...
    
    The instance 'dbc1-2.mysql:3306' is valid to be used in an InnoDB cluster.
    
    Cluster admin user 'icadmin'@'%' created.
    The instance 'dbc1-2.mysql.mysql1.svc.cluster.local:3306' is already
    ready to be used in an InnoDB cluster.
    
    Successfully enabled parallel appliers.
    
  7. Verifikasi bahwa instance siap digunakan di Cluster InnoDB MySQL.

    dba.checkInstanceConfiguration()
    

    Outputnya mirip dengan hal berikut ini:

    ...
    
    The instance 'dbc1-0.mysql.mysql1.svc.cluster.local:3306' is valid to be used in an InnoDB cluster.
    
    {
        "status": "ok"
    }
    

    Atau, Anda dapat terhubung ke setiap instance MySQL dan mengulangi perintah ini. Misalnya, jalankan perintah ini untuk memeriksa status pada instance dbc1-1:

    kubectl -n mysql1 exec -it dbc1-0 -- \
        /bin/bash \
        -c 'mysqlsh --uri="root:$MYSQL_ROOT_PASSWORD@dbc1-1.mysql.mysql1.svc.cluster.local" \
        --js --execute "dba.checkInstanceConfiguration()"'
    

Membuat Cluster InnoDB MySQL utama

Selanjutnya, buat Cluster InnoDB MySQL menggunakan perintah createCluster Admin MySQL. Mulai dengan instance dbc1-0, yang akan menjadi instance utama untuk cluster, lalu tambahkan dua replika tambahan ke cluster tersebut.

Untuk melakukan inisialisasi Cluster InnoDB MySQL, ikuti langkah-langkah berikut:

  1. Membuat Cluster InnoDB MySQL.

    var cluster=dba.createCluster('mycluster');
    

    Menjalankan perintah createCluster akan memicu operasi berikut:

    • Deploy skema metadata.
    • Pastikan konfigurasi sudah benar untuk Replikasi Grup.
    • Daftarkan sebagai instance seed dari cluster baru.
    • Buat akun internal yang diperlukan, seperti akun pengguna replikasi.
    • Mulai Replikasi Grup.

    Perintah ini menginisialisasi Cluster InnoDB MySQL dengan dbc1-0 host sebagai utama. Referensi cluster disimpan dalam variabel cluster.

    Outputnya terlihat mirip dengan ini:

    A new InnoDB cluster will be created on instance 'dbc1-0.mysql:3306'.
    
    Validating instance configuration at dbc1-0.mysql:3306...
    
    This instance reports its own address as dbc1-0.mysql.mysql1.svc.cluster.local:3306
    
    Instance configuration is suitable.
    NOTE: Group Replication will communicate with other instances using
    'dbc1-0.mysql:33061'. Use the localAddress
    option to override.
    
    Creating InnoDB cluster 'mycluster' on
    'dbc1-0.mysql.mysql1.svc.cluster.local:3306'...
    
    Adding Seed Instance...
    Cluster successfully created. Use Cluster.addInstance() to add MySQL
    instances.
    At least 3 instances are needed for the cluster to be able to withstand
    up to one server failure.
    
  2. Tambahkan instance kedua ke cluster.

    cluster.addInstance('icadmin@dbc1-1.mysql', {password: os.getenv("MYSQL_ROOT_PASSWORD"), recoveryMethod: 'clone'});
    
  3. Tambahkan instance yang tersisa ke cluster.

    cluster.addInstance('icadmin@dbc1-2.mysql', {password: os.getenv("MYSQL_ROOT_PASSWORD"), recoveryMethod: 'clone'});
    

    Outputnya mirip dengan hal berikut ini:

    ...
    The instance 'dbc1-2.mysql:3306' was successfully added to the cluster.
    
  4. Verifikasi status cluster.

    cluster.status()
    

    Perintah ini akan menampilkan status cluster. Topologinya terdiri dari tiga host, satu instance primer dan dua instance sekunder. Jika ingin, Anda dapat memanggil cluster.status({extended:1}).

    Outputnya mirip dengan hal berikut ini:

    {
        "clusterName": "mysql1",
        "defaultReplicaSet": {
            "name": "default",
            "primary": "dbc1-0.mysql:3306",
            "ssl": "REQUIRED",
            "status": "OK",
            "statusText": "Cluster is ONLINE and can tolerate up to ONE failure.",
            "topology": {
                "dbc1-0.mysql:3306": {
                    "address": "dbc1-0.mysql:3306",
                    "memberRole": "PRIMARY",
                    "mode": "R/W",
                    "readReplicas": {},
                    "replicationLag": null,
                    "role": "HA",
                    "status": "ONLINE",
                    "version": "8.0.28"
                },
                "dbc1-1.mysql:3306": {
                    "address": "dbc1-1.mysql:3306",
                    "memberRole": "SECONDARY",
                    "mode": "R/O",
                    "readReplicas": {},
                    "replicationLag": null,
                    "role": "HA",
                    "status": "ONLINE",
                    "version": "8.0.28"
                },
                "dbc1-2.mysql:3306": {
                    "address": "dbc1-2.mysql:3306",
                    "memberRole": "SECONDARY",
                    "mode": "R/O",
                    "readReplicas": {},
                    "replicationLag": null,
                    "role": "HA",
                    "status": "ONLINE",
                    "version": "8.0.28"
                }
            },
            "topologyMode": "Single-Primary"
        },
        "groupInformationSourceMember": "dbc1-0.mysql:3306"
    }
    

    Jika ingin, Anda dapat memanggil cluster.status({extended:1}) untuk mendapatkan detail status tambahan.

Membuat contoh database

Untuk membuat contoh database, ikuti langkah-langkah berikut:

  1. Membuat database dan memuat data ke dalam database.

    \sql
    create database loanapplication;
    use loanapplication
    CREATE TABLE loan (loan_id INT unsigned AUTO_INCREMENT PRIMARY KEY, firstname VARCHAR(30) NOT NULL, lastname VARCHAR(30) NOT NULL , status VARCHAR(30) );
    
  2. Memasukkan data sampel ke dalam database. Untuk menyisipkan data, Anda harus terhubung ke instance utama cluster.

    INSERT INTO loan (firstname, lastname, status) VALUES ( 'Fred','Flintstone','pending');
    INSERT INTO loan (firstname, lastname, status) VALUES ( 'Betty','Rubble','approved');
    
  3. Pastikan tabel berisi tiga baris yang disisipkan pada langkah sebelumnya.

    SELECT * FROM loan;
    

    Outputnya mirip dengan hal berikut ini:

    +---------+-----------+------------+----------+
    | loan_id | firstname | lastname   | status   |
    +---------+-----------+------------+----------+
    |       1 | Fred      | Flintstone | pending  |
    |       2 | Betty     | Rubble     | approved |
    +---------+-----------+------------+----------+
    2 rows in set (0.0010 sec)
    

Membuat ClusterSet InnoDB MySQL

Anda dapat membuat InnoDB ClusterSet MySQL untuk mengelola replikasi dari cluster utama ke cluster replika, menggunakan saluran replikasi ClusterSet khusus.

ClusterSet InnoDB MySQL memberikan toleransi bencana untuk deployment Cluster InnoDB MySQL dengan menautkan Cluster InnoDB MySQL utama dengan satu atau beberapa replikanya sendiri di lokasi alternatif, seperti beberapa zona dan beberapa region.

Jika Anda menutup MySQL Shell, buat shell baru dengan menjalankan perintah ini di terminal Cloud Shell baru:

  kubectl -n mysql1 exec -it dbc1-0 -- \
      /bin/bash -c 'mysqlsh \
      --uri="root:$MYSQL_ROOT_PASSWORD@dbc1-0.mysql.mysql1.svc.cluster.local"'

Untuk membuat ClusterSet InnoDB MySQL, ikuti langkah-langkah berikut:

  1. Di terminal MySQL Shell Anda, dapatkan objek cluster.

    \js
    cluster=dba.getCluster()
    

    Outputnya mirip dengan hal berikut ini:

    <Cluster:mycluster>
    
  2. Lakukan inisialisasi ClusterSet InnoDB MySQL dengan Cluster InnoDB MySQL yang ada dan tersimpan di objek cluster sebagai cluster utama.

    clusterset=cluster.createClusterSet('clusterset')
    

    Outputnya mirip dengan hal berikut ini:

    A new ClusterSet will be created based on the Cluster 'mycluster'.
    
    * Validating Cluster 'mycluster' for ClusterSet compliance.
    
    * Creating InnoDB ClusterSet 'clusterset' on 'mycluster'...
    
    * Updating metadata...
    
    ClusterSet successfully created. Use ClusterSet.createReplicaCluster() to add Replica Clusters to it.
    
    <ClusterSet:clusterset>
    
  3. Periksa status ClusterSet InnoDB MySQL Anda.

    clusterset.status()
    

    Outputnya mirip dengan hal berikut ini:

    {
        "clusters": {
            "mycluster": {
                "clusterRole": "PRIMARY",
                "globalStatus": "OK",
                "primary": "dbc1-0.mysql:3306"
            }
        },
        "domainName": "clusterset",
        "globalPrimaryInstance": "dbc1-0.mysql:3306",
        "primaryCluster": "mycluster",
        "status": "HEALTHY",
        "statusText": "All Clusters available."
    }
    

    Secara opsional, Anda dapat memanggil clusterset.status({extended:1}) untuk mendapatkan detail status tambahan, termasuk informasi tentang cluster.

  4. Keluar dari MySQL Shell.

    \q
    

Men-deploy Router MySQL

Anda dapat men-deploy Router MySQL untuk mengarahkan traffic aplikasi klien ke cluster yang tepat. Pemilihan rute didasarkan pada port koneksi aplikasi yang mengeluarkan operasi database:

  • Operasi tulis dirutekan ke instance Cluster utama di ClusterSet utama.
  • Operasi baca dapat dirutekan ke instance mana pun di Cluster utama.

Saat Anda memulai Router MySQL, Router tersebut akan di-bootstrap terhadap deployment ClusterSet InnoDB MySQL. Instance Router MySQL yang terhubung dengan ClusterSet InnoDB MySQL mengetahui adanya peralihan terkontrol atau failover darurat dan mengarahkan traffic ke cluster utama yang baru.

Untuk men-deploy Router MySQL, ikuti langkah-langkah berikut:

  1. Di terminal Cloud Shell, deploy Router MySQL.

    kubectl apply -n mysql1 -f c1-router.yaml
    

    Outputnya mirip dengan hal berikut ini:

    configmap/mysql-router-config created
    service/mysql-router created
    deployment.apps/mysql-router created
    
  2. Periksa kesiapan deployment Router MySQL.

    kubectl -n mysql1 get deployment mysql-router --watch
    

    Jika ketiga Pod sudah siap, outputnya akan mirip dengan berikut ini:

    NAME           READY   UP-TO-DATE   AVAILABLE   AGE
    mysql-router   3/3     3            0           3m36s
    

    Jika Anda melihat error PodUnschedulable di konsol, tunggu satu atau dua menit selagi GKE menyediakan lebih banyak node. Muat ulang, dan Anda akan melihat 3/3 OK.

  3. Mulai MySQL Shell pada anggota cluster yang ada.

    kubectl -n mysql1 exec -it dbc1-0 -- \
        /bin/bash -c 'mysqlsh --uri="root:$MYSQL_ROOT_PASSWORD@dbc1-0.mysql"'
    

    Perintah ini terhubung ke Pod dbc1-0, lalu memulai shell yang terhubung ke instance MySQL dbc1-0.

  4. Verifikasi konfigurasi router.

    clusterset=dba.getClusterSet()
    clusterset.listRouters()
    

    Outputnya mirip dengan hal berikut ini:

    {
      "domainName": "clusterset",
      "routers": {
        "mysql-router-7cd8585fbc-74pkm::": {
            "hostname": "mysql-router-7cd8585fbc-74pkm",
            "lastCheckIn": "2022-09-22 23:26:26",
            "roPort": 6447,
            "roXPort": 6449,
            "rwPort": 6446,
            "rwXPort": 6448,
            "targetCluster": null,
            "version": "8.0.27"
        },
        "mysql-router-7cd8585fbc-824d4::": {
          ...
        },
        "mysql-router-7cd8585fbc-v2qxz::": {
          ...
        }
      }
    }
    
  5. Keluar dari MySQL Shell.

    \q
    
  6. Jalankan skrip ini untuk memeriksa penempatan Pod Router MySQL.

    bash ../scripts/inspect_pod_node.sh mysql1 | sort
    

    Skrip ini menunjukkan penempatan node dan Zona Cloud dari semua Pod di namespace mysql1, dengan output yang mirip dengan berikut ini:

    gke-gkemulti-west-5-default-pool-1ac6e8b5-0h9v us-west1-c mysql-router-6654f985f5-df97q
    gke-gkemulti-west-5-default-pool-1ac6e8b5-ddjx us-west1-c dbc1-1
    gke-gkemulti-west-5-default-pool-1f5baa66-bf8t us-west1-a dbc1-2
    gke-gkemulti-west-5-default-pool-1f5baa66-kt03 us-west1-a mysql-router-6654f985f5-qlfj9
    gke-gkemulti-west-5-default-pool-4bcaca65-2l6s us-west1-b mysql-router-6654f985f5-5967d
    gke-gkemulti-west-5-default-pool-4bcaca65-jch0 us-west1-b dbc1-0
    

    Anda dapat mengamati bahwa Pod Router MySQL didistribusikan secara merata di seluruh zona; yaitu, tidak ditempatkan pada node yang sama dengan Pod MySQL, atau di node yang sama dengan Pod Router MySQL lainnya.

Mengelola upgrade Cluster InnoDB GKE dan MySQL

Update untuk MySQL dan Kubernetes dirilis secara rutin. Ikuti praktik terbaik operasional untuk mengupdate lingkungan software Anda secara rutin. Secara default, GKE mengelola upgrade cluster dan kumpulan node untuk Anda. Kubernetes dan GKE juga menyediakan fitur tambahan untuk memfasilitasi upgrade software MySQL.

Merencanakan upgrade GKE

Anda dapat mengambil langkah-langkah proaktif dan menetapkan konfigurasi untuk memitigasi risiko serta memfasilitasi upgrade cluster yang lebih lancar saat menjalankan layanan stateful, termasuk:

  • Cluster standar: Ikuti praktik terbaik GKE untuk mengupgrade cluster. Pilih strategi upgrade yang sesuai untuk memastikan upgrade terjadi selama periode masa pemeliharaan:

    • Pilih upgrade lonjakan jika pengoptimalan biaya penting dan jika beban kerja Anda dapat menoleransi penonaktifan tuntas dalam waktu kurang dari 60 menit.
    • Pilih upgrade blue-green jika beban kerja Anda tidak terlalu toleran terhadap gangguan, dan kenaikan biaya sementara karena penggunaan resource yang lebih tinggi dapat diterima.

    Untuk mempelajari lebih lanjut, lihat Mengupgrade cluster yang menjalankan beban kerja stateful. Cluster Autopilot diupgrade secara otomatis, berdasarkan saluran rilis yang Anda pilih.

  • Gunakan periode pemeliharaan untuk memastikan upgrade terjadi saat Anda menginginkannya. Sebelum masa pemeliharaan, pastikan pencadangan database Anda berhasil.

  • Sebelum mengizinkan traffic ke node MySQL yang telah diupgrade, gunakan Pemeriksaan Kesiapan dan Pemeriksaan Keaktifan untuk memastikan keduanya siap menerima traffic.

  • Buat Pemeriksaan yang menilai apakah replikasi sinkron sebelum menerima traffic. Hal ini dapat dilakukan melalui skrip kustom, bergantung pada kompleksitas dan skala database Anda.

Menetapkan kebijakan Anggaran Gangguan Pod (PDB)

Saat Cluster InnoDB MySQL berjalan di GKE, harus ada cukup instance yang berjalan kapan saja untuk memenuhi persyaratan kuorum.

Dalam tutorial ini, dengan mempertimbangkan cluster MySQL yang terdiri dari tiga instance, dua instance harus tersedia untuk membentuk kuorum. Kebijakan PodDisruptionBudget memungkinkan Anda membatasi jumlah Pod yang dapat dihentikan pada waktu tertentu. Hal ini berguna untuk operasi status stabil layanan stateful dan untuk upgrade cluster.

Untuk memastikan bahwa sejumlah kecil Pod terganggu secara bersamaan, tetapkan PDB untuk workload ke maxUnavailable: 1. Hal ini memastikan bahwa dalam operasi layanan, hanya boleh ada satu Pod yang berjalan.

Manifes kebijakan PodDisruptionBudget berikut menetapkan jumlah maksimum Pod yang tidak tersedia ke satu untuk aplikasi MySQL Anda.

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: mysql-pdb
spec:
  maxUnavailable: 1
  selector:
    matchLabels:
      app: mysql

Untuk menerapkan kebijakan PDB ke cluster Anda, ikuti langkah-langkah berikut:

  1. Terapkan kebijakan PDB menggunakan kubectl.

    kubectl apply -n mysql1 -f mysql-pdb-maxunavailable.yaml
    
  2. Lihat status PDB.

    kubectl get poddisruptionbudgets -n mysql1 mysql-pdb -o yaml
    

    Di bagian status output, lihat jumlah Pod currentHealthy dan desiredHealthy. Outputnya mirip dengan hal berikut ini:

    status:
    ...
      currentHealthy: 3
      desiredHealthy: 2
      disruptionsAllowed: 1
      expectedPods: 3
    ...
    

Rencana untuk upgrade biner MySQL

Kubernetes dan GKE menyediakan fitur untuk memfasilitasi upgrade bagi biner MySQL. Namun, Anda perlu melakukan beberapa operasi untuk mempersiapkan upgrade.

Ingatlah selalu hal-hal berikut sebelum Anda memulai proses upgrade:

  • Upgrade harus dilakukan terlebih dahulu di lingkungan pengujian. Untuk sistem produksi, Anda harus melakukan pengujian lebih lanjut di lingkungan praproduksi.
  • Untuk beberapa rilis biner, Anda tidak dapat mendowngrade versi setelah upgrade dilakukan. Luangkan waktu untuk memahami implikasi upgrade.
  • Sumber replikasi dapat mereplikasi ke versi yang lebih baru. Namun, menyalin dari versi yang lebih baru ke versi yang lebih lama biasanya tidak didukung.
  • Pastikan Anda memiliki cadangan database yang lengkap sebelum men-deploy versi yang telah diupgrade.
  • Perlu diingat bahwa Pod Kubernetes bersifat sementara. Status konfigurasi apa pun yang disimpan oleh Pod yang tidak berada dalam volume persisten akan hilang saat Pod di-deploy ulang.
  • Untuk upgrade biner MySQL, gunakan PDB, strategi update node pool, dan Probe yang sama seperti yang dijelaskan sebelumnya.

Dalam lingkungan produksi, Anda harus mengikuti praktik terbaik berikut:

  • Membuat image container dengan MySQL versi baru.
  • Mempertahankan petunjuk build gambar di repositori kontrol sumber.
  • Gunakan build image dan pipeline pengujian otomatis seperti Cloud Build, dan simpan biner image di registry image seperti Artifact Registry.

Agar tutorial ini tetap sederhana, Anda tidak akan membangun dan mempertahankan image container. Sebagai gantinya, Anda akan menggunakan image MySQL publik.

Men-deploy biner MySQL yang telah diupgrade

Untuk melakukan upgrade biner MySQL, Anda harus mengeluarkan perintah deklaratif yang mengubah versi image resource StatefulSet. GKE melakukan langkah-langkah yang diperlukan untuk menghentikan Pod saat ini, men-deploy Pod baru dengan biner yang diupgrade, dan memasang persistent disk ke Pod baru.

  1. Verifikasi bahwa PDB telah dibuat.

    kubectl get poddisruptionbudgets -n mysql1
    
  2. Dapatkan daftar kumpulan stateful.

    kubectl get statefulsets -n mysql1
    
  3. Dapatkan daftar Pod yang berjalan menggunakan label app.

    kubectl get pods --selector=app=mysql -n mysql1
    
  4. Update image MySQL dalam kumpulan stateful.

    kubectl  -n mysql1 \
        set image statefulset/dbc1 \
        mysql=mysql/mysql-server:8.0.30
    

    Outputnya mirip dengan hal berikut ini:

    statefulset.apps/mysql image updated
    
  5. Memeriksa status Pod baru dan Pod baru yang berhenti.

    kubectl get pods --selector=app=mysql -n mysql1
    

Memvalidasi upgrade biner MySQL

Selama upgrade, Anda dapat memverifikasi status peluncuran, Pod baru, dan Layanan yang ada.

  1. Konfirmasi upgrade dengan menjalankan perintah rollout status.

    kubectl rollout status statefulset/dbc1 -n mysql1
    

    Outputnya mirip dengan hal berikut ini:

    partitioned roll out complete: 3 new pods have been updated...
    
  2. Konfirmasi versi image dengan memeriksa kumpulan stateful.

    kubectl get statefulsets -o wide -n mysql1
    

    Outputnya mirip dengan hal berikut ini:

    NAME   READY   AGE   CONTAINERS   IMAGES
    dbc1   3/3     37m   mysql        mysql/mysql-server:8.0.30
    
  3. Periksa status cluster.

    kubectl -n mysql1 \
         exec -it dbc1-0 -- \
           /bin/bash \
             -c 'mysqlsh \
             --uri="root:$MYSQL_ROOT_PASSWORD@dbc1-1.mysql.mysql1.svc.cluster.local" \
             --js \
             --execute "print(dba.getClusterSet().status({extended:1})); print(\"\\n\")"'
    

    Untuk setiap instance cluster, cari nilai status dan versi dalam output. Outputnya mirip dengan hal berikut ini:

    ...
      "status": "ONLINE",
      "version": "8.0.30"
    ...
    

Rollback peluncuran deployment aplikasi terakhir

Saat Anda mengembalikan deployment versi biner yang diupgrade, proses peluncuran akan dibalik dan kumpulan Pod baru di-deploy dengan versi image sebelumnya.

Untuk mengembalikan deployment ke versi kerja sebelumnya, gunakan perintah rollout undo:

kubectl rollout undo statefulset/dbc1 -n mysql1

Outputnya mirip dengan hal berikut ini:

statefulset.apps/dbc1 rolled back

Menskalakan cluster database secara horizontal

Untuk menskalakan Cluster InnoDB MySQL secara horizontal, tambahkan node tambahan ke node pool cluster GKE (hanya diperlukan jika Anda menggunakan Standard), deploy instance MySQL tambahan, lalu tambahkan setiap instance ke MySQL yang ada Cluster InnoDB.

Menambahkan node ke cluster Standard

Operasi ini tidak diperlukan jika Anda menggunakan cluster Autopilot.

Untuk menambahkan node ke cluster Standard, ikuti petunjuk di bawah untuk Cloud Shell atau konsol Google Cloud. Untuk mengetahui langkah-langkah detailnya, lihat Mengubah ukuran node pool

gcloud

Di Cloud Shell, ubah ukuran node pool default menjadi delapan instance untuk setiap grup instance terkelola.

gcloud container clusters resize ${CLUSTER_NAME} \
     --node-pool default-pool \
     --num-nodes=8

Konsol

Untuk menambahkan node ke cluster Standard:

  1. Buka halaman Cluster gkemulti-west1 di Konsol Google Cloud.
  2. Pilih Nodes, lalu klik default pool.
  3. Scroll ke bawah ke bagian Grup instance.
  4. Untuk setiap grup instance, ubah ukuran nilai Number of nodes dari 5 menjadi 8 node.

Menambahkan Pod MySQL ke cluster utama

Untuk men-deploy Pod MySQL tambahan guna menskalakan cluster secara horizontal, ikuti langkah-langkah berikut:

  1. Di Cloud Shell, perbarui jumlah replika dalam deployment MySQL dari tiga replika menjadi lima replika.

    kubectl scale  -n mysql1 --replicas=5 -f c1-mysql.yaml
    
  2. Memverifikasi progres deployment.

    kubectl -n mysql1 get pods --selector=app=mysql -o wide
    

    Untuk menentukan apakah Pod sudah siap, gunakan flag --watch untuk menonton deployment. Jika Anda menggunakan cluster Autopilot dan melihat error Pod Unschedulable, ini mungkin mengindikasikan bahwa GKE menyediakan node untuk mengakomodasi Pod tambahan.

  3. Konfigurasikan setelan replikasi grup untuk instance MySQL baru yang akan ditambahkan ke cluster

    bash ../scripts/c1-clustersetup.sh 3 4
    

    Skrip ini mengirimkan perintah ke instance yang berjalan di Pod dengan ordinal 3 sampai 4.

  4. Buka MySQL Shell.

    kubectl -n mysql1 \
      exec -it dbc1-0 -- \
          /bin/bash \
            -c 'mysqlsh \
            --uri="root:$MYSQL_ROOT_PASSWORD@dbc1-0.mysql"'
    
  5. Konfigurasi dua instance MySQL baru.

    dba.configureInstance('root:$MYSQL_ROOT_PASSWORD@dbc1-3.mysql', {password: os.getenv("MYSQL_ROOT_PASSWORD"),clusterAdmin: 'icadmin', clusterAdminPassword: os.getenv("MYSQL_ADMIN_PASSWORD")});
    dba.configureInstance('root:$MYSQL_ROOT_PASSWORD@dbc1-4.mysql', {password: os.getenv("MYSQL_ROOT_PASSWORD"),clusterAdmin: 'icadmin', clusterAdminPassword: os.getenv("MYSQL_ADMIN_PASSWORD")});
    

    Perintah ini memeriksa apakah instance dikonfigurasi dengan benar untuk penggunaan Cluster InnoDB MySQL dan melakukan perubahan konfigurasi yang diperlukan.

  6. Tambahkan salah satu instance baru ke cluster utama.

    cluster = dba.getCluster()
    cluster.addInstance('icadmin@dbc1-3.mysql', {password: os.getenv("MYSQL_ROOT_PASSWORD"), recoveryMethod: 'clone'});
    
  7. Tambahkan instance baru kedua ke cluster utama.

    cluster.addInstance('icadmin@dbc1-4.mysql', {password: os.getenv("MYSQL_ROOT_PASSWORD"), recoveryMethod: 'clone'});
    
  8. Dapatkan status ClusterSet, yang juga mencakup status Cluster.

    clusterset = dba.getClusterSet()
    clusterset.status({extended: 1})
    

    Outputnya mirip dengan hal berikut ini:

    "domainName": "clusterset",
    "globalPrimaryInstance": "dbc1-0.mysql:3306",
    "metadataServer": "dbc1-0.mysql:3306",
    "primaryCluster": "mycluster",
    "status": "HEALTHY",
    "statusText": "All Clusters available."
    
  9. Keluar dari MySQL Shell.

    \q
    

Pembersihan

Agar tidak perlu membayar biaya pada akun Google Cloud Anda untuk resource yang digunakan dalam tutorial ini, hapus project yang berisi resource tersebut, atau simpan project dan hapus setiap resource.

Menghapus project

Cara termudah untuk menghindari penagihan adalah dengan menghapus project yang Anda buat untuk tutorial.

Menghapus project Google Cloud:

gcloud projects delete PROJECT_ID

Langkah selanjutnya