如何从集群外部访问我的 Cassandra/Kubernetes 集群?

Man*_*dha 1 kubernetes google-kubernetes-engine

我已经开始使用 Cass-Operator 并且设置工作得很好!https://github.com/datastax/cass-operator

我有一个问题。我的集群已在 GCP 上启动并运行。但是我如何从我的笔记本电脑(基本上是从外面)访问它?抱歉,我是 Kubernetes 的新手,所以我不知道如何从外部访问集群?

我可以看到节点在 GCP 仪表板上。我可以从我的笔记本电脑 ping 节点的外部 IP,但是当我运行时cqlsh external_ip 9042连接失败。

我如何将 K8s/Cassandra 集群连接到外部工作,以便我的 Web 应用程序可以访问它?

我想要:

  1. 有一个 URL,以便我的 Web 应用程序使用该 URL 连接到 cassandra/K8s 集群而不是 IP 地址。因此,我需要一个 dns。它是否在 K8S 中默认出现?会是网址吗?在某些节点中为我管理 dns 映射的 K8s 会重新启动吗?
  2. 我的 Web 应用程序应该能够在 9042 上访问 Cassandra。似乎为 http/https 完成了负载平衡。Cassandra 应用程序不是 http/https 请求。所以我不需要端口 80 或 443

我读过一些关于 Service、Loadbalancer 和 Ingress 的教程。但我无法开始。

我创建了这样的服务

kind: Service
apiVersion: v1
metadata:
  name: cass-operator-service
spec:
  type: LoadBalancer
  ports:
    - port: 9042
  selector:
    name: cass-operator
Run Code Online (Sandbox Code Playgroud)

然后创建了服务 - kubectl apply -f ./cass-operator-service.yaml

我检查了服务是否是使用创建的kubectl get svc并得到输出

NAME                    TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)          AGE 
cass-operator-service   LoadBalancer   10.51.249.224   34.91.214.233   9042:30136/TCP   4m17s 
kubernetes              ClusterIP      10.51.240.1     <none>          443/TCP          10h. 
Run Code Online (Sandbox Code Playgroud)

但是当我运行时cqlsh 34.91.214.233 9042连接失败

似乎对端口 9042 的请求将被转发到 30136。但它们应该被转发到 9042,因为 Pod 中的 Cassandra 图像正在侦听传入请求

更新

尝试了 targetPort 但仍然没有运气

manuchadha25@cloudshell:~ (copper-frame-262317)$ cat cass-operator-service.yaml
kind: Service
apiVersion: v1
metadata:
  name: cass-operator-service
spec:
  type: LoadBalancer
  ports:
    - port: 9042
      targetPort: 9042
  selector:
    name: cass-operator
manuchadha25@cloudshell:~ (copper-frame-262317)$ kubectl get service
NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.51.240.1   <none>        443/TCP   11h
manuchadha25@cloudshell:~ (copper-frame-262317)$ kubectl apply -f ./cass-operator-service.yaml
service/cass-operator-service created
manuchadha25@cloudshell:~ (copper-frame-262317)$ kubectl get service
NAME                    TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
cass-operator-service   LoadBalancer   10.51.255.184   <pending>     9042:30024/TCP   12s
kubernetes              ClusterIP      10.51.240.1     <none>        443/TCP          11h
manuchadha25@cloudshell:~ (copper-frame-262317)$ kubectl get service
NAME                    TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
cass-operator-service   LoadBalancer   10.51.255.184   <pending>     9042:30024/TCP   37s
kubernetes              ClusterIP      10.51.240.1     <none>        443/TCP          11h
manuchadha25@cloudshell:~ (copper-frame-262317)$ kubectl get service
NAME                    TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)          AGE
cass-operator-service   LoadBalancer   10.51.255.184   34.91.214.233   9042:30024/TCP   67s
kubernetes              ClusterIP      10.51.240.1     <none>          443/TCP          11h
manuchadha25@cloudshell:~ (copper-frame-262317)$ ping 34.91.214.233
PING 34.91.214.233 (34.91.214.233) 56(84) bytes of data.
64 bytes from 34.91.214.233: icmp_seq=1 ttl=109 time=7.89 ms
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

