深入玩转K8S之外网如何访问业务应用(nginx-ingress篇)

前面的文章介绍了如何安装kubernetes集群,集群部署完毕之后就可以在上面部署服务了。服务部署完之后如何访问集群中的服务呢?  访问部署在kubernetes中的服务有两种情况,一种是在kubernetes...

前面的文章介绍了如何安装kubernetes集群,集群部署完毕之后就可以在上面部署服务了。服务部署完之后如何访问集群中的服务呢? 

访问部署在kubernetes中的服务有两种情况,一种是在kubernetes集群内部访问,另一种是在集群外部访问服务。


在集群内部访问

Clusterip

Clusterip是集群内部的私有ip,在集群内部访问服务非常方便,直接通过service的Clusterip访问。如果安装了kube-dns可以使用serviceName的方式访问服务。


请看下面例子 

创建一个nginx服务,名称是my-nginx


[root@vmnode1 ~]# cat my-nginx.yaml 

apiVersion: extensions/v1beta1

kind: Deployment

metadata:

  name: my-nginx

spec:

  replicas: 2

  template:

    metadata:

      labels:

        run: my-nginx

    spec:

      containers:

      - name: my-nginx

        image: nginx:1.7.9

        ports:

        - containerPort: 80

# 创建my-nginx

[root@vmnode1 ~]# kubectl create -f ./my-nginx.yaml

[root@vmnode1 ~]# kubectl expose deploy my-nginx

[root@vmnode1 ~]# kubectl get svc

NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE

kubernetes   ClusterIP   10.254.0.1      <none>        443/TCP   36d

my-nginx     ClusterIP   10.254.180.15   <none>        80/TCP    6m

在集群中创建一个pod,通过ServiceName访问nginx服务


[root@vmnode1 ~]# kubectl run -it --image=radial/busyboxplus  sh


##通过ServerName访问nginx

/ # curl http://my-nginx<!DOCTYPE html><html><head><title>Welcome to nginx!</title><style>

    body {        width: 35em;        margin: 0 auto;        font-family: Tahoma, Verdana, Arial, sans-serif;    }</style></head><body><h1>Welcome to nginx!</h1><p>If you see this page, the nginx web server is successfully installed and

working. Further configuration is required.</p><p>For online documentation and support please refer to<a href="http://nginx.org/">nginx.org</a>.<br/>Commercial support is available at<a href="http://nginx.com/">nginx.com</a>.</p><p><em>Thank you for using nginx.</em></p></body></html>

在集群外部访问

1. Nodeport

把service的port映射到每个节点内部指定port上,所有节点内部映射的port都一样。 

看下面例子


#删除my-nginxkubectl delete svc/my-nginx

kubectl delete deploy/my-nginx123

修改my-nginx.yaml增加NodePort,在每个节点内部暴露30001端口


[root@vmnode1 ~]# cat my-nginx.yaml

apiVersion: extensions/v1beta1

kind: Deployment

metadata:  name: my-nginx

spec:

  replicas: 2

  template:

    metadata:

      labels:        run: my-nginx

    spec:

      containers:

      - name: my-nginx

        image: nginx:1.7.9

        ports:

        - containerPort: 80---apiVersion: v1

kind: Service

metadata:  name: my-nginx

  labels:    run: my-nginx

spec:

  type: NodePort

  ports:

  - port: 80

    targetPort: 80

    nodePort: 30001

  selector:    run: my-nginx

  #创建my-nginx服务

  kubectl create -f ./my-nginx.yaml

我的集群由四个几点构成 

vmnode1 192.168.123.81 

vmnode2 192.168.123.82 

vmnode3 192.168.123.83 

vmnode4 192.168.123.84


在集群之外,通过任何一个节点的ip+nodeport都可以访问集群中服务


[root@vmnode5 ~]# curl  

[root@vmnode5 ~]# curl  

[root@vmnode5 ~]# curl  

[root@vmnode5 ~]# curl http://192.168.123.84:30001

2. Loadbalancer

使用NodeIp+Nodeport的方式实现,利用云平台提供的loadbalance服务,像aws、azure、openstack、gce都提供了loadbalance服务


这里不做介绍了


3. Ingress

Ingress 使用开源的反向代理负载均衡器来实现对外暴漏服务,比如 Nginx、Apache、Haproxy等。Nginx Ingress 一般有三个组件组成:


Nginx 反向代理负载均衡器


