GA666666 Blog - Kubernetes
type: channel
link: https://ga666666.cn/index.php/category/K8s/
items: Kubernetes（v1.21）调度原理
items: Kubernetes（v1.21）安全
items: Kubernetes（v1.21）网络
items: Kubernetes（v1.21）配置和存储
items: Kubernetes（v1.21）工作负载
items: Kubernetes 概念

Kubernetes（v1.21）调度原理
type: item
date: 2022-12-08T02:24:00+00:00
description: 第一章：ResourceQuotas（资源配额）1.1 简介当多个用户或团队共享具有固定节点数目的集群时，人们会担心 有人使用超过其基于公平原则所分配到的资源量 。资源配额是帮助管理员解决这一问题的工具。资源配额，通过 ResourceQuota 对象来定义，对每个命名空间的资源消耗总量提供限制。 它可以 限制 命名空间中 某种类型的对象的总数目上限，也可以限制命令空间中的 Pod 可以使用的计算资源的总上限。资源配额的工作方式如下：不同的团队可以在不同的命名空间下工作，目前这是非约束性的，在未来的版本中可能会通过 ACL (Access Control List 访问控制列表) 来实现强制性约束。集群管理员可以为每个命名空间创建一个或多个 ResourceQuota 对象。当用户在命名空间下创建资源（如 Pod、Service 等）时，Kubernetes 的配额系统会跟踪集群的资源使用情况，以确保使用的资源用量不超过 ResourceQuota 中定义的硬性资源限额。如果资源创建或者更新请求违反了配额约束，那么该请求会报错（HTTP 403 FORBIDDEN）， 并在消息中给出有可能违反的约束。如果命名空间下的计算资源 （如 cpu 和 memory）的配额被启用，则用户必须为 这些资源设定请求值（request）和约束值（limit），否则配额系统将拒绝 Pod 的创建。 提示: 可使用 LimitRanger 准入控制器来为没有设置计算资源需求的 Pod 设置默认值。1.2 计算资源配额用户可以对给定命名空间下的可被请求的 计算资源 总量进行限制。资源名称描述limits.cpu所有非终止状态的 Pod，其 CPU 限额总量不能超过该值。limits.memory所有非终止状态的 Pod，其内存限额总量不能超过该值。requests.cpu所有非终止状态的 Pod，其 CPU 需求总量不能超过该值。requests.memory所有非终止状态的 Pod，其内存需求总量不能超过该值。hugepages-<size>对于所有非终止状态的 Pod，针对指定尺寸的巨页请求总数不能超过此值。cpu与 requests.cpu相同。 memory与 requests.memory相同。 示例：apiVersion: v1 kind: ResourceQuota metadata: name: mem-cpu namespace: default # 限制 default 名称空间 spec: hard: requests.cpu: "1" requests.memory: 1Gi limits.cpu: "2" limits.memory: 2Gi1.3 扩展资源的资源配额除上述资源外，在 Kubernetes 1.10 版本中，还添加了对 扩展资源 的支持。由于扩展资源不可超量分配，因此没有必要在配额中为同一扩展资源同时指定 requests 和 limits。 对于扩展资源而言，目前仅允许使用前缀为 requests. 的配额项。以 GPU 拓展资源为例，如果资源名称为 nvidia.com/gpu，并且要将命名空间中请求的 GPU 资源总数限制为 4，则可以如下定义配额：requests.nvidia.com/gpu: 4有关更多详细信息，请参阅查看和设置配额。1.4 存储资源配额用户可以对给定命名空间下的 存储资源 总量进行限制。此外，还可以根据相关的存储类（Storage Class）来限制存储资源的消耗。资源名称描述requests.storage所有 PVC，存储资源的需求总量不能超过该值。persistentvolumeclaims在该命名空间中所允许的 PVC总量。 <storage-class-name>.storageclass.storage.k8s.io/requests.storage在所有与 <storage-class-name>相关的持久卷申领中，存储请求的总和不能超过该值。 <storage-class-name>.storageclass.storage.k8s.io/persistentvolumeclaims在与 storage-class-name 相关的所有持久卷申领中，命名空间中可以存在的持久卷申领总数。 例如，如果一个操作人员针对 gold 存储类型与 bronze 存储类型设置配额， 操作人员可以定义如下配额：gold.storageclass.storage.k8s.io/requests.storage: 500Gibronze.storageclass.storage.k8s.io/requests.storage: 100Gi在 Kubernetes 1.8 版本中，本…

