初试 Kubernetes 暴漏服务类型之 Nginx Ingress

目录

  • Ingress 介绍
  • 环境、软件准备
  • 部署 Default Backend
  • 部署 Ingress Controller
  • 部署 Ingress
    • Name based virtual hosting
    • Simple fanout

1、Ingress 介绍

我们知道,到目前为止 Kubernetes 暴露服务的有三种方式,分别为 LoadBlancer Service、NodePort Service、Ingress。官网对 Ingress 的定义为管理对外服务到集群内服务之间规则的集合,通俗点讲就是它定义规则来允许进入集群的请求被转发到集群中对应服务上,从来实现服务暴漏。 Ingress 能把集群内 Service 配置成外网能够访问的 URL,流量负载均衡,终止SSL,提供基于域名访问的虚拟主机等等。

LoadBlancer Service

LoadBlancer Service 是 Kubernetes 结合云平台的组件,如国外 GCE、AWS、国内阿里云等等,使用它向使用的底层云平台申请创建负载均衡器来实现,有局限性,对于使用云平台的集群比较方便。

NodePort Service

NodePort Service 是通过在节点上暴漏端口,然后通过将端口映射到具体某个服务上来实现服务暴漏,比较直观方便,但是对于集群来说,随着 Service 的不断增加,需要的端口越来越多,很容易出现端口冲突,而且不容易管理。当然对于小规模的集群服务,还是比较不错的。

Ingress

Ingress 使用开源的反向代理负载均衡器来实现对外暴漏服务,比如 Nginx、Apache、Haproxy等。Nginx Ingress 一般有三个组件组成:

  • Nginx 反向代理负载均衡器
  • Ingress Controller Ingress Controller 可以理解为控制器,它通过不断的跟 Kubernetes API 交互,实时获取后端 Service、Pod 等的变化,比如新增、删除等,然后结合 Ingress 定义的规则生成配置,然后动态更新上边的 Nginx 负载均衡器,并刷新使配置生效,来达到服务自动发现的作用。
  • Ingress Ingress 则是定义规则,通过它定义某个域名的请求过来之后转发到集群中指定的 Service。它可以通过 Yaml 文件定义,可以给一个或多个 Service 定义一个或多个 Ingress 规则。

以上三者有机的协调配合起来,就可以完成 Kubernetes 集群服务的暴漏。

2、环境、软件准备

Kubernetes 使用 Nginx Ingress 暴漏服务,前提我们需要有一个正常运行的集群服务,这里我采用 kubeadm 搭建的 Kubernetes 集群,具体搭建步骤可以参考我上一篇文章 国内使用 kubeadm 在 Centos 7 搭建 Kubernetes 集群 讲述的比较详细,这里就不做演示了。不过还是要说一下的就是国内翻墙问题,由于这三个服务所需要的 images 在国外,国内用户可以去 Docker Hub 下载指定版本的镜像替代,下载完成后,通过 docker tag ... 命令修改成指定名称的镜像即可。

本次演示所依赖的各个镜像列表如下:

Image Name

Version

Des ( * 必需)

gcr.io/google_containers/nginx-ingress-controller

0.9.0-beta.10

*

gcr.io/google_containers/defaultbackend

1.0

*

说明一下,这里我没有使用最新版本的镜像,因为在 GitHub 上找最新版本对应的镜像,找半天没找到。。。所有就找了一个老一点的版本,不过也能运行哈。

可使用下边脚本,分别替换以上镜像。

#!/bin/bash

images=(
    nginx-ingress-controller:0.9.0-beta.10 
    defaultbackend:1.0)

for imageName in ${images[@]} ; do
    docker pull docker.io/chenliujin/$imageName
    docker tag docker.io/chenliujin/$imageName gcr.io/google_containers/$imageName 
    docker rmi docker.io/chenliujin/$imageName
done   

3、部署 Default Backend

首先我们需要部署一个默认后端,用来将未知请求全部负载到这个默认后端上,这个默认后端会返回 404 页面。就干了这么件事。。。

$ cd /home/wanyang3/k8s
$ git clone https://github.com/kubernetes/ingress-nginx.git
$ git checkout nginx-0.9.0-beta.10
# ls -l ingress-nginx/examples/deployment/nginx/
总用量 12
-rw-r--r--. 1 root root 1161 11月  6 17:16 default-backend.yaml
drwxr-xr-x. 2 root root   60 11月  6 17:16 kubeadm
-rw-r--r--. 1 root root 1819 11月  6 17:16 nginx-ingress-controller.yaml
-rw-r--r--. 1 root root 1655 11月  6 17:16 README.md

