Kubernetes 权威指南学习笔记2 - Kubernetes 相关概念及术语

Master

Kubernetes 中的 Master 指的是集群控制节点,每个 Kubernetes 集群里需要有一个 Master 节点来负责整个集群的管理和控制,基本上 Kubectl 所有的命令都是发给它,它来负责具体的执行过程。

Master 节点上的关键进程

  1. Kubernetes API Server (kube-apiserver):提供了 HTTP Rest 接口的关键服务进程,是 Kubernetes 里所有资源的增、删、查、改等操作的唯一入口,也是集群控制的入口进程。
  2. Kubernetes Controller Manager (kube-controller-manager):Kubernetes 里所有资源对象的自动化控制中心。
  3. Kubernetes Scheduler (kube-scheduler):负责资源调度 (pod 调度) 的进程。
    其实 Master 节点上往往还启动了一个 etcd Server 进程,因为 Kubernetes 里的所有资源对象的数据全部是保存在 etcd 中的。

Node

除了 Master,Kubernetes 集群中的其他物理主机或虚拟机被称为 Node 节点,是 Kubernetes 集群中的工作负载节点。当某个 Node 宕机时,该节点上的工作负载会被 Master 自动转移到其他节点上去。

Node 节点上的关键进程

  1. kubelet:负责 Pod 对应的容器的创建、启停等任务,同时与 Master 节点密切协作,实现集群管理的基本功能。
  2. kube-proxy:实现 Kubernetes Server 的通信与负载均衡机制的重要组件。
  3. Docker Engine (docker):Docker 引擎,负责本机的容器创建和管理工作。
    Node 节点可以在运行期间动态的增加到 Kubernetes 集群中,默认情况下 kubelet 会向 Master 注册自己,一旦 Node 被纳入集群中,kubelet 进程就会定时向 Master 发送自身的操作系统、Docker 版本、CPU和内存等情况信息,以及有哪些 Pod 在运行等等。一旦某个 Node 超过指定时间没有上报信息时,就会被 Master 标记为不可用 (Not Ready),随后 Master 会将该节点的工作负载自动转移到其他 Node 节点上。
  • 我们可以通过命令查看 Node 节点的详细信息:
# kubectl get nodes
NAME        STATUS    AGE
127.0.0.1   Ready     2d
# kubectl describe node 127.0.0.1
Name:			127.0.0.1
Role:			
Labels:			beta.kubernetes.io/arch=amd64
			beta.kubernetes.io/os=linux
			kubernetes.io/hostname=127.0.0.1
Taints:			<none>
CreationTimestamp:	Mon, 14 Jan 2019 18:58:22 +0800
Phase:			
Conditions:
  Type			Status	LastHeartbeatTime			LastTransitionTime			Reason				Message
  ----			------	-----------------			------------------			------				-------
  OutOfDisk 		False 	Fri, 18 Jan 2019 01:28:36 +0800 	Mon, 14 Jan 2019 18:58:22 +0800 	KubeletHasSufficientDisk 	kubelet has sufficient disk space available
  MemoryPressure 	False 	Fri, 18 Jan 2019 01:28:36 +0800 	Mon, 14 Jan 2019 18:58:22 +0800 	KubeletHasSufficientMemory 	kubelet has sufficient memory available
  DiskPressure 		False 	Fri, 18 Jan 2019 01:28:36 +0800 	Mon, 14 Jan 2019 18:58:22 +0800 	KubeletHasNoDiskPressure 	kubelet has no disk pressure
  Ready 		True 	Fri, 18 Jan 2019 01:28:36 +0800 	Mon, 14 Jan 2019 18:58:22 +0800 	KubeletReady 			kubelet is posting ready status
Addresses:		127.0.0.1,127.0.0.1,127.0.0.1
Capacity:
 alpha.kubernetes.io/nvidia-gpu:	0
 cpu:					1
 memory:				2055500Ki
 pods:					110
Allocatable:
 alpha.kubernetes.io/nvidia-gpu:	0
 cpu:					1
 memory:				2055500Ki
 pods:					110