Ingress Controller 可以理解为控制器,它通过不断的跟 Kubernetes API 交互,实时获取后端 Service、Pod 等的变化,比如新增、删除等,然后结合 Ingress 定义的规则生成配置,然后动态更新上边的 Nginx 负载均衡器,并刷新使配置生效,来达到服务自动发现的作用。


Ingress 则是定义规则,通过它定义某个域名的请求过来之后转发到集群中指定的 Service。它可以通过 Yaml 文件定义,可以给一个或多个 Service 定义一个或多个 Ingress 规则。


下载地址 

https://github.com/kubernetes/ingress-nginx/archive/nginx-0.11.0.tar.gz


ingress-nginx文件位于deploy目录下,各文件的作用:


configmap.yaml:提供configmap可以在线更行nginx的配置


default-backend.yaml:提供一个缺省的后台错误页面 404


namespace.yaml:创建一个独立的命名空间 ingress-nginx


rbac.yaml:创建对应的role rolebinding 用于rbac


tcp-services-configmap.yaml:修改L4负载均衡配置的configmap


udp-services-configmap.yaml:修改L4负载均衡配置的configmap


with-rbac.yaml:有应用rbac的nginx-ingress-controller组件


修改with-rbac.yaml


apiVersion: extensions/v1beta1

kind: Daemonsetmetadata:

  name: nginx-ingress-controller

  namespace: ingress-nginx 

spec:

  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      

      hostNetwork: true

      containers:

        - name: nginx-ingress-controller

          image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.11.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

            - --annotations-prefix=nginx.ingress.kubernetes.io

          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      nodeSelector:

        custom/ingress-controller-ready: "true"

需要修改的地方:


kind: DaemonSet:官方原始文件使用的是deployment,replicate 为 1,这样将会在某一台节点上启动对应的nginx-ingress-controller pod。外部流量访问至该节点,由该节点负载分担至内部的service。测试环境考虑防止单点故障,改为DaemonSet然后删掉replicate ,配合亲和性部署在制定节点上启动nginx-ingress-controller pod,确保有多个节点启动nginx-ingress-controller pod,后续将这些节点加入到外部硬件负载均衡组实现高可用性。


hostNetwork: true:添加该字段,暴露nginx-ingress-controller pod的服务端口(80)


nodeSelector: 增加亲和性部署,有custom/ingress-controller-ready 标签的节点才会部署该DaemonSet


为需要部署nginx-ingress-controller的节点设置lable


kubectl label nodes vmnode2 custom/ingress-controller-ready=true

kubectl label nodes vmnode3 custom/ingress-controller-ready=true

kubectl label nodes vmnode4 custom/ingress-controller-ready=true

加载yaml文件


kubectl create -f namespace.yaml

kubectl create -f default-backend.yaml

kubectl create -f configmap.yaml

kubectl create -f tcp-services-configmap.yaml

kubectl create -f udp-services-configmap.yaml

kubectl create -f rbac.yaml

kubectl create -f with-rbac.yaml

查看pod是否正常创建


##下载镜像可能会比较慢,等待一会所有pod都是Running状态,按Ctrl + c 退出

[root@vmnode1 deploy]# kubectl get pods --namespace=ingress-nginx  --watch

NAME                                    READY     STATUS    RESTARTS   AGEdefault-

http-backend-6c59748b9b-hc8q9   1/1       Running   0          6m

nginx-ingress-controller-7fmlp          1/1       Running   1          13d

nginx-ingress-controller-j95fb          1/1       Running   1          13d

nginx-ingress-controller-ld2jw          1/1       Running   1          13d

测试ingress 

创建一个apache的Service


[root@vmnode1 ~]# cat my-apache.yaml api

Version: extensions/v1beta1

kind: Deployment

metadata:  

name: my-apache

spec:

  replicas: 2

  template:

    metadata:

      labels:        

      run: my-apache

    spec:

      containers:

      - name: my-apache

        image: httpd:2.4

        ports:

        - containerPort: 80

---

apiVersion: v1

kind: Service

metadata:  

name: my-apache

  labels:   

   run: my-apache

spec:

  type: NodePort

  ports:

  - port: 80

    targetPort: 80

    nodePort: 30002

  selector:    

  run: my-apache



[root@vmnode1 ~]# kubectl create -f ./my-apache.yaml my-nginx

不用改,使用上面已经创建好的,如果没有自己创建一下

[root@vmnode1 ~]# cat my-nginx.yamlapi

