参考资料:

实验室集群中已经有一个ingress-controller,ingress.class为nginx。 本次实验的目标是将服务通过ingress暴露到外部服务,最好能够直接通过外网IP访问。

实验所需镜像 Link to heading

原本用的是google的镜像,但是因为在国内,弄起来太麻烦了。所以还是从dockerhub上选了一个类似的镜像。

apiVersion: v1
kind: Namespace
metadata:
  name: echoserver
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: echoserver
  namespace: echoserver
spec:
  replicas: 2
  selector:
    matchLabels:
      app: echoserver
  template:
    metadata:
      labels:
        app: echoserver
    spec:
      containers:
      - image: ealen/echo-server:latest
        imagePullPolicy: IfNotPresent
        name: echoserver
        ports:
        - containerPort: 80
        env:
        - name: PORT
          value: "80"
---
apiVersion: v1
kind: Service
metadata:
  name: echoserver
  namespace: echoserver
spec:
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  type: ClusterIP
  selector:
    app: echoserver
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: echoserver
  namespace: echoserver
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  rules:
  - http:
      paths:
      - path: /echoserver
        pathType: Prefix
        backend:
          service:
            name: echoserver
            port:
              number: 80

进行测试 Link to heading

集群内功能测试 Link to heading

通过执行kubectl get svc -n=echoserver可以拿到对应服务的ClusterIP 再执行kubectl run -i --rm --restart=Never dummy --image=dockerqa/curl:ubuntu-trusty -n=echoserver --command -- curl 10.108.58.132:80 即可在集群内部访问到目标服务。结果可以经过jq整理,为

{
  "host": {
    "hostname": "10.108.58.132",
    "ip": "::ffff:10.244.3.188",
    "ips": []
  },
  "http": {
    "method": "GET",
    "baseUrl": "",
    "originalUrl": "/",
    "protocol": "http"
  },
  "request": {
    "params": {
      "0": "/"
    },
    "query": {},
    "cookies": {},
    "body": {},
    "headers": {
      "user-agent": "curl/7.35.0",
      "host": "10.108.58.132",
      "accept": "*/*"
    }
  },
  "environment": {
    "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
    "HOSTNAME": "echoserver-6944fb9c86-mn6vz",
    "PORT": "80",
    "KUBERNETES_PORT_443_TCP": "tcp://10.96.0.1:443",
    "KUBERNETES_PORT_443_TCP_ADDR": "10.96.0.1",
    "ECHOSERVER_PORT_80_TCP": "tcp://10.108.58.132:80",
    "KUBERNETES_SERVICE_PORT_HTTPS": "443",
    "KUBERNETES_PORT": "tcp://10.96.0.1:443",
    "KUBERNETES_PORT_443_TCP_PROTO": "tcp",
    "KUBERNETES_PORT_443_TCP_PORT": "443",
    "ECHOSERVER_SERVICE_HOST": "10.108.58.132",
    "ECHOSERVER_PORT": "tcp://10.108.58.132:80",
    "KUBERNETES_SERVICE_HOST": "10.96.0.1",
    "KUBERNETES_SERVICE_PORT": "443",
    "ECHOSERVER_SERVICE_PORT": "80",
    "ECHOSERVER_PORT_80_TCP_PROTO": "tcp",
    "ECHOSERVER_PORT_80_TCP_PORT": "80",
    "ECHOSERVER_PORT_80_TCP_ADDR": "10.108.58.132",
    "NODE_VERSION": "12.19.0",
    "YARN_VERSION": "1.22.5",
    "HOME": "/root"
  }
}

集群外功能测试 Link to heading

通过kubectl get ingress -n=echoserver可以确定目标ingress的内网IP地址。 再使用curl 192.168.1.10/echoserver,ingress-controller在工作正常的情况下即可完成对应的转发

{
  "host": {
    "hostname": "192.168.1.10",
    "ip": "::ffff:10.244.1.201",
    "ips": []
  },
  "http": {
    "method": "GET",
    "baseUrl": "",
    "originalUrl": "/echoserver",
    "protocol": "http"
  },
  "request": {
    "params": {
      "0": "/echoserver"
    },
    "query": {},
    "cookies": {},
    "body": {},
    "headers": {
      "host": "192.168.1.10",
      "x-request-id": "1e1d9bcdb01d497e7cb1745a1ac6ff0e",
      "x-real-ip": "10.244.0.0",
      "x-forwarded-for": "10.244.0.0",
      "x-forwarded-host": "192.168.1.10",
      "x-forwarded-port": "80",
      "x-forwarded-proto": "http",
      "x-scheme": "http",
      "user-agent": "curl/7.63.0",
      "accept": "*/*"
    }
  },
  "environment": {
    "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
    "HOSTNAME": "echoserver-6944fb9c86-mn6vz",
    "PORT": "80",
    "KUBERNETES_PORT_443_TCP": "tcp://10.96.0.1:443",
    "KUBERNETES_PORT_443_TCP_ADDR": "10.96.0.1",
    "ECHOSERVER_PORT_80_TCP": "tcp://10.108.58.132:80",
    "KUBERNETES_SERVICE_PORT_HTTPS": "443",
    "KUBERNETES_PORT": "tcp://10.96.0.1:443",
    "KUBERNETES_PORT_443_TCP_PROTO": "tcp",
    "KUBERNETES_PORT_443_TCP_PORT": "443",
    "ECHOSERVER_SERVICE_HOST": "10.108.58.132",
    "ECHOSERVER_PORT": "tcp://10.108.58.132:80",
    "KUBERNETES_SERVICE_HOST": "10.96.0.1",
    "KUBERNETES_SERVICE_PORT": "443",
    "ECHOSERVER_SERVICE_PORT": "80",
    "ECHOSERVER_PORT_80_TCP_PROTO": "tcp",
    "ECHOSERVER_PORT_80_TCP_PORT": "80",
    "ECHOSERVER_PORT_80_TCP_ADDR": "10.108.58.132",
    "NODE_VERSION": "12.19.0",
    "YARN_VERSION": "1.22.5",
    "HOME": "/root"
  }
}