System Info:
 Machine ID:			d015a3d4bf38443f9bb8a6dc7ed5d96e
 System UUID:			564D8B7C-B1F1-C296-92E0-41D925E1E4E5
 Boot ID:			83f74ad3-7741-4ef5-a55a-b1b905532238
 Kernel Version:		3.10.0-862.el7.x86_64
 OS Image:			CentOS Linux 7 (Core)
 Operating System:		linux
 Architecture:			amd64
 Container Runtime Version:	docker://1.13.1
 Kubelet Version:		v1.5.2
 Kube-Proxy Version:		v1.5.2
ExternalID:			127.0.0.1
Non-terminated Pods:		(4 in total)
  Namespace			Name			CPU Requests	CPU Limits	Memory Requests	Memory Limits
  ---------			----			------------	----------	---------------	-------------
  default			mysql-jdxz9		0 (0%)		0 (0%)		0 (0%)		0 (0%)
  default			myweb-814g3		0 (0%)		0 (0%)		0 (0%)		0 (0%)
  default			myweb-p74pl		0 (0%)		0 (0%)		0 (0%)		0 (0%)
  default			myweb-pfs34		0 (0%)		0 (0%)		0 (0%)		0 (0%)
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.
  CPU Requests	CPU Limits	Memory Requests	Memory Limits
  ------------	----------	---------------	-------------
  0 (0%)	0 (0%)		0 (0%)		0 (0%)
No events.
  • Node 基本信息:名称、标签、创建时间等。
  • Node 当前的运行状态,Node 启动以后会做一系列的自检工作,比如磁盘满了,就会标注 OutOfDisk=True,内存不足会标注 MemoryPressure=True,磁盘不足会标注 DiskPressure=True,一切正常时才会切换为 Ready 状态 (Ready=True),表示 Node 处于健康状态,可以创建新的 Pod。
  • Node 的主机地址以及主机名。
  • Node 上的资源总量:描述 Node 上可用的系统资源,包括 CPU、内存、最大可调度 Pod 数量等。
  • Node 可分配的资源量。
  • 主机系统信息:包括主机 UUID、Linux kernel 版本号、操作系统类型与版本、Kubernetes 版本号等。
  • 当前正运行的 Pod 列表概要信息。
  • 已分配的资源使用概要信息。
  • Node 相关的 Event 信息。

Pod

Pod 是 Kubernetes 中最基本也最重要的概念,每个 Pod 都有一个特殊的被称为“根容器”的 Pause 容器。Pause 容器对应的镜像术语 Kubernetes 平台的一部分,除了 Pause 容器,每个 Pod 还包含一个或多个紧密相关的用户业务容器。

Kubernetes 给每一个 Pod 都分配了唯一的 IP 地址,称之为 Pod IP,一个 Pod 里的多个容器共享 Pod IP。Kubernetes 要求底层网络支持集群内任意两个 Pod 之间的 TCP/IP 直接通信,这通常采用虚拟二层网络技术来实现,例如 Flannel、Openvswitch 等。所以在 Kubernetes 中,一个 Pod 里的容器与、另外主机上的 Pod 容器能直接通信。

Pod 其实有两种类型:

  1. 静态 Pod (static Pod),该类型的 Pod 比较特殊,它并不存放在 Kubernetes 的 etcd 存储中,而是存放在某个具体的 Node 上的一个具体的文件中,并且只能在此 Node 上启动运行。
  2. 普通的 Pod,该类型的 Pod 一旦被创建,就会被放到 etcd 中存储,随后会被 Kubernetes Master 调度到某个具体的 Node 上并进行绑定 (Binding),随后该 Pod 被对应的 Node 上的 kubelet 进程实例化成一组相关的 Docker 容器并启动起来。在默认情况下,当 Pod 里的某个容器停止时,Kubernetes 会自动监测到这个问题并重新启动这个 Pod (重启 Pod 中的所有容器),如果 Pod 所在的 Node 宕机,则会将这个 Node 上的所有 Pod 重新调度到其他节点上。

Kubernetes 里所有的资源对象都可以采用 yaml 或者 JSON 格式的文件来定义或描述。

Pod 资源定义文件

apiVersion: v1
kind: Pod
metadata:
  name: myweb
  lables:
	name: myweb
  spec:
	containers:
	- name: myweb
	  image: kubeguide/tomcat-app:v1
	  ports:
	  - containerPort: 8080
	  env:
	  - name: MYSQL_SERVICE_HOST
	    value: 'mysql'
	  - name: MYSQL_SERVICE_PORT
	    value: '3306'

  • kind 表示这是一个 Pod 的资源定义文件
  • metadata 中的 name 属性为 Pod 的名字,Lable 属性为资源对象的标签
  • spec 一节中的 containers 显然定义了容器的各种属性

