通过kubernetes单节点集群创建服务给我没有“入口”外部IP,但谷歌容器引擎确实(?)

时间:2016-01-03 08:01:59

标签: google-cloud-platform kubernetes

我正在尝试设置单个节点kubernetes集群用于演示和测试目的,我希望它能够表现出来 就像一个'完整的'k8s集群(像谷歌容器引擎)。我的客户端有自己的k8s安装,其中 对于这个讨论,我们可以假设行为非常类似于谷歌容器引擎的k8s安装。

在完全吹制的K8上获取Ingress IP

我正在创建一个wordpress pod并将其作为服务公开,如本教程中所述: https://cloud.google.com/container-engine/docs/tutorials/hello-wordpress

如果你想复制这个问题,只需复制粘贴下面的命令,我从教程中解除了: (假设您有一个名为'stellar-access-117903'的项目..如果没有,请设置为您的Google容器的名称 发动机项目。)

# set up the cluster  (this will take a while to provision)
#
 gcloud config set project stellar-access-117903
 gcloud config set compute/zone us-central1-b
 gcloud container clusters create hello-world \
     --num-nodes 1 \
     --machine-type g1-small

# Create the pod, and expose it as a service
#
kubectl run wordpress --image=tutum/wordpress --port=80
kubectl expose rc wordpress --type=LoadBalancer

# Describe the service
kubectl describe services wordpress

describe命令的输出包含一行'LoadBalancer Ingress:{some-ip-address}',它是 正是我所期待的。现在,当我对单节点集群设置执行相同操作时,我不 得到那条线。我能够在出现在输出中的IP上点击wordpress服务 “描述服务”命令..但是在“单节点”模式中,打印出的IP是>群集IP< 该服务,通常(据我所知)不可公开访问。出于某种原因,它是 可在单节点模式下公开访问。我们可以通过以下步骤复制它。

无法在单节点K8上获取Ingress IP

首先设置单节点k8s,如本教程中所述: https://github.com/kubernetes/kubernetes/blob/master/docs/getting-started-guides/docker.md

为了便于重复,我已经包含了以下所有命令,因此您只需复制/粘贴:

K8S_VERSION=1.1.1

sudo docker run --net=host -d gcr.io/google_containers/etcd:2.0.12 /usr/local/bin/etcd --addr=127.0.0.1:4001 --bind-addr=0.0.0.0:4001 --data-dir=/var/etcd/data


sudo docker run \
    --volume=/:/rootfs:ro \
    --volume=/sys:/sys:ro \
    --volume=/dev:/dev \
    --volume=/var/lib/docker/:/var/lib/docker:ro \
    --volume=/var/lib/kubelet/:/var/lib/kubelet:rw \
    --volume=/var/run:/var/run:rw \
    --net=host \
    --pid=host \
    --privileged=true \
    -d \
    gcr.io/google_containers/hyperkube:v${K8S_VERSION} \
    /hyperkube kubelet --containerized --hostname-override="127.0.0.1" --address="0.0.0.0" --api-servers=http://localhost:8080 --config=/etc/kubernetes/manifests

sudo docker run -d --net=host --privileged gcr.io/google_containers/hyperkube:v${K8S_VERSION} /hyperkube proxy --master=http://127.0.0.1:8080 --v=2


# set your context to use the locally running k8s API server 
#
kubectl config set-cluster dev --server=http://localhost:8080
kubectl config set-context dev --cluster=dev  --namespace=$NS
kubectl config use-context dev

现在,执行针对Google Container Engine的k8s执行的相同命令

# Create the pod, and expose it as a service
#
kubectl run wordpress --image=tutum/wordpress --port=80
kubectl expose rc wordpress --type=LoadBalancer

# Describe the service
kubectl describe services wordpress

最后一个命令的输出(您将看到没有'Ingress'信息)是:

Name:           wordpress
Namespace:      default
Labels:         run=wordpress
Selector:       run=wordpress
Type:           LoadBalancer
IP:         10.0.0.61
Port:           <unnamed>   80/TCP
NodePort:       <unnamed>   31795/TCP
Endpoints:      172.17.0.30:80
Session Affinity:   None
No events.

在谷歌容器引擎的k8s中,我看到“创建负载均衡器”,“创建负载均衡器”等事件。但没什么 发生在单个节点实例中。

我想知道......我需要做一些配置才能让它们以相同的方式工作吗?他们非常重要 同样工作......只是在可扩展性上有所不同,因为我们希望针对单节点版本运行测试,并且 如果行为不同,将会非常混乱。

提前感谢您的帮助  -Chris

2 个答案:

答案 0 :(得分:1)

这是我们提出的解决方案。当我们针对单个节点Kubernetes运行时,我们通过反复试验意识到,当您公开服务时,外部IP不会通过IngressIP返回;相反,它通过clusterIP返回,如上所述,clusterIP是公开可见的。所以,我们只是修改了我们的代码来使用它。我们在单节点情况下使用clusterIP。以下是我们用于在服务上建立监视的代码,以确定k8s何时分配了我们的外部可见IP:

首先我们使用fabric8 API来创建服务配置:

            case "Service" =>
              val serviceConf = mapper.readValue(f, classOf[Service])
              val service = kube.services().inNamespace(namespaceId).create(serviceConf)
              watchService(service)

'watchService'方法定义如下:

  private def watchService(service: Service) = {
    val namespace = service.getMetadata.getNamespace
    val name = service.getMetadata.getName
    logger.debug("start -> watching service -> namespace: " + namespace + " name: " + name)
    val kube = createClient()
    try {
      @volatile var complete = false
      val socket = kube.services().inNamespace(namespace).withName(name).watch(new Watcher[Service]() {
        def eventReceived(action: Action, resource: Service) {
          logger.info(action + ":" + resource)
          action match {
            case Action.MODIFIED =>
              if (resource.getMetadata.getName == name) {
                complete = isServiceComplete(resource)
              }
            //            case Action.DELETED =>
            //              complete = true
            case _ =>
          }
        }
      })
      while (!complete) {
        Thread.sleep(5000)
        complete = isServiceComplete(kube.services().inNamespace(namespace).withName(name).get)
      }
      logger.info("Closing socket connection")
      socket.close()
    } finally {
      logger.info("Closing client connection")
      kube.close()
    }

    logger.debug("complete -> watching services , namespace: " + namespace + " name: " + name)
  }

我们介绍的关键黑客是在'isServiceComplete'方法中..当使用单节点k8s时,'isUsingMock'的值为true。这样我们就可以使用clusterIP来确定服务配置是否已经完成。

  private def isServiceComplete(service: Service) = {
    !service.getStatus.getLoadBalancer.getIngress.isEmpty  || mockServiceComplete(service)
  }

  def mockServiceComplete(service: Service): Boolean = {
    val clusterIP  = service.getSpec.getClusterIP
    logger.trace(s"mockServiceComplete:   $isUsingMock /  $clusterIP / $KUBE_SERVER" )
    isUsingMock && ! clusterIP.isEmpty
  }

很抱歉,如果这里没有太多额外的背景信息。最终我们的项目应该是开源的,我们可以发布一个完整的解决方案。

-Chris

答案 1 :(得分:0)

LoadBalancer是由后端云提供商实施的功能,因此您无法看到在本地设置中创建的功能

(请参阅云提供商:https://github.com/kubernetes/kubernetes/tree/master/pkg/cloudprovider/providers