Kubernetes 核心模块详细总结

Kubernetes 核心模块详细总结

系统梳理了 Kubernetes 认证授权、Dashboard 部署、动态卷供应、StatefulSet 有状态应用 四大模块,所有 YAML 代码均附有详细中文注释,可直接用于实验或生产参考。


一、认证与授权(RBAC + ServiceAccount)

1.1 ClusterRole 和 ClusterRoleBinding

yaml 复制代码
# ------------------------------------------------------------
# 1. 创建 ClusterRole:定义权限集合
# ------------------------------------------------------------
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: pod-role                     # 角色名称
rules:
- apiGroups: [""]                    # "" 表示核心 API 组
  resources: ["pods"]                # 操作资源:Pod
  verbs: ["get", "list", "watch"]    # 允许的操作:查看和监听
---
# ------------------------------------------------------------
# 2. 将 ClusterRole 绑定给用户(User)
# ------------------------------------------------------------
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: laoma-pod-role-binding        # 绑定名称
subjects:
- kind: User                          # 绑定主体类型:用户
  name: laoma                         # 用户名
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: pod-role                      # 引用的 ClusterRole 名称
  apiGroup: rbac.authorization.k8s.io
命令行快速创建
bash 复制代码
# 创建 ClusterRole
kubectl create clusterrole pod-role --verb=get,list,watch --resource=pods

# 绑定给用户 laoma(集群级别)
kubectl create clusterrolebinding laoma-pod-role --clusterrole=pod-role --user=laoma

# 验证:使用 laoma 用户身份查看 Pod
kubectl get pods --user=laoma

# 回收权限
kubectl delete clusterrolebinding laoma-pod-role
kubectl delete clusterrole pod-role

1.2 ServiceAccount(服务账户)

概念
  • ServiceAccount 是 Pod 中进程访问 API Server 的凭证。
  • 每个 Namespace 默认存在一个 default ServiceAccount,Pod 默认使用它。
  • 为 ServiceAccount 绑定角色,可使 Pod 内的进程获得相应权限。
实践:为 ServiceAccount 授予集群管理权限
yaml 复制代码
# ------------------------------------------------------------
# 1. 创建 ServiceAccount
# ------------------------------------------------------------
apiVersion: v1
kind: ServiceAccount
metadata:
  name: sa1
  namespace: auth                    # 指定命名空间
---
# ------------------------------------------------------------
# 2. 创建 ClusterRoleBinding 将 cluster-admin 绑定给 sa1
# ------------------------------------------------------------
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: auth-sa1-cluster-admin
subjects:
- kind: ServiceAccount
  name: sa1
  namespace: auth                    # 必须指定命名空间
roleRef:
  kind: ClusterRole
  name: cluster-admin                # 内置最高权限角色
  apiGroup: rbac.authorization.k8s.io
命令行操作
bash 复制代码
# 创建 ServiceAccount
kubectl create sa sa1 -n auth

# 绑定 cluster-admin 角色(格式:--serviceaccount=命名空间:SA名)
kubectl create clusterrolebinding auth-sa1-cluster-admin \
  --clusterrole=cluster-admin \
  --serviceaccount=auth:sa1

# 在 Pod 中使用该 ServiceAccount(在 Pod spec 中添加)
# serviceAccountName: sa1
ServiceAccount Token 管理
bash 复制代码
# 创建临时 Token(v1.24+,有效期默认 1 小时)
kubectl create token sa1 -n auth

# 创建永久 Token(通过 Secret 手动创建)
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Secret
metadata:
  name: sa1-secret
  namespace: auth
  annotations:
    kubernetes.io/service-account.name: sa1
type: kubernetes.io/service-account-token
EOF
# 删除 SA 后,关联的 Secret 会被自动清理
kubectl delete sa sa1 -n auth

二、Kubernetes Dashboard 部署

2.1 部署 Dashboard(v2.6.1)

bash 复制代码
# 下载官方 YAML(已替换为私有镜像)
wget -O recommended.yaml http://192.168.46.200/class/course-materials/softwares/stage03/kubernetes-dashboard-recommended-v2.6.1.yaml

# 查看并确认镜像地址
grep image: recommended.yaml

# 应用部署
kubectl apply -f recommended.yaml

2.2 授予管理员权限并获取 Token

