我正在尝试设置单个节点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
答案 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)