原文地址:http://www.javashuo.com/article/p-agixkvog-hs.htmlphp
1、Kubernetes系列之介绍篇
•Kubernetes介绍
1.背景介绍
云计算飞速发展
- IaaS
- PaaS
- SaaS
Docker技术日新月异
- 一次构建,处处运行
- 容器的快速轻量
- 完整的生态环境
2.什么是kubernetes
首先,他是一个
全新的基于容器技术的分布式架构领先方案。Kubernetes(k8s)是Google开源的容器集群管理系统(谷歌内部:Borg)。在Docker技术的基础上,为容器化的应用提供部署运行、资源调度、服务发现和动态伸缩等一系列完整功能,提升了大规模容器集群管理的便捷性。
Kubernetes是一个完备的分布式系统支撑平台,
具备完备的集群管理能力,多扩多层次的安全防御和准入机制、多租户应用支撑能力、透明的服务注册和发现机制、內建智能负载均衡器、强大的故障发现和自我修复能力、服务滚动升级和在线扩容能力、可扩展的资源自动调度机制以及多粒度的资源配额管理能力。同时Kubernetes提供完善的管理工具,涵盖了包括开发、部署测试、运维监控在内的各个环节。
Kubernetes中,Service是分布式集群架构的核心,一个Service对象拥有以下关键特征:
- 拥有一个惟一指定的名字
- 拥有一个虚拟IP(Cluster IP、Service IP、或VIP)和端口号
- 可以体统某种远程服务能力
- 被映射到了提供这种服务能力的一组容器应用上
Service的服务进程目前都是基于Socket通讯方式对外提供服务,好比Redis、Memcache、MySQL、Web Server,或者是实现了某个具体业务的一个特定的TCP Server进程,虽然一个Service一般由多个相关的服务进程来提供服务,每一个服务进程都有一个独立的Endpoint(IP+Port)访问点,但Kubernetes可以让咱们经过服务链接到指定的Service上。有了Kubernetes内奸的透明负载均衡和故障恢复机制,无论后端有多少服务进程,也无论某个服务进程是否会因为发生故障而从新部署到其余机器,都不会影响咱们队服务的正常调用,更重要的是这个Service自己一旦建立就不会发生变化,意味着在Kubernetes集群中,咱们不用为了服务的IP地址的变化问题而头疼了。
容器提供了强大的隔离功能,全部有必要把为Service提供服务的这组进程放入容器中进行隔离。为此,Kubernetes设计了Pod对象,将每一个服务进程包装到相对应的Pod中,使其成为Pod中运行的一个容器。为了创建Service与Pod间的关联管理,Kubernetes给每一个Pod贴上一个标签Label,好比运行MySQL的Pod贴上name=mysql标签,给运行PHP的Pod贴上name=php标签,而后给相应的Service定义标签选择器Label Selector,这样就能巧妙的解决了Service于Pod的关联问题。
在集群管理方面,Kubernetes将集群中的机器划分为一个Master节点和一群工做节点Node,其中,在Master节点运行着集群管理相关的一组进程kube-apiserver、kube-controller-manager和kube-scheduler,这些进程实现了整个集群的资源管理、Pod调度、弹性伸缩、安全控制、系统监控和纠错等管理能力,而且都是全自动完成的。Node做为集群中的工做节点,运行真正的应用程序,在Node上Kubernetes管理的最小运行单元是Pod。Node上运行着Kubernetes的kubelet、kube-proxy服务进程,这些服务进程负责Pod的建立、启动、监控、重启、销毁以及实现软件模式的负载均衡器。
在Kubernetes集群中,它解决了传统IT系统中服务扩容和升级的两大难题。你只需为须要扩容的Service关联的Pod建立一个Replication Controller简称(RC),则该Service的扩容及后续的升级等问题将迎刃而解。在一个RC定义文件中包括如下3个关键信息。
- 目标Pod的定义
- 目标Pod须要运行的副本数量(Replicas)
- 要监控的目标Pod标签(Label)
在建立好RC后,Kubernetes会经过RC中定义的的Label筛选出对应Pod实例并实时监控其状态和数量,若是实例数量少于定义的副本数量,则会根据RC中定义的Pod模板来建立一个新的Pod,而后将新Pod调度到合适的Node上启动运行,知道Pod实例的数量达到预约目标,这个过程彻底是自动化。
Kubernetes优点:
- 容器编排
- 轻量级
- 开源
- 弹性伸缩
- 负载均衡
•Kubernetes的核心概念
1.
Master
k8s集群的管理节点,负责管理集群,提供集群的资源数据访问入口。拥有Etcd存储服务(可选),运行Api Server进程,Controller Manager服务进程及Scheduler服务进程,关联工做节点Node。Kubernetes API server提供HTTP Rest接口的关键服务进程,是Kubernetes里全部资源的增、删、改、查等操做的惟一入口。也是集群控制的入口进程;Kubernetes Controller Manager是Kubernetes全部资源对象的自动化控制中心;Kubernetes Schedule是负责资源调度(Pod调度)的进程
2.
Node
Node是Kubernetes集群架构中运行Pod的服务节点(亦叫agent或minion)。Node是Kubernetes集群操做的单元,用来承载被分配Pod的运行,是Pod运行的宿主机。关联Master管理节点,拥有名称和IP、系统资源信息。运行docker eninge服务,守护进程kunelet及负载均衡器kube-proxy.
- 每一个Node节点都运行着如下一组关键进程
- kubelet:负责对Pod对于的容器的建立、启停等任务
- kube-proxy:实现Kubernetes Service的通讯与负载均衡机制的重要组件
- Docker Engine(Docker):Docker引擎,负责本机容器的建立和管理工做
Node节点能够在运行期间动态增长到Kubernetes集群中,默认状况下,kubelet会想master注册本身,这也是Kubernetes推荐的Node管理方式,kubelet进程会定时向Master汇报自身情报,如操做系统、Docker版本、CPU和内存,以及有哪些Pod在运行等等,这样Master能够获知每一个Node节点的资源使用状况,冰实现高效均衡的资源调度策略。、
3.
Pod
运行于Node节点上,若干相关容器的组合。Pod内包含的容器运行在同一宿主机上,使用相同的网络命名空间、IP地址和端口,可以经过localhost进行通。Pod是Kurbernetes进行建立、调度和管理的最小单位,它提供了比容器更高层次的抽象,使得部署和管理更加灵活。一个Pod能够包含一个容器或者多个相关容器。
Pod其实有两种类型:普通Pod和静态Pod,后者比较特殊,它并不存在Kubernetes的etcd存储中,而是存放在某个具体的Node上的一个具体文件中,而且只在此Node上启动。普通Pod一旦被建立,就会被放入etcd存储中,随后会被Kubernetes Master调度到摸个具体的Node上进行绑定,随后该Pod被对应的Node上的kubelet进程实例化成一组相关的Docker容器冰启动起来,在。在默认状况下,当Pod里的某个容器中止时,Kubernetes会自动检测到这个问起而且重启这个Pod(重启Pod里的全部容器),若是Pod所在的Node宕机,则会将这个Node上的全部Pod从新调度到其余节点上。
4.
Replication Controller
Replication Controller用来管理Pod的副本,保证集群中存在指定数量的Pod副本。集群中副本的数量大于指定数量,则会中止指定数量以外的多余容器数量,反之,则会启动少于指定数量个数的容器,保证数量不变。Replication Controller是实现弹性伸缩、动态扩容和滚动升级的核心。
5.
Service
Service定义了Pod的逻辑集合和访问该集合的策略,是真实服务的抽象。Service提供了一个统一的服务访问入口以及服务代理和发现机制,关联多个相同Label的Pod,用户不须要了解后台Pod是如何运行。
外部系统访问Service的问题
首先须要弄明白Kubernetes的三种IP这个问题
Node IP:Node节点的IP地址
Pod IP: Pod的IP地址
Cluster IP:Service的IP地址
首先,Node IP是Kubernetes集群中节点的物理网卡IP地址,全部属于这个网络的服务器之间都能经过这个网络直接通讯。这也代表Kubernetes集群以外的节点访问Kubernetes集群以内的某个节点或者TCP/IP服务的时候,必须经过Node IP进行通讯
其次,Pod IP是每一个Pod的IP地址,他是Docker Engine根据docker0网桥的IP地址段进行分配的,一般是一个虚拟的二层网络。
最后Cluster IP是一个虚拟的IP,但更像是一个伪造的IP网络,缘由有如下几点
- Cluster IP仅仅做用于Kubernetes Service这个对象,并由Kubernetes管理和分配P地址
- Cluster IP没法被ping,他没有一个“实体网络对象”来响应
- Cluster IP只能结合Service Port组成一个具体的通讯端口,单独的Cluster IP不具有通讯的基础,而且他们属于Kubernetes集群这样一个封闭的空间。
Kubernetes集群以内,Node IP网、Pod IP网于Cluster IP网之间的通讯,采用的是Kubernetes本身设计的一种编程方式的特殊路由规则。
6.
Label
Kubernetes中的任意API对象都是经过Label进行标识,Label的实质是一系列的Key/Value键值对,其中key于value由用户本身指定。Label能够附加在各类资源对象上,如Node、Pod、Service、RC等,一个资源对象能够定义任意数量的Label,同一个Label也能够被添加到任意数量的资源对象上去。Label是Replication Controller和Service运行的基础,两者经过Label来进行关联Node上运行的Pod。
咱们能够经过给指定的资源对象捆绑一个或者多个不一样的Label来实现多维度的资源分组管理功能,以便于灵活、方便的进行资源分配、调度、配置等管理工做。
一些经常使用的Label以下:
- 版本标签:"release":"stable","release":"canary"......
- 环境标签:"environment":"dev","environment":"qa","environment":"production"
- 架构标签:"tier":"frontend","tier":"backend","tier":"middleware"
- 分区标签:"partition":"customerA","partition":"customerB"
- 质量管控标签:"track":"daily","track":"weekly"
Label至关于咱们熟悉的标签,给某个资源对象定义一个Label就至关于给它大了一个标签,随后能够经过Label Selector(标签选择器)查询和筛选拥有某些Label的资源对象,Kubernetes经过这种方式实现了相似SQL的简单又通用的对象查询机制。
Label Selector在Kubernetes中重要使用场景以下:
-
- kube-Controller进程经过资源对象RC上定义Label Selector来筛选要监控的Pod副本的数量,从而实现副本数量始终符合预期设定的全自动控制流程
- kube-proxy进程经过Service的Label Selector来选择对应的Pod,自动创建起每一个Service岛对应Pod的请求转发路由表,从而实现Service的智能负载均衡
- 经过对某些Node定义特定的Label,而且在Pod定义文件中使用Nodeselector这种标签调度策略,kuber-scheduler进程能够实现Pod”定向调度“的特性
•
Kubernetes架构和组件