Version: extensions/v1beta1

kind: Deployment

metadata:  

name: my-nginx

spec:

  replicas: 2

  template:

    metadata:

      labels:        

      run: my-nginx

    spec:

      containers:

      - name: my-nginx

        image: nginx:1.7.9

        ports:

        - containerPort: 80

---

apiVersion: v1

kind: Service

metadata:  

name: my-nginx

  labels:    

  run: my-nginx

spec:

  type: NodePort

  ports:

  - port: 80

    targetPort: 80

    nodePort: 30001

  selector:    

  run: my-nginx

现在集群中有两个服务,一个是my-apache,另一个是my-nginx


[root@vmnode1 ~]# kubectl get svc

NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE

kubernetes   ClusterIP   10.254.0.1     <none>        443/TCP        51d

my-apache    NodePort    10.254.239.1   <none>        80:30002/TCP   8m

my-nginx     NodePort    10.254.66.98   <none>        80:30001/TCP   14d

配置ingress转发文件


[root@vmnode1 ~]# vi test-ingress.yaml

apiVersion: extensions/v1beta1

kind: Ingressmetadata:

  name: test-ingress

  namespace: defaultspec:

  rules:

  - host: test.apache.ingress

    http:

      paths:

      - path: /

        backend:

          serviceName: my-apache

          servicePort: 80

  - host: test.nginx.ingress

    http:

      paths:

      - path: /

        backend:

          serviceName: my-nginx

          servicePort: 80

host: 对应的域名 

path: url上下文 

backend:后向转发 到对应的 serviceName: servicePort:


[root@vmnode1 ~]# kubectl apply -f test-ingress.yaml

[root@vmnode1 ~]# kubectl get ingress

NAME           HOSTS                                    ADDRESS   PORTS     AGE

test-ingress   test.apache.ingress,test.nginx.ingress             80        1m

本文 nginx-ingress-controller运行在vmnode2,vmnode3,vmnode4三个节点上。如果网络中有dns服务器,在dns中把这两个域名映射到nginx-ingress-controller运行的任意一个节点上,如果没有dns服务器只能修改host文件了。


备注: 

正规的做法是在vmnode2,vmnode3,vmnode4这三个节点上安装keepalive,生成一个vip。在dns上把域名和vip做映射。


我这里直接在vmnode1节点上操作了。


##192.168.123.82,192.168.123.83,192.168.123.84 三个ip任选。

[root@vmnode1 ~]# echo '192.168.123.82 test.apache.ingress' >> /etc/hosts

[root@vmnode1 ~]# echo '192.168.123.83 test.nginx.ingress' >> /etc/hosts

测试test.nginx.ingress


[root@vmnode1 ~]# curl test.nginx.ingress

<!DOCTYPE html><html><head><title>Welcome to nginx!</title><style>

    body {        width: 35em;        margin: 0 auto;        font-family: Tahoma, Verdana, Arial, sans-serif;    }</style></head><body><h1>Welcome to nginx!</h1><p>If you see this page, the nginx web server is successfully installed and

working. Further configuration is required.</p><p>For online documentation and support please refer to<a href="http://nginx.org/">nginx.org</a>.<br/>Commercial support is available at<a href="http://nginx.com/">nginx.com</a>.</p><p><em>Thank you for using nginx.</em></p></body></html>

测试test.apache.ingress


[root@vmnode1 ~]# curl test.apache.ingress

<html><body><h1>It works!</h1></body></html>

如果不修改hosts文件可以通过下面的命令测试


##通过-H 指定模拟的域名

[root@vmnode1 ~]# curl -v http://192.168.123.83 -H 'host: test.apache.ingress'

[root@vmnode1 ~]# curl -v http://192.168.123.83 -H 'host: test.nginx.ingress'

参考资料

https://jimmysong.io/kubernetes-handbook/practice/traefik-ingress-installation.html 

https://kubesphere.com.cn/docs/installing-on-linux/introduction/multioverview/

http://blog.csdn.net/hekanhyde/article/details/78672931 

https://github.com/kubernetes/ingress-nginx/tree/master/deploy 

https://kubernetes.io/docs/concepts/services-networking/ingress/

  • 发表于 2021-04-07 02:33
  • 阅读 ( 446 )

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
shitian
shitian

662 篇文章

作家榜 »

  1. shitian 662 文章
  2. 石天 437 文章
  3. 每天惠23 33 文章
  4. 小A 29 文章