Your wish is my command

It’s a long journey

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

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

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/

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 |
+--------------------------------------+--------+------------+

참고 링크

Nova/keystone… Bash Completion

nova

$ wget -O /etc/bash_completion.d/nova https://raw.github.com/openstack/python-novaclient/master/tools/nova.bash_completion

keystone

$ wget -O /etc/bash_completion.d/keysotne https://raw.github.com/openstack/python-keystoneclient/master/tools/keystone.bash_completion

Haproxy: Https Redirect, Ip Block 등등..

haproxy는 loadbalancing 기능 이외에도 다양한 기능이 많습니다.

/admin을 내부 아이피만 허용하는 경우는 아래처럼 할 수 있습니다.

acl is-internal-net src 172.16.0.0/12 192.168.0.0/16 10.0.0.0/8
acl is-admin url_beg /admin
block if !is-internal-net is-admin

http를 https로 redirect하는 것도 haproxy에서 사용할 수 있죠.

redirect scheme https if !{ ssl_fc }

haproxy가 ssl offload 기능을 제공하기에 backend에는 http만 사용합니다. 그리고 밑의 application에서 https에서 온 request라는 것을 확인하기 위해서 x-forwarded-protocol을 붙여줍니다.

bind 0.0.0.0:443 ssl crt <your-certificate-file>
acl is-ssl dst_port 443
reqadd x-forwarded-protocol:\ https if is-ssl

종합하면 아래처럼 되겠습니다.

listen webapp
bind 0.0.0.0:443 ssl crt <your-certificate-file>
server server1 10.10.10.10:80 check
server server1 10.10.10.11:80 check
acl is-internal-net src 172.16.0.0/12 192.168.0.0/16 10.0.0.0/8
acl is-admin url_beg /admin
acl is-ssl dst_port 443
block if !is-internal-net is-admin
redirect scheme https if !{ ssl_fc }
reqadd x-forwarded-protocol:\ https if is-ssl

Veth가 어떤 디바이스에 연결되어있는지 찾아보기..

Quantum으로 네트워크를 구성하다보면(또는 XLC…) veth를 통해서 다른 network namespace에 interface가 peer로 역이는 것을 볼 수 있습니다.

Network Namespace는 Introducing Linux Network Namespaces 글을 참조하시면 좋습니다. 간단히 말에서 device, routing, iptables, socket 등을 포함하여 linux network stack이 완전히 격리되는 시스템입니다. namespace를 만들어 network stack을 격리시키면 외부랑 완전히 차단이 되기 때문에 root namespace의 interface와 veth로 pair를 맺어 이 interface로 통신합니다.

veth는 참고할 만한 문서를 딱히 못찾았는데요.. interface link의 클론이라고 생각하시면 됩니다. 한쪽에 들어간 패킷은 다른 한쪽으로 흐릅니다. 그리고 당연히 각각이 interface이기 때문에 mac, ipaddress가 다를 수 있습니다. 어떻게보면 bridge와도 비슷합니다.

근데 문제는 veth로 만드는 것은 쉽게 알 수 있는데, 해당 인터페이스가 어떤 인터페이스랑 peer인지 알아내는 방법이 쉽지 않습니다. iproute로는 말이지요.

아래는 quantum으로 구성한 dhcp namespace의 interface 입니다.

# ip netns exec qdhcp-fabc7ead-6132-4920-af57-2ad5e199e1c1 ip a
59: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
68: ns-39d60faa-aa: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether fa:16:3e:98:e6:f3 brd ff:ff:ff:ff:ff:ff
    inet 10.10.100.2/24 brd 10.10.100.255 scope global ns-39d60faa-aa
    inet 169.254.169.254/16 brd 169.254.255.255 scope global ns-39d60faa-aa
    inet6 fe80::f816:3eff:fe98:e6f3/64 scope link
       valid_lft forever preferred_lft forever
# ip netns exec qdhcp-fabc7ead-6132-4920-af57-2ad5e199e1c1 route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.10.100.1     0.0.0.0         UG    0      0        0 ns-39d60faa-aa
10.10.100.0     0.0.0.0         255.255.255.0   U     0      0        0 ns-39d60faa-aa
169.254.0.0     0.0.0.0         255.255.0.0     U     0      0        0 ns-39d60faa-aa

여기서 routing table을 보면 ns-39d60faa-aa 인터페이스를 통해서 외부로 나가는 것으로 보이는데, namespace 이므로 외부와 직접 연결할 수 없습니다. 당연히 ns-39d60faa-aa는 root namespace의 interface와 veth peer를 이루고 있으며, peer interface를 통해서 외부와 통신합니다.(그 peer는 bridge를 통해서 eth#으로 나가겠지요..)

그럼 여기서 본론인 어떤 interface와 peer를 이루고 있는지 알아보려고 열심히 ifconfig 또는 ip link 명령을 뒤져봐야 안나됩니다. mac도 다르고, peer 정보도 안나오고…

찾는 방법은 조금 복잡하기도 한데… ethtool을 통해서 찾을 수 있습니다.

# ip netns exec qdhcp-fabc7ead-6132-4920-af57-2ad5e199e1c1 \
  ethtool -S ns-39d60faa-aa
NIC statistics:
     peer_ifindex: 69

결과에서 예상하다시피 interface index가 69번인 interface와 peer를 이루고 있습니다. 그럼 아래처럼 찾을 수 있겠습니다.

# ip link ls | grep ^69
69: tap39d60faa-aa: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
# ip link show tap39d60faa-aa
69: tap39d60faa-aa: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 62:41:1f:e2:b2:9d brd ff:ff:ff:ff:ff:ff
# ethtool -S tap39d60faa-aa
NIC statistics:

마찬가지로 tap39d60faa-aa interface는 namespace에 있는 68번 interface와 veth peer로 연결되어 있습니다.

지금은 필요없을 지 몰라도 OpenStack 하다보면 언젠가는 마주칠지 모르는 녀석이니 참고하세용..

ps. iproute 사용법은 너무 불친절합니다.

Fixed Ip에서 Vip 찾아내기…

Quantum으로 인스턴스의 fixed ip를 기준으로 해당 인스턴스의 load balancer에 연결된 vip 얻어오기

  • overlapping ip 환경에서는 안됨… network을 구분하지 못해서…

Python 한 줄로 웹서버 만들기..

$ python -m SimpleHTTPServer
Serving HTTP on 0.0.0.0 port 8000 ...

딱.. 한줄이지만.. 정작 필요할 때는 기억이 안나서.