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

1. ภาพรวม

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

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

ในห้องทดลองนี้ คุณจะได้เรียนรู้วิธีการพัฒนาด้วยคอนเทนเนอร์ใน GCP ดังต่อไปนี้

  • การสร้างแอปพลิเคชันเริ่มต้นสำหรับ Python ใหม่
  • แนะนำกระบวนการพัฒนา
  • พัฒนาบริการ CRUD REST อย่างง่าย
  • การทำให้ใช้งานได้กับ 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 ของระบบคลาวด์ การใช้งาน Codelab นี้น่าจะไม่มีค่าใช้จ่ายใดๆ หากมี หากต้องการปิดทรัพยากรเพื่อไม่ให้มีการเรียกเก็บเงินนอกเหนือจากบทแนะนำนี้ คุณสามารถลบทรัพยากรที่คุณสร้างหรือลบทั้งโปรเจ็กต์ได้ ผู้ใช้ใหม่ของ Google Cloud จะมีสิทธิ์เข้าร่วมโปรแกรมทดลองใช้ฟรี$300 USD

เริ่มผู้แก้ไข Cloudshell

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

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

8560cc8d45e8c112.png

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

9e504cb98a6a8005.png

  1. ตัวแก้ไขจะเปิดขึ้นโดยมีนักสำรวจอยู่ด้านขวา และเอดิเตอร์จะเปิดขึ้นตรงกลาง
  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)')

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

ในห้องทดลองนี้ คุณจะทำให้โค้ดใช้งานได้กับ 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 &

คลัสเตอร์เวิร์กสเตชันของระบบคลาวด์

  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 นาทีในการเปลี่ยนสถานะเป็น READY

2e23c2e9983d1ccf.png

  1. เปิดเวิร์กสเตชันระบบคลาวด์ในคอนโซลและสร้างอินสแตนซ์ใหม่

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. เมื่อเปิดตัวเวิร์กสเตชันแล้ว คุณจะเห็น Code OSS IDE ปรากฏขึ้น คลิก "ทำเครื่องหมายว่าเสร็จสิ้น" ในหน้าเริ่มต้นใช้งาน 1 เวิร์กสเตชัน 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 ให้คุณโหลดการเปลี่ยนแปลงโค้ดซ้ำโดยอัตโนมัติในแอปขวดแก้ว 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. คัดลอกรหัสโปรเจ็กต์สำหรับห้องทดลองนี้จากหน้า qwiklabs

fcff2d10007ec5bc.png

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

ทำให้ใช้งานได้กับ Kubernetes

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

d99a88992e15fea9.png

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

bfd65e9df6d4a6cb.png

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

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

9c87ccbf5d06f50a.png

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

804abc8833ffd571.png

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

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

โหลดซ้ำแบบ Hot

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

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

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

เขียนโค้ดบริการที่เหลือ

โค้ดด้านล่างจะสร้างบริการพักพื้นฐานที่ใช้ 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 อย่างปลอดภัย ให้ตั้งค่าแอปพลิเคชันให้ใช้ข้อมูลระบุตัวตนของภาระงาน วิธีนี้ทำให้แอปพลิเคชันของคุณทำหน้าที่เป็นบัญชีบริการของตนเองและมีสิทธิ์แต่ละรายการเมื่อเข้าถึงฐานข้อมูล

  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 ที่ส่งต่อจากบริการ Python-app: http://localhost:8080 จะแสดงขึ้น"
  3. เพิ่ม 2 รายการ

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

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