:TLS配置,目前仅支持通过默认端口443提供服务;如果要配置指定的列表成员指向了不同的主机,则必须通过SNI TLS扩展机制来支持此功能
backend对象的定义由两个必选的内嵌字段组成:serviceName和servicePort,分别用于指定流量转发的后端目标service资源的名称和端口。
spec : backend : serviceName : <string> servicePort : <string>
rules对象由一系列配置Ingress资源的host规则组成,这些host规则用于将一个主机上的某个URL路径映射至相关的后端service对象,它的格式如下:
spec : rules : - host : <string> http : paths : - path : <string> backend : serviceName : <string> servicePort : <string>
注意:.spec.rules.host属性值目前不支持使用IP地址,也不支持地址后面跟端口格式的地址,而且此字段留空表示通配所有的主机名。在K8S 1.18版本中path字段加入了新的内嵌字段,具体使用方式可以参考官方文档,且host字段支持使用IP地址
tls对象由两个内嵌字段组成:hosts和secretName。仅在定义TLS主机的转发规则时才需要定义此类对象
spec : tls : hosts : <[] string > secretName : <string>
Ingress资源类型
基于HTTP暴漏的每个Service资源均可发布于一个独立的FQDN的主机名之上,如www.ilinux.io;也可以发布某主机的URL路径之上,从而将他们整合到一个web站点,如www.ilinux.io/grafana。至于是否需要发布为HTTPS类型的应用则取决于用户的业务需求
单Service资源型Ingress
暴露单个服务的方法有很多种,如服务类型中的Nodeport、LoadBalancer等,不过,一样可以考虑使用Igress来暴露服务,此时只需要为Ingress指定”default backend”即可。例如下面的配置
apiVersion : extensions / v1beta1 kind : Ingress metadata : name : my - ingress spec : backend : serviceName : my - svc servicePort : 80
Ingress控制器会为其分配一个IP地址介入请求流量,并将请求流量转至示例中的my-svc的后端Pod资源
基于URL路径进行流量分发
垂直拆分或微服务架构中,每个小的应用都有其专用的Service资源暴露服务,但在对外开放的站点上,它们可能是财经、新闻、电商、无线端或API接口等一类的独立应用,可通过主域名的URL路径分别接入,例如,www.ilinux.io/api、www.ilinux.io/wap等,用于发布集群内名称为api和wap的service资源。于是,可对应的创建一个如下的Ingress资源,它将对www.ilinux.io/api的请求统统转发至API Service资源,将对www.ilinux.io/wap的请求转发至wap service资源
apiVersion : extensions / v1beta1 kind : Ingress metadata : name : test annotations : nginx . ingress . kubernetes . io / rewrite - taget : / spec : rules : - host : www . ilinux . io http : paths : - backend : serviceName : myapp - svc - api servicePort : 80 path : / api - backend : serviceName : myapp - svc - wap servicePort : 80 path : / wap
基于主机名称的Ingress资源
上面的类型中的需求,也可以将每个应用分别以独立的FQDN主机名进行输出,如wap.ilinux.io和api.ilinux.io。这两个主机名能够被DNS所解析,并且解析到external LB的IP地址之上,分别用于发布集群内部的wap和api这两个Service资源。这种实现方案类似于web站点中的“基于域名的虚拟主机”,将多个FQDN解析至同一个IP地址,然后根据主机头进行转发。下面是一个独立FQDN主机形式发布服务的Ingress资源示例
apiVersion : extensions / v1beta1 kind : Ingress metadata : name : test spec : rules : - host : api . ilinux . io http : paths : - backend : serviceName : api servicePort : 80 - host : wap . ilinux . io http : paths : - backend : serviceName : wap servicePort : 80
TLS类型的Ingress资源
这种类型用于以HTTPS发布Service资源,基于一个含有私钥和证书的secret对象即可配置TLS协议的Ingress资源,目前来说,Ingress资源仅支持单TLS端口,并且还会卸载TLS会话。在Ingress资源中引用此secret即可让Ingress控制器加载并配置为HTTPS服务
关于TLS类型的会在后面详细讲到
apiVersion : extensions / v1beta1 kind : Ingress metadata : name : no - rules - map spec : tls : - secretName : ikubernetesSecret backend : serviceName : homesite servicePort : 80
Ingress 控制器
官网:https://kubernetes.io/zh/docs/concepts/services-networking/ingress-controllers/
为了能够让Ingress资源正常工作,集群内部必须有一个正在运行的Ingress控制器。而且Ingress控制器自身也是运行于Pod中的容器应用,一般可以是nginx或者envoy等一类的具有代理及负载均衡功能的守护进程,它监视着来自于API Server的Ingress对象状态,并以其规则生成相应的应用程序专有的格式的配置文件并通过重载或重启守护进程而使配置生效。例如,对于Nginx来说,Ingress规则需要转换为Nginx的配置信息。简单来说,Ingress控制器其实就是托管于K8S系统之上的用于实现在应用层发布服务的Pod资源,它将跟踪Ingress资源并实时生成配置规则。与作为 kube-controller-manager 可执行文件的一部分运行的其他类型的控制器不同,Ingress 控制器不是随集群自动启动的。通常我们需要单独安装它,才能使用。
同样运行为Pod资源的Ingress控制器进程又该如何接入外部的请求流量呢?常用的解决方案有如下两种
以Deployment控制器管理Ingress控制器的Pod资源,并通过NodePort或LoadBalancer类型的service对象为其接入集群外部的请求流量,这就意味着,定义一个Ingress控制器时,必须在其前端定义一个专用的service资源。如下图 借助于DaemonSet控制器,将Ingress控制器的Pod资源以单一实例的方式运行于集群的所有或部分工作节点之上,并配置这类Pod对象以hostPort或hostNetwork的方式在当前节点接入外部流量。如下图
以ingress-nginx项目为例子,部署ingress Nginx控制的配置文件被切割存放在了多个不同的文件中,并集中存放于其源码deploy子目录下,同时,为了方便用户部署,它还将所有需要的资源全部集成为一个配置文件mandatory.yaml
站点:https://github.com/kubernetes/ingress-nginx/tree/nginx-0.17.0/deploy
注意:因为有两个Deployment控制器,我们需要确保能够正常拉取到它所需要的镜像,如果无法拉取到请自行修改为可以拉取到镜像的地址。我这里只需要修改第一个deployement的镜像地址docker.io/chenliujin/defaultbackend:1.4第二个镜像地址我可以正常访问,所以无需更换
当然也可以使用更新版本的ingress 控制器
--- apiVersion : v1 kind : Namespace metadata : name : ingress - nginx --- apiVersion : apps / v1 kind : Deployment metadata : name : default - http - backend labels : app : default - http - backend namespace : ingress - nginx spec : replicas : 1 selector : matchLabels : app : default - http - backend template : metadata : labels : app : default - http - backend spec : terminationGracePeriodSeconds : 60 containers : - name : default - http - backend # Any image is permissible as long as: # 1. It serves a 404 page at / # 2. It serves 200 on a /healthz endpoint image : docker . io / chenliujin / defaultbackend : 1.4 livenessProbe : 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 --- apiVersion : v1 kind : Service metadata : name : default - http - backend namespace : ingress - nginx labels : app : default - http - backend spec : ports : - port : 80 targetPort : 8080 selector : app : default - http - backend --- kind : ConfigMap apiVersion : v1 metadata : name : nginx - configuration namespace : ingress - nginx labels : app : ingress - nginx --- kind : ConfigMap apiVersion : v1 metadata : name : tcp - services namespace : ingress - nginx --- kind : ConfigMap apiVersion : v1 metadata : name : udp - services namespace : ingress - nginx --- apiVersion : v1 kind : ServiceAccount metadata : name : nginx - ingress - serviceaccount namespace : ingress - nginx --- apiVersion : rbac . authorization . k8s . io / v1beta1 kind : ClusterRole metadata : name : nginx - ingress - clusterrole rules : - apiGroups : - "" resources : - configmaps - endpoints - nodes - pods - secrets verbs : - list - watch - apiGroups : - "" resources : - nodes verbs : - get - apiGroups : - "" resources : - services verbs : - get - list - watch - apiGroups : - "extensions" resources : - ingresses verbs : - get - list - watch - apiGroups : - "" resources : - events verbs : - create - patch - apiGroups : - "extensions" resources : - ingresses / status verbs : - update --- apiVersion : rbac . authorization . k8s . io / v1beta1 kind : Role metadata : name : nginx - ingress - role namespace : ingress - nginx rules : - apiGroups : - "" resources : - configmaps - pods - secrets - namespaces verbs : - get - apiGroups : - "" resources : - configmaps resourceNames : # Defaults to "<election-id>-<ingress-class>" # Here: "<ingress-controller-leader>-<nginx>" # This has to be adapted if you change either parameter # when launching the nginx-ingress-controller. - "ingress-controller-leader-nginx" verbs : - get - update - apiGroups : - "" resources : - configmaps verbs : - create - apiGroups : - "" resources : - endpoints verbs : - get --- apiVersion : rbac . authorization . k8s . io / v1beta1 kind : RoleBinding metadata : name : nginx - ingress - role - nisa - binding namespace : ingress - nginx roleRef : apiGroup : rbac . authorization . k8s . io kind : Role name : nginx - ingress - role subjects : - kind : ServiceAccount name : nginx - ingress - serviceaccount namespace : ingress - nginx --- apiVersion : rbac . authorization . k8s . io / v1beta1 kind : ClusterRoleBinding metadata : name : nginx - ingress - clusterrole - nisa - binding roleRef : apiGroup : rbac . authorization . k8s . io kind : ClusterRole name : nginx - ingress - clusterrole subjects : - kind : ServiceAccount name : nginx - ingress - serviceaccount namespace : ingress - nginx --- apiVersion : apps / v1 kind : Deployment metadata : name : nginx - ingress - controller namespace : ingress - nginx spec : replicas : 1 selector : matchLabels : app : ingress - nginx template : metadata : labels : app : ingress - nginx annotations : prometheus . io / port : '10254' prometheus . io / scrape : 'true' spec : serviceAccountName : nginx - ingress - serviceaccount containers : - name : nginx - ingress - controller image : quay . io / kubernetes - ingress - controller / nginx - ingress - controller : 0.17 . 0 args : - / nginx - ingress - controller - -- default - backend - service = $ ( POD_NAMESPACE )/ default - http - backend - -- configmap = $ ( POD_NAMESPACE )/ nginx - configuration - -- tcp - services - configmap = $ ( POD_NAMESPACE )/ tcp - services - -- udp - services - configmap = $ ( POD_NAMESPACE )/ udp - services - -- publish - service = $ ( POD_NAMESPACE )/ ingress - nginx - -- annotations - prefix = nginx . ingress . kubernetes . io securityContext : capabilities : drop : - ALL add : - NET_BIND_SERVICE # www-data -> 33 runAsUser : 33 env : - name : POD_NAME valueFrom : fieldRef : fieldPath : metadata . name - name : POD_NAMESPACE valueFrom : fieldRef : fieldPath : metadata . namespace ports : - name : http containerPort : 80 - name : https containerPort : 443 livenessProbe : failureThreshold : 3 httpGet : path : / healthz port : 10254 scheme : HTTP initialDelaySeconds : 10 periodSeconds : 10 successThreshold : 1 timeoutSeconds : 1 readinessProbe : failureThreshold : 3 httpGet : path : / healthz port : 10254 scheme : HTTP periodSeconds : 10 successThreshold : 1 timeoutSeconds : 1
上述文件修改完成之后,创建Ingress控制器
[ root@k8s - master01 ingress ]# kubectl apply - f mandatory . yaml namespace / ingress - nginx created deployment . apps / default - http - backend created service / default - http - backend created configmap / nginx - configuration created configmap / tcp - services created configmap / udp - services created serviceaccount / nginx - ingress - serviceaccount created clusterrole . rbac . authorization . k8s . io / nginx - ingress - clusterrole created role . rbac . authorization . k8s . io / nginx - ingress - role created rolebinding . rbac . authorization . k8s . io / nginx - ingress - role - nisa - binding created clusterrolebinding . rbac . authorization . k8s . io / nginx - ingress - clusterrole - nisa - binding created deployment . apps / nginx - ingress - controller created [ root@k8s - master01 ingress ]#
如果我们在执行这个资源列表前已经手动将镜像拉取下来了,那么可以直接使用kubectl get命令查看相关资源,如果没有拉取下来,则会自动下载相关镜像,但是需要一定的时间,所以Pod资源的创建需要等待一段才能完成,具体多长时间还是取决于网络状况,所以这里还是推荐先手动把镜像拉取下来。我们可以使用如下命令监控创建过程。待其状态为”Running”之后表示运行正常
[ root@k8s - master01 ingress ]# kubectl get pods - n ingress - nginx -- watch NAME READY STATUS RESTARTS AGE default - http - backend - c8c565f69 - 9nlvg 1 / 1 Running 0 3m43s nginx - ingress - controller - 5758bfd5fc - b5chq 1 / 1 Running 0 3m42s
上面的配置清单中采用的是基于Deployment控制器部署Ingress Nginx的方式,因此接入外部流量之前还需要手动为其创建相关的NodePort或Loadbalancer类型的service资源对象。下面的配置清单中定义了类型Nodeport类型的service资源,并明确指定了clusterIP和一个比较容易记忆的端口
apiVersion : v1 kind : Service metadata : name : nginx - ingress - controller namespace : ingress - nginx spec : type : NodePort clusterIP : 10.99 . 88.88 ports : - port : 80 name : http nodePort : 10080 - port : 443 name : https nodePort : 10443 selector : app : ingress - nginx
将上面的内容保存到文件nginx-ingress-service.yaml中,然后再创建service资源。
注意: 其标签选择器应该与mandatory.yaml配置清单中的Deployment控制器nginx-ingress-controller的选择器保持一致
[ root@k8s - master01 ingress ]# kubectl apply - f nginx - ingress - service . yaml service / nginx - ingress - controller created [ root@k8s - master01 ingress ]#
确认service对象nginx-ingress-controller的状态没有问题后即可于集群外部对其发起访问测试。目标URL为http://:10080或者http://:10443,确认可接收到响应报文后即表示ingress nginx部署完成;不过,本示例中尚且缺少一个可用的外部负载均衡器。因此,访问测试只能使用http://:进行
[ root@k8s - master01 ingress ]# kubectl get svc - n ingress - nginx NAME TYPE CLUSTER - IP EXTERNAL - IP PORT ( S ) AGE default - http - backend ClusterIP 10.99 . 194.137 < none > 80 / TCP 52m nginx - ingress - controller NodePort 10.99 . 88.88 < none > 80 : 10080 / TCP , 443 : 10443 / TCP 8m16s [ root@k8s - master01 ingress ]# [ root@k8s - master01 ingress ]# #因为我们这边没有后端应用服务,所以访问会报错 [ root@k8s - master01 ingress ]# curl http :// 172.18 . 15.114 : 10080 default backend - 404 [ root@k8s - master01 ingress ]# [ root@k8s - master01 ingress ]#
案例
发布一个tomcat应用
建设有这样一套环境,K8S集群上的tomcat-deploy控制器生成了两个运行于Pod资源中的tomcat副本,tomcat-svc是将它们统一暴露于集群中的访问入口。现在需要通过Ingress资源将tomcat-svc发布给集群外部的客户端访问。具体的需求如下图
为了便于理解,下面的测试操作过程把每一步都分解开进行
准备名称空间
本示例当中的所有资源都位于testing名称空间中,与其他的资源在逻辑上进行隔离,以方便管理。下面的配置信息保存在tomcat-testing-ns.yaml资源清单文件中
apiVersion : v1 kind : Namespace metadata : name : testing labels : env : testing
[ root@k8s - master01 tomcat ]# kubectl apply - f tomcat - testing - ns . yaml namespace / testing created [ root@k8s - master01 tomcat ]# [ root@k8s - master01 tomcat ]# kubectl get ns NAME STATUS AGE default Active 35d ingress - nginx Active 17h kube - node - lease Active 35d kube - public Active 35d kube - system Active 35d testing Active 43s [ root@k8s - master01 tomcat ]# kubectl get ns testing NAME STATUS AGE testing Active 50s [ root@k8s - master01 tomcat ]#
部署tomcat实例
在此示例中,tomcat应用本身代表着运行于tomcat容器的一个应用程序,这个应用程序通常应该包含了某应用程序的war文件的镜像文件。下面的配置清单中使用了Deployment控制器部署了2个tomcat的Pod应用,并且名称空间属于testing。它保存于tomcat-testing-deploy.yaml文件中
apiVersion : apps / v1 kind : Deployment metadata : name : tomcat - deploy namespace : testing labels : app : tomcat spec : replicas : 2 selector : matchLabels : app : tomcat template : metadata : labels : app : tomcat spec : containers : - image : docker . io / tomcat : 8.5 . 56 - jdk14 - openjdk - oracle imagePullPolicy : IfNotPresent name : tomcat ports : - containerPort : 8080 name : httpport - containerPort : 8009 name : ajpport lifecycle : postStart : exec : command : [ "/bin/sh" , "-c" , "echo '健哥说非要echo一个页面,不然就是搞学问不严谨,哈哈哈哈' > /usr/local/tomcat/webapps/aaa/a.txt" ]
资源清单配置文件配置完成后使用kubectl apply命令创建deployment。如果需要更多的Pod资源承载用户访问,那么使用deployment控制器的规模伸缩机制即可完成,或者直接修改上面的配置文件中的replicas然后执行kubectl apply命令重新进行应用
[ root@k8s - master01 tomcat ]# kubectl apply - f tomcat - testing - deploy . yaml deployment . apps / tomcat - deploy created [ root@k8s - master01 tomcat ]# [ root@k8s - master01 tomcat ]# kubectl get pods - n testing NAME READY STATUS RESTARTS AGE tomcat - deploy - 778769699c - jcptt 0 / 1 ContainerCreating 0 14s tomcat - deploy - 778769699c - nfxxb 0 / 1 ContainerCreating 0 14s [ root@k8s - master01 tomcat ]# kubectl get pods - n testing NAME READY STATUS RESTARTS AGE tomcat - deploy - 778769699c - jcptt 1 / 1 Running 0 58s tomcat - deploy - 778769699c - nfxxb 1 / 1 Running 0 58s [ root@k8s - master01 tomcat ]#
创建Service资源
Ingress资源仅通过Service资源识别相应的Pod资源,获取其IP地址和端口,而后Ingress控制器即可直接使用各Pod对象的IP地址与它直接进行通信,而无需经由Service资源的代理和调度。因此Service资源的ClusterIP对Ingress控制器来说并不起作用。不过,若集群内的其他Pod客户端需要与其通信,那么保留ClusterIP地址也是很有必要的。
下面的配置文件中定义了Service资源的tomcat-testing-svc,它通过标签选择器将相关的Pod资源对象归于一组,并通过80/TCP端口暴露Pod资源的8080/TCP端口。如果还需要暴露8009/TCP端口,那么只需要将其以类似的格式配置在列表中即可。将如下内容保存到tomcat-testing-svc.yaml文件中
apiVersion : v1 kind : Service metadata : name : tomcat - testing - svc namespace : testing labels : app : tomcat - svc spec : selector : app : tomcat ports : - name : http port : 80 targetPort : 8080 protocol : TCP - name : ajp port : 8009 targetPort : 8009 protocol : TCP
资源清单文件配置完成之后即可创建service
[ root@k8s - master01 tomcat ]# kubectl apply - f tomcat - testing - svc . yaml service / tomcat - testing - svc created [ root@k8s - master01 tomcat ]# #查看svc资源,可以看到两个tomcat已经被关联到了该service资源,并且我们为该service资源定义了一个静态的IP地址,目的是如果集群内部有其他Pod资源可以直接使用该Servie地址进行通信 [ root@k8s - master01 tomcat ]# kubectl get svc - n testing NAME TYPE CLUSTER - IP EXTERNAL - IP PORT ( S ) AGE tomcat - testing - svc ClusterIP 10.99 . 85.85 < none > 80 / TCP , 8009 / TCP 46s [ root@k8s - master01 tomcat ]# [ root@k8s - master01 tomcat ]# kubectl describe svc tomcat - testing - svc - n testing Name : tomcat - testing - svc Namespace : testing Labels : app = tomcat - svc Annotations : kubectl . kubernetes . io / last - applied - configuration : { "apiVersion" : "v1" , "kind" : "Service" , "metadata" :{ "annotations" :{}, "labels" :{ "app" : "tomcat-svc" }, "name" : "tomcat-testing-svc" , "namespace" : "te... Selector: app=tomcat Type: ClusterIP IP: 10.99.85.85 Port: http 80/TCP TargetPort: 8080/TCP Endpoints: 10.244.38.5:8080,10.244.59.6:8080 Port: ajp 8009/TCP TargetPort: 8009/TCP Endpoints: 10.244.38.5:8009,10.244.59.6:8009 Session Affinity: None Events: <none> [root@k8s-master01 tomcat]#
创建Ingress资源
通过Ingress资源的FQDN主机名或URL路径等类型发布的服务,只要用户的访问请求能够匹配到其.spec.rules.host字段定义的主机时才能被相应的规则处理。如果要明确匹配用户的处理请求,比如希望将那些发往tomcat.ilinux.io主机的所有请求代理至tomcat-testing-svc资源的后端Pod,则可以使用如下命令配置文件中的内容。将如下内容保存到tomcat-testing-ingress.yaml文件中
apiVersion : extensions / v1beta1 kind : Ingress metadata : name : tomcat namespace : testing annotations : kubernetes . io / ingress . class : "nginx" spec : rules : - host : tomcat . ilinux . io http : paths : - backend : serviceName : tomcat - testing - svc servicePort : 80
资源清单文件配置文成之后执行创建ingress资源
[ root@k8s - master01 tomcat ]# kubectl apply - f tomcat - testing - ingress . yaml ingress . extensions / tomcat created [ root@k8s - master01 tomcat ]#
Ingress资源创建完成之后,通过详细信息确认是否成功创建,并且确认是否正确关联到了对应的service资源
[ root@k8s - master01 tomcat ]# kubectl describe ingress - n testing Name : tomcat Namespace : testing Address : Default backend : default - http - backend : 80 (< none >) Rules : Host Path Backends ---- ---- -------- tomcat . ilinux . io tomcat - testing - svc : 80 ( 10.244 . 38.5 : 8080 , 10.244 . 59.6 : 8080 ) Annotations : kubectl . kubernetes . io / last - applied - configuration : { "apiVersion" : "extensions/v1beta1" , "kind" : "Ingress" , "metadata" :{ "annotations" :{ "kubernetes.io/ingress.class" : "nginx" }, "name" : "tomcat" , "namespace" : "testing" }, "spec" :{ "rules" :[{ "host" : "tomcat.ilinux.io" , "http" :{ "paths" :[{ "backend" :{ "serviceName" : "tomcat-testing-svc" , "servicePort" : 80 }}]}}]}} kubernetes . io / ingress . class : nginx Events : Type Reason Age From Message ---- ------ ---- ---- ------- Normal CREATE 113s nginx - ingress - controller Ingress testing / tomcat [ root@k8s - master01 tomcat ]#
接下来就可以通过Ingress 控制器的前端Service资源的NodePort来访问此服务,前面的示例中,该Ingress Controller的Service资源已经被创建出来了,并且IP地址被定义为10.99.88.88,节点端口为10080映射控制器的端口为80。因此,这里使用Ingress中定义的主机名tomcat.ilinux.io即可进行访问。为什么不使用在tomcat案列中的service访问呢?因为该Service的主要作用仅仅是用于关联后端Pod资源
如下图:
我们通过本地浏览器访问tomcat.ilinux.io
不过,用户对tomcat.ilinux.io主机外的地址发起的请求被此Ingress规则匹配到后将被发往Ingress控制器的默认的后端,即default-http-backend,它通常只有一个404的状态提示信息。用户也可以按需自定义默认后端。例如,下面的配置文件片段所示,它通过.spec.backend定义了所有无法由此Ingress匹配到的访问请求都由相应的后端default-svc这个service来处理
spec backend : serviceName : default - svc servicePort : 80
发布TLS类型应用
一般来说,如果有基于HTTPS通信的需求,那么它应该由外部的负载均衡器予以实现,并在SSL会话卸载后将访问请求转发到Ingress控制器。不过,如果外部负载均衡器工作于传输层而不是工作于应用层的反响代理服务器,或者存在直接通过Ingress控制器接收客户端请求的需求,又期望它们能够提供HTTPS服务时,就应该配置TLS类型的Ingress资源
将此类服务公开发布到互联网时,HTTPS服务用到的证书应该是由公信CA签署并颁发。因为是出于测试目的,所以我们直接使用openssl生成自签证书和测试使用的私钥
注意:TLS Secret中包含的证书必须以tls.crt作为其键名,私钥文件必须以tls.key为键名,因此上面生成的私钥文件和证书文件名将直接保存为键名形式,以便于后面创建Secret对象时直接作为键名引用
[ root@k8s - master01 tomcat ]# openssl genrsa - out tls . key 2048 Generating RSA private key , 2048 bit long modulus .+++ ..........................................................................+++ e is 65537 ( 0x10001 ) [ root@k8s - master01 tomcat ]# openssl req - new - x509 - key tls . key - out tls . crt - subj / C = CN / ST = Shanghai / L = Shanghai / O = DevOps / CN = tomcat . ilinux . io - days 3600 [ root@k8s - master01 tomcat ]#
在Ingress控制器上配置HTTPS主机时,不能直接使用私钥和证书文件,而是需要使用secret资源对象来传递相关的数据。所以,接下来要根据私钥和证书生成用于配置TLS Ingress的Secret资源,在创建Ingress规则时由其将用到的Secret资源中的信息注入到Ingrss控制器的Pod资源对象中,用于为其配置HTTPS虚拟主机提供相应的私钥和证书。下面的命令会创建一个TLS类型名为tomcat-testing-ingress-secret的secret资源
[ root@k8s - master01 tomcat ]# kubectl create secret tls tomcat - testing - ingress - secret -- cert = tls . crt -- key = tls . key - n testing secret / tomcat - testing - ingress - secret created [ root@k8s - master01 tomcat ]# [ root@k8s - master01 tomcat ]# kubectl get secret tomcat - testing - ingress - secret - n testing NAME TYPE DATA AGE tomcat - testing - ingress - secret kubernetes . io / tls 2 45s [ root@k8s - master01 tomcat ]#
而后去定义创建TLS类型Ingress资源的配置清单。下面的配置清单通过spec.rules定义了一组转发规则,并通过.spec.tls将此主机定义为了HTTPS类型的虚拟主机,用到的私钥和证书信息则来自于Secret资源tomcat-testing-ingress-secret
为了演示方便,我们直接修改之前创建的tomcat-testing-ingress.yaml资源清单文件。加上了.spec.tls字段的配置即可
apiVersion : extensions / v1beta1 kind : Ingress metadata : name : tomcat namespace : testing annotations : kubernetes . io / ingress . class : "nginx" spec : tls : - hosts : - tomcat . ilinux . io secretName : tomcat - testing - ingress - secret rules : - host : tomcat . ilinux . io http : paths : - backend : serviceName : tomcat - testing - svc servicePort : 80
资源清单文件修改完成之后直接应用一下文件科技
[ root@k8s - master01 tomcat ]# kubectl apply - f tomcat - testing - ingress . yaml ingress . extensions / tomcat configured [ root@k8s - master01 tomcat ]#
然后查看详细信息确认是否被成功修改,且已经正确关联到了相应的service资源
[ root@k8s - master01 tomcat ]# kubectl describe ingress tomcat - n testing Name : tomcat Namespace : testing Address : Default backend : default - http - backend : 80 (< none >) TLS : tomcat - testing - ingress - secret terminates tomcat . ilinux . io Rules : Host Path Backends ---- ---- -------- tomcat . ilinux . io tomcat - testing - svc : 80 ( 10.244 . 38.5 : 8080 , 10.244 . 59.6 : 8080 ) Annotations : kubernetes . io / ingress . class : nginx kubectl . kubernetes . io / last - applied - configuration : { "apiVersion" : "extensions/v1beta1" , "kind" : "Ingress" , "metadata" :{ "annotations" :{ "kubernetes.io/ingress.class" : "nginx" }, "name" : "tomcat" , "namespace" : "testing" }, "spec" :{ "rules" :[{ "host" : "tomcat.ilinux.io" , "http" :{ "paths" :[{ "backend" :{ "serviceName" : "tomcat-testing-svc" , "servicePort" : 80 }}]}}], "tls" :[{ "hosts" :[ "tomcat.ilinux.io" ], "secretName" : "tomcat-testing-ingress-secret" }]}} Events : Type Reason Age From Message ---- ------ ---- ---- ------- Normal UPDATE 84s nginx - ingress - controller Ingress testing / tomcat [ root@k8s - master01 tomcat ]#
接下来就可以通过Ingress控制器的前端Service资源的NodePort来访问此服务,同样使用之前创建的servie资源来访问,此Service资源以节点端口10443映射控制器的443端口。因此,这里使用Ingress中定义的主机名tomcat.ilinux.io:443即可访问tomcat应用,其访问到的效果跟之前一样,会出现一个404页面。因为tomcat的webapps目录里面没有任何内容
或者我们可以直接使用curl命令进行访问测试,只要对应的主机能够正确解析tomcat.ilinux.io主机名即可。
[ root@k8s - master01 tomcat ]# curl - k - v https :// tomcat . ilinux . io : 10443 / aaa / a . txt * About to connect () to tomcat . ilinux . io port 10443 (# 0 ) * Trying 172.18 . 15.114 ... * Connected to tomcat . ilinux . io ( 172.18 . 15.114 ) port 10443 (# 0 ) * Initializing NSS with certpath : sql :/ etc / pki / nssdb * skipping SSL peer certificate verification * SSL connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 * Server certificate : * subject : CN = tomcat . ilinux . io , O = DevOps , L = Shanghai , ST = Shanghai , C = CN * start date : Jun 30 08 : 53 : 53 2020 GMT * expire date : May 09 08 : 53 : 53 2030 GMT * common name : tomcat . ilinux . io * issuer : CN = tomcat . ilinux . io , O = DevOps , L = Shanghai , ST = Shanghai , C = CN > GET / aaa / a . txt HTTP / 1.1 > User - Agent : curl / 7.29 . 0 > Host : tomcat . ilinux . io : 10443 > Accept : */* > < HTTP / 1.1 200 < Server : nginx / 1.13 . 12 < Date : Wed , 01 Jul 2020 03 : 03 : 48 GMT < Content - Type : text / plain < Content - Length : 80 < Connection : keep - alive < Accept - Ranges : bytes < ETag : W / "80-1593514308928" < Last - Modified : Tue , 30 Jun 2020 10 : 51 : 48 GMT < Strict - Transport - Security : max - age = 15724800 ; includeSubDomains < 健哥说非要 echo 一个页面,不然就是搞学问不严谨,哈哈哈哈 * Connection #0 to host tomcat.ilinux.io left intact [ root@k8s - master01 tomcat ]#
到此为止,实践配置目标已经全部达成。需要再次提醒的是,在实际使用中,在集群之外应该存在一个用于调度用户请求至各节点上Ingress控制器相关的NodePort的负载均衡器。这个负载均衡器可以是云厂商提供,也可以是用户基于Nginx、Haproxy、LVS等手动构建并通过keepalive等解决方式实现其服务高可用配置的反向代理服务器
总结
Service通过标签选择器为一组Pod资源创建一个统一的访问入口,其可以将客户端请求代理调度至后端的Pod资源
Service资源是四层调度机制,默认调度算法为随机调度
Service的实现模式有三种:userspace(已经不再使用)、iptables和ipvs
Service共有四种类型: ClusterIP、NodePort、Loadbalancer和ExternalName,用于发布服务
Headless Service是一种特殊的service资源,可用于Pod发现
Ingress资源是发布Service资源的另一种方式,它需要结合Ingress控制器才能正常工作
Ingress Controller的实现除了Nginx之外,还有Envoy、Haproxy、Traefik等
Ingress资源需要依赖Service资源用于关联后端Pod资源