kubernetes(k8s):管理有状态应用的工作负载 API 对象StatefulSet控制器和kubectl的弹性伸缩

文章目录

  • 1.StatefulSets简介
  • 2. statefulset通过headless service维持pod的拓扑状态
    • 2.1 通过headless service(无头服务)确保网络标识是一致
    • 2.2 StatefulSet控制器
    • 2.3 StatefulSet的两种应用状态
    • 2.4 挂接存储
  • 3. kubectl的弹性伸缩
    • 3.1 方式一:改变StatefulSet副本数量
    • 3.2 方式二:更改yaml文件
    • 3.3 方式三:命令 kubectl edit 编辑该字段:
    • 3.4 方式四:使用 kubectl patch

1.StatefulSets简介

StatefulSet 是用来管理有状态应用的工作负载 API 对象。

StatefulSet 用来管理 Deployment 和扩展一组 Pod,并且能为这些 Pod 提供序号和唯一性保证。

和 Deployment 相同的是,StatefulSet 管理了基于相同容器定义的一组 Pod。但和 Deployment 不同的是,StatefulSet 为它们的每个 Pod 维护了一个固定的 ID。这些 Pod 是基于相同的声明来创建的,但是不能相互替换:无论怎么调度,每个 Pod 都有一个永久不变的 ID

StatefulSet 和其他控制器使用相同的工作模式。你在 StatefulSet 对象 中定义你期望的状态,然后 StatefulSet 的 控制器 就会通过各种更新来达到那种你想要的状态。

StatefulSets 对于需要满足以下一个或多个需求的应用程序很有价值:

  • 稳定的、唯一的网络标识符。 DNS
  • 稳定的、持久的存储。 PV&PVC
  • 有序的、优雅的部署和缩放。
  • 有序的、自动的滚动更新。

在上面,稳定意味着 Pod 调度或重调度的整个过程是有持久性的。如果应用程序不需要任何稳定的标识符或有序的部署、删除或伸缩,则应该使用由一组无状态的副本控制器提供的工作负载来部署应用程序,比如 Deployment 或者 ReplicaSet 可能更适用于您的无状态应用部署需要。

2. statefulset通过headless service维持pod的拓扑状态

2.1 通过headless service(无头服务)确保网络标识是一致

(1)创建Headless service 无头服务

apiVersion: v1
kind: Service
metadata:
 name: nginx
 labels:
  app: nginx
spec:
 ports:
 - port: 80
   name: web
 clusterIP: None
 selector:
  app: nginx

开启一个nginx服务
kubernetes(k8s):管理有状态应用的工作负载 API 对象StatefulSet控制器和kubectl的弹性伸缩_第1张图片

2.2 StatefulSet控制器

apiVersion: apps/v1
kind: StatefulSet
metadata:
 name: web
spec:
 serviceName: "nginx"
 replicas: 2
 selector:
  matchLabels:
   app: nginx
 template:
  metadata:
   labels:
    app: nginx
  spec:
   containers:
   - name: nginx
     image: reg.westos.org/k8s/nginx
     ports:
     - containerPort: 80
       name: web

kubernetes(k8s):管理有状态应用的工作负载 API 对象StatefulSet控制器和kubectl的弹性伸缩_第2张图片

[kubeadm@server1 statefulset]$ kubectl describe svc nginx 
Name:              nginx
Namespace:         default
Labels:            app=nginx
Annotations:       Selector:  app=nginx
Type:              ClusterIP
IP:                None
Port:              web  80/TCP
TargetPort:        80/TCP
Endpoints:         10.244.1.104:80,10.244.2.49:80
Session Affinity:  None
Events:            <none>
[kubeadm@server1 statefulset]$ 

StatefulSet给所有的Pod进行了编号,编号规则是

$(statefulset名称)-$(序号),从0开始。

将我们的deployment.yaml中的replicas: 0改为0时,statefulset会自动回收pod,将pod重建之后名称不变(还是web0和web1)但是ip变了。

2.3 StatefulSet的两种应用状态

StatefulSet将应用状态抽象成了两种情况:

  • 拓扑状态:应用实例必须按照某种顺序启动。新创建的Pod必须和原来Pod的网络标识一样
  • 存储状态:应用的多个实例分别绑定了不同存储数据。

