分类 Cloud 下的文章

kubernetes指定pod调度到固定node节点上

默认情况下,新建pod会有master的调度器选择一个合适的node去创建
在某些情况下,如果我们想要让pod固定到某个node上面去,可以有如下2种方式

指定nodename

spec:
  nodeName: n01     #指定node节点

通过nodeselect选择指定的lable

首先为node设置标签
kubectl label nodes n01 nodename=01
然后在deployment中指定nodeselector即可

nodeSelector:
  nodename: '01'

Kubernetes网络插件Flannel的3种工作模式(转)

前言

跨主机通信的一个解决方案是Flannel,由CoreOS推出,支持3种实现:UDP、VXLAN、host-gw
udp模式:使用设备flannel.0进行封包解包,不是内核原生支持,上下文切换较大,性能非常差
vxlan模式:使用flannel.1进行封包解包,内核原生支持,性能较强
host-gw模式:无需flannel.1这样的中间设备,直接宿主机当作子网的下一跳地址,性能最强
host-gw的性能损失大约在10%左右,而其他所有基于VXLAN“隧道”机制 的网络方案,性能损失在20%~30%左右

一、UDP模式(性能差)

核心就是通过TUN设备flannel0实现(TUN设备是工作在三层的虚拟网络设备,功能是:在操作系统内核和用户应用程序之间传递IP包)
相比两台宿主机直接通信,多出了flanneld的处理过程,这个过程,使用了flannel0这个TUN设备,仅在发出IP包的过程中就要经过了三次用户态到内核态的数据拷贝(linux的上下文切换代价比较大),所以性能非常差
原理如下:

1-1

以flanel0为例,操作系统将一个IP包发给flanel0,flanel0把IP包发给创建这个设备的应用程序:flanel进程(内核态->用户态)
相反,flanel进程向flanel0发送一个IP包,IP包会出现在宿主机的网络栈中,然后根据宿主机的路由表进行下一步处理(用户态->内核态)
当IP包从容器经过docker0出现在宿主机,又根据路由表进入flanel0设备后,宿主机上的flanneld进程就会收到这个IP包

flannel管理的容器网络里,一台宿主机上的所有容器,都属于该宿主机被分配的“子网”,子网与宿主机的对应关系,存在Etcd中(例如Node1的子网是100.96.1.0/24,container-1的IP地址是100.96.1.2)
当flanneld进程处理flannel0传入的IP包时,就可以根据目的IP地址(如100.96.2.3),匹配到对应的子网(比如100.96.2.0/24),从Etcd中找到这个子网对应的宿主机的IP地址(10.168.0.3)
然后flanneld在收到container-1给container-2的包后,把这个包直接封装在UDP包里,发送给Node2(UDP包的源地址,就是Node1,目的地址是Node2)
每台宿主机的flanneld都监听着8285端口,所以flanneld只要把UDP发给Node2的8285端口就行了。然后Node2的flanneld再把IP包发送给它所管理的TUN设备flannel0,flannel0设备再发给docker0

二、VXLAN模式(性能较好)

什么是VXLAN?
VXLAN,即Virtual Extensible LAN(虚拟可扩展局域网),是Linux本身支持的一网种网络虚拟化技术。VXLAN可以完全在内核态实现封装和解封装工作,从而通过“隧道”机制,构建出覆盖网络(Overlay Network)

VXLAN的设计思想是:
在现有的三层网络之上,“覆盖”一层虚拟的、由内核VXLAN模块负责维护的二层网络,使得连接在这个VXLAN二层网络上的“主机”(虚拟机或容器都可以),可以像在同一个局域网(LAN)里那样自由通信。
为了能够在二nfcu网络上打通“隧道”,VXLAN会在宿主机上设置一个特殊的网络设备作为“隧道”的两端,叫VTEP:VXLAN Tunnel End Point(虚拟隧道端点)
原理如下:

flanel.1设备,就是VXLAN的VTEP,即有IP地址,也有MAC地址
与UPD模式类似,当container-发出请求后,上的地址10.1.16.3的IP包,会先出现在docker网桥,再路由到本机的flannel.1设备进行处理(进站)
为了能够将“原始IP包”封装并发送到正常的主机,VXLAN需要找到隧道的出口:上的宿主机的VTEP设备,这个设备信息,由宿主机的flanneld进程维护

VTEP设备之间通过二层数据桢进行通信
源VTEP设备收到原始IP包后,在上面加上一个目的MAC地址,封装成一个导去数据桢,发送给目的VTEP设备(获取 MAC地址需要通过三层IP地址查询,这是ARP表的功能)

