k8s POD控制器

POD控制器

Pod控制器,又称为工作负载(workload),是Kubernetes中用于实现管理Pod的中间层,它确保Pod资源符合预期的状态。当Pod资源出现故障时,Pod控制器会尝试进行重启,若根据重启策略无效,则会重新新建Pod资源。以下是Pod控制器的详细介绍:

一、Pod控制器的作用

1.1. 确保Pod副本数量:

Pod控制器代用户创建指定数量的Pod副本,并确保这些副本数量符合预期状态。

1.2. 自动恢复:

当Pod资源出现故障时,控制器会根据定义的策略重新编排Pod,确保应用的持续运行。

1.3. 扩缩容:

支持滚动式自动扩容和缩容功能,根据应用需求调整Pod数量。

1.4. 更新和回滚:

对于某些控制器(如Deployment),支持应用的滚动更新和版本回退。

二、常见的Pod控制器类型

2.1 ReplicaSet/ReplicationController

作用:用于保证Pod的副本数量维持在用户指定的数量。它支持Pod数量的扩缩Pod模板的更新,但不涉及应用状态的管理。
组件:主要由用户期望的Pod副本数量、标签选择器(用于判断哪个Pod归自理)和Pod资源模板组成。
特点:帮助用户管理无状态的Pod资源,精确反应用户定义的目标数量ReplicaSet不是直接使用的控制器,而是通常通过Deployment来间接管理。

2.1.1 ReplicationController(RC)
apiVersion: v1
kind: ReplicationController
metadata:
 name: rc-demo
spec: # rc期望
 replicas: 3 # 定义当前pod副本数量
 selector: # pod选择器
  app: rc-demo # 选择符合选择器标签的pod
 template: # 模版
  metadata:
   labels:
    app: rc-demo
  spec: # 容器期望
   containers:
   - name: rc-demo-container
     image: wangyanglinux/myapp:v1.0
     env: #环境变量
     - name: GET_HOSTS_FROM
       value: dns
     - name: zhangsan
       value: "123"
     ports:
     - containerPort: 80

[root@master 5]# kubectl get rc
NAME      DESIRED   CURRENT   READY   AGE
rc-demo   3         3         3       25s

[root@master 5]# kubectl get pod
NAME            READY   STATUS    RESTARTS   AGE
rc-demo-9rw48   1/1     Running   0          21s
rc-demo-hxtj8   1/1     Running   0          21s
rc-demo-v687d   1/1     Running   0          21s

[root@master 5]# kubectl label pod rc-demo-nrkvf version=v1
pod/rc-demo-nrkvf labeled
[root@master 5]# kubectl get pod --show-labels
NAME            READY   STATUS    RESTARTS   AGE     LABELS
rc-demo-9rw48   1/1     Running   0          5m38s   app=rc-demo
rc-demo-hxtj8   1/1     Running   0          5m38s   app=rc-demo
rc-demo-nrkvf   1/1     Running   0          4m17s   app=rc-demo,version=v1

[root@master 5]# kubectl label pod rc-demo-nrkvf app=test --overwrite
pod/rc-demo-nrkvf labeled

[root@master 5]# kubectl get pod --show-labels
NAME            READY   STATUS    RESTARTS   AGE     LABELS
rc-demo-9rw48   1/1     Running   0          6m35s   app=rc-demo
rc-demo-hxtj8   1/1     Running   0          6m35s   app=rc-demo
rc-demo-nrkvf   1/1     Running   0          5m14s   app=test,version=v1
rc-demo-sbhb2   1/1     Running   0          9s      app=rc-demo


# 调整副本数量
[root@master 5]# kubectl scale rc rc-demo --replicas=10
replicationcontroller/rc-demo scaled
[root@master 5]# kubectl get pod --show-labels
NAME            READY   STATUS    RESTARTS   AGE    LABELS
rc-demo-98w2k   1/1     Running   0          10s    app=rc-demo
rc-demo-9rw48   1/1     Running   0          13m    app=rc-demo
rc-demo-cdvrq   1/1     Running   0          10s    app=rc-demo
rc-demo-cf42f   1/1     Running   0          10s    app=rc-demo
rc-demo-dgj5p   1/1     Running   0          10s    app=rc-demo
rc-demo-f2g6k   1/1     Running   0          10s    app=rc-demo
rc-demo-hxtj8   1/1     Running   0          13m    app=rc-demo
rc-demo-n2fp8   1/1     Running   0          10s    app=rc-demo
rc-demo-nrkvf   1/1     Running   0          12m    app=test,version=v1
rc-demo-nw2h9   1/1     Running   0          10s    app=rc-demo
rc-demo-sbhb2   1/1     Running   0          7m2s   app=rc-demo

[root@master 5]# kubectl label pod rc-demo-nrkvf app=rc-demo --overwrite
pod/rc-demo-nrkvf labeled
[root@master 5]# kubectl get pod --show-labels
NAME            READY   STATUS    RESTARTS   AGE     LABELS
rc-demo-98w2k   1/1     Running   0          41s     app=rc-demo
rc-demo-9rw48   1/1     Running   0          13m     app=rc-demo
rc-demo-cdvrq   1/1     Running   0          41s     app=rc-demo
rc-demo-cf42f   1/1     Running   0          41s     app=rc-demo
rc-demo-dgj5p   1/1     Running   0          41s     app=rc-demo
rc-demo-f2g6k   1/1     Running   0          41s     app=rc-demo
rc-demo-hxtj8   1/1     Running   0          13m     app=rc-demo
rc-demo-n2fp8   1/1     Running   0          41s     app=rc-demo
rc-demo-nrkvf   1/1     Running   0          12m     app=re-demo,version=v1
rc-demo-nw2h9   1/1     Running   0          41s     app=rc-demo
rc-demo-sbhb2   1/1     Running   0          7m33s   app=rc-demo

