k8s

K8S 基础使用

Posted by Run-dream Blog on March 13, 2024

先从使用者的角度来学习下k8s的基本概念。

环境

kubenetes 环境已经由SA搭建好了,我们只要使用和部署。

  • 安装 kubectl 参考 https://kubernetes.io/zh-cn/docs/tasks/tools/install-kubectl-linux/

  • 配置 kube config
    mkdir ~/.kube/
    cp your_config ~/.kube/config
    
  • 在 vscode 上安装 kubenetes 插件

基本概念

命名空间(Namespace)

名字空间是在多个用户之间划分集群资源的一种方法(通过资源配额)。 目前SA只给我们开了一个 namespace 的权限

参考 https://kubernetes.io/zh-cn/docs/concepts/overview/working-with-objects/namespaces/

节点(Node)

Kubernetes 通过将容器放入在节点(Node)上运行的 Pod 中来执行你的工作负载。 节点可以是一个虚拟机或者物理机器,取决于所在的集群配置。 每个节点包含运行 Pod 所需的服务。 Node 组件包括:

  • kubelet kubelet 会在集群中每个节点(node)上运行。 它保证容器(containers)都运行在 Pod 中。 kubelet 接收一组通过各类机制提供给它的 PodSpec,确保这些 PodSpec 中描述的容器处于运行状态且健康。 kubelet 不会管理不是由 Kubernetes 创建的容器。
  • kube-proxy
    kube-proxy 是集群中每个节点(node)上所运行的网络代理, 实现 Kubernetes 服务(Service) 概念的一部分。 kube-proxy 维护节点上的一些网络规则, 这些网络规则会允许从集群内部或外部的网络会话与 Pod 进行网络通信。 如果操作系统提供了可用的数据包过滤层,则 kube-proxy 会通过它来实现网络规则。 否则,kube-proxy 仅做流量转发。
  • container runtime 这个基础组件使 Kubernetes 能够有效运行容器。 它负责管理 Kubernetes 环境中容器的执行和生命周期。

参考 https://kubernetes.io/zh-cn/docs/concepts/architecture/nodes/

工作负载(workloads)

工作负载是在 Kubernetes 上运行的应用程序。 参考 https://kubernetes.io/zh-cn/docs/concepts/workloads/

Pod

在 Kubernetes 中,无论你的负载是由单个组件还是由多个一同工作的组件构成, 你都可以在一组 Pod 中运行它。 在 Kubernetes 中,Pod 代表的是集群上处于运行状态的一组 容器的集合。

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80

Pod 通常不是直接创建的,而是使用工作负载资源创建的 Init 容器是一种特殊容器,在 Pod 内的应用容器启动之前运行。Init 容器可以包括一些应用镜像中不存在的实用工具和安装脚本。 Sidecar 容器是与主应用容器在同一个 Pod 中运行的辅助容器。 这些容器通过提供额外的服务或功能(如日志记录、监控、安全性或数据同步)来增强或扩展主应用容器的功能, 而无需直接修改主应用代码。 参考 https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/

ReplicaSet

ReplicaSet 的目的是维护一组在任何时候都处于运行状态的 Pod 副本的稳定集合。 因此,它通常用来保证给定数量的、完全相同的 Pod 的可用性。 这实际上意味着,你可能永远不需要操作 ReplicaSet 对象:而是使用 Deployment,并在 spec 部分定义你的应用。

参考 https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/replicaset/

Deployment

Deployment 为 Pod 和 ReplicaSet 提供声明式的更新能力。

  • 创建
    apiVersion: apps/v1
    kind: Deployment
    metadata:
    name: nginx-deployment
    labels:
      app: nginx
    spec:
    replicas: 3
    selector:
      matchLabels:
        app: nginx
    template:
      metadata:
        labels:
          app: nginx
      spec:
        containers:
        - name: nginx
          image: nginx:1.14.2
          ports:
          - containerPort: 80
    

    使用 ``` bash kubectl apply -f https://k8s.io/examples/controllers/nginx-deployment.yaml kubectl get deployments #检查 Deployment 是否已创建 kubectl rollout status deployment/nginx-deployment #查看 Deployment 上线状态 kubectl get rs #查看 Deployment 创建的 ReplicaSet

- 更新
仅当 Deployment Pod 模板(即 .spec.template)发生改变时,例如模板的标签或容器镜像被更新, 才会触发 Deployment 上线。其他更新(如对 Deployment 执行扩缩容的操作)不会触发上线动作。
``` bash
kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.16.1
kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1
kubectl edit deployment/nginx-deployment