封装过程只是加了一个二层头,不会改变“原始IP包”的内容
这些VTEP设备的MAC地址,对宿主机网络来说没什么实际意义,称为内部数据桢,并不能在宿主机的二层网络传输,Linux内核还需要把它进一步封装成为宿主机的一个普通的数据桢,好让它带着“内部数据桢”通过宿主机的eth0进行传输,Linux会在内部数据桢前面,加上一个我死的VXLAN头,VXLAN头里有一个重要的标志叫VNI,它是VTEP识别某个数据桢是不是应该归自己处理的重要标识。
在Flannel中,VNI的默认值是1,这也是为什么宿主机的VTEP设备都叫flannel.1的原因

一个flannel.1设备只知道另一端flannel.1设备的MAC地址,却不知道对应的宿主机地址是什么。
在linux内核里面,网络设备进行转发的依据,来自FDB的转发数据库,这个flannel.1网桥对应的FDB信息,是由flanneld进程维护的
linux内核再在IP包前面加上二层数据桢头,把Node2的MAC地址填进去。这个MAC地址本身,是Node1的ARP表要学习的,需
Flannel维护,这时候Linux封装的“外部数据桢”的格式如下

然后Node1的flannel.1设备就可以把这个数据桢从eth0发出去,再经过宿主机网络来到Node2的eth0
Node2的内核网络栈会发现这个数据桢有VXLAN Header,并且VNI为1,Linux内核会对它进行拆包,拿到内部数据桢,根据VNI的值,所它交给Node2的flannel.1设备

三、host-gw模式(性能最高)

这是一种纯三层网络的方案,性能最高

5

howt-gw模式的工作原理,就是将每个Flannel子网的下一跳,设置成了该子网对应的宿主机的IP地址,也就是说,宿主机(host)充当了这条容器通信路径的“网关”(Gateway),这正是host-gw的含义
所有的子网和主机的信息,都保存在Etcd中,flanneld只需要watch这些数据的变化 ,实时更新路由表就行了。
核心是IP包在封装成桢的时候,使用路由表的“下一跳”设置上的MAC地址,这样可以经过二层网络到达目的宿主机

【转】Hooking Up Web Apps With Docker

At Substantial, between the tides of client work, we interleave work on internal projects to explore product ideas and experiment with technology.

Recent experimentation by the San Francisco team for Substantial Dashincluded stepping outside our comfort zone for application deployment. We normally use Chef to provision servers and Capistrano to deploy application code to those servers.

Typical challenges

  • How do we build a host server and then install the web application?
  • How do we release a new version?
  • Is a version just application code, or does it include dependencies for the host server too?
  • Is server provisioning and app deployment reproducible?

Docker containers continue to emerge as an answer to these questions. In fact, Docker supports many of the best practices defined in The Twelve-Factor App.

Put your app in a box

Containerizing an application's runtime environment is a well-known software design pattern for modular, secure systems. The pattern occurs over multiple layers:

  • packaging the runtime environment (a "version")
  • containing the file system
  • firewalling the network
  • metering utilization of network and processor

Well-known containers (from vendor-specific to vendor-agnostic) include:

Lightweight virtualization with Docker

Docker containers share the kernel of the host, while virtual machines each have their own kernels sharing the processor. VMs are comparatively slow and expensive because they are so low-level. They duplicate the operating system overhead for every running virtual machine, preventing a single process scheduler from managing everything efficiently.

Today, the Docker daemon easily runs on Linux to host containers. The container images are typically based on a full Linux distribution so that all of the standard tools and libraries are available. Tiny containers may be created using minimal, embeddable OSs such as BusyBox.

Images vs Containers

Every Docker "container" is run from an "image."

The image is a snapshot that can be moved around and reused; docker images lists the images available to run with the Docker daemon.

The container is the live runtimedocker ps lists the containers that are currently running.

The Dockerfile

The most visible part of Docker is the Dockerfile. Create it alongside your application code to construct an image of the application's complete environment. Notice in this example Dockerfile how everything the app needs to operate is built up from stock Ubuntu Linux.

Packaging the code

Many web developers are accustomed to deploying to a long-running server using tools like Capistrano. You push new code, restart the web server, and ta-da, a new version is deployed. But what happens if you need to change a system library, like downgrade a programming language version (e.g. Ruby 2.0.0) or upgrade a dependency (e.g. LibXML or ImageMagick)? Somehow you would have to coordinate infrastructure changes with application changes; as applications grow this can become very messy.

Containers solve this conundrum of server operations by defining all dependencies alongside the application code. Thanks to the build caching, changing application code does not necessarily require rebuilding everything in the container. Notice once again in this example Dockerfile that the application code is added late in the build sequence.

