Author Archive

LibvirtHybridOVSBridgeDriver –> LibvirtGenericVIFDriver

OpenStack IceHouse Release에서는 LibvirtHybridOVSBridgeDriver가 deprecated되고 LibvirtGenericVIFDriver가 사용됩니다. 그래서 LibvirtGenericVIFDriver 설정하고 인스턴스를 생성하면 havana이전에 LibvirtHybridOVSBridgeDriver에서 생성한 openvswitch - linux bridge를 사용하여 포트를 구성하죠..

그런데 havana에서 부터 있던 인스턴스는 이렇게 생성되지 않고, LibvirtOpenVswitchDriver로 생성한 것 처럼 ovs - kvm으로 직접 연결됩니다. 이렇게 되니 아래의 문제가 생기게 되죠..

  • 당연히 security group이 작동하지 않음
  • havana에서 upgrade한 인스턴스가 stop / resume / restart 등을 한 이후에는 네트워크가 되지 않음..

이게 뭘까 좀 추적해 봤습니다.

LibvirtGenericVIFDriver에서는 vif.is_hybrid_plug_enabled()에서 해당 포트가 hybrid인지 아닌지 판단하고 있습니다. 즉 여기까지 보면 이전에는 driver에 따라서 vif 구성이 결정되었지만, 이제는 vif port의 설정에 따라서 구성이 되는 것으로 보입니다.

그러면 이 설정은 어디 있을까.. 추적해보면

nova.network.mode.VIF 에서 아래처럼 하고 있습니다.

    def is_hybrid_plug_enabled(self):                                                   
        return self['details'].get(VIF_DETAIL_OVS_HYBRID_PLUG, False)                   

vif의 detail이라는 property로 들어 있는 것이죠.. 그럼 이거는 어디 있을까.. 찾아보면..

mysql> select * from ml2_port_bindings where port_id = 'e14dbfd5-670e-405f-aaec-3796d1df1c34' \G
*************************** 1. row ***************************
    port_id: e14dbfd5-670e-405f-aaec-3796d1df1c34
       host: compute000
   vif_type: ovs
     driver: openvswitch
    segment: d3685732-365f-4a5b-baed-8adb7b2decf3
  vnic_type: normal
vif_details: {"port_filter": true, "ovs_hybrid_plug": true}
    profile: 
1 row in set (0.00 sec)

이렇게 DB의 설정값으로 고히 모셔져 있군요.. 이 값은

class OpenvswitchMechanismDriver(mech_agent.SimpleAgentMechanismDriverBase):
    def __init__(self):
        super(OpenvswitchMechanismDriver, self).__init__(
            constants.AGENT_TYPE_OVS,
            portbindings.VIF_TYPE_OVS,
            {portbindings.CAP_PORT_FILTER: True,
             portbindings.OVS_HYBRID_PLUG: True})

이렇게 기본값이 True로 설정되어 DB에 들어가고 있습니다. 하지만 아래를 보면 port에 따라서 vif_details가 들어가있지 않는 포트가 있고

mysql> select port_id, vif_details from ml2_port_bindings;
+--------------------------------------+------------------------------------------------+
| port_id                              | vif_details                                    |
+--------------------------------------+------------------------------------------------+
| 0cc863d2-adf4-49b7-9c28-1d0cf0ffd7d4 |                                                |
| 2f2782dd-cb6b-4a37-a384-8c4883e7243d |                                                |
| 30cb2d41-62df-44db-9faf-d6638438e71c |                                                |
| 901b564b-5250-4215-bcad-2630b7701a85 |                                                |
| c157a2bb-0a42-4e2a-8354-ec0560d9e28b |                                                |
| c5ab2b09-b8cb-4381-83d4-a14a7207fdeb | {"port_filter": true, "ovs_hybrid_plug": true} |
| c8e328fd-0279-46ff-ba45-177b95b97103 |                                                |
| e14dbfd5-670e-405f-aaec-3796d1df1c34 | {"port_filter": true, "ovs_hybrid_plug": true} |
+--------------------------------------+------------------------------------------------+