这里可以使用 kubectl create -f default-backend.yaml 来创建默认后端。注意,这里我们使用 deployment 方式部署,当然也可以使用 daemonset 方式部署。

不过官方也提供了对 kubeadm 搭建的集群支持,刚好我使用的集群就是通过 kubeadm 搭建,这一步就可以暂时先忽略安装 Default Backend,因为在 ingress-nginx/examples/deployment/nginx/kubeadm/nginx-ingress-controller.yaml 配置文件中同时定义好了 Default Backend 和 Ingress Controller,下边一次就安装完毕。

出现 404 的时候返回页面如下:

4、部署 Ingress Controller

接下来要部署 Ingress Controller了,有人会问咋没有 Nginx 组件呢?其实这里包含了 Nginx + Ingress Controller 组件.

# 使用 kubaadm 配置文件
$ kubectl create -f ingress-nginx/examples/deployment/nginx/kubeadm/nginx-ingress-controller.yaml
deployment "default-http-backend" created
service "default-http-backend" created
deployment "nginx-ingress-controller" created

# 使用其他的配置文件,需要先部署 default-backend
$ kubectl create -f ingress-nginx/examples/deployment/nginx/nginx-ingress-controller.yaml

部署完成后,我们查看下这两个 Pod 是否启动成功。

$ kubectl get pods --all-namespaces -o wide
NAMESPACE     NAME                                         READY     STATUS    RESTARTS   AGE       IP              NODE
kube-system   default-http-backend-2198840601-53w56        1/1       Running   0          12s       10.96.1.10      node0.localdomain
kube-system   nginx-ingress-controller-627402744-xn4dm     1/1       Running   0          12s       10.236.65.128   node0.localdomain
...

5、部署 Ingress

Ingress Controller 和 Default Backend 部署完毕了,下边该部署 Ingress 来定义转发规则了。问题来了,这个服务转发规则怎么写?通过官方示例,我们可以来参考学习下。首先既然是服务转发规则,得知道我们集群中有那些服务,才能配置规则。

通过一段时间的学习,我已经在集群中部署了一些服务了,不过为了演示效果,我们选择有 UI 界面的 Service 来做配置。这里选择 kubernetes-dashboard 和 kibana-logging 来演示一下吧。

$ kubectl get service --all-namespaces
NAMESPACE     NAME                    CLUSTER-IP       EXTERNAL-IP   PORT(S)         AGE
default       kubernetes              10.96.0.1        <none>        443/TCP         1h
kube-system   default-http-backend    10.102.201.41    <none>        80/TCP          6m
kube-system   elasticsearch-logging   10.105.149.87    <none>        9200/TCP        18m
kube-system   heapster                10.110.233.166   <none>        80/TCP          38m
kube-system   kibana-logging          10.105.121.249   <none>        5601/TCP        17m
kube-system   kube-dns                10.96.0.10       <none>        53/UDP,53/TCP   1h
kube-system   kubernetes-dashboard    10.103.252.55    <nodes>       80:32126/TCP    56m
kube-system   monitoring-grafana      10.104.71.255    <none>        80/TCP          38m
kube-system   monitoring-influxdb     10.109.173.162   <none>        8086/TCP        38m

5.1 Name based virtual hosting

首先来演示一下基于域名访问虚拟主机的 Ingress 配置,Yaml 文件如下:

# 创建 Yaml 文件
$ vim dashboard-kibana-ingress.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: dashboard-kibana-ingress
  namespace: kube-system
spec:
  rules:
  - host: dashboard.k8s.ingress
    http:
      paths:
      - backend:
          serviceName: kubernetes-dashboard
          servicePort: 80
  - host: kibana.k8s.ingress
    http:
      paths:
      - backend:
          serviceName: kibana-logging
          servicePort: 5601

# 创建 ingress
$ kubectl create -f dashboard-kibana-ingress.yaml
ingress "dashboard-kibana-ingress" created

# 查看 ingress
$ kubectl get ingress --all-namespaces
NAMESPACE     NAME                       HOSTS                              ADDRESS         PORTS     AGE
kube-system   dashboard-kibana-ingress   dashboard.k8s.ingress,kibana.k8s.ingress   10.236.65.128   80        36s

