文章目录
- Kubernetes入门学习(上)
- 介绍
- 云原生
- Kubernetes架构
- 基础概念
- Kubernetes架构
- 控制平面组件
- Node组件
- 组件关系
- 安装Kubernetes
- 基本对象和操作
- Pod(容器集)
- Deployment(部署)与ReplicaSet(副本集)
- Service(服务)
- namespace(命名空间)
- 声明式对象配置
- 容器与镜像
- 金丝雀发布
Kubernetes入门学习(上)
介绍
-
名称简介
Kubernetes 是一个开源的容器编排引擎和容器集群管理工具,用来对容器化应用进行自动化部署、 扩缩和管理。
Kubernetes 这个名字源于希腊语,意为“舵手”或“飞行员”。k8s 这个缩写是因为 k 和 s 之间有8个字符。 Google 在 2014 年开源了 Kubernetes 项目。
-
优势
Kubernetes 建立在 Google 大规模运行生产工作负载十几年经验的基础上, 结合了社区中最优秀的想法和实践。它之所以能够迅速流行起来,是因为它的许多功能高度契合互联网大厂的部署和运维需求。 -
功能
- 服务发现和负载均衡
- 存储编排
- 自动部署和回滚
- 自动完成装箱计算
- 自我修复
- 密钥与配置管理
云原生
- 定义
- 通俗理解:原生应用是采用特定操作系统的语言针对该操作系统开发的应用,而在设计和开发应用时,让他们能够运行在云基础设施(比如Kubernetes)上,从而使应用具备可弹性扩展的能力,我们称之为云原生应用。简而言之:云原生就是以容器技术为载体、基于微服务架构思想的一套技术体系和方法论。
- 官方定义:云原生技术有利于各组织在公有云、私有云和混合云等新型动态环境中,构建和运行可弹性扩展的应用。云原生的代表技术包括容器、服务网格、微服务、不可变基础设施和声明式API。
Kubernetes 是 CNCF 托管的第一个开源项目。因此现在提到云原生,往往我们都把它与kubernetes联系起来。
云原生计算基金会(CNCF)致力于培育和维护一个厂商中立的开源生态系统,来推广云原生技术。
Kubernetes架构
基础概念
- 节点(Node):Kubernetes中工作的机器叫做节点,会运行容器化应用程序,运行实际的应用和工作负载。
- Pod:Pod 是可以在 Kubernetes 中创建和管理的、最小的可部署的计算单元。Pod表示你的集群上—组正在运行的容器。这些容器共享存储、网络、以及怎样运行这些容器的声明。
- 集群:Kubernetes集群至少包含一个控制平面(control plane),以及一个或多个工作节点(worker node)。
- 控制平面**(Control Plane) 😗* 控制平面负责管理工作节点和维护集群状态。所有任务分配都来自于控制平面。
Kubernetes架构
一个Kubernetes集群至少包含一个控制平面组件(control plane),以及一个或多个工作节点组件(worker node)。
控制平面组件
控制平面组件会为集群做出全局决策,比如资源的调度、检测和响应集群事件。
-
kube-apiserver
如果需要与Kubernetes 集群进行交互,就要通过
API
。apiserver
是 Kubernetes 控制平面的前端,用于处理内部和外部请求。 -
kube-scheduler
负责监视新创建的、未指定运行节点(node)的 Pods, 并选择节点来让 Pod 在上面运行。集群状况是否良好?如果需要创建新的容器,要将它们放在哪里?这些是调度程序需要关注的问题。
scheduler
调度程序会考虑容器集的资源需求(例如 CPU 或内存)以及集群的运行状况。随后,它会将容器集安排到适当的计算节点。 -
etcd
一致且高可用的键值存储,用于存储配置数据和集群状态信息, 用作 Kubernetes 所有集群数据的后台数据库。
-
kube-controller-manager
控制器负责实际运行集群,
controller-manager
控制器管理器则是将多个控制器功能合而为一,降低了程序的复杂性。controller-manager
包含了这些控制器:- 节点控制器(Node Controller):负责在节点出现故障时进行通知和响应
- 任务控制器(Job Controller):监测代表一次性任务的 Job 对象,然后创建 Pods 来运行这些任务直至完成
- 端点控制器(Endpoints Controller):填充端点(Endpoints)对象(即加入 Service 与 Pod)
- 服务帐户和令牌控制器(Service Account & Token Controllers):为新的命名空间创建默认帐户和 API 访问令牌
-
cloud-controller-manager
控制平面还包含一个可选组件
cloud-controller-manager
。云控制器管理器(Cloud Controller Manager)允许你将你的集群连接到云提供商的 API 之上, 并将与该云平台交互的组件同与你的集群交互的组件分离开来。
Node组件
节点组件会在每个节点上运行,负责维护运行的 Pod 并提供 Kubernetes 运行环境。
-
kubelet
kubelet
会在集群中每个节点(node)上运行。 它保证容器(containers)都运行在 Pod 中。
当控制平面需要在节点中执行某个操作时,kubelet
就会执行该操作。 -
kube-proxy
kube-proxy
是集群中每个节点(node)上运行的网络代理,是实现 Kubernetes 服务(Service) 概念的一部分。
kube-proxy
维护节点网络规则和转发流量,实现从集群内部或外部的网络与 Pod 进行网络通信。 -
容器运行时(Container Runtime)
这个基础组件使 Kubernetes 能够有效运行容器。 它负责管理 Kubernetes 环境中容器的执行和生命周期。负责运行容器的软件。Kubernetes 支持许多容器运行环境,例如 containerd、docker或者其他实现了 Kubernetes CRI (容器运行环境接口)的容器。
组件关系
安装Kubernetes
参考这篇即可K8s安装部署–超级详细(无坑,v1.23)_虚拟机部署k8s_我不当正经人了z的博客-CSDN博客
容器镜像加速详见阿里云镜像加速
个人觉得这教程更好https://blog.csdn.net/IOT_AI/article/details/131975562
基本对象和操作
Pod(容器集)
-
概述
Pod 是包含一个或多个容器的容器组,是 Kubernetes 中创建和管理的最小对象。
Pod 有以下特点:
-
Pod是kubernetes中最小的调度单位(原子单元),Kubernetes直接管理Pod而不是容器。
-
同一个Pod中的容器总是会被自动安排到集群中的同一节点(物理机或虚拟机)上,并且一起调度。
-
Pod可以理解为运行特定应用的“逻辑主机”,这些容器共享存储、网络和配置声明(如资源限制)。
-
每个 Pod 有唯一的 IP 地址。 IP地址分配给Pod,在同一个 Pod 内,所有容器共享一个 IP 地址和端口空间,Pod 内的容器可以使用
localhost
互相通信。
-
-
举例
一个Pod中你可能有一个容器,为共享卷中的文件提供 Web 服务器支持,以及一个单独的 “边车 (sidercar)” 容器负责从远端更新这些文件,如下图所示:
-
操作Pod
# 拉取并且运行Pod
# --image 指定镜像
kubectl run mynginx --image=nginx
# 查看Pod
kubectl get pod
# 描述
kubectl describe pod mynginx
# 查看Pod的运行日志
kubectl logs mynginx
# 显示pod的IP和运行节点信息
kubectl get pod -owide
# 使用Pod的ip+pod里面运行容器的端口
curl 10.42.1.3
#在容器中执行
# 命令放在--后
kubectl exec mynginx -it -- /bin/bash
# --watch 隔一段时间执行一次命令用于观察
kubectl get pod --watch
# -it 交互模式
# --rm 退出后删除容器,多用于执行一次性任务或使用客户端
kubectl run mynginx --image=nginx -it --rm -- /bin/bash
# 删除
kubectl delete pod mynginx
# 强制删除
kubectl delete pod mynginx --force
Deployment(部署)与ReplicaSet(副本集)
-
介绍
-
Deployment
:Deployment
是对ReplicaSet
和Pod
更高级的抽象。它使Pod拥有多副本,自愈,扩缩容、滚动升级等能力。一个 Deployment 为 Pod 和 ReplicaSet 提供声明式的更新能力
-
ReplicaSet
:ReplicaSet
的目的是维护一组在任何时候都处于运行状态的 Pod 副本的稳定集合。 因此,它通常用来保证给定数量的、完全相同的 Pod 的可用性。通常我们不直接使用ReplicaSet
,而是在Deployment
中声明。
-
-
操作
基本操作:创建、查看、删除
#创建deployment,部署3个运行nginx的Pod kubectl create deployment nginx-deployment --image=nginx:1.22 --replicas=3 #查看deployment kubectl get deploy #查看replicaSet kubectl get rs #删除deployment kubectl delete deploy nginx-deployment
缩放
-
手动缩放
#将副本数量调整为5 kubectl scale deployment/nginx-deployment --replicas=5 kubectl get deploy
-
自动缩放
自动缩放通过增加和减少副本的数量,以保持所有 Pod 的平均 CPU 利用率不超过 75%。
自动伸缩需要声明Pod的资源限制,同时使用 Metrics Server 服务
#自动缩放 kubectl autoscale deployment/nginx-auto --min=3 --max=10 --cpu-percent=75 #查看自动缩放 kubectl get hpa #删除自动缩放 kubectl delete hpa nginx-deployment
滚动更新
#查看版本和Pod kubectl get deployment/nginx-deployment -owide kubectl get pods #更新容器镜像 kubectl set image deployment/nginx-deployment nginx=nginx:1.23 #滚动更新 kubectl rollout status deployment/nginx-deployment #查看过程 kubectl get rs --watch
版本回滚
#查看历史版本 kubectl rollout history deployment/nginx-deployment #查看指定版本的信息 kubectl rollout history deployment/nginx-deployment --revision=2 #回滚到历史版本 kubectl rollout undo deployment/nginx-deployment --to-revision=2
-
Service(服务)
-
概述
Kubernetes 中
Service
是 将运行在一个或一组 Pod 上的网络应用程序公开为网络服务的方法。Service为一组 Pod 提供相同的 DNS 名(域名),并且在它们之间进行负载均衡。
Kubernetes 为 Pod 提供分配了IP 地址,但IP地址可能会发生变化。
集群内的容器可以通过service名称访问服务,而不需要担心Pod的IP发生变化。
Kubernetes Service 定义了这样一种抽象:
逻辑上的一组可以互相替换的 Pod,通常称为微服务。
Service 对应的 Pod 集合通常是通过选择算符来确定的。
举个例子,在一个Service中运行了3个nginx的副本。这些副本是可互换的,我们不需要关心它们调用了哪个nginx,也不需要关注 Pod的运行状态,只需要调用这个服务就可以了。
-
操作
# 将已有的部署创建为服务 # --name:指定服务名 # --type:指定servicetype # --port:指定服务公开端口 # --target-port:指定容器内部端口 kubectl expose deployment/nginx-deployment \ --name=nginx-service --type=ClusterIP --port=80 --target-port=80 # 查看服务 kubectl get svc
-
ServiceType
和Port
解析-
ServiceType
取值ClusterIP
:将服务公开在集群内部。kubernetes会给服务分配一个集群内部的 IP,集群内的所有主机都可以通过这个Cluster-IP访问服务。集群内部的Pod可以通过service名称访问服务。- NodePort:通过每个节点的主机IP 和静态端口(NodePort)暴露服务。 集群的外部主机可以使用节点IP和NodePort访问服务。
- ExternalName:将集群外部的网络引入集群内部。
- LoadBalancer:使用云提供商的负载均衡器向外部暴露服务。
-
Port
-
namespace(命名空间)
-
概述
**命名空间(Namespace)**是一种资源隔离机制,将同一集群中的资源划分为相互隔离的组。
命名空间可以在多个用户之间划分集群资源(通过资源配额)。
- 例如我们可以设置开发、测试、生产等多个命名空间。
同一命名空间内的资源名称要唯一,但跨命名空间时没有这个要求。
命名空间作用域仅针对带有名字空间的对象,例如 Deployment、Service 等。
这种作用域对集群访问的对象不适用,例如 StorageClass、Node、PersistentVolume 等。
-
Kubernetes 会创建四个初始命名空间:
default
默认的命名空间,不可删除,未指定命名空间的对象都会被分配到default中。kube-system
Kubernetes 系统对象(控制平面和Node组件)所使用的命名空间。kube-public
自动创建的公共命名空间,所有用户(包括未经过身份验证的用户)都可以读取它。通常我们约定,将整个集群中公用的可见和可读的资源放在这个空间中。kube-node-lease
租约(Lease)对象使用的命名空间。每个节点都有一个关联的 lease 对象,lease 是一种轻量级资源。lease对象通过发送心跳,检测集群中的每个节点是否发生故障。
使用
kubectl get lease -A
查看lease
对象 -
操作
管理命名空间
kubectl get pod -A #创建命名空间 kubectl create namespace dev #查看命名空间 kubectl get ns #在命名空间内运行Pod kubectl run nginx --image=nginx --namespace=dev kubectl run my-nginx --image=nginx -n=dev #查看命名空间内的Pod kubectl get pods -n=dev #查看命名空间内所有对象 kubectl get all # 删除命名空间会删除命名空间下的所有内容 kubectl delete ns dev
切换当前命名空间
#查看当前上下文 kubectl config current-context #将dev设为当前命名空间,后续所有操作都在此命名空间下执行。 kubectl config set-context $(kubectl config current-context) --namespace=dev
声明式对象配置
-
云原生的代表技术包括:
-
容器
-
服务网格
-
微服务
-
不可变基础设施
-
声明式API
-
-
管理对象:命令行指令 vs 声明式配置
-
命令行指令
例如,使用
kubectl
命令来创建和管理 Kubernetes 对象。命令行就好比口头传达,简单、快速、高效。
但它功能有限,不适合复杂场景,操作不容易追溯,多用于开发和调试。
-
声明式配置
kubernetes使用yaml文件来描述 Kubernetes 对象。
声明式配置就好比申请表,学习难度大且配置麻烦。
好处是操作留痕,适合操作复杂的对象,多用于生产。
-
-
常用命令缩写
名称 缩写 Kind namespaces ns Namespace nodes no Node pods po Pod services svc Service deployments deploy Deployment replicasets rs ReplicaSet statefulsets sts StatefulSet -
配置对象
在创建的 Kubernetes 对象所对应的
yaml
文件中,需要配置的字段如下:apiVersion
- Kubernetes API 的版本kind
- 对象类别,例如Pod
、Deployment
、Service
、ReplicaSet
等metadata
- 描述对象的元数据,包括一个 name 字符串、UID 、标签和可选的 namespacespec
- 对象的配置
举例:
# my-pod.yaml apiVersion: v1 kind: Pod metadata: name: my-nginx spec: containers: - name: nginx image: nginx:1.22 ports: - containerPort: 80
使用yaml文件管理对象
#创建对象 kubectl apply -f my-pod.yaml #编辑对象,这里有点问题 kubectl edit nginx #删除对象 kubectl delete -f my-pod.yaml
-
标签
标签(Labels) 是附加到对象(比如 Pod)上的键值对,用于补充对象的描述信息。
标签使用户能够以松散的方式管理对象映射,而无需客户端存储这些映射。
由于一个集群中可能管理成千上万个容器,我们可以使用标签高效的进行选择和操作容器集合。
- 键的格式:
-
- 前缀(可选)/名称(必须)。
- 有效名称和值:
-
- 必须为 63 个字符或更少(可以为空)
- 如果不为空,必须以字母数字字符([a-z0-9A-Z])开头和结尾
- 包含破折号
**-**
、下划线**_**
、点**.**
和字母或数字
label配置模版
apiVersion: v1 kind: Pod metadata: name: label-demo labels: #定义Pod标签 environment: test app: nginx spec: containers: - name: nginx image: nginx:1.22 ports: - containerPort: 80
# 查看Pod的同时展示标签 kubectl get pod --show-labels # 根据标签查看Pod kubectl get pod -l environment=test,app=nginx
-
选择器
标签选择器 可以识别一组对象。标签不支持唯一性。
标签选择器最常见的用法是为Service选择一组Pod作为后端。
Service配置模版
apiVersion: v1 kind: Service metadata: name: my-service spec: type: NodePort selector: #与Pod的标签一致 environment: test app: nginx ports: # 默认情况下,为了方便起见,`targetPort` 被设置为与 `port` 字段相同的值。 - port: 80 targetPort: 80 # 可选字段 # 默认情况下,为了方便起见,Kubernetes 控制平面会从某个范围内分配一个端口号(默认:30000-32767) nodePort: 30007
目前支持两种类型的选择运算:基于等值的和基于集合的。
多个选择条件使用逗号分隔,相当于**And(&&)**运算。
-
等值选择:键值对
selector: matchLabels: # component=redis && version=7.0 component: redis version: 7.0
-
集合选择
selector: matchExpressions: # tier in (cache, backend) && environment not in (dev, prod) - {key: tier, operator: In, values: [cache, backend]} - {key: environment, operator: NotIn, values: [dev, prod]}
-
容器与镜像
容器运行时接口(CRI)
Kubelet运行在每个节点(Node)上,用于管理和维护Pod和容器的状态。
容器运行时接口(CRI)是kubelet 和容器运行时之间通信的主要协议。它将 Kubelet 与容器运行时解耦,理论上,实现了CRI接口的容器引擎,都可以作为kubernetes的容器运行时。
Docker没有实现(CRI)接口,Kubernetes使用
dockershim
来兼容docker。自V1.24版本起,Dockershim 已从 Kubernetes 项目中移除。
crictl
是一个兼容CRI的容器运行时命令,他的用法跟docker
命令一样,可以用来检查和调试底层的运行时容器。
crictl pull mysql:5.7-debian
crictl images
在一些局域网环境下,我们没法通过互联网拉取镜像,可以手动的导出、导入镜像。
crictl
命令没有导出、导入镜像的功能。
需要使用ctr
命令导出、导入镜像,它是containerd
的命令行接口。
从containerd
导出、导入镜像
#导出镜像,kubernetes中所有镜像都在k8s.io命名
ctr -n k8s.io images export mysql.tar docker.io/library/mysql:5.7-debian --platform linux/amd64
#导入镜像
ctr -n k8s.io images import mysql.tar
金丝雀发布
-
概述
金丝雀部署(canary deployment) 也被称为灰度发布
早期,工人下矿井之前会放入一只金丝雀检测井下是否存在有毒气体。
采用金丝雀部署,你可以在生产环境的基础设施中小范围的部署新的应用代码。
一旦应用签署发布,只有少数用户被路由到它,最大限度的降低影响。
如果没有错误发生,则将新版本逐渐推广到整个基础设施
-
部署过程
第一个版本
发布v1版本的应用,镜像使用
nginx:1.22
,数量为 3- 创建Namespace
Namespace配置模版
- 创建Deployment
Deployment配置模版
- 创建外部访问的Service
Service配置模版
# deploy-v1.yaml apiVersion: v1 kind: Namespace metadata: name: dev --- apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment-v1 namespace: dev labels: app: nginx-deployment-v1 spec: replicas: 3 selector: matchLabels: # 跟template.metadata.labels一致 app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.22 ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: canary-demo namespace: dev spec: type: NodePort selector: # 跟Deployment中的selector一致 app: nginx ports: # By default and for convenience, the `targetPort` is set to the same value as the `port` field. - port: 80 targetPort: 80 # Optional field # By default and for convenience, the Kubernetes control plane will allocate a port from a range (default: 30000-32767) nodePort: 30008
创建Canary Deployment
# deploy-cannary.yaml apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment-canary namespace: dev labels: app: nginx-deployment-canary spec: replicas: 1 selector: matchLabels: # 跟template.metadata.labels一致 app: nginx template: metadata: labels: app: nginx track: canary spec: containers: - name: new-nginx image: docker/getting-started ports: - containerPort: 80
分配流量
查看服务
kubectl describe svc canary-demo --namespace=dev
-
调整比例
待稳定运行一段时间后,扩大试用范围,将部署的v2版本数量调整为3,v1和v2的数量都是3个。
kubectl scale deployment/nginx-deployment-canary --replicas=3 -n=dev
-
下线旧版本
kubectl scale deployment/nginx-deployment-v1 --replicas=0 -n=dev
清空环境
kubectl delete all --all -n=dev