【k8s基础】k8s 基本使用

news/2025/1/7 18:33:07/文章来源:https://www.cnblogs.com/upstudy/p/18654770

介绍及教程大全

Kubernetes中文文档

结构模型

k8s 是经典的一对多模型,有一个主要的管理节点master和许多的工作节点slaver。当然,k8s 也可以配置多个管理节点,拥有两个以上的管理节点被称为 高可用。k8s 包括了许多的组件,每个组件都是单运行在一个docker容器中,然后通过自己规划的虚拟网络相互访问。你可以通过kubectl get pod -n kube-system查看所有节点上的组件容器。

在管理节点中会比工作节点运行更多的 k8s 组件,我们就是靠着这些多出来的组件来对工作节点发号施令。他们都叫什么这里就不详细提了。反正对于”基本使用“来说,这些名字并不重要。

理念

要想理解一个东西就要先明白它的内在理念。通俗点就是,k8s 做了什么?为了提供更加可靠的服务,就要增加服务器的数量,减少每个服务器的体量来平摊负载,而越来越多的虚拟机就会带来越来越高的运维成本。如何让少量的运维人员就可以管理数量众多的服务器及其上的服务呢?这就是 k8s 做的工作。

k8s 把数量众多的服务器重新抽象为一个统一的资源池,对于运维人员来说,他们面前没有服务器1、服务器2的概念,而是一个统一的资源池,增加新的服务器对运维人员来说,只是增加自资源池的可用量。不仅如此,k8s 把所有能用的东西都抽象成了资源的概念,从而提供了一套更统一,更简洁的管理方式。

k8s常用命令

命令名 类型 作用
get 列出某个类型的下属资源
describe 查看某个资源的详细信息
logs 查看某个 pod 的日志
create 新建资源
explain 查看某个资源的配置项
delete 删除某个资源
edit 修改某个资源的配置项
apply 应用某个资源的配置项

kubectl get 列出资源

要记住,k8s 把所有的东西都抽象成了资源,而kubectl get(最常用的命令)就是用来查看这些资源的。最常见的资源就是 pod 。

什么是 pod?
pod(豆荚)。 pod 的概念其实和docker中的容器非常相似。他是 k8s 中的最小工作单位。
你可以把 pod 理解成一个一个的小机器人,而 k8s 抽象出来的大资源池就是他们的工厂。

pod 和 docker 容器的关系?
pod 将一个或多个docker容器封装成一个统一的整体进行管理并对外提供服务。

不仅我们自己的服务是要包装成 pod 的,就连 k8s 自己也是运行在一堆 pod 上。

k8s 的 pod :

kubectl get pod -n kube-system-n 参数指定了要查看哪个命名空间下的 pod 。 k8s 所有的 pod 都被放置在kube-system命名空间下。

什么是命名空间?
命名空间namespace,是 k8s 中 的概念,提供同一服务的 pod 就应该被放置同一命名空间下,而不是混杂在一起。
k8s 可以用命名空间来做权限控制。如果不指定的话, pod 将被放置在默认的命名空间default下。

执行了kubectl get pod -n kube-system命令

kubectl get pod -n kube-system
执行结果:

NAME                              READY   STATUS    RESTARTS   AGE
coredns-bccdc95cf-69zrw           1/1     Running   1          4d1h
coredns-bccdc95cf-77bg4           1/1     Running   1          4d1h
etcd-master1                      1/1     Running   6          4d1h
kube-apiserver-master1            1/1     Running   6          4d1h
kube-controller-manager-master1   1/1     Running   2          4d1h
kube-flannel-ds-amd64-2d6tb       1/1     Running   0          47h
kube-flannel-ds-amd64-kp5xs       1/1     Running   0          47h
kube-flannel-ds-amd64-l9728       1/1     Running   0          47h
kube-flannel-ds-amd64-r87qc       1/1     Running   0          47h
kube-proxy-2lz7f                  1/1     Running   0          2d23h
kube-proxy-hqsdn                  1/1     Running   4          4d1h
kube-proxy-rh92r                  1/1     Running   1          4d1h
kube-proxy-tv4mt                  1/1     Running   0          3d2h
kube-scheduler-master1            1/1     Running   2          4d1h

其中每一行就是一个资源,这里我们看到的资源是 pod 。这个列表里包含了 k8s 在所有节点上运行的 pod ,加入的节点越多,那么显示的 pod 也就越多。

字段解释:

  • NAME:第一列是 pod 的名字,k8s 可以为 pod 随机分配一个五位数的后缀。
  • READY:第二列是 pod 中已经就绪的 docker 容器的数量,上文中我们提到了,pod 封装了一个或多个 docker 容器。在这里,1/1的含义为就绪1个容器/共计1个容器。
  • STATUS:第三列是 pod 的当前状态,下面是一些常见的状态:
    状态名 含义
    Running 运行中
    Error 异常,无法提供服务
    Pending 准备中,暂时无法提供服务
    Terminaling 结束中,即将被移除
    Unknown 未知状态,多发生于节点宕机
    PullImageBackOff 镜像拉取失败
  • RESTART:k8s 可以自动重启 pod,这一行就是标记了 pod 一共重启了多少次。
  • AGE:pod 一共存在了多长时间。

kubectl get可以列出 k8s 中所有资源

