8 云计算系列之Horizon的安装与虚拟机创建流程
preface
在上一章节中,我们可以在无web管理界面上创建并启动虚拟机,虽然可以这么做,但是敲命令太繁琐,所以此时我们可以安装openstack web管理界面,通过web界面的图形化操作openstack,更加方便的使用openstack。
Horizon简介
- 提供一个web界面操作openstack的系统。
- 使用Django框架基于Openstack API 开发
- 支持Session存储在DB、Memcached。
- 支持集群。
动手安装
由于Horizon也要依赖于apache等web服务,所以为了避免冲突,不要再linux-node1上安装,我们在linux-node2上安装它
1.yum安装它
[root@linux-node2 ~]# yum install openstack-dashboard
2.更改配置
[root@linux-node2 ~]# vim /etc/openstack-dashboard/local_settings
OPENSTACK_HOST = "192.168.56.11" # keystone主机
SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # 启用session共享
ALLOWED_HOSTS = ["*",] # 允许所有主机访问
CACHES = { # 设置memcached缓存session信息
'default': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
'LOCATION': '192.168.56.11:11211'
},
}
OPENSTACK_KEYSTONE_URL = "http://%s:5000/v3" % OPENSTACK_HOST #启用第3版认证API:
OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT = True # 启用对域的支持
OPENSTACK_API_VERSIONS = { #配置API版本:
"data-processing": 1.1,
"identity": 3,
"image": 2,
"volume": 2,
"compute": 2,
}
OPENSTACK_KEYSTONE_DEFAULT_DOMAIN = 'default' # 通过仪表盘创建用户时的默认域配置为 default
OPENSTACK_KEYSTONE_DEFAULT_ROLE = "_member_" #通过仪表盘创建的用户默认角色配置为 user
OPENSTACK_NEUTRON_NETWORK = { # 我们选中的是自提供网络,所以需要禁用支持3层网络服务
'enable_router': False,
'enable_quotas': False,
'enable_ipv6': False,
'enable_distributed_router': False,
'enable_ha_router': False,
'enable_lb': False,
'enable_firewall': False,
'enable_vpn': False,
'enable_fip_topology_check': False,
}
TIME_ZONE = "Asia/Shanghai" # 配置时区为上海
3.启动http服务
[root@linux-node2 openstack-dashboard]# systemctl restart httpd.service
[root@linux-node2 openstack-dashboard]# systemctl enable httpd.service
4.访问Horizon(Dashboard),访问URL:http://192.168.56.12/dashboard/auth/login/?next=/dashboard/
5.登陆Dashboard,域为default,用户名是admin,密码是admin。
5.1.如果提示身份令牌过期,那么就重启下keystone服务(systemctl restart httpd.service),如果这样不行的话,重启下系统就可以了
5.2.登陆上去以后,在点击管理成员后报错,提示说 keystone缺少 memmber 角色,那么就在keystone服务器上增加一条 member 角色,命令如下:
[root@linux-node1 keystone]# openstack role create _member_
+-----------+----------------------------------+
| Field | Value |
+-----------+----------------------------------+
| domain_id | None |
| id | 9fe2ff9ee4384b1894a90878d3e92bab |
| name | _member_ |
+-----------+----------------------------------+
6.手动在原先的网络基础上添加IP段,操作步骤如下:
6.1.管理员身份登陆 ,登陆后点击左侧面板上的管理员-->系统-->网络-->点击需要增加IP段的网络-->子网-->编辑子网-->子网详情--> 分配地址池里添加需要添加IP地址段。
同时可以在数据库查看表里面的数据验证下:
[root@linux-node1 image]# mysql -uneutron -pneutron
MariaDB [(none)]> use neutron;
MariaDB [neutron]> select * from ipallocations;
+--------------------------------------+----------------+--------------------------------------+--------------------------------------+
| port_id | ip_address | subnet_id | network_id |
+--------------------------------------+----------------+--------------------------------------+--------------------------------------+
| 1a069091-4b79-4f0e-b197-cf62d5c9aee2 | 192.168.56.108 | a15e0cf4-e456-4047-8793-ed366dce5087 | 5f693f46-8f51-47be-a04a-d3ddf7bb2899 |
| 3a76a4ae-472e-4d1a-bf66-52ab314bbf96 | 192.168.56.107 | a15e0cf4-e456-4047-8793-ed366dce5087 | 5f693f46-8f51-47be-a04a-d3ddf7bb2899 |
| e2ee384f-578b-40d5-998d-5316359a7cee | 192.168.56.100 | a15e0cf4-e456-4047-8793-ed366dce5087 | 5f693f46-8f51-47be-a04a-d3ddf7bb2899 |
+--------------------------------------+----------------+--------------------------------------+--------------------------------------+
3 rows in set (0.01 sec)
MariaDB [neutron]> select * from ipallocationpools;
+--------------------------------------+--------------------------------------+----------------+----------------+
| id | subnet_id | first_ip | last_ip |
+--------------------------------------+--------------------------------------+----------------+----------------+
| 36f36478-4497-42d7-ad99-a13ea59b3d40 | a15e0cf4-e456-4047-8793-ed366dce5087 | 192.168.56.50 | 192.168.56.99 |
| ffdaf384-1b5f-4dce-8beb-f92a11594445 | a15e0cf4-e456-4047-8793-ed366dce5087 | 192.168.56.100 | 192.168.56.200 |
+--------------------------------------+--------------------------------------+----------------+----------------+
虚拟机创建流程
个人总结为四个阶段
- keystone认证阶段
- nova组件内部信息交互
- nova与其他组件的信息交互
- 执行创建虚拟机
具体流程如下:
- 用户名密码验证后,keystone返回一个token,此时你有个token了,就可以带着token访问nova-api了
- nova-api拿到你的token后向keystone验证你的token是否合法。验证成功后,把要创建虚拟机的信息(信息包含虚拟机内存大小,CPU数量等)写入到数据库里面,也写入到消息队列里面。
- nova-schedule监听到消息队列有创建虚拟机的消息来了,那么就连接数据库,查询计算节点信息(包括但不限于节点数量,节点资源使用情况等)后调度在某个计算节点上创建这个虚拟机。
- nova-computer监听到消息队列后创建虚拟机的消息后便开始创建虚拟机了,于是它开始通过nova-conductor连接数据库,查询创建虚拟机的信息(比如VCPU数量,内存大小等)。获取后就开始创建。
- nova-computer开始创建虚拟机了,首先向glance获取镜像,glance拿着nova-computer提交过来的token去验证,验证成功后便返回镜像信息给nova-computer。
- nova-computer向neutron申请网络功能,比如ip地址分配。neutron还是得先向keystone验证nova-computer的token,验证成功后才给nova-computer创建。
- nova-computer向cinder申请硬盘,cinder向keystone验证nova-computer的token,验证成功后才给创建硬盘。
- 当所有准备工作就绪以后,nova-computer就会调用libvirt去使用kvm创建虚拟机,通过轮询的方式不断查询虚拟机的状态,展现到Horizon上面且会把状态信息写入到数据库里。
深入了解虚拟机
我们继续在linux-node1上安装nova软件,之所以再次安装nova软件,是因为想看看nova-scheduler调度。
1.安装nova软件
[root@linux-node1 ~]# yum -y install openstack-nova-compute
[root@linux-node1 ~]# systemctl start openstack-nova-compute
[root@linux-node1 ~]# systemctl enable openstack-nova-compute
2.修改配置文件,因为是在之前的基础上修改过来的,所以呢这里只是添加了novncproxy_base_url和virt_type
[root@linux-node1 openrc]# vim /etc/nova/nova.conf
[DEFAULT]
transport_url=rabbit://openstack:openstack@192.168.56.11
enabled_apis=osapi_compute,metadata
auth_strategy = keystone
use_neutron=True
firewall_driver = nova.virt.firewall.NoopFirewallDriver
[api_database]
connection=mysql+pymysql://nova:nova@192.168.56.11/nova_api
[database]
connection = mysql+pymysql://nova:nova@192.168.56.11/nova
[ephemeral_storage_encryption]
[glance]
api_servers= http://192.168.56.11:9292
[vnc]
vncserver_listen=0.0.0.0
vncserver_proxyclient_address=192.168.56.11
novncproxy_base_url=http://192.168.56.11:6080/vnc_auto.html
[keystone_authtoken]
auth_uri = http://192.168.56.11:5000
auth_url = http://192.168.56.11:35357
memcached_servers = 192.168.56.11:11211
auth_type = password
project_domain_name = default
user_domain_name = default
project_name = service
username = nova
password = nova
[libvirt]
virt_type=kvm
[neutron]
url = http://192.168.56.11:9696
auth_url = http://192.168.56.11:35357
auth_type = password
project_domain_name = Default
user_domain_name = Default
region_name = RegionOne
project_name = service
username = neutron
password = neutron
service_metadata_proxy = True
metadata_proxy_shared_secret = oldboy
[oslo_concurrency]
lock_path = /var/lib/nova/tmp
3.查看novalist
[root@linux-node1 openrc]# source admin_openrc
[root@linux-node1 openrc]# nova service-list
+----+------------------+-------------------------+----------+---------+-------+----------------------------+-----------------+
| Id | Binary | Host | Zone | Status | State | Updated_at | Disabled Reason |
+----+------------------+-------------------------+----------+---------+-------+----------------------------+-----------------+
| 1 | nova-conductor | linux-node1.example.com | internal | enabled | up | 2017-01-31T04:01:38.000000 | - |
| 3 | nova-consoleauth | linux-node1.example.com | internal | enabled | up | 2017-01-31T04:01:41.000000 | - |
| 4 | nova-scheduler | linux-node1.example.com | internal | enabled | up | 2017-01-31T04:01:41.000000 | - |
| 7 | nova-compute | linux-node2.example.com | default | enabled | up | 2017-01-31T04:01:40.000000 | - |
| 8 | nova-compute | linux-node1.example.com | nova | enabled | up | 2017-01-31T04:01:40.000000 | - |
+----+------------------+-------------------------+----------+---------+-------+----------------------------+-----------------+
4.在Horizon上创建虚拟机,我这里创建了2台,保持刚才默认的m1.nano配置(m1.nano是云主机的配置,创建命令如下:openstack flavor create --id 0 --vcpus 1 --ram 64 --disk 1 m1.nano
)
5.在linux-node1上查看镜像实例和虚拟机实例
- 镜像实例信息
[root@linux-node1 openrc]# cd /var/lib/glance/images/ # 查看镜像实例
[root@linux-node1 images]# ll -rth # 每一个目录名字就是镜像ID,我们通过openstack image list可以对比发现镜像ID一致
total 12980
-rw-r----- 1 glance glance 13287936 Jan 3 14:46 5c242396-3c7b-4bc6-bec1-3df8eb57d53d
[root@linux-node1 images]# openstack image list
+--------------------------------------+--------+--------+
| ID | Name | Status |
+--------------------------------------+--------+--------+
| 5c242396-3c7b-4bc6-bec1-3df8eb57d53d | cirros | active |
+--------------------------------------+--------+--------+
- 虚拟机实例
虚拟机实例ID可以在dashboard(horizon)上面查看到的,在一台虚拟机概况里面就可以看到虚拟机ID
[root@linux-node1 images]# virsh list --all
Id Name State
----------------------------------------------------
1 instance-00000003 running
- CentOs-7-x86_64 shut off # 之前通过kvm创建的CentOs7,和Openstack没关系
[root@linux-node1 images]# cd /var/lib/nova/instances/
[root@linux-node1 instances]# ll -rt
total 4
drwxr-xr-x 2 nova nova 53 Feb 6 22:09 _base #
drwxr-xr-x 2 nova nova 91 Feb 7 10:33 locks
-rw-r--r-- 1 nova nova 46 Feb 7 10:33 compute_nodes
drwxr-xr-x 2 nova nova 69 Feb 7 10:54 da0e8cfc-46f9-416d-a828-397d8d7e4023 # 这个目录名字就是虚拟机ID
[root@linux-node1 instances]# cd _base/
[root@linux-node1 _base]# tree
.
└── 7312bbe40cc8bc765d86d2dbd58d0a57a83ee215
6.进入虚拟机实例目录里面查看信息
[root@linux-node2 instances]# cd bfa193b8-cf7c-4a5f-b73a-7089a0e567db/ # 这个虚拟机调度到node2上创建了,目录还是/var/lib/nova/instance下面查看
[root@linux-node2 bfa193b8-cf7c-4a5f-b73a-7089a0e567db]# ll -rt
total 2212
-rw-r--r--. 1 nova nova 79 Feb 7 10:54 disk.info #磁盘信息文件
-rw-r--r--. 1 nova nova 2643 Feb 7 10:54 libvirt.xml # 虚拟机配置文件,通过libvirt创建
-rw-r--r--. 1 nova qemu 19268 Feb 7 10:55 console.log # 控制台日志输出
-rw-r--r--. 1 qemu qemu 2293760 Feb 7 10:55 disk # 磁盘文件
- disk文件解读
大家可以看到磁盘文件大小为2.2M,虚拟机大小肯定不止2.2M的,那么肯定是有疑问的,我们看看这个文件的内容
[root@linux-node2 bfa193b8-cf7c-4a5f-b73a-7089a0e567db]# file disk
disk: QEMU QCOW Image (v3), has backing file (path /var/lib/nova/instances/_base/7312bbe40cc8bc765d86d2dbd58d0a57a), 1073741824 bytes
[root@linux-node2 bfa193b8-cf7c-4a5f-b73a-7089a0e567db]# qemu-img info disk
image: disk
file format: qcow2
virtual size: 1.0G (1073741824 bytes) # 虚拟机大小为1G
disk size: 2.1M # 实际大小为2.1M
cluster_size: 65536
backing file: /var/lib/nova/instances/_base/7312bbe40cc8bc765d86d2dbd58d0a57a83ee215
Format specific information:
compat: 1.1
lazy refcounts: false
通过file disk
这个命令查看磁盘文件后,我们发现这个QCOW还有一个文件是在后端存放的,存放地址是在/var/lib/nova/instances/_base/7312bbe40cc8bc765d86d2dbd58d0a57a
,这个QCOW是显示拷贝的镜像,他有这么一个特性,虚拟机的现有磁盘文件(disk)只记录比之前的镜像文件不一样的信息,所谓的之前的镜像文件就是创建虚拟机的镜像文件,我们这里使用的是cirros,所以disk文件记录是与cirros镜像文件不一样的信息,所以disk文件大小为2.2M也是可以理解的了。
我们看看disk的后端文件:
[root@linux-node2 instances]# cd _base/
[root@linux-node2 _base]# qemu-img info 7312bbe40cc8bc765d86d2dbd58d0a57a83ee215
image: 7312bbe40cc8bc765d86d2dbd58d0a57a83ee215
file format: raw
virtual size: 39M (41126400 bytes)
disk size: 18M
这里可以看出后端文件的镜像格式为raw,raw性能最好,不支持加密,压缩。而qcow支持加密,压缩等,性能稍弱。
- disk.info文件解读
字典格式内容,key为磁盘文件位置,value为磁盘格式
[root@linux-node2 bfa193b8-cf7c-4a5f-b73a-7089a0e567db]# cat disk.info
{"/var/lib/nova/instances/bfa193b8-cf7c-4a5f-b73a-7089a0e567db/disk": "qcow2"}
- libvirt.xml 解读
因为是通过libvirt创建的虚拟机,所以关于libvirt.xml文件的配置我们可以参考这个博文:http://www.cnblogs.com/liaojiafa/p/6194056.html 。
这个libvirt.xml别去修改,修改完重启虚拟机后又恢复到最初的配置状态,除非改完别重启就行。
我们可以看看在qemu下面关于这个虚拟机的XML配置
[root@linux-node2 bfa193b8-cf7c-4a5f-b73a-7089a0e567db]# cd /etc/libvirt/qemu/
[root@linux-node2 qemu]# ls
instance-00000004.xml networks
[root@linux-node2 qemu]# cat instance-00000004.xml
.....省略几万字
7.浅谈虚拟机的网络
[root@linux-node1 instances]# brctl show
bridge name bridge id STP enabled interfaces
brq33b9ef50-35 8000.000c29c37394 no eth0
tap6a790b22-29
tapd605dd99-52
virbr0 8000.525400babde7 yes virbr0-nic
通过brctl show
可以查看到桥接网卡,brq33b9ef50 桥接到了eth0上,那么怎么理解这个呢?我们可以这么理解,我们把show出来的整个看做为一个交换机,eth0是插在这个交换机的某一个口,tap6a790b22-29也是插在这个交换机的某一个口,但是tap6a790b22-29是成对出现的,一端插在这个交换机上,一端插在虚拟机上的。所以本机只能连接上本机创建的虚拟机。
8.解读metadata
说道在创建虚拟机的时候,我们那时上传了公钥,那么问题来了,虚拟机是如何获取到这个公钥信息的呢?下面我们先看看虚拟机的console.log,
[root@linux-node1 da0e8cfc-46f9-416d-a828-397d8d7e4023]# pwd # 这个路径下面
/var/lib/nova/instances/da0e8cfc-46f9-416d-a828-397d8d7e4023
[root@linux-node1 da0e8cfc-46f9-416d-a828-397d8d7e4023]# grep checking console.log
checking http://169.254.169.254/2009-04-04/instance-id # 找到这个URL
拿到这个URL后,我们可以连接上虚拟机,通过curl获取我们所需的资料:
$ curl http://169.254.169.254/2009-04-04/meta-data/ # 罗列出所需要的信息
ami-id
ami-launch-index
ami-manifest-path
block-device-mapping/
hostname
instance-action
instance-id
instance-type
local-hostname
local-ipv4
placement/
public-hostname
public-ipv4
public-keys/
reservation-id
$ curl http://169.254.169.254/2009-04-04/meta-data/public-keys/0/openssh-key # 获取公钥信息
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCchdZOe760nvviGqVqUHebS4nBF0KGJ+6P831glLbDXaMQ8pBzFMgpaiLyiLh4eOPPLmOJQC2jtzaq515XhQoOQ/fHjh7diw6e8NIIhyPwiwx7yvB8xD8m4QtL0ewwwo0OQEgCeXoLIRqn0/i+nIlji6Im6kJMu1WJQmR5PUyVJbLJV8uUabB7UCcIRBRdvgRiFKuWtZ45TeNEGrdtmKAmjMpcZUENE9txXwuRaGNdnx/aEH6C9uzX1kWE8FfpvemBdInKrq0+m1+dC0x6u0zMsfCd0JHV1K/14wJH84oX+9j3hSxqTABQGOwCAXzox6HX5AJk/bP/JsFNP1HdY4C5 root@linux-node1.example.com
$ curl http://169.254.169.254/2009-04-04/meta-data/hostname # 获取主机名
这个metadata是由dhcp配置文件来控制的,如下所示:
[root@linux-node1 tmp]# vim /etc/neutron/dhcp_agent.ini
enable_isolated_metadata = True # 这个配置项
关于169.254.169.251这个IP,我们在虚拟机上查看下这个路由信息
$ ip ro li
default via 192.168.56.2 dev eth0
169.254.169.254 via 192.168.56.100 dev eth0 # 访问169.254.169.254 其实就是访问了 192.168.56.100 , 192.168.56.100是我们DHCP服务器的地址
192.168.56.0/24 dev eth0 src 192.168.56.108
在宿主机上查看:
[root@linux-node1 da0e8cfc-46f9-416d-a828-397d8d7e4023]# ip netns li
qdhcp-33b9ef50-354b-457b-8ea2-8498ec64835b (id: 0)
[root@linux-node1 da0e8cfc-46f9-416d-a828-397d8d7e4023]# ip netns exec qdhcp-33b9ef50-354b-457b-8ea2-8498ec64835b ip ad li
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ns-d605dd99-52@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP qlen 1000
link/ether fa:16:3e:a1:e7:54 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 192.168.56.100/24 brd 192.168.56.255 scope global ns-d605dd99-52 #
valid_lft forever preferred_lft forever
inet 169.254.169.254/16 brd 169.254.255.255 scope global ns-d605dd99-52 # 有169.254.169.254这个IP
valid_lft forever preferred_lft forever
inet6 fe80::f816:3eff:fea1:e754/64 scope link
valid_lft forever preferred_lft forever
通过上面的列子,因为就知道了虚拟机的公钥是怎么来的了。
关于169.254.169.254,是因为以前亚马逊镜像是使用169.254.169.254这个ip,后来Openstack为了和亚马逊的兼容,所以也是用了这个IP