2.1.2 ReplicaSet(RS)

ReplicaSet的匹配运算符主要包括以下几种,这些运算符用于在Pod模板的标签选择器(selector)中指定选择Pod的规则:

2.1.2.1 matchLabels:

通过直接指定键值对来选择Pod。只有当Pod的标签与matchLabels中定义的标签完全匹配时,该Pod才会被选中。
示例:

apiVersion: apps/v1
kind: ReplicaSet
metadata:
 name: rs-ml-demo
spec:
 replicas: 3
 selector:
  matchLabels: # 匹配标签
   app: rs-ml-demo #matchLabels与pod标签做子集关系匹配
   domian: Noziroh
 template:
  metadata:
   labels:
    app: rs-ml-demo
    domian: Noziroh
    version: v1
  spec:
   containers:
   - name: rs-ml-demo-container
     image: wangyanglinux/myapp:v1.0
     env:
     - name: GET_HOSTS_FROM
       value: dns
     ports:
     - containerPort: 80

[root@master 5]# kubectl get pod
NAME               READY   STATUS    RESTARTS   AGE
rc-demo-9rw48      1/1     Running   0          23m
rc-demo-hxtj8      1/1     Running   0          23m
rc-demo-nrkvf      1/1     Running   0          22m
rs-ml-demo-fm427   1/1     Running   0          20s
rs-ml-demo-kzjph   1/1     Running   0          20s
rs-ml-demo-v6nbn   1/1     Running   0          20s

2.1.2.2 matchExpressions:

提供了一种更灵活的方式来选择Pod,支持使用更复杂的逻辑条件(如AND、OR、NOT等,尽管直接通过matchExpressions实现复杂的逻辑组合需要多个表达式)。
每个matchExpressions条目可以包含key、operator和values三个字段。
key:要匹配的标签的键。
operator:比较运算符,用于定义如何匹配标签的值。常见的运算符包括In(值在列表中)、NotIn(值不在列表中)、Exists(标签存在)、DoesNotExist(标签不存在)。
values:一个值列表,当operator为In或NotIn时使用。
matchExpressions字段是一个列表,其中每个条目都定义了一个匹配条件。每个条件都由key、operator和values三个字段组成:

key:要匹配的标签的键。

operator:一个字符串,指定了与values数组中的值进行比较的运算符。常见的运算符包括:

  • In:标签的值必须存在于values数组中。
  • NotIn:标签的值不能存在于values数组中。
  • Exists:Pod必须拥有该标签,但不对标签的值进行验证。
  • DoesNotExist:Pod不能拥有该标签。

values:一个字符串数组,当operator为In或NotIn时,用于与Pod标签的值进行比较。对于Exists和DoesNotExist运算符,该字段将被忽略。

下面是一个使用matchExpressions的ReplicaSet示例:


apiVersion: apps/v1  
kind: ReplicaSet  
metadata:  
  name: my-replicaset  
spec:  
  replicas: 3  
  selector:  
    matchExpressions:  
    - key: app  
      operator: In  
      values:  
      - my-app  
    - key: environment  
      operator: NotIn  
      values:  
      - prod  
  template:  
    metadata:  
      labels:  
        app: my-app  
        environment: staging  
    spec:  
      containers:  
      - name: my-container  

        image: my-image:latest

在这个例子中,ReplicaSet my-replicaset 将选择所有标签为app: my-app且标签environment的值不是prod的Pod。这意味着,只有那些同时拥有app: my-app标签且environment标签的值不是prod(例如,environment: staging)的Pod才会被my-replicaset管理。

exist
示例:


apiVersion: apps/v1
kind: ReplicaSet
metadata:
 name: rs-me-exists-demo
spec:
 selector:
  matchExpressions:
   - key: app
     operator: Exists # 只要存在标签名为app即可
 template:
  metadata:
    labels:
     app: spring-k8s
  spec:
   containers:
    - name: rs-me-exists-demo-container
      image: wangyanglinux/myapp:v1.0
      ports:
      - containerPort: 80


[root@master 5]# kubectl create -f 02_rs.yaml 
replicaset.apps/rs-me-exists-demo created

[root@master 5]# kubectl get rs
NAME                DESIRED   CURRENT   READY   AGE
rs-me-exists-demo   1         1         1       10s

[root@master 5]# kubectl label pod rs-me-exists-demo-nhr89 app=Noziroh --overwrite
pod/rs-me-exists-demo-nhr89 labeled
rs-me-exists-demo-nhr89   1/1     Running   0          2m15s   app=Noziroh

in示例

apiVersion: apps/v1
kind: ReplicaSet
metadata:
 name: rs-me-in-demo
spec:
 selector:
  matchExpressions:
   - key: app
     operator: In
     values:
     - spring-k8s
     - hahahah
 template:
  metadata:
   labels:
     app: sg-k8s
  spec:
   containers:
    - name: rs-me-in-demo-container
      image: wangyanglinux/myapp:v1.0
      ports:
      - containerPort: 80


[root@master 5]# kubectl create -f 02_rs_in.yaml 
The ReplicaSet "rs-me-in-demo" is invalid: spec.template.metadata.labels: Invalid value: map[string]string{"app":"sg-k8s"}: `selector` does not match template `labels`
#app: sg-k8s 属于matchExpressions app:[spring-k8s,hahahah] 所以无法创建

#修改yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
 name: rs-me-in-demo
spec:
 selector:
  matchExpressions:
   - key: app
     operator: In
     values:
     - spring-k8s
     - hahahah
     - sg-k8s
 template:
  metadata:
   labels:
     app: sg-k8s
  spec:
   containers:
    - name: rs-me-in-demo-container
      image: wangyanglinux/myapp:v1.0
      ports:
      - containerPort: 80

