Docker集群Kubernetes开源架构及实践
作者:孙鑫
更新时间: 11 March 2017
版权所有,转载请联系admin@cloudbin.cn |
1 Kubernetes介绍
1.1 Kubernetes的定义
Kubernetes是Google开源的容器集群管理系统,实现基于Docker构建容器,利用Kubernetes能很方面管理多台Docker主机中的容器。
1.2 Kubernetes主要功能
- 将多台Docker主机抽象为一个资源,以集群方式管理容器,包括任务调度、资源管理、弹性伸缩、滚动升级等功能。
- 使用编排系统(YAML File)快速构建容器集群,提供负载均衡,解决容器直接关联及通信问题
- 自动管理和修复容器,简单说,比如创建一个集群,里面有十个容器,如果某个容器异常关闭,那么,会尝试重启或重新分配容器,始终保证会有十个容器在运行,反而杀死多余的。
2 Kubernetes架构:
Kubernetes以RESTFul形式开放接口,用户可操作的REST对象有三个:Pod,Service和RC (Replication).
2.1 Kubernetes的操作对象
2.1.1 Pod
Pod是kubernetes的操作调度的最小单位,,一个Pod可以由一个或多个容器组成。逻辑上表示某种应用的一个实例,比如一个web站点应用由前端、后端及数据库构建而成,这三个组件将运行在各自的容器中,那么我们可以创建包含三个container的Pod。
同一个Pod只能运行在同一个主机上,共享相同的volumes、network、namespace。
Pod运行于Node节点上,若干相关容器的组合。Pod内包含的容器运行在同一宿主机上,使用相同的网络命名空间、IP地址和端口,能够通过localhost进行通。Pod是Kurbernetes进行创建、调度和管理的最小单位,它提供了比容器更高层次的抽象,使得部署和管理更加灵活。
2.1.2 Service
Service定义了一个Pod逻辑集合的抽象资源,是Pod的路由代理抽象,用于解决Pod之间的服务发现问题。因为Pod的运行状态可动态变化(比如切换机器了、缩容过程中被终止了等),所以访问端不能以写死IP的方式去访问该Pod提供的服务。当创建一个Service后,会分配一个Cluster IP,这个IP与定义的端口提供这个Pod集合一个统一的访问接口,并且实现负载均衡。
Service的引入旨在保证Pod的动态变化对访问端透明,访问端只需要知道Service的地址,由Service来提供代理.
2.1.3 Replication Controller(RC)
RC是用来管理Pod的抽象资源。一个RC可以由一个或多个Pod组成,用于解决Pod的扩容缩容问题。通常,分布式应用为了性能或高可用性的考虑,需要复制多份资源,并且根据负载情况动态伸缩。通过Replication Controller,我们可以指定一个应用需要几份复制,Replication Controller将为每份复制创建一个Pod,并且保证实际运行Pod数量总是与该复制数量相等(例如,当前某个Pod宕机时,自动创建新的Pod来替换)。
在RC被创建后,系统会根据定义好的副本数来创建Pod数量。在运行过程中,如果Pod数量小于定义的,就会重启停止的或重新分配Pod,反之则杀死多余的。当然,也可以动态伸缩运行的Pods规模。
另外可以看到,Service和Replication Controller只是建立在Pod之上的抽象,最终是要作用于Pod的,那么它们如何跟Pod联系起来呢?这就要引入label的概念:label其实很好理解,就是为Pod加上可用于搜索或关联的一组key/value标签,而Service和Replication Controller正是通过label来与Pod关联的。
如下图所示,有三个Pod都有label为”app=backend”,创建Service和Replication Controller时可以指定同样的label:”app=backend”,再通过label selector机制,就将它们与这三个Pod关联起来了。例如,当有其他frontend Pod访问该Service时,自动会转发到其中的一个backend Pod。
2.2 Kubernetes功能组件
如下图所示是kubernetes官方文档里的kubernetes集群架构图,是个典型的master/slave模型。
2.2.1 Master节点
Master上运行kubernetes的三个组件:
2.2.1.1 apiserver
apiserver作为kubernetes系统的入口,封装了核心对象的增删改查操作,以RESTFul接口方式提供给外部客户和内部组件调用。它维护的REST对象将持久化到etcd(一个分布式强一致性的key/value存储)。
2.2.1.2 Scheduler
Scheduler负责集群的资源调度,为新建的Pod分配机器。这部分工作分出来变成一个组件,意味着可以很方便地替换成其他的调度器。
2.2.1.3 Controller-manager
Controller-manager负责执行各种控制器,目前有两类:
- endpoint-controller:定期关联Service和Pod(关联信息由endpoint对象维护),保证Service到Pod的映射总是最新的。
- replication-controller:定期关联Replication Controller和Pod,保证Replication Controller定义的复制数量与实际运行Pod的数量总是一致的。
2.2.2 Slave节点
Slave(称作minion)上运行两个组件:
2.2.2.1 kubelet
kubelet负责管控docker容器,如启动/停止、监控运行状态等。它会定期从etcd获取分配到本机的Pod,并根据Pod信息启动或停止相应的容器。同时,它也会接收apiserver的HTTP请求,汇报Pod的运行状态。
2.2.2.2 Proxy
Proxy负责为Pod提供代理。它会定期从etcd获取所有的Service,并根据Service信息创建代理。当某个客户Pod要访问其他Pod时,访问请求会经过本机proxy做转发。
2.2.3 具体软件模块
1)kubectl
客户端命令行工具,将接受的命令格式化后发送给kube-apiserver,作为整个系统的操作入口。
2)kube-apiserver
作为整个系统的控制入口,以REST API服务提供接口。
3)kube-controller-manager
用来执行整个系统中的后台任务,包括节点状态状况、Pod个数、Pods和Service的关联等。
4)kube-scheduler
负责节点资源管理,接受来自kube-apiserver创建Pods任务,并分配到某个节点。
5)etcd
负责节点间的服务发现和配置共享(一个分布式强一致性的key/value存储)。
6)kube-proxy
运行在每个计算节点上,负责Pod网络代理。定时从etcd获取到Service信息来做相应的策略。
7)kubelet
运行在每个计算节点上,作为agent,接受分配该节点的Pods任务及管理容器,周期性获取容器状态,反馈给kube-apiserver。
8)DNS
一个可选的DNS服务,用于为每个Service对象创建DNS记录,这样所有的Pod就可以通过DNS访问服务了。
3 Kubernetes集群安装部署实现
3.1 Kubernetes集群组件
– etcd 一个高可用的K/V键值对存储和服务发现系统
– flannel 实现夸主机的容器网络的通信
– kube-apiserver 提供kubernetes集群的API调用
– kube-controller-manager 确保集群服务
– kube-scheduler 调度容器,分配到Node
– kubelet 在Node节点上按照配置文件中定义的容器规格启动容器
– kube-proxy 提供网络代理服务
3.2 Kubernetes集群示意图
Kubernetes工作模式server-client,Kubenetes Master提供集中化管理Minions。部署1台Kubernetes Master节点和4台Minion节点,
示意图如下:
3.3 Kubernetes集群安装部署步骤
3.3.1 先决条件
如下操作在所有安装CentOS的机器执行
1.确保系统已经安装epel-release源
# yum -y install epel-release
2.关闭防火墙服务,避免与docker容器的防火墙规则冲突(一定要关闭,否则后面会失败)。
# systemctl stop firewalld
# systemctl disable firewalld
3.3.2 安装配置Kubernetes Master
如下操作在master上执行
1.使用yum安装etcd和kubernetes-master
# yum -y install etcd kubernetes-master
2.编辑/etc/etcd/etcd.conf文件
ETCD_NAME=default
ETCD_DATA_DIR=”/var/lib/etcd/default.etcd”
ETCD_LISTEN_CLIENT_URLS=”http://0.0.0.0:2379″
ETCD_ADVERTISE_CLIENT_URLS=”http://localhost:2379″
3.编辑/etc/kubernetes/apiserver文件
KUBE_API_ADDRESS=”–insecure-bind-address=0.0.0.0″
KUBE_API_PORT=”–port=8080″
KUBELET_PORT=”–kubelet-port=10250″
KUBE_ETCD_SERVERS=”–etcd-servers=http://127.0.0.1:2379″
KUBE_SERVICE_ADDRESSES=”–Service-cluster-ip-range=10.254.0.0/16″
KUBE_ADMISSION_CONTROL=”–admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ResourceQuota”
KUBE_API_ARGS=””
4.启动etcd、kube-apiserver、kube-controller-manager、kube-scheduler等服务,并设置开机启动。
# for SERVICES in etcd kube-apiserver kube-controller-manager kube-scheduler; do systemctl restart $SERVICES;systemctl enable $SERVICES;systemctl status $SERVICES ; done
5.在etcd中定义flannel网络
# etcdctl mk /atomic.io/network/config ‘{“Network”:”172.17.0.0/16″}’
3.3.3 安装配置Kubernetes Slaver
如下操作在node1、node2、node3、node4上执行
1.使用yum安装flannel和kubernetes-node
# yum -y install flannel kubernetes-node
2.为flannel网络指定etcd服务,修改/etc/sysconfig/flanneld文件
FLANNEL_ETCD=”http://192.168.30.20:2379″
FLANNEL_ETCD_KEY=”/atomic.io/network”
3.修改/etc/kubernetes/config文件
KUBE_LOGTOSTDERR=”–logtostderr=true”
KUBE_LOG_LEVEL=”–v=0″
KUBE_ALLOW_PRIV=”–allow-privileged=false”
KUBE_MASTER=”–master=http://192.168.30.20:8080″
4.按照如下内容修改对应node的配置文件/etc/kubernetes/kubelet
node1:
KUBELET_ADDRESS=”–address=0.0.0.0″
KUBELET_PORT=”–port=10250″
KUBELET_HOSTNAME=”–hostname-override=192.168.30.21″ #修改成对应Node的IP
KUBELET_API_SERVER=”–api-servers=http://192.168.30.20:8080″ #指定Master节点的API Server
KUBELET_POD_INFRA_CONTAINER=”–Pod-infra-container-image=registry.access.redhat.com/rhel7/Pod-infrastructure:latest”
KUBELET_ARGS=””
node2:
KUBELET_ADDRESS=”–address=0.0.0.0″
KUBELET_PORT=”–port=10250″
KUBELET_HOSTNAME=”–hostname-override=192.168.30.22″
KUBELET_API_SERVER=”–api-servers=http://192.168.30.20:8080″
KUBELET_POD_INFRA_CONTAINER=”–Pod-infra-container-image=registry.access.redhat.com/rhel7/Pod-infrastructure:latest”
KUBELET_ARGS=””
node3:
KUBELET_ADDRESS=”–address=0.0.0.0″
KUBELET_PORT=”–port=10250″
KUBELET_HOSTNAME=”–hostname-override=192.168.30.23″
KUBELET_API_SERVER=”–api-servers=http://192.168.30.20:8080″
KUBELET_POD_INFRA_CONTAINER=”–Pod-infra-container-image=registry.access.redhat.com/rhel7/Pod-infrastructure:latest”
KUBELET_ARGS=””
node4:
KUBELET_ADDRESS=”–address=0.0.0.0″
KUBELET_PORT=”–port=10250″
KUBELET_HOSTNAME=”–hostname-override=192.168.30.24″
KUBELET_API_SERVER=”–api-servers=http://192.168.30.20:8080″
KUBELET_POD_INFRA_CONTAINER=”–Pod-infra-container-image=registry.access.redhat.com/rhel7/Pod-infrastructure:latest”
KUBELET_ARGS=””
5.在所有Node节点上启动kube-proxy,kubelet,docker,flanneld等服务,并设置开机启动。
# for SERVICES in kube-proxy kubelet docker flanneld;do systemctl restart $SERVICES;systemctl enable $SERVICES;systemctl status $SERVICES; done
3.3.4 验证集群是否安装成功
在master上执行如下命令
[root@master ~]# kubectl get node
NAME STATUS AGE
192.168.30.21 Ready 1m
192.168.30.22 Ready 1m
192.168.30.23 Ready 1m
192.168.30.24 Ready 1m
3.3.5 安装图形化管理界面Kube-ui
kube-ui是kubernetes提供的web管理界面,可以展示节点的内存、CPU、磁盘、Pod、RC、SVC等信息。
1.编辑kube-dashboard-rc.yml定义文件
[root@master kube-dashboard]# cat kubernetes-dashboard-rc.yml
kind: Replication Controller
apiVersion: v1
metadata:
labels:
app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kube-system
spec:
replicas: 1
selector:
app: kubernetes-dashboard
template:
metadata:
labels:
app: kubernetes-dashboard
spec:
containers:
– name: kubernetes-dashboard
image: docker.gaoxiaobang.com/kubernetes/kube-ui:v5
imagePullPolicy: Always
ports:
– containerPort: 8080
- 创建Pod
[root@master kube-dashboard]# kubectl create –f kubernetes-dashboard-rc.yml
2.编辑kube-dashboard-svc.yml定义文件
[root@master kube-dashboard]# cat kubernetes-dashboard-svc.yml
kind: Service
apiVersion: v1
metadata:
labels:
app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kube-system
spec:
type: NodePort
ports:
– port: 80
targetPort: 8080
selector:
app: kubernetes-dashboard
- 创建Service
[root@master kube-dashboard]# kubectl create -f kubernetes-dashboard-svc.yml
4.访问192.168.30.20:8080/ui(也就是master节点),会自动跳转到http://192.168.30.20:8080/api/v1/proxy/namespaces/kube-system/Services/kubernetes-dashboard/#/dashboard/,效果如下图