Pod 的 IP 加上定义的容器端口 (containerPort),就组成了一个新的概念 — Endpoint,它代表着此 Pod 里的一个服务进程的对外通信地址。一个 Pod 也可以存在多个 Endpoint,比如将 Tomcat 定义为一个 Pod 的时候,可以对外暴露管理端口和服务端口两个 Endpoint。

Pod 资源限额

每个 Pod 都可以对能使用的服务器上的计算资源设置限额,当前可以设置限额的计算资源有 CPU 和 Memory 两种,其中 CPU 的资源单位为 CPU (Core) 的数量,是一个绝对值而非相对值。
在 Kubernetes 中,通常以千分之一的 CPU 配额为最小单位,用 m 来表示。通常一个容器的 CPU 配额被定义为 100~300m,即占用 0.1~0.3 个CPU。由于 CPU 配额是一个绝对值,所以无论在一个 Core 的机器上,还是在拥有48个 Core 的机器上,100m 这个配额代表的 CPU 的使用量都是一样的。与 CPU 配额类似,Memory 配额也是一个绝对值,它的单位是内存字节数。

  • 配额设定需要设置一下两个参数:
  1. Requests:该资源的最小申请量,系统必须满足要求。
  2. Limits:该资源的最大允许使用量,当容器试图使用超过这个量的资源时,可能会被 Kill 并重启。

资源限额定义文件:

spec:
  containers:
  - name: db
    image: mysql
    resources:
      requests:
        memory: "64Mi" # 表示容器最少申请64MiB内存
        cpu: "250m" # 表示容器最少申请0.25个CPU
      limits:
        memory: "128Mi" # 表示容器最多申请128MiB内存
        cpu: "500m" # 表示容器最多申请0.5个CPU

Event

Event 是一个事件的记录,记录了事件的最早产生时间、最后重现时间、重复次数、发起者、类型以及导致此事件的原因等信息。Event 通常会关联到某个具体的资源对象上,是排查故障的重要参考信息,之前我们看到 Node 的描述信息中就含有 Event,而 Pod 同样有 Event 记录,当我们发现某个 Pod 迟迟无法创建时,可以用 kubectl describe pod < pod_name >来查看它的描述信息,用来定义问题原因。

Label

Label 是 Kubernetes 系统中另外一个核心概念。Lable 是一个 key=value 的键值对,Label 可以附加到各种资源对象上,例如 Node、Pod、Service、RC等,一个资源对象可以定义任意数量的 Label,一个 Label 也可以添加到任意数量的资源对象上。

Label Selector (标签选择器) 查询和筛选某些具有 Label 的资源对象时,可以实现类似 SQL 中的 where 子句的对象查询机制,例如具有 name=redis-slave 这个 Label 的 Pod,可以被类比为 select * from pod where pod’s name = ‘redis-slave’ 这样的语句。

  1. name = redis-slave :匹配具有该标签的资源对象
  2. name != redis-slave :匹配不具有该标签的资源对象
  3. name in (redis-master,redis-slave) :匹配具有任意其中一个标签的资源对象 (or)
  4. name not in (redis-master,redis-slave) :匹配所有不具有该标签的资源对象

可以通过 Label Selector 表达式的组合实现复杂的条件选择,多个表达式之间用 ‘,’ 分隔,类似 ‘AND’ 的关系,即同时满足多个条件。如: name = redis-slave,env != production。

Replication Controller (RC)

RC 是 Kubernetes 系统中的核心概念之一,它声明某种 Pod 的副本数量在任意时刻都要符合某个预期值,所以 RC 的定义包括以下几个部分:

  1. Pod 的预期副本数 (replicas)
  2. 用于筛选 Pod 的 Label Selector
  3. 当 Pod 实际副本数量少于预期值时用于创建新 Pod 的模板 (template)

RC 资源定义文件:

apiVersion: v1
kind: ReplicationController
metadata:
  name: frontend
