Kubernetes Ingress实战(二):使用Ingress将第一个HTTP服务暴露到集群外部
2018-06-07
去年整理过一篇《Kubernetes Ingress实战》,经过这一年的发展Kubernetes的Ingress发生了很大的变化,原来的文章很多地方都不适用了。因此决定结合我们目前的使用情况重新写几篇Kubernetes Ingress相关的分享,内容是比较入门和初级的实操,请高手勿喷。
- Kubernetes Ingress实战(一):在Kubernetes集群中部署NGINX Ingress Controller
- Kubernetes Ingress实战(二):使用Ingress将第一个HTTP服务暴露到集群外部
- Kubernetes Ingress实战(三):使用Ingress将gRPC服务暴露到Kubernetes集群外部
- Kubernetes Ingress实战(四):Bare metal环境下Kubernetes Ingress边缘节点的高可用
- Kubernetes Ingress实战(五):Bare metal环境下Kubernetes Ingress边缘节点的高可用(基于IPVS)
- Kubernetes Ingress实战(六):Bare metal环境下Kubernetes Ingress边缘节点的高可用,Ingress Controller使用hostNetwork
1.在k8s集群中部署一个简单的http服务 #
部署一个简单的http服务到Kubernetes集群中,这里使用的http-svc.yaml这个官方的例子,注意其中的镜像是gcr.io/google_containers/echoserver:1.8
。
一般我们线上环境的服务是部署到指定的namespace中的,因为这个http-svc.yaml中使用的是default的namespace,所以这里我们对其做一下修改,将其部署到我们集群中已经存在的名称为test的namespace中:
1apiVersion: extensions/v1beta1
2kind: Deployment
3metadata:
4 name: http-svc
5 namespace: test
6spec:
7 replicas: 1
8 selector:
9 matchLabels:
10 app: http-svc
11 template:
12 metadata:
13 labels:
14 app: http-svc
15 spec:
16 containers:
17 - name: http-svc
18 image: gcr.io/google_containers/echoserver:1.8
19 ports:
20 - containerPort: 8080
21 env:
22 - name: NODE_NAME
23 valueFrom:
24 fieldRef:
25 fieldPath: spec.nodeName
26 - name: POD_NAME
27 valueFrom:
28 fieldRef:
29 fieldPath: metadata.name
30 - name: POD_NAMESPACE
31 valueFrom:
32 fieldRef:
33 fieldPath: metadata.namespace
34 - name: POD_IP
35 valueFrom:
36 fieldRef:
37 fieldPath: status.podIP
38
39---
40
41apiVersion: v1
42kind: Service
43metadata:
44 name: http-svc
45 namespace: test
46 labels:
47 app: http-svc
48spec:
49 ports:
50 - port: 80
51 targetPort: 8080
52 protocol: TCP
53 name: http
54 selector:
55 app: http-svc
1kubectl create -f http-svc.yaml
2
3
4kubectl get svc,po -n test
5NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
6svc/http-svc ClusterIP 10.96.6.97 <none> 80/TCP 35s
7
8NAME READY STATUS RESTARTS AGE
9po/http-svc-6d686cfdfc-lw578 1/1 Running 0 36s
2.使用Ingress将HTTP服务暴露到集群外 #
可以看出已经在Kubernetes集群的test namespace部署了一个http-svc的服务,但是只能在集群内部访问。下面为这个服务创建一个ingress将其暴露到集群外部。
先看以子路径path的形式暴露http-svc.ingress.yaml:
1apiVersion: extensions/v1beta1
2kind: Ingress
3metadata:
4 name: http-svc
5 namespace: test
6 annotations:
7 nginx.ingress.kubernetes.io/ssl-redirect: "false"
8spec:
9 rules:
10 - http:
11 paths:
12 - path: /http-svc
13 backend:
14 serviceName: http-svc
15 servicePort: 80
1kubectl create -f http-svc.ingress.yaml
2ingress "http-svc" created
3
4kubectl get ingress -n test
5NAME HOSTS ADDRESS PORTS AGE
6http-svc * 192.168.1.101,1... 80 1m
从集群外部访问:
1 curl 192.168.1.101/http-svc
2
3Hostname: http-svc-6d686cfdfc-lw578
4
5Pod Information:
6 node name: node7
7 pod name: http-svc-6d686cfdfc-lw578
8 pod namespace: test
9 pod IP: 10.244.6.120
10
11Server values:
12 server_version=nginx: 1.13.3 - lua: 10008
13
14Request Information:
15 client_address=10.244.1.143
16 method=GET
17 real path=/http-svc
18 query=
19 request_version=1.1
20 request_uri=http://192.168.1.101:8080/http-svc
21
22Request Headers:
23 accept=*/*
24 connection=close
25 host=192.168.1.3
26 user-agent=curl/7.29.0
27 x-forwarded-for=10.244.2.0
28 x-forwarded-host=192.168.1.101
29 x-forwarded-port=80
30 x-forwarded-proto=http
31 x-original-uri=/http-svc
32 x-real-ip=10.244.2.0
33 x-request-id=eea64169a57e0d3cd5cfe7b083559809
34 x-scheme=http
35
36Request Body:
37 -no body in request-
下面改为以域名(nginx虚拟主机)的形式暴露http-svc这个服务:
1apiVersion: extensions/v1beta1
2kind: Ingress
3metadata:
4 name: http-svc
5 namespace: test
6 annotations:
7 nginx.ingress.kubernetes.io/ssl-redirect: "false"
8spec:
9 rules:
10 - host: http-svc.frognew.com
11 http:
12 paths:
13 - path: /
14 backend:
15 serviceName: http-svc
16 servicePort: 80
1kubectl apply -f http-svc.ingress.yaml
2ingress "http-svc" configured
3
4kubectl get ingress -n test
5NAME HOSTS ADDRESS PORTS AGE
6http-svc http-svc.frognew.com 192.168.1.101,1... 80 15m
1curl 192.168.1.101 -H "Host: http-svc.frognew.com"
2
3Hostname: http-svc-6d686cfdfc-lw578
4
5Pod Information:
6 node name: node7
7 pod name: http-svc-6d686cfdfc-lw578
8 pod namespace: test
9 pod IP: 10.244.4.120
10......
如果一个Kubernetes集群中有很多http服务需要暴露到集群外边的时,如果使用NodePort的形式,每个节点上都会监听大量的NodePort,而使用ingress,可以避免这种情况。 例如对于Kubernetes Dashoboard之前是以NodePort对外暴露的:
1kind: Service
2apiVersion: v1
3metadata:
4 labels:
5 k8s-app: kubernetes-dashboard
6 name: kubernetes-dashboard
7 namespace: kube-system
8spec:
9 type: NodePort
10 ports:
11 - port: 443
12 targetPort: 8443
13 nodePort: 30001
14 selector:
15 k8s-app: kubernetes-dashboard
将Service的type修改为ClusterIp,并去掉指定的NodePort:
1kind: Service
2apiVersion: v1
3metadata:
4 labels:
5 k8s-app: kubernetes-dashboard
6 name: kubernetes-dashboard
7 namespace: kube-system
8spec:
9 type: ClusterIP
10 ports:
11 - port: 443
12 targetPort: 8443
13 selector:
14 k8s-app: kubernetes-dashboard
并创建Ingress:
1apiVersion: extensions/v1beta1
2kind: Ingress
3metadata:
4 name: kubernetes-dashboard
5 namespace: kube-system
6 annotations:
7 nginx.ingress.kubernetes.io/ssl-redirect: "false"
8 nginx.ingress.kubernetes.io/secure-backends: "true"
9spec:
10 rules:
11 - host: k8s.frognew.com
12 http:
13 paths:
14 - path: /
15 backend:
16 serviceName: kubernetes-dashboard
17 servicePort: 443
注意因为Service kubernetes-dashboard启用了https,所以是secure backend,在创建Ingress时需要用annotation指定
nginx.ingress.kubernetes.io/secure-backends: "true"
。 (更新:ingress-nginx更新的版本中改用nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
代替nginx.ingress.kubernetes.io/secure-backends: "true"
)
另外虽然在集群内部
kubernetes-dashboard
是https,而这里我们创建的ingress是http的暴露在80端口上,关于在ingress上开启https后边我们单独介绍。
1curl http://192.168.1.101 -H "Host: k8s.frognew.com"
2 <!doctype html> <html ng-app="kubernetesDashboard"> <head> <meta charset="utf-8"> <title ng-controller="kdTitle as $ctrl" ng-bind="$ctrl.title()"></title> ......