[root@master 5]# kubectl create -f 02_rs_in.yaml 
replicaset.apps/rs-me-in-demo created

删除rc rs 创建的pod

[root@master 5]# kubectl delete rc --all
replicationcontroller "rc-demo" deleted
[root@master 5]# kubectl delete rs --all
replicaset.apps "rs-me-exists-demo" deleted
replicaset.apps "rs-me-in-demo" deleted
replicaset.apps "rs-ml-demo" deleted

注意:

在实际使用中,matchLabels和matchExpressions可以单独使用,也可以组合使用(但通常不建议这样做,因为这可能会增加配置的复杂性并导致意外的选择结果)。
matchLabels提供了一种简单直观的方式来选择Pod,而matchExpressions则提供了更强大的灵活性和表达能力。
在定义ReplicaSet时,选择器的目的是确保ReplicaSet能够正确地识别和管理它应该负责的Pod。因此,在配置选择器时,需要确保它能够准确地匹配到目标Pod,以避免出现Pod丢失或ReplicaSet无正确管理Pod的情况。

2.2 Deployment

声明式定义

  • 作用:工作在ReplicaSet之上,用于管理无状态应用。它提供了应用的声明能力,允许用户定义应用的期望状态,并自动处理Pod的创建、更新和删除。
  • 功能:支持滚动更新和版本回退,还提供了事件和状态查看、暂停和继续部能。
常用命令
1. 创建Deployment

使用kubectl create命令:可以直接通过命令行创建Deployment,指定容器镜像、副本数量等参数。


kubectl create deployment my-deployment --image=nginx:latest --replicas=3

这个命令会创建一个名为my-deployment的Deployment,使用nginx:latest镜像,并设置副本数量为3。

使用YAML文件:更常见的做法是先编写一个YAML文件定义Deployment,然后使用kubectl apply命令应用这个文件。

kubectl apply -f my-deployment.yaml
2. 查看Deployment

列出所有Deployments:


kubectl get deployments

这个命令会列出当前命名空间下的所有Deployments。

查看特定Deployment的详细信息:

kubectl describe deployment my-deployment

这个命令会显示名为my-deployment的Deployment的详细信息,包括Pod模板、副本数量、事件等。

3. 更新Deployment

更改副本数量:

kubectl scale deployment my-deployment --replicas=5

这个命令会将my-deployment的副本数量更改为5。

更新容器镜像:

kubectl set image deployment my-deployment my-container=nginx:1.19.2

这个命令会将my-deployment中名为my-container的容器的镜像更新为nginx:1.19.2。

4. 滚动更新和回滚

滚动更新:默认情况下,通过更改Deployment的Pod模板(如镜像版本)并重新应用,Kubernetes会执行滚动更新。

回滚到上一个版本:

kubectl rollout undo deployment my-deployment

这个命令会将my-deployment回滚到上一个版本。

查看更新历史:

kubectl rollout history deployment my-deployment

这个命令会显示my-deployment的更新历史。

回滚到指定版本:

kubectl rollout undo deployment my-deployment --to-revision=N

其中N是想要回滚到的版本号(从kubectl rollout history命令中获取)。

暂停和恢复滚动更新

# 暂停滚动更新  
kubectl rollout pause deployment/<deployment-name>  
  
# 恢复滚动更新  
kubectl rollout resume deployment/<deployment-name>
更新策略

在Kubernetes(k8s)中,Deployment的更新策略是管理Pod版本升级和回滚的重要机制。主要的更新策略包括滚动更新(RollingUpdate)和重建(Recreate),每种策略都有其适用场景和配置方式。

1. 滚动更新(RollingUpdate)

滚动更新是Kubernetes Deployment的默认更新策略。在滚动更新过程中,Deployment控制器会逐步地将新版本的Pod逐个替换旧版本的Pod,从而确保在升级过程中始终有一定数量的可用Pod服务于客户端请求,实现平滑的服务过渡。

关键参数:

  • maxSurge:表示在滚动更新过程中,可以超出期望副本数的最大Pod数或百分比。这有助于在更新过程中保持冗余度,以应对可能的故障。
  • maxUnavailable:表示在滚动更新过程中,允许的最大不可用Pod数或百分比。这有助于控制更新过程中服务的可用性。

配置示例:


apiVersion: apps/v1  
kind: Deployment  
metadata:  
  name: myapp-deploy  
spec:  
  replicas: 3  
  strategy:  
    type: RollingUpdate  
    rollingUpdate:  
      maxSurge: 25%  # 或者设置为一个整数,如 maxSurge: 1  
      maxUnavailable: 25%  # 或者设置为一个整数,如 maxUnavailable: 1  
  selector:  
    matchLabels:  
      app: myapp  
  template:  
    metadata:  
      labels:  
        app: myapp  
    spec:  
      containers:  
      - name: myapp  

        image: myapp:v2

适用场景:

滚动更新特别适用于需要确保服务持续可用的场景,如生产环境中的应用程序升级。

2. 重建(Recreate)

重建策略会在创建新Pod之前删除所有现有的Pod。这种策略会导致应用程序的短暂中断,因为在删除旧Pod和创建新Pod之间存在时间差。

配置示例:


apiVersion: apps/v1  
kind: Deployment  
metadata:  
  name: myapp-deploy  
spec:  
  replicas: 3  
  strategy:  
    type: Recreate  
  selector:  
    matchLabels:  
      app: myapp  
  template:  
    metadata:  
      labels:  
        app: myapp  
    spec:  
      containers:  
      - name: myapp  

        image: myapp:v2

适用场景:

重建策略适用于无状态应用程序或可以容忍短暂中断的应用程序,如开发环境或测试环境中的应用程序升级。
总结

在选择Deployment的更新策略时,需要根据应用程序的特性和业务需求进行权衡。滚动更新提供了更好的服务可用性和平滑的升级体验,但可能会增加系统的复杂性和资源消耗。重建策略则更简单直接,但可能会导致服务中断。在实际应用中,可以根据具体情况选择合适的更新策略,并通过调整maxSurge和maxUnavailable等参数来优化升级过程。

金丝雀部署
  • 定义:金丝雀发布是在新旧版本之间平滑过渡的一种发布方式,通过让一部分用户先使用新版本,另一部分用户继续使用旧版本,从而逐步验证新版本的稳定性和性能。
  • 目的:降低新软件版本部署的风险,确保新版本在生产环境中能够稳定运行,同时避免对整个系统造成过大影响。
vi deployment-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
 labels:
  app: deployment-demo
 name: deployment-demo
spec:
 replicas: 10
 selector:
  matchLabels:
   app: deployment-demo
 template:
  metadata:
   labels:
    app: deployment-demo
  spec:
   containers:
   - image: wangyanglinux/myapp:v1.0
     name: deployment-demo-container
[root@master 6]# kubectl apply -f deployment-demo.yaml 
deployment.apps/deployment-demo created
[root@master 6]# kubectl create svc clusterip deployment-demo --tcp=80:80
service/deployment-demo created
[root@master 6]# kubectl get deploy deployment-demo -o yaml
spec:
  progressDeadlineSeconds: 600
  replicas: 10
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: deployment-demo
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate

# 修改滚动更新pod滚动时的数量
# json模式更新 允许pod超过最大值1个,允许不可用pod为0
# '{"spec":{"strategy":{"rollingUpdate":{"maxSurge":1,"maxUnavailable":2}}}}'
[root@master 6]# kubectl patch deploy deployment-demo -p '{"spec":{"strategy":{"rollingUpdate":{"maxSurge":1,"maxUnavailable":2}}}}'
deployment.apps/deployment-demo patched

# 进行滚动更新
# '{"spec":{"template":{"spec":{"containers":[{"image":"wangyanglinux/myapp:v2.0","name":"deployment-demo-container"}]}}}}'

[root@master 6]# kubectl patch deploy deployment-demo --patch '{"spec":{"template":{"spec":{"containers":[{"image":"wangyanglinux/myapp:v2.0","name":"deployment-demo-container"}]}}}}' && kubectl rollout pause deploy deployment-demo
deployment.apps/deployment-demo patched
deployment.apps/deployment-demo paused
[root@master 6]# kubectl get pod | grep deployment |wc -l
11
[root@master 6]# kubectl describe pod deployment-demo-7dd46c6f55-l5mdl
Image:          wangyanglinux/myapp:v2.0
[root@master 6]# kubectl rollout resume deploy deployment-demo
deployment.apps/deployment-demo resumed
# 回滚
[root@master 6]# kubectl rollout undo deployment/deployment-demo
deployment.apps/deployment-demo rolled back


[root@master 6]# kubectl get rs
NAME                         DESIRED   CURRENT   READY   AGE
deployment-demo-6465d4c5c9   0         0         0       2m34s
deployment-demo-6995c75668   10        10        10      8m3s

2.2.1. 应用(Apply)

kubectl apply 命令用于根据提供的配置文件(通常是YAML或JSON格式)来创建或更新资源。如果资源不存在,apply 会创建它;如果已存在,apply 会更新资源以匹配配置文件中的定义。


kubectl apply -f deployment.yaml

这个命令会根据deployment.yaml文件中的定义来创建或更新一个Deployment。

2.1.2. 替换(Replace)

在Kubernetes中,并没有直接的replace命令来替换整个Deployment。但是,你可以使用kubectl replace命令来替换资源的定义,但这通常用于特定的场景,比如你需要替换整个资源对象而不是简单地更新它。


kubectl replace -f deployment.yaml --force

注意:–force选项在较新版本的kubectl中可能不是必需的,具体取决于你的Kubernetes集群版本和kubectl版本。使用replace时要小心,因为它会替换整个资源对象,而不仅仅是更新它。

对比
kubectl apply kubectl replace
功能 创建或更新资源,使其与配置文件匹配 替换资源的当前配置,使其与配置文件完全匹配
特点 增量更新,幂等性,易于使用 全面替换,可能导致资源状态丢失,需要谨慎使用
适用场景 大多数资源更新场景 需要替换整个资源对象或资源状态复杂难以通过apply更新的场景

测试

apiVersion: apps/v1
kind: Deployment # 类别为Deployment
metadata:
 labels:
  app: myapp-deploy # Deployment 标签
 name: myapp-deploy # Deployment 名字
spec:
 replicas: 1
 selector:
  matchLabels:
   app: myapp-deploy # 容器标签app=myapp-deploy
 template:
  metadata:
   labels:
    app: myapp-deploy # 容器名字
  spec:
   containers:
   - image: wangyanglinux/myapp:v1.0
     name: myapp
[root@master 5]# kubectl get pod
NAME                            READY   STATUS    RESTARTS   AGE
myapp-deploy-7977896984-gsd6m   1/1     Running   0          36s
[root@master 5]# kubectl get deploy -o wide
NAME           READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES                     SELECTOR
myapp-deploy   1/1     1            1           59s   myapp        wangyanglinux/myapp:v1.0   app=myapp-deploy

[root@master 5]# kubectl get deploy -o yaml
availableReplicas: 1
[root@master 5]# kubectl scale deploy myapp-deploy --replicas=10
deployment.apps/myapp-deploy scaled
[root@master 5]# kubectl get deploy -o wide
NAME           READY   UP-TO-DATE   AVAILABLE   AGE     CONTAINERS   IMAGES                     SELECTOR
myapp-deploy   10/10   10           10          3m26s   myapp        wangyanglinux/myapp:v1.0   app=myapp-deploy
[root@master 5]# kubectl get deploy -o yaml
availableReplicas: 10