这里只介绍了如何用kubectl获取 pod 的列表。但是不要把getpod绑定在一起,pod 只是 k8s 中的一种服务,你不仅可以get pod,还可以get svc(查看服务)、get rs(查看副本控制器)、get deploy(查看部署)等等等等,虽然说kubectl get pod是最常用的一个,但是如果想查看某个资源而又不知道命令是什么,kbuectl get <资源名>就对了。

如果想看更多的信息,就可以指定-o wide参数

kubectl get pod -n kube-system -o wide
加上这个参数之后就可以看到资源的所在ip和所在节点node了。

记得加上 -n

-n可以说是kubectl get命令使用最频繁的参数了,在正式使用中,我们永远不会把资源发布在默认命名空间。所以,永远不要忘记在get命令后面加上-n。

kubectl describe 查看详情!

kubectl describe命令可以用来查看某一资源的具体信息,他同样可以查看所有资源的详情,不过最常用的还是查看 pod 的详情。他也同样可以使用-n参数指定资源所在的命名空间。

举个例子,我们可以用下面命令来查看刚才 pod 列表中的某个 pod:
kubectl describe pod kube-flannel-ds-amd64-2d6tb -n kube-system

基本属性(详细信息的开头)

# 实例名称
Name:           kube-flannel-ds-amd64-2d6tb
# 所处命名空间
Namespace:      kube-system
# 所在节点
Node:           worker2/192.168.56.22
# 启动时间
Start Time:     Wed, 03 Jul 2019 09:31:50 +0000
# 标签
Labels:         app=flannelcontroller-revision-hash=bfc6b6dd4pod-template-generation=2tier=node
# 注解
Annotations:    <none>
# 当前状态
Status:         Running
# 所在节点 IP
IP:             192.168.56.22
# 由那种资源生成 / 控制
Controlled By:  DaemonSet/kube-flannel-ds-amd64

其中几个比较常用的,例如NodelabelsControlled By。通过Node你可以快速定位到 pod 所处的机器,从而检查该机器是否出现问题或宕机等。通过labels你可以检索到该 pod 的大致用途及定位。而通过Controlled By,你可以知道该 pod 是由那种 k8s 资源创建的,然后就可以使用kubectl get <资源名>来继续查找问题。
例如上文DaemonSet/kube-flannel-ds-amd64,就可以通过kubectl get DaemonSet -n kube-system来获取上一节资源的信息。

内部镜像信息(中间部分)

在中间部分你可以找到像下面一样的Containers段落。该段落详细的描述了 pod 中每个 docker 容器的信息,常用的比如Image字段,当 pod 出现 ImagePullBackOff错误的时候就可以查看该字段确认拉取的什么镜像。其他的字段名都很通俗,直接翻译即可。

Containers:kube-flannel:Container ID:  docker://25d2c4896847bbf53735c57a60c5b3146e2b3a0f86811074bcd28a8291213c18Image:         quay.io/coreos/flannel:v0.11.0-amd64Image ID:      docker://sha256:ff281650a721f46bbe2169292c91031c66411554739c88c861ba78475c1df894Port:          <none>Host Port:     <none>Command:/opt/bin/flanneldArgs:--ip-masq--kube-subnet-mgr--iface=enp0s8State:          RunningStarted:      Wed, 03 Jul 2019 09:31:53 +0000Ready:          TrueRestart Count:  0Limits:cpu:     100mmemory:  50MiRequests:cpu:     100mmemory:  50MiEnvironment:POD_NAME:       kube-flannel-ds-amd64-2d6tb (v1:metadata.name)POD_NAMESPACE:  kube-system (v1:metadata.namespace)Mounts:/etc/kube-flannel/ from flannel-cfg (rw)/run from run (rw)/var/run/secrets/kubernetes.io/serviceaccount from flannel-token-fsqdv (ro)

事件(末尾部分)

describe查看详情的时候,最常用的信息获取处就是这个Event段落了,你可以在介绍内容的末尾找到它,如下:
Events: <none>
如果你看到上面这样,没有任何Events的话,就说明该 pod 一切正常。
当 pod 的状态不是Running时,这里一定会有或多或少的问题,长得像下面一样,然后就可以通过其中的信息分析 pod 出现问题的详细原因了:

Events:Type     Reason                  Age                 From              Message----     ------                  ----                ----              -------Normal   Killing                 29m                 kubelet, worker1  Stopping container kube-flannelWarning  FailedCreatePodSandBox  27m (x12 over 29m)  kubelet, worker1  Failed create pod sandbox: rpc error: code = Unknown desc = failed to create a sandbox for pod "kube-flannel-ds-amd64-9trbq": Error response from daemon: cgroup-parent for systemd cgroup should be a valid slice named as "xxx.slice"Normal   SandboxChanged          19m (x48 over 29m)  kubelet, worker1  Pod sandbox changed, it will be killed and re-created.Normal   Pulling                 42s                 kubelet, worker1  Pulling image "quay.io/coreos/flannel:v0.11.0-amd64"

小结

kubectl describe <资源名> <实例名>可以查看一个资源的详细信息,最常用的还是比如kubectl describe pod <pod名> -n <命名空间>来获取一个 pod 的基本信息。如果出现问题的话,可以在获取到的信息的末尾看到Event段落,其中记录着导致 pod 故障的原因。

kubectl logs 查看日志!

