k8s04- Label 和Selector-Service-ingress

  • Label 和Selector
  • Service
  • ingress

1.Label 和Selector

1定义label

应用案例

公司与xx银行有一条专属的高速光纤通道,此通道只能与192.168.7.0网段进行通信,因此只能将与xx银行通信的应用部署到192.168.7.0网段所在的节点上,此时可以对节点添加Label

#kubectl label node k8s-node02 region=subnet7
node/k8s-node02 labeled

然后可以通过Selector 对其筛选

# kubectl get no -l region=subnet7
NAME STATUS ROLES AGE VERSION
k8s-node02 Ready <none> 3d17h v1.12.3

最后在Deployment或其它控制器中指定将Pod部署到该节点

containers:
 ......
dnsPolicy: ClusterFirst
nodeSelector:
 region: subnet7
restartPolicy: Always
......

也可以用同样的方式对Service添加label

# kubectl label svc canary-v1 -n canary-production env=canary version=v1
service/canary-v1 labeled

查看该Service的标签

# kubectl get svc -n canary-production --show-labels
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE LABELS
canary-v1 ClusterIP 10.110.253.62 <none> 8080/TCP 24h
env=canary,version=v1

上述演示了对节点,Service添加了自定义标签,对于其它资源的Label方式相同

1.2 Selector选择器

​ 首先使用--show-labels 查看指定资源目前已有的Label

# kubectl get service --show-labels
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
LABELS
details ClusterIP 10.99.9.178 <none> 9080/TCP 45h
app=details
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3d19h
component=apiserver,provider=kubernetes
nginx ClusterIP 10.106.194.137 <none> 80/TCP 2d21h
app=productpage,version=v1
nginx-v2 ClusterIP 10.108.176.132 <none> 80/TCP 2d20h
<none>
productpage ClusterIP 10.105.229.52 <none> 9080/TCP 45h
app=productpage,tier=frontend
ratings ClusterIP 10.96.104.95 <none> 9080/TCP 45h
app=ratings
reviews ClusterIP 10.102.188.143 <none> 9080/TCP 45h
app=reviews

选择匹配app为details 或者 productpage的service

# kubectl get svc -l 'app in (details, productpage)' --show-labels
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
LABELS
details ClusterIP 10.99.9.178 <none> 9080/TCP 45h
app=details
nginx ClusterIP 10.106.194.137 <none> 80/TCP 2d21h
app=productpage,version=v1
productpage ClusterIP 10.105.229.52 <none> 9080/TCP 45h
app=productpage,tier=frontend

选择app为productpage或reviews 但不包括version=v1 的svc

# kubectl get svc -l version!=v1,'app in (details, productpage)' --showlabels
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
LABELS
details ClusterIP 10.99.9.178 <none> 9080/TCP 45h
app=details
productpage ClusterIP 10.105.229.52 <none> 9080/TCP 45h
app=productpage,tier=frontend

选择label的key名为app的svc

# kubectl get svc -l app --show-labels
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
LABELS
details ClusterIP 10.99.9.178 <none> 9080/TCP 45h
app=details
nginx ClusterIP 10.106.194.137 <none> 80/TCP 2d21h
app=productpage,version=v1
productpage ClusterIP 10.105.229.52 <none> 9080/TCP 45h
app=productpage,tier=frontend
ratings ClusterIP 10.96.104.95 <none> 9080/TCP 45h
app=ratings
reviews ClusterIP 10.102.188.143 <none> 9080/TCP 45h
app=reviews

1.3修改标签(label)

比如将version=v1 改为version=v2

# kubectl get svc -n canary-production --show-labels
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE LABELS
canary-v1 ClusterIP 10.110.253.62 <none> 8080/TCP 26h
env=canary,version=v1
# kubectl label svc canary-v1 -n canary-production version=v2 --
overwrite
service/canary-v1 labeled
# kubectl get svc -n canary-production --show-labels
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE LABELS
canary-v1 ClusterIP 10.110.253.62 <none> 8080/TCP 26h
env=canary,version=v2

