k8s version: 1.6.7 无CNI
[title]1. 创建Service Account[/title]
| 
					 1 2 3 4 5 6  | 
						[root@docker1 complete-example]# more nginx-ingress-sa.yaml apiVersion: v1 kind: ServiceAccount metadata:   name: nginx-ingress   namespace: default  | 
					
kubectl create -f nginx-ingress-sa.yaml
[title]2. 绑定sa到role[/title]
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14  | 
						[root@docker1 complete-example]# cat nginx-ingress-sa-role-binding.yaml  kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1beta1 metadata:   name: nginx-ingress   namespace: default subjects:   - kind: ServiceAccount     namespace: default     name: nginx-ingress roleRef:   kind: ClusterRole   name: cluster-admin   apiGroup: rbac.authorization.k8s.io  | 
					
注意这里随意给了一个较高的角色
kubectl create -f nginx-ingress-sa-role-binding.yaml
上述工作是为了保证nginx controller pod获得权限与api server通信:
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17  | 
						Kubernetes                                                  Workstation +---------------------------------------------------+     +------------------+ |                                                   |     |                  | |  +-----------+   apiserver        +------------+  |     |  +------------+  | |  |           |   proxy            |            |  |     |  |            |  | |  | apiserver |                    |  ingress   |  |     |  |  ingress   |  | |  |           |                    | controller |  |     |  | controller |  | |  |           |                    |            |  |     |  |            |  | |  |           |                    |            |  |     |  |            |  | |  |           |  service account/  |            |  |     |  |            |  | |  |           |  kubeconfig        |            |  |     |  |            |  | |  |           +<-------------------+            |  |     |  |            |  | |  |           |                    |            |  |     |  |            |  | |  +------+----+      kubeconfig    +------+-----+  |     |  +------+-----+  | |         |<--------------------------------------------------------|        | |                                                   |     |                  | +---------------------------------------------------+     +------------------+  | 
					
[title]3. 创建nginx controller pod需要使用的缺省tls 证书及key[/title]
kubectl create -f default-server-secret.yaml
相关yaml文件从https://github.com/nginxinc/kubernetes-ingress/tree/master/examples/complete-example 获取
[title]4. 部署nginx ingress controller[/title]
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33  | 
						[root@docker1 complete-example]# cat nginx-ingress-rc.yaml  apiVersion: extensions/v1beta1 kind: DaemonSet metadata:   name: nginx-ingress-ds   labels:     app: nginx-ingress-ctrl spec:   template:     metadata:       labels:         app: nginx-ingress-ctrl     spec:       serviceAccountName: nginx-ingress       containers:       - image: nginxdemos/nginx-ingress:1.0.0         name: nginx-ingress-lb         ports:         - containerPort: 80           hostPort: 80         - containerPort: 443           hostPort: 443         env:         - name: POD_NAMESPACE           valueFrom:             fieldRef:               fieldPath: metadata.namespace         # Uncomment the lines below to enable extensive logging and/or customization of         # NGINX configuration with configmaps         args:          #- -v=3          #- -nginx-configmaps=$(POD_NAMESPACE)/nginx-config           - -default-server-tls-secret=$(POD_NAMESPACE)/default-server-secret  | 
					
注意这里使用的是daemonset方式部署,为了保证每个node上都存在一个nginx pod
[title]5. 创建相关测试用APP pod及其相关service[/title]
| 
					 1 2 3 4  | 
						$ kubectl create -f tea-rc.yaml $ kubectl create -f tea-svc.yaml $ kubectl create -f coffee-rc.yaml $ kubectl create -f coffee-svc.yaml  | 
					
[title]6. 创建nginx 提供应用ssl访问时候所需的证书及key[/title]
| 
					 1  | 
						$ kubectl create -f cafe-secret.yaml  | 
					
[title]7. 创建k8s中的ingress 资源[/title]
| 
					 1  | 
						kubectl create -f cafe-ingress.yaml  | 
					
[title]8. 验证测试[/title]
| 
					 1 2 3  | 
						[root@docker1 complete-example]# kubectl get ing NAME           HOSTS              ADDRESS   PORTS     AGE cafe-ingress   cafe.example.com             80, 443   11d  | 
					
注意系统本没有显示 ingress 的 address,这可能是由于我的环境没有使用CNI缘故?但从node节点的主机IP上是可以访问到相关nginx发布的应用的.
| 
					 1 2 3 4 5 6  | 
						[root@docker1 complete-example]# kubectl get pods NAME                         READY     STATUS    RESTARTS   AGE coffee-rc-94c0j              1/1       Running   1          11d nginx-ingress-ds-hwhl3       1/1       Running   0          1h nginx-ingress-ds-j845z       1/1       Running   0          1h tea-rc-4501t                 1/1       Running   1          11d  | 
					