이 포트는 기존 havana에서 생성된 인스턴스에 연결된 포트죠..

자 그럼 이 값을 똑같이 바꾸면 어떻게 될까요..

mysql> update ml2_port_bindings 
       set vif_details = '{"port_filter": true, "ovs_hybrid_plug": true}';

녜.. 예상하는데로.. vif가 hybrid 형태로 잘 연결됩니다. ^^;

이전에는 nova reboot --hard 하면 인스턴스의 네트워크가 안되던 것이.. 이제는 잘 됩니다. ^^;


-Wunused-command-line-argument-hard-error-in-future 오류

OSX에서 brew, pip, gem 등으로 패키지 설치할 때 위와 같은 컴파일 오류가 나는 경우가 있다. 이건 Xcode가 업데이트 되면서 오류를 만들어 내는 것으로 간단히 해당 옵션을 무시하면 된다.

$ export ARCHFLAGS="-Wno-error=unused-command-line-argument-hard-error-in-future"
$ pip install foobar

sudo도 실행할 경우는 -E 옵션을 준다.


random password generator

간단하게 랜덤 암호 생성기...

OSX인 경우는 중간에 "LC_CTYPE=C"이 필요함...


nova-scheduler: 무조건 적인 평등은 좋지 않다.

어느 순간 알림이 옵니다. m1.large 인스턴스를 #개 만들 수 있는 여유밖에 없습니다. 지속적으로 인스턴스를 만들다 보니 컴퓨팅 리소스가 부족해진 것이지요.. 우선 급하게 nova-compute용 장비 집어넣고 가만히 상황을 살펴 보자니, 상황이 조금 이상합니다.

m1.large의 인스턴스를 만들 메모리가 있는 하드웨어는 없지만, 전체 여유 메모리를 보면 충분히 m1.large를 수용할 만큼 남아있습니다.

아래와 같은 상황을 봅시다.

이 상황에서 메모리가 3G인 인스턴스 만든다면 Host D에 인스턴스를 만들 수 있습니다. 하지만 1G 인스턴스를 먼저 만들면 Host D에 인스턴스가 생성되어 아래처럼 됩니다.

다시 메모리 3G 인스턴스를 만든다면 3G 메모리가 여유있는 컴퓨팅 노드가 없기 때문에 인스턴스를 만들 수 없습니다. 하지만 메모리의 총량은 1+2+1+2=6G로 충분히 3G짜리 인스턴스를 2개 만들 수 있는데도 말입니다.

이렇게 되는 이유는 nova-scheduler에서 인스턴스가 만들어질 호스트를 선택하는 scheduling을 이해하면 간단한 산수로 조정할 수 있습니다.

filter scheduler & weigher

nova developer documentation의 아래 그림을 보면 쉽게 이해가 가능합니다.

nova-scheduler는 컴퓨트 노드 중에서 생성하려는 인스턴스를 위치시킬 호스트를 선택합니다. 대략 과정을 보면..

첫 번째로 nova.conf의 scheduler_default_filters 설정된 필터로 위치시키면 안되는 호스트를 제외합니다. RamFilter는 메모리가 부족한 것을 제외.. ComputeFilter는 vCPU가 부족한 호스트를 제외합니다.

두 번째로, 선택된 호스트 중에서 scheduler_weight_classes에 지정된 가중치를 준 후, 그 중에서 가장 높은 점수를 가진 호스트를 선택합니다.  기본값은 nova.scheduler.weights.all_weigher로 모든 weigher를 적용합니다. 하지만 weigher는 RAMWeigher만 존재하고, 즉 메모리만 가중치를 주게 되어있습니다. 즉 최종적으로는 아래처럼 가중치를 계산합니다.

weight = 1.0 x host.free_ram_mb