StatefulSet给所有的Pod进行了编号,编号规则是:(statefulset名称)−(statefulset名称)−(序号),从0开始。

Pod被删除后重建,重建Pod的网络标识也不会改变,Pod的拓扑状态按照Pod的“名字+编号”的方式固定下来,并且为每个Pod提供了一个固定且唯一的访问入口,即Pod对应的DNS记录。

[kubeadm@server1 statefulset]$ kubectl run test --image=busyboxplus -itv
/ # nslookup web-0.nginx.default.svc.cluster.local  # 访问web0
(pod名称+服务名称+默认命名空间+默认域)
Server:    10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

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

/ # nslookup web-1.nginx.default.svc.cluster.local
Server:    10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

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

/ # curl web-0.nginx  # 可以解析
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

2.4 挂接存储

PV和PVC的设计,使得StatefulSet对存储状态的管理成为了可能

[kubeadm@server1 statefulset]$ kubectl delete -f statefulset.yaml

[kubeadm@server1 statefulset]$ cat statefulset.yaml 
apiVersion: apps/v1
kind: StatefulSet
metadata:
 name: web
spec:
 serviceName: "nginx"
 replicas: 2
 selector:
  matchLabels:
   app: nginx
 template:
  metadata:
   labels:
    app: nginx
  spec:
   containers:
   - name: nginx
     image: reg.westos.org/k8s/nginx
     ports:
     - containerPort: 80
       name: web
     volumeMounts:
       - name: www
         mountPath: /usr/share/nginx/html
 volumeClaimTemplates:
  - metadata:
     name: www
    spec:
     storageClassName: managed-nfs-storage
     accessModes:
     - ReadWriteOnce
     resources:
      requests:
       storage: 1Gi

[kubeadm@server1 statefulset]$ kubectl apply -f statefulset.yaml

nslookup用于查询DNS的记录,查询域名解析是否正常,在网络故障时用来诊断网络问题

自动创建了pv和pvc
kubernetes(k8s):管理有状态应用的工作负载 API 对象StatefulSet控制器和kubectl的弹性伸缩_第3张图片Pod的创建也是严格按照编号顺序进行的。比如在web-0进入到running状态,并且Conditions为Ready之前,web-1一直会处于pending状态。

StatefulSet还会为每一个Pod分配并创建一个同样编号的PVC。这样,kubernetes就可以通过Persistent Volume机制为这个PVC绑定对应的PV,从而保证每一个Pod都拥有一个独立的Volume。
kubernetes(k8s):管理有状态应用的工作负载 API 对象StatefulSet控制器和kubectl的弹性伸缩_第4张图片注意:在删除StatefulSet类型的文件时,将replicas设置为0,会自动回收pod

[kubeadm@server1 statefulset]$ cat statefulset.yaml 
apiVersion: apps/v1
kind: StatefulSet
metadata:
 name: web
spec:
 serviceName: "nginx"
 replicas: 0

[kubeadm@server1 statefulset]$ kubectl delete -f statefulset.yaml 
statefulset.apps "web" deleted

3. kubectl的弹性伸缩

首先,想要弹缩的StatefulSet. 需先清楚是否能弹缩该应用.

[kubeadm@server1 statefulset]$ kubectl get statefulset
NAME   READY   AGE
web    0/0     59m

3.1 方式一:改变StatefulSet副本数量

$ kubectl scale statefulsets <stateful-set-name> --replicas=<new-replicas>

3.2 方式二:更改yaml文件

如果StatefulSet开始由 kubectl apply 或 kubectl create --save-config 创建,更新StatefulSet manifests中的 .spec.replicas(更改replicas的数目), 然后执行命令 kubectl apply:

$ kubectl apply -f <stateful-set-file-updated>

3.3 方式三:命令 kubectl edit 编辑该字段:

kubectl edit statefulsets <stateful-set-name>

3.4 方式四:使用 kubectl patch

$ kubectl patch statefulsets <stateful-set-name> -p '{"spec":{"replicas":}}'

你可能感兴趣的:(kubernetes)