Kubernetes有状态应用管理——PetSet

1、介绍

  在Kubernetes中,大多数的Pod管理都是基于无状态、一次性的理念。例如Replication Controller,它只是简单的保证可提供服务的Pod数量。如果一个Pod被认定为不健康的,Kubernetes就会以对待牲畜的态度对待这个Pod——删掉、重建。相比于牲畜应用,PetSet(宠物应用),是由一组有状态的Pod组成,每个Pod有自己特殊且不可改变的ID,且每个Pod中都有自己独一无二、不能删除的数据。

  众所周知,相比于无状态应用的管理,有状态应用的管理是非常困难的。有状态的应用需要固定的ID、有自己内部可不见的通信逻辑、特别容器出现剧烈波动等。传统意义上,对有状态应用的管理一般思路都是:固定机器、静态IP、持久化存储等。Kubernetes利用PetSet这个资源,弱化有状态Pet与具体物理设施之间的关联。一个PetSet能够保证在任意时刻,都有固定数量的Pet在运行,且每个Pet都有自己唯一的身份。一个“有身份”的Pet指的是该Pet中的Pod包含如下特性:

    1)        有固定的主机名,且DNS可寻址

    2)        一个有序的index

    3)        静态存储

    4)        应用举例:

    5)        数据库应用,如Mysql、PostgreSQL,需要一个固定的ID(用于数据同步)以及外挂一块NFS Volume(持久化存储)。

    6)        集群软件,如zookeeper、Etcd,需要固定的成员关系。

2、使用限制

    1)        1.4新加功能,1.3及之前版本不可用;

    2)        DNS,要求使用1.4或1.4之后的DNS插件,1.4之前的插件只能解析Service对应的IP,无法解析Pod(HostName)对应的域名;

    3)        日常运维,对于PetSet,唯一能够更改的就是replicas;

    4)        需要持久化数据卷(PV),且数据卷要在创建PetSet之前创建;

    5)        删除或缩容PetSet不会删除对应的持久化数据卷,这么做是处于数据安全性的考虑;

    6)        只能通过手动的方式升级PetSet。

3、PetSet示例

  以下示例演示了创建两个PV,创建两个PetSet的过程。在PetSet创建完成之后,验证了其hostName及直接Pod访问。

3.1 创建PV

  创建PV的时候,我两个PV选择了同一个NFS server,创建也是成功的。Kubernetes在创建PV的时候并不会校验NFS server是否存在,是否能够连接成功,也不会校验storage设置的大小是否真实。所以说,PV的创建需要管理员在一开始就设置好,依赖人为的校验。

[[email protected] pv]# cat nfs-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0001
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    path: "/data/disk1"
    server: 192.168.20.47
    readOnly: false
[[email protected]-master pv]# cat nfs-pv2.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0002
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    path: "/data/disk1"
    server: 192.168.20.47
    readOnly: false
[[email protected]-master pv]# kubectl create -f nfs-pv.yaml
persistentvolume "pv0001" created
[[email protected]-master pv]# kubectl create -f nfs-pv2.yaml
persistentvolume "pv0002" created
[[email protected]-master pv]# kubectl get pv
NAME      CAPACITY   ACCESSMODES   RECLAIMPOLICY   STATUS      CLAIM     REASON    AGE
pv0001    5Gi        RWX           Recycle         Available                       8s
pv0002    5Gi        RWX           Recycle         Available                       5s

3.2 创建PetSet

  创建PetSet的时候需要先创建一个“headless”的Service,即service显示的将ClusterIP设置为none。而用户可以通过直接访问PetSet中的Pod的IP(通过Pod的HostName解析得到),来访问后端的服务的。Kubernetes在1.4之后的dns插件之上才支持这种类型的DNS解析

[[email protected] pv]# cd ../petset/
[[email protected]-master petset]# cat test-petset.yaml
# A headless service to create DNS records
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  # *.nginx.default.svc.cluster.local
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1alpha1
kind: PetSet
metadata:
  name: web