查询所有名称空间显示以下内容

在此处输入图片说明

但是使用命名空间 cass-operator 查询 pod 返回空结果

manuchadha25@cloudshell:~ (copper-frame-262317)$ kubectl get pods -l name=cass-operator
No resources found in default namespace.
Run Code Online (Sandbox Code Playgroud)

Wil*_*.F. 5

  • 由于您是 Kubernetes 的新手,您可能不熟悉StatefulSets

StatefulSet 是用于管理有状态应用程序的工作负载 API 对象。

管理一组的部署和缩放 窗格并提供有关的排序和唯一性保证 这些荚。

与 Deployment 一样,StatefulSet 管理基于相同容器规范的 Pod。与 Deployment 不同,StatefulSet 为其每个 Pod 维护一个粘性标识。这些 pod 是根据相同的规范创建的,但不可互换:每个 pod 都有一个持久标识符,它在任何重新调度时都会维护。


我如何将 K8s/Cassandra 集群连接到外部工作,以便我的 Web 应用程序可以访问它?

  • 我发现datastax/cass-operator还在开发他们的文档,我发现这个文档还没有合并到master,但是它很好地解释了如何连接到Cassandra,我强烈推荐阅读。
  • 记录从集群外部进行连接的方法有几个未解决的问题

我按照https://github.com/datastax/cass-operator 中的指南部署了 cass-operator + Cassandra 数据中心示例,从您的图像中我相信您也遵循了:

$ kubectl create -f https://raw.githubusercontent.com/datastax/cass-operator/v1.2.0/docs/user/cass-operator-manifests-v1.15.yaml
namespace/cass-operator created
serviceaccount/cass-operator created
secret/cass-operator-webhook-config created
customresourcedefinition.apiextensions.k8s.io/cassandradatacenters.cassandra.datastax.com created
clusterrole.rbac.authorization.k8s.io/cass-operator-cluster-role created
clusterrolebinding.rbac.authorization.k8s.io/cass-operator created
role.rbac.authorization.k8s.io/cass-operator created
rolebinding.rbac.authorization.k8s.io/cass-operator created
service/cassandradatacenter-webhook-service created
deployment.apps/cass-operator created
validatingwebhookconfiguration.admissionregistration.k8s.io/cassandradatacenter-webhook-registration created

$ kubectl create -f https://raw.githubusercontent.com/datastax/cass-operator/v1.2.0/operator/k8s-flavors/gke/storage.yaml
storageclass.storage.k8s.io/server-storage created

$ kubectl -n cass-operator create -f https://raw.githubusercontent.com/datastax/cass-operator/v1.2.0/operator/example-cassdc-yaml/cassandra-3.11.6/example-cassdc-minimal.yaml
cassandradatacenter.cassandra.datastax.com/dc1 created

$ kubectl get all -n cass-operator
NAME                                READY   STATUS    RESTARTS   AGE
pod/cass-operator-78c6469c6-6qhsb   1/1     Running   0          139m
pod/cluster1-dc1-default-sts-0      2/2     Running   0          138m
pod/cluster1-dc1-default-sts-1      2/2     Running   0          138m
pod/cluster1-dc1-default-sts-2      2/2     Running   0          138m

NAME                                          TYPE           CLUSTER-IP    EXTERNAL-IP    PORT(S)             AGE
service/cass-operator-metrics                 ClusterIP      10.21.5.65    <none>         8383/TCP,8686/TCP   138m
service/cassandradatacenter-webhook-service   ClusterIP      10.21.0.89    <none>         443/TCP             139m
service/cluster1-dc1-all-pods-service         ClusterIP      None          <none>         <none>              138m
service/cluster1-dc1-service                  ClusterIP      None          <none>         9042/TCP,8080/TCP   138m
service/cluster1-seed-service                 ClusterIP      None          <none>         <none>              138m

NAME                            READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/cass-operator   1/1     1            1           139m

NAME                                      DESIRED   CURRENT   READY   AGE
replicaset.apps/cass-operator-78c6469c6   1         1         1       139m

NAME                                        READY   AGE
statefulset.apps/cluster1-dc1-default-sts   3/3     138m

