Skip to content

Kubernates

Kubernetes 集群由一个控制平面和一组用于运行容器化应用的工作机器组成, 这些工作机器称作节点(Node)。每个集群至少需要一个工作节点来运行 Pod。

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

控制平面组件

控制平面组件会为集群做出全局决策,比如资源的调度。 以及检测和响应集群事件,例如当不满足 Deployment 的 replicas 字段时,要启动心得 Pod。

控制平面组件可以在集群中的任何节点上运行。 然而,为了简单起见,安装脚本通常会在同一个计算机上启动所有控制平面组件, 并且不会在此计算机上运行用户容器。

kube-apiserver

API 服务器是 Kubernetes 控制平面的组件, 该组件负责公开了 Kubernetes API,负责处理接受请求的工作。 API 服务器是 Kubernetes 控制平面的前端。

etcd

一致且高可用的键值存储,用作 Kubernetes 所有集群数据的后台数据库。

kube-scheduler

kube-scheduler 是控制平面的组件, 负责监视新创建的、未指定运行节点(node)的 Pods, 并选择节点来让 Pod 在上面运行。

调度决策考虑的因素包括单个 Pod 及 Pods 集合的资源需求、软硬件及策略约束、亲和性及反亲和性规范、数据位置、工作负载间的干扰及最后时限。

kube-controller-manager

从逻辑上讲, 每个控制器都是一个单独的进程, 但是为了降低复杂性,它们都被编译到同一个可执行文件,并在同一个进程中运行。

控制器有许多不同类型。以下是一些例子:

  • Node 控制器:负责在节点出现故障时进行通知和响应
  • Job 控制器:监测代表一次性任务的 Job 对象,然后创建 Pod 来运行这些任务直至完成
  • EndpointSlice 控制器:填充 EndpointSlice 对象(以提供 Service 和 Pod 之间的链接)。
  • ServiceAccount 控制器:为新的命名空间创建默认的 ServiceAccount。

以上并不是一个详尽的列表。

cloud-controller-manager

一个 Kubernetes 控制平面组件, 嵌入了特定于云平台的控制逻辑。 云控制器管理器(Cloud Controller Manager)允许将你的集群连接到云提供商的 API 之上, 并将与该云平台交互的组件同与你的集群交互的组件分离开来。 cloud-controller-manager 仅运行特定于云平台的控制器。 因此如果你在自己的环境中运行 Kubernetes,或者在本地计算机中运行学习环境, 所部署的集群不包含云控制器管理器。

与 kube-controller-manager 类似,cloud-controller-manager 将若干逻辑上独立的控制回路组合到同一个可执行文件中,以同一进程的方式供你运行。 你可以对其执行水平扩容(运行不止一个副本)以提升性能或者增强容错能力。

下面的控制器都包含对云平台驱动的依赖:

  • Node 控制器:用于在节点终止响应后检查云平台以确定节点是否已被删除
  • Route 控制器:用于在底层云基础架构中设置路由
  • Service 控制器:用于创建、更新和删除云平台上的负载均衡器

节点组件

节点组件会在每个节点上运行,负责维护运行的 Pod 并提供 Kubernetes 运行时环境。

kubelet

kubelet 会在集群中每个节点(node)上运行。 它保证容器(containers)都运行在 Pod 中。

kubelet 接收一组通过各类机制提供给它的 PodSpec,确保这些 PodSpec 中描述的容器处于运行状态且健康。 kubelet 不会管理不是由 Kubernetes 创建的容器。

kube-proxy(可选)

kube-proxy 是集群中每个节点(node)上所运行的网络代理, 实现 Kubernetes 服务(Service) 概念的一部分。

kube-proxy 维护节点上的一些网络规则, 这些网络规则会允许从集群内部或外部的网络会话与 Pod 进行网络通信。

如果操作系统提供了可用的数据包过滤层,则 kube-proxy 会通过它来实现网络规则。 否则,kube-proxy 仅做流量转发。

如果你使用网络插件为 Service 实现本身的数据包转发, 并提供与 kube-proxy 等效的行为,那么你不需要在集群中的节点上运行 kube-proxy。

容器运行时

这个基础组件使 Kubernetes 能够有效运行容器。 它负责管理 Kubernetes 环境中容器的执行和生命周期。

Kubernetes 支持许多容器运行环境,例如 containerd、 CRI-O 以及 Kubernetes CRI (容器运行环境接口) 的其他任何实现。

搭建

一个可行的方案:

  • i5 7200u, 4C8GB + 500GB硬盘(物理机)
  • kvm + qemu + libvirt + debian v12.10 创建虚拟机
  • 3个虚拟机 1C1GB 1 master + 2 worker(应该可以再分出 2 个虚拟机)
  • k3s 创建 kubernetes 环境
  • 额外的!zerotier + ecs 提供远程访问 虚拟机部分复杂度会高点!可以用更简单的上手方案代替。诸如: virtualbox、Multipass...。

k3s

K3s 是轻量级的 Kubernetes。K3s 易于安装,仅需要 Kubernetes 内存的一半,所有组件都在一个小于 100 MB 的二进制文件中。

