什么是Ingress
在Kubernetes中,Service和Pod的IP地址只能在集群內部網絡中路由,所有到達“邊界路由器”(Edge Router)的網絡流量要么被丟棄,要么被轉發到別處,從概念上講,它類似下圖:
Ingress是對外(公網)服務到集群內的Service之間規則的集合:允許進入集群的請求被轉發至集群內的Service,過程類似下圖:
Ingress能把Service(Kubernetes的服務)配置成外網能夠訪問的URL,流量負載均衡,終止SSL,提供於域名訪問的虛擬主機等,用戶通過訪問URL(API資源服務的形式,例如:caas.one/kibana)進入和請求Service,一個Ingress控制器負責處理所有Ingress的請求流量,它通常是一個負載均衡器,它也可以設置在邊界路由器上,或者由額外的前端來幫助處理HA方式的流量。
環境准備
如果你的kubernetes運行在GCE或者AWS等雲環境中,那么他們都有良好、穩定的負載均衡設施供您使用,本文討論的問題不包含GCE/AWS等雲環境,我們重點討論在沒有負責均衡的基礎設施的情況下,我們如何將我們的集群內Services作為一種資源暴露在公網上。
我們需要一個Ingress控制器,這里我們使用nginx1.9.1作為ingress控制器,來將我們的Service暴露在公網上,整個過程的原理如下:
- Ingress是一種對象(資源)存在於API Server(ETCD)上,它的整個生命周期(創建、更新、銷毀)可以被實時的監聽
- 編寫一個golang程序來監聽/ingresses的變化
- 我們采用nginx和golang程序來實現對Ingress控制
- 使用Nginx做負載均衡和請求路由,nginx的配置文件由Golang的模板來編寫
- /ingresses變化后,golang程序修改nginx的配置文件,reload這個nginx服務
我們將Ingress控制器(nginx-ingress-controller)作為kubernetes的pod部署在kubernetes集群中,這里我們將使用kubernetes1.2版本的新特性(DaemonSet),將nginx-ingress-controller作為Only-One-Pod-Per-Node的應用發布,然后將nginx-ingress-controller服務使用NodePort的方式暴露在外網,最后,在DNS上設置將域名指向這些主機。
使用Ingress
編寫一個簡單的ingress,它類似:
cat > ingress.yaml apiVersion: extensions/v1beta1 kind: Ingress metadata: name: test-ingress spec: backend: serviceName: testsvc servicePort: 80
可以通過kubectl -f ingress.yaml來創建ingress。
下面是更復雜一點的例子:
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: test spec: rules: - host: foo.bar.com http: paths: - path: /foo backend: serviceName: s1 servicePort: 80 - path: /bar backend: serviceName: s2 servicePort: 80
使用Ingress暴露ElasticSearch和Kibana服務
我們現有的集群中有部署了efk(elasticsearch + fluentd + kibana)技術棧,現在我們想把elastic search和kibana兩個服務暴露在公網上,方便我們的合作商來訪問,我們要達到的目的:
- 我們有兩個域名,分別是:caas.one和jingru.io
- caas.one用來暴露kibana服務,jingru.io用來暴露es服務
- 我們希望合作商能夠通過caas.one/kibana來訪問我們的內部的kibana服務
- 我們希望合作商能夠通過jingru.io/es來訪問我們的內部的es服務
為了達到我們的目標,我們將逐步建立我們ingress設施:
- 編寫glang程序(https://github.com/kubernetes/contrib/tree/master/ingress/controllers/nginx/nginx),並構建出二進制文件:nginx-ingress-controller。
- 編寫nginx.tmpl
https://github.com/lth2015/kubernetes-examples/blob/master/ingress/docker/nginx.tmpl
- 創建Ingress控制器:
編寫Dockerfile
# Copyright 2015 The Kubernetes Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/google_containers/nginx-slim:0.5 RUN apt-get update && apt-get install -y \ diffutils procps net-tools \ --no-install-recommends \ && rm -rf /var/lib/apt/lists/* COPY nginx-ingress-controller / COPY nginx.tmpl / COPY default.conf /etc/nginx/nginx.conf COPY lua /etc/nginx/lua/ WORKDIR / CMD ["/nginx-ingress-controller"]
編譯nginx-ingress-controller鏡像
docker build -t nginx-ingress-controller:0.5 .
編寫ingress.yaml
# An Ingress with 2 hosts and 3 endpoints apiVersion: extensions/v1beta1 kind: Ingress metadata: name: echomap spec: backend: serviceName: servicePort: 80 rules: - host: caas.one http: paths: - path: /kibana backend: serviceName: kibana servicePort: 5601 - host: jingru.io http: paths: - path: /es backend: serviceName: elasticsearch servicePort: 9200
在kubernetes集群中創建ingress控制器
apiVersion: extensions/v1beta1 kind: DaemonSet metadata: name: nginx-ingress-lb spec: template: metadata: labels: name: nginx-ingress-lb spec: terminationGracePeriodSeconds: 60 containers: - image: nginx-ingress-controller:0.5 name: nginx-ingress-lb imagePullPolicy: Always livenessProbe: httpGet: path: /healthz port: 10249 scheme: HTTP initialDelaySeconds: 30 timeoutSeconds: 5 # use downward API env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace ports: - containerPort: 80 hostPort: 80 - containerPort: 443 hostPort: 4444 args: - /nginx-ingress-controller - --default-backend-service=default/default-http-backend
使用命令kubectl -f ingress.yaml/nginx-ingress-controller.yaml把Ingress和Ingress控制器發布到kubernetes集群中。
下圖展示了從瀏覽器經過Ingress控制器到ingress再到service再到pod的全過程:
推薦閱讀:
Kubernetes 1.2 新功能介紹:DaemonSet
Kubernetes 1.2 新功能介紹:Deployment
Kubernetes 1.2 新功能介紹:Limit Range和Resource Quota