Runtime configuration

Configuration that remains constant across environments (dev, test, and production) can be kept with the application code. We include the standard etc/ config files right in the repo, and those files are added to the container with Dockerfile ADD statements.

Configuration that is unique to each environment or secret is passed as environment variables when the docker run command starts the container. An example run command passing environment variables is:

docker run -e BASE_URL="http://awesomeapp.com" -e SECRET_KEY=meowmeow image_tag_or_hash

Configuration of what command to run inside the container is set using the Dockerfile's CMD and/or ENTRYPOINT. If a container needs to run more than one process, then start a process manager such a supervisorto run and manage all the processes.

Hosting containers

Many container hosting options exist today. The offical Docker docs list compatible OSs and vendors. Docker-specific workflows are supported by its creator dotCloudStackDock, and more emerging companies.

Depending upon who you select to host your containers, they provide varying amounts of automation around Docker image and runtime management.

Our project's deployment testbed is the Digital Ocean Docker application. In this case, all we get is a bare-bones Ubuntu Linux host running the Docker daemon. So how can we upload our images to the host?

For the Substantial Dash project, we opted to use images as files. This is the simplest, private approach to experiment with Docker.

Distributing server applications

Installation of most open-source server applications requires a mixture of technical knowledge and pain. Docker is poised to become the de facto standard for self-contained application packages that will run practically anywhere.

