• 微服务
  • NGING Plus ingress控制器搭建实践

相关资料:

helm charts:
https://github.com/nginxinc/helm-charts

prometheus exporter:
https://github.com/nginxinc/nginx-prometheus-exporter

install:
https://docs.nginx.com/nginx-ingress-controller/installation/installation-with-helm

证书下载:
https://cs.nginx.com/login

部署 nginx plus官方的控制器

  1. 申请证书和秘钥,只有一个月有效期:https://cs.nginx.com/login
  1. 构建自己的镜像:
docker login #登陆镜像仓库
git clone https://github.com/nginxinc/kubernetes-ingress/
cd kubernetes-ingress
git checkout v1.7.1
ls nginx-repo.*  #将刚才申请到的证书放在这里(nginx-repo.crt  nginx-repo.key
)
make DOCKERFILE=DockerfileForPlus PREFIX=zackzhangkai/nginx-plus-ingress
  1. 增加 NGINX Helm(2) 的仓库地址:
helm repo add nginx-stable https://helm.nginx.com/stable 
helm upgrade
  1. 安装 NGINX Plus(helm2):
kubectl create ns nginx-demo
helm install --name my-release nginx-stable/nginx-ingress --set controller.image.repository=zackzhangkai/nginx-plus-ingress --set controller.image.tag=1.7.0 --set controller.nginxplus=true

也可以直接用官方github 仓库的 helm charts,然后把 values.yaml 相应变量改成与上面一致。

这个时会安装 configmap/deployment/pod/secret/service/sa/clusterRole/ClusterRoleBinding/crd。

部署完后,检查下各个资源状态是否正常。

这个时候发现个问题:这个时候svc 是 loadBalancer 类型的,externalIP 是 pending 状态。如果这个 pending 一直没有恢复,需要手动加下 externalIPs。或是把它改成 NodePort ,如 edit svc,改成:

spec:
  type: NodePort
  externalIPs:
  - 10.160.17.3
  1. 下载官方仓库,里面有 examples,来搭建下:
root@ks-allinone:/root/kubernetes-ingress/examples/complete-example git:(master*) # ls
 cafe-ingress.yaml  cafe-secret.yaml  cafe.yaml  dashboard.png  README.md

把 cafe-ingress.yaml/cafe-secret.yaml/cafe.yaml 分别 kubectl apply -f 应用下

root@ks-allinone:/root/kubernetes-ingress/examples/complete-example git:(master) # for i in `ls *.yaml`; do kubectl apply -f $i;done

注意我这的环境是用了 kubectl ns 插件,已经切换到了 nginx-demo 的 ns 下面,如果你安装,需要指定 ns;或是直接在 default 下也行。

  1. 看下资源,已经全部创建好了:
root@ks-allinone:/root/kubernetes-ingress/examples/complete-example git:(master) # k get all
NAME                                            READY   STATUS    RESTARTS   AGE
pod/coffee-7c45f487fd-2pgnx                     1/1     Running   0          3m2s
pod/coffee-7c45f487fd-87kln                     1/1     Running   0          3m2s
pod/my-release-nginx-ingress-697c6ff88f-98sz9   1/1     Running   0          12m
pod/tea-7769bdf646-54b7f                        1/1     Running   0          3m2s
pod/tea-7769bdf646-g728j                        1/1     Running   0          3m2s
pod/tea-7769bdf646-td7hf                        1/1     Running   0          3m2s

NAME                               TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
service/coffee-svc                 ClusterIP   10.233.27.126   <none>        80/TCP                       3m2s
service/my-release-nginx-ingress   NodePort    10.233.37.174   10.160.17.3   80:32344/TCP,443:31869/TCP   12m
service/tea-svc                    ClusterIP   10.233.35.65    <none>        80/TCP                       3m2s

NAME                                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/coffee                     2/2     2            2           3m2s
deployment.apps/my-release-nginx-ingress   1/1     1            1           12m
deployment.apps/tea                        3/3     3            3           3m2s