Kubernetes 是一个 10 个字母的单词,简写为 K8s。Kubernetes 的一半就是一个 5 个字母的单词,因此简写为 K3s。

sh
# quick-start 
$ curl -sfL https://get.k3s.io | sh -
# mynodetoken, master-node /var/lib/rancher/k3s/server/token
$ curl -sfL https://get.k3s.io | K3S_URL=https://<myserver>:6443 K3S_TOKEN=<mynodetoken> sh -
# 国内可以将地址替换成 https://rancher-mirror.rancher.cn/k3s/k3s-install.sh
$ curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | sh -
$ curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | K3S_URL=https://<myserver>:6443 K3S_TOKEN=<mynodetoken> sh -

Namespace

sh
# 临时切换命名空间
$ kubectl get all --namespace <namespace>
$ kubectl get all -n <namespace>
# 切换命名空间
$ kubectl config view 
$ kubectl config set-context --current --namespace <namespace>
$ kubectl config view --minify | grep namespace

Pod

Pod 是 Kubernetes(K8s)中最小的可调度和管理单元,用于运行容器化应用。一个 Pod 可以包含一个或多个容器(通常为 1 个主容器 + 可选辅助容器),这些容器共享网络、存储和计算资源。

端口转发

sh
$ kubectl port-forward <Pod> [--address 0.0.0.0] <tgt-port>:<org-port>

Deployment

Service

  • 服务发现,为 Pod 提供访问入口(IP/DNS)
  • 负载均衡,自动分发给多个 Pod
  • 解耦,客户端无需感知 Pod 的变化(扩容、重启)

类型

类型作用范围典型场景示例 YAML 片段
ClusterIP集群内部内部服务通信(默认类型)type: ClusterIP
NodePort集群外部开发测试,直接通过节点 IP 访问type: NodePort
LoadBalancer云服务商生产环境,自动创建云负载均衡器type: LoadBalancer
ExternalNameDNS 重定向将服务映射到外部域名type: ExternalName

Delete

sh
$ kubectl delete <RESOURCE> <name>
# 根据配置文件删除
$ kubectl delete -f <YAML>
# 删除 namespace, status 卡在 Terminating
$ kubectl get namespace <namespace-name> -o json > <json-file>
# 删除 `spec.finalizers` 字段
$ kubectl replace --raw "/api/v1/namespaces/<namespace-name>/finlize" -f <json-file>

查看资源

$ kubectl get <RESOURCE> -o wide

$ kubectl get all

$ kubectl get namespace
$ kubectl get ns

$ kubectl get node

$ kubectl get pod
$ kubectl get pods
$ kubectl get pd

$ kubectl get deployment
$ kubectl get deploy

$ kubectl get service
$ kubectl get svc

$ kubectl get replicaSet
$ kubectl get rs

$ kubectl get configMap
$ kubectl get cm

$ kubectl get ingress
$ kubectl get ing

$ kubectl get persistentVolume
$ kubectl get pv

$ kubectl get persistentVolumeClaim
$ kubectl get pvc

$ kubectl describe <RESOURCE> <name>
yaml
apiVersion: v1  
kind: Pod  
metadata:  
  name: nginx-pod  
  labels:  
    app: nginx  
spec:  
  initContainers:  
    - name: cp-ngx-conf  
      image: nginx:1.22.1  
      command: [ "sh", "-c", "cp -r /etc/nginx/* /mnt/" ]  
      volumeMounts:  
        - name: ngx-conf  
          mountPath: /mnt  
  containers:  
    - name: nginx  
      image: nginx:1.22.1  
      ports:  
        - containerPort: 80  
      volumeMounts:  
        - name: ngx-conf  
          mountPath: /etc/nginx  
  volumes:  
    - name: ngx-conf  
      hostPath:  
        path: /data/nginx  
        type: DirectoryOrCreate

示例 mysql

pod

yaml
# namespace
apiVersion: v1
kind: Namespace
metadata:
  name: mysql
# pod
apiVersion: v1
kind: Pod
metadata:
  namespace: mysql
  name: mysql-pod
  labels:
    app: mysql
spec:
  containers:
    - name: mysql
      image: mysql:8.0.23
      imagePullPolicy: IfNotPresent
      env:
        - name: MYSQL_ALLOW_EMPTY_PASSWORD
          value: 'yes'
      volumeMounts:  
        - name: mysql-data  
          mountPath: /var/lib/mysql
      ports:
        - containerPort: 3306
  volumes:  
    - name: mysql-data
      hostPath:  
        path: /data/mysql  
        type: DirectoryOrCreate

deployment

yaml
# namespace
apiVersion: v1
kind: Namespace
metadata:
  name: mysql

# deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql-deploy
  namespace: mysql
  labels:
    app: mysql
spec:
  replicas: 1
  strategy:
    type: "Recreate"
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - name: mysql
          image: mysql:8.0.23
          imagePullPolicy: IfNotPresent
          env:
            - name: MYSQL_ALLOW_EMPTY_PASSWORD
              value: 'yes'
          volumeMounts:  
            - name: mysql-data  
              mountPath: /var/lib/mysql
          ports:
            - containerPort: 3306
      volumes:  
        - name: mysql-data
          hostPath:  
            path: /data/mysql  
            type: DirectoryOrCreate