spec:
  replicas: 1
  selector:
    tier: frontend
  template:
    metadata:
      label:
        app: app-demo
        tier: frontend
    spec:
      containers:
      - name: tomcat-demo
        image: tomcat
        imagePullPolicy: IfNotPresent
        env:
        - name: GET_HOSTS_FROM
          value: dns
        ports:
        - containerPort: 80

当我们定义了一个 RC 并提交到 Kubernetes 集群中以后,Master 节点上的 Controller Manager 组件就会得到通知,定期巡检系统中当前存活的目标 Pod,并确保 Pod 实例的数量刚好等于 RC 的预期值。此外,在运行时我们可以通过修改 RC 的副本数量,来实现 Pod 的动态缩放 (Scaling) 功能,这可以通过执行 kubectl scale 命令来完成:

$ kubectl scale rc redis-slave --replicas=3
scaled

另外 kubectl 提供了 stop 和 delete 命令来一次性删除 RC 和 RC 控制的全部 Pod。

Replica Set

Replica Set 是 RC 的升级版,它与 RC 存在的唯一区别是:RS 支持基于集合的 Label Selector (Set-based Selector),而 RC 只支持基于等式的 Label Selector (Equality-based Selector),这使得 RS 的功能更强,下面是等价于之前 RC 例子的 Replica Set:

RS资源定义文件

apiVersion: extensions/v1beta1
kind: ReplicatSet
metadata:
  name: frontend
spec:
  replicas: 1
  selector:
    matchLabels:
      tier: frontend
    matchExpressions:
    - {key: tier, operator: In, values: [frontend]}
  template:
    metadata:
      label:
        app: app-demo
        tier: frontend
    spec:
      containers:
      - name: tomcat-demo
        image: tomcat
        imagePullPolicy: IfNotPresent
        env:
        - name: GET_HOSTS_FROM
          value: dns
        ports:
        - containerPort: 80

kubectl 命令行工具适用于 RC 的绝大部分命令同样也适用于 RS。此外,我们很少单独使用 RS,它主要被 Deployment 这个更高层的资源对象所用,从而形成一整套 Pod 创建、删除、更新的编排机制。当我们使用 Deployment 时,无需关心它是如何创建和维护 RS 的,这一切都是自动发生的。

Deployment

Deployment 内部使用了 Replica Set 来实现目的,无论从作用与目的、它的 YAM 定义,还是从它的具体命令行操作来看,我们都可以把它视作 RS 的一次升级,两者相似度超过90%。
Deployment的典型使用场景:

  1. 创建一个 deploy 对象来生成对应的 RS 并完成 Pod 副本的创建过程
  2. 检查 deploy 的状态来查看部署动作是否完成 (Pod 副本的数量师傅达到预期的值)
  3. 更新 deploy 以创建新的 Pod (比如镜像升级)
  4. 如果当前 deploy 不稳定,则回滚到上一个版本的 deploy
  5. 挂起或者恢复一个 deploy

Deployment 资源定义文件

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: frontend
spec:
  replicas: 1
  selector:
    matchLabels:
      tier: frontend
    matchExpressions:
    - {key: tier, operator: In, values: [frontend]}
  template:
    metadata:
      labels:
        app: app-demo
        tier: frontend
    spec:
      containers:
      - name: tomcat-demo
        image: tomcat
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8080

运行以下命令创建并查看 Deployment:

$ kubectl create -f tomcat-deployment.yaml
deployment "frontend" created
$ kubectl get deploy
NAME       DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
frontend   1         1         1            1           12s
  1. DESIRED:Pod 副本数量的预期值,即 deploy 定义的 Replica
  2. CURRENT:当前 Replica 的值,实际上 Deployment 所创建的 Replica Set 里的可以运行的 Pod 值,这个值不断增加,直到达到预期值 DESIRED 为止,表明整个部署动作完成
  3. UP-TO-DATE:最新版本的 Pod 的副本数量,用于指示滚动升级的过程中,有多少个 Pod 副本已经成功升级
  4. AVALABLE:当前集群中可用的 Pod 的副本数量,即集群中当前存活的 Pod 数量

查看 RS 信息:

$ kubectl get rs
NAME                 DESIRED   CURRENT   READY     AGE
frontend-141477217   1         1         1         6m

查看 Pod 信息:

$ kubectl get pod
NAME                       READY     STATUS    RESTARTS   AGE
frontend-141477217-1hf7n   1/1       Running   0          8m

