XingPiaoLiang's

Back

Kubernetes 遨游#

Kubernetes 名字源于希腊语,大意为「舵手」或者「飞行员」。Kubernetes 要做的事情就是:为使用者提供一个可弹性运行的分布式框架,满足各种扩展要求、故障转移、提供部署模式等等,Kubenetes 可以很好的管理系统的 Canary 部署。

  • 服务发现和负载均衡
  • **存储编排:**自动挂载存储系统,本地存储、公共云提供商等等
  • 自动部署和回滚
  • 自我修复:自动重新启动失败的容器、替换容器和异常容器

容器化部署历史背景#

image-20250619140035942

传统部署时代:在物理服务器上运行应用程序存在很重要的资源分配问题。如果同一台物理服务器上运行多个应用程序,可能出现多个应用程序中单个占用大部分资源,而导致其他的程序性能显著下降。因此而生的解决办法就是:将每个应用程序都部署在不同的物理服务器上。显然,维护多个物理服务器的成本也是很高的。

虚拟化部署时代:因此虚拟化部署油然而生了,虚拟化技术将会允许我们在单个物理服务器上的 CPU 中运行多台虚拟机(VM)各个应用程序被部署在不同的虚拟机中,而虚拟化技术能够使得不同的 VM 在同一 CPU 彼此隔离。这样能够更好地利用物理服务器的资源,可以更加轻松地添加或者更新应用程序。通过虚拟化,我们可以将物理资源呈现为可丢弃的虚拟机集群

容器部署时代:「容器」简单来说就是拥有更加宽松的隔离特性,更加轻量级的 VM,容器之间可以共享操作系统。与 VM 相同,容器都具有自己的文件系统、CPU、内存、进程空间等等。

Kubernetes 组件#

Kubernetes 集群需要正常运行,须有多个重要的组件(Components)共同组成:

Kubernetes 的组件

控制平面 Control Pane#

整个集群,都是由一个控制平面和一个及以上工作节点共同组成的。

Node 组件#

用于运行容器化应用的工作机器, 这些工作机器称作节点(Node)。每个集群至少需要一个工作节点来运行 Pod 。

插件 Addons#

使用插件可以很好的 扩展 Kubernetes 的功能,重要的插件包括:

Kubernetes 整体架构#

工作节点托管着组成应用负载的 Pod(表示集群上一组正在运行的容器)。控制平面管理集群中的工作节点和 Pod。 在生产环境中,控制平面通常跨多台计算机运行,而一个集群通常运行多个节点,以提供容错和高可用。

控制平面(kube-apiserver、etcd、kube-controller-manager、kube-scheduler)和多个节点。每个节点运行 kubelet 和 kube-proxy。

控制平面组件#

控制平面组件,会为集群做出全局决策,习惯命名为 xxx-control-pane,相当于是整个集群的「大脑」,检测以及响应集群的各种事件,当 Deployment 的配置发生改变时,停止旧 pod 启动新 pod 的行为由其做出。

kube-apiserver#

kube-apiserver 称作 API 服务器,API 服务器是整个控制平面的前端,负责公开 Kubernetes 的 API,接收请求,分发请求。

etcd#

角色是 Kubernets 所有集群数据的后台数据库,高可用的键值存储数据库。

kube-scheduler#

在控制平面中负责监视新创建的、未指定运行的节点的 pods,并对 pod 运行做出调度,选择应该在哪些节点上运行 pod。

Node 节点组件#

节点组件在每一个 Node 上运行,负责维护运行时的 Pod,并对其提供 Kubernetes 运行时环境(Runtime)

kubelet#

kubelet 组件会在集群中的每一个 node 中运行,它保证了容器都正确运行在 Pod 中。它基于 PodSpec(一个描述 Pod 的 YAML 或者 JSON 对象)。kubelet 接收 PodSpec 并根据 PodSpec 中详细描述信息,确保目标容器处于运行状态并且状态健康,当然了,他并不管理不用 Kubenetes 管理的容器。

kubelet 接收 PodSpec 的方法有很多:

  • 主要通过 apiserver API 服务器发送的 manifest(容器清单)
  • File:利用命令行参数传递路径,它将会周期性的检测该路径下的文件是否有更新
  • HTTP endpoint:利用命令行参数指定 HTTP 端点传输

kube-proxy

kube-proxy 作为集群中每个 node 上运行的网络代理。

Kubernetes 网络代理在每个节点上运行。网络代理反映了每个节点上 Kubernetes API 中定义的服务,并且可以执行简单的 TCP、UDP 和 SCTP 流转发,或者在一组后端进行 循环 TCP、UDP 和 SCTP 转发。 当前可通过 Docker-links-compatible 环境变量找到服务集群 IP 和端口, 这些环境变量指定了服务代理打开的端口。 有一个可选的插件,可以为这些集群 IP 提供集群 DNS。 用户必须使用 apiserver API 创建服务才能配置代理。