deployment/nginx-deployment 表明 Deployment 的名称,nginx 表明需要进行更新的容器, 而 nginx:1.16.1 则表示镜像的新版本以及它的标签。

  • 回滚
    kubectl rollout history deployment/nginx-deployment # 检查 Deployment 修订历史
    kubectl rollout history deployment/nginx-deployment --revision=2 #查看修订历史的详细信息
    kubectl rollout undo deployment/nginx-deployment #撤消当前上线并回滚到以前的修订版本
    kubectl rollout undo deployment/nginx-deployment --to-revision=2 #回滚到特定修订版本
    
  • 扩缩容
    kubectl scale deployment/nginx-deployment --replicas=10
    kubectl autoscale deployment/nginx-deployment --min=10 --max=15 --cpu-percent=80 #水平自动缩放
    

参考 https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/deployment/

StatefulSets

StatefulSet 是用来管理有状态应用的工作负载 API 对象。StatefulSet 用来管理某 Pod 集合的部署和扩缩, 并为这些 Pod 提供持久存储和持久标识符。 StatefulSet 对于需要满足以下一个或多个需求的应用程序很有价值:

  • 稳定的、唯一的网络标识符。
  • 稳定的、持久的存储。
  • 有序的、优雅的部署和扩缩。
  • 有序的、自动的滚动更新。
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  selector:
    matchLabels:
      app: nginx # 必须匹配 .spec.template.metadata.labels
  serviceName: "nginx"
  replicas: 3 # 默认值是 1
  minReadySeconds: 10 # 默认值是 0
  template:
    metadata:
      labels:
        app: nginx # 必须匹配 .spec.selector.matchLabels
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: nginx
        image: registry.k8s.io/nginx-slim:0.8
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "my-storage-class"
      resources:
        requests:
          storage: 1Gi

StatefulSet 中的每个 Pod 根据 StatefulSet 的名称和 Pod 的序号派生出它的主机名 稳定的唯一的网络标识 每个Pod对应一个PVC,PVC的名称是这样组成的:$(volumeClaimTemplates.name)-$(pod’s hostname),跟对应的Pod是一一对应的。 当Pod发生re-schedule(其实是recreate)后,它所对应的PVC所Bound的PV仍然会自动的挂载到新的Pod中。 默认的Pod管理是 OrderedReadyPod,也就是

  • 对于包含 N 个 副本的 StatefulSet,当部署 Pod 时,它们是依次创建的,顺序为 0..N-1。
  • 当删除 Pod 时,它们是逆序终止的,顺序为 N-1..0。
  • 在将扩缩操作应用到 Pod 之前,它前面的所有 Pod 必须是 Running 和 Ready 状态。
  • 在一个 Pod 终止之前,所有的继任者必须完全关闭。 参考 https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/statefulset/

DaemonSets

DaemonSet 确保全部(或者某些)节点上运行一个 Pod 的副本。 当有节点加入集群时, 也会为他们新增一个 Pod 。 当有节点从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。 DaemonSet 的一些典型用法:

  • 在每个节点上运行集群守护进程
  • 在每个节点上运行日志收集守护进程
  • 在每个节点上运行监控守护进程

参考 https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/daemonset/

Jobs

Job 会创建一个或者多个 Pod,并将继续重试 Pod 的执行,直到指定数量的 Pod 成功终止。 随着 Pod 成功结束,Job 跟踪记录成功完成的 Pod 个数。 当数量达到指定的成功个数阈值时,任务(即 Job)结束。 删除 Job 的操作会清除所创建的全部 Pod。 挂起 Job 的操作会删除 Job 的所有活跃 Pod,直到 Job 被再次恢复执行。 适合以 Job 形式来运行的任务主要有三种:

  • 非并行 Job
  • 具有确定完成计数的并行 Job
  • 带工作队列的并行 Job

参考 https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/job/

CronJobs

CronJob 创建基于时隔重复调度的 Job。

CronJob 用于执行排期操作,例如备份、生成报告等。 一个 CronJob 对象就像 Unix 系统上的 crontab(cron table)文件中的一行。 它用 Cron 格式进行编写, 并周期性地在给定的调度时间执行 Job。

参考 https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/cron-jobs/

Network

集群中每一个 Pod 都会获得自己的、 独一无二的 IP 地址, 这就意味着你不需要显式地在 Pod 之间创建链接,你几乎不需要处理容器端口到主机端口之间的映射。 这将形成一个干净的、向后兼容的模型;在这个模型里,从端口分配、命名、服务发现、 负载均衡、 应用配置和迁移的角度来看,Pod 可以被视作虚拟机或者物理主机。

Kubernetes 强制要求所有网络设施都满足以下基本要求(从而排除了有意隔离网络的策略):

  • Pod 能够与所有其他节点上的 Pod 通信, 且不需要网络地址转译(NAT)
  • 节点上的代理(比如:系统守护进程、kubelet)可以和节点上的所有 Pod 通信 Kubernetes 网络解决四方面的问题:
  • 一个 Pod 中的容器之间通过本地回路(loopback)通信。
  • 集群网络在不同 Pod 之间提供通信。 1.Service API 允许你向外暴露 Pod 中运行的应用, 以支持来自于集群外部的访问。 2.Ingress 提供专门用于暴露 HTTP 应用程序、网站和 API 的额外功能。
  • Gateway API 是一个插件, 为服务网络建模提供富有表现力、可扩展和面向角色的 API 系列类别。
  • 你也可以使用 Service 来发布仅供集群内部使用的服务。