通过查看 Deployment、RS、Pod 的信息,我们可以发现 Pod、RS 和 Deployment 的对应关系。很清晰的了解到一个 Deployment 创建了哪个 RS,一个 RS 创建了哪些 Pod,这样很容器排查错误。

查看 deployment 更详细的状态信息:

$ kubectl describe deploy frontend
Name:			frontend
Namespace:		default
CreationTimestamp:	Mon, 21 Jan 2019 20:02:11 +0800
Labels:			app=app-demo
			tier=frontend
Selector:		tier=frontend,tier in (frontend)
Replicas:		1 updated | 1 total | 1 available | 0 unavailable
StrategyType:		RollingUpdate
MinReadySeconds:	0
RollingUpdateStrategy:	1 max unavailable, 1 max surge
Conditions:
  Type		Status	Reason
  ----		------	------
  Available 	True	MinimumReplicasAvailable
OldReplicaSets:	<none>
NewReplicaSet:	frontend-141477217 (1/1 replicas created)
Events:
  FirstSeen	LastSeen	Count	From				SubObjectPath	Type		Reason			Message
  ---------	--------	-----	----				-------------	--------	------			-------
  12m		12m		1	{deployment-controller }			Normal		ScalingReplicaSet	Scaled up replica set frontend-141477217 to 1

Horizontal Pod Autoscaler (HPA)

通过手工执行 kubectl scale 命令,我们可以实现 Pod 扩容或缩容。但是这一过程在分布式系统中可能是频繁发生的、不可预料的,所以手动控制的方式是不现实的。Horizontal Pod Autoscaling (HPA) 与之前的 RC、Deployment 一样,也属于一种资源对象。它可以通过追踪 RC 控制的所有 Pod 的负载变化情况,来确定是否需要针对性的调整 Pod 的副本数,来实现智能扩容的特性。
HPA 可以有以下两种方式作为 Pod 负载的度量指标:

  1. CPUUtilizationPercentage
  2. 应用程序自定义的度量指标,比如服务在每秒内的请求数 (TPS 或 QPS)

CPUUtilizationPercentage 是目标 Pod 所有副本自身的 CPU 利用率的平均值。如果某一刻 CPUUtilizationPercentage 的值超过 80%,即表明当前 Pod 的副本数量很可能不足以支撑接下来的更多请求,需要进行动态扩容,而当请求高峰时段过去后,Pod 的 CPU 利用率又会降下来,此时目标 Pod 的副本数量又会自动减少到一个合理的水平。

HPA 资源定义文件

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

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

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

作用与刚刚的 yaml 配置文件相同。

Service

Service 是 Kubernetes 中最核心的资源对象之一,Kubernetes 中的每个 Service 其实就是我们经常提起的微服务架构中的一个“微服务”,之前我们所说的 Pod、RC 等资源对象其实都是为这项“微服务”— Kubernetes Service 提供服务的。
在这里插入图片描述
从图中我们看到,Kubernetes 的 Service 定义了一个服务的访问入口地址,前端的应用 (Pod) 通过这个入口地址访问到其背后的一组由 Pod 副本组成的集群实例,Service 与其后端 Pod 副本集群之间则是通过 Label Selector 来实现链接的。而 RC 的作用则是保证 Service 的服务能力和服务质量始终处于预期的标准。
由于 Pod 的 Endpoint 地址会随着 Pod 的销毁和重新创建而发生改变,而 Service 一旦创建,Kubernetes 就会自动为它分配一个可用的 Cluster IP,而且在 Service 的整个生命周期内,这个 Cluster IP 不会发生改变,这样每个服务就变成了具备唯一 IP 地址的可通信服务,服务调用也变成了最基础的 TCP 网络通信问题。

Service 资源定义文件

apiVersion: v1
kind: Service
metadata:
  name: tomcat-service
spec:
  ports:
  - port: 8080
  selector:
    tier: frontend

上面的资源定义文件定义了一个名为“tomcat-service”的 Service,它的服务端口为 8080,拥有“tier=frontend”这个 Label 的所有 Pod 副本都属于它。

$ kubectl get svc tomcat-service -o yaml
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: 2019-01-21T16:13:34Z
  name: tomcat-service
  namespace: default
  resourceVersion: "466446"
  selfLink: /api/v1/namespaces/default/services/tomcat-service
  uid: 80be3db2-1d97-11e9-badc-000c29e1e4e5
