Ingress是k8s的一个资源对象,作为一个集群服务的入口,用于管理对集群中服务的外部访问。
可以将Ingress配置为提供服务外部访问的URL,负载均衡,绑定SSL / TLS,并提供基于名称的虚拟主机。
作为集群服务的入口,Ingress类似一个代理,处于多个service的前端,不会公开任意端口或协议,通常会作为HTTP(s)负载均衡器转发http(s)流量。而要将HTTP和HTTPS以外的服务公开到Internet时,通常使用NodePort或 LoadBalancer 类型的服务。
为了使Ingress正常工作,集群必须运行一个Ingress Controller。Ingress Controller是一个部署为Kubernetes Pod的守护程序,它监视apiserver的ingresses endpoint 以获取对Ingress 资源的更新。k8s支持多个ingress controller,这里仅介绍使用ingress nginx。
ingress-nginx是围绕Ingress构建的,使用ConfigMap存储NGINX配置,会动态生效ingress中定义的规则。
ingress-nginx部署:
# 安装 先部署后端service:hostnamev1,hostnamev2,app # cat hostnamev1-demo.yaml 部署http-ingress做代理 # kubectl explain ingress.spec.rules describe ingress看下对应关系 # kubectl get ingress 访问测试 # curl www.xlbubble.xyz ingress-nginx rewrite转发 # kubectl edit ingress http-ingress 参数解释: 大致意思就是将/app(/|$)(.*)重写为/$2,如/app--> /,/app/zoneinfo--> /zoneinfo。 ingress-nginx控制器中的nginx配置文件,可以看到有写入对应的nginx配置 # kubectl exec -n ingress-nginx -it nginx-ingress-controller-568867bf56-ghvvv  bash 给hostnamev1配置https # 创建secret,我这里用的是腾讯云的域名+证书,没有证书可以自己生成。 访问测试 # curl https://www.xlbubble.xyz -I
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml
# 查看
kubectl get pods -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx -w 
# 查看ingress-nginx版本
POD_NAMESPACE=ingress-nginx
POD_NAME=$(kubectl get pods -n $POD_NAMESPACE -l app.kubernetes.io/name=ingress-nginx -o jsOnpath='{.items[0].metadata.name}')
kubectl exec -it $POD_NAME -n ingress-nginx -- /nginx-ingress-controller --version
# 创建ingress-ingress的service,service给ingress提供ip和代理ingress端口映射,这里直接使用的是官方的yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/baremetal/service-nodeport.yaml
# kubectl get svc -n ingress-nginx
NAME            TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx   NodePort   10.10.150.34   Ingress 实践
apiVersion: v1
kind: Service
metadata:
    name: hostnamev1
    namespace: default
spec:
    selector:
        demo: hostnamev1
        release: canary
    ports:
    - name: http
      port: 80
      targetPort: 8000
---
apiVersion: apps/v1
kind: Deployment
metadata:
    name: hostnamev1-deploy
    namespace: default
spec:
    replicas: 2 
    selector:
        matchLabels:
            demo: hostnamev1
            release: canary
    template:   
        metadata:
            labels:
                demo: hostnamev1
                release: canary
        spec:
            containers:
            - name: hostnamev1
              image: xlbubble/hostname:1.0
              ports:
              - name: http
                containerPort: 8000
# hostnamev2-demo.yaml
apiVersion: v1
kind: Service
metadata:
    name: hostnamev2
    namespace: default
spec:
    selector:
        demo: hostnamev2
        release: canary
    ports:
    - name: http
      port: 80
      targetPort: 8000
---
apiVersion: apps/v1
kind: Deployment
metadata:
    name: hostnamev2-deploy
    namespace: default
spec:
    replicas: 2 
    selector:
        matchLabels:
            demo: hostnamev2
            release: canary
    template:   
        metadata:
            labels:
                demo: hostnamev2
                release: canary
        spec:
            containers:
            - name: hostnamev2
              image: xlbubble/hostname:2.0
              ports:
              - name: http
                containerPort: 8000
# cat app-demo.yaml
apiVersion: v1
kind: Service
metadata:
    name: app
    namespace: default
spec:
    selector:
        demo: app
    ports:
    - name: http
      port: 8080
      targetPort: 8080
---
apiVersion: v1
kind: Pod
metadata:
    name: app
    namespace: default
    labels:
        demo: app
spec:
    containers:
    - name: app
      image: tomcat:9.0.30-jdk8-openjdk-slim
      ports:
      - name: http
        containerPort: 8080
# kubectl apply -f hostnamev1-demo.yaml
# kubectl apply -f hostnamev2-demo.yaml
# kubectl apply -f app-demo.yaml
# cat http-ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
    name: http-ingress
    namespace: default
    annotations:
        kubernetes.io/ingress.class: 'nginx'
spec:
    rules: # 定义后端转发规则
    - host: www.xlbubble.xyz # 通过www域名进行转发
      http:
          paths: 
          - path: # 配置访问路径
            backend: # 配置后端服务
                serviceName: hostnamev1 # 绑定后端service hostnamev1
                servicePort: 80 # 指定service端口
          - path: /app
            backend:
                serviceName: app
                servicePort: 8080
    - host: test.xlbubble.xyz
      http:
          paths:
          - path:
            backend:
                serviceName: hostnamev2
                servicePort: 80
