在 Oracle Linux KVM 上建立多 VM LAMP 堆疊

簡介

Oracle Virtualization 解決方案的核心是 Oracle Linux KVM 主機。在此虛擬機器管理程式上,您可以執行許多虛擬機器,每個虛擬機器都會執行支援的作業系統之一,包括 Oracle Linux、RHEL、Windows、Ubuntu、Solaris 以及其他作業系統。此虛擬化解決方案透過 Oracle Linux Virtualization Manager 進行管理,該解決方案提供單一介面,讓事物保持井然有序。除了多主機 / 多 VM 管理之外,Oracle Linux Virtualization Manager 還支援 Oracle Virtualization 解決方案的主要功能。例如,Oracle Linux Virtualization Manager 提供 VM 容錯移轉的自動高可用性、零停機主機之間的即時移轉、以角色為基礎的存取控制與稽核記錄,以及簡化的備份與災害復原工作流程。這些企業功能可將 Oracle Linux KVM 從個別主機轉換為真正的企業虛擬化平台。

在本教學課程中,我們將探討 Oracle 虛擬化的核心虛擬機器管理程式技術。核心型虛擬機器 (KVM) 是開放原始碼的 type-1 (裸機) 虛擬機器管理程式。這項功能允許主機系統 (例如 Oracle Linux) 在支援的硬體上執行時代管多個虛擬機器 (VM) 或來賓。

本教學課程部署 Oracle Linux KVM 以建立設定 LAMP 堆疊應用程式的虛擬機器,讓您能夠跨多個 VM 代管包含 Linux、Apache、MySQL 和 PHP 元件的完整 Web 開發環境。

重要事項:本實驗環境中的兩個應用模組代碼僅供教育之用。專為協助開發人員使用 LAMP 堆疊學習和練習應用程式開發技能而設計。這些代碼不適用於生產環境,且不應用於即時設定。

目標

必備條件

具備 sudo 權限之非 root 使用者的任何 Oracle Linux 系統。

步驟 1:部署 Oracle Linux

注意:如果是在您自己的租用戶中執行,請先閱讀 linux-virt-labs GitHub 專案 README.md 並完成先決條件,再部署實驗環境環境。

  1. 在 Luna Desktop 上開啟終端機。

  2. 複製 linux-virt-labs GitHub 專案。

    git clone https://github.com/oracle-devrel/linux-virt-labs.git
    
  3. 變更至工作目錄。

    cd linux-virt-labs/ol
    
  4. 安裝必要的集合。

    ansible-galaxy collection install -r requirements.yml
    
  5. 部署實驗環境環境。

    ansible-playbook create_instance.yml -e localhost_python_interpreter="/usr/bin/python3.6" -e instance_ocpus="4" -e instance_memory="64"
    

    自由實驗環境環境需要額外的變數 local_python_interpreter,此變數會設定在 localhost 上執行的播放 ansible_python_interpreter。由於環境會安裝 Oracle Cloud Infrastructure SDK for Python 的 RPM 套件 (位於 python3.6 模組底下),因此需要此變數。

    預設部署資源配置使用 AMD CPU 和 Oracle Linux 8。若要使用 Intel CPU,請增加 -e instance_shape="VM.Standard3.Flex"

    重要事項: 請等待播放手冊順利執行,然後到達暫停工作。在手冊的這個階段,Oracle Linux 的安裝已完成,實例已就緒。記下先前的播放,此播放會列印其部署節點的公用和專用 IP 位址,以及執行實驗室時所需的任何其他部署資訊。

