基于Google云原生工程师的kubernetes最佳实践(二)

目录

二、应用部署篇

为deployment打上丰富的label,以便selecting

使用sidecar容器部署agent、proxy等组件

使用init container处理依赖关系,而不要用sidecar

镜像tag使用版本号,不要用latest或空tag

为pod设置readiness和liveness探针

不要给所有服务都使用LoadBalancer,使用ingress

为负载均衡或ingress分配静态IP

用service映射外部依赖服务

使用helm chart管理应用

将所有下游依赖视为不可靠的

微服务划分的粒度不要太细

使用service mesh如istio、linkerd管理微服务

考虑使用Paas平台简化应用管理

不要在生产环境任意使用nodeport

在生产环境给Namespace设置ResourceQuota

不要随便打开容器特权模式

限制emptydir容量

使用emptydir存储临时日志

使用service时尽量配置全域名

 Google云原生工程师最佳实践指南下载


二、应用部署

为deployment打上丰富的label,以便selecting


使用sidecar容器部署agent、proxy等组件

        在Kubernetes中,Sidecar容器用于增强或扩展主应用容器的功能,提供如日志记录、监控、安全性或数据同步等附加服务。Sidecar容器与主应用容器共享同一个Pod,从而能够访问相同的网络和存储资源​​。

        例如,使用Fluentd实现日志记录的Sidecar容器、使用Istio实现服务网格管理的Sidecard容器​


使用init container处理依赖关系,而不要用sidecar

        在需要处理依赖性或预初始化任务时,推荐使用Init容器。这样做的好处是,你可以确保在主应用容器开始运行之前所有必要的准备工作都已经完成。这有助于避免主应用容器因缺少必要的依赖或配置而启动失败


镜像tag使用版本号,不要用latest或空tag

        使用明确的标签能够提供关于镜像的更多信息,而不是仅仅使用latest,这样可以避免潜在的混淆和不可预测的行为。

为pod设置readiness和liveness探针

不要给所有服务都使用LoadBalancer,使用ingress

        虽然LoadBalancer提供了一种简便的方式来暴露服务,但在很多情况下,使用Ingress可能更为合适。Ingress特别适用于需要复杂路由、SSL终止或基于名称的虚拟托管的场景。通过使用Ingress,可以有效地管理流量路由规则,并减少公有云环境中的外部IP使用,从而降低成本

为负载均衡或ingress分配静态IP

        为负载均衡器或Ingress分配静态IP的原因在于确保服务的持续可访问性和稳定性。在默认情况下,当你在Kubernetes中创建LoadBalancer类型的服务时,分配给它的公共IP地址只在该资源的生命周期内有效。如果你删除了Kubernetes服务,关联的负载均衡器和IP地址也会被删除。因此,如果你想为重部署的Kubernetes服务分配特定的IP地址或保留一个IP地址,就需要创建并使用静态公共IP地址

        通过一个具体的例子来理解如何为Ingress-Nginx控制器分配静态IP。在这个例子中,创建一个负载均衡器服务,并配置Ingress控制器使用这个服务分配的静态IP。

第一步:创建负载均衡器服务

首先,你需要创建一个类型为LoadBalancer的服务,该服务将自动为Ingress-Nginx控制器分配一个静态IP。

apiVersion: v1
kind: Service
metadata:
  name: ingress-nginx-lb
spec:
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
  - port: 443
    targetPort: 443
    protocol: TCP

这个配置定义了一个名为 ingress-nginx-lb的服务,它将在端口80和443上监听传入的HTTP和HTTPS请求。

第二步:等待服务获取静态IP

一旦服务被创建,你需要等待几分钟,直到服务被分配一个外部IP地址。你可以通过运行以下命令来检查服务状态:

kubectl get svc ingress-nginx-lb

当服务获得一个外部IP地址后,你可以在输出中看到这个IP地址。

