阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

Kubernetes应用部署模型解析(部署篇)

132次阅读
没有评论

共计 7713 个字符,预计需要花费 20 分钟才能阅读完成。

【编者按】Kubernetes 可用来管理 Linux 容器集群,加速开发和简化运维(即 DevOps)。但目前网络上关于 Kubernetes 的文章介绍性远多于实际使用。本系列文章着眼于实际部署,带您快速掌握 Kubernetes。在介绍部署之前需要了解的原理和概念之后,作者在本文中以一个简单的 nginx 服务来展示了复制器和 Service 的使用,特别通过对 Service 的 cluster IP 和 NodePort 的分析,使得读者能够了解这个模型中的网络特性。

一个简单的应用

讲了这么多的原理和概念,本章我们就部署一个简单应用来感受一下 Kubernetes 的部署模型。

部署 Kubernetes 集群

在 kubernetes github站点 上有数十种针对各种环境的部署文档,本文选择基于Ubuntu 的集群部署方案。在没有使用本地 docker 镜像的情况下,在部署过程中需要确保能够访问站点 gcr.io。

基于 Ubuntu的集群部署方案文档 写得比较详细,按照它的步骤几乎不会出错。在进行真正的部署之前,一定要确保:

  1. 所有的节点安装了 docker version 1.2+ 和 bridge-utils
  2. 如果没有本地的 docker registry, 要确保节点能访问互联网 gcr.io
  3. 确保管理节点能够 ssh 访问所有节点。比如 ssh gongysh@192.168.0.201 ls

这里我们集群将采用下图显示的结构。我们将在管理节点上运行集群管理命令。我们将有一个服务和代理混合的节点,还有两个纯的代理节点。

Kubernetes 应用部署模型解析(部署篇)

 

首先我们要下载 kubernetes 的代码到管理节点上:

 

$ git clone https://github.com/GoogleCloudPlatform/kubernetes.git

然后进行本地构建:

cd kubernetes
./build/run.sh hack/build-do.sh

修改 config-default.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 same
export roles=("ai" "i" "i")
# Define minion numbers
export 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 range
export 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 应用

我们以下面的图来安装一个简单的静态内容的 nginx 应用:

Kubernetes 应用部署模型解析(部署篇)

 

首先,我们用复制器启动一个 2 个备份的 nginx Pod。然后在前面挂 Service,一个 service 只能被集群内部访问,一个能被集群外的节点访问。下面所有的命令都是在管理节点上运行的。

部署 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

 

我们定义了一个 nginx pod 复制器,复制份数为 2,我们使用 nginx docker 镜像。

执行下面的操作创建 nginx pod 复制器:

 

$  kubectl -s http://192.168.0.201:8080 create -f nginx-rc.yaml

 

由于 kubernetes 要去 gcr.io 下载 gcr.io/google_containers/pause 镜像,然后下载 nginx 镜像,所以所创建的 Pod 需要等待一些时间才能处于 running 状态。

$  kubectl -s http://192.168.0.201:8080 get pods
NAME                     READY     REASON    RESTARTS   AGE
nginx-controller-6zr34   1/1       Running   0          48m
nginx-controller-njlgt   1/1       Running   0          48m

我们可以使用 describe 命令查看 pod 所分到的节点:

$  $ 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

从上表可以看出,这个复制器启动了两个 Pod,分别运行在 192.168.0.201 和 203 代理节点主机上。

部署节点内部可访问的 nginx service

Service 的 type 有 ClusterIP 和 NodePort 之分,缺省是 ClusterIP,这种类型的 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

执行下面的命令创建 service:

$ 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 service
NAME                      LABELS                                    SELECTOR     IP(S)           PORT(S)
kubernetes                component=apiserver,provider=kubernetes   <none>       192.168.3.1     443/TCP
nginx-service-clusterip   <none>                                    name=nginx   192.168.3.91   8001/TCP

 

验证 service 的可访问性:

上面的输出告诉我们这个Service 的 Cluster IP 是 192.168.3.91,端口是 8001。下面我们验证这个 PortalNet IP 的工作情况:

$ 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 Pod 运行在 201 和 203 节点上。上面我们特意从 202 代理节点上访问我们的服务来体现 Service Cluster IP 在所有集群代理节点的可到达性。

部署外部可访问的 nginx service

