实习将近一个月了,期间不断努力,终于算是把OpenStack Ironic项目实现裸机部署的过程理解了一遍,并在小规模集群上成功实践。整理一些这段时间工作的内容,就算是一个阶段性的小项目总结了。
Ironic
Ironic是OpenStack的一个子项目,用于实现在云里像管理虚拟机一样管理裸机。
Ironic在OpenStack中的概念架构图如下
其中Bare Metal就是我们要控制的物理机了,Neutron为其提供网络服务,Cinder提供块存储服务,Glance则提供裸机部署时的镜像缓存服务,在部署过程中,我们的Ironic模块要和Neutron,Nova,Glance,Keystone这些核心的OpenStack项目配合,才能完美实现裸机部署的过程。
裸机部署过程中用到的一些核心的技术
(PXE) 预引导执行环境,PXE是英特尔和微软开发的Wired for Management(WfM)规范的一部分。PXE使系统的BIOS和网络接口卡(NIC)能够从网络引导计算机而不是磁盘。引导是系统将OS加载到本地存储器的过程,以便处理器可以执行该过程。允许系统通过网络引导这种功能简化了管理员和服务器部署和服务器的管理。
动态主机配置协议(DHCP) DHCP是用于英特网协议(IP)网络的标准化网络协议,用于动态分配网络配置参数,例如接口和服务的IP地址。使用PXE,BIOS使用DHCP获取网络接口的IP地址,并找到存储网络引导程序(NBP)的服务器。
网络引导程序(NBP) NBP等同于GRUB(Grand Unified Bootloader)或 LILO(Linux LOader) - 传统上用于本地引导的加载器。与硬件驱动器环境中的引导程序一样,NBP负责将OS那个加载到内存中,以便可以通过网络引导操作系统。
普通文件传输协议(TFTP) TFTP是一种简单的文件传输协议,通常用于在本地环境中的计算机之间自动传输配置或引导文件。在PXE环境中,TFTP用于使用来自DHCP服务器的信息通过网络下载NBP。
智能平台管理接口(IPMI) IPMI是系统管理员用于计算机系统的带外管理和监视其操作的标准化计算机系统接口。这是一种通过仅使用于硬件而不是操作系统的网络连接来管理可能无响应或断电的系统的方法。
Ironic裸机部署的过程
核心流程分析
1、引导实例请求通过 Nova API 进入,通过消息队列进入 Nova 调度程序。
2、Nova Scheduler 应用过滤器并查找符合条件的虚拟机监控nova调度程序,还使用flavor的extra_specs(例如 cpu_arch)来匹配目标物理节点。
3、Nova compute 管理选中hypervisor的资源声明。
4、Nova compute 管理器根据 nova引导请求中网络接口在Networking服务中创建(未绑定)租户虚拟接口(VIF)。这里需要注意的是,端口的MAC将随机生成,并且当VIF连接到某个节点以对应于节点网络接口卡时MAC将更新。
5、nova compute创建一个 spawn 任务,它包含所有信息,例如从哪个镜像引导等。它从Nova compute的virt层调用 driver.spawn。在spawn过程中,virt驱动程序执行以下操作: 更新目标ironic节点的deploy镜像,实例UUID,请求的功能和各种flavor属性。通过调用ironic API 验证节点的电源和部署的接口。将之前创建的VIF附加到节点。每个neutron port 可以被附加到任何ironic port和port group,port groups 比 ports有更高的优先级。在Ironic这边,这个工作时由 network interface做的。
6、Nova 的 ironic驱动程序通过 Ironic API 向服务裸机节点的 Ironic conductor 发出部署请求。
7、配置虚拟接口,Neutron API更新DHCP端口以设置 PXE/TFTP选项。在使用neutron网络接口的情况下,ironic在网络服务中创建单独的配置端口,在 flat 网络接口的情况下,nova创建的端口用于配置和部署实例网络。
8、Ironic节点的启动接口准备PXE配置和缓存 deploy kernel和 ramdisk。
9、Ironic 节点通过 Management interfacec发出命令来启动节点的网络引导。
10、Ironic 节点的 Deploy Interface 缓存实例镜像(在 iSCSI 部署接口的情况下),缓存kernel和ramdisk,在netboot的时候需要它。
11、Ironic节点的Power Interface 指示节点的电源接口通电。
12、节点引导部署ramdisk
13、根据确切的驱动程序需求,conductor 将通过iSCSI复制镜像到物理节点。
14、节点的引导接口将 pxe config切换为引用实例镜像,要求 ramdisk agent 软关闭节点电源,如果ramdisk agent 软关闭电源失败,则通过IPMI/BMS呼叫关机裸机节点电源。
15、部署接口会触发网络接口,以便在创建时删除配置端口,并将租户端口绑定到节点。然后给节点上电。
16、裸机节点的 provisioning state更新为active状态。
部署实践
安装好ubuntu server 16.04系统作为裸机部署的控制节点
配置网络
1
2
3
4
5
6
7
8
9
10
11
12
13
auto eth0
iface eth0 inet static
gateway 192.168.0.253
address 192.168.0.50/24
mtu 1500
#neutron
auto eth1
iface eth1 inet manual
up ip link set dev eth1 promisc on
up ip link set dev eth1 up
down ip link set dev eth1 down
down ip link set dev eth1 promisc off
eth0 做为 API_NET 接口,提供 OpenStack 的管理网络,我们给它分配一个静态IP,这里的地址需要和你的实际网络环境一致。
eth1 做为 EXT_NET 接口,提供 OpenStack 的 neutron 网络,这里我们启动网口但是不对它进行IP配置。
安装kolla环境,部署OpenStack with Ironic
更新apt源,安装依赖
1
2
3
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install python-jinja2 python-pip libssl-dev -fy
配置 pip 加速,使用阿里云 pip 源
1
2
3
4
5
6
mkdir ~/.pip
tee ~/.pip/pip.conf <<-'EOF'
[global]
trusted-host = mirrors.aliyun.com
index-url = https://mirrors.aliyun.com/pypi/simple
EOF
安装 kolla,kolla-ansible,python-openstackclient
1
2
3
4
sudo pip install --upgrade pip
sudo pip install ansible
sudo pip install kolla-ansible==4.0.3
sudo pip install python-openstackclient
Kolla部署Ironic配置
1
sudo cp -r /usr/local/share/kolla-ansible/etc_examples/kolla /etc/kolla
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
sudo vim /etc/kolla/global.yml
# 关键配置修改
# Valid options are [ centos, oraclelinux, ubuntu ]
kolla_base_distro: "centos"
# Valid options are [ binary, source ]
kolla_install_type: "binary"
# Valid option is Docker repository tag
openstack_release: "4.0.0"
# api_net 的地址
kolla_internal_vip_address: "192.168.0.50"
network_interface: "eth0"
neutron_external_interface: "eth1"
neutron_plugin_agent: "openvswitch"
kolla_enable_tls_external: "no"
ironic_cleaning_network: "public1"
ironic_dnsmasq_dhcp_range: "192.168.8.1,192.168.8.5"
enable_ironic: "yes"
enable_haproxy: "no"
Ironic 相关配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 启用内核支持模块,删除open-iscsi
sudo modprobe configfs
sudo apt-get remove open-iscsi
sudo mkdir -p /etc/kolla/config/ironic
cd /etc/kolla/config/ironic
# 下载和存储ironic部署时引导镜像
sudo wget http://otcloud-gateway.bj.intel.com/deployment-img/ironic-agent.kernel
sudo wget http://otcloud-gateway.bj.intel.com/deployment-img/ironic-agent.initramfs
sudo mv ironic.conf /etc/kolla/config/ironic.conf
#ironic.conf的内容
[DEFAULT]
enabled_drivers=pxe_ipmitool
[conductor]
automated_clean=false
# pxe 寻找tftp服务器是通过这个地址找的,如果不配置,pxe将无法从tftp服务拿到镜像,从而超时失败
[pxe]
tftp_server=192.168.1.50
kolla快速部署环境
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 生成密码
kolla-genpwd
# 初始化环境,安装一些基础依赖如 docker
sudo kolla-ansible \
-i /usr/local/share/kolla-ansible/ansible/inventory/all-in-one \
bootstrap-servers
# 配置dockerhub加速,我们用国内的阿里云源加速
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://ao6wb0ej.mirror.aliyuncs.com"]
}
EOF
# 配置完后重启docker
sudo systemctl daemon-reload
sudo service docker restart
# 拉取镜像
sudo kolla-ansible pull
# 预检查
sudo kolla-ansible prechecks \
-i /usr/local/share/kolla-ansible/ansible/inventory/all-in-one
# 部署
sudo kolla-ansible deploy \
-i /usr/local/share/kolla-ansible/ansible/inventory/all-in-one
# 生成部署环境文件,/etc/kolla/admin-openrc.sh 里面有重要的系统初始化配置
sudo kolla-ansible post-deploy
配置br-ex
1
2
3
4
5
6
7
8
# 配置 eth1 即neutron对应的网卡所在的网络环境
auto br-ex
iface br-ex inet static
address 192.168.1.50
netmask 255.255.255.0
gateway 192.168.1.253
dns-nameserver 192.168.1.253
# 注释掉 eth1 原来的配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/bin/bash
# ironic 管理网段
EXT_NET_CIDR='192.168.1.0/24'
EXT_NET_RANGE='start=192.168.1.20,end=192.168.1.100'
EXT_NET_GATEWAY='192.168.1.253'
EXT_NET_CIDR_DNS='192.168.1.253'
# ironic init setup
# create ironic manage network
openstack network create --provider-physical-network physnet1 \
--provider-network-type flat public1
openstack subnet create \
--allocation-pool ${EXT_NET_RANGE} --network public1 \
--subnet-range ${EXT_NET_CIDR} --gateway ${EXT_NET_GATEWAY} --dns-nameserver ${EXT_NET_CIDR_DNS} -- public1-subnet
# 上传部署的引导镜像
openstack image create --disk-format aki --container-format aki --public \
--file /etc/kolla/config/ironic/ironic-agent.kernel deploy-vmlinuz
openstack image create --disk-format ari --container-format ari --public \
--file /etc/kolla/config/ironic/ironic-agent.initramfs deploy-initrd
使用diskimage-builder制作ubuntu部署镜像
1
2
3
sudo pip install diskimage-builder
sudo apt install -y qemu-utils
disk-image-create ubuntu baremetal dhcp-all-interfaces -o my-image
1
2
3
4
5
6
7
8
9
10
11
12
13
glance image-create --name my-kernel --visibility public \
--disk-format aki --container-format aki < my-image.vmlinuz
glance image-create --name my-image.initrd --visibility public \
--disk-format ari --container-format ari < my-image.initrd
MY_VMLINUZ_UUID=$(glance image-list|grep my-kernel|awk -F "| " '{print $2}')
MY_INITRD_UUID=$(glance image-list|grep my-image.initrd|awk -F "| " '{print $2}')
glance image-create --name my-image --visibility public \
--disk-format qcow2 --container-format bare --property \
kernel_id=$MY_VMLINUZ_UUID --property \
ramdisk_id=$MY_INITRD_UUID < my-image.qcow2
1
2
3
4
5
6
7
8
9
10
# 生成密钥对
if [ ! -f ~/.ssh/id_rsa.pub ]; then
echo Generating ssh key.
ssh-keygen -t rsa -f ~/.ssh/id_rsa
fi
if [ -r ~/.ssh/id_rsa.pub ]; then
echo Configuring nova public key and quotas.
openstack keypair create --public-key ~/.ssh/id_rsa.pub mykey
fi
注册BareMetal节点,启动部署裸机的操作系统
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
source server_ipmi
# 物理裸机的配置,可小不可大于实际值
RAM=65536
DISK=800
VCPUS=32
HOST_CPU_ARCH=x86_64
export IRONIC_API_VERSION=1.20
DEPLOY_VMLINUZ_UUID=$(glance image-list|grep deploy-vmlinuz|awk -F "| " '{print $2}')
DEPLOY_INITRD_UUID=$(glance image-list|grep deploy-initrd|awk -F "| " '{print $2}')
# node1 创建 flavor
nova flavor-create ai-bm-node1 1 ${RAM} ${DISK} ${VCPUS}
nova flavor-key ai-bm-node1 set cpu_arch=x86_64
nova flavor-key ai-bm-node1 set resources:CUSTOM_BAREMETAL_NODE1_AI=1
nova flavor-key ai-bm-node1 set resources:VCPU=0
nova flavor-key ai-bm-node1 set resources:MEMORY_MB=0
nova flavor-key ai-bm-node1 set resources:DISK_GB=0
# 创建 node
ironic node-create -d pxe_ipmitool -n node1
NODE1_UUID=$(ironic node-list|grep node1|awk -F "| " '{print $2}')
# 设置 node 的 ipmi信息
ironic node-update $NODE1_UUID add driver_info/ipmi_username=$s1_ipmi_username \
driver_info/ipmi_password=$s1_ipmi_password driver_info/ipmi_address=$s1_ipmi_address \
driver_info/ipmi_terminal_port=623
# 设置 node 的引导镜像信息
ironic node-update $NODE1_UUID add driver_info/deploy_kernel=$DEPLOY_VMLINUZ_UUID \
driver_info/deploy_ramdisk=$DEPLOY_INITRD_UUID
# 设置 node 的基本配置信息
ironic node-update $NODE1_UUID add properties/cpus=${VCPUS} properties/memory_mb=${RAM} \
properties/local_gb=${DISK} properties/cpu_arch=${HOST_CPU_ARCH}
# 设置 node 的resource-class,方面node判断部署到哪个裸机节点
openstack --os-baremetal-api-version 1.21 baremetal node set $NODE1_UUID \
--resource-class CUSTOM_BAREMETAL_NODE1_AI
# 设置 启动网口的 MAC 地址,即 node 的 port
ironic port-create -n $NODE1_UUID -a $s1_nic_mac_address
# 设置 node状态为 provide
ironic --ironic-api-version 1.20 node-set-provision-state $NODE1_UUID manage
ironic --ironic-api-version 1.20 node-set-provision-state $NODE1_UUID provide
# 启动部署
openstack server create --image my-image --flavor ai-bm-node1 \
--key-name mykey --network public1 node1
脚本github地址
https://github.com/vajn/ironic_setup