Kubernetes（v1.21）安全
type: item
date: 2022-12-08T02:24:00+00:00
description: 第一章：访问控制概述1.1 概述用户使用 kubectl、客户端库或构造 REST 请求来访问 Kubernetes API。 人类用户和 Kubernetes 服务账户都可以被鉴权访问 API。 当请求到达 API 时，它会经历多个阶段，如下图所示：1.2 客户端在 Kubernetes 集群中，客户端通常由两类：① User Account：一般是独立于 Kubernetes 之外的其他服务管理的用户账号。② Service Account：Kubernetes 管理的账号，用于为Pod的服务进程在访问 Kubernetes 时提供身份标识。1.3 认证、授权和准入控制api-server 是访问和管理资源对象的唯一入口。任何一个请求访问 api-server，都要经过下面的三个流程：① Authentication（认证）：身份鉴别，只有正确的账号才能通过认证。② Authorization（授权）：判断用户是否有权限对访问的资源执行特定的动作。③ Admission Control（准入控制）：用于补充授权机制以实现更加精细的访问控制功能。1.4 权限流程控制用户携带令牌或者证书给 Kubernetes 的 api-server 发送请求，要求修改集群资源。Kubernetes 开始认证。Kubernetes 认证通过之后，会查询用户的授权（有哪些权限）。用户执行操作的过程中（操作 CPU、内存、硬盘、网络……），利用准入控制来判断是否可以执行这样的操作。第二章：认证管理2.1 Kubernetes 的客户端身份认证方式Kubernetes 集群安全的关键点在于如何识别并认证客户端身份，它提供了 3 种客户端身份认证方式：① HTTP Base 认证：通过 用户名+密码 的方式进行认证。这种方式是把 用户名:密码 用 BASE64 算法进行编码后的字符串放在 HTTP 请求中的 Header 的 Authorization 域里面发送给服务端。服务端收到后进行解码，获取用户名和密码，然后进行用户身份认证的过程。② HTTP Token 认证：通过一个 Token 来识别合法用户。这种认证方式是用一个很长的难以被模仿的字符串--Token 来表明客户端身份的一种方式。每个 Token 对应一个用户名，当客户端发起 API 调用请求的时候，需要在 HTTP 的 Header 中放入 Token，API Server 接受到 Token 后会和服务器中保存的 Token 进行比对，然后进行用户身份认证的过程。③ HTTPS 证书认证：基于 CA 根证书签名的双向数字证书认证方式。这种认证方式是安全性最高的一种方式，但是同时也是操作起来最麻烦的一种方式。2.2 总结Kubernetes 允许同时配置多种认证方式，只要其中任意一种方式认证通过即可。第三章：授权管理3.1 概述授权发生在认证成功之后，通过认证就可以知道请求用户是谁，然后 Kubernetes 会根据事先定义的授权策略来决定用户是否有权限访问，这个过程就称为授权。每个发送到 API Server 的请求都带上了用户和资源的信息：比如发送请求的用户、请求的路径、请求的动作等，授权就是根据这些信息和授权策略进行比较，如果符合策略，则认为授权通过，否则会返回错误。3.2 API Server目前支持的几种授权策略AlwaysDeny：表示拒绝所有请求，一般用于测试。AlwaysAllow：允许接收所有的请求，相当于集群不需要授权流程（Kubernetes 默认的策略）。ABAC：基于属性的访问控制，表示使用用户配置的授权规则对用户请求进行匹配和控制。Webhook：通过调用外部REST服务对用户进行授权。Node：是一种专用模式，用于对 kubelet 发出的请求进行访问控制。RBAC：基于角色的访问控制（ kubeadm 安装方式下的默认选项）。证明：kubeadm 安装方式的默认授权策略cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep -i rbac3.3 RBAC3.3.1 概述RBAC（Role Based Access Control）：基于角色的访问控制，主要是在描述一件事情：给哪些对象授权了哪些权限。RBAC 模型：Kubernetes 中的 RBAC 也是基于 RBAC 模型扩展的，涉及到如下的概念：对象：User、Group、ServiceAccount。角色：代表一组定义在资源上的可操作的动作（权限）的集合。绑定：将定义好的角色和用户绑定在一起，也可以理解为分配角色。RBAC 引入了 4 个顶级资源对象：Role：角色，用于指定一组权限，限定名称空间下的权限。ClusterRole：集群角…

