Kubernetes Ingress实战(二):使用Ingress将第一个HTTP服务暴露到集群外部

2018-06-07 阅读: Kubernetes

去年整理过一篇《Kubernetes Ingress实战》,经过这一年的发展Kubernetes的Ingress发生了很大的变化,原来的文章很多地方都不适用了。因此决定结合我们目前的使用情况重新写几篇Kubernetes Ingress相关的分享,内容是比较入门和初级的实操,请高手勿喷。

1.在k8s集群中部署一个简单的http服务

部署一个简单的http服务到Kubernetes集群中,这里使用的http-svc.yaml这个官方的例子,注意其中的镜像是gcr.io/google_containers/echoserver:1.8。 一般我们线上环境的服务是部署到指定的namespace中的,因为这个http-svc.yaml中使用的是default的namespace,所以这里我们对其做一下修改,将其部署到我们集群中已经存在的名称为test的namespace中:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: http-svc
  namespace: test
spec:
  replicas: 1
  selector:
    matchLabels:
      app: http-svc
  template:
    metadata:
      labels:
        app: http-svc
    spec:
      containers:
      - name: http-svc
        image: gcr.io/google_containers/echoserver:1.8
        ports:
        - containerPort: 8080
        env:
          - name: NODE_NAME
            valueFrom:
              fieldRef:
                fieldPath: spec.nodeName
          - name: POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: POD_NAMESPACE
            valueFrom:
              fieldRef:
                fieldPath: metadata.namespace
          - name: POD_IP
            valueFrom:
              fieldRef:
                fieldPath: status.podIP

---

apiVersion: v1
kind: Service
metadata:
  name: http-svc
  namespace: test
  labels:
    app: http-svc
spec:
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP
    name: http
  selector:
    app: http-svc

kubectl create -f http-svc.yaml


kubectl get svc,po -n test
NAME           TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
svc/http-svc   ClusterIP   10.96.6.97   <none>        80/TCP    35s

NAME                           READY     STATUS    RESTARTS   AGE
po/http-svc-6d686cfdfc-lw578   1/1       Running   0          36s

2.使用Ingress将HTTP服务暴露到集群外

可以看出已经在Kubernetes集群的test namespace部署了一个http-svc的服务,但是只能在集群内部访问。下面为这个服务创建一个ingress将其暴露到集群外部。

先看以子路径path的形式暴露http-svc.ingress.yaml:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: http-svc
  namespace: test
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
  rules:
  - http:
      paths:
      - path: /http-svc
        backend:
          serviceName: http-svc
          servicePort: 80
kubectl create -f http-svc.ingress.yaml
ingress "http-svc" created

kubectl get ingress -n test
NAME       HOSTS     ADDRESS            PORTS     AGE
http-svc   *         192.168.1.101,1...   80        1m

从集群外部访问:

 curl 192.168.1.101/http-svc

Hostname: http-svc-6d686cfdfc-lw578

Pod Information:
        node name:      node7
        pod name:       http-svc-6d686cfdfc-lw578
        pod namespace:  test
        pod IP: 10.244.6.120

Server values:
        server_version=nginx: 1.13.3 - lua: 10008

Request Information:
        client_address=10.244.1.143
        method=GET
        real path=/http-svc
        query=
        request_version=1.1
        request_uri=http://192.168.1.101:8080/http-svc

Request Headers:
        accept=*/*
        connection=close
        host=192.168.1.3
        user-agent=curl/7.29.0
        x-forwarded-for=10.244.2.0
        x-forwarded-host=192.168.1.101
        x-forwarded-port=80
        x-forwarded-proto=http
        x-original-uri=/http-svc
        x-real-ip=10.244.2.0
        x-request-id=eea64169a57e0d3cd5cfe7b083559809
        x-scheme=http

Request Body:
        -no body in request-

下面改为以域名(nginx虚拟主机)的形式暴露http-svc这个服务:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: http-svc
  namespace: test
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
  rules:
  - host: http-svc.frognew.com
    http:
      paths:
      - path: /
        backend:
          serviceName: http-svc
          servicePort: 80
kubectl apply -f http-svc.ingress.yaml
ingress "http-svc" configured

kubectl get ingress -n test
NAME       HOSTS                         ADDRESS            PORTS     AGE
http-svc   http-svc.frognew.com   192.168.1.101,1...   80        15m
curl 192.168.1.101 -H "Host: http-svc.frognew.com"

Hostname: http-svc-6d686cfdfc-lw578

Pod Information:
	node name:	node7
	pod name:	http-svc-6d686cfdfc-lw578
	pod namespace:	test
	pod IP:	10.244.4.120
......

如果一个Kubernetes集群中有很多http服务需要暴露到集群外边的时,如果使用NodePort的形式,每个节点上都会监听大量的NodePort,而使用ingress,可以避免这种情况。 例如对于Kubernetes Dashoboard之前是以NodePort对外暴露的:

kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kube-system
spec:
  type: NodePort
  ports:
    - port: 443
      targetPort: 8443
      nodePort: 30001
  selector:
    k8s-app: kubernetes-dashboard

将Service的type修改为ClusterIp,并去掉指定的NodePort:

kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kube-system
spec:
  type: ClusterIP
  ports:
    - port: 443
      targetPort: 8443
  selector:
    k8s-app: kubernetes-dashboard

并创建Ingress:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: kubernetes-dashboard
  namespace: kube-system
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
    nginx.ingress.kubernetes.io/secure-backends: "true"
spec:
  rules:
  - host: k8s.frognew.com
    http:
      paths:
      - path: /
        backend:
          serviceName: kubernetes-dashboard
          servicePort: 443

注意因为Service kubernetes-dashboard启用了https,所以是secure backend,在创建Ingress时需要用annotation指定nginx.ingress.kubernetes.io/secure-backends: "true"

另外虽然在集群内部kubernetes-dashboard是https,而这里我们创建的ingress是http的暴露在80端口上,关于在ingress上开启https后边我们单独介绍。

curl http://192.168.1.101 -H "Host: k8s.frognew.com"
 <!doctype html> <html ng-app="kubernetesDashboard"> <head> <meta charset="utf-8"> <title ng-controller="kdTitle as $ctrl" ng-bind="$ctrl.title()"></title> ......

参考

标题:Kubernetes Ingress实战(二):使用Ingress将第一个HTTP服务暴露到集群外部
本文链接:https://blog.frognew.com/2018/06/kubernetes-ingress-2.html
转载请注明出处。

目录