Kubernetes 核心概念简介

时间:2018-05-22 14:40:15   收藏:0   阅读:408
Kubernets 中的Node, Pod,Replication Controller, Service 等都可以看作一种资源对象,这些资源几乎都可以通过使用Kubernetes提供的kubectl 工具执行增删改查,并将其保存在etcd中持久化储存。通过跟踪对比etcd库中保存的“资源预设状态”与当前环境中的实际资源状态进行对比,对差异资源状态进行纠错,来实现自动控制集群状态的功能。下面将分别介绍这个组件角色。

管理角色

Kubernetes中有两种管理角色,Master和Node.

Master

Master是Kubernetes集群的控制节点,所有对于Kubernetes的命令操作都需要在控制节点执行。Master一般运行如下进程:

kube-apiserver: Kubernetes API Server, 提供了HTTP Rest接口的关键服务进程,是所有资源增,删,改,查的入口,也是集群控制的入口进程,kubectl是直接与 API Server交互的,默认监听 6443端口。

kube-controller-manager: 每个资源一般都对应有一个控制器,而controller manager就是负责管理这些控制器的,它是自动化的循环控制器,是Kubernetes的核心控制守护进程。默认监听10252端口。

kube-scheduler : 负责将pod资源调度到合适的node 上。其本身提供了复杂丰富的调度算法,可以根据node 节点的性能,负载,数据位置等各种情况进行合理的调度。默认监听10251 端口。

etcd: 一个高可用的键值存储系统,Kubernetes使用它来存储各个资源的状态,从而实现了Restful的API。默认监听2379和2380端口(2379提供服务,2380用于集群节点通信)

Node

除了Master节点,集群中的其它节点被称作Node节点,Node节点是业务应用实际的运行的平台,通过Master 调度不同的任务到Node节点上,以docker 的方式运行。当某个Node节点宕机时,其上的工作负载会被Master自动转移到其它Node节点上。
Node节点上运行着如下进程:

kubelet: Kubelet是在每个Node节点上运行agent,是Node节点上面最重要的模块,它负责维护和管理该Node上面的所有容器,但是Kubelet不会管理不是由Kubernetes创建的容器。本质上,它负责使Pod得运行状态与期望的状态一致。Kubelet会定时向Master汇报自己当前的自身信息,如操作系统,Docker版本,CPU,内存,pod运行状态等信息。

kube-proxy:该模块实现了Kubernetes中的服务发现和反向代理功能。反向代理支持TCP和UDP连接转发,默认基于Round Robin算法将客户端流量转发到与service对应的一组后端pod。服务发现方面,kube-proxy使用etcd的watch机制,监控集群中service和endpoint对象数据的动态变化,并且维护一个service到endpoint的映射关系,从而保证了后端pod的IP变化不会对访问者造成影响。

runtime: 这里一般使用docker 容器,Kubernetes也支持其他的容器。

Node节点的状态管理

1、通过在Master查看Node状态:

[root@node-1 ~]# kubectl get nodes
NAME      STATUS    ROLES     AGE       VERSION
node-1    Ready     master    22h       v1.10.2
node-2    Ready     <none>    22h       v1.10.2
node-3    Ready     <none>    1h        v1.10.2

2、查看Node的详细信息,如下命令会输出节点当前状态的详细信息,包括可用资源总量:

kubectl describe node node-2

Pod

Pod是Kubernetes中非常重要的基本单位。Pod是应用运行的载体,整个Kubernetes系统都是围绕着Pod展开的,比如如何部署运行Pod、如何保证Pod的数量、如何访问Pod等。Pod是一个或多个容器的集合。
在每一个Pod中都有一个特殊的Pause容器和一个或多个业务容器,Pause来源于pause-amd64镜像,Pause容器在Pod中具有非常重要的作用:

Pod 的定义

Kubernetes中所有的资源对象都可以采用YAML或者JSON格式的文件来定义,比如,我们可以定义如下的Pod对象:

apiVersion: v1
kind: Pod
metadata:
  name: myweb
  labels:
    name: myweb
spec:
  containers:
  - name: myweb
    image: kubeguide/tomcat-app:v1
    ports:
    - containerPort: 8080
    env:
    - name: MYSQL_SERVER_HOST
      value: ‘mysql‘
    - name: MYSQL_SERVER_PORT
      value: ‘3306‘

2、Pod Volume可以使用分布式文件系统,将Pod Volume定义在Pod上,然后被各个容器挂载到自身的容器。目前Kubernetes支持多种文件存储。

3、我们还可以对pod使用的资源进行配额,一般是对CPU和内存的限制:

apiVersion: v1
kind: Pod
metadata:
  name: mysql
  labels:
    name: mysql
spec:
  containers:
  - name: db
    image: mysql
    resources:
      requests:                  # 最小资源申请量
        memory: "64Mi"     # 64M内存
        cpu: "250m"           # 0.25个CPU
      limits:                       # 最大配额
        memory: "128Mi"   # 128M 内存
        cpu: "500m"           # 0.5个CPU

4、 Pod 常用操作:

kubectl create -f  pod_file.yaml            # 创建pod
kubectl describe pods POD_NAME  # 查看pod详细信息
kubectl get pods                               # pods 列表
kubectl delete pod POD_NAME    # 删除pod
kubectl replace  pod_file.yaml      # 更新pod

Label

Label 是用户自定义的键值对,主要是用于标记资源对象,如Node,Pod,Service,RC等。一个资源可以定义任意数量的Label,同一个Label也可以被添加到任意数量的资源对象上去,Label 通常在资源对象定义时确定,也可以在对象创建后动态的添加或删除。

可以给资源对象绑定多个不同Label,来实现多维度的资源分组管理功能,一些常见的Label示例:

提示:Deployment,ReplicaSet,DaemonSet和Job等管理对象可以在Selector中使用基于集合的筛选条件定义。

Label Selector (标签选择器) ,主要用于对拥有某些Label的资源对象进行查询和筛选,类似SQL的查询机制。
Label Selector可以通过基于等式集合的查询方式进行匹配查询,通过多个表达式的组合,从而实现复杂的条件选择,如:

name=mysql,env!=production
name notin (tomcat),env!=production

Replication Controller

Replication Controller(RC)是Kubernetes中的另一个核心概念,Kubernetes中通过RC来保证应用能够持续运行,它会确保任何时间Kubernetes中都有指定数量的Pod处于运行状态。在此基础上,RC还提供了一些更高级的特性,比如滚动升级、升级回滚等。

RC在Kubernetes中定义了一个期望的场景,即声明某种pod副本数量在任意时刻符合某个预期的值,其定义的内容如下:

RC运行过程: 当我们定义了一个RC的YAML文件(或者调用kubectl命令)提交到Kubernets集群后,Master 上的Controller Manager组件就得到通知,定期巡检系统中当前存活的目标Pod,并确保目标Pod实例的数量刚好邓毅此RC的期望值。如果有过多的Pod副本在运行,系统就会停掉一些Pod,反之则会自动创建一些Pod。

自动伸缩

通过修改RC数量,实现Pod的动态缩放:

kubectl scale rc myweb --replicas=10        # 将pod 扩展到10个       
kubectl scale rc myweb --replicas=1          # 将pod 缩到 1个

滚动升级

使用RC可以进行动态平滑升级,保证业务始终在线。其具体实现方式:

 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

ReplicaSet

replica set,可以被认为 是“升级版”的Replication Controller。replica set也是用于保证与label selector匹配的pod数量维持在期望状态。区别在于,replica set引入了对基于子集的selector查询条件,而Replication Controller仅支持基于值相等的selecto条件查询。replica set很少被单独使用,目前它多被Deployment用于进行pod的创建、更新与删除的编排机制。

RC(Replica Set)特性和作用

