Docker集群(三) —— Kubernetes 简单入门

【摘要】KubernetesGoogle开源的Docker容器集群管理系统,为容器化的应用提供资源调度部署运行服务发现扩容缩容等整一套功能。本文介绍了kubernetes的重要概念,并通过实例的示例解释了如何应用kubernetes管理docker集群。

因操作系统不同、应用场景不同kubernetes的使用方法有不同,本文只介绍其中一种笔者实践过的切实可行的方法,旨在使读者快速了解Kubernetes,对其有直观的感受。本文以单机版举例,下面的例子都在同一台物理结点上执行,多结点的情况需要解决网络问题,要引入flannel,我们在另一篇中介绍。

1   启动

前置条件:已经安装好docker。

前面的安装完成之后,下面我们启动kubernetes。

2.1
首先启动ETCD

在shell下敲(加sudo):将“10.43.86.110”换成你的linux机器ip。


etcd  --initial-advertise-peer-urls http://10.43.86.110:7001  --advertise-client-urls http://10.43.86.110:4001 --listen-peer-urls  http://0.0.0.0:7001 --listen-client-urls http://0.0.0.0:4001

Etcd启动之后大概是这样:


etcd  --initial-advertise-peer-urls http://10.43.86.110:7001  --advertise-client-urls http://10.43.86.110:4001 --listen-peer-urls http://0.0.0.0:7001  --listen-client-urls http://0.0.0.0:4001

2016-01-16 13:13:10.155368 I  | etcdmain: etcd Version: 2.2.1

2016-01-16 13:13:10.156616 I  | etcdmain: Git SHA: 75f8282

2016-01-16 13:13:10.157180 I  | etcdmain: Go Version: go1.5.1

2016-01-16 13:13:10.158041 I  | etcdmain: Go OS/Arch: linux/amd64

2016-01-16 13:13:10.158220 I  | etcdmain: setting maximum number of CPUs to 1, total number of available  CPUs is 1

2016-01-16 13:13:10.158820 W  | etcdmain: no data-dir provided, using default data-dir ./default.etcd

2016-01-16 13:13:10.177120 N  | etcdmain: the server is already initialized as member before, starting as  etcd member...

2016-01-16 13:13:10.177572 I  | etcdmain: listening for peers on http://0.0.0.0:7001

2016-01-16 13:13:10.187725 I  | etcdmain: listening for client requests on http://0.0.0.0:4001

2016-01-16 13:13:11.749759 I  | etcdserver: recovered store from snapshot at index 760076

2016-01-16 13:13:11.763795 I  | etcdserver: name = default

2016-01-16 13:13:11.786005 I  | etcdserver: data dir = default.etcd

2016-01-16 13:13:11.790356 I  | etcdserver: member dir = default.etcd/member

2016-01-16 13:13:11.790411 I  | etcdserver: heartbeat = 100ms

2016-01-16 13:13:11.790424 I  | etcdserver: election = 1000ms

2016-01-16 13:13:11.790436 I  | etcdserver: snapshot count = 10000

2016-01-16 13:13:11.791149 I  | etcdserver: advertise client URLs = http://10.43.86.110:4001

2016-01-16 13:13:11.791360 I  | etcdserver: loaded cluster information from store: <nil>

2016-01-16 13:13:14.483279 I  | etcdserver: restarting member ce2a822cea30bfca in cluster 7e27652122e8b2ae  at commit index 769230

2016-01-16 13:13:14.530205 I  | raft: ce2a822cea30bfca became follower at term 13

2016-01-16 13:13:14.561409 I  | raft: newRaft ce2a822cea30bfca [peers: [ce2a822cea30bfca], term: 13,  commit: 769230, applied: 760076, lastindex: 769230, lastterm: 13]

2016-01-16 13:13:14.632877 I  | etcdserver: starting server... [version: 2.2.1, cluster version: 2.2]

2016-01-16 13:13:18.150987 I  | raft: ce2a822cea30bfca is starting a new election at term 13