步驟 2:驗證環境支援虛擬化

  1. 開啟終端機,並使用 SSH 連線至 ol-node-01 執行處理。

    ssh opc@<ip_address_of_instance>
    
  2. 執行下列命令以判斷您的 CPU 類型。

    grep -e 'vendor_id' /proc/cpuinfo | uniq
    

    vendor_id 會報告 AMD CPU 的 AuthenticAMD 或 Intel CPU 的 GenuinIntel

  3. 檢查硬體是否支援虛擬化。

    執行符合您 CPU 類型的命令。

    1. 檢查 AMD V CPU 擴充是否存在。
    grep -w -o 'svm' /proc/cpuinfo | uniq
    
    1. 確認 Intel VT CPU 延伸存在。
    grep -w -o 'vmx' /proc/cpuinfo | uniq
    

    指令輸出中有其中一個旗標表示此系統支援虛擬化。您也可以使用 lscpu 指令,在輸出中尋找 Virtualization 項目。

  4. 檢查載入的 KVM 模組。

    lsmod | grep kvm
    

    輸出會在安裝虛擬化套裝軟體並啟動 libvirtd 服務之後顯示 KVM 核心模組。在 OCI 等雲端系統上,這些模組會在 libvirtd 啟動時自動載入,而不是在套裝軟體安裝期間自動載入。載入順序是:install package → start libvirtd service → 模組會顯示在 lsmod 輸出中。

步驟 3:安裝並啟動 KVM

  1. 檢查 Oracle Linux 的執行中版本。

    hostnamectl | grep 'Operating System'
    
  2. 安裝 Oracle Linux 虛擬化的相關軟體套裝程式。

    此命令會安裝虛擬化套裝程式,其中包括 libvirt 與 Oracle Linux 的其他相依性。libvirt 套裝軟體提供軟體程式庫與 API 以管理 KVM 虛擬機器,並包含可在背景中執行的 libvirtd 常駐程式,以處理實際的 VM 管理。

    sudo dnf module install -y virt
    
  3. 安裝 virt-install,這是使用 KVM (核心型虛擬機器) 虛擬機器管理程式建立及設定虛擬機器 (VM) 的工具。

    sudo dnf install -y virt-install
    
  4. 驗證主機機器已就緒,並設定為執行 libvirt VM。

    virt-host-validate
    

    如果所有檢查都通過,系統會準備用於建立 VM。如果有任何檢查失敗,請遵循指示來更正問題。如果有任何檢查傳回 WARN 值,請考慮遵循指示來改善虛擬化功能。

  5. 啟動 Systemd 服務,使它們能夠在每次啟動時自動啟動。

    sudo systemctl enable --now libvirtd.service
    
  6. 請查看服務狀態以確認服務已啟動並在執行中。

    sudo systemctl status libvirtd.service
    

    此輸出會將服務顯示為已啟用且在執行中。如有需要,請輸入字母 'q' 以結束輸出模式。

