K8s的Service、Ingress
● 在kubernetes中,Pod是应用程序的载体,我们可以通过Pod的IP来访问应用程序,但是Pod的IP地址不是固定的,这就意味着不方便直接采用Pod的IP对服务进行访问。● 为了解决这个问题,kubernetes提供了Service资源,Service会对提供同一个服务的多个Pod进行聚合,并且,通过访问Service的入口地址就能访问到后面的Pod服务。Service在很多情况下只是一个
文章目录
Service介绍
概述
● 在kubernetes中,Pod是应用程序的载体,我们可以通过Pod的IP
来访问应用程序,但是Pod的IP地址
不是固定的,这就意味着不方便直接采用Pod的IP对服务进行访问。
● 为了解决这个问题,kubernetes提供了Service资源,Service会对提供同一个服务的多个Pod进行聚合
,并且提供一个统一的入口地址
,通过访问Service的入口地址就能访问到后面的Pod服务。
Service在很多情况下只是一个概念
,真正起作用的其实是kube-proxy服务进程
,每个Node节点上都运行了一个kube-proxy的服务
进程。当创建Service的时候会通过API Server
向etcd
写入创建的Service
的信息,而kube-proxy会基于监听的机制发现这种Service的变化,然后它会将最新的Service信息转换为对应的访问规则。
防止Pod失联【服务发现】
定义Pod访问策略【负载均衡】
页面
前端的Pod访问到后端的Pod
,中间会通过Service一层,而Service在这里还能做负载均衡
,负载均衡的策略有很多种实现策略,例如:
- 随机
- 轮询
- 响应比
Pod和Service的关系
这里Pod 和 Service 之间还是根据
label 和 selecto
r 建立关联的 【和Controller一样】
Service常用类型
- ClusterIp:集群内部访问
- NodePort:对外访问应用使用
- LoadBalancer:对外访问应用使用,公有云
Service类型
Service的资源清单:
apiVersion: v1 # 版本
kind: Service # 类型
metadata: # 元数据
name: # 资源名称
namespace: # 命名空间
spec:
selector: # 标签选择器,用于确定当前Service代理那些Pod
app: nginx
type: NodePort # Service的类型,指定Service的访问方式
clusterIP: # 虚拟服务的IP地址
sessionAffinity: # session亲和性,支持ClientIP、None两个选项,默认值为None
ports: # 端口信息
- port: 8080 # Service端口
protocol: TCP # 协议
targetPort : # Pod端口
nodePort: # 主机端口
spec.type的说明:
- ClusterIP:默认值,它是kubernetes系统
自动分配的虚拟IP
,只能在集群内部访问
。 - NodePort:将Service通过指定的Node上的端口暴露给外部,通过此方法,就可以在集群外部访问服务。
- LoadBalancer:使用外接负载均衡器完成到服务的负载分发,注意此模式需要外部云环境的支持。
- ExternalName:把集群外部的服务引入集群内部,直接使用。
Service使用
● 在使用Service之前,首先利用Deployment创建出3个Pod,注意
要为Pod设置app=nginx-pod
的标签。
● 创建deployment.yaml
文件,内容如下:
apiVersion: apps/v1
kind: Deployment
metadata:
name: pc-deployment
namespace: dev
spec:
replicas: 3
selector:
matchLabels:
app: nginx-pod
template:
metadata:
labels:
app: nginx-pod
spec:
containers:
- name: nginx
image: nginx:1.17.1
ports:
- containerPort: 80
创建Deployment:
kubectl apply -f deployment.yaml
查看Pod信息:
kubectl get pod -n dev -o wide --show-labels
为了方便后面的测试,修改三台Nginx的index.html
:
kubectl exec -it pc-deployment-7d7dd5499b-59qkm -c nginx -n dev /bin/sh
# 进入pod,选择nginx这个容器,在dev这个namespace下, /bin/bash 命令
echo "10.244.1.30" > /usr/share/nginx/html/index.html # > 重定向到index.html页面,覆盖其中内容
测试访问:
curl 10.244.0.31:80
curl 10.244.0.32:80
curl 10.244.0.33:80
ClusterIP类型的Service
创建Service
创建service-clusterip.yaml
文件,内容如下:
apiVersion: v1
kind: Service
metadata:
name: service-clusterip
namespace: dev
spec:
selector:
app: nginx-pod
clusterIP: 10.244.11.11 # service的IP地址,如果不写,默认会生成一个
type: ClusterIP
ports:
- port: 80 # Service的端口
targetPort: 80 # Pod的端口
创建Service:
kubectl apply -f service-clusterip.yaml
查看Service
kubectl get svc -n dev -o wide
查看Service的详细信息
kubectl describe svc service-clusterip -n dev
访问
默认的负载策略为rr(轮询),ClusterIP意思是给Service分配的是只有当前k8s集群内部才能访问的ip,外部无法访问
NodePort类型的Service
创建的Service的IP地址只能在集群内部
才可以访问,如果希望Service暴露给集群外部使用
,那么就需要使用到另外一种类型的Service,称为NodePort
类型的Service。NodePort的工作原理就是将Service的端口映射到Node的一个端口上,然后就可以通过NodeIP:NodePort
来访问Service了
创建Service
创建service-nodeport.yaml文件,内容如下:
apiVersion: v1
kind: Service
metadata:
name: service-nodeport
namespace: dev
spec:
selector:
app: nginx-pod
type: NodePort # Service类型为NodePort
ports:
- port: 80 # Service的端口
targetPort: 80 # Pod的端口
nodePort: 30002 # 指定绑定的node的端口(默认取值范围是30000~32767),如果不指定,会默认分配
创建Service:
kubectl apply -f service-nodeport.yaml
查看Service
kubectl get svc service-nodeport -n dev -o wide # -o wide 查看详细信息
访问
LoadBalancer类型的Service
LoadBalancer
和NodePort
很相似,目的都是向外部暴露一个端口
,区别在于LoadBalancer会在集群的外部再来做一个负载均衡设备,而这个设备需要外部环境的支持,外部服务发送到这个设备上的请求,会被设备负载之后转发到集群中。
Ingress
Ingress和Pod关系
pod 和 ingress 是通过service进行关联的,而ingress作为统一入口,由service关联一组pod中
Ingress工作流程
在实际的访问中,我们都是需要维护很多域名
, a.com 和 b.com
然后不同的域名对应的不同的Service
,然后service管理不同的pod
使用Ingress
配置ingress-controller
ingress-controller.yaml
apiVersion: v1
kind: Namespace
metadata:
name: ingress
labels:
app.kubernetes.io/name: ingress
app.kubernetes.io/part-of: ingress
---
kind: ConfigMap
apiVersion: v1
metadata:
name: nginx-configuration
namespace: ingress
labels:
app.kubernetes.io/name: ingress
app.kubernetes.io/part-of: ingress
---
kind: ConfigMap
apiVersion: v1
metadata:
name: tcp-services
namespace: ingress
labels:
app.kubernetes.io/name: ingress
app.kubernetes.io/part-of: ingress
---
kind: ConfigMap
apiVersion: v1
metadata:
name: udp-services
namespace: ingress
labels:
app.kubernetes.io/name: ingress
app.kubernetes.io/part-of: ingress
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: nginx-ingress-serviceaccount
namespace: ingress
labels:
app.kubernetes.io/name: ingress
app.kubernetes.io/part-of: ingress
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: nginx-ingress-clusterrole
labels:
app.kubernetes.io/name: ingress
app.kubernetes.io/part-of: ingress
rules:
- apiGroups:
- ""
resources:
- configmaps
- endpoints
- nodes
- pods
- secrets
verbs:
- list
- watch
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
- apiGroups:
- ""
resources:
- services
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
- apiGroups:
- "extensions"
- "networking.k8s.io"
resources:
- ingresses
verbs:
- get
- list
- watch
- apiGroups:
- "extensions"
- "networking.k8s.io"
resources:
- ingresses/status
verbs:
- update
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:
name: nginx-ingress-role
namespace: ingress
labels:
app.kubernetes.io/name: ingress
app.kubernetes.io/part-of: ingress
rules:
- apiGroups:
- ""
resources:
- configmaps
- pods
- secrets
- namespaces
verbs:
- get
- apiGroups:
- ""
resources:
- configmaps
resourceNames:
# Defaults to "<election-id>-<ingress-class>"
# Here: "<ingress-controller-leader>-<nginx>"
# This has to be adapted if you change either parameter
# when launching the nginx-ingress-controller.
- "ingress-controller-leader-nginx"
verbs:
- get
- update
- apiGroups:
- ""
resources:
- configmaps
verbs:
- create
- apiGroups:
- ""
resources:
- endpoints
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
name: nginx-ingress-role-nisa-binding
namespace: ingress
labels:
app.kubernetes.io/name: ingress
app.kubernetes.io/part-of: ingress
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: nginx-ingress-role
subjects:
- kind: ServiceAccount
name: nginx-ingress-serviceaccount
namespace: ingress
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: nginx-ingress-clusterrole-nisa-binding
labels:
app.kubernetes.io/name: ingress
app.kubernetes.io/part-of: ingress
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: nginx-ingress-clusterrole
subjects:
- kind: ServiceAccount
name: nginx-ingress-serviceaccount
namespace: ingress
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-ingress-controller
namespace: ingress
labels:
app.kubernetes.io/name: ingress
app.kubernetes.io/part-of: ingress
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: ingress
app.kubernetes.io/part-of: ingress
template:
metadata:
labels:
app.kubernetes.io/name: ingress
app.kubernetes.io/part-of: ingress
annotations:
prometheus.io/port: "10254"
prometheus.io/scrape: "true"
spec:
hostNetwork: true
# wait up to five minutes for the drain of connections
terminationGracePeriodSeconds: 300
serviceAccountName: nginx-ingress-serviceaccount
nodeSelector:
kubernetes.io/os: linux
containers:
- name: nginx-ingress-controller
image: lizhenliang/nginx-ingress-controller:0.30.0
args:
- /nginx-ingress-controller
- --configmap=$(POD_NAMESPACE)/nginx-configuration
- --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services
- --udp-services-configmap=$(POD_NAMESPACE)/udp-services
- --publish-service=$(POD_NAMESPACE)/ingress
- --annotations-prefix=nginx.ingress.kubernetes.io
securityContext:
allowPrivilegeEscalation: true
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
# www-data -> 101
runAsUser: 101
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
ports:
- name: http
containerPort: 80
protocol: TCP
- name: https
containerPort: 443
protocol: TCP
livenessProbe:
failureThreshold: 3
httpGet:
path: /healthz
port: 10254
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 10
readinessProbe:
failureThreshold: 3
httpGet:
path: /healthz
port: 10254
scheme: HTTP
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 10
lifecycle:
preStop:
exec:
command:
- /wait-shutdown
---
apiVersion: v1
kind: LimitRange
metadata:
name: ingress
namespace: ingress
labels:
app.kubernetes.io/name: ingress
app.kubernetes.io/part-of: ingress
spec:
limits:
- min:
memory: 90Mi
cpu: 100m
type: Container
创建
ingress-controller
# 需要执行两次 kubectl apply -f ingress-controller.yaml !
kubectl apply -f ingress-controller.yaml
kubectl apply -f ingress-controller.yaml
查看
ingress-controller
kubectl get pods -n ingress
创建tomcat和Nginx
创建
控制器
,tomcat-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: tomcat-deployment
spec: # 详细描述
replicas: 1
selector:
matchLabels:
app: tomcat-pod
template: # 模块 当副本数据不足的时候,会根据下面的模板创建Pod副本
metadata:
labels:
app: tomcat-pod
spec:
containers:
- name: tomcat
image: tomcat:8.0
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: tomcat
spec:
selector:
app: tomcat-pod
type: NodePort
ports:
- port: 8080
targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec: # 详细描述
replicas: 1
selector:
matchLabels:
app: nginx-pod
template: # 模块 当副本数据不足的时候,会根据下面的模板创建Pod副本
metadata:
labels:
app: nginx-pod
spec:
containers:
- name: nginx
image: nginx:1.18.0
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
selector:
app: nginx-pod
type: NodePort
ports:
- port: 80
targetPort: 80
运行命令,创建
deploy和svc
kubectl apply -f tomcat-nginx.yaml
查看pod,svc,deploy
kubectl get pod
kubectl get deploy
kubectl get svc
创建ingress规则文件
ingress-rule.yaml
---
# http
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: tomcat-nginx-ingress
spec:
rules:
- host: example.nginx.com
http:
paths:
- path: /
backend:
serviceName: nginx
servicePort: 80
- host: example.tomcat.com
http:
paths:
- path: /
backend:
serviceName: tomcat
servicePort: 8080
---
# https
# apiVersion: networking.k8s.io/v1beta1
# kind: Ingress
# metadata:
# name: tls-example-ingress
# spec:
# tls:
# - hosts:
# - sslexample.ctnrs.com
# secretName: secret-tls
# rules:
# - host: sslexample.ctnrs.com
# http:
# paths:
# - path: /
# backend:
# serviceName: web
# servicePort: 80
kubectl apply -f ingress-rule.yaml
kubectl get ingress
配置hosts文件
C:\Windows\System32\drivers\etc
加入以下
两个配置
192.168.111.101 example.nginx.com
192.168.111.101 example.tomcat.com
访问
流程据我理解是这样:
浏览器输入http://example.tomcat.com/,代理到
192.168.111.101
这个地址,然后ingress-rule规则
判断来源是example.tomcat.com
,然后把它转到service
名为tomcat
的服务,并且端口是8080,然后转到Pod
的8080端口,完成请求!
完成配置!
更多推荐
所有评论(0)