【云原生实战】从零构建无节点 EKS:Karpenter 极简注入与全自动算力接管指南

在传统的 EKS 架构中,我们总要先买几台 EC2 作为底座。但今天,我们将挑战最高难度的"真空启动":在一个没有任何节点的 EKS-Dev-SGB-Demo-02 集群中,直接注入 Karpenter,让它成为唯一的算力造物主。

第一阶段:打通环境"路标" (Tagging)

Karpenter 不会自动乱买机器,我们需要给它指定"地盘"。根据你截图中的网络信息,我们需要给指定的子网(Subnet)和安全组(Security Group)打上特定的标签。

  1. 给子网打标签 :找到你截图里的 subnet-070c55a...subnet-09ca880... 等子网,给它们加上标签:

    • karpenter.sh/discovery: EKS-Dev-SGB-Demo-02
  2. 给安全组打标签 :找到你截图里的集群安全组 sg-0907dbb657ed29a5c,加上同样的标签:

    • karpenter.sh/discovery: EKS-Dev-SGB-Demo-02

原理:Karpenter 启动后,会自动扫描带这个标签的网络资源,以后买的新机器都会塞进这些子网里。

第二阶段:打破死锁,拉起 Karpenter 的"大脑"

既然没有 EC2,我们就用 AWS Fargate(Serverless 容器)来跑 Karpenter 控制器。

1. 创建 Fargate Profile

我们需要告诉 EKS:"只要是部署在 karpenter 命名空间里的 Pod,统统用 Fargate 跑,不要找我要物理机。"

通过命令行执行(使用 eksctl):

复制代码
eksctl create fargateprofile \
  --cluster EKS-Dev-SGB-Demo-02 \
  --name karpenter-profile \
  --namespace karpenter

2. 准备 IAM 权限 (IRSA)

Karpenter 需要买机器的权限。我们需要建立 OIDC 关联,并为它创建一个 IAM 角色(这里省略复杂的 JSON 策略,直接用 eksctl 一键搞定):

复制代码
eksctl create iamserviceaccount \
  --cluster EKS-Dev-SGB-Demo-02 --name karpenter --namespace karpenter \
  --role-name "KarpenterControllerRole-SGB-Demo" \
  --attach-policy-arn "arn:aws:iam::aws:policy/AmazonEKSWorkerNodeProvisionerPolicy" \
  --role-only \
  --approve

3. Helm 安装 Karpenter

现在环境就绪,直接使用 Helm 把 Karpenter 部署到我们刚刚划定的 Fargate 空间里:

复制代码
helm upgrade --install karpenter oci://public.ecr.aws/karpenter/karpenter \
  --version 1.0.0 \
  --namespace karpenter --create-namespace \
  --set serviceAccount.annotations."eks\.amazonaws\.com/role-arn"="arn:aws:iam::YOUR_ACCOUNT_ID:role/KarpenterControllerRole-SGB-Demo" \
  --set settings.clusterName=EKS-Dev-SGB-Demo-02 \
  --wait

此时执行 kubectl get pods -n karpenter,你会看到 Karpenter 正在 Fargate 的加持下成功启动!死锁打破!

第三阶段:下发"造机法则" (NodePool & EC2NodeClass)

Karpenter 脑子虽然启动了,但还不知道你要买什么样的机器。在最新的 Karpenter API 中,我们需要下发两个核心配置。

创建一个 karpenter-rules.yaml 文件:

复制代码
---
# 1. 定义 AWS 相关的云资源参数 (EC2NodeClass)
apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
  name: default
spec:
  amiFamily: AL2023 # 使用最新的 Amazon Linux 2023
  role: "KarpenterNodeRole-SGB-Demo" # 新机器用的 IAM 角色
  subnetSelectorTerms:
    - tags:
        karpenter.sh/discovery: "EKS-Dev-SGB-Demo-02" # 认准我们刚才打标签的子网
  securityGroupSelectorTerms:
    - tags:
        karpenter.sh/discovery: "EKS-Dev-SGB-Demo-02" # 认准我们刚才打标签的安全组

---
# 2. 定义机器规格和缩容逻辑 (NodePool)
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: default
spec:
  template:
    spec:
      nodeClassRef:
        group: karpenter.k8s.aws
        kind: EC2NodeClass
        name: default
      requirements:
        - key: karpenter.sh/capacity-type
          operator: In
          values: ["spot", "on-demand"] # 优先买 Spot 实例,省钱!
        - key: kubernetes.io/arch
          operator: In
          values: ["amd64", "arm64"] # 支持按需买 x86 或 Graviton 芯片
  # 极其激进的缩容策略:机器空闲 30 秒立刻关机退款
  disruption:
    consolidationPolicy: WhenEmpty
    consolidateAfter: 30s

执行 kubectl apply -f karpenter-rules.yaml

第四阶段:见证奇迹的时刻

现在你的集群依然是 0 个 EC2 节点。让我们随便扔一个 Nginx 上去:

复制代码
kubectl create deployment nginx --image=nginx --replicas=5