步驟 4:使用 Oracle Cloud 映像檔建立兩個虛擬機器

  1. 變更為 KVM 影像儲存位置。

    cd /var/lib/libvirt/images
    
  2. 下載 Oracle Linux VM 樣板。

    sudo curl -O https://yum.oracle.com/templates/OracleLinux/OL8/u10/x86_64/OL8U10_x86_64-kvm-b237.qcow2
    

    建立 VM-01 (資料庫)

  3. 建立中繼資料檔案。

    cat << 'EOF' | sudo tee ~/meta-data > /dev/null
    instance-id: iid-local01
    local-hostname: vm-01
    EOF
    
  4. 建立使用者資料檔案。

    cat << 'EOF' | sudo tee ~/user-data > /dev/null
    #cloud-config
    
    system_info:
      default_user:
        name: opc
    
    ssh_authorized_keys:
      - <paste_public_key_here>
    EOF
    
  5. 產生用於安全連線至 VM 的 SSH 金鑰組。

    ssh-keygen -t rsa -b 4096
    

    Enter 接受每個預設值。此命令會將金鑰組寫入使用者本位目錄中的 .ssh 目錄。

  6. 擷取產生的公用 SSH 金鑰。
    SSHKEY=$(cat ~/.ssh/id_rsa.pub)
    
  7. 使用產生的公用 SSH 金鑰更新使用者資料檔案。
    sed -i "s|<paste_public_key_here>|${SSHKEY}|g" ~/user-data
    
  8. 產生包含使用者資料與中繼資料檔案的 ISO 影像。
    sudo genisoimage -output /var/lib/libvirt/images/vm-01.iso -volid cidata -joliet -rock ~/user-data ~/meta-data
    
  9. 尋找與下載影像相符的 OS 變體。
    osinfo-query os | grep ol8
    
  10. 將 Oracle Linux 映像檔複製到 vm-01 的新磁碟映像檔。
    sudo cp /var/lib/libvirt/images/OL8U10_x86_64-kvm-b237.qcow2 /var/lib/libvirt/images/vm-01.qcow
    
  11. 使用指定的資源和組態,建立名為 vm-01 的新虛擬機器。
    sudo virt-install --name vm-01 \
    --memory 2048 \
    --vcpus 2 \
    --disk /var/lib/libvirt/images/vm-01.qcow,device=disk,bus=virtio \
    --disk /var/lib/libvirt/images/vm-01.iso,device=cdrom \
    --os-type linux --os-variant ol8.10 \
    --virt-type kvm --graphics none \
    --network network=default,model=virtio \
    --noautoconsole \
    --import
    
  12. 列出所有執行中的虛擬機器。
    sudo virsh list
    
  13. 擷取 vm-01 虛擬機器的 IP 位址。

    sudo virsh net-dhcp-leases --network default
    
  14. 連線 ssh 以驗證虛擬機器是否運作。

    ssh opc@<ip_address_of_vm-01>
    
  15. 結束 vm-01 伺服器以繼續下一個步驟。

    exit
    

    您可以執行 hostnamectl,驗證版本並取得虛擬機器內作業系統的其他詳細資訊。

    建立 VM-02 (Web 伺服器)

  16. 建立 vm-02 的中繼資料檔案。

    cat << 'EOF' | sudo tee ~/meta-data > /dev/null
    instance-id: iid-local02
    local-hostname: vm-02
    EOF
    
  17. 產生 vm-02 的 ISO 影像。
    sudo genisoimage -output /var/lib/libvirt/images/vm-02.iso -volid cidata -joliet -rock ~/user-data ~/meta-data
    
  18. 將 Oracle Linux 映像檔複製到 vm-02 的新磁碟映像檔。
    sudo cp /var/lib/libvirt/images/OL8U10_x86_64-kvm-b237.qcow2 /var/lib/libvirt/images/vm-02.qcow
    
  19. 使用指定的資源和組態,建立名為 vm-02 的新虛擬機器。
    sudo virt-install --name vm-02 \
    --memory 2048 \
    --vcpus 2 \
    --disk /var/lib/libvirt/images/vm-02.qcow,device=disk,bus=virtio \
    --disk /var/lib/libvirt/images/vm-02.iso,device=cdrom \
    --os-type linux --os-variant ol8.10 \
    --virt-type kvm --graphics none \
    --network network=default,model=virtio \
    --noautoconsole \
    --import
    
  20. 列出所有執行中的虛擬機器。
    sudo virsh list
    
  21. 擷取 vm-02 虛擬機器的 IP 位址。

    sudo virsh net-dhcp-leases --network default
    
  22. 連線 ssh 以驗證虛擬機器是否運作。

    ssh opc@<ip_address_of_vm-02>
    
  23. 結束 vm-01 伺服器以繼續下一個步驟。

    exit
    
  24. 您可以執行 hostnamectl,驗證版本並取得虛擬機器內作業系統的其他詳細資訊。

    hostnamectl
    

    輸出範例:

    [oracle@ol-node01 images]$ ssh opc@192.168.122.46
    The authenticity of host '[host]' can't be established.
    ECDSA key fingerprint is [fingerprint].
    Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
    Warning: Permanently added '[IP]' (ECDSA) to the list of known hosts.
    
    [opc@vm-01 ~]$ hostnamectl
       Static hostname: vm-01
             Icon name: computer-vm
               Chassis: vm
            Machine ID: [MachineID]
               Boot ID: [BootID]
        Virtualization: kvm
      Operating System: Oracle Linux Server 8.10
           CPE OS Name: cpe:/o:oracle:linux:8:10:server
                Kernel: Linux 5.15.0-206.153.7.1.el8uek.x86_64
          Architecture: x86-64
    
  25. 擷取 vm-01 的 IP 位址。
     VM01_IP=$(sudo virsh net-dhcp-leases --network default | grep vm-01 | tail -1 | awk '{print $5}' | cut -d'/' -f1)
    
  26. 擷取 vm-02 的 IP 位址。
     VM02_IP=$(sudo virsh net-dhcp-leases --network default | grep vm-02 | tail -1 | awk '{print $5}' | cut -d'/' -f1)
    
  27. 儲存 VM 的 IP 位址以供日後使用:
     echo "VM-01 (Web): $VM01_IP"
    
     echo "VM-02 (Web): $VM02_IP"
    
  28. 測試 VM 的 SSH 命令。
     ssh -o ConnectTimeout=10 opc@$VM01_IP "echo 'VM-01 OK'"
    
     ssh -o ConnectTimeout=10 opc@$VM02_IP "echo 'VM-02 OK'"
    

