关于 Kubernetes一些基本概念和术语笔记(二)

网友投稿 554 2022-05-27

写在前面

学习K8s,所以整理记忆

一个不欣赏自己的人,是难以快乐的。-------三毛

7、 Horizontal Pod Autoscaler

HPA与之前的RC、 Deployment一样,也属于一种Kubernetes资源对象

。通过

追踪分析RC控制的所有目标Pod的负载变化情况,来确定是否需要针对性地调整目标Pod的副本数,这是HPA的实现原理

。当前, HPA可以有以下两种方式作为Pod负载的度量指标。

apiversion: autoscaling/v1 kind: HorizontalPodAutoscaler metadata: name: php-apache namespace: default spec maxReplicas: 10 minReplicas: 1 scaleTargetRef: kind: Deployment name: php-apache targetcpuutilizationPercentage: 90

CPUUtilizationPercentage是一个算术平均值,即目标Pod所有副本自身的CPU利用率的平均值。一个Pod自身的CPU利用率是该Pod当前CPU的使用量除以它的Pod Request的值,比,如我们定义一个Pod的Pod Request为0.4,而当前Pod的CPU使用量为0.2,则它的CPU使用率为50%

根据上面的定义,我们可以知道这个HPA控制的目标对象为一个名叫php-apache Deployment里的Pod副本,当这些Pod副本的CPUUtilizationPercentage的值超过90%时会触发自动动态扩容行为,扩容或缩容时必须满足的一个约束条件是Pod的副本数要介于1与10之间。

除了可以通过直接定义yaml文件并且调用kubectrl create的命令来创建一个HPA资源对象的方式,我们还能通过下面的简单命令行直接创建等价的HPA对象:

kubectl autoscale deployment php-apache --cpu-percent=90--min-1 --max=10

8、 StatefulSet

在Kubernetes系统中, Pod的管理对象RC, Deployment, DaemonSet和Job都是面向无状态的服务。

但现实中有很多服务是有状态的,特别是一些复杂的中间件集群,例如MysQL集·群、MongoDB集群、ZooKeeper集群等,这些应用集群有以下一些共同点:

如果用RC/Deployment控制Pod副本数的方式来实现上述有状态的集群,则我们会发现第1点是无法满足的,因为Pod的名字是随机产生的, Pod的IP地址也是在运行期才确定且可能有变动的,我们事先无法为每个Pod确定唯一不变的ID,

为了能够在其他节点上恢复某个失败的节点,

这种集群中的Pod需要挂接某种共享存储

,为了解决这个问题, Kubernetes从v1.4版本开始引入了PetSet这个新的资源对象,并且在v1.5版本时更名为StatefulSet, StatefulSet从本质上来说,可以看作DeploymentRC的一个特殊变种,它有如下一些特性。)

statefulSet除了要与PV卷捆绑使用以存储Pod的状态数据,还要与Headless Service配合使用,

即在每个StatefulSet的定义中要声明它属于哪个Headless Service

.

Headless Service与普通Service的关键区别在于,它没有Cluster IP

,如果解析Headless Service的DNS域名,则返回的是该Service对应的全部Pod的Endpoint列表。StatefulSet在Headless Service的基础上又为StatefulSet控制的每个Pod实例创建了一个DNS域名,这个域名的格式为:

$(podname).$(headless service name)

9、 Service (服务)

Service也是Kubernetes里的最核心的资源对象之一,

关于 Kubernetes中一些基本概念和术语笔记(二)

Kubernetes里的每个Service其实就是我们经常提起的微服务架构中的一个“微服务”,之前我们所说的Pod, RC等资源对象其实都是为这节所说的“服务”-Kubernetes Service作“嫁衣”的

Pod,RC与Service的逻辑关系

Kubernetes的Service定义了一个服务的访问入口地址,前端的应用(Pod)通过这个入口地址访问其背后的一组由Pod副本组成的集群实例, Service与其后端Pod副本集群之间则是通过Label Selector来实现“无缝对接”的。而RC的作用实际上是保证Service的服务能力和服务质量始终处干预期的标准。

每个Pod都会被分配一个单独的IP地址,而且每个Pod都提供了一个独立的Endpoint(Pod IP+ContainerPort)以被客户端访问,现在多个Pod副本组成了一个集群来提供服务.客户端如何来访问它们呢?一般的做法是部署一个负载均衡器(软件或硬件),