[root@master 5]# kubectl get pod -o wide
NAME                            READY   STATUS    RESTARTS   AGE     IP               NODE    NOMINATED NODE   READINESS GATES
myapp-deploy-7977896984-6gwzj   1/1     Running   0          101s    10.244.166.167   node1   <none>           <none>
myapp-deploy-7977896984-9mmn4   1/1     Running   0          101s    10.244.104.35    node2   <none>           <none>
myapp-deploy-7977896984-b47vm   1/1     Running   0          101s    10.244.166.170   node1   <none>           <none>
myapp-deploy-7977896984-b6t5j   1/1     Running   0          101s    10.244.166.168   node1   <none>           <none>
myapp-deploy-7977896984-gsd6m   1/1     Running   0          4m42s   10.244.104.34    node2   <none>           <none>
myapp-deploy-7977896984-jbg62   1/1     Running   0          101s    10.244.166.171   node1   <none>           <none>
myapp-deploy-7977896984-m2kh6   1/1     Running   0          101s    10.244.104.36    node2   <none>           <none>
myapp-deploy-7977896984-r8shx   1/1     Running   0          101s    10.244.104.38    node2   <none>           <none>
myapp-deploy-7977896984-rp6rz   1/1     Running   0          101s    10.244.104.37    node2   <none>           <none>
myapp-deploy-7977896984-th76j   1/1     Running   0          101s    10.244.166.169   node1   <none>           <none>

[root@master 5]# curl 10.244.166.167
www.xinxianghf.com | hello MyAPP | version v1.0

[root@master 5]# vim 01_deploy.yaml
- image: wangyanglinux/myapp:v2.0

[root@master 5]# kubectl apply -f 01_deploy.yaml 
deployment.apps/myapp-deploy configured

[root@master 5]# kubectl get deploy -o wide
NAME           READY   UP-TO-DATE   AVAILABLE   AGE     CONTAINERS   IMAGES                     SELECTOR
myapp-deploy   1/1     1            1           6m38s   myapp        wangyanglinux/myapp:v2.0   app=myapp-deploy

[root@master 5]# kubectl get pod -o wide
NAME                           READY   STATUS    RESTARTS   AGE   IP              NODE    NOMINATED NODE   READINESS GATES
myapp-deploy-58b4dc6f5-dggz9   1/1     Running   0          95s   10.244.104.39   node2   <none>           <none>

[root@master 5]# curl 10.244.104.39
www.xinxianghf.com | hello MyAPP | version v2.0

[root@master 5]# vim 01_deploy.yaml
replicas: 10
- image: wangyanglinux/myapp:v3.0

[root@master 5]# kubectl replace -f 01_deploy.yaml 
deployment.apps/myapp-deploy replaced

[root@master 5]# kubectl get deploy -o wide 
NAME           READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES                     SELECTOR
myapp-deploy   10/10   10           10          17m   myapp        wangyanglinux/myapp:v3.0   app=myapp-deploy

[root@master 5]# kubectl get pod -o wide 
NAME                            READY   STATUS    RESTARTS   AGE   IP               NODE    NOMINATED NODE   READINESS GATES
myapp-deploy-6fd574ffd6-287zl   1/1     Running   0          97s   10.244.104.44    node2   <none>           <none>
myapp-deploy-6fd574ffd6-2rqpt   1/1     Running   0          60s   10.244.166.180   node1   <none>           <none>
myapp-deploy-6fd574ffd6-987n5   1/1     Running   0          97s   10.244.104.41    node2   <none>           <none>
myapp-deploy-6fd574ffd6-cmw6z   1/1     Running   0          61s   10.244.104.47    node2   <none>           <none>
myapp-deploy-6fd574ffd6-g2pkf   1/1     Running   0          97s   10.244.104.42    node2   <none>           <none>
myapp-deploy-6fd574ffd6-g9prr   1/1     Running   0          79s   10.244.166.178   node1   <none>           <none>
myapp-deploy-6fd574ffd6-jqjbz   1/1     Running   0          72s   10.244.166.179   node1   <none>           <none>
myapp-deploy-6fd574ffd6-vnzg4   1/1     Running   0          97s   10.244.166.174   node1   <none>           <none>
myapp-deploy-6fd574ffd6-zlfnz   1/1     Running   0          97s   10.244.166.175   node1   <none>           <none>
myapp-deploy-6fd574ffd6-zscjl   1/1     Running   0          63s   10.244.104.46    node2   <none>           <none>

[root@master 5]# kubectl diff -f 01_deploy.yaml 
diff -u -N /tmp/LIVE-1713354067/apps.v1.Deployment.default.myapp-deploy /tmp/MERGED-2968072580/apps.v1.Deployment.default.myapp-deploy
--- /tmp/LIVE-1713354067/apps.v1.Deployment.default.myapp-deploy	2024-08-22 23:48:21.313569984 +0800
+++ /tmp/MERGED-2968072580/apps.v1.Deployment.default.myapp-deploy	2024-08-22 23:48:21.314569996 +0800
@@ -4,7 +4,7 @@
   annotations:
     deployment.kubernetes.io/revision: "3"
   creationTimestamp: "2024-08-22T15:29:32Z"
-  generation: 4
+  generation: 5
   labels:
     app: myapp-deploy
   name: myapp-deploy
@@ -13,7 +13,7 @@
   uid: 383e54ba-ce53-4320-85d9-d72fd6abb35b
 spec:
   progressDeadlineSeconds: 600
-  replicas: 10
+  replicas: 1
   revisionHistoryLimit: 10
   selector:
     matchLabels:
@@ -30,7 +30,7 @@
         app: myapp-deploy
     spec:
       containers:
-      - image: wangyanglinux/myapp:v3.0
+      - image: wangyanglinux/myapp:v2.0
         imagePullPolicy: IfNotPresent
         name: myapp
         resources: {}


# deployment与rs关联升级 滚动更新
[root@master 5]# kubectl get rs -o wide
NAME                      DESIRED   CURRENT   READY   AGE   CONTAINERS   IMAGES                     SELECTOR
myapp-deploy-58b4dc6f5    0         0         0       20m   myapp        wangyanglinux/myapp:v2.0   app=myapp-deploy,pod-template-hash=58b4dc6f5
myapp-deploy-6fd574ffd6   10        10        10      10m   myapp        wangyanglinux/myapp:v3.0   app=myapp-deploy,pod-template-hash=6fd574ffd6
myapp-deploy-7977896984   0         0         0       26m   myapp        wangyanglinux/myapp:v1.0   app=myapp-deploy,pod-template-hash=7977896984

2.1.3. 删除(Delete)

kubectl delete 命令用于删除一个或多个资源。要删除一个Deployment,你可以使用以下命令:


kubectl delete deployment <deployment-name>

将替换为你的Deployment的名称。

2.1.4. 注意事项

在使用apply或replace时,请确保你的配置文件是最新的,以避免不必要的配置错误或资源状态不一致。
在删除Deployment之前,请确保你了解这将会删除该Deployment管理的所有Pods,并且你有适当的备份或恢划。
kubectl apply是更新资源的推荐方式,因为它可以处理资源配置的增量更新,而replace则更适合于替换整个对象。
对于复杂的应用场景,可能需要结合使用kubectl的多个命令,以及编写适当的Kubernetes配置文件,来精确你的应用部署和更新过程。

2.3 StatefulSet

  • 作用:用于管理有状态的应用。它为Pod提供了稳定的网络标识、顺序部署、及扩展和滚动更新的能力。
  • 特点:Pod的名称是有序的,且每个Pod都有独立的存储卷。它通常与HeadleService(无头服务)和PVC(持久化卷声明)一起使用,以实现稳定的持久和网络标识。

主要特点

    1. 稳定的唯一网络标识符:
    • 每个StatefulSet的Pod都有一个稳定的网络标识符(如DNS名称),这个标识符由控制器自动生成,并与Pod的生命周期保持关联。这使得有状态应用更容易被其他应用或服务访问和发现。
    1. 有序部署和扩展:
    • StatefulSet能够按照定义的顺序逐个创建和更新Pod实例,确保它们按照固定的命名规则有序启动。在扩展时,新的Pod也会按照相同的顺序创建,从而保证有状态应用的数据一致性和可用性。
    1. 稳定的存储:
    • 每个StatefulSet的Pod都可以使用持久卷(PersistentVolume)来存储数据,这些存储卷在Pod重新启动或迁移时保持不变,从而确保数据的持久性和可靠性。
    1. 域名解析:
    • 每个StatefulSet的Pod都有一个稳定的域名,格式通常为...svc.cluster.local。这使得有状态应用可以通过域名进行服务发现和通信。
    1. 有序删除:
      在删除StatefulSet时,控制器会按照指定的顺序逐个删除Pod,确保有状态应用在删除过程中不会丢失数据。

应用场景

StatefulSet适用于需要持久化存储和唯一标识的有状态应用场景,包括但不限于:

  • 数据库(如MySQL、PostgreSQL、MongoDB)
  • 消息队列(如RabbitMQ、Kafka)
  • 分布式存储(如Elasticsearch、Cassandra)

在这些场景中,StatefulSet提供的稳定网络标识、有序部署和扩展、持久化存储等特性对于保证应用的数据一致性和高可用性至关重要。
组成部分

StatefulSet主要由以下几个部分组成:

  • Headless Service:用于定义Pod的网络标识(DNS域名),没有Cluster IP,解析其名称时将返回该Headless Service对应的全部Pod的Endpoint列表。
  • volumeClaimTemplates:存储卷申请模板,用于为StatefulSet中的每个Pod生成独立的持久卷声明(PersistentVolumeClaim),从而实现数据的持久化存储。
  • StatefulSet定义:定义具体应用,包括Pod副本数、Pod模板(容器配置、存储卷挂载等)、关联的Headless Service等。

示例

以下是一个简单的StatefulSet示例,用于部署一个具有3个副本的MySQL数据库服务:

apiVersion: apps/v1  
kind: StatefulSet  
metadata:  
  name: mysql-statefulset  
spec:  
  serviceName: mysql  
  replicas: 3  
  selector:  
    matchLabels:  
      app: mysql  
  template:  
    metadata:  
      labels:  
        app: mysql  
    spec:  
      containers: 
      - name: mysql-container  
        image: mysql:latest  
        ports:  
        - containerPort: 3306  
        env:  
        - name: MYSQL_ROOT_PASSWORD  
          value: "password"  
        volumeMounts:  
        - name: mysql-storage  
          mountPath: /var/lib/mysql  
  volumeClaimTemplates:  
  - metadata:  
      name: mysql-storage  
    spec:  
      accessModes: ["ReadWriteOnce"]  
      storageClassName: "standard"  
      resources:  
        requests:  
          storage: 1Gi

在这个示例中,StatefulSet mysql-statefulset 定义了3个MySQL Pod副本,每个Pod都挂载了一个名为mysql-storage的持久卷,用于存储数据库数据。这个持久卷通过volumeClaimTemplates自动生成,并请求了1GiB的存储空间。同时,StatefulSet还关联了一个名为mysql的Headless Service,用于提供Pod的网络标识和域名解析。

2.4 DaemonSet

