存档

‘Docker’ 分类的存档

OpenStack Magnum 初体验

2017年1月9日 没有评论

OpenStack 的容器历史

自容器技术变为目前云计算最火热和最前沿的技术以来,OpenStack 作为一个云计算管理平台(亦或是云计算生态系统), 怎么将容器管理纳入到其内,成为了近两年 OpenStack 发展的一个热门方向。

OpenStack 的容器整合之路先后经历了以下几种历程:

os_container.png

目前 MagnumMurano 是 OpenStack 中血统最正的容器项目。

可以通过 gitstatus 的分析结果看一下 magnum 的开发活跃度

os_magnum_commits_by_year.png

os_magnum_month_of_year.png

由上面的分析可以看到,magnum 目前开发非常活跃。

Magnum 介绍

Magnum 利用 Keystone, Nova, Heat, Neutron 等已有的 OpenStack组件,整合容器的 集群管理系统如 kubernetes, Mesos 等, 为用户更加简单灵活,多租户的容器服务.

在 Magnum 中的设计中,容器和虚拟机一样为一等公民, 有自己独立的逻辑实现,而不是像 nova docker driver 那样仅仅是 nova 的后端实现。

目前 Magnum 主要为用户提供以下功能:

  • 容器管理集群的部署: 支持 Kubernetes, Docker Swarm, Mesos 这三种容器管理集群类型的部署
  • 容器管理集群的管理: 对容器管理集群进行弹性扩容, 修改配置,提供访问容器管理集群的认证信息

Magnum 的主要概念:

  • Bay: 表示一个集群,比如一个 Mesos 集群,新版本中已经改为 cluster
  • BayModel: 集群的 flavor, 类似于虚拟机的 flavor, BayModel 定义 Docker 集群的一些规格, 比如节点使用的 k8s 或者 mesos 镜像, 网络参数等. 新版本中已经改为 ClusterTemplate
  • Cluser: 同 bay
  • ClusterTemplate: 同 BayModel
  • Node: 指 bay 中的某个节点,即 nova 中的虚拟机, 容器在该 node 里面运行.
  • COE: Container Orchestration Engine, 容器集群管理后端,目前支持的有 k8s, Swarm 和 Mesos. magnum 的主要工作就是将用户的请求转发到 COE, 完成容器的管理。

以下是 k8s 中的一些概念扫盲(下文中的演示部分使用 k8s 来举例)

  • Pod: k8s 的部署调度单元, 一般多个容器组成一个 Pod, Pod 里的容器运行相同的应用, 属于同一 Pod的容器运行在同一个Minion(Host)上,作为一个统一管理单元,共享相同的 volume 和 network namespace/IP和Port空间。详细信息参考 k8s 中的介绍。在新版本中 Pod 的相关管理 命令已经从 magnum 中移除, 要管理 Pod 需要使用 k8s 提供的 kubectl 工具。
  • Replication controller: 用来保证用户定义数量的 Pod 副本在任何时候都是处于 正常运行状态的。也即他的职责是用来管理 Pod 的伸缩
  • Service: 可以理解为是pod网关,因为pod在运行中可能被删除或者ip发生变化,service可以 保证pod的动态变化对访问端是透明的。

800px-Magnum_architecture.png

安装

可以采用 devstack 或者手动安装的方式安装,下面是使用 devstack 安装 magnum 部分的相关配置

# magnum 需要 heat 来编排调度 node
enable_plugin heat http://git.trystack.cn/openstack/heat.git
ENABLED_SERVICES+=,h-eng,h-api,h-api-cfn,h-api-cw
 
# magnum 需要负载均衡组件来做集群管理,特别的,这里使用 v2 的 lbaas 服务
enable_plugin neutron-lbaas http://git.trystack.cn/openstack/neutron-lbaas.git
enable_plugin octavia http://git.trystack.cn/openstack/octavia
disable_service q-lbaas
ENABLED_SERVICES+=,q-lbaasv2
ENABLED_SERVICES+=,octavia,o-cw,o-hk,o-hm,o-api
 
# 启用 magnum 和 magnum-u 插件
enable_plugin magnum http://git.trystack.cn/openstack/magnum.git
enable_plugin magnum-ui http://git.trystack.cn/openstack/magnum-ui.git

安装完成后,可以通过以下命令确认 magnum 服务正常运行。