Kubernetes中运行在每个Node上的kube-proxy进程其实就是一个智能的软件负载均衡器,它负责把对Service的请求转发到后端的某个Pod实例上,并在内部实现服务的负载均衡与会话保持机制

Kubernetes发明了一种很巧妙又影响深远的设计:

Service不是共用一个负载均衡器的IP地址,而是每个Service分配了一个全局唯一的虚拟IP地址,这个虚拟IP被称为Cluster IP,这样一来,每个服务就变成了具备唯一IP地址的“通信节点”,服务调用就变成了最基础的TCP网络通信问题。

我们知道, Pod的Endpoint地址会随着Pod的销毁和重新创建而发生改变,因为新Pod的IP地址与之前旧Pod的不同。而

Service一旦被创建, Kubernetes就会自动为它分配一个可用的Cluster IP,而且在Service的整个生命周期内,它的Cluster IP不会发生改变

。于是,服务发现这个棘手的问题在Kubernetes的架构里也得以轻松解决:只要用Service的Name与Service的Cluster IP地址做一个DNS域名映射即可完美解决问题。

┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-pod-create] └─$kubectl get svc myweb -o yaml apiVersion: v1 kind: Service metadata: creationTimestamp: "2021-10-16T14:25:08Z" name: myweb namespace: liruilong-pod-create resourceVersion: "339816" uid: 695aa461-166c-4937-89ed-7b16ac49c96b spec: clusterIP: 10.109.233.35 clusterIPs: - 10.109.233.35 externalTrafficPolicy: Cluster ipFamilies: - IPv4 ipFamilyPolicy: SingleStack ports: - nodePort: 30001 port: 8080 protocol: TCP targetPort: 8080 selector: app: myweb sessionAffinity: None type: NodePort status: loadBalancer: {}

Kubernetes Service支持多个Endpoint(端口),

在存在多个Endpoint的情况下,要求每个Endpoint定义一个名字来区分

。下面是Tomcat多端口的Service定义样例:

spec: ports: - port: 8080 name: service-port - port: 8005 name: shutdown-port

多端口为什么需要给每个端口命名呢?这就涉及Kubernetes的服务发现机制了

外部系统访问 Service,采用NodePort是解决上述问题的最直接、最有效、最常用的做法。具体做法如下,以tomcat-service为例,我们在Service的定义里做如下扩展即可:

... spec: type: NodePort posts: - port: 8080 nodePort: 31002 selector: tier: frontend ...

即这里我们可以通过nodePort:31002 来访问Service,NodePort的实现方式是在Kubernetes集群里的每个Node上为需要外部访问的Service开启个对应的TCP监听端口,外部系统只要用任意一个Node的IP地址+具体的NodePort端口即可访问此服务,在任意Node上运行netstat命令,我们就可以看到有NodePort端口被监听:

Service 负载均衡问题

但NodePort还没有完全解决外部访问Service的所有问题,比如负载均衡问题,假如我们的集群中有10个Node,则此时最好有一个负载均衡器,外部的请求只需访问此负载均衡器的IP地址,由负载均衡器负责转发流量到后面某个Node的NodePort上。如图

10、 Volume (存储卷)

Volume是Pod中能够被多个容器访问的共享目录。Kuberetes的Volume概念、用途和目的与Docker的Volume比较类似,但两者不能等价。

Volume的使用也比较简单,在大多数情况下,我们先在Pod上声明一个Volume,然后在容器里引用该Volume并Mount到容器里的某个目录上。举例来说,我们要给之前的Tomcat Pod增加一个名字为datavol的Volume,并且Mount到容器的/mydata-data目录上,则只要对Pod的定义文件做如下修正即可(注意黑体字部分):

template: metadata: labels: app: app-demo tier: frontend spec: volumes: - name: datavol emptyDir: {} containers: - name: tomcat-demo image: tomcat volumeMounts: - mountPath: /myddata-data name: datavol imagePullPolicy: IfNotPresent

除了可以让一个Pod里的多个容器共享文件、让容器的数据写到宿主机的磁盘上或者写文件到网络存储中, Kubernetes的Volume还扩展出了一种非常有实用价值的功能,即

容器配置文件集中化定义与管理

,这是通过ConfigMap这个新的资源对象来实现的.

Kubernetes提供了非常丰富的Volume类型,下面逐一进行说明。

一个emptyDir Volume是在Pod分配到Node时创建的

