NingG +

Kubernetes 系列:核心架构

1.概要

Kubernetes 集群,几个基本疑问:

几个方面:

2.架构

两个方面:

  1. 基本工作过程
  2. 架构:逻辑架构、物理架构

2.1.基本工作过程

Kubernetes 的核心工作过程:

  1. 资源对象NodePodServiceReplication Controller 等都可以看作一种资源对象
  2. 操作:通过使用 kubectl 工具,执行增删改查
  3. 存储:对象的目标状态预设状态),保存在 etcd 中持久化储存;
  4. 自动控制:跟踪、对比 etcd 中存储的目标状态与资源的当前状态,对差异资源纠偏自动控制集群状态。

Kubernetes 实际是:高度自动化资源控制系统,将其管理的一切抽象为资源对象,大到服务器 Node 节点,小到服务实例 Pod。

Kubernetes 的资源控制是一种声明+引擎的理念:

  1. 声明:对某种资源,声明他的目标状态
  2. 自动:Kubernetes 自动化资源控制系统,会一直努力将该资源对象维持在目标状态

2.2.架构(物理+逻辑)

Kubernetes 集群,是主从架构:

下述几个组件,都是独立的进程,每个进程都是 Go 语言编写,实际部署 Kubernetes 集群,就是部署这些程序。

具体,2 种角色的节点,需要运行的进程和职责不同,详细描述如下。

Master 管理节点:管理整个 Kubernetes 集群,接收外部命令,维护集群状态。

补充说明:

schedulercontroller-manager都是通过apiserveretcd中获取各种资源的状态,进行相应的调度控制操作。

Node 节点:Master 节点,将任务调度到 Node 节点,以 docker 方式运行;当 Node 节点宕机时,Master 会自动将 Node 上的任务调度到其他 Node 上。

2.3.集群的高可用

Kubernetes 集群,在生产环境,必须实现高可用:

  1. 实现Master节点及其核心组件的高可用;
  2. 如果Master节点出现问题的话,那整个集群就失去了控制;

具体的 HA 示意图:

上述方式可以用作 HA,但仍未成熟,据了解,未来会更新升级 HA 的功能.

具体工作原理:

官网关联资料:

3.核心概念

涉及到的多个核心概念:

部署服务相关的资源:

其他资源:

几个资源之间的关系:(当前的理解,待修正)

Pod

Pod 是 Kubernetes 集群运行的最小单元。

Pause 容器

下面是一个 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'
  - name: db
    image: mysql
    resources:
      requests:                  # 最小资源申请量
        memory: "64Mi"     # 64M内存
        cpu: "250m"           # 0.25个CPU
      limits:                       # 最大配额
        memory: "128Mi"   # 128M 内存
        cpu: "500m"           # 0.5个CPU

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 几个方面:

常见的 Label:

Label Selector (标签选择器) :筛选出具有指定 Label 的资源,方便进行管理。

具体的 Label Selector:

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

更多细节:

RC,Replication Controller

复制控制器(Replication Controller),也是一种资源,声明 Pod 副本的目标状态,具体作用:

一般配置参数:

示例:

apiVersion: v1
kind: ReplicationController
metadata:
  name: nginx
spec:
  replicas: 3
  selector:
    app: nginx
  template:
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80

RC运行过程:

  1. 定义一个RC的YAML文件(或者调用kubectl命令)提交到Kubernets集群后,
  2. Master 上的 Controller Manager 组件就得到通知,定期巡检系统中当前存活的目标Pod
  3. Controller Manager 确保运行状态的 Pod 数量,跟预期的 Pod 数量相匹配
  4. 过多的 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

升级开始后:

  1. 首先依据提供的定义文件创建V2版本的RC,
  2. 然后每隔10s(–update-period=10s)逐步的增加V2版本的Pod副本数,逐步减少V1版本Pod的副本数。
  3. 升级完成之后,删除V1版本的RC。
  4. 保留V2版本的RC,及实现滚动升级。

升级过程中,发生了错误中途退出时:

  1. 可以选择继续升级,Kubernetes能够智能的判断升级中断之前的状态,然后紧接着继续执行升级。
  2. 也可以进行回退,命令如下:
 kubectl rolling-update my-rcName-v1 -f my-rcName-v2-rc.yaml --update-period=10s --rollback

ReplicaSet

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

