f10@t's blog

Kubernetes-集群环境搭建使用及问题记录(二)

字数统计: 5.8k阅读时长: 23 min
2021/08/09

上一篇中我搭建了一个单master+三个从节点的Kubernetes集群,并直接使用nginx镜像进行了简单部署。这一篇来主要学习一下Kubernetes最主要的功能--容器编排。本篇将记录容器编排的重要概念、配置文件如何辨写开始,最后展示一个很简单的Hello-world。下一篇将深入实战,部署一个SpringCloud项目。

image-20210810183438958

为何以及如何进行容器编排

用过docker-compose的应该都知道,docker-compose通过已yml的格式来叙述,描述如何对不同镜像的容器进行管理,包括设置端口、标签等等,极大地简化了我们自定义Dockerfile再去创建、管理容器的过程。然而docker-compose的作用范围是有限的,它不能一次性在多个机器上部署容器,也不能进行根据实际情况负载均衡等等,所以Docker官方出了一个叫做Swarm的东西,虽然解决了上述问题但是由于提供的功能太少,很少被应用于生产中,所以才有了今天的Kubernetes。

类似地,Kubernetes也使用yml文件来进行容器编排工作,我们直接使用kubectl进行应用就可以了。其实前面我们部署网络插件Flannel的时候就已经用到这个东西了,那个kube-flannel.yml就是资源编排文件。

怎么写资源编排文档?

资源编排文件常用字段及其含义

下面我们先来直接看一个Demo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
namespace: default
spec:
replicas: 3
selector:
matchLabels:
app: nginx # 以上为第一部分,为控制器部分
template: # 以下为第二部分,为被控制对象部分
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80

首先这个yaml文档由两部分构成:控制器部分被控制对象部分。上述的关键字含义如下:

名称 含义
apiVersion API版本
kind 资源类型(比如常用的Deployment,使用kubectl api-resources就可以查看)
metadata 资源元数据(一些比如名称、命名空间等属性)
spec 资源规格
replicas 副本数量
selector 标签选择器
template Pod模板
metadata Pod元数据
template.spec Pod规格
containers 容器配置

如何开始写呢?

新建文档

从前一章节的关键字表可以看到,资源编排文档中有大量的关键字,记忆起来比较困难,所以我们有两种方式来编写:

  • kubectl create来生成yaml文件并进行修改
  • 若资源已经部署,则可以使用kubectl get命令导出其yaml文件并对其进行修改

第一种方式比如我们创建一个例子,先来看一下create命令的help:

image-20210809175523694

我们创建一个测试:kubectl create deployment web --image=nginx -o yaml --dry-run=client,参数含义如下:

  • deployment代表开发环境,后面跟名称
  • --image代表使用的镜像名称
  • -o yaml代表输出yaml格式
  • --dry-run=client代表不在集群中执行,只生成yaml文件,

结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: web
name: web
spec:
replicas: 1
selector:
matchLabels:
app: web
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: web
spec:
containers:
- image: nginx
name: nginx
resources: {}
status: {}

第二种方式我们去找一个已经部署的pod,比如我已经部署了的nginx(这里没开那个虚拟机所以挂了)

image-20210809180052697

我们直接导出:kubectl get deployment nginx -o yaml,结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "1"
creationTimestamp: "2021-08-03T15:39:14Z"
generation: 1
labels:
app: nginx
name: nginx
namespace: default
resourceVersion: "45961"
uid: b0b01395-9e7f-4cd1-b0d7-0787780d2595
spec:
progressDeadlineSeconds: 600
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
app: nginx
... ...

可以看到相对的就要复杂了很多。

关键的一点-定义资源类型