- 服务分组,小集群,多集群
- 服务分组,大集群,单集群
•Kubernetes 组件:
Kubernetes Master控制组件,调度管理整个系统(集群),包含以下组件:
1.Kubernetes API Server
做为Kubernetes系统的入口,其封装了核心对象的增删改查操做,以RESTful API接口方式提供给外部客户和内部组件调用。维护的REST对象持久化到Etcd中存储。
2.Kubernetes Scheduler
为新创建的Pod进行节点(node)选择(即分配机器),负责集群的资源调度。组件抽离,能够方便替换成其余调度器。
3.Kubernetes Controller
负责执行各类控制器,目前已经提供了不少控制器来保证Kubernetes的正常运行。
4. Replication Controller
管理维护Replication Controller,关联Replication Controller和Pod,保证Replication Controller定义的副本数量与实际运行Pod数量一致。
5. Node Controller
管理维护Node,按期检查Node的健康状态,标识出(失效|未失效)的Node节点。
6. Namespace Controller
管理维护Namespace,按期清理无效的Namespace,包括Namesapce下的API对象,好比Pod、Service等。
7. Service Controller
管理维护Service,提供负载以及服务代理。
8.EndPoints Controller
管理维护Endpoints,关联Service和Pod,建立Endpoints为Service的后端,当Pod发生变化时,实时更新Endpoints。
9. Service Account Controller
管理维护Service Account,为每一个Namespace建立默认的Service Account,同时为Service Account建立Service Account Secret。
10. Persistent Volume Controller
管理维护Persistent Volume和Persistent Volume Claim,为新的Persistent Volume Claim分配Persistent Volume进行绑定,为释放的Persistent Volume执行清理回收。
11. Daemon Set Controller
管理维护Daemon Set,负责建立Daemon Pod,保证指定的Node上正常的运行Daemon Pod。
12. Deployment Controller
管理维护Deployment,关联Deployment和Replication Controller,保证运行指定数量的Pod。当Deployment更新时,控制实现Replication Controller和 Pod的更新。
13.Job Controller
管理维护Job,为Jod建立一次性任务Pod,保证完成Job指定完成的任务数目
14. Pod Autoscaler Controller
实现Pod的自动伸缩,定时获取监控数据,进行策略匹配,当知足条件时执行Pod的伸缩动做。
•Kubernetes Node运行节点,运行管理业务容器,包含以下组件:
1.Kubelet
负责管控容器,Kubelet会从Kubernetes API Server接收Pod的建立请求,启动和中止容器,监控容器运行状态并汇报给Kubernetes API Server。
2.Kubernetes Proxy
负责为Pod建立代理服务,Kubernetes Proxy会从Kubernetes API Server获取全部的Service信息,并根据Service的信息建立代理服务,实现Service到Pod的请求路由和转发,从而实现Kubernetes层级的虚拟转发网络。
3.Docker
Node上须要运行容器服务
2、基于kubernetes构建Docker集群环境实战
kubernetes是google公司基于docker所作的一个分布式集群,有如下主件组成
etcd: 高可用存储共享配置和服务发现,做为与minion机器上的flannel配套使用,做用是使每台 minion上运行的docker拥有不一样的ip段,最终目的是使不一样minion上正在运行的docker containner都有一个与别的任意一个containner(别的minion上运行的docker containner)不同的IP地址。
flannel: 网络结构支持
kube-apiserver: 不论经过kubectl仍是使用remote api 直接控制,都要通过apiserver
kube-controller-manager: 对replication controller, endpoints controller, namespace controller, and serviceaccounts controller的循环控制,与kube-apiserver交互,保证这些controller工做
kube-scheduler: Kubernetes scheduler的做用就是根据特定的调度算法将pod调度到指定的工做节点(minion)上,这一过程也叫绑定(bind)
kubelet: Kubelet运行在Kubernetes Minion Node上. 它是container agent的逻辑继任者
kube-proxy: kube-proxy是kubernetes 里运行在minion节点上的一个组件, 它起的做用是一个服务代理的角色
图为GIT+Jenkins+Kubernetes+Docker+Etcd+confd+Nginx+Glusterfs架构:
以下:

环境:
centos7系统机器三台:
10.0.0.81: 用来安装kubernetes master
10.0.0.82: 用做kubernetes minion (minion1)
10.0.0.83: 用做kubbernetes minion (minion2)
1、关闭系统运行的防火墙及selinux
1。若是系统开启了防火墙则按以下步骤关闭防火墙(全部机器)
# systemctl stop firewalld # systemctl disable firewalld
2.关闭selinux
1
2
|
#setenforce 0
#sed -i '/^SELINUX=/cSELINUX=disabled' /etc/sysconfig/selinux
|
2、MASTER安装配置
1.
安装并配置Kubernetes master(yum 方式)
1
|
# yum -y install etcd kubernetes
|
配置etcd。确保列出的这些项都配置正确而且没有被注释掉,下面的配置都是如此 html
1
2
3
4
5
6
|
#vim /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"
|
配置kubernetes前端
1
2
3
4
5
6
7
8
|
vim
/etc/kubernetes/apiserver
KUBE_API_ADDRESS=
"--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=
""
|
2. 启动etcd, kube-apiserver, kube-controller-manager and kube-scheduler服务
1
|
# for SERVICES in etcd kube-apiserver kube-controller-manager kube-scheduler; do systemctl restart $SERVICES systemctl enable $SERVICES systemctl status $SERVICES done
|
3.设置etcd网络node
1
|
#etcdctl -C 10.0.0.81:2379 set /atomic.io/network/config '{"Network":"10.1.0.0/16"}'
|
4. 至此master配置完成,运行kubectl get nodes能够查看有多少minion在运行,以及其状态。这里咱们的minion还都没有开始安装配置,因此运行以后结果为空
1
|
# kubectl get nodes NAME LABELS STATUS
|
3、MINION安装配置(每台minion机器都按以下安装配置)
1. 环境安装和配置
1
|
# yum -y install flannel kubernetes
|
配置kubernetes链接的服务端IPmysql
1
2
3
|
#vim /etc/kubernetes/config
KUBE_MASTER=
"--master=http://10.0.0.81:8080"
KUBE_ETCD_SERVERS=
"--etcd_servers=http://10.0.0.81:2379"
|
配置kubernetes ,(请使用每台minion本身的IP地址好比10.0.0.81:代替下面的$LOCALIP)linux
1
2
3
4
5
|
#vim /etc/kubernetes/kubelet<br>KUBELET_ADDRESS="--address=0.0.0.0"
KUBELET_PORT=
"--port=10250"
# change the hostname to this host’s IP address KUBELET_HOSTNAME="--hostname_override=$LOCALIP"
KUBELET_API_SERVER=
"--api_servers=http://10.0.0.81:8080"
KUBELET_ARGS=
""
|
2. 准备启动服务(若是原本机器上已经运行过docker的请看过来,没有运行过的请忽略此步骤)
运行ifconfig,查看机器的网络配置状况(有docker0)
1
2
3
4
5
|
# ifconfig docker0
Link encap:Ethernet HWaddr 02:42:B2:75:2E:67 inet addr:172.17.0.1 Bcast:0.0.0.0 Mask:255.255.0.0 UP
BROADCAST MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0
errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
|
warning:在运行过docker的机器上能够看到有docker0,这里在启动服务以前须要删掉docker0配置,在命令行运行:sudo ip link delete docker0nginx
3.配置flannel网络git
1
2
3
|
#vim /etc/sysconfig/flanneld
FLANNEL_ETCD_ENDPOINTS=
"http://10.0.0.81:2379"
FLANNEL_ETCD_PREFIX=
"/atomic.io/network"
|
PS:其中atomic.io与上面etcd中的Network对应
4. 启动服务
1
|
# for SERVICES in flanneld kube-proxy kubelet docker; do systemctl restart $SERVICES systemctl enable $SERVICES systemctl status $SERVICES done
|
4、配置完成验证安装
肯定两台minion(10.0.0.82和10.0.0.83)和一台master(10.0.0.81)都已经成功的安装配置而且服务都已经启动了。
切换到master机器上,运行命令kubectl get nodes
1
2
3
4
|
# kubectl get nodes
NAME STATUS AGE
10.0.0.82 Ready 1m
10.0.0.83 Ready 1m
|
能够看到配置的两台minion已经在master的node列表中了。若是想要更多的node,只须要按照minion的配置,配置更多的机器就能够了。web
3、Kubernetes之深刻了解Pod
一、yaml格式的Pod配置文件内容及注解
深刻Pod以前,首先咱们来了解下Pod的yaml总体文件内容及功能注解。
以下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
# yaml格式的pod定义文件完整内容:
apiVersion: v1
#必选,版本号,例如v1
kind: Pod
#必选,Pod
metadata:
#必选,元数据
name: string
#必选,Pod名称
namespace: string
#必选,Pod所属的命名空间
labels:
#自定义标签
- name: string
#自定义标签名字
annotations:
#自定义注释列表
- name: string
spec:
#必选,Pod中容器的详细定义
containers:
#必选,Pod中容器列表
- name: string
#必选,容器名称
image: string
#必选,容器的镜像名称
imagePullPolicy: [Always | Never | IfNotPresent]
#获取镜像的策略 Alawys表示下载镜像 IfnotPresent表示优先使用本地镜像,不然下载镜像,Nerver表示仅使用本地镜像
command
: [string]
#容器的启动命令列表,如不指定,使用打包时使用的启动命令
args: [string]
#容器的启动命令参数列表
workingDir: string
#容器的工做目录
volumeMounts:
#挂载到容器内部的存储卷配置
- name: string
#引用pod定义的共享存储卷的名称,需用volumes[]部分定义的的卷名
mountPath: string
#存储卷在容器内mount的绝对路径,应少于512字符
readOnly: boolean
#是否为只读模式
ports:
#须要暴露的端口库号列表
- name: string
#端口号名称
containerPort: int
#容器须要监听的端口号
hostPort: int
#容器所在主机须要监听的端口号,默认与Container相同
protocol: string
#端口协议,支持TCP和UDP,默认TCP
env
:
#容器运行前需设置的环境变量列表
- name: string
#环境变量名称
value: string
#环境变量的值
resources:
#资源限制和请求的设置
limits:
#资源限制的设置
cpu: string
#Cpu的限制,单位为core数,将用于docker run --cpu-shares参数
memory: string
#内存限制,单位能够为Mib/Gib,将用于docker run --memory参数
requests:
#资源请求的设置
cpu: string
#Cpu请求,容器启动的初始可用数量
memory: string
#内存清楚,容器启动的初始可用数量
livenessProbe:
#对Pod内个容器健康检查的设置,当探测无响应几回后将自动重启该容器,检查方法有exec、httpGet和tcpSocket,对一个容器只需设置其中一种方法便可
exec
:
#对Pod容器内检查方式设置为exec方式
command
: [string]
#exec方式须要制定的命令或脚本
httpGet:
#对Pod内个容器健康检查方法设置为HttpGet,须要制定Path、port
path: string
port: number
host: string
scheme: string
HttpHeaders:
- name: string
value: string
tcpSocket:
#对Pod内个容器健康检查方式设置为tcpSocket方式
port: number
initialDelaySeconds: 0
#容器启动完成后首次探测的时间,单位为秒
timeoutSeconds: 0
#对容器健康检查探测等待响应的超时时间,单位秒,默认1秒
periodSeconds: 0
#对容器监控检查的按期探测时间设置,单位秒,默认10秒一次
successThreshold: 0
failureThreshold: 0
securityContext:
privileged:
false
restartPolicy: [Always | Never | OnFailure]
#Pod的重启策略,Always表示一旦无论以何种方式终止运行,kubelet都将重启,OnFailure表示只有Pod以非0退出码退出才重启,Nerver表示再也不重启该Pod
nodeSelector: obeject
#设置NodeSelector表示将该Pod调度到包含这个label的node上,以key:value的格式指定
imagePullSecrets:
#Pull镜像时使用的secret名称,以key:secretkey格式指定
- name: string
hostNetwork:
false
#是否使用主机网络模式,默认为false,若是设置为true,表示使用宿主机网络
volumes:
#在该pod上定义共享存储卷列表
- name: string
#共享存储卷名称 (volumes类型有不少种)
emptyDir: {}
#类型为emtyDir的存储卷,与Pod同生命周期的一个临时目录。为空值
hostPath: string
#类型为hostPath的存储卷,表示挂载Pod所在宿主机的目录
path: string
#Pod所在宿主机的目录,将被用于同期中mount的目录
secret:
#类型为secret的存储卷,挂载集群与定义的secre对象到容器内部
scretname: string
items:
- key: string
path: string
configMap:
#类型为configMap的存储卷,挂载预约义的configMap对象到容器内部
name: string
items:
- key: string
path: string
|
二、Pod基本用法:
在使用docker时,咱们可使用docker run命令建立并启动一个容器,而在Kubernetes系统中对长时间运行的容器要求是:其主程序须要一直在前台运行。若是咱们建立的docker镜像的启动命令是后台执行程序,例如Linux脚本:
nohup ./startup.sh &
则kubelet建立包含这个容器的pod后运行完该命令,即认为Pod执行结束,以后根据RC中定义的pod的replicas副本数量生产一个新的pod,而一旦建立出新的pod,将在执行完命令后陷入无限循环的过程当中,这就是Kubernetes须要咱们建立的docker镜像以一个前台命令做为启动命令的缘由。
对于没法改造为前台执行的应用,也可使用开源工具supervisor辅助进行前台运行的功能。
****Pod能够由一个或多个容器组合而成
例如:两个容器应用的前端frontend和redis为紧耦合的关系,应该组合成一个总体对外提供服务,则应该将这两个打包为一个pod.
配置文件frontend-localredis-pod.yaml以下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
apiVersion:v1
kind: Pod
metadata:
name: redis-php
label:
name: redis-php
spec:
containers:
- name: frontend
image: kubeguide
/guestbook-php-frontend
:localredis
ports:
- containersPort: 80
- name: redis-php
image:kubeguide
/redis-master
ports:
- containersPort: 6379
|
属于一个Pod的多个容器应用之间相互访问只须要经过localhost就能够通讯,这一组容器被绑定在一个环境中。
使用kubectl create建立该Pod后,get Pod信息能够看到以下图:
1
2
3
|
#kubectl get gods
NAME READY STATUS RESTATS AGE
redis-php 2
/2
Running 0 10m
|
能够看到READY信息为2/2,表示Pod中的两个容器都成功运行了.redis
查看pod的详细信息,能够看到两个容器的定义和建立过程。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
[root@kubernetes-master ~]
# kubectl describe redis-php
the server doesn't have a resource
type
"redis-php"
[root@kubernetes-master ~]
# kubectl describe pod redis-php
Name: redis-php
Namespace: default
Node: kubernetes-minion
/10
.0.0.23
Start Time: Wed, 12 Apr 2017 09:14:58 +0800
Labels: name=redis-php
Status: Running
IP: 10.1.24.2
Controllers: <none>
Containers:
nginx:
Container ID: docker:
//d05b743c200dff7cf3b60b7373a45666be2ebb48b7b8b31ce0ece9be4546ce77
Image: nginx
Image ID: docker-pullable:
//docker
.io
/nginx
@sha256:e6693c20186f837fc393390135d8a598a96a833917917789d63766cab6c59582
Port: 80
/TCP
State: Running
Started: Wed, 12 Apr 2017 09:19:31 +0800
|
三、静态Pod
静态pod是由kubelet进行管理的仅存在于特定Node的Pod上,他们不能经过API Server进行管理,没法与ReplicationController、Deployment或者DaemonSet进行关联,而且kubelet没法对他们进行健康检查。静态Pod老是由kubelet进行建立,而且老是在kubelet所在的Node上运行。
建立静态Pod有两种方式:配置文件或者HTTP方式
1)配置文件方式
首先,须要设置kubelet的启动参数"--config",指定kubelet须要监控的配置文件所在的目录,kubelet会按期扫描该目录,冰根据目录中的 .yaml或 .json文件进行建立操做
假设配置目录为/etc/kubelet.d/配置启动参数:--config=/etc/kubelet.d/,而后重启kubelet服务后,再宿主机受用docker ps或者在Kubernetes Master上均可以看到指定的容器在列表中
因为静态pod没法经过API Server直接管理,因此在master节点尝试删除该pod,会将其变为pending状态,也不会被删除
1
2
3
4
5
|
#kubetctl delete pod static-web-node1
pod
"static-web-node1"
deleted
#kubectl get pods
NAME READY STATUS RESTARTS AGE
static-web-node1 0
/1
Pending 0 1s
|
要删除该pod的操做只能在其所在的Node上操做,将其定义的.yaml文件从/etc/kubelet.d/目录下删除
1
2
|
#rm -f /etc/kubelet.d/static-web.yaml
#docker ps
|
四、Pod容器共享Volume
Volume类型包括:emtyDir、hostPath、gcePersistentDisk、awsElasticBlockStore、gitRepo、secret、nfs、scsi、glusterfs、persistentVolumeClaim、rbd、flexVolume、cinder、cephfs、flocker、downwardAPI、fc、azureFile、configMap、vsphereVolume等等,能够定义多个Volume,每一个Volume的name保持惟一。在同一个pod中的多个容器可以共享pod级别的存储卷Volume。Volume能够定义为各类类型,多个容器各自进行挂载操做,讲一个Volume挂载为容器内须要的目录。
以下图:

如上图中的Pod中包含两个容器:tomcat和busybox,在pod级别设置Volume “app-logs”,用于tomcat想其中写日志文件,busybox读日志文件。
配置文件以下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
apiVersion:v1
kind: Pod
metadata:
name: redis-php
label:
name: volume-pod
spec:
containers:
- name: tomcat
image: tomcat
ports:
- containersPort: 8080
volumeMounts:
- name: app-logs
mountPath:
/usr/local/tomcat/logs
- name: busybox
image:busybox
command
: [
"sh"
,
"-C"
,
"tail -f /logs/catalina*.log"
]
volumes:
- name: app-logs
emptyDir:{}
|
busybox容器能够经过kubectl logs查看输出内容
1
|
#kubectl logs volume-pod -c busybox
|
tomcat容器生成的日志文件能够登陆容器查看
1
|
#kubectl exec -ti volume-pod -c tomcat -- ls /usr/local/tomcat/logs
|
5.Pod的配置管理
应用部署的一个最佳实践是将应用所需的配置信息于程序进行分离,这样可使得应用程序被更好的复用,经过不用配置文件也能实现更灵活的功能。将应用打包为容器镜像后,能够经过环境变量或外挂文件的方式在建立容器时进行配置注入。ConfigMap是Kubernetes v1.2版本开始提供的一种统一集群配置管理方案。
5.1 ConfigMap:容器应用的配置管理
容器使用ConfigMap的典型用法以下:
(1)生产为容器的环境变量。
(2)设置容器启动命令的启动参数(需设置为环境变量)。
(3)以Volume的形式挂载为容器内部的文件或目录。
ConfigMap以一个或多个key:value的形式保存在Kubernetes系统中共应用使用,既能够用于表示一个变量的值,也能够表示一个完整的配置文件内容。
经过yuaml配置文件或者直接使用kubelet create configmap 命令的方式来建立ConfigMap
5.2 ConfigMap的建立
举个小例子cm-appvars.yaml来描述将几个应用所需的变量定义为ConfigMap的用法:
1
2
3
4
5
6
7
8
|
# vim cm-appvars.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: cm-appvars
data:
apploglevel: info
appdatadir:
/var/data
|
执行kubectl create命令建立该ConfigMap
1
2
|
#kubectl create -f cm-appvars.yaml
configmap
"cm-appvars.yaml"
created
|
查看创建好的ConfigMap:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
#kubectl get configmap
NAME DATA AGE
cm-appvars 2 3s
[root@kubernetes-master ~]
# kubectl describe configmap cm-appvars
Name: cm-appvars
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
appdatadir: 9 bytes
apploglevel: 4 bytes
[root@kubernetes-master ~]
# kubectl get configmap cm-appvars -o yaml
apiVersion: v1
data:
appdatadir:
/var/data
apploglevel: info
kind: ConfigMap
metadata:
creationTimestamp: 2017-04-14T06:03:36Z
name: cm-appvars
namespace: default
resourceVersion:
"571221"
selfLink:
/api/v1/namespaces/default/configmaps/cm-appvars
uid: 190323cb-20d8-11e7-94ec-000c29ac8d83
|
另:建立一个cm-appconfigfile.yaml描述将两个配置文件server.xml和logging.properties定义为configmap的用法,设置key为配置文件的别名,value则是配置文件的文本内容:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
apiVersion: v1
kind: ConfigMap
metadata:
name: cm-appvars
data:
key-serverxml:
<?xml Version=
'1.0'
encoding=
'utf-8'
?>
<Server port=
"8005"
shutdown
=
"SHUTDOWN"
>
.....
<
/service
>
<
/Server
>
key-loggingproperties:
"handlers=lcatalina.org.apache.juli.FileHandler,
...."
|
在pod "cm-test-app"定义中,将configmap "cm-appconfigfile"中的内容以文件形式mount到容器内部configfiles目录中。
Pod配置文件cm-test-app.yaml内容以下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
#vim cm-test-app.yaml
apiVersion: v1
kind: Pod
metadata:
name: cm-
test
-app
spec:
containers:
- name: cm-
test
-app
image: tomcat-app:v1
ports:
- containerPort: 8080
volumeMounts:
- name: serverxml
#引用volume名
mountPath:
/configfiles
#挂载到容器内部目录
configMap:
name: cm-
test
-appconfigfile
#使用configmap定义的的cm-appconfigfile
items:
- key: key-serverxml
#将key=key-serverxml
path: server.xml
#value将server.xml文件名进行挂载
- key: key-loggingproperties
#将key=key-loggingproperties
path: logging.properties
#value将logging.properties文件名进行挂载
|
建立该Pod:
1
2
|
#kubectl create -f cm-test-app.yaml
Pod
"cm-test-app"
created
|
登陆容器查看configfiles目录下的server.xml和logging.properties文件,他们的内容就是configmap “cm-appconfigfile”中定义的两个key的内容
1
2
3
|
#kubectl exec -ti cm-test-app -- bash
root@cm-rest-app:/
# cat /configfiles/server.xml
root@cm-rest-app:/
# cat /configfiles/logging.properties
|
5.3使用ConfigMap的条件限制
使用configmap的限制条件以下:
-
- configmap必须在pod之间建立
- configmap也能够定义为属于某个Namespace,只有处于相同namespaces中的pod能够引用
- configmap中配额管理还未能实现
- kubelet只支持被api server管理的pod使用configmap,静态pod没法引用
- 在pod对configmap进行挂载操做时,容器内部职能挂载为目录,没法挂载文件。
6.Pod生命周期和重启策略
Pod在整个生命周期过程当中被定义为各类状态,熟悉Pod的各类状态有助于理解如何设置Pod的调度策略、重启策略
Pod的状态包含如下几种,如图:

Pod的重启策略(RestartPolicy)应用于Pod内全部的容器,而且仅在Pod所处的Node上由kubelet进行判断和重启操做。当某哥容器异常退出或者健康检查石柏师,kubelet将根据RestartPolicy的设置进行相应的操做
Pod的重启策略包括Always、OnFailure及Nerver,默认值为Always。
kubelet重启失效容器的时间间隔以sync-frequency乘以2n来计算,例如一、二、四、8倍等,最长延时5分钟,而且成功重启后的10分钟后重置该事件。
Pod的重启策略和控制方式息息相关,当前可用于管理Pod的控制器宝库ReplicationController、Job、DaemonSet及直接经过kubelet管理(静态Pod),每种控制器对Pod的重启策略要求以下:
-
- RC和DaemonSet:必须设置为Always,须要保证该容器持续运行
- Job:OnFailure或Nerver,确保容器执行完成后再也不重启
- kubelet:在Pod失效时重启他,不论RestartPolicy设置什么值,而且也不会对Pod进行健康检查
七、Pod健康检查
对Pod的健康检查能够经过两类探针来检查:LivenessProbe和ReadinessProbe
-
- LivenessProbe探针:用于判断容器是否存活(running状态),若是LivenessProbe探针探测到容器不健康,则kubelet杀掉该容器,并根据容器的重启策略作响应处理
- ReadinessProbe探针:用于判断容器是否启动完成(ready状态),能够接受请求。若是ReadinessProbe探针探测失败,则Pod的状态被修改。Endpoint Controller将从service的Endpoint中删除包含该容器所在的Pod的Endpoint。
kubelet定制执行LivenessProbe探针来诊断容器的健康情况。LivenessProbe有三种事项方式。
(1)ExecAction:在容器内部执行一个命令,若是该命令的返回值为0,则表示容器健康
例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
apiVersion:v1
kind: Pod
metadata:
name: liveness-
exec
label:
name: liveness
spec:
containers:
- name: tomcat
image: grc.io
/google_containers/tomcat
args:
-
/bin/sh
- -c
-
echo
ok >
/tmp
.health;
sleep
10;
rm
-fr
/tmp/health
;
sleep
600
livenessProbe:
exec
:
command
:
-
cat
-
/tmp/health
initianDelaySeconds:15
timeoutSeconds:1
|
(2)TCPSocketAction:经过容器ip地址和端口号执行TCP检查,若是可以创建tcp链接代表容器健康
例:
1
2
3
4
5
6
7
8
9
10
11
12
|
kind: Pod
metadata:
name: pod-with-healthcheck
spec:
containers:
- name: nginx
image: nginx
livenessProbe:
tcpSocket:
port: 80
initianDelaySeconds:30
timeoutSeconds:1
|
(3)HTTPGetAction:经过容器Ip地址、端口号及路径调用http get方法,若是响应的状态吗大于200且小于400,则认为容器健康
例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
apiVersion:v1
kind: Pod
metadata:
name: pod-with-healthcheck
spec:
containers:
- name: nginx
image: nginx
livenessProbe:
httpGet:
path:
/_status/healthz
port: 80
initianDelaySeconds:30
timeoutSeconds:1
|
对于每种探针方式,都须要设置initialDelaySeconds和timeoutSeconds两个参数,它们含义以下:
- initialDelaySeconds:启动容器后首次监控检查的等待时间,单位秒
- timeouSeconds:健康检查发送请求后等待响应的超时时间,单位秒。当发生超时就被认为容器没法提供服务无,该容器将被重启
8.玩转Pod调度
在Kubernetes系统中,Pod在大部分场景下都只是容器的载体而已,一般须要经过RC、Deployment、DaemonSet、Job等对象来完成Pod的调度和自动控制功能。
8.1 RC、Deployment:全自动调度
RC的主要功能之一就是自动部署容器应用的多份副本,以及持续监控副本的数量,在集群内始终维护用户指定的副本数量。
在调度策略上,除了使用系统内置的调度算法选择合适的Node进行调度,也能够在Pod的定义中使用NodeSelector或NodeAffinity来指定知足条件的Node进行调度。
1)NodeSelector:定向调度
Kubernetes Master上的scheduler服务(kube-Scheduler进程)负责实现Pod的调度,整个过程经过一系列复杂的算法,最终为每一个Pod计算出一个最佳的目标节点,一般咱们没法知道Pod最终会被调度到哪一个节点上。实际状况中,咱们须要将Pod调度到咱们指定的节点上,能够经过Node的标签和pod的nodeSelector属性相匹配来达到目的。
(1)首先经过kubectl label命令给目标Node打上标签
kubectl label nodes <node-name> <label-key>=<label-value>
例:
1
|
#kubectllabel nodes k8s-node-1 zonenorth
|
(2)而后在Pod定义中加上nodeSelector的设置
例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
apiVersion:v1
kind: Pod
metadata:
name: redis-master
label:
name: redis-master
spec:
replicas: 1
selector:
name: redis-master
template:
metadata:
labels:
name: redis-master
spec:
containers:
- name: redis-master
images: kubeguide
/redis-master
ports:
- containerPort: 6379
nodeSelector:
zone: north
|
运行kubectl create -f命令建立Pod,scheduler就会将该Pod调度到拥有zone=north标签的Node上。 若是多个Node拥有该标签,则会根据调度算法在该组Node上选一个可用的进行Pod调度。
须要注意的是:若是集群中没有拥有该标签的Node,则这个Pod也没法被成功调度。
2)NodeAffinity:亲和性调度
该调度策略是未来替换NodeSelector的新一代调度策略。因为NodeSelector经过Node的Label进行精确匹配,全部NodeAffinity增长了In、NotIn、Exists、DoesNotexist、Gt、Lt等操做符来选择Node。调度侧露更加灵活。
8.2 DaemonSet:特定场景调度
DaemonSet用于管理集群中每一个Node上仅运行一份Pod的副本实例,如图