如果想查看一个 pod 的具体日志,就可以通过kubectl logs <pod名>来查看。
注意,这个只能查看 pod 的日志。通过添加-f参数可以持续查看日志。
例如,查看kube-system命名空间中某个flannel pod 的日志,注意修改 pod 名称:
kubectl logs -f -n kube-system kube-flannel-ds-amd64-2d6tb

输出结果:

E0706 06:55:15.848891       1 reflector.go:201] github.com/coreos/flannel/subnet/kube/kube.go:310: Failed to list *v1.Node: Get https://10.96.0.1:443/api/v1/nodes?resourceVersion=0: dial tcp 10.96.0.1:443: connect: connection refused
E0706 06:55:16.948058       1 reflector.go:201] github.com/coreos/flannel/subnet/kube/kube.go:310: Failed to list *v1.Node: Get https://10.96.0.1:443/api/v1/nodes?resourceVersion=0: dial tcp 10.96.0.1:443: connect: connection refused
E0706 06:55:17.949165       1 reflector.go:201] github.com/coreos/flannel/subnet/kube/kube.go:310: Failed to list *v1.Node: Get https://10.96.0.1:443/api/v1/nodes?resourceVersion=0: dial tcp 10.96.0.1:443: connect: connection refused
E0706 06:55:18.954108       1 reflector.go:201] github.com/coreos/flannel/subnet/kube/kube.go:310: Failed to list *v1.Node: Get https://10.96.0.1:443/api/v1/nodes?resourceVersion=0: dial tcp 10.96.0.1:443: connect: connection refused
E0706 06:55:19.955267       1 reflector.go:201] github.com/coreos/flannel/subnet/kube/kube.go:310: Failed to list *v1.Node: Get https://10.96.0.1:443/api/v1/nodes?resourceVersion=0: dial tcp 10.96.0.1:443: connect: connection refused
E0706 06:55:21.046592       1 reflector.go:201] github.com/coreos/flannel/subnet/kube/kube.go:310: Failed to list *v1.Node: Get https://10.96.0.1:443/api/v1/nodes?resourceVersion=0: dial tcp 10.96.0.1:443: connect: connection refused
E0706 06:55:22.048285       1 reflector.go:201] github.com/coreos/flannel/subnet/kube/kube.go:310: Failed to list *v1.Node: Get https://10.96.0.1:443/api/v1/nodes?resourceVersion=0: dial tcp 10.96.0.1:443: connect: connection refused
E0706 06:55:23.147040       1 reflector.go:201] github.com/coreos/flannel/subnet/kube/kube.go:310: Failed to list *v1.Node: Get https://10.96.0.1:443/api/v1/nodes?resourceVersion=0: dial tcp 10.96.0.1:443: connect: connection refused
E0706 06:55:24.148350       1 reflector.go:201] github.com/coreos/flannel/subnet/kube/kube.go:310: Failed to list *v1.Node: Get https://10.96.0.1:443/api/v1/nodes?resourceVersion=0: dial tcp 10.96.0.1:443: connect: connection refused
E0706 06:55:25.247352       1 reflector.go:201] github.com/coreos/flannel/subnet/kube/kube.go:310: Failed to list *v1.Node: Get https://10.96.0.1:443/api/v1/nodes?resourceVersion=0: dial tcp 10.96.0.1:443: connect: connection refused
E0706 06:55:26.248831       1 reflector.go:201] github.com/coreos/flannel/subnet/kube/kube.go:310: Failed to list *v1.Node: Get https://10.96.0.1:443/api/v1/nodes?resourceVersion=0: dial tcp 10.96.0.1:443: connect: connection refused
E0706 06:55:27.347224       1 reflector.go:201] github.com/coreos/flannel/subnet/kube/kube.go:310: Failed to list *v1.Node: Get https://10.96.0.1:443/api/v1/nodes?resourceVersion=0: dial tcp 10.96.0.1:443: connect: connection refused
E0706 06:55:28.348182       1 reflector.go:201] github.com/coreos/flannel/subnet/kube/kube.go:310: Failed to list *v1.Node: Get https://10.96.0.1:443/api/v1/nodes?resourceVersion=0: dial tcp 10.96.0.1:443: connect: connection refused
E0706 06:55:29.350578       1 reflector.go:201] github.com/coreos/flannel/subnet/kube/kube.go:310: Failed to list *v1.Node: Get https://10.96.0.1:443/api/v1/nodes?resourceVersion=0: dial tcp 10.96.0.1:443: connect: connection refused
...

如果你发现某个 pod 的服务有问题,但是状态还是显示Running,就可以使用kubectl logs来查看其详细日志。

kubectl create 创建资源!

k8s 中的所有东西都可以通过kubectl create命令创建,无论你是想创建一个 pod 还是一个大型的滚动升级服务deploymentcreate命令都可以做到。使用create生成一个资源主要有两种常用方法:从yaml配置文件创建简易创建

从yaml配置文件创建

如果想让 k8s 生成一个和你想象中一模一样的资源,那你就要充分而详细的描述这个资源,k8s 就提供了这么一个方法,你可以使用yaml格式创建一个文件,按照 k8s 指定好的结构定义一个对象,然后使用如下方法将该文件传递给 k8s。它就可以按照你的描述进行生成了。

配置文件(yaml)