下面我们创建 NodePort 类型的 Service,这种类型的 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

执行下面的命令创建 service:

 

$ 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 service
NAME                      LABELS                                    SELECTOR     IP(S)          PORT(S)
kubernetes                component=apiserver,provider=kubernetes   <none>       192.168.3.1    443/TCP
nginx-service-clusterip   <none>                                    name=nginx   192.168.3.91   8001/TCP
nginx-service-nodeport    <none>                                    name=nginx   192.168.3.84   8000/TCP

 

使用下面的命令获得这个 service 的节点级别的端口:

 

$ kubectl -s http://192.168.0.201:8080 describe service nginx-service-nodeport 2>/dev/null | grep NodePort
Type:			NodePort
NodePort:		<unnamed>	32606/TCP

 

验证 service 的可访问性:

上面的输出告诉我们这个Service 的节点级别端口是32606。下面我们验证这个Service 的工作情况:

 

$ 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 规则解析

下面的图是 IPTables 中流量经过的 table 和 chain。

Kubernetes 应用部署模型解析(部署篇)

可以看出,Kubernetes 在 nat 表中插入了下面四条 chain:

1.  KUBE-PORTALS-CONTAINER

这个 chain 主要是处理所有 service 对象的 cluster IP 和 port 到 kube-proxy 本地端口的映射。比如下面规则:

-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

就是为 nginx-service-nodeport 服务的 Cluster IP 准备的。其中 192.168.3.84/32 是该服务获得的 Cluster IP,端口 8000 是其在定义文件中指定的 spec.ports.port。43981 则是 kube-proxy 为这个 service 分配的本地端口。规则的意思是到 192.168.3.84:8000 的流量重定向到 43981。

2.  KUBE-NODEPORT-CONTAINER

这条 chain 上则串连着类型为 NodePort 的 service 的 NodePort 规则。比如下面规则:

-A KUBE-NODEPORT-CONTAINER -p tcp -m comment --comment "default/nginx-service-nodeport:" -m tcp --dport 32606 -j REDIRECT --to-ports 43981

就是为 nginx-service-nodeport 服务的 NodePort 32606 准备的。意思是访问本地 32606 端口的流量重新定向到 43981,后者是 kube-proxy 为这个 service 分配的本地端口。

3.  KUBE-PORTALS-HOST

这条 chain 上也关联着各个 service 的 Cluster IP 和 Port 的规则,比如:

 

-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

 

这条规则是和 KUBE-PORTALS-CONTAINER 类似的,只不过流量来自于本地进程。

4.  KUBE-NODEPORT-HOST

这条 chain 上则关联着类型为 NodePort 的 service 的 NodePort 规则。比如下面规则:

-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

这条规则是和 KUBE-NODEPORT-CONTAINER 类似的,只不过流量来自于本地进程。

总结

笔者认为 Docker 已经不是仅代表容器本身,而是一组以应用部署为中心的技术,产品和最佳实践生态系统。Kubernetes 以其出身,文档的成熟度,社区的支持在这个生态系统中表现得比较突出。在部署 Kubernetes 时,我们首先要理解 Kubernetes 的组件结构,它们有哪些角色,各个角色的作用是什么和它们之接的通信。在应用部署时,了解 Kubernetes 的应用模型是非常重要的。笔者认为复制器和 Service 的概念是 Kubernetes 模型的核心,复制器和 Service 共同完成了应用的高可用性要求。最后本文以一个简单的 nginx 服务来展示了复制器和 Service 的使用,特别通过对 Service 的cluster IP 和NodePort 的分析,使得读者能够了解这个模型中的网络特性。

最后就是容器技术的选型,本文使用 D ocker 作为容器,其实 Kubernetes 也支持 CoreOS 的 rkt 容器。kubelet 的参数 –container_runtime 用于选择使用的容器技术。

OpenStack, Kubernetes, Mesos 谁主沉浮  http://www.linuxidc.com/Linux/2015-09/122696.htm

Kubernetes 集群搭建过程中遇到的问题及解决  http://www.linuxidc.com/Linux/2015-12/125735.htm

Kubernetes 的详细介绍:请点这里
Kubernetes 的下载地址:请点这里

本文永久更新链接地址:http://www.linuxidc.com/Linux/2015-12/125762.htm

正文完
星哥说事-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-21发表,共计7713字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中