k8s ingress实现方案

Posted leechm_liqi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了k8s ingress实现方案相关的知识,希望对你有一定的参考价值。

目录

基本介绍

如何构建ingress controller

nginx容器服务的部署

1. ingress HTTP代理访问

2. ingress HTTPS代理访问

3. Nginx 进行 BasicAuth基础认证

4. Nginx 进行重写


对于我们传统的SVC来说,它只支持四层反向代理,但是如果遇到七层的话,就无法去实现,如下:

假如说,我们有如上的一个集群,我们现在想要对整个集群,或者是Apache进行https的加密访问,也就是我们的客户端想要跟我们的Apache进行HTTPS访问,我们完全不需要在每一台Apache上配置我们的HTTPS,我们只需要在nginx上开启HTTPS认证即可。。。。当我们的客户访问到NGINX的时候,由于NGINX和客户端之间是加密访问,NGINX因为本地没有数据,它会向后端进行反向代理,反向代理的时候走是HTTPS协议,但是NGINX和Apache都是在一个集群之下,属于内部访问(clusterIp)的形式,所以也没有必要采用HTTPS连接,但是NGINX对外部的话,都是采用HTTPS连接,此时NGINX的作用相当于是HTTPS会话卸载的目的。

如果放在我们的k8s集群之中的话,若仅仅通过svc的方式去实现一个加密访问的话,就需要在每个Apache上配置一个HTTPS加密认证证书,然后在默认的svc上进行所谓的HTTPS连接,这样是不友好的,因为HTTPS加密认证的消耗资源还是挺大的。

基本介绍

先简单介绍一下ingress的方案实现

1. ingress-haproxy

2. ingress-nginx

这里只介绍nginx的实现方案

分析:首先我们的客户端先访问至我们的域名,也就是说对于ingress来说,我们必须要绑定一个域名(或者多个也行),毕竟实现的是一个七层的代理,不同的域名会访问至我们的Nginx软件,Nginx会反向代理或者是负载均衡至后端的服务,这些service会对应我们的容器服务。

上面的流程,我们需要了解个问题,

1. Nginx就是如何跟我们的后端服务(容器)进行连接的?

其实对于Nginx的暴露方案,还是我们的NodePort,这样Nginx就会以内部的服务暴露给外部用户,然后外部用户就可以访问到我们的Nginx,然后Nginx连接不同的service。也就是说我们也需要创建对应容器服务的svc与Nginx进行关联。

ingress修改之后的nginx内部的实现方案

如何构建ingress controller

Ingress-Nginx 官方网站:https://kubernetes.github.io/ingress-nginx/

ingress-nginx Gitee地址:https://gitee.com/leechm/k8s-ingress-nginx.git

去ingress-nginx的码云地址下载对应的ingress-nginx版本,就可以去部署了

[root@master1 ingress]# git clone -b nginx-0.25.0 https://gitee.com/leechm/k8s-ingress-nginx.git
[root@master1 static]# pwd
/root/k8s/test/ingress/k8s-ingress-nginx/deploy/static
[root@master1 static]# kubectl apply -f ./

注意,若报错如下:

Failed to list *v1beta1.Ingress: ingresses.networking.k8s.io is forbidden.......

编辑ingress的 mandatory.yaml 在ClusterRole位置添加下述代码然后重新replace -f 即可

- apiGroups:
      - "extensions"
      - "networking.k8s.io"
    resources:
      - ingresses
    verbs:
      - list
      - watch

最后部署成功如下:

[root@master1 static]# kubectl get pod -n ingress-nginx 
NAME                                        READY   STATUS    RESTARTS   AGE
nginx-ingress-controller-7995bd9c47-9q2gt   1/1     Running   4          7m47s
[root@master1 static]# 

然后为Ingress Controller 创建一个NodePort 类型得Service

[root@master1 static]# kubectl apply -f  ./provider/baremetal/service-nodeport.yaml 
service/ingress-nginx created
[root@master1 static]# kubectl get svc -n ingress-nginx 
NAME            TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx   NodePort   10.1.39.237   <none>        80:31531/TCP,443:32449/TCP   11s
[root@master1 static]# 

这样我们的nginx controller就已经暴露出去了

service-nodeport.yaml文件,这个文件得目的是为Ingress Controller 接入外部得流量,如果没有这个文件,是无法通过外部浏览器访问的。nginx controller部署完成之后,我们进行代理方案的试验,即开始服务的部署。

nginx容器服务的部署

下面的三种访问方式,其实最主要的区别在于Ingress这个类型的不一样,像Deployment和它对于的Service都是一样的,所以我们可以只创建一次Deployment和Service,但是我下面的步骤,创建了三次,这个可忽略啊。

1. ingress HTTP代理访问

deployment、Service、Ingress Yaml 文件

[root@master1 ingress]# cat ingress-depl-http.yaml 
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx-dm
spec:
  replicas: 2
  template:
    metadata:
      labels:
        name: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:alpine
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
spec:
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  selector:
    name: nginx
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: nginx-test
spec:
  rules:
    - host: www.leechm.com
      http:
        paths:
        - path: /
          backend:
            serviceName: nginx-svc
            servicePort: 80
