Sonar无法通过istio虚拟服务访问,但可以通过端口转发在本地访问

Sonar cannot be access via istio virtual service but can be locally accessed after port forwarding

我正在尝试在 Kubernetes 集群中实施 SonarQube。部署 运行 正确,并且还通过虚拟服务公开。我可以通过 localhost:port/sonar 打开 UI 但我无法通过我的外部 ip 访问它。我知道声纳绑定到本地主机并且不允许从远程服务器外部访问。我 运行 在 GKE 上使用 MYSQL 数据库。这是我的 YAML 文件:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: sonarqube
  namespace: sonar
  labels:
    service: sonarqube
    version: v1
spec:
  replicas: 1
  template:
    metadata:
      name: sonarqube
      labels:
        name: sonarqube
    spec:
      terminationGracePeriodSeconds: 15
      initContainers:
        - name: volume-permission
          image: busybox
          command:
            - sh
            - -c
            - sysctl -w vm.max_map_count=262144
          securityContext:
            privileged: true
      containers:
        - name: sonarqube
          image: sonarqube:6.7
          resources:
            limits:
              memory: 4Gi
              cpu: 2
            requests:
              memory: 2Gi
              cpu: 1
          args:
            - -Dsonar.web.context=/sonar
            - -Dsonar.web.host=0.0.0.0
          env:
            - name: SONARQUBE_JDBC_USERNAME
              valueFrom:
                secretKeyRef:
                  name: cloudsql-db-credentials
                  key: username
            - name: SONARQUBE_JDBC_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: cloudsql-db-credentials
                  key: password
            - name: SONARQUBE_JDBC_URL
              value: jdbc:mysql://***.***.**.*:3306/sonar?useUnicode=true&characterEncoding=utf8
          ports:
            - containerPort: 9000
              name: sonarqube-port
---
apiVersion: v1
kind: Service
metadata:
  labels:
    service: sonarqube
    version: v1
  name: sonarqube
  namespace: sonar
spec:
  selector:
    name: sonarqube
  ports:
    - name: http
      port: 80
      targetPort: sonarqube-port
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: sonarqube-internal
  namespace: sonar
spec:
  hosts:
    - sonarqube.staging.jeet11.internal
    - sonarqube
  gateways:
    - default/ilb-gateway
    - mesh
  http:
    - route:
        - destination:
            host: sonarqube
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: sonarqube-external
  namespace: sonar
spec:
  hosts:
    - sonarqube.staging.jeet11.com
  gateways:
    - default/elb-gateway
  http:
    - route:
        - destination:
            host: sonarqube
---

部署成功完成。我公开的服务提供了一个映射到主机 url 的 public ip,但我无法访问主机 url 上的服务。

我需要更改映射,以便声纳与服务器 ip 绑定,但我无法理解该怎么做。我无法将它绑定到我的集群 ip,也不能绑定到我的内部或外部服务 ip。

我该怎么办?请帮忙!

不要传递参数只是尝试 运行 没有它曾经为我工作。

我的部署文件就是这样希望对你有帮助

apiVersion: v1
kind: Service
metadata:
  name: sonarqube-service
spec:
  selector:
    app: sonarqube
  ports:
  - protocol: TCP
    port: 9000
    targetPort: 9000
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  labels:
    app: sonarqube
  name: sonarqube
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: sonarqube
    spec:
      containers:
        - name: sonarqube
          image: sonarqube:7.1
          resources:
            requests:
              memory: "1200Mi"
              cpu: .10
            limits:
              memory: "2500Mi"
              cpu: .50
          volumeMounts:
          - mountPath: "/opt/sonarqube/data/"
            name: sonar-data
          - mountPath: "/opt/sonarqube/extensions/"
            name: sonar-extensions
          env:
          - name: "SONARQUBE_JDBC_USERNAME"
            value: "root"  #Put your db username
          - name: "SONARQUBE_JDBC_URL"
            value: "jdbc:mysql://192.168.112.4:3306/sonar?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true" #DB URL
          - name: "SONARQUBE_JDBC_PASSWORD"
            value : password
          ports:
          - containerPort: 9000
            protocol: TCP
      volumes:
      - name: sonar-data
        persistentVolumeClaim:
          claimName: sonar-data
      - name: sonar-extensions
        persistentVolumeClaim:
          claimName: sonar-extensions

我最近遇到了同样的问题,今天我设法解决了这个问题。

我希望以下解决方案适用于面临相同问题的任何人!

环境

  • 云提供商:Azure - AKS
    • 无论您使用什么提供商,这都应该有效。
  • Istio 版本:1.7.3
  • K8版本:1.16.10

