目录
kubernetes的作用
k8s核心资源pod
Pod如何管理多个容器?
Pod网络
k8s中容器的共享方式
Pod存储
已经学习了docker为什么还要学习Pod
Pod与Docker之间的关系
Pod的优势
收集业务日志
pod工作方式
自主式(不推荐)
yaml文件详解
镜像下载策略
create和apply的区别
控制器管理的Pod(推荐)
特点
yaml文件详解
k8s组件
master组件
work组件
addons附加组件
pod的创建流程
kubernetes的作用
主要用来管理容器。因为到了容器时代,好多东西都在变,以前物理机的时候好多东西都是一成不变的,如IP地址不变,网络不变,存储不变。到了容器之后,好多东西都在变,这个时候管理起来就很困难了,就不适合用人去管理了,需要用到机器来管理了,这时候k8s就出现了。
Kubernetes是一个开源的容器编排系统,主要用于管理容器化应用程序的部署、扩展和运行。它提供了一个平台来自动化容器的部署、扩展和管理,可以跨多个主机运行,并且可以利用云计算平台和虚拟化技术来进行高效的资源利用。
Kubernetes支持多层次的容器对象和服务发现,可以帮助开发团队简化和自动化容器应用程序的部署、更新和管理流程,改善了容器工作负载的可靠性和弹性。
同时,Kubernetes还提供了可插拔的扩展性机制,可以快速部署定制化的插件和扩展,以扩展容器平台的功能和性能。
k8s核心资源pod
pod是k8s中最小的管理单元,那么什么是pod,简单来说,容器就在pod里面,可以包含单个或多个容器。什么时候pod里面放多个容器?就是你多个容器之间需要共享存储、网络等。也就是说,应该把整个pod看作虚拟机,然后每个容器相当于运行在虚拟机的进程。
Pod如何管理多个容器?
Pod中可以同时运行多个容器。同一个Pod中的容器会自动的分配到同一个 node 上。同一个Pod中的容器共享资源、网络环境,它们总是被同时调度,在一个Pod中同时运行多个容器是一种比较高级的用法,只有当你的容器需要紧密配合协作的时候才考虑用这种模式。例如,你有一个容器作为web服务器运行,需要用到共享的volume,有另一个“sidecar”容器来从远端获取资源更新这些文件。
一些Pod有init容器和应用容器。 在应用程序容器启动之前,运行初始化容器。
Init容器(Init Container)是Kubernetes中的一种特殊类型的容器,它只是在Pod中的其他容器启动之前执行一次的初始化容器。
应用容器(Application Container)是在Kubernetes中运行的负责承载应用程序的容器。
Pod网络
Pod是有IP地址的,假如pod不是共享物理机ip,由网络插件(calico、flannel、weave)划分的ip,每个pod都会被分配到唯一的IP地址
#查看所有pod
[root@k8s-master1 ~]# kubectl get pod -A -owide
#查看指定命名空间下的pod
[root@k8s-master1 ~]# kubectl get pods -n kube-system -owide
kubectl 是客户端命令
get pod 是获取pod信息
-A 是获取所有pod信息
-owide 会输出具体是哪个节点和IP地址
-n kube-system 指定kube-system名称空间
在k8s中是有名称空间这个概念的,它们用不同的名称空间来隔离不通的pod。
比如说我有两个名称空间,分别是lyh和lzz,我在lyh中有个nginx和mysql,在lzz中也有个nginx和mysql,
在我查lyh下的pod的话,我是看不到lzz里的pod,这些名称空间之间是相互隔离的。
k8s里有一个默认的名称空间叫defaule
k8s中容器的共享方式
在k8s中,启动Pod时,会先启动⼀个pause 的容器,然后将后续的所有容器都 link 到这个pause 的容器,以实现⽹络共享。
Pod存储
创建Pod的时候可以指定挂载的存储卷。 POD中的所有容器都可以访问共享卷,允许这些容器共享数据。 Pod只要挂载持久化数据卷,Pod重启之后数据还是会存在的。
已经学习了docker为什么还要学习Pod
Pod与Docker之间的关系
Docker是一个开源的容器引擎,可以在Docker Engine中运行一个或多个容器实例,实现容器的构建、发布和管理。与Docker相比,Pod是Kubernetes中的一个逻辑概念,与容器引擎无关。在Kubernetes中,Pod被用来表示一个或多个紧密关联的容器组成的应用程序,而不是Docker容器本身。
Pod的优势
-
Pod可以包含多个容器,可以共享同一个网络和存储空间,并且可以通过容器和同一个Pod中的其他容器进行通信。这种方式可以更好地管理容器中的应用程序,减少资源浪费。
-
Pod 的生命周期可以被Kubernetes自动管理,避免人工操作的繁琐和错误,使得应用的部署更加容易和高效。
-
Kubernetes能够对Pod进行自动调度和平衡,确保应用程序容器的负载均衡和高可用性,进而提高整个应用系统的稳定性和性能。
收集业务日志
在k8s里,只需要在pod里面跑一个filebeat就可以收集日志了,不需要单独创建一个pod跑filebeat了
某服务模块已经实现了一些核心的业务逻辑,并且稳定运行了一段时间,日志记录在了某个目录下,按照不同级别分别为 error.log、access.log、warning.log、info.log,现在希望收集这些日志并发送到统一的日志处理服务器上。
这时我们可以修改原来的服务模块,在其中添加日志收集、发送的服务,但这样可能会影响原来服务的配置、部署方式,从而带来不必要的问题和成本,也会增加业务逻辑和基础服务的藕合度。
但如果使用Pod的方式,通过简单的编排,既可以保持原有服务逻辑、部署方式不变,又可以增加新的日志收集服务。
而且如果我们对所有服务的日志生成有一个统一的标准,或者仅对日志收集服务稍加修改,就可以将日志收集服务和其他服务进行Pod编排,提供统一、标准的日志收集方式。
这里的“核心业务服务”、“日志收集服务”分别是一个镜像,运行在隔离的容器环境中。
pod工作方式
在K8s中,所有的资源都可以使用一个yaml文件来创建,创建Pod也可以使用yaml配置文件。或者使用kubectl run在命令行创建Pod(不常用)。
有两种方式分为自主式和控制器
自主式(不推荐)
所谓的自主式Pod,就是直接定义一个Pod资源,如下:
#创建nginx的pod
[root@k8s-master1 ~]# mkdir /pod-yaml
[root@k8s-master1 ~]# cd /pod-yaml
[root@k8s-master1 pod-yaml]# vim pod-nginx.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-test
namespace: default
labels:
app: nginx
spec:
containers:
- name: nginx-test
ports:
- containerPort: 80
image: nginx:1.23.3
imagePullPolicy: IfNotPresent
#k8s集群(三台机子都要)拉取相关镜像
[root@k8s-master1 pod-yaml]# docker pull nginx:1.23.3
[root@k8s-master1 pod-yaml]# kubectl apply -f pod-nginx.yaml
[root@k8s-master1 pod-yaml]# kubectl apply -f pod-nginx.yaml
pod/nginx-test created
[root@k8s-master1 pod-yaml]# kubectl get pods
nginx-test 0/1 ContainerCreating 0 44s
ContainerCreating 状态是Kubernetes正在尝试从Docker Hub或其他容器仓库中下载镜像并创建容器。
可以用kubectl describe pod nginx命令查看状态
#指定标签查看,假设公司有100个pod,这时有标签查看就会非常方便
[root@k8s-master1 pod-yaml]# kubectl get pod -l app=nginx
NAME READY STATUS RESTARTS AGE
nginx-test 1/1 Running 0 84s
但是自主式Pod是存在一个问题的,假如我们不小心删除了pod:
[root@k8s-master1 pod-yaml]# kubectl delete pod nginx-test
pod "nginx-test" deleted
#如果删不掉,查看状态是Terminating,可以用下面这条命令
[root@k8s-master1 pod-yaml]# kubectl delete pod nginx-test--force --grace-period=0
这条命令的作用是强制删除名为 nginx-test 的Pod,并且不等待Pod中的容器正常终止,默认情况下kubectl delete pod 命令会先发送SIGTERM信号给Pod,等待Pod的TerminationGracePeriod过期或所有容器正常终止,再删除Pod。但是,使用 --force 和 --grace-period=0 标志将完全绕过该流程,强制终止Pod和其中的所有容器,并立即将它们从Kubernetes中删除。
#查看
[root@k8s-master1 pod-yaml]# kubectl get pods
No resources found in default namespace.
#结果是空,说明pod已经被删除了通过上面可以看到,如果直接定义一个Pod资源,那Pod被删除,就彻底被删除了,不会再创建一个新的Pod,这在生产环境还是具有非常大风险的,所以今后我们接触的Pod,都是控制器管理的。
yaml文件详解
#这是刚刚的yaml文件
apiVersion: v1 #pod资源版本,如果你不知道是什么版本,用kubectl explain pod.apiVersion这个命令会输出版本号
kind: Pod #你创建的资源类型
metadata: #定义元数据,主要用来定义名称和命名空间
name: nginx-test #定义pod名称
namespace: default #定义pod命名空间
labels: #定义pod的标签
app: nginx #可以定义多个标签
spec: #从spec以下是用来定义pod中的容器的
containers: #容器
- name: nginx-test #容器名
ports: #暴露的端口号
- containerPort: 80
image: nginx:1.23.3 #容器镜像
imagePullPolicy: IfNotPresent #镜像下载策略
镜像下载策略
Always: 每次需要镜像时都会强制重新下载。这个策略确保在每个容器重启时都会有最新的镜像,但也会增加带宽和拉取时间,特别是在大型部署中。
IfNotPresent: 如果本地不存在该镜像,则拉取并使用该镜像。否则,使用已存在的本地镜像。这种策略使容器可以快速启动,但可能会导致部署中存在旧版本的镜像。
Never: 只使用本地可用的镜像。如果本地不存在该镜像,则失败。这个策略适用于确保在生产环境中使用预先下载好的镜像以减少网络流量。
create和apply的区别
create一次以后,如果进行第二次create就会报错,比如说第一次把pod-nginx.yaml起来了,后来我把pod-nginx.yaml更改了,这时再用create起就会报错,如果用apply的话就不会报错
[root@k8s-master1 pod-yaml]# kubectl create -f pod-nginx.yaml
pod/nginx-test created
[root@k8s-master1 pod-yaml]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-test 0/1 ContainerCreating 0 2s
[root@k8s-master1 pod-yaml]# kubectl create -f pod-nginx.yaml
Error from server (AlreadyExists): error when creating "pod-nginx.yaml": pods "nginx-test" already exists
[root@k8s-master1 pod-yaml]# kubectl delete pod nginx-test
pod "nginx-test" deleted
[root@k8s-master1 pod-yaml]#
[root@k8s-master1 pod-yaml]#
[root@k8s-master1 pod-yaml]# kubectl get pods
No resources found in default namespace.
[root@k8s-master1 pod-yaml]#
[root@k8s-master1 pod-yaml]#
[root@k8s-master1 pod-yaml]# kubectl apply -f pod-nginx.yaml
pod/nginx-test created
[root@k8s-master1 pod-yaml]# kubectl apply -f pod-nginx.yaml
pod/nginx-test unchanged
[root@k8s-master1 pod-yaml]# kubectl apply -f pod-nginx.yaml
pod/nginx-test unchanged
在Kubernetes中,`create` 和 `apply` 都是用来创建和更新Kubernetes资源(比如Pod、Deployment、Service等)的命令,但有以下几点区别:
- `kubectl create` 命令只能创建新的资源,而不能对已有的资源进行更新。因此,如果尝试使用 `kubectl create` 命令创建一个已存在的资源,则会返回错误。相反, `kubectl apply` 命令可以在首次创建资源时创建它们,也可以更新已有的资源。
- `kubectl create` 命令不会检查资源在最新版本中是否已更改。因此,如果使用旧的 YAML 文件运行 `kubectl create` 命令,则可能会导致集群中的资源与预期不同。相反, `kubectl apply` 命令将检查最新状态,如果资源的状态已经更改,则它会执行必要的操作并将资源更新到最新版本。
- `kubectl apply` 命令具有部分更新资源的能力。这意味着它可以仅更新所需的更改,而不是像 `kubectl replace` 命令一样覆盖整个对象。
因此,当需要创建新资源时,可以使用 `kubectl create` 命令。如果需要更新资源,最好使用 `kubectl apply` 命令,因为它可以执行部分更新并确保将资源更新为最新版本。
控制器管理的Pod(推荐)
常见的管理Pod的控制器:Replicaset、Deployment、Job、CronJob、Daemonset、Statefulset。控制器管理的Pod可以确保Pod始终维持在指定的副本数运行。如,通过Deployment管理Pod
特点
-
自动创建和删除 Pod:控制器会根据配置文件中的期望状态自动创建和删除 Pod,以确保 Pod 的数量始终符合要求。
-
自动故障转移:控制器可以检测到 Pod 的故障并尝试重新创建它,确保 Pod 始终处于可用状态。
-
自动扩展和收缩:控制器可以根据资源使用情况自动扩展和收缩 Pod 的数量,确保应用程序在任何情况下都具有足够的资源。
-
滚动更新:控制器支持滚动更新,可以逐渐将新版本的 Pod 替换为旧版本,以避免应用程序的宕机时间。
-
状态监测:控制器可以监测 Pod 的状态并向用户报告故障和警告,以确保应用程序的可靠性和稳定性。
#修改pod-nginx.yaml
[root@k8s-master1 pod-yaml]# vim pod-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-test
labels:
app: nginx-deploy
spec:
selector:
matchLabels:
app: nginx
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: my-nginx
ports:
- containerPort: 80
image: nginx:1.23.3
imagePullPolicy: IfNotPresent
#创建depolyment、replicaset和pod
[root@k8s-master1 pod-yaml]# kubectl apply -f pod-nginx.yaml
deployment.apps/nginx-test created
#查看
[root@k8s-master1 pod-yaml]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-test-78dc6966dd-rzc2l 1/1 Running 0 55s
nginx-test-78dc6966dd-xxkvp 1/1 Running 0 55s
#删除rzc21
[root@k8s-master1 pod-yaml]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-test-78dc6966dd-rzc2l 1/1 Running 0 55s
nginx-test-78dc6966dd-xxkvp 1/1 Running 0 55s
[root@k8s-master1 pod-yaml]#
[root@k8s-master1 pod-yaml]#
[root@k8s-master1 pod-yaml]# kubectl delete pod nginx-test-78dc6966dd-rzc2l
pod "nginx-test-78dc6966dd-rzc2l" deleted
[root@k8s-master1 pod-yaml]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-test-78dc6966dd-x7ktk 1/1 Running 0 6s
nginx-test-78dc6966dd-xxkvp 1/1 Running 0 87s
#查看deployments
[root@k8s-master1 pod-yaml]# kubectl get deployments.apps
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-test 2/2 2 2 2m18s
#查看replicaset,这里可以简写为rs
[root@k8s-master1 pod-yaml]# kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-test-78dc6966dd 2 2 2 10m
通过上面可以发现通过deployment管理的pod,可以确保pod始终维持在指定副本数量。
yaml文件详解
apiVersion: apps/v1 #deployment版本
kind: Deployment #定义资源类型为deployment
metadata: #定义元数据
name: nginx-test #deployment名称
labels:
app: nginx-deploy #deployment标签
spec: #定义Replicaset
selector: #标签选择器
matchLabels: #replicaset要控制拥有app:nginx标签的pod
app: nginx
replicas: 2 #pod运行的副本数,也就是期望值
template:
metadata:
labels: #此处是给pod打标签,必须和replicaset要控制的标签一致
app: nginx
spec:
containers: #定义容器
- name: my-nginx #容器名
ports: #容器端口号
- containerPort: 80
image: nginx:1.23.3 #容器镜像
imagePullPolicy: IfNotPresent #镜像下载策略
为什么deployment和replicaset都是pod控制器,而deployment可以管理replicaset
在 Kubernetes 中,Deployment
和 ReplicaSet
都是 Pod 控制器,但它们的功能和职责有所不同。
ReplicaSet
负责管理一个指定数量的 Pod 副本,并通过检测 Pod 状态的变化来自动调整 Pod 的数量,以保持所需数量的 Pod 副本。而 Deployment
提供了一种方便的方式来管理多个 ReplicaSet
和 Pod 对象,允许用户逐步更新 Pod 副本而不会对用户造成影响。
具体而言,当用户需要更改 Pod 模板信息时,Deployment
会创建一个新的 ReplicaSet
,并逐渐将新的 Pod 副本添加到集群中,同时停止和删除旧的 ReplicaSet
及其 Pod。通过这种方式,Deployment
可以实现一些高级功能,例如滚动升级、回滚、恢复和自动扩缩容等。
因此,Deployment
和 ReplicaSet
明确了不同的功能和职责,同时充分利用了多种 Pod 控制器的能力,使得用户可以更灵活地管理和调度 Kubernetes 应用程序
k8s组件
master组件
kube-apiserver 它是k8s集群的控制中枢,集群内部通信和外部跟集群通信都系要警告apiserver。它的端口号是6443
controller-manager 集群的状态管理器,主要用来创建,更新,删除所管理的资源,始终保持pod和其他资源达到期望值
scheduler 集群调度中心,他有两种策略(预选、优选)
work组件
kubelet 负责监听节点上pod的状态,并将其汇报给apiserver
kube-proxy 负责pod之间的通信和负载均衡, 它的工作模式有两种(ipvs、iptables)
addons附加组件
etcd 存储了Kubernetes的所有配置信息
calico 用于Kubernetes容器网络的解决方案
coredns CoreDNS是Kubernetes集群中的域名解析服务
docker 容器
metric-server 统计pod占用的内存、cpu、存储等信息
dashboard k8s的一个web界面
pod的创建流程
kubectl apply -f pod-nginx.yaml->找到(/root/.kube/config)config文件,基于config文件指定的用户访问指定的集群,这样就找到了apiserver
第一步: 通过 kubectl 命令向 apiserver 提交创建pod的请求,apiserver接收到pod创建请求后,会将pod的属性信息(metadata)写入etcd。
第二步:apiserver触发watch机制准备创建pod,信息转发给调度器scheduler,调度器使用调度算法选择node,调度器将node信息给apiserver,apiserver将绑定的node信息写入etcd
第三步:apiserver又通过watch机制,调用kubelet,指定pod信息,调用容器运行时创建并启动pod内的容器。
第四步:创建完成之后反馈给kubelet, kubelet又将pod的状态信息给apiserver, apiserver又将pod的状态信息写入etcd。