즉.. 인스턴스는 가장 메모리가 여유가 많은 호스트에 위치합니다. 이게 평균적으로 합리적인 것 같지만, 처음 이슈 제기처럼 총 메모리는 여유 있어도, 메모리가 많이 필요한 인스턴스를 만들 수 없습니다. ^^;

weigher를 조절

그럼 위 문제를 해결하기 위해서 1G의 작은 인스턴스는 메모리가 많이 할당된 것으로 보내는 방법으로 가면 어떨까요? 간단히 weighting을 메모리 역순으로 한다면?

이 것도 문제가 발생하죠. 한 호스트에 인스턴스가 만들어지면, 해당 호스트는 메모리가 가장 작을 것이므로, 다음 인스턴스도 그 호스트에 만들어집니다. 결국 한 호스트의 메모리가 다 차면, 다음 호스트에 만드는 현상이 발생합니다. 문서에서는 spread와 stack으로 표현하고 있습니다.

결국 이 것도 해결 방법이 아닙니다. 따라서 아래의 결론에 다다릅니다.

  • 메모리가 작게 필요한 인스턴스는 메모리가 작게 남은 호스트에 위치한다.
  • 메모리가 크게 필요한 인스턴스는 전과 같게 메모리가 큰 호스트에 위치한다.

즉, 아래 그림처럼 1G 인스턴스를 Host A에 만들어서, Host B 또는 Host D에 만들어져, 3G 인스턴스를 만들 여유 메모리를 소모하지 않고, 다음에 Host B, D를 만들 수 있게 합니다.

RAMStackWeigher

이 것을 weigher로 만들면 아래처럼 몇 줄 안되는 weigher가 됩니다. 코드는 머 대충 돌아갑니다. ^^;

class RAMStackWeigher(weights.BaseHostWeigher):
    def _weight_multiplier(self):
        return 1.0

    def _weigh_object(self, host_state, weight_properties):
        instance_type = weight_properties['instance_type']
        instance_memory_mb = instance_type['memory_mb']
        free_ram_mb = host_state.free_ram_mb

        if instance_memory_mb > CONF.ram_weight_stack_min:
            return free_ram_mb
        else:
            if free_ram_mb <= CONF.ram_weight_stack_host_free_ram:
                return - free_ram_mb
            else:
                return free_ram_mb - CONF.ram_weight_stack_host_free_ram - (1024 * 256)

참고)

  • weigher는 모든 호스트에 대해서 _weigh_object를 호출하고 _weight_multiplier 순으로 호출됩니다.

scheduler_weight_classes는 ListOpt 이므로 다른 weight를 주고 싶다면, 다른 weigher를 만들어서 옵션에 등록하면 됩니다.

결론...

기본 nova-scheduler는 평등을 지향합니다. 평등은 좋은 것 처럼 보이지만, 자원을 효율적으로 사용하지는 못하는 문제가 있습니다. 효율화를 위해서는 약간(?)의 차별은 필요합니다.


libvirt LIEFCYCLE_EVENT

nova-compute 로그 파일에 life cycle event가 숫자로 나오는데.. 이거 찾아보기 귀찮아서

EVENT_LIFECYCLE_STARTED = 0
EVENT_LIFECYCLE_STOPPED = 1
EVENT_LIFECYCLE_PAUSED = 2
EVENT_LIFECYCLE_RESUMED = 3

openvswitch bridge에 vlan port 추가

OpenVSwitch는 기본으로 trunk 모드로 동작한다. 이 경우 특정 vlan에 대한 interface를 추가하는 작업은.. 아래처럼.

$ ovs-vsctl add-port <bridge> <port> tag=<vlan-id> \
  -- set Interface <port> type=internal

ex

$ ovs-vsctl add-port br0 vlan1000 tag=1000 \
  -- set Interface vlan1000 type=internal

flavor에 따라서 생성되는 인스턴스가 생성되는 존 설정하기

가끔 이런 경우가 있습니다.

이 flavor로 만드는 인스턴스는 성능이 좋아야 합니다. 그러니 이 flavor로 만드는 인스턴스는 성능이 좋은 물리 호스트에 만들어 주세요.

