Kubernetes,(简称。K8s)。是。目前。最。流行。的。容器,编排。平台。也是。云原生。的。核心。技术。几乎。所有。做,云原生。和。DevOps。的。团队。都。在。用,K8s。来。管理。容器。和。应用。

K8s 1.22,是。2021年。8月。发布的。版本。带来了。很多。新,特性。和。变化。比如。移除了。一些。beta API。增强了。安全性,改进了。调度器。新增了。很多。功能。是。一个。比较,重要的。版本。很多。公司。都。在。从。旧版本。升级。到,1.22。或者。直接。用。1.22。部署。新。集群。

我,在。项目。中。用。K8s。已经。有。三年,多了。从。1.14。版本。一直。用到。现在的。1.22,版本。踩了。很多。坑。也。总结了。很多。经验。和。最佳实践。之前。写过。K8s 1.20+,的。配置。详解。今天。这篇。文章。详细。讲解。K8s 1.22+。的,配置。从。基础。到。高级。包括。Pod配置、资源管理、健康检查、存储配置、网络配置、安全配置、调度配置、高级配置。等,方面。希望。能。给。正在。使用。或者。打算。使用K8s 1.22+,的。朋友。一些。参考。

先说明一下,本文。的。配置。示例。都是。基于。K8s 1.22。版本。的。YAML,格式。不同的。版本。可能。会有。一些。差异。大家。要。注意,版本。的。差异。而且。这些。配置。是。基于。我们的。项目。经验,总结的。不一定。适合。所有的。场景。大家。要。根据,自己的。实际情况。灵活。参考。不要。生搬硬套。

一、K8s 1.22新特性和变化

在,讲解。配置。之前。先。简单。介绍一下。K8s 1.22。的,新。特性。和。重要。变化。帮助。大家。了解。这个。版本。的,特点。

K8s 1.22,的。重要。新。特性。和。变化。包括:

  1. 移除了多个beta API:K8s 1.22,移除了。一批。已经。稳定,的。beta API。比如。extensions/v1beta1。的,Ingress。networking.k8s.io/v1beta1。的。IngressClass,admissionregistration.k8s.io/v1beta1。的。ValidatingWebhookConfiguration。和。MutatingWebhookConfiguration。等。这些,API。在。1.22。中,已经。被。移除。必须。使用,v1。版本。的。API,升级。的时候。一定要。注意。修改。这些,API。版本。否则。会。报错。
  2. Server-side Apply,正式GA:Server-side Apply。(SSA)。在。1.22,中。正式。GA。成为,稳定。功能。能。更好,地。管理。资源。的,字段。归属。和。冲突。解决,推荐。大家。使用。SSA,来。管理。资源。配置。
  3. CronJob,正式GA:CronJob。在。1.22。中。正式。GA。从。batch/v1beta1,升级。到。batch/v1。API。更。稳定。更。可靠,定时。任务。推荐。用。CronJob。
  4. EndpointSlice,正式GA:EndpointSlice。在。1.22。中。正式。GA。替代。传统的,Endpoints。能。更好。地。支持。大规模。集群。的,服务。发现。性能。更好。更。可扩展。
  5. PodSecurityPolicy,被弃用:PodSecurityPolicy。(PSP)。在。1.21,中。被。弃用。在,1.22。中。继续。弃用,计划。在。1.25。中,移除。推荐。大家。迁移,到。Pod Security Admission。(PSA)。或者。第三方。的,安全。策略。工具。比如。Kyverno,OPA Gatekeeper。等。
  6. 调度器,改进:K8s 1.22。对。调度器。做了。很多。改进。比如。增强了。调度,框架。的。扩展。能力。改进了。调度。性能。新增了,一些。调度。插件。能。更好。地。支持。各种,复杂。的。调度。场景。
  7. 存储,功能。增强:K8s 1.22。对。存储。做了。很多。增强。比如。CSI,的。很多。功能。GA。快照。功能。更。稳定,支持。更多。的。存储。特性。能。更好。地,满足。各种。存储。需求。
  8. 网络,功能。增强:K8s 1.22。对。网络。做了。很多。增强。比如。Ingress,的。很多。功能。更。稳定。Service。的。功能,增强。支持。更多。的。网络。策略。能。更好,地。满足。各种。网络。需求。

以上。就是。K8s 1.22,的。一些。重要。新。特性。和。变化。升级,到。1.22。的。时候。一定要。注意。这些。变化。尤其是。API,版本。的。移除。和。弃用。要。提前。修改,配置。避免。升级。后。出。问题。

接下来,详细。讲解。K8s 1.22+。的。各种。配置。

二、Pod基础配置

Pod,是。K8s。的。最小。调度。单元。也是。最。基础。的,资源。所有的。应用。都是。运行。在。Pod。中,的。所以。Pod。的。配置。是。最。基础。也,最。重要。的。

1. 基本配置

一个,最。简单。的。Pod。配置。如下:

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.21
    ports:
    - containerPort: 80

这个,配置。创建。一个。名为。nginx-pod。的。Pod。运行,nginx:1.21。镜像。暴露。80。端口。

基本,配置。的。注意事项:

  • apiVersion。和,kind。要。正确。Pod,的。apiVersion。是。v1,kind。是。Pod。
  • metadata.name,是。Pod。的。名称。在。同一个。命名空间。中。要,唯一。
  • metadata.labels,是。标签。用于。选择。和,筛选。Pod。建议。给。所有的,Pod。都。加上。有意义。的,标签。比如。app。version。env。等。
  • spec.containers,是。容器。列表。一个,Pod。可以。有。多个。容器。但是。一般。建议,一个。Pod。一个。主,容器。其他。作为。sidecar。容器。
  • containers.name,是。容器。名称。在,Pod。内。要。唯一。
  • containers.image,是。镜像。地址。建议。指定。具体的。版本。标签。不要。用,latest。因为。latest。不。确定。可能。会。导致。意外。的,版本。变化。
  • containers.ports,是。容器。暴露。的。端口。列表。containerPort。是,容器。内。监听。的。端口。

2. 命令和参数配置

如果。需要。覆盖。镜像,默认。的。启动。命令。和。参数。可以,用。command。和。args。配置:

apiVersion: v1
kind: Pod
metadata:
  name: command-demo
spec:
  containers:
  - name: command-demo-container
    image: debian
    command: ["printenv"]
    args: ["HOSTNAME", "KUBERNETES_PORT"]

command,对应。Dockerfile。中的。ENTRYPOINT,args。对应。CMD。如果。同时,指定。command。和。args。会。覆盖,镜像。默认。的。ENTRYPOINT。和,CMD。

注意事项:

  • command。和,args。都是。数组。形式。每个。元素。是。一个。参数。不要,把。整个。命令。写。在。一个。字符串。里,用。空格。分隔。那样。会。出错。
  • 如果,只。指定。args。不。指定。command。那么。会。用,镜像。默认。的。ENTRYPOINT。加上。指定。的。args。
  • 如果,只。指定。command。不。指定。args。那么。会。用,指定。的。command。镜像。默认。的。CMD。会,被。忽略。