spec:
  clusterIP: 10.254.17.136
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    tier: frontend
  sessionAffinity: None
  type: ClusterIP
status:
  loadBalancer: {}

在 spec.ports 定义中,targetPort 属性用来确定提供该服务的容器的暴露 (expose) 的端口,即具体业务进程在容器内的 targetPort 上提供 TCP/IP 接入,而 port 属性则定义了 Service 的虚拟端口。如果没有指定 targetPort,则默认 targetPort 与 port 相同。
如果服务需要存在多个 Endpoint 的情况下,需要给每个 Endpoint 命名来区分,我们可以这样定义:

apiVersion: v1
kind: Service
metadata:
  name: tomcat-service
spec:
  ports:
  - port: 8080
    name: service-port
  - port: 8005
    name: shutdown-port
  selector:
    tier: frontend

Node IP、Pod IP、Cluster IP

Node IP,Node 节点的 IP 地址,即 Kubernetes 集群中每个节点的物理网卡的 IP 地址,这是一个真实存在的物理网络,所有属于这个网络中的服务器之间都能通过这个网络直接通信。这也表明了 Kubernetes 集群之外的节点访问 Kubernetes 集群之内的某个节点或者 TCP/IP 服务的时候,必须要通过 Node IP 进行通信。

Pod IP,Pod 的 IP 地址,它是通过 Docker Engine 根据 docker0 网桥的 IP 地址段进行分配的,通常是一个虚拟的二层网络。Kubernetes 要求位于不同 Node 上的 Pod 能够彼此直接通信,所以 Kubernetes 里的一个 Pod 中的容器访问另外一个 Pod 中的容器时,就是通过 Pod IP 所在的虚拟二层网络进行通信的,而真实的 TCP/IP 流量则是通过 Node IP 所在的物理网卡流出的。

Cluster IP,它是一个虚拟的 IP,Cluster IP 仅仅作用于 Kubernetes Service 这个对象,并由 Kubernetes 管理和分配 IP 地址 (来源于 Cluster IP 地址池)。且 Cluster IP 无法被 Ping,只能结合 Service Port 组成一个具体的通信端口,单独的 Cluter IP 不具备 TCP/IP 通信的基础,并且它们属于 Kubernetes 集群这个封闭的空间内,集群之外的节点需要访问这个通信端口,则需要做一些额外的工作。

NodePort

NodePort 是 Kubernetes 集群外部访问集群内部的 Service 的一个最直接、最有效、最常用的解决办法。以下就是我们如何在 Service 的资源定义文件中开启 NodePort 的具体方法:

apiVersion: v1
kind: Service
metadata:
  name: tomcat-service
spec:
  type: NodePort
  ports:
  - port: 8080
    nodePort: 31002
  selector:
    tier: frontend

上面的资源文件中,nodePort: 31002 这个属性表明我们手动指定 tomcat-service 的 NodePort 为 31002,如果我们不指定端口,Kubernetes 会自动分配一个可用的端口。然后我们就可以通过 Node IP + NodePort 的方式来访问 Service 了。

NodePort 的实现方式是在 Kubernetes 集群的每个 Node 上开启一个与 Service 对应的 TCP 监听端口,外部系统只要用任意一个 Node 的 IP 地址 + NodePort 即可访问该服务,但是这样无法解决 Service 的所有问题,比如负载均衡问题。我们需要结合集群外部的 Load balancer 负载均衡器来实现负载均衡,如 HAProxy 或 Nginx。于是 Kubernetes 提供了 type = LoadBalancer 的解决方案,不过需要我们的集群运行在谷歌的 GCE 公有云上才可以使用该功能。

Volume

Volume 是 Pod 中能够被多个容器访问的共享目录。Kubernetes 中的 Volume 定义在 Pod 上,然后被该 Pod 中的多个容器挂载到具体的文件目录下。Kubernetes 中的 Volume 的生命周期与 Pod 的生命周期相对应,与容器的生命周期不相关,当容器销毁或重启时,Volume 中的数据也不会丢失。且 Kubernetes 支持多种类型的 Volume,例如 GlusterFS、Ceph 等先进的分布式文件系统。

Pod 中容器挂载 Volume 配置文件

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

