Kubernetes 核心资源对象与应用编排基础

Kubernetes入门,不仅需要先了解以下基础概念,并需要拥有编写基础yaml的能力。

我这里先从宏观上列出来:

  1. 基础资源:Namespace、Pod、Label、Deployment、Service
  2. Pod 详情:Pod 配置、生命周期、调度、亲和性、污点容忍
  3. Pod 控制器:ReplicaSet、Deployment、DaemonSet、Job、CronJob、HPA
  4. 网络访问:Service、Ingress
  5. 存储:EmptyDir、HostPath、NFS、PV、PVC
  6. 配置和安全:ConfigMap、Secret、认证、授权、准入控制
  7. 可视化管理:Dashboard

k8s 核心资源对象与应用编排基础

    • 一、Kubernetes是什么?
    • 二、必须掌握的知识
    • 三、Kubernetes总图
    • [四、Kubernetes 的YAML文件怎么看?](#四、Kubernetes 的YAML文件怎么看?)
    • [五、NameSpace 作用](#五、NameSpace 作用)
    • [六、Pod 是最小的运行单元](#六、Pod 是最小的运行单元)
    • [七、Label 与 Selector 匹配规则](#七、Label 与 Selector 匹配规则)
    • [八、Deployment 管理无状态应用的核心对象](#八、Deployment 管理无状态应用的核心对象)
    • [九、Service 对外来访问提供一个核心入口](#九、Service 对外来访问提供一个核心入口)
    • [十、Ingress 与 Gateway API 外部集群访问入口](#十、Ingress 与 Gateway API 外部集群访问入口)
    • [十一、ConfigMap 与 Secret:配置不要写死在镜像里:](#十一、ConfigMap 与 Secret:配置不要写死在镜像里:)
    • [十二、Pod 探针](#十二、Pod 探针)
    • 十三、resources:requests与limits
    • [十四、Pod 的声明周期与常见错误](#十四、Pod 的声明周期与常见错误)
    • [十五、调度 Pod 会被安放到那个节点上。](#十五、调度 Pod 会被安放到那个节点上。)
    • 十六、控制器
    • 十七、存储
    • 十八、RBAC

一、Kubernetes是什么?

他是一套,可以自动化部署、管理、扩缩容、自愈恢复应用的平台。

在我看来,k8s的核心思想就是声明 ,通过 yaml 声明状态,然后系统会尽量让 实际状态 向着 声明状态 靠近。

二、必须掌握的知识

就是我在文章开头,就有专门提到的哪些。

三、Kubernetes总图

Kubernetes不是单体软件,而是由多个组件组成的编排系统。

整体可以被划分成 控制平面工作节点 两部分。

其中,控制平面 中,有

kube-apiserver 是k8s的通信总入口,像 kubectl 就是通过它才能控制集群;

etcd 保存整个集群的状态数据(一般通过yaml控制的,都会写道这里);

kube-scheduler 用来计算 Pod 调度位置;

controller-manager 用来控制实际情况向着期望靠近;

工作节点 ,有

kubelet 每个节点的代理,负责管理 Pod 的生命周期,通过控制 containerd 来操控 Pod;

containterd 用于容器的 拉取、运行、删除等操作;

kube-proxy 通常用来实现 service 的网络转发规则,让请求可以打到 Pod 上;

创建过程

由 kubectl 将yaml 文件转发至 apiserver,

然后将 yaml 转化成的资源对象 存进 etcd 中,

而scheduler、controller 与 kubelet 通过监听 apiserver 感知资源变化,并进行 Pod 位置计算、与调度

最终由 kubelet 操控 containerd 让现实 情况,朝着期望靠近。

外来请求访问过程

一般先达到 Ingress 上,然后转发至 service 中,

然后 kube-proxy 根据 service 中的规则匹配,

将请求打到 Pod 上。

四、Kubernetes 的YAML文件怎么看?

如下,是一个典型的yaml文件。

yaml 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: demo
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.27
          ports:
            - containerPort: 80

通常 yaml 文件的核心,是由四部分构成。

  1. apiVersion 用来声明所在组版本
  2. kind 用来声明新建的资源类型,比如 Pod、Service、Deployment 呀
  3. metadata 用来定义我是谁(元数据),比如名字、所在命名空间、该组件的标签、额外的注释等
  4. 而 spec 则来定义期望状态,希望如何被 k8s 维护,比如创建几个副本、开放哪个端口、生命周期是什么

最后,k8s 会尽量让实际状态朝着 spec 的定义靠拢。

五、NameSpace 作用

NameSpace 的作用就是给 kubernetes 进行逻辑分组。

很多时候,都是需要做到,权限划分、环境隔离的,

比如不同环境、不同项目、不同团队等;

一般命名空间可以定义成:test 用来测试、dev 用来开发、prod 用来生产等;

yaml 复制代码
apiVersion: v1
Kind: Namespace
metadata:
	name: dev

通常 namespace 只是通过为不同资源,打上一个标签字段,从而做到逻辑隔离。

他本是并不是物理隔离!

如果想要做到更强的隔离效果,需要结合RBAC进行权限控制、NetworkPolicy(类似于防火墙规则) 进行网络隔离。

六、Pod 是最小的运行单元

Pod 是 Kubernetes 里面的最小的可调度单元,

他内部可以运行多个容器,如果没有强绑定的要求,通常只会运行一个主容器,

Pod 拥有自己的 IP、生命周期、挂载卷、资源限制;

通常 Pod 的状态变化是从, pending、runing、最后或许会成为 succeed 或 faild。

但实际环境中,是不会直接创建 Pod 的,

而是通过 depolyment、Service、daemset 等进行间接创建;

因为直接创建的 Pod ,不容易管理状体、迭代、自愈等行为。

常见创建 yaml 文件:

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  namespace: demo
  labels:
    app: nginx
spec:
  containers:
    - name: nginx
      image: nginx:1.27
      ports:
        - containerPort: 80

常见操作方式:

cmd 复制代码
kubectl apply -f pod.yaml
kubectl get pod -n demo
kubectl describe pod nginx-pod -n demo
kubectl logs nginx-pod -n demo

七、Label 与 Selector 匹配规则

Label 为资源打上标签;

Selector 根据标签,对资源进行筛选

这个机制在 k8s 中很重要,因为很多对象之间通常是通过标签 进行关联的,而非名字。

比如 Deployment 通过标签管理 Pod。Service 通过 selector 找到 Pod。

打标签:

yaml 复制代码
metadata:
	labels:
		app: nginx
		env: dev
# app=nginx、env=dev 这两个标签

匹配:

yaml 复制代码
selector:
	app: nginx

八、Deployment 管理无状态应用的核心对象

deployment 通常是借助的 replicaset 的手,间接管理一组无状态 的 Pod。

进行 版本迭代、滚动、扩缩容、自愈等功能。

创建 Deployment / yaml 的操作方式:

yaml 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: demo
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.27
          ports:
            - containerPort: 80

常见的操作命令:

yaml 复制代码
kubectl apply -f deployment.yaml
kubectl get deploy -n demo
kubectl get rs -n demo
kubectl get pod -n demo
kubectl scale deploy nginx --replicas=5 -n demo
kubectl set image deployment/nginx nginx=nginx:1.28 -n demo
kubectl rollout status deployment/nginx -n demo
kubectl rollout history deployment/nginx -n demo
kubectl rollout undo deployment/nginx -n demo

九、Service 对外来访问提供一个核心入口

Pod 一经重启、扩缩容等操作,可能会导致IP发生改变,所以无法对外界提供稳定的访问入口。

Service 就是 一个暴露在一个或多个 Pod 上的网络访问方案 。把多个 Pod 的访问入口聚合在一起,提供统一的、稳定的访问集群的入口

起作用的方式:Service 通过 label 与 selector 进行筛选作用域,

并维护一个 EndpointSlice 列表用来记录Pod 的 ip,用于将访问Service的请求转发到 Pod 上。

Service,有二个最常见的类型:

ClusterIP 只允许集群内部访问,是默认类型。

NodePort 每个节点开放对外端口,允许外部的访问集群。

其余两个类型因为不太常用,这里就不展开了;

创建方式:

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
  namespace: demo
spec:
  type: ClusterIP
  selector:
    app: nginx
  ports:
    - port: 80
      targetPort: 80

常用命令:

yaml 复制代码
kubectl apply -f service.yaml
kubectl get svc -n demo
kubectl describe svc nginx-svc -n demo
kubectl get endpoints -n demo

十、Ingress 与 Gateway API 外部集群访问入口

Service 解决的是,如何访问一组 Pod;

而 Ingress 解决的是 http/https 请求的流量进入集群时,根据域名和路径,将请求分发到对应的 Service 上;

并且 Ingress 只是一种规则,具体的作用靠 Ingress Controller 实现。

Gateway API 是 Ingress 的新一代增强版。有更清晰的权限划分、更强的路由拓展能力,可以适应更复杂的流量治理场景。

yaml 文件编写:

yaml 复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-ingress
  namespace: demo
spec:
  rules:
    - host: www.metaassist.cn
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: nginx-svc
                port:
                  number: 80

十一、ConfigMap 与 Secret:配置不要写死在镜像里:

通常在运行容器的时候,

如 登录mysql、redis的账号密码、运行环境等

一些可变的配置,不应该直接写死在镜像里。

通常一些普通配置,可以写在 ConfigMap 中。

yaml 复制代码
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
  namespace: demo
data:
  APP_ENV: "dev"
  LOG_LEVEL: "debug"

使用时:

yaml 复制代码
envFrom:
  - configMapRef:
      name: app-config

而一些敏感的配置项,可以放到 secret 中。

但 secret 的信息安全保证,不是通过 base64 的编码确定的。

而是通过,权限控制、etcd 静态加密,才做到保护隐私的。

其实 ConfigMap 与 Secret 主要区别于语义和习惯。

ConfigMap 多用于普通配置。

Secret 多用于敏感信息配置。

十二、Pod 探针

生产环境中,常遇到主进程启动了,但是他所运行的业务不一定可以用。

也就是说,虽然 Pod 进入 Running 状态了,但是并不代表,他就一定可以使用。

比如,

  • 虽然启动进程了,但是端口可能没有监听、
  • 应用启动较慢,还没准备好接收请求、
  • 甚至是数据库没连接导致启动失败,但进程未退出。
    所以 Pod 探针是监控状态,从而采取不同应对措施的。

有三类探针,分别是:

startupProbe 探针:用来判断是否成功启动,通常用于启动缓慢的Pod;

livenessProbe 探针:用来判断Pod是否还存活,用于判断异常,从而决定是否要重启;

ReadinessProbe 探针:用来判断Pod是否能接收外来访问流量,如果异常就直接从 service 名单上去除。

yaml 复制代码
spec:
  containers:
    - name: nginx
      image: nginx:1.27
      ports:
        - containerPort: 80

      livenessProbe:
        httpGet:
          path: /healthz
          port: 80
        initialDelaySeconds: 10
        periodSeconds: 5

      readinessProbe:
        httpGet:
          path: /ready
          port: 80
        initialDelaySeconds: 5
        periodSeconds: 5

十三、resources:requests与limits

requests: 声明调度时最低资源需求,比如 cpu核数与所需内存;然后调度器会根据 requests 来判断哪个 Node 可以放下该 Pod。

limits:运行时,限定 cpu核数 与 所需内存 上限;

yaml 编写方式:

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
spec:
  containers:
    - name: nginx
      image: nginx:1.27
      resources:
        requests:
          cpu: "100m"
          memory: "128Mi"
        limits:
          cpu: "500m"
          memory: "512Mi"

十四、Pod 的声明周期与常见错误

Pending:Pod 刚被创建,但是还未运行;

Running:Pod内,至少有一个容器在运行;

Succeeded:Pod 已经成功运行完毕,并且已经已把 Pod 正常退出;

Failed:Pod 运行失败,并且已退出;

Unknown:无法确定 Pod 状态;


ImagePullBackOff:镜像拉取失败

ErrImagePull:镜像拉取错误

CrashLoopBackOff:容器反复崩溃重启

CreateContainerConfigError:创建容器时,配置错误

OOMKilled:内存超限。

一般出现错误的时候,先用 describe 查询 k8s 层面的错误,从宏观上定位;

确定之后,在用 logs 对具体容器的日志进行排查。

两者不在一个层次上。

yaml 复制代码
kubectl get pod -n demo
kubectl describe pod <pod> -n demo
kubectl logs <pod> -n demo
kubectl logs <pod> -c <container> -n demo
kubectl get events -n demo

十五、调度 Pod 会被安放到那个节点上。

亲和性是 Pod 主动选择靠近、污点是 Node 节点主动排斥,容忍度是 Pod 表示可以接收 Node 的污点。

常用调度概念:

nodeSelector:最简单的节点选择

nodeAffinity:更灵活的节点亲和性

podAffinity:让 Pod 靠近某些 Pod

podAntiAffinity:让 Pod 避开某些 Pod

taint:节点打污点,拒绝普通 Pod

toleration:Pod 声明可以容忍某些污点

以 Deployment 为例的 yaml 文件:

yaml 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ai-demo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ai-demo
  template:
    metadata:
      labels:
        app: ai-demo
    spec:
    		# Pod 主动去靠近 带有 gpu=true 标签的节点
      nodeSelector: 
        gpu: "true"
			# 可以容忍 dedicated=gpu 节点上的,NoSchedule 的污点
      tolerations:
        - key: "dedicated"
          operator: "Equal"
          value: "gpu"
          effect: "NoSchedule"

      containers:
        - name: ai-demo
          image: nginx:1.27

污点常见的几个效果:

NoSchedule:不允许新的普通 Pod 调度到这个节点;

PreferNoSchedule:尽量不允许,但不是绝对禁止;

NoExecute:不但不允许新的 Pod 进行调度,而且还会对旧的进行驱逐。

十六、控制器

ReplicaSet:保证Pod的副本数,一般不直接创建,而是由 Deployment 进行控制;

DaemonSet:对每个节点都创建固定容器;

Job:一次性任务清单,并会确保把清单内的所有 Pod 创建完毕。创建失败则会按照策略重试;

CronJob:定时任务;

HPA:自动扩缩容;

十七、存储

emptyDir :一个临时目录,Pod创建时产生、Pod销毁时同步销毁;
HostPath :将宿主机的目录进行挂载到Pod中;
NFS :多个Pod可以共享的,远程存储方式;
PV/PVC

PV 是 Kubernetes 中抽象出来的持久化存储资源;

PVC 是用户对存储资源的申请。

Pod 不直接关心底层是 NFS、Ceph 还是云盘,而是通过 PVC 来申请和挂载存储。

最典型是 PVC + Pod 挂载:

yaml 复制代码
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: app-pvc
  namespace: demo
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

意思是:

我申请一块 1Gi 的持久化存储。

Pod 使用这个 PVC:

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  namespace: demo
spec:
  containers:
    - name: nginx
      image: nginx:1.27
      volumeMounts:
        - name: data
          mountPath: /usr/share/nginx/html

  volumes:
    - name: data
      persistentVolumeClaim:
        claimName: app-pvc

意思是:

把 app-pvc 申请到的存储,挂载到容器里的 /usr/share/nginx/html 目录。

十八、RBAC

RBAC 是基于角色的访问控制。

官方文档上说,Kubernetes RBAC API 包含四种对象:Role、ClusterRole、RoleBinding、ClusterRoleBinding。

你要记住:

Role:命名空间级权限

ClusterRole:集群级权限

RoleBinding:把 Role 或 ClusterRole 绑定给用户 / ServiceAccount

ClusterRoleBinding:在集群级别绑定 ClusterRole

ServiceAccount:Pod 访问 apiserver 时使用的身份

相关推荐
LZZ and MYY1 小时前
将Virtual PLCnext 部署在PVE的LXC容器
云原生·容器·kubernetes
姚不倒11 小时前
Go语言进阶:接口、错误处理与并发编程(goroutine/channel/context)
云原生·golang
仙柒41514 小时前
Docker存储原理
运维·docker·容器
快乐的哈士奇17 小时前
LangFuse 自托管实战:选型理由、Docker 部署与常用配置全解析
运维·人工智能·docker·容器
weixin_4492900119 小时前
Docker + MySQL 在 Windows 11 上的本地安装部署文档
mysql·docker·容器
Ysn071919 小时前
中文乱码:在 Docker 容器中设置中文语言环境
运维·python·docker·容器
米高梅狮子19 小时前
01.CentOS-Stream-8-packstack安装OpenStack
linux·云原生·容器·kubernetes·centos·自动化·openstack
亚空间仓鼠21 小时前
Docker容器化高可用架构部署方案(十三)
docker·容器·架构
米高梅狮子21 小时前
01.mysql的备份与恢复
运维·数据库·mysql·docker·容器·kubernetes·github