欢迎访问我的博客,你的支持,是我最大的动力!

从Docker到Kubernetes实践全接触(一)基础概念

Docker 小马奔腾 7413℃ 评论
目录:
[显示]

《Kubernetes权威指南》 2017.9

Kubernetes入门

Kubernetes是什么

Kubernetes是一个全新的基于容器技术的分布式架构解决方案

在Kubernetes中,Service是分布式集群架构的核心。一个Service对象拥有如下关键特征:
拥有一个唯一指定的名字
拥有一个虚拟IP(Cluster IP、Service IP或VIP)和端口号
能够提供某种远程服务能力
被映射到提供这种服务能力的一组容器应用上

Service的服务进程目前都基于Socket通信方式对外提供服务。K8s内建透明的负载均衡和故障恢复机制,通过service提供服务,service后端包括多个提供服务的服务进程(运行于容器中)。不需要再考虑服务IP地址的变化的问题

Pod对象,Pod中运行容器Container。为建立Service与Pod间的关联关系,首先为每个Pod都有设置一个标签Label,然后给相应的Service定义标签选择器Label Selector。

Pod运行于节点Node环境中,节点可以是物理机或者云或者虚拟机。通常一个节点上运行几百个Pod,每个Pod里运行一个特殊的容器Pause,其他容器则为业务容器,业务容器共享Pause容器的网络栈和Volume挂载卷

只有提供服务的Pod才会被映射成一个Service

集群管理方面,K8s将集群中机器区分为一个Master节点和一群工作节点Node。Master节点上运行管理相关的进程:kube-apiserver、kuba-controller-manager、kube-scheduler,这些进程实现整个集群的资源管理、Pod调度、弹性伸缩、安全控制、系统监控、纠错管理等功能,且都是自动完成的;Node是集群的工作结点,Node上K8s管理的最小运行单元是Pod,Node上运行K8s的kubelet、kube-proxy服务进程,负载Pod的创建、启动、监控、重启、销毁以及软负载均衡

K8s扩容,仅需为需扩容的Service关联的Pod创建一个RC(Replication Controller)
RC中定义3个关键信息:目标Pod定义、目标Pod需要运行的副本数量Replicas、要监控的目标Pod的标签Label
创建好RC后,系统根据RC中定义的Label筛选出对应Pod实例并实时监控其状态和数量,若发现数量小于副本数,则根据RC中定义的Pod模板创建Pod,这个过程是自动化的

为什么要用Kubernetes

微服务 超强横向扩展能力

从一个简单的例子开始

部署:
1)关闭防火墙服务
systemctl disable firewalld
systemctl stop firewalld
2)安装etcd和Kubernetes软件(会自动安装Docker软件)
#etcd是高可用、强一致性的服务发现存储仓库
yum install etcd kubernetes
3)按顺序启动所有服务
systemctl start etcd
systemctl start docker
systemctl start kube-apiserver
systemctl start kube-controller-manager
systemctl start kube-scheduler
systemctl start kubelet
systemctl start kube-proxy
一个单机版的Kubernetes集群就安装启动完成

测试镜像下载地址 https://hub.docker.com/u/kubeguide/

启动MySQL服务

先为MySQL服务创建一个RC定义文件:mysql-rc.yaml

创建好mysql-rc.yaml后,需要将其发布到集群中,在master节点执行命令
kubectl create -f mysql-rc.yaml
查看刚刚创建的RC
kubectl get rc
查看Pod创建情况
kubectl get pods

问题解决:
问题描述1
message: 'unable to create pods: No API token found for service account "default",
retry after the token is automatically created and added to the service account'
解决办法:
kubectl --version
Kubernetes v1.5.2
vi /etc/kubernetes/apiserver
注释行:KUBE_ADMISSION_CONTROL="--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota"
添加行:KUBE_ADMISSION_CONTROL=""
重启kube-apiserver服务
systemctl restart kube-apiserver
问题描述2
docker pull registry.access.redhat.com/rhel7/pod-infrastructure:latest
Trying to pull repository registry.access.redhat.com/rhel7/pod-infrastructure ...
open /etc/docker/certs.d/registry.access.redhat.com/redhat-ca.crt: no such file or directory
解决:
yum install *rhsm*
添加redhat-uep.pem文件
vi /etc/rhsm/ca/redhat-uep.pem
https://github.com/candlepin/python-rhsm/blob/master/etc-conf/ca/redhat-uep.pem
查看pods情况
kubectl describe pods
或者修改pod-infra镜像位置
cat /etc/kubernetes/kubelet
## pod infrastructure container
##KUBELET_POD_INFRA_CONTAINER="--pod-infra-container-image=registry.access.redhat.com/rhel7/pod-infrastructure:latest"

