kubernetes应用部署原理
Kubernetes应用部署模型解析(原理篇)
Kubernetes架构

Kubernetes代理节点Kubelet和Kube-proxy运行在代理节点上。他们监听服务节点的信息来启动容器和实现Kubernetes网络和其它业务模型,比如Service、Pod等。当然每个代理节点都运行Docker。Docker负责下载容器镜像和运行容器。
Kubelet
Kube-ProxyKube-proxy是一个简单的网络代理和负载均衡器。它具体实现Service模型,每个Service都会在所有的Kube-proxy节点上体现。根据Service的selector所覆盖的Pods, Kube-proxy会对这些Pods做负载均衡来服务于Service的访问者。
Kubernetes服务节点Kubernetes服务组件形成了Kubernetes的控制平面,目前他们运行在单一节点上,但是将来会分开来部署,以支持高可用性。
etcd所有的持久性状态都保存在etcd中。Etcd同时支持watch,这样组件很容易得到系统状态的变化,从而快速响应和协调工作。
Kubernetes API Server这个组件提供对API的支持,响应REST操作,验证API模型和更新etcd中的相应对象。
Scheduler通过访问Kubernetes中/binding API, Scheduler负责Pods在各个节点上的分配。Scheduler是插件式的,Kubernetes将来可以支持用户自定义的scheduler。
Kubernetes Controller Manager ServerController Manager Server负责所有其它的功能,比如endpoints控制器负责Endpoints对象的创建,更新。node控制器负责节点的发现,管理和监控。将来可能会把这些控制器拆分并且提供插件式的实现。
Kubernetes模型Kubernetes的伟大之处就在于它的应用部署模型,主要包括Pod、Replication controller、Label和Service。
PodKubernetes的最小部署单元是Pod而不是容器。作为First class API公民,Pods能被创建,调度和管理。简单地来说,像一个豌豆荚中的豌豆一样,一个Pod中的应用容器同享同一个上下文:
- PID 名字空间。但是在docker中不支持
- 网络名字空间,在同一Pod中的多个容器访问同一个IP和端口空间。
- IPC名字空间,同一个Pod中的应用能够使用SystemV IPC和POSIX消息队列进行通信。
- UTS名字空间,同一个Pod中的应用共享一个主机名。
- Pod中的各个容器应用还可以访问Pod级别定义的共享卷。
Pods被调度到节点,保持在这个节点上直到被销毁。当节点死亡时,分配到这个节点的Pods将会被删掉。将来可能会实现Pod的迁移特性。在实际使用时,我们一般不直接创建Pods,
我们通过replication
controller来负责Pods的创建,复制,监控和销毁。一个Pod可以包括多个容器,他们直接往往相互协作完成一个应用功能。
Replication controller复制控制器确保Pod的一定数量的份数(replica)在运行。如果超过这个数量,控制器会杀死一些,如果少了,控制器会启动一些。控制器也会在节点失效、维护的时候来保证这个数量。所以强烈建议即使我们的份数是1,也要使用复制控制器,而不是直接创建Pod。
ServiceService定义了一个Pod的逻辑集合和访问这个集合的策略。集合是通过定义Service时提供的Label选择器完成的。举个例子,我们假定有3个Pod的备份来完成一个图像处理的后端。这些后端备份逻辑上是相同的,前端不关心哪个后端在给它提供服务。虽然组成这个后端的实际Pod可能变化,前端客户端不会意识到这个变化,也不会跟踪后端。Service就是用来实现这种分离的抽象。
Service Cluster IP和 kuber proxy每个代理节点都运行了一个kube-proxy进程。这个进程从服务进程那边拿到Service和Endpoint对象的变化。
对每一个Service, 它在本地打开一个端口。 到这个端口的任意连接都会代理到后端Pod集合中的一个Pod
IP和端口。在创建了服务后,服务Endpoint模型会体现后端Pod的
IP和端口列表,kube-proxy就是从这个endpoint维护的列表中选择服务后端的。另外Service对象的sessionAffinity属性也会帮助kube-proxy来选择哪个具体的后端。缺省情况下,后端Pod的选择是随机的。可以设置service.spec.sessionAffinity
成"ClientIP"来指定同一个ClientIP的流量代理到同一个后端。在实现上,kube-proxy会用IPtables规则把访问Service的Cluster
IP和端口的流量重定向到这个本地端口。下面的部分会讲什么是service的Cluster IP。
内部使用者的服务发现Kubernetes在一个集群内创建的对象或者在代理集群节点上发出访问的客户端我们称之为内部使用者。要把服务暴露给内部使用者,Kubernetes支持两种方式:环境变量和DNS。
环境变量当kubelet在某个节点上启动一个Pod时,它会给这个Pod的容器为当前运行的Service设置一系列环境变量,这样Pod就可以访问这些Service了。一般地情况是{SVCNAME}_SERVICE_HOSTh和{SVCNAME}_SERVICE_PORT变量,
其中{SVCNAME}是Service名字变成大写,中划线变成下划线。比如Service "Redis-master",它的端口是 TCP 6379,分配到的Cluster IP地址是 10.0.0.11,kubelet可能会产生下面的变量给新创建的Pod容器:
REDIS_MASTER_SERVICE_PORT=6379
REDIS_MASTER_PORT=tcp://10.0.0.11:6379
REDIS_MASTER_PORT_6379_TCP=tcp://10.0.0.11:6379
REDIS_MASTER_PORT_6379_TCP_PROTO=tcp
REDIS_MASTER_PORT_6379_TCP_PORT=6379
REDIS_MASTER_PORT_6379_TCP_ADDR= 10.0.0.11
DNS一个可选的Kubernetes附件(强烈建议用户使用)是DNS服务。它跟踪集群中Service对象,为每个Service对象创建DNS记录。这样所有的Pod就可以通过DNS访问服务了。
名字空间"my-ns"中有个叫my-service的服务,DNS服务会创建一条"my-service.my-ns"的DNS记录。同在这个命名空间的Pod就可以通过"my-service"来得到这个Service分配到的Cluster
IP,在其它命名空间的Pod则可以用全限定名"my-service.my-ns"来获得这个Service的地址。
Pod IP and Service Cluster IPPod IP
地址是实际存在于某个网卡(可以是虚拟设备)上的,但Service Cluster
IP就不一样了,没有网络设备为这个地址负责。它是由kube-proxy使用Iptables规则重新定向到其本地端口,再均衡到后端Pod的。我们前面说的Service环境变量和DNS都使用Service的Cluster
IP和端口。