NAME                                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/coffee-7c45f487fd                     2         2         2       3m2s
replicaset.apps/my-release-nginx-ingress-697c6ff88f   1         1         1       12m
replicaset.apps/tea-7769bdf646                        3         3         3       3m2s
  1. 看下 ingress:
# k get ing cafe-ingress -o yaml
  ...
  spec:
    rules:
    - host: cafe.example.com
      http:
        paths:
        - backend:
            serviceName: tea-svc
            servicePort: 80
          path: /tea
        - backend:
            serviceName: coffee-svc
            servicePort: 80
          path: /coffee
    tls:
    - hosts:
      - cafe.example.com
      secretName: cafe-secret

可以看到rule:

  1. 匹配的是 http 流量。

  2. path 为/tea 的到 tea-svc这个服务。path 为/coffee 的到 coffe-svc这个服务。
    这两个服务是后端,真正的 webservice 服务。且指定了 service 的 port。

  3. host是 cafe.example.com。这个需要注意,这个 host 是 request 请求 header 的 host。如果没有指定 request,那么就是访问时url 中的域名。

    另外还可以定义 rewrite或是 app-root,如:

  metadata:
    annotations:
      nginx.ingress.kubernetes.io/app-root: /app1
  1. 现在可以访问:
root@ks-allinone:/root/kubernetes-ingress/examples/complete-example git:(master*) #   kubectl get svc
my-release-nginx-ingress   NodePort    10.233.37.174   10.160.17.3   80:32344/TCP,443:31869/TCP   15m
root@ks-allinone:/root # IC_HTTPS_PORT=31869
root@ks-allinone:/root # IC_IP=10.160.17.3
curl --resolve cafe.example.com:$IC_HTTPS_PORT:$IC_IP https://cafe.example.com:$IC_HTTPS_PORT/coffee --insecure

 # curl --resolve cafe.example.com:$IC_HTTPS_PORT:$IC_IP https://cafe.example.com:$IC_HTTPS_PORT/tea --insecure
Server address: 10.233.99.71:8080
Server name: tea-7769bdf646-g728j
Date: 05/Jun/2020:03:11:01 +0000
URI: /tea
Request ID: d2d3f122b029a91576f920e66ec0ccb2

注意 curl 的使用,–resolve 参数是将 cafe.example.com:$IC_HTTPS_PORT指定访问到$IC_IP 。ingress 在 url 的 host 需要匹配这个 cafe.example.com 这个域名,二者相对应。
如果直接用 ip 访问,而修改 header中的 host 也是可以的

curl -H "Host:cafe.example.com" https://10.160.17.3:31165/coffee -k

说明 ingress 中的 host 只是匹配请求的 host,当没有明确指定 host 时,它与 域名保持一致。
控制器默认暴露两个端口 80/443,目前也仅支持这两个端口。

问题:

  1. 如果有多个 ingress 控制器,如何指定哪个 Ingress 用哪个控制器?
    多控制器:
    1.18之后改用了IngressClassIngressClassName
    1.18之前:
    如果要让 ingress资源指定 controller,需在在定义这个 ingress 时在 annotiations 里面指定kubernetes.io/ingress.class

  2. 这个 annotations 的value 如何指定呢?
    这个值并不是固定的,而是在 controller deployment 的启动参数里面会有个 –ingress-class=xxx ,如果没有设置就要设置,否则会出现所有的控制器全部会监测到这个ingress,并生成自己的配置文件:

# kubectl edit ing bookinfo-ingress -n pj-demo
      kubernetes.io/ingress.class: nginxnc
# kubectl edit deploy my-release-nginx-ingress -o yaml
    spec:
      containers:
      - args:
        - -ingress-class=nginxnc
  1. 如何看 ingress controller中的 nginx 的配置文件?
kubectl exec nginx-ingress-7fdb5cd6b8-8jvgl -- nginx -T  #可以列出所有的 Nginx 配置。

监控

接下来,需要安装 exporter, 用 Promethues/Granfana实现监控 及大屏展示