k8s的管理角色
master
负责整个集群的管理和控制,基本上k8s的所有控制命令都由它来执行。
通常占据一个(高可用是3个)独立的服务器,因为其很重要,并且会启动一个etcd服务,用于存储k8s的资源对象数据。
master节点上的关键进程:
kube-apiserver:k8s中资源的增删改查的唯一入口,也是集群控制的入口进程。
kube-controller-manager:k8s中资源对象的自动化控制中心
kube-schedular:负责资源调度的进程

node
k8s集群中的工作负载节点,每个node都会被分配工作负载,当某个Node宕机时,其上的工作负载会被master自动转移到其他节点。
node节点上的关键进程:
kubelet:负责pod对应的容器的创建与启停
kube-proxy:实现k8s服务的通信与负载均衡
docker engine:负责本节点容器的创建与管理

kubectl get nodes #获取集群中的node
kubectl describe node nodeName #获取node的详细信息,如name labels 运行状态(磁盘 内存 cpu等资源) 资源量 主机信息等

k8s集群 node master工作方式
完备的node节点可以在运行期间动态的增加到k8s集群中,node中的kubelet进程会向master注册自己。
node被纳入集群管理范围后,会向master汇报自身信息(cpu、内存、pod等),master在获知每个node的资源使用情况后,可以实现高效均衡的资源调度策略;
如果node超时不上报信息,会被master判定为失联,node被设置为不可用,随后master会触发自动的工作负载转移。

pod
结构:pause容器 + 多个相关的业务容器
该结构的好处:
1)以与业务无关且不易死亡的pause容器作为pod的根容器,以pause容器的状态代表整个容器组的状态
2)pod中的业务容器可以共享pause容器的Ip和挂载的Volume
k8s为每个容器分配了唯一的Ip地址,称之为唯一PodIp,pod中的多个容器共享该PodIp。

pod分类:
普通pod与静态Pod
普通Pod:
创建后即存储到etcd中,随后会被master调度到某个具体的node上并进行绑定,node上的kublet进程会将该pod实例化为一组相关的docker容器并启动。
如果Pod中某个容器停止,k8s会自动检测到,并重启这个Pod中(pod下的所有容器);如果pod所在的Node宕机,则master会将该node上的所有pod重新调度到其他节点上。

静态pod:
不存储在etcd中,存放到具体node的具体文件中,并且只在此node上启动运行。

pod的Endpoint:pod的IP加上这里的容器端口,代表pod里的一个服务进程对外的通信地址;一个pod可能具有多个endpoint
pod volume:定义在pod之上,被各个容器挂在到自己的文件系统中。


envent:
一个事件的记录,包括事件的产生时间、最后重现时间、重复次数、发起者、类型等信息。
通常会关联到某个具体的资源对象中,用于排查故障。
如发现某个Pod无法创建时,可以通过pod的event记录获取具体的原因,指令如下:
kubectl describe pod podName

pod的资源配置
每个Pod都可以对其能使用的服务器上的计算资源设置限额,包括CPU和Memory两种
k8s中,以千分之一的cpu配额为最小单位,用m来表示。一个容器的cpu配额被定义为100-300m,即占用0.1-0.3个cpu。
注意:这里的配额是绝对值,无论1核数的机器还是38核数的机器,100m配额多代表的CPU的使用量都是一样的。
memory配额也是一个绝对值,他的单位是内存字节数。

k8s中,一个计算资源进行配额限定需要设定如下两个参数:
1)requests:资源的最小申请量,系统必须满足要求
2)limits:资源最大允许使用量,不可超过;如果试图超过时,可能会被kill并重启
资源设置技巧:
通常request设置为较小的数值,满足容器平时工作负载的资源需求;limit则为峰值负载下资源占用的最大量。下面是一个mysql的实例:
spec:
 containers:
 - name: db
   image: mysql
   resources:
    requests:
     memory: "64Mi"
     cpu:"250m"
    limits:
     memory: "128Mi"
     cpu:"500m"

label
一个Label是一个key=value的键值对,两者均是由用户指定。Label可以附加到各种资源对象上。
给指定的资源对象增加label,然后配合label selector查询和筛选用于某些label的资源对象,实现资源的分组管理。
常用的label实例:
版本标签:"release":"stable","release":"canary"...
环境标签:"env":"dev", "env":"qa", "env":"product"
架构标签:"tier":"frontend", "tier":"backend"...