spec:
  serviceName: "nginx"
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
      annotations:
        pod.alpha.kubernetes.io/initialized: "true"
    spec:
      terminationGracePeriodSeconds: 0
      containers:
      - name: nginx
        image: gcr.io/google_containers/nginx-slim:0.8
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes:
      - ReadWriteMany
      resources:
        requests:
          storage: 1Gi
[[email protected]-master petset]# kubectl create -f test-petset.yaml
service "nginx" created
petset "web" created
[[email protected]-master petset]# kubectl get petset
NAME      DESIRED   CURRENT   AGE
web       2         2         11s
[[email protected]-master petset]# kubectl get pod
NAME      READY     STATUS    RESTARTS   AGE
web-0       1/1       Running   0          16s
web-1       1/1       Running   0          12s
[[email protected]-master petset]# kubectl get pv
NAME  CAPACITY  ACCESSMODES RECLAIMPOLICY STATUS CLAIM  REASON    AGE
pv0001    5Gi  RWX   Recycle  Bound     default/www-web-0             1m
pv0002    5Gi  RWX   Recycle  Bound     default/www-web-1             1m
[[email protected]-master petset]# kubectl get pvc
NAME        STATUS    VOLUME    CAPACITY   ACCESSMODES   AGE
www-web-0   Bound     pv0001    5Gi        RWX           22s
www-web-1   Bound     pv0002    5Gi        RWX           22s
[[email protected]-master petset]# kubectl exec -ti web-0 /bin/bash
[email protected]-0:/# cd /usr/share/nginx/html
[email protected]-0:/usr/share/nginx/html# ls
[email protected]-0:/usr/share/nginx/html# touch 1.out
[email protected]-0:/usr/share/nginx/html# exit
exit
[[email protected]-master petset]# ssh 192.168.20.47 #登录到NFS主机
[email protected]192.168.20.47‘s password:
Last login: Tue Mar 28 11:54:58 2017 from 10.0.251.145
[[email protected] ~]# echo "123456">> /data/disk1/1.out
[[email protected] ~]# exit
登出
Connection to 192.168.20.47 closed.
[[email protected]-master petset]# kubectl exec -ti web-0 /bin/bash
[email protected]-0:/# cat /usr/share/nginx/html/1.out
123456
[email protected]-0:/# exit
exit
[[email protected]-master petset]# kubectl exec -ti web-1 /bin/bash
[email protected]-1:/# cat /usr/share/nginx/html/1.out
123456
[email protected]-1:/# exit
exit
[[email protected]-master petset]#

3.3 验证域名解析

  检查PetSet中的Pod的hostName

[[email protected] ~]# for i in 0 1; do kubectl exec web-$i -- sh -c ‘hostname‘; done
web-0
web-1

  检查通过hostName解析IP

[[email protected]master dns14]# kubectl get svc nginx
NAME      CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
nginx     None         <none>        80/TCP    5h
[[email protected]-master dns14]# kubectl describe svc nginx
Name:            nginx
Namespace:        default
Labels:            app=nginx
Selector:        app=nginx
Type:            ClusterIP
IP:            None
Port:            web    80/TCP
Endpoints:        10.0.28.3:80,10.0.82.6:80
Session Affinity:    None
No events.
[[email protected]-master ~]# kubectl get pod -o wide
NAME     READY     STATUS    RESTARTS   AGE       IP          NODE
web-0      1/1       Running   0          42m       10.0.28.3   k8s-node-1
web-1      1/1       Running   0          42m       10.0.82.6   k8s-node-4
[[email protected]-master ~]# kubectl exec -i -t frontend-service-1988680557-xuysd /bin/bash #进入集群中的一个pod
[[email protected]-service-1988680557-xuysd /]# nslookup web-0.nginx
Server:        10.254.10.2
Address:    10.254.10.2#53

