设为首页 收藏本站
查看: 723|回复: 0

[经验分享] Kubernetes有状态应用管理

[复制链接]

尚未签到

发表于 2018-1-4 14:41:20 | 显示全部楼层 |阅读模式
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)        静态存储;
  2)        有固定的主机名,且DNS可寻址(稳定的网络身份,这是通过一种叫 Headless Service 的特殊Service来实现的。 和普通Service相比,Headless Service没有Cluster IP,用于为一个集群内部的每个成员提供一个唯一的DNS名字,用于集群内部成员之间通信 。);
  3)        一个有序的index(比如PetSet的名字叫mysql,那么第一个启起来的Pet就叫mysql-0,第二个叫mysql-1,如此下去。当一个Pet down掉后,新创建的Pet会被赋予跟原来Pet一样的名字,通过这个名字就能匹配到原来的存储,实现状态保存。)
  应用举例:
  1)        数据库应用,如Mysql、PostgreSQL,需要一个固定的ID(用于数据同步)以及外挂一块NFS Volume(持久化存储)。
  2)        集群软件,如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,若为nfs这种无法通过调用API来创建存储的网络存储,数据卷要在创建PetSet之前静态创建;若为aws-ebs、vSphere、openstack Cinder这种可以通过API调用来动态创建存储的虚拟存储,数据卷除了可以通过静态的方式创建以外,还可以通过StorageClass进行动态创建。需要注意的是,动态创建出来的PV,默认的回收策略是delete,及在删除数据的同时,还会把虚拟存储卷删除);
  5)        删除或缩容PetSet不会删除对应的持久化数据卷,这么做是处于数据安全性的考虑;
  6)        只能通过手动的方式升级PetSet。

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

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

