Kubernetes超详细教程,一篇文章帮助你从零开始学习k8s,从入门到实战
k8s 概述
k8s github地址:https://github.com/kubernetes/kubernetes
官方文档:https://kubernetes.io/zh-cn/docs/home/
k8s,全程是 kubernetes,这个名字源于希腊语,意为"舵手"或"飞行员”
k8s 这个缩写是因为 k 和 s 之间有八个字符
Google 在2014年开源了 k8s 项目,k8s 是一个用于自动化部署、扩展和管理容器化应用程序的开源系统。同样类似的容器编排工具还有 docker swarm/mesos 等,但 k8s 应用最为广泛,社区更为活跃。
什么是 k8s
k8s 是一个开源的容器编排平台,用于自动化部署、扩展和管理容器化应用程序。它最初由 Google 开发,现由 Cloud Native Computing Foundation(CNCF)维护。k8s 的目标是简化应用程序的部署和管理,提供弹性、可扩展、高可用的服务。
k8s 基于容器技术,如 docker,作为应用程序的基本构建块。容器是一种轻量级的虚拟化技术,可以将应用程序及其依赖项打包到一个独立的、可移植的运行环境中。通过使用容器,开发者可以将应用程序与其运行环境隔离开来,并实现快速部署和跨平台运行。
k8s 提供了一套丰富的功能,用于管理容器化应用的生命周期。它的核心概念包括:
Pod
:Pod 是 k8s 管理的最小调度单位,它可以包含一个或多个容器,并共享网络和存储资源。Pod 提供了容器之间的通信和协作。Deployment
:Deployment 定义了应用程序的期望状态,并负责创建和管理 Pod 的副本。它支持滚动更新、回滚和扩缩容等操作。Service
:Service 定义了一组 Pod 的访问方式和网络策略,为 Pod 提供了稳定的网络端点。Service 可以通过负载均衡将请求分发到后端的 Pod上。Namespace
:Namespace 提供了一种逻辑隔离的机制,用于将集群中的资源划分为多个虚拟集群。不同的 Namespace 可以拥有独立的资源配额、访问控制策略等。Volume
:Volume 是用于持久化数据的抽象,它可以在 Pod 之间共享和持久化存储数据。k8s 支持多种类型的 Volume,如本地磁盘、网络存储等。
除了上述核心概念之外,k8s 还提供了许多其他功能,包括自动扩展、存储管理、配置管理、日志和监控等。它支持水平扩展和自动化恢复,可以根据应用程序的资源需求和约束条件自动调度和管理容器的运行。k8s 还提供了丰富的 API 和命令行工具,使得开发者和运维人员可以方便地管理和操作容器化应用。
k8s 的设计目标是高度可扩展和高可用的,可以在大规模的集群上运行和管理应用程序。它可以部署在各种云平台和裸机环境中,支持多种操作系统和容器运行时。k8s 已经成为容器编排领域的事实标准,被广泛应用于云原生应用的开发和运维中。
为什么要使用 k8s
当你的应用只是跑在一台机器,直接一个 docker + docker-compose 就够了,方便轻松;
当你的应用需要跑在3、4台机器上,你依旧可以每台机器单独配置运行环境 + 负载均衡;
当你应用访问数不断增加,机器逐渐增加到十几台、上百台、上千台时,每次加机器、软件更新、版本回滚,都会变得非常麻烦、痛不欲生
这时候,k8s 就可以一展身手了;
它是一个全新的基于容器技术的分布式架构领先方案,是谷歌十几年依赖大规模应用容器技术的经验积累和升华的一个重要成果。
运维、部署问题。集群拓展问题、容器编排管理问题
若是咱们的系统设计遵循了 k8s 的设计思想,那么传统系统架构中那些和业务没有多大关系的底层代码或功能模块,均可以马上从咱们的视线消失,咱们没必要再费心于负载均衡器和部署实施问题,没必要再考虑引用或本身开发一个复杂的服务治理框架,没必要再头疼于服务监控和故障处理模块的开发。使用 k8s 提供的解决方案,咱们节省了超过30%的开发成本,同时能够将精力更加集中于业务自己,并且因为 k8s 提供了强大的自动化机制,因此系统后期的运维难度和运维成本也大幅度下降。
k8s 是一个开放的开发平台。没有限定任何编程接口,因此不管是 Java、Go、C++ 还是用 python 编写的服务,均可以毫无困难地映射为 k8s 的Service,并经过标准的 TCP 通讯协议进行交互。此外,因为 k8s 平台对现有的编程语言、编程框架、中间价没有任何侵入性,所以现有的系统很容易改造升级并迁移到 k8s 平台上。
IT 行业历来都是一个由新技术驱动的行业。
新兴的容器化技术当前已经被不少公司所采用,其从单机走向集群已成为必然,而云计算的蓬勃发展正在加速这一进程。k8s 做为当前惟一被业界普遍承认和看好的容器分布式系统解决方案,能够预见,在将来几年内,会有大量的新系统选择它,无论这些系统是运行在企业本地服务器或者是被托管到公有云上。
项目部署的发展历程
谈起 k8s 的发展历史,首先回顾一下项目部署的发展历程,分布经历了物理机、虚拟机、容器化三个阶段的演变。
- 传统部署时代:
早期,应用程序直接在物理服务器上运行,无法为物理服务器中的应用程序定义资源边界,这会导致资源分配问题。例如,如果在物理服务器上运行多个应用程序,则可能会出现一个应用程序占用大部分资源的情况,结果可能导致其他应用程序的性能下降。一种解决方案是在不同的物理服务器上运行每个应用程序,但是由于资源利用不足而无法扩展,并且维护许多物理服务器的成本很高。
- 虚拟化部署时代:
为了解决物理机存在的弊端,引入了虚拟化技术,支持在单个物理服务器的 CPU 上运行多个虚拟机(VM),每个 VM 是一台完整的计算机,在虚拟化硬件之上运行所有组件,包括其自己的操作系统。虚拟化技术允许应用程序在 VM 之间隔离,提供一定程度的安全,一个应用程序的信息不能被另一应用程序随意访问。虚拟化技术能够更好地利用物理服务器上的资源,由于可轻松地添加或更新应用程序而实现更好的可伸缩性,降低了硬件成本。
- 容器部署时代:
容器类似于 VM,但是具有被放宽的隔离属性,可以在应用程序之间共享操作系统,因此容器被认为是轻量级的隔离。容器与 VM 类似,具有自己的文件系统、CPU、内存、进程空间等,由于它们与基础架构分离,因此可以跨云和操作系统发行版本进行移植。
问题出现:一旦容器多了,如何进行管理
随着微服务、容器化等技术的发展,解决了资源利用率不高的问题,但是随之而来却是如何进行容器管理,过多的容器使得运维工作也成为了一种负担,因此容器编排对于大型依托于容器化部署的分布式系统至关重要。在容器编排方面,k8s 所扮演的角色如下图所示:
k8s 相当于在容器之上,对服务器资源以及容器调度等过程进行管理
k8s 的特点与功能
特点:
- 可移植:支持公有云,私有云,混合云,多重云;
- 可扩展:模块化,插件化,可挂载,可组合;
- 自动化:自动部署,自动重启,自动复制,自动伸缩/扩展。
功能:
- 自动装箱:基于容器对应用运行环境的资源配置要求自动部署应用容器。
- 自我修复(自愈能力):当容器失败时,会对容器进行重启;当所部署的 Node 节点有问题时,会对容器进行重新部署和重新调度;当容器未通过监控检查时,会关闭此容器直到容器正常运行时,才会对外提供服务。
- 水平扩展:通过简单的命令、用户UI 界面或基于 CPU 等资源使用情况,对应用容器进行规模扩大或规模剪裁。
- 服务发现:用户不需使用额外的服务发现机制,就能够基于 k8s 自身能力实现服务发现和负载均衡。
- 滚动更新:可以根据应用的变化,对应用容器运行的应用,进行一次性或批量式更新。
- 版本回退:可以根据应用部署情况,对应用容器运行的应用,进行历史版本即时回退。
- 密钥和配置管理:在不需要重新构建镜像的情况下,可以部署和更新密钥和应用配置,类似热部署。
- 存储编排:自动实现存储系统挂载及应用,特别对有状态应用实现数据持久化非常重要,存储系统可以来自于本地目录、网络存储(NFS、Gluster、Ceph、Cinder 等)公共云存储服务等
k8s 优点
k8s 作为一个容器编排平台,具有许多优点,使其成为云原生应用开发和运维的首选工具
- 自动化管理:k8s 可以自动化地部署、扩展和管理应用程序。它提供了丰富的功能,如自动调度、自动伸缩、自动恢复等,减轻了人工管理的负担,提高了应用程序的可靠性和稳定性。
- 弹性扩展:k8s 支持水平扩展,可以根据应用程序的负载情况动态调整应用程序的副本数量。当负载增加时,k8s 可以自动添加新的副本来处理更多的请求,当负载减少时,k8s 可以自动缩减副本数量,以节省资源。
- 高可用性:k8s 具有高可用性的设计,可以在集群中自动进行容器的调度和迁移,以实现故障转移和负载均衡。它可以检测到容器或节点的故障,并自动重新调度容器到可用节点上,从而确保应用程序的连续可用性。
- 灵活的部署模型:k8s 可以部署各种类型的应用程序,包括微服务架构、传统的单体应用程序、批处理作业等。它提供了丰富的部署配置选项,可以根据应用程序的需求进行定制化配置,并支持多种部署策略,如滚动更新、蓝绿部署等。
- 跨平台和云厂商无关性:k8s 可以在各种云平台和裸机环境中部署和运行,它与特定的操作系统和容器运行时无关。这意味着开发者可以在不同的环境中无缝迁移应用程序,而不必担心依赖于特定的硬件或软件。
- 强大的生态系统:k8s 拥有庞大的社区和丰富的生态系统,提供了许多插件和工具,用于扩展和增强其功能。开发者可以从这些插件中选择适合自己需求的工具,以满足特定的开发和运维需求。
- 可观测性和监控:k8s 提供了丰富的监控和日志功能,可以实时监控应用程序的状态和性能指标,帮助开发者快速诊断和解决问题。它还支持集成外部监控工具和日志分析系统,以进一步增强可观测性。
总的来说,k8s 具有自动化管理、弹性扩展、高可用性、灵活的部署模型、跨平台和云厂商无关性、强大的生态系统以及可观测性和监控等优点,使其成为容器编排领域的事实标准,被广泛应用于云原生应用的开发和运维中。
k8s 设计架构
k8s 集群 = 多个 master node + 多个 work node
k8s 中包含了很多新的概念,它通过整合资源,提供了一套便于应用部署的方案及实现,极大减少了系统运维的工作量。
官方架构设计图:
k8s 通常是集群化部署,一个 k8s 集群由一组被称作节点(Node)的机器组成,一个节点可以理解为一台服务器,这些节点上运行 k8s 所管理的容器化应用。集群具有至少一个控制节点(MasterNode)和若干工作节点(WorkNode),节点可以是物理机或者虚拟机。
控制节点包含了控制平面(Contro Plane),控制平面中的组件用来管理整个集群,工作节点用来托管对应的工作负载 Pod。
一般来说节点上都会包含 kubelet、kube-proxy 等组件以及容器运行时。
需要知道的一些概念:
- 控制平面:让我们从 k8s 集群的神经中枢(即控制平面)开始说起。在这里,我们可以找到用于控制集群的 k8s 组件以及一些有关集群状态和配置的数据。这些核心 k8s 组件负责处理重要的工作,以确保容器以足够的数量和所需的资源运行。 控制平面会一直与您的计算机保持联系。集群已被配置为以特定的方式运行,而控制平面要做的就是确保万无一失。
- kube-apiserver:如果需要与您的 k8s 集群进行交互,就要通过 API。k8s API 是 k8s 控制平面的前端,用于处理内部和外部请求。API 服务器会确定请求是否有效,如果有效,则对其进行处理。您可以通过 REST 调用、kubectl 命令行界面或其他命令行工具(例如 kubeadm)来访问 API。
- kube-scheduler:您的集群是否状况良好?如果需要新的容器,要将它们放在哪里?这些是 k8s 调度程序所要关注的问题。调度程序会考虑容器集的资源需求(例如 CPU 或内存)以及集群的运行状况。随后,它会将容器集安排到适当的计算节点。
- kube-controller-manager:控制器负责实际运行集群,而 k8s 控制器管理器则是将多个控制器功能合而为一。控制器用于查询调度程序,并确保有正确数量的容器集在运行。如果有容器集停止运行,另一个控制器会发现并做出响应。控制器会将服务连接至容器集,以便让请求前往正确的端点。还有一些控制器用于创建帐户和 API 访问令牌。
- etcd:配置数据以及有关集群状态的信息位于 etcd(一个键值存储数据库)中。etcd 采用分布式、容错设计,被视为集群的最终事实来源。
- 容器集 Pod:容器集是 k8s 对象模型中最小、最简单的单元。它代表了应用的单个实例。每个容器集都由一个容器(或一系列紧密耦合的容器)以及若干控制容器运行方式的选件组成。容器集可以连接至持久存储,以运行有状态应用。
- 容器运行时引擎:为了运行容器,每个计算节点都有一个容器运行时引擎。比如 docker,但 k8s 也支持其他符合开源容器运动(OCI)标准的运行时,例如 rkt 和 CRI-O。
- kubelet:每个计算节点中都包含一个 kubelet,这是一个与控制平面通信的微型应用。kubelet 可确保容器在容器集内运行。当控制平面需要在节点中执行某个操作时,kubelet 就会执行该操作。
- kube-proxy:每个计算节点中还包含 kube-proxy,这是一个用于优化 k8s 网络服务的网络代理。kube-proxy 负责处理集群内部或外部的网络通信。
k8s 使用场景
k8s 适用于各种使用场景,尤其适用于云原生应用的开发和运维。以下是一些常见的k8s 使用场景:
- 微服务架构:k8s 可以有效地管理和部署微服务架构。它可以将不同的微服务部署为独立的容器,通过 Service 和 Ingress 等机制实现微服务之间的通信和负载均衡。k8s 提供了弹性扩展和自动恢复的能力,可以根据负载情况动态调整微服务的副本数量,确保高可用性和性能。
- 自动化部署和持续集成/持续交付(CI/CD):k8s 可以与 CI/CD 工具集成,实现自动化的部署和持续交付。开发者可以使用 k8s 的 Deployment 和Service 等资源对象定义应用程序的期望状态,并通过 CI/CD 工具自动构建、测试和发布应用程序到 k8s 集群中。
- 弹性扩展和负载均衡:k8s 支持水平扩展,可以根据应用程序的负载情况动态调整副本数量。它可以根据负载自动添加或删除容器实例,并通过Service 和 Ingress 等机制实现负载均衡,确保请求能够平均分发到后端的容器上。
- 多租户和多环境管理:k8s 提供了 Namespace 的概念,可以将集群中的资源划分为多个虚拟集群,实现多租户的管理。通过使用不同的Namespace,可以将不同的应用程序或不同的环境(如开发、测试、生产)隔离开来,提供更好的资源隔离和安全性。
- 批处理和定时任务:k8s 可以用于批处理作业和定时任务的管理。通过使用 CronJob 等资源对象,可以定义和调度定时任务,例如数据处理、报表生成等。k8s 提供了任务的并行执行、故障恢复和任务状态监控等功能,适用于处理大规模的批处理工作负载。
- 混合云和多云环境管理:k8s 具有跨平台和云厂商无关性的特性,可以在混合云和多云环境中部署和管理应用程序。它可以在不同的云平台上运行,如 AWS、Azure、Google Cloud 等,同时也可以在私有云和裸机环境中部署。这使得开发者可以在不同的环境中无缝迁移应用程序,并减少对特定云厂商的依赖。
总的来说,k8s 适用于微服务架构、自动化部署和 CI/CD、弹性扩展和负载均衡、多租户和多环境管理、批处理和定时任务,以及混合云和多云环境管理等多种使用场景。它提供了丰富的功能和灵活的配置选项,使开发者能够更方便地管理和运维容器化应用程序。
minikube 安装
minikube 是一个用于在本地计算机上运行单个节点的 k8s 集群的工具。它允许开发人员可以在自己的计算机上进行本地的 k8s 开发和测试。通过minikube,您可以模拟一个完整的 k8s 集群环境,包括节点、Pod、服务和存储等组件。它是一个轻量级、易于安装和使用的工具,适用于在本地进行 k8s 相关的开发、测试和学习。
徒手搭建过 k8s 的同学都晓得其中的煎熬,复杂的认证,配置环节相当折磨人,出错率相当高,而 minikube 就是为解决这个问题而衍生出来的工具,minikube 可以在单机环境下快速搭建可用的 k8s 集群,非常适合测试和本地开发,现有的大部分在线 k8s 实验环境也是基于 minikube 的。
可以在 minikube 上体验 kubernetes 的相关功能。
minikube 基于 go 语言开发,可以在单机环境下快速搭建可用的 k8s 集群,快速启动,消耗机器资源较少,可在你的笔记本电脑上的虚拟机内轻松创建单机版 k8s 集群,非常适合测试和本地开发。
minikube 架构
下图是 minikube的架构,可以看出,master 节点与其它节点合为一体,而整体则通过宿主机上的 kubectl 进行管理,这样可以更加节省资源。
其支持大部分 k8s 的功能,列表如下:
DNS
NodePorts
ConfigMaps and Secrets
Dashboards
Container Runtime: Docker, and rkt
Enabling CNI (Container Network Interface)
Ingress
…
minikube 支持 Windows、macOS、Linux 三种 OS系统,会根据平台不同,下载对应的虚拟机镜像,并在镜像内安装 K8S。
我们这里直接使用 Windows 安装体验。
minikube 安装
下载步骤:
- 安装 docker
-
下载地址:https://docs.docker.com/desktop/install/windows-install/
-
知道下载后的
Docker for Windows Installer
安装文件,完成安装。 -
安装好之后会重启
安装好后如图所示
- 安装 minikube
minikube 下载地址 https://minikube.sigs.k8s.io/docs/start/
1、点击这里下载安装程序minikube-installer.exe
,安装即可
2、配置环境变量
3、命令行测试,需要保证 docker 启动
minikube 常用命令
查看 minikube 版本
minikube version
C:UsersDELL>minikube version
W0323 17:19:55.916748 1800 main.go:291] Unable to resolve the current Docker CLI context "default": context "default": context not found: open C:UsersDELL.dockercontextsmeta37a8eec1ce19687d132fe29051dca629d164e2c4958ba141d5f4133a33f0688fmeta.json: The system cannot find the path specified.
minikube version: v1.32.0
commit: 8220a6eb95f0a4d75f7f2d7b14cef975f050512d
启动 minikube
minikube start
C:UsersDELL>minikube start
W0323 17:24:17.006260 23440 main.go:291] Unable to resolve the current Docker CLI context "default": context "default": context not found: open C:UsersDELL.dockercontextsmeta37a8eec1ce19687d132fe29051dca629d164e2c4958ba141d5f4133a33f0688fmeta.json: The system cannot find the path specified.
* Microsoft Windows 11 Home China 10.0.22631.3296 Build 22631.3296 上的 minikube v1.32.0
* 根据现有的配置文件使用 docker 驱动程序
* 正在集群 minikube 中启动控制平面节点 minikube
* 正在拉取基础镜像 ...
> index.docker.io/kicbase/sta...: 453.90 MiB / 453.90 MiB 100.00% 2.61 Mi
! minikube was unable to download gcr.io/k8s-minikube/kicbase:v0.0.42, but successfully downloaded docker.io/kicbase/stable:v0.0.42 as a fallback image
* Creating docker container (CPUs=2, Memory=4000MB) ...
* 正在 Docker 24.0.7 中准备 Kubernetes v1.28.3…
- 正在生成证书和密钥...
- 正在启动控制平面...
- 配置 RBAC 规则 ...
* 配置 bridge CNI (Container Networking Interface) ...
* 正在验证 Kubernetes 组件...
- 正在使用镜像 gcr.io/k8s-minikube/storage-provisioner:v5
* 启用插件: storage-provisioner, default-storageclass
* 完成!kubectl 现在已配置,默认使用"minikube"集群和"default"命名空间
检查 minikube 集群状态
minikube status
C:UsersDELL>minikube status
W0323 17:30:34.612462 4616 main.go:291] Unable to resolve the current Docker CLI context "default": context "default": context not found: open C:UsersDELL.dockercontextsmeta37a8eec1ce19687d132fe29051dca629d164e2c4958ba141d5f4133a33f0688fmeta.json: The system cannot find the path specified.
minikube
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured
获取 minikube 集群的 ip 地址
minikube ip
C:UsersDELL>minikube ip
W0323 17:31:38.368205 2484 main.go:291] Unable to resolve the current Docker CLI context "default": context "default": context not found: open C:UsersDELL.dockercontextsmeta37a8eec1ce19687d132fe29051dca629d164e2c4958ba141d5f4133a33f0688fmeta.json: The system cannot find the path specified.
192.168.49.2
通过 SSH 连接到正在运行的 minikube 集群
minikube ssh
C:UsersDELL>minikube ssh
W0323 17:34:12.883919 24608 main.go:291] Unable to resolve the current Docker CLI context "default": context "default": context not found: open C:UsersDELL.dockercontextsmeta37a8eec1ce19687d132fe29051dca629d164e2c4958ba141d5f4133a33f0688fmeta.json: The system cannot find the path specified.
# 查看集群下所有的 docker 容器
docker@minikube:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1407610b3a2f 6e38f40d628d "/storage-provisioner" 6 minutes ago Up 6 minutes k8s_storage-provisioner_storage-provisioner_kube-system_d4ee5dfb-c7e0-441c-baa2-12474b5ad5c4_1
f6403b614117 ead0a4a53df8 "/coredns -conf /etc…" 7 minutes ago Up 7 minutes k8s_coredns_coredns-5dd5756b68-w9wgv_kube-system_0a9ad253-2304-447e-8ab3-2f06da88a721_0
606d3bac1dbb registry.k8s.io/pause:3.9 "/pause" 7 minutes ago Up 7 minutes k8s_POD_coredns-5dd5756b68-w9wgv_kube-system_0a9ad253-2304-447e-8ab3-2f06da88a721_0
4cdfd56f9d60 bfc896cf80fb "/usr/local/bin/kube…" 7 minutes ago Up 7 minutes k8s_kube-proxy_kube-proxy-cdq9d_kube-system_2f2aca3c-4d8c-45c1-8efc-b7d0d4938025_0
821e8c045d0c registry.k8s.io/pause:3.9 "/pause" 7 minutes ago Up 7 minutes k8s_POD_kube-proxy-cdq9d_kube-system_2f2aca3c-4d8c-45c1-8efc-b7d0d4938025_0
c7f05331626d registry.k8s.io/pause:3.9 "/pause" 7 minutes ago Up 7 minutes k8s_POD_storage-provisioner_kube-system_d4ee5dfb-c7e0-441c-baa2-12474b5ad5c4_0
ae5966109c8a 6d1b4fd1b182 "kube-scheduler --au…" 7 minutes ago Up 7 minutes k8s_kube-scheduler_kube-scheduler-minikube_kube-system_75ac196d3709dde303d8a81c035c2c28_0
49f497991344 10baa1ca1706 "kube-controller-man…" 7 minutes ago Up 7 minutes k8s_kube-controller-manager_kube-controller-manager-minikube_kube-system_7da72fc2e2cfb27aacf6cffd1c72da00_0
51420b3b4a70 73deb9a3f702 "etcd --advertise-cl…" 7 minutes ago Up 7 minutes k8s_etcd_etcd-minikube_kube-system_9aac5b5c8815def09a2ef9e37b89da55_0
982fdca2d503 537434729123 "kube-apiserver --ad…" 7 minutes ago Up 7 minutes k8s_kube-apiserver_kube-apiserver-minikube_kube-system_55b4bbe24dac3803a7379f9ae169d6ba_0
7f2976f13746 registry.k8s.io/pause:3.9 "/pause" 7 minutes ago Up 7 minutes k8s_POD_kube-scheduler-minikube_kube-system_75ac196d3709dde303d8a81c035c2c28_0
b2b10a4815fa registry.k8s.io/pause:3.9 "/pause" 7 minutes ago Up 7 minutes k8s_POD_kube-controller-manager-minikube_kube-system_7da72fc2e2cfb27aacf6cffd1c72da00_0
eff72a86aa15 registry.k8s.io/pause:3.9 "/pause" 7 minutes ago Up 7 minutes k8s_POD_kube-apiserver-minikube_kube-system_55b4bbe24dac3803a7379f9ae169d6ba_0
7236c52d6a38 registry.k8s.io/pause:3.9 "/pause" 7 minutes ago Up 7 minutes k8s_POD_etcd-minikube_kube-system_9aac5b5c8815def09a2ef9e37b89da55_0
停止服务 minikube
minikube stop
启动 minikube 的仪表板(可视化界面),执行此命令后,将自动打开一个浏览器窗口,显示 minikube 集群的仪表板界面
minikube dashboard
C:UsersDELL>minikube dashboard
W0323 17:40:48.423278 11632 main.go:291] Unable to resolve the current Docker CLI context "default": context "default": context not found: open C:UsersDELL.dockercontextsmeta37a8eec1ce19687d132fe29051dca629d164e2c4958ba141d5f4133a33f0688fmeta.json: The system cannot find the path specified.
* 正在开启 dashboard ...
- 正在使用镜像 docker.io/kubernetesui/dashboard:v2.7.0
- 正在使用镜像 docker.io/kubernetesui/metrics-scraper:v1.0.8
* 某些 dashboard 功能需要启用 metrics-server 插件。为了启用所有功能,请运行以下命令:
minikube addons enable metrics-server
* 正在验证 dashboard 运行情况 ...
* 正在启动代理...
* 正在验证 proxy 运行状况 ...
^C
C:UsersDELL>minikube dashboard
W0323 17:41:42.866075 25216 main.go:291] Unable to resolve the current Docker CLI context "default": context "default": context not found: open C:UsersDELL.dockercontextsmeta37a8eec1ce19687d132fe29051dca629d164e2c4958ba141d5f4133a33f0688fmeta.json: The system cannot find the path specified.
* 正在验证 dashboard 运行情况 ...
* 正在启动代理...
* 正在验证 proxy 运行状况 ...
* 正在使用默认浏览器打开 http://127.0.0.1:59903/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/ ...
停止 minikube 集群服务
minikube stop
C:UsersDELL>minikube stop
W0323 17:53:55.131539 25916 main.go:291] Unable to resolve the current Docker CLI context "default": context "default": context not found: open C:UsersDELL.dockercontextsmeta37a8eec1ce19687d132fe29051dca629d164e2c4958ba141d5f4133a33f0688fmeta.json: The system cannot find the path specified.
* 正在停止节点 "minikube" ...
* 正在通过 SSH 关闭“minikube”…
* 1 个节点已停止。
可以通过以下命令获取 minibuke 相关信息
# 获取所有节点
kubectl get node
C:UsersDELL>kubectl get node
NAME STATUS ROLES AGE VERSION
minikube Ready control-plane 17m v1.28.3
# 获取所有命名空间中的Pod列表
kubectl get pods -A
C:UsersDELL>kubectl get pods -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-5dd5756b68-w9wgv 1/1 Running 0 19m
kube-system etcd-minikube 1/1 Running 0 19m
kube-system kube-apiserver-minikube 1/1 Running 0 19m
kube-system kube-controller-manager-minikube 1/1 Running 0 19m
kube-system kube-proxy-cdq9d 1/1 Running 0 19m
kube-system kube-scheduler-minikube 1/1 Running 0 19m
kube-system storage-provisioner 1/1 Running 1 (18m ago) 19m
kubernetes-dashboard dashboard-metrics-scraper-7fd5cb4ddc-lxkt2 1/1 Running 0 7m45s
kubernetes-dashboard kubernetes-dashboard-8694d4445c-sl6cc 1/1 Running 0 7m45s
服务器裸机搭建 k8s 集群
环境准备
- 至少3个服务器(本次使用3台阿里云服务器),4核4G以上(按量付费),内网要能互相通信,也就是必须要在同一个网段下
本次实验的3个服务器私网 ip 如下:
192.168.0.1 (主机)
192.168.0.2
192.168.0.3
这3个服务器一台为 master node(初始化主节点)、两台 work node(工作节点)
- 3个服务器都要安装 docker
3个服务器同时执行命令:
在输入命令行位置右键发送键输入到所有会话
# 移除之前安装的 docker
sudo yum remove docker
docker-client
docker-client-latest
docker-common
docker-latest
docker-latest-logrotate
docker-logrotate
docker-engine
# 安装 gcc 环境
sudo yum install -y gcc
sudo yum install -y gcc-c++
# 配置yum源
sudo yum install -y yum-utils
# 使用国内的镜像。
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 更新 yum 索引
sudo yum makecache fast
# 安装 docker
sudo yum install -y docker-ce docker-ce-cli containerd.io
# 配置阿里云镜像加速,在自己的阿里云镜像加速器查看
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://g8vxwvax.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
# 设置开机启动Docker
sudo systemctl enable docker
# 检查是否安装成功
docker -v
- 安装 k8s 前的系统环境准备,官方要求
# 节点之中不可以有重复的主机名,mac地址等,设置不同的hostname
# 3个服务器分别执行
hostnamectl set-hostname k8s-master
hostnamectl set-hostname k8s-node1
hostnamectl set-hostname k8s-node2
# 3台服务器全部执行
# 关闭防火墙
sudo systemctl stop firewalld
sudo systemctl disable firewalld
# 将 SElinux 设置为 permissive 模式,禁用
sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcin$/SELINUX=permissive/' /etc/selinux/config
# 关闭swap分区
sudo swapoff -a
sudo sed -ri 's/.*swap.*/#&/' /etc/fstab
# 允许 iptables 检查桥接流量(所有节点)
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sudo sysctl --system
至此,我们的所有环境就配置好了,接下来就要搭建 k8s 集群了
安装集群三大件 kubelet、kubeadm、kubectl
你需要在每台机器上安装以下的软件包:
kubeadm
:用来初始化集群的指令。kubelet
:在集群中的每个节点上用来启动 Pod 和容器等。kubectl
:用来与集群通信的命令行工具。
参考阿里巴巴开源镜像站 k8s 安装步骤:https://developer.aliyun.com/mirror/kubernetes
# 3台服务器全部执行
# 安装 kubeadm、kubelet 和 kubectl,配置yum文件,因为国内无法直接访问google,这里需要将官网中的google的源改为国内源
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
setenforce 0
yum install -y kubelet kubeadm kubectl
systemctl enable kubelet && systemctl start kubelet
# 查看版本信息
kubectl version
在 k8s v1.24 及更早版本中,我们使用 docker 作为容器引擎在 k8s 上使用时,依赖一个 dockershim 的内置 k8s 组件,k8s v1.24发行版中将dockershim 组件给移除了,取而代之的就是 cri-dockerd(当然还有其它容器接口),简单讲 CRI 就是容器运行时接口(Container Runtime Interface,CRI),也就是说 cri-dockerd 就是以 docker 作为容器引擎而提供的容器运行时接口,如果我们想要用 docker 作为 k8s 的容器运行引擎,我们需要先部署好 cri-dockerd,用 cri-dockerd 来与 kubelet 交互,然后再由 cri-dockerd 和 docker api 交互,使我们在 k8s 能够正常使用 docker 作为容器引擎。
# 下载
wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.4/cri-dockerd-0.3.4.amd64.tgz
# 解压cri-docker
tar xvf cri-dockerd-*.amd64.tgz
cp -r cri-dockerd/ /usr/bin/
chmod +x /usr/bin/cri-dockerd/cri-dockerd
# 写入启动cri-docker配置文件
cat > /usr/lib/systemd/system/cri-docker.service <<EOF
[Unit]
Description=CRI Interface for Docker Application Container Engine
Documentation=https://docs.mirantis.com
After=network-online.target firewalld.service docker.service
Wants=network-online.target
Requires=cri-docker.socket
[Service]
Type=notify
ExecStart=/usr/bin/cri-dockerd/cri-dockerd --network-plugin=cni --pod-infra-container-image=registry.aliyuncs.com/google_containers/pause:3.7
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
StartLimitBurst=3
StartLimitInterval=60s
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TasksMax=infinity
Delegate=yes
KillMode=process
[Install]
WantedBy=multi-user.target
EOF
# 写入cri-docker的socket配置文件
cat > /usr/lib/systemd/system/cri-docker.socket <<EOF
[Unit]
Description=CRI Docker Socket for the API
PartOf=cri-docker.service
[Socket]
ListenStream=%t/cri-dockerd.sock
SocketMode=0660
SocketUser=root
SocketGroup=docker
[Install]
WantedBy=sockets.target
EOF
# 当你新增或修改了某个单位文件(如.service文件、.socket文件等),需要运行该命令来刷新systemd对该文件的配置。
systemctl daemon-reload
# 确保docker是启动的
# 启用并立即启动cri-docker.service单元。
systemctl enable --now cri-docker.service
# 显示docker.service单元的当前状态,包括运行状态、是否启用等信息。
systemctl status cri-docker.service
出现以下内容说明启动成功:
[root@k8s-master ~]# systemctl status cri-docker.service
● cri-docker.service - CRI Interface for Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/cri-docker.service; enabled; vendor preset: disabled)
Active: active (running) since Sun 2024-03-24 16:01:06 CST; 9s ago
Docs: https://docs.mirantis.com
Main PID: 3238 (cri-dockerd)
Tasks: 9
Memory: 14.5M
CGroup: /system.slice/cri-docker.service
└─3238 /usr/bin/cri-dockerd/cri-dockerd --network-plugin=cni --pod-infra-container-image=registry.aliyuncs.com/googl...
Mar 24 16:01:06 k8s-master cri-dockerd[3238]: time="2024-03-24T16:01:06+08:00" level=info msg="Start docker client with r...ut 0s"
Mar 24 16:01:06 k8s-master cri-dockerd[3238]: time="2024-03-24T16:01:06+08:00" level=info msg="Hairpin mode is set to none"
Mar 24 16:01:06 k8s-master cri-dockerd[3238]: time="2024-03-24T16:01:06+08:00" level=info msg="Loaded network plugin cni"
Mar 24 16:01:06 k8s-master cri-dockerd[3238]: time="2024-03-24T16:01:06+08:00" level=info msg="Docker cri networking mana...n cni"
Mar 24 16:01:06 k8s-master cri-dockerd[3238]: time="2024-03-24T16:01:06+08:00" level=info msg="Docker Info: &{ID:a848d1ba... [Nati
Mar 24 16:01:06 k8s-master cri-dockerd[3238]: time="2024-03-24T16:01:06+08:00" level=info msg="Setting cgroupDriver cgroupfs"
Mar 24 16:01:06 k8s-master cri-dockerd[3238]: time="2024-03-24T16:01:06+08:00" level=info msg="Docker cri received runtim...:,},}"
Mar 24 16:01:06 k8s-master cri-dockerd[3238]: time="2024-03-24T16:01:06+08:00" level=info msg="Starting the GRPC backend ...face."
Mar 24 16:01:06 k8s-master cri-dockerd[3238]: time="2024-03-24T16:01:06+08:00" level=info msg="Start cri-dockerd grpc backend"
Mar 24 16:01:06 k8s-master systemd[1]: Started CRI Interface for Docker Application Container Engine.
Hint: Some lines were ellipsized, use -l to show in full.
总结:环境准备
- 机器环境
- 安装了 k8s 的组件
- 安装 cri 环境
安装并初始化 master 节点
# 所有机器添加master节点的域名映射,这里要改为自己当下master的ip
echo "192.168.0.1 cluster-master" >> /etc/hosts
# node节点ping测试映射是否成功
ping cluster-master
# 如果init失败,可以kubeadm重置
kubeadm reset --cri-socket unix:///var/run/cri-dockerd.sock
####### 主节点初始化(只在master执行) #######
# 注意修改apiserver的地址为master节点的ip
## 注意service、pod的网络节点不能和master网络ip重叠
kubeadm init
--apiserver-advertise-address=192.168.0.1
--control-plane-endpoint=cluster-master
--image-repository registry.cn-hangzhou.aliyuncs.com/google_containers
--kubernetes-version v1.28.2
--service-cidr=10.96.0.0/16
--pod-network-cidr=192.169.0.0/16
--cri-socket unix:///var/run/cri-dockerd.sock
等待命令运行完毕即可,执行成功后可以看到
[root@k8s-master ~]# kubeadm init
> --apiserver-advertise-address=192.168.0.1
> --control-plane-endpoint=cluster-master
> --image-repository registry.cn-hangzhou.aliyuncs.com/google_containers
> --kubernetes-version v1.28.2
> --service-cidr=10.96.0.0/16
> --pod-network-cidr=192.169.0.0/16
> --cri-socket unix:///var/run/cri-dockerd.sock
[init] Using Kubernetes version: v1.28.2
......
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Alternatively, if you are the root user, you can run:
export KUBECONFIG=/etc/kubernetes/admin.conf
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
You can now join any number of control-plane nodes by copying certificate authorities
and service account keys on each node and then running the following as root:
kubeadm join cluster-master:6443 --token 9jk1zp.v738zd885ew7m7lp
--discovery-token-ca-cert-hash sha256:6a1cb9a74d02f28b06471114e28faa8de6cbc3501eb3a9a989123840c281e85a
--control-plane
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join cluster-master:6443 --token 9jk1zp.v738zd885ew7m7lp
--discovery-token-ca-cert-hash sha256:6a1cb9a74d02f28b06471114e28faa8de6cbc3501eb3a9a989123840c281e85a
根据上面的提示信息,我们在 master 中执行以下命令:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
export KUBECONFIG=/etc/kubernetes/admin.conf
初始化完成后,可以使用命令查看节点信息了
kubectl get nodes
# 发现是 NotReady 状态
[root@k8s-master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master NotReady control-plane 5m47s v1.28.2
work 节点加入集群
加入节点命令,此命令的参数是在初始化完成后给出的,每个人的都不一样,需要复制自己生成的。
是上面初始化 master 节点执行后信息的最后几行,查看自己生成的
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join cluster-master:6443 --token 9jk1zp.v738zd885ew7m7lp
--discovery-token-ca-cert-hash sha256:6a1cb9a74d02f28b06471114e28faa8de6cbc3501eb3a9a989123840c281e85a
根据自己生成的信息执行以下命令:
kubeadm join cluster-master:6443 --token 9jk1zp.v738zd885ew7m7lp
--discovery-token-ca-cert-hash sha256:6a1cb9a74d02f28b06471114e28faa8de6cbc3501eb3a9a989123840c281e85a
--cri-socket unix:///var/run/cri-dockerd.sock
# 需要注意的是,如果由于当前版本不再默认支持docker,如果服务器使用的docker,需要在命令后面加入参数--cri-socket unix:///var/run/cri-dockerd.sock。
执行完成后,在 master 主机上查看节点信息
[root@k8s-master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master NotReady control-plane 11m v1.28.2
k8s-node1 NotReady <none> 13s v1.28.2
k8s-node2 NotReady <none> 7s v1.28.2
#另外token默认的有效期为24小时,过期之后就不能用了,需要重新创建token,操作如下
kubeadm token create --print-join-command
# 另外,短时间内生成多个token时,生成新token后建议删除前一个旧的。
# 查看命令
kubeadm token list
# 删除命令
kubeadm token delete tokenid
部署 calico
我们需要部署一个 pod 网络插件,安装 Pod 网络是 Pod 之间进行通信的必要条件,k8s 支持众多网络方案,这里选用 calico 方案。
文档:https://kubernetes.io/docs/concepts/cluster-administration/addons/
calico 历史版本地址:https://docs.tigera.io/archive#v3.1.7
# 下载calico.yml
curl https://docs.tigera.io/archive/v3.25/manifests/calico.yaml -O
我们 initmaster 上面配置的 --pod-network-cidr=192.169.0.0/16
,这里面也要对应修改
可能存在的问题:calico 默认会找 eth0 网卡,如果当前机器网卡不是这个名字,可能会无法启动,需要手动配置以下。
使用以下命令查找:
ll /etc/sysconfig/network-scripts/
框起来的就是网卡名字,我这里是 eth0。如果是用虚拟机搭建的,网卡名字可能不同
如果网卡名字不是 eth0,需要编辑calico.yaml
配置文件加入如下内容 ,在 CLUSTER_TYPE 同级目录下
- name: IP_AUTODETECTION_METHOD
value: "interface=eth0" # 改成你自己的网卡名字
网卡名字为 eth0 的则不需要配置
修改完配置后,我们应用一下,应用完毕之后需要等待一下。
kubectl apply -f calico.yaml
[root@k8s-master ~]# kubectl apply -f calico.yaml
poddisruptionbudget.policy/calico-kube-controllers created
serviceaccount/calico-kube-controllers created
serviceaccount/calico-node created
configmap/calico-config created
customresourcedefinition.apiextensions.k8s.io/bgpconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/bgppeers.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/blockaffinities.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/caliconodestatuses.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/clusterinformations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/felixconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/globalnetworkpolicies.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/globalnetworksets.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/hostendpoints.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamblocks.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamconfigs.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamhandles.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ippools.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipreservations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/kubecontrollersconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/networkpolicies.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/networksets.crd.projectcalico.org created
clusterrole.rbac.authorization.k8s.io/calico-kube-controllers created
clusterrole.rbac.authorization.k8s.io/calico-node created
clusterrolebinding.rbac.authorization.k8s.io/calico-kube-controllers created
clusterrolebinding.rbac.authorization.k8s.io/calico-node created
daemonset.apps/calico-node created
deployment.apps/calico-kube-controllers created
等待一会以后,发现我们的节点状态变为了 Ready ,就OK了
[root@k8s-master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master Ready control-plane 40m v1.28.2
k8s-node1 Ready <none> 29m v1.28.2
k8s-node2 Ready <none> 29m v1.28.2
查看所有的 pod
kubectl get pod -A
[root@k8s-master ~]# kubectl get pod -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system calico-kube-controllers-658d97c59c-wzj97 1/1 Running 0 9m18s
kube-system calico-node-f76hr 1/1 Running 0 2m10s
kube-system calico-node-llncs 1/1 Running 0 2m
kube-system calico-node-lwqjh 1/1 Running 0 109s
kube-system coredns-6554b8b87f-pbmbq 1/1 Running 0 42m
kube-system coredns-6554b8b87f-pgrq2 1/1 Running 0 42m
kube-system etcd-k8s-master 1/1 Running 0 42m
kube-system kube-apiserver-k8s-master 1/1 Running 0 42m
kube-system kube-controller-manager-k8s-master 1/1 Running 0 42m
kube-system kube-proxy-58b62 1/1 Running 0 31m
kube-system kube-proxy-b6x29 1/1 Running 0 42m
kube-system kube-proxy-jxct4 1/1 Running 0 31m
kube-system kube-scheduler-k8s-master 1/1 Running 0 42m
测试 k8s 的自愈能力
我们将一个节点关机重启,reboot。
将 k8s-node2 关机:
[root@k8s-node2 ~]# poweroff
Connection closing...Socket close.
Connection closed by foreign host.
Disconnected from remote host(k8s-node2) at 17:02:36.
Type `help' to learn how to use Xshell prompt.
在 master 主机查看节点状态:
[root@k8s-master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master Ready control-plane 49m v1.28.2
k8s-node1 Ready <none> 37m v1.28.2
k8s-node2 NotReady <none> 37m v1.28.2
发现 k8s-node2 已经是 NotReady 了,这时我们启动 k8s-node2 这台主机
等待一会,重新在 master 主机查看节点状态
[root@k8s-master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master Ready control-plane 51m v1.28.2
k8s-node1 Ready <none> 40m v1.28.2
k8s-node2 Ready <none> 39m v1.28.2
发现 k8s-node2 又自动加入到集群了
k8s 的自愈能力非常强大,主要包括以下几个方面:
-
自动重启:k8s 监控容器的状态,一旦发现容器崩溃或异常退出,会自动重启容器,确保应用持续可用。
-
自动扩缩容:k8s 基于资源利用率和负载情况,可以自动扩展或缩减容器副本的数量,以满足应用程序的需求。通过水平扩展和自动负载均衡,k8s可以动态调整容器副本的数量,提高应用程序的可伸缩性和性能。
-
自动容错和故障迁移:k8s 提供了容器的健康检查机制,可以监控容器的状态,并在容器不健康或不可访问时自动将其从集群中删除,以避免影响其他容器的正常运行。同时,k8s 还支持故障迁移,将故障容器重新部署到其他可用的节点上,以确保应用程序的高可用性。
-
自动滚动升级:k8s 支持滚动升级应用程序,可以在不中断服务的情况下逐步更新容器版本。通过逐步替换容器副本,k8s 实现了应用程序的平滑升级,降低了升级过程中的风险。
-
自动恢复:k8s 可以监控节点的健康状态,一旦发现节点故障或不可访问,会自动将容器迁移到其他可用节点上,实现容器的自动恢复。
总的来说,k8s 具有自动管理和调度容器的能力,可以监控容器的状态、自动重启容器、自动扩缩容、自动容错和故障迁移、自动滚动升级等,提供了强大的自愈能力,确保应用程序的高可用性、可伸缩性和稳定性。
安装 k8s Dashboard 可视化界面
项目地址:https://github.com/kubernetes/dashboard
编辑文件recommended.yaml
:
apiVersion: v1
kind: Namespace
metadata:
name: kubernetes-dashboard
---
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: dashboard-admin
namespace: kubernetes-dashboard
---
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
type: NodePort
ports:
- port: 443
targetPort: 8443
nodePort: 31443
selector:
k8s-app: kubernetes-dashboard
---
apiVersion: v1
kind: Secret
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard-certs
namespace: kubernetes-dashboard
type: Opaque
---
apiVersion: v1
kind: Secret
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard-csrf
namespace: kubernetes-dashboard
type: Opaque
data:
csrf: ""
---
apiVersion: v1
kind: Secret
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard-key-holder
namespace: kubernetes-dashboard
type: Opaque
---
kind: ConfigMap
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard-settings
namespace: kubernetes-dashboard
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
rules:
- apiGroups: [""]
resources: ["secrets"]
resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs", "kubernetes-dashboard-csrf"]
verbs: ["get", "update", "delete"]
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["kubernetes-dashboard-settings"]
verbs: ["get", "update"]
- apiGroups: [""]
resources: ["services"]
resourceNames: ["heapster", "dashboard-metrics-scraper"]
verbs: ["proxy"]
- apiGroups: [""]
resources: ["services/proxy"]
resourceNames: ["heapster", "http:heapster:", "https:heapster:", "dashboard-metrics-scraper", "http:dashboard-metrics-scraper"]
verbs: ["get"]
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
rules:
- apiGroups: ["metrics.k8s.io"]
resources: ["pods", "nodes"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: kubernetes-dashboard
subjects:
- kind: ServiceAccount
name: kubernetes-dashboard
namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: kubernetes-dashboard
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: kubernetes-dashboard
subjects:
- kind: ServiceAccount
name: kubernetes-dashboard
namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: dashboard-admin
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: dashboard-admin
namespace: kubernetes-dashboard
---
kind: Deployment
apiVersion: apps/v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
k8s-app: kubernetes-dashboard
template:
metadata:
labels:
k8s-app: kubernetes-dashboard
spec:
containers:
- name: kubernetes-dashboard
image: kubernetesui/dashboard:v2.0.0-rc7
imagePullPolicy: Always
ports:
- containerPort: 8443
protocol: TCP
args:
- --auto-generate-certificates
- --namespace=kubernetes-dashboard
volumeMounts:
- name: kubernetes-dashboard-certs
mountPath: /certs
- mountPath: /tmp
name: tmp-volume
livenessProbe:
httpGet:
scheme: HTTPS
path: /
port: 8443
initialDelaySeconds: 30
timeoutSeconds: 30
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsUser: 1001
runAsGroup: 2001
volumes:
- name: kubernetes-dashboard-certs
secret:
secretName: kubernetes-dashboard-certs
- name: tmp-volume
emptyDir: {}
serviceAccountName: kubernetes-dashboard
nodeSelector:
"beta.kubernetes.io/os": linux
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
---
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: dashboard-metrics-scraper
name: dashboard-metrics-scraper
namespace: kubernetes-dashboard
spec:
ports:
- port: 8000
targetPort: 8000
selector:
k8s-app: dashboard-metrics-scraper
---
kind: Deployment
apiVersion: apps/v1
metadata:
labels:
k8s-app: dashboard-metrics-scraper
name: dashboard-metrics-scraper
namespace: kubernetes-dashboard
spec:
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
k8s-app: dashboard-metrics-scraper
template:
metadata:
labels:
k8s-app: dashboard-metrics-scraper
annotations:
seccomp.security.alpha.kubernetes.io/pod: 'runtime/default'
spec:
containers:
- name: dashboard-metrics-scraper
image: kubernetesui/metrics-scraper:v1.0.4
ports:
- containerPort: 8000
protocol: TCP
livenessProbe:
httpGet:
scheme: HTTP
path: /
port: 8000
initialDelaySeconds: 30
timeoutSeconds: 30
volumeMounts:
- mountPath: /tmp
name: tmp-volume
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsUser: 1001
runAsGroup: 2001
serviceAccountName: kubernetes-dashboard
nodeSelector:
"beta.kubernetes.io/os": linux
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
volumes:
- name: tmp-volume
emptyDir: {}
编辑完成后执行应用:
kubectl apply -f recommended.yaml
执行完成后,查看所有 pod
看到这两个成功启动即可
执行下面命令:
# 当前默认命名空间下的服务 -A 全部命名空间下的服务
kubectl get svc -A
[root@k8s-master ~]# kubectl get svc -A
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 70m
kube-system kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 70m
kubernetes-dashboard dashboard-metrics-scraper ClusterIP 10.96.12.26 <none> 8000/TCP 100s
kubernetes-dashboard kubernetes-dashboard NodePort 10.96.157.187 <none> 443:31443/TCP 100s
可以看到,访问端口是31443,协议是443,也就是 https
打开浏览器,访问集群任意节点(ip 为3个服务器任意一个即可)即可以进入控制面板。
这里测试我们使用 chrome 浏览器
由于浏览器 chrome 使用 https 不安全,在这个页面凭空输入:thisisunsafe,即可进入
由于登录需要 token,接下来我们创建一个 token
编辑文件dash-token.yaml
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: admin
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: admin
namespace: kubernetes-dashboard
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin
namespace: kubernetes-dashboard
labels:
kubernetes.io/cluster-service: "true"
addonmanager.kubernetes.io/mode: Reconcile
执行应用这个文件,获取令牌:
kubectl apply -f dash-token.yaml
kubectl create token admin --namespace kubernetes-dashboard
[root@k8s-master ~]# kubectl apply -f dash-token.yaml
clusterrolebinding.rbac.authorization.k8s.io/admin created
serviceaccount/admin created
[root@k8s-master ~]# kubectl create token admin --namespace kubernetes-dashboard
eyJhbGciOiJSUzI1NiIsImtpZCI6IkV6MDJ6S1NSMDlvTmJKRGc4WWJ5RUk1aW5MOUxRMUFmNFk3M1BMWmVGWTQifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNzExMjc2MzY5LCJpYXQiOjE3MTEyNzI3NjksImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsInNlcnZpY2VhY2NvdW50Ijp7Im5hbWUiOiJhZG1pbiIsInVpZCI6ImY4NjNhZjk5LTczMWEtNDlkZi04ODhhLWU3MDBlMGNhZWQ2OSJ9fSwibmJmIjoxNzExMjcyNzY5LCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZXJuZXRlcy1kYXNoYm9hcmQ6YWRtaW4ifQ.CwVQxLVq6fKRacovFHCQat20Xz-M1OjLCZnKM_ERHa87UchqD6aRYSoZG-oFvW2TVGLvRIwa3ViNNVMWtFMEUwy0Zzg_nM6SdqWc-fvvfWLabA_Deqi0gANlcCcUW6lLlm37iQ9nUrsfRK6LLFlow9J_wkOnB6ZmzSQcNltEbBk5SL4-Zf0goOdycLI79p8xFM26TVg5U-2eILCGBLnVAUMHpADBvkmaKSR3ix1VLFk2g6aPV89ySmt4dTwuXS--bEGW7EY1hF3-8Z_c93x9yP7p7sgdvzKYcwTmeE4ML8M3VGVoK_Nnv5-MBmyDFfDoRSaUdtJBcLiIEUXzkJuhBQ
拿到 token 去登录即可
可以在 dashboard 界面查看自己 k8s 集群的所有信息
k8s 核心概念及操作命令
namespace(简称 ns)
k8s 资源创建的两种方式:使用命令行创建、使用 yaml 文件创建
什么是 ns
在 k8s 中,ns 是一种用于对集群资源进行逻辑分组和隔离的机制。它允许将 k8s 集群划分为多个虚拟集群,一个 ns 可以看作是一个虚拟的集群,每个 ns 内的资源相互隔离,不同 ns 之间的资源不会冲突,它将物理集群划分为多个逻辑部分,不同的业务(web、数据库、消息中间件)可以部署在不同的命名空间,实现业务的隔离,并且可以对其进行资源配额,限制 cpu、内存等资源的使用,名称空间用来隔离资源,是一种标识机制,不会隔离网络。
ns 的主要作用如下:
- 逻辑分组:ns 可以将集群中的资源进行逻辑分组,使得不同的应用程序或团队可以在同一个集群中独立管理和操作自己的资源,避免资源的混淆和冲突。
- 资源隔离:不同的 ns 之间的资源是相互隔离的,即使具有相同名称的资源也可以在不同的 ns 中存在。这样可以确保不同应用程序或团队之间的资源不会相互干扰,提高了安全性和稳定性。
- 访问控制:ns 提供了基于 ns 的访问控制机制,可以通过角色和角色绑定来控制不同 ns 内的资源访问权限,实现细粒度的权限控制。
- 资源配额:可以为每个 ns 设置资源配额,限制该 ns 内的资源使用量,避免某个应用程序或团队过度占用资源,导致其他应用程序受到影响。
- 监控和日志:k8s 可以对不同 ns 中的资源进行监控和日志记录,方便对集群中不同 ns 的资源进行分析和故障排查。
通过使用 ns,k8s 提供了一种灵活的资源隔离和管理机制,可以将集群划分为多个虚拟集群,实现资源的逻辑分组和隔离,提高了集群的安全性、可管理性和可扩展性。
ns 适合用于隔离不同用户创建的资源,每一个添加到 k8s 集群的工作负载必须放在一个命名空间中,不指定 ns 默认都在 default 下面。
初始 ns
k8s 启动时会创建四个初始名字空间:
-
default
:k8s 包含这个名字空间,以便于你无需创建新的名字空间即可开始使用新集群。 -
kube-node-lease
:该名字空间包含用于与各个节点关联的 Lease(租约)对象。 节点租约允许 kubelet 发送心跳, 由此控制面能够检测到节点故障。 -
kube-public
:所有的客户端(包括未经身份验证的客户端)都可以读取该名字空间。 该名字空间主要预留为集群使用,以便某些资源需要在整个集群中可见可读。 该名字空间的公共属性只是一种约定而非要求。 -
kube-system
:该名字空间用于 k8s 系统创建的对象。
ns 基本命令
获取所有的 ns
kubectl get ns
[root@k8s-master ~]# kubectl get ns
NAME STATUS AGE
default Active 3h18m
kube-node-lease Active 3h18m
kube-public Active 3h18m
kube-system Active 3h18m
kubernetes-dashboard Active 128m
创建 ns
kubectl create ns ns名称
[root@k8s-master ~]# kubectl create ns yigongsui
namespace/yigongsui created
[root@k8s-master ~]# kubectl get ns
NAME STATUS AGE
default Active 5h25m
kube-node-lease Active 5h25m
kube-public Active 5h25m
kube-system Active 5h25m
kubernetes-dashboard Active 4h16m
yigongsui Active 14s
删除 ns,假如这里面有服务资源,也会删除(慎用)
kubectl delete ns ns名称
[root@k8s-master ~]# kubectl delete ns yigongsui
namespace "yigongsui" deleted
[root@k8s-master ~]# kubectl get ns
NAME STATUS AGE
default Active 5h33m
kube-node-lease Active 5h33m
kube-public Active 5h33m
kube-system Active 5h33m
kubernetes-dashboard Active 4h24m
yaml 文件创建 ns
编辑文件my-ns.yaml
,名字可以任取,必须是 yaml 文件
apiVersion: v1
kind: Namespace
metadata:
name: my-ns
创建命令有两种:
kubectl apply -f my-ns.yaml
kubectl create -f my-ns.yaml
区别:
apply
:创建或更新,如果 ns 存在且发生了变化,会进行更新create
:只能用于创建,如果 ns 存在,会报错
# 编辑 yaml 文件
[root@k8s-master k8s]# vim my-ns.yaml
# yaml 文件内容
[root@k8s-master k8s]# cat my-ns.yaml
apiVersion: v1
kind: Namespace
metadata:
name: my-ns
# yaml 文件创建 ns
[root@k8s-master k8s]# kubectl apply -f my-ns.yaml
namespace/my-ns created
[root@k8s-master k8s]# kubectl get ns
NAME STATUS AGE
default Active 5h39m
kube-node-lease Active 5h39m
kube-public Active 5h39m
kube-system Active 5h39m
kubernetes-dashboard Active 4h30m
my-ns Active 10s
[root@k8s-master k8s]# kubectl create -f my-ns.yaml
Error from server (AlreadyExists): error when creating "my-ns.yaml": namespaces "my-ns" already exists
yaml 资源配置清单,是声明式管理 k8s 资源
删除 yaml 文件指定的 ns
kubectl delete -f my-ns.yaml
[root@k8s-master k8s]# kubectl delete -f my-ns.yaml
namespace "my-ns" deleted
将 ns 的信息以 yaml 格式输出
kubectl get ns my-ns -o yaml
[root@k8s-master k8s]# kubectl get ns my-ns -o yaml
apiVersion: v1
kind: Namespace
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","kind":"Namespace","metadata":{"annotations":{},"name":"my-ns"}}
creationTimestamp: "2024-03-24T14:12:23Z"
labels:
kubernetes.io/metadata.name: my-ns
name: my-ns
resourceVersion: "33348"
uid: 36e5f296-7213-46b3-9a89-fb21354fe151
spec:
finalizers:
- kubernetes
status:
phase: Active
yaml 文件属性信息
apiVersion: api版本标签信息
kind:资源类型
metadata:资源元数据信息
spec: 属性
apiVersion: apps/v1 # 指定api版本标签
kind: Deployment # 定义资源的类型/角色,deployment为副本控制器,此处资源类型可以是Deployment、Job、Ingress、Service等
metadata: # 定义资源的元数据信息,比如资源的名称、namespace、标签等信息
name: nginx-deployment # 定义资源的名称,在同一个namespace空间中必须是唯一的
namespace: kube-public # 定义资源所在命名空间
labels: # 定义资源标签
app: nginx
name: test01
spec: # 定义资源需要的参数属性,诸如是否在容器失败时重新启动容器的属性
replicas: 3 # 副本数
selector: # 定义标签选择器
matchLabels: # 定义匹配标签
app: nginx # 需与.spec.template.metadata.labels 定义的标签保持一致
template: # 定义业务模板,如果有多个副本,所有副本的属性会按照模板的相关配置进行匹配
metadata:
labels: # 定义Pod副本将使用的标签,需与.spec.selector.matchLabels 定义的标签保持一致
app: nginx
spec:
containers: # 定义容器属性
- name: nignx # 定义一个容器名,一个 - name: 定义一个容器
image: nginx:1.21 # 定义容器使用的镜像以及版本
ports:
- name: http
containerPort: 80 # 定义容器的对外的端口
- name: https
containerPort: 443
pod
什么是 pod
在 k8s 中,pod 是最小的可部署和可管理的计算单元。它是 k8s 中应用的最小单位,也是在 k8s 上运行容器化应用的资源对象,其他的资源对象都是用来支撑或者扩展 Pod 对象功能的,用于托管应用程序的运行实例。
pod 是一个逻辑主机,它由一个或多个容器组成,这些容器共享同一个网络命名空间、存储卷和其他依赖资源。这些容器通过共享相同的资源,可以更方便地进行通信、共享数据和协同工作。
一个 pod 可以包含一个或多个容器,这些容器一起运行在同一个主机上,并共享同一个 IP 地址和端口空间。它们可以通过 localhost 直接通信,无需进行网络通信。这使得容器之间的通信更加高效和简便。
pod 还提供了一些额外的功能,例如:
- 共享存储卷:pod 中的容器可以共享同一个存储卷,从而实现数据的共享和持久化。
- 同一命名空间:pod 中的容器共享同一个网络命名空间,它们可以通过 localhost 直接通信。
- 生命周期管理:pod 可以定义容器的启动顺序、重启策略和终止行为。
- 资源调度:pod 可以作为 k8s 调度器的最小调度单位,用于将容器放置在集群中的不同节点上。
需要注意的是,pod 是临时性的,它可能会被创建、删除或重新创建。因此,pod 不具备持久性和可靠性。如果需要实现高可用性和容错性,可以使用 replicaSet、deployment 等 k8s 资源来管理和控制 pod 的副本。
总之,pod 是 k8s 中的基本概念,用于托管应用程序的运行实例。它由一个或多个容器组成,共享同一个网络命名空间和存储卷,提供了容器间通信、存储共享和生命周期管理等功能。
了解:
每一个 pod 都有一个特殊的被称为”根容器“的 pause容器。pause 容器对应的镜像属于 k8s 平台的一部分.
k8s 不会直接处理容器,而是 pod。
pod 是多进程设计,运用多个应用程序,也就是一个 pod 里面有多个容器,而一个容器里面运行一个应用程序。
pod 基本命令
创建一个 pod,默认在 default 下
# kubectl run pod名 --image=镜像名
kubectl run my-nginx --image=nginx
[root@k8s-master k8s]# kubectl run my-nginx --image=nginx
pod/my-nginx created
获取当前集群中的 pod 列表以及与每个 pod 相关的详细信息,默认是 default
kubectl get pod
参数:
-A
:等价于--all-namespaces
,获取所有 ns 下的 pod 信息-n
:等价于--namespace=
,获取指定 ns 下的信息
[root@k8s-master k8s]# kubectl get pod
NAME READY STATUS RESTARTS AGE
my-nginx 1/1 Running 0 88s
获取指定 pod 的详细信息
# kubectl describe pod pod名
kubectl describe pod my-nginx
[root@k8s-master k8s]# kubectl describe pod my-nginx
Name: my-nginx
Namespace: default
Priority: 0
Service Account: default
Node: k8s-node1/192.168.0.2
Start Time: Sun, 24 Mar 2024 23:02:15 +0800
Labels: run=my-nginx
Annotations: cni.projectcalico.org/containerID: c16d009c2f2fcde906fd693d565d13086c4c2b5ad268d92b0cab4eff4cef1059
cni.projectcalico.org/podIP: 192.169.36.67/32
cni.projectcalico.org/podIPs: 192.169.36.67/32
Status: Running
IP: 192.169.36.67
IPs:
IP: 192.169.36.67
Containers:
my-nginx:
Container ID: docker://97119d84370669ae58a833ec2dbd094ba8ed5891abf884b771366beb8875bd8b
Image: nginx
Image ID: docker-pullable://nginx@sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31
Port: <none>
Host Port: <none>
State: Running
Started: Sun, 24 Mar 2024 23:02:26 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-lh4lf (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
kube-api-access-lh4lf:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 5m30s default-scheduler Successfully assigned default/my-nginx to k8s-node1
Normal Pulling 5m30s kubelet Pulling image "nginx"
Normal Pulled 5m20s kubelet Successfully pulled image "nginx" in 9.882s (9.882s including waiting)
Normal Created 5m19s kubelet Created container my-nginx
Normal Started 5m19s kubelet Started container my-nginx
查看 pod 的日志
# kubectl logs pod名
kubectl logs my-nginx
[root@k8s-master k8s]# kubectl logs my-nginx
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2024/03/24 15:02:26 [notice] 1#1: using the "epoll" event method
2024/03/24 15:02:26 [notice] 1#1: nginx/1.21.5
2024/03/24 15:02:26 [notice] 1#1: built by gcc 10.2.1 20210110 (Debian 10.2.1-6)
2024/03/24 15:02:26 [notice] 1#1: OS: Linux 3.10.0-1160.108.1.el7.x86_64
2024/03/24 15:02:26 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2024/03/24 15:02:26 [notice] 1#1: start worker processes
2024/03/24 15:02:26 [notice] 1#1: start worker process 31
2024/03/24 15:02:26 [notice] 1#1: start worker process 32
2024/03/24 15:02:26 [notice] 1#1: start worker process 33
2024/03/24 15:02:26 [notice] 1#1: start worker process 34
删除指定 pod
# kubectl delete pod pod名
kubectl delete pod my-nginx
[root@k8s-master k8s]# kubectl delete pod my-nginx
pod "my-nginx" deleted
[root@k8s-master k8s]# kubectl get pod
No resources found in default namespace.
yaml 文件创建 pod
编辑文件my-pod.yaml
,内容如下:
apiVersion: v1
kind: Pod
metadata:
name: my-nginx
labels:
run: my-nginx
spec:
containers:
- image: nginx
name: nginx01
这是创建一个名为 my-nginx 的 pod,并在其中运行名为 nginx01 的容器(镜像为 nginx)。
编辑完成后执行以下命令:
kubectl apply -f my-pod.yaml
[root@k8s-master k8s]# vim my-pod.yaml
[root@k8s-master k8s]# cat my-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: my-nginx
labels:
run: my-nginx
spec:
containers:
- image: nginx
name: nginx01
[root@k8s-master k8s]# kubectl apply -f my-pod.yaml
pod/my-nginx created
[root@k8s-master k8s]# kubectl get pod
NAME READY STATUS RESTARTS AGE
my-nginx 1/1 Running 0 2m
[root@k8s-master k8s]# kubectl describe pod my-nginx
Name: my-nginx
Namespace: default
Priority: 0
Service Account: default
Node: k8s-node1/192.168.0.2
Start Time: Sun, 24 Mar 2024 23:26:05 +0800
Labels: run=my-nginx
Annotations: cni.projectcalico.org/containerID: af662227a2724395f76f3459401c0a1293d6453f9501a3198ad276ff49f93223
cni.projectcalico.org/podIP: 192.169.36.68/32
cni.projectcalico.org/podIPs: 192.169.36.68/32
Status: Running
IP: 192.169.36.68
IPs:
IP: 192.169.36.68
Containers:
nginx01:
Container ID: docker://4ea31b6af6e594aa9c502133c9c5034ce15d6c96a1c5d1ccb86f7d2189b147d1
Image: nginx
Image ID: docker-pullable://nginx@sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31
Port: <none>
Host Port: <none>
State: Running
Started: Sun, 24 Mar 2024 23:26:06 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-khgxd (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
kube-api-access-khgxd:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 2m49s default-scheduler Successfully assigned default/my-nginx to k8s-node1
Normal Pulling 2m49s kubelet Pulling image "nginx"
Normal Pulled 2m48s kubelet Successfully pulled image "nginx" in 237ms (237ms including waiting)
Normal Created 2m48s kubelet Created container nginx01
Normal Started 2m48s kubelet Started container nginx01
访问 pod 中的应用
# 在 k8s 中每一个 pod 都会分配一个 ip
# 执行 kubectl get pod 命令使用-o wide参数展示 pod 更多的列
kubectl get pod -o wide
[root@k8s-master k8s]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
my-nginx 1/1 Running 0 12m 192.169.36.68 k8s-node1 <none> <none>
根据 ip 地址就可以访问 my-nginx 下的容器 nginx01 了
# 默认为http协议,也就是80端口,nginx默认端口就是80
curl 192.169.36.68 或 curl 192.169.36.68:80
[root@k8s-master k8s]# curl 192.169.36.68
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
以交互方式进入 pod 的内部
# kubectl exec -it pod名 /bin/bash
kubectl exec -it nginx01 /bin/bash
参数:
c
:指定要进入哪个容器
[root@k8s-master k8s]# kubectl exec -it my-nginx -c nginx01 /bin/bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@my-nginx:/# cd /usr/share/nginx/html/
root@my-nginx:/usr/share/nginx/html# ls
50x.html index.html
root@my-nginx:/usr/share/nginx/html# echo "hello my-nginx" > index.html
root@my-nginx:/usr/share/nginx/html# exit
exit
[root@k8s-master k8s]# curl 192.169.36.68
hello my-nginx
pod 运行多个应用(容器)
编辑文件my-pod2.yaml
apiVersion: v1
kind: Pod
metadata:
name: my-pod
labels:
run: my-pod
spec:
containers:
- name: nginx1
image: nginx
- name: tomcat1
image: tomcat:8.5.92
[root@k8s-master k8s]# kubectl apply -f my-pod2.yaml
pod/my-pod created
[root@k8s-master k8s]# kubectl get pod
NAME READY STATUS RESTARTS AGE
my-nginx 1/1 Running 0 28m
my-pod 2/2 Running 0 2m41s
访问 pod 中的两个容器 nginx1 和 tomcat1
# 查看 pod 的ip
[root@k8s-master k8s]# kubectl get pod -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
my-nginx 1/1 Running 0 29m 192.169.36.68 k8s-node1 <none> <none>
my-pod 2/2 Running 0 3m53s 192.169.36.69 k8s-node1 <none> <none>
# 访问 nginx1
[root@k8s-master k8s]# curl 192.169.36.69:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
# 访问 tomcat1
[root@k8s-master k8s]# curl 192.169.36.69:8080
<!doctype html><html lang="en"><head><title>HTTP Status 404 – Not Found</title><style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}HTTP Status 404 – Not Found
Type Status Report
Description The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.
Apache Tomcat/8.5.92