上面表格中的kind我特意打了加粗,是因为这一个非常重要的概念,这个概念你搞不清楚,在部署应用的时候你会比较懵逼。我们先运行一下kubectl api-resource来看一下都有哪些类型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
NAME                            SHORTNAMES  APIVERSION                       NAMESPACED  KIND
bindings v1 true Binding
componentstatuses cs v1 false ComponentStatus
configmaps cm v1 true ConfigMap
endpoints ep v1 true Endpoints
events ev v1 true Event
limitranges limits v1 true LimitRange
namespaces ns v1 false Namespace
nodes no v1 false Node
persistentvolumeclaims pvc v1 true PersistentVolumeClaim
persistentvolumes pv v1 false PersistentVolume
pods po v1 true Pod
podtemplates v1 true PodTemplate
replicationcontrollers rc v1 true ReplicationController
resourcequotas quota v1 true ResourceQuota
secrets v1 true Secret
serviceaccounts sa v1 true ServiceAccount
services svc v1 true Service
mutatingwebhookconfigurations admissionregistration.k8s.io/v1 false MutatingWebhookConfiguration
validatingwebhookconfigurations admissionregistration.k8s.io/v1 false ValidatingWebhookConfiguration
customresourcedefinitions crd,crds apiextensions.k8s.io/v1 false CustomResourceDefinition
apiservices apiregistration.k8s.io/v1 false APIService
controllerrevisions apps/v1 true ControllerRevision
daemonsets ds apps/v1 true DaemonSet
deployments deploy apps/v1 true Deployment
replicasets rs apps/v1 true ReplicaSet
statefulsets sts apps/v1 true StatefulSet
tokenreviews authentication.k8s.io/v1 false TokenReview
localsubjectaccessreviews authorization.k8s.io/v1 true LocalSubjectAccessReview
selfsubjectaccessreviews authorization.k8s.io/v1 false SelfSubjectAccessReview
selfsubjectrulesreviews authorization.k8s.io/v1 false SelfSubjectRulesReview
subjectaccessreviews authorization.k8s.io/v1 false SubjectAccessReview
horizontalpodautoscalers hpa autoscaling/v1 true HorizontalPodAutoscaler
cronjobs cj batch/v1 true CronJob
jobs batch/v1 true Job
certificatesigningrequests csr certificates.k8s.io/v1 false CertificateSigningRequest
leases coordination.k8s.io/v1 true Lease
endpointslices discovery.k8s.io/v1 true EndpointSlice
events ev events.k8s.io/v1 true Event
ingresses ing extensions/v1beta1 true Ingress
flowschemas flowcontrol.apiserver.k8s.io/v1befalse FlowSchema
prioritylevelconfigurations flowcontrol.apiserver.k8s.io/v1befalse PriorityLevelConfiguration
ingressclasses networking.k8s.io/v1 false IngressClass
ingresses ing networking.k8s.io/v1 true Ingress
networkpolicies netpol networking.k8s.io/v1 true NetworkPolicy
runtimeclasses node.k8s.io/v1 false RuntimeClass
poddisruptionbudgets pdb policy/v1 true PodDisruptionBudget
podsecuritypolicies psp policy/v1beta1 false PodSecurityPolicy
clusterrolebindings rbac.authorization.k8s.io/v1 false ClusterRoleBinding
clusterroles rbac.authorization.k8s.io/v1 false ClusterRole
rolebindings rbac.authorization.k8s.io/v1 true RoleBinding
roles rbac.authorization.k8s.io/v1 true Role
priorityclasses pc scheduling.k8s.io/v1 false PriorityClass
csidrivers storage.k8s.io/v1 false CSIDriver
csinodes storage.k8s.io/v1 false CSINode
csistoragecapacities storage.k8s.io/v1beta1 true CSIStorageCapacity
storageclasses sc storage.k8s.io/v1 false StorageClass
volumeattachments storage.k8s.io/v1 false VolumeAttachment

人都麻了,一堆类型,所以我们只看常用的东西,搞清楚这个问题:Kubernetes的有哪些类型的资源,如果你对哪一个不清楚想要了解的话可以使用kubectl explain xxx来查看。

常用的几个比如:

  • Deployment
  • service
  • pod
  • ReplicationController