SSD를 사용하는 호스트, RAM이 특별하게 많이 필요한 인스턴스, Disk I/O가 많이 필요한 인스턴스 등등 이런 요청은 다양합니다. 그런 경우는 이전에서 만든 host aggregate와 flavor를 연결하여 특정 flavor는 특정 존에 생성되도록 강제 할 수 있습니다.

인스턴스를 어떤 compute node에 위치시킬 것인가는 nova-scheduler에 의해서 결정되므로, nova-scheduler에서 flavor와 host aggregate를 동시에 고려하는 Filter가 있으면 되겠죠. 녜.. 당연히 있고, 그 것이 AggregateInstanceExtraSpecsFilter 입니다.

당연히 이 필터를 nova scheduler 필터에 추가하고..

/etc/nova.conf:

scheduler_default_filters=AggregateInstanceExtraSpecsFilter,\
                          AvailabilityZoneFilter,RamFilter,ComputeFilter

특정 zone에 인스턴스를 생성할 flavor에 아래처럼 flavor의 extra-specs에 넣습니다.

# nova flavor-show 1
+----------------------------+----------------------------+
| Property                   | Value                      |
+----------------------------+----------------------------+
| name                       | m1.tiny                    |
| ram                        | 512                        |
| OS-FLV-DISABLED:disabled   | False                      |
| vcpus                      | 1                          |
| extra_specs                | {u'locate_zone1': u'true'} |
| swap                       |                            |
| os-flavor-access:is_public | True                       |
| rxtx_factor                | 1.0                        |
| OS-FLV-EXT-DATA:ephemeral  | 0                          |
| disk                       | 0                          |
| id                         | 1                          |
+----------------------------+----------------------------+

이제 host aggregate에서 해당 extra-specs에 locate_zone1=true가 설정된 인스턴스를 만들 수 있게 meta-data로 설정하면 됩니다.

# nova aggregate-set-metadata 1 locate_zone1=true
Aggregate 1 has been successfully updated.
+----+------+-------------------+--------------------------------+------------------------------------------------------------+
| Id | Name | Availability Zone | Hosts                          | Metadata                                                   |
+----+------+-------------------+--------------------------------+------------------------------------------------------------+
| 1  | agg1 | zone1             | [u'compute000', u'compute001'] | {u'locate_zone1': u'true', u'availability_zone': u'zone1'} |
+----+------+-------------------+--------------------------------+------------------------------------------------------------+

이제 flavor 1로 인스턴스를 만들면 zone1에 생성되는 것을 볼 수 있습니다.

# nova list --all-tenants --fields flavor,host
+--------------------------------------+--------+------------+
| ID                                   | Flavor | Host       |
+--------------------------------------+--------+------------+
| 0a3e3ff7-fa2e-47c5-b820-25d3c6f005aa | 1      | compute001 |
| 2211556d-abef-48d1-91fa-3fd2bc4286d5 | 1      | compute000 |
| 70535b26-a284-4ad3-8f14-e09bde385b97 | 1      | compute000 |
| ba8bf1ce-acd8-4b25-8a08-56ff71283c32 | 1      | compute001 |
+--------------------------------------+--------+------------+

참고 링크


host-aggregation을 availability-zone으로 사용하기

Host aggregation은 Availability zone 처럼 사용할 수 있습니다.

기본 설치 상태에서 보면 아래처럼 nova zone만 보입니다.