Kubernetes（v1.21）网络
type: item
date: 2022-12-08T02:23:00+00:00
description: 第一章：Kubernetes 网络1.1 概述Kubernetes 网络解决四个方面的问题：① 一个 Pod 中容器之间通过本地回路（loopback）通信。② 集群网络在不同 Pod 之间提供通信；换言之，Pod 和 Pod 之间能互相通信（通过 calico 网络插件实现 Pod 之间网络的扁平化；当然，Node 节点之间的通信也是通过 calico 网络插件）。③ Service 资源允许我们对外暴露 Pod 中运行的应用程序，以支持来自集群之外的访问；换言之，Service 和 Pod 之间能互相通信。④ 可以使用 Service 来发布仅供集群内部使用的服务。1.2 Kubernetes 网络架构图1.2.1 架构图1.2.2 访问流程第二章：Service2.1 概述在 Kubernetes 中，Pod 是应用程序的载体，我们可以通过 Pod 的 IP 来访问应用程序，但是 Pod 的 IP 地址不是固定的，这就意味着不方便直接采用 Pod 的 IP 对服务进行访问。为了解决这个问题，Kubernetes 提供了 Service 资源，Service 会对提供同一个服务的多个 Pod 进行聚合，并且提供一个统一的入口地址，通过访问 Service 的入口地址就能访问到后面的 Pod 服务。Service 在很多情况下只是一个概念，真正起作用的其实是 kube-proxy 服务进程，每个 Node 节点上都运行了一个 kube-proxy 的服务进程。当创建 Service 的时候会通过 API Server 向 etcd 写入创建的 Service 的信息，而 kube-proxy 会基于监听的机制发现这种 Service 的变化，然后它会将最新的 Service 信息转换为对应的访问规则（其实，就是 EndPoint，后面讲）。Service 的资源清单：apiVersion: v1 # 版本 kind: Service # 类型 metadata: # 元数据 name: # 资源名称 namespace: # 命名空间 spec: selector: # 标签选择器，用于确定当前Service代理那些Pod app: nginx type: NodePort # Service的类型，指定Service的访问方式 clusterIP: # 虚拟服务的IP地址 sessionAffinity: # session亲和性，支持ClientIP、None两个选项，默认值为None ports: # 端口信息 - port: 8080 # Service端口 protocol: TCP # 协议 targetPort : # Pod端口 nodePort: # 主机端口spec.type 的说明：ClusterIP（默认值）：通过集群的内部 IP 暴露服务，选择该值时服务只能够在集群内部访问。NodePort：通过每个节点上的 IP 和静态端口（NodePort）暴露服务。 NodePort 服务会路由到自动创建的 ClusterIP 服务。 通过请求 <节点 IP>:<节点端口>，我们可以从集群的外部访问一个 NodePort 服务。LoadBalancer：使用云提供商的负载均衡器向外部暴露服务。 外部负载均衡器可以将流量路由到自动创建的 NodePort 服务和 ClusterIP 服务上。ExternalName：通过返回 CNAME 和对应值，可以将服务映射到 externalName 字段的内容（如：foo.bar.example.com）。 无需创建任何类型代理。OSI 网络模型和 TCP/IP 协议：注意：Service 会基于 Pod 的探针机制（readinessProbe，就绪探针）完成 Pod 的自动剔除（没有就绪的 Pod）和上线工作。Service 即使是无头服务（Headless Service），其他的 Kubernetes 应用资源（如：Pod 等）不能通过 IP 访问，但是可以将 Service 名字当成域名来访问；非无头服务，更是如此了。Service 默认使用的协议是 TCP 协议，对应的是 OSI 网络模型中的第四层传输层，所以也有人称 Service 为四层网络负载均衡。selector 只有在 Service 的 spec.type 是 ClusterIP、NodePort、LoadBalancer 才有效。2.2 准备工作在使用 Service 之前，首先利用 Deployment 创建出 3 个Pod 。vi k8s-deploy.yamlapiVersion: apps/v1 kind: Deployment metadata: name: nginx-deploy…

