step1. 透過UI創建VM
step2. SSH連線VM
直接連線(3種SHH額外方式)
step3. 終端機指令
安裝apache2並檢測server啟動狀態
$ sudo apt update
$ sudo apt install apache2 -y
$ sudo systemctl status apache2
$ sudo apt install net-tools
$ sudo netstat -tulnp | grep 80
step4. 測試連線
執行指令
curl http://[apache2 server ip]/
結果
step5. 建立網頁
指令
第三行展示錯誤的寫入html方法 (原因 : 這是一個多指令組合的指令,因此sudo只會允許第一個指令使用root,這就是為甚麼第三行會出現permission denied)
$ cd /var/www/html
$ sudo echo "RRRRRRRRRR" > markerpen_yelling.htm
-bash: markerpen_yelling.htm: Permission denied
$ sudo bash -c 'echo "RRRRRRRRRR" > markerpen_yelling.htm'
指令解說 bash -c
bash
是一個 Unix Shell,而 -c
參數告訴 bash
去執行後面引號中的命令字符串,並把它作為完整的腳本來運行。
指令解說 sudo -l
作用 : 可以確認自己可以使用到sudo的哪些指令
$ sudo -l
Matching Defaults entries for mingchu_chou92 on webtesting1:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, use_pty
User mingchu_chou92 may run the following commands on webtesting1:
(ALL : ALL) NOPASSWD: ALL (這代表有sudo的最高權限)
hostname -I
可以利用這項技術實現多台Server之間的IP管理
$ sudo bash -c 'echo "$(hostname -I)" > hostip.htm'
$ curl http://34.81.100.236/hostip.htm
10.140.0.3 (VM會把自己的IP顯示出來)
step1. 透過UI創建VM (先不要點create,點選下方的Advanced Option當中的Management)
step2. 透過UI創建VM (寫入自動執行腳本 + create VM)
這個腳本會在VM開機的後執行腳本
#! /bin/bash
apt update
apt -y install apache2
cat <<EOF > /var/www/html/index.html
<html><body><p>Linux startup script added directly. $(hostname -I) </p></body></html>
名稱
建立本地網頁,運行於GCP平台
[會有permission denied的問題,導致stroage放到GCE的時候出現無法複製的問題]
[permission會因為service account導致這個問題發生]
架構圖
step1. 在本地端創建一個網頁
step2. 創建 Cloud Storage 內部的 Bucket + 上傳資料
Bucket上傳方法1
找到 Cloud Storage
創建 Bucket
上傳檔案
Bucket上傳方法2
先創建 Bucket
大致操作都一樣,但是可以嘗試不要使用multui-region比免花太多錢
上傳資料到 GCE Shell
上
請記得這個shell是GCP提供給user的特殊須擬機,他有5GB的儲存空間,儘管我們把機器reboot資料仍然會在裡面不會消失,除非我們刪除
從 GCE Shell
上傳到 Bucket
從 GCE Shell 上傳到 Bucket
$ gsutil ls gs:// (顯示目前有哪些bucket)
$ gsutil cp [args] [fileA] [Bucket-Location] (Bucket位置可以從上一個指令獲得)
檢查是否有上傳成功
step3. 把Bucket的資料移到GCE的VM內
先跟以前一樣創建VM(ubuntu的虛擬機)
但是這個要特別注意,如果有其他project存在的話,會因為這個選項會導致我們沒辦法把東西移動過去(不過這都是以後再說的了…)
SSH連線
安裝伺服器 + 架設伺服器
$ sudo apt update
$ sudo apt install apache2 -y
$ gsutil cp -r gs://marktestingbucket2-markwatchcloud .
$ sudo cp -r marktestingbucket2-markwatchcloud/ /var/www/html/
檢查
Project-Name
Storage逆向回傳
架構
Example3展是怎麼從本地->Storages->VM
現在展示 VM -> Storages -> 本地
運行指令
$ echo "hahahahahaha" > markerpenlaughing.htm
$ gsutil ls gs://
gs://marktestingbucket1-markwatchcloud/
gs://marktestingbucket2-markwatchcloud
$ gsutil cp markerpenlaughing.htm gs://marktestingbucket1-markwatchcloud/
報錯訊息 (Service Account權限不足)
解決方法
解決方法1.
解決方法2.
創建IAM帳戶 (根據林廣哲所說,這個步驟似乎並不需要)
調整GCE的VM設定 (需要回到GCE暫停VM才可以調整設定)
將VM的Service Acocunt修改
修改權限
也要把Sotrage
也改成可讀可寫
進入ssh修改系統
刪除原先的permission設定快取,否則系統會優先讀取這個設定
指令 : rm -rf .gsutil/
檢查
project-name
建立DB,讓使用者連線Server進一步訪問DB
架構
step1. server 建置
step 1-1
step 1-2
#! /bin/bash
apt update
apt -y install apache2
cat <<EOF > /var/www/html/index.html
<html><body><p>Linux startup script added directly. $(hostname -I) </p></body></html>
step2. DB 建置
step2-1. 建立一個ubuntu22.04 + 不需要防火牆規則的VM
基本配置都跟VM建置一樣,不再贅述
step2-2. 進入DB虛擬機的ssh下載mariadb
按照下面指令以及程式碼輸入
$ sudo apt-get install apt-transport-https curl
$ sudo curl -o /etc/apt/keyrings/mariadb-keyring.pgp 'https://mariadb.org/mariadb_release_signing_key.pgp'
$ sudo vim /etc/apt/sources.list.d/mariadb.sources
$ sudo cat /etc/apt/sources.list.d/mariadb.sources
# MariaDB 11.1 repository list - created 2023-11-08 06:16 UTC
# https://mariadb.org/download/
X-Repolib-Name: MariaDB
Types: deb
# deb.mariadb.org is a dynamic mirror if your preferred mirror goes offline. See https://mariadb.org/mirrorbits/ for details.
# URIs: https://deb.mariadb.org/11.1/ubuntu
URIs: https://ftp.ubuntu-tw.org/mirror/mariadb/repo/11.1/ubuntu
Suites: jammy
Components: main main/debug
Signed-By: /etc/apt/keyrings/mariadb-keyring.pgp
$ sudo apt-get update # 更新
$ sudo apt install mariadb-server # 安裝 MariaDB
$ sudo systemctl status mariadb # 安裝完服務就已經啟動了,可以再檢查一下
$ sudo mysql_secure_installation # 初始化 MariaDB
Enter current password for root (enter for none): 直接按下Enter
Switch to unix_socket authentication [Y/n] : 選擇n
Change the root password? [Y/n] : 看個人想換甚麼密碼
Remove anonymous users? [Y/n] : 考量安全選擇y
Disallow root login remotely? [Y/n] : y
Remove test database and access to it? [Y/n] : y
Reload privilege tables now? [Y/n] : y
step2-3. 檢查DB狀態
step2-4. 嘗試登入 + 建立資料庫
終端指令
sudo mysql -u root -p
DB指令
create database markdb;
use markdb;
create table addrbook(name varchar(50) not null, action char(20));
insert into addrbook(name,action) values ("mark","yelling:RRRRRRRR");
select name,action from addrbook;
step2-5. 修改DB配置,使其允許其他IP登入
下載net-tool 並解查 mariadb的port號
檢查DB
sudo apt install net-tools (記得要先exit離開DB)
sudo netstat -tunlp | grep mariadb
結果 : 127.0.0.1:3306 -> 表示只能連接到localhost才能到3306port存取DB
為了讓Server可以連接到db,我們會希望設定是0.0.0.0:[對應port號]
修改db配置
$ sudo vim /etc/mysql/mariadb.conf.d/50-server.cnf
找到bind-address並改成0.0.0.0
$ sudo systemctl restart mariadb
仍然無法存取的原因及結果
但是DB的root本身仍不允許除了localhost以外的人登入
因此儘管看到mariadb的服務變成`0.0.0.0:3306`
依樣無法用其他ip登入root
mingchu_chou92@mdb-server:~$ mysql -h 10.140.0.8 -u root -p
mysql: Deprecated program name. It will be removed in a future release, use '/usr/bin/mariadb' instead
Enter password:
ERROR 2002 (HY000): Received error packet before completion of TLS handshake. The authenticity of the following error cannot be verified: 1130 - Host 'mdb-server.asia-east1-a.c.imposing-union-436602-v2.internal' is not allowed to connect to this MariaDB server
打開DB允許哪些IP存取的權限
終端畫面
mingchu_chou92@mdb-server:~$ mysql -u root -p
mysql: Deprecated program name. It will be removed in a future release, use '/usr/bin/mariadb' instead
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 32
Server version: 11.1.6-MariaDB-ubu2204 mariadb.org binary distribution
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]> GRANT ALL PRIVILEGES ON *.* TO 'root'@'10.140.0.8' IDENTIFIED BY 'mark' WITH GRANT OPTION;
Query OK, 0 rows affected (0.001 sec)
MariaDB [(none)]> GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'mark' WITH GRANT OPTION;
Query OK, 0 rows affected (0.001 sec)
MariaDB [(none)]> FLUSH PRIVILEGES; (更新)
GRANT ALL PRIVILEGES ON *.* TO '[使用者]'@'[允許的IP位置]' IDENTIFIED BY 'mark' WITH GRANT OPTION; (其中 `%` 可以表示 `任意的IP位置都被允許`)
結果:
step3. 建立server與db之間的連線
step3-1. 打開server的ssh
step3-2. 嘗試ping db檢查連線
step3-3. 在server端安裝maria-db的client程式
`$ sudo apt install mysql-client`
step3-4. 嘗試登入DB
step3-5. 建立防火牆
請注意因為這台db跟server的VM都使採用default的網路,因此一定要填寫default network
限制網路只限制在台灣的IP
將防火牆設定加入db當中
建立一台不在台灣的VM,並嘗試連線看看
step3-6. 建立php後端程式向db發送請求
檢查sudo dpkg -l | grep apache2
終端畫面
$ sudo apt install software-properties-common
$ sudo add-apt-repository ppa:ondrej/php
$ sudo apt update
$ sudo apt upgrade -y
$ sudo apt install php8.1 libapache2-mod-php8.1 php8.1-gd php8.1-mysql php8.1-curl php8.1-mbstring php8.1-intl -y
$ sudo apt install php8.1-gmp php8.1-bcmath php8.1-imagick php8.1-xml php8.1-zip -y
$ sudo a2enmod php8.1
$ sudo systemctl restart apache2
<?php
phpinfo();
?>
終端畫面
mingchu_chou92@www-server:~$ vim test.php
mingchu_chou92@www-server:~$ cat test.php
<?php
$servername="10.140.0.8";
$username="root";
$password="mark";
$dbname="markdb";
$conn = new mysqli($servername, $username, $password, $dbname);
if($conn->connect_error){
die("connection failed: " . $conn->connect_error);
}
else{
echo "connect OK!" . "<br>";
}
$sql="select name,action from addrbook";
$result=$conn->query($sql);
if($result->num_rows>0){
while($row=$result->fetch_assoc()){
echo "name: " . $row["name"] . "\taction: " . $row["action"] . "<br>";
}
} else {
echo "0 record";
}
?>
mingchu_chou92@www-server:~$ sudo cp test.php /var/www/html/
結果
step1. Build VPC Network
and VMs
Set VPC Network's firewall
Set VPC Newtork's Route Rule
Set the costum VPC
Set Costum VPC's subnet/firewall/route rules
Change Costum VPC's firewall rules
可以自己設定是要allow或是deny又或是Priority數值
檢查
建立VM1,並安裝上自己建立的VPC
建立VM2,大致跟VM1相同,但是選擇VPC2 (VPC根VM的region要相同哦…)
step2. 建立雙向(VPC1與VPC2的雙向) VPC Peering
進入VPC Peering介面
建立第一條 VPC Peering設定
可以發現建立完處於inactive的狀態是因為只有建立單向
所以建立另一向的VPC Peering以避免inactive狀態
確認兩台VM是否可以互相用ICMP/HTTP/SSH通訊 | SSH Between VMs
ICMP
HTTP
SSH
創建sql並且是private ip (default VPC) + 打開sql的admin管理(安裝SQL可以參考這裡)
創建一個Instance + Ubuntu20.04作業系統 + default VPC設置
ssh進入Instance並安裝mysql的client端軟體(要怎麼SSH可以參考這邊)
在Client端(沒有安裝sql-server的那台VM)安裝SQL-Client軟體 + 嘗試登入建立好的sql-server
$ sudo apt install mysql-client -y
$ mysql -h 'sql public ip' -u root -p
在DB內部建立檔案
create database markdb;
use markdb;
create table addrbook(name varchar(50) not null, action char(20));
insert into addrbook(name,action) values ("mark","yelling:RRRRRRRR");
insert into addrbook(name,action) values ("markerpen","laughing:HAHAHAHA");
select name,action from addrbook;
$ sudo apt install apache2 php libapache2-mod-php php-mysql -y
$ sudo systemctl restart apache2
$ sudo vim /var/www/html/mark.php
$ sudo cat /var/www/html/mark.php
<?php
$servername="10.56.224.3";
$username="root";
$password="123456";
$dbname="markdb";
$conn = new mysqli($servername, $username, $password, $dbname);
if($conn->connect_error){
die("connection failed: " . $conn->connect_error);
}
else{
echo "connect OK!" . "<br>";
}
$sql="select name,action from addrbook";
$result=$conn->query($sql);
if($result->num_rows>0){
while($row=$result->fetch_assoc()){
echo "name: " . $row["name"] . "\taction: " . $row["action"] . "<br>";
}
} else {
echo "0 record";
}
?>
結果
unmanaged load balancer
(這些server一定要在同樣的 region 跟 zone)step1. 創建相同 Region&Zone 的兩台VM + 開機建立網頁伺服器 + Ubuntu作業系統
www-mark1
& www-mark2
+ 地區都是 Taiwan
& asia-east1-c
step2. 將要管理的VM加入到同一個 Group
底下
step2-1. 切入 Instance groups + 點 CREATE INSTANCE GROUP
step2-2. 創建 unmanaged load-balancer
step3. 創建 Load-Balancer
step3-1. 進入 Load Balancer(LB)
頁面 + 創建LB
step3-2. 創建LB種類
step3-3. 創建LB的名稱+位置+網路
step3-4. 創建LB的 Frontend configuration
step3-5. 創建LB的 Backend configuration
step3-6. 創建LB的 Health Check
刪除web server的公有網路
step1. 照ex8創建整個網路架構
step2. 創建Firewall允許http存取load-balancer + 允許health-check存取load-balancer
允許http存取load-balancer
允許health-checkk存取load-balancer
step3. 修改GCE兩台VMs的設定
兩台VM的允許Http流量關閉 + 新增剛才創建的兩個Firewall tags
關閉External IP
step4. 檢查load-balance
step1. 創建template
step2. 在GCE/Instance Group/ 創建instance-group
Minimum number of instances
至少要建立的VM數量 ; Maximum number of instances
則表示系統最多建立的VMs數量step3. 創建load-balancer
step3-1. 創建load-balancer
step3-2. 增加frontend-config
step3-3. 增加backend-config
step4. 壓力測試
cat /dev/zero > /dev/null
+ 右邊執行top
step1-1. 創建unmanaged instance group
step1-2. 在DNS網站建立一個Domain-Name
step2. 創建Load-Balancer
step3. Frontend configuration
step4. Backend configuration + Health-Check
step1. 在VPC當中加入允許health-check的防火牆規則,並確認是否有允許Http(網頁伺服器)以及SSH(debug用)的規則
step2. 因為 apache-server 沒有 public ip,為了讓 apache-server 可以安裝網頁軟體,所以我們需要NAT設置讓 server 不用 public ip 也可以到公網
step3. 創建一個不用 public ip 的 template
這個腳本會在VM開機的後執行腳本
#! /bin/bash
apt update
apt -y install apache2
cat <<EOF > /var/www/html/index.html
<html><body><p>Linux startup script added directly. $(hostname -I) </p></body></html>
step4. 創建instance group
step5. 創建load balancer
Build Load Balancer with different region
架構圖
額外新增Firewall Rule (health-check)
額外新增Firewall Rule (http)
加入NAT(給第一個region)
新增一個給別的region的subnet
加入NAT(給第二個region)
在第一個region創建兩台vm
#! /bin/bash
apt update
apt -y install apache2
cat <<EOF > /var/www/html/index.html
<html><body><p>Linux startup script added directly. $(hostname -I) </p></body></html>
在第二個region創建兩台vm(基本操作跟上面依樣,只有下面幾個操作略微不同)
#! /bin/bash
apt update
apt -y install apache2
cat <<EOF > /var/www/html/index.html
<html><body><p>Linux startup script added directly. $(hostname -I) . In US</p></body></html>
SSH進入 + 執行以下指令
這個資料夾名稱,跟創建LB的時候有關聯很重要,請記住
$ cd /var/www/html/
$ sudo bash -c 'mkdir us; mv index.html us/'
創建兩個groups
Frontend 設置
Backend 設置 (給region1)
Backend 設置 (給region2)
Healtth-Check共用
創建Domain name
新增對應的path
修改Domain name
Internal Load-Balancer
架構圖
增加allow-http的規則
架設NAT
創建apache-server vm
automation腳本
#! /bin/bash
apt update
apt -y install apache2
cat <<EOF > /var/www/html/index.html
<html><body><p>Linux startup script added directly. $(hostname -I) </p></body></html>
創建apache-client vm (大部分都跟apache-server的設置一樣,唯獨以下4個設置不同)
創建group
創建LB
frontend 設置
backend 設置
先enable
創建
新增Domain-name
step1. 上傳Iris訓練模型到cloud storage
$ mkdir test-iris; cd test-iris
$ git clone https://github.com/saedhussain/gcp_serverless_ml.git
$ pip install pandas; pip install scikit-learn
$ cd Iris_model; python
$ python create_iris_model.py
$ export PROJECT_ID=$DEVSHELL_PROJECT_ID
$ export BUCKET=[取一個cloud storage名稱]
$ gsutil mb -p $PROJECT_ID -c standard -l [region名稱] gs://${BUCKET}
$ gsutil cp ./[model名稱] gs://${BUCKET}
step2. 創建cloud function
python版本請改成3.8
main要修改的地方
測試指令
test cmd :
$ curl -m 70 -X POST [你的cloud storage連結 : 可以在cloud function的TESTING當中查看] \
-H "Authorization: bearer $(gcloud auth print-identity-token)" \
-H "Content-Type: application/json" \
-d '{
"features": [2,3,4,5]
}'
Use Cloud Function to modify cloud storage
架構圖
step1. 創建兩個cloud storage(一個用來接收使用者上傳的資料,另一個儲存大於1MB的檔案)
$ export PROJECT_ID=$DEVSHELL_PROJECT_ID
$ export ORIGIN_BUCKET=[取一個cloud storage名稱]
$ export LARGE_BUCKET=[取一個cloud storage名稱]
$ gsutil mb -p $PROJECT_ID -c standard -l [region名稱] gs://${ORIGIN_BUCKET}
$ gsutil mb -p $PROJECT_ID -c standard -l [region名稱] gs://${LARGE_BUCKET}
step2. 創建cloud function
# cloud storage 對應的 cloud function
import functions_framework
from google.cloud import storage
from google.cloud.storage import Blob
# Triggered by a change in a storage bucket
@functions_framework.cloud_event
def hello_gcs(cloud_event):
data = cloud_event.data
event_id = cloud_event["id"]
event_type = cloud_event["type"]
bucket = data["bucket"]
name = data["name"]
metageneration = data["metageneration"]
timeCreated = data["timeCreated"]
updated = data["updated"]
print("="*30)
print(f"Event ID: {event_id}")
print(f"Event type: {event_type}")
print(f"Bucket: {bucket}")
print(f"File: {name}")
print(f"Metageneration: {metageneration}")
print(f"Created: {timeCreated}")
print(f"Updated: {updated}")
print(f"Processing file: {name}.")
storage_client = storage.Client(project='[你的projet-id]')
source_bucket=storage_client.get_bucket('[你用來接收使用者上傳資料的storage]')
destination_bucket=storage_client.get_bucket('[你用來接收大於1MB資料的storage]')
blobs=list(source_bucket.list_blobs(prefix=''))
print(blobs)
for blob in blobs:
if blob.size > 1000000 and blob.name == name:
source_blob = source_bucket.blob(blob.name)
new_blob = source_bucket.copy_blob(source_blob, destination_bucket, blob.name)
blob.delete(if_generation_match=None)
print(f'File moved from {source_blob} to {new_blob}')
else:
print("File size is below 1MB\n")
requirement.txt
functions-framework==3.*
google-cloud-storage
google-cloud
step1. 創建DB
$ gcloud sql instances create [你的DB instance 名稱] --database-version=MYSQL_5_7 --cpu=2 --memory=4GB --root-password=[DB的密碼] --assign-ip --zone=[你想要的region+zone] --availability-type=zonal --no-backup
$ gcloud sql databases create [DB名稱] --instance=[DB instance 名稱]
$ gcloud sql connect [DB-Instance名稱] --user=root
> use mark-db;
>(mark-db) CREATE TABLE info (
id INT NOT NULL AUTO_INCREMENT,
firstname VARCHAR(20),
lastname VARCHAR(20),
age VARCHAR(3),
collegename VARCHAR(150),
PRIMARY KEY (id)
);
>(mark-db) exit
step2. 在當前目錄下建立程式碼
import sqlalchemy
#connection name we noted earlier
connection_name = "[你的project id:DB-Instance名稱]"
#database name
db_name = "[你的db名稱]"
db_user = "root"
db_password = "admin1234"
driver_name = 'mysql+pymysql'
query_string = dict({"unix_socket": "/cloudsql/{}".format(connection_name)})
def writeToSql(request):
#You can change this to match your personal details
stmt = sqlalchemy.text("INSERT INTO info ( firstname, lastname, age, collegename) values ('Sagadevan', 'Kounder', '21', 'XYZ College')")
db = sqlalchemy.create_engine(
sqlalchemy.engine.url.URL(
drivername=driver_name,
username=db_user,
password=db_password,
database=db_name,
query=query_string,
),
pool_size=5,
max_overflow=2,
pool_timeout=30,
pool_recycle=1800
)
try:
with db.connect() as conn:
conn.execute(stmt)
print("Insert successful")
except Exception as e:
print ("Some exception occured" + e)
return 'Error: {}'.format(str(e))
return 'ok'
requirement.txt
SQLAlchemy==1.3.12
PyMySQL==0.9.3
step3. 建立cloud function
$ gcloud functions deploy writeToSql --entry-point writeToSql --runtime python310 --trigger-http --allow-unauthenticated --no-gen2 --source .
$ gcloud functions deploy [cloud function 名稱] --entry-point [function的entry point] --runtime [python版本] --trigger-http --allow-unauthenticated --no-gen2 --source [程式碼的位置]
結果
step1. 根據之前的iris範例建立出對應的模型
$ mkdir test-iris; cd test-iris
$ git clone https://github.com/saedhussain/gcp_serverless_ml.git
$ pip install pandas; pip install scikit-learn
$ cd Iris_model; python
$ python create_iris_model.py
$ export PROJECT_ID=$DEVSHELL_PROJECT_ID
$ export BUCKET=[取一個cloud storage名稱]
$ gsutil mb -p $PROJECT_ID -c standard -l [region名稱] gs://${BUCKET}
$ gsutil cp ./[model名稱] gs://${BUCKET}
step2. 寫對應的app egine 程式碼
import numpy as np
import os
import pickle
from flask import Flask, jsonify
app = Flask(__name__)
# 全局模型變數
model = None
# 下載模型檔案的函數
def download_model_file():
from google.cloud import storage
BUCKET_NAME = "iris-bk"
PROJECT_ID = "avian-casing-435202-m5"
GCS_MODEL_FILE = "iris_model_jan_2020_v1.pkl"
client = storage.Client(PROJECT_ID)
bucket = client.get_bucket(BUCKET_NAME)
blob = bucket.blob(GCS_MODEL_FILE)
folder = '/tmp/'
if not os.path.exists(folder):
os.makedirs(folder)
blob.download_to_filename(folder + "local_model.pkl")
# 載入模型
def load_model():
global model
if not model:
download_model_file()
model = pickle.load(open("/tmp/local_model.pkl", 'rb'))
# 處理路徑格式的功能
@app.route('/features/<path:features>', methods=['GET'])
def iris_predict(features):
global model
# 確保模型已加載
load_model()
# 分解輸入的特徵
try:
feature_list = [float(i) for i in features.split("_")]
if len(feature_list) != 4:
return jsonify({"error": "Invalid number of features. Expected 4 values."}), 400
except ValueError:
return jsonify({"error": "Features must be numeric and separated by underscores."}), 400
# 使用模型進行預測
prediction = model.predict(np.array([feature_list]))
return jsonify({"prediction": prediction[0]})
if __name__ == "__main__":
app.run(host='0.0.0.0', port=8080)
requirements.txt
google-resumable-media==0.6.0
google-cloud-storage==1.30.0
google-cloud-bigquery==1.26.1
flask
pandas
numpy
scikit-learn
app.yaml
runtime: python310
service: iris-test
結果
輸入對應的指令就可以得到preediction的結果
step1. 創建以下幾個檔案
train_model.py (訓練iris-prediction model)
# -*- coding: utf-8 -*-
import pickle
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn import tree
# simple demo for traing and saving model
iris=datasets.load_iris()
x=iris.data
y=iris.target
#labels for iris dataset
labels ={
0: "setosa",
1: "versicolor",
2: "virginica"
}
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=.25)
classifier=tree.DecisionTreeClassifier()
classifier.fit(x_train,y_train)
predictions=classifier.predict(x_test)
#export the model
model_name = 'model.pkl'
print("finished training and dump the model as {0}".format(model_name))
pickle.dump(classifier, open(model_name,'wb'))
import pickle
from flask import Flask, request, jsonify
app = Flask(__name__)
# Load the model
model = pickle.load(open('model.pkl', 'rb'))
labels = {
0: "versicolor",
1: "setosa",
2: "virginica"
}
@app.route("/", methods=["GET"])
def index():
"""Basic HTML response."""
body = (
"<html>"
"<body style='padding: 10px;'>"
"<h1>Welcome to my Flask API</h1>"
"</body>"
"</html>"
)
return body
@app.route('/api', methods=['POST'])
def predict():
# Get the data from the POST request.
data = request.get_json(force = True)
predict = model.predict(data['feature'])
return jsonify(predict[0].tolist())
if __name__ == '__main__':
app.run(debug = True, host = '0.0.0.0', port=8080)
requirements.txt
scikit-learn
flask
Dockerfile
FROM python:3.9
WORKDIR /app
ADD . /app
RUN pip install -r requirements.txt
CMD ["python", "main.py"]
EXPOSE 8080
step2. 創建Arifact Registry,將Dockerfile創建出來的鏡像打包上傳
$ docker build -t asia-east1-docker.pkg.dev/avian-casing-435202-m5/mark-iris-docker/mark-iris:1.0 .
$ docker push asia-east1-docker.pkg.dev/avian-casing-435202-m5/mark-iris-docker/mark-iris:1.0
step3. 點選完Deploy之後
step4. 撰寫clent.py
並執行
# -*- coding: utf-8 -*-
import requests
# Change the value of experience that you want to test
url = '[你的cloud run網址]/api'
feature = [[5.8, 4.0, 1.2, 0.2]]
labels ={
0: "setosa",
1: "versicolor",
2: "virginica"
}
r = requests.post(url,json={'feature': feature})
print(labels[r.json()])
執行client.py
結果
$ python client.py
setosa