Kubernetes (一般称为K8s,K8s是将8个字母“ubernete”替换为“8”的缩写) 是一个以容器为中心的基础架构,能够实如今物理集群或虚拟机集群上调度和运行容器,提供容器自动部署、扩展和管理的开源平台。知足了应用程序在生产环境中的一些通用需求:应用实例副本、水平自动扩展、命名与发现、负载均衡、滚动升级、资源监控等。html
Kubernetes (希腊语"舵手" 或 "飞行员") 由Joe Beda,Brendan Burns和Craig McLuckie创立,并由其余谷歌工程师,包括Brian Grant和Tim Hockin进行加盟创做,并由谷歌在2014年首次对外宣布 。它的开发和设计都深受谷歌的Borg系统的影响,它的许多顶级贡献者以前也是Borg系统的开发者。在谷歌内部,Kubernetes的原始代号曾经是Seven,即星际迷航中友好的Borg(博格人)角色。Kubernetes标识中舵轮有七个轮辐就是对该项目代号的致意。node
Kubernetes v1.0于2015年7月21日发布。随着v1.0版本发布,谷歌与Linux 基金会合做组建了Cloud Native Computing Foundation (CNCF)并把Kubernetes做为种子技术来提供。mysql
Rancher Labs在其Rancher容器管理平台中包含了Kubernetes的发布版。Kubernetes也在不少其余公司的产品中被使用,好比Red Hat在OpenShift产品中,CoreOS的Tectonic产品中, 以及IBM的IBM云私有产品中。linux
一、可移植: 支持公有云,私有云,混合云,多重云(multi-cloud)nginx
二、可扩展: 模块化, 插件化, 可挂载, 可组合git
三、自动化: 自动部署,自动重启,自动复制,自动伸缩/扩展github
四、快速部署应用,快速扩展应用golang
五、无缝对接新的应用功能web
六、节省资源,优化硬件资源的使用sql
Kubernetes遵循master-slave architecture。Kubernetes的组件能够分为管理单个的 node 组件和控制平面的一部分的组件。
Kubernetes Master是集群的主要控制单元,用于管理其工做负载并指导整个系统的通讯。Kubernetes控制平面由各自的进程组成,每一个组件均可以在单个主节点上运行,也能够在支持high-availability clusters的多个主节点上运行。
Kubernetes主要由如下几个核心组件组成:
组件名称 |
说明 |
etcd |
保存了整个集群的状态; |
apiserver |
提供了资源操做的惟一入口,并提供认证、受权、访问控制、API注册和发现等机制; |
controller manager |
负责维护集群的状态,好比故障检测、自动扩展、滚动更新等; |
scheduler |
负责资源的调度,按照预约的调度策略将Pod调度到相应的机器上; |
kubelet |
负责维护容器的生命周期,同时也负责Volume(CVI)和网络(CNI)的管理; |
Container runtime |
负责镜像管理以及Pod和容器的真正运行(CRI); |
kube-proxy |
负责为Service提供cluster内部的服务发现和负载均衡; |
核心组件结构图
除了核心组件,还有一些推荐的Add-ons:
组件名称 |
说明 |
kube-dns |
负责为整个集群提供DNS服务 |
Ingress Controller |
为服务提供外网入口 |
Heapster |
提供资源监控 |
Dashboard |
提供GUI |
Federation |
提供跨可用区的集群 |
Fluentd-elasticsearch |
提供集群日志采集、存储与查询 |
系统版本说明
[root@k8s-master ~]# cat /etc/redhat-release
CentOS Linux release 7.2.1511 (Core)
[root@k8s-master ~]# uname -r
3.10.0-327.el7.x86_64
[root@k8s-master ~]# getenforce
Disabled
[root@k8s-master ~]# systemctl status firewalld.service
● firewalld.service - firewalld - dynamic firewall daemon
Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled)
Active: inactive (dead)
主机IP规划
主机名 IP 功能
k8s-master 10.0.0.11/172.16.1.11 Master
k8s-node-1 10.0.0.12/172.16.1.12 node1
k8s-node-2 10.0.0.13/172.16.1.13 node2
设置hosts解析
[root@k8s-master ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
10.0.0.11 k8s-master
10.0.0.12 k8s-node-1
10.0.0.13 k8s-node-2
在三个节点上分别操做
[root@k8s-master ~]# yum install etcd docker kubernetes flannel -y
[root@k8s-node-1 ~]# yum install docker kubernetes flannel -y
[root@k8s-node-2 ~]# yum install docker kubernetes flannel -y
安装的软件版本说明
[root@k8s-master ~]# rpm -qa etcd docker kubernetes flannel
flannel-0.7.1-2.el7.x86_64
docker-1.12.6-71.git3e8e77d.el7.centos.1.x86_64
kubernetes-1.5.2-0.7.git269f928.el7.x86_64
etcd-3.2.11-1.el7.x86_64
yum安装的etcd默认配置文件在/etc/etcd/etcd.conf。
最终配置文件
[root@k8s-master ~]# grep -Ev '^$|#' /etc/etcd/etcd.conf
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"
ETCD_NAME="default"
ETCD_ADVERTISE_CLIENT_URLS="http://10.0.0.11:2379"
启动etcd
[root@k8s-master ~]# systemctl enable etcd
[root@k8s-master ~]# systemctl start etcd
测试etcd
etcdctl set testdir/testkey0 0
etcdctl set testdir/testkey0 0
[root@k8s-master ~]# etcdctl -C http://10.0.0.11:2379 cluster-health
member 8e9e05c52164694d is healthy: got healthy result from http://10.0.0.11:2379
cluster is healthy
/etc/kubernetes/apiserver配置文件内容
[root@k8s-master ~]# grep -Ev '^$|#' /etc/kubernetes/apiserver
KUBE_API_ADDRESS="--insecure-bind-address=0.0.0.0"
KUBE_API_PORT="--port=8080"
KUBE_ETCD_SERVERS="--etcd-servers=http://10.0.0.11: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=""
/etc/kubernetes/config配置文件
[root@k8s-master ~]# grep -Ev '^$|#' /etc/kubernetes/config
KUBE_LOGTOSTDERR="--logtostderr=true"
KUBE_LOG_LEVEL="--v=0"
KUBE_ALLOW_PRIV="--allow-privileged=false"
KUBE_MASTER="--master=http://10.0.0.11:8080"
启动服务
systemctl enable kube-apiserver.service
systemctl start kube-apiserver.service
systemctl enable kube-controller-manager.service
systemctl start kube-controller-manager.service
systemctl enable kube-scheduler.service
systemctl start kube-scheduler.service
/etc/kubernetes/config配置文件
[root@k8s-node-1 ~]# grep -Ev '^$|#' /etc/kubernetes/config
KUBE_LOGTOSTDERR="--logtostderr=true"
KUBE_LOG_LEVEL="--v=0"
KUBE_ALLOW_PRIV="--allow-privileged=false"
KUBE_MASTER="--master=http://10.0.0.11:8080"
[root@k8s-node-1 ~]# grep -Ev '^$|#' /etc/kubernetes/kubelet
KUBELET_ADDRESS="--address=0.0.0.0"
KUBELET_HOSTNAME="--hostname-override=10.0.0.12"
KUBELET_API_SERVER="--api-servers=http://10.0.0.11:8080"
KUBELET_POD_INFRA_CONTAINER="--pod-infra-container-image=registry.access.redhat.com/rhel7/pod-infrastructure:latest"
KUBELET_ARGS=""
/etc/kubernetes/config配置文件
[root@k8s-node-2 ~]# grep -Ev '^$|#' /etc/kubernetes/config
KUBE_LOGTOSTDERR="--logtostderr=true"
KUBE_LOG_LEVEL="--v=0"
KUBE_ALLOW_PRIV="--allow-privileged=false"
KUBE_MASTER="--master=http://10.0.0.11:8080"
[root@k8s-node-2 ~]# grep -Ev '^$|#' /etc/kubernetes/kubelet
KUBELET_ADDRESS="--address=0.0.0.0"
KUBELET_HOSTNAME="--hostname-override=10.0.0.13"
KUBELET_API_SERVER="--api-servers=http://10.0.0.11:8080"
KUBELET_POD_INFRA_CONTAINER="--pod-infra-container-image=registry.access.redhat.com/rhel7/pod-infrastructure:latest"
KUBELET_ARGS=""
启动
systemctl enable kubelet.service
systemctl start kubelet.service
systemctl enable kube-proxy.service
systemctl start kube-proxy.service
在master上查看集群中节点及节点状态
# kubectl -s http://10.0.0.11:8080 get node
[root@k8s-master ~]# kubectl -s http://10.0.0.11:8080 get node
NAME STATUS AGE
10.0.0.12 Ready 49s
10.0.0.13 Ready 56s
[root@k8s-master ~]# kubectl get nodes
NAME STATUS AGE
10.0.0.12 Ready 1m
10.0.0.13 Ready 1m
至此Kubernetes基础部署完成
二进制安装:
能够安装最新版的1.9,二进制安装须要手动建立配置文件和systemd启动文件,优点是有助于理解系统各组件的交互原理和熟悉组件启动参数,有助于快速排查解决实际问题
kubuadm:
kubeadm是Kubernetes官方推出的快速部署Kubernetes集群工具,其思路是将Kubernetes相关服务容器化(Kubernetes静态Pod)以简化部署。
minikube:
minikube 由 CoreOS 提供在单机上构件 kubernetes 集群。minikube命令能够运行在windows/linux/macos等平台,使用minikube搭建本地集群是很是方便的,同时minikube提供了完整的kubernetes集群的功能。对于初识者minikube是一种很好的安装方式,并且上手也很是快。但问题在于minikube安装的时候须要链接互联网,并且网络须要足够好
编译安装:
kubernetes是使用golang开发的,编译安装须要go环境,编译时间特别长,不建议
ansible部署:
因为k8s部署二进制安装步骤较多,因而有网友将其写成ansible剧本简化部署https://github.com/gjmzj/kubeasz
安装软件包
yum install flannel
修改配置文件
[root@k8s-master ~]# grep "^[a-Z]" /etc/sysconfig/flanneld
FLANNEL_ETCD_ENDPOINTS="http://10.0.0.11:2379"
FLANNEL_ETCD_PREFIX="/atomic.io/network"
Flannel使用Etcd进行配置,来保证多个Flannel实例之间的配置一致性,因此须要在etcd上进行以下配置:(‘/atomic.io/network/config’这个key与上文/etc/sysconfig/flannel中的配置项FLANNEL_ETCD_PREFIX是相对应的,错误的话启动就会出错)
配置网络范围
etcdctl mk /atomic.io/network/config '{ "Network": "172.16.0.0/16" }'
操做建立网络
[root@k8s-master ~]# etcdctl mk /atomic.io/network/config '{ "Network": "172.16.0.0/16" }'
{ "Network": "172.16.0.0/16" }
master节点操做
systemctl enable flanneld.service
systemctl start flanneld.service
service docker restart
systemctl restart kube-apiserver.service
systemctl restart kube-controller-manager.service
systemctl restart kube-scheduler.service
node节点操做
systemctl enable flanneld.service
systemctl start flanneld.service
service docker restart
systemctl restart kubelet.service
systemctl restart kube-proxy.service
Pod 是Kubernetes的基本操做单元,也是应用运行的载体。整个Kubernetes系统都是围绕着Pod展开的,好比如何部署运行Pod、如何保证Pod的数量、如何访问Pod等。另外,Pod是一个或多个机关容器的集合,这能够说是一大创新点,提供了一种容器的组合的模型。
建立 |
kubectl create -f xxx.yaml |
查询 |
kubectl get pod yourPodName kubectl describe pod yourPodName |
删除 |
kubectl delete pod yourPodName |
更新 |
kubectl replace /path/to/yourNewYaml.yaml |
在Docker中,容器是最小的处理单元,增删改查的对象是容器,容器是一种虚拟化技术,容器之间是隔离的,隔离是基于Linux Namespace实现的。而在Kubernetes中,Pod包含一个或者多个相关的容器,Pod能够认为是容器的一种延伸扩展,一个Pod也是一个隔离体,而Pod内部包含的一组容器又是共享的(包括PID、Network、IPC、UTS)。除此以外,Pod中的容器能够访问共同的数据卷来实现文件系统的共享。
在kubernetes中,镜像的下载策略为:
Always:每次都下载最新的镜像
Never:只使用本地镜像,从不下载
IfNotPresent:只有当本地没有的时候才下载镜像
Pod被分配到Node以后会根据镜像下载策略进行镜像下载,能够根据自身集群的特色来决定采用何种下载策略。不管何种策略,都要确保Node上有正确的镜像可用。
经过yaml文件,能够在Pod中设置:
启动命令,如:spec-->containers-->command;
环境变量,如:spec-->containers-->env-->name/value;
端口桥接,如:spec-->containers-->ports-->containerPort/protocol/hostIP/hostPort(使用hostPort时须要注意端口冲突的问题,不过Kubernetes在调度Pod的时候会检查宿主机端口是否冲突,好比当两个Pod均要求绑定宿主机的80端口,Kubernetes将会将这两个Pod分别调度到不一样的机器上);
Host网络,一些特殊场景下,容器必需要以host方式进行网络设置(如接收物理机网络才可以接收到的组播流),在Pod中也支持host网络的设置,如:spec-->hostNetwork=true;
数据持久化,如:spec-->containers-->volumeMounts-->mountPath;
重启策略,当Pod中的容器终止退出后,重启容器的策略。这里的所谓Pod的重启,实际上的作法是容器的重建,以前容器中的数据将会丢失,若是须要持久化数据,那么须要使用数据卷进行持久化设置。Pod支持三种重启策略:Always(默认策略,当容器终止退出后,老是重启容器)、OnFailure(当容器终止且异常退出时,重启)、Never(从不重启);
Replication Controller(RC)是Kubernetes中的另外一个核心概念,应用托管在Kubernetes以后,Kubernetes须要保证应用可以持续运行,这是RC的工做内容,它会确保任什么时候间Kubernetes中都有指定数量的Pod在运行。在此基础上,RC还提供了一些更高级的特性,好比滚动升级、升级回滚等。
RC与Pod的关联是经过Label来实现的。Label机制是Kubernetes中的一个重要设计,经过Label进行对象的弱关联,能够灵活地进行分类和选择。对于Pod,须要设置其自身的Label来进行标识,Label是一系列的Key/value对,在Pod-->metadata-->labeks中进行设置。
Label的定义是任一的,可是Label必须具备可标识性,好比设置Pod的应用名称和版本号等。另外Lable是不具备惟一性的,为了更准确的标识一个Pod,应该为Pod设置多个维度的label。以下:
"release" : "stable", "release" : "canary"
"environment" : "dev", "environment" : "qa", "environment" : "production"
"tier" : "frontend", "tier" : "backend", "tier" : "cache"
"partition" : "customerA", "partition" : "customerB"
"track" : "daily", "track" : "weekly"
举例,当你在RC的yaml文件中定义了该RC的selector中的label为app:my-web,那么这个RC就会去关注Pod-->metadata-->labeks中label为app:my-web的Pod。修改了对应Pod的Label,就会使Pod脱离RC的控制。一样,在RC运行正常的时候,若试图继续建立一样Label的Pod,是建立不出来的。由于RC认为副本数已经正常了,再多起的话会被RC删掉的。
弹性伸缩是指适应负载变化,以弹性可伸缩的方式提供资源。反映到Kubernetes中,指的是可根据负载的高低动态调整Pod的副本数量。调整Pod的副本数是经过修改RC中Pod的副本是来实现的,示例命令以下:
扩容Pod的副本数目到10
$ kubectl scale relicationcontroller yourRcName --replicas=10
缩容Pod的副本数目到1
$ kubectl scale relicationcontroller yourRcName --replicas=1
滚动升级是一种平滑过渡的升级方式,经过逐步替换的策略,保证总体系统的稳定,在初始升级的时候就能够及时发现、调整问题,以保证问题影响度不会扩大。Kubernetes中滚动升级的命令以下:
$ kubectl rolling-update my-rcName-v1 -f my-rcName-v2-rc.yaml --update-period=10s
升级开始后,首先依据提供的定义文件建立V2版本的RC,而后每隔10s(--update-period=10s)逐步的增长V2版本的Pod副本数,逐步减小V1版本Pod的副本数。升级完成以后,删除V1版本的RC,保留V2版本的RC,及实现滚动升级。
升级过程当中,发生了错误中途退出时,能够选择继续升级。Kubernetes可以智能的判断升级中断以前的状态,而后紧接着继续执行升级。固然,也能够进行回退,命令以下:
$ kubectl rolling-update my-rcName-v1 -f my-rcName-v2-rc.yaml --update-period=10s --rollback
回退的方式实际就是升级的逆操做,逐步增长V1.0版本Pod的副本数,逐步减小V2版本Pod的副本数。
这里所说的replica set,能够被认为 是“升级版”的Replication Controller。也就是说。replica set也是用于保证与label selector匹配的pod数量维持在指望状态。区别在于,replica set引入了对基于子集的selector查询条件,而Replication Controller仅支持基于值相等的selecto条件查询。这是目前从用户角度肴,二者惟一的显著差别。 社区引入这一API的初衷是用于取代vl中的Replication Controller,也就是说.当v1版本被废弃时,Replication Controller就完成了它的历史使命,而由replica set来接管其工做。虽然replica set能够被单独使用,可是目前它多被Deployment用于进行pod的建立、更新与删除。Deployment在滚动更新等方面提供了不少很是有用的功能,关于DeplOymCn的更多信息,读者们能够在后续小节中得到。
为了适应快速的业务需求,微服务架构已经逐渐成为主流,微服务架构的应用须要有很是好的服务编排支持。Kubernetes中的核心要素Service便提供了一套简化的服务代理和发现机制,自然适应微服务架构。
在Kubernetes中,在受到RC调控的时候,Pod副本是变化的,对于的虚拟IP也是变化的,好比发生迁移或者伸缩的时候。这对于Pod的访问者来讲是不可接受的。Kubernetes中的Service是一种抽象概念,它定义了一个Pod逻辑集合以及访问它们的策略,Service同Pod的关联一样是居于Label来完成的。Service的目标是提供一种桥梁, 它会为访问者提供一个固定访问地址,用于在访问时重定向到相应的后端,这使得非 Kubernetes原生应用程序,在无须为Kubemces编写特定代码的前提下,轻松访问后端。
Service同RC同样,都是经过Label来关联Pod的。当你在Service的yaml文件中定义了该Service的selector中的label为app:my-web,那么这个Service会将Pod-->metadata-->labeks中label为app:my-web的Pod做为分发请求的后端。当Pod发生变化时(增长、减小、重建等),Service会及时更新。这样一来,Service就能够做为Pod的访问入口,起到代理服务器的做用,而对于访问者来讲,经过Service进行访问,无需直接感知Pod。
须要注意的是,Kubernetes分配给Service的固定IP是一个虚拟IP,并非一个真实的IP,在外部是没法寻址的。真实的系统实现上,Kubernetes是经过Kube-proxy组件来实现的虚拟IP路由及转发。因此在以前集群部署的环节上,咱们在每一个Node上均部署了Proxy这个组件,从而实现了Kubernetes层级的虚拟转发网络。
当Service的Endpoints包含多个IP的时候,及服务代理存在多个后端,将进行请求的负载均衡。默认的负载均衡策略是轮训或者随机(有kube-proxy的模式决定)。同时,Service上经过设置Service-->spec-->sessionAffinity=ClientIP,来实现基于源IP地址的会话保持。
1.4.3.3 发布Service
Service的虚拟IP是由Kubernetes虚拟出来的内部网络,外部是没法寻址到的。可是有些服务又须要被外部访问到,例如web前段。这时候就须要加一层网络转发,即外网到内网的转发。Kubernetes提供了NodePort、LoadBalancer、Ingress三种方式。
NodePort,在以前的Guestbook示例中,已经延时了NodePort的用法。NodePort的原理是,Kubernetes会在每个Node上暴露出一个端口:nodePort,外部网络能够经过(任一Node)[NodeIP]:[NodePort]访问到后端的Service。
LoadBalancer,在NodePort基础上,Kubernetes能够请求底层云平台建立一个负载均衡器,将每一个Node做为后端,进行服务分发。该模式须要底层云平台(例如GCE)支持。
Ingress,是一种HTTP方式的路由转发机制,由Ingress Controller和HTTP代理服务器组合而成。Ingress Controller实时监控Kubernetes API,实时更新HTTP代理服务器的转发规则。HTTP代理服务器有GCE Load-Balancer、HaProxy、Nginx等开源方案。
Kubernetes中有一个很重要的服务自发现特性。一旦一个service被建立,该service的service IP和service port等信息均可以被注入到pod中供它们使用。Kubernetes主要支持两种service发现 机制:环境变量和DNS。
环境变量方式
Kubernetes建立Pod时会自动添加全部可用的service环境变量到该Pod中,若有须要.这些环境变量就被注入Pod内的容器里。须要注意的是,环境变量的注入只发送在Pod建立时,且不会被自动更新。这个特色暗含了service和访问该service的Pod的建立时间的前后顺序,即任何想要访问service的pod都须要在service已经存在后建立,不然与service相关的环境变量就没法注入该Pod的容器中,这样先建立的容器就没法发现后建立的service。
DNS方式
Kubernetes集群如今支持增长一个可选的组件——DNS服务器。这个DNS服务器使用Kubernetes的watchAPI,不间断的监测新的service的建立并为每一个service新建一个DNS记录。若是DNS在整个集群范围内均可用,那么全部的Pod都可以自动解析service的域名。Kube-DNS搭建及更详细的介绍请见:基于Kubernetes集群部署skyDNS服务
此处设计思想是,Kubernetes经过为每一个service分配一个惟一的ClusterIP,因此当使用ClusterIP:port的组合访问一个service的时候,无论port是什么,这个组合是必定不会发生重复的。另外一方面,kube-proxy为每一个service真正打开的是一个绝对不会重复的随机端口,用户在service描述文件中指定的访问端口会被映射到这个随机端口上。这就是为何用户能够在建立service时随意指定访问端口。
Kubernetes提供了一种更加简单的更新RC和Pod的机制,叫作Deployment。经过在Deployment中描述你所指望的集群状态,Deployment Controller会将如今的集群状态在一个可控的速度下逐步更新成你所指望的集群状态。Deployment主要职责一样是为了保证pod的数量和健康,90%的功能与Replication Controller彻底同样,能够看作新一代的Replication Controller。可是,它又具有了Replication Controller以外的新特性:
Replication Controller所有功能:Deployment继承了上面描述的Replication Controller所有功能。
事件和状态查看:能够查看Deployment的升级详细进度和状态。
回滚:当升级pod镜像或者相关参数的时候发现问题,可使用回滚操做回滚到上一个稳定的版本或者指定的版本。
版本记录: 每一次对Deployment的操做,都能保存下来,给予后续可能的回滚使用。
暂停和启动:对于每一次升级,都可以随时暂停和启动。
多种升级方案:Recreate----删除全部已存在的pod,从新建立新的; RollingUpdate----滚动升级,逐步替换的策略,同时滚动升级时,支持更多的附加参数,例如设置最大不可用pod数量,最小升级间隔时间等等。
相比于RC,Deployment直接使用kubectl edit deployment/deploymentName 或者kubectl set方法就能够直接升级(原理是Pod的template发生变化,例如更新label、更新镜像版本等操做会触发Deployment的滚动升级)。操做示例——首先 咱们一样定义一个nginx-deploy-v1.yaml的文件,副本数量为2:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
建立deployment:
$ kubectl create -f nginx-deploy-v1.yaml --record
deployment "nginx-deployment" created
$ kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 3 0 0 0 1s
$ kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 3 3 3 3 18s
正常以后,将nginx的版本进行升级,从1.7升级到1.9。第一种方法,直接set镜像:
$ kubectl set image deployment/nginx-deployment2 nginx=nginx:1.9
deployment "nginx-deployment2" image updated
第二种方法,直接edit:
$ kubectl edit deployment/nginx-deployment
deployment "nginx-deployment2" edited
查看Deployment的变动信息(如下信息得以保存,是建立时候加的“--record”这个选项起的做用):
$ kubectl rollout history deployment/nginx-deployment
deployments "nginx-deployment":
REVISION CHANGE-CAUSE
1 kubectl create -f docs/user-guide/nginx-deployment.yaml --record
2 kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
3 kubectl set image deployment/nginx-deployment nginx=nginx:1.91
$ kubectl rollout history deployment/nginx-deployment --revision=2
deployments "nginx-deployment" revision 2
Labels: app=nginx
pod-template-hash=1159050644
Annotations: kubernetes.io/change-cause=kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
Containers:
nginx:
Image: nginx:1.9.1
Port: 80/TCP
QoS Tier:
cpu: BestEffort
memory: BestEffort
Environment Variables: <none>
No volumes.
最后介绍下Deployment的一些基础命令。
$ kubectl describe deployments #查询详细信息,获取升级进度
$ kubectl rollout pause deployment/nginx-deployment2 #暂停升级
$ kubectl rollout resume deployment/nginx-deployment2 #继续升级
$ kubectl rollout undo deployment/nginx-deployment2 #升级回滚
$ kubectl scale deployment nginx-deployment --replicas 10 #弹性伸缩Pod数量
关于多重升级,举例,当你建立了一个nginx1.7的Deployment,要求副本数量为5以后,Deployment Controller会逐步的将5个1.7的Pod启动起来;当启动到3个的时候,你又发出更新Deployment中Nginx到1.9的命令;这时Deployment Controller会当即将已启动的3个1.7Pod杀掉,而后逐步启动1.9的Pod。Deployment Controller不会等到1.7的Pod都启动完成以后,再依次杀掉1.7,启动1.9。
在Docker的设计实现中,容器中的数据是临时的,即当容器被销毁时,其中的数据将会丢失。若是须要持久化数据,须要使用Docker数据卷挂载宿主机上的文件或者目录到容器中。在Kubernetes中,当Pod重建的时候,数据是会丢失的,Kubernetes也是经过数据卷挂载来提供Pod数据的持久化的。Kubernetes数据卷是对Docker数据卷的扩展,Kubernetes数据卷是Pod级别的,能够用来实现Pod中容器的文件共享。目前,Kubernetes支持的数据卷类型以下:
1) EmptyDir
2) HostPath
3) GCE Persistent Disk
4) AWS Elastic Block Store
5) NFS
6) iSCSI
7) Flocker
8) GlusterFS
9) RBD
10) Git Repo
11) Secret
12) Persistent Volume Claim
理解每一个存储系统是一件复杂的事情,特别是对于普通用户来讲,有时候并不须要关心各类存储实现,只但愿可以安全可靠地存储数据。Kubernetes中提供了Persistent Volume和Persistent Volume Claim机制,这是存储消费模式。Persistent Volume是由系统管理员配置建立的一个数据卷(目前支持HostPath、GCE Persistent Disk、AWS Elastic Block Store、NFS、iSCSI、GlusterFS、RBD),它表明了某一类存储插件实现;而对于普通用户来讲,经过Persistent Volume Claim可请求并得到合适的Persistent Volume,而无须感知后端的存储实现。Persistent Volume和Persistent Volume Claim的关系其实相似于Pod和Node,Pod消费Node资源,Persistent Volume Claim则消费Persistent Volume资源。Persistent Volume和Persistent Volume Claim相互关联,有着完整的生命周期管理:
1) 准备:系统管理员规划或建立一批Persistent Volume;
2) 绑定:用户经过建立Persistent Volume Claim来声明存储请求,Kubernetes发现有存储请求的时候,就去查找符合条件的Persistent Volume(最小知足策略)。找到合适的就绑定上,找不到就一直处于等待状态;
3) 使用:建立Pod的时候使用Persistent Volume Claim;
4) 释放:当用户删除绑定在Persistent Volume上的Persistent Volume Claim时,Persistent Volume进入释放状态,此时Persistent Volume中还残留着上一个Persistent Volume Claim的数据,状态还不可用;
5) 回收:是否的Persistent Volume须要回收才能再次使用。回收策略能够是人工的也能够是Kubernetes自动进行清理(仅支持NFS和HostPath)
自动扩展做为一个长久的议题,一直为人们津津乐道。系统可以根据负载的变化对计算资源的分配进行自动的扩增或者收缩,无疑是一个很是吸引人的特征,它可以最大可能地减小费用或者其余代价(如电力损耗)。自动扩展主要分为两种,其一为水平扩展,针对于实例数目的增减;其二为垂直扩展,即单个实例可使用的资源的增减。Horizontal Pod Autoscaler(HPA)属于前者。
Horizontal Pod Autoscaler的操做对象是Replication Controller、ReplicaSet或Deployment对应的Pod,根据观察到的CPU实际使用量与用户的指望值进行比对,作出是否须要增减实例数量的决策。controller目前使用heapSter来检测CPU使用量,检测周期默认是30秒。
在HPA Controller检测到CPU的实际使用量以后,会求出当前的CPU使用率(实际使用量与pod 请求量的比率)。而后,HPA Controller会经过调整副本数量使得CPU使用率尽可能向指望值靠近.另外,考虑到自动扩展的决策可能须要一段时间才会生效,甚至在短期内会引入一些噪声. 例如当pod所须要的CPU负荷过大,从而运行一个新的pod进行分流,在建立的过程当中,系统的CPU使用量可能会有一个攀升的过程。因此,在每一次做出决策后的一段时间内,将再也不进行扩展决策。对于ScaleUp而言,这个时间段为3分钟,Scaledown为5分钟。再者HPA Controller容许必定范围内的CPU使用量的不稳定,也就是说,只有当aVg(CurrentPodConsumption/Target低于0.9或者高于1.1时才进行实例调整,这也是出于维护系统稳定性的考虑。
编辑dashboard.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
# Keep the name in sync with image version and
# gce/coreos/kube-manifests/addons/dashboard counterparts
name: kubernetes-dashboard-latest
namespace: kube-system
spec:
replicas: 1
template:
metadata:
labels:
k8s-app: kubernetes-dashboard
version: latest
kubernetes.io/cluster-service: "true"
spec:
containers:
- name: kubernetes-dashboard
image: index.tenxcloud.com/google_containers/kubernetes-dashboard-amd64:v1.4.1
resources:
# keep request = limit to keep this container in guaranteed class
limits:
cpu: 100m
memory: 50Mi
requests:
cpu: 100m
memory: 50Mi
ports:
- containerPort: 9090
args:
- --apiserver-host=http://10.0.0.11:8080
livenessProbe:
httpGet:
path: /
port: 9090
initialDelaySeconds: 30
timeoutSeconds: 30
编辑dashboardsvc.yaml文件
apiVersion: v1
kind: Service
metadata:
name: kubernetes-dashboard
namespace: kube-system
labels:
k8s-app: kubernetes-dashboard
kubernetes.io/cluster-service: "true"
spec:
selector:
k8s-app: kubernetes-dashboard
ports:
- port: 80
targetPort: 9090
在master执行以下命令:
kubectl create -f dashboard.yaml
kubectl create -f dashboardsvc.yaml
[root@k8s-master ~]# kubectl get deployment --all-namespaces
NAMESPACE NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
kube-system kubernetes-dashboard-latest 1 1 1 1 1h
[root@k8s-master ~]# kubectl get svc --all-namespaces
NAMESPACE NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default kubernetes 10.254.0.1 <none> 443/TCP 9d
kube-system kubernetes-dashboard 10.254.44.119 <none> 80/TCP 1h
[root@k8s-master ~]# kubectl get pod -o wide --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE
kube-system kubernetes-dashboard-latest-3866786896-vsf3h 1/1 Running 0 1h 10.0.82.2 k8s-node-1
打开浏览器访问:http://10.0.0.11:8080/ui/
编辑skydns-rc.yaml文件
# Copyright 2016 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# TODO - At some point, we need to rename all skydns-*.yaml.* files to kubedns-*.yaml.*
# Should keep target in cluster/addons/dns-horizontal-autoscaler/dns-horizontal-autoscaler.yaml
# in sync with this file.
# __MACHINE_GENERATED_WARNING__
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: kube-dns
namespace: kube-system
labels:
k8s-app: kube-dns
kubernetes.io/cluster-service: "true"
spec:
replicas: 1
# replicas: not specified here:
# 1. In order to make Addon Manager do not reconcile this replicas parameter.
# 2. Default is 1.
# 3. Will be tuned in real time if DNS horizontal auto-scaling is turned on.
strategy:
rollingUpdate:
maxSurge: 10%
maxUnavailable: 0
selector:
matchLabels:
k8s-app: kube-dns
template:
metadata:
labels:
k8s-app: kube-dns
annotations:
scheduler.alpha.kubernetes.io/critical-pod: ''
scheduler.alpha.kubernetes.io/tolerations: '[{"key":"CriticalAddonsOnly", "operator":"Exists"}]'
spec:
containers:
- name: kubedns
image: myhub.fdccloud.com/library/kubedns-amd64:1.9
resources:
# TODO: Set memory limits when we've profiled the container for large
# clusters, then set request = limit to keep this container in
# guaranteed class. Currently, this container falls into the
# "burstable" category so the kubelet doesn't backoff from restarting it.
limits:
memory: 170Mi
requests:
cpu: 100m
memory: 70Mi
livenessProbe:
httpGet:
path: /healthz-kubedns
port: 8080
scheme: HTTP
initialDelaySeconds: 60
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 5
readinessProbe:
httpGet:
path: /readiness
port: 8081
scheme: HTTP
# we poll on pod startup for the Kubernetes master service and
# only setup the /readiness HTTP server once that's available.
initialDelaySeconds: 3
timeoutSeconds: 5
args:
- --domain=cluster.local.
- --dns-port=10053
- --config-map=kube-dns
- --kube-master-url=http://10.0.0.11:8080
# This should be set to v=2 only after the new image (cut from 1.5) has
# been released, otherwise we will flood the logs.
- --v=0
#__PILLAR__FEDERATIONS__DOMAIN__MAP__
env:
- name: PROMETHEUS_PORT
value: "10055"
ports:
- containerPort: 10053
name: dns-local
protocol: UDP
- containerPort: 10053
name: dns-tcp-local
protocol: TCP
- containerPort: 10055
name: metrics
protocol: TCP
- name: dnsmasq
image: myhub.fdccloud.com/library/kube-dnsmasq-amd64:1.4
livenessProbe:
httpGet:
path: /healthz-dnsmasq
port: 8080
scheme: HTTP
initialDelaySeconds: 60
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 5
args:
- --cache-size=1000
- --no-resolv
- --server=127.0.0.1#10053
#- --log-facility=-
ports:
- containerPort: 53
name: dns
protocol: UDP
- containerPort: 53
name: dns-tcp
protocol: TCP
# see: https://github.com/kubernetes/kubernetes/issues/29055 for details
resources:
requests:
cpu: 150m
memory: 10Mi
- name: dnsmasq-metrics
image: myhub.fdccloud.com/library/dnsmasq-metrics-amd64:1.0
livenessProbe:
httpGet:
path: /metrics
port: 10054
scheme: HTTP
initialDelaySeconds: 60
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 5
args:
- --v=2
- --logtostderr
ports:
- containerPort: 10054
name: metrics
protocol: TCP
resources:
requests:
memory: 10Mi
- name: healthz
image: myhub.fdccloud.com/library/exechealthz-amd64:1.2
resources:
limits:
memory: 50Mi
requests:
cpu: 10m
# Note that this container shouldn't really need 50Mi of memory. The
# limits are set higher than expected pending investigation on #29688.
# The extra memory was stolen from the kubedns container to keep the
# net memory requested by the pod constant.
memory: 50Mi
args:
- --cmd=nslookup kubernetes.default.svc.cluster.local 127.0.0.1 >/dev/null
- --url=/healthz-dnsmasq
- --cmd=nslookup kubernetes.default.svc.cluster.local 127.0.0.1:10053 >/dev/null
- --url=/healthz-kubedns
- --port=8080
- --quiet
ports:
- containerPort: 8080
protocol: TCP
dnsPolicy: Default # Don't use cluster DNS.
编辑skydns-svc.yaml文件
# Copyright 2016 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# TODO - At some point, we need to rename all skydns-*.yaml.* files to kubedns-*.yaml.*
# Warning: This is a file generated from the base underscore template file: skydns-svc.yaml.base
apiVersion: v1
kind: Service
metadata:
name: kube-dns
namespace: kube-system
labels:
k8s-app: kube-dns
kubernetes.io/cluster-service: "true"
kubernetes.io/name: "KubeDNS"
spec:
selector:
k8s-app: kube-dns
clusterIP: 10.254.230.254
ports:
- name: dns
port: 53
protocol: UDP
- name: dns-tcp
port: 53
protocol: TCP
在master执行以下命令:
kubectl create -f skydns-rc.yaml
kubectl create -f skydns-svc.yaml
查询dns服务的clusterip。
kubectl get svc --namespace=kube-system
[root@k8s-matser ~]# kubectl get svc --namespace=kube-system
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns 10.254.230.254 <none> 53/UDP,53/TCP 7m
kubernetes-dashboard 10.254.249.6 <none> 80/TCP 4h
修改各node节点上的/etc/kubernetes/kubelet配置文件,增长以下行:
KUBELET_ARGS="--cluster_dns=10.254.230.254 --cluster_domain=cluster.local"
重启各node节点kubelet:
systemctl restart kubelet
添加一个busybox的pod用于测试,busybox.yaml内容以下:
apiVersion: v1
kind: Pod
metadata:
labels:
name: busybox
role: master
name: busybox
spec:
containers:
- name: busybox
image: myhub.fdccloud.com/library/busybox
command:
- sleep
- "3600"
执行以下操做:
kubectl exec -it busybox sh
nslookup kubernetes
nslookup kubernetes.default.svc.cluster.local
若是能正常解析,则部署OK。
Heapster是kubernetes集群监控工具。在1.2的时候,kubernetes的监控须要在node节点上运行cAdvisor做为agent收集本机和容器的资源数据,包括cpu、内存、网络、文件系统等。在新版的kubernetes中,cAdvisor被集成到kubelet中。经过netstat能够查看到kubelet新开了一个4194的端口,这就是cAdvisor监听的端口,如今咱们而后能够经过http://<node-ip>:4194的方式访问到cAdvisor。Heapster就是经过每一个node上的kubelet,也就是实际的cAdvisor上收集数据并汇总,保存到后端存储中。
Heapster支持多种后端存储,包括influxDB,Elasticsearch,Kafka等,在这篇文档里,咱们使用influxDB做为后端存储来展现heapster的相关配置。须要说明的是,heapster依赖kubernetes dns配置。
建立目录heapster-influxdb,在目录中建立如下文件
[root@k8s-master heapster-influxdb]# cat influxdb-grafana-controller.yaml
apiVersion: v1
kind: ReplicationController
metadata:
labels:
name: influxGrafana
name: influxdb-grafana
namespace: kube-system
spec:
replicas: 1
selector:
name: influxGrafana
template:
metadata:
labels:
name: influxGrafana
spec:
containers:
- name: influxdb
image: docker.io/kubernetes/heapster_influxdb:v0.5
volumeMounts:
- mountPath: /data
name: influxdb-storage
- name: grafana
image: docker.io/kubernetes/heapster_grafana:v2.6.0
env:
- name: INFLUXDB_SERVICE_URL
value: http://monitoring-influxdb:8086
# The following env variables are required to make Grafana accessible via
# the kubernetes api-server proxy. On production clusters, we recommend
# removing these env variables, setup auth for grafana, and expose the grafana
# service using a LoadBalancer or a public IP.
- name: GF_AUTH_BASIC_ENABLED
value: "false"
- name: GF_AUTH_ANONYMOUS_ENABLED
value: "true"
- name: GF_AUTH_ANONYMOUS_ORG_ROLE
value: Admin
- name: GF_SERVER_ROOT_URL
value: /api/v1/proxy/namespaces/kube-system/services/monitoring-grafana/
volumeMounts:
- mountPath: /var
name: grafana-storage
volumes:
- name: influxdb-storage
emptyDir: {}
- name: grafana-storage
emptyDir: {}
#######
[root@k8s-master heapster-influxdb]# cat grafana-service.yaml
apiVersion: v1
kind: Service
metadata:
labels:
kubernetes.io/cluster-service: 'true'
kubernetes.io/name: monitoring-grafana
name: monitoring-grafana
namespace: kube-system
spec:
# In a production setup, we recommend accessing Grafana through an external Loadbalancer
# or through a public IP.
# type: LoadBalancer
ports:
- port: 80
targetPort: 3000
selector:
name: influxGrafana
#########
[root@k8s-master heapster-influxdb]# cat influxdb-service.yaml
apiVersion: v1
kind: Service
metadata:
labels: null
name: monitoring-influxdb
namespace: kube-system
spec:
ports:
- name: http
port: 8083
targetPort: 8083
- name: api
port: 8086
targetPort: 8086
selector:
name: influxGrafana
#######
[root@k8s-master heapster-influxdb]# cat heapster-controller.yaml
apiVersion: v1
kind: ReplicationController
metadata:
labels:
k8s-app: heapster
name: heapster
version: v6
name: heapster
namespace: kube-system
spec:
replicas: 1
selector:
k8s-app: heapster
version: v6
template:
metadata:
labels:
k8s-app: heapster
version: v6
spec:
containers:
- name: heapster
image: docker.io/kubernetes/heapster:canary
imagePullPolicy: Always
command:
- /heapster
- --source=kubernetes:http://10.0.0.11:8080?inClusterConfig=false
- --sink=influxdb:http://monitoring-influxdb:8086
########
[root@k8s-master heapster-influxdb]# cat heapster-service.yaml
apiVersion: v1
kind: Service
metadata:
labels:
kubernetes.io/cluster-service: 'true'
kubernetes.io/name: Heapster
name: heapster
namespace: kube-system
spec:
ports:
- port: 80
targetPort: 8082
selector:
k8s-app: heapster
一个个的yaml文件建立太慢,能够直接指定目录来建立
[root@k8s-master ~]# kubectl create -f influxdb/
service "monitoring-grafana" created
replicationcontroller "heapster" created
service "heapster" created
replicationcontroller "influxdb-grafana" created
service "monitoring-influxdb" created
systemctl restart kube-apiserver.service
登陆dashboard,出现cpu和内存使用即成功
准备配置文件
[root@k8s-master ~]# cat wordpres_nfs_pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv0001
labels:
type: nfs001
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Recycle
nfs:
path: "/data/web"
server: 10.0.0.11
readOnly: false
#######
[root@k8s-master ~]# cat wordpress_nfs_pvc.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: nfs
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi
########
[root@k8s-master ~]# cat mysql_nfs_pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv0002
labels:
type: nfs002
spec:
capacity:
storage: 20Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Recycle
nfs:
path: "/data/db"
server: 10.0.0.11
readOnly: false
############
[root@k8s-master ~]# cat mysql_nfs_pvc.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: nfs2
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 2Gi
[root@k8s-master ~]# kubectl create -f wordpress_nfs_pv.yaml
[root@k8s-master ~]# kubectl create -f wordpress_nfs_pvc.yaml
[root@k8s-master ~]# kubectl create -f mysql_nfs_pv.yaml
[root@k8s-master ~]# kubectl create -f mysql_nfs_pvc.yaml
[root@k8s-master ~]# cat mysql-rc.yaml
apiVersion: v1
kind: ReplicationController
metadata:
name: mysql
spec:
replicas: 1
selector:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: 10.0.0.11:5000/mysql:5.7
ports:
- containerPort: 3306
volumeMounts:
- name: nfs-vol2
mountPath: /var/lib/mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: "somewordpress"
- name: MYSQL_DATABASE
value: "wordpress"
- name: MYSQL_USER
value: "wordpress"
- name: MYSQL_PASSWORD
value: "wordpress"
volumes:
- name: nfs-vol2
persistentVolumeClaim:
claimName: nfs2
#########
[root@k8s-master ~]# cat mysql-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
clusterIP: 10.254.178.148
ports:
- port: 3306
selector:
app: mysql
#######
[root@k8s-master ~]# kubectl create -f mysql-rc.yaml
[root@k8s-master ~]# kubectl create -f mysql-svc.yaml
[root@k8s-master ~]# cat myweb-rc-nfs.yaml
apiVersion: v1
kind: ReplicationController
metadata:
name: myweb
spec:
replicas: 1
selector:
app: myweb
template:
metadata:
labels:
app: myweb
spec:
nodeName: '10.0.0.13'
containers:
- name: myweb
image: 10.0.0.11:5000/wordpress:latest
ports:
- containerPort: 80
volumeMounts:
- name: nfs-vol
mountPath: /var/www/html
env:
- name: WORDPRESS_DB_HOST
value: '10.254.178.148'
- name: WORDPRESS_DB_USER
value: 'wordpress'
- name: WORDPRESS_DB_PASSWORD
value: 'wordpress'
volumes:
- name: nfs-vol
persistentVolumeClaim:
claimName: nfs
#############
[root@k8s-master ~]# cat myweb-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: myweb
spec:
type: NodePort
ports:
- port: 80
nodePort: 30001
selector:
app: myweb
#################
[root@k8s-master ~]# kubectl create -f myweb-rc-nfs.yaml
[root@k8s-master ~]# kubectl create -f myweb-svc.yaml
访问http://10.0.0.12:30001安装wordpress,删除mysql或者myweb开头的pod,wordpress依旧能访问,数据不丢,即成功!