apiVersion: v1
kind: Pod
metadata:name: kubia-manual
spec:containers:- image: luksa/kubianame: kubiaports:- containerPort: 8080protocol: TCP

执行创建命令

kubectl create -f <配置文件名.yaml>即可创建
执行结果:

root@master1:~/k8s-yaml# k create -f kubia-manual.yaml 
pod/kubia-manual created

如果你的配置文件有问题的话那么 k8s 就会报错,如下,错误一般都是拼写导致的,比如下面这个就是Pod.spec.containers[0].ports[0]中存在一个无法识别的名称contaienrPort

root@master1:~/k8s-yaml# k create -f kubia-manual.yaml 
error: error validating "kubia-manual.yaml": 
error validating data: [ValidationError(Pod.spec.containers[0].ports[0]): unknown field "contaienrPort" in io.k8s.api.core.v1.ContainerPort, 
ValidationError(Pod.spec.containers[0].ports[0]): missing required field "containerPort" in io.k8s.api.core.v1.ContainerPort]; 
if you choose to ignore these errors, turn validation off with --validate=false

简易创建

k8s 为一些常用的资源提供了简易创建的方法,比如说servicenamespacedeployment等,这些方法可以使用kubectl create <资源类型> <资源名>的方式创建。

例如创建一个名为hello-world的命名空间:

kubectl create namespace hello-world

了解哪些资源可以快速生成的话,使用kubectl create -h命令查看。

kubectl explain 解释配置

k8s 可以通过配置文件来生成资源,而为了尽可能详细的描述资源的模样,k8s 提供了数量庞大的配置项。
那么有没有一种方式可以快速的了解到某个配置项的作用呢?
有,那就是explain(解释)命令。
kubectl explain <配置名>

执行kubectl explain pod(用来了解创建 pod 中基本属性都是干什么的)

kubectl explain pod
执行结果:

root@master1:~/k8s-yaml# kubectl explain pod
KIND:     Pod
VERSION:  v1DESCRIPTION:Pod is a collection of containers that can run on a host. This resource iscreated by clients and scheduled onto hosts.FIELDS:apiVersion   <string>APIVersion defines the versioned schema of this representation of anobject. Servers should convert recognized schemas to the latest internalvalue, and may reject unrecognized values. More info:https://git.k8s.io/community/contributors/devel/api-conventions.md#resourceskind <string>Kind is a string value representing the REST resource this objectrepresents. Servers may infer this from the endpoint the client submitsrequests to. Cannot be updated. In CamelCase. More info:https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kindsmetadata     <Object>Standard object's metadata. More info:https://git.k8s.io/community/contributors/devel/api-conventions.md#metadataspec <Object>Specification of the desired behavior of the pod. More info:https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-statusstatus       <Object>Most recently observed status of the pod. This data may not be up to date.Populated by the system. Read-only. More info:https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status

可以看到,给出的解释非常详细,并且每个解释的最后都附带了一条链接,便于更加深入的进行了解,好了,那我想要了解matedata(元数据)字段都有哪些配置项怎么办呢?
kubectl explain pod.matedata
执行结果:

root@master1:~/k8s-yaml# kubectl explain pod.metadata
KIND:     Pod
VERSION:  v1RESOURCE: metadata <Object>DESCRIPTION:Standard object's metadata. More info:https://git.k8s.io/community/contributors/devel/api-conventions.md#metadataObjectMeta is metadata that all persisted resources must have, whichincludes all objects users must create.FIELDS:annotations  <map[string]string>Annotations is an unstructured key value map stored with a resource thatmay be set by external tools to store and retrieve arbitrary metadata. Theyare not queryable and should be preserved when modifying objects. Moreinfo: http://kubernetes.io/docs/user-guide/annotationsclusterName  <string>The name of the cluster which the object belongs to. This is used todistinguish resources with same name and namespace in different clusters.This field is not set anywhere right now and apiserver is going to ignoreit if set in create or update request....

通过这种方式,我们可以了解到每一个资源的每一个配置项。想了解某个属性的子属性,就加个.继续查。

kubectl delete 删除一切

delete命令的使用非常简单,如下:
kubectl delete <资源类型> <资源名>

# 要删除一个名为kubia-4n2tg的 pod
kubectl delete pod kubia-4n2tg# 要删除所有的 pod
kubectl delete pod --all# 如果要删除一切!(注意!执行删除一切命令没有二次验证,所有资源均会被直接删除。)
kubectl delete all --all

kubectl edit 修改配置!

如果在日常维护过程中,因为某些原因我们需要变更一些服务的设置该怎么办呢?从创建新资源小节我们可以了解到,每个资源都是通过一个yaml配置文件生成的,哪怕是简易创建的资源,也是 k8s 从一个默认的配置文件创建而来的。

我们可以在get命令后附加-o yaml文件查看某个现有资源的配置项。例如,查看 pod kubia-manual的配置项:
kubectl get pod kubia-manual -o yaml

执行之后就可以看到一个很长的配置列表,你也可以试一下自己创建的 pod 的配置项,你会发现同样很长,这就是因为 k8s 会读取你提供的信息,并将必要但是你没有提供的其他信息设为默认值填写进去。而kubectl edit就可以编辑刚才打开的这个列表。例如,编辑在create小节中创建的 pod kubia-manual。
kubectl edit pod kubia-manual