这种用法适合一些有下列需求的应用:
- 在每一个Node上运行个以GlusterFS存储或者ceph存储的daemon进程
- 在每一个Node上运行一个日志采集程序,例如fluentd或者logstach
- 在每一个Node上运行一个健康程序,采集Node的性能数据。
DaemonSet的Pod调度策略相似于RC,除了使用系统内置的算法在每台Node上进行调度,也能够在Pod的定义中使用NodeSelector或NodeAffinity来指定知足条件的Node范围来进行调度。
8.3 批处理调度
9.Pod的扩容和缩荣
在实际生产环境中,咱们常常遇到某个服务须要扩容的场景,也有可能由于资源精确须要缩减资源而须要减小服务实例数量,此时咱们能够Kubernetes中RC提供scale机制来完成这些工做。
以redis-slave RC为例,已定义的最初副本数量为2,经过kubectl scale命令能够将Pod副本数量从新调整
1
2
3
4
5
6
7
|
#kubectl scale rc redis-slave --replicas=3
ReplicationController
"redis-slave"
scaled
#kubectl get pods
NAME READY STATUS RESTARTS AGE
redis-slave-1sf23 1
/1
Running 0 1h
redis-slave-54wfk 1
/1
Running 0 1h
redis-slave-3da5y 1
/1
Running 0 1h
|
除了能够手工经过kubectl scale命令完成Pod的扩容和缩容操做之外,新版本新增长了Horizontal Podautoscaler(HPA)的控制器,用于实现基于CPU使用路进行启动Pod扩容缩容的功能。该控制器基于Mastger的kube-controller-manager服务启动参数 --horizontal-pod-autoscler-sync-period定义的时长(默认30秒),周期性监控目标Pod的Cpu使用率并在知足条件时对ReplicationController或Deployment中的Pod副本数量进行调整,以符合用户定义的平均Pod Cpu使用率,Pod Cpu使用率来源于heapster组件,因此需预先安装好heapster。
10.Pod的滚动升级
当集群中的某个服务须要升级时,咱们须要中止目前与该服务相关的全部Pod,而后从新拉取镜像并启动。若是集群规模较大,因服务所有中止后升级的方式将致使长时间的服务不可用。由此,Kubernetes提供了rolling-update(滚动升级)功能来解决该问题。
滚动升级经过执行kubectl rolling-update命令一键完成,该命令建立一个新的RC,而后自动控制旧版本的Pod数量逐渐减小到0,同时新的RC中的Pod副本数量从0逐步增长到目标值,最终实现Pod的升级。须要注意的是,系统要求新的RC须要与旧的RC在相同的Namespace内,即不能把别人的资产转到到自家名下。
例:将redis-master从1.0版本升级到2.0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
apiVersion: v1
kind: replicationController
metadata:
name: redis-master-v2
labels:
name: redis-master
Version: v2
spec:
replicas: 1
selector:
name: redis-master
Version: v2
template:
labels:
name: redis-master
Version: v2
spec:
containers:
- name: master
images: kubeguide
/redis-master
:2.0
ports:
- containerPort: 6379
|
须要注意的点:
(1)RC的name不能与旧的RC名字相同
(2)在sele中应至少有一个label与旧的RC的label不一样,以标识为新的RC。本例中新增了一个名为version的label与旧的RC区分
运行kubectl rolling-update来完成Pod的滚动升级:
1
|
#kubectl rolling-update redis-master -f redis-master-controller-v2.yaml
|
另外一种方法就是不使用配置文件,直接用kubectl rolling-update加上--image参数指定新版镜像名来完成Pod的滚动升级
1
|
#kubectl rolling-update redis-master --image=redis-master:2.0
|
与使用配置文件的方式不一样的是,执行的结果是旧的RC被删除,新的RC仍然使用就的RC的名字。
若是在更新过程总发现配置有误,则用户能够中断更新操做,并经过执行kubectl rolling-update-rollback完成Pod版本的回滚。