好了,通过上边操作,我们已经把域名分别绑定到指定的 Service 上了。

dashboard.k8s.ingress --|               |-> dashboard.k8s.ingress kubernetes-dashboard:80
                        | 10.236.65.128 |
kibana.k8s.ingress    --|               |-> kibana.k8s.ingress kibana-logging:5601

然后,我们要能本地访问,还需要本机绑定 Host,否则这两个域名肯定找不到的。

$ echo "10.236.65.128 dashboard.k8s.ingress" >> /etc/hosts
$ echo "10.236.65.128 kibana.k8s.ingress" >> /etc/hosts

好了,现在我们打开浏览器,访问以下这两个域名看看效果吧。

访问 dashboard.k8s.ingress 完美运行,但是访问 kibana.k8s.ingress 却不能正常进入到 UI 界面,控制台调试以下,发现出现了请求资源 404 错误,类似下边的请求资源的错误。

/api/v1/proxy/namespaces/kube-system/services/kibana-logging/bundles/commons.bundle.js?v=10146 

不对呀!我们的请求地址是 http://kibana.k8s.ingress/app/kibana#/discover?_g=... 开头的地址,为什么请求的资源地址还是 /api/v1/proxy/namespaces/kube-system/services/kibana-logging/ 呢?查看了下 Kibana 的 Yaml 配置文件,找到答案了。

$ cat kubernetes/cluster/addons/fluentd-elasticsearch/kibana-controller.yaml
...
env:
  - name: "ELASTICSEARCH_URL"
    value: "http://elasticsearch-logging:9200"
  - name: "KIBANA_BASE_URL"
    value: "/api/v1/proxy/namespaces/kube-system/services/kibana-logging"
...

原来是环境变量中配置了 KIBANA_BASE_URL 这个属性,怪不得会去请求这个地址的资源文件呢。解决办法就是,把这个值设置为空值,因为我们访问地址 http://kibana.k8s.ingress/... 后边没有 BASE_URL。

$ vim kubernetes/cluster/addons/fluentd-elasticsearch/kibana-controller.yaml
...
env:
  - name: "ELASTICSEARCH_URL"
    value: "http://elasticsearch-logging:9200"
  - name: "KIBANA_BASE_URL"
    value: ""
...

$ kubectl apply -f kubernetes/cluster/addons/fluentd-elasticsearch/kibana-controller.yaml

稍等一会,在去访问 Kibana 地址 http://kibana.k8s.ingress/app/kibana#/discover?_g=...,这下就出来了。

5.2 Simple fanout

接下来我们来演示一下通过域名下不同的路径转发到不同的服务上去的 Ingress 配置,我们先只配置一下 kubernetes-dashboard 转发规则,Yaml 文件如下:

# 创建 Yaml 文件
$ vim my-k8s-ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-k8s-ingress
  namespace: kube-system
  annotations:
    ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: my.k8s.ingress
    http:
      paths:
      - path: /dashboard
        backend:
          serviceName: kubernetes-dashboard
          servicePort: 80

# 创建 ingress
$ kubectl create -f my-k8s-ingress.yaml
ingress "my-k8s-ingress" created

# 查看 ingress
$ kubectl get ingress --all-namespaces
NAMESPACE     NAME                       HOSTS                                      ADDRESS         PORTS     AGE
kube-system   dashboard-kibana-ingress   dashboard.k8s.ingress,kibana.k8s.ingress   10.236.65.128   80        19h
kube-system   my-k8s-ingress             my.k8s.ingress                             10.236.65.128   80        1h

然后,我们要能本地访问,还需要本机绑定 Host,否则这个域名也肯定找不到的。

$ echo "10.236.65.128 my-k8s-ingress" >> /etc/hosts

好了,现在我们打开浏览器,访问以下 http://my.k8s.ingress/dashboard/#!/workload?namespace=_all 域名看看效果吧。

OK,成功运行。下边我们要新添加一个匹配规则,将 http://my.k8s.ingress/kibana 转发到 kibana-logging 服务上去。最终实现如下绑定:

my.k8s.ingress -> 10.236.65.128 -> / dashboard    kubernetes-dashboard:80
                                   / kibana       kibana-logging:5601

现在修改一下配置,这里有两种方式修改已经存在的 ingress 规则。

方式一:

$ kubectl edit ingress my.k8s.ingress
...
spec:
  rules:
  - host: my.k8s.ingress
    http:
      paths:
      - path: /dashboard
        backend:
          serviceName: kubernetes-dashboard
          servicePort: 80
      - path: /kibana
        backend:
          serviceName: kibana-logging
          servicePort: 5601
...

方式二:

vim my-k8s-ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-k8s-ingress
  namespace: kube-system
  annotations:
    ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: my.k8s.ingress
    http:
      paths:
      - path: /dashboard
        backend:
          serviceName: kubernetes-dashboard
          servicePort: 80
      - path: /kibana
        backend:
          serviceName: kibana-logging
          servicePort: 5601

# 重新应用或替换 ingress
$ kubectl apply -f my-k8s-ingress.yaml 或者 kubectl replace -f my-k8s-ingress.yaml 

稍等一会,我们去访问 http://my.k8s.ingress/kibana/app/kibana#/discover?_g=... 却不能正常进入到 UI 界面,控制台调试以下,发现出现了请求资源 404 错误,更上边问题一样,出现资源请求 404 错误。

/bundles/commons.bundle.js?v=10146 

原因很简单,请求地址少了一层 /kibana 这下就简单了,修改下 Kibana 的 Yaml 配置文件。

$ vim kubernetes/cluster/addons/fluentd-elasticsearch/kibana-controller.yaml
...
env:
  - name: "ELASTICSEARCH_URL"
    value: "http://elasticsearch-logging:9200"
  - name: "KIBANA_BASE_URL"
    value: "/kibana"
...

$ kubectl apply -f kubernetes/cluster/addons/fluentd-elasticsearch/kibana-controller.yaml

稍等一会,在去访问 Kibana 地址 http://my.k8s.ingress/kibana/app/kibana#/discover?_g=...,这下就出来了。

参考资料

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏乐沙弥的世界

远程桌面 NoMachine 的快速安装与使用

        对于需要经常远程到X windows的网友来说,VNC与Xmanager经常被使用,而NoMachine也是不错的选择之一,该工具简单,易用,尤...

954
来自专栏哎_小羊

初试 Netflix 开源持续云交付平台 Spinnaker

目录 Spinnaker 介绍 环境、软件准备 安装 Development Spinnaker 配置依赖环境 配置并安装 Spinnaker 演示 Spi...

1.1K8
来自专栏java一日一条

HTTP Header 详解

HTTP(HyperTextTransferProtocol) 即超文本传输协议,目前网页传输的的通用协议。HTTP协议采用了请求/响应模 型,浏览器或其他客户...

734
来自专栏有趣的django

Django REST framework+Vue 打造生鲜超市(三)

四、xadmin后台管理 4.1.xadmin添加富文本插件 (1)xadmin/plugins文件夹下新建文件ueditor.py 代码如下: # xadmi...

5047
来自专栏JadePeng的技术博客

gitbook安装与使用,并使用docker部署

本文简单介绍如何安装并使用gitbook,最后如何使用docker构建书籍镜像。 1. 前置条件 需要Nodejs环境,安装npm,国内用户再安装cnpm np...

38410
来自专栏大内老A

Windows安全认证是如何进行的?[Kerberos篇]

最近一段时间都在折腾安全(Security)方面的东西,比如Windows认证、非对称加密、数字证书、数字签名、TLS/SSL、WS-Security等。如果时...

1857
来自专栏后端之路

tomcat 生产环境crash

最近生产系统erp不太稳定,时不时出现tomcat crash,并且log下面没有留下任何证据。 收到邮件如下 告警主机:f6_web0 告警时间:2016.1...

1857
来自专栏惨绿少年

Linux中常见问题(磁盘 定时任务)

第1章 linux无法上网 1) 第一步,先ping域名. ping www.baidu.com 2)再ping一个公网ip , ping 223.5.5.5...

1780
来自专栏大内老A

[原创]谈谈基于Kerberos的Windows Network Authentication - Part II

四、引入Ticket Granting  Service 通过上面的介绍,我们发现Kerberos实际上一个基于Ticket的认证方式。Client想要获取Se...

1859
来自专栏NetCore

Identity Service - 解析微软微服务架构eShopOnContainers(二)

接上一篇,众所周知一个网站的用户登录是非常重要,一站式的登录(SSO)也成了大家讨论的热点。微软在这个Demo中,把登录单独拉了出来,形成了一个Service,...

2165

扫码关注云+社区