简介

在一个集群中, 我们可以直接访问pod.
但是当节点死亡时(或pod消失), Pod 随之死亡, 此时控制器会自动建具有不同 IP 的新 Pod.
service就解决了这个问题。

service是一种抽象, 它定义并指向了一组Pod(endpoints).

创建时, 将为每个服务分配一个唯一的 IP 地址(cluster IP)。此地址与服务的生命周期相关联, 并且一般不会更改。
可以将 Pod 配置为与服务通信, 服务将自动负载均衡到其中某个 Pod。

也就是说, 服务是沟通集群外界和pod群组的桥梁。

相关命令

以nginx-svc这个服务为例
简单的yaml文件如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apiVersion: v1
kind: Service
metadata:
name: my-nginx
labels:
run: my-nginx
spec:
externalIPs:
- 172.18.0.3
ports:
- name: http
port: 80
targetPort: 80
selector:
run: my-nginx
type: LoadBalancer

创建
kubectl apply -f nginx-svc.yaml

获取
kubectl get svc my-nginx

描述
kubectl describe svc my-nginx

编辑
kubectl edit scv my-nginx

访问服务

内部访问

在集群内部, 访问service主要通过2种方式: 环境变量和DNS

比如linux自带的环境变量, 就是在env文件里定义好变量名和服务域名(IP), 写死的.

DNS是由coreDNS负责解析的, 每个service会自带一个名字name, 这个name由如下规则定义域名
<name>.<namespace>.svc.cluster.local

例如一个叫collector的名字的服务, ns为juice, 则dns为
collector.juice.svc.cluster.local

注意, 这个dns只能在pod里使用

外部访问

如果是从集群外部访问, 我们可以通过两种方式:NodePorts 和 LoadBalancer
NodePorts好配置, Loadbalancer就是生产环境的内容了, 不了解.
还有一个ingress也可以用来访问服务, 不过这个是另一个对象, 相当于服务的再抽象, 这里不多说(反正我暂时用不到).

当节点有externalIP(也就是所在的机器节点的IP地址)时,我们只需要简单创建服务即可从外部访问
如下为示例的yaml文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
apiVersion: v1
kind: Service
metadata:
namespace: juice
name: juice-collector
spec:
selector:
app: juice-collector
ports:
- port: 30002
targetPort: 30002
protocol: TCP
nodePort: 30002
type: NodePort

如上, 我们只需要指定nodeport或者load-balancer即可

此时我们通过curl https://<EXTERNAL-IP>:<NODE-PORT> -k即可访问

这个ExternalIP是什么呢?

先说结论:
ExternalIP可以简单理解为公网IP, 即物理机器对外的IP地址. 这是和硬件绑定的, k8s不能创建ExternalIP.
这个公网是相对的, 比如如果是一个学校的局域网IP, 那这个就是在学校内的"公网IP", 而不是校外的公网.

调查ExternalIP

首先在k8s官网可以找到这么一句话

其中 external-ip 是你的服务的外部 IP 地址(LoadBalancer Ingress)

英文版的是这样的

ExternalIP: Typically the IP address of the node that is externally routable (available from outside the cluster).

都说的很含糊

然后搜索引擎, 只能找到这种答复

只有公有云上才有ExternalIP
ExternalIP 是公网IP
裸金属众所周知都是<None>

并且, 某些plugin会判断InternalIP和ExternalIP, 产生不同的结果

那么k8s是怎么发现的呢?通过找到这篇文章, 发现了源码层面的奥义(这里就不搬运了,源码分析可以自己去原文看)

以下为部分原文

首先,InternalIP是可以被指定的,kubeadm 的init带有一个参数--node-ip让你去指定它。所谓InternalIP实际上就是指Kubernetes集群内部可以被直接访问的Node的IP地址,那么ExternalIP呢?按照定义,它只是在集群外部可路由的,但是Kubernetes并没有规定它到底应该是什么。它把这个字段的设置或者说实现,交给了Cloud Provider,云供应商。

需要特别特别强调的是,不要看到云供应商就以为是公有云,实际上也可以是OpenStack或者vSphere。云供应商需要符合CPI接口规范去开发插件,在Kubernetes的Github组里你可以搜到各种cloud-provider-xxx。

在OpenStack的源码里可以找到ExternalIP对应的定义

  • 本地环境时, 这个IP是虚拟机创建的时候指定的参数
  • 云环境时, 这个IP是云服务提供商指定的, 也就是公网IP

ExternalIP 不是k8s自己的, 可以简单理解为公网IP, 在本地环境时是虚拟机硬件层面的东西

服务发现

//todo


参考文章
https://zhuanlan.zhihu.com/p/466681599