【问题标题】:Exposing a Kubernetes service outside the cluster在集群外公开 Kubernetes 服务
【发布时间】:2021-12-21 01:31:47
【问题描述】:

我正在尝试公开一个在集群外部公开的简单 grafana 服务。以下是我在此处发布之前在故障排除和研究方面所做的工作,以及我的设置的一些细节。

Grafana 部署 YAML

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: grafana
  name: grafana
spec:
  selector:
    matchLabels:
      app: grafana
  template:
    metadata:
      labels:
        app: grafana
    spec:
      replicas: 2
      securityContext:
        fsGroup: 472
        supplementalGroups:
          - 0
      containers:
        - name: grafana
          image: 'grafana/grafana:8.0.4'
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 3000
              name: http-grafana
              protocol: TCP
          env:
            - name: GF_DATABASE_CA_CERT_PATH
              value: /etc/grafana/BaltimoreCyberTrustRoot.crt.pem
          readinessProbe:
            failureThreshold: 3
            httpGet:
              path: /robots.txt
              port: 3000
              scheme: HTTP
            initialDelaySeconds: 10
            periodSeconds: 30
            successThreshold: 1
            timeoutSeconds: 2
          livenessProbe:
            failureThreshold: 3
            initialDelaySeconds: 30
            periodSeconds: 10
            successThreshold: 1
            tcpSocket:
              port: 3000
            timeoutSeconds: 1
          resources:
            requests:
              cpu: 250m
              memory: 750Mi
          volumeMounts:
            - name: grafana-configmap-pv
              mountPath: /etc/grafana/grafana.ini
              subPath: grafana.ini
            - name: grafana-pv
              mountPath: /var/lib/grafana
            - name: cacert
              mountPath: /etc/grafana/BaltimoreCyberTrustRoot.crt.pem
              subPath: BaltimoreCyberTrustRoot.crt.pem
      volumes:
        - name: grafana-pv
          persistentVolumeClaim:
            claimName: grafana-pvc
        - name: grafana-configmap-pv
          configMap:
            name: grafana-config
        - name: cacert
          configMap:
            name: mysql-cacert

Grafana 服务 yaml

apiVersion: v1
kind: Service
metadata:
  name: grafana
spec:
  type: ClusterIP
  ports:
    - port: 3000
      protocol: TCP
      targetPort: http-grafana
  clusterIP: 10.7.2.57
  selector:
    app: grafana
  sessionAffinity: None

我已将 nginx 安装为 Ingress 控制器。这是 nginx 控制器服务的 YAML

kind: Service
apiVersion: v1
metadata:
  name: ingress-nginx-controller
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/version: 1.0.0
    helm.sh/chart: ingress-nginx-4.0.1
spec:
  ports:
    - name: http
      protocol: TCP
      appProtocol: http
      port: 80
      targetPort: http
      nodePort: 32665
    - name: https
      protocol: TCP
      appProtocol: https
      port: 443
      targetPort: https
      nodePort: 32057
  selector:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
  clusterIP: 10.7.2.203
  clusterIPs:
    - 10.7.2.203
  type: NodePort
  sessionAffinity: None
  externalTrafficPolicy: Cluster
status:
  loadBalancer: {}

入口资源yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: grafana-ingress
spec:
  rules:
  - host: test.grafana.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: grafana
            port:
              number: 3000

入口 ip 10.7.0.5 根本无法访问。我尝试过多次重新部署资源。 grafana POD ips 可通过端口 3000 访问,我可以登录等,但无法通过 nginx 负载均衡器访问 grafana。我错过了什么?

已编辑:

kubectl get services的结果

NAME          TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
grafana       ClusterIP   10.7.2.55    <none>        3000/TCP   2d14h
hello-world   ClusterIP   10.7.2.140   <none>        80/TCP     42m
kubernetes    ClusterIP   10.7.2.1     <none>        443/TCP    9d

kubectl 获取入口的结果

NAME              CLASS    HOSTS   ADDRESS    PORTS   AGE
grafana-ingress   <none>   *       10.7.0.5   80      2d2h

kubectl get pods 的结果

default         grafana-85cdb8c656-6zgkg                    1/1     Running     0          2d21h
default         grafana-85cdb8c656-7n626                    1/1     Running     0          2d21h
default         hello-world-78796d6bfd-fwb98                1/1     Running     0          2d12h
ingress-nginx   ingress-nginx-controller-57ffff5864-rw57w   1/1     Running     0          2d12h

【问题讨论】:

  • 您使用的是哪个版本的 Kubernetes,您是如何设置集群的?您是否使用裸机安装或某些云提供商?你能显示使用kubectl get pod,svc的结果吗?
  • @kkopczak 添加了已编辑的部分,其中包含 kubectl get pod,svc.ingress 的结果。我正在使用 Azure Kubernetes 服务和版本 1.20.1。使用 Manifest 或 yaml 创建所有资源。

标签: nginx kubernetes


【解决方案1】:

您的入口控制器的 Service 是 NodePort 类型,这意味着它没有公共 IP 地址。 Service 的 ClusterIP (10.7.2.203) 只在集群的内部网络中有用。

如果您的集群节点有公共 IP 地址,您可以使用这些地址连接到入口控制器。由于它的 Service 是 NodePort 类型,它会侦听集群所有节点上的特定端口。根据您提供的服务规范,这些端口对于 HTTP 是 32665,对于 HTTPS 是 32057。

如果您希望入口控制器具有专用 IP 地址,您可以将其 Service 的类型更改为 LoadBalancer。您的 Kubernetes 服务提供商将为您的服务分配一个公共 IP 地址。然后,您可以使用该 IP 地址连接到您的入口控制器。

这仅在您使用托管 Kubernetes 服务时才有效。如果您是自我管理的,那么您需要设置一个负载均衡器来侦听公共 IP 地址并将流量路由到集群的节点。

【讨论】:

  • 做到了。我确信我确实尝试过 LoadBalancer 作为一个选项,但没有密切关注它公开的公共 IP。还需要在我们的网络内部公开 grafana 服务,因此我还必须在入口资源 service.beta.kubernetes.io/azure-load-balancer-internal: "true" 上添加符号
【解决方案2】:

您仍然将您的服务暴露在 k8s 内部网络中。

  • 一种解决方案是在您的 pod 定义中使用“hostNetwork: True” (link),因此您的 pod 将通过您的主机网络公开 而不是 k8s 内部网络(请注意,它确实扩展了您的 安全风险)。

  • 另一种方法是使用云中的负载均衡器服务 提供者或部署本地负载均衡器服务,例如 MetalB

  • 或者你可以手动部署一个代理服务,比如 nginx 或 haproxy 一个或多个节点将来自 k8s 内部网络的流量代理到 您的主机网络和外部世界。

【讨论】:

    猜你喜欢
    • 2020-04-25
    • 2019-01-05
    • 2017-02-13
    • 1970-01-01
    • 2020-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-13
    相关资源
    最近更新 更多