之后就会弹出系统设置的默认编辑器。这时我们就可以做任意修改,例如将名称改为kubia-manual-v2
首先定位到metadata.name字段,然后修改他的值:

apiVersion: v1
kind: Pod
metadata:creationTimestamp: "2019-07-07T07:31:11Z"name: kubia-manual # > kubia-manual-v2namespace: defaultresourceVersion: "790349"selfLink: /api/v1/namespaces/default/pods/kubia-manualuid: 51eaa1e6-5749-4e79-aec9-12cf2a3e485d
spec:...

修改完成后输入:wq保存,随后你会发现, k8s 居然报错了

A copy of your changes has been stored to "/tmp/kubectl-edit-vj0ts.yaml"
error: At least one of apiVersion, kind and name was changed

不要着急,这个是 k8s 做出的限制,你无法修改一个运行中资源的名称或类型。那我们就来修改一下他的其他属性好了。

例如将拉取镜像的标签指定为latest。重新edit配置文件,找到spec中containers.image字段,然后在最后添加:latest后保存。随后 k8s 会弹出保存成功,如下:
pod/kubia-manual edited

这时我们再kubectl describe pod kubia-manual查看该 pod 的详情,就可以发现对应的字段已经更新了:

Name:         kubia-manual
Namespace:    default
Priority:     0
Node:         worker1/192.168.56.21
Start Time:   Sun, 07 Jul 2019 07:31:11 +0000
Labels:       <none>
Annotations:  <none>
Status:       Running
IP:           10.244.1.14
Containers:kubia:Container ID:   docker://89617ffcc9b1455c514e5129a9b2694c43a2aff9b4c0449d5efc4aea1fe41db6# 已经显式的应用了 latest 标签Image:          luksa/kubia:latestImage ID:       docker-pullable://luksa/kubia@sha256:3f28e304dc0f63dc30f273a4202096f0fa0d08510bd2ee7e1032ce600616de24Port:           8080/TCP

小节

kubectl edit <资源类型> <资源名> 可以编辑一个资源的具体配置项,更详细的文档请参考 k8s 中文网 - kubectl edit 。
edit命令在实际使用中更偏向于人工修改某个配置项来解决问题,例如修改镜像地址解决拉取不到镜像的问题。

kubectl apply 应用配置

上一节我们知道了一个简单快捷的编辑配置方法kubectl edit,但是如果我们想对资源进行大范围的修改呢?总不能打开配置项一个一个手动修改吧。这时候就可以用到我们的kubectl apply命令了。基本用法如下:
kubectl apply -f <新配置文件名.yaml>

kubeclt apply可以说是edit命令的升级版,它和edit最大的区别就是,apply接受一个yaml配置文件,而不是打开一个编辑器去修改。k8s 在接受到这个配置文件后,会根据metadata中的元数据来查找目标资源,如果没有的话则直接新建,如果找到的话就依次比对配置文件之间有什么不同点,然后应用不同的配置

这么做的好处有很多,例如你通过kubectl apply -f https://some-network-site/resourse.yaml命令从一个网站上部署了你的资源,这样当它的管理者更新了这个配置文件后,你只需要再次执行这个命令就可以应用更新后的内容了,而且完全不用关心修改了哪些配置项。

除了修改手段不同以外,apply命令的行为和edit保持一致,你可以访问 k8s 中文网 - kubectl apply 来查看更多用法。

k8s 如何让你的应用活的更久

众所周知,k8s 可以托管你的服务 / 应用,当出现各种原因导致你的应用挂掉之后,k8s 会自动重启你的服务,那么 k8s 是如何做到的呢?
是通过副本控制器存活探针功能实现这个效果。

注:下面提到的 pod 类型均为持久型,不包含其他如Job之类的应用。

副本控制器

副本控制器是什么

副本控制器是 k8s 中用于控制 pod 数量的一个工具,只要 告诉它你期望中的 pod 有多少,他就会努力去把 pod 控制在这个数量。
这个副本控制器具体有两种,分别是:

  • ReplicationController(简称rc)
  • ReplicaSet(简称rs)

副本控制器为了达到目标(把 pod 数量维持在你给它的期望值)都做了那些事:

  • 找到目标 pod。
  • 检查其数量,如果不符合则自动增减。

如何找到目标 pod(通过标签查找指定目标)

副本控制器是通过** pod 的标签**来进行查找的,在创建副本控制器时,需要给他指定标签选择器。在生成之后,它就会通过自己携带的选择器来查找 pod 并将其纳入自己的管辖之下。
比如,你可以通过下述文件创建一个ReplicationController,我们给其命名为kubia-controller

ReplicationController.yaml

apiVersion: v1
# 说明类型为 rc
kind: ReplicationController
metadata:name: kubia-controller
spec:# 这里指定了期望的副本数量replicas: 3# 这里指定了目标 pod 的选择器selector:# 目标 pod: app 标签的值为 kubiaapp: kubia# pod 模板template:metadata:# 指定 pod 的标签labels:app: kubiaspec:# 指定 pod 容器的内容containers:- name: kubiaimage: luksa/kubiaports:- containerPort: 8080