测试环境为了节省资源,只设置coffee,tea应用分别只其一个pod.
docker inspect 某个具体ingress controller pod:
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20  | 
						        "NetworkSettings": {             "Bridge": "",             "SandboxID": "849a063de3679beb132885677e95de4e953e5d9731940d614fc04982aa5a7f1f",             "HairpinMode": false,             "LinkLocalIPv6Address": "",             "LinkLocalIPv6PrefixLen": 0,             "Ports": {                 "443/tcp": [                     {                         "HostIp": "0.0.0.0",                         "HostPort": "443"                     }                 ],                 "80/tcp": [                     {                         "HostIp": "0.0.0.0",                         "HostPort": "80"                     }                 ]             },  | 
					
访问某个具体的ingress controller所在node的宿主IP:访问coffee目录获得如下应用显示请求被分往coffee pod
访问/tea目录,请求被分往tea pod:
当创建ingress resource时, ingress controller上日志显示:
| 
					 1  | 
						I0924 13:05:24.593156       1 event.go:218] Event(v1.ObjectReference{Kind:"Ingress", Namespace:"default", Name:"cafe-ingress", UID:"efc09df3-9884-11e7-911f-000c29420d98", APIVersion:"extensions", ResourceVersion:"168360", FieldPath:""}): type: 'Normal' reason: 'AddedOrUpdated' Configuration for default/cafe-ingress was added or updated  | 
					
说明nginx controller获得相关ingress指定的配置更新.
[title]Ingress原理[/title]
Ingress (resource)是k8s中配置controller的具体规则实现,可以理解为k8s具备L7 LB实现(比如基于host,基于uri)。
Ingress controller监控ingress resource配置,并对LB进行配置。一般来说controller会和具体的software LB作为一个pod被部署,不同的SW LB需要不同的controller实现。真正执行这些规则来分发请求的是 SW LB,所以controller里可以是nginx也可以其它比如traefik。下图描述了ingress的原理(注意图中错误: nginx实际直接将请求发送给pod,不经过service):
nginx controller通过监视api server获取相关ingress、service、endpoint、secret、node、configmap对象,并在程序内部不断循环监视相关service是否有新的endpoints变化,一旦发生变化则自动更新nginx.tmpl 模板配置并产生新的配置文件进行reload
ingress resource里配置的是service名称,但nginx controller是直接将请求发送到相关pods.
nginx自动产生的一个配置示例:
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77  | 
						[root@docker1 complete-example]# kubectl exec nginx-ingress-ds-hwhl3 -- cat /etc/nginx/conf.d/default-cafe-ingress.conf upstream default-cafe-ingress-cafe.example.com-tea-svc {  server 10.2.13.5:80; <<<<<<< pod地址 } upstream default-cafe-ingress-cafe.example.com-coffee-svc {  server 10.2.13.4:80; <<<<<<< pod地址 } server {  listen 80;  listen 443 ssl;  ssl_certificate /etc/nginx/secrets/default-cafe-secret;  ssl_certificate_key /etc/nginx/secrets/default-cafe-secret;  server_tokens on;  server_name cafe.example.com;  if ($scheme = http) {   return 301 https://$host:443$request_uri;  }  location /tea {   proxy_http_version 1.1;   proxy_connect_timeout 60s;   proxy_read_timeout 60s;   client_max_body_size 1m;   proxy_set_header Host $host;   proxy_set_header X-Real-IP $remote_addr;   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;   proxy_set_header X-Forwarded-Host $host;   proxy_set_header X-Forwarded-Port $server_port;   proxy_set_header X-Forwarded-Proto $scheme;   proxy_buffering on;   proxy_pass http://default-cafe-ingress-cafe.example.com-tea-svc;  }  location /coffee {   proxy_http_version 1.1;   proxy_connect_timeout 60s;   proxy_read_timeout 60s;   client_max_body_size 1m;   proxy_set_header Host $host;   proxy_set_header X-Real-IP $remote_addr;   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;   proxy_set_header X-Forwarded-Host $host;   proxy_set_header X-Forwarded-Port $server_port;   proxy_set_header X-Forwarded-Proto $scheme;   proxy_buffering on;   proxy_pass http://default-cafe-ingress-cafe.example.com-coffee-svc;  } }  | 
					
[title]ingress的一些问题[/title]
还不能支持较为复杂的LB特性,例如会话保持,nginx controller扩展了ingress可以做会话保持但必须使用nginx plus。
业务规则发生变化,会导致频繁修改ingress配置,且所变化都会引起nginx reload配置,这在大并发,复杂系统环境下可能会产生较大问题
外部访问的入口依赖使用controller所在node的宿主IP,且端口暴露在node IP上,对于多个应用需要同时使用相同端口时候会导致端口冲突
外部访问入口分散在多个node IP上,使得外部统一访问变得困难,且存在潜在的单点故障,一个node 失败,客户端只有重新发起到新的node节点的访问(虽然可以使用dns来轮询这些IP),因此有必要为这些入口访问点构建统一的虚拟IP(漂移IP),这可以通过在k8s环境外部使用其它高级LB来实现,比如F5。或者将多个提供访问的node节点构建为一个集群(比如使用keepalived),可参考 https://jimmysong.io/kubernetes-handbook/practice/edge-node-configuration.html
所以基本上ingress的方案还得需要一个外部LB来做统一的高容量请求入口,ingress只能作为k8s内部的二级LB(且功能有限)。与其这样,不如直接通过将pod暴露给外部LB来直接做负载均衡,可参考:https://www.myf5.net/post/2334.htm
其它缺点:
nginx无图形界面统一管理,nginx plus有 但是是商业版本。
ingress没有业务监控检查功能
只支持http L7
不能混合支持L4/L7 LB
不支持TLS的SNI,以及SSL re-encrypt
(2020.6修改,L4/L7.SNI,ssl passthrough 都能支持了)



                
文章评论