Volume 的各种类型

  1. emptyDir
    emptyDir 是在 Pod 分配到 Node 时创建的。其初始内容为空,无需指定宿主机上的对应目录文件。当 Pod 从 Node 上移除时,emptyDir 中的数据也会被永久删除。

  2. hostPath
    hostPath 在 Pod 上挂载宿主机上的文件或目录,需注意的是在不同 Node 上具有相同配置的 Pod 可能会因为宿主机上的目录和文件不同而导致对 Volume 上目录和文件的访问结果不一致;且如果使用了资源配额管理,则 Kubernetes 无法将 hostPath 在宿主机上使用的资源纳入管理。

volumes:
- name: "persistent-storage"
  hostPath:
    path: "/data"
  1. NFS
    使用 NFS 网络文件系统提供的共享目录存储数据时,我们需要在系统中部署一个 NFS Server。
volumes:
- name: nfs
  nfs:
    server: <NFS-Server>
  1. 其他类型
  • iscsi
  • flocker
  • glusterfs
  • rbd
  • gitRepo
  • secret

Persistent Volume

上文的 Volume 是定义在 Pod 上的,而 Persistent Volume (PV) 和与之相关的 Persistent Volume Claim (PVC) 则可以将网络存储的“网盘”挂载到集群中。PV 与 Volume 的区别如下:

  1. PV 只能是网络存储,不属于任何 Node,但可以在每个 Node 上访问
  2. PV 并不是定义在 Pod 上的,而是独立于 Pod 之外的定义
  3. PV 目前只有几种类型:NFS、RBD、ISCSI、GlusterFS、AWS、ElasticBlockStore 等

PV 资源定义文件 (NFS)

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

其中 accessMode 属性是 PV 的权限控制,分为:ReadWriteOnce (读写权限,只能被单个 Node 挂载)、ReadOnlyMany (只读权限,允许被多个 Node 挂载) 和 ReadWriteMany (读写权限,允许被多个 Node 挂载)。

如果某个 Pod 想使用某个 PV,我们还需要一个 PVC

PVC 资源定义文件

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: myclaim
spec:
  accessMode:
  - ReadWriteOnce
  resources:
    requests:
      storage: 8Gi

然后,在 Pod 的 Volume 定义中引用 PVC 即可:

volumes:
- name: mypd
  persistentVolumeClaim:
    claimName: myclaim

PV 状态分为以下几种:

  1. Available:空闲状态
  2. Bound:已经绑定在某个 PVC 上
  3. Released:对应的 PVC 已经删除,但资源没有被收回
  4. Failed:PV 资源回收失败

Namespace

Namespace 是 Kubernetes 系统中另一个非常重要的概念,Namespace 在很多情况下用于实现多租户的资源隔离。Namespace 通过将集群内部的资源对象“分配”到不同的 Namespace 中,形成逻辑上分组的不同项目、小组或用户组,便于不同的分组在共享使用整个集群的资源的同时还能被分别管理。
Kubernetes 集群在启动后,会创建一个名为“default”的Namespace,如果不特别指明 Namespace,则用户创建的 Pod、RC、Service 都将会被系统创建到这个默认的名为 default 的 Namespace 中。

Namepace

apiVersion: v1
kind: Namespace
metadata:
  name: development

只有 Namespace, 我们在创建资源对象时才能制定这个资源对象属于哪个 Namespace:

apiVersion: v1
kind: Pod
metadata:
  name: busybox
  namespace: development
spec:
  containers:
  - image: busybox
    command:
    - sleep:
    - "3600"
    name: busybox

此时使用 kubectl get 命令将无法查看信息,因为 kubectl get 命令在没有参数的情况下默认显示 “default” 命名空间的资源对象。想要查看某个命名空间的资源对象时,可以加入 --namespace 参数来查看。

$ kubectl get pods --namespace=development
NAME      READY   STATUS     RESTARTS   AGE
busybox    1/1    Running     0         2m

Annotation

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

  1. build 信息、release 信息、Docker 镜像信息等,如时间戳、release id 号、PR 号、镜像 hash 值、docker registry 地址等
  2. 日志库、监控库、分析库等资源库的地址信息
  3. 程序调试工具信息,例如工具名称、版本号等
  4. 团队的联系信息,例如电话号码、负责人名称、网址等
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值