Deployment

Deployment主要职责同样是为了保证pod的数量和健康,90%的功能与Replication Controller完全一样,可以看做新一代的Replication Controller。Deployment内部使用了Replica Set来实现。
Deployment 相对于RC一个最大的升级是我们可以随时知道当前Pod "部署"的进度,和详细的运行状态。
具有以下使用场景:

创建Pod: 可以创建一个Deployment对象来生成对应的Replica Set,完成Pod副本的创建。
查看事件状态: 通过检查Deployment的状态来查看部署动作是否完成,如副本数量是否达到了预期的值。
升级:更新Deployment以创建新的Pod,同时还可以清理不再需要的旧版本ReplicaSet。
回滚: 如果当前的Pod不稳定或者有bug,可以回滚到一个早期的稳定版本。
暂停和恢复:可以随时暂停Deployment对象,修改对应的参数配置,之后再恢复Deployment继续发布。

Deployment 定义

Deployment的定义和Replica Set的定义几乎一样,仅仅是API版本和kind类型不同:

# Deployment的声明
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80

# Replica Set的声明
apiVersion: v1
kind: ReplicaSet
metadata:
  name: mysql
...

创建一个deployment

1、这里以上面的nginx为例,创建nginx:

[root@node-1 ~]# kubectl create -f nginx.yaml 
deployment.apps "nginx-deployment" created

2、查看Deployment信息:

# 刚执行时,显示的AVAILABLE数量时0
[root@node-1 ~]# kubectl get deployments
NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3         3         3            0           22s

# 1分钟后显示已经有3个可用nginx-deployment
[root@node-1 ~]# kubectl get deployments
NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3         3         3            3           1m

# 查看pods
[root@node-1 ~]# kubectl get pods | grep nginx
nginx-deployment-666865b5dd-cfmfp   1/1       Running   0          11m
nginx-deployment-666865b5dd-nhxtv   1/1       Running   0          11m
nginx-deployment-666865b5dd-qj7sf   1/1       Running   0          11m

# 查看 rs
[root@node-1 ~]# kubectl get rs
NAME                          DESIRED   CURRENT   READY     AGE
nginx-deployment-666865b5dd   3         3         3         25m

# 查看deployments的详细部署信息
[root@node-1 ~]# kubectl describe deployments
...

对于上述kubectl get deployments的输出,其含义:

使用kubectl describe deployments命令可以获取指定Deployment的详细状态

滚动升级

例如,我们要对当前的nginx-deployment进行升级或者回滚,可以使用如下两种方式。

* 直接 set 镜像

1、若要对docker镜像进行更新,直接 set 镜像:

[root@node-1 ~]# kubectl set image deployment/nginx-deployment nginx=nginx:1.12.2

2、查看状态,可以发现在保证pod 可用的状态下,会平滑的替换旧的deployment对象,并且会记录此过程:

[root@node-1 ~]# kubectl  get deployments
NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3         4         1            3           3h

[root@node-1 ~]# kubectl  get deployments
NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3         4         2            3           3h

[root@node-1 ~]# kubectl  get deployments
NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3         3         3            3           4h

[root@node-1 ~]# kubectl get rs
NAME                          DESIRED   CURRENT   READY     AGE
nginx-deployment-666865b5dd   0         0         0         4h
nginx-deployment-69647c4bc6   3         3         3         3m

[root@node-1 ~]# kubectl describe deployments   # 会显示详细events事件
* 直接edit Deployment

1、执行 edit命令修改Deployment配置,类似KVM的virsh edit 命令,修改后立即生效(如果没有修改,将不会发生任何变化):

[root@node-1 ~]# kubectl edit deployments/nginx-deployment

2、查看deployment状态:

[root@node-1 ~]# kubectl get deployments 
NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3         4         1            3           5h

[root@node-1 ~]# kubectl get deployments 
NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3         4         3            3           5h

[root@node-1 ~]# kubectl get deployments 
NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3         3         3            3           5h