步驟 5:在 VM-01 上設定 MySQL

安裝 MySQL

  1. 從 ol-node-01 執行處理 SSH 建立與 VM-01 的 SSH 連線。
     ssh opc@$VM01_IP
    
  2. 下載 MySQL 儲存區域組態。
     sudo yum -y install https://dev.mysql.com/get/mysql84-community-release-el8-1.noarch.rpm
    
  3. 停用預設的 MySQL 模組以避免衝突。
     sudo yum -y module disable mysql
    
  4. 安裝 MySQL 伺服器與用戶端。
     sudo yum install -y mysql mysql-server
    
  5. 啟動 MySQL 服務。
     sudo systemctl start mysqld
    
  6. 啟用 MySQL 服務以在啟動時啟動。
     sudo systemctl enable mysqld
    
  7. 允許透過防火牆傳入的 MySQL 流量。
     sudo firewall-cmd --permanent --add-service=mysql
    
  8. 重新載入防火牆組態以套用變更。
     sudo firewall-cmd --reload
    

    設定 MySQL

  9. 從 MySQL 日誌擷取暫時 root 密碼。
     TEMP_PASS=$(sudo grep 'temporary password' /var/log/mysqld.log | awk '{print $NF}')
    
  10. 使用臨時 root 密碼登入 MySQL。
     mysql -uroot -p$TEMP_PASS --connect-expired-password
    
  11. 將 root 密碼變更為安全的值。
     ALTER USER 'root'@'localhost' IDENTIFIED BY '[password]';
    
  12. 使用安全的密碼建立 'admin' 使用者。
     CREATE USER 'admin'@'%' IDENTIFIED BY '[password]';
    
  13. 將所有權限授予 'admin' 使用者。
     GRANT ALL PRIVILEGES ON *.* TO 'admin'@'%' WITH GRANT OPTION;
    
  14. 使用安全密碼建立 'empuser' 使用者。
     CREATE USER 'empuser'@'%' IDENTIFIED BY '[password]';
    
  15. 將所有權限授予 'empuser'。
     GRANT ALL PRIVILEGES ON *.* TO 'empuser'@'%' WITH GRANT OPTION;
    
  16. 重新載入權限表格以套用變更。
     FLUSH PRIVILEGES;
    
  17. 結束 MySQL shell。
     \q
    
  18. VM-01 結束 SSH 階段作業。
     exit
    

步驟 6:在 VM-02 上設定 Apache/PHP

  1. 從 ol-node-01 執行處理 SSH 建立與 VM-02 的 SSH 連線。
     ssh opc@$VM02_IP
    
  2. 安裝 Apache HTTP 伺服器。
     sudo yum install -y httpd
    
  3. 安裝 PHP 8. 2 及其相依性 。
     sudo dnf install -y @php:8.2
    
  4. 安裝 PHP MySQL 和 JSON 延伸功能。
     sudo yum install -y php-mysqlnd php-json
    
  5. 啟用並啟動 Apache HTTP 伺服器。
     sudo systemctl enable --now httpd
    
  6. 允許連接埠 80 的內送 HTTP 流量。
     sudo firewall-cmd --permanent --add-port=80/tcp
    
  7. 重新載入防火牆組態以套用變更。
     sudo firewall-cmd --reload
    
  8. 允許 Apache 連線網路資源。
     sudo setsebool -P httpd_can_network_connect 1
    
  9. VM-02 結束 SSH 階段作業。
     exit
    