什么是标签?
标签是 k8s 中用于分类 pod 提供的一个附加属性(当然所有资源都可以添加标签),一个标签包含标签名及标签值,如app=kubiaapp就是标签名,kubia是标签值,一个 pod 可以贴上多个标签,k8s 中的绝大多数资源都是通过**标签来筛选/控制 pod **的。

可以通过如下命令来查看标签:

  • 显示 pod 标签:kubectl get pod --show-labels
  • 将指定标签单独列出一列:kubectl get pod -L <标签名>
  • 筛选指定标签的 pod:kubectl get pod -l <标签名>

使用yaml创建副本控制器

kubectl create -f ReplicationController.yaml

使用kubectl get pod,就会发现副本控制器kubia-controller自己创建了三个 pod:

root@master1:~# kubectl get pod                    
NAME          READY   STATUS    RESTARTS   AGE
kubia-2bb8c   1/1     Running   0          46s
kubia-6jv9r   1/1     Running   0          46s
kubia-rqnbx   1/1     Running   0          46s

kubia-controller在创建之后发现自己要管理的 pod 一个都没有(在ReplicationController.yaml里我们指定了要检查标签app的值为kubia的 pod),于是kubia-controller根据ReplicationController.yaml里我们告诉它的 pod 模板创建了三个新的 pod。

如果我们使用kubectl delete pod kubia-2bb8c杀死其中的一个 pod。再次查看之后就会发现kubia-controller又创建出了一个全新的 pod:

root@master1:~# kubectl delete pod kubia-2bb8c
pod "kubia-2bb8c" deleted
root@master1:~# kubectl get pod
NAME          READY   STATUS    RESTARTS   AGE
kubia-6bdq7   1/1     Running   0          80s
kubia-6jv9r   1/1     Running   0          13m
kubia-rqnbx   1/1     Running   0          13m

这里需要强调的是,副本控制器是通过 pod 的标签来进行控制的。如果修改了某个 pod 的标签,那么就可以使其脱离指定rc的控制。

例如,我们刚才生成的kubia-controller控制器是控制标签app的值为kubia的 pod。如下,我们修改一个已存在 pod 的标签。然后就会发现kubia-controller又新建了一个 pod,这说明标签被我们修改的 pod 脱离了该副本控制器的管理:

root@master1:~# kubectl label pod kubia-6bdq7 app=kubia-v1 --overwrite 
pod/kubia-6bdq7 labeled
root@master1:~# kubectl get pod -L app
NAME          READY   STATUS    RESTARTS   AGE   APP
kubia-6bdq7   1/1     Running   0          12m   kubia-v1
kubia-6jv9r   1/1     Running   0          24m   kubia
kubia-rqnbx   1/1     Running   0          24m   kubia
kubia-tsz58   1/1     Running   0          17s   kubia

这时再把这个 pod 的标签改回来,就可以看到kubia-controller因为副本数量大于 4,不符合期望数量而删除了一个 pod。

ReplicaSet(简称rs)

了解完了ReplicationController之后再来看一下ReplicaSet(简称rs)。其实这两个的区别就是,rs支持更加完善的标签选择器
例如,rc的标签选择器允许包含某个标签的 pod。而rs支持如下条件:

  • 匹配缺少某个标签的 pod
  • 包含特定标签名的 pod
  • 匹配多组标签
  • 只匹配标签名而不关心标签值
  • 等等...

下面来看一下如何生成一个rs,首先生成如下replicaset.yaml文件:

# 需要指定对应的 apiVersion
apiVersion: apps/v1beta2
kind: ReplicaSet
metadata:name: kubia
spec:replicas: 3selector:# 只有这里和 rc 的写法不同matchLabels:app: kubiatemplate:metadata:labels:app: kubiaspec:containers:- name: kubiaimage: luksa/kubiaports:- containerPort: 8080

然后使用kubectl create -f replicaset.yaml来创建出一个rs资源,如果你认真观察了,你就会发现这个配置与rc的配置几乎完全一样。事实上,k8s 在实际的使用中几乎已经用rs完全代替了rc

存活探针

了解完了副本控制器后,我们再来看一下存活探针,这个存活探针是用在什么地方的呢?我们知道副本控制器可以把 pod 的数量保持在期望的数量。再详细一点就是:副本控制器可以把运行状态在Running的 pod 数量维持在期望的数量

那么问题来了,如果 pod 里运行的 docker 容器已经假死了,但是 k8s 不知道他已经挂掉了怎么办?
例如:一个 java 程序因为内存溢出异常停止服务了,但是JVM依旧在运行。这时 k8s 依旧会把该 pod 的状态标记为Running。

这时候,如果有一个小工具,把他插在 pod 上,不停的进行测试,然后对外输出 pod 里运行的服务是否状态良好就好了。是的,这个小工具就是存活探针

存活探针都有什么手段来进行测试?

存活探针的监测方式包括以下三种:

  • HTTP GET请求:向指定端口发送get请求,若响应的状态码正常(2xx, 3xx),则证明容器存活
  • TCP 套接字:尝试与指定窗口建立tcp连接,建立成功则容器正常
  • Exec 执行命令:在容器中指定任意命令,若命令的退出状态码为0,则容器正常。

最常用的http get存活探针

如何创建一个http存活探针:

liveness-probe.yaml

apiVersion: v1
kind: Pod
metadata:name: kubia-liveness
spec:containers:- image: luksa/kubia-unhealthyname: kubia# 这下面就是探针!livenessProbe:httpGet:path: /port: 8080