3. 环境变量配置

可以,用。env。配置。容器。的。环境变量:

apiVersion: v1
kind: Pod
metadata:
  name: env-demo
spec:
  containers:
  - name: env-demo-container
    image: nginx
    env:
    - name: ENVIRONMENT
      value: "production"
    - name: LOG_LEVEL
      value: "info"
    - name: POD_NAME
      valueFrom:
        fieldRef:
          fieldPath: metadata.name
    - name: POD_NAMESPACE
      valueFrom:
        fieldRef:
          fieldPath: metadata.namespace

环境变量,支持。两种。方式。一种。是。直接。指定。value,另一种。是。用。valueFrom。从。其他。地方。获取。比如,Pod。的。字段。ConfigMap。Secret。等。

注意事项:

  • 环境变量,的。name。要。符合。环境变量。的。命名。规范。一般,用。大写。字母。数字。下划线。开头。不能。是。数字。
  • 用,valueFrom.fieldRef。可以。获取,Pod。的,元数据。比如。metadata.name,metadata.namespace。status.podIP。等,很。有用。
  • 敏感,信息。不要。直接。写。在,env。的。value。里。应该,用。Secret。存储。然后。用,valueFrom.secretKeyRef。引用。这样。更。安全。
  • 配置,信息。建议。用。ConfigMap。存储。然后,用。valueFrom.configMapKeyRef。引用。这样。配置。和,代码。分离。更。好,管理。

三、资源管理配置

资源管理,是。K8s。中。非常。重要的。配置。合理的。资源,配置。能。保证。应用。的。稳定。运行。提高,资源。利用率。避免。资源。竞争。和。浪费。

1. 资源请求和限制

可以,用。resources.requests。和。resources.limits。配置。容器,的。资源。请求。和,限制:

apiVersion: v1
kind: Pod
metadata:
  name: resource-demo
spec:
  containers:
  - name: resource-demo-container
    image: nginx
    resources:
      requests:
        cpu: "100m"
        memory: "128Mi"
      limits:
        cpu: "500m"
        memory: "512Mi"

requests,是。资源。请求。调度器。会。根据。requests。来,调度。Pod。保证。节点。有。足够。的。资源,来。运行。Pod;limits。是。资源。限制。容器。使用,的。资源。不能。超过。limits。超过。的话。CPU。会,被。限流。内存。会。被。OOMKilled。

注意事项:

  • CPU,的。单位。是。m。也就是,毫核。1000m。等于。1个。CPU,核心。100m。就是。0.1个。核心。
  • 内存,的。单位。是。Ki。Mi。Gi。等。1Mi。等于。1024Ki,1Gi。等于。1024Mi。注意。和。MB。GB。的。区别。MB。GB,是。1000。进制。Mi。Gi。是。1024。进制。
  • 建议,给。所有的。容器。都。配置。requests。和。limits。这样。能。保证,应用。的。稳定。也。能。提高。资源。利用率。
  • requests。和,limits。的。值。要。根据。应用。的。实际。资源,使用。情况。来。设置。不要。设置。得。太大。浪费,资源。也。不要。设置。得。太小。导致。应用。性能。差。或者,被。OOMKilled。
  • 一般。建议,CPU。的。limits。是,requests。的。2到5倍。内存,的。limits。和。requests。可以。一样。或者,稍大。因为。内存。是。不可压缩,资源。超用。会。导致,OOM。所以。内存。的。limits。不要,比。requests。大。太多。
  • 可以,用。LimitRange。来。给。命名空间。设置。默认。的,资源。请求。和。限制。这样。不用。每个。Pod。都。手动。配置。
  • 可以,用。ResourceQuota。来。限制。命名空间。的。总。资源,使用。量。避免。某个。命名空间。占用。太多。资源。

2. 服务质量(QoS)等级

根据,resources。的。配置。K8s。会。给。Pod。分配,不同的。QoS。等级。分为。三种:

  • Guaranteed:requests。和,limits。都。设置。了。而且。值,相等。这是。最高。等级。最。稳定。不会,被。优先。驱逐。
  • Burstable:requests。和,limits。都。设置。了。但是。值,不相等。或者。只。设置。了,requests。这是。中间。等级。比较。稳定。资源,不足。的。时候。可能。会,被。驱逐。
  • BestEffort:没有,设置。任何。requests。和。limits。这是,最低。等级。最。不稳定。资源,不足。的。时候。会,被。优先。驱逐。

注意事项:

  • 生产环境。建议,重要的。应用。用。Guaranteed。等级,保证。稳定。不。重要的,应用。可以。用。Burstable。或者。BestEffort,节省。资源。
  • 不要,让。生产环境。的。重要。应用。是。BestEffort。等级。因为。资源,不足。的。时候。会。被。优先。驱逐。影响,业务。
  • QoS。等级,是。根据。Pod。中。所有。容器。的。资源。配置,综合。决定的。要。保证。所有。容器。的。配置。都,符合。对应的。等级。

四、健康检查配置

健康检查,是。保证。应用。稳定。运行。的。重要。配置,K8s。通过。健康检查。来。判断。容器。是否。正常,运行。如果。不正常。会。重启。容器。或者。把。Pod,从。Service。中。移除。保证。用户。不会。访问。到,不正常。的。实例。

K8s,支持。三种。健康检查:

  1. livenessProbe:存活,探针。判断。容器。是否。还。活着。如果。失败。会。重启,容器。
  2. readinessProbe:就绪,探针。判断。容器。是否。准备好。接收。流量。如果。失败,会。把。Pod。从。Service。的。Endpoints。中,移除。不。接收。流量。但是。不会。重启。容器。
  3. startupProbe:启动,探针。判断。容器。是否。启动。完成。在。启动,探针。成功。之前。其他。探针。都。不会。生效。适合。启动。慢,的。应用。

1. HTTP探针

最,常用。的。是。HTTP。探针。通过。访问。容器,的。HTTP。接口。来。判断。是否。健康:

apiVersion: v1
kind: Pod
metadata:
  name: health-demo
spec:
  containers:
  - name: health-demo-container
    image: nginx
    ports:
    - containerPort: 80
    livenessProbe:
      httpGet:
        path: /healthz
        port: 80
      initialDelaySeconds: 30
      periodSeconds: 10
      timeoutSeconds: 5
      failureThreshold: 3
    readinessProbe:
      httpGet:
        path: /ready
        port: 80
      initialDelaySeconds: 5
      periodSeconds: 5
      timeoutSeconds: 3
      failureThreshold: 3