作用:确保在集群中的每个Node上都运行一个Pod的副本。它通常用于运行集群存储、日志收集等守护进程类任务。
特点:无论Node何时加入集群,DaemonSet都会确保在该Node上运行一个Pod副本(除非Node被标记为不可调度)。

一、概述

DaemonSet 控制器能够确保 Kubernetes 集群中的每个节点(或选定的节点)都运行一个 Pod 的副本。当集群中增加新的节点时,DaemonSet 会自动在该节点上创建一个 Pod 副本;当节点从集群中移除时,DaemonSet 也会自动删除该节点上的 Pod。

二、工作原理
  • 定义对象:用户定义一个 DaemonSet 对象,指定 Pod 模板和其他配置选项。Pod 模板定义了 Pod 的规格,包括容器、存储和网络配置。
  • 调度 Pod:当 DaemonSet 控制器接收到创建请求时,它会在每个匹配的节点上创建一个 Pod 实例。
  • 监控 Pod:DaemonSet 控制器监视 Pod 的状态,并确保每个节点上都有 Pod 实例。如果节点失败或重启,DaemonSet 控制器会自动在该节点上重新创建 Pod 实例。
  • 更新 Pod:如果用户更新了 Pod 模板,DaemonSet 控制器将负责在所有节点上滚动更新 Pod 实例,以应用新的配置。
  • 节点选择:DaemonSet 允许用户通过节点标签选择器来指定应在哪些节点上运行 Pod。如果没有指定选择器,Pod 将在所有节点上运行。
三、相关特性
  • 节点覆盖:DaemonSet 确保在集群中的所有节点或选定节点上运行一个 Pod 实例,或者在满足特定条件的节点上运行。
  • 自动恢复:如果节点失败或重启,DaemonSet 会自动在该节点上重新创建 Pod,确保服务的连续性。
  • 滚动更新:当 Pod 模板更新时,DaemonSet 支持滚动更新,逐步替换旧的 Pod 实例。但通常建议避免在 DaemonSet 中使用 RollingUpdate 更新策略,因为这可能不适用于需要高度稳定性的守护进程应用程序。
  • 灵活性:用户可以指定节点标签选择器来控制 Pod 在哪些节点上运行,提供灵活性。
  • 资源和调度:DaemonSet 支持资源请求和限制,允许用户为 Pod 指定所需的 CPU 和内存资源。
  • 集成:DaemonSet 与 Kubernetes 的其他资源和功能(如服务发现、存储卷和网络策略)紧密集成。
四、应用场景
  • 日志收集:在每个节点上运行日志收集器,如 Fluentd、Logstash 或 Filebeat,以收集并转发节点上的日志数据。
  • 监控代理:在每个节点上运行监控代理,如 Prometheus Node Exporter、collectd 等,以收集节点的性能指标并发送到监控中心。
  • 存储守护进程:在每个节点上运行存储守护进程,如 Glusterd 或 Ceph,以提供分布式存储服务。
五、示例

以下是一个简单的 DaemonSet YAML 配置文件示例,用于在 Kubernetes 集群的每个节点上部署一个 Nginx Pod:

apiVersion: apps/v1  
kind: DaemonSet  
metadata:  
  name: nginx-daemonset  
  namespace: default  
spec:  
  selector:  
    matchLabels:  
      app: nginx-daemonset  
  template:  
    metadata:  
      labels:  
        app: nginx-daemonset  
    spec:  
      containers:  
      - name: nginx  
        image: nginx:latest  
        ports:  
        - containerPort: 80

在创建了这个 DaemonSet 后,Kubernetes 将在每个节点上部署一个 Nginx Pod 副本。如果集群中有新的节点加入,DaemonSet 将自动在该节点上创建一个新的 Nginx Pod 副本。

2.5 Job

作用:用于运行批处理任务,即执行一次性任务。当Pod完成其工作后,Job控制器会负责清理这些Pod。

K8s Job是Kubernetes中的一个核心概念,用于执行一次性任务或批处理作业。以下是关于K8s Job的详细解释:

一、基本概念
  • 定义:Job是Kubernetes中的一种资源对象,专门用于处理那些需要运行至完成且不需要持续运行的任务。
  • 用途:Job主要用于执行数据处理、备份恢复、日志打包压缩等一次性或批处理任务。
二、主要特性
  • 任务执行:Job会创建一个或多个Pod来执行定义的任务,并确保这些Pod成功完成任务。
  • 自动清理:当所有Pod都成功完成任务后,Job会停止这些Pod(默认情况下,已完成的Pod会被自动清理)。
  • 失败重试:如果Pod执行失败,Job会根据定义的策略进行重试,直到任务成功或达到最大重试次数。
  • 并行与串行:Job支持并行执行任务,也支持串行执行任务,具体取决于配置。
三、关键字段
  • apiVersion:指定Job资源对象的API版本,通常为batch/v1。
  • kind:指定资源对象的类型为Job。
  • metadata:包含Job的元数据,如名称(name)、命名空间(namespace)等。
  • spec:定义Job的规格,包括任务模板(template)、完成次数(completions)、并行度(parallelism)、重启策略(restartPolicy)等。
    • template:定义了Pod的模板,包括使用的镜像、命令、参数等。
    • completions:指定需要成功完成的任务数量。
    • parallelism:指定同时运行的Pod数量。
    • backoffLimit:指定任务失败后的重试次数。
四、使用场景
  • 数据处理:如从数据库中导出数据到CSV文件。
  • 日志打包压缩:如按时间段打包日志文件。
  • 备份恢复:如备份数据库到云存储服务。
  • 批处理任务:如根据输入参数计算机器学习模型的特征向量。
五、操作示例

以下是一个简单的Job配置文件示例:


apiVersion: batch/v1  
kind: Job  
metadata:  
  name: ubuntu-job  