然后使用kubectl create -f libeness-probe.yaml即可创建一个拥有http探针的 pod。可以看到,想要创建探针只需要给containers数组的元素指定livenessProbe字段即可,然后使用httpGet创建一个 http 探针。httpGet需要如下两个属性:请求的访问路径path以及访问端口port

可以看到不需要指定其 ip 地址,因为 pod 的 ip 并不是固定的。探针会动态的获取其 ip 地址进行测试。这里使用的luksa/kubia-unhealthy是一个存在”异常“的 web 应用。向端口8080请求超过 5 次后服务会停止正常服务

启动之后获取 pod 看一下:

root@master1:~# kubectl get pod
NAME             READY   STATUS    RESTARTS   AGE
kubia-liveness   1/1     Running   0          83s

没问题呀,看起来一切正常,我们执行kubectl logs -f kubia-liveness打开它的日志看一下:

root@master1:~# kubectl logs -f kubia-liveness
Kubia server starting...
Received request from ::ffff:10.244.3.1
Received request from ::ffff:10.244.3.1
Received request from ::ffff:10.244.3.1
...

你会看到服务正在缓慢的被请求,这个请求就是我们定义的http探针发出的。当我们耐心的等待到 8 次之后,日志突然被关闭了,怎么回事?这时我们再kubectl get pod看一下,可以看到他的RESTARTS值从0变成了1,原来是因为容器重启了呀:

root@master1:~# kubectl get pod
NAME             READY   STATUS    RESTARTS   AGE
kubia-liveness   1/1     Running   1          4m51s

我们还可以通过kubectl describe pod kubia-liveness来查看他的详细重启信息,以下是 pod 的事件信息,你可以在输出的末尾找到它:

Events:Type     Reason     Age                    From               Message----     ------     ----                   ----               -------Normal   Scheduled  9m36s                  default-scheduler  Successfully assigned default/kubia-liveness to worker2Normal   Created    4m53s (x3 over 8m34s)  kubelet, worker2   Created container kubiaNormal   Started    4m52s (x3 over 8m33s)  kubelet, worker2   Started container kubiaWarning  Unhealthy  3m35s (x9 over 7m35s)  kubelet, worker2   Liveness probe failed: HTTP probe failed with statuscode: 500Normal   Killing    3m34s (x3 over 7m15s)  kubelet, worker2   Container kubia failed liveness probe, will be restartedNormal   Pulling    3m4s (x4 over 9m35s)   kubelet, worker2   Pulling image "luksa/kubia-unhealthy"Normal   Pulled     3m2s (x4 over 8m43s)   kubelet, worker2   Successfully pulled image "luksa/kubia-unhealthy"

可以看到第四条事件被标记为了Warning,而原因是因为探针检查到了 pod 的响应状态为 500服务器错误。然后从第 5 ~ 7 条事件可以看到 pod 被杀死并重新启动。

在 pod 重启数十次之后你可能会发现他的状态变成了 CrashLoopBackOff,这是容器多次异常退出导致的。不过不用担心,k8s 依旧会尽力重启它,经过几十秒时候你就可以看到容器的状态重新变成Running了。

存活探针的附加属性

现在我们更近一步,了解存活探针的具体配置。执行kubectl get pod kubia-liveness -o yaml命令来打开该容器的完整yaml配置。然后我们定位到livenessProbe字段,如下,可以看到完整的配置里多出了几个属性,需要我们关注的就是下面添加了注释的四条属性:

livenessProbe:httpGet:path: /port: 8080scheme: HTTP# 失败多少次将重启 podfailureThreshold: 3# 测试间隔periodSeconds: 10# 失败后成功多少次将解除失败状态successThreshold: 1# 超时时长timeoutSeconds: 1

首先回想一下,luksa/kubia-unhealthy容器会响应五次请求,然后返回500服务器异常,那为什么我们看到日志里刷新出了 8 次请求后容器才重启呢?这个就是failureThreshold属性的功劳。

存活探针在发现了请求失败时首先会将 pod 标记为异常状态。然后继续发送请求,如果依旧失败的请求次数超过了failureThreshold的次数,那么容器将会被删除重建,而在被标记为异常状态之后如果请求成功了,并且成功的总次数超过了successThreshold的次数。那么异常状态将会被清除。至于timeoutSeconds属性则代表了请求的超时时间,而periodSeconds则是间隔多久进行下一次测试,它们两个的单位都是秒。

上述四个属性是属于livenessProbe对象的,而非httpGet对象,在创建时不要搞错缩进了。

探针导致的问题

探针并不是尽善尽美的,如果使用不当的话很容易引起无限重启的问题。最容易发生的是以下三种:

  • 探针请求超时时间太短:从配置中可以看到,默认的超时时长是1,如果服务的正常处理时间就超过了 1 秒的话,那么探针将一直认为服务异常了,从而导致容器一直重启。
  • 初始延迟太短:其实还有一个属性是上文没有提到的,就是initialDelaySeconds。这个属性描述了在首次检测之前需要等待多少秒,如果这个时间指定的太短的话,就会导致容器还没有完全启动检测就已经开始了。自然会导致问题的产生。
  • 检测的接口需要验证:在创建http探针的时候一定要指定没有身份验证的接口,探针不会区分身份验证失败和服务器错误的状态码有什么区别。