。从它的名称就可以看出,它的初始内容为空,并且无须指定宿主机上对应的目录文件,因为这是

Kubernetes自动分配的一个目录

,当Pod从Node上移除时, emptyDir中的数据也会被永久删除。emptyDir的一些用途如下。

hostPath为在Pod上挂载宿主机上的文件或目录,它通常可以用于以下几方面。

|容器应用程序生成的日志文件需要永久保存时,可以使用宿主机的高速文件系统进行存储。|

需要访问宿主机上Docker引擎内部数据结构的容器应用时,可以通过定义hostPath为宿主机/var/lib/docker目录,使容器内部应用可以直接访问Docker的文件系统。

在使用这种类型的Volume时,需要注意以下几点。

在不同的Node上具有相同配置的Pod可能会因为宿主机上的目录和文件不同而导致对Volume上目录和文件的访问结果不一致。)

如果使用了资源配额管理,则Kubernetes无法将hostPath在宿主机上使用的资源纳入管理。在下面的例子中使用宿主机的/data目录定义了一个hostPath类型的Volume:

volumes: - name: "persistent-storage" hostPath: path: "/data"

使用这种类型的Volume表示使用谷歌公有云提供的永久磁盘(PersistentDisk, PD)存放Volume的数据,它与emptyDir不同, PD上的内容会被永久存,当Pod被删除时, PD只是被卸载(Unmount),但不会被删除。需要注意是,你需要先创建一个永久磁盘(PD),才能使用gcePersistentDisk.

与GCE类似,该类型的Volume使用亚马逊公有云提供的EBS Volume存储数据,需要先创建一个EBS Volume才能使用awsElasticBlockStore.

使用NFS网络文件系统提供的共享目录存储数据时,我们需要在系统中部署一个NFSServer,定义NES类型的Volume的示例如下

yum -y install nfs-utils

... volumes: - name: test-volume nfs: server: nfs.server.locathost path: "/" ....

11、 Persistent Volume

Volume是定义在Pod上的,属于“计算资源”的一部分,而实际上, “网络存储”是相对独立于“计算资源”而存在的一种实体资源。比如在使用虚拟机的情况下,我们通常会先定义一个网络存储,然后从中划出一个“网盘”并挂接到虚拟机上

Persistent Volume(简称PV)和与之相关联的Persistent Volume Claim (简称PVC)也起到了类似的作用。PV可以理解成

Kubernetes集群中的某个网络存储中对应的一块存储

,它与Volume很类似,但有以下区别。

apiversion: v1 kind: PersistentVolume metadata: name: pv0003 spec: capacity: storage: 5Gi accessModes: - ReadWriteOnce nfs: path: /somepath server: 172.17.0.2

PV的accessModes属性

, 目前有以下类型:

ReadWriteOnce:读写权限、并且只能被单个Node挂载。

ReadOnlyMany:只读权限、允许被多个Node挂载。

ReadWriteMany:读写权限、允许被多个Node挂载。

如果某个Pod想申请某种类型的PV,则首先需要定义一个PersistentVolumeClaim (PVC)对象:

kind: Persistentvolumeclaim apiversion: v1 metadata: name: myclaim spec: accessModes: - Readwriteonce resources: requests: storage: BGi

引用PVC

volumes: - name: mypd persistentvolumeclaim: claimName: myclaim

12、 Namespace (命名空间)

Namespace (命名空间)是Kubernetes系统中非常重要的概念

, Namespace在很多情况下用于实现

多租户的资源隔离

。Namespace通过将集群内部的资源对象“分配”到不同的Namespace 中,形成逻辑上分组的不同项目、小组或用户组,便于不同的分组在共享使用整个集群的资源的同时还能被分别管理。Kubernetes集群在启动后,会创建一个名为"default"的Namespace,通过kubectl可以查看到:

kub-system 本身的各种 pod,是kubamd默认的空间。pod使用命名空间相互隔离

┌──[root@vms81.liruilongs.github.io]-[~/ansible] └─$kubectl get namespaces NAME STATUS AGE default Active 13h kube-node-lease Active 13h kube-public Active 13h kube-system Active 13h ┌──[root@vms81.liruilongs.github.io]-[~/ansible] └─$kubectl get ns NAME STATUS AGE default Active 13h kube-node-lease Active 13h kube-public Active 13h kube-system Active 13h ┌──[root@vms81.liruilongs.github.io]-[~/ansible] └─$

命名空间基本命令