# nova availability-zone-list
+-----------------------+----------------------------------------+
| Name                  | Status                                 |
+-----------------------+----------------------------------------+
| internal              | available                              |
| |- control0           |                                        |
| | |- nova-conductor   | enabled 🙂 2013-12-11T08:36:33.000000 |
| | |- nova-consoleauth | enabled 🙂 2013-12-11T08:36:36.000000 |
| | |- nova-cert        | enabled 🙂 2013-12-11T08:36:36.000000 |
| | |- nova-scheduler   | enabled 🙂 2013-12-11T08:36:31.000000 |
| nova                  | available                              |
| |- compute003         |                                        |
| | |- nova-compute     | enabled 🙂 2013-12-11T08:36:31.000000 |
| |- compute002         |                                        |
| | |- nova-compute     | enabled 🙂 2013-12-11T08:36:31.000000 |
| |- compute001         |                                        |
| | |- nova-compute     | enabled 🙂 2013-12-11T08:36:31.000000 |
| |- compute000         |                                        |
| | |- nova-compute     | enabled 🙂 2013-12-11T08:36:31.000000 |
+-----------------------+----------------------------------------+

여기서 host-aggregate를 2개 만들고 각각에 2개씩 compute node를 넣어봅니다.

# nova aggregate-create agg1
# nova aggregate-create agg2
# nova aggregate-list
+----+------+-------------------+
| Id | Name | Availability Zone |
+----+------+-------------------+
| 1  | agg1 | None              |
| 2  | agg2 | None              |
+----+------+-------------------+
# nova aggregate-add-host 1 compute000
Aggregate 1 has been successfully updated.
+----+------+-------------------+-----------------+----------+
| Id | Name | Availability Zone | Hosts           | Metadata |
+----+------+-------------------+-----------------+----------+
| 1  | agg1 | None              | [u'compute000'] | {}       |
+----+------+-------------------+-----------------+----------+
# nova aggregate-add-host 1 compute001
Aggregate 1 has been successfully updated.
+----+------+-------------------+--------------------------------+----------+
| Id | Name | Availability Zone | Hosts                          | Metadata |
+----+------+-------------------+--------------------------------+----------+
| 1  | agg1 | None              | [u'compute000', u'compute001'] | {}       |
+----+------+-------------------+--------------------------------+----------+
# nova aggregate-add-host 2 compute002
Aggregate 2 has been successfully updated.
+----+------+-------------------+-----------------+----------+
| Id | Name | Availability Zone | Hosts           | Metadata |
+----+------+-------------------+-----------------+----------+
| 2  | agg2 | None              | [u'compute002'] | {}       |
+----+------+-------------------+-----------------+----------+
# nova aggregate-add-host 2 compute003
Aggregate 2 has been successfully updated.
+----+------+-------------------+--------------------------------+----------+
| Id | Name | Availability Zone | Hosts                          | Metadata |
+----+------+-------------------+--------------------------------+----------+
| 2  | agg2 | None              | [u'compute002', u'compute003'] | {}       |
+----+------+-------------------+--------------------------------+----------+

여기서 다시 nova availability-zone-list 하면 아무런 변화기 없습니다. nova aggregate-list 결과에 보면 "Availability Zone"이라는 항목이 있습니다. 녜.. host aggregate에 zone 설정이 없어서 그런 것이죠..

다시 host aggregate에 availability zone을 설정해보죠.

# nova aggregate-update 1 agg1 zone1
Aggregate 1 has been successfully updated.
+----+------+-------------------+--------------------------------+----------------------------------+
| Id | Name | Availability Zone | Hosts                          | Metadata                         |
+----+------+-------------------+--------------------------------+----------------------------------+
| 1  | agg1 | zone1             | [u'compute000', u'compute001'] | {u'availability_zone': u'zone1'} |
+----+------+-------------------+--------------------------------+----------------------------------+
# nova aggregate-update 2 agg1 zone2
Aggregate 2 has been successfully updated.
+----+------+-------------------+--------------------------------+----------------------------------+
| Id | Name | Availability Zone | Hosts                          | Metadata                         |
+----+------+-------------------+--------------------------------+----------------------------------+
| 2  | agg1 | zone2             | [u'compute002', u'compute003'] | {u'availability_zone': u'zone2'} |
+----+------+-------------------+--------------------------------+----------------------------------+

이제 다시 availability zone을 보면