Kubernetes（v1.21）配置和存储
type: item
date: 2022-12-08T02:23:00+00:00
description: 第一章：概述1.1 概述容器的生命周期可能很短，会被频繁的创建和销毁。那么容器在销毁的时候，保存在容器中的数据也会被清除。这种结果对用户来说，在某些情况下是不乐意看到的。为了持久化保存容器中的数据，Kubernetes 引入了 Volume 的概念。和 Docker 中的卷管理（匿名卷、具名卷、自定义挂载目录，都是挂载在本机，功能非常有限）不同的是，Kubernetes 天生就是集群，所以为了方便管理，Kubernetes 将 卷 抽取为一个对象资源，这样可以更方便的管理和存储数据。Volume 是 Pod 中能够被多个容器访问的共享目录，它被定义在 Pod 上，然后被一个 Pod 里面的多个容器挂载到具体的文件目录下，Kubernetes 通过 Volume 实现同一个 Pod 中不同容器之间的数据共享以及数据的持久化存储。Volume 的生命周期不和 Pod 中的单个容器的生命周期有关，当容器终止或者重启的时候，Volume 中的数据也不会丢失。1.2 Kubernetes 支持的 Volume 类型1.2.1 简版Kubernetes 的 Volume 支持多种类型，如下图所示：1.2.2 细分类型Kubernetes 目前支持多达 28 种数据卷类型（其中大部分特定于具体的云环境如 GCE/AWS/Azure 等）非持久性存储：emptyDirHostPath网络连接性存储：SAN：iSCSI、ScaleIO Volumes、FC (Fibre Channel)NFS：nfs，cfs分布式存储GlusterfsRBD (Ceph Block Device)CephFSPortworx VolumesQuobyte Volumes云端存储GCEPersistentDiskAWSElasticBlockStoreAzureFileAzureDiskCinder (OpenStack block storage)VsphereVolumeStorageOS自定义存储FlexVolume第二章：配置2.1 配置最佳实战云原生应用的 12 要素中，提出了配置分离。在推送到集群之前，配置文件应该存储在版本控制系统中。这将允许我们在必要的时候快速回滚配置更改，它有助于集群重新创建和恢复。使用 YAML 而不是 JSON 编写配置文件，虽然这些格式几乎可以在所有场景中互换使用，但是 YAML 往往更加用户友好。建议相关对象分组到一个文件，一个文件通常比几个文件更容易管理。请参阅 guestbook-all-in-one.yaml 文件作为此语法的示例。除非必要，否则不指定默认值（简单的最小配置会降低错误的可能性）。将对象描述放在注释中，以便更好的内省。2.2 Secret2.2.1 概述Secret 对象类型用来保存敏感信息，如：密码、OAuth2 令牌以及 SSH 密钥等。将这些信息放到 Secret 中比放在 Pod 的定义或者容器镜像中更加安全和灵活。由于创建 Secret 可以独立于使用它们的 Pod， 因此在创建、查看和编辑 Pod 的工作流程中暴露 Secret（及其数据）的风险较小。 Kubernetes 和在集群中运行的应用程序也可以对 Secret 采取额外的预防措施，如：避免将机密数据写入非易失性存储。Secret 类似于 ConfigMap 但专门用于保存机密数据。注意：Secret 和 ConfigMap 是保存在 etcd 中。2.2.2 Secret 的种类命令行：create secret --help细分类型：内置类型用法Opaque用户定义的任意数据kubernetes.io/service-account-token服务账号令牌kubernetes.io/dockercfg~/.dockercfg文件的序列化形式 kubernetes.io/dockerconfigjson~/.docker/config.json文件的序列化形式 kubernetes.io/basic-auth用于基本身份认证的凭据kubernetes.io/ssh-auth用于 SSH 身份认证的凭据kubernetes.io/tls用于 TLS 客户端或者服务器端的数据bootstrap.kubernetes.io/token启动引导令牌数据2.2.3 Pod 如何引用要使用 Secret，Pod 需要引用 Secret。 Pod 可以用三种方式之一来使用 Secret ：作为挂载到一个或多个容器上的 卷 中的文件。（volume进行挂载）作为容器的环境变量（envFrom字段引用）由 kubelet 在为 Pod 拉取镜像时使用（此时Secret是docker-registry类型的）Secret 对象的名称必须是合法的 D…