下面我将着重叙述上述的这四种类型。个人认为理解的必要性很大

kind: Pod

我们看一下Pod,这是Kubernetes调度资源的最小单位,它是在机器上运行的一系列的容器的组合,由客户端创建并分发到集群中去创建、运行等等。一句话总结:

Pod is a collection of containers that can run on a host. This resource is created by clients and scheduled onto hosts.

下面是定义Pod时的重要元素:

  • apiVersion:声明Kubernetes的API版本,目前是v1

  • kind:声明API对象的类型,这里类型是Pod

  • metadata:设置Pod的元数据

    • name:指定Pod的名称,Pod名称必须在Namespace内唯一
  • spec:配置Pod的具体规格

    • restartPolicy:设置Pod的重启策略
    • volumes:定义挂载在Pod中的目录,数组形式,每一项定义一个容器
      • name:挂载在Pod中的目录名称,比如data。注意pod中所有容器都可以访问到。
      • hostPath:宿主机路径,比如/tmp
    • containers:设置Pod中容器的规格,数组形式,每一项定义一个容器('- '开头为一项)
      • name:指定容器的名称,在Pod的定义中唯一
      • image:设置容器镜像
      • command:设置容器的启动命令
      • volumeMounts: 配置挂载数据卷,数组形式,每一项定义一个容器
        • name:挂载名称,比如web_data
        • mountPath:/data,注意这里的路径是Pod中.spec.volumes中定义的volume
      • ports:设置容器端口,数组形式,每一项定义一个容器
        • name:设置端口名称,比如在Pod内唯一,当只配置一个端口的时候,为可选项,否则配置多个端口的时候为必选项
        • containerPort:必选项目,设置在容器内的端口,有效值范围为0-65536(不包括0和65536)
        • protocol:可选项,设置端口的网络层协议,TCP或UDP,默认TCP
        • hostIP:可选项,设置在宿主机上的IP。0.0.0.0代表任意可用的
        • hostPort:可选项,设置在宿主机的端口,有效值范围为0-65536(不包括0和65536)
经典Hello-World

下一章会使用SpringCloud项目做一个深入的学习,下来我们先写一个pod资源类型的Hello World来简单了解一下流程,在这个pod中包含了Pod基本信息、数据卷信息的使用展示。

我直接写yaml了,中间会插注释说明。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
apiVersion: v1       # 声明Kubernetes的API版本
kind: Pod # 声明资源类型为Pod
metadata: # 开始设置Pod的元数据
name: pod-demo # 设置Pod的名称,该名称应在Namespace内是唯一的
spec: # 设置Pod的具体规格
restartPolicy: Never # 设置Pod的重启策略,这里无需重启,容器正常退出就结束
volumes: # 设置数据卷信息
- name: tmp-data
hostPath:
path: /tmp
containers: # 设置Pod的容器规格,呈数组格式('- '开始),每一项定义一个容器
- name: write # 指定容器的名称,在Pod中的定义唯一
image: "ubuntu:18.04" # 设置容器的镜像
volumeMounts:
- name: tmp-data
mountPath: /buffer
command: ["/bin/bash", "-c", "echo \"Hello World\" > /buffer/hello.txt"] # 设容器的启动命令,这里我们拷贝数据进行数据卷的验证
- name: read # 再创建一个容器来读取内容
image: "ubuntu:18.04"
volumeMounts:
- name: tmp-data
mountPath: /buffer
command: ["cat", "/buffer/hello.txt"] # 读取这个文件

上面这个例子中我们定义了一个使用Ubuntu:18.04作为镜像的容器的Pod资源类型,其实上面这个定义的效果就相当于我们docker中docker run --name hello-world ubuntu:18.04 /bin/echo Hello World

我们把这个资源创建到Kubernetes中,在pod起来后,使用log命令并指定容器来查看输出:

image-20210812182431428

