在K8S的Ingress中支持物理机上部署的程序
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在K8S的Ingress中支持物理机上部署的程序相关的知识,希望对你有一定的参考价值。
参考技术A K8S Ingress通过管理集群中的外部服务用的Service,把流量从nginx转到对应部署的容器中,提供7层负载均衡能力。在我们公司存在混合部署的情况,有业务同时在容器和物理机、云主机上部署服务实例,但是也需要通过K8S Ingress把外部流量转入进行,由于Ingress不支持流量转到物理机上的实例,所以我们需要做一些扩展来支持这种场景。
在 Ingress Nginx主流程 一文中,已经介绍了Ingress Nginx的驱动流程,系统的主要驱动逻辑是监控API Server中相关资源的变化,并通过事件回调去驱动系统的运行。
我们可以通过适当改造Ingress Nginx Controller来让他支持物理机实例。
ingress-nginx-controller的实现是通过k8s中的资源发现,把Server或Pod的变化,实时更新配置到Nginx中,基于Nginx的反向代理服务,基于vhost子域名以及URL路由到后端的Pod中。
K8S原生的资源无法发现物理部署的服务,所以我们需要利用K8S的资源扩展机制,给K8S添加一种新的资源:PhysicalDeployment资源,下面是一个对应的物理资源例子:
phyendpoint-example有两个实例,分别是10.0.0.1:10001和10.0.0.2:1001,由于ingress中的nginx使用的lua功能来实现upstream,没有使用nginx原生的upstream,所以它暂时不具备被动探测服务不可用的功能,也就是说,当一个endpoint故障或者不能工作时,ingress无法做到想nginx原生upstream那样,先隔离该实例,10秒后重试这种被动探测能力。
ingress主要依赖于k8s原生的pod的主动探测能力来发现不可用服务,当主动探测一个endpoint不可用时,ingress能够及时(当然也不够实时)发现问题,并隔离该pod。
所以,这里还需要针对PhysicalEndpoint实现自己的控制器,在控制器中定期对PhysicalEndpoint管理的Endpoint进行探测,并及时更新它的状态。
ingress主要基于service来发现Endpoints,这里需要增加对PhysicalEndpoint的事件侦听服务,并与Service服务一起订阅合并Endpoints后,通过nginx的API更新到对应的upstream服务列表中。
为了合并容器与物理部署,需要对Service也做稍许扩展,增加annotation,让我们在服务发现时除了发现该service的容器Endpoint之外,还去发现对应的annotation中的PhysicalEndpoint中的Endpoint。
如下图是一个例子:
通过简单的扩展,就可以让Ingress同时把流量向容器和物理机部署的服务进行转发,不仅能够解决部分业务确实存在物理机部署的需求,同时对于我们公司的现状的容器化推广有很大帮助,排除了不少阻力。
用Kubernetes部署企业大数据应用
在Docker容器技术火热发展的今天,如何将分布在不同物理机上的Docker容器组织、管理、调度起来成为一个急需解决的问题,Kubernetes正是解决这个问题的最佳实践。Kubernetes是一个开源的系统,可以自动部署,扩展和管理运行在Docker容器中的应用程序。Kubernetes可以根据应用程序对资源的需求在集群中创建相应的容器,在容器中启动程序,同时借助于网络插件在不同物理机的容器之间建立通信链接。基于Kubernetes,可以非常便利的将运行在容器中的大数据程序部署和管理起来。
简介
Kubernetes原型是Google内部的产品,具有15年产品负载管理的经验,目前是开源系统中Docker容器管理最成熟的产品,可以支持管理1000个节点,运行30000个Pods,在单个节点上,kubelet可支持100个Pods。Kubernetes按组管理容器,这样可以按照逻辑单元组织应用程序,使得应用程序易于管理。同时支持水平扩展,可以增加和减少大数据计算节点的规模。Kubernetes本身不管理容器网络,容器网络需要依赖于第三方网络插件来建立,比如Flannel和Weave。
表1.Kubernetes相关的术语
Kubernetes架构
Kubernetes本身也是一个分布式系统,采用mast-slave模式运行在物理机上,Node节点上必须装有Docker用于启动容器。其架构如图1所示:
Master节点上主要运行Kubernetes API Server,Scheduler,Controller manager这几个组件,负责接收Node节点的连接,从Node节点收集资源,调度Pod,通知Node创建Pod, 管理ReplicationController,提供REST接口等。
Node节点上主要运行kubelet和kube-proxy组件。kubelet负责管理容器,kube-proxy负责网络代理和负载均衡。
图1. Kubernetes 架构
Weave(容器间网络支持)
Weave在每个Docker物理机上都启动了一个特殊的route容器,不同的宿主机上的route容器连接起来,route拦截所有普通容器的ip请求,通过UDP包发送到其它宿主机上的容器,这样在不同物理机上的容器端就可以看到一个扁平的网络。通过weave创建的overlay网络同时支持tcp通信和udp通信。
图2. Weave示意图
1.安装Weave
在每台Docker host上执行下面的命令安装Weave:
$ curl -L git.io/weave -o /usr/local/bin/weave
$ chmod +x /usr/local/bin/weave
$ weave setup
从Weave网站下载的Weave的binary是个脚本文件,执行weave setup会下载weave使用的几个Docker镜像,weave也是以docker镜像的形式发布产品包,没有提供rpm安装包:
docker.io/weaveworks/weave
docker.io/weaveworks/weaveexec
docker.io/weaveworks/plugin
docker.io/weaveworks/weavedb
2.建立Weave overlayye
在每台Docker host上启动weave proxy服务容器:
$ weave launch-proxy --rewrite-inspect --without-dns --no-detect-tls
找一台Docker host作为weave master,启动weave router服务容器:
$ weave launch-router
将其它Docker hosts加入weave master创建的网络:
$ weave launch-router $(weave master host name)
3.验证容器间的网络
首先在命令行设置weave的环境变量(eval(weave env))。该命令会使docker run命令访问weave的socket文件(/var/run/weave/weave.sock),而不是直接访问Docker本身的socket文件 (/var/run/docker.sock)。如果想还原命令行docker socket的绑定可以执行eval $(weave env –restore)。
在Docker host 1上启动带有weave网络的容器,我们会发现docker 容器里面多了一个 ethwe的网络,这个网络就是weave分配给容器的虚拟网络(如10.32.0.2)。启动netperf的server端。
$ docker run -ti --rm -v /opt/netserver:/opt/netserver -v /usr/sbin/ifconfig:/usr/sbin/ifconfig rhel /bin/sh
sh-4.2# ifconfig ethwe
ethwe: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1410
inet 10.32.0.2 netmask 255.240.0.0 broadcast 0.0.0.0
inet6 fe80::34ee:70ff:fe7d:e533 prefixlen 64 scopeid 0x20<link>
ether 36:ee:70:7d:e5:33 txqueuelen 0 (Ethernet)
RX packets 13 bytes 830 (830.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 8 bytes 620 (620.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
sh-4.2# /opt/netserver
Starting netserver with host 'IN(6)ADDR_ANY' port '12865' and family AF_UNSPEC
在Docker host 2上启动另一个docker容器,我们看到处于不同物理机上的容器网络区段不同(如 10.44.0.2)。用netperf client端测试TCP和UDP通信。
$ docker run -ti --rm -v /opt/netperf:/opt/netperf -v /usr/sbin/ifconfig:/usr/sbin/ifconfig rhel /bin/sh
sh-4.2# ifconfig ethwe
ethwe: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1410
inet 10.44.0.2 netmask 255.240.0.0 broadcast 0.0.0.0
inet6 fe80::b460:77ff:fe81:1f5d prefixlen 64 scopeid 0x20<link>
ether b6:60:77:81:1f:5d txqueuelen 0 (Ethernet)
RX packets 8 bytes 592 (592.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 7 bytes 550 (550.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
TCP_STREAM 类型测试:
sh-4.2# /opt/netperf -H 10.32.0.2 -l 10 -t TCP_STREAM
MIGRATED TCP STREAM TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to 10.32.0.2 () port 0 AF_INET
Recv Send Send
Socket Socket Message Elapsed
Size Size Size Time Throughput
bytes bytes bytes secs. 10^6bits/sec
87380 16384 16384 10.32 90.63
UDP_STREAM类型测试:
sh-4.2# /opt/netperf -H 10.32.0.2 -l 10 -t UDP_STREAM
MIGRATED UDP STREAM TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to 10.32.0.2 () port 0 AF_INET
Socket Message Elapsed Messages
Size Size Time Okay Errors Throughput
bytes bytes secs # # 10^6bits/sec
212992 65507 10.00 509277 0 26688.73
212992 10.00 2475 129.70
经笔者测试,目前只有Weave支持容器间UDP网络通信,其它插件Flannel,OpenVSwitch以及Calico均不支持。
部署Kubernetes环境
1.在所有节点上安装Kubernetes和etcd:
$ yum install kubernetes etcd
2.确保所有节点上Docker service已经启动:
$ systemctl start docker
3.在Kubernetes master 节点上,更改下列配置文件:
a). /etc/etcd/etcd.conf:
ETCD_LISTEN_CLIENT_URLS="http://kube01:2379"
ETCD_ADVERTISE_CLIENT_URLS="http://kube01:2379"
b). /etc/kubernetes/config
KUBE_ALLOW_PRIV="--allow-privileged=true"
KUBE_MASTER="--master=http://kube01:8080"
c). /etc/kubernetes/apiserver
KUBE_API_ADDRESS="--insecure-bind-address=0.0.0.0"
KUBE_ETCD_SERVERS="--etcd-servers=http://kube01:2379"
KUBE_ADMISSION_CONTROL="--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ResourceQuota"
d). /etc/kubernetes/kubelet: (这里将master也用作slave node)
KUBELET_ADDRESS="--address=0.0.0.0"
KUBELET_HOSTNAME="--hostname-override=kube01"
KUBELET_API_SERVER="--api-servers=http://kube01:8080"
KUBELET_ARGS="--docker-endpoint=unix:///var/run/weave/weave.sock"
4.启动Kubernetes master:
# systemctl start etcd kube-apiserver kube-controller-manager kube-scheduler kube-proxy kubelet
5.在kubernetes node节点,更改下列配置文件:
a). /etc/kubernetes/config
KUBE_ALLOW_PRIV="--allow-privileged=true"
KUBE_MASTER="--master=http://kube01:8080"
b). /etc/kubernetes/kubelet
KUBELET_ADDRESS="--address=0.0.0.0"
KUBELET_HOSTNAME="--hostname-override=kube02"
KUBELET_API_SERVER="--api-servers=http://kube01:8080"
KUBELET_ARGS="--docker-endpoint=unix:///var/run/weave/weave.sock"
6.启动Kubernetes node:
$ systemctl start kube-proxy kubelet
7.检查Kubernetes 集群状态:
$ kubectl get nodes
NAME LABELS STATUS AGE
kube02 kubernetes.io/hostname=kube02 Ready 13m
kube01 kubernetes.io/hostname=kube01 Ready 16m
8.启动Kubernetes Dashboard模块:
最开始Kubernetes的WEB模块叫做kube-ui,是一个只读的UI,目前发展到Kubernetes Dashboard,可以查看和修改,以及从WEB上提交YAML文件。Kubernetes Dashboard需要使用”kube-system”的namespace,如果没有该namespace,那么需要先创建该namespace。
apiVersion: v1
kind: Namespace
metadata:
name: kube-system
然后创建Kubernetes Dashboard模块:
$kubectl create -f https://rawgit.com/kubernetes/dashboard/master/src/deploy/kubernetes-dashboard.yaml
deployment "kubernetes-dashboard" created
You have exposed your service on an external port on all nodes in your
cluster. If you want to expose this service to the external internet, you may
need to set up firewall rules for the service port(s) (tcp:32283) to serve traffic.
See http://releases.k8s.io/release-1.2/docs/user-guide/services-firewalls.md for more details.
service "kubernetes-dashboard" created
Kubernetes Dashboard 会启动一个gcr.io/google_containers/kubernetes-dashboard-amd64:v1.1.0的Docker容器,该容器需要访问Kubernetes master的8080端口,一般情况下,该容器会被调度到任意主机上启动,所以需要把该yaml文件下载下来并手工指定apiserver-host配置。创建后访问任意Node的32283端口即可访问Kubernetes dashboard(如图3所示)。
图3. Kubernetes Dashboard.
至此,我们完成了Kubernetes集群的安装部署,并且解决了Docker容器在不同物理机间的网络支持问题,接下来将给大家介绍如何在当前Kubernetes环境中部署IBM Spectrum Symphony集群。
部署集群
IBM Spectrum Symphony是一款大数据和高性能分析的产品。它一方面实现了对所有Hadoop接口的完全兼容,另一方面提供了自己的API,使得高性能分析应用很容易在几千台机器上动态地运行。
1.首先编译Symphony的docker镜像(sym712):
$ docker build –t sym712 –f Dockerfile ./
Dockerfile内容如下:
FROM rhel
MAINTAINER Jin Ming Lv <lvjinm@cn.ibm.com>
# Add user 'egoadmin' & install ssh-server and other basic tools
RUN useradd -m egoadmin
&& echo "egoadmin:egoadmin" | chpasswd
&& echo "egoadmin ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
&& echo -e "[base] name=CentOS-7 - Base - centos.com baseurl=http://mirror.centos.org/centos/7/os/$basearch/ gpgcheck=1 gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-CentOS-7" > /etc/yum.repos.d/CentOS7-Base.repo
&& yum clean all
&& yum install -y openssh-server which net-tools sudo wget hostname tar openssh-clients gettext iputils
&& sed -i 's/UsePAM yes/UsePAM no/g' /etc/ssh/sshd_config
&& ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
&& ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key
&& ssh-keygen -t dsa -f /etc/ssh/ssh_host_ed25519_key
&& mkdir /var/run/sshd
ADD platform_sym_adv_entitlement.dat /opt/platform_sym_adv_entitlement.dat
# Download & Install Symphony package
RUN wget --no-check-certificate -O /opt/symsetup_linux-x86_64.bin https://lweb.eng.platformlab.ibm.com/engr/pcc/release_eng/work/sym/sym_mainline/last/symsetup7.1.2.0_x86_64.bin
&& export CLUSTERADMIN=egoadmin
&& export CLUSTERNAME=symphony712
&& export DERBY_DB_HOST=localhost
&& export BASEPORT=17869
&& export SIMPLIFIEDWEM=Y
&& chmod +x /opt/*
&& /opt/symsetup_linux-x86_64.bin --quiet --force
&& rm -f /opt/*.bin
USER egoadmin
2.启动Symphony Master节点,用Replication Controller定义一个Symphony Master容器。用Replication Controller而不用Pod定义容器的好处在于Kubernetes会保证有一个Symphony master的容器存在,即便容器所在的物理机宕机。同时我们指定master容器需要使用的内存和CPU大小。
kind: ReplicationController
apiVersion: v1
metadata:
name: sym-master
spec:
replicas: 1
selector:
component: sym-master
template:
metadata:
labels:
component: sym-master
spec:
containers:
- name: sym-master
image: sym712
command: ["/bin/sh", "-c", "source /opt/ibm/platform/profile.platform; egoconfig join `hostname` -f; egoconfig setentitlement /opt/platform_sym_adv_entitlement.dat; egosh ego start; sudo /usr/sbin/sshd -D"]
resources:
requests:
cpu: 100m
memory: 4096M
limits:
memory: 8192M
调用Kubernetes命令创建Symphony master容器。
$ kubectl create -f /tmp/sym_master.yaml
replicationcontroller "sym-master" created
$ kubectl get rc
NAME DESIRED CURRENT AGE
sym-master 1 1 10s
查看master 容器已经启动。
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
sym-master-04yws 1/1 Running 0 1m
# kubectl get pods
NAME READY STATUS RESTARTS AGE
sym-master-rc-04yws 1/1 Running 0 1m
# kubectl describe pod sym-master-04yws | grep IP
IP: 10.32.0.1
kind: ReplicationController
apiVersion: v1
metadata:
name: sym-compute
spec:
replicas: 2
selector:
component: sym-compute
template:
metadata:
labels:
component: sym-compute
spec:
containers:
- name: sym-compute
image: sym712
command: ["/bin/sh", "-c", "source /opt/ibm/platform/profile.platform; sudo chmod 777 /etc/hosts; echo '10.32.0.1 sym-master-rc-04yws' >> /etc/hosts; egoconfig join sym-master-rc-04yws -f; egosh ego start; sudo /usr/sbin/sshd -D"]
resources:
requests:
memory: 2048M
调用Kubernetes命令创建Symphony compute节点。
$ kubectl create -f /tmp/sym_compute.yaml
replicationcontroller "sym- compute " created
5.查看pod启动状态:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
sym-compute-a6aff 1/1 Running 0 28s
sym-compute- r5arf 1/1 Running 0 28s
sym-master-04yws 1/1 Running 0 19m
6.登录到任何一个container, 可以查看Symphony 集群的启动状态:
$ docker exec -it 24b61a193f9c /bin/bash
[egoadmin@sym-master-rc-9vicc platformsymphony]$ egosh resource list -l
NAME status mem swp tmp ut it pg r1m r15s r15m ls
sym-master-04yws ok 391M 670M 91G 25% 37 337.6 5.8 0.7 8.9 0
sym-compute-a6aff ok 391M 668M 91G 27% 47 418.2 6.3 0.0 8.9 0
sym-compute-r5arf ok 391M 668M 91G 27% 47 418.2 6.3 0.0 8.9 0
此时,Symphony集群的master和两个compute nodes已经正常启动。
7.Kubernetes的replicationcontroller支持扩减容,如果我们想将compute nodes扩展到10个,可以执行以下命令。
$ kubectl scale --replicas=10 replicationcontrollers sym-compute
replicationcontroller "sym-compute" scaled
8.将Symphony master的WEB服务端口部署为Kubernetes的service,这样可以在集群外部访问到集群中Symphony master WEB GUI服务。
定义一个NodePort的Service,将sym-master的8443端口expose到集群外。
kind: Service
apiVersion: v1
metadata:
name: sym-webgui
spec:
ports:
- port: 8443
targetPort: 8443
protocol: TCP
name: https
selector:
component: sym-master
type: NodePort
在Kubernetes中创建该Service:
$kubectl create -f sym-webgui-svc.yaml。
$ kubectl describe service sym-webgui
Name: sym-webgui
Namespace: default
Labels: <none>
Selector: component=sym-master
Type: NodePort
Port: https 8443/TCP
NodePort: https 31439/TCP
Endpoints: 10.32.0.1:8443
Session Affinity: None
No events.
Kubernetes会为该Service分配一个可用的端口31439,访问Kubernetes集群中任意Node的31439端口可以访问到Symphony master的8334端口。
比如在集群外部访问https://docker_host1:31439/platform/login/login.html可以访问到Symphony的GUI Portal。
结束语
随着Docker容器技术和大数据技术的发展,两者的结合变得非常重要,将大数据平台运行在Docker容器中可以享受Docker带来的隔离、发布等优势特性,使得大数据平台的搭建变得非常简单,同时又有很好的性能。本文以IBM Spectrum Symphony为例,来说明如何利用Kubernetes在集群中快速搭建和启动一个大数据平台。Kubernetes目前已经发展的比较成熟,达到了商用的标准,其中的Feature也是很多,本文没有一一阐述,大家可以关注Kubernetes开源社区。
作者简介:吕金明,2011加入IBM至今,一直从事分布式计算以及大数据相关的研发工作,以及大数据产品的集成,如Hadoop、Yarn、Spark,Docker等开源框架及技术。
以上是关于在K8S的Ingress中支持物理机上部署的程序的主要内容,如果未能解决你的问题,请参考以下文章
云原生之kubernetes实战在k8s集群下部署ingress对外访问服务
实操教程丨如何在K8S集群中部署Traefik Ingress Controller