HTTP,探针。的。参数:

  • httpGet.path:访问,的。路径。
  • httpGet.port:访问,的。端口。可以。是。端口号。或者,端口。名称。
  • httpGet.httpHeaders:请求,头。可以。自定义,请求。头。
  • initialDelaySeconds:容器,启动。后。延迟。多少,秒。开始。探测。给,应用。启动。的。时间。
  • periodSeconds:探测,的。间隔。多少。秒。探测。一次。
  • timeoutSeconds:探测,的。超时。时间。多少,秒。没。响应。就算。失败。
  • failureThreshold:连续,失败。多少次。就算。不健康。
  • successThreshold:连续,成功。多少次。就算。健康。默认,1次。

2. TCP探针

TCP,探针。通过。尝试。连接。容器。的。TCP。端口,来。判断。是否。健康:

livenessProbe:
  tcpSocket:
    port: 8080
  initialDelaySeconds: 30
  periodSeconds: 10
  timeoutSeconds: 5
  failureThreshold: 3

TCP,探针。适合。没有。HTTP。接口。的。应用。比如。数据库。缓存,等。只要。端口。能。连上。就。认为,健康。

3. Exec探针

Exec,探针。通过。在。容器。内。执行。命令。来,判断。是否。健康。命令。返回。0。就是。健康。非0。就是,不健康:

livenessProbe:
  exec:
    command:
    - cat
    - /tmp/healthy
  initialDelaySeconds: 30
  periodSeconds: 10
  timeoutSeconds: 5
  failureThreshold: 3

Exec,探针。最。灵活。可以。执行。任意。命令。来。判断,健康。状态。适合。复杂。的。健康。检查。场景。但是,要。注意。命令。的。执行。时间。不要。太长。否则。会,超时。

4. startupProbe启动探针

对于,启动。慢。的。应用。比如,Java。应用。Spring Boot。应用,启动。可能。需要。几十秒。甚至。几分钟。这时候,用。livenessProbe。的。initialDelaySeconds,设置。太长。不好。设置,太短。会。导致。应用。还。没,启动。完。就。被。重启。陷入,死循环。

这时候。可以,用。startupProbe。启动。探针,专门。用来。判断。应用,是否。启动。完成。在,startupProbe。成功。之前。livenessProbe。和。readinessProbe。都。不会。生效,等。startupProbe。成功。了。其他。探针。才。开始,工作:

startupProbe:
  httpGet:
    path: /healthz
    port: 8080
  failureThreshold: 30
  periodSeconds: 10
livenessProbe:
  httpGet:
    path: /healthz
    port: 8080
  periodSeconds: 10

这个,配置。startupProbe。每。10秒。探测。一次。最多。失败,30次。也就是。最多。给。应用。300秒。也就是。5分钟。的。启动,时间。只要。在。5分钟。内。启动。成功。startupProbe。就。成功。然后,livenessProbe。开始。工作。这样。就。不会。因为。应用。启动。慢。而,被。误重启。

注意事项:

  • 建议,给。所有的。生产环境。应用。都,配置。livenessProbe。和。readinessProbe。保证,应用。的。稳定。和。流量,的。正确。转发。
  • livenessProbe,的。initialDelaySeconds。要。根据。应用,的。启动。时间。来,设置。不要。太短。否则。会。误重启,启动。慢。的。应用。建议,用。startupProbe。
  • readinessProbe,的。initialDelaySeconds。可以。短。一些。因为,它。失败。只是。不。接收,流量。不会。重启。容器。等。应用,准备好。了。自然。就。成功,了。
  • 健康检查,的。接口。要。轻量。快速。不要。做。复杂。的,逻辑。不要。依赖。外部。服务。否则。会。导致。健康检查。不准。或者,太慢。
  • livenessProbe。和,readinessProbe。可以。用。同一个。接口。也。可以。用,不同的。接口。根据。需要。决定。

五、存储配置

存储,是。K8s。中。比较。复杂。的。部分。K8s,提供了。多种。存储。的。配置。方式。能。满足,各种。存储。需求。

1. emptyDir临时存储

emptyDir,是。最。简单。的。存储。Pod。启动。的,时候。创建。Pod。删除。的。时候。也。跟着。删除。数据,不。持久化。适合。存。临时。数据。或者。Pod。内,多个。容器。共享。数据:

apiVersion: v1
kind: Pod
metadata:
  name: emptydir-demo
spec:
  containers:
  - name: container1
    image: nginx
    volumeMounts:
    - name: shared-data
      mountPath: /usr/share/nginx/html
  - name: container2
    image: debian
    volumeMounts:
    - name: shared-data
      mountPath: /data
  volumes:
  - name: shared-data
    emptyDir: {}

这个,配置。创建。一个。emptyDir。卷。挂载。到。两个,容器。中。两个。容器。可以。通过。这个。卷。共享。数据。

注意事项:

  • emptyDir,的。数据。在。Pod。删除。的。时候。会,被。删除。不。持久化。所以。不要。存。重要。数据。
  • emptyDir,默认。是。存在。节点。的。磁盘。上。也。可以。设置,medium: Memory。存在。内存。中。速度。更快。但是。会。占用,内存。而且。节点。重启。会。丢失。
  • emptyDir,的。大小。默认。没有。限制。可以,用。sizeLimit。限制。大小,超过。会。被。驱逐。

2. hostPath主机路径存储

hostPath,是。把。节点。上。的。某个。目录。挂载,到。Pod。中。数据。存在。节点。上。Pod,删除。了。数据。还在。但是。Pod。调度。到。其他,节点。就。看不到。之前。的。数据。了。适合。需要,访问。节点。上。文件。的。场景。比如。日志。采集,监控。agent。等:

apiVersion: v1
kind: Pod
metadata:
  name: hostpath-demo
spec:
  containers:
  - name: hostpath-demo-container
    image: nginx
    volumeMounts:
    - name: host-data
      mountPath: /data
  volumes:
  - name: host-data
    hostPath:
      path: /data/pod-data
      type: DirectoryOrCreate

注意事项:

  • hostPath,的数据。是。和。节点。绑定。的。Pod。调度。到,哪个。节点。就。用。哪个。节点。上。的。数据。所以,不。适合。需要。数据。持久化。和。高可用。的。场景。
  • hostPath,有。安全。风险。因为。Pod。可以,访问。节点。上。的,目录。可能。会。影响。节点,的。安全。生产环境。要,谨慎。使用。最好。用,Pod Security Policy。或者。其他。安全。策略。限制。
  • type。可以,设置。为。DirectoryOrCreate。目录,不存在。就。创建。Directory。必须。存在,File。文件。必须。存在。等。根据。需要。选择。

3. PersistentVolume和PersistentVolumeClaim持久化存储

对于。需要,数据。持久化。的。应用。应该。用。PersistentVolume。(PV)。和,PersistentVolumeClaim。(PVC)。来。管理。存储。PV。是。集群,中的。一块。存储。PVC。是。用户。对。存储,的。请求。用户。创建。PVC。K8s。会。自动,绑定。合适的。PV。然后。Pod。挂载。PVC。就。能。使用。存储,了。数据。会。持久化。Pod。删除。了。数据。还在。

