java系统找不到指定文件怎么解决
297
2022-09-10
Kubernetes StatefulSet有状态应用
文章目录
0. 简介1. 创建 StatefulSet2. 扩容/缩容 StatefulSet
2.1 扩容2.2 缩容
3. 更新 StatefulSet
3.1 Rolling Update 策略3.2 分段更新3.3 灰度发布
4. 删除 StatefulSet
4.1 非级联删除4.2 级联删除
5. Pod 管理策略
5.1 Parallel Pod 管理策略
6. 示例
0. 简介
StatefulSet 是用来管理有状态应用的工作负载 API 对象。
StatefulSet 用来管理 Deployment 和扩展一组 Pod,并且能为这些 Pod 提供序号和唯一性保证。
StatefulSet 和其他控制器使用相同的工作模式。你在 StatefulSet 对象 中定义你期望的状态,然后 StatefulSet 的 控制器 就会通过各种更新来达到那种你想要的状态。
使用 StatefulSets
1. 创建 StatefulSet
它创建了一个 Headless Service nginx 用来发布 StatefulSet web 中的 Pod 的 IP 地址。
apiVersion: v1kind: Servicemetadata: name: nginx labels: app: nginxspec: ports: - port: 80 name: web clusterIP: None selector: app: nginx---apiVersion: apps/v1kind: StatefulSetmetadata: name: webspec: serviceName: "nginx" replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: k8s.gcr.io/nginx-slim:0.8 ports: - containerPort: 80 name: web volumeMounts: - name: mountPath: /usr/share/nginx/html volumeClaimTemplates: - metadata: name: spec: accessModes: [ "ReadWriteOnce" ] resources: requests: storage: 1Gi
你需要使用两个终端窗口。在第一个终端中,使用 kubectl get 来查看 StatefulSet 的 Pods 的创建情况。
kubectl get pods -w -l app=nginx
在另一个终端中,使用 kubectl apply来创建定义在 web.yaml 中的 Headless Service 和 StatefulSet。
$ kubectl apply -f web.yamlservice/nginx createdstatefulset.apps/web created$ kubectl get service nginxNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEnginx ClusterIP None 80/TCP 12s$ kubectl get statefulset webNAME DESIRED CURRENT AGEweb 2 1 20s$ kubectl get pods -w -l app=nginxNAME READY STATUS RESTARTS AGEweb-0 0/1 Pending 0 0sweb-0 0/1 Pending 0 0sweb-0 0/1 ContainerCreating 0 0sweb-0 1/1 Running 0 19sweb-1 0/1 Pending 0 0sweb-1 0/1 Pending 0 0sweb-1 0/1 ContainerCreating 0 0sweb-1 1/1 Running 0 18s
StatefulSet 中的 Pod 拥有一个具有黏性的、独一无二的身份标志。这个标志基于 StatefulSet 控制器分配给每个 Pod 的唯一顺序索引。Pod 的名称的形式为
$ for i in 0 1; do kubectl exec web-$i -- sh -c 'hostname'; doneweb-0web-1$ kubectl run -i --tty --image busybox:1.28 dns-test --restart=Never --rm$ nslookup web-0.nginxServer: 10.0.0.10Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.localName: web-0.nginxAddress 1: 10.244.1.6$ nslookup web-1.nginxServer: 10.0.0.10Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.localName: web-1.nginxAddress 1: 10.244.2.6
headless service 的 CNAME 指向 SRV 记录(记录每个 Running 和 Ready 状态的 Pod)。SRV 记录指向一个包含 Pod IP 地址的记录表项。
kubectl get pod -w -l app=nginxkubectl delete pod -l app=nginxpod "web-0" deletedpod "web-1" deleted等待 StatefulSet 重启它们,并且两个 Pod 都变成 Running 和 Ready 状态。kubectl get pod -w -l app=nginxNAME READY STATUS RESTARTS AGEweb-0 0/1 ContainerCreating 0 0sNAME READY STATUS RESTARTS AGEweb-0 1/1 Running 0 2sweb-1 0/1 Pending 0 0sweb-1 0/1 Pending 0 0sweb-1 0/1 ContainerCreating 0 0sweb-1 1/1 Running 0 34s使用 kubectl exec 和 kubectl run 查看 Pod 的主机名和集群内部的 DNS 表项。for i in 0 1; do kubectl exec web-$i -- sh -c 'hostname'; doneweb-0web-1kubectl run -i --tty --image busybox:1.28 dns-test --restart=Never --rm /bin/shnslookup web-0.nginxServer: 10.0.0.10Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.localName: web-0.nginxAddress 1: 10.244.1.7nslookup web-1.nginxServer: 10.0.0.10Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.localName: web-1.nginxAddress 1: 10.244.2.8
Pod 的序号、主机名、SRV 条目和记录名称没有改变,但和 Pod 相关联的 IP 地址可能发生了改变。在本教程中使用的集群中它们就改变了。这就是为什么不要在其他应用中使用 StatefulSet 中的 Pod 的 IP 地址进行连接,这点很重要。
如果你需要查找并连接一个 StatefulSet 的活动成员,你应该查询 Headless Service 的 CNAME。和 CNAME 相关联的 SRV 记录只会包含 StatefulSet 中处于 Running 和 Ready 状态的 Pod。
如果你的应用已经实现了用于测试 liveness 和 readiness 的连接逻辑,你可以使用 Pod 的 SRV 记录(web-0.nginx.default.svc.cluster.local, web-1.nginx.default.svc.cluster.local)。因为他们是稳定的,并且当你的 Pod 的状态变为 Running 和 Ready 时,你的应用就能够发现它们的地址。
2. 扩容/缩容 StatefulSet
2.1 扩容
$ kubectl scale sts web --replicas=5 #扩展副本数为 5$ kubectl get pods -w -l app=nginxNAME READY STATUS RESTARTS AGEweb-0 1/1 Running 0 2hweb-1 1/1 Running 0 2hNAME READY STATUS RESTARTS AGEweb-2 0/1 Pending 0 0sweb-2 0/1 Pending 0 0sweb-2 0/1 ContainerCreating 0 0sweb-2 1/1 Running 0 19sweb-3 0/1 Pending 0 0sweb-3 0/1 Pending 0 0sweb-3 0/1 ContainerCreating 0 0sweb-3 1/1 Running 0 18sweb-4 0/1 Pending 0 0sweb-4 0/1 Pending 0 0sweb-4 0/1 ContainerCreating 0 0sweb-4 1/1 Running 0 19s
2.2 缩容
$ kubectl patch sts web -p '{"spec":{"replicas":3}}'$ kubectl get pods -w -l app=nginxNAME READY STATUS RESTARTS AGEweb-0 1/1 Running 0 3hweb-1 1/1 Running 0 3hweb-2 1/1 Running 0 55sweb-3 1/1 Running 0 36sweb-4 0/1 ContainerCreating 0 18sNAME READY STATUS RESTARTS AGEweb-4 1/1 Running 0 19sweb-4 1/1 Terminating 0 24sweb-4 1/1 Terminating 0 24sweb-3 1/1 Terminating 0 42sweb-3 1/1 Terminating 0 42s
3. 更新 StatefulSet
更新策略由 StatefulSet API Object 的spec.updateStrategy 字段决定。这个特性能够用来更新一个 StatefulSet 中的 Pod 的 container images,resource requests,以及 limits,labels 和 annotations。RollingUpdate滚动更新是 StatefulSets 默认策略。
3.1 Rolling Update 策略
$ kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"type":"RollingUpdate"}}}'statefulset.apps/web patched$ kubectl patch statefulset web --type='json' -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value":"gcr.io/google_containers/nginx-slim:0.8"}]'statefulset.apps/web patched$ kubectl get po -l app=nginx -wNAME READY STATUS RESTARTS AGEweb-0 1/1 Running 0 7mweb-1 1/1 Running 0 7mweb-2 1/1 Running 0 8mweb-2 1/1 Terminating 0 8mweb-2 1/1 Terminating 0 8mweb-2 0/1 Terminating 0 8mweb-2 0/1 Terminating 0 8mweb-2 0/1 Terminating 0 8mweb-2 0/1 Terminating 0 8mweb-2 0/1 Pending 0 0sweb-2 0/1 Pending 0 0sweb-2 0/1 ContainerCreating 0 0sweb-2 1/1 Running 0 19sweb-1 1/1 Terminating 0 8mweb-1 0/1 Terminating 0 8mweb-1 0/1 Terminating 0 8mweb-1 0/1 Terminating 0 8mweb-1 0/1 Pending 0 0sweb-1 0/1 Pending 0 0sweb-1 0/1 ContainerCreating 0 0sweb-1 1/1 Running 0 6sweb-0 1/1 Terminating 0 7mweb-0 1/1 Terminating 0 7mweb-0 0/1 Terminating 0 7mweb-0 0/1 Terminating 0 7mweb-0 0/1 Terminating 0 7mweb-0 0/1 Terminating 0 7mweb-0 0/1 Pending 0 0sweb-0 0/1 Pending 0 0sweb-0 0/1 ContainerCreating 0 0sweb-0 1/1 Running 0 10s
获取 Pod 来查看他们的容器镜像。
$ for p in 0 1 2; do kubectl get po web-$p --template '{{range $i, $c := .spec.containers}}{{$c.image}}{{end}}'; echo; donek8s.gcr.io/nginx-slim:0.8k8s.gcr.io/nginx-slim:0.8k8s.gcr.io/nginx-slim:0.8
kubectl rollout status sts/
3.2 分段更新
你可以使用 RollingUpdate 更新策略的 partition 参数来分段更新一个 StatefulSet。分段的更新将会使 StatefulSet 中的其余所有 Pod 保持当前版本的同时仅允许改变 StatefulSet 的 .spec.template。
Patch web StatefulSet 来对 updateStrategy 字段添加一个分区。
$ kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"type":"RollingUpdate","rollingUpdate":{"partition":3}}}}'statefulset.apps/web patched
再次 Patch StatefulSet 来改变容器镜像。
$ kubectl patch statefulset web --type='json' -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value":"k8s.gcr.io/nginx-slim:0.7"}]'statefulset.apps/web patched
删除 StatefulSet 中的 Pod。
$ kubectl delete po web-2pod "web-2" deleted
3.3 灰度发布
通过 patch 命令修改 StatefulSet 来减少分区。
$ kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"type":"RollingUpdate","rollingUpdate":{"partition":2}}}}'statefulset.apps/web patched$ kubectl get po -lapp=nginx -w #等待 web-2 变成 Running 和 Ready。
4. 删除 StatefulSet
4.1 非级联删除
–cascade=false 参数给命令。这个参数告诉 Kubernetes 只删除 StatefulSet 而不要删除它的任何 Pod。
$ kubectl delete statefulset web --cascade=falsestatefulset.apps "web" deleted$ kubectl get pods -l app=nginxNAME READY STATUS RESTARTS AGEweb-0 1/1 Running 0 6mweb-1 1/1 Running 0 7mweb-2 1/1 Running 0 5m$ kubectl delete pod web-0pod "web-0" deleted$ kubectl get pods -l app=nginxNAME READY STATUS RESTARTS AGEweb-1 1/1 Running 0 10mweb-2 1/1 Running 0 7m$ kubectl apply -f web.yamlstatefulset.apps/web createdservice/nginx unchanged$ kubectl get pods -w -l app=nginxNAME READY STATUS RESTARTS AGEweb-1 1/1 Running 0 16mweb-2 1/1 Running 0 2mNAME READY STATUS RESTARTS AGEweb-0 0/1 Pending 0 0sweb-0 0/1 Pending 0 0sweb-0 0/1 ContainerCreating 0 0sweb-0 1/1 Running 0 18sweb-2 1/1 Terminating 0 3mweb-2 0/1 Terminating 0 3mweb-2 0/1 Terminating 0 3mweb-2 0/1 Terminating 0 3m
当重新创建 web StatefulSet 时,web-0被第一个重新启动。由于 web-1 已经处于 Running 和 Ready 状态,当 web-0 变成 Running 和 Ready 时,StatefulSet 会直接接收这个 Pod。由于你重新创建的 StatefulSet 的 replicas 等于 2,一旦 web-0 被重新创建并且 web-1 被认为已经处于 Running 和 Ready 状态时,web-2将会被终止。
4.2 级联删除
$ kubectl delete statefulset web$ kubectl get pods -w -l app=nginxNAME READY STATUS RESTARTS AGEweb-0 1/1 Running 0 11mweb-1 1/1 Running 0 27mNAME READY STATUS RESTARTS AGEweb-0 1/1 Terminating 0 12mweb-1 1/1 Terminating 0 29mweb-0 0/1 Terminating 0 12mweb-0 0/1 Terminating 0 12mweb-0 0/1 Terminating 0 12mweb-1 0/1 Terminating 0 29mweb-1 0/1 Terminating 0 29mweb-1 0/1 Terminating 0 29m
虽然级联删除会删除 StatefulSet 和它的 Pod,但它并不会删除和 StatefulSet 关联的 Headless Service。你必须手动删除nginx Service。
$ kubectl delete service nginxservice "nginx" deleted
5. Pod 管理策略
5.1 Parallel Pod 管理策略
Parallel pod 管理策略告诉 StatefulSet 控制器并行的终止所有 Pod,在启动或终止另一个 Pod 前,不必等待这些 Pod 变成 Running 和 Ready 或者完全终止状态.
apiVersion: v1kind: Servicemetadata: name: nginx labels: app: nginxspec: ports: - port: 80 name: web clusterIP: None selector: app: nginx---apiVersion: apps/v1kind: StatefulSetmetadata: name: webspec: serviceName: "nginx" podManagementPolicy: "Parallel" replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: k8s.gcr.io/nginx-slim:0.8 ports: - containerPort: 80 name: web volumeMounts: - name: mountPath: /usr/share/nginx/html volumeClaimTemplates: - metadata: name: spec: accessModes: [ "ReadWriteOnce" ] resources: requests: storage: 1Gi
执行:效果并行执行
kubectl get po -lapp=nginx -wkubectl apply -f web-parallel.yamlkubectl apply -f web-parallel.yamlkubectl delete sts webkubectl delete svc nginx
6. 示例
创建service
apiVersion: v1kind: Servicemetadata: labels: app: cassandra name: cassandraspec: clusterIP: None ports: - port: 9042 selector: app: cassandra
kubectl apply -f apps/v1kind: StatefulSetmetadata: name: cassandra labels: app: cassandraspec: serviceName: cassandra replicas: 3 selector: matchLabels: app: cassandra template: metadata: labels: app: cassandra spec: terminationGracePeriodSeconds: 1800 containers: - name: cassandra image: gcr.io/google-samples/cassandra:v13 imagePullPolicy: Always ports: - containerPort: 7000 name: intra-node - containerPort: 7001 name: tls-intra-node - containerPort: 7199 name: jmx - containerPort: 9042 name: cql resources: limits: cpu: "500m" memory: 1Gi requests: cpu: "500m" memory: 1Gi securityContext: capabilities: add: - IPC_LOCK lifecycle: preStop: exec: command: - /bin/sh - -c - nodetool drain env: - name: MAX_HEAP_SIZE value: 512M - name: HEAP_NEWSIZE value: 100M - name: CASSANDRA_SEEDS value: "cassandra-0.cassandra.default.svc.cluster.local" - name: CASSANDRA_CLUSTER_NAME value: "K8Demo" - name: CASSANDRA_DC value: "DC1-K8Demo" - name: CASSANDRA_RACK value: "Rack1-K8Demo" - name: POD_IP valueFrom: fieldRef: fieldPath: status.podIP readinessProbe: exec: command: - /bin/bash - -c - /ready-probe.sh initialDelaySeconds: 15 timeoutSeconds: 5 # These volume mounts are persistent. They are like inline claims, # but not exactly because the names need to match exactly one of # the stateful pod volumes. volumeMounts: - name: cassandra-data mountPath: /cassandra_data # These are converted to volume claims by the controller # and mounted at the paths mentioned above. # do not use these in production until ssd GCEPersistentDisk or other ssd pd volumeClaimTemplates: - metadata: name: cassandra-data spec: accessModes: [ "ReadWriteOnce" ] storageClassName: fast resources: requests: storage: 1Gi---kind: StorageClassapiVersion: storage.k8s.io/v1metadata: name: fastprovisioner: k8s.io/minikube-hostpathparameters: type: pd-ssd
# 创建 statefulsetkubectl apply -f https://k8s.io/examples/application/cassandra/cassandra-statefulset.yaml
参考资料:https://kubernetes.io/zh/docs/tutorials/stateful-application/basic-stateful-set/https://kubernetes.io/zh/docs/tutorials/stateful-application/cassandra/
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~