K8s 的端口port映射问题

背景

对于port 可能有以下大概三种需求

  1. 同一个pod 里不同container 可以访问
  2. 在一个cluster 里, 不同pod 里可以访问
  3. 暴露到集群外面。即 可以在集群外通过ip 端口访问

先来了解下 k8s cluster networking

k8s cluster networking

每个pod 都有自己的 IP 地址 。这意味着你不需要 处理容器port 对 主机 port 的映射。pods 就像VM 或者 物理机哪样

k8s 的IP 地址 存在于 pod scope - 在一个Pod 的 容器们 共享 networknamespaces, 包括IP 地址。这意味着在一个pod 里的容器们 能够通过localhost 访问彼此的 端口。这也意味着 在一个pod 里的容器们需要协调 端口的使用。这就叫做 "IP-per-pod" model

来看一个例子

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  selector:
    matchLabels:
      run: my-nginx
  replicas: 2
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
        ports:
        - containerPort: 80

将上面代码保存为nginx.yaml

kubectl apply -f nginx.yaml
# 查看pod
kubectl get pods -l run=my-nginx -o wide
# 查看pod ip
kubectl get pods -l run=my-nginx -o yaml | grep podIP

你可以ssh 连接到集群里的任意一个node 并curl IPs。 Note: 这个容器没有用node 的80 端口。也没有用NAT 规则到这个pod 上。这意味着可以在同一个node 上使用相同的 containerPort 并且在 你的集群里用ip 从node或者其他 pod 上去访问 它们。类似 Docker, ports 仍然可以被 published 到 host node 的接口上。但在这个网络模型下这个需求大大减少了。

Service

为什么需要 service ?

我们可以直接与pod 交流。但是当 一个node die 的时候会发生什么呢?
pod 也会die, 然后Deployment 会创建新的pods(IP不同)。这是 Service 要解决的问题。
来看一个service yaml

apiVersion: v1
kind: Service
metadata:
  name: my-nginx
  labels:
    run: my-nginx
spec:
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 80
  selector:
    run: my-nginx

kubectl get svc my-nginx

➜  k8s_demo kubectl get svc my-nginx
NAME       TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE
my-nginx   ClusterIP   10.68.82.69   <none>        8080/TCP   26s

你可以从集群里的任意node 上 curl nginx Service on <CLUSTER-IP>:<PORT>。 Note: service IP 是完全虚拟的。

访问 Service

两种方式

  • 环境变量
  • DNS

环境变量

kubectl exec my-nginx-3800858182-jr4a2 -- printenv | grep SERVICE
这事你并没有发现 my-nginx servervice.因为 pods 先启动的。还带来的一个缺点是 2个pods 都在一个机器上,当机器挂掉, service 也会挂掉。我们先杀死两个pod 然后 等待deployment 重新创建。会正确调度并且带有正确的环境变量。

DNS

k8s 提供了DNS 集群附加服务会自动授予其他services dns name。你可以检查它是不是在你的集群运行.
你可以在一个pod里 curl <service-name>:<port> 来访问service

kubectl get services kube-dns --namespace=kube-system

NAME       TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE
kube-dns   ClusterIP   10.68.0.2    <none>        53/UDP,53/TCP,9153/TCP   338d

expose internet

使用Nodeport 或者loadbalance

其他

当删除一个service, 再apply, cluster IP 也会变化
下面这张图 是说明了 deployment 的port 参数。这表示这个参数是不必要的,即使没有也会暴露出来


image.png

参考

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。