1、上集回顾前端
一、Service 3种模型:userspace,iptables,ipvsnode
二、Service类型nginx
ClusterIP,NodePortgit
NodePort:client -> NodeIP:NodePort -> ClusterIP:ServicePort -> PodIP:containerPortgithub
LoadBalancerjson
ExternelName后端
No ClusterIP: Hedless Serviceapi
serviceName -> PodIPtomcat
2、ingress安全
一、在客户端访问咱们k8s服务时,四层调度器自己是没有办法解除ssl会话的,这就意味着客户端必须与后端服务器(pod)之间直接创建ssl会话,这里还有个显著的问题在于若是调度器在ssl会话创建之后的下一个请求被调度到第二台服务器上那么这个ssl还要从新创建,所以咱们只要认为内部网络是安全的那么咱们能够把会话在前端调度器上卸载,可是四层调度是不能卸载的,所以咱们须要七层的负载均衡机制。所以若是他们是http服务咱们又指望构建https,那么咱们只须要他在互联网上这个不安全的网络中传输实现https,内网中使用http,所以咱们须要使用卸载器,可是咱们Service调度时,不管是iptables仍是ipvs都只是四层调度,所以也就意味着若是你想要在k8s上运行一个应用基于https提供服务,咱们就必须得在后端每个pod上配置https,由于只有这样他们才会创建起https联系,因此咱们如今也指望在接入那一层上就可以卸载ssl,向内部调度时就再也不是ssl了。对这种需求,k8s采用一种很独特的方式来实现,咱们在整个集群中,在进行调度时后端被代理的pod资源是不配置https的,就是明文的http,可是我使用一个独特的调度器(运行在pod中),对于此pod来说,其是一个运行在七层(用户空间)的正常的应用程序,好比nginx,haproxy等,当用户试图访问某一服务时,咱们不让他先去到达前端的service,而是先到这个pod,而后pod与pod之间不须要service而是直接通讯来完成反向代理,咱们用一个pod来反代至后端咱们真正提供服务的pod,此前咱们用service代理的,如今用pod,而这个pod若是须要被访问到那么仍是须要通过service,所以客户端通过此pod的service调度之后,与咱们专门配置了https的此pod进行交互,这里的service咱们定义成nodePort,依然没有什么问题,依然老路径仍是存在的,可是等到达这个pod之后由此pod直接代理至两个明文的pod,所以此pod就成为https的会话卸载器了。若是这种方式进行调度那么调度方式以下: client --> LB --> nodePort --> service -->会话卸载器pod --> 后端pod 这种方式性能确定会很是很是差,如图。
二、其实咱们还能够这样干,可让咱们pod直接共享咱们节点的网络名称空间,因而,上述中的会话卸载器pod咱们能够直接让他共享节点网络名称空间,这就意味着其监听着宿主机的地址,这样咱们客户端的请求就能够之间到达这个pod,而后再由他进行调度。
三、在一个节点上运行的容器,容器可使用本身的虚拟网络,也能够共享宿主机的网络,若是这个容器共享宿主机的网络也就意味着这个容器内的进程一旦监听套接字时它监听的是宿主机的地址,至关于一个进程运行在宿主机上同样的,这样一来这个pod在每一个节点上就只能运行一个了,通常来说集群中只有一个,那么其只须要运行在集群的某一个节点便可,可是若是 监听在节点的端口时就会有问题,service时不管访问哪个节点的端口都行,由于你访问哪个节点的nodePort他都能经过它的ip地址送达到后端pod上,可是如今这个Pod要监听节点的网络名称空间,而且经过这个节点的网络名称空间直达这个pod,那么若是运行这种类型的pod那么就必定只能运行在一个节点上,访问时客户端就只能访问这个节点,而且若是这个节点挂了呢?
四、要解决这个问题,咱们能够用DaemonSet控制器,它能够在每一个节点上都运行相应的pod 副本而且只运行一个,这样假如咱们有三个节点那么咱们三个节点上均可以运行这个pod。这样就都能实现代理和负载均衡,可是又回到了调度到哪个节点均可以的问题,这样不管哪一个节点挂掉了都仍是能够访问到,可是若是咱们有太多的节点那么每一个节点都运行一个这样的pod就太占资源。daemonset还可让pod运行在有限的节点的范围上(部分节点),因而再未来作k8s集群时能够这样干,好比咱们有三千个节点,那么咱们专门拿三个节点出来作pod的接入式的负载均衡的专用主机,而且给这三个节点打上污点让其它pod没法调度上来,而后咱们就定义这个DaemonSet控制器上的pod只运行在这三个节点上各自运行一份而且能容忍这些污点,因此这三个主机在集群中只容许这一个类型的pod,专门负责为集群接入外部的七层调度的流量。而这个pod在k8s中有个专门的称呼叫 Ingress Controller。这个Ingress Controller比较独特,以前讲的DaemonSet,deployment,replacSet等控制器都不同,DaemonSet deployment,replaciSet等等都是做为Controller manager的一部分存在,众多控制器都是做为Controller manager的一个子组件做为其组成部分组成的。而Ingress Controller倒是本身独立运行的一个或一组pod资源,它一般就是一个应用程序,这个应用程序就是拥有七层代理能力和调度能力的应用程序,目前k8s上的选择有四种,其中最不受待见的就是Haproxy,通常默认是nginx,如今在服务网格中你们比较倾向Envoy,固然还有其它与nginx相竞争的听说原本就是为微服务而生的Traefik,因此用Ingress Controller时会发现咱们有三种选择:
a、nginx:这是后来改造的
b、Traefik:这种设计就是为微服务这种动态生成而生的
c、Envoy :去作微服务的你们都比较倾向于Envoy
五、做为调度器,有时候要调度不仅一个后端服务,假若有一个调度器pod,后端有一组pod提供电商服务,第二组pod提供了社交服务,第三组pod提供了论坛服务,第四组pod提供了网关服务。那么咱们这四组http服务怎么可以分别调度呢?
a、从nginx的角度来说,接入服务端时咱们经过uptream_server便可,可是接入客户端时咱们应该如何标识这四种不一样的请求呢,首先咱们能够在nginx上作四个虚拟主机,在四个主机名上作四个主机,每个主机名对应一组后端的pod。那万一咱们没那么多主机名呢?此时咱们能够经过不一样的路径来作url映射,而后每一组路径就映射到一组后端pod上,可是pod存在生命周期,随时均可能挂掉替换为一个新pod,新pod的ip就会变了,另外咱们pod的应用的规模也能够动态伸缩的,咱们简单改一下副本数其数量也会变,这种一变前面代理的配置也就无效了,咱们service经过关联标签来解决这个问题,并且service随时 watch着api server上的api时刻来关注本身关联的slector的资源是否变更了,只要变更咱们api server就会当即通知service而后service当即改变。 因此service经过label selector始终关联着对应label能适配的后端pod,不管怎么变都能应付并且能及时做出反应,那么此处nginx运行在pod中也就意味着这个配置是在pod内部而且后端pod随时还会发生变更,Ingress 也会时刻watch着api 中的后端pod资源的改变。那它怎么知道这是哪一个pod资源呢?Ingress Controller本身没有这个能力,它并不知道目前符合本身条件关联的被代理的pod资源有哪些,它必须借助于service来实现,咱们要想定义一个这种调度能力功能其实仍是须要建service,这个service经过label selector关联至后端的pod上来,但这个service不是被当作被代理时的中间节点,它仅仅是帮忙分类的,这个service 关联了几个pod那么咱们就将这几个pod配置写在这个upstream中,调度时是不会通过service的,service在此处仅仅是帮忙分组的,分完组之后咱们须要获得的也不是service的IP,而是pod的ip,所以此时可使用headless service,可是这个service却没有用,是否是headless都无所谓,它只要帮忙完成分组知道找哪几个pod就能够了,pod一变,service对应的资源也就变了,问题是变了后这个结果怎么反应到这个配置文件中来,此时须要依赖于一个专门的资源 Ingress。
六、在k8s上有一种特殊的资源叫Ingress,Ingress 和Ingress Controller是两回事,咱们定义一个Ingress 时就是说了它其实就是定义咱们指望这个Ingress Controller是如何给咱们建一个前端(多是一个虚拟主机,也多是一个url映射)接入层,同时又给咱们定义一个后端upstream_server,这个upstream_server中有几个主机 Ingress是经过这个service 获得的,而且Ingress有一个特色,做为资源来说他能够经过编辑注入到Ingress Controller里面来,直接把它注入并保存为配置文件,并且一旦Ingress发现Service选定的后端的pod资源发生改变了,这个改变必定会及时返回到Ingress中,这个Ingress会及时注入到这个前端调度器pod中,就是注入到upstream配置文件中,并且还能触发这个pod中的主容器中的进程重载配置文件。因此咱们要想使用这个功能咱们须要在集群中:
a、要有个service去对后端某一个特定类型的pod资源进行分类,这个service只是起分类做用的。
b、Ingress基于这个分类识别出有几个pod,而且识别其ip地址是什么,而且将这个ip地址返回的结果生成配置信息注入到upstream_server(以nginx为例),可是nginx又不是特别适用这个场景,每次变更都在重载,若是是Traefik和Envoy 等天生就是为这种场景而生的,只要动了就加载生效,不须要重载。(它能够监控这个配置文件发生变化,只要发生变化就会动态重载)。
七、若是咱们想要使用代理,咱们应该怎么作?
a、须要先部署一个Ingress Controller,而后部署一个pod进来,这个pod可能原本是空的,没有什么有效的东西,接下来咱们要根据本身的须要 经过虚拟主机的方式或者经过url代理的方式来配置一个前端,而后再根据咱们Service收集到的后端pod的IP定义成upstream_server,把这些信息反应在Ingress当中由Ingress动态注入到Ingress Controller中才能够
b、从图中咱们能够看到,当访问咱们服务时首先由外部的负载均衡器将请求调度到咱们nodePort的Service上,而nodePort上的Service再将请求调度至咱们内部的一个pod 叫IngressController上来,Ingress Controller根据Ingress中的定义(虚拟主机或url),每个主机名对应后面的一组pod资源(经过service分组),所以此处用到两组Service,第一个Service是帮集群接入外部流量的(固然也能够不用,能够把这个Ingress Controller pod运行为共享网络节点网络名称空间方式而且将其定义为Dameset方式运行在特定节点上就能够了),那么咱们在定义pod资源时只须要在pod的一个配置选项中加入hostnetwork便可。第二个Service只用来作pod归组不被调度时使用。
c、接下来咱们要使用ingress的功能得先去安装部署Ingress Controller 这个pod,然后再定义Ingress,然后再定义后端pod生成Service,而后再创建关联关系。
3、Ingress 定义
一、Ingress 也是标准的kubernetes资源对象,所以也拥有相应的对象属性。
[root@k8smaster ~]# kubectl explain ingress.spec KIND: Ingress VERSION: extensions/v1beta1 RESOURCE: spec <Object> DESCRIPTION: Spec is the desired state of the Ingress. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status IngressSpec describes the Ingress the user wishes to exist. FIELDS: backend <Object> #定义后端主机,定义后端有哪几个pod,其属性有serviceName和sericePort A default backend capable of servicing requests that don't match any rule. At least one of 'backend' or 'rules' must be specified. This field is optional to allow the loadbalancer controller or defaulting logic to specify a global default. rules <[]Object> #定义规则,分为主机和http,http又有paths路径定义调度到哪儿去。 (即主机调度和路径调度两种方式) A list of host rules used to configure the Ingress. If unspecified, or no rule matches, all traffic is sent to the default backend. tls <[]Object> TLS configuration. Currently the Ingress only supports a single TLS port, 443. If multiple members of this list specify different hosts, they will be multiplexed on the same port according to the hostname specified through the SNI TLS extension, if the ingress controller fulfilling the ingress supports SNI.
[root@k8smaster ~]# kubectl explain ingress.spec.backend KIND: Ingress VERSION: extensions/v1beta1 RESOURCE: backend <Object> DESCRIPTION: A default backend capable of servicing requests that don't match any rule. At least one of 'backend' or 'rules' must be specified. This field is optional to allow the loadbalancer controller or defaulting logic to specify a global default. IngressBackend describes all endpoints for a given service and port. FIELDS: serviceName <string> -required- #backend正是靠咱们service的定义来找到咱们后端相关联的有哪几个pod资源的,一旦pod资源发生变化这个service就发生变化,service变化Ingress就变化,
Ingress变化就开始注入到Ingress Controller中去。
Specifies the name of the referenced service. servicePort <string> -required- Specifies the port of the referenced service.
二、部署Ingress,k8s集群由master,node和附件组成,一共有四个核心附件:
a、dns
b、Heapster
c、Dashboard
d、Ingress Controller
4、Ingress建立
一、首先下载github上对应的yaml文件
[root@k8smaster ingress-nginx]# for file in namespace.yaml configmap.yaml rbac.yaml tcp-services-configmap.yaml with-rbac.yaml udp-services-configmap.yaml default-backend.yaml; \ > do wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.17.1/deploy/$file; done ...
二、将下载yaml文件建立使用
[root@k8smaster ingress-nginx]# ls configmap.yaml namespace.yaml rbac.yaml tcp-services-configmap.yaml udp-services-configmap.yaml with-rbac.yaml [root@k8smaster ingress-nginx]# kubectl apply -f namespace.yaml namespace/ingress-nginx created [root@k8smaster ingress-nginx]# kubectl apply -f ./ configmap/nginx-configuration created namespace/ingress-nginx configured 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 configmap/tcp-services created configmap/udp-services created deployment.extensions/nginx-ingress-controller created
也可直接使用一次性部署yaml文件
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml
[root@k8smaster ingress-nginx]# kubectl get pods -n ingress-nginx -o wide NAME READY STATUS RESTARTS AGE IP NODE default-http-backend-846b65fb5f-ggwwp 1/1 Running 0 29m 10.244.1.77 k8snode1 nginx-ingress-controller-d658896cd-nqt4b 1/1 Running 21 2h 10.244.2.76 k8snode2
三、尝试建立Ingress,为了让某个Ingress能显现真正的效果来咱们要作一些前提准备,好比咱们要部署几个后端被代理的应用
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: test-ingress annotations: #此属性相当重要,由于在annotations中咱们必须指明ingress controller类型是nginx nginx.ingress.kubernetes.io/rewrite-target: / spec: rules: - http: paths: - path: /testpath backend: serviceName: test servicePort: 80
四、直接部署在裸机上时要额外加上一项叫作service-nodeport.yaml,若是不加上这一项会发现ingress controller部署完之后在集群内部能够被访问,在集群外部是没法被访问到的,由于ingress controller没法接入外部的流量,若是要接入流量则须要再部署一个nodePort的service,或者也能够将ingress controller部署为直接共享节点网络名称空间的方式,但这个时候咱们须要手动改造with-rbac.yaml这个文件中的kind 类型由Deployent改成DaemonSet,而后去掉replicas,而后在pod template上的spec中加一项hostnetwork用于共享宿主机的网络名称空间,固然须要保证监听的端口不被冲突。
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/baremetal/service-nodeport.yaml
五、接下来能够尝试使用ingress规则来应用
a、首先建立一组应用pod和对应的service
[root@k8smaster ingress]# cat deploy-demo.yaml apiVersion: v1 kind: Service metadata: name: myapp namespace: default spec: selector: app: myapp release: canary ports: - name: http targetPort: 80 port: 80 --- apiVersion: apps/v1 kind: Deployment metadata: name: myapp-deploy namespace: default spec: replicas: 3 selector: matchLabels: app: myapp release: canary template: metadata: labels: app: myapp release: canary spec: containers: - name: myapp image: ikubernetes/myapp:v2 ports: - name: http containerPort: 80
b、建立nodePort service
[root@k8smaster ingress-nginx]# cat service-nodeport.yaml apiVersion: v1 kind: Service metadata: name: ingress-nginx namespace: ingress-nginx spec: type: NodePort ports: - name: http #服务为http port: 80 #service端口为80 targetPort: 80 #容器端口为80 protocol: TCP nodePort: 30080 - name: https port: 443 #service 端口为443 targetPort: 443 #容器端口为443 protocol: TCP nodePort: 30443 selector: app: ingress-nginx --- [root@k8smaster ingress-nginx]# kubectl apply -f ./ configmap/nginx-configuration unchanged deployment.extensions/default-http-backend unchanged service/default-http-backend unchanged namespace/ingress-nginx configured serviceaccount/nginx-ingress-serviceaccount unchanged clusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole configured role.rbac.authorization.k8s.io/nginx-ingress-role unchanged rolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding unchanged clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding configured service/ingress-nginx created configmap/tcp-services unchanged configmap/udp-services unchanged deployment.extensions/nginx-ingress-controller unchanged
[root@k8smaster ingress]# kubectl get pods -n ingress-nginx -o wide --show-labels
NAME READY STATUS RESTARTS AGE IP NODE LABELS
default-http-backend-846b65fb5f-ggwwp 1/1 Running 1 1d 10.244.1.82 k8snode1 app=default-http-backend,pod-template-hash=4026219619
nginx-ingress-controller-d658896cd-nqt4b 1/1 Running 22 1d 10.244.2.81 k8snode2 app=ingress-nginx,pod-template-hash=821445278
此时访问咱们节点端口显示 default backend - 404 ,此时表示咱们调度器已经正常工做。
c、此时将步骤a中建立的myapp Deploymet开始使用咱们b中这个Service发布出去而不在咱们里面同时建立的这个service上本身改为nodePort发布出去了
[root@k8smaster ingress]# cat ingress-myapp.yaml apiVersion: extensions/v1beta1 Kind: Ingress metadata: name: ingress-myapp namespaces: default annotations: #进行说明咱们接下来要用到的规则是nginx,就是靠annotations来识别类型的,只有进行注解了才能转化为对应的与controller相匹配的规则 kubernetes.io/ingress.class: "nginx" spec: rules: #定义把谁转到谁那儿去 - host: myapp.wohaoshuai.com #要确保在外部经过互联网访问时能解析此主机名,而且解析结果恰好能到达咱们Service nodePort映射的主机上去 http: #定义先后端路径 paths: #不给默认为/ - path: #前端路径,空表示默认的/ backend: #匹配后端service serviceName: myapp servicePort: 80 [root@k8smaster ingress]# kubectl apply -f ingress-myapp.yaml ingress.extensions/ingress-myapp created [root@k8smaster ingress]# kubectl get ingress NAME HOSTS ADDRESS PORTS AGE ingress-myapp myapp.wohaoshuai.com 80 10s [root@k8smaster ingress]# kubectl describe ingress ingress-myapp Name: ingress-myapp Namespace: default Address: Default backend: default-http-backend:80 (<none>) Rules: Host Path Backends ---- ---- -------- myapp.wohaoshuai.com myapp:80 (<none>) Annotations: kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"extensions/v1beta1","kind":"Ingress","metadata":{"annotations":{"kubernetes.io/ingress.class":"nginx"},"name":"ingress-my app","namespace":"default"},"spec":{"rules":[{"host":"myapp.wohaoshuai.com","http":{"paths":[{"backend":{"serviceName":"myapp","servicePort":80},"path":null}]}}]}} kubernetes.io/ingress.class: nginx Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal CREATE 30s nginx-ingress-controller Ingress default/ingress-myapp
d、上述建立完成的ingress一旦应用其会自动注入到ingress controller中去,也就是说其会自动转换成nginx的配置文件(从下面信息中可看到),访问myapp.wohaoshuai.com:30080便可
[root@k8smaster ingress]# kubectl get pods -n ingress-nginx NAME READY STATUS RESTARTS AGE default-http-backend-846b65fb5f-ggwwp 1/1 Running 0 1h nginx-ingress-controller-d658896cd-nqt4b 1/1 Running 21 4h [root@k8smaster ingress]# kubectl exec -it nginx-ingress-controller-d658896cd-nqt4b /bin/bash -n ingress-nginx www-data@nginx-ingress-controller-d658896cd-nqt4b:/etc/nginx$ ls fastcgi.conf fastcgi_params.default koi-win mime.types.default nginx.conf owasp-modsecurity-crs template win-utf fastcgi.conf.default geoip lua modsecurity nginx.conf.default scgi_params uwsgi_params fastcgi_params koi-utf mime.types modules opentracing.json scgi_params.default uwsgi_params.default www-data@nginx-ingress-controller-d658896cd-nqt4b:/etc/nginx$ cat nginx.conf|grep wohaoshuai ## start server myapp.wohaoshuai.com server_name myapp.wohaoshuai.com ; ## end server myapp.wohaoshuai.com
从上面配置文件中能够看出svc只是起到了识别后端pod信息的做用而不起调度做用
5、建立一个真正可用的ingress 实例
一、咱们如今作这么一个东西,原本咱们起了两到三个tomcat pod,每一个pod监听本身的8080和8009端口,所以咱们在三个pod以前作一个Service做为一个固定访问端点代理,可是这个Service待会儿不会用到,它只是用来识别而已,咱们Service对应的8080和8009端口对应后端pod的8080和8009端口。咱们定义一个deployment来部署这三个tomcat,用来监听8080和8009端口,而后定义一个Service把8080和8009暴露出去,可是没有真正向集群外部暴露,由于其是cluster IP类型的,他只是用来被前端等会儿叫ingress controller定义ingress规则向里面映射的时候所识别后端有哪几个Pod而已。
二、建立Deployment 和 Service,而后建立ingress
[root@k8smaster ingress]# cat tomcat-deploy.yaml apiVersion: v1 kind: Service metadata: name: tomcat namespace: default spec: selector: app: tomcat release: canary ports: - name: http targetPort: 8080 port: 8080 - name: ajp targetPort: 8009 port: 8009 --- apiVersion: apps/v1 kind: Deployment metadata: name: tomcat-deploy namespace: default spec: replicas: 3 selector: matchLabels: app: tomcat release: canary template: metadata: labels: app: tomcat release: canary spec: containers: - name: myapp image: tomcat:8.5.32-jre8-alpine ports: - name: http containerPort: 8080 - name: ajp containerPort: 8009 [root@k8smaster ingress]# kubectl apply -f tomcat-deploy.yaml service/tomcat created deployment.apps/tomcat-deploy created [root@k8smaster ingress]# cat ingress-tomcat.yaml apiVersion: extensions/v1beta1 kind: Ingress metadata: name: ingress-tomcat namespace: default annotations: #进行说明咱们接下来要用到的规则是nginx,就是靠annotations来识别类型的,只有进行注解了才能转化为对应的与controller相匹配的规则 kubernetes.io/ingress.class: "nginx" spec: rules: #定义把谁转到谁那儿去 - host: tomcat.wohaoshuai.com #要确保在外部经过互联网访问时能解析此主机名,而且解析结果恰好能到达咱们Service nodePort映射的主机上去 http: #定义先后端路径 paths: #不给默认为/ - path: #前端路径,空表示默认的/ backend: #匹配后端service serviceName: tomcat servicePort: 8080 #咱们没有指ingress因此默认ingress是80端口 [root@k8smaster ingress]# kubectl apply -f ingress-tomcat.yaml ingress.extensions/ingress-myapp configured
建立完成后在各节点host文件添加tomcat.lwohaoshuai.com解析访问 tomcat.wohaoshuai.com:30080便可
三、若是咱们想要建立https的虚拟主机就稍微要麻烦一点,第一,这个虚拟主机要工做为https服务的话在nginx上这个虚拟主机得是ssl虚拟主机配置为ssl虚拟主机则须要证书和私钥,而这个证书和私钥咱们须要将其建立为特定格式才能提供给咱们的ingress.那么如今咱们作一组证书和私钥而且把它们做为一个独特的对象,这个叫secret。
a、建立私钥和证书
[root@k8smaster ingress]# openssl genrsa -out tls.key 2048 #建立私钥 Generating RSA private key, 2048 bit long modulus ..+++ ........................................+++ e is 65537 (0x10001) [root@k8smaster ingress]# ls deploy-demo.yaml ingress-myapp.yaml ingress-tomcat.yaml tls.key tomcat-deploy.yaml [root@k8smaster ingress]# openssl req -new -x509 -key tls.key -out tls.crt(自签证书) -subj /C=CN/ST=Beijing/L=Beijing/O=DevOps/CN=tomcat.wohaoshuai.com(国家为CN,所在的省为北京,地址为北京,组织为DevOps,此外,证书中应该包含的名字应该和此前定义的域名一致,为tomcat.wohaoshuai.com) #建立自签证书 [root@k8smaster ingress]# ls deploy-demo.yaml ingress-myapp.yaml ingress-tomcat.yaml tls.crt tls.key tomcat-deploy.yaml
b、注意生成的证书是不能直接贴到nginx的pod中去的,咱们须要把它先转成特殊格式,这个特殊格式叫secret,它也是标准的k8s集群对象,它能够直接注入到pod中被pod所引用。所以接下来咱们须要把它作成secret
[root@k8smaster ingress]# kubectl create secret tls tomcat-ingress-secret --cert=tls.crt --key=tls.key secret/tomcat-ingress-secret created [root@k8smaster ingress]# kubectl get secret NAME TYPE DATA AGE default-token-jvtl7 kubernetes.io/service-account-token 3 36d tomcat-ingress-secret kubernetes.io/tls 2 15s [root@k8smaster ingress]# kubectl describe secret tomcat-ingress-secret Name: tomcat-ingress-secret Namespace: default Labels: <none> Annotations: <none> Type: kubernetes.io/tls Data ==== tls.crt: 1306 bytes tls.key: 1679 bytes
c、建立完之后咱们就能够拿这个secret在ingress.spec.rules中定义了
[root@k8smaster ingress]# kubectl explain ingress.spec.tls KIND: Ingress VERSION: extensions/v1beta1 RESOURCE: tls <[]Object> DESCRIPTION: TLS configuration. Currently the Ingress only supports a single TLS port, 443. If multiple members of this list specify different hosts, they will be multiplexed on the same port according to the hostname specified through the SNI TLS extension, if the ingress controller fulfilling the ingress supports SNI. IngressTLS describes the transport layer security associated with an Ingress. FIELDS: hosts <[]string> #表示把哪一个主机作成tls格式的 Hosts are a list of hosts included in the TLS certificate. The values in this list must match the name/s used in the tlsSecret. Defaults to the wildcard host setting for the loadbalancer controller fulfilling this Ingress, if left unspecified. secretName <string> #用哪一个secret来获取证书,私钥等相关信息 SecretName is the name of the secret used to terminate SSL traffic on 443. Field is left optional to allow SSL routing based on SNI hostname alone. If the SNI host in a listener conflicts with the "Host" header field used by an IngressRule, the SNI host is used for termination and value of the Host header is used for routing.
[root@k8smaster ingress]# kubectl apply -f ingress-tomcat-tls.yaml ingress.extensions/ingress-tomcat-tls created [root@k8smaster ingress]# cat ingress-tomcat-tls.yaml apiVersion: extensions/v1beta1 kind: Ingress metadata: name: ingress-tomcat-tls namespace: default annotations: #进行说明咱们接下来要用到的规则是nginx,就是靠annotations来识别类型的,只有进行注解了才能转化为对应的与controller相匹配的规则 kubernetes.io/ingress.class: "nginx" spec: tls: - hosts: - tomcat.wohaoshuai.com secretName: tomcat-ingress-secret rules: #定义把谁转到谁那儿去 - host: tomcat.wohaoshuai.com #要确保在外部经过互联网访问时能解析此主机名,而且解析结果恰好能到达咱们Service nodePort映射的主机上去 http: #定义先后端路径 paths: #不给默认为/ - path: #前端路径,空表示默认的/ backend: #匹配后端service serviceName: tomcat servicePort: 8080 #咱们没有指ingress因此默认ingress是80端口 [root@k8smaster ingress]# kubectl get ingress NAME HOSTS ADDRESS PORTS AGE ingress-myapp myapp.wohaoshuai.com 80 20h ingress-tomcat tomcat.wohaoshuai.com 80 18h ingress-tomcat-tls tomcat.wohaoshuai.com 80, 443 33s [root@k8smaster ingress]# kubectl describe ingress ingress-tomcat-tls Name: ingress-tomcat-tls Namespace: default Address: Default backend: default-http-backend:80 (<none>) TLS: tomcat-ingress-secret terminates tomcat.wohaoshuai.com Rules: Host Path Backends ---- ---- -------- tomcat.wohaoshuai.com tomcat:8080 (<none>) Annotations: kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"extensions/v1beta1","kind":"Ingress","metadata":{"annotations":{"kubernetes.io/ingress.class":"nginx"},"name":"ingress-to mcat-tls","namespace":"default"},"spec":{"rules":[{"host":"tomcat.wohaoshuai.com","http":{"paths":[{"backend":{"serviceName":"tomcat","servicePort":8080},"path":null}]}}],"tls":[{"hosts":["tomcat.wohaoshuai.com"],"secretName":"tomcat-ingress-secret"}]}} kubernetes.io/ingress.class: nginx Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal CREATE 1m nginx-ingress-controller Ingress default/ingress-tomcat-tls [root@k8smaster ingress]# kubectl exec -it nginx-ingress-controller-d658896cd-nqt4b /bin/bash -n ingress-nginx www-data@nginx-ingress-controller-d658896cd-nqt4b:/etc/nginx$ cat nginx.conf|grep ssl
经过https://tomcat.wohaoshuai.com:30443访问便可。能够看到咱们ssl主机创建起来了,可是咱们后端pod并无提供任何ssl功能