1.1 svc 服务的概念
将运行在一组 Pods 上的应用程序公开为网络服务的抽象方法。
Kubernetes 为 Pods 提供自己的 IP 地址,并为一组 Pod 提供相同的 DNS 名,也就是服务名, 并且可以在它们之间进行负载平衡。这就是服务
svc 的原理:
逻辑上的一组 Pod, 称为微服务
这组 Pod 能够通过 Service 访问到,通常是通过 标签选择器
svc 发现这组服务后,会根据负载均衡规则,将负载发给每一个 Pod
svc 本质就是一个 负载均衡器
svc 将负载转发给后端的 Pod ,是通过 kube-proxy 转发的
1.2 svc 服务的创建
如果没有指明 svc 的名字,svc 的名字是控制器的名字
–selector 选项用来指明,该 svc 控制哪些 Pod 做负载均衡,如果没指定,则是根据控制器的 标签 来选择
只要新启动的 Pod 的标签与 svc 管理 Pod 的标签相同,那么这个新建的 Pod 也会被该 svc 管理。
port 是暴露在 clusterIP 上的端口,供集群内部使用,targetPort 是容器内部的端口,nodePort 是暴露在 Node 节点上的端口,供外部访问 svc
例如:
kubectl expose 控制器 控制器名 [--port=port] [--protocol=TCP|UDP|SCTP] [--target-port=number-or-name]
[--name=name] [--external-ip=external-ip-of-service] [--type=type] [--selector=key=value] [options]
apiVersion v1
kind Service
metadata
name my-service
spec
selector
app nginx
ports
protocol TCP
port80
targetPort80
2. Service 服务发现
服务发现概念:
当 kubentes 中的一个 Pod 要访问 另一个服务的时候,这时候就要用到服务发现。
这个服务有可能是一个 Pod ,也可能是一组 Pod
这个服务就需要 让 Pod 能够访问到,因此称为服务发现
服务发现的类型有:
clusterIP
环境变量
方法:
在创建出服务后,默认的服务类型为 ClusterIP,可以通过 ClusterIP:Port 来访问对应的 svc 服务。
缺点:
服务需要先创建,才能查看 clsterIP
服务如果重建,ip 会变化,那么后面需要访问该服务的所有 Pod 都需要改变 clsterIP
例如:
[root@k8s-master svc]# kubectl get deployments.apps -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
web1 3/3 3 3 84m nginx nginx app=nginx
[root@k8s-master svc]# kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
web1-5c579f944f-6q8z5 1/1 Running 0 46m app1=nginx1,app=nginx,pod-template-hash=5c579f944f
web1-5c579f944f-h7fb5 1/1 Running 0 46m app1=nginx1,app=nginx,pod-template-hash=5c579f944f
web1-5c579f944f-hw5wq 1/1 Running 0 46m app1=nginx1,app=nginx,pod-template-hash=5c579f944f
[root@k8s-master svc]# kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
mysvc ClusterIP 10.98.157.226 <none> 80/TCP 39m app=nginx
[root@k8s-master svc]# kubectl run --image=busybox --rm -it -- bash
/ #
/ # wget 10.98.157.226
Connecting to 10.98.157.226 (10.98.157.226:80)
saving to 'index.html'
index.html 100% |***************************************************************************************************| 5 0:00:00 ETA
'index.html' saved
/ # cat index.html
3333
当 Pod 运行在 Node 上,kubelet 会为每个活跃的 Service 添加一组环境变量。
常用的 svc 的环境变量有::
{SVCNAME}_SERVICE_HOST : 表示服务的 ClusterIP
{SVCNAME}_SERVICE_PORT : 表示服务的 Port
缺点:
Pod 只能发现同一个命名空间里的服务
例如:
nginx 的服务为:
[root@k8s-master svc]# kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
mysvc ClusterIP 10.98.157.226 <none> 80/TCP 52m app=nginx
[root@k8s-master svc]# kubectl run --image=busybox --rm -it -- bash
/ # env | grep 'MYSVC'
MYSVC_PORT_80_TCP=tcp://10.98.157.226:80
MYSVC_SERVICE_HOST=10.98.157.226
MYSVC_PORT=tcp://10.98.157.226:80
MYSVC_SERVICE_PORT=80
MYSVC_PORT_80_TCP_ADDR=10.98.157.226
MYSVC_PORT_80_TCP_PORT=80
MYSVC_PORT_80_TCP_PROTO=tcp
DNS(推荐)
原理
在 kube-system 命名空间中,创建了coredns,可以自动发现所有命名空间中服务的 clusterIP
只要创建了一个服务,不管该服务在哪个命名空间中创建的,都回自动向 kube-system 命名空间下的 coredns 注册
因此,在同一个命名空间中,一个服务访问另一个服务的时候,可以直接通过服务名来访问
如果是不同命名空间,一个服务访问另一个服务的时候,可以通过 服务名.命名空间名 来访问
例如:
nginx 的 服务为:
[root@k8s-master svc]# kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
mysvc ClusterIP 10.98.157.226 <none> 80/TCP 52m app=nginx
[root@k8s-master svc]# kubectl run --image=busybox --rm -it -- bash
If you don't see a command prompt, try pressing enter.
/ # curl mysvc
sh: curl: not found
/ # wget mysvc
Connecting to mysvc (10.98.157.226:80)
saving to 'index.html'
index.html 100% |***************************************************************************************************| 5 0:00:00 ETA
'index.html' saved
/ # cat index.html
1111
服务名.命名空间名,来访问服务
[root@k8s-master svc]# kubectl run --image=busybox --rm -it -n default -- bash
/ # wget mysvc.gsh
Connecting to mysvc.gsh (10.98.157.226:80)
saving to 'index.html'
index.html 100% |***************************************************************************************************| 5 0:00:00 ETA
'index.html' saved
/ # cat index.html
2222
3. Service 服务发布
:对一些应用(如 Frontend)的某些部分,可能希望通过外部(Kubernetes 集群外部)IP 地址暴露 Service。
ServiceTypes 允许指定一个需要的类型的 Service,默认是 ClusterIP 类型。
ServiceTypes 服务发布的类型有:
ClusterIP :通过集群的内部 IP 暴露服务
选择该值,服务只能够在集群内部可以访问
ClusterIP 是默认的 ServiceType。
NodePort :通过每个 Node 上的 IP 和静态端口(NodePort)暴露服务。
NodePort 服务会路由到 ClusterIP 服务,这个 ClusterIP 服务会自动创建。
通过请求 <NodeIP>:<NodePort>,可以从集群的外部访问一个 NodePort 服务。
LoadBalancer :使用云提供商的负载均衡器,可以向外部暴露服务。
外部的负载均衡器可以路由到 NodePort 服务和 ClusterIP 服务。
ExternalName:通过返回 CNAME 和它的值,可以将服务映射到 externalName 字段的内容(例如, foo.bar.example.com)。
没有任何类型代理被创建,这只有 Kubernetes 1.7 或更高版本的 kube-dns 才支持。
svc 服务发布的另一种形式:Ingress
Ingress 不是服务类型,但它充当集群的入口点。
Ingress 可以将路由规则整合到一个资源中,因为它可以在同一IP地址下公开多个服务。
3.1
ClusterIP 类型 只能是在集群内部访问,多用于服务发现。
3.2 NodePort 类型
NodePort 类型,是将 容器 暴露出的端口 targetPort 映射到 node (worker)节点上,名为 nodePort,是的可以通过 nodeIP:NodePort 来访问 服务。
Kubernetes 控制平面将在 –service-node-port-range 标志指定的范围内分配端口(默认值:30000-32767)
apiVersion v1
kind Service
metadata
name my-service
spec
type NodePort
selector
app MyApp
ports
# 默认情况下,为了方便起见,`targetPort` 被设置为与 `port` 字段相同的值。
port80
targetPort80
# 可选字段
# 默认情况下,为了方便起见,Kubernetes 控制平面会从某个范围内分配一个端口号(默认:30000-32767)
nodePort30007
注意:
targetPort : 容器需要暴露出来的端口
port : 表示用于集群内部使用的 端口,一般与 targetPort 相同
nodePort : 表示 容器端口映射到 node 节点的 端口,范围:30000-32767
3.3
LoadBalancer 类型,需要从运行商获取到公网地址,也就是暴露在互联网上 ip 地址,这样才能够为外部访问,通过将 svc 绑定一个公网 ip,用户就可以通过这个公网 ip 来直接访问服务。
LoadBalancer 类型需要借助第三方工具来实现,可以通过 MetalLB 这个工具实现,官网地址为:https://metallb.universe.tf/
安装方法:
创建命名空间:
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.9.3/manifests/namespace.yaml
创建 secret
kubectl create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)"
创建 MetalLB 的相关 Pod
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.9.3/manifests/metallb.yaml
配置使用方法:
创建 地址池 的 yaml 文件:(简单示例,使用 Layer 2 Configuration)
apiVersion v1
kind ConfigMap
metadata
namespace metallb-system
name config
data
config
address-pools:
- name: default
protocol: layer2
addresses:
- 10.113.44.70-10.113.44.80
kubectl expose deployment web1 --name=mysvc --type=LoadBalancer --port=80
创建 loadBalancer 类型的 svc 后,可以看到 该 svc 服务与一个地址池中的公网 ip 绑定
[root@k8s-master svc]# kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
mysvc LoadBalancer 10.99.241.135 10.113.44.70 80:31003/TCP 2m16s app=nginx
[root@k8s-master svc]# curl 10.113.44.70
...
Welcome to nginx!
...
3.4
3.4.1
Ingress 公开了从集群外部到集群内服务的 HTTP 和 HTTPS 路由。 流量路由由 Ingress 资源上定义的规则控制。
Ingress 相当于一个 nginx 反向代理,通过不同的 path 指定到不同的 pod 上。
internet
|
[ Ingress ]
--|-----|--
[ Services ]
注意:
可以将 Ingress 配置为服务提供外部可访问的 URL、负载均衡流量、终止 SSL/TLS,以及提供基于名称的虚拟主机等能力。
Ingress 控制器 通常负责通过负载均衡器来实现 Ingress,尽管它也可以配置边缘路由器或其他前端来帮助处理流量。
Ingress 不会公开任意端口或协议。 将 HTTP 和 HTTPS 以外的服务公开到 Internet 时,通常使用 Service.Type=NodePort 或 Service.Type=LoadBalancer 类型的服务。
3.4.2 安装方法
Ingress 的安装方法:
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/mandatory.yaml -O ingress-nginx.yaml
kubectl apply -f ingress-nginx.yaml
在 ingress-nginx 命名空间中,创建 deployment 的服务 svc ,将 deployment 暴露出去,这样外部才可以通过这个代理访问服务
3.4.3
ingress 其实就是个路由器,通过不同的 网址站点以及 path 转发给不同的 service
apiVersion networking.k8s.io/v1
kind Ingress
metadata
name minimal-ingress
annotations
nginx.ingress.kubernetes.io/rewrite-target /
spec
rules
host"foo.bar.com"
http
paths
path /testpath
pathType Prefix
backend
service
name test
port
number80
说明:
host : 可选的,
如果未指定 host,表示通过指定 IP 地址的所有入站 HTTP 通信。 如果提供了 host,则 rules 适用于该 host。
paths : 路径列表
例如,/testpath, 每个路径都有一个由 serviceName 和 servicePort 定义的关联后端。
在负载均衡器将流量定向到引用的服务之前,主机和路径都必须匹配传入请求的内容。
backend : 后端
服务和端口名称的组合。 与规则的 host 和 path 匹配的对 Ingress 的 HTTP(和 HTTPS )请求将发送到列出的 backend。
backend 也就是对应的 service
pathType : 路径类型
ImplementationSpecific : 匹配方法取决于 IngressClass。 具体实现可以将其作为单独的 pathType 处理或者与 Prefix 或 Exact 类型作相同处理。
Exact : 精确匹配 URL 路径,且区分大小写。
Prefix : 基于以 / 分隔的 URL 路径前缀匹配。区分大小写,并且对路径中的元素逐个完成。
示例:
创建 nginx pod 和 服务svc:
[root@k8s-master svc]# kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
pod1 1/1 Running 0 11m test=aaa
pod2 1/1 Running 0 11m test=bbb
pod3 1/1 Running 0 11m test=ccc
[root@k8s-master svc]# kubectl expose pod pod1 --port=80 --name=svc1
service/svc1 exposed
[root@k8s-master svc]# kubectl expose pod pod2 --port=80 --name=svc2
service/svc2 exposed
[root@k8s-master svc]# kubectl expose pod pod3 --port=80 --name=svc3
service/svc3 exposed
[root@k8s-master svc]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
svc1 ClusterIP 10.102.121.210 <none> 80/TCP 2m9s
svc2 ClusterIP 10.98.163.119 <none> 80/TCP 2m4s
svc3 ClusterIP 10.98.137.91 <none> 80/TCP 2m
可以看到,通过不同的服务,可以访问不同的 内容
[root@k8s-master svc]# curl 10.106.21.33
11111
[root@k8s-master svc]# curl 10.110.145.160
22222
[root@k8s-master svc]# curl 10.111.168.199
33333
[root@k8s-master svc]# cat test-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: "www.aa.com"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: svc1
port:
number: 80
- host: "www.aa.com"
http:
paths:
- path: /app
pathType: Prefix
backend:
service:
name: svc3
port:
number: 80
- host: "www.bb.com"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: svc2
port:
number: 80
查看 ingress-nginx 创建的 svc 的 端口
在 /etc/hosts 中添加 dns 映射
[root@k8s-master svc]# kubectl apply -f test-ingress.yaml
ingress.networking.k8s.io/test-ingress created
// 创建 ingress
[root@k8s-master svc]# kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
test-ingress <none> www.aa.com,www.aa.com,www.bb.com 80 8s
// 查看 ingress-nginx 的 svc,暴露的 端口
[root@k8s-master svc]# kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress NodePort 10.101.220.216 <none> 80:31462/TCP 6d
// 在 /etc/hosts 中添加 域名的dns映射
[root@k8s-master svc]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
10.113.71.253 k8s-master
10.113.71.254 k8s-node-1
10.113.71.132 k8s-node-2
10.113.71.133 k8s-node-3
10.113.71.254 www.aa.com
10.113.71.254 www.bb.com
// 通过 不同的域名 访问不同的 svc
[root@k8s-master svc]# curl www.aa.com:31462
11111
[root@k8s-master svc]# curl www.bb.com:31462
22222
[root@k8s-master svc]# curl www.aa.com:31462/app
33333
评论