第三步:更新Ingress控制器配置

        接下来,你需要更新Ingress控制器的部署,以便它使用上一步中获得的静态IP地址。这通常通过在Ingress控制器的部署配置中添加--publish-service参数来实现,指向刚创建的负载均衡器服务。以下是更新Ingress控制器部署的示例:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: ingress-nginx-controller
spec:
  replicas: 1
  template:
    spec:
      containers:
      - name: nginx-ingress-controller
        image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.26.1
        args:
          - /nginx-ingress-controller
          - --publish-service=$(POD_NAMESPACE)/ingress-nginx-lb #指向刚创建的负载均衡器服务

在这个配置中,我们通过--publish-service参数指定了Ingress控制器应该使用ingress-nginx-lb服务的IP地址。

第四步:创建Ingress资源

创建Ingress资源,它将使用Ingress控制器和关联的静态IP地址来路由传入的流量。以下是一个基本的Ingress资源的示例YAML配置:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
spec:
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-service
            port:
              number: 80

        这个Ingress资源配置了一个规则,将所有指向myapp.example.com域的HTTP请求路由到名为my-service`的服务。

        通过这个过程,Ingress-Nginx控制器将使用分配给负载均衡器服务的静态IP地址来处理传入的流量。这样可以确保Ingress的访问地址在服务更新或重部署时保持不变。

 官方参考链接:https://kubernetes.github.io/ingress-nginx/examples/static-ip/

用service映射外部依赖服务

        要在Kubernetes中访问外部的MySQL服务,你可以通过定义一个Endpoints资源和一个Service资源来实现。这样做可以让集群内的Pods通过Kubernetes的内部DNS解析和访问外部服务,就好像这个服务是集群内部的一样。

以下是如何定义这些资源的示例:

1. 定义Endpoints资源:
   这个资源指向外部MySQL服务的具体IP地址和端口。例如,如果外部MySQL服务的地址是192.168.1.100,端口是3306

Endpoints的定义如下所示:

   apiVersion: v1
   kind: Endpoints
   metadata:
     name: mysql-external
   subsets:
     - addresses:
         - ip: 192.168.1.100
       ports:
         - port: 3306

2. 定义Service资源:
   这个资源定义了一个逻辑名称(在这个例子中是mysql-external),Pods可以通过这个名称找到对应的Endpoints并通过它访问外部的MySQL服务。

Service的定义如下所示:

   apiVersion: v1
   kind: Service
   metadata:
     name: mysql-external  #Service的名称必须和Endpoints的名称匹配
   spec:
     ports:
       - protocol: TCP
         port: 3306
         targetPort: 3306

        通过上述配置,集群内的Pods可以通过mysql-external这个名称来访问外部的MySQL服务,就像访问集群内部的服务一样。这种方式简化了外部资源的访问,并允许你在Kubernetes中对这些外部依赖进行抽象。

        请注意,因为这个Service没有选择器(selector),它不会自动与Endpoints关联。在这种情况下,Service的名称必须和Endpoints的名称匹配,这样Service才能正确地将流量转发到定义的外部IP和端口上


使用helm chart管理应用

将所有下游依赖视为不可靠的

        设计应用时,不应假设所有的下游依赖服务是可靠的。要为服务之间的通信建立重试、熔断、降级等保护机制,以降低级联故障的风险。


微服务划分的粒度不要太细

        拆分微服务时需要控制好粒度,过于细化会导致开发、部署和运维的复杂度剧增。应该以业务边界为基准,将密切相关的功能划分到同一个服务中。


使用service mesh如istio、linkerd管理微服务

        在微服务架构中,服务间的通信会变得更加复杂。使用Service Mesh可以提供一整套可靠的通信、监控、安全和流量管理功能。

        Istio和Linkerd是目前主流的Service Mesh方案。它们能自动在服务之间注入智能代理(Sidecar),拦截服务通信,并提供诸如流量控制、熔断、重试、​​金丝雀发布、安全加密等高级功能,而无需修改应用代码。

        使用Service Mesh可以显著降低微服务开发和运维的复杂性,提升整体系统的可观测性、弹性和安全性。


考虑使用Paas平台简化应用管理

        Kubernetes自身作为一个强大而灵活的容器编排平台,它的学习曲线较陡峭,需要一定的运维成本。可以考虑使用基于Kubernetes的PaaS(平台即服务)产品,如OpenShift、Kuboard、Rancher等,这些平台在Kubernetes之上提供了更高级别的抽象,集成了诸多开发者工具,能够显著简化应用的构建、部署、运维等生命周期管理。

不要在生产环境任意使用nodeport

NodePort类型的Service会在每个Node上开放一个端口(默认在30000-32768范围),将该端口映射到集群内的目标Pod。这种方式存在一些限制:

  • 端口范围有限制
  • 每个端口只能映射一个服务
  • 需要防火墙放行对应端口规则
  • 造成端口管理混乱的问题

因此在生产环境中,不建议滥用NodePort。更好的做法是使用Ingress Controller或者LoadBalancer等云负载均衡器,并结合Service的ClusterIP类型来暴露服务。

在生产环境给Namespace设置ResourceQuota

        Kubernetes的Namespace提供了一种对象隔离的机制。在生产环境中,我们往往会为不同的应用、团队或环境创建单独的Namespace。

        为了防止某个Namespace下的资源使用失控,影响整个集群的运行,最佳实践是为每个Namespace配置资源的使用Quota,包括限制Namespace下的CPU、内存、存储等资源总量,以及对单个资源对象的资源限制。

        这样能够实现多租户场景下的资源管控,保证资源的合理分配和隔离,提高集群的稳定性和可靠性。    

ResourceQuota Yaml

apiVersion: v1
kind: ResourceQuota
metadata:
  name: mem-cpu-demo
  namespace: quota-mem-cpu-example
spec:
  hard:
    requests.cpu: "1"
    requests.memory: 1Gi
    limits.cpu: "2"
    limits.memory: 2Gi

LimitRange和ResourceQuota区别:

1. 作用范围:

   - LimitRange:作用于单个命名空间。

   - ResourceQuota:也作用于单个命名空间,但它是一个更全面的限制。

2. 作用对象:

   - LimitRange:主要针对单个容器或Pod。

   - ResourceQuota:针对整个命名空间里的所有Pod和其他资源。

3. 类型:

   - LimitRange:设置CPU、内存等资源的最小、最大、默认值。

   - ResourceQuota:限制命名空间内可以使用的总资源量。

4. 功能:

   - LimitRange:确保容器使用资源在一定范围内。

   - ResourceQuota:确保命名空间不会超过分配的资源。

5. 例子:

   - LimitRange:Pod里的容器必须有512MB至2GB的内存。

   - ResourceQuota:整个命名空间最多可以有10个Pod,总计不超过10GB内存。

LimitRange是微观的,针对单个容器或Pod。ResourceQuota是宏观的,针对整个命名空间。两者通常一起使用,确保资源使用既高效又安全。

当LimitRange和ResourceQuota发生冲突时,ResourceQuota限制优先

不要随便打开容器特权模式

        在Kubernetes中,避免使用特权模式运行容器是一项重要的安全最佳实践。当容器以特权模式运行时,它拥有宿主机上几乎所有的权限,这与在宿主机上以root用户运行程序类似。这种高权限级别会带来显著的安全风险,因为它提供了足够的权限来执行许多可能危及整个宿主机的操作。

为什么要避免使用特权模式:

  1. 提升攻击面:特权容器具有访问宿主机资源的能力,包括访问硬件设备和操作系统级别的操作。如果攻击者成功利用运行在特权模式下的容器中的漏洞,他们可以获得对整个宿主机的控制。

  2. 违反最小权限原则:按照最小权限原则,应用和服务应仅被授予它们完成工作所必需的权限,而不是更多。特权模式违反了这一原则,因为它为容器提供了超出其实际需求的权限。

  3. 难以审计和追踪:以特权模式运行的容器可能会执行许多非标准的操作,这些操作可能难以通过Kubernetes的日志和监控工具来审计和追踪。

打开特权模式YAML

apiVersion: v1
kind: Pod
metadata:
  name: privileged-pod
spec:
  containers:
  - name: nginx
    image: nginx
    securityContext:
      privileged: true    #打开特权模式,极易造成安全逃逸

限制emptydir容量

sizeLimit字段仅作为Pod被驱逐的阈值,而不是硬性限制。这意味着,如果emptyDir使用的空间超过了sizeLimit,指定的大小,Kubernetes会触发Pod的驱逐机制,而不是阻止额外数据的写入

限制emptydir YAML

apiVersion: v1
kind: Pod
metadata:
  name: pod-with-emptydir
spec:
  containers:
  - name: nginx
    image: nginx
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  volumes:
  - name: cache-volume
    emptyDir:
      sizeLimit: "128Mi" # 限制最大容量为128Mi

官网参考链接:

https://kubernetes.io/zh-cn/docs/concepts/storage/volumes/#emptydir-%E9%85%8D%E7%BD%AE%E7%A4%BA%E4%BE%8B

使用emptydir存储临时日志

        在Kubernetes中,使用emptyDir卷存储日志是一种常见的做法,尤其是在处理短暂的或临时的日志数据时。emptyDir是一个临时目录,它与Pod的生命周期相同,这意味着当Pod启动时创建,并在Pod终止时删除。即使Pod运行过程中容器重启多次,之前的应用运行日志仍存在与emptydir中。这种特性使得emptyDir成为存储容器运行期间产生的临时日志文件的理想选择。

使用service时尽量配置全域名

全域名格式:my-service.my-namespace.svc.cluster.local

查看pod的dns解析服务器地址

解释:

  • nameserver: 定义DNS服务器的IP,其实就是kube-dns那个service的IP

  • search:  定义域名的查找后缀规则,查找配置越多,说明域名解析查找匹配次数越多。集群匹配有 default.svc.cluster.local、svc.cluster.local、cluster.local 3个后缀,最多进行8次查询 (IPV4和IPV6查询各四次) 才能得到正确解析结果。不同命名空间,这个参数的值也不同。

  • option: 定义域名解析配置文件选项,支持多个KV值。例如该参数设置成ndots:5,说明如果访问的域名字符串内的点字符数量超过ndots值,则认为是完整域名,并被直接解析;如果不足ndots值,则追加search段后缀再进行查询。

对于Kubernetes集群内的DNS解析,使用更具体、更完整的域名通常会提供更好的性能

        这是因为使用完整域名可以减少DNS解析器需要尝试的搜索后缀(由search参数定义)的数量,从而减少解析时间。具体来说:

1. 完整域名:

        例如,svc-nacos.prod-namespace.svc.cluster.local。这是最具体的域名形式,它直接对应于特定的服务。使用这样的完整域名可以立即定位到目标,无需额外的搜索和尝试,因此这种方式是最高效的。

2. 部分域名:

        例如,svc-nacos.prod-namespace.svc 或 svc-nacos.prod-namespace。这些仍然是相对明确的域名,但它们需要DNS解析器根据 search列表中的后缀来进行一定程度的匹配尝试。虽然这种情况下的性能损失不大,但仍然不如直接使用完整域名。

3. 最短域名:

        例如,仅仅使用 svc-nacos。这种情况下,DNS解析器需要使用search列表中的所有后缀进行尝试,直到找到正确的地址。这会导致最多的DNS查询,因此是这三种情况中性能最低的。

   总结来说,为了获得最佳的性能,建议在Kubernetes集群内部进行通信时使用完整的域名。这样可以减少DNS查询次数,加快解析速度,从而提高整体的网络性能。

 Google云原生工程师最佳实践指南下载

Kubernetes_Best_Practices.pdficon-default.png?t=N7T8https://c74p900o8m.feishu.cn/docx/S84ddjQg2oQRpMxxOykcdP8Snsc

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/485154.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++实现FFmpeg音视频实时拉流并播放

1.准备工作: 下载rtsp流媒体服务器rtsp-simple-server,安装go开发环境并编译 编译好后启动流媒体服务器 准备一个要推流的mp4视频文件,如db.mp4 使用ffmpeg开始推流 推流命令: ffmpeg -re -stream_loop -1 -i db.mp4 -c copy -rtsp_transport tcp -f rtsp rtsp://192.168.16…

笔记本和台式机主板内部结构分析

笔记本和态势机主板内存接口以及配件安装位置 笔记本主板 1 以thinkpad L-490为例,使用拆机小工具拆机,打开后面板,内部结构示意图如下 台式机主板 以技嘉-B660M-AORUS-PRO-AX型号主板为例 笔记本电脑和台式机电脑的相同之处 CPU:笔记本…

前端学习之css media查询、自定义字体、过度动画、css变换、动画、渐变、多列、字体图标

media查询 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>media查询</title><!-- media查询&#xff1a;根据设备类型不同&#xff1a;比如说打印机、屏幕不同而产生不一样效果格式&#x…

Web安全基础入门+信息收集篇

教程介绍 学习信息收集&#xff0c;针对域名信息,解析信息,网站信息,服务器信息等&#xff1b;学习端口扫描&#xff0c;针对端口进行服务探针,理解服务及端口对应关系&#xff1b;学习WEB扫描&#xff0c;主要针对敏感文件,安全漏洞,子域名信息等&#xff1b;学习信息收集方法…

海外媒体宣发:十大国外中文网站-大舍传媒

十大国外中文网站 1、欧洲时报 覆盖欧洲且较具影响力的华文媒体 国外中文新闻网站&#xff0c;欧洲时报文化传媒集团旗舰日报《欧洲时报》旗下官方网站&#xff0c;总部设在法国巴黎&#xff0c;创刊于1983年&#xff0c;现已成为唯一发行覆盖全欧、发行量最大、最具影响力的华…

每日一题 --- 两两交换链表中的节点[力扣][Go]

两两交换链表中的节点 题目&#xff1a;24. 两两交换链表中的节点 给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点交换&#xff09;。 示例 1&a…

算法打卡day15

今日任务&#xff1a; 1&#xff09;110.平衡二叉树 2&#xff09;257. 二叉树的所有路径 3&#xff09;404.左叶子之和 110.平衡二叉树 题目链接&#xff1a;110. 平衡二叉树 - 力扣&#xff08;LeetCode&#xff09; 给定一个二叉树&#xff0c;判断它是否是高度平衡的二叉树…

隐私计算实训营学习四:SecretFlow的安装和部署

文章目录 一、SecretFlow安装二、SecretFolw部署模式简介三、SecretFlow部署-仿真模式四、SecretFlow部署-生产模式 一、SecretFlow安装 SecretFlow运行要求&#xff1a; Python > 3.8操作系统&#xff1a;CentOS7、Anolis8、Ubuntu 18.04/20.04、macOS 11.1、WSL2资源&am…

共享打印机以及修复脱机状态打印机

title: 共享打印机以及修复脱机状态打印机 search: 2024-03-23 tags: “#共享打印机以及修复脱机状态打印机” 如何将打印机共享在局域网内 Tips&#xff1a;考虑将打印机共享&#xff0c;无非是要考虑两个问题&#xff0c;一个是将打印机作为外设的电脑怎么将打印机共享&…

随机密码生成器源码

源码简介 纯HTML&#xff0c;该去的已去掉&#xff0c;该简化的简化&#xff0c;最高支持32位混合随机密码生成 安装教程 纯HTML&#xff0c;直接将压缩包上传网站目录解压即可 首页截图 源码下载 随机密码生成器源码-小8源码屋源码简介 纯HTML&#xff0c;该去的已去掉&a…

阿里云4核16G服务器优惠价格26元1个月、149元半年

阿里云4核16G服务器优惠价格26.52元1个月、79.56元3个月、149.00元半年。2024年腾讯云服务器优惠价格表&#xff0c;一张表整理阿里云服务器最新报价&#xff0c;阿里云服务器网整理云服务器ECS和轻量应用服务器详细CPU内存、公网带宽和系统盘详细配置报价单&#xff0c;大家也…

Java学习笔记 | JavaSE基础语法05 | 方法

文章目录 0.前言1. 方法概述2. 方法的定义和调用2.1 无参数方法定义和调用2.2 带参数方法定义和调用1 带参数方法定义和调用2 形参和实参3 带参数方法练习 2.3 带返回值方法的定义和调用1 带返回值方法定义和调用2 带返回值方法练习13 带返回值方法练习24 带返回值方法练习3 3.…

STM32学习笔记(6_2)- TIM定时器中断和定时器内外时钟源选择代码

无人问津也好&#xff0c;技不如人也罢&#xff0c;都应静下心来&#xff0c;去做该做的事。 最近在学STM32&#xff0c;所以也开贴记录一下主要内容&#xff0c;省的过目即忘。视频教程为江科大&#xff08;改名江协科技&#xff09;&#xff0c;网站jiangxiekeji.com 现在开…

浙大版《C语言程序设计(第4版)》题目集-习题3-5 三角形判断

给定平面上任意三个点的坐标(x1,y1)、(x2,y2)、(x3,y3)&#xff0c;检验它们能否构成三角形。 输入格式: 输入在一行中顺序给出六个[−100,100]范围内的数字&#xff0c;即三个点的坐标x1、y1、x2、y2、x3、y3。 输出格式: 若这3个点不能构成三角形&#xff0c;则在一行中输…

移植 Zephyr 到 Art-Pi

背景 ​ 最近工作中接触到了 Zephyr&#xff0c;不由觉得 Zephyr 是个很强大、全面、优秀的实时操作系统&#xff0c;但同时是有一定的上手难度的&#xff0c;其复杂的构建系统让小编倒吸一口凉气。为了深入研究并完全掌控 Zephyr&#xff0c;小编决定把它移植到手头的开发板上…

[leetcode] 240. 搜索二维矩阵 II

编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性&#xff1a; 每行的元素从左到右升序排列。每列的元素从上到下升序排列。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,…

c高级 day3 shell脚本

1&#xff1a;输入数组&#xff0c;输出数组的所有元素&#xff0c;以及数组长度 37 read -a arr38 echo ${arr[*]}39 echo ${#arr[*]} 运行结果&#xff1a; 2&#xff1a;定义数组存储当前目录下的所有.sh文件&#xff0c;计算文件的个数 43 arr(ls *.sh)44 echo ${#arr…

大数据Spark--入门

文章目录 Spark 概述Spark 是什么Spark and HadoopSpark and HadoopSpark 核心模块 Spark 简单上手创建Maven项目增加 Scala 插件增加依赖关系WordCount异常处理 Spark 概述 Spark 所需资料 链接&#xff1a;https://pan.baidu.com/s/12iaW68vriL6i-xI1kmr0_g?pwdm4zc 提取码…

使能 Linux 内核自带的 FlexCAN 驱动

一. 简介 前面一篇文章学习了 ALPHA开发板修改CAN的设备树节点信息&#xff0c;并加载测试过设备树文件&#xff0c;文件如下&#xff1a; ALPHA开发板修改CAN的设备树节点信息-CSDN博客 本文是学习使能 IMX6ULL的 CAN驱动&#xff0c;也就是通过内核配置来实现。 二. 使能…

栅格地图路径规划:基于小龙虾优化算法(Crayfsh optimization algorithm,COA)的机器人路径规划(提供MATLAB代码)

一、机器人路径规划介绍 移动机器人&#xff08;Mobile robot&#xff0c;MR&#xff09;的路径规划是 移动机器人研究的重要分支之&#xff0c;是对其进行控制的基础。根据环境信息的已知程度不同&#xff0c;路径规划分为基于环境信息已知的全局路径规划和基于环境信息未知或…