3、一般常见的修改是修改镜像版本和参数。

回滚

1、执行回滚命令,到上一个版本:

[root@node-1 ~]# kubectl rollout undo deployment/nginx-deployment

2、使用如下命令,可以查看保存的deployment历史:

[root@node-1 ~]# kubectl get rs
NAME                          DESIRED   CURRENT   READY     AGE
nginx-deployment-666865b5dd   0         0         0         5h
nginx-deployment-68dfb7c95b   3         3         3         27m
nginx-deployment-69647c4bc6   0         0         0         1h

命令参考

Service

Service是Kubernetes中的核心对象之一。Kubernetes中的Pod,RC,等资源对象最终都是为Service服务。
Service定义了一个服务访问的入口地址,前端应用Pod通过这个地址访问后端的Pod集群实例,Service通过Label Selector来实现与后端Pod集群的通讯。其中,RC的作用是保障集群中始终有可用的Pod集群,从而确保了服务质量。

Service原理

Service的服务原理图:

技术分享图片

在上图中,我们需要理解以下几点:

外部访问Service

由于Cluster IP是一个内部地址,外部的node 节点无法直接访问到,当我们的外部用户需要访问这些服务时,需要在定义Service时添加NodePort的扩展。下面的文件定义了一个nginx服务添加外部NodePort的示例。
编辑service文件:

apiVersion: v1
kind: Service
metadata: 
  name: nginx
spec:
  type: NodePort
  ports:
    - port: 80
      nodePort: 30008   # 对外的用户访问端口,默认范围是30000-32767
  selector:
    app: nginx

当我们创建这个service后,所有的节点上都会有30008的端口映射,访问任意节点都会转发到对应的Pod集群中。

命令参考

Volume

在Kubernetes中,Volume是能被Pod中多个容器访问的共享目录。由于Pod中的容器随时可能会被销毁或重建,对于一些需要数据共享或要持久化保存的数据,我们需要使用单独的存储空间,挂载到对应的Pod上。当容器终止时,Volume中的数据不会丢失。

Volume的定义格式:

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: k8s.gcr.io/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  volumes:
  - name: cache-volume
    emptyDir: {}                    # 指定Volume类型

Kubernetes支持多种类型的Volume,下面会对一些常见的Volume做出说明。

本地存储

网络存储

volumes:
  - name: nfs
    nfs:
          server: NFS-SERVER-IP   # NFS 服务器地址
            path: "/"

Persistent Volume

理解并管理五花八门的存储是一件让人头疼的事情,Kubernetes为了解决这些问题,对所有的网络存储进行了抽象,让我们在管理这些存储时不必考虑后端的实现细节,对于不同的网络存储统一使用一套相同的管理手段。
PersistentVolume为用户和管理员提供了一个API,它抽象了如何提供存储以及如何使用它的细节。 为此,引入两个新的API资源:PersistentVolume和PersistentVolumeClaim。
PersistentVolume(PV): 是管理员设置的单独的网络存储集群,它不属于任何节点,但是可以被每个节点访问。 PV是Volumes之类的卷插件,具有独立于的生命周期。 此API对象用于捕获存储实现的细节,如NFS,iSCSI,GlusterFS,CephFS或特定于云提供程序的存储系统。
PersistentVolumeClaim(PVC):是用户对存储的请求的定义。 它与pod相似。pods消耗节点资源,PVC消耗PV资源, Pods可以请求特定级别的资源(CPU和内存)。Claim可以配置特定的存储资源大小和访问模式(例如,多种不同的读写权限),并根据用户定义的需求去使用合适的Persistent Volume。

定义Persistent Volume

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv1
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  nfs:
    path: /somepath
    server: 10.2.2.2

accessModes有三种权限:

定义Persistent Volume Claim

如果某个Pod想申请某种类型的PV,可以做如下定义:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: myclaim
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      stroage: 8Gi

定义之后再Pod的Volume中引用上述PVC:

volumes:
  - name: mypd
    persistentVolumeClaim:
          claimName: myclaim

PV的状态

PV是有状态的对象,有如下几种状态:

Namespace

Namespace(命名空间)是Kubernetes中非常重要的概念,Namespace在很多情况下实现多租户的资源隔离,将集群中的不同资源对象分配到不同的Namespace中,形成逻辑上分组的不同项目,便于不同分组在使用集群资源的同时还能被分别管理。
Kubernetes在启动之后,默认会创建一个default的Namespace:

[root@node-1 ~]# kubectl get namespaces
NAME          STATUS    AGE
default       Active    3d

当我们创建对象时,不指定namespace就会使用默认的default:

[root@node-1 ~]# kubectl get pods --all-namespaces
NAMESPACE     NAME                                READY     STATUS    RESTARTS   AGE
default       mysql-fw2pj                         1/1       Running   2          1d
default       myweb-4jk8j                         1/1       Running   2          1d
default       myweb-68zfl                         1/1       Running   2          1d
default       myweb-bv8pt                         1/1       Running   2          1d
default       nginx-deployment-68dfb7c95b-6zcj4   1/1       Running   2          1d
default       nginx-deployment-68dfb7c95b-g89nd   1/1       Running   3          1d
default       nginx-deployment-68dfb7c95b-zvtkf   1/1       Running   2          1d
kube-system   etcd-node-1                         1/1       Running   7          3d
 ...

Namespace的定义

使用yaml文件定义一个名为deployment的Namespace:

apiVersion: v1
kind: Namespace
metadata:
  name: deployment

当创建对象时,就可以指定这个资源对象属于哪个Namespace:

apiVersion: v1
kind: Pod
metadata:
  name: myweb
  namespace: development

当我们指定非默认的namespace之后,使用如下命令就只能查看默认区域的namespaces:

# kubectl get pods

查看所有namespace区域的对象要使用--all-namespaces参数:

# kubectl get pods --all-namespaces

#也可以指定namespaces:
# kubectl get pods --namespace=kube-system

Horizontal Pod Autoscaler

HPA与之前介绍的RC,deployment一样,也是属于Kubernetes的一种资源对象。HPA通过追踪分析RC控制的所有目标Pod的负载变化情况,来确定是否需要针对性的调整目标Pod的副本数。HPA有以下两种方式来度量Pod的负载情况:

CPU的利用率百分比通常是度量的Pod CPU 1min内的平均值,使用Heapster扩展组件来得到这个值,这里定义一个简单的例子:

apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: myweb
  namespace: default
spec:
  maxReplicas: 10
  minReplicas: 2
  scaleTargetRef:
    kind: Deployment
    name: myweb
  targetCPUUtilizationPercentage: 90

当Pod 副本的CPU利用率超过90%时会触发自动扩容行为,且Pod数量最多不能超过10,最少不能低于2.
除此之外,也可以使用命令操作:

kubectl autoscale deployment myweb  --cpu-percent=90 --min=1 --max=10

StatefulSet

在Kubernetes系统中,Pod管理的对象如 RC,Deployment,DaemonSet 和Job 都是面向无状态的服务。对于无状态的服务我们可以任意销毁并在任意节点重建,但是在实际的应用中,很多服务是有状态的,特别是对于复杂的中间件集群,如Mysql集群,MongoDB集群,Zookeeper集群,etcd集群等,这些服务都有固定的网络标识,并有持久化的数据存储,这就需要使用StatefulSet对象。
StatefulSet具有以下特性:

参考资料:
https://kubernetes.io/docs/concepts/
https://www.cnblogs.com/zhenyuyaodidiao/p/6500720.html
《Kubernets权威指南》

原文:http://blog.51cto.com/tryingstuff/2119034

评论(0
© 2014 bubuko.com 版权所有 - 联系我们:wmxa8@hotmail.com
打开技术之扣,分享程序人生!