$ magnum service-list
+----+-----------------------+------------------+-------+----------+-----------------+---------------------------+---------------------------+
| id | host                  | binary           | state | disabled | disabled_reason | created_at                | updated_at                |
+----+-----------------------+------------------+-------+----------+-----------------+---------------------------+---------------------------+
| 1  | localhost.localdomain | magnum-conductor | up    |          | -               | 2017-01-03T10:48:14+00:00 | 2017-01-04T06:45:33+00:00 |
+----+-----------------------+------------------+-------+----------+-----------------+---------------------------+---------------------------+

创建容器管理集群

在容器的世界中,容器是运行在操作系统之上的特殊的 “应用程序”, 由在此操作系统上运行的容器管理程序 k8s 或者 mesos 管理. 在 magnum 中,这个操作系统(和管理程序)是 nova 中的虚拟机。不难理解这样使用 带来的好处,可以复用 nova,glance,cinder,neutron 等等的功能。反正容器本身只需要一个运行时的操作 系统,不管这个操作系统实在虚拟机还是物理机上。

创建容器管理集群的规格

类似于虚拟机的使用,在创建容器管理集群的时候,需要有一个规格,也即上面说过的 ClusterTemplate, 根据此规格的定义来创建容器管理集群。

$ nova keypair-add --pub-key ~/.ssh/id_rsa.pub testkey
$ magnum cluster-template-create \
  --name k8s-cluster-template \          <-- 规格的名字
  --image fedora-atomic-latest \         <-- 运行 node 的镜像
  --keypair testkey \                    <-- 导入一个密钥到 k8s node 上, 方便后续的访问
  --external-network public \            <-- 给每个 node 分配浮动 IP时用到的外部网络
  --dns-nameserver 192.168.2.64 \        <-- node 里面的 dns 配置, 我这里选用一台内网的地址,是为了防止集群初始化的时候访问 google 的服务失败,在这里做翻墙处理 :)
  --flavor m1.small \                    <-- node 虚拟机的规格
  --docker-volume-size 5 \               <-- 给 docker 预留的 volume 的大小
  --network-driver flannel \             <-- 容器使用的网络后端,这里选用 flannel
  --coe kubernetes                       <-- 容器的管理后端,这里选择 k8s

创建 k8s 集群

$ magnum cluster-create --name k8s-cluster --cluster-template k8s-cluster-template --node-count 2
 
$ magnum cluster-list # 等到 status 变为 CREATE_COMPLETE 说明集群创建成功。
+--------------------------------------+-------------+---------+------------+--------------+-----------------+
| uuid                                 | name        | keypair | node_count | master_count | status          |
+--------------------------------------+-------------+---------+------------+--------------+-----------------+
| dd483a45-2b7a-4294-b918-680e1399a7cc | k8s-cluster | testkey | 2          | 1            | CREATE_COMPLETE |
+--------------------------------------+-------------+---------+------------+--------------+-----------------+
 
$ magnum cluster-show k8s-cluster
+---------------------+------------------------------------------------------------+
| Property            | Value                                                      |
+---------------------+------------------------------------------------------------+
| status              | CREATE_COMPLETE                                            |
| cluster_template_id | 8538544b-c809-478f-a98d-e0c35bfeef9c                       |
| node_addresses      | ['192.168.5.136', '192.168.5.134']                         |        <-- k8s 的 minion node
| uuid                | dd483a45-2b7a-4294-b918-680e1399a7cc                       |
| stack_id            | b9e815a8-a746-49b0-a307-755c17415324                       |
| status_reason       | Stack CREATE completed successfully                        |
| created_at          | 2017-01-04T09:07:45+00:00                                  |
| updated_at          | 2017-01-04T09:10:05+00:00                                  |
| coe_version         | v1.2.0                                                     |
| keypair             | testkey                                                    |
| api_address         | https://192.168.5.137:6443                                 |        <-- k8s api endpoint
| master_addresses    | ['192.168.5.137']                                          |        <-- k8s 的master node
| create_timeout      | 60                                                         |
| node_count          | 2                                                          |
| discovery_url       | https://discovery.etcd.io/6a6004c6a9730be2e0896e412caea0a9 |
| master_count        | 1                                                          |
| container_version   | 1.9.1                                                      |
| name                | k8s-cluster                                                |
+---------------------+------------------------------------------------------------+

由于 magnum 后端使用 heat 来做集群的编排,所以也可以通过 heat 来查看相关状态:

$ heat stack-list
+--------------------------------------+--------------------------+-----------------+----------------------+--------------+
| id                                   | stack_name               | stack_status    | creation_time        | updated_time |
+--------------------------------------+--------------------------+-----------------+----------------------+--------------+
| 5fb85534-54fe-407d-ac2d-f3c319024735 | k8s-cluster-644272c22n6h | CREATE_COMPLETE | 2017-01-05T02:28:43Z | None         |
+--------------------------------------+--------------------------+-----------------+----------------------+--------------+