如果你发现pod报错或者一直维持在创建中的状态,那你可以使用命令kubectl describe pod xxx来查看,这个命令可以做到查询pod的状态以及生命周期事件。

kind: Republication Controller

2021/9/7 更新

在Kubernetes v1.16之前,维护pod的只有Republication Controller,但是在新版本中官方建议使用ReplicaSet来取代RC,二者本质相同,只不过RC只支持等式选择器,而ReplicaSet支持集合式选择器。

但是官方不建议用户直接使用ReplicaSet,而是使用Deployment,它可以看做是RC的升级版,支持滚动更新(ReplicaSet不支持)、版本记录、回滚、暂停更新等高级特性,所以你也可以大概了解下RC,把重点放在Deployment上。

这一节的记录内容非常重要,可以帮助你理解Pod的生命周期、RC的作用、RC的功能。具体来说这一节我将主要叙述RC的如下功能:

  • 定义方式?
  • 如何关联RC和Pod?
  • 如何弹性伸缩和自动伸缩?
  • 如何实现应用手动升级?

Kubernetes中RC的主要要素包括以下内容:

  • kind:声明API对象类型,这里就是Replication Controller
  • metadata:设置RC的元数据
    • name: 指定RC的名称,该名称必须在NameSpace中唯一。
  • spec: 配置RC的具体规格
    • replicas:设置RC控制的Pod副本数目
    • selector:指定RC的Label Selector来匹配Pod的Label
  • template:设置Pod模板,同Pod的定义一致

Replication Controller(RC)是一个很重要的概念,应用托管在k8s后,为了保证这个应用可以持续的运行,所以有RC,他可以确保任意时刻k8s中都存在指定数量的Pod副本数量(.spec.replicas),并提供了弹性伸缩、滚动升级等特性。一个定义RC的配置文件如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: v1 
kind: ReplicationController
metadata:
name: my-nginx
spec:
replicas: 2 # 设置Pod副本数目为2
selector: # 用来匹配Pod的Label
app: nginx
template: # Pod模板,相当于Pod定义
metadata:
labels:
app: nginx # 为Pod打Label
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80

同样,使用kubectl create -f xxx.yaml就可以生效了,你可以使用命令:

kubectl get pod --selector app=nginx --label-columns app

来查看这个RC创建的Pod。

因为RC中定义了副本数目,所以你删除已经创建的pod他就会新建一个pod来保证replicas的数目。只有你直接删除了rc资源kubectl delete rc xxx他才会删除对应的pod;而如果你想只删除rc而不删除它对应的pods的话,删除的时候需要带上参数--cascade=false

当然,你也可以不通过上述写文件,然后create的方式来创建,好比nginx,你也可以直接kubectl run my-nginx --image nginx --replicas 2 --labels app=nginx

RC使用Pod和直接定义Pod有什么区别吗?

一般相对于直接定义一个Pod,更多的是定义一个RC,让RC来创建Pod,有点像工厂模式那味儿啊。上面那个RC的配置文件也可以看出,我们是通过.spec.template来设置Pod模板的,通过这种方式设置Pod有三个要注意的地方:

  • 不需要指定Pod名称,名称是自动生成且唯一的,你指定了也没用
  • Pod模板重启策略必须是Always,这是为了保证Pod的副本数目
  • Pod模板的Label不能为空,否则RC无法同Pod模板创建出来的Pod相关联
Pod模板可以单独定义吗?非得写RC里?

Pod模板是可以单独定义的,类型是PodTemplate,一个例子podtemplate.yaml如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
apiVersion: v1 
kind: PodTemplate
metadata:
name: nginx
template:
metadata:
labels:
name: nginx
spec:
containers:
- image: nginx
name: nginx
ports:
- containerPort: 80

然后我们部署到k8s中:

kubectl create -f podtemplate.yaml

然后你可以查看当前有那些模板:

kubectl get podTemplate nginx

然后你就可以在RC里面直接引用了:

1
2
3
4
5
6
7
8
apiVersion: v1
kind: ReplicationController
metadata:
name: my-nginx
spec:
replicas: 2
templateRef:
name: nginx # 使用templateRef来进行引用
RC和Pod之间的关联 - Label

这俩的关联主要就是通过Label标签来进行的,再看一眼上面那个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
apiVersion: v1 
kind: ReplicationController
metadata:
name: my-nginx
spec:
replicas: 2
selector: # 用来匹配Pod的Label
app: myApp
template:
metadata:
labels:
app: myApp # 为Pod打Label
version: v1 # 你也可以添加其他标签来准确标识
release: stable
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80

我们就是通过.spec.selector来匹配.spec.template.metadata.labels的。有一种比较好的、方便开发的方法:修改当前Pod的标签

好比说上面资源部署后,创建了myApp-abcde这个pod,我们进行修改

kubectl label pod myApp-abcde app=debug --overwrite

这样RC就会创建一个新的Pod进行关联,相当于我们有了一个备份的应用可以进行调试了,调试结束后就可以kubectl delete pod xx删除这个pod了。

RC如何实现手动弹性伸缩?

即横向扩展,在Kubernetes中就是根据负载的高低动态来调整Pod的副本数目,主要是通过kubectl scale命令来完成的。

好比说你定义了一个RC,他的.spec.replicas值为1,即只有一个副本,那如果后面你想要扩容,你就可以直接手动进行扩容:

kubectl scale replicationcontroller xxx --replicas=n

上面这条命令扩容至n个这个RC管理的Pod。特别地,如果n=0,那意思就是删除所有这个RC管理的Pod。

RC如何实现自动伸缩?

手动固然方便,但是人不可能时时刻刻观察这业务的负载,我们就需要更细颗粒度的伸缩控制,那就是自动伸缩了。Kubernetes中通过Horizontal Pod AutoScaler来实现Pod的自动伸缩,该资源主要通过监视和RC关联的Pod的整体资源使用情况,当匹配了设定的策略的时候,它就会通过RC来调整Pod的副本数目。示意图如下所示:

image-20210813150034315

在k8s v1.8以下主要使用Heapster来作为性能指标的采集来源,v1.11废弃,后续使用Metrics Server进行指标的采集。具体的工作原理官方解释如下(附上我的渣渣翻译):

The Horizontal Pod Autoscaler is implemented as a control loop, with a period controlled by the controller manager's --horizontal-pod-autoscaler-sync-period flag (with a default value of 15 seconds).

Pod横向自动扩展是以控制循环(control loop)来单位来进行的,这个循环的时间是由--horizontal-pod-autoscaler-sync-period参数控制的,默认为15s

During each period, the controller manager queries the resource utilization against the metrics specified in each HorizontalPodAutoscaler definition. The controller manager obtains the metrics from either the resource metrics API (for per-pod resource metrics), or the custom metrics API (for all other metrics).

在这每一个作用周期内,控制器(controller manager)将按照每一个HorizontalPodAutoscaler的配置文件(就是yaml,Kind是horizontalpodautoscaler)定义的指标(比如CPU、内存等)来获取资源的利用率。这些指标的来源包括资源指标API(resouce metrics API)和自定义的指标API。

... ...

The autoscaler accesses corresponding scalable controllers (such as replication controllers, deployments, and replica sets) by using the scale sub-resource.

自动扩展功能通过Scale(Scale是一个用于设置副本数量和查看健康情况的接口)来访问相关的可扩展控制器(比如replication controller、deployments、replica sets)

首先我们创建一个RC,这里说明一下,我写的配置文件没有问题,但是不知道为什么实际实验的时候我出现了成功创建了Pod,但是一直处于ContainerCreating的状态,且describe无报错,docker那边也显示容器正在运行。有相同情况的大佬希望评论一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
apiVersion: v1
kind: ReplicationController
metadata:
name: my-nginx
spec:
selector:
app: nginx
version: v1
template:
metadata:
labels:
app: nginx
version: v1
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
protocol: TCP