Node#

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

通常集群中会有若干个节点;而在一个学习所用或者资源受限的环境中,集群中也可能只有一个节点。

Kubernetes 中的容器#

Kubernetes 集群中的每个Node 都会运行容器, 这些容器构成分配给该节点的 Pod。 单个 Pod 中的容器会在共同调度下,于同一位置运行在相同的节点上

镜像#

容器镜像标准定义如下:

容器镜像(Image)所承载的是封装了应用程序及其所有软件依赖的二进制数据。 容器镜像是可执行的软件包,可以单独运行;该软件包对所处的运行时环境具有明确定义的运行时环境假定。

在 Kubernetes 中使用镜像,Pod 是一组正在运行着的容器的集合,显然镜像主要的活跃场所就是在 Pod。如果我们想要在 Kubernetes 中使用或更新镜像,需要修改的就是 PodSpec。

  • 如果在配置时不指定仓库的主机名,Kubernetes 将会默认使用 Docker 公共仓库进行拉取镜像

    当然可以通过在容器进行时中配置这一默认行为,设置默认镜像仓库。

  • 镜像组成:host/name : taghost/name : digest

    • digest 摘要,使用标签我们能够辨识同一镜像序列中的不同版本,而 digest 则是镜像的唯一标识符,由哈希算法生成如 sha256:1ff6c18fbef2045af6b9c16bf034cc421a29027b800e4f9b68ae9b1cb3e9ae07 Docker 等使用 digest 来唯一标识镜像
    • 比如:docker.io/erasernoob/higress-gateway:latest erasernoob/higress-gateway:3.0
    • 如果不指定特定的 tag,那么 Kubenetes 将会默认拉取 latest
    • 镜像拉取策略IfNotPresent Always Never

工作负载 Workloads#

A workload is an application running on Kubernetes.

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

为了避免用户直接管理每一个 Pod,Kubernetes 使用负载资源替用户管理一组 Pod,这些负载资源通过配置控制器来确保 Pod 的运行状态以及正确运行的个数,与用户指定配置的状态一致。

在 Kubernetes 中存在以下内置的负载资源

  • DeploymentReplicaSet

  • StatefulSet 让你能够运行一个或者多个以某种方式跟踪应用状态的 Pod。 例如,如果你的负载会将数据作持久存储,你可以运行一个 StatefulSet,将每个 Pod 与某个 PersistentVolume 对应起来。你在 StatefulSet 中各个 Pod 内运行的代码可以将数据复制到同一 StatefulSet 中的其它 Pod 中以提高整体的服务可靠性。

  • DaemonSet 定义提供节点本地支撑设施的 Pod。这些 Pod 可能对于你的集群的运维是 非常重要的,例如作为网络链接的辅助工具或者作为网络 插件 的一部分等等。每次你向集群中添加一个新节点时,如果该节点与某 DaemonSet 的规约匹配,则控制平面会为该 DaemonSet 调度一个 Pod 到该新节点上运行。

  • JobCronJob。 定义一些一直运行到结束并停止的任务。 你可以使用 Job 来定义只需要执行一次并且执行后即视为完成的任务。你可以使用 CronJob 来根据某个排期表来多次运行同一个 Job。

同时,还可以使用定制资源定义(CRD)已添加第三方工作负载资源。

Pod#

Pod 是 Kubernetes 中创建和管理的、最小的可部署的计算单元。

Pod 就像是豌豆荚,里面的一个个豌豆就是容器,这些容器共享存储、网络以及一些预先定义好的运行这些容器的规约。Pod 中的内容总是在共享的上下文中进行,相当于是一个「逻辑主机」,包含多个应用容器。

注:若要运行 Pod 则需要提前在每个节点中安装好 Container Runtime

使用 Pod#

Pod Spec YAML 文件,在使用 Pod 的过程中是必不可少的,下面是一个简单的 Pod Spec 定义,包括了元数据和容器规范:

apiVersion: v1         # API 版本,Pod 使用的是 v1
kind: Pod              # 资源类型是 Pod
metadata:              # 元数据部分
  name: nginx          # Pod 的名字叫 nginx
spec:                  # Pod 的规范部分(Pod Spec)
  containers:          # 容器列表(Pod 可以有多个容器)
  - name: nginx        # 容器名称
    image: nginx:1.14.2  # 使用的镜像是 nginx 1.14.2
    ports:             # 容器暴露的端口
    - containerPort: 88
yaml

通过运行以下命令,Pod 就创建成功了:

kubectl apply -f https://k8s.io/examples/pods/simple-pod.yaml(yaml location)
bash

通过 kubectl get pods 命令查看当前的命名空间下的所有 Pods 状态(同时可以使用 -f 参数对状态进行追踪)

erasernoob@LAPTOP-NHH2LRV8:~/project/rk8s$ ktl get pods -n higress-system
NAME                                          READY   STATUS    RESTARTS      AGE
higress-console-85db5bfcc8-pnhqx              1/1     Running   2 (40h ago)   2d10h
higress-console-grafana-57f45598c7-drkw8      1/1     Running   2 (40h ago)   2d10h
higress-console-loki-699644ddff-zlfpm         1/1     Running   2 (40h ago)   2d10h
higress-console-prometheus-7c84669775-g6s49   1/1     Running   2 (40h ago)   2d10h
higress-controller-75bf975b57-qnqz9           2/2     Running   4 (40h ago)   2d10h
higress-gateway-5cb8d798b9-jrfww              1/1     Running   0             24h
redis-stack-server-0                          1/1     Running   2 (40h ago)   2d10h
bash

使用 WorkLoad Resource 来管理 Pod#

通常我们并不需要直接一个一个的创建 Pod,或者是单实例(Singleton)的 Pod,我们使用 Workload Resource 来创建和管理一组 Pod。因为 Pod 被设计成了相对临时性的、用后即抛的一次性实体,同时重启 Pod重启 Container也不应该被混淆,Pod 不是进程而是容器运行的环境。

资源的控制器能够处理副本的管理、上线,并在 Pod 失效时提供自愈能力。 例如,如果一个节点失败,控制器注意到该节点上的 Pod 已经停止工作, 就可以创建替换性的 Pod。调度器会将替身 Pod 调度到一个健康的节点执行。

  • 使用 Deployments Manager 管理一组 Pod:

    kubectl get deployments -n higress-system 命令得到当前命名空间下的所有 Deployments

    erasernoob@LAPTOP-NHH2LRV8:~/project/rk8s$ ktl get deployments -n higress-system
    NAME                         READY   UP-TO-DATE   AVAILABLE   AGE
    higress-console              1/1     1            1           2d10h
    higress-console-grafana      1/1     1            1           2d10h
    higress-console-loki         1/1     1            1           2d10h
    higress-console-prometheus   1/1     1            1           2d10h
    higress-controller           1/1     1            1           2d10h
    higress-gateway              1/1     1            1           2d10h
    bash

    以下是一个创建了一个 ReplicaSet 同时带有三个 nginx Pods 的 deployments spec 示例:

    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 # docker image
            ports:
            - containerPort: 80
    
    yaml
    1. 创建 一个新的 deployment
    kubectl apply -f https://k8s.io/examples/controllers/nginx-deployment.yaml
    bash
    1. 查看当前 deployment 状态
    kubectl get deployments
    bash
    1. 查看当前回滚状态
    kubectl rollout status deployment/nginx-deployment
    bash
    1. 查看当前的 Replicaset(rs)
    kubectl get rs
    bash

    输出大概如下:

    NAME                          DESIRED   CURRENT   READY   AGE
    nginx-deployment-75675f5897   3         3         3       18s
    bash
    1. 更新 Pods 中的容器镜像
    kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.16.1
    
    kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1
    bash
    1. 直接修改整个 deployment spec
    kubectl edit deployment/nginx-deployment
    bash
    1. 查看当前 deployment 的整个状态信息
    kubectl describe deployments
    bash
    1. 回滚
    kubectl rollout status deployment/higress-gateway # check the rollout status
    kubectl rollout restart # 触发重新部署
    bash

命令合集#

创建新集群#

首先我们需要一个 cluster.conf 文件:

# cluster.conf
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
# networking:
  # WARNING: It is _strongly_ recommended that you keep this the default
  # (127.0.0.1) for security reasons. However it is possible to change this.
  # apiServerAddress: "0.0.0.0"
  # By default the API server listens on a random open port.
  # You may choose a specific port but probably don't need to in most cases.
  # Using a random port makes it easier to spin up multiple clusters.
  # apiServerPort: 6443
nodes:
- role: control-plane
  kubeadmConfigPatches:
  - |
    kind: InitConfiguration
    nodeRegistration:
      kubeletExtraArgs:
        node-labels: "ingress-ready=true"
  extraPortMappings:
  - containerPort: 80
    hostPort: 80
    protocol: TCP
  - containerPort: 443
    hostPort: 443
    protocol: TCP
                                   
yml

上述文件,指定了节点的角色 control-pane 以及 暴露了相对应的端口 443 80

使用 kind 创建集群

kind create cluster --name higress --config=cluster.conf
kubectl config use-context kind-higress
bash

查看某一 Pod 的日志

kubectl logs  higress-gateway-5cb8d798b9-jrfww -n higress-system -f
bash

将本地镜像加载到集群中#

 kind load docker-image higress-gatway:4.0 --name higress-test
plaintext

接下就可以在集群中访问到宿主机上的本地镜像了。

k8s 概念原理
https://astro-pure.js.org/blog/k8s
Author erasernoob
Published at June 19, 2025
Comment seems to stuck. Try to refresh?✨