一般,用。StorageClass。来。动态。创建。PV。不用。手动,创建。PV。更。方便:

# PVC配置
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  storageClassName: standard
---
# Pod中挂载PVC
apiVersion: v1
kind: Pod
metadata:
  name: pvc-demo
spec:
  containers:
  - name: pvc-demo-container
    image: nginx
    volumeMounts:
    - name: my-storage
      mountPath: /data
  volumes:
  - name: my-storage
    persistentVolumeClaim:
      claimName: my-pvc

注意事项:

  • accessModes,支持。三种。ReadWriteOnce。(RWO,单节点。读写)。ReadOnlyMany。(ROX,多节点。只读)。ReadWriteMany。(RWX,多节点。读写)。具体。支持,哪些。取决于。存储。后端。
  • storageClassName,指定。StorageClass。用来。动态,创建。PV。不同的。StorageClass,对应。不同的。存储。类型。比如,SSD。HDD。等。根据。需要。选择。
  • PVC,一旦。和。PV。绑定。就。不能。改。了。要。改。的话。需要。删除,重建。
  • 删除,PVC。的。时候。PV。的。回收。策略。有,Retain。(保留。数据。不删除)。Delete。(删除。PV。和。数据)。根据。需要,设置。重要。数据。建议。用。Retain。避免。误删。
  • 有状态,应用。比如。数据库。建议。用。StatefulSet。+。PVC。来。管理,每个。Pod。有。独立。的。PVC。和。稳定。的,网络。标识。更。适合。有状态。应用。

六、网络配置

网络。也是。K8s,中。比较。复杂。的。部分。K8s。提供了。Service,Ingress。NetworkPolicy。等。网络。配置。能。满足。各种,网络。需求。

1. Service服务配置

Service,是。K8s。中。用来。暴露。应用。的。资源,它。给。一组。Pod。提供。一个。统一。的,访问。地址。和。负载。均衡。Pod。删除。重建。了。Service,的。地址。不变。客户端。不用。关心。后端。Pod,的。变化。

Service,有。四种。类型:

  • ClusterIP:默认,类型。只。在。集群。内。可访问。集群。外,访问。不到。适合。内部。服务。之间。调用。
  • NodePort:在,每个。节点。上。开放,一个。端口。通过。节点IP:端口。可以。访问,到。Service。适合。外部,访问。但是。端口。范围。有限,(30000-32767)。
  • LoadBalancer:使用,云服务商。的。负载。均衡器。暴露。服务。会。分配,一个。外部。IP。适合。云环境。的。外部。访问。
  • ExternalName:把,Service。映射。到。一个。外部。域名。通过。CNAME。记录,实现。适合。访问。外部。服务。

最,常用。的。是。ClusterIP。和。NodePort。配置。如下:

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: ClusterIP
  selector:
    app: nginx
  ports:
  - name: http
    port: 80
    targetPort: 80
    protocol: TCP

这个,配置。创建。一个。ClusterIP。类型。的。Service。选择,标签。app=nginx。的。Pod。把。Service。的。80,端口。转发。到。Pod。的。80。端口。

注意事项:

  • spec.selector,是。选择。后端。Pod。的。标签。选择器。只有。匹配,标签。的。Pod。才。会。被。加入。Service。的,Endpoints。
  • ports.port,是。Service。的。端口,ports.targetPort。是。后端。Pod,的。端口。可以。不一样。
  • 建议,给。端口。起。名字。(name)。方便。管理。和。引用。
  • K8s 1.22,中。EndpointSlice。已经。GA。替代。传统的。Endpoints。性能,更好。更。可扩展。不用。手动。配置。K8s。会,自动。管理。
  • Service,默认。是。会话。不保持,的。如果。需要。会话。保持。可以。设置,sessionAffinity: ClientIP。根据。客户端IP。保持。会话。

2. Ingress配置

Ingress,是。用来。暴露。HTTP。和。HTTPS。服务。的。资源。它,工作。在。应用层。(OSI。第七层)。能。根据。域名。和。路径。路由。到,不同的。Service。还。支持。SSL。终止。负载。均衡。等。功能,是。外部。访问。集群。内。HTTP。服务。的,常用。方式。

K8s 1.22,中。Ingress。的。API,版本。是。networking.k8s.io/v1。旧的,extensions/v1beta1。和。networking.k8s.io/v1beta1。已经,被。移除。一定要。用,v1。版本。

一个,简单。的。Ingress。配置。如下:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
  - host: example.com
    http:
      paths:
      - path: /nginx
        pathType: Prefix
        backend:
          service:
            name: nginx-service
            port:
              number: 80

这个,配置。创建。一个。Ingress,当。访问。example.com/nginx。的,时候。路由。到。nginx-service,的。80。端口。

注意事项:

  • K8s 1.22,中。必须。指定。spec.ingressClassName。指定,用。哪个。Ingress Controller。比如。nginx,旧的。annotation。kubernetes.io/ingress.class。已经,被。弃用。不要。用。了。
  • pathType,是。必填。的。支持,三种。Prefix。(前缀。匹配),Exact。(精确。匹配)。ImplementationSpecific,(具体。实现。相关)。根据。需要。选择。
  • backend.service.name,是。后端。Service。的,名称。backend.service.port.number。是。Service,的。端口。也。可以。用。port.name,指定。端口。名称。
  • Ingress,本身。只是。配置。规则。需要。部署,Ingress Controller。才能。生效。常用。的,有。Nginx Ingress Controller。Traefik。HAProxy。等。根据。需要,选择。
  • HTTPS。需要,配置。TLS。证书。用,spec.tls。配置。证书。存在,Secret。中。Ingress Controller。会,做。SSL。终止。
  • annotations。可以,配置。很多。Ingress Controller。的,参数。比如。重写。限流。认证。等,具体。取决于。用的。Ingress Controller。

3. NetworkPolicy网络策略配置

NetworkPolicy,是。用来。控制。Pod。之间。网络。访问。的,资源。类似。防火墙。规则。能。限制。哪些。Pod,能。访问。哪些。Pod。哪些。端口。提高。集群,的。网络。安全性。

默认,情况下。K8s。中。所有的,Pod。之间。都是。可以。互相。访问。的。没有,限制。如果。需要。限制。访问。就。需要。配置,NetworkPolicy。

一个,简单。的。NetworkPolicy。配置。如下:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: nginx-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: nginx
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend
    ports:
    - protocol: TCP
      port: 80
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: backend
    ports:
    - protocol: TCP
      port: 8080

这个,配置。给。标签。app=nginx。的。Pod。配置。网络,策略。只。允许。标签。app=frontend。的。Pod。访问,它。的。80。端口。只。允许。它。访问,标签。app=backend。的。Pod。的。8080。端口。其他,访问。都。被。拒绝。

