去年整理过一篇《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中:
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-svckubectl 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 36s2.使用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: 80kubectl 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: 80kubectl 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 15mcurl 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"。 (更新:ingress-nginx更新的版本中改用nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"代替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> ......