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