背景

客户有一个java应用比较耗内存,在kubernetes上对cpu和内存进行了限制,但效果不大好,应用经常被kill掉,由于该应用属于核心应用,后面就解除限制,在jvm上对堆内存进行了限制,因为没有配置kubernetes资源请求限制,kubernetes在调度上就无法灵活调度,经常将多个副本调度到同一节点,多个大内存应用运行在同一个节点,内存很容易就被耗尽导致jvm gc频繁,频繁的gc又导致了服务器cpu负载过大,最终应用挂掉无法访问。如果kubernetes能将应用多个副本调度到不同节点那么至少能保证一个节点挂掉,其他节点应用还可以继续服务。

方案

  • DaemonSet

首先想到的是DaemonSet,DaemonSet能保证应用跑在不同的节点,但DaemonSet应用场景一般是作为守护进程或者日志收集,并且每个节点都会部署一个副本,这并不是我们想要的结果,因此不考虑DaemonSet。

  • nodeAffinity

节点亲和性(nodeAffinity)可以通过条件让kubernetes将应用调度到指定节点上,在我们期望的场景中是kubernetes能够将应用调度到不同节点,这个通过节点的标签无法构建表达式。nodeAffinity适合需要将应用调度到明确的节点上。

  • podAntiAffinity

和节点亲和性只能通过节点标签来指定节点不同的是,pod的亲和性可以通过运行在该node上的pod标签进行节点选择,那么假设所有应用都带有app标签,值为app的名称,那么我们可以这么表达不希望调度到节点上有pod标签和我一样的节点,用podAntiAffinity表达如下

affinity:
  podAntiAffinity:
    preferredDuringSchedulingIgnoredDuringExecution:
    - podAffinityTerm:
        labelSelector:
          matchExpressions:
          - key: app
            operator: NotIn
            values:
            - nginx
        topologyKey: kubernetes.io/hostname

一个完整的nginx示例

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment-1
  labels:
    app: nginx
spec:
  replicas: 9
  selector:
    matchLabels:
      app: nginx
  strategy:
    rollingUpdate:
      maxSurge: 0
      maxUnavailable: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:alpine
        ports:
        - containerPort: 80
        - containerPort: 443
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: NotIn
                  values:
                  - nginx
              topologyKey: kubernetes.io/hostname
            weight: 100

亲和性还有软亲和(preferredDuringSchedulingIgnoredDuringExecution)和硬亲和(requiredDuringSchedulingIgnoredDuringExecution)之分,硬亲和必须满足条件才进行调度,比如上面的nginx配置了硬亲和不在同一节点上运行,假设副本数超过了节点数,那么超过的副本将不满足条件,超过的副本状态会变为Unavaliable,如果是软亲和,kubernetes会尽量满足条件,如果不满足也会调度到其他节点上,如果是硬亲和建议副本数不要超过节点数

Trackback

no comment untill now

Add your comment now