An example of packaging modern server software for simplified distribution is Discourse, an open-source discussion forum (used byBoingBoing BBSEmber.js forums, and Mozilla Community.

Discourse's Docker project coordinates both a single-container, all-in-one, simple deployment and a multi-container, service-oriented, high-availability deployment.

The Future

The prospects for web application deployment continue to evolve. Docker currently lies between maturity of its core functionality (stable, secure containers) and emergence of high-level utility (like "drag-and-drop" install and scaling of web services). This experiement is just the beginning.

【转】Dockerfile Best Practices

Dockerfiles provide a simple syntax for building images. The following are a few tips and tricks to help you get the most out of Dockerfiles.

1: Use the cache

Each instruction in a Dockerfile commits the change into a new image which will then be used as the base of the next instruction. If an image exists with the same parent and instruction ( except for ADD ) docker will use the image instead of executing the instruction, i.e. the cache.

In order to effectively utilize the cache you need to keep your Dockerfiles consistent and only add the alterations at the end. All my Dockerfiles start with the same 5 lines.

FROM ubuntu
MAINTAINER Michael Crosby <michael@crosbymichael.com>

RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
RUN apt-get update
RUN apt-get upgrade -y

Changing MAINTAINER instruction will force docker to execute the proceeding RUN instructions to update apt instead of hitting the cache.

1. Keep common instructions at the top of the Dockerfile to utilize the cache.

2: Use tags

Unless you are experimenting with docker you should always pass the -t option to docker build so that the resulting image is tagged. A simple human readable tag will help you manage what each image was created for.

docker build -t="crosbymichael/sentry" .

2. Always pass -t to tag the resulting image.

3: EXPOSE-ing ports

Two of the core concepts of docker are repeatability and portability. Images should able to run on any host and as many times as needed. With Dockerfiles you have the ability to map the private and public ports, however, you should never map the public port in a Dockerfile. By mapping to the public port on your host you will only be able to have one instance of your dockerized app running.

# private and public mapping
EXPOSE 80:8080

# private only
EXPOSE 80

If the consumer of the image cares what public port the container maps to they will pass the -p option when running the image, otherwise, docker will automatically assign a port for the container.

3. Never map the public port in a Dockerfile.

4: CMD and ENTRYPOINT syntax

Both CMD and ENTRYPOINT are straight forward but they have a hidden, err, "feature" that can cause issues if you are not aware. Two different syntaxes are supported for these instructions.

CMD /bin/echo
# or
CMD ["/bin/echo"]

This may not look like it would be an issues but the devil in the details will trip you up. If you use the second syntax where the CMD ( or ENTRYPOINT ) is an array, it acts exactly like you would expect. If you use the first syntax without the array, docker pre-pends /bin/sh -c to your command. This has always been in docker as far as I can remember.

Pre-pending /bin/sh -c can cause some unexpected issues and functionality that is not easily understood if you did not know that docker modified your CMD. Therefore, you should always use the array syntax for both instructions because both will be executed exactly how you intended.

4. Always use the array syntax when using CMD and ENTRYPOINT.

5. CMD and ENTRYPOINT better together

In case you don't know ENTRYPOINT makes your dockerized application behave like a binary. You can pass arguments to the ENTRYPOINT during docker run and not worry about it being overwritten ( unlike CMD ). ENTRYPOINT is even better when used with CMD. Let's checkout my Rethinkdb Dockerfile and see how to use this.

# Dockerfile for Rethinkdb
# http://www.rethinkdb.com/

FROM ubuntu

MAINTAINER Michael Crosby <michael@crosbymichael.com>

RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
RUN apt-get update
RUN apt-get upgrade -y

RUN apt-get install -y python-software-properties
RUN add-apt-repository ppa:rethinkdb/ppa
RUN apt-get update
RUN apt-get install -y rethinkdb

# Rethinkdb process
EXPOSE 28015
# Rethinkdb admin console
EXPOSE 8080

# Create the /rethinkdb_data dir structure
RUN /usr/bin/rethinkdb create

ENTRYPOINT ["/usr/bin/rethinkdb"]

CMD ["--help"]

This is everything that is required to get Rethinkdb dockerized. We have my standard 5 lines at the top to make sure the base image is updated, ports exposed, etc... With the ENTRYPOINT set, we know that whenever this image is run, all arguments passed during docker run will be arguments to the ENTRYPOINT ( /usr/bin/rethinkdb ).

I also have a default CMD set in the Dockerfile to --help. What this does is incase no arguments are passed during docker run, rethinkdb's default help output will display to the user. This is same functionality that you would expect interacting with the rethinkdb binary.

docker run crosbymichael/rethinkdb


Output

Running 'rethinkdb' will create a new data directory or use an existing one,
  and serve as a RethinkDB cluster node.
File path options:
  -d [ --directory ] path           specify directory to store data and metadata
  --io-threads n                    how many simultaneous I/O operations can happen
                                    at the same time

Machine name options:
  -n [ --machine-name ] arg         the name for this machine (as will appear in
                                    the metadata).  If not specified, it will be
                                    randomly chosen from a short list of names.

Network options:
  --bind {all | addr}               add the address of a localinterface to listen
                                    on when accepting connections; loopback
                                    addresses are enabled by default
  --cluster-port port               port for receiving connections from other nodes
  --driver-port port                port for rethinkdb protocol client drivers
  -o [ --port-offset ] offset       all ports used locally will have this value
                                    added
  -j [ --join ] host:port           host and port of a rethinkdb node to connect to
  .................

Now lets run the container with the --bind all argument.

docker run crosbymichael/rethinkdb --bind all


Output

info: Running rethinkdb 1.7.1-0ubuntu1~precise (GCC 4.6.3)...
info: Running on Linux 3.2.0-45-virtual x86_64
info: Loading data from directory /rethinkdb_data
warn: Could not turn off filesystem caching for database file: "/rethinkdb_data/metadata" (Is the file located on a filesystem that doesn't support direct I/O (e.g. some encrypted or journaled file systems)?) This can cause performance problems.
warn: Could not turn off filesystem caching for database file: "/rethinkdb_data/auth_metadata" (Is the file located on a filesystem that doesn't support direct I/O (e.g. some encrypted or journaled file systems)?) This can cause performance problems.
info: Listening for intracluster connections on port 29015
info: Listening for client driver connections on port 28015
info: Listening for administrative HTTP connections on port 8080
info: Listening on addresses: 127.0.0.1, 172.16.42.13
info: Server ready
info: Someone asked for the nonwhitelisted file /js/handlebars.runtime-1.0.0.beta.6.js, if this should be accessible add it to the whitelist.

And there it is, a full Rethinkdb instance running with access to the db and admin console by, interacting with the image the same way you interact with the binary. Very powerful and yet extremely simple. I love simple.

5. ENTRYPOINT and CMD are better together.


I hope this post helps you to get started working with Dockerfiles and building images that we all can use and benefit from. Going forward, I believe that Dockerfiles will be a very important part of what makes docker so simple and easy to use whether you are consuming or producing images. I plan to invest much of my time to provide a complete, powerful, yet simple solution to building docker images via the Dockerfile.

PaaS的现在和未来:将由开发者决定(译)

原文地址:

http://www.informationweek.com/cloud/platform-as-a-service/paas-present-and-future-developers-will-decide/d/d-id/1127808

 

PaaS不同于IaaS,IBM的Ric Telford预测在未来的两年时间内,PaaS会逐步成熟起来。

大概2年多前,我曾写过一篇"PaaS Comes Of Age"的文章,文章中我认为,我们正进入一个PaaS的时代 -- 对企业来说,平台服务将会变成非常关键的云能力。自从我写了那篇文章之后,已经发生了很多变化,我们看到“PaaS时代来临”的故事正逐步走向成熟。

对于不了解的人来说,PaaS可能会被认为是一种能力的交付模式,传统上你会把这种能力和中间件关联起来。没有那么切合,PaaS也刚好位于云计算栈的中间层,在IaaS层和SaaS层之间。PaaS可以从云端实现应用开发和运行时服务的任意组合,以某种标准的模型(申请、按需付费等)。

今天,有很多类型的PaaS服务,以至于很难去让PaaS保持一致。很多公司也汇聚到了这个领域,从IaaS层向上发展(亚马逊的RDS服务或者弹性Beanstalk服务),从SaaS层向下发展(Salesforce的Force.com),甚至是作为公司的一个新的驱动力(谷歌的AppEngine或者微软的Azure)。此外,还有很多的纯粹单一的PaaS提供商(比如EngineYard)和一些创业公司。

在PaaS领域,一方面需要认真观察的是开放标准和开源的作用。不像IaaS,亚马逊已经成为了事实上的标准,PaaS可能更多的是基于规范去建立一套开放的标准。IBM刚刚发布BlueMix,并为PaaS能力投入十亿美元。IBM这次发布的关键是对Cloud Foundry的支持,它是云计算PaaS层的一个开源产品。Cloud Foundry是由VMware发起的,并分拆做为Pivotal的一部分,Cloud Foundry已经有大约40个企业贡献者。为了不被淘汰,红帽的OpenShift也是开源的,而且也有一些稳定活跃的贡献者。

看看未来PaaS会是什么样,这将非常有趣。如果它遵循IT领域的类似技术发展轨迹,就可以设想下面的这些事情:

  • 在PaaS规范化之前,公司需要熟悉并了解相关的概念。对于大部分企业来说,我们仍然处在“tire-kicking”的时代,企业在开始真正的摆脱传统的中间件模式之前,需要能看到PaaS的价值。在PaaS真正的发展之前,这可能需要1年或2年的时间。然而,就像从传统的C/S应用向基于互联网的应用转变,转变开始的时候,PaaS就会快速地发展。
  • 开放系统将会和私有系统共存,有点类似Java和.Net,每一类都有会相应的追随者。
  • 开发者将会决定PaaS的未来。想想在微软或者安卓早期的时候吧。那些成功吸引和保持软件开发者的PaaS提供商将会不断上升。如果某天你看到一些“PaaS-justifying应用”,请不要感到惊讶,一些引人注目的SaaS产品只能运行在一个特定供应商的PaaS上(对游戏玩家来说,有点像Xbox One上的Titanfall)。
  • PaaS接下来将会整合,但PaaS市场不会像IaaS市场那么多。一些人认为IaaS提供商将会整合到只剩下6个大的提供商。
  • 如果你看看今天的类似情况--服务器和存储市场--这似乎是对的。但PaaS系统有一套更广泛的功能,其中的一个,其生态系统将逐步发展成为标准,有点像今天的Java社区,但是依然会有不少的竞争者。

我会在2年后回来看看这些预言是否是准确的。

搜狐云景Container经验谈

    搜狐PaaS公有云平台“搜狐云景”已于5月21日正式开启公测,为广大开发者提供应用开发的一站式服务。为了给开发者提供更加灵活的应用托管平台,搜狐云景平台底层使用了Container的技术,其实它在搜狐内部的私有云平台上已经使用了很长时间,在整个过程中,我们也踩过了很多的坑,积累了不少的经验。近几年,Container相关技术不断得到架构师、研发人员、运维人员等的持续关注,而且也不断涌出了不少Container的实现方案,比如:Cloud Foundry的Warden、Google的Imctfy等,随着云计算在国内的逐步壮大、成熟,相信未来会有越来越多的平台会采用类Container技术,我们也希望能把我们的一些经验、教训分享给大家,和大家一起共同推进Container技术的发展。

    在使用Container技术之前,搜狐私有云PaaS平台使用了沙盒模式,利用JVM虚拟机对用户的进程进行隔离和安全控制,这种方式的优势是可以侵入到JVM内部对用户的代码进行拦截,方便的实施白名单机制,进而保证平台的安全性。但随着接入应用数量的逐渐增多,更多的需求接踵而来,比如:需要多语言的支持,应用希望有更大的灵活性,不希望平台有过多的限制等。新版PaaS平台设计之初,我们也考虑了多种方案,首选的方案就是继续采用沙盒模式,为每种语言去实现一个沙盒,这种方案的代价比较大,而且仍然无法满足应用的灵活性需求。第二种方案就是采用虚拟化技术进行隔离,传统的半虚或全虚的虚拟化技术如:KVM、Xen等,由于是完整的模拟OS,因此带来的 Overhead会比较大,而且一台物理机上能生成的虚拟机数量也非常有限,这样的虚拟化技术并不适合应用在PaaS平台上。而基于内核的虚拟化方案Container则很好的满足了我们的需求,宿主上的所有Container都共享同一个内核,共享同一个OS,它足够的轻量,它的provisioning时间在秒级,一个宿主上甚至可以运行上千个Container,可以极大地提升资源利用率,因此,我们最终就选用了Container方案。

    Container在不同的平台下也有不同的方案,比如:Solaris Zones,FreeBSD Jails,Linux平台下的LXC,OpenVZ,Linux VServer等。搜狐一直以来就是Linux平台,因此也就只能在该平台下去选择相应的技术。其实就技术的成熟度来讲,OpenVZ发展的比较早,有很多特性,相对也比较稳定,国内外有很多VPS就是使用的OpenVZ,但OpenVZ和VServer是单独的一个内核分支,没有进入upstream中,而LXC则从2.6.29就进入到了主内核中,我们还是希望跟着主内核走,因此最后就采用了LXC。

    搜狐云景的整个弹性运行环境就是基于容器构建的,这些容器都运行在物理服务器上,总体上分为以下几层:

CloudScape_Container

1)     Node OS:即物理服务器的操作系统层,所有的Container都共享此OS和系统内核。

2)     Node Agent:对Container的生命周期进行管控,它和云景平台的其它模块通信,进行容器的创建、销毁、更新等操作,并负责对Containers进行监控。

3)     LXC Scripts:在LXC的基本命令行基础上,抽象出一层对Container的管理功能。