spec:  
  template:  
    spec:  
      containers:  
      - name: ubuntu-container  
        image: ubuntu  
        command: ["echo", "Hello, Kubernetes!"]  
      restartPolicy: Never
[root@master ~]# kubectl logs  ubuntu-job-wlg8x
Hello, Kubernetes!

该配置文件定义了一个名为example-job的Job,它将启动一个Pod,该Pod包含一个运行echo "Hello, Kubernetes!"命令的容器。由于restartPolicy设置为Never,所以Pod在成功完成任务后不会重启。

六、注意事项
  • Job适用于一次性任务或批处理作业,不适用于长时间运行的服务。
  • 需要确保Job配置文件中定义的容器可以正常运行,并有足够的资源和权限执行指定操作。

2.6 CronJob

作用:用于周期性地创建Job对象,执行定时任务。它类似于Unix中的crontab,用于安排周期性作业。

在Kubernetes(K8s)中,CronJob是一种非常有用的资源对象,它基于Cron表达式,允许用户在指定的时间间隔内自动运行容器化的任务。以下是关于K8s CronJob的详细解释:

一、基本概念
  • 定义:CronJob是Kubernetes中用于周期性执行任务的资源对象,它相当于在Job之上增加了基于时间的调度配置。
  • 用途:CronJob通常用于部署定时备份、定时检查、定时同步、定时报告等周期性任务。
二、关键属性
  • schedule:指定任务执行的时间表,使用标准的Cron表达式语法。例如,“0 * * * *”表示每小时执行一次任务。
  • jobTemplate:定义要执行的任务的模板,通常是一个Pod模板。这个模板包含了任务所需的容器镜像、命令、环境变量等配置。
  • concurrencyPolicy:指定任务并发策略,默认为Allow。Allow表示允许并发执行任务,Forbid表示禁止并发执行任务(新任务将会被跳过),Replace表示如果任务正在执行,则会终止当前任务并启动新任务。
  • successfulJobsHistoryLimit和failedJobsHistoryLimit:分别指定保留成功和失败任务历史记录的数量。默认情况下,成功任务的历史记录保留数量为3,失败任务的历史记录保留数量为1。
三、工作原理
  • 定义对象:用户创建一个CronJob对象,指定Pod模板和其他配置选项。
  • 监控Job:Kubernetes的调度器会监控CronJob对象的状态。
  • 生成Job:根据CronJob定义的时间表,调度器在预定的时间创建Job对象。
  • 执行任务:Kubernetes根据Job模板创建Pod,并开始执行任务。
  • 监控Pod:Kubernetes监控Pod的状态,确保任务成功完成。
  • 记录历史:由CronJob创建的Job都会被记录,包括成功和失败的Job。
  • 清理资源:完成的Job及对应的Pod会根据CronJob的配置进行清理。
四、Cron表达式

Cron表达式由五个或六个字段组成,分别代表分钟、小时、日、月、星期几(以及可选的年份)。每个字段的取值范围不同,可以使用通配符、逗号、连字符等方式进行配置。以下是一些常见的Cron表达式示例:

  • 每分钟执行一次任务:* * * * *
  • 每小时执行一次任务:0 * * * *
  • 每天凌晨1点执行任务:0 1 * * *
  • 每周一凌晨1点执行任务:0 1 * * 1
  • 每月1号凌晨1点执行任务:0 1 1 * *
五、使用场景
  • 定时备份:定期备份数据库或文件系统。
  • 日志清理:定时清理过期的日志或缓存数据。
  • 数据同步:定时拉取或更新数据,如镜像、代码库等。
  • 发送通知:定时发送通知或警报。
六、操作示例

以下是一个简单的CronJob配置文件示例:


apiVersion: batch/v1  
kind: CronJob  
metadata:  
  name: hello-cronjob  
spec:  
  schedule: "*/1 * * * *"  # 每一分钟执行一次任务  
  jobTemplate:  
    spec:  
      template:  
        spec:  
          containers:  
          - name: hello  
            image: ubuntu  
            command: ["/bin/sh", "-c", "date; echo Hello from the Kubernetes cluster"]  
          restartPolicy: OnFailure

该配置文件定义了一个名为hello-cronjob的CronJob,它将每分钟执行一次任务,任务内容为打印当前日期和时间,并输出“Hello from the Kubernetes cluster”。

七、注意事项
  • CronJob的时间精度为分钟级别,不支持秒级别的定时任务。
  • 在设计CronJob时,应充分考虑任务执行的时间、频率和并发策略,以避免资源冲突或过度消耗。
  • 对于重要的定时任务,建议设置失败重试和历史记录保留策略,以便在任务失败时能够及时发现并处理。

三、Pod与控制器之间的关系

控制器是Kubernetes中用于管理一组Pod的高级对象,而Pod是Kubernetes中运行容器的最小单元。
控制器通过定义一组标签选择器来跟踪和控制具有这些标签的Pod。当Pod因故障而终止时,控制器会根据定义的规则自动创建新的Pod来替换它,从而确保应用的持续运行和所需的副本数量。

四、Pod控制器的实现机制

Pod控制器是由Master节点的kube-controller-manager组件提供的。它通过内部和解(reconciliation loop)机制不断地监控Kubernetes集群内资源对象的状态,以保证集群中的资源对象的状限接近于用户所期望的状态。
当资源对象状态发生变动时,API Server将状态写入etcd中,并通过水平触发机制将事件主动通知给相关的客户端程序(包括kube-controller-manager)。然后,控制器通过API Server的watch实时监控目标资源对象的变动,并在必要时执行和解操作。

综上所述,Pod控制器是Kubernetes中用于管理Pod资源的重要机制,它通过确保Pod副本数量、自动恢复、扩缩容、更新和回滚等功能,为应用的持续运行和运维自动化提供了有力支持。

你可能感兴趣的:(kubernetes,容器,云原生)