- 需求分析说明
大家知道kubernetes中service是通过iptables或者ipvs生产的虚拟IP地址,由于iptables和ipvs是工作在4层的,而这一层是没有办法对第7层的https进协议进行解析,如有kubernetes要提供https的服务,那需要在后端提供服务的pod上配置ssl证书,这样一来在kubernetes内部也是通过https进行访问,这样不仅影响整体访问性能,并且管理大量的证书也将成为问题。那么有什么办法来解决这个问题呢? 答案就是通过Ingress-Control来卸载https,使得内部通信使用http协议,外部通信任然使用https,那为什么ingress-Control能卸载https呢?因为它本来就是一个运行在kubernetes上的一个pod。 -
设计架构图
访问流量设计
- 定义Ingress资源,配置自动注入Ingress-Controller中
- 客户端发起请求流量首先通过https协议到达提供Web服务的Service
- Service将流量调度至关联的Ingress-Contorller
- Ingress-Controller通过定义好的Ingress资源配置将流量调度到后端的pod上
- Ingress-Controller安装
官方文档路径
可参考:https://github.com/kubernetes/ingress-nginx/blob/master/docs/deploy/index.md
该安装步骤花费时间比较长,主要是镜像较大下载比较慢,请耐心等待,大家可以提前下载镜像,
镜像地址 pull image quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.25.0
也可以直接运行以下命令:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml
针对于自己搭建的kubernetes,需要通过nodeport的方式将服务发布至集群外部
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/baremetal/service-nodeport.yaml
添加nodeProt:30080、30443这两个固定端口,前提是所有worknode都没有使用这两个端口。
vim service-nodeport.yaml
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP
nodePort: 30080
- name: https
port: 443
targetPort: 443
protocol: TCP
nodePort: 30443
检查
[root@master ~]# kubectl get pods -n ingress-nginx
NAME READY STATUS RESTARTS AGE
nginx-ingress-controller-7995bd9c47-wjqch 1/1 Running 0 2d1h
[root@master ~]# kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx NodePort 10.111.39.187 <none> 80:30080/TCP,443:30443/TCP 47h
[root@master ~]#
创建后台pod提供web服务,并通过service来管理pod节点
[root@master ingress-nginx]# vim ingress-myapp.yaml
apiVersion: v1
kind: Service
metadata:
name: myingress
namespace: default
spec:
selector:
app: myingress
release: canary
ports:
- name: http
port: 80
targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: myingress-deploy
namespace: default
spec:
replicas: 5
selector:
matchLabels:
app: myingress
release: canary
template:
metadata:
labels:
app: myingress
release: canary
spec:
containers:
- name: myingress
image: ikubernetes/myapp:v2
ports:
- name: http
containerPort: 80
查看关联:myingress关联管理后端的pod
[root@master ingress-nginx]# kubectl describe svc myingress
Name: myingress
Namespace: default
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"myingress","namespace":"default"},"spec":{"ports":[{"name":"http"...
Selector: app=myingress,release=canary
Type: ClusterIP
IP: 10.106.109.93
Port: http 80/TCP
TargetPort: 80/TCP
Endpoints: 10.244.1.38:80,10.244.1.39:80,10.244.2.39:80 + 2 more...
Session Affinity: None
Events: <none>
[root@master ingress-nginx]#
创建自签证书
[root@master ingress-nginx] openssl genrsa -out tls.kye 2048
[root@master ingress-nginx] openssl req -new -x509 -key tls.key -out tls.crt
创建证书资源
[root@master ingress-nginx] kubectl create secret tls nginx-secret --cert=tls.crt --key=tls.key
[root@master ingress-nginx]# kubectl get secret nginx-secret
NAME TYPE DATA AGE
nginx-secret kubernetes.io/tls 2 47h
编辑ingress资源yaml文件
[root@master ingress-nginx]# vim nginx-ssl-ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx-ssl
namespace: default
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
tls:
- hosts:
- nginx.peaoguo.com #server's hostname必须与证书中保持一致
secretName: nginx-secret #kubernetes证书资源名称
rules:
- host: nginx.peaoguo.com #自签证书中的Common Name即server's hostname
http:
paths:
- path:
backend:
serviceName: myingress #关联后端pod的service名称
servicePort: 80 #后端pod web服务端口
创建ingress资源并注入ingress-Controller中
[root@master ingress-nginx]# kubectl apppy -f nginx-ssl-ingress.yaml
查看ingress-Contorller中配置是否生效
[root@master ingress-nginx]# kubectl exec -it nginx-ingress-controller-7995bd9c47-wjqch -n ingress-nginx -- /bin/sh
$ cat nginx.conf
server {
server_name nginx.peaoguo.com ;
listen 80;
set $proxy_upstream_name "-";
set $pass_access_scheme $scheme;
set $pass_server_port $server_port;
set $best_http_host $http_host;
set $pass_port $pass_server_port;
listen 443 ssl http2;
# PEM sha: 4d98ac3d91d0649fb02c4d19c5b2e353a7fb031f
ssl_certificate /etc/ingress-controller/ssl/default-fake-certificate.pem;
ssl_certificate_key /etc/ingress-controller/ssl/default-fake-certificate.pem;
ssl_certificate_by_lua_block {
certificate.call()
}
location / {
set $namespace "default";
set $ingress_name "nginx-ssl";
set $service_name "myingress";
set $service_port "80";
set $location_path "/";
rewrite_by_lua_block {
lua_ingress.rewrite({
force_ssl_redirect = true,
use_port_in_redirects = false,
})
balancer.rewrite()
plugins.run()
}
- 集群内部访问测试
[root@master ingress-nginx]# while true ; do curl -k https://nginx.peaoguo.com:443/hostname.html ;sleep 1 ; done
myingress-deploy-96d96877d-9rckx
myingress-deploy-96d96877d-j6d9d
myingress-deploy-96d96877d-j6d9d
myingress-deploy-96d96877d-9rckx
myingress-deploy-96d96877d-lw7tx
myingress-deploy-96d96877d-lw7tx
myingress-deploy-96d96877d-j6d9d
myingress-deploy-96d96877d-gxgwr
myingress-deploy-96d96877d-lw7tx
myingress-deploy-96d96877d-gxgwr
myingress-deploy-96d96877d-gxgwr
myingress-deploy-96d96877d-qt7c9
myingress-deploy-96d96877d-9rckx
-
集群外部访问
nginx.peaoguo.com
nginx.peaoguo.com/hostname.html
网友评论