Kubernetes（v1.21）工作负载
type: item
date: 2022-12-08T02:22:00+00:00
description: 第一章：工作负载工作负载是运行的 Kubernetes 上的一个应用程序。一个应用很复杂，可能由单个组件或者多个组件共同完成。我们可以用一组 Pod 来描述一个应用，也就是一个工作负载，而 Pod 是一组容器。换言之，工作负载控制一组 Pod ，Pod 控制一组容器（如：Deployment【工作负载】部署 3 个副本的 nginx-pod ，每个 nginx-pod 里面是真正的 nginx 容器）。工作负载能让 Pod 拥有自愈能力。我们主要研究不同的工作负载如何控制 Pod 的行为。第二章：Pod2.1 什么是 Pod ？Pod 是一组（一个多多个）容器的集合（Pod 就像是豌豆荚，而容器就像是豌豆荚中的豌豆）。这些容器共享存储、网络等。实际开发中，我们一般不直接创建 Pod ，而是创建一个工作负载（如：Deployment等），让它们来创建 Pod 。Pod 的特点：① Pod 对容器有自愈能力（自我恢复能力），Pod 可以自动重启失败的容器。② Pod 自己不能恢复自己，Pod 被删除了就没有了，但是有时我们希望如果 Node 节点宕机了，这些 Pod 还可以在其他节点重新启动。③ Pod 中可以有一个容器，也可以有多个容器。④ 如果 Pod 中有多个容器协同工作（通常而言，都是有关系了），我们将提供服务的称为主容器，另外的容器称为 SideCar 。⑤ Pod 天生为其成员容器提供了两种共享资源：网络 和 存储。一个 Pod 由一个 Pause 容器设置整个 Pod 里面的所有容器的网络、名称空间等信息。2.2 Pod 的使用可以使用 Deployment 等各种工作负载的 yaml 文件创建 Pod ，也可以直接创建 Pod 。Pod 的模板如下：apiVersion: v1 kind: Pod metadata: name: "nginx-pod" # pod 的名称 namespace: default labels: app: "nginx" # 标签 spec: containers: - name: nginx # 容器的名称 image: "nginx:1.20.2" # 镜像的名称 resources: # 资源限制 limits: cpu: 200m memory: 500Mi requests: cpu: 100m memory: 200Mi env: # 环境变量 - name: hello value: world ports: # 端口 - containerPort: 80 # 容器的端口 name: nginx # 容器端口的名称 volumeMounts: # 卷挂载 - name: localtime mountPath: /etc/localtime volumes: # 卷声明，下面的这种方式相当于 Docker 的具名卷 - name: localtime hostPath: path: /usr/share/zoneinfo/Asia/Shanghai restartPolicy: Always示例：多容器协同vim k8s-multi-pod.yamlapiVersion: v1 kind: Pod metadata: name: multi-pod labels: app: multi-alpine-pod spec: containers: - name: nginx image: nginx:1.20.2 volumeMounts: # 声明卷挂载 - name: nginx-volume mountPath: /usr/share/nginx/html - name: alpine image: alpine command: - /bin/sh - -c - while true; do sleep 1 ;echo $(date "+%Y-%m-%d-%H:%M:%S") > /app/index.html ;done; volumeMounts: # 声明卷挂载 - name: nginx-volume mountPath: /app volumes: - name: nginx-volume emptyDir: {} # 相当于 Docker 中的匿名挂载，会在外部创建一个位置 restartPolicy: Alwayskubectl apply -f k8s-multi-pod.yaml温馨提示：如果想进多容器协同的 Pod 中查看指定容器，使用这样的命令：kubectl exec -it Pod的名称 -c Pod中的容器名 -- COMMAND。2.3 Pod 的初始化容器初始化容器是在 Pod 的主容器启动之前要运行的容器，主要是做一些主容器的前置工…