发生了什么?

  1. EKS 发现有 5 个 Nginx Pod 需要运行,但没有机器,状态变为 Pending

  2. 跑在 Fargate 里的 Karpenter 瞬间捕捉到这个求救信号。

  3. 它计算出 5 个 Nginx 只需要极小的资源,于是直接调用 AWS API。

  4. 不到 45 秒钟 ,一台全新的、最便宜的 EC2(比如 t3.medium)被造了出来,加入集群,5 个 Nginx 瞬间变为 Running

  5. 当你执行 kubectl scale deployment nginx --replicas=0 时,Karpenter 发现机器空了,30 秒后自动触发 Terminate,物理机关机,停止计费。

至此,你完成了一个最高形态的 EKS 架构演进:无极弹性,0 资源闲置。


现在要求起一批gpu需求的pod,而且不要让其他pod调用到这批机器上。

核心逻辑:给 GPU 机器装上"专用锁"

我们要创建一个专门针对 GPU 的 NodePool。这个配置包含两个核心要点:

  1. Taints (污点/锁):给拉起来的 GPU 机器加一把锁,默认禁止任何人进入。

  2. Requirements (规格):限定 Karpenter 只能去买带显卡的机器(如 G5, P4 家族)。

1. 编写 GPU 专属 NodePool (karpenter-gpu-pool.yaml)
复制代码
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: gpu-pool
spec:
  template:
    spec:
      # 【关键:这就是那把锁】
      # 任何被这套规则创建出来的机器,都会自带这三个污点
      taints:
        - key: "nvidia.com/gpu"
          value: "true"
          effect: NoSchedule
        - key: "sku"
          value: "gpu-exclusive"
          effect: NoSchedule

      nodeClassRef:
        group: karpenter.k8s.aws
        kind: EC2NodeClass
        name: default # 复用之前的网络配置

      requirements:
        # 限定只买 GPU 机型 (G系列或P系列)
        - key: "node.kubernetes.io/instance-type"
          operator: In
          values: ["g5.2xlarge", "g5.4xlarge", "p4d.24xlarge"]
        - key: "karpenter.sh/capacity-type"
          operator: In
          values: ["on-demand"] # 训练任务通常建议用按需实例

2. 编写 GPU Pod 配置 (带着钥匙进来)

现在,如果你提交一个普通的 Nginx,它绝对不会落在这批机器上,因为 Nginx 没有"钥匙"。

你的 GPU 任务必须在 YAML 中声明:

  1. Tolerations (容忍度/钥匙):能够忍受上面的污点。

  2. NodeSelector (定向投放):明确要求去有 GPU 的机器。

GPU 任务 YAML 示例:
复制代码
apiVersion: v1
kind: Pod
metadata:
  name: gpu-training-task
spec:
  # 【钥匙 1】:必须配置容忍度,才能在带污点的机器上运行
  tolerations:
  - key: "nvidia.com/gpu"
    operator: "Equal"
    value: "true"
    effect: "NoSchedule"
  - key: "sku"
    operator: "Equal"
    value: "gpu-exclusive"
    effect: "NoSchedule"

  # 【钥匙 2】:明确要求使用显卡资源
  containers:
  - name: cuda-container
    image: nvidia/cuda:12.0-base
    resources:
      limits:
        nvidia.com/gpu: 1 # 申请 1 块显卡

3. 为什么这样配置能实现你的要求?

我们可以从两个视角来看这个自动化的过程:

场景 A:普通的 Java/前端 Pod 进来
  1. EKS 发现这些 Pod 没有任何 Tolerations

  2. Karpenter 查看 gpu-pool,发现这批机器都有"锁"(Taint)。

  3. Karpenter 判定:gpu-pool 无法服务这些普通 Pod。

  4. Karpenter 会转而使用 default 队列去买普通的 t3.medium 这种便宜机器,绝对不会浪费昂贵的 GPU 资源给普通应用。

场景 B:带 GPU 需求的训练 Pod 进来
  1. EKS 发现 Pod 申请了 nvidia.com/gpu: 1

  2. Karpenter 扫描 NodePool,发现只有 gpu-pool 能满足 GPU 需求。

  3. 虽然 gpu-pool 有锁,但这个 Pod 刚好带着匹配的"钥匙"(Tolerations)。

  4. Karpenter 瞬间调用 AWS API,拉起一台 G5 实例。


相关推荐
bush47 小时前
嵌入式linux学习记录七,中断
linux·嵌入式
RisunJan7 小时前
Linux命令-nologin(用于系统账户或需要禁止交互式登录的场景)
linux·运维
是阿建吖!7 小时前
【Linux】信号
android·linux·c语言·c++
城北徐宫7 小时前
Linux信号深度解剖:5种产生、3张表、4次切换
linux·c++·学习
倔强的石头1067 小时前
【Linux指南】Linux快捷键与系统实用技巧
linux·运维·服务器
番茄地瓜7 小时前
Linux 配置静态 IP 步骤
linux·运维·服务器
liulilittle7 小时前
论 Linux 内核态全局稳态带宽的卡尔曼估计与工程实现
linux·服务器·网络·c++·计算机网络·tcp·通信
Irissgwe8 小时前
五、应用层协议HTTP
linux·网络·网络协议·http·状态码·url
.千余8 小时前
【Linux】 传输层协议UDP:从端口号到传输机制
linux·运维·udp
囚~徒~9 小时前
轻量化的虚拟机
linux·运维·服务器