步驟 7:測試 Apache

  1. 顯示 VM-02 YOUR_VM_02_PUBLIC_IP 的公用 IP 位址:
     echo "VM-02 (Web): $VM02_IP"
    
  2. 開啟新的終端機 Luna 或企業內部部署環境,並建立 SSH 通道,以從本機機器存取 VM-02 Web 伺服器。

    … 務必先取代 ** ** 和 ** **

     ssh -L 8081:<YOUR_VM_02_PUBLIC_IP>:80 opc@<YOUR_OCI_PUBLIC_IP>
    
  3. 透過 SSH 通道存取 Web 伺服器,使用 Luna 或內部部署環境的瀏覽器測試 Apache。
     http://localhost:8081
    

    重要事項: 讓 SSH 通道和瀏覽器保持開啟,供日後使用

步驟 8:建立測試應用程式


  1. 返回您的 opc@ol-node-01 ssh 執行處理。

  2. 從 DHCP 租賃擷取 VM-01 的 IP 位址。
     VM01_IP=$(sudo virsh net-dhcp-leases --network default | grep vm-01 | tail -1 | awk '{print $5}' | cut -d'/' -f1)
    
  3. 從 DHCP 租賃擷取 VM-02 的 IP 位址。
     VM02_IP=$(sudo virsh net-dhcp-leases --network default | grep vm-02 | tail -1 | awk '{print $5}' | cut -d'/' -f1)
    
  4. 從 ol-node-01 執行處理 SSH 建立與 VM-02 的 SSH 連線。
     ssh opc@$VM02_IP
    
  5. 建立 PHP 資訊頁面以顯示 PHP 組態。
     sudo tee /var/www/html/info.php > /dev/null << 'EOF'
     <?php phpinfo(); ?>
     EOF
    
  6. 建立資料庫連線測試應用程式。

     sudo tee /var/www/html/dbtest.php > /dev/null << 'EOF'
     <?php
     echo "<h1>Multi-VM LAMP Stack Test</h1>";
    
     // Database connection details
     define('DB_SERVER', '$VM01_IP');
     define('DB_USERNAME', 'admin');
     define('DB_PASSWORD', '[password]');
     define('DB_NAME', 'mysql');
    
     echo "<p>Testing connection to MySQL at: " . DB_SERVER . "</p>";
    
     // Test network connectivity
     $fp = @fsockopen(DB_SERVER, 3306, $errno, $errstr, 5);
     if (!$fp) {
         echo "<p style='color: red;'>ERROR: Cannot reach MySQL server</p>";
         echo "<p>Error: $errstr ($errno)</p>";
     } else {
         echo "<p style='color: green;'>✓ Network connection successful</p>";
         fclose($fp);
            
         // Test MySQL connection
         $link = mysqli_connect(DB_SERVER, DB_USERNAME, DB_PASSWORD, DB_NAME);
         if($link === false){
             echo "<p style='color: red;'>ERROR: Could not connect to MySQL</p>";
             echo "<p>Error: " . mysqli_connect_error() . "</p>";
         } else {
             echo "<p style='color: green;'>✓ Successfully Connected to MySQL!</p>";
             echo "<p>MySQL Version: " . mysqli_get_server_info($link) . "</p>";
             echo "<p>Host Info: " . mysqli_get_host_info($link) . "</p>";
             mysqli_close($link);
         }
     }
     ?>
     EOF
    
  7. 設定應用程式檔案權限。
     sudo chown apache:apache /var/www/html/*.php
    
  8. 以儲存的 IP 位址值變更 $VM01_IP 值,以更新行 define ('DB_SERVER','$VM01_IP');
     sudo vi /var/www/html/dbtest.php
    

    輸出範例:

    ``` 文字 … 程式碼再定義 ('DB_SERVER','192.168.122.??');… 程式碼之後

  9. 結束 VM-02

     exit
    

步驟 9:存取您的 Web 伺服器和資料庫測試應用程式


  1. 如果關閉 SSH 通道,請建立以進行基本測試。
     ssh -L 8081:$VM02_IP:80 opc@<YOUR_OCI_PUBLIC_IP>
    
  2. 基本 LAMP 測試 瀏覽:
     http://localhost:8081/info.php
    
  3. 基本資料庫測試示範 瀏覽至:
    http://localhost:8081/dbtest.php
    

預期的結果:

基本測試:綠色「成功連線至 MySQL!」訊息


步驟 10:建立及載入員工資料庫

  1. 您應該在 opc@ol-node-01 ssh 執行處理中。

  2. 從 DHCP 租賃擷取 VM-01 的 IP 位址。
     VM01_IP=$(sudo virsh net-dhcp-leases --network default | grep vm-01 | tail -1 | awk '{print $5}' | cut -d'/' -f1)
    
  3. 從 DHCP 租賃擷取 VM-02 的 IP 位址。
     VM02_IP=$(sudo virsh net-dhcp-leases --network default | grep vm-02 | tail -1 | awk '{print $5}' | cut -d'/' -f1)
    
  4. opc@ol-node-01 SSH 執行處理中,建立 VM-01 的 SSH 連線。
     ssh opc@$VM01_IP
    
  5. 變更為 /tmp 資料夾。
     cd /tmp
    
  6. 下載 MySQL 員工範例資料庫。
     curl -L -o master.zip https://github.com/datacharmer/test_db/zipball/master/
    
  7. 安裝壓縮工具。
     sudo dnf install -y unzip
    
  8. 擷取資料庫。
     sudo unzip master.zip
    
     sudo mv datacharmer-test_db-* employees_db
    
     cd employees_db
    
  9. 載入資料庫。
     mysql -u admin -p[password] < employees.sql
    
  10. 確認資料庫已載入 。
     mysql -u admin -p[password] -e "USE employees; SHOW TABLES; SELECT COUNT(*) FROM employees;"
    
  11. 結束資料庫 VM。
     exit
    

步驟 11:建立員工資料庫 Web 應用程式

  1. ol-node-01 SSH 執行處理,建立 VM-02 的 SSH 連線。
     ssh opc@$VM02_IP
    
  2. 建立專業員工資料庫應用程式。
     sudo tee /var/www/html/employees.php > /dev/null << 'EOF'
     <!DOCTYPE html>
     <html lang="en">
     <head>
         <meta charset="UTF-8">
         <meta name="viewport" content="width=device-width, initial-scale=1.0">
         <title>Employee Database - Multi-VM LAMP Demo</title>
         <style>
             body { 
                 font-family: Arial, sans-serif; 
                 max-width: 1200px; 
                 margin: 0 auto; 
                 padding: 20px;
                 background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
             }
             .header { 
                 background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                 color: white; 
                 text-align: center; 
                 padding: 30px;
                 border-radius: 15px;
                 margin-bottom: 20px;
                 box-shadow: 0 8px 16px rgba(0,0,0,0.1);
             }
             .info-box { 
                 background: rgba(255,255,255,0.9);
                 padding: 25px; 
                 border-radius: 12px;
                 box-shadow: 0 4px 8px rgba(0,0,0,0.1);
                 margin-bottom: 20px;
                 backdrop-filter: blur(10px);
             }
             .success { color: #28a745; font-weight: bold; }
             .error { color: #dc3545; font-weight: bold; }
             table { 
                 width: 100%; 
                 border-collapse: collapse; 
                 margin: 20px 0;
                 background: rgba(255,255,255,0.9);
                 border-radius: 12px;
                 overflow: hidden;
                 box-shadow: 0 4px 8px rgba(0,0,0,0.1);
             }
             th, td { 
                 padding: 15px; 
                 text-align: left; 
                 border-bottom: 1px solid #ddd;
             }
             th { 
                 background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                 color: white;
                 font-weight: bold;
             }
             tr:hover { background-color: rgba(102, 126, 234, 0.1); }
             .stats { 
                 display: grid; 
                 grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); 
                 gap: 20px; 
                 margin: 20px 0; 
             }
             .stat-card { 
                 background: white; 
                 padding: 20px; 
                 border-radius: 10px; 
                 text-align: center; 
                 box-shadow: 0 4px 8px rgba(0,0,0,0.1);
             }
             .stat-number { font-size: 2em; font-weight: bold; color: #667eea; }
         </style>
     </head>
     <body>
         <div class="header">
             <h1>🏢 Employee Database Demo</h1>
             <p>MySQL Employee Sample Database on Multi-VM Architecture</p>
         </div>
    
         <?php
         // Database connection details
         define('DB_SERVER', '$VM01_IP');
         define('DB_USERNAME', 'empuser');
         define('DB_PASSWORD', '[password]');
         define('DB_NAME', 'employees');
    
         try {
             // Connect to MySQL database on separate VM
             $pdo = new PDO("mysql:host=" . DB_SERVER . ";dbname=" . DB_NAME, DB_USERNAME, DB_PASSWORD);
             $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
                
             echo '<div class="info-box success">';
             echo '<h2>✅ Connected to Employee Database</h2>';
             echo '<p><strong>Database Server:</strong> ' . DB_SERVER . ' (vm-01)</p>';
             echo '<p><strong>Web Server:</strong> ' . gethostname() . ' (vm-02)</p>';
             echo '</div>';
                
             // Get database statistics
             $stats = [];
                
             $stmt = $pdo->query("SELECT COUNT(*) as count FROM employees");
             $stats['employees'] = $stmt->fetch()['count'];
                
             $stmt = $pdo->query("SELECT COUNT(*) as count FROM departments");
             $stats['departments'] = $stmt->fetch()['count'];
                
             $stmt = $pdo->query("SELECT COUNT(*) as count FROM salaries");
             $stats['salaries'] = $stmt->fetch()['count'];
                
             $stmt = $pdo->query("SELECT COUNT(*) as count FROM titles");
             $stats['titles'] = $stmt->fetch()['count'];
                
             echo '<div class="info-box">';
             echo '<h2>📊 Database Statistics</h2>';
             echo '<div class="stats">';
             echo '<div class="stat-card"><div class="stat-number">' . number_format($stats['employees']) . '</div><div>Employees</div></div>';
             echo '<div class="stat-card"><div class="stat-number">' . number_format($stats['departments']) . '</div><div>Departments</div></div>';
             echo '<div class="stat-card"><div class="stat-number">' . number_format($stats['salaries']) . '</div><div>Salary Records</div></div>';
             echo '<div class="stat-card"><div class="stat-number">' . number_format($stats['titles']) . '</div><div>Job Titles</div></div>';
             echo '</div>';
             echo '</div>';
                
             // Show recent employees
             echo '<div class="info-box">';
             echo '<h2>👥 Sample Employee Data</h2>';
             $stmt = $pdo->query("SELECT emp_no, first_name, last_name, gender, hire_date FROM employees ORDER BY hire_date DESC LIMIT 20");
             $employees = $stmt->fetchAll();
                
             echo '<table>';
             echo '<thead><tr><th>Employee #</th><th>First Name</th><th>Last Name</th><th>Gender</th><th>Hire Date</th></tr></thead>';
             echo '<tbody>';
                
             foreach ($employees as $emp) {
                 echo '<tr>';
                 echo '<td>' . htmlspecialchars($emp['emp_no']) . '</td>';
                 echo '<td>' . htmlspecialchars($emp['first_name']) . '</td>';
                 echo '<td>' . htmlspecialchars($emp['last_name']) . '</td>';
                 echo '<td>' . htmlspecialchars($emp['gender']) . '</td>';
                 echo '<td>' . htmlspecialchars($emp['hire_date']) . '</td>';
                 echo '</tr>';
             }
             echo '</tbody></table>';
             echo '</div>';
                
             // Show departments
             echo '<div class="info-box">';
             echo '<h2>🏬 Departments</h2>';
             $stmt = $pdo->query("SELECT dept_no, dept_name FROM departments ORDER BY dept_name");
             $departments = $stmt->fetchAll();
                
             echo '<table>';
             echo '<thead><tr><th>Department Code</th><th>Department Name</th></tr></thead>';
             echo '<tbody>';
                
             foreach ($departments as $dept) {
                 echo '<tr>';
                 echo '<td>' . htmlspecialchars($dept['dept_no']) . '</td>';
                 echo '<td>' . htmlspecialchars($dept['dept_name']) . '</td>';
                 echo '</tr>';
             }
             echo '</tbody></table>';
             echo '</div>';
                
         } catch (PDOException $e) {
             echo '<div class="info-box error">';
             echo '<h2>❌ Database Connection Error</h2>';
             echo '<p>Error: ' . htmlspecialchars($e->getMessage()) . '</p>';
             echo '</div>';
         }
         ?>
    
         <div class="info-box">
             <h2>🏗️ Multi-VM Architecture</h2>
             <p><strong>Database VM (vm-01):</strong> MySQL Server with Employee Database</p>
             <p><strong>Web VM (vm-02):</strong> Apache + PHP Web Application</p>
             <p><strong>Data Source:</strong> MySQL Sample Employee Database</p>
             <p><strong>Records:</strong> 300,000+ employees, 400,000+ salary records</p>
         </div>
     </body>
     </html>
     EOF
    
  3. 設定適當的權限。
     sudo chown apache:apache /var/www/html/employees.php
    
  4. 以儲存的 IP 位址值變更 $VM01_IP 值,以更新行 define ('DB_SERVER','$VM01_IP');
     sudo vi /var/www/html/employees.php
    

    輸出範例:

    ``` 文字 … 程式碼再定義 ('DB_SERVER','192.168.122.??');… 程式碼之後

  5. 結束 Web 伺服器 VM。
     exit
    

步驟 12:存取員工應徵

  1. 如果關閉 SSH 通道,請建立以進行基本測試。
     ssh -L 8081:$VM02_IP:80 opc@<YOUR_OCI_PUBLIC_IP>
    
  2. 員工資料庫示範瀏覽至:
     http://localhost:8081/employees.php
    

預期的結果:


可用的應用程式:

🔧 基本 LAMP 測試 (http://localhost:8081/dbtest.php)

🏢 員工資料庫示範 (http://localhost:8081/employees.php)


基本管理命令

VM 管理

  1. 列出執行中的 VM 及其狀態。
     sudo virsh list
    
  2. 啟動 VM-01
     sudo virsh start vm-01
    
  3. 關閉 VM-01
     sudo virsh shutdown vm-01
    
  4. 在預設網路上顯示 VM 的 DHCP 租賃。
     sudo virsh net-dhcp-leases --network default
    

設定在 Oracle Cloud Infrastructure 上執行此實驗室

  1. 虛擬雲端網路設定: `` 瀏覽:網路 → 虛擬雲端網路 → 啟動 VCN 精靈
    • 名稱:olt-vcn-01
    • 建立 VCN 瀏覽:網路 → 虛擬雲端網路 → kvm-network → 安全清單 新增這些輸入規則:
    • SSH:來源 0.0.0.0/0、TCP 連接埠 22
    • HTTP:來源 0.0.0.0/0,TCP 連接埠 80 ```
  2. 運算執行處理設定:
         Navigation: Hamburger Menu → Compute → Instances → Create Instance
    
         Configuration:
         - Name: ol-node-01
         - Image: Oracle Linux 8 (Latest)
         - Shape: VM.Standard.E4.Flex (4 OCPUs, 16GB RAM)
         - Boot Volume: 100 GB
         - VCN: ol-vcn-01 
         - Subnet: Public subnet ol-vcn-01
         - Assign Public IP: Yes
         - Add SSH Key: Upload your public key
    
  3. 使用 SSH 測試運算公用 IP。
     ssh opc@<ol-vcn-01_PUBLIC_IP>
    
  4. 繼續步驟 2:驗證環境支援虛擬化。

接下來的步驟

瞭解如何使用 Oracle Linux Virtual Manager (OLVM) 管理主機和 vms

確認

其他學習資源

docs.oracle.com/learn 上探索其他實驗室,或在 Oracle Learning YouTube 頻道上存取更多免費學習內容。此外,請造訪 education.oracle.com/learning-explorer 以成為 Oracle Learning Explorer。

如需產品文件,請造訪 Oracle Help Center