Kubernetes核心概念与基本使用
基本概念
Kubernetes 是一个生产级别的开源平台, 可编排在计算机集群内和跨计算机集群的应用容器的部署(调度)和执行。
Kubernetes 协调一个高可用计算机集群,每个计算机互相连接之后作为同一个工作单元运行。 Kubernetes 中的抽象允许你将容器化的应用部署到集群,而无需将它们绑定到某个特定的独立计算机。 为了使用这种新的部署模型,需要以将应用与单个主机解耦的方式打包:它们需要被容器化。 与过去的那种应用直接以包的方式深度与主机集成的部署模型相比,容器化应用更灵活、更可用。 Kubernetes 以更高效的方式跨集群自动分布和调度应用容器。 Kubernetes 是一个开源平台,并且可应用于生产环境。
一个 Kubernetes 集群包含两种类型的资源:
- 控制面(Control Plane) 调度整个集群
- 节点(Nodes) 负责运行应用
Kubernetes 集群由一个控制平面和一组用于运行容器化应用的工作机器组成, 这些工作机器称作节点(Node)。每个集群至少需要一个工作节点来运行 Pod。
工作节点托管着组成应用负载的 Pod。控制平面管理集群中的工作节点和 Pod。 在生产环境中,控制平面通常跨多台计算机运行,而一个集群通常运行多个节点,以提供容错和高可用。
控制平面
有些地方又叫做Kubernetes Master,是K8s集群中的核心组件,负责集群的管理和控制。
控制平面组件会为集群做出全局决策,比如资源的调度。 以及检测和响应集群事件,例如当不满足 Deployment 的 replicas 字段时,要启动新的 Pod)。
控制平面组件可以在集群中的任何节点上运行。 然而,为了简单起见,安装脚本通常会在同一个计算机上启动所有控制平面组件, 并且不会在此计算机上运行用户容器。
包括以下组件:
etcd:一个分布式键值存储系统,用于存储集群状态。
API Server:集群的入口点,提供RESTful API接口。
Controller Manager:负责集群中各种资源的监控和自动修复。
controller manager又包括
kube-scheduler, 负责监视新创建的、未指定运行节点的 Pod, 并选择节点来让 Pod 在上面运行。从逻辑上讲, 每个controller都是一个单独的进程, 但是为了降低复杂性,它们都被编译到同一个可执行文件,并在同一个进程中运行。还包括cloud-controller-manager 嵌入了特定于云平台的控制逻辑。 云控制器管理器(Cloud Controller Manager)允许将你的集群连接到云提供商的 API 之上, 并将与该云平台交互的组件同与你的集群交互的组件分离开来。
控制器有许多不同类型。以下是一些例子:
Node 控制器:负责在节点出现故障时进行通知和响应
Job 控制器:监测代表一次性任务的 Job 对象,然后创建 Pod 来运行这些任务直至完成
EndpointSlice 控制器:填充 EndpointSlice 对象(以提供 Service 和 Pod 之间的链接)。
ServiceAccount 控制器:为新的命名空间创建默认的 ServiceAccount。
- Scheduler:负责将Pod调度到合适的节点上。
节点组件
Kubernetes Node是集群中的工作节点,负责运行Pod。每个Node节点包括以下组件:
- Kubelet:负责Pod的生命周期管理,包括Pod的创建、启动、停止和删除。
- Container Runtime:用于运行容器的环境,如Docker。
- Kube-Proxy:负责网络代理,实现Pod之间的通信。
Pod是Kubernetes中的基本部署单元,包含一个或多个容器。Pod在Kubernetes集群中负责运行应用程序。
控制平面组件会为集群做出全局决策,比如资源的调度。 以及检测和响应集群事件,例如当不满足 Deployment 的 replicas 字段时,要启动新的 Pod)。
控制平面组件可以在集群中的任何节点上运行。 然而,为了简单起见,安装脚本通常会在同一个计算机上启动所有控制平面组件, 并且不会在此计算机上运行用户容器。 请参阅使用 kubeadm 构建高可用性集群中关于跨多机器安装控制平面的示例。
节点
Kubernetes 通过将容器放入在节点(Node)上运行的 Pod 中来执行工作负载。 节点可以是一个虚拟机或者物理机器,取决于所在的集群配置。 每个节点包含运行 Pod 所需的服务; 这些节点由控制面负责管理。
通常集群中会有若干个节点;而在一个学习所用或者资源受限的环境中,你的集群中也可能只有一个节点。一个 Pod 总是运行在某个 Node(节点) 上。节点是 Kubernetes 中工作机器, 可以是虚拟机或物理计算机,具体取决于集群。每个 Node 都由控制面管理。 节点可以有多个 Pod,Kubernetes 控制面会自动处理在集群中的节点上调度 Pod。 控制面的自动调度考量了每个节点上的可用资源。
节点上的组件包括kubelet、容器运行时以及kube-proxy。
Pod
Pod 是一个或多个应用容器(例如 Docker)的组合,并且包含共享的存储(卷)、IP 地址和有关如何运行它们的信息。
Pod 是 Kubernetes 抽象出来的,表示一组一个或多个应用容器(如 Docker), 以及这些容器的一些共享资源。这些资源包括:
- 卷形式的共享存储
- 集群内唯一的 IP 地址,用于联网
- 有关每个容器如何运行的信息,例如容器镜像版本或要使用的特定端口
Pod 是可以在 Kubernetes 中创建和管理的、最小的可部署的计算单元。只有容器紧耦合并且需要共享磁盘等资源时,才应将其编排在一个 Pod 中。
Pod(就像在鲸鱼荚或者豌豆荚中)是一组(一个或多个)容器; 这些容器共享存储、网络、以及怎样运行这些容器的规约。 Pod 中的内容总是并置(colocated)的并且一同调度,在共享的上下文中运行。 Pod 所建模的是特定于应用的“逻辑主机”,其中包含一个或多个应用容器, 这些容器相对紧密地耦合在一起。 在非云环境中,在相同的物理机或虚拟机上运行的应用类似于在同一逻辑主机上运行的云应用。
除了应用容器,Pod 还可以包含在 Pod 启动期间运行的Init容器。 也可以注入临时性容器来调试正在运行的 Pod。
Pod 的共享上下文包括一组 Linux 名字空间、控制组(CGroup)和可能一些其他的隔离方面, 即用来隔离容器的技术。 在 Pod 的上下文中,每个独立的应用可能会进一步实施隔离。
Kubernetes 集群中的 Pod 主要有两种用法:
运行单个容器的 Pod。”每个 Pod 一个容器”模型是最常见的 Kubernetes 用例; 在这种情况下,可以将 Pod 看作单个容器的包装器,并且 Kubernetes 直接管理 Pod,而不是容器。
运行多个协同工作的容器的 Pod。 Pod 可以封装由紧密耦合且需要共享资源的多个并置容器组成的应用。 这些位于同一位置的容器构成一个内聚单元。
将多个并置、同管的容器组织到一个 Pod 中是一种相对高级的使用场景。 只有在一些场景中,容器之间紧密关联时你才应该使用这种模式。
容器
每个运行的容器都是可重复的; 包含依赖环境在内的标准,意味着无论你在哪里运行它都会得到相同的行为。
容器将应用程序从底层的主机设施中解耦。 这使得在不同的云或 OS 环境中部署更加容易。
Kubernetes 集群中的每个节点都会运行容器, 这些容器构成分配给该节点的Pod。 单个 Pod 中的容器会在共同调度下,于同一位置运行在相同的节点上
容器技术和虚拟机差别
Docker(容器技术) 和 虚拟机(VM) 的区别是理解现代云计算架构的基础。
虽然它们的目的都是提供隔离的环境来运行应用程序,但它们的底层架构和资源使用方式有着根本性的不同。
最大的区别在于它们如何与底层硬件和操作系统(Host OS)交互。
| 特性 | Docker 容器 (Container) | 虚拟机 (VM) |
|---|---|---|
| 隔离级别 | 进程级隔离 (共享内核) | 硬件级隔离 (完全虚拟化) |
| 操作系统 | 共享宿主机操作系统内核 | 包含完整的独立操作系统 (Guest OS) |
| 启动速度 | 极快(秒级甚至毫秒级) | 慢(需要启动整个操作系统) |
| 资源占用 | 极低(只包含应用和必需的库) | 很高(每个 VM 都要占用大量 CPU、内存和磁盘) |
| 核心组件 | Docker Engine (容器运行时) | Hypervisor (VMM, 如 VMware, VirtualBox) |
| 大小 | 几十到几百 MB | 几 GB 到几十 GB |
VM 的原理是完全虚拟化硬件。
Hypervisor (管理程序):这是一个软件层,直接运行在物理硬件或宿主操作系统之上。
完整 OS:每个虚拟机都包含一个完整的、独立的操作系统(Guest OS),包括自己的内核、驱动、系统库和应用。
硬件模拟:Hypervisor 负责模拟所有硬件(CPU、内存、网卡、磁盘),让 Guest OS 以为自己独占了硬件。
总结:VM 提供了强大的隔离性,但代价是巨大的资源开销,因为你需要同时运行两个或更多的完整操作系统
Docker 的原理是操作系统级虚拟化(或容器化)。
- 共享内核:所有容器都共享宿主机的操作系统内核。容器只是宿主机上的一个隔离进程。
- 精简文件系统:容器只打包应用程序运行时所需的文件、库和依赖项,不包含整个操作系统。
- Docker Engine:Docker 引擎负责管理容器的生命周期,并使用 Linux 内核的两个核心技术来实现隔离和资源限制:
- Namespaces (命名空间):实现进程、网络、用户等资源的隔离。
- Cgroups (控制组):实现对 CPU、内存、I/O 等资源的限制和配额。
- 总结:容器非常轻量,启动速度快,资源利用率高,但隔离性略低于 VM(如果内核存在安全漏洞,所有容器都可能受到影响)。
容器镜像
容器镜像是一个随时可以运行的软件包, 包含运行应用程序所需的一切:代码和它需要的所有运行时、应用程序和系统库,以及一些基本设置的默认值。
容器旨在设计成无状态且不可变的: 你不应更改已经运行的容器的代码。如果有一个容器化的应用程序需要修改, 正确的流程是:先构建包含更改的新镜像,再基于新构建的镜像重新运行容器。
容器运行时
这个基础组件使 Kubernetes 能够有效运行容器。 它负责管理 Kubernetes 环境中容器的执行和生命周期。
可以允许集群为一个 Pod 选择其默认的容器运行时。如果你需要在集群中使用多个容器运行时, 你可以为一个 Pod 指定 RuntimeClass, 以确保 Kubernetes 会使用特定的容器运行时来运行这些容器。
每个 Pod 内部部署什么容器,完全取决于你的应用需求,但它通常包含:
- 一个主要的业务容器(Main Container)。
- 零个或多个辅助容器(Sidecar, Init Containers)
主容器 (Main Container)
这是 Pod 的核心,它运行你的应用程序的实际业务逻辑。
- 数量: 通常是 1 个。
- 示例:
- 一个 Java Spring Boot 应用服务器。
- 一个 NGINX Web 服务器。
- 一个 Python Flask API 服务。
- 一个 Node.js 后端应用
辅助容器(尤其是 Sidecar 模式)是 Pod 设计的强大之处。它们与主容器共享网络和存储空间,但执行不同的辅助任务。
A. Sidecar 容器 (最常见)
Sidecar 容器是与主容器同时运行的辅助容器,用于增强或扩展主容器的功能,而不必修改主容器的代码。
- 数量: 0 个或多个。
- 运行时间: 与主容器的生命周期相同(同时启动,同时终止)。
- 常见作用:
- 日志收集: Sidecar 容器运行一个日志代理(如 Fluentd、Logstash),监控主容器的日志文件并将其转发到集中的日志系统。
- 服务网格代理 (如 Istio/Envoy): Sidecar 容器作为网络代理,处理主容器所有的入站和出站流量,实现安全、路由、监控等功能。
- 监控采集: Sidecar 容器运行一个 Prometheus Exporter,专门暴露主容器的性能指标。
- 数据同步: Sidecar 容器负责定期从外部系统同步配置或证书文件。
B. Init 容器 (初始化容器)
Init 容器在任何主容器启动之前运行,并且必须成功完成才能让主容器启动。它们用于执行设置和准备工作。
- 数量: 0 个或多个。
- 运行时间: 串行运行(一个接一个),并在主容器启动前完成。
- 常见作用:
- 等待依赖: 等待外部数据库或服务启动并可用。
- 环境准备: 从配置服务器下载配置文件、脚本或证书。
- 权限设置: 在共享卷上设置正确的文件权限。
每个节点上的多个 Pod 可以有完全不同的容器配置。例如:
Node 1 可能运行一个 Web Pod(主容器 + Envoy Sidecar)。
Node 2 可能运行一个 DB Pod(主容器 + Init 容器用于数据初始化)
数据库(如 MySQL, PostgreSQL)和 Redis 这种重量级、有状态的服务, 一般不会 作为辅助容器 (Sidecar) 部署在业务 Pod 内部。它们通常会被部署为独立的、单容器 Pod 或 StatefulSet,位于集群的独立节点上。
集群包含多个运行着 Kubernetes 代理程序、 由控制平台管理的一组节点(物理机或虚拟机)。 Kubernetes v1.34 单个集群支持的最大节点数为 5,000。 更具体地说,Kubernetes 设计为满足以下所有标准的配置:
- 每个节点的 Pod 数量不超过 110
- 节点数不超过 5,000
- Pod 总数不超过 150,000
- 容器总数不超过 300,000
Minikube
Minikube,k3s 和 Kind (Kubernetes IN Docker) 等都是用于在本地机器上运行 Kubernetes 集群的工具
常用的 NGINX Web 服务器 Deployment 示例
Deployment 是用于管理无状态应用(Stateless Application)的标准控制器。
在无状态应用中,所有的 Pod 副本都是完全相同的,并且可以互相替换。Pod 本身不保存任何需要持久化的数据,它们通常从外部数据库或存储中获取数据。
Deployment 和 StatefulSet 是“管理者”和“指导者”,而 Pod 是它们管理的“工作单位”1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34# my-app-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx-deployment # Deployment 的名称
labels:
app: my-nginx
spec:
# 1. 副本设置
replicas: 3 # 期望运行的 Pod 副本数量
# 2. 选择器:匹配哪些 Pod 属于这个 Deployment
selector:
matchLabels:
app: my-nginx
# 3. Pod 模板
template:
metadata:
labels:
app: my-nginx # 这个标签非常关键,用于 Service 选择 Pod
spec:
containers:
- name: nginx-container # 容器的名称
image: nginx:latest # 容器使用的镜像
ports:
- containerPort: 80 # 容器暴露的端口
# 资源请求(可选但推荐)
resources:
limits:
memory: "128Mi"
cpu: "500m"
requests:
memory: "64Mi"
cpu: "250m"
Kubernetes Deployment 检查 Pod 的健康状况,并在 Pod 中的容器终止的情况下重新启动新的容器。 Deployment 是管理 Pod 创建和扩展的推荐方法。
部署应用
利用minikube创建Deployment
Deployment 指挥 Kubernetes 如何创建和更新应用的实例。 创建 Deployment 后,Kubernetes 控制平面将 Deployment 中包含的应用实例调度到集群中的各个节点上。
创建应用实例后,Kubernetes Deployment 控制器会持续监视这些实例。 如果托管实例的节点关闭或被删除,则 Deployment 控制器会将该实例替换为集群中另一个节点上的实例。 这提供了一种自我修复机制来解决机器故障维护问题。1
2 运行包含 Web 服务器的测试容器镜像
kubectl create deployment hello-node --image=registry.k8s.io/e2e-test-images/agnhost:2.53 -- /agnhost netexec --http-port=8080
kubectl create deployment 是一个快捷命令,而 kubectl apply -f xx.yaml 是管理集群资源(包括 Deployment)的标准、推荐方式
查看Deployment:1
2
3
4
5kubectl get pods //查看pods
kubectl get deployments
kubectl get events // 查看集群事件
kubectl get services
kubectl config view //查看 kubectl 配置
创建 Deployment 时,Kubernetes 创建了一个 Pod 来托管你的应用实例。 Pod 是 Kubernetes 抽象出来的,表示一组一个或多个应用容器(如 Docker), 以及这些容器的一些共享资源。这些资源包括:
- 卷形式的共享存储
- 集群内唯一的 IP 地址,用于联网
- 有关每个容器如何运行的信息,例如容器镜像版本或要使用的特定端口
Pod 为特定于应用的“逻辑主机”建模,并且可以包含相对紧耦合的不同应用容器。 例如,Pod 可能既包含带有 Node.js 应用的容器,也包含另一个不同的容器, 用于提供 Node.js 网络服务器要发布的数据。Pod 中的容器共享 IP 地址和端口, 始终位于同一位置并且共同调度,并在同一节点上的共享上下文中运行。
利用minikbe创建Service
Kubernetes 中的Service是一种抽象概念,它定义的是 Pod 的一个逻辑集合和一种用来访问 Pod 的协议。 Service 使从属 Pod 之间的松耦合成为可能。
和所有 Kubernetes 对象清单一样,Service 用 YAML 或者 JSON 来定义。 Service 下的一组 Pod 通常由一个标签选择算符来标记 (请参阅下面的说明来了解为什么你可能想要一个 spec 中不包含 selector 的 Service)。
默认情况下,Pod 只能通过 Kubernetes 集群中的内部 IP 地址访问。 要使得容器可以从 Kubernetes 虚拟网络的外部访问,必须将 Pod 通过 Kubernetes Service 公开出来。
Service 的作用是为一组 Pod 提供一个稳定、不变的网络入口。这非常关键,因为 Pod 的 IP 地址是临时的、不稳定的。Service 负责跟踪 Pod 的变化,并将请求自动转发到健康的 Pod 副本上。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20apiVersion: v1
kind: Service
metadata:
name: my-web-service # Service 的名称
labels:
app: my-web
spec:
# 关键:Service如何找到它要暴露的Pod
selector:
app: my-nginx # 必须与目标 Deployment/Pod 的标签匹配
# 关键:Service 的类型,决定了如何被访问
type: LoadBalancer # 常见的类型:ClusterIP, NodePort, LoadBalancer
# 关键:端口配置
ports:
- protocol: TCP
port: 80 # Service 暴露给外部或集群内部的端口
targetPort: 80 # Service 转发到的 Pod 容器的端口
# nodePort: 30000 (如果 type 为 NodePort,可以指定或让K8s自动分配)
type 字段是创建 Service 时最重要的决定,它定义了 Service 的访问方式:
| Service Type | 访问方式 | 访问范围 | 典型用途 |
|---|---|---|---|
| ClusterIP (默认) | Service 分配一个集群内部 IP (Cluster IP)。 | 集群内部。只能从集群内部的 Pod 或 Node 访问。 | 集群内部组件通信(如 Web-API 连 Database)。 |
| NodePort | 在每个节点上打开一个固定的端口。 | 集群外部。可以通过 任何节点 IP:NodePort 访问。 | 测试环境或自建集群中简单暴露服务。 |
| LoadBalancer | 在云环境中(如 AWS, GKE, Azure)自动创建云平台负载均衡器。 | 集群外部。提供一个外部 IP 地址和负载均衡能力。 | 生产环境中暴露 Web 服务。 |
| ExternalName | 将服务映射到 DNS 名称。 | 集群内部。用于代理外部服务。 | 将集群内服务重定向到集群外的数据库或服务 |
kubectl基础
kubectl 命令的常见格式是:kubectl action resource。
这会对指定的资源(类似 node 或 deployment)执行指定的操作(类似 create、describe 或 delete)。 你可以在子命令之后使用 --help 获取可能参数相关的更多信息 (例如:kubectl get nodes --help)。
通过运行 kubectl version 命令,查看 kubectl 是否被配置为与你的集群通信。1
kubectl create deployment kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1
创建deployment1
kubectl proxy
在 Kubernetes 内运行的Pod]运行在一个私有的、隔离的网络上。 默认这些 Pod 可以从同一 Kubernetes 集群内的其他 Pod 和服务看到,但超出这个网络后则看不到。 当我们使用 kubectl 时,我们通过 API 端点交互与应用进行通信。
kubectl get- 列出资源kubectl describe- 显示有关资源的详细信息kubectl logs- 打印 Pod 中容器的日志kubectl exec- 在 Pod 中的容器上执行命令
扩缩应用
Deployment 仅创建了一个 Pod 用于运行这个应用。当流量增加时,需要扩容应用满足用户需求。
扩缩是通过改变 Deployment 中的副本数量来实现的1
kubectl get deployments
输出应该类似这样:1
2NAME READY UP-TO-DATE AVAILABLE AGE
kubernetes-bootcamp 1/1 1 1 11m
我们应该有 1 个 Pod。如果没有,请重新运行命令。结果显示:
- NAME 列出了集群中的 Deployment 的名称。
- READY 显示当前副本数与期望副本数的比例。
- UP-TO-DATE 显示已更新至期望状态的副本数。
- AVAILABLE 显示可用的 Pod 的数量。
- AGE 显示应用已运行的时间。
1 | kubectl scale deployments/kubernetes-bootcamp --replicas=4 |
进行扩缩容
负载均衡
使用副本后,使用 curl 访问对外公开的 IP 和端口。多次执行访问命令,每个请求都命中了不同的 Pod,这证明负载均衡正在工作
滚动更新
滚动更新通过增量式更新 Pod 实例并替换为新的实例,允许在 Deployment 更新过程中实现零停机
用户希望应用程序始终可用,而开发人员则需要每天多次部署它们的新版本。 在 Kubernetes 中,这些是通过滚动更新(Rolling Update)完成的。
滚动更新允许通过使用新的实例逐步更新 Pod 实例,实现零停机的 Deployment 更新。 新的 Pod 将被调度到具有可用资源的节点上。
如果 Deployment 的访问是公开的,Service 在更新期间仅将流量负载均衡到可用的 Pod。
与应用程序规模扩缩类似,如果 Deployment 的访问是公开的,Service 在更新期间仅将流量负载均衡到可用的 Pod。可用的 Pod 是指对应用的用户可用的实例。
滚动更新允许以下操作:
- 将应用程序从一个环境升级到另一个环境(通过容器镜像更新)
- 回滚到以前的版本
- 持续集成和持续交付应用程序,无需停机
要列出你的 Deployment,可以运行 get deployments 子命令:1
kubectl get deployments
要列出正在运行的 Pod,可以运行 get pods 子命令:1
kubectl get pods
要查看应用程序当前的镜像版本,可以运行 describe pods 子命令, 然后查找 Image 字段:1
kubectl describe pods
要将应用程序的镜像版本更新为 v2,可以使用 set image 子命令, 后面跟着 Deployment 名称和新版本的镜像:1
kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=docker.io/jocatalin/kubernetes-bootcamp:v2
此命令通知 Deployment 为应用程序使用不同的镜像,并启动滚动更新。 要检查新 Pod 的状态,并查看旧 Pod 的终止状况,可以使用 get pods 子命令:1
kubectl get pods
要回滚 Deployment 到你上一次工作版本的更新,可以运行 rollout undo 子命令:1
kubectl rollout undo deployments/kubernetes-bootcamp
rollout undo 命令会恢复 Deployment 到先前的已知状态(v2 的镜像)。 更新是有版本控制的,你可以恢复 Deployment 到任何先前已知状态。
配置
很多应用在其初始化或运行期间要依赖一些配置信息。 大多数时候,存在要调整配置参数所设置的数值的需求。 ConfigMap 是 Kubernetes 的一种机制,可让你将配置数据注入到应用的Pod内部。
ConfigMap 概念允许你将配置清单与镜像内容分离,以保持容器化的应用程序的可移植性
从字面量创建ConfigMap
使用 kubectl create configmap 命令基于字面量创建一个 ConfigMap:1
kubectl create configmap fruits --from-literal=fruits=apples
可以从目录和文件以及字面值都能创建ConfiMap1
2
3
4
5
6
7
8 将示例文件下载到 `configure-pod-container/configmap/` 目录
wget https://kubernetes.io/examples/configmap/game.properties -O configure-pod-container/configmap/game.properties
wget https://kubernetes.io/examples/configmap/ui.properties -O configure-pod-container/configmap/ui.properties
创建 ConfigMap
kubectl create configmap game-config --from-file=configure-pod-container/configmap/
kubectl create configmap game-config-2 --from-file=configure-pod-container/configmap/game.properties
kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=charm
编辑配置文件1
kubectl edit configmaps special-config
查看配置文件1
2
3
4
5
6
7
8
9
10
11
12kubectl get configmaps special-config -o yaml
apiVersion: v1
data:
special.how: very
special.type: charm
kind: ConfigMap
metadata:
creationTimestamp: "2025-12-10T13:35:12Z"
name: special-config
namespace: default
resourceVersion: "10165"
uid: ecdc4d73-0b2a-406b-ae65-b19a64977c56
删除配置文件1
kubectl delete configmap special-config
卷挂载的ConfigMap
实现这一目标需要三个步骤:创建 ConfigMap、定义 Deployment 中的 Volume、定义容器中的 Volume Mount。
首先创建一个包含多个配置文件的 ConfigMap1
2
3
4
5
6
7
8
9
10
11
12
13
14
15apiVersion: v1
kind: ConfigMap
metadata:
name: game-config # ConfigMap 名称
data:
# 配置项 1: 作为一个文件挂载
game.properties: |
server.port=8080
debug.mode=false
version=1.2.0
# 配置项 2: 作为一个文件挂载
ui.properties: |
theme=dark
language=zh-cn
创建Deployement,在 Deployment 的 Pod 模板中进行配置:
- 在
spec.volumes中定义一个卷(Volume),类型为configMap,并引用我们创建的game-config。 - 在
spec.containers的volumeMounts中,指定这个卷应该挂载到容器内的哪个路径
1 | apiVersion: apps/v1 |
在 Pod 上作为卷挂载的 ConfigMap 所发生的变更将在后续的 kubelet 同步后无缝生效。
配置为 Pod 环境变量的 ConfigMap 所发生变更将在后续的 Pod 上线操作后生效。
尽管 ConfigMap 中的键的取值已经变更,Pod 中的环境变量仍然显示先前的值。 这是因为当源数据变更时,在 Pod 内运行的进程的环境变量不会被更新; 如果你想强制更新,需要让 Kubernetes 替换现有的 Pod。新 Pod 将使用更新的信息来运行。
你可以触发该替换。使用 kubectl rollout 为 Deployment 执行上线操作:1
2
3
4
5 触发上线操作
kubectl rollout restart deployment configmap-env-var
等待上线操作完成
kubectl rollout status deployment configmap-env-var --watch=true
环境变量注入
通过 ConfigMap 将配置数据注入到容器的环境变量中。1
2
3
4
5
6
7
8
9
10apiVersion: v1
kind: ConfigMap
metadata:
name: fruits # 必须与 Deployment 中引用的 name: fruits 匹配
data:
键:fruits (必须与 Deployment 中引用的 key: fruits 匹配)
fruits: "Apple, Banana, Orange, Grapes"
您也可以添加其他键值对,但它们不会被这个 Deployment 引用
color: "Red"
创建ConfigMap文件1
kubectl apply -f fruits-configmap.yaml
Deployment文件1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32apiVersion: apps/v1
kind: Deployment
metadata:
name: configmap-env-var
labels:
app.kubernetes.io/name: configmap-env-var
spec:
replicas: 3
selector:
matchLabels:
app.kubernetes.io/name: configmap-env-var
template:
metadata:
labels:
app.kubernetes.io/name: configmap-env-var
spec:
containers:
- name: alpine
image: alpine:3
env:
- name: FRUITS
valueFrom:
configMapKeyRef:
key: fruits
name: fruits
command:
- /bin/sh
- -c
- while true; do echo "$(date) The basket is full of $FRUITS";
sleep 10; done;
ports:
- containerPort: 80
env 属性用于设置容器的环境变量。当定义一个环境变量时,通常会直接使用 value 属性来指定一个静态值。
然而,valueFrom 属性提供了一种更动态的方式来设置环境变量的值,它可以从集群内的其他资源(如 ConfigMap、Secret、或 Pod/Node 的字段)中获取数据。这在您不希望将敏感信息(如密码)或配置值直接硬编码到 Pod 定义中时非常有用。1
2
3
4
5
6
7
8
9
10
11
12spec:
containers:
- name: my-app
image: my-registry/my-app:latest
env:
# 使用 value 属性设置一个静态的环境变量
- name: APP_ENVIRONMENT
value: "production" # 环境变量 APP_ENVIRONMENT 的值被硬编码为 "production"
# 使用 value 属性设置另一个静态变量
- name: TIMEOUT_SECONDS
value: "30"1
2
3
4
5
6
7env:
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: app-config # 引用 ConfigMap 的名称
key: log_level # 引用 ConfigMap 中要使用的键
optional: false # (可选) 如果 ConfigMap 或 key 不存在,是否允许启动
边车容器
边车容器是与主应用程序容器在同一Pod内一起运行的辅助容器。这些容器通过提供额外的服务或功能(如日志记录、监控、安全或数据同步)来增强或扩展主应用容器的功能, 而无需直接修改主应用程序代码。
Kubernetes将边车容器作为Init容器的一个特例来实现, Pod 启动后,边车容器仍保持运行状态。 本文档使用术语”常规 Init 容器”来明确指代仅在 Pod 启动期间运行的容器。
如果你的集群启用了 SidecarContainers 特性门控,你可以为 Pod 的 initContainers 字段中列出的容器指定 restartPolicy。 这些可重新启动的边车(Sidecar) 容器独立于其他 Init 容器以及同一 Pod 内的主应用容器, 这些容器可以启动、停止和重新启动,而不会影响主应用容器和其他 Init 容器。
无状态应用
公开外部IP地址
1 | apiVersion: apps/v1 |
创建一个Deployment对象和一个关联的ReplicaSet对象。 ReplicaSet 有五个Pod, 每个都运行 Hello World 应用。1
kubectl apply -f https://k8s.io/examples/service/load-balancer-example.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14显示有关 Deployment 的信息
kubectl get deployments hello-world
kubectl describe deployments hello-world
显示有关 ReplicaSet 对象的信息
kubectl get replicasets
kubectl describe replicasets
创建公开 Deployment 的 Service 对象
kubectl expose deployment hello-world --type=LoadBalancer --name=my-service
显示有关 Service 的信息
kubectl get services my-service
显示有关 Service 的详细信息
kubectl describe services my-service
显示节点信息
kubectl get pods --output=wide
有状态应用
StatefulSet 运行一组 Pod,并为每个 Pod 保留一个稳定的标识。 这可用于管理需要持久化存储或稳定、唯一网络标识的应用
StatefulSet 是用来管理有状态应用的工作负载 API 对象。
StatefulSet 用来管理某Pod集合的部署和扩缩, 并为这些 Pod 提供持久存储和持久标识符。
和Deplopyment 类似, StatefulSet 管理基于相同容器规约的一组 Pod。但和 Deployment 不同的是, StatefulSet 为它们的每个 Pod 维护了一个有粘性的 ID。这些 Pod 是基于相同的规约来创建的, 但是不能相互替换:无论怎么调度,每个 Pod 都有一个永久不变的 ID。
StatefulSet 对于需要满足以下一个或多个需求的应用程序很有价值:
- 稳定的、唯一的网络标识符。
- 稳定的、持久的存储。
- 有序的、优雅的部署和扩缩。
- 有序的、自动的滚动更新。
1 | apiVersion: v1 |
1 | apiVersion: apps/v1 |
StatefulSet 默认以严格的顺序创建其 Pod。
对于一个拥有 n 个副本的 StatefulSet,Pod 被部署时是按照 {0..n-1} 的序号顺序创建的。 在第一个终端中使用 kubectl get 检查输出
参考资料
- Kubernetes 架构 | Kubernetes
- K8s入门指南:阮一峰亲授,轻松掌握容器编排核心技巧 - 云原生实践
- 白话多集群:工具和应用助手 - 阮一峰的网络日志
- Kubernetes一小时轻松入门_哔哩哔哩_bilibili
在线环境:
