html
Pod
资源对象是一种集合了一到多个应用容器、存储资源、专用IP
及支撑容器运行的其余选项的逻辑组件,如图所示。Pod
表明着Kubernetes
的部署单元及原子运行单元,即一个应用程序的单一运行实例,它一般由共享资源且关系紧密的一个或多个应用容器组成。前端
Kubernetes
的网络模型要求其各Pod
对象的IP
地址位于同一网络平面内(同一IP
网段),各Pod
之间可以使用其IP
地址直接进行通讯,不管它们运行于集群内的哪一个工做节点上,这些Pod
对象都像运行于同一局域网中的多个主机。node不过,
Pod
对象中的各进程均运行于彼此隔离的容器中,并于容器间共享两种关键资源:网络和存储卷。nginx
网络:每一个
Pod
对象都会被分配一个集群内专用的IP
地址,也称为Pod IP
,同一Pod
内部的全部容器共享Pod
对象的Network
和UTS
名称空间,其中包括主机名、IP
地址和端口等。所以,这些容器间的通讯能够基于本地回环接口lo
进行,而与Pod
外的其余组件的通讯则须要使用Service
资源对象的ClusterIP
及相应的端口完成。web存储卷:用户能够为
Pod
对象配置一组“存储卷”资源,这些资源能够共享给其内部的全部容器使用,从而完成容器间数据的共享。存储卷还能够确保在容器终止后重启,甚至是被删除后也能确保数据不会丢失,从而保证了生命周期内的Pod
对象数据的持久化存储。编程
一个
Pod
对象表明某个应用程序的一个特定实例,若是须要扩展应用程序,则意味着为此应用程序同时建立多个Pod
实例,每一个实例均表明应用程序的一个运行的“副本”(replica
)。这些副本化的Pod
对象的建立和管理一般由另外一组称为“控制器”(Controller
)的对象实现,例如,Deployment
控制器对象。后端建立
Pod
时,还可使用Pod Preset
对象为Pod
注入特定的信息,如ConfigMap
、Secret
、存储卷、挂载卷和环境变量等。有了Pod Preset
对象,Pod
模板的建立者就无须为每一个模板显示提供全部信息,所以,也就无须事先了解须要配置的每一个应用的细节便可完成模板定义。缓存基于指望的目标状态和各节点的资源可用性,
Master
会将Pod
对象调度至某选定的工做节点运行,工做节点于指向的镜像仓库(image register
)下载镜像,并于本地的容器运行时环境中启动容器。Master
会将整个集群的状态保存于etcd
中,并经过API Server
共享给集群的各组件及客户端。网络
app
但
Pod
对象自己并不具备“自愈”功能,如果由于工做节点甚至是调度器自身致使了运行失败,那么它将会被删除;一样,资源耗尽或节点故障致使的回收操做也会删除相关的Pod
对象。在设计上,Kubernetes
使用”控制器“实现对一次性的(用后即弃)Pod
对象的管理操做,例如,要确保部署的应用程序的Pod副本数量严格反映用户指望的数目,以及基于Pod
模板来建立Pod
对象等,从而实现Pod
对象的扩缩容、滚动更新和自愈能力等。例如,某节点发生故障时,相关的控制器会将此节点上运行的Pod
对象从新调度到其余节点进行重建。控制器自己也是一种资源类型,它有着多种实现,其中与工做负载相关的实现如
Replication Controller
、Deployment
、StatefulSet
、DaemonSet
和Jobs
等,也可统称它们为Pod
控制器。
Pod
控制器的定义一般由指望的副本数量、Pod
模板和标签选择器(Label Selector
)组成。Pod
控制器会根据标签选择器对Pod
对象的标签进行匹配检查,全部知足选择条件的Pod
对象都将受控于当前控制器并计入其副本总数,并确保此数目可以精确反映指望的副本数。
换言之,
Service
是“微服务”的一种实现,事实上它是一种抽象:经过规则定义出由多个Pod
对象组合而成的逻辑集合,并附带访问这组Pod
对象的策略。Service
对象挑选、关联Pod
对象的方式同Pod
控制器同样,都是要基于Label Selector
进行定义,其示意图以下
集群内的
Pod
对象可直接请求此类的Cluster IP
,例如,图中来自Pod client
的访问请求便可以Service
的Cluster IP
做为目标地址,但集群网络属于私有网络地址,它们仅在集群内部可达。将集群外部的访问流量引入集群内部的经常使用方法是经过节点网络进行,实现方法是经过工做节点的IP
地址和某端口(NodePort
)接入请求并将其代理至相应的Service
对象的Cluster IP
上的服务端口,然后由Service
对象将请求代理至后端的Pod
对象的Pod IP
及应用程序监听的端口。所以,图中的External Clients
这种来自集群外部的客户端没法直接请求此Service
提供的服务,而是须要事先经由某一个工做节点(如NodeY
)的IP
地址进行,这类请求须要两次转发才能到达目标Pod
对象,所以在通讯效率上必然存在负面影响。事实上,
NodePort
会部署于集群中的每个节点,这就意味着,集群外部的客户端经过任何一个工做节点的IP
地址来访问定义好的NodePort
均可以到达相应的Service
对象。此种场景下,若是存在集群外部的一个负载均衡器,便可将用户请求负载均衡至集群中的部分或者全部节点。这是一种称为“LoadBalancer”
类型的Service
,它一般是由Cloud Provider
自动建立并提供的软件负载均衡器,不过,也能够是有管理员手工配置的诸如F5
一类的硬件设备。简单来讲,
Service
主要有三种经常使用类型:第一种是仅用于集群内部通讯的ClusterIP
类型;第二种是接入集群外部请求的NodePort
类型,它工做与每一个节点的主机IP
之上;第三种是LoadBalancer
类型,它能够把外部请求负载均衡至多个Node
的主机IP
的NodePort
之上。此三种类型中,每一种都以其前一种为基础才能实现,并且第三种类型中的LoadBalancer
须要协同集群外部的组件才能实现,而且此外部组件并不接受Kubernetes
的管理。
在
Kubernetes
集群上自主运行的Pod
对象在非计划内终止后,其生命周期即告结束,用户须要再次手动建立相似的Pod
对象才能确保其容器中的依然可得。对于Pod
数量众多的场景,尤为是对微服务业务来讲,用户必将疲于应付此类需求。Kubernetes
的工做负载(workload
)类型的控制器可以自动确保由其管控的Pod
对象按用户指望的方式运行,所以,Pod的建立和管理大多会经过这种类型的控制器来进行,包括Deployment
、ReplicasSet
、ReplicationController
等。
1)建立Deployment控制器对象
kubectl run
命令可用于命令行直接建立Deploymen
t控制器,并以--image
选项指定的镜像运行Pod
中的容器,--dry-run
选项能够用于命令的测试,但并不真正执行资源对象的建立过程。
# 建立一个名字叫作nginx的deployment控制器,并指定pod镜像使用nginx:1.12版本,并暴露容器内的80端口,并指定副本数量为1个,并先经过--dry-run测试命令是否错误。 [root@k8s-master ~]# kubectl run nginx --image=nginx:1.12 --port=80 --replicas=1 --dry-run=true [root@k8s-master ~]# kubectl run nginx --image=nginx:1.12 --port=80 --replicas=1 deployment.apps/nginx created [root@k8s-master ~]# kubectl get pods #查看全部pod对象 NAME READY STATUS RESTARTS AGE nginx-685cc95cd4-9z4f4 1/1 Running 0 89s ###参数说明: --image 指定须要使用到的镜像。 --port 指定容器须要暴露的端口。 --replicas 指定目标控制器对象要自动建立Pod对象的副本数量。
2)打印资源对象的相关信息
kubectl get
命令可用来获取各类资源对象的相关信息,它既能显示对象类型特有格式的简要信息,也能按照指定格式为YAML
或JSON
的详细信息,或者使用Go
模板自定义要显示的属性及信息等。
[root@k8s-master ~]# kubectl get deployment #查看全部deployment控制器对象 NAME READY UP-TO-DATE AVAILABLE AGE nginx 1/1 1 1 66s ###字段说明: NAME 资源对象名称 READY 指望由当前控制器管理的Pod对象副本数及当前已有的Pod对象副本数 UP-TO-DATE 更新到最新版本定义的Pod对象的副本数量,在控制器的滚动更新模式下,表示已经完成版本更新的Pod对象的副本数量 AVAILABLE 当前处于可用状态的Pod对象的副本数量,便可正常提供服务的副本数。 AGE Pod的存在时长 说明:Deployment资源对象经过ReplicaSet控制器实例完成对Pod对象的控制,而非直接控制。另外,经过控制器建立的Pod对象都会被自动附加一个标签。格式为“run=<Controller_Name>”。 [root@k8s-master ~]# kubectl get deployment -o wide #查看deployment控制器对象的详细信息 NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR nginx 1/1 1 1 69m nginx nginx:1.12 run=nginx [root@k8s-master ~]# kubectl get pods #查看pod资源 NAME READY STATUS RESTARTS AGE nginx-685cc95cd4-9z4f4 1/1 Running 0 72m [root@k8s-master ~]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-685cc95cd4-9z4f4 1/1 Running 0 73m 10.244.1.12 k8s-node1 <none> <none> ###字段说明: NAME pode资源对象名称 READY pod中容器进程初始化完成并可以正常提供服务时即为就绪状态,此字段用于记录处于就绪状态的容器数量 STATUS pod的当前状态,其值有Pending、Running、Succeeded、Failed和Unknown等其中之一 RESTARTS Pod重启的次数 IP pod的IP地址,一般由网络插件自动分配 NODE pod被分配的节点。
3)访问Pod对象
这里部署的是
pod
是运行的为nginx
程序,因此咱们能够访问是否ok
,在kubernetes
集群中的任意一个节点上均可以直接访问Pod
的IP
地址。
[root@k8s-master ~]# kubectl get pods -o wide #查看pod详细信息 NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-685cc95cd4-9z4f4 1/1 Running 0 88m 10.244.1.12 k8s-node1 <none> <none> [root@k8s-master ~]# curl 10.244.1.12 #kubernetes集群的master节点上访问 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html> [root@k8s-node2 ~]# curl 10.244.1.12 #kubernetes集群的node节点上访问 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>
[root@k8s-master ~]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-685cc95cd4-9z4f4 1/1 Running 0 99m 10.244.1.12 k8s-node1 <none> <none> [root@k8s-master ~]# kubectl delete pods nginx-685cc95cd4-9z4f4 #删除上面的pod pod "nginx-685cc95cd4-9z4f4" deleted [root@k8s-master ~]# kubectl get pods -o wide #能够看出,当上面pod刚删除,接着deployment控制器又立刻建立了一个新的pod,且此次分配在k8s-node2节点上了。 NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-685cc95cd4-z5z9p 1/1 Running 0 89s 10.244.2.14 k8s-node2 <none> <none> [root@k8s-master ~]# curl 10.244.1.12 #访问以前的pod,能够看到已经不能访问 curl: (7) Failed connect to 10.244.1.12:80; 没有到主机的路由 [root@k8s-master ~]# [root@k8s-master ~]# curl 10.244.2.14 #访问新的pod,能够正常访问 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>
简单来讲,一个
Service
对象可视做经过其标签选择器过滤出的一组Pod
对象,并可以为此组Pod
对象监听的套接字提供端口代理及调度服务。就比如上面作的测试,若是没有Service
,那么每次都得去访问pod
对象本身的地址等。且那还只是建立了一个pod
对象,若是是多个。那么该如何是好?故使用Service
解决此问题。
1)建立Service对象(将Service端口代理至Pod端口示例)
"kubectl expose"
命令可用于建立Service
对象以将应用程序“暴露”(expose
)于网络中。
#方法一 [root@k8s-master ~]# kubectl expose deployment nginx --name=nginx-svc --port=80 --target-port=80 --protocol=TCP #为deployment的nginx建立service,取名叫nginx-svc,并经过service的80端口转发至容器的80端口上。 service/nginx-svc exposed #方法二 [root@k8s-master ~]# kubectl expose deployment/nginx --name=nginx-svc --port=80 --target-port=80 --protocol=TCP service/nginx-svc exposed ###参数说明: --name 指定service对象的名称 --port 指定service对象的端口 --target-port 指定pod对象容器的端口 --protocol 指定协议 [root@k8s-master ~]# kubectl get svc #查看service对象。或者kubectl get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 25h nginx-svc ClusterIP 10.109.54.136 <none> 80/TCP 41s
# master节点上经过ServiceIP进行访问 [root@k8s-master ~]# curl 10.109.54.136 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html> #新建一个客户端pod进行访问,这里这个客户端使用busybox镜像,且pod副本数量为1个,-it表示进入终端模式。--restart=Never,表示从不重启。 [root@k8s-master ~]# kubectl run client --image=busybox --replicas=1 -it --restart=Never If you don't see a command prompt, try pressing enter. / # wget -O - -q 10.109.54.136 #访问上面建立的(service)nginx-svc的IP <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> ...... / # / # wget -O - -q nginx-svc #访问上面建立的(service)名称nginx-svc <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title>
2)建立Service对象(将建立的Pod对象使用“NodePort”类型的服务暴露到集群外部)
[root@k8s-master ~]# kubectl run mynginx --image=nginx:1.12 --port=80 --replicas=2 #建立一个deployments控制器并使用nginx镜像做为容器运行的应用。 [root@k8s-master ~]# kubectl get pods #查看建立的pod NAME READY STATUS RESTARTS AGE client 1/1 Running 0 15h mynginx-68676f64-28fm7 1/1 Running 0 24s mynginx-68676f64-9q8dj 1/1 Running 0 24s nginx-685cc95cd4-z5z9p 1/1 Running 0 16h [root@k8s-master ~]# [root@k8s-master ~]# kubectl expose deployments/mynginx --type="NodePort" --port=80 --name=mynginx-svc #建立一个service对象,并将mynginx建立的pod对象使用NodePort类型暴露到集群外部。 service/mynginx-svc exposed [root@k8s-master ~]# [root@k8s-master ~]# kubectl get svc #查看service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 41h mynginx-svc NodePort 10.111.89.58 <none> 80:30884/TCP 10s nginx-svc ClusterIP 10.109.54.136 <none> 80/TCP 15h ###字段说明: PORT(S) 这里的mynginx-svc对象能够看出,集群中各工做节点会捕获发往本地的目标端口为30884的流量,并将其代理至当前service对象的80端口。因而集群外部的用户可使用当前集群中任一节点的此端口来请求Service对象上的服务。 [root@k8s-master ~]# [root@k8s-master ~]# netstat -nlutp |grep 30884 #查看master节点上是否有监听上面的30884端口 tcp6 0 0 :::30884 :::* LISTEN 7340/kube-proxy [root@k8s-node1 ~]# [root@k8s-node1 ~]# netstat -nlutp |grep 30884 #查看node节点是否有监听上面的30884端口 tcp6 0 0 :::30884 :::* LISTEN 2537/kube-proxy
3)Service资源对象的描述
[root@k8s-master ~]# kubectl describe service mynginx-svc Name: mynginx-svc Namespace: default Labels: run=mynginx Annotations: <none> Selector: run=mynginx Type: NodePort IP: 10.111.89.58 Port: <unset> 80/TCP TargetPort: 80/TCP NodePort: <unset> 30884/TCP Endpoints: 10.244.1.14:80,10.244.2.15:80 Session Affinity: None External Traffic Policy: Cluster Events: <none> ###字段说明: Selector 当前Service对象使用的标签选择器,用于选择关联的Pod对象 Type 即Service的类型,其值能够是ClusterIP、NodePort和LoadBalancer等其中之一 IP 当前Service对象的ClusterIP Port 暴露的端口,即当前Service用于接收并响应的端口 TargetPort 容器中的用于暴露的目标端口,由Service Port路由请求至此端口 NodePort 当前Service的NodePort,它是否存在有效值与Type字段中的类型相关 Endpoints 后端端点,即被当前Service的Selector挑中的全部Pod的IP及其端口 Session Affinity 是否启用会话粘性 External Traffic Policy 外部流量的调度策略
Service
对象内建的负载均衡机制可在其后端副本数量不止一个时自动进行流量分发,它还会自动监控关联到的Pod
的健康状态,以确保将请求流量分发至可用的后端Pod
对象。若某Deployment
控制器管理包含多个Pod
实例,则必要时用户还能够为其使用“滚动更新”机制将其容器镜像升级到新的版本或变动那些支持动态修改的Pod
属性。使用
kubect run
命令建立Deployment
对象时,“--replicas=”
选项可以指定由该对象建立或管理的Pod
对象副本的数量,且其数量支持运行时进行修改,并当即生效。“kubectl scale”
命令就是专用于变更控制器应用规模的命令,它支持对Deployment
资源对象的扩容和缩容操做。
[root@k8s-master ~]# kubectl get pods -l run=nginx #查看标签run=nginx的pod NAME READY STATUS RESTARTS AGE nginx-685cc95cd4-z5z9p 1/1 Running 0 17h [root@k8s-master ~]# [root@k8s-master ~]# kubectl scale deployments/nginx --replicas=3 #将其扩容到3个 deployment.extensions/nginx scaled [root@k8s-master ~]# [root@k8s-master ~]# kubectl get pods -l run=nginx #再次查看 NAME READY STATUS RESTARTS AGE nginx-685cc95cd4-f2cwb 1/1 Running 0 5s nginx-685cc95cd4-pz9dk 1/1 Running 0 5s nginx-685cc95cd4-z5z9p 1/1 Running 0 17h [root@k8s-master ~]# [root@k8s-master ~]# kubectl describe deployments/nginx #查看Deployment对象nginx详细信息 Name: nginx Namespace: default CreationTimestamp: Thu, 29 Aug 2019 15:29:31 +0800 Labels: run=nginx Annotations: deployment.kubernetes.io/revision: 1 Selector: run=nginx Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable StrategyType: RollingUpdate ... #由nginx自动建立的pod资源所有拥有同一个标签选择器“run=nginx”,所以,前面建立的Service资源对象nginx-svc的后端端点也已经经过标签选择器自动扩展到了这3个Pod对象相关的端点 [root@k8s-master ~]# kubectl describe service/nginx-svc Name: nginx-svc Namespace: default Labels: run=nginx Annotations: <none> Selector: run=nginx Type: ClusterIP IP: 10.109.54.136 Port: <unset> 80/TCP TargetPort: 80/TCP Endpoints: 10.244.1.15:80,10.244.2.14:80,10.244.2.16:80 Session Affinity: None Events: <none>
缩容的方式和扩容类似,只不过是将
Pod
副本的数量调至比原来小的数字便可。例如将nginx
的pod
副本缩减至2个
[root@k8s-master ~]# kubectl scale deployments/nginx --replicas=2 deployment.extensions/nginx scaled [root@k8s-master ~]# [root@k8s-master ~]# kubectl get pods -l run=nginx NAME READY STATUS RESTARTS AGE nginx-685cc95cd4-pz9dk 1/1 Running 0 10m nginx-685cc95cd4-z5z9p 1/1 Running 0 17h
[root@k8s-master ~]# kubectl get services #查看当前全部的service对象 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 43h mynginx-svc NodePort 10.111.89.58 <none> 80:30884/TCP 96m nginx-svc ClusterIP 10.109.54.136 <none> 80/TCP 17h [root@k8s-master ~]# kubectl delete service nginx-svc #删除service对象nginx-svc
[root@k8s-master ~]# kubectl delete deployment --all deployment.extensions "mynginx" deleted
注意:受控于控制器的Pod
对象在删除后会被重建,删除此类对象须要直接删除其控制器对象。不过,删除控制器时若不想删除其Pod
对象,可在删除命令上使用“--cascade=false“
选项。
虽然直接命令式管理的相关功能强大且适合用于操纵
Kubernetes
资源对象,但其明显的缺点是缺少操做行为以及待运行对象的可信源。另外,直接命令式管理资源对象存在较大的局限性,它们在设置资源对象属性方面提供的配置能力至关有限,并且还有很多资源并不支持命令操做进行建立,例如,用户没法建立带有多个容器的Pod
对象,也没法为Pod
对象建立存储卷。所以,管理资源对象更有效的方式是基于保存有对象配置信息的配置清单来进行。