การพัฒนา InnerLoop โดยใช้ Cloud Workstations กับ Python

1. ภาพรวม

แล็บนี้สาธิตฟีเจอร์และความสามารถที่ออกแบบมาเพื่อปรับปรุงเวิร์กโฟลว์การพัฒนาสำหรับวิศวกรซอฟต์แวร์ที่ได้รับมอบหมายให้พัฒนาแอปพลิเคชัน Python ในสภาพแวดล้อมที่มีคอนเทนเนอร์ การพัฒนาคอนเทนเนอร์โดยทั่วไปกำหนดให้ผู้ใช้ต้องเข้าใจรายละเอียดของคอนเทนเนอร์และกระบวนการบิลด์คอนเทนเนอร์ นอกจากนี้ โดยปกติแล้ว นักพัฒนาซอฟต์แวร์จะต้องหยุดโฟลว์การทำงาน ย้ายออกจาก IDE เพื่อทดสอบและแก้ไขข้อบกพร่องของแอปพลิเคชันในสภาพแวดล้อมระยะไกล เครื่องมือและเทคโนโลยีที่กล่าวถึงในบทแนะนำนี้ช่วยให้นักพัฒนาแอปทำงานกับแอปพลิเคชันที่อยู่ในคอนเทนเนอร์ได้อย่างมีประสิทธิภาพโดยไม่ต้องออกจาก IDE

สิ่งที่คุณจะได้เรียนรู้

ในแล็บนี้ คุณจะได้เรียนรู้วิธีการพัฒนาด้วยคอนเทนเนอร์ใน GCP ซึ่งรวมถึง

  • การสร้างแอปพลิเคชันเริ่มต้นใหม่ใน Python
  • ดูขั้นตอนการพัฒนา
  • พัฒนาบริการ REST ของ CRUD แบบง่าย
  • การทำให้ใช้งานได้ใน GKE
  • การแก้ไขข้อบกพร่องของสถานะข้อผิดพลาด
  • การใช้เบรกพอยท์ / บันทึก
  • การเปลี่ยนแปลงการฮอตดีพลอยกลับไปยัง GKE

58a4cdd3ed7a123a.png

2. การตั้งค่าและข้อกำหนด

การตั้งค่าสภาพแวดล้อมแบบเรียนรู้ด้วยตนเอง

  1. ลงชื่อเข้าใช้ Google Cloud Console แล้วสร้างโปรเจ็กต์ใหม่หรือใช้โปรเจ็กต์ที่มีอยู่ซ้ำ หากยังไม่มีบัญชี Gmail หรือ Google Workspace คุณต้องสร้างบัญชี

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • ชื่อโปรเจ็กต์คือชื่อที่แสดงสำหรับผู้เข้าร่วมโปรเจ็กต์นี้ ซึ่งเป็นสตริงอักขระที่ Google APIs ไม่ได้ใช้ โดยคุณจะอัปเดตได้ทุกเมื่อ
  • รหัสโปรเจ็กต์จะไม่ซ้ำกันในโปรเจ็กต์ Google Cloud ทั้งหมดและเปลี่ยนแปลงไม่ได้ (เปลี่ยนไม่ได้หลังจากตั้งค่าแล้ว) Cloud Console จะสร้างสตริงที่ไม่ซ้ำกันโดยอัตโนมัติ ซึ่งโดยปกติแล้วคุณไม่จำเป็นต้องสนใจว่าสตริงนั้นคืออะไร ใน Codelab ส่วนใหญ่ คุณจะต้องอ้างอิงรหัสโปรเจ็กต์ (โดยปกติจะระบุเป็น PROJECT_ID) หากไม่ชอบรหัสที่สร้างขึ้น คุณก็สร้างรหัสแบบสุ่มอีกรหัสหนึ่งได้ หรือคุณจะลองใช้ชื่อของคุณเองเพื่อดูว่าพร้อมใช้งานหรือไม่ก็ได้ คุณจะเปลี่ยนแปลงรหัสนี้หลังจากขั้นตอนนี้ไม่ได้ และรหัสจะยังคงอยู่ตลอดระยะเวลาของโปรเจ็กต์
  • โปรดทราบว่ายังมีค่าที่ 3 ซึ่งคือหมายเลขโปรเจ็กต์ที่ API บางตัวใช้ ดูข้อมูลเพิ่มเติมเกี่ยวกับค่าทั้ง 3 นี้ได้ในเอกสารประกอบ
  1. จากนั้นคุณจะต้องเปิดใช้การเรียกเก็บเงินใน Cloud Console เพื่อใช้ทรัพยากร/API ของ Cloud การทำตาม Codelab นี้ไม่ควรมีค่าใช้จ่ายมากนัก หรืออาจไม่มีเลย หากต้องการปิดทรัพยากรเพื่อไม่ให้มีการเรียกเก็บเงินนอกเหนือจากบทแนะนำนี้ คุณสามารถลบทรัพยากรที่สร้างขึ้นหรือลบทั้งโปรเจ็กต์ได้ ผู้ใช้ Google Cloud รายใหม่มีสิทธิ์เข้าร่วมโปรแกรมช่วงทดลองใช้ฟรีมูลค่า$300 USD