创建一个与之关联的Service

定义文件mysql-svc.yaml

其中metadata.name是服务名ServiceName,port属性定义虚端口,spec.selector确定哪些pod副本对应到本服务

创建service
kubectl create -f mysql-svc.yaml
查看service
kubectl get svc
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes 10.254.0.1 <none> 443/TCP 22h
mysql 10.254.167.198 <none> 3306/TCP 2m
mysql被分配了cluster ip为10.254.167.198,端口为3306,cluster ip是自动分配的,其它pod无法预先知道,需要一个服务发现机制,最初是使用环境变量

启动tomcat应用

创建tomcat的rc文件:myweb-rc.yaml

注意template下面的metadata和spec应为同一级别,否则报错:found invalid field spec for v1.ObjectMeta

tomcat容器内会使用环境变量MYSQL_SERVICE_HOST的值连接MySQL服务,更安全的用法是使用服务名称mysql

创建tomcat的rc
kubectl create -f myweb-rc.yaml
查看rc
kubectl get rc
查看pod
kubectl get pods

创建对应的service

type=NodePort和nodePort=30001两个属性,表明此serivce开启了NodePort方式的外网访问模式,在集群外,可以通过30001端口访问服务

创建服务
kubectl create -f myweb-svc.yaml
查看服务
kubectl get services
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes 10.254.0.1 <none> 443/TCP 23h
mysql 10.254.167.198 <none> 3306/TCP 35m
myweb 10.254.17.18 <nodes> 8080:30001/TCP 40s
Kubernetes基本概念和术语

Kubernetes中的资源会保存到etcd中持久化存储

Master

集群控制节点,负责整个集群的管理和控制。几乎所有控制命令都发给它,由它来具体负责执行过程,Master节点通常会占据一个独立服务器(高可用部署建议用3台服务器),原因是它太重要,若宕机或不可用,对集群内容器应用的管理将失效

master节点运行一组关键进程:
Kubernetes API Server,kube-apiserver,提供HTTP Rest接口,是所有资源增、删、改、查等操作的唯一入口,也是集群控制的入口进程
Kubernetes Controller Manager,kube-controller-manager,所有资源对象的自动化控制中心
Kubernetes Scheduler,kube-scheduler,负责资源调度(Pod调度)的进程
Master节点还需要启动一个etcd服务,用于保存所有资源对象的数据

Node

集群中除master外的节点,可以是物理主机,也可以是虚拟机,是集群工作负载节点,当某个node宕机时,其上的工作负载(docker容器)会被自动转移到其他节点上去

node节点运行一组关键进程:
kubelet,负责pod对应容器的创建、启停等任务,同时与master协作,实现集群管理的基本功能
kube-proxy,实现service的通信与负载均衡
Docker Engine,docker,负责容器创建和管理工作

node节点可以动态增加到集群中,前提是该节点上已正确安装、配置和启动上述关键进程。默认kubelet会向master汇报自身情况

查看集群中的所有node
kubectl get nodes
查看某个node的详细信息
kubectl describe node <node_name>
kubectl describe node 127.0.0.1
#node运行状态,node启动后会做自检,若磁盘满了,就标注OutOfDisk=True,否则继续检查内存,若内存不足,就标注MemoryPressure=True,最后一切正常,就设置Ready=True

Pod

Pod都有一个特殊的根容器Pause容器,Pause容器属于平台的一部分,此外还包含一个或多个紧密相关的用户业务容器

Pod里的多个业务容器共享Pause容器的IP/Volume,解决容器间通信和资源共享问题

k8s为每个pod都分配唯一ip地址,称为Pod IP,pod里的多个容器共享该ip

一个pod里的容器与另外主机上的pod容器能够直接通信,采用的是虚拟二层网络技术实现的,如flannel、open vswitch等

pod有两种类型:普通pod及静态pod(static pod),后者不存放在etcd存储里,而是存放在某个具体node上的具体文件中,且只在此node上启动运行

普通pod一但被创建,就存放在etcd中,随后被master调度到某个具体的node上并进行绑定binding,随后被对应node上的kubelet进程实例化成一组相关的docker容器并启动。默认pod中某个容器停止时,k8s会自动检测到这个问题并重启该pod(重启所有容器),若pod所在node宕机,则会将这个node上所有pod重新调度到其他节点上

k8s里所有资源对象都可以通过yaml或json格式的文件来定义或描述

Endpoint是Pod里服务进程对处通信的地址(端口)
Pod Volume是定义在Pod之上,被各个容器挂载到自己的文件系统中的
Event是一个事件的记录,记录事件最早产生时间、最后重现时间、重复次数、发起者、类型及导致此事件的原因等,event通常会关联到某个具体的资源上,是排查故障的重要参考信息

kubectl describe pod myweb

每个Pod都可以设置资源限额,主要是CPU和Memory,其中CPU单位为Core的数量,是绝对值。最小单位为千分之一的CPU,用m表示,通常一个容器CPU配额为100~300m,即0.1~0.3个CPU;Memory配额也是绝对值,单位是内存字节数

一个计算资源进行配额限定要设定两个参数:
Requests,该资源最小申请量,系统必须满足要求
Limits,最大允许使用量,不能被突破,当容器试图使用超过这个量的资源时,可能会被kill并重启
通常将Requests设置为一个比较小的数值,符合容器平时工作负载情况下的资源需求,把Limits设置为峰值负载情况下资源占用的最大值,如

Label 标签

一个Label是一个key-value的键值对,key与value由用户指定。label可以附加到各种资源上,如Node、Pod、Service、RC等
一个资源对象可以定义任意数量的label,同一个label可以被添加到任意数量的资源对象上,label通常在资源对象定义时确定,也可以在对象创建后动态添加或删除

label用来实现多维度资源分组管理
常用Label示例:
版本:"release":"stable"、"release":"canary"
环境:"environment":"dev"、"enviroment":"qa"、"environment":"production"
架构:"tier":"frontend"、"tier":"backend"、"tier":"middleware"
分区:"partition":"customerA"
质管:"track":"daily"、"track":"weekly"

Label定义后,可以通过Label Selector进行筛选。有两种方式,基于等式,基于集合,如
name=redis-slave
env!=production
name in (redis-master,redis-slave)
name not in (php-frontend)
多个表达式可以组合,用逗号分隔,多个条件间是AND的关系,即需要同时满足,如
name=redis-slave,env!=production

管理对象如Deployment、ReplicaSet、DaemonSet、Job可以在selector中使用基于集合的筛选条件定义

matchExpressions用于定义基于集合的筛选条件,可用的条件运算符有:In、NotIn、Exists、DoesNotExist
若同时设置matchLabels和matchExpressions,则两组条件为AND关系

Label Selector在K8s中的应用场景:
kube-controller通过资源对象RC定义的Label Selector筛选要监控的Pod副本数量,实现副本数量符合预期设定的全自动控制流程
kube-proxy通过Service的Label Selector选择对就的Pod,自动建立每个Service到对应Pod的请求转发路由表,实现智能负载均衡机制
对某些Node定义特定的Label,并在Pod定义文件中使用NodeSelector标签调度策略,kube-scheduler可以实现Pod定向调度的特性

Replication Controller

RC定义一个期望的场景,即声明某种Pod副本数量在任意时刻都符合某个预期值,包括三个部分:
Pod期待的副本数replicas
用于筛选目标Pod的Label Selector
当Pod数量小于预期时,用于创建Pod的模板template

运行中,可以通过修改RC的副本数量,实现Pod的动态缩放Scaling,如
kubectl scale rc myweb --replicas=3
删除RC并不会影响通过该RC已创建好的Pod,为了删除所有Pod,可以设置replicas的值为0,然后更新该RC
kubectl提供了stop和delete来一次性删除RC和RC控制的全部Pod
滚动升级
Replica Sets是Replication Controller的升级版,支持基于集合的Lable selector
Replica Sets和Deployment逐步替换之前的RC,v1.3
RC的特性与作用:
1)定义RC可以实现Pod的创建过程及副本数量的自动控制
2)RC里包括完整的Pod定义模板
3)RC通过Label Selector机制实现对Pod副本的控制
4)改变RC中Pod副本的数量,可以实现Pod的扩容或缩容
5)改变RC中模板中镜像版本,可以实现Pod的滚动升级

Deployment

Deployment内部使用Replica Set实现。相对于RC,最大的升级是可以看到Pod部署的进度

Deployment典型使用场景:
创建Deployment对象来生成对应的Replica Set并完成Pod副本的创建
检查Deployment状态查看部署动作是否完成
更新Deployment以创建新的Pod,如镜像升级
回滚到一个早先的Deployment版本
暂停Deployment以修改多个PodTemplateSpec配置项,再恢复,进行新的发布
扩展Deployment以应对高负载
清朝不再需要的旧版本ReplicaSets

Deployment的定义仅apiVersion和kind有所区别