小结
k8s 通过副本控制器和存活探针来保证服务健康可靠。副本控制器分为ReplicationControllerReplicaSet两种,但是在实际使用中rs已经全面取代了rc。副本控制器通过规定好的标签来将容器纳入自己的管理,并根据用户指定的期望数量来维持实际存在的容器数量。但是副本控制器只能保证Running的副本数量不会减改变,而不能得知处于Running状态的容器是否健康。为了实现这个目标,我们使用存活探针来获取容器内部的服务是否健康。通过自定义的探针,k8s 就可以持续的获取容器的内部状态,进而完成更加可靠的健康管理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/864947.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Scss 入门

Scss 是对 CSS 的扩展,提供了比 CSS 更简洁的语法和更强大的功能。不过,在部署时,我们要先把 Scss 编译成 CSS,才能让浏览器识别。编译 Scss 的方法有很多,这里我们使用 VS Code 的插件 Live Sass Compiler 进行自动编译。 基本准备配置保存目录。在 VS Code 配置文件中添…

Seed Lab实验:RSAPublic-Key Encryption and Signature Lab

Seed Lab实验:RSAPublic-Key Encryption and Signature Lab笔记RSAPublic-Key Encryption and Signature Lab 1.推导RSA私钥 import gmpy2p = 0xF7E75FDC469067FFDC4E847C51F452DF q = 0xE85CED54AF57E53E092113E62F436F4F e = 0x0D88C3n = q * p phi = (p - 1) * (q - 1) d =…

双稳态触发器

双稳态触发器双稳态触发器是一种具有记忆功能的逻辑单元电路,它能储存一位二进制码。 特点有两个稳定状态“0”态和“1”态; 能根据输入信号将触发器置成“0”或“1”态; 输入信号消失后,被置成的“0”或“1”态能保存下来,即具有记忆功能。RS触发器 基本RS触发器 输入低电…

在Lazarus下的Free Pascal编程教程——以数据处置推动程序运行的模块化程序设计方法

0.前言 我想通过编写一个完整的游戏程序方式引导读者体验程序设计的全过程。我将采用多种方式编写具有相同效果的应用程序,并通过不同方式形成的代码和实现方法的对比来理解程序开发更深层的知识。 了解我编写教程的思路,请参阅体现我最初想法的那篇文章中的“1.编程计划”和…

foobar2000 v2.24.1 汉化版

foobar2000 v2.24.1 汉化版 -----------------------【软件截图】---------------------- -----------------------【软件介绍】---------------------- foobar2000 是一个 Windows 平台下的高级音频播放器.包含完全支持 unicode 及支持播放增益的高级标签功能. 特色: * 支持的…

ABB机器人IO板DSQC652维修方法归纳

ABB机械手IO板DSQC652维修需要一定的专业知识和技能,以下是详细的维修步骤和注意事项:1. 初步检查断电操作:在维修前,确保机器人系统完全断电,避免触电或损坏设备。外观检查:检查DSQC652板是否有明显的物理损坏,如烧焦痕迹、裂纹或元件脱落。连接检查:检查IO板与控制器…

车载以太网一致性测试套件TAE.AETP

随着汽车电子电气架构的发展,高带宽、高速率的数据通信需求逐步涌现,具有稳定、高效特点的车载以太网技术逐步成为汽车主干网通信主流方案。为了满足复杂的通信需求,越来越多的以太网通信协议被应用到车载领域与之而来的是更多新技术的测试验证需求,经纬恒润自主研发的车载…

直播电商运营工具如何选?看这一篇就够了

近年来,直播电商迅速崛起,成为电商行业的新风口。无论是头部主播还是中小商家,都希望通过直播带货实现销售增长。然而,随着市场竞争的加剧,直播电商的运营难度也在不断增加。商家们面临着选品、数据分析、用户互动、流量获取等多重挑战。如何高效管理直播流程、精准分析数…

使用 NodeLocalDNS 提升集群 DNS 性能和可靠性

本文主要分享如何使用 NodeLocal DNSCache 来提升集群中的 DNS 性能以及可靠性,包括部署、使用配置以及原理分析,最终通过压测表明使用后带来了高达 50% 的性能提升。1.背景 什么是 NodeLocalDNS NodeLocal DNSCache 是一套 DNS 本地缓存解决方案。NodeLocal DNSCache 通过在…

如何提高企业团队间的协作效率?四大关键策略

在现代企业管理中,团队协作和任务管理是提升整体工作效率的关键。然而,随着团队规模的扩大和任务复杂性的增加,如何高效地分配任务、跟踪进度并确保协作流畅,成为了企业管理者头痛的问题。尤其在跨部门合作和远程团队的背景下,传统的沟通方式和任务管理手段显得尤为不适应…

ASE60N02-ASEMI中低压N沟道MOS管ASE60N02

ASE60N02-ASEMI中低压N沟道MOS管ASE60N02编辑:ll ASE60N02-ASEMI中低压N沟道MOS管ASE60N02 型号:ASE60N02 品牌:ASEMI 封装:TO-252 批号:最新 最大漏源电流:60A 漏源击穿电压:20V RDS(ON)Max:6mΩ 引脚数量:3 芯片个数: 沟道类型:N沟道MOS管、低压MOS管 漏电流:u…