persistentVolume、persistentVolumeClaim

storageClassName

  • local-path:动态分配(无需手动创建 PV)。可容忍数据丢失(当 Pod 调度到其他节点)
  • local-storage:静态分配(手动创建 PV 并管理)。数据绑定到节点

accessModes

访问模式描述适用场景
ReadWriteOnce (RWO)卷可以被 单个节点 以读写方式挂载- 单 Pod 独占读写
- 例如:MySQL、PostgreSQL
ReadOnlyMany (ROX)卷可以被 多个节点 以只读方式挂载- 多 Pod 共享只读数据
- 例如:配置文件、静态资源
ReadWriteMany (RWX)卷可以被 多个节点 以读写方式挂载- 多 Pod 共享读写
- 例如:NFS、CephFS

configMap

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

yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql-conf
  namespace: mysql
data:
  MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'

pv

yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: my-pv
spec:
  capacity:
    storage: 2Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: local-storage
  local:
    path: /path/to/storage
  nodeAffinity:
    required:
      nodeSelectorTerms:
        - matchExpressions:
            - key: kubernetes.io/hostname
              operator: In
              values:
                - worker-0

pvc

yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
  namespace: mysql
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: local-storage
  resources:
    requests:
      storage: 2Gi
  volumeName: my-pv

deployment

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql-deploy
  namespace: mysql
  labels:
    app: mysql
spec:
  replicas: 1
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - name: mysql
          image: mysql:8.0.23
          imagePullPolicy: IfNotPresent
          envFrom:  
            - configMapRef:  
                name: mysql-conf
          ports:
            - containerPort: 3306
          volumeMounts:
            - name: mysql-data
              mountPath: /var/lib/mysql
      volumes:
        - name: mysql-data
          persistentVolumeClaim:
            claimName: my-pvc

hostPath.type

取值行为
‌""空字符串(默认)用于向后兼容,这意味着在安装 hostPath 卷之前不会执行任何检查。
DirectoryOrCreate如果在给定路径上什么都不存在,那么将根据需要创建空目录,权限设置为 0755,具有与 kubelet 相同的组和属主信息。
Directory在给定路径上必须存在的目录。
FileOrCreate如果在给定路径上什么都不存在,那么将在那里根据需要创建空文件,权限设置为 0644,具有与 kubelet 相同的组和所有权。
File在给定路径上必须存在的文件。
Socket在给定路径上必须存在的 UNIX 套接字。
CharDevice(仅 Linux 节点) 在给定路径上必须存在的字符设备。
BlockDevice(仅 Linux 节点) 在给定路径上必须存在的块设备。

emptyDir

对于定义了 emptyDir 卷的 Pod,在 Pod 被指派到某节点时此卷会被创建。 就像其名称所表示的那样,emptyDir 卷最初是空的。尽管 Pod 中的容器挂载 emptyDir 卷的路径可能相同也可能不同,但这些容器都可以读写 emptyDir 卷中相同的文件。 当 Pod 因为某些原因被从节点上删除时,emptyDir 卷中的数据也会被永久删除。

image.pullPolicy

拉取 OCI 对象的策略。可能的值为:AlwaysNever 或 IfNotPresent。 如果指定了 :latest 标记,则默认为 Always,否则默认为 IfNotPresent

取值行为
Alwayskubelet 始终尝试拉取此引用。如果拉取失败,kubelet 会将 Pod 设置为 Failed
Neverkubelet 从不拉取此引用,仅使用本地镜像或工件。 如果本地没有任何镜像层存在,或者该镜像的清单未被缓存,则 Pod 会变为 Failed
IfNotPresent如果引用在磁盘上不存在,kubelet 会进行拉取。 如果引用不存在且拉取失败,则 Pod 会变为 Failed

helm

无法连接到集群

sh
# KUBECONFIG 正确指向 K3s 的配置文件
$ export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
# KUBECONFIG 正确指向 minikube 的配置文件
$ export KUBECONFIG=~/.kube/config

mysql-pod.yaml

yaml
apiVersion: v1
kind: Namespace
metadata:
  name: mysql

apiVersion: v1
kind: Pod
metadata:
  namespace: mysql
  name: mysql-pod
  labels:
    app: mysql
spec:
  containers:
    - name: mysql
      image: mysql:8.0.23
      imagePullPolicy: IfNotPresent
      env:
        - name: MYSQL_ALLOW_EMPTY_PASSWORD
          value: 'yes'
      ports:
        - containerPort: 3306

Ref

https://docs.k3s.io/zh/

https://kubernetes.io/zh-cn/docs/home/

https://geekhour.net/2023/12/23/kubernetes/

yaml

https://bgithub.xyz/gzyunke/test-k8s/tree/main/yaml

multiPass

https://canonical.com/multipass

https://www.cnblogs.com/satire/p/15681820.html