Name:    web-0.nginx.default.svc.cluster.local
Address: 10.0.28.3

[[email protected]-service-1988680557-xuysd /]# nslookup web-1.nginx
Server:        10.254.10.2
Address:    10.254.10.2#53

Name:    web-1.nginx.default.svc.cluster.local
Address: 10.0.82.6

<680557-xuysd /]# nslookup web-1.nginx.default.svc.cluster.local  #通常情况下,直接解析web-1.nginx即可得到对应的IP,但再一些容器内发现只有解析全部的名称“web-1.nginx.default.svc.cluster.local”才能得到IP,这个地方需要研究下区别在哪。
Server:        10.254.10.2
Address:    10.254.10.2#53

Non-authoritative answer:
Name:    web-1.nginx.default.svc.cluster.local
Address: 10.0.82.6

3.4 验证Pet重建

#为web-0添加一个index页面,内容为它自己的HostName,注意该目录我们将其外挂到了PV之上,是一个NFS路径
[[email protected]-master dns14]# kubectl exec web-0 -- sh -c ‘echo $(hostname) > /usr/share/nginx/html/index.html‘
#在其它Pod上获取web-0的欢迎页
[[email protected]-master dns14]# kubectl exec -it web-1 -- curl web-0.nginx
web-0
[[email protected]-master dns14]# kubectl exec -it web-0 -- curl web-0.nginx
web-0
#查询web-0的存活时间
[[email protected]-master dns14]# kubectl get pod | grep web
web-0                               1/1       Running   0          5h
web-1                               1/1       Running   0          5h
[[email protected]-master dns14]# kubectl delete pod web-0  #删除web-0
pod "web-0" deleted
[[email protected]-master dns14]# kubectl get pod | grep web  #可以看到,web-0被删除后几乎立即又被重建了
web-0             1/1       Running   0          3s
web-1             1/1       Running   0          5h
[[email protected]-master dns14]# kubectl get pod | grep web
web-0            1/1       Running   0          5s
web-1            1/1       Running   0          5h
#查看web-0中的欢迎页是否还在
[[email protected]-master dns14]# kubectl exec -it web-0 -- curl web-0.nginx
web-0
[[email protected]-master dns14]# kubectl exec -it web-1 -- curl web-0.nginx
web-0

4、运维

4.1 Pet互相发现

  通常,Pets需要互相知道对方的存在,在之前的示例中,我们演示了操作员“告诉”一个Pet,它有多少个同伴,但这显然是不够的。一种方法是,在Pod内部调用Kubectl的api来获取该Pet对应的PetSet中的其他成员,但并不推荐这么做。这样做的话,就会使得你的Pod可以反过来操控外部的组件。另一种方法是通过DNS解析,利用工具nslookup工具可以将nginx(上文定义的headless service)中的所有endPoint都查找出来。具体见下:

# apt-get update && apt-get install -y dnsutils
...
#  nslookup -type=srv nginx
Server:        10.254.10.2
Address:    10.254.10.2#53

nginx.default.svc.cluster.local    service = 10 50 0 web-1.nginx.default.svc.cluster.local.
nginx.default.svc.cluster.local    service = 10 50 0 web-0.nginx.default.svc.cluster.local.
# nslookup web-1.nginx.default.svc.cluster.local
Server:        10.254.10.2
Address:    10.254.10.2#53

Name:    web-1.nginx.default.svc.cluster.local
Address: 10.0.82.6

# nslookup web-0.nginx.default.svc.cluster.local
Server:        10.254.10.2
Address:    10.254.10.2#53

Name:    web-0.nginx.default.svc.cluster.local
Address: 10.0.28.3