两种label selector(标签选择器)表达式
1 基于等式,如:
name=redis-slave:匹配所有具有标签name=redis-slave的资源对象
env!=production:匹配所有不具有标签env=production的资源对象
2 基于集合,如:
name in (redis-master, redis-slave):匹配所有具有标签name=redis-slave或name=redis-master的资源对象
name not in (php):匹配所有不具有标签name=php的资源对象

可以通过使用多个label selector表达式的组合实现复杂的条件选择,多个表达式用“,”分隔即可,几个条件之间是“and”的关系,同时满足多个提哦啊见,如:
name=redis,env not in (product):具有标签name=redis且不具有标签env=product的资源。

新的管理对象,如Deployment、ReplicaSet等可以在Selector中使用基于集合的筛选条件定义,如:
selector:
    matchLabels:
     app:myweb
    matchExpressions:
     - {key: tier, operator: In, values:[fronted]}
matchLabels定义一组Label,与直接写在selector相同;
matchExpressions用于定义一组基于集合的筛选条件,可用运算符包括:In,NotIn,Exists和DoesNotExist。
两者同时使用,则表示“And”的含义。

label selector在k8s中的使用场景:
1)kube-controller:筛选要监控的pod副本的数量,实现pod副本的数量符合资源RC上定义的数量。
2)kube-proxy:获取满足条件的Pod,自动建立每个service到对应Pod的请求转发路由表,从而实现service的智能负载均衡机制。
3)kube-scheduler实现Pod定向调度


replication controller
rc,副本控制器,定义一种期望的场景,主要包括:
1)pod期待的副本数,k8s会通过新建或kill等方式保证该数量
2)用于筛选目标pod的label selector
3)当pod的副本数少于期望数量时,用于创建Pod的模板
4) 通过修改RC中Pod副本数量,可以实现pod的扩容或缩容功能
5) 通过修改Rc中Pod模板中的镜像的版本,可以实现Pod的滚动升级功能

通过kubectl scale实现修改RC的副本数量
kubectl scale rc redis-slave --replicas=3
注意:删除RC并不会影响已经通过该RC已经创建爱你好的Pod。为了删除Pod,可以设置relicas的值为0,然后更新该RC。
kubectl stop/delete 可以一次停止、删除RC与RC控制的全部Pod

RC在k8s的1.2中,升级为另外一个新的概念,Replica Set,与RC的唯一区别是支持了基于集合的label selector。
replica set与deployment逐渐替换了RC


deployment
更好的解决Pod的编排问题,RC的一次升级,可以随时知道当前Pod部署的进度。
使用场景:
1)创建deployment对象来生成对应的replica set,并完成Pod副本的创建
2)检查deployment的状态来看部署动作是否完成
3)更新deployment创建新的pod
4)当前不稳定,回滚
5)暂定deployment,以便于修改PodTemplateSpec的配置项
6)扩展deployment,应对高负载
7)查看deploymen的状态,作为是否发布成功的指标

deployment的定义与replica Set的定义很类似,只有API和Kind的不同如:
apiVersion: extensions/v1beta1   apiVersion: v1
kind: Deployment                  kind: ReplicaSet
metadata:                        metadate:
 name: nginx-deployment           name: nginx-repset

相关指令
kubectl create -f tomcat-deployment.yaml #创建deployment
kubectl get deployments #查看deploynent的信息
输出内容解释如下:
DESIRED: Pod副本的期望值,即deployment中定义的replica
CURREMT: 当前Replica的值,这个值应该不断增加,直到达到DESIRED为止
UP-TO-DATE:最新版本的Pod的数量,用于指示在滚动升级过程中,已经成功升级的Pod副本数
AVALIABLE: 当前集群中可用的Pod副本数

kubectl get rs #获取对应的replica set
kubectl get pods #获取对应的pod

1.4.7 Horizontal Pod Autoscaler - 横向自动扩容
如果流量激增导致需要进行Pod的扩容扩或缩容,一种解决方式是手动执行kubectl scale命令,但是这种显然不够智能。
分布式系统要能够根据当前负载的变化情况自动触发扩、缩容,这就是HPA。