bash 复制代码
# 将 cluster-admin 角色绑定给 Dashboard 的 ServiceAccount
kubectl create clusterrolebinding kubernetes-dashboard-cluster-admin \
  --clusterrole=cluster-admin \
  --serviceaccount=kubernetes-dashboard:kubernetes-dashboard

# 生成 Token(有效期 24 小时)
kubectl -n kubernetes-dashboard create token kubernetes-dashboard

2.3 通过 Ingress 暴露 Dashboard(可选)

yaml 复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-dashboard
  namespace: kubernetes-dashboard
  annotations:
    nginx.ingress.kubernetes.io/ssl-passthrough: "true"   # 透传 TLS
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
  ingressClassName: nginx
  rules:
  - host: dashboard.laoma.cloud
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: kubernetes-dashboard
            port:
              number: 443

2.4 登录验证

  • 浏览器访问 https://dashboard.laoma.cloud(需配置域名解析)
  • 选择 "Token" 方式,粘贴上一步生成的 Token。
  • 若使用 NodePort 方式,访问 https://<节点IP>:<NodePort>,也需使用 Token 登录。

三、动态卷供应(StorageClass)

3.1 部署 Local Path Provisioner(本地存储)

Local Path Provisioner 利用节点本地磁盘提供动态存储,适合对性能要求高、无需网络存储的场景。

yaml 复制代码
# ------------------------------------------------------------
# Local Path Provisioner 完整清单(关键部分)
# ------------------------------------------------------------
apiVersion: v1
kind: Namespace
metadata:
  name: local-path-storage
---
# 1. ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
  name: local-path-provisioner-service-account
  namespace: local-path-storage
---
# 2. RBAC 授权(Role、ClusterRole、Binding)
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: local-path-provisioner-role
rules:
- apiGroups: [""]
  resources: ["nodes", "persistentvolumeclaims", "pods"]
  verbs: ["get", "list", "watch"]
- apiGroups: [""]
  resources: ["persistentvolumes"]
  verbs: ["get", "list", "watch", "create", "patch", "update", "delete"]
---
# 3. Deployment(核心控制器)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: local-path-provisioner
  namespace: local-path-storage
spec:
  replicas: 1
  selector:
    matchLabels:
      app: local-path-provisioner
  template:
    metadata:
      labels:
        app: local-path-provisioner
    spec:
      serviceAccountName: local-path-provisioner-service-account
      containers:
      - name: local-path-provisioner
        image: hub.laoma.cloud/rancher/local-path-provisioner:v0.0.37
        command: ["local-path-provisioner", "--debug", "start", "--config", "/etc/config/config.json"]
        volumeMounts:
        - name: config-volume
          mountPath: /etc/config/
        env:
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
      volumes:
      - name: config-volume
        configMap:
          name: local-path-config
---
# 4. ConfigMap(定义本地存储路径)
apiVersion: v1
kind: ConfigMap
metadata:
  name: local-path-config
  namespace: local-path-storage
data:
  config.json: |
    {
      "nodePathMap":[
        {
          "node":"DEFAULT_PATH_FOR_NON_LISTED_NODES",
          "paths":["/opt/local-path-provisioner"]
        }
      ]
    }
---
# 5. StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: local-path
provisioner: rancher.io/local-path
volumeBindingMode: WaitForFirstConsumer   # 等待 Pod 调度再创建 PV
reclaimPolicy: Delete

部署命令

bash 复制代码
kubectl apply -f local-path-storage.yaml
kubectl get sc local-path

验证使用

yaml 复制代码
# 创建 PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: local-path-pvc
spec:
  accessModes: ["ReadWriteOnce"]
  resources:
    requests:
      storage: 5Gi
  storageClassName: local-path
---
# 创建 Deployment 挂载该 PVC(Pod 调度后 PV 才会创建)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: webapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: webapp
  template:
    metadata:
      labels:
        app: webapp
    spec:
      containers:
      - image: nginx
        name: nginx
        volumeMounts:
        - name: data
          mountPath: /usr/share/nginx/html
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: local-path-pvc

3.2 部署 NFS Provisioner(共享存储)

NFS 无内置 Provisioner,需自行部署外部控制器。