4)     Containers:即真正的容器,它是由Node Agent发出调度指令,通过LXC Scripts创建出来的容器。

    搜狐云景目前使用的内核版本为2.6.32,此系列的内核版本对Container的支持还不太完善,我们前期在测试和使用过程中,也遇到了不少的问题,其中不乏一些严重的Bug,因此,搜狐内部专门成立了一个系统研发团队,负责对Kernel和LXC进行研究,在标准的内核基础上做了大量的工作,修复了若干Bug,同时也将一些新特性移植到了内核中,从而形成了我们自己的内核。下面简单介绍一下我们做的一些主要工作:

1)     将AUFS和OverlayFS移植到内核中,通过这种UnionFS技术,我们为每个Container挂载一个基础的只读RootFS和一个可读写的文件系统,从而可以实现一个Node上所有容器共享同一个RootFS,大大缩减了空间的占用,而且可以共享一些基础的动态链接库以及Page Cache。

2)     在2.6的标准内核中引入了setfs系统调用,从而实现了对lxc-attach的支持,搜狐云景的Node Agent上有不少操作需要通过此命令去实现对Container的管理。

3)     修复了一些可能导致Kernel Crash的Bug,比如:系统 Driver的Bug,AUFS操作的Bug。这类的Bug影响非常大,直接可造成内核崩溃,Node自动重启,从而造成上面的所有Container全部消失,极大的影响整个平台的稳定性。

