Linux
Kubernetes控制器
  • By刘立博
  • 2023-01-29 13:09:07
  • 509人已阅读

ReplicaSet工作原理

ReplicaSet是通过一组字段来定义的,包括一个用来识别可获得Pod集合的选择运算符,一个用来表明副本数量的数字,一个用来指定Pod模版的字段等等,每个ReplicaSet使得副本个数达到期望值,进而实现存在价值,当ReplicaSet需要创建新Pod时,会使用所提供的Pod模版

 

一个栗子:使用ReplicaSet保证nginx Pod个数为3

(1)创建ReplicaSet

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          ports:
            - containerPort: 80

(2)启动ReplicaSet

kubectl apply -f replicaSet
kubectl get po

(3)测试

kubectl delete po nginx-t6mgs
kubectl get po

Deployments控制器

Deployment控制器为Pods和ReplicaSet提供声明和更新能力

 

一个栗子:创建一个包含Pod和ReplicaSet的Deployment控制器

(1)创建Deployment控制器

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        resources:
          limits:
            memory: "128Mi"
            cpu: "500m"
        ports:
        - containerPort: 80

(2)启动并查看Deployment控制器

kubectl apply -f deployment
kubectl get po

有状态应用StatefulSets

StatefulSets用来管理有状态应用对象,并且能为这些Pod提供唯一性序号。与Deployment相同的是,Stateful管理了基于相同容器定义的一组Pod,不同之处是StatefulSet为每个Pod维护了一个固定ID,这些Pod是基于相同声明来创建的,但是不能相互替换:无论怎么调度,每个Pod都有一个永远不变的ID

 

StatefulSets的场景

(1)稳定的、唯一的网络标识

(2)稳定的、持久存储

(3)有序的、优雅的部署和缩放

(4)有序的、自动的滚动更新

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

 

StatefulSets的限制

(1)给定Pod存储必须有PersistentVolume驱动基于所请求的Storage Class来提供,或者由管理员实现提供

(2)删除或者收缩StatefulSets并不会删除他关联的存储卷,这样做事为了保证数据安全,他通常比自动清除StatefulSets所有相关资源更有价值

(3)StatefulSets当前需要Headless服务负责Pod网络标识,需要创建此服务

(4)删除StatefulSets时,不提供任何终止Pod的保证,可以将其收缩至0后,再删除

 

一个栗子:创建一个挂载存储的Nginx有状态应用

 

(1)创建有状态应用配置

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  selector:
    matchLabels:
      app: nginx # has to match .spec.template.metadata.labels
  serviceName: "nginx"
  replicas: 3 # by default is 1
  template:
    metadata:
      labels:
        app: nginx # has to match .spec.selector.matchLabels
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "my-storage-class"
      resources:
        requests:
          storage: 1Gi
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: my-storage-class
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
# Supported policies: Delete, Retain
reclaimPolicy: Delete

(2)启动有状态应用

kubectl apply -f stateful

DaemonSet后台任务

DaemonSet可以确保节点上运行一个Pod脚本吗,当有节点加入集群时,也会为他们新增一个Pod,当有节点从集群中移除时,Pod也会被回收,删除DaemonSet将会删除创建的所有Pod

 

DaemonSet的典型用法

(1)集群的每个节点运行存储Daemon

(2)在每个节点上运行日志收集

(3)在每个节点上运行监控

 

DaemonSet调度

 

DaemonSet确保所有符合条件的节点运行一个Pod副本,通常运行Pod的节点由Kubernetes调度器选择,不过DaemonSet由DaemonSet控制器创建和调度,这就带来了以下问题:

 

Pod行为不一致:正常Pod在被创建后等待调度处于Pending状态,DaemonSet创建后不会处于Pending状态

Pod抢占:启用抢占后,DaemonSet控制器不考虑Pod优先级和抢占情况指定调度策略

 

与Daemon Pod通信

与DaemonSet中的Pod可以使用以下几种方式通信:

 

(1)NodeIP

DaemonSet中的Pod可以使用hostPort,从而可以通过节点IP访问到Pod,客户端能通过某种方法获取节点IP列表,并且给予此也可以获取到相应的端口

 

(2)DNS

创建具有相同Pod选择器的HeaderLess服务,通过使用endPoints资源或从DNS检索到多个A记录来发现DaemonSet

 

(3)Service

创建具有相同Pod选择器的服务,并使用该服务随机访问到某个节点上的守护进程

 

更新DaemonSet

如果节点的标签被修改,DaemonSet将立刻向匹配的节点添加Pod,同时删除不匹配的Pod

可以修改DaemonSet创建的Pod,不过并非所有字段都可以实时更新,当某节点下次被创建时,还是会使用最初的模版

可以删除DaemonSet,如果指定了 --cascade=false选项,Pod将保留在节点上,如果创建了相同名称的DaemonSet,此时Pod会根据updateStrategy执行替换操作

 

DaemonSet替代方案

 

init脚本

直接在节点启动守护进程的做法当然是可行的,不过基于DaemonSet运行这些进程有如下好处:

(1)像所运行的其他应用一样,DaemonSet具备为守护进程提供监控和日志管理的能力

(2)为守护进程和应用所使用的配置语言和工具是相同的

(3)在资源受限的容器中运行守护进行能够增加守护进程和应用容器的隔离性,然后,这一点可以通过在容器中运行守护进程但不在Pod中运行来实现

 

Deployment

DaemonSet与Deployment非常类似,他们都能创建Pod,并且Pod中的进程都不希望被终止,建议为无状态服务使用Deployment,当需要Pod副本总是运行在全部或特定主机上或者需要优先Pod启动时,应该使用DaemonSet

 

一个栗子:创建daemon

 

(1)编写daemon配置

apiVersion: apps/v1 
kind: DaemonSet 
metadata: 
  name: my-daemonset
spec: 
  selector: 
    matchLabels: 
      app: my-daemon
  template: 
    metadata: 
      labels: 
        app: my-daemon
    spec: 
      containers: 
        - name: daemonset-container 
          image: httpd 
          ports: 
          - containerPort : 80

(2)启动

kubectl apply -f daemon
kubectl get all

Job任务

Job会创建一个或者多个Pod,并确保指定数量的Pods成功终止,当数量达到指定的成功个数时,热舞结束,删除Job操作会清除创建的全部Pods

 

一个栗子:执行Job

(1)编写Job

apiVersion: batch/v1
kind: Job
metadata:
  name: pi
spec:
  template:
    spec:
      containers:
      - name: pi
        image: perl
        command: ["perl","-Mbignum=bpi","-wle","print bpi(1000)"]
      restartPolicy: Never
  backoffLimit: 4

(2)启动

kubectl apply -f job
kubectl get all