2016-01-16 13:13:18.211244 I  | raft: ce2a822cea30bfca became candidate at term 14

2016-01-16 13:13:18.221462 I  | raft: ce2a822cea30bfca received vote from ce2a822cea30bfca at term 14

2016-01-16 13:13:18.292336 I  | raft: ce2a822cea30bfca became leader at term 14

2016-01-16 13:13:18.318144 I  | raft: raft.node: ce2a822cea30bfca elected leader ce2a822cea30bfca at term  14

2016-01-16  13:13:18.365497 I | etcdserver: published {Name:default  ClientURLs:[http://10.43.86.110:4001]} to cluster 7e27652122e8

2.2
接下来启动kubernetes

Kubernetes有两种组件:master和slave。Master是控制部分,上面运行apiserver,controller,scheduler三个组件。Slave是实际提供资源的部分,上面运行kubelet,proxy两个组件,可以有多个slave。可以把两部分都启动在同一个物理结点上,但是逻辑上要明确他们是不同的。不要问我master挂了怎么办,我还没研究这块。

下面我们按顺序启动master上的三个组件,

2.2.1 
先启动apiserver。


Sudo kube-apiserver--etcd-servers=http://10.43.86.110:4001  --service-cluster-ip-range=123.123.123.0/24 --address=0.0.0.0

解释一下这个命令,比较重要:

--etcd-servers参数是刚才启动ETCD时的--advertise-client-urls参数,表示告诉kubernetes去这个地方找ETCD。

--service-cluster-ip-range=123.123.123.0/24这个参数表示kubernetes分配的service集群的地址段范围。请先记下这个地址,至于service是什么,后面还会讲到,会看到这个地址。目前我们先把kubernetes启动起来。

更多的命令参数可以敲Sudo kube-apiserver –help
研究研究。

2.2.2 
接下来是controller:


sudo  kube-controller-manager --master=10.43.86.110:8080

这里的 --master=10.43.86.110:8080地址就是指apiserver的地址。如果出现有如下错误信息,没有设置cloudprovider可忽略,不影响使用。

controllermanager.go:198]Failed to start service controller: ServiceController should not be run withouta cloudprovider

2.2.3 
然后是scheduler


sudo  kube-scheduler --master=10.43.86.110:8080

这里的 --master=10.43.86.110:8080地址就是指apiserver的地址。

2.2.4 
上面就将master的几个组件启动了,下面启动slave的两个组件。


sudo  kubelet --api-servers=10.43.86.110:8080  --pod-infra-container-image=gcr.io/google_containers/pause

sudo  kube-proxy --master=10.43.86.110:8080

这里注意: kubelet
启动pod时要求使用一个pause镜像,要连google,由于被墙,所以请自己上网下一个镜像的包,

使用  docker load <
镜像包名称命令将镜像解压下来。可以使用docker images查看一下是否成功。看看是否有一个镜像为gcr.io/google_containers/pause。

至此,kubernetes就启动完成了。

3   Kubernetes的使用

本节介绍kubernetes怎么使用,即怎么管理docker集群。要介绍这个,必须了解kubernetes的几个术语:pod、label、service,以及两个重要的yaml文件。下面逐一介绍。

3.1
Node:

先用node这个词表示系统运行的物理结点,node可以是linux机器,也可以是IaaS上的一台虚拟机。

3.2
Pod:

Pod是kubernetes引入的概念,是kubernetes的最基本操作单元。Pod里面包含一个或者多个容器(dockercontainer)。Pod中的多个容器应该是紧耦合的,技术上可以不是紧耦合,但是我现在看这样不会带来任何好处,只有麻烦。可以将原来opentack上面的VM同现在的Pod对等起来考虑问题,都是包含一些执行程序、提供业务,都是调度的单元,但是他们不一样。

每个Pod拥有自己的ip地址,Pod内的容器共享网络,通过localhost就可以互相通信。这时候Pod地址、Pod内的容器地址都是一个意思。Docker
自己没有解决容器间的通信问题。现在有几个问题:

1.   Pod的地址即docker容器地址,一般docker启动时才确定,怎么让其他进程知道

2.   Pod之间怎么通信

3.   多个Pod怎么同时提供服务?

下面讲service时会解决这些问题。

3.3
Label:

label是一个核心概念,kubernetes中的各种对象Pod,service,RC等都有各自的label。这样在其他的对象中的label
selector中就可以指定label来确定操作哪些对象。可能看了这个还是不明白,等下看到例子就懂了。

3.4
Service:

一个service是一组提供相同服务的Pod的对外访问接口。Service是个虚拟的东西,他依靠Pod为其提供支持,一个service需要一组提供相同服务的Pod。Service通过label标签来确定选择哪些Pod作为他的支持。

Service有两种:集群内service对外暴露service。集群内service会在kubernetes的cluster
IP Range池中分配一个IP地址(查上面--service-cluster-ip-range这个参数看一下),这个ip地址在集群内的Pod都可以访问,但是对外不可见。每次启动一个service时,kubernetes都在这个ip-range里面随机的为service分配ip地址。

对外保留的Service需要明确 type:NodePort,这样系统就会在Node上面打开一个主机上的真实端口,客户就能够在集群外访问这个service
了。

Service、Pod、label之间的关系是这样的:

1.1
RC(replication controller).yaml

简单的说,RC文件定义了docker集群中希望启动多少个、什么样的Pod。Kubernetes的controller通过RC文件完成Pod的创建、监控、启停等。

1.2
Service.yaml

Service文件定义了服务的名称、类型、端口、寻找哪些pod支持此服务。

下面通过例子讲这两个文件。

1.3
举例:

下面通过这个例子看一下Node,Pod,Service,Label各自是什么以及他们之间的关系。假设有两个需求非常专业:一个是将字符串小写改为大写upper,一个是将字符串反序reversi(我们假设这两个东西很不容易做,我将他们做成了独立的服务)。现在,我想做一个应用,将一个字符串变大小并反序,那么需要依次使用upper和reversi两个服务。

最下面的stringservice使用上面的upper-service
和reversi-service,完成这个业务。

1.1.1 
两个文件

1.1.1.1  
以upper-service为例,我们先写一个upper-rc.yaml


apiVersion:  v1

kind:  ReplicationController 
//RC文件这块就这样写

metadata:

name : upper  /////
本RC的名字,通过kubectl get rc可以查看当前运行的RC

labels:

name : upper
// 本RC的自定义标签

spec:

replicas:  2 
//  指定启动多少个Pod

selector:

name : upper
  //
管理拥有这个标签的Pod

template:   // Pod的定义

metadata:

labels:

name : upper/// Pod的标签。两个红色要一致。

spec:

containers: 
// Pod内运行的容器列表

- name: upper

          image : upperstring 
/// 容器的镜像名称

ports:

- containerPort : 8010
//容器需要监听的端口号

之后,运行sudo kubectlcreate –f upper-rc.yaml
即可创建出两个Pod,每个里面有一个docker容器。可以通过sudo kubectl get rc和 sudo kubectl get pods来查看执行情况。并通过docker
ps命令查看容器的启动情况。有时pod启动的有点慢,要等一会。


$  sudo kubectl get rc

CONTROLLER   CONTAINER(S)   IMAGE(S)      SELECTOR     REPLICAS

upper        upper           upperstring   name=upper   2

$  sudo kubectl get pods

upper-6f8ed     1/1        Running     0          3m

upper-mjl0r     1/1        Running     0          3m

可以看到启动了两个upper  Pod,名字-后面是随机的。

通过docker ps
查看启动的容器情况:


$ docker ps

CONTAINER ID        IMAGE                            COMMAND                  CREATED             STATUS              PORTS               NAMES

d08baa9df450        upperstring                      "/bin/sh -c  ‘/home/up"   6 minutes ago       Up 6 minutes                            k8s_upper.c0cbee37_upper-mjl0r_default_45bb014d-bea0-11e5-ac25-080027026c8b_4171e732

4496ac505776        gcr.io/google_containers/pause   "/pause"                 6 minutes ago       Up 6 minutes                             k8s_POD.e81ae784_upper-mjl0r_default_45bb014d-bea0-11e5-ac25-080027026c8b_56ba3c8f

可以看到每个Pod对应了两个容器, 一个是upper,另一个是google的pause。

1.1.1.2  
下面写upper-service.yaml


apiVersion  : v1

kind:  Service  // Service 
文件这块就这样写

metadata:

name: upper // service
的名字

labels:

name: upper  
//service的自定义标签

spec:   //详细描述

ports:

- port : 8010 //
服务监听的端口号

targetPort: 8010
// 服务转发到后端的Pod的端口号,要和RC文件对应上

selector:

name : upper 
// 具有这个标签的Pod,都作为本service的管理范围。

之后,运行sudo kubectlcreate –f upper-service.yaml
启动起upper这个服务。可以通过之后,运行sudo kubectl get services
查看service的情况。


$ sudo kubectl get services

NAME         LABELS                                     SELECTOR     IP(S)             PORT(S)

kubernetes    component=apiserver,provider=kubernetes   <none>      
123.123.123.1      443/TCP

upper       
name=upper                                 name=upper  
123.123.123.122   8010/TCP

可以看到有两个service在运行,其中一个是kubernetes自己的,服务的IP地址是123.123.123.1,另一个则是刚刚启动的upper,IP地址为123.123.123.122。这个就是我们启动kubernetes时为这个kubernetes集群分配的地址段。

至此,upper这个服务就在这个docker集群中启动了。

那么同样的,reversi服务的RC文件和Service文件为:


apiVersion:  v1

kind:  ReplicationController

metadata:

name : reversi

labels:

name : reversi

spec:

replicas: 2

selector:

name : reversi

template:

metadata:

labels:

name : reversi

spec:

containers:

- name: reversi

image : reversistring

ports:

- containerPort : 8005


apiVersion  : v1

kind:  Service

metadata:

name: reversi

labels:

name: reversi

spec:

ports:

- port : 8009

targetPort: 8005

selector:

name : reversi

1.1.2 
对外暴露的service

最后一个string-service有点不一样,他不是集群内service,是需要对客户端暴露的。他的RC文件写法一样,但是service写法有不同。

RC.yaml:


apiVersion:  v1

kind:  ReplicationController

metadata:

name : tcpserver

labels:

name : tcpserver

spec:

replicas: 3

selector:

name : tcpserver

template:

metadata:

labels:

name : tcpserver

spec:

containers:

- name: tcpserver

image : tcpserver

ports:

- containerPort : 8000

Service.yaml:


apiVersion  : v1

kind:  Service

metadata:

name: tcpserver

labels:

name: tcpserver

spec:

type: NodePort 
// service的访问方式,默认为ClusterIP,表示集群内地址。此处设置为NodePort表示使用宿主机的端口,这样可以通过宿主机的IP从外部访问此服务。即这个服务是对外可见的。

ports:

- port : 30001

targetPort: 8000
// 转发到后端的Pod的端口号。

nodePort: 30002
// 外部通过这个端口号访问此服务

selector:

name : tcpserver

1.1.3 
Service之间的通信

现在,三个service都启动了,并且各自指定了一定数目的Pod为自己提供服务。那么service之间怎么通信,比如string-service需要upper-service提供服务,但是upper-service的地址是启动时随机分配的,string-service如何知道往那个地址发消息?

Kubernetes通过环境变量来解决这个问题。在一个service启动后,kubernetes会在其他的容器里面增加响应的环境变量,记录service的地址。环境变量的命令为
“服务名_HOST”。比如upper服务启动后,在string-service的pod容器里面就会有一个UPPER_SERVICE_HOST和UPPER_SERVICE_PORT环境变量,通过这个,string-service程序就可以访问upper服务。这个非常重要,我们可以通过dockerinspect
容器ID 来查看一下容器内部的情况,就会看到如下的信息:


"Env":  [

"UPPER_SERVICE_PORT=8010",

"UPPER_SERVICE_HOST=123.123.123.122",

"TCPSERVER_PORT=tcp://123.123.123.74:30001",

"TCPSERVER_PORT_30001_TCP_PROTO=tcp",

"KUBERNETES_PORT_443_TCP=tcp://123.123.123.1:443",

"KUBERNETES_PORT_443_TCP_PORT=443",

"KUBERNETES_PORT_443_TCP_ADDR=123.123.123.1",

"REVERSI_PORT_8009_TCP_PROTO=tcp",

"KUBERNETES_SERVICE_HOST=123.123.123.1",

"REVERSI_SERVICE_HOST=123.123.123.86",

"REVERSI_PORT_8009_TCP=tcp://123.123.123.86:8009",

"REVERSI_PORT_8009_TCP_PORT=8009",

"KUBERNETES_SERVICE_PORT=443",

"KUBERNETES_PORT=tcp://123.123.123.1:443",

"UPPER_PORT_8010_TCP_ADDR=123.123.123.122",

"REVERSI_SERVICE_PORT=8009",

"REVERSI_PORT=tcp://123.123.123.86:8009",

"TCPSERVER_SERVICE_HOST=123.123.123.74",

"TCPSERVER_SERVICE_PORT=30001",

"UPPER_PORT=tcp://123.123.123.122:8010",

"TCPSERVER_PORT_30001_TCP_PORT=30001",

"TCPSERVER_PORT_30001_TCP_ADDR=123.123.123.74",

"UPPER_PORT_8010_TCP_PROTO=tcp",

"UPPER_PORT_8010_TCP=tcp://123.123.123.122:8010",

"UPPER_PORT_8010_TCP_PORT=8010",

"REVERSI_PORT_8009_TCP_ADDR=123.123.123.86",

"TCPSERVER_PORT_30001_TCP=tcp://123.123.123.74:30001",

"KUBERNETES_PORT_443_TCP_PROTO=tcp",

"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

],

可以看到,这里的环境变量信息,同前面sudokubectl get services命令得到的信息是完全对应的。

现在,我们就可以通过Node主机的地址(公网地址)10.43.86.110
和 30002端口号来访问这些服务。

时间: 2024-10-19 12:15:43

Docker集群(三) —— Kubernetes 简单入门的相关文章

Docker集群管理系统Kubernetes

一.Kubernetes简介 Kubernetes 是Google开源的容器集群管理系统,基于Docker构建一个容器的调度服务,提供资源调度.均衡容灾.服务注册.动态扩缩容等功能套件,利用Kubernetes能方便地管理跨机器运行容器化的应用.而且Kubernetes支持GCE.vShpere.CoreOS.OpenShift.Azure等平台上运行,也可以直接部署在物理主机上. 二.Kubernetes架构 1. Pod 在Kubernetes系统中,调度的最小颗粒不是单纯的容器,而是抽象成

docker 集群三 (etcd+flannel) 上

挺不喜欢讲原理的东西的,自己看书比谁讲的都好,贴一个集群的图共理解. . 下载安装包首先下载etcd安装包和flannel安装包,如果有人需要下载,请回复后续我上传到百度网 盘提供,当然也可以自己去网上找找.etcd-v3.2.10-linux-amd64.tar.gztar zxvf flannel-v0.9.0-linux-amd64.tar.gz 多机器安装etcd上传etcd安装包etcd-v3.2.10-linux-amd64.tar.gz解压etcd安装包tar zxvf etcd-

Docker集群(一) —— Docker网络及flannel介绍

[摘要]本文介绍docker网络原理和设置,以及在docker集群中需要解决的问题.最后介绍flannel在解决docker网络问题中的作用. 1   基础 在介绍docker的网络之前,必须先认识docker所依赖的几个linux技术,这对理解docker的网络有帮助.因水平有限这一节仅简单介绍,对linux网络原理感兴趣的TX可以继续深入研究. 1.1 网络命名空间: Linux Namespaces机制提供一种资源隔离方案.PID,IPC,Network等系统资源不再是全局性的,而是属于特

k8s docker集群搭建

?Kubernetes介绍 1.背景介绍 云计算飞速发展 - IaaS - PaaS - SaaS Docker技术突飞猛进 - 一次构建,到处运行 - 容器的快速轻量 - 完整的生态环境 2.什么是kubernetes 首先,他是一个全新的基于容器技术的分布式架构领先方案.Kubernetes(k8s)是Google开源的容器集群管理系统(谷歌内部:Borg).在Docker技术的基础上,为容器化的应用提供部署运行.资源调度.服务发现和动态伸缩等一系列完整功能,提高了大规模容器集群管理的便捷性

Docker 集群环境实现方式

Docker 集群环境实现的新方式 近几年来,Docker 作为一个开源的应用容器引擎,深受广大开发者的欢迎.随着 Docker 生态圈的不断建设,应用领域越来越广.云计算,大数据,移动技术的快速发展,加之企业业务需求的不断变化,紧随技术更新的步伐,导致企业架构要随时更改以适合业务需求.当前,越来越多的公司都已将以 Docker 为代表的容器技术用于企业级业务平台,比如:腾讯,京东,美团,新浪,阿里巴巴等互联网公司.数据的安全.Docker 容器的稳定运行是众多用户关注的,这就要求我们提供一套行

Docker 集群环境实现的新方式

近几年来,Docker 作为一个开源的应用容器引擎,深受广大开发者的欢迎.随着 Docker 生态圈的不断建设,应用领域越来越广.云计算,大数据,移动技术的快速发展,加之企业业务需求的不断变化,紧随技术更新的步伐,导致企业架构要随时更改以适合业务需求.当前,越来越多的公司都已将以 Docker 为代表的容器技术用于企业级业务平台,比如:腾讯,京东,美团,新浪,阿里巴巴等互联网公司.数据的安全.Docker 容器的稳定运行是众多用户关注的,这就要求我们提供一套行之有效的管理大型容器集群的整体解决方

Docker集群下,如何用Flannel实现容器互联

当您将多台服务器节点组成一个Docker集群时,需要对集群网络进行设置,否则默认情况下,无法跨主机容器互联,接下来我们首先分析一下原因. 跨主机容器互联 下图描述了一个简单的集群网络,在该集群内,有两台服务器甲和乙,每台服务器上都有两张网卡,分别连接公网和私网,两台服务器可以通过私网互联,在两个服务器节点上分别安装了Docker,并且运行了A/B/C/D 4个容器. 每台服务器节点上都有一个 docker0 网桥,这是docker启动后初始化的虚拟设备,每个容器都与docker0网桥连接,并且,

使用Ceph集群作为Kubernetes的动态分配持久化存储

使用Docker快速部署Ceph集群 , 然后使用这个Ceph集群作为Kubernetes的动态分配持久化存储. Kubernetes集群要使用Ceph集群需要在每个Kubernetes节点上安装ceph-common

Redis集群搭建与简单使用【转】

Redis集群搭建与简单使用 安装环境与版本 用两台虚拟机模拟6个节点,一台机器3个节点,创建出3 master.3 salve 环境. redis 采用 redis-3.2.4 版本. 两台虚拟机都是 oracle linux 6.6 ,一台(IP:192.168.31.245),一台(IP:192.168.31.210) . 安装过程 1. 下载并解压 cd /root/software wget http://download.redis.io/releases/redis-3.2.4.t