然后我们使用子命令autoscale来为RC创建HPA:

kubectl autoscale rc my-nginx --min=1 --max=5 --cpu-percent=50

上面的命令含义为

  • 为名为my-nginx的rc创建HPA
  • 该HPA策略为若CPU使用率大于50%就进行调整
  • 该HPA的调整范围最小为1个,最多为5个副本

创建好的HPA可以使用命令kubectl get hpa来查看。

RC怎么实现应用的滚动升级?

好比说上面那个配置文件叫my-nginx-v1,假如此刻有5个副本且我们打算把应用升级为my-nginx-v2,如何进行一次性的滚动升级呢?很简单:

kubectl rolling-update my-nginx-v1 -f my-nginx-v2.yaml --update-period=10s

上面这条命令做了什么呢?

  • 首先根据定义的文件创建V2版本的RC
  • 每隔10s(--update-period),逐步增加V2版本的RC副本数并逐渐减少V1版本的副本数
  • 全部替换完后自动删除V1版本的RC,并保留V2版本的RC

当然这个过程需要一点点时间,如果你在这个期间发现搞错了也是可以回滚的:

kubectl rolling-update my-nginx-v1 -f my-nginx-v2.yaml --update-period=10s --rollback

Kind: Deployment

在了解了上面的RC后,在看Deployment就知道是干什么的了。Deployment是Kubernetes提供的一中更加简单地更新RC和Pod的机制。

官方对Deploment的解释如下(附渣渣理解):

A Deployment provides declarative updates for Pods and ReplicaSets.

You describe a desired state in a Deployment, and the Deployment Controller changes the actual state to the desired state at a controlled rate. You can define Deployments to create new ReplicaSets, or to remove existing Deployments and adopt all their resources with new Deployments.

一个Deployment提供了一个方法--可以用来为pods和ReplicaSets进行更新升级

你只需要在Deployment中声明你想要的状态,然后就交给Deployment就行了,它会自动以受控的速率将现有的状态转变为期待的状态。你可以声明Deployment来创建新的ReplicaSets,或者删除现有的Deployment并通过新的Deployment收取其资源。

官方说明典型的使用Deployment场景如下:

  • 创建Deployment来上线ReplicaSets(which官方不建议用户手动创建or管理)
  • 通过更新Deployment中的PodTemplateSpec字段来声明Pod的新状态
  • 可以使用Deployment进行回滚
  • 可以扩大Deployment来承担更多负载
  • 可以使用Deployment来判断上线过程是否出现停滞
  • 可以使用Deployment来清理较旧的ReplicaSet
从一个Deployment Demo开始

下面我们创建一个nginx的deployment:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment-demo
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80

然后直接部署到集群中:

kubectl apply -f nginx-deployment-demo.yaml

你也可以使用命令来完成:

kubectl create deploy nginx-deployment --image=nginx --replicas=3

创建成功后,我们可以查看deployment资源的状态以及创建的pod信息: image-20210907202007096

最终状态如下: image-20210907202059726

Deployment的扩容和缩容

虽然可以通过修改yaml文件并重新应用,但是相较麻烦,所以这里只记录使用命令如何进行扩容和缩容。

命令非常简单:

  • 扩容:kubectl scale deploy nginx-deployment --replicas=5 -> 将当前副本数扩展到5个
  • 缩容:kubectl scale deploy nginx-deployment --replicas=2 -> 将当前副本数缩小到2个。(注意缩小到0只是副本为0个而不是删除了deployment)

kind: Service

上面RC也说到了,Pod副本是由RC来控制的,是变化的资源,且在滚动更新、伸缩的时候也会带来一些问题,因为访问者需要能够发现这个副本且能感知到其发生的变化。