[root@master1 ingress]# 
[root@master1 ingress]# kubectl get svc -A
NAMESPACE       NAME            TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)                      AGE
default         kubernetes      ClusterIP   10.1.0.1       <none>        443/TCP                      20h
default         myapp           ClusterIP   10.1.220.137   <none>        80/TCP                       17h
default         nginx-svc       ClusterIP   10.1.57.234    <none>        80/TCP                       2m52s
ingress-nginx   ingress-nginx   NodePort    10.1.39.237    <none>        80:31531/TCP,443:32449/TCP   11m
kube-system     kube-dns        ClusterIP   10.1.0.10      <none>        53/UDP,53/TCP,9153/TCP       20h
[root@master1 ingress]# kubectl get ingresses -A
NAMESPACE   NAME         HOSTS            ADDRESS   PORTS   AGE
default     nginx-test   www.leechm.com             80      13m

我们的nginx-svc是一个ClusterIP 的形式,这个仅供集群内部访问,但是我们这里有一个ingress-nginx与之绑定,并且ingress-nginx是以NodePort 形式。因为我们物理机此时还没有进行域名解析,此时需要去设置一下

C:\\Windows\\System32\\drivers\\etc

通过浏览器访问

2. ingress HTTPS代理访问

创建证书,以及 cert 存储方式

[root@master1 https] openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginxsvc/O=nginxsvc" 
[root@master1 https] kubectl create secret tls tls-secret --key tls.key --cert tls.crt

deployment、Service、Ingress Yaml 文件

[root@master1 https]# cat ingress-depl-https.yaml 
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx-dm
spec:
  replicas: 2
  template:
    metadata:
      labels:
        name: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:alpine
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
spec:
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  selector:
    name: nginx
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: nginx-test-https
spec:
  tls:
    - hosts:
      - www1.leechm.com
      secretName: tls-secret
  rules:
    - host: www1.leechm.com
      http:
        paths:
        - path: /
          backend:
            serviceName: nginx-svc
            servicePort: 80
[root@master1 https]# 
[root@master1 https]# kubectl get svc -n ingress-nginx 
NAME            TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx   NodePort   10.1.39.237   <none>        80:31531/TCP,443:32449/TCP   96m
[root@master1 https]# 

添加Windows域名解析

注意:为啥443端口是加密访问,这个得从我们之前部署nginx的时候,对于80端口是HTTP,443端口是HTTPS。

3. Nginx 进行 BasicAuth基础认证

[root@master1 basic-auth]# yum -y install httpd 
[root@master1 basic-auth]# htpasswd -c auth foo 
New password: 
Re-type new password: 
Adding password for user foo
[root@master1 basic-auth]# kubectl create secret generic basic-auth --from-file=auth
secret/basic-auth created
[root@master1 basic-auth]# 
[root@master1 basic-auth]# kubectl apply -f basic-auth.yaml 
deployment.extensions/nginx-dm unchanged
service/nginx-svc unchanged
ingress.extensions/ingress-with-auth created

deployment、Service、Ingress Yaml 文件

[root@master1 basic-auth]# cat basic-auth.yaml 
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx-dm
spec:
  replicas: 2
  template:
    metadata:
      labels:
        name: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:alpine
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
spec:
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  selector:
    name: nginx
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-with-auth
  annotations:
    nginx.ingress.kubernetes.io/auth-type: basic
    nginx.ingress.kubernetes.io/auth-secret: basic-auth
    nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - foo'
spec:
  rules:
  - host: www2.leechm.com
    http:
      paths:
      - path: /
        backend:
          serviceName: nginx-svc
          servicePort: 80

[root@master1 basic-auth]# 

记得添加Windows域名,然后访问一下,输入账号密码即可

4. Nginx 进行重写

[root@master1 basic-auth]# cat basic-auth-rewrite.yaml 
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx-dm
spec:
  replicas: 2
  template:
    metadata:
      labels:
        name: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:alpine
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
spec:
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  selector:
    name: nginx
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: nginx-test
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: http://www2.leechm.com:31531/
spec:
  rules:
  - host: www.re.com
    http:
      paths:
      - path: /
        backend:
          serviceName: nginx-svc
          servicePort: 8
[root@master1 basic-auth]# 

添加Windows域名关系

192.168.64.150 www.re.com

上面的basic-auth-rewrite.yaml 实现的效果就是通过访问www.re.com:31531,地址跳转到http://www2.leechm.com:31531/

补充:

我们的nginx-ingress-controller这个的作用就是实现反向代理

[root@master1 basic-auth]# kubectl get pod -n ingress-nginx 
NAME                                        READY   STATUS    RESTARTS   AGE
nginx-ingress-controller-7995bd9c47-9q2gt   1/1     Running   5          148m

我们可以进入看看

[root@master1 ingress]# kubectl exec -it nginx-ingress-controller-7995bd9c47-9q2gt -n ingress-nginx bash

www-data@nginx-ingress-controller-7995bd9c47-9q2gt:/etc/nginx$ cat nginx.conf

Ingress Controller 会动态感知集群中的Ingress的规则变化,然后读取,动态生成Nginx的配置文件,最后注入到运行nginx的pod的中,然后会自动reload,配置生效,例如:

以上是关于k8s ingress实现方案的主要内容,如果未能解决你的问题,请参考以下文章

企业运维实战--k8s学习笔记 通过Ingress-nginx实现k8s七层负载均衡Ingress加密认证以及地址重写

K8S基于ingress-nginx实现灰度发布

k8s 通过 Ingress-nginx 高可用 实现灰度发布

k8s 通过 Ingress-nginx 高可用 实现灰度发布

k8s ingress实现http/https7层和tcp四层代理

K8S基于ingress-nginx实现灰度发布