第7章 Pod控制器
1.控制器作用
1.pod类型的资源,删除pod后,不会重建
2.替用户监视并保证相应的节点上始终有用户所期望的副本数量的pod在运行
3.如果所运行的pod副本数超过了用户期望的,那么控制器就会删掉,直到和用户期望的一致
4.如果所运行的pod副本数低于用户期望的,那么控制器就会创建,直到和用户期望的一致
2.常用控制器类型
ReplicaSet RS:
按用户期望的副本创建pod,并始终保持相应数量副本
Deployment:
Deployment通过控制RS来保证POD始终保持相应的数量副本
支持滚动更新,回滚,回滚默认保留10个版本
提供声明式配置,支持动态修改
管理无状态应用最理想的控制器
node节点可能会运行0个或多个POD
DeamonSet:
一个节点只运行一个,必须是始终运行的状态
StatefulSet:
有状态应用
3.ReplicaSet控制器
https://kubernetes.io/zh/docs/concepts/workloads/controllers/replicaset/
ReplicaSet 的目的是维护一组在任何时候都处于运行状态的 Pod 副本的稳定集合。 因此,它通常用来保证给定数量的、完全相同的 Pod 的可用性。
1)编写RS控制器资源配置清单
apiVersion: apps/v1                      #接口版本号
 kind: ReplicaSet                        #资源类型 ReplicaSet
 metadata:                               #RS的原数据
   name: nginx-rs                        #RS原数据名称
   labels:                               #RS原数据标签
     app: nginx-rs                       #RS具体标签
 spec:                                   #定义pod的实际运行配置
   replicas: 2                           #要运行几个Pod
   selector:                             #选择器
     matchLabels:                        #匹配标签
       app: nginx-rs                    #匹配Pod的标签
   template:                             #创建的Pod的配置模板
     metadata:                           #pod自己的原数据
       labels:                           #pod自己的标签
         app: nginx-rs                  #pod具体标签名
     spec:                               #定义容器运行的配置
       containers:                       #容器参数
       - name: nginx-rs                  #容器名
         image: nginx                    #容器镜像
         imagePullPolicy: IfNotPresent   #镜像拉取策略
         ports:                          #暴露端口
         - name: http                    #端口说明
           containerPort: 80             #容器暴露的端口
2)应用RS资源配置清单
 kubectl create -f nginx-rs.yaml
3)查看RS资源
kubectl get rs
kubectl get pod -o wide
4)修改yaml文件应用修改
vim nginx-rs.yaml
kubectl apply -f nginx-rs.yaml
5)动态修改配置 扩容 收缩 升级
kubectl edit rs nginx
kubectl scale rs nginx --replicas=5
6)如何删除rs控制器创建的Pod?
现象:不能直接删除rs创建的pod,因为删除后rs还会在创建
结论:所以正确的操作是要直接删除rs控制器,这样rs控制器会把创建的所有pod一起删除
方法1:直接从配置文件删除
kubectl delete -f nginx-rs.yaml
方法2:直接使用命令删除
kubectl delete rs nginx-rs
4.Deployment控制器
1)Deployment和RS控制器的关系
Deployment创建ReplicaSet
由ReplicaSet创建并控制Pod使用保持期望数量在运行
更新版本时Deployment创建新版本的ReplicaSet实现Pod的轮询升级
2)资源配置清单
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx-dp
  name: nginx-dp
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx-dp
  template:
    metadata:
      labels:
        app: nginx-dp
      name: nginx-dp
    spec:
      containers:
      - image: nginx
        imagePullPolicy: IfNotPresent
        name: nginx-dp
3)应用资源配置清单
kubectl create -f nginx-dp.yaml
4)查看dp资源信息
kubectl get pod -o wide
kubectl get deployments.apps
kubectl describe deployments.apps nginx-dp
5)更新版本
方法1: 命令行根据资源配置清单修改镜像
kubectl set image -f nginx-dp.yaml nginx-containers=nginx:1.24.0
查看有没有更新
kubectl get pod
kubectl describe deployments.apps nginx-dp
kubectl describe pod nginx-dp-7c596b4d95-6ztld
方法2: 命令行根据资源类型修改镜像打开2个窗口:第一个窗口监控pod状态
 kubectl get pod -w