外部访问ServiceService对象在Cluster IP range池中分配到的IP只能在内部访问,如果服务作为一个应用程序内部的层次,还是很合适的。如果这个Service作为前端服务,准备为集群外的客户提供业务,我们就需要给这个服务提供公共IP了。
是代理节点的物理IP地址。和先前的Cluster IP
range上分配到的虚拟的IP一样,kube-proxy同样会为这些publicIP提供Iptables
重定向规则,把流量转发到后端的Pod上。有了publicIP,我们就可以使用load
balancer等常用的互联网技术来组织外部对服务的访问了。
Label和Label selectorLabel标签在Kubernetes模型中占着非常重要的作用。Label表现为key/value对,附加到Kubernetes管理的对象上,典型的就是Pods。它们定义了这些对象的识别属性,用来组织和选择这些对象。Label可以在对象创建时附加在对象上,也可以对象存在时通过API管理对象的Label。
environment = productiontier != frontendenvironment = production,tier != frontend
environment in (production, qa)tier notin (frontend, backend)partition
一个简单的应用
部署Kubernetes集群
- 所有的节点安装了docker version 1.2+ 和 bridge-utils
- 如果没有本地的docker registry, 要确保节点能访问互联网gcr.io
- 确保管理节点能够ssh 访问所有节点。比如ssh gongysh@192.168.0.201 ls

$ git clone https://github.com/GoogleCloudPlatform/kubernetes.git
cd kubernetes./build/run.sh hack/build-do.sh
gongysh@fedora20:~/git/kubernetes/cluster/ubuntu$
cat config-default.sh#!/bin/bash# Define all your cluster nodes, MASTER
node comes first"# And separated with blank space like
<user_1@ip_1> <user_2@ip_2> <user_3@ip_3>export
nodes="gongysh@192.168.0.201 gongysh@192.168.0.202 gongysh@192.168.0.203"#
Define all your nodes role: a(master) or i(minion) or ai(both master
and minion), must be the order sameexport roles=("ai" "i" "i")# Define
minion numbersexport NUM_MINIONS=${NUM_MINIONS:-3}# define the IP range
used for service portal.# according to rfc 1918 ref: https://tools.ietf.org/html/rfc1918
choose a private ip range here.export
SERVICE_CLUSTER_IP_RANGE=192.168.3.0/24# define the IP range used for
flannel overlay network, should not conflict with above
SERVICE_CLUSTER_IP_RANGE rangeexport FLANNEL_NET=172.16.0.0/16....
$ cd cluster$ KUBERNETES_PROVIDER=ubuntu ./kube-up.sh
Kubernetes cluster is running. The master is running at: http://192.168.0.201
... calling validate-cluster Found 3 nodes. 1 NAME
LABELS STATUS 2 192.168.0.201 <none>
Ready 3 192.168.0.202 <none> Ready 4
192.168.0.203 <none> Ready Validate output: Cluster
validation succeeded Done, listing cluster services: Kubernetes master
is running at http://192.168.0.201:8080

