标签:规则 create 重复 data grep 详细信息 关联 sts client
博文大纲:
一、Ingress简介
1)Ingress组成
2)Ingress工作原理
3) Ingress可以解决什么问题?
二、配置Ingress-nginx
1)搭建registry私有仓库
2)创建用于测试的Pod
2)创建tomcat服务及其service
3)确保以上资源对象成功创建
4)创建Ingress-controller资源对象
5)创建Ingress资源对象
6)为Ingress-controller资源对象创建一个service资源对象
7)创建基于虚拟主机的Ingress规则
三、配置HTTPS
在Kubernetes中,服务和Pod的IP地址仅在集群内部网络内部使用,对于集群的应用是不可见的。
为了使外部的应用能够访问集群内的服务,在Kubernetes目前提供了以下几种方案:
1)NodePort
2)LoadBalancer
3)Ingress
Ingress 是反向代理规则,用来规定 HTTP/S 请求应该被转发到哪个 Service 上,比如根据请求中不同的 Host 和 url 路径让请求落到不同的 Service 上;
Ingress Controller 就是一个反向代理程序,它负责解析 Ingress 的反向代理规则,如果 Ingress 有增删改的变动,所有的 Ingress Controller 都会及时更新自己相应的转发规则,当 Ingress Controller 收到请求后就会根据这些规则将请求转发到对应的 Service;
1)Ingress controller通过与Kubernetes api进行交互,动态的感知集群中Ingress规则的变化;
2)然后读取它,按照自定义的规则,规则就是写明了哪个域名对应哪个service,生成一段nginx配置;
3)再写到nginx-ingress-controller的pod里,这个Ingress controller的pod里运行着一个Nginx服务,控制器会把生成的nginx配置写入/etc/nginx.conf文件中;
4)然后reload一下使配置生效。以此达到域名分别配置和动态更新的问题;
1)动态配置服务
如果是按照传统方式,当新增加一个服务时,我们可能需要在流量入口部署一台反向代理服务器指向我们新的K8s服务,而如果使用了Ingress,则只需配置好这个服务,当服务启动时,便会自动注册到Ingress中,不需要额外的操作;
2)减少不必要的端口映射
配置过k8s的都清楚, 第一步是要关闭防火墙的, 主要原因是k8s的很多服务会以NodePort方式映射出去, 这样就相当于给宿主机打了很多孔, 既不安全也不优雅. 而Ingress可以避免这个问题, 除了Ingress自身服务可能需要映射出去, 其他服务都不用NodePort方式;
搭建私有仓库的目的,仅仅是为了更快的获取镜像,如果网络稳定,也可跳过此步骤!
[root@master ~]# docker run -itd --name registry --restart=always -p 5000:5000 -v /registry:/var/lib/registry registry:2
#搭建registry私有仓库
[root@master ~]# vim /usr/lib/systemd/system/docker.service
#修改docker的配置文件,指向私有仓库
ExecStart=/usr/bin/dockerd --insecure-registry 192.168.1.4:5000
[root@master ~]# scp /usr/lib/systemd/system/docker.service root@node01:/usr/lib/systemd/system/
[root@master ~]# scp /usr/lib/systemd/system/docker.service root@node02:/usr/lib/systemd/system/
#将修改好的配置文件发送到Kubernetes集群中的各个节点
[root@master ~]# systemctl daemon-reload
[root@master ~]# systemctl restart docker
#所有节点都需重新启动服务
[root@master ~]# docker pull httpd
[root@master ~]# docker pull tomcat:8.5.45
[root@master ~]# docker tag httpd:latest 192.168.1.4:5000/httpd:v1
[root@master ~]# docker tag tomcat:8.5.45 192.168.1.4:5000/tomcat:v1
[root@master ~]# docker push 192.168.1.4:5000/httpd:v1
[root@master ~]# docker push 192.168.1.4:5000/tomcat:v1
#下载使用的镜像,并将其上传到私有仓库
[root@master ~]# vim httpd01.yaml
apiVersion: v1
kind: Namespace
metadata:
name: test-ns
#创建名称空间test-ns
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: httpd01
namespace: test-ns
spec:
replicas: 2
template:
metadata:
labels:
app: httpd-01
spec:
containers:
- name: httpd
image: 192.168.1.4:5000/httpd:v1
#使用httpd的镜像创建Deployment资源,副本数量为2个,并打标签为httpd-01
---
apiVersion: v1
kind: Service
metadata:
name: httpd-svc
namespace: test-ns
spec:
selector:
app: httpd-01
ports:
- protocol: TCP
port: 80
targetPort: 80
#创建service资源对象与Deployment资源使用标签的方式进行关联
[root@master ~]# kubectl apply -f httpd01.yaml
[root@master ~]# vim tomcat01.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: tomcat01
namespace: test-ns
spec:
replicas: 2
template:
metadata:
labels:
app: tomcat-01
spec:
containers:
- name: tomcat
image: 192.168.1.4:5000/tomcat:v1
#使用tomcat的镜像创建Deployment资源,副本数量为2个,并打标签为tomcat-01
---
apiVersion: v1
kind: Service
metadata:
name: tomcat-svc
namespace: test-ns
spec:
selector:
app: tomcat-01
ports:
- protocol: TCP
port: 8080
targetPort: 8080
#创建service资源对象与Deployment资源使用标签的方式进行关联
[root@master ~]# kubectl apply -f tomcat01.yaml
[root@master ~]# kubectl get pod -n test-ns #确保pod正常运行
NAME READY STATUS RESTARTS AGE
httpd01-6575d9cdcd-kjcmm 1/1 Running 0 13m
httpd01-6575d9cdcd-tjkwk 1/1 Running 0 13m
tomcat01-65b74df4d4-6b9vz 1/1 Running 0 11m
tomcat01-65b74df4d4-wfhfz 1/1 Running 0 11m
[root@master ~]# kubectl get svc -n test-ns #确保service创建成功
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
httpd-svc ClusterIP 10.104.32.150 <none> 80/TCP 13m
tomcat-svc ClusterIP 10.99.184.215 <none> 8080/TCP 11m
[root@master ~]# curl -I 10.104.32.150
HTTP/1.1 200 OK
Date: Fri, 21 Feb 2020 11:09:16 GMT
Server: Apache/2.4.41 (Unix)
Last-Modified: Mon, 11 Jun 2007 18:53:14 GMT
ETag: "2d-432a5e4a73a80"
Accept-Ranges: bytes
Content-Length: 45
Content-Type: text/html
[root@master ~]# curl -I 10.99.184.215:8080
HTTP/1.1 200
Content-Type: text/html;charset=UTF-8
Transfer-Encoding: chunked
Date: Fri, 21 Feb 2020 11:09:28 GMT
#访问SVC的clusterIP+端口,确定可以访问到后端Pod
创建ingress-nginx资源所使用的镜像链接:https://pan.baidu.com/s/1skhA3jSCH7-c-iStCXbuNQ
提取码:nx6o
获取Ingress-nginx的yaml文件,方法如下:
[root@master ~]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.29.0/deploy/static/mandatory.yaml
[root@master ~]# vim mandatory.yaml
#对下载的yaml文件进行简单的修改
spec: #定位到212行,也就是该行
hostNetwork: true #添加该行,表示使用主机网络
# wait up to five minutes for the drain of connections
terminationGracePeriodSeconds: 300
serviceAccountName: nginx-ingress-serviceaccount
nodeSelector:
Ingress: nginx ##设置节点的标签选择器,指定在哪台节点上运行
containers:
- name: nginx-ingress-controller
image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.29.0
#该资源使用的镜像,该镜像下载较慢,可使用步骤开头提供的网盘链接!
[root@master ~]# kubectl label nodes node01 Ingress=nginx
#对node01节点打相应的标签,以便指定Ingress-nginx运行在node01
[root@master ~]# kubectl get nodes node01 --show-labels
#查看node01的标签是否存在
[root@node01 ~]# docker load < nginx-ingress.tar
#node01节点导入镜像(也可自行下载)
[root@master ~]# kubectl apply -f mandatory.yaml
关于上面yaml文件中写入的“hostNetwork: true”具体解释:如果添加了此字段,意味着pod中运行的应用可以直接使用node节点的端口,这样node节点主机所在网络的其他主机,就可以通过访问该端口访问此应用。(类似于docker映射到宿主机的端口。)
[root@master ~]# kubectl get pod -n ingress-nginx -o wide
#确认Ingress-nginx容器正常运行
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-ingress-controller-577ffd8c54-zntwl 1/1 Running 0 9s 192.168.1.5 node01 <none> <none>
[root@master ~]# vim ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-ingress
namespace: test-ns
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: www.lzj.com
http:
paths:
- path: /
backend:
serviceName: httpd-svc
servicePort: 80
- path: /tomcat
backend:
serviceName: tomcat-svc
servicePort: 8080
#通过www.lzj.com 来访问到我们后端httpd容器提供的服务;
#通过www.lzj.com/tomcat 来访问我们后端tomcat提供的服务
[root@master ~]# kubectl apply -f ingress.yaml
ingress.extensions/test-ingress created
[root@master ~]# kubectl get ingresses. -n test-ns
#创建Ingress资源对象
NAME HOSTS ADDRESS PORTS AGE
test-ingress www.lzj.com 80 23s
其实,至此已经实现了我们想要的功能,前提是自行配置DNS解析,或者直接修改client的hosts文件。访问页面如下(注意:一定要自己解决域名解析的问题,若不知道域名对应的是哪个IP,请跳过这两个图,看下面的文字解释):
访问httpd服务(自定义首页内容):
访问tomcat服务:
在上面的访问测试中,虽然访问到了对应的服务,但是有一个弊端,就是在做DNS解析的时候,只能指定Ingress-nginx容器所在的节点IP。而指定k8s集群内部的其他节点IP(包括master)都是不可以访问到的,如果这个节点一旦宕机,Ingress-nginx容器被转移到其他节点上运行(不考虑节点标签的问题,其实保持Ingress-nginx的yaml文件中默认的标签的话,那么每个节点都是有那个标签的)。随之还要我们手动去更改DNS解析的IP(要更改为Ingress-nginx容器所在节点的IP,通过命令“kubectl get pod -n ingress-nginx -o wide”可以查看到其所在节点),很是麻烦。
有没有更简单的一种方法呢?答案是肯定的,就是我们为Ingress-nginx规则再创建一个类型为nodePort的Service,这样,在配置DNS解析时,就可以使用www.lzj.com 绑定所有node节点,包括master节点的IP了,很是灵活。
在刚才获取Ingress-controller资源对象的yaml文件的页面,然后下拉页面,即可看到以下,可以根据k8s集群环境来选择适合自己的yaml文件。假如自己是在Azure云平台搭建的K8s集群,则选择复制Azure下面的命令即可,我这里是自己的测试环境,所以选择Bare-metal下面的yaml文件,如图:
创建这个Service有两种方法:一是直接复制其web页面的命令到master节点上执行,二是将其链接地址复制到终端使用wget下载下来再执行,本次采用第二种方法,顺便可以查看文件中内容。
[root@master ~]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.29.0/deploy/static/provider/baremetal/service-nodeport.yaml
[root@master ~]# cat service-nodeport.yaml
apiVersion: v1
kind: Service
metadata:
name: ingress-nginx
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
spec:
type: NodePort
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP
- name: https
port: 443
targetPort: 443
protocol: TCP
selector:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
---
[root@master ~]# kubectl apply -f service-nodeport.yaml
[root@master ~]# kubectl get svc -n ingress-nginx
#查看运行的service对象
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx NodePort 10.96.121.169 <none> 80:30487/TCP,443:31117/TCP 21s
#可以看到service分别将80和443端口映射到了节点的30487和31111端口(随机映射的,也可以修改yaml文件指定端口)
至此,这个www.lzj.com 的域名即可和群集中任意节点的30487/31111端口进行绑定了。
测试如下(域名解析对应的IP可以是k8s群集内的任意节点IP):
至此,就实现了最初的需求!
如果需要将www.lzj.com 和www.zhj.com 都对应上后端的pod容器所运行的服务。应进行以下配置:
[root@master ~]# vim ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-ingress
namespace: test-ns
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: www.lzj.com
http:
paths:
- path: /
backend:
serviceName: httpd-svc
servicePort: 80
- path: /tomcat
backend:
serviceName: tomcat-svc
servicePort: 8080
- host: www.zhj.com #就是将原本的域名对应的svc服务复制一份,更改一下域名而已!
http:
paths:
- path: /
backend:
serviceName: httpd-svc
servicePort: 80
- path: /tomcat
backend:
serviceName: tomcat-svc
servicePort: 8080
[root@master ~]# kubectl apply -f ingress.yaml
至此,即可实现访问www.lzj.com 和www.zhj.com 都可以访问到后端的httpd提供的页面(自行解决域名解析问题),如下:
Ingress-nginx资源的流程总结,如图:
从图中可以看出:后端有多个pod,pod与service进行关联,service又被ingress规则发现并动态写入到ingress-nginx-controller容器中,然后又为ingress-nginx-controller创建了一个Service映射到群集节点上的端口,来供client来访问。
在真正的生产环境中,创建Ingress Controller肯定使用的是DaemonSet资源类型,来保证Ingress Controller的高可用!
在上面的操作中,实现了使用ingress-nginx为后端所有pod提供一个统一的入口,那么,有一个非常严肃的问题需要考虑,就是如何为我们的pod配置CA证书来实现HTTPS访问?在pod中直接配置CA么?那需要进行多少重复性的操作?而且,pod是随时可能被kubelet杀死再创建的。当然这些问题有很多解决方法,比如直接将CA配置到镜像中,但是这样又需要很多个CA证书。
在上面的一系列流程中,关键的点就在于ingress规则,我们只需要在ingress的yaml文件中,为域名配置CA证书即可,只要可以通过HTTPS访问到域名,至于这个域名是怎么关联到后端提供服务的pod,这就是属于k8s群集内部的通信了,即便是使用http来通信,也无伤大雅。
为了简单起见,以下配置在上述环境下执行以下配置:
[root@node01 ~]# openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginxsvc/O=nginxsvc"
#创建CA证书
[root@node01 ~]# ls | grep tls #确认产生了以下两个文件
tls.crt
tls.key
[root@master ~]# kubectl create secret tls tls-secret --key=tls.key --cert tls.crt
#创建secret资源对象
[root@master ~]# kubectl describe secrets tls-secret
#查看secret资源对象详细信息
Name: tls-secret
Namespace: default
Labels: <none>
Annotations: <none>
Type: kubernetes.io/tls
Data
====
tls.crt: 1143 bytes
tls.key: 1704 bytes
[root@master ~]# vim ingress.yaml
#对Ingresss资源对象进行修改
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-ingress
namespace: test-ns
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
tls: #在原本的基础上添加以下内容即可
- hosts:
- www.lzj.com
- www.zhj.com
secretName: tls-secret #填写须使用该证书的域名及证书的名称
rules:
- host: www.lzj.com
http:
paths:
- path: /
backend:
serviceName: httpd-svc
servicePort: 80
- path: /tomcat
backend:
serviceName: tomcat-svc
servicePort: 8080
- host: www.zhj.com
http:
paths:
- path: /
backend:
serviceName: httpd-svc
servicePort: 80
- path: /tomcat
backend:
serviceName: tomcat-svc
servicePort: 8080
[root@master ~]# kubectl apply -f ingress.yaml
[root@master ~]# kubectl describe ingresses. test-ingress -n test-ns
#查看Ingress-nginx的详细信息
Name: test-ingress
Namespace: test-ns
Address: 10.96.121.169
Default backend: default-http-backend:80 (<none>)
TLS: #确认该证书已经绑定到对应的域名上
tls-secret terminates www.lzj.com,www.zhj.com
Rules:
Host Path Backends
---- ---- --------
www.lzj.com
/ httpd-svc:80 (10.244.1.9:80,10.244.2.8:80)
/tomcat tomcat-svc:8080 (10.244.1.10:8080,10.244.2.9:8080)
www.zhj.com
/ httpd-svc:80 (10.244.1.9:80,10.244.2.8:80)
/tomcat tomcat-svc:8080 (10.244.1.10:8080,10.244.2.9:8080)
访问测试:
———————— 本文至此结束,感谢阅读 ————————
标签:规则 create 重复 data grep 详细信息 关联 sts client
原文地址:https://blog.51cto.com/14157628/2472849