4)     修复了一些Container的安全性问题:比如:在Container内部可以直接mount cgroup,从而修改cgroup对该容器的管控配额信息。禁止容器对系统敏感文件的读写操作,防止容器内部对Node的一些危险操作。

5)     修改了容器内系统信息显示的问题,比如:top/free等命令显示不准确。

    Container技术主要是通过Namespace机制对不同实例的资源进行隔离,包括网络隔离、进程隔离、文件系统隔离等,保证运行在一个容器的应用,不会影响到其它容器的应用。通过Cgroup机制对每个实例的资源进行管控,主要实现了对以下资源的限制,防止实例滥用系统资源:

1)     内存:设置每个容器所能使用的最大物理内存,当容器内的进程使用内存超限后,则Cgroup会自动将相应的进程Kill掉。

2)     CPU:通过为不同的容器指定不同的CPU核,去限制其只能使用特定的核,并为每个容器设置不同的CPU shares,另外还控制每个容器对CPU资源的最长连续使用时间,防止某个容器过度使用CPU资源。

3)     磁盘:LXC目前对磁盘配额的支持不够,搜狐云景通过LVM卷去限制单个容器的配额,并可以方便的对磁盘进行扩容。

    在网络隔离方面,我们也使用了Iptables、TC、SDN等技术方案,对实例的网络流、流量进行管控,最终可以细化到实例可访问哪些网络资源,不能访问哪些网络资源。针对一些静态的访问策略,比如:容器无法访问某台服务器,搜狐云景在设备上做ACL或者在服务器上通过Iptables去实现。在搜狐云景上也会有一些动态的策略,比如:某个应用绑定了Cache服务,则需要动态将该应用的所有实例开通到Cache服务器的网络连接权限,这些动态策略主要是通过SDN去完成的。通过TC,我们去限制每个容器的流入流出流量,防止发生由于某个容器的异常流量,造成云景内部网络带宽跑满,从而影响到其它应用的正常运行。

    搜狐私有PaaS平台V2版本从最初选型测试Container,到目前已经在公有云平台“搜狐云景”上使用Container,经历了近3年的时间,一路走下来,虽然踩了很多的坑,但也收获了很多,整个平台也从最初的极不稳定期(初期,Node或者Container总会隔三差五的挂掉),发展到了现在的稳定运行期(现在,Node或Container几乎没有出现Crash的情况)。现在搜狐内部已有多个业务线将其应用迁移到了私有PaaS平台上,每个实例均运行在不同的Container中。目前我们私有PaaS平台的可用性可达到99.99%。内部应用对资源的需求相对比较大,因此,我们的单台物理机上目前运行30-50个左右的容器,而对搜狐云景来说,我们提供了更多不同配置的容器,最小容器配置为256M内存,这样单台物理机上可运行上百个不同类型的容器,可满足不同应用的需求。

    虽然Container技术已经被众多的互联网企业所接受和采用,并大量地应用在企业内部的云平台上,但不可否认的是,现在Container相关的技术仍然还不太完善,还有不少的问题,它在CPU  、IO等隔离性方面还比较薄弱。尤其是将Container技术应用在公有云平台上,会面临不小的挑战,如何保证公有云平台上应用和环境的安全性,是需要大家持续研究和跟进的。而且,现在也有了一些方案,比如:OpenShift将SELinux和Container进行结合,而Ubuntu则通过Apparmor去加强Container的安全性。相信随着云计算在业界的不断蓬勃发展,Container相关技术也会得到持续的改进和完善,并被大量地应用在企业的云平台上。目前,大家所能看到的是Container被广泛地使用在了PaaS平台,其实在大部分企业内部的IaaS平台上,Container也是一个很不错的选择方案。由于其更轻量、性能更好,我认为在不少场景中,Container可能可以完全替代现有的虚拟化技术,如:Xen、KVM等,而且相信未来支持Container的IaaS管理平台也会不断地涌现出来,Container的未来值得我们期待!