# kubectl apply -f http-ingress.yaml
NAME           HOSTS                                ADDRESS        PORTS   AGE
http-ingress   www.xlbubble.xyz,test.xlbubble.xyz   10.10.150.34   80      14m
# kubectl get pods -o wide
NAME                                 READY   STATUS    RESTARTS   AGE    IP           
app                                  1/1     Running   0          34m    10.244.2.56   
hostnamev1-deploy-cd74d7fbd-82k4q    1/1     Running   0          106m   10.244.2.53   
hostnamev1-deploy-cd74d7fbd-lmr6m    1/1     Running   0          106m   10.244.1.55   
hostnamev2-deploy-759d846c95-k7ckn   1/1     Running   0          61m    10.244.1.56   
hostnamev2-deploy-759d846c95-q9xf9   1/1     Running   0          61m    10.244.2.54   
# kubectl describe ingress http-ingress
Name:             http-ingress
Namespace:        default
Address:          10.10.150.34
Default backend:  default-http-backend:80 (
Rules: # ingress配置规则
  Host               Path  Backends
  ----               ----  --------
  www.xlbubble.xyz   
                            hostnamev1:80 (10.244.1.55:8000,10.244.2.53:8000)
                     /app   app:8080 (10.244.2.56:8080)
  test.xlbubble.xyz  
                        hostnamev2:80 (10.244.1.56:8000,10.244.2.54:8000)
... Version: 1.0 | hostnamev1-deploy-cd74d7fbd-82k4q 
# curl test.xlbubble.xyz Version: 2.0 | hostnamev2-deploy-759d846c95-k7ckn 
# 访问app 404,这里访问www.xlbubble.xyz/app会默认转发到后端10.244.2.56:8080/app上,也就是带着路径转发,如果要直接转发到10.244.2.56:8080,需要额外配置,见下文ingress-nginx rewrite转发
# curl www.xlbubble.xyz/app -I 
HTTP/1.1 404 
Server: openresty/1.15.8.2
Date: Fri, 03 Dec 2019 04:10:38 GMT
Content-Type: text/html;charset=utf-8
Connection: keep-alive
Vary: Accept-Encoding
Content-Language: en
#
...
    annotations:
        kubernetes.io/ingress.class: 'nginx'
        nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
    rules:
    - host: www.xlbubble.xyz
      http:
          paths:
          - path:
            backend:
                serviceName: hostnamev1
                servicePort: 80
          - path: /app(/|$)(.*)
            backend:
                serviceName: app
                servicePort: 8080
# 访问测试,访问www.xlbubble.xyz/app转发到了10.244.2.56:8080/
# curl www.xlbubble.xyz/app -I
HTTP/1.1 200 
Server: openresty/1.15.8.2
Date: Fri, 03 Dec 2019 09:43:49 GMT
Content-Type: text/html;charset=UTF-8
Connection: keep-alive
Vary: Accept-Encoding
nginx.ingress.kubernetes.io/rewrite-target: /$2:必须将流量重定向到的目标URI(/$2),$2表示第二个参数,就下面这第二个括号里的
path: /app(/|$)(.*):(.*)中的所有参数都将传给$2
$ cat nginx.conf
  ...
   ## start server_  # ingress-nginx默认配置
   ...
   ## end server_
    ## start server test.xlbubble.xyz
server {
server_name test.xlbubble.xyz ;
listen 80  ;
listen 443  ssl http2 ; # 已经配置了ssl,就差http-ingress.yaml中配置和挂载ssl证书了
set $proxy_upstream_name "-";
ssl_certificate_by_lua_block {
certificate.call()
}
location / {  # http-ingress中定义的配置
set $namespace      "default";
set $ingress_name   "http-ingress";
set $service_name   "hostnamev2";
set $service_port   "80";
set $location_path  "/";
...
}
}
## end server test.xlbubble.xyz
## start server www.xlbubble.xyz
server {
server_name www.xlbubble.xyz ;
listen 80  ;
listen 443  ssl http2 ;
set $proxy_upstream_name "-";
ssl_certificate_by_lua_block {
certificate.call()
}
location /app {
set $namespace      "default";
set $ingress_name   "http-ingress";
set $service_name   "app";
set $service_port   "8080";
set $location_path  "/app";
...
}
location / {
set $namespace      "default";
set $ingress_name   "http-ingress";
set $service_name   "hostnamev1";
set $service_port   "80";
set $location_path  "/";
...
}
}
## end server www.xlbubble.xyz
kubectl create secret tls tomcat-ingress-secret --cert=1_www.xlbubble.xyz_bundle.crt --key=2_www.xlbubble.xyz.key
# cat http-ingress-tls.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
    name: http-ingress
    namespace: default
    annotations:
        kubernetes.io/ingress.class: 'nginx'
spec:
    tls: # 配置ssl证书
    - hosts: 
      - www.xlbubble.xyz # 指定证书域名
      secretName: http-ingress-secret # 绑定证书
    rules:
    - host: www.xlbubble.xyz
      http:
          paths:
          - path: 
            backend:
                serviceName: hostnamev1
                servicePort: 80
HTTP/1.1 200 OK
Server: openresty/1.15.8.2
Date: Fri, 03 Dec 2019 11:01:03 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 59
Connection: keep-alive
Strict-Transport-Security: max-age=15724800; includeSubDomains
X-Powered-By: Express
ETag: W/"3b-mLuijDfag/PvLxTOq9nzeLxp0gQ"
# http访问发现,ingress-nginx自动配置了http跳转https
# curl www.xlbubble.xyz -I
HTTP/1.1 308 Permanent Redirect
Server: openresty/1.15.8.2
Date: Fri, 03 Dec 2019 11:16:32 GMT
Content-Type: text/html
Content-Length: 177
Connection: keep-alive
Location: https://www.xlbubble.xyz/