深刻玩轉K8S以外網如何訪問業務應用(nginx-ingress篇)

前面的文章介紹瞭如何安裝kubernetes集羣,集羣部署完畢以後就能夠在上面部署服務了。服務部署完以後如何訪問集羣中的服務呢? 
訪問部署在kubernetes中的服務有兩種狀況,一種是在kubernetes集羣內部訪問,另外一種是在集羣外部訪問服務。html

在集羣內部訪問

Clusterip

Clusterip是集羣內部的私有ip,在集羣內部訪問服務很是方便,直接經過service的Clusterip訪問。若是安裝了kube-dns能夠使用serviceName的方式訪問服務。node

請看下面例子 
建立一個nginx服務,名稱是my-nginxnginx

[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服務git

[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都同樣。 
看下面例子github

#刪除my-nginxkubectl delete svc/my-nginx
kubectl delete deploy/my-nginx123

修改my-nginx.yaml增長NodePort,在每一個節點內部暴露30001端口web

[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.84apache

在集羣以外,經過任何一個節點的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服務api

這裏不作介紹了服務器

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 
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/

本文轉載自:https://blog.csdn.net/newcrane/article/details/79092577

相關文章
相關標籤/搜索