Kubernetes Ingress
一、简介
Service的表现形式为IP:Port,即工作在TCP/IP层。而对于基于HTTP的服务来说,不同的URL地址经常对应到不同的后端服务或者虚拟机,这些应用层的转发机制仅仅通过Kubernetes的Service机制是无法实现的。Kubernetes使用了一个Ingress策略定义和一个具体的Ingress Controller,两者结合并实现了一个完整的Ingress负载均衡器。
在定义Ingress策略之前,需要先部署Ingress Controller,以实现为所有的后端Service都提供一个统一的入口。Ingress Controller需要实现基于不同HTTP URL向后转发的负载分发规则,并可以灵活设置7层分发策略。
Ingress Controller 将以Pod的形式运行,监控API Server 的 ingress接口后端的backend services,如果service发生变化,则Ingress Controller应自动更新其转发规则。
二、创建Ingress Controller 和默认的backend服务
下面使用Nginx来实现一个Ingress Controller,需要实现的基本逻辑如下:
-
监听API Server,获取全部Ingress定义
-
-
执行nginx -s reload命令,重新加载nginx.conf配置文件的内容
(1)新建一个namespace,并为默认的ServiceAccount/default 绑定一个ClusterRole
# kubectl create namespace nginx-ingress
serviceaccount-role.yaml
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: nginx-ingress-lb subjects: - kind: ServiceAccount name: default namespace: nginx-ingress roleRef: kind: ClusterRole name: cluster-admin apiGroup: rbac.authorization.k8s.io
# kubectl create -f serviceaccount-role.yaml
(2)创建backend
为了让Ingress Controller正常启动,还需要配置一个默认的backend,用于客户端访问不存在的URL时返回404应答
default-backend.yaml
apiVersion: v1 kind: Service metadata: name: default-http-backend namespace: nginx-ingress labels: k8s-app: default-http-backend spec: ports: - port: 80 targetPort: 8080 selector: k8s-app: default-http-backend --- apiVersion: apps/v1 kind: Deployment metadata: name: default-http-backend labels: k8s-app: default-http-backend namespace: nginx-ingress spec: replicas: 1 selector: matchLabels: k8s-app: default-http-backend template: metadata: labels: k8s-app: default-http-backend spec: terminationGracePeriodSeconds: 60 containers: - name: default-http-backend image: chenliujin/defaultbackend livenessProbe: httpGet: path: /healthz port: 8080 scheme: HTTP initialDelaySeconds: 30 timeoutSeconds: 5 readinessProbe: httpGet: path: /healthz port: 8080 scheme: HTTP initialDelaySeconds: 30 timeoutSeconds: 5 ports: - containerPort: 8080 resources: limits: cpu: 10m memory: 20Mi requests: cpu: 10m memory: 20Mi
# kubectl create -f default-backend.yaml
(3)创建Ingress Controller
nginx-ingress-controller-daemonset.yaml
apiVersion: apps/v1 kind: DaemonSet metadata: name: nginx-ingress-lb labels: name: nginx-ingress-lb namespace: nginx-ingress spec: selector: matchLabels: name: nginx-ingress-lb template: metadata: labels: name: nginx-ingress-lb spec: terminationGracePeriodSeconds: 60 containers: - name: nginx-ingress-lb image: siriuszg/nginx-ingress-controller readinessProbe: httpGet: path: /healthz port: 10254 scheme: HTTP initialDelaySeconds: 10 periodSeconds: 5 timeoutSeconds: 10 livenessProbe: httpGet: path: /healthz port: 10254 scheme: HTTP initialDelaySeconds: 10 periodSeconds: 5 timeoutSeconds: 10 ports: - containerPort: 80 hostPort: 80 - containerPort: 443 hostPort: 443 env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace args: - /nginx-ingress-controller - --default-backend-service=$(POD_NAMESPACE)/default-http-backend
# kubectl create -f nginx-ingress-controller-daemonset.yaml
(4)查看
# kubectl get pods -n nginx-ingress NAME READY STATUS RESTARTS AGE default-http-backend-5bd785fcbc-jmg5f 1/1 Running 0 35m nginx-ingress-lb-svfw2 1/1 Running 0 36m nginx-ingress-lb-xkvc6 1/1 Running 0 36m nginx-ingress-lb-zs6bk 1/1 Running 0 36m
(5)验证
用curl访问任意node的80端口,验证nginx-ingress-controller和default-http-backend服务正常工作
# curl node1 default backend - 404
三、定义Ingress策略
部署一个应用,通过ingress策略转发获取web信息
(1)mysql-deployment.yaml
apiVersion: v1 kind: Service metadata: name: mysql namespace: nginx-ingress spec: selector: app: mysql ports: - port: 3306 targetPort: 3306 --- apiVersion: apps/v1 kind: Deployment metadata: name: mysql labels: app: mysql namespace: nginx-ingress spec: selector: matchLabels: app: mysql replicas: 1 template: metadata: labels: app: mysql spec: containers: - name: mysql image: mysql:5.6 imagePullPolicy: IfNotPresent ports: - containerPort: 3306 env: - name: MYSQL_ROOT_PASSWORD value: "123456"
(2)webapp-deployment.yaml
apiVersion: v1 kind: Service metadata: name: webapp namespace: nginx-ingress spec: selector: app: webapp ports: - port: 8080 targetPort: 8080 --- apiVersion: apps/v1 kind: Deployment metadata: name: webapp namespace: nginx-ingress labels: app: webapp spec: selector: matchLabels: app: webapp replicas: 2 template: metadata: labels: app: webapp spec: containers: - name: tomcat-webapp image: kubeguide/tomcat-app:v1 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 env: - name: MYSQL_SERVICE_HOST value: "mysql" - name: MYSQL_SERVICE_PORT value: "3306"
(3)webapp-ingress.yaml
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: mywebsite-ingress namespace: nginx-ingress spec: rules: - host: mywebsite.com http: paths: - path: /demo backend: serviceName: webapp servicePort: 8080
(4)查看ingress
# kubectl get ingress -n nginx-ingress -o wide NAME CLASS HOSTS ADDRESS PORTS AGE mywebsite-ingress <none> mywebsite.com 192.168.10.106,192.168.10.107,192.168.10.108 80 28m
登入任意一个nginx-ingress-controller,查看nginx.conf
server { server_name mywebsite.com ; listen 80 ; listen 443 ssl http2 ; set $proxy_upstream_name "-"; ssl_certificate_by_lua_block { certificate.call() } location /demo { set $namespace "nginx-ingress"; set $ingress_name "mywebsite-ingress"; set $service_name "webapp"; set $service_port "8080"; set $location_path "/demo"; .....
(5)访问客户端
# curl -H 'Host:mywebsite.com' http://192.168.10.106/demo/ <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>HPE University Docker&Kubernetes Learning</title> </head> <body align="center"> <h2>Congratulations!!</h2> <br></br> <input type="button" value="Add..." onclick="location.href='input.html'" > <br></br> <TABLE align="center" border="1" width="600px"> ...
(6)外部浏览器访问
修改本机hosts文件
192.168.10.108 mywebsite.com