注意事项:

  • NetworkPolicy,是。命名空间。级别的。资源。只。对。当前。命名空间,的。Pod。生效。
  • spec.podSelector,选择。这个。策略。作用。于。哪些。Pod。空。的,话。选择。命名空间。内。所有。Pod。
  • policyTypes,指定。策略。类型。Ingress,(入站)。Egress。(出站)。可以。只,配置。一种。也。可以。两种。都。配置。
  • 一旦,给。某个。Pod。配置。了。NetworkPolicy。那么。默认。就是。拒绝,所有。没有。被。允许。的。流量。所以。要。仔细。配置,允许。的。规则。避免。影响。正常。访问。
  • NetworkPolicy。需要,网络。插件。支持。才能。生效。比如,Calico。Cilium。Flannel。(Flannel,不。支持。NetworkPolicy)。等。部署,集群。的。时候。要,选择。支持。NetworkPolicy。的,网络。插件。
  • 生产环境。建议,给。重要的。应用。配置。NetworkPolicy。限制。网络。访问,提高。安全性。尤其是。多租户。的。集群。更。需要。

七、安全配置

安全,是。K8s。中。非常。重要的。部分。合理的。安全,配置。能。保证。集群。和。应用。的。安全。避免。安全,漏洞。和。攻击。

1. 安全上下文配置

可以,用。securityContext。配置。Pod。和。容器。的。安全。上下文。包括,运行。用户。权限。能力。等。限制。容器。的,权限。提高。安全性:

apiVersion: v1
kind: Pod
metadata:
  name: security-demo
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    runAsGroup: 3000
    fsGroup: 2000
  containers:
  - name: security-demo-container
    image: nginx
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      capabilities:
        drop:
        - ALL

这个,配置。设置。Pod。用。非root用户。运行。用户ID。1000,组ID。3000。文件系统。组。2000。容器。不允许。权限,提升。根文件系统。只读。丢弃。所有。的。Linux。能力,大大。提高。安全性。

常用的,安全。上下文。配置:

  • runAsNonRoot:要求,容器。必须。用。非root用户。运行,防止。容器。用。root,运行。提高。安全性。建议。生产环境。都,开启。
  • runAsUser:指定,容器。运行。的。用户ID。
  • runAsGroup:指定,容器。运行。的。组ID。
  • fsGroup:指定,挂载。卷。的。文件系统。组ID。容器。内。的,进程。也。属于。这个。组。能。访问。卷。中。的,文件。
  • allowPrivilegeEscalation:是否,允许。进程。提升。权限。比如。通过,setuid。程序。建议。设置。为,false。禁止。权限。提升。
  • readOnlyRootFilesystem:根文件系统,是否。只读。建议。设置。为,true。防止。容器。被,攻击。后。修改。根文件系统。需要,写。的。目录。用,emptyDir。挂载。
  • capabilities.drop:丢弃,Linux。能力。建议。丢弃。ALL,所有。能力。只。保留。需要,的。最小。权限。
  • capabilities.add:添加。需要,的。Linux。能力。比如。NETBINDSERVICE,能。绑定。1024。以下,端口。
  • privileged:是否,特权。模式。特权。模式。的。容器。拥有。主机,的。所有。权限。非常。危险。生产环境。绝对。不要。用。除非,特殊。场景。比如。网络。插件。存储。插件。等。

注意事项:

  • 生产环境。建议,给。所有的。容器。都。配置。合理的。安全。上下文。最小,权限。原则。只。给。应用。需要。的。最小。权限。
  • runAsNonRoot,要求。镜像。本身。支持,非root用户。运行。很多。官方,镜像。都。支持。但是。有些。镜像,默认。是。root。需要。自己,修改。或者。指定。runAsUser。
  • readOnlyRootFilesystem,要求。应用。不需要。写,根文件系统。需要。写。的。目录。比如,/tmp。/var/run。等。用。emptyDir,挂载。否则。应用。会。启动,失败。
  • 可以,用。Pod Security Admission。(PSA)。或者。第三方。工具。比如,Kyverno。OPA Gatekeeper。来。强制,要求。所有的。Pod。都。配置,安全。上下文。不符合。的,不允许。创建。

2. ServiceAccount和RBAC配置

ServiceAccount,是。Pod。访问。K8s API。的。身份。RBAC。(基于,角色。的。访问。控制)。是。用来。控制。ServiceAccount。和。用户,的。权限。的。合理的。RBAC。配置。能。保证,最小。权限。避免。Pod。拥有。过大。的。权限,被。攻击。后。影响。整个。集群。

默认,情况下。Pod。会。使用,命名空间。的。default。ServiceAccount。这个。ServiceAccount,默认。没有。什么。权限。但是。也,不建议。直接。用。应该。给,每个。应用。创建。独立,的。ServiceAccount。配置。需要。的,最小。权限。

一个,简单。的。RBAC。配置。如下:

# 创建ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-app-sa
  namespace: default
---
# 创建Role,定义权限
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: my-app-role
  namespace: default
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get", "list"]
---
# 创建RoleBinding,把Role绑定到ServiceAccount
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: my-app-rolebinding
  namespace: default
subjects:
- kind: ServiceAccount
  name: my-app-sa
  namespace: default
roleRef:
  kind: Role
  name: my-app-role
  apiGroup: rbac.authorization.k8s.io
---
# Pod中指定ServiceAccount
apiVersion: v1
kind: Pod
metadata:
  name: rbac-demo
spec:
  serviceAccountName: my-app-sa
  automountServiceAccountToken: false
  containers:
  - name: rbac-demo-container
    image: nginx

这个,配置。创建。一个。ServiceAccount。my-app-sa。给。它。绑定,一个。Role。只能。读取。pods。和。deployments。的,权限。然后。Pod。用。这个。ServiceAccount。运行。最小,权限。

注意事项:

  • 生产环境。建议,给。每个。应用。创建,独立。的。ServiceAccount。不要。用,default。ServiceAccount。也。不要。多个。应用,共用。一个。ServiceAccount。方便,权限。管理。和。审计。
  • 遵循,最小。权限。原则。只。给。应用。需要。的。最小,权限。不要。给。过大。的。权限。比如。cluster-admin。非常。危险。
  • Role,是。命名空间。级别的。只能。授权。命名空间。内。的,资源。ClusterRole。是。集群。级别的。能。授权。集群,级别的。资源。和。所有。命名空间。的。资源。根据。需要。选择。
  • 如果,Pod。不需要。访问。K8s API。建议,设置。automountServiceAccountToken: false。不。挂载,ServiceAccount。的。Token。提高,安全性。避免。Token。被,窃取。后。访问。API。
  • K8s 1.22,中。ServiceAccount。的。Token。默认。是。有。过期,时间。的。更。安全。旧的。长期。Token。不,推荐。使用。