Services即服务,它用于是K8s中一个抽象的概念,具体来说,它定义了一个Pod的逻辑集合以及访问他们的策略,和RC类似,Service和Pod之间的关联也是通过Label来完成的,Service的目标是提供一种桥梁,来为访问者提供一个固定的访问地址,用来在访问时重定向到相应的后端。-- 即代理的角色。Service的定义中重要元素和上面都类似,这里不赘述。

下面我们首先创建一个Deployment,镜像为nginx,包含两个副本: image-20210907205706951

这个时候你只能在node01上访问他自己的(10.10.12.32)上的nginx服务(80端口),但是你不能从master亦或是node02上访问到,所以我们需要service来代理这些pod:

kubectl create service clusterip nginx-deployment --tcp=8080:80

这里注意,我们的deployment名称为nginx-deployment,所以我们的clusterip后面跟的名称要一致,然后我们来看一下详情:

image-20210907210107159

可以看到服务的地址是10.10.11.51,代理的pod地址就是上面那两个,这时我们直接访问这个服务地址的8080即可访问到pod的80端口:

image-20210907210433488

结语

K8s包含的内容还是不少的,关于K8s Service的服务发现我会单独整理一篇。下一篇可能会就部署一个SpringCloud应用来讨论细节,学习如何将分布式应用部署到k8s中去。

出现的问题以及解决办法

response from daemon: cgroup-parent for systemd cgroup should be a valid slice named as "xxx.slice"

这是因为你的docker和kubelet配置的cgroup政策不同,虽然我的kubernetes(v.1.21.3)最开始自己定义的是这样的:

image-20210812140223916

但是Kubernetes官方建议docker使用systemd的方式,所以这里我们需要把docker和kubernetes的cgroupDriver都改为systemd方式:

  • /var/lib/kubelet/config.yaml image-20210812140307970

  • /etc/docker/daemon.json image-20210812140420930

最后记得执行systemctl daemon-reload && systemctl restart docker && systemctl restart kubelet来生效、重启

这样就没有问题了。

log命令出现error: a container name must be specified for pod pod-demo, choose one of: [xxx xxxx ...]

这是因为你的pod里配置了多个container,所以在使用log命令的时候需要指定要查看的容器具体是哪一个,比如你要查看A容器的日志,那就是kubectl logs [pod name] -c [container name]。或者使用--all-containers参数查看全部容器。

参考学习

《Kubernetes实战》 - 吴龙辉 著

《Kubernetes权威指南:从Docker到Kubernetes实践全接触(第二版)》- 龚正等 著

k8s中的所有api-resources类型简介 - 知乎

CATALOG
  1. 1. 为何以及如何进行容器编排
  2. 2. 怎么写资源编排文档?
    1. 2.1. 资源编排文件常用字段及其含义
  3. 3. 如何开始写呢?
    1. 3.1. 新建文档
    2. 3.2. 关键的一点-定义资源类型
      1. 3.2.1. kind: Pod
        1. 3.2.1.1. 经典Hello-World
      2. 3.2.2. kind: Republication Controller
        1. 3.2.2.1. RC使用Pod和直接定义Pod有什么区别吗?
        2. 3.2.2.2. Pod模板可以单独定义吗?非得写RC里?
        3. 3.2.2.3. RC和Pod之间的关联 - Label
        4. 3.2.2.4. RC如何实现手动弹性伸缩?
        5. 3.2.2.5. RC如何实现自动伸缩?
        6. 3.2.2.6. RC怎么实现应用的滚动升级?
      3. 3.2.3. Kind: Deployment
        1. 3.2.3.1. 从一个Deployment Demo开始
        2. 3.2.3.2. Deployment的扩容和缩容
      4. 3.2.4. kind: Service
  4. 4. 结语
  5. 5. 出现的问题以及解决办法
    1. 5.1. response from daemon: cgroup-parent for systemd cgroup should be a valid slice named as "xxx.slice"
    2. 5.2. log命令出现error: a container name must be specified for pod pod-demo, choose one of: [xxx xxxx ...]
  6. 6. 参考学习