4.2 更新及扩缩容

  如之前使用限制(3)中讲的,对于PetSet,Kubernetes能帮我们自动做的仅有“replicas”,即副本数量。对于扩充副本数量来说,Kubernetes每次会按照顺序,一个个的创建Pod,且在前一个没有running或ready之前,不会创建下一个;对于缩减副本数量来说,Kubernetes每次会按照顺序,一个个的删除Pod。且在前一个没有真正的shutdown之前,不会删除下一个。

  需要注意的是,缩容时,虽然删除了一些Pod,但Pod对于的持久化存储PVC—PV是不会被删除的。例如,我们一开始创建了3个Pet,pod-0、pod-1、pod-2,挂载了pvc-0——pv-0、pvc-1——pv-1、pvc-2——pv-2,在缩容到2个副本的时候,最后一个pod-2会被删除,但pvc-2——pv-2则不会被删除,里面的数据还是安全的。PV的最终删除就像它一开始创建一样,是由管理员统一管理的。

4.3 镜像更新

  有时需要更新镜像到新的版本,那该如何操作呢?虽然Kubernetes没有给我们提供一些自动更新整个Pet集群的功能,但通过它提供的edit和set image功能也基本上够我们用的了。更新Pet中的镜像功能示例如下:

[[email protected] ~]# kubectl get po web-0 --template ‘{{range $i, $c := .spec.containers}}{{$c.image}}{{end}}‘
gcr.io/google_containers/nginx-slim:0.8
[[email protected]-master ~]# kubectl exec -i -t frontend-service-1988680557-xuysd /bin/bash #进入集群中的一个pod
[[email protected]-service-1988680557-xuysd /]# nslookup web-0.nginx
Server:        10.254.10.2
Address:    10.254.10.2#53

Name:    web-0.nginx.default.svc.cluster.local
Address: 10.0.28.3

[[email protected]-master ~]# kubectl edit petset/web  #执行之后就像打开一个vi界面,修改对应的镜像名称或版本,保存退出
petset "web" edited
#也可以用set image的方式进行更改
[[email protected]-master ~]#  kubectl set image petset/web nginx=gcr.io/google_containers/nginx-slim:0.7
petset "web" image updated
[[email protected]-master ~]# kubectl delete po web-0  #手动删除第一个Pod,PetSet会自动给我们再起一个
pod "web-0" deleted
[[email protected]-master ~]# kubectl get po web-0 -o wide  #查看Pod的IP已经更改了
NAME      READY     STATUS    RESTARTS   AGE       IP          NODE
web-0     1/1       Running   0          34s       10.0.62.4   k8s-node-2
[[email protected]-master ~]# kubectl get po web-0 --template ‘{{range $i, $c := .spec.containers}}{{$c.image}}{{end}}‘
gcr.io/google_containers/nginx-slim:0.7  #查看镜像版本信息,版本也已经更改了

之后可以一个个的将PetSet中的Pod删除,PetSet会自动按照新版本的镜像帮我们启动起来。

时间: 2024-10-14 05:47:47

Kubernetes有状态应用管理——PetSet的相关文章

kubernetes有状态集群服务部署与管理

有状态集群服务的两个需求:一个是存储需求,另一个是集群需求.对存储需求,Kubernetes的解决方案是:Volume.Persistent Volume .对PV,除了手动创建PV池外,还可以通过Storage Class来让存储系统自动创建. 对集群需求,Kubernetes的解决方案是Pet Set.Pet Set 又通过Init Container来做集群初始化,通过Headless Service来为集群成员提供稳定 的网络身份. 在K8S运行的服务,从简单到复杂可以分成三类:无状态服

kubernetes API Server 权限管理实践

API Server 权限管理应用 API Server权限控制方式介绍 API Server权限控制分为三种:Authentication(身份认证).Authorization(授权).AdmissionControl(准入控制). 身份认证: 当客户端向Kubernetes非只读端口发起API请求时,Kubernetes通过三种方式来认证用户的合法性.kubernetes中,验证用户是否有权限操作api的方式有三种:证书认证,token认证,基本信息认证. 证书认证 设置apiserver

基于kubernetes自研容器管理平台的技术实践