第二个窗口更新操作
kubectl set image deployment nginx-dp nginx-dp=nginx:1.24
kubectl set image deployment nginx-dp nginx-dp=nginx:1.25
查看更新后的deployment信息
kubectl describe deployments.apps nginx-dp
 ----------------------------------------------------
   Normal  ScalingReplicaSet  14m                  deployment-controller  Scaled up replica set nginx-dp-7c596b4d95 to 1
   Normal  ScalingReplicaSet  14m                  deployment-controller  Scaled down replica set nginx-dp-9c74bb6c7 to 1
   Normal  ScalingReplicaSet  14m                  deployment-controller  Scaled up replica set nginx-dp-7c596b4d95 to 2
   Normal  ScalingReplicaSet  13m                  deployment-controller  Scaled down replica set nginx-dp-9c74bb6c7 to 0
   Normal  ScalingReplicaSet  8m30s                deployment-controller  Scaled up replica set nginx-dp-9c74bb6c7 to 1
   Normal  ScalingReplicaSet  8m29s (x2 over 32m)  deployment-controller  Scaled up replica set nginx-dp-9c74bb6c7 to 2
   Normal  ScalingReplicaSet  8m29s                deployment-controller  Scaled down replica set nginx-dp-7c596b4d95 to 1
   Normal  ScalingReplicaSet  8m28s                deployment-controller  Scaled down replica set nginx-dp-7c596b4d95 to 0
更新过程:
nginx-dp-7c596b4d95-8z7kf   #老的版本
nginx-dp-7c596b4d95-6ztld   #老的版本
nginx-dp-9c74bb6c7-pgfxz    0/1     Pending
nginx-dp-9c74bb6c7-pgfxz    0/1     Pending
nginx-dp-9c74bb6c7-pgfxz    0/1     ContainerCreating  #拉取新版本镜像
nginx-dp-9c74bb6c7-pgfxz    1/1     Running            #运行新POD
nginx-dp-7c596b4d95-8z7kf   1/1     Terminating        #停止一个旧的POD
nginx-dp-9c74bb6c7-h7mk2    0/1     Pending
nginx-dp-9c74bb6c7-h7mk2    0/1     Pending
nginx-dp-9c74bb6c7-h7mk2    0/1     ContainerCreating  #拉取新版本镜像
nginx-dp-9c74bb6c7-h7mk2    1/1     Running            #运行新POD
nginx-dp-7c596b4d95-6ztld   1/1     Terminating        #停止一个旧的POD
nginx-dp-7c596b4d95-8z7kf   0/1     Terminating        #等待旧的POD结束
nginx-dp-7c596b4d95-6ztld   0/1     Terminating        #等待旧的POD结束
查看滚动更新状态:
kubectl rollout status deployment nginx-dp
滚动更新示意图:
6)回滚上一个版本
kubectl describe deployments.apps nginx-dp
kubectl rollout undo deployment nginx-dp
kubectl describe deployments.apps nginx-dp
7)回滚到指定版本
v1 1.14.0 v2 1.15.0 v3 3.333.3回滚到v1版本
创建第一版 1.24.0
kubectl create -f nginx-dp.yaml  --record
更新第二版 1.25.0
kubectl set image deployment nginx-dp nginx-dp=nginx:1.25.0
更新第三版 1.99.0(故意写错)
kubectl set image deployment nginx-dp nginx-dp=nginx:1.99.0
查看所有历史版本
 kubectl rollout history deployment nginx-dp
查看指定历史版本信息
 kubectl rollout history deployment nginx-dp --revision=1
回滚到指定版本
 kubectl rollout undo deployment nginx-dp --to-revision=1
8)扩缩容
kubectl scale deployment nginx-dp --replicas=5
kubectl scale deployment nginx-dp --replicas=2
总结:
动态修改镜像版本
kubectl set image deployment nginx-dp nginx-dp=nginx:1.24
kubectl set image deployment nginx-dp nginx-dp=nginx:1.25
查看所有历史版本
kubectl rollout history deployment nginx-dp
查看指定历史版本号
kubectl rollout history deployment nginx-dp --revision=2
回滚上一次
kubectl rollout undo deployment nginx-dp
回滚到指定版本
kubectl rollout undo deployment nginx-dp --to-revision=1
扩/缩容
kubectl scale deployment/nginx-dp --replicas=10
5.DaemonSet控制器
1) DaemonSet类型介绍

DaemonSet 确保全部(或者某些)节点上运行一个 Pod 的副本。 当有节点加入集群时, 也会为他们新增一个 Pod 。 当有节点从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。
简单来说就是每个节点只部署一个POD。
常见的应用场景:
监控容器
日志收集容器
2) DaemonSet举例
apiVersion: apps/v1
 kind: DaemonSet
 metadata:
   name: nginx-ds
   labels:
     app: nginx-ds
 spec:
   selector:
     matchLabels:
       app: nginx-ds
   template:
     metadata:
       labels:
         app: nginx-ds
     spec:
       containers:
       - name: nginx-ds
         image: nginx:1.16
         ports:
         - containerPort: 80
