文章目录
- 服务的介绍
- 服务代理
- 服务发现
- 连接集群外服务
- 服务发布
- 无头服务
- 服务,pod和dns的关系
- 端口转发
- 通过expose 暴露应用
- 服务案例
- INGRESS
- MetalLB使用
- 参考文档
服务的介绍
服务的作用是啥?
提供外部调用,保证podip的真实性看看服务解决了什么问题?
[root@k8s-01 chapter05]# cat web-rs.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:name: web
spec:replicas: 3selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:containers:- name: nginximage: 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: 80targetPort: 80selector: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: ClientIPports:- port: 80targetPort: 80selector: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.24sessionAffinity: ClientIPports:- port: 80targetPort: 80selector: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. DNSDNS的服务方式
一个完整的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: v1FIELD: apiVersion <string>DESCRIPTION:APIVersion defines the versioned schema of this representation of anobject. Servers should convert recognized schemas to the latest internalvalue, 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.31ports:- port: 30001
[root@k8s-01 chapter05]# cat external-endpoints-alias.yaml
apiVersion: v1
kind: Service
metadata:name: external-service
spec:type: ExternalNameexternalName: feitianshi.cc.ccports:- 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: NodePortports:- port: 80targetPort: 80nodePort: 30123selector: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: LoadBalancerports:- port: 80targetPort: 80selector:app: nginx[root@k8s-01 chapter05]# cat service-external-ip.yaml
apiVersion: v1
kind: Service
metadata:name: my-service
spec:selector:app: nginxports:- name: httpprotocol: TCPport: 80targetPort: 80externalIPs:- 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: Noneports:- port: 80targetPort: 80selector: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#53Name: 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#53Name: 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.examplePods
pods的主机名和子域名字段
比如在名称空间my-namespace中将主机名设置为“foo”,子域设置为“bar”的pod将具有完全限定的域为:foo.bar.my-namespace.svc.cluster-domain.examplePods dns策略有以下4种:
Default
ClusterFirst
ClusterFirstWithHostNet
NonePod 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-masterlabels:app: redis
spec:selector:matchLabels:app: redisrole: mastertier: backendreplicas: 1template:metadata:labels:app: redisrole: mastertier: backendspec:containers:- name: masterimage: redis # or just image: redisresources:requests:cpu: 100mmemory: 100Miports:- containerPort: 6379[root@k8s-01 chapter05]# cat redis-master-service.yaml
apiVersion: v1
kind: Service
metadata:name: redis-masterlabels:app: redisrole: mastertier: backend
spec:ports:- port: 6379targetPort: 6379selector:app: redisrole: mastertier: 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-examplereplicas: 2template:metadata:labels:run: load-balancer-examplespec:containers:- name: hello-worldimage: "mike0405/node-hello:1.0"ports:- containerPort: 8080protocol: TCP[root@k8s-01 chapter05]# cat hello-service.yaml
apiVersion: v1
kind: Service
metadata:name: hello
spec:selector:app: hellotier: backendports:- protocol: TCPport: 80targetPort: 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: hellotier: frontendports:- protocol: "TCP"port: 80targetPort: 80type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:name: frontend
spec:selector:matchLabels:app: hellotier: frontendtrack: stablereplicas: 1template:metadata:labels:app: hellotier: frontendtrack: stablespec:containers:- name: nginximage: "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: hellotier: backendtrack: stablereplicas: 7template:metadata:labels:app: hellotier: backendtrack: stablespec:containers:- name: helloimage: "mike0405/hello-go-gke:1.0"ports:- name: httpcontainerPort: 80
---
apiVersion: v1
kind: Service
metadata:name: hello
spec:selector:app: hellotier: backendports:- protocol: "TCP"port: 80targetPort: 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 - serviceingress 可以理解成nginx配置文件
MetalLB使用
这个了解下,根据实际情况看
参考文档
https://edu.csdn.net/course/detail/27762?spm=1003.2449.3001.8295.2