03 理解K8s的架构和资源对象
你好,我是雪飞。
上一讲我带你动手搭建了一套 K8s 集群,你在搭建过程中是不是感觉有点难?没关系,这是很正常的。你会发现,明明是按照文档一步步执行,总是有报错。这种情况,建议你在搭建的时候,仔细阅读文档,执行过程中注意规范操作,避免小错误。最好要明白每一步操作的目的,多试几次就一定能成功。我还记得当时我第一次搭建成功那一刻真是非常激动,这就是一个程序员的小快乐吧,相信你也能体会到这种快乐!
今天这节课我们就来深入学习 K8s 的各种组件和资源对象,并动手在 K8s 环境部署一个 Nginx 的应用。你会发现 K8s 架构设计非常灵活高效,提供的资源对象也是非常丰富,能够满足各种各样的部署需求。
K8s 组件
K8s 由管理节点和工作节点组成,因为它们所承担的工作内容不一样,所以这两个节点上安装着不同的 K8s 组件。管理节点安装承担调度和管理相关的组件,而工作节点自然就是安装具体执行的组件了。下面我们分别介绍这两种节点上的组件。
管理节点(Master Node)
管理节点是 K8s 集群的“大脑”,负责管理整个集群。管理节点上运行的核心组件包括:
- API server:它是整个 K8s 集群的唯一访问入口,它对外开放了一套 RESTful API 接口,要访问 K8s 里的资源对象就需要调用 API server 提供的接口。资源对象是 K8s 提供的用于实现各种管理和部署需求的“工具包”。K8s 内部的各个组件之间不能直接互相调用,也需要调用 API server 的接口来完成自己需要的工作。就连我们使用的 kubectl 命令交互工具也是通过调用 API server 的接口来操作集群。
- Scheduler:它负责对集群内部的资源对象进行调度,相当于调度员的角色。K8s 中管理的最小资源对象是 Pod,Pod 相当于一个容器组,里面包含了多个容器,当 K8s 接到一个Pod 对象的部署任务,Scheduler 就会根据调度策略来决定这个 Pod 应该运行在哪些节点上。
- Controller Manager:它是 K8s 的管理中心,它包含的 Controller 控制器和 K8s 的资源对象一一对应,负责集群内资源对象的管理,它保障资源对象维持在预期的工作状态。
- etcd:它是一个键值对存储组件,相当于整个 K8s 集群组件共享的数据库,用于保存集群的所有配置数据,包含集群中当前的资源对象、状态数据、统计数据等。etcd 中存储的数据通常需要做备份,如果集群出现问题可以使用备份数据恢复所有资源对象和工作状态。
Master 节点上还安装了一个 kubectl 工具,虽然它不是 K8s 的组件,但是它是用来执行 K8s 命令的交互工具。
工作节点(Node)
工作节点是 K8s 集群中具体运行容器的服务器。它们是集群的执行者,就像“四肢”一样,负责实际运行各种资源对象。每个工作节点都包含以下组件:
- kubelet:你可以将它视为每个节点上的 K8s 管理员。它负责启动、停止、复制容器、监控容器的健康状况等工作。其他组件都是部署在 K8s 自身集群里的,而 kubelet 不一样,它是直接安装在服务器上的,属于系统级服务。这是因为 kubelet 需要管理集群中的容器,这需要能对服务器进行操作的高级权限,因此它不能通过容器的方式部署。
- Container Runtime:这个组件叫做容器运行时组件,它负责实际运行和管理容器,你可以把它看作是容器引擎。节点上的 kubelet 与容器运行时进行交互,从而管理容器的生命周期。K8s 支持第三方提供的容器运行时组件,我们常用的是 Docker 或 Containerd。
- kube-proxy:它就像集群中的交通枢纽,负责管理集群内部的网络流量。它的主要任务包括服务发现和负载均衡,同时提供更加动态和灵活的网络代理服务。
工作节点的数量可以自由扩展,但是工作节点越多,对 Master 节点的配置要求也就越高,毕竟配置高的大脑才能管的了更多节点。通常我们开发的 toB 业务系统,10 个左右的工作节点也就够用。
介绍了这些 K8s 的组件,我们就可以去集群里找找这些组件。在 Master 节点上执行 “kubectl get pod” 命令查看 Pod 列表,可以看到 K8s 的这些核心组件几乎都是以 Pod 的方式运行在集群中,除了 kubelet 是直接安装到服务器上。
[root@k8s-master ~]# kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-66f779496c-dgtfq 1/1 Running 0 13h
coredns-66f779496c-zjzlc 1/1 Running 0 13h
etcd-k8s-master 1/1 Running 0 13h
kube-apiserver-k8s-master 1/1 Running 0 13h
kube-controller-manager-k8s-master 1/1 Running 0 13h
kube-proxy-7stts 1/1 Running 0 13h
kube-proxy-k4grz 1/1 Running 0 13h
kube-proxy-spxv2 1/1 Running 0 13h
kube-scheduler-k8s-master 1/1 Running 0 13h
总的来说,K8s 集群架构由管理节点和工作节点组成。管理节点负责整个集群的状态监控和资源对象调度,而工作节点专门负责运行和管理容器,这种分离的设计不仅增强了 K8s 的灵活性和扩展性,也让它能够有效地支持大规模和动态变化的云原生应用部署需求。
插件
除了核心组件外,K8s 还提供了许多插件来拓展功能。介绍两个常用的 K8s 插件。
- core DNS:它是 K8s 集群中的域名解析插件,提供了简单而可靠的 DNS 服务。你可以通过域名的方式轻松地访问到集群中 Pod 和 Service 这些资源对象。
- Dashboard:Dashboard 是 K8s 集群中的 Web 界面管理工具,它提供了一个可视化界面,让你可以在不熟悉 K8s 命令的情况下,轻松地管理和监控集群中的资源对象。
K8s 的资源对象(Resource Object)
上面介绍组件的时候一直提到 K8s 的资源对象,现在就来介绍一下。资源对象是 K8s 中的核心概念,它是 K8s 提供管理集群和部署应用的各种工具。有的资源对象负责管理容器,有的资源对象负责管理配置参数,还有些负责管理网络和存储等等。这些资源对象通过 K8s 的 API 进行定义和管理,所以每个资源对象都有它对应的 API 版本。
这里我简单介绍几个重要的资源对象,让你有个总体了解。
最常用的资源对象就是 Pod,它是 K8s 中的基本部署单元,每个 Pod 包含一个或多个容器,这些容器里就运行着我们的应用镜像。
在 Pod 的基础上,K8s 做了一些满足不同功能需求的封装,包装成了新的资源对象,例如可以执行任务和定时任务的 Job 和 CronJob,以及提供了类似每个节点上守护进程的 DaemonSet,这些资源对象里都包含了实际要运行的 Pod。
Deployment 和 StatefulSet 分别对应着无状态应用和有状态应用的部署。它们都可以同时部署多个 Pod 副本,从而实现应用 Pod 的高可用和弹性伸缩。
无状态应用就是指应用在处理请求时不依赖于任何状态信息。每次对请求的处理和响应都是独立的。无状态应用更容易扩展,它可以水平复制多个应用,例如常见的 Web 服务,可以部署在多个服务器上,不管我们的请求到了哪个服务器,得到的结果都一样。
有状态应用与无状态应用相反,处理请求需要维护应用之前的状态信息。这可能包括用户会话、数据库连接等,同时有状态应用的多个应用会存在一些复杂关系,比如主从关系或者主备关系等,数据库应用 MySQL就是有状态应用。
K8s 还提供负责负载均衡和服务发现的 Service 和实现路由访问规则的 Ingress,以及提供负责持久化存储的 PV(Persistent Volume) 和 PVC(Persistent Volume Claim) ,甚至还提供了负责存储变量参数的 ConfigMap 和 Secret。
总之,通过这些丰富的资源对象,你可以灵活地部署和管理应用,方便地使用网络和存储,快速实现你所期望的部署方式。学好 K8s 主要就是对这些资源对象的熟练使用,后续的课程中我会陆续介绍这些资源对象的使用方法。
快速使用 K8s 部署应用
理论部分讲完了,现在我就带你动手实验一下在 K8s 集群上部署应用。我们部署一个 Nginx 镜像的应用,在讲 Docker 容器的时候已经使用过 Nginx 镜像,部署成功之后可以通过 HTTP 请求直接访问它的默认网站首页,从而来验证 Nginx 应用是否部署成功。
实验内容和步骤如下:
- 我们选择使用 K8s 提供的 Deployment 作为部署对象,Deployment 用来部署无状态应用,刚好适合部署 Nginx 这种 web 应用。先部署一个 Deployment ,设置 3 个 Pod 应用副本,这样就在集群里就同时运行了 3 个 Pod,每个 Pod 里都运行了 Nginx 镜像的容器。
- Nginx 应用的 Pod 运行起来之后,要提供访问网络,这时就需要部署 Service。上面内容讲过 Service 是 K8s 提供的用于网络访问的资源对象 ,它可以创建一个访问集群中 Pod 的网络通路,从而让我们访问到运行 Nginx 应用的 Pod,同时返回响应结果。
注意:需要设置 Service 的类型为 NodePort,这样我们就可以通过任意集群节点服务器的公网 IP 和 NodePort 端口号来访问 Nginx 应用。
在 K8s 中部署资源对象可以通过两种方式:使用命令行工具 kubectl 直接执行命令部署,或者使用 YAML 或 JSON 格式的配置文件部署。这里两种方式我都给你演示一下吧。
使用 kubectl 命令部署
kubectl 提供了一系列的命令来与集群交互,从而管理资源对象。你可以直接在 Master 节点服务器的 Shell 终端窗口中输入 kubectl 命令来创建、查看、更新或删除资源对象。
第一步:部署 Deployment
- nginx-deployment-kc:Deployment 的名称,可以自行定义,我这里加了后缀 kc 是为了方便演示这是使用 kubectl 命令安装的资源对象。
- –image=nginx:表示容器使用 Nginx 镜像,K8s 会自动拉取 Nginx 镜像。
- –replicas=3:表示 Pod 副本数为3个,即部署了3个同样的运行 Nginx 应用的 Pod。
- –port=80:表示 Nginx 容器对外需要暴露80端口。
第二步:部署 Service,向外暴露 Nginx 容器的端口
- nginx-deployment-kc:因为 Service 是针对 Deployment 来提供网络服务,所以这个参数要跟上面部署的 Deployment 名称相同,Service 自己的默认名称和 Deployment 名称相同。
- –type=NodePort:指定 Service 的类型为 NodePort。
- –port=80 和 --target-port=80:表示 Service 对外暴露端口为80,同时对应 Pod 中的容器的暴露端口也是80。
第三步:检查部署状态
结果如下:
[root@k8s-master ~]# kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment-kc 3/3 3 3 70s
[root@k8s-master ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-deployment-kc NodePort 10.108.2.2 <none> 80:32608/TCP 10s
返回结果中,可以看到我们部署好的 Deployment 和 Service。在查看 Service 列表的时候可以看到 Service 的 TYPE 为 NodePort,同时会在 PORT 列看到 “80:32608/TCP”,这个 32608 端口号就是集群分配的可以外部访问 Service 的端口号。
第四步:验证实验结果
此时,在浏览器中可以使用集群中任意节点服务器的“公网 IP + NodePort 端口号”来访问 Nginx 应用,在我的集群中访问地址为 “http://82.156.143.14:32608”。由于 Master 节点默认设置了不能被调度 Pod,所以这里不要使用 Master 节点的公网 IP。
注意:如果使用公有云服务器,需要在集群节点上配置防火墙,开放该 NodePort 端口号才能访问。
使用 YAML 文件部署
第一步:部署 Deployment
在 Master 节点上新建一个 YAML 格式的部署文件,文件名为 “nginx-deployment.yaml”,用来部署 Deployment。
# nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment-yaml # Deployment 名称
spec:
replicas: 3 # 副本数3个
selector:
matchLabels:
app: nginx-deployment-yaml
template:
metadata:
labels:
app: nginx-deployment-yaml
spec:
containers:
- name: my-nginx-c
image: nginx # nginx 镜像
ports:
- containerPort: 80 # 暴露端口
在 Master 节点服务器的 Shell 终端窗口中执行 “kubectl apply” 命令,这个命令可以让 K8s 通过 YAML 文件来自动部署 Deployment。
第二步:部署 Service,向外暴露 Nginx 容器的端口
在 Master 节点上新建一个 Service 的 YAML 部署文件,文件名为 “nginx-service.yaml”,用来部署 Service。
# nginx-service.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-service-yaml
spec:
selector:
app: nginx-deployment-yaml
ports:
- protocol: TCP
port: 80
targetPort: 80
type: NodePort # 类型是 NodePort
同样执行 “kubectl apply” 命令,通过 YAML 文件来自动部署 Service。
第三步:检查部署状态和验证实验结果
检查状态和验证结果与使用 kubectl 命令部署方式相同,这里就不再重复。看到 NodePort 端口号之后,就可以通过节点服务器的“公网 IP + NodePort 端口号”来访问 Nginx 应用。
删除资源对象
在实验中,我们通过 kubectl 命令部署了名为 “nginx-deployment-kc” 的 Deployment 和名为 “nginx-deployment-kc” 的 Service。通过执行 YAML 文件的方式分别部署了名为 “nginx-deployment-yaml” 的 Deployment 和名为 “nginx-service-yaml” 的 Service 。
实验结束,如果部署的资源对象都不需要了,可以使用以下命令直接删除。
如果是用 YAML 文件部署的资源对象,也可以通过这种方式删除。
小结
在这节课中,首先我介绍了 K8s 管理节点和工作节点上运行的核心组件。
管理节点就像 K8s 的大脑,运行着 API Server、Scheduler、Controller Manager 和 Etcd 组件。工作节点就像 K8s 的四肢,运行着 kubelet、kube-proxy 和 Container Runtime 容器运行时组件。这些组件相互独立,又协同工作,共同组成了 K8s 的核心架构,所以 K8s 拥有强大的灵活性和扩展性。
其次,我介绍了 K8s 的资源对象,它是 K8s 提供的管理集群和部署应用的工具集。其中有最小部署单元 Pod,有用于执行任务的 Job 和 CronJob,有用于守护类任务的 Daemonset,有用于部署应用的 Deployment 和 Statefulset,有用于网络访问的 Service和 Ingress,有用于持久化存储的 PV 和 PVC,还有用于共享参数的 ConfigMap 和 Secret,等等。K8s 提供了非常丰富的资源对象,满足了各种各样的部署需求。
最后,我带你在 K8s 集群中部署了一个 Nginx 应用,展示了通过 kubectl 命令和 YAML 文件来部署 K8s 应用的两种方式。
思考题
这就是今天的全部内容,最后留一道练习题给你。
按照课程中讲的两种部署方式,你自己动手试验一下,看看是否能成功部署一个 Apache 应用。欢迎你把过程写到留言区。相信经过动手实践,会让你对知识的理解更加深刻。
- 子路无倦 👍(2) 💬(0)
部署Apache服务器 ImageName: httpd 部署deployment touch apache-deployment.yaml 文件内容 # apache-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: test-apache-dep # Deployment 名称 spec: replicas: 3 # 副本数3个 selector: matchLabels: app: test-apache-dep template: metadata: labels: app: test-apache-dep spec: containers: - name: my-apache-dep image: httpd # apache 镜像 ports: - containerPort: 80 # 暴露端口 执行 kubectl apply -f apache-deployment.yaml 部署service touch apache-service.yaml 内容 # apache-service.yaml apiVersion: v1 kind: Service metadata: name: apache-service spec: selector: app: test-apache-dep ports: - protocol: TCP port: 80 targetPort: 80 type: NodePort # 类型是 NodePort kubectl apply -f apache-service.yaml 查看状态: kubectl get po/svc 验证: curl -X GET http://172.22.1.121:31254 Resp: <html><body><h1>It works!</h1></body></html>
2024-12-25 - AMI 👍(1) 💬(1)
在部署nginx镜像的时候,没有拉到nginx镜像,怎么用解决这个问题,不好意思,k8s,我真的是零基础 [root@k8s-master ~]# kubectl get pod NAME READY STATUS RESTARTS AGE nginx-deployment-kc-7c9b7fbfc7-5xdbk 0/1 ImagePullBackOff 0 7m49s nginx-deployment-kc-7c9b7fbfc7-f4kqc 0/1 ImagePullBackOff 0 7m49s nginx-deployment-kc-7c9b7fbfc7-l7lfd 0/1 ImagePullBackOff 0 7m49s
2024-10-25