创建Deployment
kubectl create -f tomcat-deployment.yaml
查看Deployment
kubectl describe deployments
kubectl get deployments
查看Replica Set
kubectl get rs
查看Pods
kubectl get pods

Horizontal Pod Autoscaler

Pod横向自动扩容。通过追踪分析RC控制的所有目标Pod负载变化情况来确定是否针对性调整目标Pod的副本数。负载度量指标:
CPUUtilizationPercentage
应用程序自定义的度量指标,如请求数TPS/QPS
CPUUtilizationPercentage是一个算术平均值,是目标Pod所有副本的CPU利用率的平均值,通常是1min的平均值,需要Heapster扩展组件来得到这个值,需要需部署Heapster,另外Pod还需要定义Pod Request的值

HPA的一个例子

除了通过定义yaml文件并调用kubectl create 创建HPA资源对象外,还可以通过命令行直接创建
kubectl autoscale deployment php-apache --cpu-percent=90 --min=1 --max=10

StatefulSet

RC、Deployment、DaemonSet和Job都是面向无状态的服务
MySQL集群、MongoDB集群、Akka集群、ZooKeeper集群是有状态集群

StatefulSet里每个Pod都有稳定、唯一的网络标识,可用来发现集群内的其他成员
StatefulSet控制的Pod副本的启停顺序是受控的,操作第n个Pod时,前n-1个已经是运行且准备好的状态
StatefulSet的Pod采用稳定持久化的存储卷,通过PV/PVC实现,删除Pod时默认不会删除与StatefulSet相关的存储卷

$(podname).$(headless service name)

Service服务

Service定义一个服务访问入口地址,前端应用通过该入口地址访问背后的一组Pod副本组成的集群实例,Service与Pod通过Label Selector实现无缝对接,RC则保证服务质量达到预期

每个Node上的kube-proxy实际是一个智能的软件负载均衡器,负责把对Service的请求转发到后端的某个Pod实例上,在内部实现服务的负载均衡与会话保持机制

创建:
kubectl create -f tomcat-service.yaml
查看endpoints
kubectl get endpoints
查看service的Cluster IP
kubectl get svc tomcat-service -o yaml

Kubernetes的服务发现机制

环境变量注入,DNS系统

外部系统访问Service的问题

Node IP,Node节点的IP
Pod IP,Pod的IP
Cluster IP,Service的IP

Cluster IP无法被ping,因为没有实体网络对象来响应

添加type: NodePort和nodePort:31002后,外部可以通过31002进行访问

对每个Service,我们通常需要配置一个对应的Load balancer,可以使用HAProxy、Nginx等

Volume存储卷

Volume是Pod中能够被多个容器访问的共享目录。K8s中定义的volume生命周期与Pod相同,和Pod内的容器无关,且支持GlusterFS、Ceph等先进的分布式文件系统

使用:在Pod上声明一个Volume,然后在容器里引用并Mount到容器的某个目录上

Volume类型:
1、emptyDir
初始内容为空,无须指定宿主机上的对应目录,自动分配,当Pod从Node上删除时,emptyDir中数据会被永久删除
2、hostPath
挂载宿主机上的文件或目录
3、gcePersistentDisk
使用谷歌公有云提供的永久磁盘,永久保存
4、awsElasticBlockStore
使用亚马逊公有云提供的存储
5、NFS
6、其他类型的Volume
iscsi、flocker、glusterfs、rbd、gitRepo、secret

Persistent Volume

PV可以理解成K8s集群中某个网络存储中对应的一块存储

PV只能是网络存储,不属于任何Node,但可以在每个Node上访问
PV独立于Pod定义

ReadWriteOnce,读写权限,只能被一个Node挂载
ReadOnlyMany,只读,允许被多个Node挂载
ReadWriteMany,读写,允许被多个Node挂载

如果某个Pod想申请PV,首先要定义一个PersistentVolumeClaim(PVC)对象,然后在Pod的Volume定义中引用PVC

PV在有状态的对象
Available,空闲
Bound,已经绑定到某个PVC上
Released,对应PVC已删除,但资源还没有被集群收回
Failed,PV自动回收失败

Namespace命名空间

K8s启动后,会创建一个名为default的Namespace,查看:
kubectl get namespaces

kubectl get pods --namespace=development

为每个租户创建一个Namespace可实现多租户资源隔离,结合资源配额管理,可以限定不同租户能占用的资源,如CPU使用量、内存使用量等

Annotation注解

用户任意定义的附加信息

转载请注明:轻风博客 » 从Docker到Kubernetes实践全接触(一)基础概念

喜欢 (1)or分享 (0)