工具 - 调试

  • kubectl logs -n istio-system -l app=istiod
    • 来自 Istiod 的日志和控制平面中发生的事件。
  • istioctl analyze -n <namespace>
    • 这通常会为您提供给定命名空间的任何警告和错误。
    • 让您知道配置是否有误。
  • 基亚利 - istioctl dashboard kiali
    • 查看您是否获得入站流量。
    • 另外,显示任何错误配置。
  • 普罗米修斯 - istioctl dashboard prometheus
    • 查询指标 - istio_requests_total。这会向您显示进入该服务的流量。
    • 如果有任何配置错误,您将看到 destination_appunknown.

问题

  • 无法通过外部 IP 访问 sonarqube UI,但可通过本地主机 (port-forward) 访问。
  • 无法通过 Istio Ingressgateway 路由流量。

解决方案

Sonarqube 服务清单

apiVersion: v1
kind: Service
metadata:
  name: sonarqube
  namespace: sonarqube
  labels:
    name: sonarqube
spec:
  type: ClusterIP
  ports:
  - name: http
    port: 9000
    targetPort: 9000
  selector:
    app: sonarqube
status:
  loadBalancer: {}
  • 你的目标端口是容器端口。为避免任何混淆,只需将服务 port 编号分配为与服务 targetport.
  • 相同的编号
  • 端口名称在这里非常重要。 “Istio 要求服务端口遵循‘protocol-suffix’的命名形式,其中‘-后缀’部分是可选的”- KIA0601 - Port name must follow [-suffix] form

sonarqube 的 Istio 网关和虚拟服务清单

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: sonarqube-gateway
  namespace: sonarqube
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 9000
      name: http
      protocol: HTTP
    hosts:
    - "XXXX.XXXX.com.au"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: sonarqube
  namespace: sonarqube
spec:
  hosts:
  - "XXXX.XXXX.com.au"
  gateways:
  - sonarqube-gateway
  http:
  - route:
    - destination:
        host: sonarqube
        port:
          number: 9000
  • 网关协议必须设置为HTTP
  • 网关服务器端口虚拟服务目标端口相同。如果您有不同的应用 服务端口,那么您的 VirtualService 目标端口 号码应该与应用 服务端口 匹配. 网关服务器端口应该匹配应用服务目标端口
  • 现在到了有趣的时刻! 主机。如果你想访问集群外的服务,那么你需要有你的host-name(无论你想映射sonarqube服务器的host-name)作为DNS A记录 映射到 istio-ingressgateway.
  • 的外部 Public IP 地址
  • 获取ingressgateway的EXTERNAL-IP地址,运行kubectl -n istio-system get service istio-ingressgateway.
  • 如果你做一个简单的 nslookup (运行 - nslookup <hostname>),你得到的 IP 地址必须与分配给 istio-ingressgateway 服务的 IP 地址匹配。

在 ingressgateway 中公开一个新端口

  • 请注意,您的 sonarqube 网关端口是您要引入 Kubernetes 的新端口,您要告诉集群在该端口上侦听。但是您的负载均衡器不知道这个端口。因此,您需要在您的 kubernetes 外部负载均衡器上打开指定的网关端口。参考 - Info
  • 您无需手动更改负载均衡器服务。您只需更新入口网关以包含新端口,这将自动更新负载均衡器。
  • 您可以通过 运行ning istioctl analyze -n sonarqube 确定端口是否导致问题。您应该收到以下警告;

[33mWarn[0m [IST0104] (Gateway sonarqube-gateway.sonarqube) The gateway refers to a port that is not exposed on the workload (pod selector istio=ingressgateway; port 9000) Error: Analyzers found issues when analyzing namespace: sonarqube. See https://istio.io/docs/reference/config/analysis for more information about causes and resolutions.

  • 您应该在控制平面中得到相应的错误。 运行 kubectl logs -n istio-system -l app=istiod.
  • 此时您需要更新 Istio ingressgateway 服务以公开新端口。 运行 kubectl edit svc istio-ingressgateway -n istio-system 并将以下部分添加到端口。

绕过创建新端口

  • 在上一节中,您了解了如何公开新端口。这是可选的,取决于您的用例。
  • 在本节中,您将了解如何使用已公开的端口。
  • 如果你看istio-ingressgateway的服务。你可以看到有暴露的默认端口。这里我们将使用端口 80.

  • 您的设置如下所示;

  • 要避免使用您的主机名指定端口,只需添加匹配的 uri 前缀,如虚拟服务清单中所示。

测试时间

  • 如果到目前为止一切正常,那么你就可以开始了。

  • 在测试过程中,我犯了一个错误,没有指定端口。如果你得到 404 状态,这仍然是一件好事,通过这种方式你可以验证它使用的是什么服务器。如果你设置正确,它应该使用 istio-envoy 服务器,而不是nginx.

  • 不指定端口。这仅在您添加匹配 uri 前缀时有效。