一.容器云的背景 伴随着微服务的架构的普及,结合开源的Dubbo和Spring Cloud等微服务框架,宜信内部很多业务线逐渐了从原来的单体架构逐渐转移到微服务架构.应用从有状态到无状态,具体来说将业务状态数据如:会话.用户数据等存储到中间件中服务中. 微服务的拆分虽然将每个服务的复杂度降低,但服务实例的数目却呈现出爆炸式增长,这给运维增加难度,一方面是服务部署.升级,另一方面是服务的监控故障恢复等. 在2016年,容器技术尤其是Docker迅速流行起来,公司内部开始尝试将容器放到容器内运行,虽

flux,redux,vuex状态集管理工具之间的区别

一:redux和flux的区别 1)redux是flux中的一个实现 2))在redux中我们只能定义一个store,在flux中我们可以定义多个 3)在redux中,store和dispatch都放到了store,结构更加清晰 4)在redux中本身就内置State对象,对仓库的管理更加明确 二:redux和vuex的区别 1)vuex是redux的基础上进行改变,对仓库的管理更加明确 2)使用mutation来替换redux中的reducer 3)vuex有自动渲染的功能,所以不需要更新 三

Kubernetes 集群日志管理 - 每天5分钟玩转 Docker 容器技术(180)

Kubernetes 开发了一个 Elasticsearch 附加组件来实现集群的日志管理.这是一个 Elasticsearch.Fluentd 和 Kibana 的组合.Elasticsearch 是一个搜索引擎,负责存储日志并提供查询接口:Fluentd 负责从 Kubernetes 搜集日志并发送给 Elasticsearch:Kibana 提供了一个 Web GUI,用户可以浏览和搜索存储在 Elasticsearch 中的日志. 部署 Elasticsearch 附加组件本身会作为 K

Kubernetes 集群日志管理

Kubernetes 开发了一个 Elasticsearch 附加组件来实现集群的日志管理.这是一个 Elasticsearch.Fluentd 和 Kibana 的组合.Elasticsearch 是一个搜索引擎,负责存储日志并提供查询接口:Fluentd 负责从 Kubernetes 搜集日志并发送给 Elasticsearch:Kibana 提供了一个 Web GUI,用户可以浏览和搜索存储在 Elasticsearch 中的日志. 部署 Elasticsearch 附加组件本身会作为 K

Kubernetes 健康状态检查(九)

强大的自愈能力是 Kubernetes 这类容器编排引擎的一个重要特性.自愈的默认实现方式是自动重启发生故障的容器.除此之外,用户还可以利用 Liveness 和 Readiness 探测机制设置更精细的健康检查,进而实现如下需求: 零停机部署. 避免部署无效的镜像. 更加安全的滚动升级. 一.Liveness 探测 Liveness 探测让用户可以自定义判断容器是否健康的条件.如果探测失败,Kubernetes 就会重启容器. 我们创建一个 Pod 的配置文件liveness.yaml,可以使

kubernetes容器集群管理部署master节点组件

集群部署获取k8s二进制包 [[email protected] ~]# wget https://dl.k8s.io/v1.15.0/kubernetes-server-linux-amd64.tar.gz [[email protected] ~]# ls kubernetes-server-linux-amd64.tar.gz [[email protected] ~]# mkdir master [[email protected] ~]# mv kubernetes-server-li

# IT明星不是梦 # 图解kubernetes容器状态同步机制核心实现

在K8s中将Pod调度到某一台Node节点之后,后续的状态维护信息则是由对应机器上的kubelet进行维护,如何实时反馈本地运行状态,并通知apiserver则是设计的难点, 本节主要是通过感知Pod状态变化和探测状态改变两个流程来实际分析其核心数据结构,来了解内部设计 1. 状态管理 1.1 静态Pod 静态Pod主要是指的那些不是通过感知apiserver创建的pod, 因为apiserver上并不包含,但是同时也需要维护和获取这类Pod的状态, k8s中就设计了一个镜像Pod的概念,其实就