近期SCE两次严重事故的总结

近2周,SCE就发生了2次严重事故

一次是上周,SCE1.0的前端Nginx,因为一个下载的应用将vm的内存吃满,直接造成所有nginx全部挂掉,影响了1.0线上所有的app,故障时间25分钟。

一次是今天,SCE2.0的前端Router,由于一个并发更新upstream的bug,造成所有router全部挂掉,而刚好master也出现了问题,循环调用router,导致router不断挂掉,故障断断续续持续了近1个半小时,影响2.0线上的所有App。

接连出现这样的2次严重事故,肯定会使其它部门的同学对SCE平台的稳定性持有异议,也可能也会间接影响未来其它应用的接入。

整个SCE团队都应该思考并反思一下,为什么会出现这样的事故?

我想从以下几个方面做一些总结:

  • SCE平台的主要模块没有进行完整深入细致的测试,导致线上在某个时刻由于某个原因触发某个bug,直接导致模块挂掉
  • SCE平台的核心模块(Router/Master)提前没有预案,没有备用方案,一旦出问题后,只能根据线上的情况去修复,无法快速切换到另外一种方案上
  • 整个SCE2.0平台太过追求技术完美,太过自动化了,一旦核心模块出问题,无法及时手动介入干预,只能通过其他辅助办法去绕开相应的逻辑
  • 目前SCE平台的模块耦合性太高,master在其中担任了重要角色,一旦master出现故障,整个平台都会有问题,Router都没法重启,目前3.0版本已经在改进这个问题了
  • SCE团队的服务意识和故障紧急处理能力有待提高,当整个平台都挂掉后,所有人首要考虑的问题是,尽快找到故障点,并及时恢复,先不要纠结于找问题的具体原因,使应用恢复正常才是最紧急最重要的事情!
  • 开发、运维同学平常对处理故障的准备不足,平时不带工作笔记本回家,出问题时,使用家里笔记本拨号vpn,没有权限下载代码或者没有权限访问某个url,在最紧急的时候,在这上面白白浪费了很多时间。