Kubernetes 概念
type: item
date: 2022-12-08T02:20:00+00:00
description: 第一章 Kubernetes 对象（Kubernetes Objects）1.1 什么是 Kubernetes 的对象？官网。Kubernetes 里面操作的资源实体，就是 Kubernetes 的对象，可以使用 yaml 来声明，然后让 Kubernetes 根据 yaml 的声明创建出这个对象。操作 Kubernetes 对象，无论是创建、修改还是删除，都需要使用 Kubernetes 的 API 。如：当使用 kubectl 命令行的时候，CLI 会执行必要的 Kubernetes API 调用。Kubernetes 对象指的是 Kubernetes 系统的持久化实体，所有的这些 Kubernetes 对象，就代表了当前集群中的实际情况。常规的应用中，我们将应用程序产生的数据存放在数据库中；同理，Kubernetes 将其数据以 Kubernetes 对象的形式通过 api-server 存储在 etcd 中。具体来说，这些数据（Kubernetes 对象）描述了：集群中运行了那些容器化应用程序，以及在哪个节点上运行。集群中应用程序可用的资源，如：网络、存储等。应用程序相关的策略定义，如：重启策略、升级策略和容错策略等。其他 Kubernetes 管理应用程序时所需要的信息。每一个 Kubernetes 对象都包含了两个重要字段：spec：需要由我们来提供，描述了我们对该对象所期望的 目标状态 。status：只能由 Kubernetes 系统来修改，描述了该对象在 Kubernetes 系统中的实际状态。Kubernetes 通过对应的控制器（如：Deployment 等），不断的使得实际状态趋向于我们期望的目标状态。示例：查看 Deployment 时在系统底层运行的 yamlkubectl create deployment my-nginx --image=nginx -o yamlkubectl get deployment my-nginx -o yamlapiVersion: apps/v1 kind: Deployment metadata: annotations: deployment.kubernetes.io/revision: "1" creationTimestamp: "2022-03-11T06:39:04Z" generation: 1 labels: app: my-nginx name: my-nginx namespace: default resourceVersion: "21848" uid: 0919fb61-2543-49be-a6cc-9f4d41add783 spec: # 期望的状态 progressDeadlineSeconds: 600 replicas: 1 # 副本数量 revisionHistoryLimit: 10 selector: matchLabels: app: my-nginx strategy: rollingUpdate: maxSurge: 25% maxUnavailable: 25% type: RollingUpdate template: metadata: creationTimestamp: null labels: app: my-nginx spec: containers: - image: nginx # 使用这个镜像创建容器 imagePullPolicy: Always name: nginx resources: {} terminationMessagePath: /dev/termination-log terminationMessagePolicy: File dnsPolicy: ClusterFirst restartPolicy: Always schedulerName: default-scheduler securityContext: {} terminationGracePeriodSeconds: 30 status: # 当前状态 conditions: - lastTransitionTime: "2022-03-11T06:39:04Z" lastUpdateTime: "2022-03-11T06:39:04Z" message: Deployment does not have minimum availability. reason: MinimumReplicasUnavailable status: "False" type: Available - lastTransitionTime: "2022-03-11T06:39:04Z" lastUpdateTime: "2…