┌──[root@vms81.liruilongs.github.io]-[~/ansible] └─$kubectl create ns liruilong namespace/liruilong created ┌──[root@vms81.liruilongs.github.io]-[~/ansible] └─$kubectl get ns NAME STATUS AGE default Active 13h kube-node-lease Active 13h kube-public Active 13h kube-system Active 13h liruilong Active 4s ┌──[root@vms81.liruilongs.github.io]-[~/ansible] └─$kubectl create ns k8s-demo namespace/k8s-demo created ┌──[root@vms81.liruilongs.github.io]-[~/ansible] └─$kubectl get ns NAME STATUS AGE default Active 13h k8s-demo Active 3s kube-node-lease Active 13h kube-public Active 13h kube-system Active 13h liruilong Active 20s ┌──[root@vms81.liruilongs.github.io]-[~/ansible] └─$kubectl delete ns k8s-demo namespace "k8s-demo" deleted ┌──[root@vms81.liruilongs.github.io]-[~/ansible] └─$kubectl get ns NAME STATUS AGE default Active 13h kube-node-lease Active 13h kube-public Active 13h kube-system Active 13h liruilong Active 54s ┌──[root@vms81.liruilongs.github.io]-[~/ansible] └─$

命名空间切换

┌──[root@vms81.liruilongs.github.io]-[~/.kube] └─$vim config ┌──[root@vms81.liruilongs.github.io]-[~/.kube] └─$kubectl config get-contexts CURRENT NAME CLUSTER AUTHINFO NAMESPACE * context1 cluster1 kubernetes-admin1 context2 cluster2 kubernetes-admin2 ┌──[root@vms81.liruilongs.github.io]-[~/.kube] └─$kubectl config set-context context2 --namespace=kube-system Context "context2" modified. ┌──[root@vms81.liruilongs.github.io]-[~/.kube] └─$kubectl config get-contexts CURRENT NAME CLUSTER AUTHINFO NAMESPACE * context1 cluster1 kubernetes-admin1 context2 cluster2 kubernetes-admin2 kube-system ┌──[root@vms81.liruilongs.github.io]-[~/.kube] └─$kubectl config set-context context1 --namespace=kube-public Context "context1" modified.

或者可以这样切换名称空间

kubectl config set-context $(kubectl config current-context) --namespace= kubectl config view | grep namespace kubectl get pods

创建pod时指定命名空间

apiVersion: v1 kind: Pod metadata: creationTimestamp: null labels: run: pod-static name: pod-static namespeace: default spec: containers: - image: nginx imagePullPolicy: IfNotPresent name: pod-demo resources: {} dnsPolicy: ClusterFirst restartPolicy: Always status: {}

当我们给每个租户创建一个Namespace来实现多租户的资源隔离时,还能结合Kubernetes"的资源配额管理,限定不同租户能占用的资源,例如CPU使用量、内存使用量等。

13、 Annotation (注解)

Annotation与Label类似,也使用key/value键值对的形式进行定义。

不同的是Label具有严格的命名规则,它定义的是Kubernetes对象的元数据(Metadata),并且用于Label Selector.

Annotation则是用户任意定义的“附加”信息,以便于外部工具进行查找, Kubernetes的模块自身会通过Annotation的方式标记资源对象的一些特殊信息。

┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-pod-create] └─$kubectl annotate nodes vms82.liruilongs.github.io "dest=这是一个工作节点" node/vms82.liruilongs.github.io annotated ┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-pod-create] └─$kubectl describe nodes vms82.liruilongs.github.io Name: vms82.liruilongs.github.io Roles: worker1 Labels: beta.kubernetes.io/arch=amd64 beta.kubernetes.io/os=linux disktype=node1 kubernetes.io/arch=amd64 kubernetes.io/hostname=vms82.liruilongs.github.io kubernetes.io/os=linux node-role.kubernetes.io/worker1= Annotations: dest: 这是一个工作节点 kubeadm.alpha.kubernetes.io/cri-socket: /var/run/dockershim.sock node.alpha.kubernetes.io/ttl: 0 projectcalico.org/IPv4Address: 192.168.26.82/24 projectcalico.org/IPv4IPIPTunnelAddr: 10.244.171.128 volumes.kubernetes.io/controller-managed-attach-detach: true .....................

Kubernetes

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:陈世欣:增长黑客实战案例解析
下一篇:【云驻共创】程序员解忧铺来啦
相关文章