最新消息:

Kubernetes Nginx Ingress 教程

Linux ipcpu 363浏览

Kubernetes Nginx Ingress 教程.md

一、Ingress 介绍

Kubernetes 暴露服务的方式目前只有三种:LoadBlancer Service、NodePort Service、Ingress;

Ingress 是什么?

众所周知 Kubernetes 具有强大的副本控制能力,能保证在任意副本(Pod)挂掉时自动从其他机器启动一个新的,还可以动态扩容等,总之一句话,这个 Pod 可能在任何时刻出现在任何节点上,也可能在任何时刻死在任何节点上;那么自然随着 Pod 的创建和销毁,Pod IP 肯定会动态变化;那么如何把这个动态的 Pod IP 暴露出去?

借助于 Kubernetes 的 Service 机制,Service 可以以标签的形式选定一组带有指定标签的 Pod,并监控和自动负载他们的 Pod IP,那么我们向外暴露只暴露 Service IP 就行了;这就是 NodePort 模式:即在每个节点上开起一个端口,然后转发到内部 Service IP 上,如下图所示NodePort

采用 NodePort 方式暴露服务面临一个坑爹的问题是,服务一旦多起来,NodePort 在每个节点上开启的端口会及其庞大,而且难以维护;这时候引出的思考问题是 “能不能使用 Nginx 啥的只监听一个端口,比如 80,然后按照域名向后转发?” 这思路很好,简单的实现就是使用 DaemonSet 在每个 node 上监听 80,然后写好规则,因为 Nginx 外面绑定了宿主机 80 端口(就像 NodePort),本身又在集群内,那么向后直接转发到相应 Service IP 就行了,如下图所示

从上面的思路,采用 Nginx 似乎已经解决了问题,但是其实这里面有一个很大缺陷:每次有新服务加入怎么改 Nginx 配置?总不能手动改或者来个 Rolling Update 前端 Nginx Pod 吧?这时候 “伟大而又正直勇敢的” Ingress 登场,如果不算上面的 Nginx,Ingress 只有两大组件:Ingress Controller 和 Ingress

Ingress 这个玩意,简单的理解就是 你原来要改 Nginx 配置,然后配置各种域名对应哪个 Service,现在把这个动作抽象出来,变成一个 Ingress 对象,你可以用 yml 创建,每次不要去改 Nginx 了,直接改 yml 然后创建/更新就行了;那么问题来了:”Nginx 咋整?”

Ingress Controller 这东西就是解决 “Nginx 咋整” 的;Ingress Controoler 通过与 Kubernetes API 交互,动态的去感知集群中 Ingress 规则变化,然后读取他,按照他自己模板生成一段 Nginx 配置,再写到 Nginx Pod 里,最后 reload 一下,工作流程如下图

当然在实际应用中,最新版本 Kubernetes 已经将 Nginx 与 Ingress Controller 合并为一个组件,所以 Nginx 无需单独部署,只需要部署 Ingress Controller 即可

二、部署Nginx Ingress Controller

建议使用DaemonSet方式部署

官方给出的配置文件在 https://github.com/kubernetes/ingress-nginx/tree/master/deploy

我的kubernetes集群是1.5的版本,以下是我的配置文件

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nginx-ingress-serviceaccount
---
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  name: nginx-ingress-lb
spec:
  template:
    metadata:
      labels:
        name: nginx-ingress-lb
    spec:
      serviceAccountName: nginx-ingress-serviceaccount
      terminationGracePeriodSeconds: 60
      hostNetwork: true
      containers:
      - image: 47.52.174.242:5000/google_containers/nginx-ingress-controller:0.8.3
        name: nginx-ingress-lb
        imagePullPolicy: IfNotPresent
        securityContext:
          privileged: true
        # use downward API
        ports:
        - containerPort: 80
          hostPort: 80
        - containerPort: 443
          hostPort: 443
        livenessProbe:
          failureThreshold: 3
          httpGet:
            path: /healthz
            port: 10254
            scheme: HTTP
          initialDelaySeconds: 10
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 1
        readinessProbe:
          failureThreshold: 3
          httpGet:
            path: /healthz
            port: 10254
            scheme: HTTP
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 1
        env:
          - name: POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: POD_NAMESPACE
            valueFrom:
              fieldRef:
                fieldPath: metadata.namespace
        args:
        - /nginx-ingress-controller
        - --default-backend-service=default/svc-nginx

知得注意的以下几点:

  1. 这里面需要使用ServiceAccount,否则Pod会报错无法连接APIServer
  2. 使用hostNetwork和hostPort直接监听Node服务器上的端口。
  3. 创建Nginx Ingress Controller之前必须有一个默认后端default backend,随便找个nginx放上就好,需要创建好service。

三、创建ingress

这里我借用了traefik的案例 https://github.com/containous/traefik/tree/master/examples/k8s

需要现部署3个服务stilton,cheddar和wensleydale,然后再基于虚拟主机创建ingress

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: cheese
spec:
  rules:
  - host: stilton.minikube
    http:
      paths:
      - path: /
        backend:
          serviceName: stilton
          servicePort: http
  - host: cheddar.minikube
    http:
      paths:
      - path: /
        backend:
          serviceName: cheddar
          servicePort: http
  - host: wensleydale.minikube
    http:
      paths:
      - path: /
        backend:
          serviceName: wensleydale
          servicePort: http

四、测试

[root@k80 k8s]# curl http://cheddar.minikube/ -x 10.130.8.25:80
<html>
...
  <body>
    <h1>Cheddar</h1>
  </body>
</html>
[root@k80 k8s]# curl http://wensleydale.minikube/ -x 10.130.8.25:80
<html>
...
  <body>
    <h1>Wensleydale</h1>
  </body>
</html>

通过指定不同的域名,显示出不同的内容。

五、业务状态健康检查

Nginx Ingress Controller 需要配置livenessProbe和readinessProbe。

Service和Ingress没有健康检查功能。

提供服务的Pod或者Deployment也可以通过livenessProbe和readinessProbe来进行健康检查。

六、HTTPS的配置

随着https站点的普及,支持https站点也是必须的,接下来我们给nginx配置证书:

首先我们需要将我们的证书文件转换为K8S中的Secret。

kubectl create secret tls ipcpu.tls --key server.key --cert server.pem

然后创建支持https的Ingress:

cat <<EOF | kubectl create -f - 
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: tls-fanout
spec:
  tls:
  - hosts:
    - foo.ipcpu.com.cn
    secretName: ipcpu.tls
  rules:
  - host: foo.ipcpu.com.cn
    http:
      paths:
      - path: /
        backend:
          serviceName: wensleydale
          servicePort: 80
EOF

然后测试

[root@k80 nginx-ingress]# cat <<EOF >>/etc/hosts
> 10.130.8.25          foo.ipcpu.com.cn
> EOF
[root@k80 nginx-ingress]# curl -I https://foo.ipcpu.com.cn
HTTP/1.1 200 OK
Server: nginx/1.11.3
Content-Type: text/html
Content-Length: 521

七、参考资料

https://mritd.me/2017/03/04/how-to-use-nginx-ingress/
http://blog.opskumu.com/k8s-ingress.html
http://www.jianshu.com/p/8afb493dc4eb
https://my.oschina.net/jxcdwangtao/blog/1523812
https://github.com/kubernetes/ingress-nginx/
https://help.aliyun.com/document_detail/53770.html?spm=5176.doc56336.6.826.YOsGbq

转载请注明:IPCPU-网络之路 » Kubernetes Nginx Ingress 教程