今年SCE计划开放公有云服务,目前看来,我们的平台在很多方面还有不少的问题,需要整个团队在近期尽快整改,解决掉以上问题。

私有云都搞不好,都会出这么严重的事故,未来公有云上的应用会更杂更乱,就更难把控了。

出现问题不可怕,可怕的是出问题后,只是简单的把问题解决掉,不反思,不总结经验,不整改!如果是这样的话,那么以前的坑就白踩了,以后还会出类似的问题的!

总之,希望SCE团队能从最近的两次事故中总结教训,大家共同努力,保证平台的稳定性,逐步增强其它产品线使用SCE平台的信心。
 

 

排查Container网络启动慢的原因

近日,在给其它部门部署SCE集群后,发现container启动后,网络在一段时间内无法使用

造成SCE的agent在启动后通过yum安装其它包时出错,用户的app无法启动

自己使用脚本进行测试,container自身启动很快,耗时不到1s

启动后,立即lxc-attach执行一个wget命令,发现堵塞在connect上很长时间,如下:

1

堵塞大概20s左右后,该wget请求才开始执行,这时,container的网络才正常

算上这个时间,一个容器从启动到交付使用,差不多需要30s时间,这个是不能容忍的...

目前container的网络是使用桥接模式,网卡需要开启混杂模式

查看/var/log/messages日志,如下:

2

发现,该容器的veth从learning状态到forwarding状态耗费了15s时间

上网搜了一下,这个是网桥的forward delay参数决定的

执行brctl showstp br0可以看到

3

这个值默认就是15s,尝试通过brctl setfd br0 1设置成1s后

再进行测试,发现容器的网络很快就可以正常使用了

整个容器从启动到安装完包,启动用户进程,总共在6s左右的时间

恩,这个时间基本还是可以接受的

 

测试QingCloud的VPN

首先,在青云中建立2个网络,ip段分别为192.168.100.0 和 192.168.201.0

然后,将他们连接到同一个路由器,路由器的ip地址为10.50.27.96

再建立2个主机,分别将他们放到2个网络中,最终通过DHCP服务,他们获得的ip地址为192.168.100.2和192.168.101.2

申请一个公网ip地址117.121.25.21,并将它绑定在路由器上,这样可以通过设置端口转发,就能通过公网地址去ssh到相应的主机上

最终,这个网络的拓扑图如下:

topology

在路由器上开启VPN服务,vpn网络的默认地址段为10.255.1.0,下载证书配置文件

然后,再另外一个私有网络的机器上配置相应的openvpn,服务启动后,会发现,它自动添加了两条192.168的路由,如下:

route

这样,就能通过vpn访问192.168.100/101网络的机器了

 

之前,在公司的办公网络环境下测试vpn,一直没有尝试成功,后来发现是增加路由时出错,可能是MIS对路由策略进行了控制。

所以,即使连接上了vpn,也无法连接到青云的网络里

 

总体感觉:QingCloud的确不错,用起来很方便,操作界面也浅显易懂,用户体验很棒,看来人家还是做了不少工作的...

 

EC2的预留实例

EC2的标准按需实例,价格相对来说还是比较贵的
比如:一个默认的小型实例,1VCPU/1.7G内存/160G磁盘,每小时$0.088元
如果一个比较稳定的应用需要长期跑在EC2上,可以考虑使用其预留实例
http://aws.amazon.com/cn/ec2/reserved-instances
预留实例实际上是预先交一个一次性的费用,然后可享受比较优惠的小时费用,可选择1年或3年期
比如:3年期的预留低使用率小型实例,每小时$0.041元,几乎就相当于半价了,能节约不少成本
对于高使用率实例,每小时仅$0.02元
需要注意的是:对于低使用率和中使用率预留实例,是按照实例实际运行的时间去收费的
而对于高使用率实例,则是按小时收费,不管实例是否在运行,均计费

最新文章

最近回复

  • feifei435:这两个URI实际是不一样的
  • zsy: git push origin 分支 -f 给力!
  • 冼敏兵:简单易懂,good fit
  • Jack:无需改配置文件,看着累! # gluster volume se...
  • Mr.j:按照你的方法凑效了,折腾死了。。。。
  • zheyemaster:补充一句:我的网站路径:D:\wamp\www ~~菜鸟站长, ...
  • zheyemaster:wamp2.5(apache2.4.9)下局域网访问403错误的...
  • Git中pull对比fetch和merge | 炼似春秋:[…] 首先,我搜索了git pull和git fe...
  • higkoo:总结一下吧, 性能调优示例: gluster volume s...
  • knowaeap:请问一下博主,你维护的openyoudao支持opensuse吗

分类

归档

其它