Kubernetes学习-相关概念
Kubernetes架构图
上图可以看到如下组件,使用特别的图标表示Service和Label:
- Pod
- Container(容器)
- Label()(标签)
- Replication Controller(复制控制器)
- Service()(服务)
- Node(节点)
- Kubernetes Master(Kubernetes主节点)
Pod
Pod 是Kubernetes的基本操作单元,也是应用运行的载体。整个Kubernetes系统都是围绕着Pod展开的,比如如何部署运行Pod、如何保证Pod的数量、如何访问Pod等。另外,Pod是一个或多个机关容器的集合,提供了一种容器的组合的模型。
Pod(上图绿色方框)安排在节点上,包含一组容器和卷。同一个Pod里的容器共享同一个网络命名空间,可以使用localhost互相通信。Pod是短暂的,不是持续性实体。
- Pod是短暂的,pod重建的时候数据会丢失,对于需要持久化的数据,因为Kubernetes支持卷的概念,故可以使用持久化的卷类型。这样就能持久化容器数据使其能够跨重启而存在。
- 创建Pod时可以手动创建单个Pod,也可以使用Replication Controller使用Pod模板创建出多份拷贝。
- Pod是短暂的,那么重启时IP地址可能会改变,那么怎么才能从前端容器正确可靠地指向后台容器呢?这时可以使用Service。
Pods提供两种共享资源:网络和存储。
网络:
每个Pod被分配一个独立的IP地址,Pod中的每个容器共享网络命名空间,包括IP地址和网络端口。
Pod内的容器可以使用localhost相互通信。
当Pod中的容器与Pod 外部通信时,他们必须协调如何使用共享网络资源(如端口)。
存储:
Pod可以指定一组共享存储volumes。
Pod中的所有容器都可以访问共享volumes,允许这些容器共享数据。
volumes 还用于Pod中的数据持久化,以防其中一个容器需要重新启动而丢失数据。
- 基本操作
创建 kubectl create -f xxx.yaml
查询 kubectl get pod yourPodName kubectl describe pod yourPodName
删除 kubectl delete pod yourPodName
更新 kubectl replace /path/to/yourNewYaml.yaml
- Pod与容器
在Docker中,容器是最小的处理单元,增删改查的对象是容器,容器是一种虚拟化技术,容器之间是隔离的,隔离是基于Linux Namespace实现的。而在Kubernetes中,Pod包含一个或者多个相关的容器,Pod可以认为是容器的一种延伸扩展,一个Pod也是一个隔离体,而Pod内部包含的一组容器又是共享的(包括PID、Network、IPC、UTS)。除此之外,Pod中的容器可以访问共同的数据卷来实现文件系统的共享。
- Pod与Controller
Controller可以创建和管理多个Pod,提供副本管理、滚动升级和集群级别的自愈能力。如果一个Node故障,Controller就能自动将该节点上的Pod调度到其他健康的Node上。
- 镜像
在kubernetes中,镜像的下载策略为:
Always:每次都下载最新的镜像
Never:只使用本地镜像,从不下载
IfNotPresent:只有当本地没有的时候才下载镜像
Pod被分配到Node之后会根据镜像下载策略进行镜像下载,可以根据自身集群的特点来决定采用何种下载策略。无论何种策略,都要确保Node上有正确的镜像可用。
- 其他
通过yaml文件,可以在Pod中设置:
启动命令,如:spec-->containers-->command;
环境变量,如:spec-->containers-->env-->name/value;
端口桥接,如:spec-->containers-->ports-->containerPort/protocol/hostIP/hostPort(使用hostPort时需要注意端口冲突的问题,不过Kubernetes在调度Pod的时候会检查宿主机端口是否冲突,比如当两个Pod均要求绑定宿主机的80端口,Kubernetes将会将这两个Pod分别调度到不同的机器上);
Host网络,一些特殊场景下,容器必须要以host方式进行网络设置(如接收物理机网络才能够接收到的组播流),在Pod中也支持host网络的设置,如:spec-->hostNetwork=true;
数据持久化,如:spec-->containers-->volumeMounts-->mountPath;
重启策略,当Pod中的容器终止退出后,重启容器的策略。这里的所谓Pod的重启,实际上的做法是容器的重建,之前容器中的数据将会丢失,如果需要持久化数据,那么需要使用数据卷进行持久化设置。Pod支持三种重启策略:Always(默认策略,当容器终止退出后,总是重启容器)、OnFailure(当容器终止且异常退出时,重启)、Never(从不重启);
- Pod生命周期
Pod被分配到一个Node上之后,就不会离开这个Node,直到被删除。当某个Pod失败,首先会被Kubernetes清理掉,之后ReplicationController将会在其它机器上(或本机)重建Pod,重建之后Pod的ID发生了变化,那将会是一个新的Pod。所以,Kubernetes中Pod的迁移,实际指的是在新Node上重建Pod。
Replication Controller
Replication Controller确保任意时间都有指定数量的Pod“副本”在运行。如果为某个Pod创建了Replication Controller并且指定3个副本,它会创建3个Pod,并且持续监控它们。如果某个Pod不响应,那么Replication Controller会替换它。
当创建Replication Controller时,需要指定两个东西:
使用过程:
- rc.yaml文件
apiVersion: v1
kind: ReplicationController
metadata: #设置rc的元数据
name: frontend
labels:
name: frontend
spec:
replicas: 3 #设置Pod的具体数量
selector: #通过selector来匹配相应的Pod的label
name: frontend
template: #设置Pod的模板
metadata:
labels:
name: frontend
spec:
containers:
- name: frontend
image: kubeguide/guestbook-php-frontend:latest
imagePullPolicy: IfNotPresent #镜像拉取策略,分为Always,Never,IfNotPresent,默认是Always
env :
- name : GET_HOSTS_FROM
value : env
ports:
- containerPort: 80
yaml字段的含义:
spec.replicas:副本数量3
spec.selector:RC通过spec.selector来筛选要控制的Pod
spec.template:这里写Pod的定义(但不需要apiVersion和kind)
spec.template.metadata.labels:Pod的label,可以看到这个label与spec.selector相同
这个文件的意思:
定义一个RC对象,它的名字是frontend(metadata.name:frontend),保证有3个Pod运行(spec.replicas:3),Pod的镜像是kubeguide/guestbook-php-frontend:latest(spec.template.spec.containers.image:kubeguide/guestbook-php-frontend:latest)
关键在于spec.selector与spec.template.metadata.labels,这两个字段必须相同,否则下一步创建RC会失败。(也可以不写spec.selector,这样默认与spec.template.metadata.labels相同)
RC的常用操作命令:
通过kubectl创建RC
# kubectl create -f rc.yaml
查看RC具体信息
# kubectl describe rc frontend
通过RC修改Pod副本数量(需要修改yaml文件的spec.replicas字段到目标值,然后替换旧的yaml文件)
# kubectl replace -f rc.yaml
或
# kubect edit replicationcontroller frontend
对RC使用滚动升级,来发布新功能或修复BUG
# kubectl rolling-update frontend --image=kubeguide/guestbook-php-frontend:latest
当Pod中只有一个容器时,通过–image参数指定新的Tag完成滚动升级,但如果有多个容器或其他字段修改时,需要指定yaml文件
# kubectl rolling-update frontend -f FILE.yaml
如果在升级过程中出现问题(如发现配置错误、长时间无响应),可以使用CTRL+C退出,再进行回滚
# kubectl rolling-update frontend --image=kubeguide/guestbook-php-frontend:latest --rollback
但如果升级完成后出现问题(比如新版本程序出core),此命令就无能为力了。我们需要使用同样方法,利用原来的镜像,“升级”为旧版本。
Deployment
更加方便的管理Pod和Replica Set
k8s是一个高速发展的项目,在新的版本中,官方推荐使用Replica Set和Deployment来代替RC。那么它们优势在哪里,我们来看一看:
RC只支持基于等式的selector(env=dev或environment!=qa),但Replica Set还支持新的,基于集合的selector(version in (v1.0, v2.0)或env notin (dev, qa)),这对复杂的运维管理很方便。
使用Deployment升级Pod,只需要定义Pod的最终状态,k8s会为你执行必要的操作,虽然能够使用命令
# kubectl rolling-update
完成升级,但它是在客户端与服务端多次交互控制RC完成的,所以REST API中并没有rolling-update的接口,这为定制自己的管理系统带来了一些麻烦。Deployment拥有更加灵活强大的升级、回滚功能。
目前,Replica Set与RC的区别只是支持的selector不同,后续肯定会加入更多功能。Deployment使用了Replica Set,它是更高一层的概念。除非用户需要自定义升级功能或根本不需要升级Pod,在一般情况下,我们推荐使用Deployment而不直接使用Replica Set。
Deployment的一些基础命令。
$ kubectl describe deployments #查询详细信息,获取升级进度
$ kubectl rollout pause deployment/nginx-deployment2 #暂停升级
$ kubectl rollout resume deployment/nginx-deployment2 #继续升级
$ kubectl rollout undo deployment/nginx-deployment2 #升级回滚
$ kubectl scale deployment nginx-deployment --replicas 10 #弹性伸缩Pod数量
使用子命令create,创建Deployment
# kubectl create -f deployment.yaml --record
注意–record参数,使用此参数将记录后续创建对象的操作,方便管理与问题追溯
使用子命令edit,编辑spec.replicas/spec.template.spec.container.image字段,完成deployment的扩缩容与滚动升级(这要比子命令rolling-update速度快很多)
# kubectl edit deployment hello-deployment
使用rollout history命令,查看Deployment的历史信息
# kubectl rollout history deployment hello-deployment
上面提到RC在rolling-update升级成功后不能直接回滚,而使用Deployment却可以回滚到上一版本,但要加上–revision参数,指定版本号
# kubectl rollout history deployment hello-deployment --revision=2
使用rollout undo回滚到上一版本
# kubectl rollout undo deployment hello-deployment
使用–to-revision可以回滚到指定版本
# kubectl rollout undo deployment hello-deployment --to-revision=2
Volume
在Docker中,容器中的数据是临时的,当容器被销毁时,其中的数据将会丢失。如果需要持久化数据,需要使用Docker数据卷挂载宿主机上的文件或者目录到容器中。Docker中有docker Volume的概念,Docker的Volume只是磁盘中的一个目录,生命周期不受管理。当然Docker现在也提供Volume将数据持久化存储,但支持功能比较少(例如,对于Docker 1.7,每个容器只允许挂载一个Volume,并且不能将参数传递给Volume)。
在Kubernetes中,当Pod重建的时候,数据也会丢失,Kubernetes也是通过数据卷挂载来提供Pod数据的持久化的。Kubernetes数据卷是对Docker数据卷的扩展,Kubernetes数据卷是Pod级别的,可以用来实现Pod中容器的文件共享。Kubernetes Volume具有明确的生命周期 - 与pod相同。因此,Volume的生命周期比Pod中运行的任何容器要持久,在容器重新启动时可以保留数据,当然,当Pod被删除不存在时,Volume也将消失。注意,Kubernetes支持许多类型的Volume,Pod可以同时使用任意类型/数量的Volume。
要使用Volume,pod需要指定Volume的类型和内容(spec.volumes字段),和映射到容器的位置(spec.containers.volumeMounts字段)。
容器中的进程可以看到Docker image和volumes组成的文件系统。Docker image处于文件系统架构的root,任何volume都映射在镜像的特定路径上。Volume不能映射到其他volume上,或者硬链接到其他volume。容器中的每个容器必须堵路地指定他们要映射的volume。
Kubernetes支持Volume类型有:
- emptyDir
- hostPath
- gcePersistentDisk
- awsElasticBlockStore
- nfs
- iscsi
- fc (fibre channel)
- flocker
- glusterfs
- rbd
- cephfs
- gitRepo
- secret
- persistentVolumeClaim
- downwardAPI
- projected
- azureFileVolume
- azureDisk
- vsphereVolume
- Quobyte
- PortworxVolume
- ScaleIO
- StorageOS
- local
emptyDir
使用emptyDir,当Pod分配到Node上时,将会创建emptyDir,并且只要Node上的Pod一直运行,Volume就会一直存。当Pod(不管任何原因)从Node上被删除时,emptyDir也同时会删除,存储的数据也将永久删除。注:删除容器不影响emptyDir。
从名称就可以看出,它的初始内容为空。同一个pod中所有容器可以读和写emptyDir中的相同文件。
emptyDir的用途:
- 临时空间,例如用于某些应用程序运行时所需的临时目录,且无需永久保存;
- 长时间任务的中间过程CheckPoint临时保存目录;
- 一个容器需要从另一个容器中获取数据的目录(多容器共享目录)
示例:
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: gcr.io/google_containers/test-webserver
name: test-container
volumeMounts:
- mountPath: /cache
name: cache-volume
volumes:
- name: cache-volume
emptyDir: {}
hostPath
hostPath允许挂载Node上的文件系统到Pod里面去。如果Pod需要使用Node上的文件,可以使用hostPath。
hostPath通常应用于:
- 容器应用程序生成的日志文件需要永久保存,可以使用宿主机的高速文件系统进行存储;
- 需要访问宿主机上Docker引擎内部数据结构的容器应用,可以通过定义hostpath为宿主机/var/lib/docker目录,使得容器内部应用可以直接访问Docker的文件系统。
使用此类型的Volume时需注意:
在不同Node上具有相同配置的Pod可能会因为宿主机上的目录和文件不用而导致对Volume上目录和文件的访问结果不一致
示例
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: gcr.io/google_containers/test-webserver
name: test-container
volumeMounts:
- mountPath: /test-pd #容器路径
name: test-volume
volumes:
- name: test-volume
hostPath:
# directory location on host
path: /data #宿主机路径
gcePersistentDisk
gcePersistentDisk可以挂载GCE上的永久磁盘到容器,需要Kubernetes运行在GCE的VM中。与emptyDir不同,Pod删除时,gcePersistentDisk被删除,但Persistent Disk 的内容任然存在。这就意味着gcePersistentDisk能够允许我们提前对数据进行处理,而且这些数据可以在Pod之间“切换”。
提示:使用gcePersistentDisk,必须用gcloud或使用GCE API或UI 创建PD
创建PD
使用GCE PD与pod之前,需要创建它
gcloud compute disks create --size=500GB --zone=us-central1-a my-data-disk
示例
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: gcr.io/google_containers/test-webserver
name: test-container
volumeMounts:
- mountPath: /test-pd
name: test-volume
volumes:
- name: test-volume
# This GCE PD must already exist.
gcePersistentDisk:
pdName: my-data-disk
fsType: ext4
awsElasticBlockStore
awsElasticBlockStore可以挂载AWS上的EBS盘到容器,需要Kubernetes运行在AWS的EC2上。与emptyDir Pod被删除情况不同,Volume仅被卸载,内容将被保留。这就意味着awsElasticBlockStore能够允许我们提前对数据进行处理,而且这些数据可以在Pod之间“切换”。
提示:必须使用aws ec2 create-volumeAWS API 创建EBS Volume,然后才能使用。
创建EBS Volume
在使用EBS Volume与pod之前,需要创建它。
aws ec2 create-volume --availability-zone eu-west-1a --size 10 --volume-type gp2
AWS EBS配置示例
apiVersion: v1
kind: Pod
metadata:
name: test-ebs
spec:
containers:
- image: gcr.io/google_containers/test-webserver
name: test-container
volumeMounts:
- mountPath: /test-ebs
name: test-volume
volumes:
- name: test-volume
# This AWS EBS volume must already exist.
awsElasticBlockStore:
volumeID: <volume-id>
fsType: ext4
NFS
NFS 是Network File System的缩写,即网络文件系统。Kubernetes中通过简单地配置就可以挂载NFS到Pod中,而NFS中的数据是可以永久保存的,同时NFS支持同时写操作。Pod被删除时,Volume被卸载,内容被保留。这就意味着NFS能够允许我们提前对数据进行处理,而且这些数据可以在Pod之间相互传递。
iSCSI
iscsi允许将现有的iscsi磁盘挂载到我们的pod中,和emptyDir不同的是,删除Pod时会被删除,但Volume只是被卸载,内容被保留,这就意味着iscsi能够允许我们提前对数据进行处理,而且这些数据可以在Pod之间“切换”。
flocker
Flocker是一个开源的容器集群数据卷管理器。它提供各种存储后端支持的数据卷的管理和编排。
glusterfs
glusterfs,允许将Glusterfs(一个开源网络文件系统)Volume安装到pod中。不同于emptyDir,Pod被删除时,Volume只是被卸载,内容被保留。味着glusterfs能够允许我们提前对数据进行处理,而且这些数据可以在Pod之间“切换”。
RBD
RBD允许Rados Block Device格式的磁盘挂载到Pod中,同样的,当pod被删除的时候,rbd也仅仅是被卸载,内容保留,rbd能够允许我们提前对数据进行处理,而且这些数据可以在Pod之间“切换”。
cephfs
cephfs Volume可以将已经存在的CephFS Volume挂载到pod中,与emptyDir特点不同,pod被删除的时,cephfs仅被被卸载,内容保留。cephfs能够允许我们提前对数据进行处理,而且这些数据可以在Pod之间“切换”。
提示:可以使用自己的Ceph服务器运行导出,然后在使用cephfs。
gitRepo
gitRepo volume将git代码下拉到指定的容器路径中。
示例:
apiVersion: v1
kind: Pod
metadata:
name: server
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- mountPath: /mypath
name: git-volume
volumes:
- name: git-volume
gitRepo:
repository: "git@somewhere:me/my-git-repository.git"
revision: "22f1d8406d464b0c0874075539c1f2e96c253775"
secret
secret volume用于将敏感信息(如密码)传递给pod。可以将secrets存储在Kubernetes API中,使用的时候以文件的形式挂载到pod中,而不用连接api。 secret volume由tmpfs(RAM支持的文件系统)支持。
persistentVolumeClaim
persistentVolumeClaim用来挂载持久化磁盘的。PersistentVolumes是用户在不知道特定云环境的细节的情况下,实现持久化存储(如GCE PersistentDisk或iSCSI卷)的一种方式。
downwardAPI
通过环境变量的方式告诉容器Pod的信息
projected
Projected volume将多个Volume源映射到同一个目录
目前,可以支持以下类型的卷源:
- secret
- downwardAPI
- configMap
所有卷源都要求与pod在同一命名空间中。
示例
apiVersion: v1
kind: Pod
metadata:
name: volume-test
spec:
containers:
- name: container-test
image: busybox
volumeMounts:
- name: all-in-one
mountPath: "/projected-volume"
readOnly: true
volumes:
- name: all-in-one
projected:
sources:
- secret:
name: mysecret
items:
- key: username
path: my-group/my-username
- downwardAPI:
items:
- path: "labels"
fieldRef:
fieldPath: metadata.labels
- path: "cpu_limit"
resourceFieldRef:
containerName: container-test
resource: limits.cpu
- configMap:
name: myconfigmap
items:
- key: config
path: my-group/my-config apiVersion: v1
kind: Pod
metadata:
name: volume-test
spec:
containers:
- name: container-test
image: busybox
volumeMounts:
- name: all-in-one
mountPath: "/projected-volume"
readOnly: true
volumes:
- name: all-in-one
projected:
sources:
- secret:
name: mysecret
items:
- key: username
path: my-group/my-username
- secret:
name: mysecret2
items:
- key: password
path: my-group/my-password
mode: 511
FlexVolume
alpha功能
AzureFileVolume
AzureFileVolume用于将Microsoft Azure文件卷(SMB 2.1和3.0)挂载到Pod中。
AzureDiskVolume
Azure是微软提供的公有云服务,如果使用Azure上面的虚拟机来作为Kubernetes集群使用时,那么可以通过AzureDisk这种类型的卷插件来挂载Azure提供的数据磁盘。
vsphereVolume
需要条件:配置了vSphere Cloud Provider的Kubernetes。
vsphereVolume用于将vSphere VMDK Volume挂载到Pod中。卸载卷后,内容将被保留。它同时支持VMFS和VSAN数据存储。
重要提示:使用POD之前,必须使用以下方法创建VMDK。
创建一个VMDK卷
- 使用vmkfstools创建。先将ssh接入ESX,然后使用以下命令创建vmdk
vmkfstools -c 2G /vmfs/volumes/DatastoreName/volumes/myDisk.vmdk
- 使用vmware-vdiskmanager创建
shell vmware-vdiskmanager -c -t 0 -s 40GB -a lsilogic myDisk.vmdk
示例
apiVersion: v1
kind: Pod
metadata:
name: test-vmdk
spec:
containers:
- image: gcr.io/google_containers/test-webserver
name: test-container
volumeMounts:
- mountPath: /test-vmdk
name: test-volume
volumes:
- name: test-volume
# This VMDK volume must already exist.
vsphereVolume:
volumePath: "[DatastoreName] volumes/myDisk"
fsType: ext4
Quobyte
在kubernetes中使用Quobyte存储,需要提前部署Quobyte软件,要求必须是1.3以及更高版本,并且在kubernetes管理的节点上面部署Quobyte客户端。
PortworxVolume
Portworx能把你的服务器容量进行蓄积(pool),将你的服务器或者云实例变成一个聚合的高可用的计算和存储节点。
PortworxVolume可以通过Kubernetes动态创建,也可以在Kubernetes pod中预先配置和引用。示例:
apiVersion: v1
kind: Pod
metadata:
name: test-portworx-volume-pod
spec:
containers:
- image: gcr.io/google_containers/test-webserver
name: test-container
volumeMounts:
- mountPath: /mnt
name: pxvol
volumes:
- name: pxvol
# This Portworx volume must already exist.
portworxVolume:
volumeID: "pxvol"
fsType: "<fs-type>"
ScaleIO
ScaleIO是一种基于软件的存储平台(虚拟SAN),可以使用现有硬件来创建可扩展共享块网络存储的集群。ScaleIO卷插件允许部署的pod访问现有的ScaleIO卷(或者可以为持久卷声明动态配置新卷,请参阅 Scaleio Persistent Volumes)。
示例:
apiVersion: v1
kind: Pod
metadata:
name: pod-0
spec:
containers:
- image: gcr.io/google_containers/test-webserver
name: pod-0
volumeMounts:
- mountPath: /test-pd
name: vol-0
volumes:
- name: vol-0
scaleIO:
gateway: https://localhost:443/api
system: scaleio
volumeName: vol-0
secretRef:
name: sio-secret
fsType: xfs
StorageOS
StorageOS是一家英国的初创公司,给无状态容器提供简单的自动块存储、状态来运行数据库和其他需要企业级存储功能,但避免随之而来的复杂性、刚性以及成本。
核心:是StorageOS向容器提供块存储,可通过文件系统访问。
StorageOS容器需要64位Linux,没有额外的依赖关系,提供免费开发许可证。
安装说明,请参阅StorageOS文档
apiVersion: v1
kind: Pod
metadata:
labels:
name: redis
role: master
name: test-storageos-redis
spec:
containers:
- name: master
image: kubernetes/redis:v1
env:
- name: MASTER
value: "true"
ports:
- containerPort: 6379
volumeMounts:
- mountPath: /redis-master-data
name: redis-data
volumes:
- name: redis-data
storageos:
# The `redis-vol01` volume must already exist within StorageOS in the `default` namespace.
volumeName: redis-vol01
fsType: ext4
有关动态配置和持久卷声明的更多信息,请参阅StorageOS示例。
Local
目前处于 Kubernetes 1.7中的 alpha 级别。
Local 是Kubernetes集群中每个节点的本地存储(如磁盘,分区或目录),在Kubernetes1.7中kubelet可以支持对kube-reserved和system-reserved指定本地存储资源。
通过上面的这个新特性可以看出来,Local Storage同HostPath的区别在于对Pod的调度上,使用Local Storage可以由Kubernetes自动的对Pod进行调度,而是用HostPath只能人工手动调度Pod,因为Kubernetes已经知道了每个节点上kube-reserved和system-reserved设置的本地存储限制。
示例:
apiVersion: v1
kind: PersistentVolume
metadata:
name: example-pv
annotations:
"volume.alpha.kubernetes.io/node-affinity": '{
"requiredDuringSchedulingIgnoredDuringExecution": {
"nodeSelectorTerms": [
{ "matchExpressions": [
{ "key": "kubernetes.io/hostname",
"operator": "In",
"values": ["example-node"]
}
]}
]}
}'
spec:
capacity:
storage: 100Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Delete
storageClassName: local-storage
local:
path: /mnt/disks/ssd1
请注意,本地PersistentVolume需要手动清理和删除。
有关local卷类型的详细信息,请参阅 Local Persistent Storage user guide
Using subPath
有时,可以在一个pod中,将同一个卷共享,使其有多个用处。volumeMounts.subPath特性可以用来指定卷中的一个子目录,而不是直接使用卷的根目录。
以下是使用单个共享卷的LAMP堆栈(Linux Apache Mysql PHP)的pod的示例。HTML内容映射到其html文件夹,数据库将存储在mysql文件夹中:
apiVersion: v1
kind: Pod
metadata:
name: my-lamp-site
spec:
containers:
- name: mysql
image: mysql
volumeMounts:
- mountPath: /var/lib/mysql
name: site-data
subPath: mysql
- name: php
image: php
volumeMounts:
- mountPath: /var/www/html
name: site-data
subPath: html
volumes:
- name: site-data
persistentVolumeClaim:
claimName: my-lamp-site-data
Resources
emptyDir Volume的存储介质(Disk,SSD等)取决于kubelet根目录(如/var/lib/kubelet)所处文件系统的存储介质。不限制emptyDir或hostPath Volume使用的空间大小,不对容器或Pod的资源隔离。
Service
Service是定义一系列Pod以及访问这些Pod的策略的一层抽象。因为Service是抽象的,所以在图表里通常看不到它们的存在。
Service通过Label找到Pod组。当你在Service的yaml文件中定义了该Service的selector中的label为app:my-web,那么这个Service会将Pod-->metadata-->labeks中label为app:my-web的Pod作为分发请求的后端。当Pod发生变化时(增加、减少、重建等),Service会及时更新。这样一来,Service就可以作为Pod的访问入口,起到代理服务器的作用,而对于访问者来说,通过Service进行访问,无需直接感知Pod。
Service的目标是提供一种桥梁, 它会为访问者提供一个固定访问地址,用于在访问时重定向到相应的后端,这使得非 Kubernetes原生应用程序,在无须为Kubemces编写特定代码的前提下,轻松访问后端。
需要注意的是,Kubernetes分配给Service的固定IP是一个虚拟IP,并不是一个真实的IP,在外部是无法寻址的。真实的系统实现上,Kubernetes是通过Kube-proxy组件来实现的虚拟IP路由及转发。所以在之前集群部署的环节上,我们在每个Node上均部署了Proxy这个组件,从而实现了Kubernetes层级的虚拟转发网络。有一个特别类型的Kubernetes Service,称为'LoadBalancer',作为外部负载均衡器使用,在一定数量的Pod之间均衡流量。比如,对于负载均衡Web流量很有用。
现在,假定有2个后台Pod,并且定义后台Service的名称为‘backend-service’,lable选择器为(tier=backend, app=myapp)。backend-service 的Service会完成如下两件重要的事情:
- 会为Service创建一个本地集群的DNS入口,因此前端Pod只需要DNS查找主机名为 ‘backend-service’,就能够解析出前端应用程序可用的IP地址。
- 现在前端已经得到了后台服务的IP地址,但是它应该访问2个后台Pod的哪一个呢?Service在这2个后台Pod之间提供透明的负载均衡,会将请求分发给其中的任意一个。通过每个Node上运行的代理(kube-proxy)完成。
Service代理外部服务
Service不仅可以代理Pod,还可以代理任意其他后端,比如运行在Kubernetes外部Mysql、Oracle等。这是通过定义两个同名的service和endPoints来实现的。示例如下:
redis-service.yaml
apiVersion: v1
kind: Service
metadata:
name: redis-service
spec:
ports:
- port: 6379
targetPort: 6379
protocol: TCP
redis-endpoints.yaml
apiVersion: v1
kind: Endpoints
metadata:
name: redis-service
subsets:
- addresses:
- ip: 10.0.251.145
ports:
- port: 6379
protocol: TCP
基于文件创建完Service和Endpoints之后,在Kubernetes的Service中即可查询到自定义的Endpoints。
[root@k8s-master demon]# kubectl describe service redis-service
Name: redis-service
Namespace: default
Labels: <none>
Selector: <none>
Type: ClusterIP
IP: 10.254.52.88
Port: <unset> 6379/TCP
Endpoints: 10.0.251.145:6379
Session Affinity: None
No events.
[root@k8s-master demon]# etcdctl get /skydns/sky/default/redis-service
{"host":"10.254.52.88","priority":10,"weight":10,"ttl":30,"targetstrip":0}
Service内部负载均衡
当Service的Endpoints包含多个IP的时候,及服务代理存在多个后端,将进行请求的负载均衡。默认的负载均衡策略是轮训或者随机(有kube-proxy的模式决定)。同时,Service上通过设置Service-->spec-->sessionAffinity=ClientIP,来实现基于源IP地址的会话保持。
发布Service
Service的虚拟IP是由Kubernetes虚拟出来的内部网络,外部是无法寻址到的。但是有些服务又需要被外部访问到,例如web前段。这时候就需要加一层网络转发,即外网到内网的转发。Kubernetes提供了NodePort、LoadBalancer、Ingress三种方式。
- NodePort,在之前的Guestbook示例中,已经延时了NodePort的用法。NodePort的原理是,Kubernetes会在每一个Node上暴露出一个端口:nodePort,外部网络可以通过(任一Node)[NodeIP]:[NodePort]访问到后端的Service。
- LoadBalancer,在NodePort基础上,Kubernetes可以请求底层云平台创建一个负载均衡器,将每个Node作为后端,进行服务分发。该模式需要底层云平台(例如GCE)支持。
- Ingress,是一种HTTP方式的路由转发机制,由Ingress Controller和HTTP代理服务器组合而成。Ingress Controller实时监控Kubernetes API,实时更新HTTP代理服务器的转发规则。HTTP代理服务器有GCE Load-Balancer、HaProxy、Nginx等开源方案。
servicede 自发性机制
Kubernetes中有一个很重要的服务自发现特性。一旦一个service被创建,该service的service IP和service port等信息都可以被注入到pod中供它们使用。Kubernetes主要支持两种service发现 机制:环境变量和DNS。
环境变量方式
Kubernetes创建Pod时会自动添加所有可用的service环境变量到该Pod中,如有需要.这些环境变量就被注入Pod内的容器里。需要注意的是,环境变量的注入只发送在Pod创建时,且不会被自动更新。这个特点暗含了service和访问该service的Pod的创建时间的先后顺序,即任何想要访问service的pod都需要在service已经存在后创建,否则与service相关的环境变量就无法注入该Pod的容器中,这样先创建的容器就无法发现后创建的service。
DNS方式
Kubernetes集群现在支持增加一个可选的组件——DNS服务器。这个DNS服务器使用Kubernetes的watchAPI,不间断的监测新的service的创建并为每个service新建一个DNS记录。如果DNS在整个集群范围内都可用,那么所有的Pod都能够自动解析service的域名。
多个service如何避免地址和端口冲突
此处设计思想是,Kubernetes通过为每个service分配一个唯一的ClusterIP,所以当使用ClusterIP:port的组合访问一个service的时候,不管port是什么,这个组合是一定不会发生重复的。另一方面,kube-proxy为每个service真正打开的是一个绝对不会重复的随机端口,用户在service描述文件中指定的访问端口会被映射到这个随机端口上。这就是为什么用户可以在创建service时随意指定访问端口。
service目前存在的不足
Kubernetes使用iptables和kube-proxy解析service的人口地址,在中小规模的集群中运行良好,但是当service的数量超过一定规模时,仍然有一些小问题。首当其冲的便是service环境变量泛滥,以及service与使用service的pod两者创建时间先后的制约关系。目前来看,很多使用者在使用Kubernetes时往往会开发一套自己的Router组件来替代service,以便更好地掌控和定制这部分功能。
Kubernetes学习-相关概念的更多相关文章
- Kubernetes学习之路目录
Kubernetes基础篇 环境说明 版本说明 系统环境 Centos 7.2 Kubernetes版本 v1.11.2 Docker版本 v18.09 Kubernetes学习之路(一)之概念和架构 ...
- kubernetes学习资源
参考文章: 1.kubernetes学习资源 1. <Kubernetes与云原生应用>系列之Kubernetes的系统架构与设计理念 2.[docker专业介绍的网站dockerinfo ...
- Kubernetes 学习笔记(一):基础概念
个人笔记,仅本人查阅使用,不保证正确. 零.微服务 微服务架构专注于应用解耦合,通过将应用彻底地组件化和服务化,每个微服务只包含一个非常小的功能,比如权限管理.日志收集等等.由这一组微服务组合起来,提 ...
- Kubernetes学习笔记(八):Deployment--声明式的升级应用
概述 本文核心问题是:如何升级应用. 对于Pod的更新有两种策略: 一是删除全部旧Pod之后再创建新Pod.好处是,同一时间只会有一个版本的应用存在:缺点是,应用有一段时间不可用. 二是先创建新Pod ...
- Kubernetes 学习(十)Kubernetes 容器持久化存储
0. 前言 最近在学习张磊老师的 深入剖析Kubernetes 系列课程,最近学到了 Kubernetes 容器持久化存储部分 现对这一部分的相关学习和体会做一下整理,内容参考 深入剖析Kuberne ...
- kubernetes学习笔记
docker实现了更便捷的单机容器虚拟化的管理, docker的位置处于操作系统层与应用层之间; 相对传统虚拟化(KVM,XEN): docker可以更加灵活的去实现一些应用层功能, 同时对资源的利用 ...
- kubernetes学习01—kubernetes介绍
本文收录在容器技术学习系列文章总目录 一.简介 1.Kubernetes代码托管在GitHub上:https://github.com/kubernetes/kubernetes/. 2.Kubern ...
- kubernetes学习14—Dashboard搭建和认证
本文收录在容器技术学习系列文章总目录 一.介绍 Kubernetes Dashboard是Kubernetes集群的基于Web的通用UI.它允许用户管理在群集中运行的应用程序并对其进行故障排除,以及管 ...
- 深入剖析Kubernetes学习笔记:开篇词(00)
一.关于Kubernetes初学的疑惑 就在这场因"容器"而起的技术变革中,kubernetes项目已经成为容器技术的事实标准,重新定义了基础设置领域对应用编排与管理的种种可能 1 ...
随机推荐
- oracle11g之管理oracle数据库笔记(理论基础知识)
第三章 管理oracle数据库 1.启动数据库步骤;(创建启动实例--> ...
- oracle11g之Oracle体系结构(理论基础知识)
第二章 oracle的体系结构 一.oracle体系结构概述1.实例和数据库组成完整的Oracle数据库系统数据库:一系列物理文件的集合(数据文件,控制文件,联机日志,参数文件等)实例:一组oracl ...
- spring,springMVC,mybatis项目添加maven后报500错
<resources> <resource> <directory>src/main/java</directory> <includes> ...
- SpringBoot 动态打包
配置pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="h ...
- Notes 20180506 : Java程序设计语言概述
2.Java程序设计语言概述 如果对于开发语言的排行榜有所关注的话,那么会发现很长一段时间以来Java都是位居榜首的高级开发语言,作为一个Java开发者,为此感到骄傲的同时也深感忧虑,骄傲的是自己接触 ...
- ora.ctssd OBSERVER
[grid@ydb1 ~]$ crsctl status res -t -init ora.ctssd 1 ONLINE ONLINE ydb1 ...
- JS与OC交互,JS中调用OC方法(获取JSContext的方式)
最近用到JS和OC原生方法调用的问题,查了许多资料都语焉不详,自己记录一下吧,如果有误欢迎联系我指出. JS中调用OC方法有三种方式: 1.通过获取JSContext的方式直接调用OC方法 2.通过继 ...
- TCP|UDP|Http|Socket
TCP_IP.Http.Socket的区别 - 计算机网络知识库 iOS-Socket网络通信-框架与API - 简书 CocoaAsyncSocket + Protobuf 处理粘包和拆包问题 - ...
- MySQL案例04:Cause: java.sql.SQLException: Could not retrieve transaction read-only status from server
今天同事发现程序日志有异常抛出,询问原因,进过排查发现与java的连接参数有关系,具体处理过程如下: 一.错误信息 "message": "\n### Error upd ...
- 解决 SSH 不能输入中文的问题
有些应用的进程名称可能是中文,还有一些应用创建的目录可以也会是中文,在 SSH 上使用 debugserver 没有办法输入中文的进程名称,也没办法在 SSH 上操作中文的目录,网上试了一些方法,不过 ...