部署nginx pod 和复制器
$ cat nginx-rc.yaml apiVersion: v1 kind: ReplicationController
metadata: name: nginx-controller spec: replicas: 2 selector:
name: nginx template: metadata: labels: name:
nginx spec: containers: - name: nginx image:
nginx ports: - containerPort: 80
$ kubectl -s http://192.168.0.201:8080 create -f nginx-rc.yaml
$ kubectl -s http://192.168.0.201:8080
get podsNAME READY REASON RESTARTS
AGEnginx-controller-6zr34 1/1 Running 0
48mnginx-controller-njlgt 1/1 Running 0 48m
$ $ kubectl -s http://192.168.0.201:8080
describe pod nginx-controller-6zr34 2>/dev/null | grep Node:Node:
192.168.0.203/192.168.0.203$ kubectl -s http://192.168.0.201:8080 describe pod nginx-controller-njlgt 2>/dev/null | grep Node:Node: 192.168.0.201/192.168.0.201
部署节点内部可访问的nginx service
$ cat nginx-service-clusterip.yaml apiVersion: v1 kind: Service
metadata: name: nginx-service-clusterip spec: ports: - port:
8001 targetPort: 80 protocol: TCP selector: name:
nginx
$ kubectl -s http://192.168.0.201:8080 create -f ./nginx-service-clusterip.yaml services/nginx-service $ kubectl -s http://192.168.0.201:8080
get serviceNAME LABELS
SELECTOR IP(S) PORT(S)kubernetes
component=apiserver,provider=kubernetes <none>
192.168.3.1 443/TCPnginx-service-clusterip <none>
name=nginx 192.168.3.91 8001/TCP
$ ssh 192.168.0.202 curl -s 192.168.3.91:8001 <!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>
部署外部可访问的nginx service
$ cat nginx-service-nodeport.yaml apiVersion: v1 kind: Service
metadata: name: nginx-service-nodeport spec: ports: - port:
8000 targetPort: 80 protocol: TCP type:
NodePort selector: name: nginx
$ kubectl -s http://192.168.0.201:8080 create -f ./nginx-service-nodeport.yaml services/nginx-service-nodeport $ kubectl -s http://192.168.0.201:8080
get serviceNAME LABELS
SELECTOR IP(S) PORT(S)kubernetes
component=apiserver,provider=kubernetes <none>
192.168.3.1 443/TCPnginx-service-clusterip <none>
name=nginx 192.168.3.91
8001/TCPnginx-service-nodeport <none>
name=nginx 192.168.3.84 8000/TCP
$ kubectl -s http://192.168.0.201:8080
describe service nginx-service-nodeport 2>/dev/null | grep
NodePortType: NodePortNodePort:
<unnamed> 32606/TCP
$ curl 192.168.0.201:32606 <!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>
代理节点上的IP tables规则解析