如果将ingress改为

---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: echoserver
  namespace: echoserver
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  rules:
  - host: http-svc.frognew.com
    http:
      paths:
      - path: /echoserver
        pathType: Prefix
        backend:
          service:
            name: echoserver
            port:
              number: 80

则可以使用如下命令进行测试 curl 192.168.1.10/echoserver -H "Host: http-svc.frognew.com" 但是在集群内部使用curl http-svc.frognew.com/echoserver则无法解析,会报404错误。就是说nginx并不会对其进行解析。我的一个猜想是这个设置应该要在IngressController中进行,而不能只在ingress中设置,不过暂时还未成功。

快速总结 Link to heading

从上述两个实验可以很快速的认识到yaml配置文件中的项目内容。 ingress中配置的实际上是转发的URL,其本质和服务器的router是类似的。对于给定的IP请求,一旦满足指定的router,nginx controller就会将对应的请求发送到指定的服务上,服务通过port收到内容,再通过targetPort将请求投送到pod的指定端口中,完成转发。

host与nip.io Link to heading

如果需要使用host解析的话,正常情况下需要ELB的设置。但是使用nip.io也可以达到类似的效果

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: echoserver
  namespace: echoserver
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  rules:
  - host: echoserver.192.168.1.10.nip.io
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: echoserver
            port:
              number: 80

通过上述的修改后,可以直接在集群外部使用curl echoserver.192.168.1.10.nip.io访问到服务,得到的结果如下(经过jq整理)

{
  "host": {
    "hostname": "echoserver.192.168.1.10.nip.io",
    "ip": "::ffff:10.244.1.201",
    "ips": []
  },
  "http": {
    "method": "GET",
    "baseUrl": "",
    "originalUrl": "/",
    "protocol": "http"
  },
  "request": {
    "params": {
      "0": "/"
    },
    "query": {},
    "cookies": {},
    "body": {},
    "headers": {
      "host": "echoserver.192.168.1.10.nip.io",
      "x-request-id": "7b8b5cd857f5771388cd349d395fe979",
      "x-real-ip": "10.244.0.0",
      "x-forwarded-for": "10.244.0.0",
      "x-forwarded-host": "echoserver.192.168.1.10.nip.io",
      "x-forwarded-port": "80",
      "x-forwarded-proto": "http",
      "x-scheme": "http",
      "user-agent": "curl/7.63.0",
      "accept": "*/*"
    }
  },
  "environment": {
    "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
    "HOSTNAME": "echoserver-6944fb9c86-btmf8",
    "PORT": "80",
    "KUBERNETES_SERVICE_PORT_HTTPS": "443",
    "KUBERNETES_PORT_443_TCP_PROTO": "tcp",
    "ECHOSERVER_SERVICE_PORT": "80",
    "ECHOSERVER_PORT_80_TCP": "tcp://10.108.58.132:80",
    "ECHOSERVER_PORT_80_TCP_PORT": "80",
    "ECHOSERVER_PORT_80_TCP_PROTO": "tcp",
    "KUBERNETES_SERVICE_HOST": "10.96.0.1",
    "KUBERNETES_PORT_443_TCP_PORT": "443",
    "ECHOSERVER_PORT": "tcp://10.108.58.132:80",
    "KUBERNETES_PORT": "tcp://10.96.0.1:443",
    "KUBERNETES_PORT_443_TCP": "tcp://10.96.0.1:443",
    "KUBERNETES_PORT_443_TCP_ADDR": "10.96.0.1",
    "ECHOSERVER_SERVICE_HOST": "10.108.58.132",
    "ECHOSERVER_PORT_80_TCP_ADDR": "10.108.58.132",
    "KUBERNETES_SERVICE_PORT": "443",
    "NODE_VERSION": "12.19.0",
    "YARN_VERSION": "1.22.5",
    "HOME": "/root"
  }
}