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 ...
随机推荐
- Java多线程框架Executor详解
原文链接 http://www.imooc.com/article/14377 为什么引入Executor线程池框架new Thread()的缺点 每次new Thread()耗费性能调用ne ...
- mysql 8.0给数据库添加用户和赋权
-- 使用mysql 数据库 USE mysql -- 为mysql创建用户:case_dev 密码为:pass123 CREATE USER case_dev IDENTIFIED BY 'pass ...
- 大家来找茬:富连网今天中午抢购二手iPhone时网站无法访问的问题
前几天在新闻区看到富士康卖二手iPhone的新闻,今天又看到说今天中午12点开抢.一大早就发现富连网无法访问了.前几天刚看到新闻的时候注册了个账号进去看了看,发现页面加载速度非常慢,今天中午基本无法打 ...
- tensorflow中使用Batch Normalization
在深度学习中为了提高训练速度,经常会使用一些正正则化方法,如L2.dropout,后来Sergey Ioffe 等人提出Batch Normalization方法,可以防止数据分布的变化,影响神经网络 ...
- 微服务,ApiGateway 与 Kong
一. 微服务 二. Api Gateway 三. Kong 的使用 一. 微服务 对于一些传统的 大型项目,传统的方式会有一些缺陷,比如说 新人熟悉系统成本高(因为整个系统作为一个整体,彼此会有一定的 ...
- rpx
rpx(responsive pixel): 可以根据屏幕宽度进行自适应.规定屏幕宽为750rpx.如在iPhone6上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = ...
- [nginx]站点目录及文件访问控制
nginx.conf配置文件 http ->多个server -> 多个location ->可限制目录和文件访问(根据i扩展名限制或者rewrite.) 根据目录或扩展名,禁止用户 ...
- 根据第三方提供的webservice地址获取文件信息
import org.apache.axis.client.Call; import org.apache.axis.client.Service; import org.apache.axis.en ...
- (原创)拨开迷雾见月明-剖析asio中的proactor模式(二)
在上一篇博文中我们提到异步请求是从上层开始,一层一层转发到最下面的服务层的对象win_iocp_socket_service,由它将请求转发到操作系统(调用windows api),操作系统处理完异步 ...
- 腾讯云主机安装登录mysql失败--解决方案[重置root密码并实现远程连接]
登录MySQL时报错:Access denied for user 'root'@'localhost' (using password: YES) 解决步骤: 1.使用ssh工具连接主机,使用mys ...