-A KUBE-PORTALS-CONTAINER -d 192.168.3.84/32 -p tcp -m comment --comment
"default/nginx-service-nodeport:" -m tcp --dport 8000 -j REDIRECT
--to-ports 43981
IP准备的。其中192.168.3.84/32是该服务获得的Cluster
IP,端口8000是其在定义文件中指定的spec.ports.port。43981则是kube-proxy为这个service分配的本地端口。规则的意思是到192.168.3.84:8000的流量重定向到43981。
-A
KUBE-NODEPORT-CONTAINER -p tcp -m comment --comment
"default/nginx-service-nodeport:" -m tcp --dport 32606 -j REDIRECT
--to-ports 43981
-A KUBE-PORTALS-HOST -d 192.168.3.84/32 -p tcp -m comment --comment
"default/nginx-service-nodeport:" -m tcp --dport 8000 -j DNAT
--to-destination 192.168.0.201:43981
-A
KUBE-NODEPORT-HOST -p tcp -m comment --comment
"default/nginx-service-nodeport:" -m tcp --dport 30975 -j DNAT
--to-destination 192.168.0.201:43981
总结
IP和NodePort的分析,使得读者能够了解这个模型中的网络特性。
kubernetes应用部署原理的更多相关文章
- Kubernetes一键部署利器:kubeadm
要真正发挥容器技术的实力,你就不能仅仅局限于对 Linux 容器本身的钻研和使用. 这些知识更适合作为你的技术储备,以便在需要的时候可以帮你更快的定位问题,并解决问题. 而更深入的学习容器技术的关键在 ...
- Docker Kubernetes 服务发现原理详解
Docker Kubernetes 服务发现原理详解 服务发现支持Service环境变量和DNS两种模式: 一.环境变量 (默认) 当一个Pod运行到Node,kubelet会为每个容器添加一组环境 ...
- Kubernetes 应用部署实战
Kubernetes 应用部署实战 2018-08-08 19:44:56 wuxiangping2017 阅读数 3084 收藏 更多 分类专栏: linux运维与架构师 简介 伙计们,请搬好 ...
- 浅析Kubernetes的工作原理
先放一张Kubernetes的架构图: 整体来看,是一个老大,多个干活的这种结构,基本上所有的分布式系统都是这样,但是里面的组件名称就纷繁复杂,下面将一一解析. 1.元数据存储与集群维护 作为一个集群 ...
- 简化kubernetes应用部署工具之Helm应用部署
介绍 微服务和容器化给复杂应用部署与管理带来了极大的挑战.Helm是目前Kubernetes服务编排领域的唯一开源子项目,做为Kubernetes应用的一个包管理工具,可理解为Kubernetes的a ...
- [原]CentOS7安装Rancher2.1并部署kubernetes (二)---部署kubernetes
################## Rancher v2.1.7 + Kubernetes 1.13.4 ################ ##################### ...
- [原]CentOS7安装Rancher2.1并部署kubernetes (一)---部署Rancher
################## Rancher v2.1.7 + Kubernetes 1.13.4 ################ ##################### ...
- [译]Kubernetes 分布式应用部署和人脸识别 app 实例
原文地址:KUBERNETES DISTRIBUTED APPLICATION DEPLOYMENT WITH SAMPLE FACE RECOGNITION APP 原文作者:skarlso 译文出 ...
- Centos下Kubernetes+Flannel部署(新)
一.准备工作 1) 三台centos主机 k8s master: 10.11.151.97 tc-151-97 k8s node1: 10.11.151.100 tc-151-100 k8s no ...
随机推荐
- Android Camera开发:给摄像头预览界面加个ZoomBar(附完整代码下载)
源码:http://files.cnblogs.com/android100/StandardCamera2013-10-18.zip 废话不说了,就是加个seekbar,拖动的话能够调节焦距,让画面 ...
- 为什么有时候PHP没有闭合标签结束符 ?>
找了一些资料,大家对PHP闭合标签的总结如下: 好处:如果这个是一个被别人包含的程序,没有这个结束符,可以减少很多很多问题,比如说:header, setcookie, session_start这些 ...
- CSS中易忽略的点
一.使用斜杠/分割的关键字 1.font H2{ font:12px/100% sans-serif; } 分割的分别是 字体大小 与 行高 ,其他关键是用空白符分割. 2.background di ...
- Ajax接收并显示后台传来的list集合内的数据信息
最近在学习Ajax做一个留言系统的时候碰到需要将list集合从后台传到前台ajax接收并显示的情况,在网上搜了很多,但很多情况都不是和我遇见的情况一样的,现在,直接贴出我的问题及解决方法. 后台代码: ...
- 频分复用(Frequency Division Multiplexer)
作者:桂. 时间:2017年12月19日20:43:04 链接:http://www.cnblogs.com/xingshansi/p/8067839.html 前言 主要记录基本的频分复用原理,以及 ...
- K8S 详细介绍
k8s的中文文档,参考地址:http://docs.kubernetes.org.cn/227.html
- 什么是UML?分哪两类?
统一建模语言(UML是 Unified Modeling Language的缩写)是用来对软件密集系统进行可视化建模的一种语言.UML为面向对象开发系统的产品进行说明.可视化.和编制文档的一种标准语言 ...
- Word实用教程——五分钟教你如何在任意页开始添加页码
最近在写一篇论文,但是在排版上遇到一点小问题,就是要加入页码,而且页码是从目录的下一页开始计数,于是我就在网上找如何在任意页添加页码.后来辗转终于搞定,真心觉得这一个小功能让微软做的如此的麻烦,真是活 ...
- redis中键空间通知
通过redis的键空间通知,当redis删除过期key的时候,及时更新mongodb数据库中user的状态 var Redis = require('ioredis'); var redis = ne ...
- .NET微信扫码支付模式二API接口开发测试
主要实现微信扫码支付,官网的SDKdemo 就不要使用 一直不能调试通过的,还是自己按照API接口文档一步一步来实现,吐槽下微信一点责任感都木有,能不能demo搞个正常的吗,不要坑惨了一大群码农们有点 ...