1. 部署 NFS 服务(在 10.1.8.30 上)
bash 复制代码
apt install -y nfs-kernel-server
mkdir -m 777 /shares
echo "/shares *(rw,sync,no_root_squash,no_all_squash,insecure)" >> /etc/exports
systemctl restart nfs-server
# 客户端安装 nfs-common
2. 部署 NFS Provisioner
yaml 复制代码
# ------------------------------------------------------------
# RBAC 授权
# ------------------------------------------------------------
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-client-provisioner
  namespace: kube-storage
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: nfs-client-provisioner-runner
rules:
- apiGroups: [""]
  resources: ["persistentvolumes"]
  verbs: ["get","list","watch","create","delete"]
- apiGroups: [""]
  resources: ["persistentvolumeclaims"]
  verbs: ["get","list","watch","update"]
- apiGroups: ["storage.k8s.io"]
  resources: ["storageclasses"]
  verbs: ["get","list","watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: run-nfs-client-provisioner
subjects:
- kind: ServiceAccount
  name: nfs-client-provisioner
  namespace: kube-storage
roleRef:
  kind: ClusterRole
  name: nfs-client-provisioner-runner
  apiGroup: rbac.authorization.k8s.io
---
# ------------------------------------------------------------
# NFS Provisioner Deployment
# ------------------------------------------------------------
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nfs-client-provisioner
  namespace: kube-storage
spec:
  replicas: 1
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: nfs-client-provisioner
  template:
    metadata:
      labels:
        app: nfs-client-provisioner
    spec:
      serviceAccountName: nfs-client-provisioner
      volumes:
      - name: nfs-client-root
        nfs:
          server: 10.1.8.30           # NFS 服务器 IP
          path: /shares               # 共享根目录
      containers:
      - name: nfs-client-provisioner
        image: hub.laoma.cloud/sig-storage/nfs-subdir-external-provisioner:v4.0.2
        volumeMounts:
        - name: nfs-client-root
          mountPath: /persistentvolumes
        env:
        - name: PROVISIONER_NAME
          value: fuseim.pri/ifs       # 必须与 StorageClass 的 provisioner 一致
        - name: NFS_SERVER
          value: 10.1.8.30
        - name: NFS_PATH
          value: /shares
---
# ------------------------------------------------------------
# StorageClass
# ------------------------------------------------------------
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-storage
provisioner: fuseim.pri/ifs
reclaimPolicy: Delete
allowVolumeExpansion: true
volumeBindingMode: Immediate
parameters:
  onDelete: retain                   # 删除 PVC 时保留 NFS 数据
  archiveOnDelete: "false"
验证部署
bash 复制代码
kubectl apply -f nfs-rbac.yaml
kubectl apply -f nfs-provisioner.yaml
kubectl apply -f nfs-storageclass.yaml

# 查看 StorageClass
kubectl get sc nfs-storage

# 测试:创建 PVC,绑定后写入数据
kubectl apply -f nfs-pvc.yaml
kubectl get pvc webclaim   # 状态应为 Bound

四、StatefulSet 有状态应用部署

4.1 StatefulSet 核心概念

  • 固定身份 :Pod 名称为 <statefulset-name>-<序号>(如 nginx-0)。
  • 有序操作:创建/缩容/更新均按序号顺序执行。
  • 稳定存储 :通过 volumeClaimTemplates 为每个 Pod 自动创建独立的 PVC,Pod 删除后 PVC 保留,重建后复用。
  • 需要 Headless Service :提供固定 DNS 解析(pod-name.service-name.namespace.svc.cluster.local)。

4.2 示例:部署 3 节点 Nginx 集群

Headless Service
yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: nginx
  namespace: statefulset
spec:
  clusterIP: None                     # 无头服务
  selector:
    app: nginx
  ports:
  - port: 80
    targetPort: 80
    name: nginx-port
StatefulSet
yaml 复制代码
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nginx
  namespace: statefulset
spec:
  serviceName: nginx                   # 关联 Headless Service
  replicas: 3
  minReadySeconds: 10                  # Pod 就绪后等待 10 秒才认为可用
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
          name: nginx
        volumeMounts:
        - name: nginx-data
          mountPath: /usr/share/nginx/html
  # ---------- PVC 模板 ----------
  volumeClaimTemplates:
  - metadata:
      name: nginx-data                 # 与 volumeMounts.name 一致
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "nfs-storage"  # 使用动态卷存储类
      resources:
        requests:
          storage: 10Gi
验证 Pod 顺序创建与数据持久性
bash 复制代码
# 观察 Pod 创建顺序(nginx-0 → nginx-1 → nginx-2)
kubectl get pods -w

# 为每个 Pod 写入不同数据(模拟)
kubectl exec nginx-0 -- sh -c "echo 'nginx-0' > /usr/share/nginx/html/index.html"
kubectl exec nginx-1 -- sh -c "echo 'nginx-1' > /usr/share/nginx/html/index.html"
kubectl exec nginx-2 -- sh -c "echo 'nginx-2' > /usr/share/nginx/html/index.html"

# 通过 Headless Service DNS 访问
kubectl run test --image=nginx -it -- bash
curl nginx-0.nginx    # 返回 nginx-0
curl nginx-1.nginx    # 返回 nginx-1
curl nginx-2.nginx    # 返回 nginx-2

# 删除 nginx-2,等待重建后数据依然存在
kubectl delete pod nginx-2
# 重建后再次访问 nginx-2.nginx,数据仍为 nginx-2

4.3 示例:部署 Etcd 集群(自动组网)

Headless Service
yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: etcd
  namespace: statefulset
spec:
  clusterIP: None
  selector:
    app: etcd
  ports:
  - port: 2379
    name: client
  - port: 2380
    name: peer
StatefulSet(关键环境变量配置)
yaml 复制代码
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: etcd
  namespace: statefulset
spec:
  serviceName: etcd
  replicas: 3
  selector:
    matchLabels:
      app: etcd
  template:
    metadata:
      labels:
        app: etcd
    spec:
      containers:
      - name: etcd
        image: registry.aliyuncs.com/google_containers/etcd:3.5.10-0
        command: ["/usr/local/bin/etcd"]
        ports:
        - containerPort: 2379
          name: client
        - containerPort: 2380
          name: peer
        env:
        # 1. 节点名称:来自 Pod 名称
        - name: ETCD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        # 2. 数据目录
        - name: ETCD_DATA_DIR
          value: /var/lib/etcd
        # 3. 节点间通信地址(固定 DNS)
        - name: ETCD_INITIAL_ADVERTISE_PEER_URLS
          value: "http://$(ETCD_NAME).etcd.statefulset.svc.cluster.local:2380"
        - name: ETCD_LISTEN_PEER_URLS
          value: "http://0.0.0.0:2380"
        # 4. 客户端监听地址
        - name: ETCD_LISTEN_CLIENT_URLS
          value: "http://0.0.0.0:2379"
        - name: ETCD_ADVERTISE_CLIENT_URLS
          value: "http://$(ETCD_NAME).etcd.statefulset.svc.cluster.local:2379"
        # 5. 初始集群成员列表(硬编码)
        - name: ETCD_INITIAL_CLUSTER
          value: "etcd-0=http://etcd-0.etcd.statefulset.svc.cluster.local:2380,etcd-1=http://etcd-1.etcd.statefulset.svc.cluster.local:2380,etcd-2=http://etcd-2.etcd.statefulset.svc.cluster.local:2380"
        - name: ETCD_INITIAL_CLUSTER_TOKEN
          value: "etcd-token"
        - name: ETCD_INITIAL_CLUSTER_STATE
          value: "new"
        volumeMounts:
        - name: etcd-data
          mountPath: /var/lib/etcd
  volumeClaimTemplates:
  - metadata:
      name: etcd-data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "nfs-storage"
      resources:
        requests:
          storage: 10Gi
验证集群
bash 复制代码
# 查看成员列表(应从 etcd-0 节点执行)
kubectl exec etcd-0 -- etcdctl member list
# 预期看到三个成员,状态均为 started

# 写入数据
kubectl exec etcd-0 -- etcdctl put /test/key "hello"
# 从 etcd-2 读取
kubectl exec etcd-2 -- etcdctl get /test/key   # 输出 hello

4.4 示例:部署 Redis 集群(1 主 2 从 + Sentinel)

Headless Service
yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: redis
  namespace: statefulset
spec:
  clusterIP: None
  selector:
    app: redis
  ports:
  - port: 6379
    name: redis
  - port: 26379
    name: sentinel
StatefulSet(启动脚本动态判断主从)
yaml 复制代码
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis
  namespace: statefulset
spec:
  serviceName: redis
  replicas: 3
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
      - name: redis
        image: redis:7.0-alpine
        ports:
        - containerPort: 6379
        - containerPort: 26379
        command: ["/bin/sh", "-c"]
        args:
        - |
          # 获取 Pod 序号
          NODE_ID=$(hostname | awk -F'-' '{print $2}')
          # 生成 Redis 配置
          cat > /data/redis.conf << EOF
          bind 0.0.0.0
          protected-mode no
          port 6379
          dir /data
          appendonly yes
          requirepass "redis123"
          masterauth "redis123"
          EOF
          # 非 0 节点设置为从节点
          if [ "$NODE_ID" != "0" ]; then
            echo "replicaof redis-0.redis.statefulset.svc.cluster.local 6379" >> /data/redis.conf
          fi
          # 启动 Redis
          redis-server /data/redis.conf &

          # 等待主节点域名解析成功
          until nslookup redis-0.redis.statefulset.svc.cluster.local; do
            sleep 2
          done

          # 生成 Sentinel 配置
          cat > /data/sentinel.conf << EOF
          bind 0.0.0.0
          protected-mode no
          port 26379
          sentinel resolve-hostnames yes
          sentinel announce-hostnames yes
          sentinel monitor mymaster redis-0.redis.statefulset.svc.cluster.local 6379 2
          sentinel auth-pass mymaster redis123
          sentinel down-after-milliseconds mymaster 5000
          sentinel failover-timeout mymaster 10000
          EOF
          # 启动 Sentinel
          redis-sentinel /data/sentinel.conf
        volumeMounts:
        - name: redis-data
          mountPath: /data
  volumeClaimTemplates:
  - metadata:
      name: redis-data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "nfs-storage"
      resources:
        requests:
          storage: 10Gi
验证
bash 复制代码
# 查看主从状态
kubectl exec redis-0 -- redis-cli -a redis123 info replication
# 预期 role:master,connected_slaves:2

# 查看 Sentinel 监控的主节点
kubectl exec redis-0 -- redis-cli -p 26379 sentinel master mymaster

# 故障转移测试:删除主节点
kubectl delete pod redis-0
# 等待重建后,redis-0 自动变为从节点,其他节点选举新主

五、常用运维命令速查

用途 命令
查看 StorageClass kubectl get sc
查看 PVC 绑定状态 kubectl get pvc -n <ns>
查看 StatefulSet 状态 kubectl get sts -n <ns>
查看 Pod 顺序创建日志 kubectl get pods -n <ns> -w
进入 Pod 调试 kubectl exec -it <pod> -n <ns> -- /bin/sh
删除 StatefulSet 但保留 PVC kubectl delete sts <name> -n <ns> --cascade=orphan
强制删除 Pod(模拟故障) kubectl delete pod <pod> -n <ns> --grace-period=0 --force
生成 ServiceAccount Token kubectl create token <sa> -n <ns>
创建 ClusterRoleBinding kubectl create clusterrolebinding <name> --clusterrole=<role> --serviceaccount=<ns>:<sa>

六、安全与最佳实践

  1. 敏感信息管理 :密码、Token 必须使用 Secret,禁止明文出现在 YAML 中。
  2. 资源配额 :为命名空间设置 ResourceQuotaLimitRange,防止资源抢占。
  3. 健康检查 :为所有工作负载配置 livenessProbereadinessProbestartupProbe
  4. 存储回收策略 :根据数据重要性设置 reclaimPolicy: RetainDelete
  5. 权限最小化 :仅授予 ServiceAccount 所需的最小权限,避免使用 cluster-admin

相关推荐
小林ixn2 小时前
Docker + Nginx 反向代理:从“我电脑能跑”到“哪里都能跑”
nginx·docker·容器
三言老师2 小时前
K8s集群运行时异常趋势分析预警实操
java·开发语言·kubernetes
深念Y2 小时前
Wine 运行 HiTool 踩坑记录
linux·windows·容器·桌面·wine·虚拟器
coder_lorraine2 小时前
手把手教你用 Docker Compose 部署 Twikoo 评论系统
mongodb·docker·容器
微擎应用市场2 小时前
微擎面板 W7Panel:一站式云原生管理平台,让 Kubernetes 触手可及
云原生·容器·kubernetes
张洛闻Eren2 小时前
云原生k8s【第一课】: Docker 容器技术
运维·云原生·容器·k8s
量化分析2 小时前
迁移docker部署的wordpress
运维·docker·容器
名明鸣冥2 小时前
k8s-agent架构思考(二)
容器·架构·kubernetes
三言老师2 小时前
K8s 集群 LocalPV 静态 PV 资源手动创建实操
linux·运维·服务器·kubernetes