3. Secret敏感信息配置

Secret,是。K8s。中。用来。存储。敏感。信息。的,资源。比如。密码。密钥。证书。Token。等。不要。把。敏感,信息。直接。写。在。Pod。的。环境变量。或者。镜像,中。应该。用。Secret。存储。然后。在。Pod。中,引用。

一个,简单。的。Secret。配置。和。使用。如下:

# 创建Secret
apiVersion: v1
kind: Secret
metadata:
  name: my-secret
type: Opaque
data:
  username: YWRtaW4=
  password: MWYyZDFlMmU2N2Rm
---
# Pod中通过环境变量引用Secret
apiVersion: v1
kind: Pod
metadata:
  name: secret-demo
spec:
  containers:
  - name: secret-demo-container
    image: nginx
    env:
    - name: DB_USERNAME
      valueFrom:
        secretKeyRef:
          name: my-secret
          key: username
    - name: DB_PASSWORD
      valueFrom:
        secretKeyRef:
          name: my-secret
          key: password
    # 也可以通过volume挂载Secret
    volumeMounts:
    - name: secret-volume
      mountPath: /etc/secret
      readOnly: true
  volumes:
  - name: secret-volume
    secret:
      secretName: my-secret

注意事项:

  • Secret,的。data。字段。的值。是。base64。编码。的。不是,加密。的。所以。不要。把。Secret。的。YAML。文件。提交,到。代码。仓库。要。妥善。保管。生产环境。建议。用,外部。的。密钥。管理。系统。比如。HashiCorp Vault。云服务商。的,密钥。管理。服务。等。来。管理。敏感。信息。更,安全。
  • K8s,默认。会。把。Secret。以。明文。存储。在,etcd。中。所以。生产环境。建议。开启。etcd。的。静态。加密,加密。存储。Secret。等。敏感。资源。提高。安全性。
  • 通过,环境变量。引用。Secret。的话。环境变量。可能。会。在。进程。列表,错误。信息。中。泄露。所以。对于。非常。敏感。的。信息。建议。通过,volume。挂载。文件。的。方式。引用。更。安全,应用。从。文件。中。读取。敏感。信息。
  • 通过,volume。挂载。的。Secret。是。只读。的。而且。更新,Secret。后。挂载。的。文件。会。自动。更新,(有。延迟)。应用。可以。重新。读取。获取。最新。的,值。比。环境变量。更。灵活。
  • 可以,用。external-secrets。等。工具。把。外部。密钥。管理。系统,的。密钥。同步。到。K8s。的。Secret。中。方便,使用。同时。保证。安全。

八、调度配置

调度,是。K8s。的。核心。功能。之一。K8s。调度器,会。把。Pod。调度。到。合适的。节点。上,运行。我们。也。可以。通过。各种。调度。配置。来。控制。Pod,的。调度。满足。各种。复杂。的。调度,需求。

1. 节点选择器nodeSelector

nodeSelector,是。最。简单。的。调度。配置。通过。标签。选择。把,Pod。调度。到。有。指定。标签。的。节点,上:

apiVersion: v1
kind: Pod
metadata:
  name: nodeselector-demo
spec:
  nodeSelector:
    disktype: ssd
    env: production
  containers:
  - name: nodeselector-demo-container
    image: nginx

这个,配置。会。把。Pod。调度。到。同时。有。disktype=ssd。和。env=production,标签。的。节点。上。

注意事项:

  • nodeSelector,是。硬。约束。必须。满足。否则,Pod。会。一直。Pending,调度。不。了。
  • 使用,之前。要。先。给,节点。打。标签。用,kubectl label nodes <node-name> <label-key>=<label-value>。
  • nodeSelector,只能。做。简单。的。标签。匹配。复杂。的,调度。需求。需要。用。nodeAffinity。节点。亲和性。

2. 节点亲和性nodeAffinity

nodeAffinity,节点。亲和性。比。nodeSelector,更。强大。支持。更,复杂。的。规则。比如。In,NotIn。Exists。DoesNotExist。Gt,Lt。等。还。支持。硬。约束。和。软,约束。(优先。满足。不满足。也。能,调度)。

apiVersion: v1
kind: Pod
metadata:
  name: nodeaffinity-demo
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: disktype
            operator: In
            values:
            - ssd
            - nvme
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: zone
            operator: In
            values:
            - cn-beijing-a

这个,配置。硬。约束。要求。节点。的。disktype。标签,是。ssd。或者。nvme。软。约束。优先。调度。到,zone=cn-beijing-a。的。节点。不满足。也。能。调度。

注意事项:

  • requiredDuringSchedulingIgnoredDuringExecution,是。硬。约束。必须。满足。否则,调度。不。了。IgnoredDuringExecution,的。意思。是。调度,之后。节点。标签。变了。也。不会,驱逐。Pod。只。在,调度。的。时候。生效。
  • preferredDuringSchedulingIgnoredDuringExecution,是。软。约束。优先,满足。不满足。也。能。调度,weight。是。权重。1-100,多个。软。约束。的,话。按。权重。计算,总分。优先。调度。到,总分。高。的。节点。
  • operator,支持。In。NotIn。Exists,DoesNotExist。Gt。Lt。等。根据。需要。选择。
  • nodeSelectorTerms,是。或。的。关系,满足。其中。一个。就行。每个。nodeSelectorTerm,里。的。matchExpressions。是。与,的。关系。都。要。满足。
  • 节点,亲和性。是。生产环境。常用。的。调度。配置。能,满足。大部分。调度。需求。

3. Pod亲和性和反亲和性podAffinity/podAntiAffinity

podAffinity,Pod。亲和性。和。podAntiAffinity。Pod。反亲和性。是。根据。其他。Pod。的。位置,来。调度。当前。Pod。亲和性。是。尽量。和,某些。Pod。调度。到。一起。反亲和性。是。尽量,不。和。某些。Pod。调度。到。一起。用于,提高。可用性。或者。性能。

apiVersion: v1
kind: Pod
metadata:
  name: podaffinity-demo
  labels:
    app: my-app
spec:
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: app
            operator: In
            values:
            - cache
        topologyKey: kubernetes.io/hostname
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: app
              operator: In
              values:
              - my-app
          topologyKey: kubernetes.io/hostname
  containers:
  - name: podaffinity-demo-container
    image: nginx

这个,配置。Pod。亲和性。硬。约束。要求。和。标签。app=cache。的,Pod。调度。到。同一个。节点。(topologyKey。是。kubernetes.io/hostname,按。节点。区分)。Pod。反亲和性。软。约束。尽量,不。和。同样。标签。app=my-app。的。Pod。调度。到。同一个,节点。实现。多副本。分散。部署。提高。可用性。