RC(Replica Set)特性和作用:

  1. 通过定义一个RC,实现Pod的创建过程及副本数量的自动控制。
  2. RC 里包括完整的Pod定义模板。
  3. RC通过Label Selector 机制是对Pod副本的自动控制。
  4. 通过改变RC副本数量,可以实现Pod副本的扩容缩容
  5. 通过改变RCPod模板中的镜像版本,可以实现Pod滚动升级

Deployment

Deployment 主要职责同样是为了保证运行状态 pod 的数量

  1. 90%的功能与Replication Controller完全一样
  2. 可看做新一代的Replication Controller
  3. Deployment内部使用了Replica Set来实现;
  4. 相对于 RC,Deployment 有个增强,可以查看:Pod 部署进度运行状态

具体实现细节:

  1. 创建 Pod:创建 Deployment 对象,来生成 Replica Set,控制 Pod 副本的创建;
  2. 查看状态:检查 Deployment 的状态,来查看是否完成部署,例如,副本数量是否为目标数量;
  3. 滚动升级:更新 Deployment,以创建新的 Pod,同事清理不再需要的旧版本的 Replica Set;
  4. 回滚:如果当前 Pod 不稳定 or 有 bug,则,可以回滚到一个早期的稳定版本;
  5. 暂停和恢复:随时暂停 Deployment 对象,修改对应的参数配置,之后再恢复 Deployment 继续发布;

Deployment 定义

具体 Deployment 定义的实例:

# 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 并查看状态:

# 创建 Deployment
kubectl create -f nginx.yaml 

# 查看 Deployment
# 刚执行时,显示的AVAILABLE数量时0
kubectl get deployments

# 滚动升级
kubectl set image deployment/nginx-deployment nginx=nginx:1.12.2

# 查看 Replica Set(RS)
# 每次升级 Deployment,都会生成一个新的 RS
kubectl get rs
...
NAME                          DESIRED   CURRENT   READY     AGE
nginx-deployment-666865b5dd   0         0         0         22m
nginx-deployment-69647c4bc6   3         3         3         5m
...

所有 Deployment 的操作命令,可以参考:

Service

Service 定义了服务访问入口:

TODO:

详细的说明:

外部访问的 Service:

下面的文件定义了一个nginx服务添加外部NodePort的示例:

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

特别说明:

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

本质:在所有节点 Node 的 kube-proxy 上,登记了 Service –> ClusterIP:NodePort –> Pod IP:ContainerPort 的映射关系。

疑问:

命令参考

Volume

关于磁盘存储:

  1. Pod中,多个容器共享 Volume;
  2. 使用单独的存储空间,挂载到对应的Pod上,保证数据持久化;
  3. 当容器终止时,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做出说明:

本地存储: 网络存储: Persistent Volume:

本地存储

本地存储:

apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /test-pd
  name: test-volume
volumes:
- name: test-volume
hostPath:
  # directory location on host
  path: /data
  # this field is optional
  type: Directory

网络存储

网络存储

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

除此之外,Kubernetes还支持其他的存储方式,具体详情可以查看官方文档。

Persistent Volume

理解并管理五花八门的存储是一件让人头疼的事情,Kubernetes为了解决这些问题,对所有的网络存储进行了抽象,让我们在管理这些存储时不必考虑后端的实现细节,对于不同的网络存储统一使用一套相同的管理手段。

PersistentVolume为用户和管理员提供了一个API,它抽象了如何定义存储以及使用存储的细节。 为此,引入两个新的API资源:PersistentVolume和PersistentVolumeClaim。

定义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是有状态的对象,有如下几种状态:

Namespace

Namespace 用于实现多租户隔离。

几个常用命令,查询 namespace:

# 查询所有的 namespace
kubectl get namespaces

# 查询 namespaces 的细节
kubectl describe namespaces

# 查询所有的 pod
kubectl get pods --all-namespaces

# 默认只会查询 default 中的 pod 信息
kubectl get pods

# 查询指定 namespace 的 pod
kubectl get pods --namespace=kube-system

Namespace的定义

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

apiVersion: v1
kind: Namespace
metadata:
  name: deployment

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

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

疑问:

Horizontal Pod Autoscaler(HPA)

HPA 也是一类资源对象:

HPA有以下两种方式来度量Pod的负载情况:

简单示例:

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具有以下特性:

4.遗留问题

定义资源的模板:

5.参考资料

Top