HPA的两种Pod负载度量指标
1)CPUUtilizationPercentage:所有cpu利用率的平均值,一个Pod的cpu利用率是当前cpu的使用量除以他的Pod Request的值。
1.2版本的k8s需要安装Heapster来获取cpu使用率。
2)应用程序自定义的度量指标,比如服务在没秒内的请求数(TPS QPS)

HPA机制:
假如某一时刻CPUUP的值超过了80%,则意味着当前Pod副本很可能不足以支撑你接下来更多的请求,需要动态扩容;
的那个请求高峰过去以后,Pod的CPU利用率又会降下来,此时对应的Pod副本数应该自动减少到一个合理的水平。

HPA实例:
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata: 
  name: php-apache
  namespace:default
spec:
 maxReplicas:10
 minReplicas:1
 scaleTargetRef:
  kind:Deploymnet
  name:php-apache
 targetCPUUtilizationPercentage: 90

说明:该HPA控制的目标对象是名为php-apache的Deployment里的Pod副本,当其CPUUtilizationPercentage超过90%则会触发自动扩容,且Pod的副本数限制在1-10之间。

等价的命令行方式
kubectl autoscale deployment php-apache --cpu-percent=90 --min=1 --max=10

1.4.8 statefulSet
产生的原因:
如Mysql、MongoDb、Akka、zk等集群有如下特点:
1)每个节点都有固定身份ID,通过该ID,集群成员可以相互发现和通信
2)集群的规模是比较固定的
3)集群中每个节点都有状态,且会持久化
4)如果磁盘损坏,则某个节点无法正常运行,集群功能受损。

如果用RC/deployment控制Pod副本数的方式来实现上述有状态的集群,因为Pod的名字是随机的,且Pod的IP地址在运行期才确定且可能有变动,所以无法满足上述集群的特点。
statefulSet就是用于解决上述问题,有如下的特性:
1)statefulSet里的每个Pod都有稳定、唯一的网络标识,可以用来发现集群内的其他成员
2)statsfulSet控制的Pod副本的启停顺序是受控的,启动第n个Pod时,要求前n-1个pod已经是运行且准备好的状态
3)statsfulSet中的Pod采用持久化的存储卷,通过PV/PVC来实现。

statefulSet要与headless service配合使用,即在每个statsfulset的定义中要声明它属于哪个headless service。headless service与service的区别是没有cluster ip,解析headless service的DNS域名,则返回该service对应的全部Pod的endPoint列表。
StatefulSet在Headless Service的基础上为Stateful控制的每个Pod创建了一个DNS域名,域名格式为:
$(podname).$(headless service name)
如三节点的卡发卡的State服了Set集群,对应的headless service名字为kafaka,statefulSet的名字为kafaka,则statefulSet中3个Pod的DNS名称分别为:kafaka-0.kafaka,kafaka-1.kafaka,kafaka-3.kafaka,这些dns名称可以直接在集群的配置文件中固定下来。

1.4.9 service服务
Pod RC 与service的关系
service  --> labelSelector --> pods:service通过labelSelector与多个pod实现对接
rc  --> labelSelector --> pods:rc通过labelSelector保证pod副本个数的稳定

客户端 pod service是怎么交互的?
每个pod提供独立的Endpoint(PodIP + containerPort);
每个service拥有一个全局唯一的虚拟IP,即clusterIp,且clusterIp随着service的创建产生,且不会改变,通过label selector对应到多个pod。
服务发现:用service的name和service的cluster IP地址做一个DNS域名映射即可完美解决问题。(port通过service对应的rc来定义)
service实例:
apiVersion: v1
kind: service
metadata:
 name: tomcat-service
spec:
 ports:
 - port: 8080
 selector:
  tier: frontend

含义:定义了名为“tomcat-service”的service,端口8080,拥有"tier: frontend"的pod都属于该service,创建指令:
kubectl create -f tomcat-server.yaml
kubectl get endpoints :获取endpoints列表
kubectl get svc tomcat-service -o yaml


service多端口问题
需要在rc文件中指定对应服务的名称和端口
service实例:
apiVersion: v1
kind: service
metadata:
 name: tomcat-service
