关于 Kubernetes中Service的一些笔记
Posted 山河已无恙
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于 Kubernetes中Service的一些笔记相关的知识,希望对你有一定的参考价值。
写在前面
- 学习
K8s
,整理记忆 - 博文内容涉及:
K8s
中通过Servie
的实现的服务创建
,服务发现
,服务发布
- 以及
Load balancer
负载,Ingress7层路由负载
等的实际Demo
陈平安说,“我喜欢的姑娘,她已经是最好看了。可是比最好看更好看的她,是我在看她的时候、她假装不知道的时候,侧着脸,睫毛微颤的模样。” ——烽火戏诸侯《剑来》
Service
Service
是Kubernetes
的核心概念,可以为一组具有相同功能的容器应用提供一个统一的入口地址
,并且通过多实例的方式将请求负载分发到后端的各个容器应用上。具体涉及service的负载均衡机制、如何访问Service
、 Headless Service
, DNS服务
的机制和实践、Ingress 7层路由机制
等。
我们这里以服务的
创建,发布,发现
三个角度来学习,偏实战,关于Headless Service
,DNS服务
的机制和实践、Ingress 7层路由机制
等一些原理理论会在之后的博文里分享
通过Service的定义, Kubernetes实现了一种分布式应用统一入口的定义和负载均衡机制。Service还可以进行其他类型的设置,例如设置多个端口号、直接设置为集群外部服务,或实现为Headless Service (无头服务)模式.
Kubernetes的Service定义了一个服务的访问入口地址
,前端的应用(Pod)
通过这个入口地址访问其背后的一组由Pod副本组成的集群实例, Service与其后端Pod副本集群之间则是通过Label Selector来实现“无缝对接”的。而RC或者deploy的作用实际上是保证Service的服务能力和服务质量始终处干预期的标准。
服务创建
为什么需要Service
学习环境准备,新建一个liruilong-svc-create
命名空间
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$d=k8s-svc-create
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$mkdir $d ;cd $d
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create]
└─$kubectl config set-context $(kubectl config current-context) --namespace=liruilong-svc-create
Context "kubernetes-admin@kubernetes" modified.
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create]
└─$kubectl create ns liruilong-svc-create
namespace/liruilong-svc-create created
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create]
└─$kubectl get svc
No resources found in liruilong-svc-create namespace.
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create]
└─$
使用pod资源创建服务
我们先来创建一个普通服务即不使用Service资源,只是通过pod创建
通过命令行的方式生成一个pod资源的yaml文件,然后我们修改一下
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create]
└─$kubectl run pod-svc --image=nginx --image-pull-policy=IfNotPresent --dry-run=client -o yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: pod-svc
name: pod-svc
spec:
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: pod-svc
resources:
dnsPolicy: ClusterFirst
restartPolicy: Always
status:
这里我们修改下,使当前的pod可以对外提供能力,使用的方式,通过设置容器级别的hostPort
,将容器应用的端口号映射到宿主机上
ports:
- containerPort: 80 # 容器端口
hostPort: 800 # 提供能力的端口
通过宿主机映射,当pod发生调度后,节点没法提供能力
通过设置Pod级别
的hostNetwork=true
,该Pod中所有容器的端口号都将被直接映射到物理机上。 在设置hostNetwork=true
时需要注意,在容器的ports定义部分如果不指定hostPort,则默认hostPort等于containerPort,如果指定了hostPort,则hostPort必须等于containerPort的值:
spec
nostNetwork: true
containers:
name: webapp
image: tomcat
imagePullPolicy: Never
ports:
- containerPort: 8080
通过下面的方式生成的pod可以通过800端口对外提供能力,这里的的IP为宿主机IP
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create]
└─$cat pod-svc.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: pod-svc
name: pod-svc
spec:
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: pod-svc
ports:
- containerPort: 80
hostPort: 800
resources:
dnsPolicy: ClusterFirst
restartPolicy: Always
status:
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create]
└─$
这是一个单独的pod资源,生成的pod基于当前Node对外提供能力
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create]
└─$kubectl apply -f pod-svc.yaml
pod/pod-svc created
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create]
└─$kubectl get pods -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-svc 1/1 Running 0 3s 10.244.70.50 vms83.liruilongs.github.io <none> <none>
对于pod-svc
来讲,我们可以通过pod_ip+端口的方式访问,其实是类似于docker一样,把端口映射到宿主机的方式
然后我们以同样的方式生成几个新的pod,也是基于当前Node节点对外提供能力,这里我们只有两个节点,所以在生成第三个的时候,pod直接pending了,端口冲突,我们使用了宿主机映射的方式,所以每个node只能调度一个pop上去
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create]
└─$sed 's/pod-svc/pod-svc-1/' pod-svc.yaml | kubectl apply -f -
pod/pod-svc-1 created
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create]
└─$kubectl get pods -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-svc 1/1 Running 0 2m46s 10.244.70.50 vms83.liruilongs.github.io <none> <none>
pod-svc-1 1/1 Running 0 13s 10.244.171.176 vms82.liruilongs.github.io <none> <none>
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create]
└─$sed 's/pod-svc/pod-svc-2/' pod-svc.yaml | kubectl apply -f -
pod/pod-svc-2 created
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create]
└─$kubectl get pods -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-svc 1/1 Running 0 4m18s 10.244.70.50 vms83.liruilongs.github.io <none> <none>
pod-svc-1 1/1 Running 0 105s 10.244.171.176 vms82.liruilongs.github.io <none> <none>
pod-svc-2 0/1 Pending 0 2s <none> <none> <none> <none>
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create]
└─$
这个时候,如果我们想多创建几个pod来提供能力,亦或者做负载。就要用到Service了
Service的创建
一般来说,对外提供服务的应用程序需要通过某种机制来实现,对于容器应用最简便的方式就是通过TCP/IP机制及监听IP和端口号来实现。即PodIP+容器端口的方式
直接通过Pod的IP地址和端口号可以访问到容器应用内的服务,但是Pod的IP地址是不可靠的
,如果容器应用本身是分布式的部署方式,通过多个实例共同提供服务,就需要在这些实例的前端设置一个负载均衡器来实现请求的分发。
Kubernetes中的Service就是用于解决这些问题的核心组件。通过kubectl expose命令来创建Service
新创建的Service,系统为它分配了一个虚拟的IP地址(ClusterlP) , Service所需的端口号则从Pod中的containerPort复制而来:
下面我们就使用多个pod和deploy的方式为Service提供能力,创建Service
使用deployment创建SVC
创建一个有三个ng副本的deployment
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create]
└─$kubectl create deployment web1 --image=nginx --replicas=3 --dry-run=client -o yaml
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: web1
name: web1
spec:
replicas: 3
selector:
matchLabels:
app: web1
strategy:
template:
metadata:
creationTimestamp: null
labels:
app: web1
spec:
containers:
- image: nginx
name: nginx
resources:
status:
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create]
└─$kubectl create deployment web1 --image=nginx --replicas=3 --dry-run=client -o yaml > web1.yaml
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create]
└─$kubectl get pods -o wide
No resources found in liruilong-svc-create namespace.
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create]
└─$kubectl apply -f web1.yaml
deployment.apps/web1 created
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create]
└─$kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web1-6fbb48567f-2zfkm 0/1 ContainerCreating 0 2s <none> vms83.liruilongs.github.io <none> <none>
web1-6fbb48567f-krj4j 0/1 ContainerCreating 0 2s <none> vms83.liruilongs.github.io <none> <none>
web1-6fbb48567f-mzvtk 0/1 ContainerCreating 0 2s <none> vms82.liruilongs.github.io <none> <none>
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create]
└─$
通过deploy: web1 为服务能力提供者,创建一个Servie服务
除了使用kubectl expose
命令创建Service
,我们也可以通过配置文件定义Service
,再通过kubectl create
命令进行创建
Service定义中的关键字段是ports和selector 。ports定义部分指定了Service所需的虚拟端口号为8081,如果与Pod容器端口号8080不一样,所以需要再通过targetPort来指定后端Pod的端口号。selector定义部分设置的是后端Pod所拥有的label:
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create]
└─$kubectl expose --name=svc1 deployment web1 --port=80
service/svc1 exposed
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create]
└─$kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
svc1 ClusterIP 10.110.53.142 <none> 80/TCP 23s app=web1
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create]
└─$kubectl get pods
NAME READY STATUS RESTARTS AGE
web1-6fbb48567f-2zfkm 1/1 Running 0 14m
web1-6fbb48567f-krj4j 1/1 Running 0 14m
web1-6fbb48567f-mzvtk 1/1 Running 0 14m
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create]
└─$kubectl get ep -owide
NAME ENDPOINTS AGE
svc1 10.244.171.177:80,10.244.70.60:80,10.244.70.61:80 13m
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create]
└─$kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
web1-6fbb48567f-2zfkm 1/1 Running 0 18m app=web1,pod-template-hash=6fbb48567f
web1-6fbb48567f-krj4j 1/1 Running 0 18m app=web1,pod-template-hash=6fbb48567f
web1-6fbb48567f-mzvtk 1/1 Running 0 18m app=web1,pod-template-hash=6fbb48567f
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create]
└─$
使用pod创建Service
每个Pod都会被分配一个单独的IP地址,而且每个Pod都提供了一个独立的Endpoint(Pod IP+ContainerPort)
以被客户端访问,现在多个Pod副本组成了一个集群来提供服务.客户端如何来访问它们呢?一般的做法是部署一个负载均衡器(软件或硬件),
Kubernetes
中运行在每个Node
上的kube-proxy
进程其实就是一个智能的软件负载均衡器
,它负责把对Service的请求转发到后端的某个Pod实例上,并在内部实现服务的负载均衡与会话保持机制。
资源文件定义
┌──[root@vms81.liruilongs.github.io]-[~/ansible/liveness-probe]
└─$cat readiness-probe.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: pod-liveness
name: pod-liveness
spec:
containers:
image: nginx
imagePullPolicy: IfNotPresent
name: pod-liveness
resources:
dnsPolicy: ClusterFirst
restartPolicy: Always
status:
创建3个有Ngixn的pod,通过POD创建一个SVC做测试用
┌──[root@vms81.liruilongs.github.io]-[~/ansible/liveness-probe]
└─$sed 's/pod-liveness/pod-liveness-1/' readiness-probe.yaml | kubectl apply -f -
pod/pod-liveness-1 created
┌──[root@vms81.liruilongs.github.io]-[~/ansible/liveness-probe]
└─$sed 's/pod-liveness/pod-liveness-2/' readiness-probe.yaml | kubectl apply -f -
pod/pod-liveness-2 created
┌──[root@vms81.liruilongs.github.io]-[~/ansible/liveness-probe]
└─$kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-liveness 1/1 Running 0 3m1s 10.244.70.50 vms83.liruilongs.github.io <none> <none>
pod-liveness-1 1/1 Running 0 2m 10.244.70.51 vms83.liruilongs.github.io <none> <none>
pod-liveness-2 1/1 Running 0 111s 10.244.70.52 vms83.liruilongs.github.io <none> <none>
修改主页文字
┌──[root@vms81.liruilongs.github.io]-[~/ansible/liveness-probe]
└─$serve=pod-liveness
┌──[root@vms81.liruilongs.github.io]-[~/ansible/liveness-probe]
└─$kubectl exec -it $serve -- sh -c "echo $serve > /usr/share/nginx/html/index.html"
┌──[root@vms81.liruilongs.github.io]-[~/ansible/liveness-probe]
└─$kubectl exec -it $serve -- sh -c "cat /usr/share/nginx/html/index.html"
pod-liveness
┌──[root@vms81.liruilongs.github.io]-[~/ansible/liveness-probe]
└─$serve=pod-liveness-1
┌──[root@vms81.liruilongs.github.io]-[~/ansible/liveness-probe]
└─$kubectl exec -it $serve -- sh -c "echo $serve > /usr/share/nginx/html/index.html"
┌──[root@vms81.liruilongs.github.io]-[~/ansible/liveness-probe]
└─$serve=pod-liveness-2
┌──[root@vms81.liruilongs.github.io]-[~/ansible/liveness-probe]
└─$kubectl exec -it $serve -- sh -c "echo $serve > /usr/share/nginx/html/index.html"
┌──[root@vms81.liruilongs.github.io]-[~/ansible/liveness-probe]
└─$
修改标签
┌──[root@vms81.liruilongs.github.io]-[~/ansible/liveness-probe]
└─$kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
pod-liveness 1/1 Running 0 15m run=pod-liveness
pod-liveness-1 1/1 Running 0 14m run=pod-liveness-1
pod-liveness-2 1/1 Running 0 14m run=pod-liveness-2
┌──[root@vms81.liruilongs.github.io]-[~/ansible/liveness-probe]
└─$kubectl edit pods pod-liveness-1
pod/pod-liveness-1 edited
┌──[root@vms81.liruilongs.github.io]-[~/ansible/liveness-probe]
└─$kubectl edit pods pod-liveness-2
pod/pod-liveness-2 edited
┌──[root@vms81.liruilongs.github.io]-[~/ansible/liveness-probe]
└─$kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
pod-liveness 1/1 Running 0 17m run=pod-liveness
pod-liveness-1 1/1 Running 0 16m run=pod-liveness
pod-liveness-2 1/1 Running 0 16m run=pod-liveness
┌──[root@vms81.liruilongs.github.io]-[~/ansible/liveness-probe]
└─$
使用POD创建SVC
┌──[root@vms81.liruilongs.github.io]-[~/ansible/liveness-probe]
└─$kubectl expose --name=svc pod pod-liveness --port=80
service/svc exposed
┌──[root@vms81.liruilongs.github.io]-[~/ansible/liveness-probe]
└─$kubectl get ep
NAME ENDPOINTS AGE
svc 10.244.70.50:80,10.244.70.51:80,10.244.70.52:80 16s
┌──[root@vms81.liruilongs.github.io]-[~/ansible/liveness-probe]
└─$kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
svc ClusterIP 10.104.246.121 <none> 80/TCP 36s
┌──[root@vms81.liruilongs.github.io]-[~/ansible/liveness-probe]
└─$kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-liveness 1/1 Running 0 24m 10.244.70.50 vms83.liruilongs.github.io <none> <none>
pod-liveness-1 1/1 Running 0 23m 10.244.70.51 vms83.liruilongs.github.io <none> <none>
pod-liveness-2 1/1 Running 0 23m 10.244.70.52 vms83.liruilongs.github.io <none> <none>
测试SVC正常,三个POD会正常 负载
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$while true; do curl 10.104.246.121 ; sleep 1
> done
pod-liveness
pod-liveness-2
pod-liveness
pod-liveness-1
pod-liveness-2
^C
基于 ClusterlP
提供的两种负载分发策略
目前 Kubernetes
提供了两种负载分发策略:RoundRobin
和SessionAffinity
负载分发策略 | 描述 |
---|---|
RoundRobin | 轮询模式,即轮询将请求转发到后端的各个Pod上。 |
SessionAffinity | 基于客户端IP地址进行会话保持的模式, |
在默认情况下, Kubernetes采用RoundRobin模式对客户端请求进行,负载分发,但我们也可以通过设置service.spec.sessionAffinity=ClientIP
来启用SessionAffinity
策略。
查看svc包含的Pod
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create]
└─$kubectl get svc -owide | grep -v NAME | awk 'print $NF' | xargs kubectl get pods -l
NAME READY STATUS RESTARTS AGE
pod-svc 1/1 Running 0 18m
pod-svc-1 1/1 Running 0 17m
pod-svc-2 1/1 Running 0 16m
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create]
└─$
端口的请求转发及多端口设置
一个容器应用也可能提供多个端口的服务,那么在Service的定义中也可以相应地设置为将多个端口转发到多个应用服务。
Kubernetes Service支持多个Endpoint(端口),在存在多个Endpoint的情况下,要求每个Endpoint定义一个名字来区分。下面是Tomcat多端口的Service定义样例:
- port: 8080
targetPort: 80
name: web1
- port: 8008
targetPort: 90
name: web2
多端口为什么需要给每个端口命名呢?这就涉及Kubernetes的服务发现机制了(通过DNS是方式实现的服务发布)
命令行的方式
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create]
└─$kubectl expose --name=svc pod pod-svc --port=808 --target-port=80 --selector=run=pod-svc
service/svc exposed
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create]
└─$kubectl get svc -owide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
svc ClusterIP 10.102.223.233 <none> 808/TCP 4s run=pod-svc
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create]
└─$
kube-proxy的路由规则不同,ServiceIP的访问也不同
- iptable: Service(CLUSTER-IP )地址 ping 不通
- ipvs: Service(CLUSTER-IP )地址可以ping通
服务的发现
所谓服务发现,就是我们在pod内部,或者说容器内部,怎么获取到要访问的服务的IP和端口。类似于微服务中的注册中心概念
Kubernetes 的服务发现机制 | 区别 |
---|---|
最早时Kubernetes采用了Linux环境变量 的方式解决这个问题,即每个Service生成一些对应的Linux环境变量(ENV),并在每个Pod的容器在启动时,自动注入这些环境变量 | 命名空间隔离 |
后来Kubernetes通过Add-On增值包的方式引入了DNS系统 ,把服务名作为DNS域名 ,这样一来,程序就可以直接使用服务名来建立通信连接了。目前Kubernetes上的大部分应用都已经采用了DNS这些新兴的服务发现机制 | 命名空间可见 |
环境准备,我们还是用之前的那个pod做的服务来处理
┌──[root@vms81.liruilongs.github.io]-[~]
└─$kubectl get pods -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-svc 1/1 Running 0 69m 10.244.70.35 vms83.liruilongs.github.io <none> <none>
pod-svc-1 1/1 Running 0 68m 10.244.70.39 vms83.liruilongs.github.io <none> <none>
pod-svc-2 1/1 Running 0 68m 10.244.171.153 vms82.liruilongs.github.io <none> <none>
┌──[root@vms81.liruilongs.github.io]-[~]
└─$s=pod-svc
┌──[root@vms81.liruilongs.github.io]-[~]
└─$kubectl exec -it $s -- sh -c "echo $s > /usr/share/nginx/html/index.html"
┌──[root@vms81.liruilongs.github.io]-[~]
└─$s=pod-svc-1
┌──[root@vms81.liruilongs.github.io]-[~]
└─$kubectl exec -it $s -- sh -c "echo $s > /usr/share/nginx/html/index.html"
┌──[root@vms81.liruilongs.github.io]-[~]
└─$s=pod-svc-2
┌──[root@vms81.liruilongs.github.io]-[~]
└─$kubectl exec -it $s -- sh -c "echo $s > /usr/share/nginx/html/index.html"
┌──[root@vms81.liruilongs.github.io]-[~]
└─$kubectl get svc -owide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
svc ClusterIP 10.102.223.233 <none> 808/TCP 46m run=pod-svc
┌──[root@vms81.liruilongs.github.io]-[~]
└─$while true ;do curl 10.102.223.233:808;sleep 2 ; done
pod-svc-2
pod-svc-1
pod-svc
pod-svc
pod-svc
pod-svc-2
^C
┌──[root@vms81.liruilongs.github.io]-[~]
└─$
测试镜像准备
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible node -m shell -a "docker pull yauritux/busybox-curl"
通过Linux环境变量方式发现:命名空间隔离
在每个创建的pod里会存在已经存在的SVC的变量信息,这些变量信息基于命名空间隔离,
其他命名空间没有
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-svc-create]
└─$kubectl run testpod -it --rm --image=yauritux/busybox-curl --image-pull-policy=IfNotPresent -n default
If you don't see a command prompt, try pressing enter.
/home # env | grep ^SVC
/home #
只存在当前命名空间,只能获取相同namespace里的变量
换句话的意思,在相同的命名空间里,我们可以在容器里通过变量的方式获取已经存在的Service来提供能力
┌──[root@vms81.liruilongs.github.io]-[~]
└─$kubectl run testpod -it --rm --image=yauritux/busybox-curl --image-pull-policy=IfNotPresent
If you don't see a command prompt, try pressing enter.
/home # env | grep ^SVC
SVC_PORT_808_TCP_ADDR=10.102.223.233
SVC_PORT_808_TCP_PORT=808
SVC_PORT_808_TCP_PROTO=tcp
SVC_SERVICE_HOST=10.102.223.233
SVC_PORT_808_TCP=tcp://10.102.223.233:808
SVC_SERVICE_PORT=808
SVC_PORT=tcp://10.102.223.233:808
/home #
/home # while true ;do curl $SVC_SERVICE_HOST:$SVC_PORT_808_TCP_PORT ;sleep 2 ; done
pod-svc-2
pod-svc-2
pod-svc
pod-svc
^C
/home #
通过DNS的方式发现:命名空间可见
Kubernetes发明了一种很巧妙又影响深远的设计:
Service不是共用一个负载均衡器的IP地址,而是每个Service
分配了一个全局唯一的虚拟IP地址,这个虚拟IP被称为Cluster IP
,这样一来,每个服务就变成了具备唯一IP地址的“通信节点”
,服务调用就变成了最基础的TCP网络通信问题
。
Service一旦被创建, Kubernetes就会自动为它分配一个可用的Cluster IP,而且在Service的整个生命周期内,它的Cluster IP不会发生改变。于是,服务发现这个棘手的问题在Kubernetes的架构里也得以轻松解决:只要用Service的Name与Service的Cluster IP地址做一个DNS域名映射即可完美解决问题。
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$kubectl get svc -n kube-system -owide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 6d20h k8s-app=kube-dns
metrics-server ClusterIP 10.111.104.173 <none> 443/TCP 6d18h k8s-app=metrics-server
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$kubectl get pods -n kube-system -l k8s-app=kube-dns
NAME READY STATUS RESTARTS AGE
coredns-7f6cbbb7b8-ncd2s 1/1 Running 2 (23h ago) 3d22h
coredns-7f6cbbb7b8-pjnct 1/1 Running 2 (23h ago) 3d22h
有个这个DNS服务之后,创建的每个SVC就会自动的注册一个DNS
┌──[root@vms81.liruilongs.github.io]-[~]
└─$kubectl run testpod -it --rm --image=yauritux/busybox-curl --image-pull-policy=IfNotPresent
If you don't see a command prompt, try pressing enter.
/home # cat /etc/resolv.conf
nameserver 10.96.0.10
search liruilong-svc-create.svc.cluster.local svc.cluster.local cluster.local localdomain 168.26.131
options ndots:5
/home #
在kube-system里有dns,可以自动发现所有命名空间里的服务的clusterIP
,所以,在同一个命名空间里,一个服务访问另外一个服务的时候,可以直接通过服务名来访问
,只要创建了一个服务(不管在哪个ns里创建的),都会自动向kube-system里的DNS注册
如果是不同的命名空间,可以通过服务名.命名空间名
来访问`服务名.命名空间
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$kubect以上是关于关于 Kubernetes中Service的一些笔记的主要内容,如果未能解决你的问题,请参考以下文章
关于Kubernetes中Service Account的一些笔记:Pod内部如何访问K8s集群
关于 Kubernetes中Service使用Metallb实现LoadBalancer的一个Demo
关于 Kubernetes中Service使用Metallb实现LoadBalancer的一个Demo
关于 Kubernetes中Service使用ingress-nginx-controller实现Ingress负载均衡器的一个Demo
关于 Kubernetes中Service使用ingress-nginx-controller实现Ingress负载均衡器的一个Demo