文章目录
- 服务的介绍
- 服务代理
- 服务发现
- 连接集群外服务
- 服务发布
- 无头服务
- 服务,pod和dns的关系
- 端口转发
- 通过expose 暴露应用
- 服务案例
- INGRESS
- MetalLB使用
- 参考文档
服务的介绍
服务的作用是啥?
提供外部调用,保证podip的真实性
看看服务解决了什么问题?
[root@k8s-01 chapter05]# cat web-rs.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: web
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
[root@k8s-01 chapter05]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-97499b967-jzxwg 1/1 Running 0 35h 10.244.1.2 k8s-02 <none> <none>
web-dgn64 1/1 Running 0 76s 10.244.1.54 k8s-02 <none> <none>
web-x4kkz 1/1 Running 0 76s 10.244.1.52 k8s-02 <none> <none>
web-xx2md 1/1 Running 0 76s 10.244.1.53 k8s-02 <none> <none>
rs控制数量为3,如果这3个换了呢,这些ip地址如何让客户端知道呢?
pod 和服务之间的关系,依旧是标签来控制
[root@k8s-01 chapter05]# cat web-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
ports:
- port: 80
targetPort: 80
selector:
app: nginx[root@k8s-01 chapter05]# kubectl apply -f web-svc.yaml
service/my-service created
[root@k8s-01 chapter05]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 35h
my-service ClusterIP 10.107.106.26 <none> 80/TCP 5s
nginx NodePort 10.104.210.165 <none> 80:30001/TCP 35h
上面是创建了服务,服务创建之后,有一个ip
查看集群分配给服务的Ip
# kubectl get svc
#访问刚才创建的服务三种方式
创建一个Pod,访问服务的Ip
在k8s的任何一个节点访问
使用任何一个现有服务所属任何pod访问
下面图片有它的处理过程
查看服务和后面pod的ip地址信息
[root@k8s-01 chapter05]# kubectl describe svc my-service
Name: my-service
Namespace: default
Labels: <none>
Annotations: Selector: app=nginx
Type: ClusterIP
IP: 10.107.106.26
Port: <unset> 80/TCP
TargetPort: 80/TCP
Endpoints: 10.244.1.2:80,10.244.1.52:80,10.244.1.53:80 + 1 more...
Session Affinity: None
Events: <none>
#此处如果删除一个pod,查看service中的podip 也会随着变化
实验一: 配置 sessionAffinity: ClientIP
[root@k8s-01 chapter05]# cat web-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
sessionAffinity: ClientIP
ports:
- port: 80
targetPort: 80
selector:
app: nginx
[root@k8s-01 chapter05]# kubectl delete svc/my-service
service "my-service" deleted
[root@k8s-01 chapter05]# kubectl apply -f web-svc.yaml
service/my-service created
[root@k8s-01 chapter05]# kubectl describe svc my-service
Name: my-service
Namespace: default
Labels: <none>
Annotations: Selector: app=nginx
Type: ClusterIP
IP: 10.104.130.27
Port: <unset> 80/TCP
TargetPort: 80/TCP
Endpoints: 10.244.1.2:80,10.244.1.52:80,10.244.1.53:80 + 1 more...
Session Affinity: ClientIP
Events: <none>
实验二:设置自定义的服务ip
[root@k8s-01 chapter05]# vim web-svc.yaml
[root@k8s-01 chapter05]# kubectl apply -f web-svc.yaml
service/my-service created
[root@k8s-01 chapter05]# kubectl describe svc web-service
Error from server (NotFound): services "web-service" not found
[root@k8s-01 chapter05]# cat web-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
clusterIP: 10.104.130.24
sessionAffinity: ClientIP
ports:
- port: 80
targetPort: 80
selector:
app: nginx
[root@k8s-01 chapter05]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-97499b967-jzxwg 1/1 Running 0 35h
web-tsxck 1/1 Running 0 34m
web-x4kkz 1/1 Running 0 50m
web-xx2md 1/1 Running 0 50m
[root@k8s-01 chapter05]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 36h
my-service ClusterIP 10.104.130.24 <none> 80/TCP 33s
nginx NodePort 10.104.210.165 <none> 80:30001/TCP 35h
实验三: 创建没有选择器的服务
服务通常抽象访问Kubernetes pods,但是它也可以抽象访问其它类型的后端,比如:
比如使用外部的数据库集群
指向服务到不同的命名空间或其它kubernetes集群的服务
在上面任何一种情况下,都可以定义一个没有Pod选择器的服务,比如:
由于上面定义的服务没有选择器,对应的Endpoint对象也不会自动创建,因此需要手工的创建Endpoint.
kind: Endpoints
服务代理
Userspace
Iptables
Ipvs
以上三种模式,ipvs用的多
服务发现
查看某个pod的 环境变量
kubectl exec web-tsxck env
生产环境中要先创建服务在创建pod,否则pod里面的环境变量没有服务的变量
服务发现通过两种方式,1.环境变量 2. DNS
DNS的服务方式
一个完整的FQDN如下所示:
Backend-database.default.svc.cluster.local
进入到容器里面,
kubectl exec -it web-sfe1d -- bash
curl http://my-service
curl http://my-service.default.svc.cluster.local
cat /etc/resolv.conf
连接集群外服务
一般是数据库,云数据库信息
查看服务的endpoints
[root@k8s-01 chapter05]# kubectl get endpoints
NAME ENDPOINTS AGE
kubernetes 192.168.100.30:6443 37h
my-service 10.244.1.2:80,10.244.1.52:80,10.244.1.53:80 + 1 more... 80m
nginx 10.244.1.2:80,10.244.1.52:80,10.244.1.53:80 + 1 more... 37h
查看apiversion版本
[root@k8s-01 chapter05]# kubectl explain endpoints.apiVersion
KIND: Endpoints
VERSION: v1
FIELD: apiVersion <string>
DESCRIPTION:
APIVersion defines the versioned schema of this representation of an
object. Servers should convert recognized schemas to the latest internal
value, and may reject unrecognized values. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
[root@k8s-01 chapter05]# cat external-service.yaml
apiVersion: v1
kind: Service
metadata:
name: external-service
spec:
ports:
- port: 80[root@k8s-01 chapter05]# cat external-endpoints.yaml
apiVersion: v1
kind: Endpoints
metadata:
name: external-service
subsets:
- addresses:
- ip: 192.168.100.31
ports:
- port: 30001
[root@k8s-01 chapter05]# cat external-endpoints-alias.yaml
apiVersion: v1
kind: Service
metadata:
name: external-service
spec:
type: ExternalName
externalName: feitianshi.cc.cc
ports:
- port: 30001
注意:此部分实验未成功,各位可以自己参考配置文件
[root@k8s-01 chapter05]# kubectl describe svc external-service
Name: external-service
Namespace: default
Labels: <none>
Annotations: Selector: <none>
Type: ClusterIP
IP: 10.105.6.128
Port: <unset> 80/TCP
TargetPort: 80/TCP
Endpoints: 192.168.100.31:30001
Session Affinity: None
Events: <none>
服务发布
发布服务的类型如下
ClusterIP 内部访问
NodePort 外部访问
LoadBalancer 外部访问
ExternalName 内部访问
案例
NodePort:
创建服务
kubectl create –f web-svc-nodeport.yaml
检查NodePort服务
kubectl get svc web-nodeport
[root@k8s-01 chapter05]# cat web-svc-nodeport.yaml
apiVersion: v1
kind: Service
metadata:
name: web-nodeport
spec:
type: NodePort
ports:
- port: 80
targetPort: 80
nodePort: 30123
selector:
app: nginx[root@k8s-01 chapter05]# kubectl create -f web-svc-nodeport.yaml
service/web-nodeport created
[root@k8s-01 chapter05]# kubectl get svc web-nodeport
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
web-nodeport NodePort 10.105.18.188 <none> 80:30123/TCP 8s
[root@k8s-01 chapter05]# curl 10.105.18.188
<!DOCTYPE html>
[root@k8s-01 chapter05]# cat web-svc-loadbalancer.yaml
apiVersion: v1
kind: Service
metadata:
name: web-loadbalancer
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 80
selector:
app: nginx
[root@k8s-01 chapter05]# cat service-external-ip.yaml
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: nginx
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
externalIPs:
- 192.168.100.199
无头服务
无头服务:没有clusterIp字段的服务就是无头服务。
有些服务需要直接连接后端的pod
案例:
- 创建无头服务
# kubectl create –f web-headless.yaml
[root@k8s-01 chapter05]# cat web-headless.yaml
apiVersion: v1
kind: Service
metadata:
name: web-headless
spec:
clusterIP: None
ports:
- port: 80
targetPort: 80
selector:
app: nginx
- 查看创建的服务
# kubectl get svc
# kubectl describe svc web-headless
通过dns发现pods
# kubectl run dnsutils --image=tutum/dnsutils --generator=run-pod/v1 --command -- sleep infinity
# kubectl exec dnsutils nslookup web-headless
[root@k8s-01 chapter05]# kubectl exec dnsutils nslookup web-headless
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl kubectl exec [POD] -- [COMMAND] instead.
Server: 10.96.0.10
Address: 10.96.0.10#53
Name: web-headless.default.svc.cluster.local
Address: 10.244.1.61
Name: web-headless.default.svc.cluster.local
Address: 10.244.1.60
Name: web-headless.default.svc.cluster.local
Address: 10.244.1.2
Name: web-headless.default.svc.cluster.local
Address: 10.244.1.59
[root@k8s-01 chapter05]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 40h
my-service ClusterIP 10.104.130.24 <none> 80/TCP 2s
nginx NodePort 10.104.210.165 <none> 80:30001/TCP 39h
web-headless ClusterIP None <none> 80/TCP 8m50s
[root@k8s-01 chapter05]# kubectl exec dnsutils nslookup my-service
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl kubectl exec [POD] -- [COMMAND] instead.
Server: 10.96.0.10
Address: 10.96.0.10#53
Name: my-service.default.svc.cluster.local
Address: 10.104.130.24
无头服务比有头服务更快些,注意区分
服务,pod和dns的关系
什么东西可以获取DNS的名称?
集群中定义的每个服务都会被分配一个DNS名称。默认情况下,客户机pod的dns搜索列表包括Pod自己的名称空间和集群的默认域。
假设k8s集群bar的名称空间中有一个名为foo的服务,在该名称空间运行的pod可以直接对foo执行dns查询来查找此服务。在别的名称空间中执行foo.bar进行查询。
服务
A记录
普通服务分配一个DNS A记录作为表单的名称my-svc.my-namespace.svc.cluster-domain.example,这将解析到服务的集群IP。
无头服务也分配一个DNS记录,针对my-svg.my-namespace.svg.cluster-domain.example表单的名称。与普通服务不同,这将解析为服务选择的pod的ip集。
SRV记录
SRV记录是作为普通服务或无头服务一部分的指定端口创建的。每于每个指定端口,SRV记录都有相应的形式_my-port-name._my-port-protocol.my-svc.my-namespace.svc.cluster-domain.example。
对于无头服务,这解析为多个答案,每个答案对应一个支持的pod,并包含pod的端口号和域名。
Auto-generated-name.my-svcc.my-namespace.svc.cluster-domain.example
Pods
pods的主机名和子域名字段
比如在名称空间my-namespace中将主机名设置为“foo”,子域设置为“bar”的pod将具有完全限定的域为:foo.bar.my-namespace.svc.cluster-domain.example
Pods dns策略有以下4种:
Default
ClusterFirst
ClusterFirstWithHostNet
None
Pod dns配置
属性有以下三个:
Nameservers
Searchs
options
端口转发
对于排错比较方便
创建redis的部署和应用
创建deployment资源
# kubectl create –f redis-master-deployment.yaml
查看部署状态
# kubectl get pods
查看replicaset状态
# kubectl get rs
创建服务
# kubectl create –f redis-master-service.yaml
查看服务
# kubectl get svc | grep redis
校验运行在pod中的redis server是否侦听在6379端口
# kubectl get pods redis-master-7db7f6579f-zd27q –template=‘{{(index(index.spec.containers 0).ports 0).containerPort}}{{“\n”}}’
执行端口转发
# kubectl port-forward redis-master-7db7f6579f-zd27q 7000:6379
客户端进行测试
# redis-cli –p 7000
[root@k8s-01 chapter05]# cat redis-master-deployment.yaml
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
name: redis-master
labels:
app: redis
spec:
selector:
matchLabels:
app: redis
role: master
tier: backend
replicas: 1
template:
metadata:
labels:
app: redis
role: master
tier: backend
spec:
containers:
- name: master
image: redis # or just image: redis
resources:
requests:
cpu: 100m
memory: 100Mi
ports:
- containerPort: 6379
[root@k8s-01 chapter05]# cat redis-master-service.yaml
apiVersion: v1
kind: Service
metadata:
name: redis-master
labels:
app: redis
role: master
tier: backend
spec:
ports:
- port: 6379
targetPort: 6379
selector:
app: redis
role: master
tier: backend
通过expose 暴露应用
创建资源
# kubectl create –f hello-application.yaml
查看关于部署的信息
# kubectl get deployment hello-world
# kubectl describe deployments hello-world
# kubectl get replicasets
# kubectl describe replicasets
暴露刚才的部署
# kubectl expose deployment hello-world --type=NodePort --name=example-service
显示关于服务的信息
# kubectl describe services example-service
列出在Hello World应用运行的Pods
# kubectl get pods –selector=“run=load-balancer-example” --output=wide
使用下面的方法进行测试
# curl http://<public-node-ip>:<node-port>
[root@k8s-01 chapter05]# cat hello-application.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-world
spec:
selector:
matchLabels:
run: load-balancer-example
replicas: 2
template:
metadata:
labels:
run: load-balancer-example
spec:
containers:
- name: hello-world
image: "mike0405/node-hello:1.0"
ports:
- containerPort: 8080
protocol: TCP
[root@k8s-01 chapter05]# cat hello-service.yaml
apiVersion: v1
kind: Service
metadata:
name: hello
spec:
selector:
app: hello
tier: backend
ports:
- protocol: TCP
port: 80
targetPort: http
服务案例
创建后端的部署
# kubectl create –f hello.yaml
创建后端的服务
# kubectl create –f hello-service.yaml
创建前端的部署和服务
# kubectl create –f fronted.yaml
测试前端和后端的交互
# curl http://${EXTERNAL_IP}
[root@k8s-01 chapter05]# curl 192.168.100.31:32746
{"message":"Hello"}
[root@k8s-01 chapter05]# curl 192.168.100.31:32746
{"message":"Hello"}
[root@k8s-01 chapter05]# cat frontend.yaml
apiVersion: v1
kind: Service
metadata:
name: frontend
spec:
selector:
app: hello
tier: frontend
ports:
- protocol: "TCP"
port: 80
targetPort: 80
type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
spec:
selector:
matchLabels:
app: hello
tier: frontend
track: stable
replicas: 1
template:
metadata:
labels:
app: hello
tier: frontend
track: stable
spec:
containers:
- name: nginx
image: "mike0405/hello-frontend:1.0"
lifecycle:
preStop:
exec:
command: ["/usr/sbin/nginx","-s","quit"][root@k8s-01 chapter05]#
[root@k8s-01 chapter05]# cat hello.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello
spec:
selector:
matchLabels:
app: hello
tier: backend
track: stable
replicas: 7
template:
metadata:
labels:
app: hello
tier: backend
track: stable
spec:
containers:
- name: hello
image: "mike0405/hello-go-gke:1.0"
ports:
- name: http
containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: hello
spec:
selector:
app: hello
tier: backend
ports:
- protocol: "TCP"
port: 80
targetPort: 80
[root@k8s-01 chapter05]# kubectl get pod
NAME READY STATUS RESTARTS AGE
dnsutils 1/1 Running 0 129m
frontend-76c7d58dc5-l5kcz 1/1 Running 0 5m30s
hello-84ccf7cd9d-97htk 1/1 Running 0 7m2s
hello-84ccf7cd9d-9sl6v 1/1 Running 0 7m2s
hello-84ccf7cd9d-9tg8f 1/1 Running 0 7m2s
hello-84ccf7cd9d-bps5g 1/1 Running 0 7m2s
hello-84ccf7cd9d-lh446 1/1 Running 0 7m2s
hello-84ccf7cd9d-tl2gx 1/1 Running 0 7m2s
hello-84ccf7cd9d-w2hjz 1/1 Running 0 7m2s
hello-world-7457d6ddb5-g2fcf 1/1 Running 0 37m
hello-world-7457d6ddb5-mknkq 1/1 Running 0 37m
nginx-97499b967-jzxwg 1/1 Running 0 42h
redis-master-7d557b94bb-8wqjh 1/1 Running 0 60m
web-764vs 1/1 Running 0 4h8m
web-kd8ml 1/1 Running 0 4h8m
web-rqc7q 1/1 Running 0 4h8m
INGRESS
为什么需要INGRESS ?
一个重要原因,每个LoadBalancer服务都需要自己负载均衡器和自己的公共IP地址,而一个Ingress只需要一个,即使提供对数个服务的访问时也是如此。对象发送HTTP请求时请求中的主机和路径决定请求转发给哪个服务。
internet - ingress - service
ingress 可以理解成nginx配置文件
MetalLB使用
这个了解下,根据实际情况看
参考文档
https://edu.csdn.net/course/detail/27762?spm=1003.2449.3001.8295.2