การพัฒนา InnerLoop ด้วย Python

1. ภาพรวม

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

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

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

  • การสร้างแอปพลิเคชันเริ่มต้นใหม่ของ Python
  • ดูขั้นตอนการพัฒนา
  • พัฒนาบริการ REST ของ CRUD แบบง่าย

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

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

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

b35bf95b8bf3d5d8.pnga99b7ace416376c4.pngbd84a6d3004737c5.png

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

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

แล็บนี้ออกแบบและทดสอบเพื่อใช้กับ 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)')

รับซอร์สโค้ด

  1. ซอร์สโค้ดสำหรับแล็บนี้อยู่ใน container-developer-workshop ใน GoogleCloudPlatform บน GitHub โคลนด้วยคำสั่งด้านล่าง แล้วเปลี่ยนเป็นไดเรกทอรี
git clone https://github.com/GoogleCloudPlatform/container-developer-workshop.git &&
cd container-developer-workshop/labs/python
mkdir music-service && cd music-service 
cloudshell workspace .

หากเทอร์มินัลไม่ได้เปิดอยู่ ให้ใช้ชุดค่าผสมของปุ่ม `ctrl+`` เพื่อเปิดหน้าต่างเทอร์มินัลใหม่

จัดสรรโครงสร้างพื้นฐานที่ใช้ในแล็บนี้

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

../setup.sh

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

  1. สร้างไฟล์ชื่อ requirements.txt แล้วคัดลอกเนื้อหาต่อไปนี้ลงในไฟล์
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 แล้วจึงทําการติดตั้งใช้งานแอปพลิเคชันใน GKE โดยอัตโนมัติ ซึ่งจะเกิดขึ้นเบื้องหลังโดยซ่อนรายละเอียดจากขั้นตอนการทำงานของนักพัฒนาแอป

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

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

fdc797a769040839.png

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

cfce0d11ef307087.png

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

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

f95b620569ba96c5.png

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

94acdcdda6d2108.png

เมื่อสร้างและทดสอบเสร็จแล้ว แท็บเอาต์พุตจะแสดงข้อความ Attached debugger to container "python-app-8476f4bbc-h6dsl" successfully. และ URL http://localhost:8080

  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. คลิก Cloud Code ในเมนูด้านล่าง แล้วเลือก Debug on Kubernetes เพื่อเรียกใช้แอปพลิเคชันในโหมด debug
  • ในKubernetes Run/Debug - DetailedมุมมองของOutputหน้าต่าง ให้สังเกตว่า Skaffold จะนำแอปพลิเคชันนี้ไปใช้งานในโหมดแก้ไขข้อบกพร่อง
  1. เมื่อเรียกใช้เป็นครั้งแรก พรอมต์จะถามว่าแหล่งที่มาอยู่ตรงไหนในคอนเทนเนอร์ ค่านี้เกี่ยวข้องกับไดเรกทอรีใน Dockerfile

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

583436647752e410.png

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

  1. เมื่อกระบวนการเสร็จสมบูรณ์ คุณจะเห็นว่าดีบักเกอร์แนบอยู่
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. โหลดเบราว์เซอร์ซ้ำและสังเกตว่าดีบักเกอร์จะหยุดกระบวนการที่เบรกพอยต์และช่วยให้คุณตรวจสอบตัวแปรและสถานะของแอปพลิเคชันที่ทำงานจากระยะไกลใน GKE ได้
  5. คลิกส่วนตัวแปร
  6. คลิก Locals แล้วคุณจะเห็นตัวแปร "message"
  7. ดับเบิลคลิกชื่อตัวแปร "message" แล้วเปลี่ยนค่าในป๊อปอัปเป็นค่าอื่น เช่น "Greetings from Python"
  8. คลิกปุ่มดำเนินการต่อในแผงควบคุมการแก้ไขข้อบกพร่อง 607c33934f8d6b39.png
  9. ตรวจสอบการตอบกลับในเบราว์เซอร์ ซึ่งตอนนี้จะแสดงค่าที่อัปเดตที่คุณเพิ่งป้อน
  10. หยุดโหมด "แก้ไขข้อบกพร่อง" โดยกดปุ่มหยุด 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" 

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

  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 container-developer-workshop
  1. ลบโปรเจ็กต์เพื่อนำโครงสร้างพื้นฐานและทรัพยากรที่เกี่ยวข้องทั้งหมดออก