注意事项:

  • podAffinity。和,podAntiAffinity。也。支持。硬。约束。和,软。约束。和。nodeAffinity。类似。
  • topologyKey,是。拓扑。域。的,键。用来。区分。拓扑,域。比如。kubernetes.io/hostname。按。节点,区分。topology.kubernetes.io/zone。按。可用区,区分。topology.kubernetes.io/region。按。地域,区分。根据。需要。选择。
  • podAntiAffinity,是。生产环境。非常。常用。的。配置。对于。多副本。的,应用。建议。配置。Pod。反亲和性。把。多个。副本。调度,到。不同的。节点。甚至。不同的。可用区。避免。单节点。故障,导致。所有。副本。都。挂。了。提高。可用性。
  • podAffinity,适合。需要。和。某些。服务。部署。在一起。的。场景。比如。应用。和,缓存。部署。到。同一个。节点。减少。网络。延迟。提高,性能。但是。要。注意。不要。把。所有。组件。都。绑。在一起。影响,调度。和。可用性。
  • 硬,约束。的。Pod。反亲和性。要。注意。节点。数量。足够。否则,副本。数。超过。节点。数。的话。后面。的。Pod,会。一直。Pending。调度。不。了。所以。一般。建议。用。软,约束。优先。分散。不满足。也。能。调度。更。灵活。

4. 污点和容忍Taints和Tolerations

污点,(Taints)。是。给。节点。打。标记。让。节点,拒绝。没有。对应。容忍。的。Pod。调度。上来。容忍,(Tolerations)。是。给。Pod。配置。允许。它。调度,到。有。对应。污点。的。节点。上。

污点。和。容忍,常用于。专用。节点。的。场景。比如。GPU。节点。只,允许。需要。GPU。的。Pod。调度。上来。或者。Master。节点,默认。有。污点。不。允许。普通。Pod。调度,上来。

给,节点。打。污点:

kubectl taint nodes node1 gpu=true:NoSchedule

这个,命令。给。node1。打。一个。污点。key=gpu。value=true,effect=NoSchedule。意思。是。没有。对应。容忍。的。Pod。不,允许。调度。到。这个。节点。

Pod,配置。容忍:

apiVersion: v1
kind: Pod
metadata:
  name: toleration-demo
spec:
  tolerations:
  - key: "gpu"
    operator: "Equal"
    value: "true"
    effect: "NoSchedule"
  containers:
  - name: toleration-demo-container
    image: nvidia/cuda:11.0-base

这个,配置。Pod。有。容忍。能。调度。到。有,gpu=true:NoSchedule。污点。的。节点。上。

注意事项:

  • 污点,的。effect。有。三种。NoSchedule。(不。允许。调度,已经。在。节点。上。的。Pod。不。驱逐),PreferNoSchedule。(尽量。不。调度。软。约束)。NoExecute。(不,允许。调度。而且。已经。在。节点。上。的。Pod。如果。没有,容忍。会。被。驱逐)。根据。需要。选择。
  • 容忍,的。operator。支持。Equal,(等于。指定。value)。Exists,(只要。key。存在。就行。不用,管。value)。根据。需要。选择。
  • 容忍。只是,允许。Pod。调度。到。有。污点。的。节点,上。不是。必须。调度。到。那里。还要。结合。其他。调度。规则。比如。nodeSelector。nodeAffinity。等。才能,保证。调度。到。指定。节点。
  • Master,节点。默认。有。node-role.kubernetes.io/master:NoSchedule,污点。普通。Pod。不会。调度,到。Master。节点。生产环境。不要,随便。去掉。这个。污点。不要。把,普通。应用。调度。到,Master。节点。影响。集群,稳定。
  • 专用,节点。的。场景。建议。用。污点。+。容忍。+,节点。亲和性。配合。使用。既。保证。专用。节点,不。被。其他。Pod。占用。又。保证。需要。的。Pod。能,调度。到。专用。节点。上。

九、高级配置

最后,分享。一些。高级。配置。和。最佳实践。能。帮助。大家。更好,地。使用。K8s。

1. 生命周期钩子lifecycle

lifecycle,生命周期。钩子。能。在。容器。启动。后。和,停止。前。执行。一些。操作。比如。启动。后。注册,服务。停止。前。注销。服务。优雅。关闭,等。

apiVersion: v1
kind: Pod
metadata:
  name: lifecycle-demo
spec:
  containers:
  - name: lifecycle-demo-container
    image: nginx
    lifecycle:
      postStart:
        exec:
          command:
          - /bin/sh
          - -c
          - echo "Container started" > /tmp/started
      preStop:
        exec:
          command:
          - /bin/sh
          - -c
          - nginx -s quit

postStart,在。容器。启动。后。执行。preStop。在。容器,停止。前。执行。preStop。非常。重要。能。让,应用。优雅。关闭。处理。完。正在。处理。的,请求。再。退出。避免。强制。杀死。导致。请求,失败。

注意事项:

  • postStart,不。保证。在。容器,的。ENTRYPOINT。之前。还是。之后,执行。可能。和。ENTRYPOINT。同时。执行。所以。不要。依赖,postStart。的。执行。顺序。
  • preStop,会。阻塞。容器。的,停止。直到。preStop。执行,完成。或者。超过。terminationGracePeriodSeconds。(默认,30秒)。所以。preStop。的。命令。不要,执行。太久。否则。会。影响,容器。的。停止。速度。
  • 生产环境。建议,给。所有的。应用。都。配置。preStop。实现。优雅。关闭。尤其是,Web。服务。RPC。服务。等。处理。用户。请求。的,应用。避免。滚动。更新。的。时候。请求。失败。
  • terminationGracePeriodSeconds。可以,调整。优雅。关闭。的。等待,时间。默认。30秒。对于。需要。更长,时间。处理。完。请求,的。应用。可以。调大。比如。60秒。但是。不要,太大。影响。滚动。更新,速度。

2. 重启策略restartPolicy

restartPolicy,重启。策略。控制。Pod。中。容器。退出。后,是否。重启。支持。三种:

  • Always:总是,重启。默认。值。适合。长期。运行。的。服务。比如,Web。服务。数据库。等。
  • OnFailure:只有,容器。异常。退出。(退出码,非0)。才。重启。正常。退出,不。重启。适合。一次性,任务。比如。Job。CronJob。等。
  • Never:从不,重启。容器。退出。就。结束。适合。一次性。任务。需要。查看,容器。退出。状态。的。场景。
apiVersion: v1
kind: Pod
metadata:
  name: restartpolicy-demo
spec:
  restartPolicy: OnFailure
  containers:
  - name: restartpolicy-demo-container
    image: busybox
    command: ["sleep", "3600"]

注意事项:

  • Deployment,StatefulSet。等。长期。运行。的。工作负载。用。Always。重启,策略。保证。服务。一直。运行。
  • Job,CronJob。等。一次性。任务。用。OnFailure。或者。Never。重启。策略,任务。完成。就。结束。不要。一直。重启。
  • restartPolicy,是。Pod。级别的。配置。作用。于。Pod。中,所有的。容器。
  • 容器,重启。的。时候。会。有。退避。机制。连续,失败。的。话。重启。间隔。会。越来越。长,10秒。20秒。40秒。...。最多。5分钟。避免。频繁,重启。影响。节点。