$ CASS_USER=$(kubectl -n cass-operator get secret cluster1-superuser -o json | jq -r '.data.username' | base64 --decode)
$ CASS_PASS=$(kubectl -n cass-operator get secret cluster1-superuser -o json | jq -r '.data.password' | base64 --decode)

$ echo $CASS_USER
cluster1-superuser

$ echo $CASS_PASS
_5ROwp851l0E_2CGuN_n753E-zvEmo5oy31i6C0DBcyIwH5vFjB8_g
Run Code Online (Sandbox Code Playgroud)
  • kubectl get all上面的命令中我们可以看到有一个名为 statefulset 的statefulset.apps/cluster1-dc1-default-sts控制 cassandra pod。
  • 为了创建一个 LoadBalancer 服务,让所有由它管理的 pod 可用,statefulset我们需要使用分配给它们的相同标签:
$ kubectl describe statefulset cluster1-dc1-default-sts -n cass-operator
Name:               cluster1-dc1-default-sts
Namespace:          cass-operator
CreationTimestamp:  Tue, 30 Jun 2020 12:24:34 +0200
Selector:           cassandra.datastax.com/cluster=cluster1,cassandra.datastax.com/datacenter=dc1,cassandra.datastax.com/rack=default
Labels:             app.kubernetes.io/managed-by=cass-operator
                    cassandra.datastax.com/cluster=cluster1
                    cassandra.datastax.com/datacenter=dc1
                    cassandra.datastax.com/rack=default
Run Code Online (Sandbox Code Playgroud)
  • 现在让我们创建 LoadBalancer 服务 yaml 并使用标签作为selectors服务:
apiVersion: v1
kind: Service
metadata:
  name: cassandra-loadbalancer
  namespace: cass-operator
  labels:
    cassandra.datastax.com/cluster: cluster1
    cassandra.datastax.com/datacenter: dc1
    cassandra.datastax.com/rack: default
spec:
  type: LoadBalancer
  ports:
  - port: 9042
    protocol: TCP
  selector:
    cassandra.datastax.com/cluster: cluster1
    cassandra.datastax.com/datacenter: dc1
    cassandra.datastax.com/rack: default
Run Code Online (Sandbox Code Playgroud)

“我的 Web 应用程序应该能够在 9042 上访问 Cassandra。似乎对 http/https 进行了负载平衡。Cassandra 应用程序不是 http/https 请求。所以我不需要端口 80 或 443。”

  • 当您创建类型为 的服务时 LoadBalancer,Google Cloud 控制器会唤醒并 在您的项目中配置 网络负载平衡器。负载均衡器具有可从项目外部访问的稳定 IP 地址。

  • 网络负载平衡器支持任何和所有端口。您可以使用网络负载平衡对 TCP 和 UDP 流量进行负载平衡。由于负载均衡器是直通负载均衡器,您的后端会自行终止负载均衡的 TCP 连接或 UDP 数据包。

  • 现在让我们应用 yaml 并注意列出的 pod 的端点 IP:

$ kubectl apply -f cassandra-loadbalancer.yaml 
service/cassandra-loadbalancer created

$ kubectl get service cassandra-loadbalancer -n cass-operator 
NAME                     TYPE           CLUSTER-IP    EXTERNAL-IP    PORT(S)          AGE
cassandra-loadbalancer   LoadBalancer   10.21.4.253   146.148.89.7   9042:30786/TCP   5m13s

$ kubectl describe svc cassandra-loadbalancer -n cass-operator
Name:                     cassandra-loadbalancer
Namespace:                cass-operator
Labels:                   cassandra.datastax.com/cluster=cluster1
                          cassandra.datastax.com/datacenter=dc1
                          cassandra.datastax.com/rack=default
Annotations:              Selector:  cassandra.datastax.com/cluster=cluster1,cassandra.datastax.com/datacenter=dc1,cassandra.datastax.com/rack=default
Type:                     LoadBalancer
IP:                       10.21.4.253
LoadBalancer Ingress:     146.148.89.7
Port:                     <unset>  9042/TCP
TargetPort:               9042/TCP
NodePort:                 <unset>  30786/TCP
Endpoints:                10.24.0.7:9042,10.24.2.7:9042,10.24.3.9:9042
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>
Run Code Online (Sandbox Code Playgroud)
  • 为了测试它,我将使用带有 cassandra 容器的云 shell 来使用LoadBalancer上面提供的IP模拟您的笔记本:
$ kubectl create -f https://raw.githubusercontent.com/datastax/cass-operator/v1.2.0/docs/user/cass-operator-manifests-v1.15.yaml
namespace/cass-operator created
serviceaccount/cass-operator created
secret/cass-operator-webhook-config created
customresourcedefinition.apiextensions.k8s.io/cassandradatacenters.cassandra.datastax.com created
clusterrole.rbac.authorization.k8s.io/cass-operator-cluster-role created
clusterrolebinding.rbac.authorization.k8s.io/cass-operator created
role.rbac.authorization.k8s.io/cass-operator created
rolebinding.rbac.authorization.k8s.io/cass-operator created
service/cassandradatacenter-webhook-service created
deployment.apps/cass-operator created
validatingwebhookconfiguration.admissionregistration.k8s.io/cassandradatacenter-webhook-registration created

$ kubectl create -f https://raw.githubusercontent.com/datastax/cass-operator/v1.2.0/operator/k8s-flavors/gke/storage.yaml
storageclass.storage.k8s.io/server-storage created

$ kubectl -n cass-operator create -f https://raw.githubusercontent.com/datastax/cass-operator/v1.2.0/operator/example-cassdc-yaml/cassandra-3.11.6/example-cassdc-minimal.yaml
cassandradatacenter.cassandra.datastax.com/dc1 created

$ kubectl get all -n cass-operator
NAME                                READY   STATUS    RESTARTS   AGE
pod/cass-operator-78c6469c6-6qhsb   1/1     Running   0          139m
pod/cluster1-dc1-default-sts-0      2/2     Running   0          138m
pod/cluster1-dc1-default-sts-1      2/2     Running   0          138m
pod/cluster1-dc1-default-sts-2      2/2     Running   0          138m

NAME                                          TYPE           CLUSTER-IP    EXTERNAL-IP    PORT(S)             AGE
service/cass-operator-metrics                 ClusterIP      10.21.5.65    <none>         8383/TCP,8686/TCP   138m
service/cassandradatacenter-webhook-service   ClusterIP      10.21.0.89    <none>         443/TCP             139m
service/cluster1-dc1-all-pods-service         ClusterIP      None          <none>         <none>              138m
service/cluster1-dc1-service                  ClusterIP      None          <none>         9042/TCP,8080/TCP   138m
service/cluster1-seed-service                 ClusterIP      None          <none>         <none>              138m

NAME                            READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/cass-operator   1/1     1            1           139m

NAME                                      DESIRED   CURRENT   READY   AGE
replicaset.apps/cass-operator-78c6469c6   1         1         1       139m

NAME                                        READY   AGE
statefulset.apps/cluster1-dc1-default-sts   3/3     138m

$ CASS_USER=$(kubectl -n cass-operator get secret cluster1-superuser -o json | jq -r '.data.username' | base64 --decode)
$ CASS_PASS=$(kubectl -n cass-operator get secret cluster1-superuser -o json | jq -r '.data.password' | base64 --decode)

$ echo $CASS_USER
cluster1-superuser

$ echo $CASS_PASS
_5ROwp851l0E_2CGuN_n753E-zvEmo5oy31i6C0DBcyIwH5vFjB8_g
Run Code Online (Sandbox Code Playgroud)

“有一个 url,以便我的 Web 应用程序使用该 URL 来连接到 cassandra/K8s 集群而不是 IP 地址。所以我需要一个 dns。它在 K8S 中是否默认出现?将是 url?K8s 会管理 dns在某些节点上为我映射重新启动?”

  • 关于 cassandra-operator 的文档也有一个关于Ingress的部分,我也推荐阅读。
  • Kubernetes 没有默认的 DNS 名称。
  • 您必须注册一个域,将 DNS 指向负载均衡器的 IP,这样它将解析网络负载均衡器的 IP。
  • Network LoadBalancer 绑定了一个静态公共 IP,Kubernetes 节点的任何变化都不会导致服务不可用。

如果您有任何问题,请在评论中告诉我。