# nova availability-zone-list
+-----------------------+----------------------------------------+
| Name                  | Status                                 |
+-----------------------+----------------------------------------+
| internal              | available                              |
| |- control0           |                                        |
| | |- nova-conductor   | enabled 🙂 2013-12-11T09:01:15.000000 |
| | |- nova-consoleauth | enabled 🙂 2013-12-11T09:01:09.000000 |
| | |- nova-cert        | enabled 🙂 2013-12-11T09:01:09.000000 |
| | |- nova-scheduler   | enabled 🙂 2013-12-11T09:01:14.000000 |
| zone1                 | available                              |
| |- compute001         |                                        |
| | |- nova-compute     | enabled 🙂 2013-12-11T09:01:15.000000 |
| |- compute000         |                                        |
| | |- nova-compute     | enabled 🙂 2013-12-11T09:01:15.000000 |
| zone2                 | available                              |
| |- compute003         |                                        |
| | |- nova-compute     | enabled 🙂 2013-12-11T09:01:15.000000 |
| |- compute002         |                                        |
| | |- nova-compute     | enabled 🙂 2013-12-11T09:01:15.000000 |
+-----------------------+----------------------------------------+

녜.. 그렇습니다. host aggregate를 availability zone으로 사용할 수 있습니다.

그리고 이렇게 만들어진 존을 지정하여 인스턴스를 만드는 것은 아래처럼 할 수 있습니다.

# nova boot --flavor=<flavor> --nic net-id=<net-id> \
    --image=<image-id> --key_name=<keyname> \
    --availability-zone zone1:compute000 <instance-name>

admin 권한으로는 compute node까지 지정이 가능하고, admin이 아닌 경우는 zone 까지만 지정 가능합니다.

참고링크: http://russellbryantnet.wordpress.com/2013/05/21/availability-zones-and-host-aggregates-in-openstack-compute-nova/


quantum lbaas

create pool

$ NET_ID=e5768970-4e96-467d-9be1-e0e0b789f025
$ quantum lb-pool-create --name test --lb-method \
  ROUND_ROBIN --protocol TCP --subnet-id=$NET_ID

quantum lb-pool-list
+--------------------------------------+------+-------------+----------+----------------+----------------+
| id                                   | name | lb_method   | protocol | admin_state_up | status         |
+--------------------------------------+------+-------------+----------+----------------+----------------+
| 044208a8-9e29-4fee-b41b-9b58567f3874 | test | ROUND_ROBIN | TCP      | True           | PENDING_CREATE |
+--------------------------------------+------+-------------+----------+----------------+----------------+

create vip

$ quantum lb-vip-create --name test-vip1 --protocol-port 80 --protocol TCP --subnet-id=$NET_ID test
$ quantum lb-vip-list
+--------------------------------------+-----------+-------------+----------+----------------+--------+
| id                                   | name      | address     | protocol | admin_state_up | status |
+--------------------------------------+-----------+-------------+----------+----------------+--------+
| 515fa2c5-a135-4b59-b247-803e844383f1 | test-vip1 | 10.10.100.5 | TCP      | True           | ACTIVE |
+--------------------------------------+-----------+-------------+----------+----------------+--------+

여기서 pool도 status가 ACTIVE로 바뀌고.. lbaas가 동작하는 노드에 qlbaas- 로 ip namespace가 생긴다.

생성된 vip에... 다른 port로 만들면 오류가 발생

$ quantum lb-vip-create --name test-vip-https --protocol-port 443 --protocol TCP --subnet-id=$NET_ID test --address=10.10.100.5
Another Vip already exists for pool 044208a8-9e29-4fee-b41b-9b58567f3874

kvm: linux bridge 대신 openvswitch 사용하기

/etc/default/openvswitch-switch

BRCOMPAT=yes

bridge 호환 모듈, 데몬

$ apt-get install openvswitch-brcompat

  • Copyright © 1996-2010 Your wish is my command. All rights reserved.
    iDream theme by Templates Next | Powered by WordPress