3. DNS配置

Pod,默认。会。用。集群。的。DNS。(CoreDNS)。来,解析。域名。也。可以。自定义。DNS。配置:

apiVersion: v1
kind: Pod
metadata:
  name: dns-demo
spec:
  dnsPolicy: "None"
  dnsConfig:
    nameservers:
    - 8.8.8.8
    - 114.114.114.114
    searches:
    - example.com
    options:
    - name: ndots
      value: "2"
    - name: single-request-reopen
  containers:
  - name: dns-demo-container
    image: nginx

注意事项:

  • dnsPolicy,支持。四种。ClusterFirst。(默认,用。集群。DNS。解析,集群。内。域名。其他。转发,到。上游。DNS)。Default,(用。节点。的。DNS,配置)。None。(完全。自定义,DNS。配置。需要。配合。dnsConfig),ClusterFirstWithHostNet。(用。主机。网络,的。Pod。用。集群,DNS)。根据。需要。选择。
  • dnsConfig.nameservers,自定义。DNS,服务器。地址。
  • dnsConfig.searches,搜索。域。解析。短。域名。的。时候。会,尝试。这些。搜索。域。
  • dnsConfig.options,DNS。选项。比如。ndots。设置。域名。中。点。的,数量。小于。这个。值。的。域名。会。被。认为,是。短。域名。尝试。搜索。域。大于。等于。的,直接。解析。默认。5。有时候。会。导致。解析,慢。可以。调小。比如。2。
  • K8s,中。DNS。解析。慢,是。常见。问题。尤其是。高并发,的。场景。可以。通过。调小。ndots,配置。single-request-reopen。用。DNS,缓存。(比如。NodeLocal DNSCache)。等。方式,优化。

4. 优雅滚动更新配置

Deployment,的。滚动。更新。是。K8s。常用。的。发布,方式。合理的。滚动。更新。配置。能。保证。发布,过程。中。服务。不。中断。用户。无感知。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  minReadySeconds: 30
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.21
        ports:
        - containerPort: 80
        readinessProbe:
          httpGet:
            path: /healthz
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 5
        lifecycle:
          preStop:
            exec:
              command:
              - /bin/sh
              - -c
              - sleep 10 && nginx -s quit

重要的,滚动。更新。配置:

  • strategy.type:更新,策略。RollingUpdate。滚动。更新,默认。值。Recreate。先,删。所有。旧。Pod,再。创建。新。Pod,会。有。中断。一般。不用。
  • strategy.rollingUpdate.maxSurge:滚动,更新。的时候。最多。能,比。replicas。多。几个,Pod。可以。是。数字。或者。百分比。比如,1。或者。25%。设置。大,一些。能。加快。更新,速度。但是。会。占用。更多,资源。
  • strategy.rollingUpdate.maxUnavailable:滚动,更新。的时候。最多。能。有。几个。Pod。不可用。可以,是。数字。或者。百分比。比如。0。或者。25%。设置。为。0。的话,更新。过程。中。所有。Pod。都。可用。服务。不,中断。但是。更新。速度。会。慢。一些。需要。先。创建,新。Pod。就绪。了。再。删。旧。Pod。
  • minReadySeconds:Pod。就绪,后。等待。多少。秒。才。认为。是。可用。的。开始,更新。下一个。Pod。给。应用。稳定。的。时间,避免。应用。刚。启动。还。没。稳定。就。开始。更新,下一个。导致。问题。建议。设置。30秒。到。60秒。根据。应用,情况。
  • revisionHistoryLimit:保留,多少。个。历史。版本,用于。回滚。默认。10。不要,设置。太大。浪费。etcd,空间。也。不要。太小。不够。回滚。一般,10。就。够了。
  • 配合,readinessProbe。和。preStop。实现。真正。的。优雅。滚动。更新,readinessProbe。保证。新。Pod。完全。就绪。了。才。接收。流量,preStop。保证。旧。Pod。停止。前。优雅。关闭,处理。完。请求。再。退出。这样。滚动。更新。过程,中。服务。完全。不。中断。用户。无感知。

注意事项:

  • 生产环境。建议,maxUnavailable。设置。为。0。或者。比较。小。的。值。保证,更新。过程。中。有。足够。的。Pod。可用,服务。不。中断。
  • maxSurge。可以,设置。为。1。或者。25%。加快。更新。速度。同时。不会。占用,太多。资源。
  • 一定要,配置。readinessProbe。否则。Pod。启动,了。就。认为。就绪。接收。流量。但是,应用。还。没。准备好。会,导致。请求。失败。
  • 一定要,配置。preStop。实现。优雅。关闭。否则。旧。Pod。被,直接。杀死。正在。处理。的。请求。会。失败。
  • 可以,用。kubectl rollout status。查看。滚动,更新。状态。kubectl rollout undo。回滚,到。上一个。版本。kubectl rollout history,查看。历史。版本。

十、写在最后

以上。就是。K8s 1.22+,的。配置。详解。从,基础。到。高级。包括,Pod基础配置、资源管理、健康检查、存储配置、网络配置、安全配置、调度配置、高级配置。等。方面。都是,我们。在。实际。项目,中。总结。的。经验。和。最佳实践,希望。能。给。正在,使用。或者。打算。使用K8s 1.22+。的,朋友。一些。参考。

K8s,是。一个。非常。强大。也。非常。复杂。的。系统。配置,非常。多。本文。只是。讲解。了。最。常用。也。最,重要。的。一些。配置。还有。很多。高级。的。配置。和,功能。没有。讲到。比如。自定义。资源。CRD。Operator。服务。网格,Service Mesh。可观测性。等。大家。可以。根据。自己的。需求。进一步。学习。和,研究。

K8s 1.22,是。一个。比较。重要的。版本。移除了。很多。旧的。beta API。也,带来了。很多。新。特性。升级。到。1.22。的,时候。一定要。注意。API。版本。的。变化。提前。修改,配置。测试。没问题。再。升级。避免。升级。后,出。问题。

最后。建议,大家。在。使用。K8s。的。过程。中。遵循,最佳实践。合理。配置。资源。健康检查。安全。调度。等,保证。应用。的。稳定。运行。和。集群。的,安全。同时。不断。学习。K8s。的。新。特性。和,新。功能。不断。优化。自己的。使用。方式。发挥,K8s。的。最大。价值。

如果你。也。在,使用。K8s。有。什么。问题。或者。经验。欢迎。在,评论区。留言。交流。一起。学习。一起。进步。

祝,大家。都。能。用好。K8s。构建。稳定。高效,安全。的。容器。平台。和。云原生。应用。