1.4 删除标签(Label)

​ 删除key名为version的标签

# kubectl label svc canary-v1 -n canary-production versionservice/canary-v1 labeled
# kubectl get svc -n canary-production --show-labels
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE LABELS
canary-v1 ClusterIP 10.110.253.62 <none> 8080/TCP 26h
env=canary

2 Service

2.1 定义service

定义Service的yaml文件如下

kind: Service
apiVersion: v1
metadata:
  name: my-service
spec:
   selector:
     app: nginx
   ports:
     - protocol: TCP
       port: 80
       targetPort: 80

创建服务

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.15.12
        ports:
        - containerPort: 80

该示例为my-service:80 即可访问到具有app=myapp 标签的Pod的80端口上

需要注意的是,Service能够将一个接收端映射到任意的targetPort,如果targetPort为空,

targetPort将被设置为与Port字段相同的值,targetPort可以设置为一个字符串,引用backend Pod 的一个端口的名称,这样的话即使更改了 Pod 的端口,也不会对 Service 的访问造成影响。
Kubernetes Service 能够支持 TCP、UDP、SCTP 等协议,默认为 TCP 协议。

2.2 Service类型

Kubernetes Service Type(服务类型)主要包括以下几种:
➢ ClusterIP:在集群内部使用,默认值,只能从集群中访问。
➢ NodePort:在所有安装了 Kube-Proxy 的节点上打开一个端口,此端口可以代理至后端
Pod,可以通过 NodePort 从集群外部访问集群内的服务,格式为 NodeIP:NodePort。
➢ LoadBalancer:使用云提供商的负载均衡器公开服务,成本较高。
➢ ExternalName:通过返回定义的 CNAME 别名,没有设置任何类型的代理,需要 1.7 或
更高版本 kube-dns 支持。

2.3 NodePort 类型

​ 如果将Service的type字段设置为NodePort,则Kubenetes将从--service-node-port-range 参数指定的范围

(默认为30000-32767)中自动分配端口,也可以手动指定NodePort,创建该Service后,集群每个节点都将暴露一个端口,通过某个宿主机的IP+端口即可访问到后端的应用

定义一个NodePort类型的Service格式如下

kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kube-system
spec:
  type: NodePort
  ports:
    - port: 443
      targetPort: 8443
      nodePort: 30000
  selector:
    k8s-app: kubernetes-dashboard

2.4 使用Service代理K8s外部服务

使用场景

​➢ 希望在生产环境中使用某个固定的名称而非 IP 地址访问外部的中间件服务;
➢ 希望 Service 指向另一个 Namespace 中或其他集群中的服务;
➢ 正在将工作负载转移到 Kubernetes 集群,但是一部分服务仍运行在 Kubernetes 集群
之外的 backend。

# cat nginx-svc-external.yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx-svc-external
  name: nginx-svc-external
spec:
  ports:
  - name: http
    port: 80
 	protocol: TCP
 	targetPort: 80
  sessionAffinity: None
  type: ClusterIP
# cat nginx-ep-external.yaml
apiVersion: v1
kind: Endpoints
metadata:
 labels:
 app: nginx-svc-external
 name: nginx-svc-external
subsets:
- addresses:
 - ip: 140.205.94.189
 ports:
 - name: http
 port: 80
 protocol: TCP

​ Endpoint IP 地址不能是 loopback(127.0.0.0/8)、link-local(169.254.0.0/16)或者 linklocal 多播地址(224.0.0.0/24)。

访问没有 Selector 的 Service 与有 Selector 的 Service 的原理相同,通过 Service 名称即可访
问,请求将被路由到用户定义的 Endpoint。

2.5 ExternalName Service

​ ExternalName Service 是 Service 的特例,它没有 Selector,也没有定义任何端口和 Endpoint,
它通过返回该外部服务的别名来提供服务。
​ 比如可以定义一个 Service,后端设置为一个外部域名,这样通过 Service 的名称即可访问到
该域名。使用 nslookup 解析以下文件定义的 Service,集群的 DNS 服务将返回一个值为
my.database.example.com 的 CNAME 记录:

kind: Service
apiVersion: v1
metadata:
  name: my-service
  namespace: prod
spec:
  type: ExternalName
  externalName: my.database.example.com

2.6 多端口 Service

例如将 Service 的 80 端口代理到后端的 9376,443 端口代理到后端的 9377:

kind: Service
apiVersion: v1
metadata:
  name: my-service
spec:
  selector:
    app: myapp
  ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: 9376
  - name: https
    protocol: TCP
    port: 443
    targetPort: 9377

3 ingress

3.1 ingress 安装

官方安装文档:https://kubernetes.github.io/ingress-nginx/deploy/#bare-metal-clusters

# kubectl create -f deploy-ingress.yaml
namespace/ingress-nginx created
serviceaccount/ingress-nginx created
serviceaccount/ingress-nginx-admission created
role.rbac.authorization.k8s.io/ingress-nginx created
role.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrole.rbac.authorization.k8s.io/ingress-nginx created
clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created
rolebinding.rbac.authorization.k8s.io/ingress-nginx created
rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission
created
configmap/ingress-nginx-controller created
service/ingress-nginx-controller created
service/ingress-nginx-controller-admission created
deployment.apps/ingress-nginx-controller created
job.batch/ingress-nginx-admission-create create
job.batch/ingress-nginx-admission-patch created
ingressclass.networking.k8s.io/nginx created
validatingwebhookconfiguration.admissionregistration.k8s.io/ingressnginx-admission created

3.2 使用域名发布K8S的服务

创建一个web服务

kubectl create deploy nginx --image=registry.cnbeijing.aliyuncs.com/dotbalo/nginx:1.15.12

暴露服务

kubectl expose deploy nginx --port 80

创建ingress

vim web-ingress.yaml
apiVersion: networking.k8s.io/v1 # k8s >= 1.22 必须 v1
kind: Ingress
metadata:
  name: nginx-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: nginx.test.com
    http:
      paths:
      - backend:
        service:
 		  name: nginx
 		  port:
 			number: 80
 		path: /
	    pathType: ImplementationSpecific

pathType:路径的匹配方式,目前有 ImplementationSpecific、Exact 和 Prefix 方式
◆ Exact:精确匹配,比如配置的 path 为/bar,那么/bar/将不能被路由;
◆ Prefix:前缀匹配,基于以 / 分隔的 URL 路径。比如 path 为/abc,可以匹配
到/abc/bbb 等,比较常用的配置;
◆ ImplementationSpecific:这种类型的路由匹配根据 Ingress Controller 来实现,

可以当做一个单独的类型,也可以当做 Prefix 和 Exact。ImplementationSpecific
是 1.18 版本引入 Prefix 和 Exact 的默认配置;

3.3ingress 特例 不配置域名发布服务

# vim ingress-no-host.yaml
apiVersion: networking.k8s.io/v1 # k8s >= 1.22 必须 v1
kind: Ingress
metadata:
  name: nginx-ingress-no-host
spec:
  ingressClassName: nginx
  rules:
  - http:
    paths:
    - backend:
      service:
 		name: nginx
		port:
 		  number: 80
 	path: /no-host
 	pathType: ImplementationSpecific

3.4ingress 接口变化解析

1.19 之前的 v1beta1:

apiVersion: networking.k8s.io/v1beta1 # 1.22 之前可以使用 v1beta1
kind: Ingress
metadata:
  name: simple-fanout-example
  annotations:
 	kubernetes.io/ingress.class: "nginx" # 不同的 controller,ingress.class
可能不一致
spec:
  rules:
  - host: foo.bar.com
 	http:
 	  paths:
 	  - path: /foo
 		pathType: Prefix
 		backend:
	 	  serviceName: service1
 		  servicePort: 4200
	  - path: /bar
 		pathType: ImplementationSpecific
 		backend:
 		  serviceName: service2
 		  servicePort: 8080
posted @ 2022-11-11 00:40  名字长的像一只老山羊  阅读(116)  评论(0编辑  收藏  举报