我一直在努力设置 Kubernetes 集群。我的设置有两个节点和一个主节点。所有三台机器都在 Proxmox 集群上运行,并有 2 个虚拟网络接口。其中一个接口(下面列出)与其他机器处于桥接网络中。另一个暴露在内部网络中。
桥接接口的网络设置如下:
Network: 10.10.0.0
Broadcast: 10.10.255.255
Netmask: 255.255.0.0
kubernetes-master IP: 10.10.0.1
kubernetes-worker01 IP: 10.10.0.2
kubernetes-worker02 IP: 10.10.0.3
所有服务器都可以毫无问题地互相通信。我还没有设置任何类型的防火墙。
root@kubernetes-master:~/manifests# kubectl get nodes
NAME STATUS AGE
10.10.0.2 Ready 5d
10.10.0.3 Ready 5d
我有一个 hello world nodeJS 应用程序,它在端口 8080 上提供 HTTP 服务器,并在查询时显示“Hello world”。它的设置如下:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: hello-node-deployment
spec:
replicas: 4
template:
metadata:
labels:
app: hello-node
spec:
containers:
- name: hello-node
image: kubernetes-master:5000/hello-node:v1
ports:
- containerPort: 8080
然后我创建了一个新的服务,它应该通过 NodePort 公开部署。
apiVersion: v1
kind: Service
metadata:
name: hello-node-service
labels:
app: hello-node
spec:
ports:
- port: 8080
protocol: TCP
selector:
app: hello-node
type: NodePort
启动服务和部署后:
root@kubernetes-master:~/manifests# kubectl describe service hello-node-service
Name: hello-node-service
Namespace: default
Labels: app=hello-node
Selector: app=hello-node
Type: NodePort
IP: 10.100.0.88
Port: <unset> 8080/TCP
NodePort: <unset> 30862/TCP
Endpoints: 192.168.0.22:8080,192.168.0.23:8080,192.168.0.89:8080 + 1 more...
Session Affinity: None
No events.
root@kubernetes-master:~/manifests# kubectl get pods --selector="app=hello-node" --output=wide
NAME READY STATUS RESTARTS AGE IP NODE
hello-node-deployment-815057587-0w896 1/1 Running 0 24m 192.168.0.89 10.10.0.2
hello-node-deployment-815057587-62d2b 1/1 Running 0 24m 192.168.0.23 10.10.0.3
hello-node-deployment-815057587-d6t4z 1/1 Running 0 24m 192.168.0.90 10.10.0.2
hello-node-deployment-815057587-k7qcx 1/1 Running 0 24m 192.168.0.22 10.10.0.3
此后,主节点无法联系到所提供节点端口 (10.10.0.2:30862、10.10.0.2:30862) 上的任何节点。连接挂起,无法成功。
如果我通过 ssh 连接到节点,我可以通过直接与 pod 对话成功查询服务:
root@kubernetes-worker02:~# curl http://192.168.0.22:8080
Hello World!
我是不是漏掉了什么?这是预期的行为还是我的设置有问题?
答案1
Kubernetes 不仅需要节点能够相互通信,还需要网络(或路由表)以便 Pod 能够相互通信。它本质上是另一个仅用于 Pod 的网络(通常称为覆盖/底层网络),允许节点 A 上的 Pod 与节点 B 上的 Pod 通信。
从表面上看,您没有设置 pod 网络。您可以通过多种方式实现覆盖网络(这是它如此令人困惑的原因之一)。阅读有关网络要求的更多信息这里。
如果只有 2 个节点,我建议您实际设置我称之为“无 SDN Kubernetes”的东西,然后手动将 pod 路由添加到每个节点。这需要您做两件事。
- 为每个节点上的 pod 指定子网
- 手动运行命令来创建路线
我有关于如何操作的详细信息我写的关于这个主题的博客文章。
不幸的是,设置 pod 网络只能让你完成一半。为了实现自动 NodePort 服务,你还需要安装 kube-proxy。kube-proxy 的工作是监视服务在哪个端口启动,然后将该端口路由到集群内的正确服务/pod。它通过 IP 表执行此操作,并且大部分是自动的。
我找不到手动部署 kube-proxy 的很好示例(通常通过部署工具来处理)。下面是DaemonSet这kubeadm工具应该自动创建在集群中的每个节点上运行 kube-proxy。
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
generation: 1
labels:
component: kube-proxy
k8s-app: kube-proxy
kubernetes.io/cluster-service: "true"
name: kube-proxy
tier: node
name: kube-proxy
namespace: kube-system
spec:
selector:
matchLabels:
component: kube-proxy
k8s-app: kube-proxy
kubernetes.io/cluster-service: "true"
name: kube-proxy
tier: node
template:
metadata:
labels:
component: kube-proxy
k8s-app: kube-proxy
kubernetes.io/cluster-service: "true"
name: kube-proxy
tier: node
spec:
containers:
- command:
- kube-proxy
- --kubeconfig=/run/kubeconfig
image: gcr.io/google_containers/kube-proxy-amd64:v1.5.2
imagePullPolicy: IfNotPresent
name: kube-proxy
securityContext:
privileged: true
terminationMessagePath: /dev/termination-log
volumeMounts:
- mountPath: /var/run/dbus
name: dbus
- mountPath: /run/kubeconfig
name: kubeconfig
dnsPolicy: ClusterFirst
hostNetwork: true
restartPolicy: Always
terminationGracePeriodSeconds: 30
volumes:
- hostPath:
path: /etc/kubernetes/kubelet.conf
name: kubeconfig
- hostPath:
path: /var/run/dbus
name: dbus
另一个可能有用的资源是Kubernetes 的艰难之路。它不直接适用于在 proxmox 上的虚拟机中运行(它假定是 GCE 或 AWS),但它向您展示了运行正常运行的 Kubernetes 集群所需的最低限度的步骤和资源。