เริ่มโปรแกรมแก้ไข Cloud Shell

Lab นี้ออกแบบและทดสอบเพื่อใช้กับ Google Cloud Shell Editor วิธีเข้าถึงเครื่องมือแก้ไข

  1. เข้าถึงโปรเจ็กต์ Google ที่ https://console.cloud.google.com
  2. คลิกไอคอนโปรแกรมแก้ไข Cloud Shell ที่มุมขวาบน

8560cc8d45e8c112.png

  1. แผงใหม่จะเปิดขึ้นที่ด้านล่างของหน้าต่าง
  2. คลิกปุ่ม "เปิดเครื่องมือแก้ไข"

9e504cb98a6a8005.png

  1. เครื่องมือแก้ไขจะเปิดขึ้นพร้อมกับ Explorer ทางด้านขวาและเครื่องมือแก้ไขในพื้นที่ส่วนกลาง
  2. นอกจากนี้ ควรมีแผงเทอร์มินัลที่ด้านล่างของหน้าจอด้วย
  3. หากเทอร์มินัลไม่ได้เปิดอยู่ ให้ใช้ชุดค่าผสมของปุ่ม `ctrl+`` เพื่อเปิดหน้าต่างเทอร์มินัลใหม่

การตั้งค่าสภาพแวดล้อม

ใน Cloud Shell ให้ตั้งค่ารหัสโปรเจ็กต์และหมายเลขโปรเจ็กต์สำหรับโปรเจ็กต์ บันทึกเป็นตัวแปร PROJECT_ID และ PROJECT_ID

export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID \
    --format='value(projectNumber)')

จัดสรรโครงสร้างพื้นฐานที่ใช้ใน Lab นี้

ในแล็บนี้ คุณจะได้ติดตั้งใช้งานโค้ดใน GKE และเข้าถึงข้อมูลที่จัดเก็บไว้ในฐานข้อมูล Spanner นอกจากนี้ คุณยังใช้เวิร์กสเตชันระบบคลาวด์เป็น IDE ได้ด้วย สคริปต์การตั้งค่าด้านล่างจะเตรียมโครงสร้างพื้นฐานนี้ให้คุณ

  1. ดาวน์โหลดสคริปต์การตั้งค่าและทำให้สคริปต์ใช้งานได้
wget https://raw.githubusercontent.com/GoogleCloudPlatform/container-developer-workshop/main/labs/python/setup_with_cw.sh
chmod +x setup_with_cw.sh
  1. เปิดไฟล์ setup_with_cw.sh แล้วแก้ไขค่าของรหัสผ่านที่ตั้งค่าเป็น CHANGEME ในปัจจุบัน
  2. เรียกใช้สคริปต์การตั้งค่าเพื่อสร้างคลัสเตอร์ GKE และฐานข้อมูล Spanner ที่คุณจะใช้ในแล็บนี้
./setup_with_cw.sh &

คลัสเตอร์ Cloud Workstations

  1. เปิด Cloud Workstations ใน Cloud Console รอให้คลัสเตอร์อยู่ในสถานะ READY

305e1a3d63ac7ff6.png

สร้างการกำหนดค่าเวิร์กสเตชัน

  1. หากเซสชัน Cloud Shell ถูกตัดการเชื่อมต่อ ให้คลิก "เชื่อมต่ออีกครั้ง" แล้วเรียกใช้คำสั่ง gcloud CLI เพื่อตั้งค่ารหัสโปรเจ็กต์ แทนที่รหัสโปรเจ็กต์ตัวอย่างด้านล่างด้วยรหัสโปรเจ็กต์ Qwiklabs ของคุณก่อนเรียกใช้คำสั่ง
gcloud config set project qwiklabs-gcp-project-id
  1. ดาวน์โหลดและเรียกใช้สคริปต์ด้านล่างในเทอร์มินัลเพื่อสร้างการกำหนดค่า Cloud Workstations
wget https://raw.githubusercontent.com/GoogleCloudPlatform/container-developer-workshop/main/labs/python/workstation_config_setup.sh
chmod +x workstation_config_setup.sh
./workstation_config_setup.sh
  1. ตรวจสอบผลลัพธ์ในส่วนการกำหนดค่า โดยจะใช้เวลา 2 นาทีในการเปลี่ยนเป็นสถานะพร้อม

2e23c2e9983d1ccf.png

  1. เปิด Cloud Workstations ในคอนโซล แล้วสร้างอินสแตนซ์ใหม่

a53adeeac81a78c8.png

  1. เปลี่ยนชื่อเป็น my-workstation แล้วเลือกการกำหนดค่าที่มีอยู่: codeoss-python

f052cd47701ec774.png

  1. ตรวจสอบผลลัพธ์ในส่วนเวิร์กสเตชัน

เปิดเวิร์กสเตชัน

  1. เริ่มและเปิดตัวเวิร์กสเตชัน ระบบจะใช้เวลา 2-3 นาทีในการเริ่มเวิร์กสเตชัน

682f8a307032cba3.png

  1. อนุญาตคุกกี้ของบุคคลที่สามโดยคลิกไอคอนในแถบที่อยู่ 1b8923e2943f9bc4.png

fcf9405b6957b7d7.png

  1. คลิก "เว็บไซต์ไม่ทำงานใช่ไหม"

36a84c0e2e3b85b.png

  1. คลิก "อนุญาตคุกกี้"

2259694328628fba.png

  1. เมื่อเปิดตัวเวิร์กสเตชันแล้ว คุณจะเห็น IDE ของ Code OSS ปรากฏขึ้น คลิก "ทำเครื่องหมายว่าเสร็จสิ้น" ในหน้าเริ่มต้นใช้งาน IDE ของเวิร์กสเตชัน

94874fba9b74cc22.png

3. สร้างแอปพลิเคชันเริ่มต้น Python ใหม่

ในส่วนนี้ คุณจะได้สร้างแอปพลิเคชัน Python ใหม่

  1. เปิดเทอร์มินัลใหม่

c31d48f2e4938c38.png

  1. สร้างไดเรกทอรีใหม่และเปิดเป็นพื้นที่ทำงาน
mkdir music-service && cd music-service

code-oss-cloud-workstations -r --folder-uri="$PWD"

คลิกปุ่มอนุญาตหากเห็นข้อความนี้ เพื่อให้คุณคัดลอกและวางลงในเวิร์กสเตชันได้

58149777e5cc350a.png

  1. สร้างไฟล์ชื่อ requirements.txt แล้วคัดลอกเนื้อหาต่อไปนี้ลงในไฟล์

789e8389170bd900.png

Flask
gunicorn
google-cloud-spanner
ptvsd==4.3.2
  1. สร้างไฟล์ชื่อ app.py แล้ววางโค้ดต่อไปนี้ลงในไฟล์
import os
from flask import Flask, request, jsonify
from google.cloud import spanner

app = Flask(__name__)

@app.route("/")
def hello_world():
    message="Hello, World!"
    return message

if __name__ == '__main__':
    server_port = os.environ.get('PORT', '8080')
    app.run(debug=False, port=server_port, host='0.0.0.0')

  1. สร้างไฟล์ชื่อ Dockerfile แล้ววางข้อความต่อไปนี้ลงในไฟล์
FROM python:3.8
ARG FLASK_DEBUG=0
ENV FLASK_DEBUG=$FLASK_DEBUG
ENV FLASK_APP=app.py
WORKDIR /app
COPY requirements.txt .
RUN pip install --trusted-host pypi.python.org -r requirements.txt
COPY . .
ENTRYPOINT ["python3", "-m", "flask", "run", "--port=8080", "--host=0.0.0.0"]

หมายเหตุ: FLASK_DEBUG=1 ช่วยให้คุณโหลดการเปลี่ยนแปลงโค้ดไปยังแอป Flask ของ Python โดยอัตโนมัติได้ Dockerfile นี้ช่วยให้คุณส่งค่านี้เป็นอาร์กิวเมนต์การสร้างได้

สร้างไฟล์ Manifest

ในเทอร์มินัล ให้เรียกใช้คำสั่งต่อไปนี้เพื่อสร้าง skaffold.yaml และ deployment.yaml เริ่มต้น

  1. เริ่มต้น Skaffold ด้วยคำสั่งต่อไปนี้
skaffold init --generate-manifests

เมื่อได้รับแจ้ง ให้ใช้ลูกศรเพื่อย้ายเคอร์เซอร์และใช้แป้นเว้นวรรคเพื่อเลือกตัวเลือก

เลือก:

  • 8080 สำหรับพอร์ต
  • y เพื่อบันทึกการกำหนดค่า

อัปเดตการกำหนดค่า Skaffold

  • เปลี่ยนชื่อแอปพลิเคชันเริ่มต้น
  • เปิด skaffold.yaml
  • เลือกชื่อรูปภาพที่ตั้งเป็น dockerfile-image ในปัจจุบัน
  • คลิกขวาแล้วเลือก "เปลี่ยนทุกรายการ"
  • พิมพ์ชื่อใหม่เป็นภาษาpython-app
  • แก้ไขส่วนบิลด์เพิ่มเติมเพื่อ
  • เพิ่ม docker.buildArgs ลงในบัตร FLASK_DEBUG=1
  • ซิงค์การตั้งค่าเพื่อโหลดการเปลี่ยนแปลงใดๆ ในไฟล์ *.py จาก IDE ไปยังคอนเทนเนอร์ที่ทำงานอยู่

หลังจากแก้ไขแล้ว ส่วนบิลด์ในไฟล์ skaffold.yaml จะเป็นดังนี้

build:
 artifacts:
 - image: python-app
   docker:
     buildArgs:
       FLASK_DEBUG: "1"
     dockerfile: Dockerfile
   sync:
     infer:
     - '**/*.py'

แก้ไขไฟล์การกำหนดค่า Kubernetes

  1. เปลี่ยนชื่อเริ่มต้น
  • เปิดไฟล์ deployment.yaml
  • เลือกชื่อรูปภาพที่ตั้งเป็น dockerfile-image ในปัจจุบัน
  • คลิกขวาแล้วเลือก "เปลี่ยนทุกรายการ"
  • พิมพ์ชื่อใหม่เป็นภาษาpython-app

4. การเดินผ่านกระบวนการพัฒนา

เมื่อเพิ่มตรรกะทางธุรกิจแล้ว คุณจะสามารถนําไปใช้และทดสอบแอปพลิเคชันได้ ส่วนต่อไปนี้จะแสดงการใช้ปลั๊กอิน Cloud Code ปลั๊กอินนี้ทำงานร่วมกับ Skaffold เพื่อเพิ่มประสิทธิภาพกระบวนการพัฒนา เมื่อคุณทําการติดตั้งใช้งานใน GKE ในขั้นตอนต่อไปนี้ Cloud Code และ Skaffold จะสร้างอิมเมจคอนเทนเนอร์ พุชไปยัง Container Registry แล้วติดตั้งใช้งานyourแอปพลิเคชันใน GKE โดยอัตโนมัติ ซึ่งจะเกิดขึ้นเบื้องหลังโดยซ่อนรายละเอียดจากขั้นตอนการทำงานของนักพัฒนาแอป

ลงชื่อเข้าใช้ Google Cloud

  1. คลิกไอคอน Cloud Code แล้วเลือก "ลงชื่อเข้าใช้ Google Cloud"

1769afd39be372ff.png

  1. คลิก "ไปลงชื่อเข้าใช้"

923bb1c8f63160f9.png

  1. ตรวจสอบเอาต์พุตในเทอร์มินัลและเปิดลิงก์

517fdd579c34aa21.png

  1. เข้าสู่ระบบด้วยข้อมูลเข้าสู่ระบบของนักเรียน Qwiklabs

db99b345f7a8e72c.png

  1. เลือก "อนุญาต"

a5376553c430ac84.png

  1. คัดลอกรหัสยืนยันแล้วกลับไปที่แท็บเวิร์กสเตชัน

6719421277b92eac.png

  1. วางรหัสยืนยันแล้วกด Enter

e9847cfe3fa8a2ce.png

เพิ่มคลัสเตอร์ Kubernetes

  1. เพิ่มคลัสเตอร์

62a3b97bdbb427e5.png

  1. เลือก Google Kubernetes Engine

9577de423568bbaa.png

  1. เลือกโปรเจ็กต์

c5202fcbeebcd41c.png

  1. เลือก "python-cluster" ที่สร้างขึ้นในการตั้งค่าเริ่มต้น

719c2fc0a7f9e84f.png

  1. ตอนนี้คลัสเตอร์จะปรากฏในรายการคลัสเตอร์ Kubernetes ในส่วน Cloud Code ไปยังส่วนต่างๆ และสำรวจคลัสเตอร์จากที่นี่

7e5f50662d4eea3c.png

ตั้งค่ารหัสโปรเจ็กต์ปัจจุบันโดยใช้ gcloud CLI

  1. คัดลอกรหัสโปรเจ็กต์สำหรับ Lab นี้จากหน้า Qwiklabs

fcff2d10007ec5bc.png

  1. จากเทอร์มินัล ให้เรียกใช้คำสั่ง gcloud CLI เพื่อตั้งค่ารหัสโปรเจ็กต์ แทนที่รหัสโปรเจ็กต์ตัวอย่างก่อนเรียกใช้คำสั่ง แทนที่รหัสโปรเจ็กต์ก่อนเรียกใช้คำสั่งด้านล่าง
gcloud config set project qwiklabs-gcp-project-id

ทําให้ใช้งานได้ใน Kubernetes

  1. เลือก Cloud Code  ในบานหน้าต่างที่ด้านล่างของ Cloud Shell Editor

d99a88992e15fea9.png

  1. เลือกเรียกใช้ใน Kubernetes ในแผงที่ปรากฏขึ้นที่ด้านบน หากได้รับข้อความแจ้ง ให้เลือก "ใช่" เพื่อใช้บริบท Kubernetes ปัจจุบัน

bfd65e9df6d4a6cb.png

คำสั่งนี้จะเริ่มการสร้างซอร์สโค้ดแล้วจึงเรียกใช้การทดสอบ การสร้างและการทดสอบจะใช้เวลาสักครู่ การทดสอบเหล่านี้รวมถึงการทดสอบหน่วยและขั้นตอนการตรวจสอบที่ตรวจสอบกฎที่ตั้งค่าไว้สำหรับสภาพแวดล้อมการติดตั้งใช้งาน ขั้นตอนการตรวจสอบนี้ได้รับการกำหนดค่าไว้แล้ว และจะช่วยให้คุณได้รับคำเตือนเกี่ยวกับปัญหาในการทำให้ใช้งานได้แม้ว่าคุณจะยังทำงานในสภาพแวดล้อมในการพัฒนาซอฟต์แวร์อยู่ก็ตาม

  1. เมื่อเรียกใช้คำสั่งเป็นครั้งแรก ข้อความแจ้งจะปรากฏที่ด้านบนของหน้าจอเพื่อถามว่าคุณต้องการใช้บริบท Kubernetes ปัจจุบันหรือไม่ ให้เลือก "ใช่" เพื่อยอมรับและใช้บริบทปัจจุบัน
  2. จากนั้นระบบจะแสดงข้อความแจ้งเพื่อถามว่าควรใช้รีจิสทรีคอนเทนเนอร์ใด กด Enter เพื่อยอมรับค่าเริ่มต้นที่ระบุ
  3. เลือกแท็บ "เอาต์พุต" ในบานหน้าต่างด้านล่างเพื่อดูความคืบหน้าและการแจ้งเตือน ใช้เมนูแบบเลื่อนลงเพื่อเลือก "Kubernetes: เรียกใช้/แก้ไขข้อบกพร่อง"

9c87ccbf5d06f50a.png

  1. เลือก "Kubernetes: เรียกใช้/แก้ไขข้อบกพร่อง - โดยละเอียด" ในเมนูแบบเลื่อนลงของช่องทางทางด้านขวาเพื่อดูรายละเอียดเพิ่มเติมและบันทึกที่สตรีมแบบสดจากคอนเทนเนอร์

804abc8833ffd571.png

เมื่อสร้างและทดสอบเสร็จแล้ว บันทึกของแท็บเอาต์พุตจะมี URL http://localhost:8080 แสดงอยู่ในมุมมอง "Kubernetes: เรียกใช้/แก้ไขข้อบกพร่อง"

  1. ในเทอร์มินัล Cloud Code ให้วางเมาส์เหนือ URL แรกในเอาต์พุต (http://localhost:8080) จากนั้นเลือก "เปิดตัวอย่างเว็บ" ในเคล็ดลับเครื่องมือที่ปรากฏขึ้น
  2. แท็บเบราว์เซอร์ใหม่จะเปิดขึ้นและแสดงข้อความ Hello, World!

Hot Reload

  1. เปิดไฟล์ app.py
  2. เปลี่ยนข้อความทักทายเป็น Hello from Python

สังเกตได้ทันทีว่าในOutputหน้าต่างKubernetes: Run/Debugมุมมอง ผู้สังเกตการณ์จะซิงค์ไฟล์ที่อัปเดตกับคอนเทนเนอร์ใน Kubernetes

Update initiated
Build started for artifact python-app
Build completed for artifact python-app

Deploy started
Deploy completed

Status check started
Resource pod/python-app-6f646ffcbb-tn7qd status updated to In Progress
Resource deployment/python-app status updated to In Progress
Resource deployment/python-app status completed successfully
Status check succeeded
...
  1. หากเปลี่ยนไปใช้Kubernetes: Run/Debug - Detailedมุมมอง คุณจะเห็นว่าระบบจดจำการเปลี่ยนแปลงไฟล์ จากนั้นจะสร้างและติดตั้งแอปใหม่
files modified: [app.py]
Syncing 1 files for gcr.io/veer-pylab-01/python-app:3c04f58-dirty@sha256:a42ca7250851c2f2570ff05209f108c5491d13d2b453bb9608c7b4af511109bd
Copying files:map[app.py:[/app/app.py]]togcr.io/veer-pylab-01/python-app:3c04f58-dirty@sha256:a42ca7250851c2f2570ff05209f108c5491d13d2b453bb9608c7b4af511109bd
Watching for changes...
[python-app] * Detected change in '/app/app.py', reloading
[python-app] * Restarting with stat
[python-app] * Debugger is active!
[python-app] * Debugger PIN: 744-729-662
  1. รีเฟรชแท็บเบราว์เซอร์ที่คุณเห็นผลลัพธ์ก่อนหน้าเพื่อดูผลลัพธ์ที่อัปเดตแล้ว

การแก้ไขข้อบกพร่อง

  1. ไปที่มุมมองการแก้ไขข้อบกพร่องและหยุดเธรดปัจจุบัน 647213126d7a4c7b.png หากระบบขอ คุณสามารถเลือกทำความสะอาดหลังจากการเรียกใช้แต่ละครั้งได้
  2. 70d6bd947d04d1e6.png
  3. คลิก Cloud Code ในเมนูด้านล่าง แล้วเลือก Debug on Kubernetes เพื่อเรียกใช้แอปพลิเคชันในโหมด debug
  • ในKubernetes Run/Debug - DetailedมุมมองของOutputหน้าต่าง ให้สังเกตว่า Skaffold จะนำแอปพลิเคชันนี้ไปใช้งานในโหมดแก้ไขข้อบกพร่อง
  1. เมื่อกระบวนการเสร็จสมบูรณ์ คุณจะเห็นดีบักเกอร์ที่แนบมาและแท็บเอาต์พุตระบุว่า Attached debugger to container "python-app-8476f4bbc-h6dsl" successfully. และ URL http://localhost:8080 แสดงอยู่
Port forwarding pod/python-app-8bd64cf8b-cskfl in namespace default, remote port 5678 -> http://127.0.0.1:5678
  1. แถบสถานะด้านล่างจะเปลี่ยนสีจากสีน้ำเงินเป็นสีส้มเพื่อระบุว่าอยู่ในโหมดแก้ไขข้อบกพร่อง
  2. ในKubernetes Run/Debug ให้สังเกตว่ามีการเริ่มคอนเทนเนอร์ที่แก้ไขข้อบกพร่องได้
**************URLs*****************
Forwarded URL from service python-app: http://localhost:8080
Debuggable container started pod/python-app-8bd64cf8b-cskfl:python-app (default)
Update succeeded
***********************************

ใช้เบรกพอยท์

  1. เปิดไฟล์ app.py
  2. ค้นหาข้อความที่ระบุว่า return message
  3. เพิ่มเบรกพอยต์ในบรรทัดนั้นโดยคลิกพื้นที่ว่างทางด้านซ้ายของหมายเลขบรรทัด ตัวบ่งชี้สีแดงจะแสดงขึ้นเพื่อระบุว่าได้ตั้งค่าเบรกพอยต์แล้ว
  4. เมื่อเรียกใช้เป็นครั้งแรก ระบบจะแสดงข้อความแจ้งเพื่อถามว่าแหล่งที่มาอยู่ตรงไหนในคอนเทนเนอร์ ค่านี้เกี่ยวข้องกับไดเรกทอรีใน Dockerfile

กด Enter เพื่อยอมรับค่าเริ่มต้น

fccc866f32b5ed86.png

การสร้างและทำให้แอปพลิเคชันใช้งานได้จะใช้เวลา 2-3 นาที

  1. โหลดเบราว์เซอร์ซ้ำและสังเกตว่าโปรแกรมแก้ไขข้อบกพร่องจะหยุดกระบวนการที่เบรกพอยท์และช่วยให้คุณตรวจสอบตัวแปรและสถานะของแอปพลิเคชันที่ทำงานจากระยะไกลใน GKE ได้
  2. คลิกส่วนตัวแปร
  3. คลิก Locals แล้วคุณจะเห็นตัวแปร "message"
  4. ดับเบิลคลิกชื่อตัวแปร "message" แล้วเปลี่ยนค่าในป๊อปอัปเป็นค่าอื่น เช่น "Greetings from Python"
  5. คลิกปุ่ม "ดำเนินการต่อ" ในแผงควบคุมการแก้ไขข้อบกพร่อง 607c33934f8d6b39.png
  6. ตรวจสอบการตอบกลับในเบราว์เซอร์ ซึ่งตอนนี้จะแสดงค่าที่อัปเดตที่คุณเพิ่งป้อน
  7. หยุดโหมด "แก้ไขข้อบกพร่อง" โดยกดปุ่มหยุด 647213126d7a4c7b.png และนำเบรกพอยท์ออกโดยคลิกเบรกพอยท์อีกครั้ง

5. การพัฒนาบริการ REST แบบ CRUD อย่างง่าย

ตอนนี้แอปพลิเคชันของคุณได้รับการกำหนดค่าอย่างเต็มรูปแบบสำหรับการพัฒนาแบบคอนเทนเนอร์แล้ว และคุณได้ทำตามเวิร์กโฟลว์การพัฒนาพื้นฐานด้วย Cloud Code แล้ว ในส่วนต่อไปนี้ คุณจะได้ฝึกฝนสิ่งที่ได้เรียนรู้โดยการเพิ่มปลายทางของบริการ REST ที่เชื่อมต่อกับฐานข้อมูลที่มีการจัดการใน Google Cloud

เขียนโค้ดบริการ REST

โค้ดด้านล่างสร้างบริการ REST อย่างง่ายที่ใช้ Spanner เป็นฐานข้อมูลที่สนับสนุนแอปพลิเคชัน สร้างแอปพลิเคชันโดยคัดลอกโค้ดต่อไปนี้ลงในแอปพลิเคชัน

  1. สร้างแอปพลิเคชันหลักโดยแทนที่ app.py ด้วยเนื้อหาต่อไปนี้
import os
from flask import Flask, request, jsonify
from google.cloud import spanner


app = Flask(__name__)


instance_id = "music-catalog"

database_id = "musicians"

spanner_client = spanner.Client()
instance = spanner_client.instance(instance_id)
database = instance.database(database_id)


@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"

@app.route('/singer', methods=['POST'])
def create():
    try:
        request_json = request.get_json()
        singer_id = request_json['singer_id']
        first_name = request_json['first_name']
        last_name = request_json['last_name']
        def insert_singers(transaction):
            row_ct = transaction.execute_update(
                f"INSERT Singers (SingerId, FirstName, LastName) VALUES" \
                f"({singer_id}, '{first_name}', '{last_name}')"
            )
            print("{} record(s) inserted.".format(row_ct))

        database.run_in_transaction(insert_singers)

        return {"Success": True}, 200
    except Exception as e:
        return e



@app.route('/singer', methods=['GET'])
def get_singer():

    try:
        singer_id = request.args.get('singer_id')
        def get_singer():
            first_name = ''
            last_name = ''
            with database.snapshot() as snapshot:
                results = snapshot.execute_sql(
                    f"SELECT SingerId, FirstName, LastName FROM Singers " \
                    f"where SingerId = {singer_id}",
                    )
                for row in results:
                    first_name = row[1]
                    last_name = row[2]
                return (first_name,last_name )
        first_name, last_name = get_singer()  
        return {"first_name": first_name, "last_name": last_name }, 200
    except Exception as e:
        return e


@app.route('/singer', methods=['PUT'])
def update_singer_first_name():
    try:
        singer_id = request.args.get('singer_id')
        request_json = request.get_json()
        first_name = request_json['first_name']
        
        def update_singer(transaction):
            row_ct = transaction.execute_update(
                f"UPDATE Singers SET FirstName = '{first_name}' WHERE SingerId = {singer_id}"
            )

            print("{} record(s) updated.".format(row_ct))

        database.run_in_transaction(update_singer)
        return {"Success": True}, 200
    except Exception as e:
        return e


@app.route('/singer', methods=['DELETE'])
def delete_singer():
    try:
        singer_id = request.args.get('singer')
    
        def delete_singer(transaction):
            row_ct = transaction.execute_update(
                f"DELETE FROM Singers WHERE SingerId = {singer_id}"
            )
            print("{} record(s) deleted.".format(row_ct))

        database.run_in_transaction(delete_singer)
        return {"Success": True}, 200
    except Exception as e:
        return e

port = int(os.environ.get('PORT', 8080))
if __name__ == '__main__':
    app.run(threaded=True, host='0.0.0.0', port=port)

เพิ่มการกำหนดค่าฐานข้อมูล

หากต้องการเชื่อมต่อกับ Spanner อย่างปลอดภัย ให้ตั้งค่าแอปพลิเคชันให้ใช้ Workload Identity ซึ่งจะช่วยให้แอปพลิเคชันของคุณทำหน้าที่เป็นบัญชีบริการของตัวเองและมีสิทธิ์แต่ละรายการเมื่อเข้าถึงฐานข้อมูล

  1. อัปเดต deployment.yaml เพิ่มโค้ดต่อไปนี้ที่ส่วนท้ายของไฟล์ (ตรวจสอบว่าคุณเก็บการเยื้องแท็บไว้ในตัวอย่างด้านล่าง)
      serviceAccountName: python-ksa
      nodeSelector:
        iam.gke.io/gke-metadata-server-enabled: "true" 

หลังจากทำการเปลี่ยนแปลงแล้ว ส่วนข้อมูลจำเพาะควรมีลักษณะดังนี้

   spec:
     containers:
     - name: python-app
       image: python-app
     serviceAccountName: python-ksa
     nodeSelector:
       iam.gke.io/gke-metadata-server-enabled: "true"

ทำให้แอปพลิเคชันใช้งานได้และตรวจสอบ

  1. ในแผงที่ด้านล่างของ Cloud Shell Editor ให้เลือก Cloud Code แล้วเลือก Debug on Kubernetes ที่ด้านบนของหน้าจอ
  2. เมื่อการสร้างและการทดสอบเสร็จสมบูรณ์แล้ว แท็บเอาต์พุตจะแสดงข้อความ Resource deployment/python-app status completed successfully และ URL ที่ระบุคือ "Forwarded URL from service python-app: http://localhost:8080"
  3. เพิ่มรายการ 2-3 รายการ

จากเทอร์มินัล Cloud Shell ให้เรียกใช้คำสั่งด้านล่าง

curl -X POST http://localhost:8080/singer -H 'Content-Type: application/json' -d '{"first_name":"Cat","last_name":"Meow", "singer_id": 6}'
  1. ทดสอบ GET โดยเรียกใช้คำสั่งด้านล่างในเทอร์มินัล
curl -X GET http://localhost:8080/singer?singer_id=6
  1. ทดสอบการลบ: ตอนนี้ลองลบรายการโดยเรียกใช้คำสั่งต่อไปนี้ เปลี่ยนค่าของรหัสสินค้าหากจำเป็น
curl -X DELETE http://localhost:8080/singer?singer_id=6
    This throws an error message
500 Internal Server Error

ระบุและแก้ไขปัญหา

  1. โหมดแก้ไขข้อบกพร่องและค้นหาปัญหา มาดูเคล็ดลับบางส่วนกัน
  • เราทราบว่ามีบางอย่างผิดปกติกับคำสั่ง DELETE เนื่องจากไม่ได้แสดงผลลัพธ์ที่ต้องการ ดังนั้นคุณจึงตั้งค่าเบรกพอยต์ใน app.py ในเมธอด delete_singer
  • เรียกใช้การดำเนินการทีละขั้นตอนและดูตัวแปรในแต่ละขั้นตอนเพื่อสังเกตค่าของตัวแปรภายในในหน้าต่างด้านซ้าย
  • หากต้องการสังเกตค่าที่เฉพาะเจาะจง เช่น singer_id และ request.args ให้เพิ่มตัวแปรเหล่านี้ลงในหน้าต่าง Watch
  1. โปรดทราบว่าค่าที่กำหนดให้กับ singer_id คือ None เปลี่ยนโค้ดเพื่อแก้ไขปัญหา

ข้อมูลโค้ดที่แก้ไขแล้วจะมีลักษณะดังนี้

@app.route('/delete-singer', methods=['DELETE', 'GET'])
def delete_singer():
    try:
        singer_id = request.args.get('singer_id')
  1. เมื่อรีสตาร์ทแอปพลิเคชันแล้ว ให้ทดสอบอีกครั้งโดยลองลบ
  2. หยุดเซสชันการแก้ไขข้อบกพร่องโดยคลิกสี่เหลี่ยมสีแดงในแถบเครื่องมือการแก้ไขข้อบกพร่อง 647213126d7a4c7b.png

6. ล้างข้อมูล

ยินดีด้วย ในแล็บนี้ คุณได้สร้างแอปพลิเคชัน Python ใหม่ตั้งแต่ต้นและกำหนดค่าให้ทำงานร่วมกับคอนเทนเนอร์ได้อย่างมีประสิทธิภาพ จากนั้นคุณได้ทําการทำให้ใช้งานได้และแก้ไขข้อบกพร่องของแอปพลิเคชันไปยังคลัสเตอร์ GKE ระยะไกลตามโฟลว์ของนักพัฒนาซอฟต์แวร์เดียวกันกับที่พบในสแต็กแอปพลิเคชันแบบดั้งเดิม

วิธีล้างข้อมูลหลังจากทำแล็บเสร็จ

  1. ลบไฟล์ที่ใช้ในห้องทดลอง
cd ~ && rm -rf ~/music-service
  1. ลบโปรเจ็กต์เพื่อนำโครงสร้างพื้นฐานและทรัพยากรที่เกี่ยวข้องทั้งหมดออก