在 Oracle Linux KVM 上创建多 VM LAMP 堆栈

简介

Oracle 虚拟化解决方案的核心是 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 故障转移提供自动高可用性、在无停机时间的主机之间实时迁移 VM、基于角色的访问控制和审计日志记录,以及简化备份和灾难恢复工作流。这些企业功能将 Oracle Linux KVM 从单个主机转换为真正的企业虚拟化平台。

在本教程中,我们将探讨支持 Oracle 虚拟化的核心虚拟机管理程序技术。基于内核的虚拟机 (KVM) 是一个开源 type-1(裸金属)虚拟机管理程序。此功能允许主机系统(例如 Oracle Linux)在受支持的硬件上运行时托管多个虚拟机 (VM) 或来宾。

本教程部署了 Oracle Linux KVM 以创建配置有 LAMP 堆栈应用程序的虚拟机,使您能够在多个 VM 中托管具有 Linux、Apache、MySQL 和 PHP 组件的完整 Web 开发环境。

重要提示:本练习中的两个应用程序代码仅用于教育目的。它们旨在帮助开发人员学习和实践 LAMP 堆栈中的应用开发技能。这些代码不适用于生产环境,不应在活动环境中按原样使用。

目标

Prerequisites

具有 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。此变量是必需的,因为环境安装了适用于 Python 的 Oracle Cloud Infrastructure SDK 的 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 packages → start libvirtd service → module appear in lsmod output。

步骤 3:安装和启动 KVM

  1. 检查正在运行的 Oracle Linux 版本。

    hostnamectl | grep 'Operating System'
    
  2. 安装用于 Oracle Linux 虚拟化的关联软件包。

    此命令安装虚拟化软件包,其中包括 libvirt 和 Oracle Linux 上的其他依赖项。libvirt 软件包提供了用于管理 KVM 虚拟机的软件库和 API,并包含后台运行的 libvirtd 守护进程,用于处理实际的 VM 管理。

    sudo dnf module install -y virt
    
  3. 安装 virt-install,这是一种使用 KVM(基于内核的虚拟机)虚拟机管理程序创建和配置虚拟机 (Virtual Machine,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
    

    Theutput 将该服务显示为已启用且正在运行。如果需要,输入字母“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. 生成 SSH 密钥对以安全连接到 VM。

    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 验证版本并获取有关虚拟机中 OS 的其他详细信息。

    创建 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 验证版本并获取有关虚拟机中 OS 的其他详细信息。

    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. 使用 Luna 或本地环境的浏览器通过 SSH 隧道访问 Web 服务器来测试 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
    

预期结果:

基本测试:绿色“Successfully Connected to 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 向导
    • 产品名称:ol-vcn-01
    • Create VCN Navigate:Networking → Virtual Cloud Networks → kvm-network → Security Lists 添加以下入站规则:
    • 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 帮助中心