[iyunv@k8s-master 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  
[iyunv@k8s
-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  
[iyunv@k8s
-master pv]# kubectl create -f nfs-pv.yaml  
persistentvolume
"pv0001" created  
[iyunv@k8s
-master pv]# kubectl create -f nfs-pv2.yaml  
persistentvolume
"pv0002" created  
[iyunv@k8s
-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解析
  

[iyunv@k8s-master pv]# cd ../petset/  
[iyunv@k8s
-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
  
[iyunv@k8s
-master petset]# kubectl create -f test-petset.yaml  
service
"nginx" created  
petset
"web" created  
[iyunv@k8s
-master petset]# kubectl get petset  
NAME      DESIRED   CURRENT   AGE
  
web
2         2         11s  
[iyunv@k8s
-master petset]# kubectl get pod  
NAME      READY     STATUS    RESTARTS   AGE
  
web
-0       1/1       Running   0          16s  
web
-1       1/1       Running   0          12s  
[iyunv@k8s
-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  
[iyunv@k8s
-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  
[iyunv@k8s
-master petset]# kubectl exec -ti web-0 /bin/bash  
root@web
-0:/# cd /usr/share/nginx/html  
root@web
-0:/usr/share/nginx/html# ls  
root@web
-0:/usr/share/nginx/html# touch 1.out  
root@web
-0:/usr/share/nginx/html# exit  
exit
  
[iyunv@k8s
-master petset]# ssh 192.168.20.47 #登录到NFS主机  
root@
192.168.20.47's password:  
Last login: Tue Mar 28 11:54:58 2017 from 10.0.251.145
  
[iyunv@localhost ~]# echo "123456">> /data/disk1/1.out
  
[iyunv@localhost ~]# exit
  
登出
  
Connection to 192.168.20.47 closed.
  
[iyunv@k8s-master petset]# kubectl exec -ti web-0 /bin/bash
  
root@web-0:/# cat /usr/share/nginx/html/1.out
  
123456
  
root@web-0:/# exit
  
exit
  
[iyunv@k8s-master petset]# kubectl exec -ti web-1 /bin/bash
  
root@web-1:/# cat /usr/share/nginx/html/1.out
  
123456
  
root@web-1:/# exit
  
exit
  
[iyunv@k8s-master petset]#
  


3.3 验证域名解析
  检查PetSet中的Pod的hostName
  

[iyunv@k8s-master ~]# for i in 0 1; do kubectl exec web-$i -- sh -c 'hostname'; done  
web
-0  
web
-1  

  检查通过hostName解析IP
  

[iyunv@k8s-master dns14]# kubectl get svc nginx  
NAME      CLUSTER
-IP   EXTERNAL-IP   PORT(S)   AGE  
nginx     None
<none>        80/TCP    5h  
[iyunv@k8s
-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.
  
[iyunv@k8s
-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  
[iyunv@k8s
-master ~]# kubectl exec -i -t frontend-service-1988680557-xuysd /bin/bash #进入集群中的一个pod  
[iyunv@frontend
-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  

  
[iyunv@frontend
-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路径  
[iyunv@k8s
-master dns14]# kubectl exec web-0 -- sh -c 'echo $(hostname) > /usr/share/nginx/html/index.html'  
#在其它Pod上获取web
-0的欢迎页  
[iyunv@k8s
-master dns14]# kubectl exec -it web-1 -- curl web-0.nginx  
web
-0  
[iyunv@k8s
-master dns14]# kubectl exec -it web-0 -- curl web-0.nginx  
web
-0  
#查询web
-0的存活时间  
[iyunv@k8s
-master dns14]# kubectl get pod | grep web  
web
-0                               1/1       Running   0          5h  
web
-1                               1/1       Running   0          5h  
[iyunv@k8s
-master dns14]# kubectl delete pod web-0  #删除web-0  
pod
"web-0" deleted  
[iyunv@k8s
-master dns14]# kubectl get pod | grep web  #可以看到,web-0被删除后几乎立即又被重建了  
web
-0             1/1       Running   0          3s  
web
-1             1/1       Running   0          5h  
[iyunv@k8s
-master dns14]# kubectl get pod | grep web  
web
-0            1/1       Running   0          5s  
web
-1            1/1       Running   0          5h  
#查看web
-0中的欢迎页是否还在  
[iyunv@k8s
-master dns14]# kubectl exec -it web-0 -- curl web-0.nginx  
web
-0  
[iyunv@k8s
-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中的镜像功能示例如下:
  

[iyunv@k8s-master ~]# kubectl get po web-0 --template '{{range $i, $c := .spec.containers}}{{$c.image}}{{end}}'  
gcr.io
/google_containers/nginx-slim:0.8  
[iyunv@k8s
-master ~]# kubectl exec -i -t frontend-service-1988680557-xuysd /bin/bash #进入集群中的一个pod  
[iyunv@frontend
-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  

  
[iyunv@k8s
-master ~]# kubectl edit petset/web  #执行之后就像打开一个vi界面,修改对应的镜像名称或版本,保存退出  
petset
"web" edited  
#也可以用set image的方式进行更改
  
[iyunv@k8s
-master ~]#  kubectl set image petset/web nginx=gcr.io/google_containers/nginx-slim:0.7  
petset
"web" image updated  
[iyunv@k8s
-master ~]# kubectl delete po web-0  #手动删除第一个Pod,PetSet会自动给我们再起一个  
pod
"web-0" deleted  
[iyunv@k8s
-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  
[iyunv@k8s
-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会自动按照新版本的镜像帮我们启动起来。

5、后续新功能
  官方给出后续将会逐步推出的新功能如下:
  1)        数据安全与本地数据存储(目前仅支持网络共享存储卷,在IO高的情况下网络存储卷可能会出现性能瓶颈,后续Kubernetes将会推出支持本地存储的PetSet)
  2)        丰富通知实践
  3)        公网的网络身份
  4)        广域网集群发布(跨多个可用区、region、云服务提供商)
  5)        更多的自动运维手段(包括镜像升级等)

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-431538-1-1.html 上篇帖子: Kubernetes留言板 下篇帖子: kubernetes-deployments
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表