Tuesday, September 23, 2014

Docker命令速查

基本语法

docker [OPTIONS] COMMAND [arg...]

选项

-D=true|false
    使用debug模式。默认为false。

-H, --host=[unix:///var/run/docker.sock]: tcp://[host:port]来绑定或者unix://[/path/to/socket]来使用。
    在daemon模式下绑定的socket,通过一个或多个tcp://host:port, unix:///path/to/socket, fd://* or fd://socketfd来指定。

--api-enable-cors=true|false
    在远端API中启用CORS头。缺省为false。

-b=""
    将容器挂载到一个已存在的网桥上。指定为'none'时则禁用容器的网络。

--bip=""
    让动态创建的docker0采用给定的CIDR地址; 与-b选项互斥。

-d=true|false
    使用daemon模式。缺省为false。

--dns=""
    让Docker使用给定的DNS服务器。

-g=""
    指定Docker运行时的root路径。缺省为/var/lib/docker。

--icc=true|false
    启用容器间通信。默认为true。

--ip=""
    绑定端口时候的默认IP地址。缺省为0.0.0.0。

--iptables=true|false
    禁止Docker添加iptables规则。缺省为true。

--mtu=VALUE
    指定容器网络的mtu。缺省为1500。

-p=""
    指定daemon的PID文件路径。缺省为/var/run/docker.pid。

-s=""
    强制Docker运行时使用给定的存储驱动。

-v=true|false
    输出版本信息并退出。缺省值为false。

--selinux-enabled=true|false
    启用SELinux支持。缺省值为false。SELinux目前不支持BTRFS存储驱动。

命令

docker的命令可以采用docker-CMD或者docker CMD的方式执行。两者一致。
docker-attach(1)
    依附到一个正在运行的容器中。

docker-build(1)
    从一个Dockerfile创建一个image

docker-commit(1)
    从一个容器的修改中创建一个新的image

docker-cp(1)
    从容器中复制文件到宿主系统中

docker-diff(1)
    检查一个容器文件系统的修改

docker-events(1)
    从服务端获取实时的事件

docker-export(1)
    导出容器内容为一个tar包

docker-history(1)
    显示一个image的历史

docker-images(1)
    列出存在的image

docker-import(1)
    导入一个tar包来创建一个image

docker-info(1)
    显示一些相关的系统信息

docker-inspect(1)
    显示一个容器的底层具体信息。

docker-kill(1)
    关闭一个运行中的容器 (包括进程和所有资源)

docker-load(1)
    从一个tar包中加载一个image

docker-login(1)
    注册或登录到一个Docker的仓库服务器

docker-logout(1)
    从Docker的仓库服务器登出

docker-logs(1)
    获取容器的log信息

docker-pause(1)
    暂停一个容器中的所有进程

docker-port(1)
    查找一个nat到一个私有网口的公共口

docker-ps(1)
    列出容器

docker-pull(1)
    从一个Docker的注册服务器下拉一个image或仓库

docker-push(1)
    将一个image或者仓库推送到一个Docker的注册服务器

docker-restart(1)
    重启一个运行中的容器

docker-rm(1)
    删除给定的若干个容器

docker-rmi(1)
    删除给定的若干个image

docker-run(1)
    创建一个新容器,并在其中运行给定命令

docker-save(1)
    保存一个image为tar包文件

docker-search(1)
    在Docker index中搜索一个image

docker-start(1)
    启动一个容器

docker-stop(1)
    终止一个运行中的容器

docker-tag(1)
    为一个image打标签

docker-top(1)
    查看一个容器中的正在运行的进程信息

docker-unpause(1)
    将一个容器内所有的进程从暂停状态中恢复

docker-version(1)
    输出Docker的版本信息

docker-wait(1)
    阻塞直到一个容器终止,然后输出它的退出符

网卡虚拟化技术:VMDq和SR-IOV

本文来谈谈虚机跟服务器物理网卡的交互问题。
通常情况下,一个服务器上跑几十个虚机,对计算和网络的需求是很惊人的。前者促生了当下的多核技术发展,后者则不能简单的用多网卡来实现。
试想,每个虚机如果都需要10G的交换能力,服务器要配置几十块物理网卡,且不说主板是否支持这么多的接口,光成本上就难以接受。
另外,如果给vm分配的接口都是软件交换机的虚拟接口,维护这些接口和转发本身就要消耗大量的服务器计算资源。
因此,业界推出了VMDq和SR-IOV技术来提升虚机的网络性能。


VMDq
VMM在服务器的物理网卡中为每个虚机分配一个独立的队列,这样虚机出来的流量可以直接经过软件交换机发送到指定队列上,软件交换机无需进行排序和路由操作。
但是,VMM和虚拟交换机仍然需要将网络流量在VMDq和虚机之间进行复制。


SR-IOV
对于SR-IOV来说,则更加彻底,它通过创建不同虚拟功能(VF)的方式,呈现给虚拟机的就是独立的网卡,因此,虚拟机直接跟网卡通信,不需要经过软件交换机。
VF和VM之间通过DMA进行高速数据传输。
SR-IOV的性能是最好的,但是需要一系列的支持,包括网卡、主板、VMM等。




[1] http://windowsitpro.com/virtualization/q-are-vmdq-and-sr-iov-performing-same-function

虚拟机网络接入技术

随着云计算技术的发展,跟传统的服务器上直接跑应用相比,服务器上运行虚机,虚机里面跑应用的场景已经越来越普遍。
这种情况下,网络往往成为最关键的性能瓶颈,特别是不同虚机之间的高速网络流量如何进行有效的交换。


要解决大流量交换的问题,基本上有两套简单思路,一个是软交换,即放在服务器里面,让软件来实现,典型的代表有各种虚拟交换的解决方案,例如OpenvSwitch。
另外一个是流量对服务器透明,全部扔到服务器外面的物理交换机做,主要是现在讨论的IEEE Edge Virtual Bridging (EVB)标准,包括802.1qbg and 802.1qbh。


软交换比较容易实现。
VMM为每个虚机创建一个虚拟网卡,对应到软件交换机的一个端口。服务器的物理网卡也接到软件交换机的一个接口上。所有的交换由软件交换机完成。
这种方案的优点是虚机之间转发性能非常好,并且在软件交换机容易实现各种控制功能。但问题就是对服务器os的cpu资源消耗多,并且对外交换时容易出现性能瓶颈。


EVB标准则试图将虚机发出的所有流量都导入到外面的交换机上进行决策。优势是可以利用外面硬件交换机的性能和复杂控制特性,缺点是一进一出带宽效率低,需要改动服务器上的驱动支持。


参考:
[1] http://www.cisco.com/c/en/us/products/collateral/switches/nexus-1000v-switch-vmware-vsphere/whitepaper_c11-620065.html
[2] http://wikibon.org/wiki/v/Edge_Virtual_Bridging

OpenStack Heat template中类型定义的一个坑

最新的Heat template目前支持string | number | json | comma_delimited_list | boolean等类型。


采用默认的hot格式,yaml文件格式。


定义一个string类型的属性,内容为true或false的时候,会报错。


查看heat engine的log会发现这个属性值默认被转为了boolean类型。


这是为何呢?
查看heat的代码,heat是调用的yaml库来直接load文件的,而对于yaml语言来说,如下的字符串都会被解析为bool类型。


y, Y, yes, Yes, YES
n, N, no, No, NO
true, True, TRUE
false, False, FALSE
on, On, ON
off, Off, OFF

OpenStack Heat中添加新资源示例

在OpenStack Heat中,资源都是通过继承resource类来实现的。
heat-engine在启动的时候会扫描预设目录来加载各种资源插件。
这种模式提供了极大的灵活性,用户可以很容易的添加自己的资源类型和指定响应行动。
下面给出了定义新资源的一个简单示例,资源被创建后在log中给出属性信息。

#This file should be put into the plugin_dirs of OpenStack HEAT.
#plugin_dirs=/usr/lib64/heat,/usr/lib/heat
#After that, restart the heat engine to enable it.
# service openstack-heat-engine restart

#Provide the OS::Neutron::ServicePolicy resource.

from heat.engine import attributes
from heat.engine import properties
from heat.engine import resource
from heat.openstack.common import log as logging


LOG = logging.getLogger(__name__)


classServicePolicy(resource.Resource):


    PROPERTIES = (
        NAME, SRC, DST,
    ) = (
        'name', 'src', 'dst',
    )


    ATTRIBUTES = (
        NAME,
    )


    properties_schema = {
        NAME: properties.Schema(
            properties.Schema.STRING,
            _('Name of the service policy.')
        ),
        SRC: properties.Schema(
            properties.Schema.STRING,
            _('Source of the service policy.')
        ),
        DST: properties.Schema(
            properties.Schema.STRING,
            _('Destination of the service policy.')
        ),
    }
    attributes_schema = {
        NAME: attributes.Schema(
            _('Name of the service policy.')
        ),
    }


    def handle_create(self):
        LOG.info(self.properties.get(self.NAME))
        LOG.info(self.properties.get(self.SRC))
        LOG.info(self.properties.get(self.DST))


    def handle_delete(self):
        pass


    def _resolve_attribute(self, name):
        if name == self.NAME:
            return self.properties.get(self.NAME)


def resource_mapping():
    return {
        'OS::Neutron::ServicePolicy':ServicePolicy,
    }