spec:
 ports:
 - port: 8080
  name: service-port
 - port: 8005
  name: shutdown-port
 selector:
  tier: frontend

k8s的服务发现机制
add-On增值包的方式引入了DNS系统

外部系统如何访问service?
nodePort,在service的定义文件中增加,将service的port与node实际节点的port做映射即可。实例如下:
service实例:
apiVersion: v1
kind: service
metadata:
 name: tomcat-service
spec:
type: NodePort
 ports:
 - port: 8080
  name: service-port
  nodeport: 31002
 - port: 8005
  name: shutdown-port
  nodeport: 31003
 selector:
  tier: frontend
特别指出:nodePort灭有解决外部访问service时的负载均衡问题,假设集群中有10个node,那么就需要增加nginx或HAProxy等负载均衡器。


k8s中的三种Ip:
Pod IP:虚拟的Pod Ip,k8s内部pod之间通讯使用
Cluster IP:k8s集群内部的地址,k8s集群内部的service相互使用,无法供外部使用
Node IP:节点对电影的物理网卡IP,真实存在,k8s集群之外的节点访问使用

1.4.10 Volume
Pod中多个容器访问的共享目录,Pod中的volume与Pod生命周期相同,与容器无关,支持ceph等先进的分布式文件系统。
实例如下:增肌了volume,并挂载到容器的/mydata-data目录上。
  template:                                            #根据此模板创建Pod的副本(实例)
    metadata:
      labels:
        app: mysql                                     #Pod副本拥有的标签,对应RC的Selector
    spec:
      volumes:
          -name: datavol
           emptyDir: {}
      containers:                                      #Pod内容器的定义部分
      - name: mysql                                    #容器的名称
        image: hub.c.163.com/library/mysql              #容器对应的Docker image
        volumeMounts:
         -mountPath: /mydata-data
          name:datavol
        ports: 
        - containerPort: 3306                          #容器应用监听的端口号
        env:                                           #注入容器内的环境变量
        - name: MYSQL_ROOT_PASSWORD 
          value: "123456"

支持的volume类型:
1)emptyDir:空目录
2)hostPath:宿主机上的文件或目录
3)gcePersistentDisk 永久磁盘
4) awsElasticBlockStore
5)NFS
6).....

1.4.11 Persistent Volume
一般的volume定义在pod上,是计算资源的一部分;
pv是k8s集群中某个网络存储中对应的一块存储,与一般volume有如下区别:
1)pv是网络存储,不属于任何node
2)pv不是定义在pod中
3)pv支持NFS、FC、RDB等

PV的yaml定义文件
apiVersion: v1
kind: PersistentVolume
metadata:
 name:pv0003
spec:
 capacity:
  storage: 5Gi
 accessModes:
  - ReadWriteOnce
 nfs:
  path: /somepath
  server: 172....
accessModes属性与含义
ReadWriteOnce:读写,只能单Node挂载
ReadOnlyMany: 读,多Node挂载
ReadWriteMany:读写,多Node挂载

PV被pod使用
1 定义pvc,对应yaml如下:
kind: PersistenVolumeClain
apiVersion: v1
metadata:
 name: myclaim
spec:
 accessModes:
  - ReadWriteOnce
 resources:
  requests:
   storage: 8Gi
?????  没有引用上面定义的pv???
2 在pod的volume定义中引用上述pvc
volumes:
 - name: mypd
  persistentVolumeClaim:
   claimName: myclaim

PV的状态:
Avaliable:空闲
Released:已经被释放
Bound:已经绑定到某个pvc
Failed:PV自动回收失败

1.4.12 Namespace
通过namespace可以对k8s中的资源进行逻辑分组,实现资源的隔离
namespace的yaml定义:
apiVersion: v1
kind: Namespace
metadata:
 name: deployment

指定pod的namespace
apiVersion: v1
kind: Pod
metadata:
 name: busybox
 namespace: development #指定pod的用户空间
spec:
 .....

相关指令:
此时kubectl get pods将无法显示上面的pod,这是因为kubectl get命令将仅侠士属于default命名空间的资源对象。
--namespace可以指定命名空间,如:
kubectl get pods --namespace=development

1.4.13 annotation
用户在k8s中定义附加信息,如build、release、镜像、日志库、团队信息等,便于外部工具的查找

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