在 horizon 上也可以看到用到的资源的拓扑图:

os_magnum_ui.png

配置集群的访问方式

注入 k8s 的访问密钥到 k8s 集群中,这里利用 magnum 提供的 cluster-config 命令, 该命令会生成三个 *.pem证书文件和一个 k8s 客户端的配置文件 config, 并将相应的公钥注入到 k8s 中. 将这四个文件拷贝到任何想访问 k8s 集群的终端即可。

# Set kubectl to use the correct certs
$ magnum cluster-config k8s-cluster
$ ls *.pem config
ca.pem  cert.pem  config  key.pem

使用容器管理集群

严格来讲上面已经完成了容器管理集群的部署,照着 k8s 的文档就可以开始使用容器了。

安装配置 k8s 客户端

$ wget https://github.com/kubernetes/kubernetes/releases/download/v1.0.1/kubernetes.tar.gz
$ tar -xvzf kubernetes.tar.gz
$ sudo cp -a kubernetes/platforms/linux/amd64/kubectl /usr/bin/kubectl

拷贝 k8s 的证书文件到当前目录下,再导入 k8s 的配置文件即可开始使用,例如下面的实例:

$ export KUBECONFIG=config
$ kubectl cluster-info
Kubernetes master is running at https://192.168.5.131:6443
KubeUI is running at https://192.168.5.131:6443/api/v1/proxy/namespaces/kube-system/services/kube-ui

创建容器集群

我们以 k8s 源码目录 kubernetes/examples/redis 下的 redis 集群为例子。

$ kubectl create -f redis-master.yaml
$ kubectl create -f redis-sentinel-service.yaml
$ kubectl create -f redis-controller.yaml
$ kubectl create -f redis-sentinel-controller.yaml

创建完成之后可以看到所有资源的状态都就绪了。

$ kubectl get pods,rc,services
NAME                   READY     STATUS    RESTARTS   AGE
redis-master           2/2       Running   0          2h
redis-ptvgd            1/1       Running   0          1h
redis-sentinel-6wiha   1/1       Running   0          3m
CONTROLLER       CONTAINER(S)   IMAGE(S)              SELECTOR              REPLICAS
redis            redis          kubernetes/redis:v1   name=redis            2
redis-sentinel   sentinel       kubernetes/redis:v1   redis-sentinel=true   2
NAME             LABELS                                    SELECTOR              IP(S)          PORT(S)
kubernetes       component=apiserver,provider=kubernetes   <none>                10.254.0.1     443/TCP
redis-sentinel   name=sentinel,role=service                redis-sentinel=true   10.254.38.28   26379/TCP

验证我们创建的redis集群:

首先进入容器中设置一个 key:

$ kubectl exec redis-master -ti /bin/bash
root@redis-master:/data# redis-cli  
127.0.0.1:6379> set var "hello world"
OK

找另外一台机器作为 redis 客户端

dunrong@localhost$ kubectl port-forward -p redis-master 6380:6379                <-- 将 k8s 中 redis 的服务端口(6379) 端口映射到本地6380
I0110 17:56:55.657227    2903 portforward.go:225] Forwarding from 127.0.0.1:6380 -> 6379
I0110 17:56:55.657335    2903 portforward.go:225] Forwarding from [::1]:6380 -> 6379

然后用 redis-cli 访问:

dunrong@localhost$ redis-cli -p 6380
127.0.0.1:6380> GET var
"hello world"
127.0.0.1:6380>

that’s it!

小结

从上面的介绍和 demo 来看,目前用 magnum 作为容器的方案是完全可行的。 但由于容器在 OpenStack 中还属于快速开发阶段,在我看来他的作用目前仅仅是一个 k8s, mesos 之类的的容器管理集群的部署脚本,且在使用中存在各种各样的 bug。如果用户具有 一定的 OpenStack 和容器技术的经验,那么使用 OpenStack 在生产中管理部署容器是可行的。

tips

在 k8s 初始化的时候,默认情况下件会到 google的镜像仓库去下载一些 docker 镜像, 由于 你懂的 的原因,在大中华区这步肯定会失败。解决方案无外乎是让整个集群都能 科学上网 , 我这里使用一种最简单的方式。在创建 ClusterTemplate 的时候,指定 DNS 为另外一台机器,并这台机器上安装 dnsmasq, 将 gcr 的域名请求做本地解决即可。

分类: Docker, OpenStack 标签: ,