• Kubernetes的负载均衡问题(Nginx Ingress)


    Kubernetes关于服务的暴露主要是通过NodePort方式,通过绑定minion主机的某个端口,然后进行pod的请求转发和负载均衡,但这种方式下缺陷是

    • Service可能有很多个,如果每个都绑定一个node主机端口的话,主机需要开放外围一堆的端口进行服务调用,管理混乱
    • 无法应用很多公司要求的防火墙规则

    理想的方式是通过一个外部的负载均衡器,绑定固定的端口,比如80,然后根据域名或者服务名向后面的Service ip转发,Nginx很好的解决了这个需求,但问题是如果有新的服务加入,如何去修改Nginx的配置,并且加载这些配置? Kubernetes给出的方案就是Ingress,Ingress包含了两大主件Ingress Controller和Ingress.

    • Ingress解决的是新的服务加入后,域名和服务的对应问题,基本上是一个ingress的对象,通过yaml进行创建和更新进行加载。
    • Ingress Controller是将Ingress这种变化生成一段Nginx的配置,然后将这个配置通过Kubernetes API写到Nginx的Pod中,然后reload.

     

    具体实现如下:

    1.生成一个默认的后端,如果遇到解析不到的URL就转发到默认后端页面

    [root@k8s-master ingress]# cat default-backend.yaml 
    apiVersion: extensions/v1beta1
    kind: Deployment
    metadata:
      name: default-http-backend
      labels:
        k8s-app: default-http-backend
      namespace: kube-system
    spec:
      replicas: 1
      template:
        metadata:
          labels:
            k8s-app: default-http-backend
        spec:
          terminationGracePeriodSeconds: 60
          containers:
          - name: default-http-backend
            # Any image is permissable as long as:
            # 1. It serves a 404 page at /
            # 2. It serves 200 on a /healthz endpoint
            image: gcr.io/google_containers/defaultbackend:1.0
            livenessProbe:
              httpGet:
                path: /healthz
                port: 8080
                scheme: HTTP
              initialDelaySeconds: 30
              timeoutSeconds: 5
            ports:
            - containerPort: 8080
            resources:
              limits:
                cpu: 10m
                memory: 20Mi
              requests:
                cpu: 10m
                memory: 20Mi
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: default-http-backend
      namespace: kube-system
      labels:
        k8s-app: default-http-backend
    spec:
      ports:
      - port: 80
        targetPort: 8080
      selector:
        k8s-app: default-http-backend

    2.部署Ingress Controller

    具体文件可以参考官方的

    https://github.com/kubernetes/ingress/blob/master/examples/daemonset/nginx/nginx-ingress-daemonset.yaml

    这里贴一个我的

    [root@k8s-master ingress]# cat nginx-ingress-controller.yaml 
    apiVersion: v1
    kind: ReplicationController
    metadata:
      name: nginx-ingress-lb
      labels:
        name: nginx-ingress-lb
      namespace: kube-system
    spec:
      replicas: 1
      template:
        metadata:
          labels:
            name: nginx-ingress-lb
          annotations:
            prometheus.io/port: '10254'
            prometheus.io/scrape: 'true'
        spec:
          terminationGracePeriodSeconds: 60
          hostNetwork: true
          containers:
          - image: gcr.io/google_containers/nginx-ingress-controller:0.9.0-beta.7
            name: nginx-ingress-lb
            readinessProbe:
              httpGet:
                path: /healthz
                port: 10254
                scheme: HTTP
            livenessProbe:
              httpGet:
                path: /healthz
                port: 10254
                scheme: HTTP
              initialDelaySeconds: 10
              timeoutSeconds: 1
            ports:
            - containerPort: 80
              hostPort: 80
            - containerPort: 443
              hostPort: 443
            env:
              - name: POD_NAME
                valueFrom:
                  fieldRef:
                    fieldPath: metadata.name
              - name: POD_NAMESPACE
                valueFrom:
                  fieldRef:
                    fieldPath: metadata.namespace
              - name: KUBERNETES_MASTER
                value: http://192.168.0.105:8080
            args:
            - /nginx-ingress-controller
            - --default-backend-service=$(POD_NAMESPACE)/default-http-backend
            - --apiserver-host=http://192.168.0.105:8080

    曾经出现的问题是,启动后pod总是在CrashLoopBack的状态,通过logs一看发现nginx-ingress-controller的启动总是去连接apiserver内部集群ip的443端口,导致因为安全问题不让启动,后来在args里面加入

    - --apiserver-host=http://192.168.0.105:8080

    后成功启动.

    3.配置ingress

     配置如下

    [root@k8s-master ingress]# cat dashboard-weblogic.yaml 
    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      name: dashboard-weblogic-ingress
      namespace: kube-system
    spec:
      rules:
      - host: helloworld.eric
        http:
          paths:
          - path: /console
            backend:
              serviceName: helloworldsvc 
              servicePort: 7001
          - path: /
            backend:
              serviceName: kubernetes-dashboard
              servicePort: 80

    理解如下:

    • host指虚拟出来的域名,具体地址(我理解应该是Ingress-controller那台Pod所在的主机的地址)应该加入/etc/hosts中,这样所有去helloworld.eric的请求都会发到nginx
    • path:/console匹配后面的应用路径
    • servicePort主要是定义服务的时候的端口,不是NodePort.
    • path:/ 匹配后面dashboard应用的路径,以前通过访问master节点8080/ui进入dashboard的,但dashboard其实是部署在minion节点中,实际是通过某个路由语句转发过去而已,dashboard真实路径如下:

    而yaml文件是

    [root@k8s-master ~]# cat kubernetes-dashboard.yaml 
    apiVersion: extensions/v1beta1
    kind: Deployment
    metadata:
    # Keep the name in sync with image version and
    # gce/coreos/kube-manifests/addons/dashboard counterparts
      name: kubernetes-dashboard-latest
      namespace: kube-system
    spec:
      replicas: 1
      template:
        metadata:
          labels:
            k8s-app: kubernetes-dashboard
            version: latest
            kubernetes.io/cluster-service: "true"
        spec:
          containers:
          - name: kubernetes-dashboard
            image: gcr.io/google_containers/kubernetes-dashboard-amd64:v1.5.1
            resources:
              # keep request = limit to keep this container in guaranteed class
              limits:
                cpu: 100m
                memory: 50Mi
              requests:
                cpu: 100m
                memory: 50Mi
            ports:
            - containerPort: 9090
            args:
             -  --apiserver-host=http://192.168.0.105:8080
            livenessProbe:
              httpGet:
                path: /
                port: 9090
              initialDelaySeconds: 30
              timeoutSeconds: 30
    ---
    kind: Service
    metadata:
      name: kubernetes-dashboard
      namespace: kube-system
      labels:
        k8s-app: kubernetes-dashboard
        kubernetes.io/cluster-service: "true"
    spec:
      selector:
        k8s-app: kubernetes-dashboard
      ports:
      - port: 80
        targetPort: 9090

    所以访问192.168.51.5:9090端口就会出现dashboard

    4.测试 

    Ok,一切就绪,装逼开始

    访问http://helloworld.eric/console 

    访问http://helloword.eric/    出现dashboard

    5.配置TLS SSL访问

    TLS的配置相当于WebLogic中证书的配置,配置过程如下

    • 证书生成
    # 生成 CA 自签证书
    mkdir cert && cd cert
    openssl genrsa -out ca-key.pem 2048
    openssl req -x509 -new -nodes -key ca-key.pem -days 10000 -out ca.pem -subj "/CN=kube-ca"
    
    # 编辑 openssl 配置
    cp /etc/pki/tls/openssl.cnf .
    vim openssl.cnf
    
    # 主要修改如下
    [req]
    req_extensions = v3_req # 这行默认注释关着的 把注释删掉
    # 下面配置是新增的
    [ v3_req ]
    basicConstraints = CA:FALSE
    keyUsage = nonRepudiation, digitalSignature, keyEncipherment
    subjectAltName = @alt_names
    [alt_names]
    DNS.1 = helloworld.eric
    #DNS.2 = kibana.mritd.me
    
    # 生成证书
    openssl genrsa -out ingress-key.pem 2048
    openssl req -new -key ingress-key.pem -out ingress.csr -subj "/CN=helloworld.eric" -config openssl.cnf
    openssl x509 -req -in ingress.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out ingress.pem -days 365 -extensions v3_req -extfile openssl.cnf

    需要注意的是DNS需要修改成自己的host名,然后在配置csr证书请求的时候需要将域名或者访问名带入subj,比如

    -subj "/CN=helloworld.eric" 
    • 创建secret
    kubectl create secret tls ingress-secret --namespace=kube-system --key cert/ingress-key.pem --cert cert/ingress.pem 
    • 修改Ingress文件启用证书
    [root@k8s-master ingress]# cat tls-weblogic.yaml 
    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      name: dashboard-weblogic-ingress
      namespace: kube-system
    spec:
      tls:
      - hosts:
        - helloworld.eric
        secretName: ingress-secret
      rules:
      - host: helloworld.eric
        http:
          paths:
          - path: /console
            backend:
              serviceName: helloworldsvc 
              servicePort: 7001
          - path: /
            backend:
              serviceName: kubernetes-dashboard
              servicePort: 80
    •  测试

     然后访问helloworld.eric/console,会自动转到https页面,同时查看证书并加入授信列表,可见

    访问helloworld.eric

  • 相关阅读:
    关于二分操作的基本应用
    东北育才 d1t4 漂流
    东北育才 d1t1 优雅的序列
    从零开始的图的存储方法
    从零理解的KMP算法
    openjudge T017 黑社会团伙 (并查集)
    东北育才 day6
    poj3071 Football
    noip2015 跳石头
    noip2015 信息传递
  • 原文地址:https://www.cnblogs.com/ericnie/p/6965091.html
Copyright © 2020-2023  润新知