> ## Documentation Index
> Fetch the complete documentation index at: https://docs.akria.net/llms.txt
> Use this file to discover all available pages before exploring further.

# 第8组：K8s 基础 | Kubernetes Basics

> 测试你对 Pod, Service, Deployment 等 k8s 资源的理解

<a href="quiz" className="text-emerald-600 hover:underline text-sm">← 返回选单</a>

## 📝 词汇测验

export const QuizRunner = () => {
  const questions = [
    {
        "q": "'Cluster' 意为：",
        "o": [
            "单个设备",
            "集群",
            "单机",
            "断连"
        ],
        "a": "集群",
        "h": "多台服务器组成的系统。"
    },
    {
        "q": "'Node' 指：",
        "o": [
            "电线",
            "节点/服务器",
            "代码",
            "注释"
        ],
        "a": "节点/服务器",
        "h": "集群中的一台机器。"
    },
    {
        "q": "'Deployment' 意为：",
        "o": [
            "销毁",
            "部署",
            "检查",
            "购买"
        ],
        "a": "部署",
        "h": "发布应用代码。"
    },
    {
        "q": "'Service' 意为：",
        "o": [
            "服务",
            "私有",
            "秘密",
            "系统"
        ],
        "a": "服务",
        "h": "K8s 中暴露网络访问的对象。"
    },
    {
        "q": "'Ingress' 指：",
        "o": [
            "出口",
            "入口/流量网关",
            "底层",
            "终端"
        ],
        "a": "入口/流量网关",
        "h": "管理外部访问的入口。"
    },
    {
        "q": "'Volume' 在存储中是：",
        "o": [
            "声音",
            "卷/存储卷",
            "空间",
            "密度"
        ],
        "a": "卷/存储卷",
        "h": "持久化数据存储。"
    },
    {
        "q": "'Namespace' 意为：",
        "o": [
            "名字",
            "命名空间/隔离区",
            "地点",
            "范围"
        ],
        "a": "命名空间/隔离区",
        "h": "资源的逻辑隔离。"
    },
    {
        "q": "'ConfigMap' 用于存储：",
        "o": [
            "密码",
            "配置信息",
            "图片",
            "日志"
        ],
        "a": "配置信息",
        "h": "非敏感配置。"
    },
    {
        "q": "'Secret' 用于存储：",
        "o": [
            "公开信息",
            "敏感信息/密码",
            "临时文件",
            "视频"
        ],
        "a": "敏感信息/密码",
        "h": "加密存储的配置。"
    },
    {
        "q": "'Manifest' 指：",
        "o": [
            "剧本",
            "清单/部署文件",
            "报告",
            "合同"
        ],
        "a": "清单/部署文件",
        "h": "YAML 描述文件。"
    }
];

  const [idx, setIdx] = React.useState(0);
  const [scr, setScr] = React.useState(0);
  const [fin, setFin] = React.useState(false);
  const [sel, setSel] = React.useState(null);
  const [ok, setOk] = React.useState(null);
  const [ready, setReady] = React.useState(false);
  const [sq, setSq] = React.useState([]);

  React.useEffect(() => {
    setReady(true);
    setSq(questions.map(q => ({ ...q, o: [...q.o].sort(() => Math.random() - 0.5) })));
  }, []);

  const onAnswer = (o) => {
    if (sel) return;
    setSel(o);
    const isOk = o === questions[idx].a;
    setOk(isOk);
    if (isOk) setScr(scr + 1);
    setTimeout(() => {
      if (idx + 1 < questions.length) {
        setIdx(idx + 1);
        setSel(null);
        setOk(null);
      } else {
        setFin(true);
      }
    }, 1500);
  };

  if (!ready) return <div className="p-10 text-center opacity-50">Loading...</div>;

  if (fin) {
    return (
      <div className="p-10 rounded-2xl bg-white dark:bg-gray-900 border text-center shadow-xl">
        <div className="text-2xl font-bold text-emerald-600 mb-4">测试完成！</div>
        <div className="text-lg mb-8">得分: {scr} / {questions.length}</div>
        <div className="flex gap-4 justify-center">
            <button className="bg-emerald-600 hover:bg-emerald-700 text-white px-8 py-3 rounded-lg font-bold transition-all" onClick={() => {setIdx(0);setScr(0);setFin(false);setSel(null);setOk(null);}}>重新开始</button>
            <a href="quiz" className="bg-gray-100 hover:bg-gray-200 text-gray-700 px-8 py-3 rounded-lg font-bold transition-all no-underline">返回选单</a>
        </div>
      </div>
    );
  }

  const curr = sq[idx];
  if (!curr) return null;

  return (
    <div className="p-6 rounded-2xl bg-white dark:bg-gray-900 border shadow-lg">
      <div className="mb-4 text-xs opacity-50 font-mono text-right">进度: {idx + 1} / {questions.length}</div>
      
      <div className="h-1 bg-gray-100 rounded-full mb-6 overflow-hidden">
        <div className="h-full bg-emerald-500 transition-all duration-300" style={{width: ((idx + 1) / questions.length * 100) + '%'}}></div>
      </div>

      <div className="text-xl font-bold mb-8 text-gray-900 dark:text-gray-100">{curr.q}</div>
      
      <div className="space-y-3">
        {curr.o.map((o, i) => (
          <button 
            key={i} 
            className={"w-full text-left p-4 rounded-xl border-2 transition-all font-medium " + (sel === o ? (ok ? "bg-emerald-50 dark:bg-emerald-900/20 border-emerald-500 text-emerald-700 dark:text-emerald-400" : "bg-red-50 dark:bg-red-900/20 border-red-500 text-red-700 dark:text-red-400") : (sel && o === curr.a ? "bg-emerald-50 dark:bg-emerald-900/20 border-emerald-500 text-emerald-700 dark:text-emerald-400 opacity-80" : "bg-gray-50 dark:bg-gray-800 border-gray-100 dark:border-gray-700 hover:border-emerald-500 hover:shadow-md text-gray-700 dark:text-gray-300"))}
            onClick={() => onAnswer(o)}
          >
            {o}
          </button>
        ))}
      </div>
      
      {sel && (
        <div className={"mt-6 p-4 rounded-lg border-l-4 " + (ok ? "bg-emerald-50 dark:bg-emerald-900/20 border-emerald-500 text-emerald-800 dark:text-emerald-300" : "bg-red-50 dark:bg-red-900/20 border-red-500 text-red-800 dark:text-red-300")}>
          <div className="font-bold flex items-center gap-2">
            {ok ? "✅ 正确!" : "❌ 错误"}
            <span className="font-normal opacity-70 text-sm ml-auto">正确答案: {curr.a}</span>
          </div>
          <div className="text-sm opacity-80 mt-2">💡 提示: {curr.h}</div>
        </div>
      )}
    </div>
  );
};

<QuizRunner />