6.StatefulSet控制器
https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/statefulset/
https://kubernetes.io/zh-cn/docs/concepts/services-networking/service/#headless-services
https://kubernetes.io/zh-cn/docs/tutorials/stateful-application/basic-stateful-set/
https://blog.nashtechglobal.com/how-to-set-up-a-2-node-elasticsearch-cluster-on-kubernetes-minikube/
https://www.processon.com/view/link/66e155c15b0abf01932963a4?cid=66e0f355df5e372d74ea06b9
1)有状态和无状态服务介绍
无状态服务:
应用之间不需要通过IP通讯,比如部署多台Nginx,但是每个Nginx之间不需要通过IP通讯
有状态服务:
应用之间需要通过固定的IP通讯,如果IP地址改变了,应用状态就会不正常,比如MySQL的主从复制,Redis主从复制,ES集群,mongo副本集
2)StatefulSet介绍
StatefulSet类似于前面我们学的Replica
3)Headless Service
正常流程:
域名 --> ClsterIP --> Pod
Headless Service:
域名 --> Pod
4)定义Headless Service
cat > nginx-svc.yaml << 'EOF'
 apiVersion: v1
 kind: Service
 metadata:
   name: nginx
   namespace: default
   labels:
     app: nginx
 spec:
   selector:
     app: nginx
   ports:
   - name: http
     port: 80
   clusterIP: None
 EOF
唯一的区别就是 clusterIP: None
5)StatefulSet
创建pv:
cat > nginx-pv.yaml << 'EOF'
 apiVersion: v1
 kind: PersistentVolume
 metadata:
   name: pv01
 spec:
   capacity:
     storage: 1Gi
   accessModes:
   - ReadWriteOnce
   hostPath:
     path: /tmp/pv01
 ---
 apiVersion: v1
 kind: PersistentVolume
 metadata:
   name: pv02
 spec:
   capacity:
     storage: 1Gi
   accessModes:
   - ReadWriteOnce
   hostPath:
     path: /tmp/pv02
 EOF
创建资源配置清单:
cat > nginx-sf.yaml << 'EOF'
 apiVersion: apps/v1
 kind: StatefulSet
 metadata:
   name: web
   namespace: default
 spec:
   serviceName: "nginx"
   replicas: 2
   selector:
     matchLabels:
       app: nginx
   template:
     metadata:
       labels:
         app: nginx
     spec:
       containers:
       - name: nginx
         image: nginx:1.7.9
         ports:
         - name: web
           containerPort: 80
         volumeMounts:
         - name: www
           mountPath: /usr/share/nginx/html
   volumeClaimTemplates:
   - metadata:
       name: www
     spec:
       accessModes: [ "ReadWriteOnce" ]
       resources:
         requests:
           storage: 1Gi
 EOF
部署ES集群
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: es-pv1
  labels:
    type: local
spec:
  storageClassName: local-storage
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  local:
    path: /data/es
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - node-01
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: es-pv2
  labels:
    type: local
spec:
  storageClassName: local-storage
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  local:
    path: /data/es
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - node-02
---
apiVersion: v1
kind: Service
metadata:
  name: es
  labels:
    app: es
spec:
  ports:
  - port: 9200
    name: web
  clusterIP: None
  selector:
    app: es
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: es
spec:
  selector:
    matchLabels:
      app: es
  serviceName: "es"
  replicas: 2
  template:
    metadata:
      labels:
        app: es
    spec:
      imagePullSecrets:
      - name: harbor-secret
      containers:
      - name: es
        image: luffy.com/base/elasticsearch:7.9.1
        imagePullPolicy: IfNotPresent
        env:
        - name: node.name
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: cluster.name
          value: es-k8s
        - name: discovery.seed_hosts
          value: "es-0.es,es-1.es"
        - name: cluster.initial_master_nodes
          value: "es-0,es-1"
        - name: ES_JAVA_OPTS
          value: "-Xms512m -Xmx512m"
        ports:
        - containerPort: 9200
          name: web
        - containerPort: 9300
          name: cluster
        volumeMounts:
        - name: es-data
          mountPath: /usr/share/elasticsearch/data
  volumeClaimTemplates:
  - metadata:
      name: es-data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi
      storageClassName: local-storage
---
apiVersion: v1
kind: Service
metadata:
  name: es-svc
  labels:
    app: es
