13.headless、statefulset
一、headless
通常会用service来为一组pod做负载均衡,但有时并不需要要这种负载均衡。比如一个集群服务(zk、kafka),客户端需要知道一组pod所有的ip;再比如由客户端自己处理的负载均衡逻辑(如两套mysql)。
headless service配置就是把clusterIP改为None。spec.clusterIP.
这样的执行kubectl describe svc zk 会显示两个Endpoints的地址,它们是两个POD的地址+端口。
用nslookup查询headless service域名会出现两个IP。
svc域名:servicename.namespace.svc.cluster.local
每个pod都会拥有一个基于其顺序索引的稳定的主机名。重启pod,pod的IP会变化,名字不会变化。
在statefulset是一定要有headless
在deployment中,每一个pod是没有名称,是随机字符串,是无序的。而statefulset中是要求有序的,每一个pod的名称必须是固定的。当节点挂了,重建之后的标识符是不变的,每一个节点的节点名称是不能改变的。pod名称是作为pod识别的唯一标识符,必须保证其标识符的稳定并且唯一。
为了实现标识符的稳定,这时候就需要一个headless service 解析直达到pod,还需要给pod配置一个唯一的名称。
例
apiVersion: v1 kind: Service metadata: name: nginx-svc labels: app: nginx_web spec: ports: - port: 80 name: nginx-svcpord clusterIP: None selector: app: nginx_web --- apiVersion: apps/v1 kind: StatefulSet metadata: name: nginx-web spec: selector: matchLabels: app: nginx_web serviceName: "nginx-svc" replicas: 2 template: metadata: labels: app: nginx_web spec: containers: - name: nginx-pod image: nginx ports: - containerPort: 80 name: nginx-conpord
nslookup nginx-svc.default.svc.cluster.local 172.16.101.27



这两个pod,是按顺序启动了,一台running了才会启动另外一个pod

查询pod ip
pod域名:podname.svc名.default.cluster.local
扩缩容statefulset
kubectl scale sts web --replicas=3 -n default ##扩容 kubectl scale sts web --replicas=1 -n default ##缩容
二、statefulset简介
pod重新调度后podName及HostName不变。由Headless来实现。
有序的部署,有序扩展,有序删除。pod的启动按定义好的顺序依次进行。下一个pod启动之前,前一个pod必须是running/ready。
statefulset由3部分组成:
Headless Service:
volumeClaimTemplates:提供稳定的存储
Statefulset:管理pod
volumeClaimTemplates的作用:
大部分有状态副本集都会用到持久存储,比如分布式系统来说,由于数据是不一样的,每个节点都需要自己专用的存储节点。而在deployment中pod模板中创建的存储卷是一个共享的存储卷,多个pod使用同一个存储卷,而statefulset定义中的每一个pod都不能使用同一个存储卷,由此基于pod模板创建pod是不适应的,这就需要引入volumeClainTemplate,当在使用statefulset创建pod时,会自动生成一个PVC,从而请求绑定一个PV,从而有自己专用的存储卷。Pod名称、PVC和PV关系图如下:

statefulset使用时注意创建顺序:
Volume--->Persistent Volume--->Persistent Volume Claim--->Service--->StatefulSet
查看statefulset的定义
kubectl explain statefulset
KIND: StatefulSet VERSION: apps/v1 DESCRIPTION: StatefulSet represents a set of pods with consistent identities. Identities are defined as: - Network: A single stable DNS and hostname. - Storage: As many VolumeClaims as requested. The StatefulSet guarantees that a given network identity will always map to the same storage identity. FIELDS: apiVersion <string> kind <string> metadata <Object> spec <Object> status <Object> [root@k8s-master ~]# kubectl explain statefulset.spec KIND: StatefulSet VERSION: apps/v1 RESOURCE: spec <Object> DESCRIPTION: Spec defines the desired identities of pods in this set. A StatefulSetSpec is the specification of a StatefulSet. FIELDS: podManagementPolicy <string> #Pod管理策略 replicas <integer> #副本数量 revisionHistoryLimit <integer> #历史版本限制 selector <Object> -required- #选择器,必选项 serviceName <string> -required- #服务名称,必选项 template <Object> -required- #模板,必选项 updateStrategy <Object> #更新策略 volumeClaimTemplates <[]Object> #存储卷申请模板,列表对象形式
如上,一个完整的statefulset控制器由一个headless service、一个statefulset和一个volumeClaimTemplate组成。
三、例
vim stateful-demo.yaml
apiVersion: v1 kind: Service metadata: name: myapp-svc ##定义headless service名,用于关联到每个pod资源创建DNS资源记录。 labels: app: myapp-svc spec: ports: - port: 80 name: web clusterIP: None ##定义headless service selector: app: myapp-pod --- apiVersion: apps/v1 kind: StatefulSet metadata: name: myapp ##创建statefulset名 spec: serviceName: myapp-svc replicas: 3 ##3个副本 selector: matchLabels: app: myapp-pod template: ##定义pod template metadata: labels: app: myapp-pod spec: containers: - name: myapp image: ikubernetes/myapp:v1 ports: - containerPort: 80 name: web volumeMounts: - name: myappdata mountPath: /usr/share/nginx/html volumeClaimTemplates: ##基于volumeclaimtemplates向已创建的pv进行请求存储卷 - metadata: name: myappdata spec: accessModes: ["ReadWriteOnce"]
storageClassName: nfs resources: requests: storage: 2Gi ##请求2Gi的专用存储卷
vim pv-demo.yaml
apiVersion: v1 kind: PersistentVolume metadata: name: pv001 labels: name: pv001 spec: persistentVolumeReclaimPolicy: Delete nfs: path: /data/volumes/v1 server: nfs accessModes: ["ReadWriteMany","ReadWriteOnce"] capacity: storage: 2Gi --- apiVersion: v1 kind: PersistentVolume metadata: name: pv002 labels: name: pv002 spec: nfs: path: /data/volumes/v2 server: nfs accessModes: ["ReadWriteOnce"]
storageClassName: nfs capacity: storage: 2Gi --- apiVersion: v1 kind: PersistentVolume metadata: name: pv003 labels: name: pv003 spec: nfs: path: /data/volumes/v3 server: nfs accessModes: ["ReadWriteMany","ReadWriteOnce"] capacity: storage: 2Gi --- apiVersion: v1 kind: PersistentVolume metadata: name: pv004 labels: name: pv004 spec: nfs: path: /data/volumes/v4 server: nfs accessModes: ["ReadWriteMany","ReadWriteOnce"] storageClassName: nfs capacity: storage: 2Gi --- apiVersion: v1 kind: PersistentVolume metadata: name: pv005 labels: name: pv005 spec: nfs: path: /data/volumes/v5 server: nfs accessModes: ["ReadWriteMany","ReadWriteOnce"]
storageClassName: nfs capacity: storage: 2Gi
kubectl get pv
kubectl get pvc
kubectl get sts
kubectl get pod -w




启动pod是从myapp-0开始的。删除是从myapp-2开始的。用kubectl get pod -w ## -w实进刷新,可以看到myapp逐个启动/删除过程。
删除重建绑定的pv依然是原来的PVC,即myapp-0依然绑定的pv002
四、滚动更新、版本升级、更新策略
更新策略:.spec.updateStrategy.type RollinUpdate 默认为RollingUpdate。
statefulset控制器将在statefulset中删除并重新创建每个pod。按序删除重建。
4.1.版本更新
把stateful-demo.yaml中的image版本修改为v2,再次kubectl apply -f stateful-demo.yaml更新
用kubectl get pod -w查看滚动更新过程。
在创建的每一个pod中,每个pod自已的名称都是可以被解析的。

4.2.扩展伸缩
kubectl scale sts myapp --replicas=4 ##副本增加到4个

4.3.缩容
以补丁方式缩容
kubectl patch sts myapp -p '{"spec":{"replicas":2}}'


4.4.更新策略和版本升级
修改更新策略,让只有编号>=2的才会进行更新。
kubectl patch sts myapp -p '{"spec":{"updateStrategy":{"rollingUpdate":{"partition":2}}}}'

版本升级,将image版本改为2,升级后对比myapp-2和myapp-1的image版本是不一样的,这样就实现金丝雀发布效果。
kubectl set image sts/myapp myapp=ikubernetes/myapp:v3
kubectl get pods myapp-2 -o yaml | grep image
把剩下的pod也更新版本,只需要将partition值改为0
kubectl patch sts myapp -p '{"spec":{"updateStrategy":{"rollingUpdate":{"partition":0}}}}'

浙公网安备 33010602011771号