参考:https://kubernetes.io/zh-cn/docs/concepts/services-networking/

Services

Kubernetes 中 Service 是 将运行在一个或一组 Pod 上的网络应用程序公开为网络服务的方法。

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app.kubernetes.io/name: MyApp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376

应用上述清单时,系统将创建一个名为 “my-service” 的、 服务类型默认为 ClusterIP 的 Service。 该 Service 指向带有标签 app.kubernetes.io/name: MyApp 的所有 Pod 的 TCP 端口 9376。 Pod 中的端口定义是有名字的,你可以在 Service 的 targetPort 属性中引用这些名字。 在 Kubernetes API 中,Endpoints (该资源类别为复数形式)定义的是网络端点的列表,通常由 Service 引用, 以定义可以将流量发送到哪些 Pod。 Service 可用的 type 值及其行为有:

  • ClusterIP 通过集群的内部 IP 公开 Service,选择该值时 Service 只能够在集群内部访问。 这也是你没有为服务显式指定 type 时使用的默认值。 你可以使用 Ingress 或者 Gateway API 向公共互联网公开服务。
  • NodePort 通过每个节点上的 IP 和静态端口(NodePort)公开 Service。 为了让 Service 可通过节点端口访问,Kubernetes 会为 Service 配置集群 IP 地址, 相当于你请求了 type: ClusterIP 的服务。
  • LoadBalancer 使用云平台的负载均衡器向外部公开 Service。Kubernetes 不直接提供负载均衡组件; 你必须提供一个,或者将你的 Kubernetes 集群与某个云平台集成。
  • ExternalName 将服务映射到 externalName 字段的内容(例如,映射到主机名 api.foo.bar.example)。 该映射将集群的 DNS 服务器配置为返回具有该外部主机名值的 CNAME 记录。 集群不会为之创建任何类型代理。 外部 IP 如果有外部 IP 能够路由到一个或多个集群节点上,则 Kubernetes Service 可以在这些 externalIPs 上公开出去。

参考 https://kubernetes.io/zh-cn/docs/concepts/services-networking/service/

Ingress

Ingress 是对集群中服务的外部访问进行管理的 API 对象,典型的访问方式是 HTTP。 Ingress 可以提供负载均衡、SSL 终结和基于名称的虚拟托管。

参考 https://kubernetes.io/zh-cn/docs/concepts/services-networking/ingress/

Storage

容器中的文件在磁盘上是临时存放的。

参考 https://kubernetes.io/zh-cn/docs/concepts/storage/

Persistent Volumes

是集群中的一块存储,可以由管理员事先制备, 或者使用存储类(Storage Class)来动态制备。 持久卷是集群资源,就像节点也是集群资源一样。

Persistent Volume Claims

表达的是用户对存储的请求。概念上与 Pod 类似。 Pod 会耗用节点资源,而 PVC 申领会耗用 PV 资源

Storage Classes

为管理员提供了描述存储”类”的方法。

Configuration

参考 https://kubernetes.io/zh-cn/docs/concepts/configuration/

Config Maps

ConfigMap 是一种 API 对象,用来将非机密性的数据保存到键值对中。使用时, Pod 可以将其用作环境变量、命令行参数或者存储卷中的配置文件。 使用 ConfigMap 的四种方式:

  1. 在容器命令和参数内
  2. 容器的环境变量
  3. 在只读卷里面添加一个文件,让应用来读取
  4. 编写代码在 Pod 中运行,使用 Kubernetes API 来读取 ConfigMap

第四种方法意味着你必须编写代码才能读取 ConfigMap 和它的数据。然而, 由于你是直接使用 Kubernetes API,因此只要 ConfigMap 发生更改, 你的应用就能够通过订阅来获取更新,并且在这样的情况发生的时候做出反应。 通过直接进入 Kubernetes API,这个技术也可以让你能够获取到不同的名字空间里的 ConfigMap。 参考 https://kubernetes.io/zh-cn/docs/concepts/configuration/configmap/

Secrets

Secret 是一种包含少量敏感信息例如密码、令牌或密钥的对象。 这样的信息可能会被放在 Pod 规约中或者镜像中。 使用 Secret 意味着你不需要在应用程序代码中包含机密数据。 由于创建 Secret 可以独立于使用它们的 Pod, 因此在创建、查看和编辑 Pod 的工作流程中暴露 Secret(及其数据)的风险较小。 参考 https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/

Custom Resources

Helm Releases