跳转到内容
搜索 RunEntLinux 文档

仅搜索 RunEntLinux 通用文档,各发行版文档使用各自的搜索入口。

    浏览当前文档目录

    Cloud-Init 配置

    Cloud-Init 是云实例首次启动时自动执行初始化配置的行业标准工具。几乎所有主流云平台(AWS、阿里云、腾讯云、Azure、GCP)以及本地虚拟化环境都依赖 Cloud-Init 来完成实例的网络配置、用户创建、软件安装等工作。

    Cloud-Init 是一个运行在云实例内部的服务,它在系统首次启动时执行以下操作:

    • 从云平台的元数据服务(Metadata Service)获取实例信息
    • 读取用户提供的 user-data 配置
    • 按照配置完成系统初始化(创建用户、安装软件、写入文件等)

    在 Enterprise Linux(CentOS/AlmaLinux/Rocky Linux)官方云镜像中,Cloud-Init 已经预装。

    Cloud-Init 的执行分为多个阶段:

    阶段说明
    cloud-init-local最早执行,应用本地数据源配置
    cloud-init获取元数据和用户数据,配置网络
    cloud-config执行用户数据中的配置模块
    cloud-final最后阶段,运行用户自定义脚本和命令
    Terminal window
    # 查看 cloud-init 版本
    cloud-init --version
    # 查看 cloud-init 运行状态
    cloud-init status
    # 查看详细状态(包括错误信息)
    cloud-init status --long
    # 查看 cloud-init 已识别的数据源
    cloud-id

    User-Data 是传递给 Cloud-Init 的配置文件,使用 YAML 格式编写,文件必须以 #cloud-config 开头。

    #cloud-config
    # 设置默认用户密码(仅用于测试,生产环境请使用 SSH 密钥)
    chpasswd:
    list: |
    root:ChangeMe123!
    expire: false
    # 创建用户
    users:
    - default
    - name: deploy
    groups: wheel
    sudo: ALL=(ALL) NOPASSWD:ALL
    shell: /bin/bash
    ssh_authorized_keys:
    - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... deploy@workstation
    - name: developer
    groups: wheel
    lock_passwd: false
    passwd: $6$rounds=4096$salt$hashedpassword...
    # 允许 SSH 密码登录(默认通常禁用)
    ssh_pwauth: true
    #cloud-config
    # 更新已有软件包
    package_update: true
    # 升级所有软件包
    package_upgrade: true
    # 安装指定软件包
    packages:
    - vim-enhanced
    - git
    - htop
    - tmux
    - nginx
    - python3
    - epel-release
    - firewalld
    # 安装完成后重启(如果需要)
    package_reboot_if_required: true
    #cloud-config
    yum_repos:
    epel:
    name: Extra Packages for Enterprise Linux
    baseurl: https://dl.fedoraproject.org/pub/epel/$releasever/Everything/$basearch/
    enabled: true
    gpgcheck: true
    gpgkey: https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-$releasever
    docker-ce:
    name: Docker CE Stable
    baseurl: https://download.docker.com/linux/centos/$releasever/$basearch/stable
    enabled: true
    gpgcheck: true
    gpgkey: https://download.docker.com/linux/centos/gpg
    #cloud-config
    write_files:
    # 写入 Nginx 配置
    - path: /etc/nginx/conf.d/myapp.conf
    owner: root:root
    permissions: '0644'
    content: |
    server {
    listen 80;
    server_name example.com;
    root /var/www/myapp;
    index index.html;
    }
    # 写入系统优化参数
    - path: /etc/sysctl.d/99-custom.conf
    permissions: '0644'
    content: |
    net.core.somaxconn = 65535
    net.ipv4.tcp_max_syn_backlog = 65535
    vm.swappiness = 10
    # Base64 编码内容
    - path: /etc/ssl/certs/myapp.crt
    encoding: b64
    permissions: '0644'
    content: LS0tLS1CRUdJTi...
    #cloud-config
    # 在配置阶段运行的命令(早期执行)
    bootcmd:
    - echo "Boot command running" > /tmp/bootcmd.log
    - [ cloud-init-per, once, mymkfs, mkfs, -t, ext4, /dev/vdb ]
    # 在 cloud-final 阶段执行的命令
    runcmd:
    # 启用并启动服务
    - systemctl enable --now nginx
    - systemctl enable --now firewalld
    # 配置防火墙
    - firewall-cmd --permanent --add-service=http
    - firewall-cmd --permanent --add-service=https
    - firewall-cmd --reload
    # 应用 sysctl 参数
    - sysctl --system
    # 部署应用
    - mkdir -p /var/www/myapp
    - echo "<h1>Hello from Cloud-Init</h1>" > /var/www/myapp/index.html
    # 自定义脚本
    - |
    #!/bin/bash
    echo "Instance initialized at $(date)" >> /var/log/cloud-init-custom.log
    hostnamectl set-hostname myserver.example.com

    以下是一个生产可用的完整 user-data 示例:

    #cloud-config
    hostname: web-server-01
    fqdn: web-server-01.example.com
    manage_etc_hosts: true
    users:
    - default
    - name: ops
    groups: wheel
    sudo: ALL=(ALL) NOPASSWD:ALL
    shell: /bin/bash
    ssh_authorized_keys:
    - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... ops@bastion
    package_update: true
    packages:
    - epel-release
    - vim-enhanced
    - git
    - htop
    - nginx
    - firewalld
    - fail2ban
    write_files:
    - path: /etc/fail2ban/jail.local
    permissions: '0644'
    content: |
    [DEFAULT]
    bantime = 3600
    findtime = 600
    maxretry = 5
    [sshd]
    enabled = true
    runcmd:
    - systemctl enable --now nginx
    - systemctl enable --now firewalld
    - systemctl enable --now fail2ban
    - firewall-cmd --permanent --add-service=http
    - firewall-cmd --permanent --add-service=https
    - firewall-cmd --reload
    - echo "Init complete: $(date)" >> /var/log/cloud-init-custom.log
    final_message: "Cloud-Init 配置完成,耗时 $UPTIME 秒"

    在没有云平台的本地环境中,可以使用 NoCloud 数据源来测试 Cloud-Init 配置。

    Terminal window
    # 创建工作目录
    mkdir -p /tmp/cloud-init-test
    # 创建 meta-data 文件
    cat > /tmp/cloud-init-test/meta-data << 'EOF'
    instance-id: test-001
    local-hostname: test-vm
    EOF
    # 创建 user-data 文件
    cat > /tmp/cloud-init-test/user-data << 'EOF'
    #cloud-config
    users:
    - default
    - name: testuser
    groups: wheel
    sudo: ALL=(ALL) NOPASSWD:ALL
    shell: /bin/bash
    packages:
    - vim-enhanced
    - htop
    runcmd:
    - echo "NoCloud test successful" > /tmp/cloud-init-test-result.txt
    EOF
    Terminal window
    # 安装 genisoimage 工具
    sudo dnf install -y genisoimage
    # 生成 cloud-init seed ISO
    genisoimage -output /tmp/seed.iso \
    -volid cidata \
    -joliet -rock \
    /tmp/cloud-init-test/user-data \
    /tmp/cloud-init-test/meta-data
    Terminal window
    # 下载云镜像(以 AlmaLinux 9 为例)
    wget https://repo.almalinux.org/almalinux/9/cloud/x86_64/images/AlmaLinux-9-GenericCloud-latest.x86_64.qcow2
    # 复制一份用于测试
    cp AlmaLinux-9-GenericCloud-latest.x86_64.qcow2 /tmp/test-vm.qcow2
    # 扩展磁盘
    qemu-img resize /tmp/test-vm.qcow2 20G
    # 使用 virt-install 创建虚拟机并挂载 seed ISO
    sudo virt-install \
    --name cloud-init-test \
    --memory 2048 \
    --vcpus 2 \
    --disk /tmp/test-vm.qcow2,format=qcow2 \
    --disk /tmp/seed.iso,device=cdrom \
    --os-variant almalinux9 \
    --network bridge=virbr0 \
    --graphics none \
    --console pty,target_type=serial \
    --import \
    --noautoconsole

    除了 ISO 方式,也可以通过本地目录传递:

    Terminal window
    # 将配置放在指定目录
    sudo mkdir -p /var/lib/cloud/seed/nocloud
    sudo cp /tmp/cloud-init-test/meta-data /var/lib/cloud/seed/nocloud/
    sudo cp /tmp/cloud-init-test/user-data /var/lib/cloud/seed/nocloud/

    在应用之前,建议先验证 user-data 配置的语法正确性:

    Terminal window
    # 安装 cloud-init(如果尚未安装)
    sudo dnf install -y cloud-init
    # 验证 user-data 配置语法
    cloud-init schema --config-file /tmp/cloud-init-test/user-data
    # 查看 cloud-init 实际使用的合并配置
    sudo cloud-init query --all

    在调试过程中,可能需要重新运行 Cloud-Init:

    Terminal window
    # 清除 cloud-init 状态(让它认为是首次启动)
    sudo cloud-init clean
    # 清除状态并在下次启动时重新运行
    sudo cloud-init clean --reboot
    # 仅清除日志
    sudo cloud-init clean --logs
    Terminal window
    # 主日志文件(最常用)
    sudo cat /var/log/cloud-init.log
    # 输出日志(显示 runcmd 等的标准输出)
    sudo cat /var/log/cloud-init-output.log
    # 查看特定阶段的日志
    sudo journalctl -u cloud-init-local
    sudo journalctl -u cloud-init
    sudo journalctl -u cloud-config
    sudo journalctl -u cloud-final
    # 查看实时日志
    sudo tail -f /var/log/cloud-init.log

    user-data 未执行

    Terminal window
    # 确认 cloud-init 是否成功获取到 user-data
    sudo cloud-init query userdata
    # 检查数据源是否正确识别
    cat /run/cloud-init/ds-identify.log
    # 查看 cloud-init 状态
    cloud-init status --long

    网络配置问题

    Terminal window
    # 这个文件默认不存在:它就是下面要新建的「禁用 cloud-init 网络管理」配置
    # 先确认是否已有其他网络配置片段
    ls -l /etc/cloud/cloud.cfg.d/
    # 如需禁止 cloud-init 管理网络
    cat > /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg << 'EOF'
    network: {config: disabled}
    EOF

    软件包安装失败

    Terminal window
    # 搜索日志中的错误
    sudo grep -i "error\|fail\|warn" /var/log/cloud-init.log | tail -20
    # 检查 dnf 日志
    sudo cat /var/log/dnf.log

    在某些场景下可能需要彻底禁用 Cloud-Init:

    Terminal window
    # 方法一:创建禁用标记文件
    sudo touch /etc/cloud/cloud-init.disabled
    # 方法二:禁用所有 cloud-init 服务
    sudo systemctl disable cloud-init-local cloud-init cloud-config cloud-final
    # 方法三:完全卸载
    sudo dnf remove -y cloud-init

    Cloud-Init 的全局默认配置位于 /etc/cloud/cloud.cfg,可以通过在 /etc/cloud/cloud.cfg.d/ 目录下添加自定义文件来覆盖默认值:

    Terminal window
    # 自定义默认用户
    sudo cat > /etc/cloud/cloud.cfg.d/10-custom-user.cfg << 'EOF'
    system_info:
    default_user:
    name: admin
    lock_passwd: true
    gecos: Admin User
    groups: [wheel, adm]
    sudo: ["ALL=(ALL) NOPASSWD:ALL"]
    shell: /bin/bash
    EOF
    # 自定义数据源优先级
    sudo cat > /etc/cloud/cloud.cfg.d/90-datasource.cfg << 'EOF'
    datasource_list: [ NoCloud, AliYun, Ec2, None ]
    EOF

    Cloud-Init 是云环境自动化的基石。掌握它的配置方法后,可以实现实例的零接触部署,与后续介绍的 Ansible、Terraform 等工具配合使用可构建完整的自动化运维体系。