spec:
  ports:
  - port: 9200
    name: web
    targetPort: 9200
  selector:
    app: es
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: es-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: k8s.es.com
    http:
      paths:
      - path: /
        pathType: ImplementationSpecific
        backend:
          service:
            name: es-svc
            port:
              number: 9200
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: es
spec:
  selector:
    matchLabels:
      app: es
  serviceName: "es"
  replicas: 2
  template:
    metadata:
      labels:
        app: es
    spec:
      imagePullSecrets:
      - name: harbor-secret
      containers:
      - name: es
        image: luffy.com/base/elasticsearch:7.9.1
        imagePullPolicy: IfNotPresent
        env:
        - name: node.name
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: cluster.name
          value: es-k8s
        - name: discovery.seed_hosts
          value: "es-0.es,es-1.es"
        - name: cluster.initial_master_nodes
          value: "es-0,es-1"
        - name: ES_JAVA_OPTS
          value: "-Xms512m -Xmx512m"
        ports:
        - containerPort: 9200
          name: web
        - containerPort: 9300
          name: cluster
        volumeMounts:
        - name: es-data
          mountPath: /usr/share/elasticsearch/data
  volumeClaimTemplates:
  - metadata:
      name: es-data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi
      storageClassName: local-storage
7.Pod 水平自动扩缩 HAP
1)HPA介绍
官网地址:
https://kubernetes.io/zh/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/
HPA工作原理:
HAP通过收集来的监控指标分析所有Pod的负载情况,并且根据我们设定好的标准来自动扩容收缩ReplicationController、 Deployment、ReplicaSet 或 StatefulSet 中的 Pod 数量
2)Metrics Server介绍
在HAP早期版本使用的是一个叫Heapster组件来提供CPU和内存指标的,在后期的版本k8s转向了使用Metrcis Server组件来提供Pod的CPU和内存指标,Metrcis Server通过Metrics API将数据暴露出来,然后我们就可以使用k8s的API来获取相应的数据。

3)Metrics Server安装
下载项目yaml文件
wget https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.4.0/components.yaml
由于默认的镜像是从google云下载的,所以需要一些手段先下载下来,然后再导入本地的节点中。
修改配置文件:
spec:
       hostNetwork: true                     #使用host网络模式
       containers:
       - args:
         - --cert-dir=/tmp
         - --secure-port=4443
         - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
         - --kubelet-use-node-status-port
         - --kubelet-insecure-tls            #跳过证书检查
         image: metrics-server:v0.4.0        #修改为本地的镜像
创建资源:
kubectl apply -f components.yaml
查看结果:
[root@master ~]# kubectl top node
 NAME    CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
 master   79m          7%     1794Mi          46%
 node1    26m          2%     795Mi           20%
 node2    23m          2%     785Mi           20%
4)生成测试镜像
创建测试首页
cat > index.php << 'EOF'
 <?php
   $x = 0.0001;
   for ($i = 0; $i <= 1000000; $i++) {
     $x += sqrt($x);
   }
   echo "OK!";
 ?>
 EOF
创建dockerfile
cat > dockerfile << 'EOF'
FROM php:5-apache
ADD index.php /var/www/html/index.php
RUN chmod a+rx index.php
EOF
生成镜像
docker build -t php:v1 .
将镜像导出发送到其他节点:
docker save php:v1 > php.tar
scp php.tar 10.0.0.12:/opt/
scp php.tar 10.0.0.13:/opt/
导入镜像:
docker load  < /opt/php.tar
5)创建Deployment资源
cat >php-dp.yaml<< 'EOF'
 apiVersion: apps/v1
 kind: Deployment
 metadata:
   name: php-apache
 spec:
   replicas: 1
   selector:
     matchLabels:
       run: php-apache
   template:
     metadata:
       labels:
         run: php-apache
     spec:
       containers:
       - image: php:v1
         imagePullPolicy: IfNotPresent
         name: php-apache
         ports:
         - containerPort: 80
           protocol: TCP
         resources:
           requests:
             cpu: 200m
 EOF
6)创建HPA资源
cat > php-hpa.yaml <<EOF
 apiVersion: autoscaling/v1
 kind: HorizontalPodAutoscaler
 metadata:
   name: php-apache
   namespace: default
 spec:
   maxReplicas: 10
   minReplicas: 1
   scaleTargetRef:
     apiVersion: apps/v1
     kind: Deployment
     name: php-apache
   targetCPUUtilizationPercentage: 50
 EOF
7)查看HPA扩所容情况
kubectl get hpa -w
kubectl get pod -w
8)压测
 while true; do wget -q -O- http://10.2.1.18; done
9)简单创建命令
创建dp
kubectl run php-apache --image=php:v1 --requests=cpu=200m --expose --port=80
创建hpa
 kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10
10) 收缩
如果CPU使用率降下来了,k8s会默认5分钟后进行收缩

更新: 2024-09-12 09:55:36