tags:
categories:
Kubernetes Service定义了这样一种抽象: 一个Pod 的逻辑分组,一种可以访问它们的策略. 它通常称为微服务。通常是通过Label Selector标签选的的方式,匹配一组Pod然后对外访问服务的机制。
Service能够提供负载均衡的能力,但是在使用上有以下限制:
Service在K8s中有以下四种类型
在Kubernetes集群中,每个Node运行一个kube-proxy进程。kube- proxy负责为Service 实现了一种VIP (虚拟IP)的形式,而不是ExternalName的形式。在Kubernetes v1.0版本,代理完全在userspace。
在Kubernetes v1.1版本,新增了iptables代理,但并不是默认的运行模式。从Kubernetes v1.2起,默认就是iptables代理。在Kubernetes v1.8.0-beta.0中,添加了ipvs代理。在Kubernetes 1.14版本开始默认使用ipvs代理
在Kubernetes v1.0版本,Service 是“4层”(TCP/UDP overIP)概念。在Kubernetes v1.1版本,新增了Ingress API (beta 版),用来表示“7层”(HTTP) 服务
为何不使用round-robin DNS? DNS会在系统中进行缓存。。。就起不到负载均衡的效果。。。
userspace代理模式:每次访问都需要kube-proxy进行代理,而且kube-apiserver也监控kube-proxy进行服务更新和端点维护,所以kube-proxy的压力就会很大。
iptables代理模式:访问直接由防火墙iptables调度完成,不需要经过kube-proxy调度。大大提升速度,提到kube-proxy的稳定性。
ipvs代理模式(现在的标准):kube-proxy 会监视Kubernetes Service 对象和Endpoints,调用netlink 接口以相应地创建ipvs规则并定期与Kubernetes Service对象和Endpoints 对象同步ipvs规则,以确保ipvs状态与期望一致。访问服务时,流量将被重定向到其中一个后端Pod
clusterIP主要在每个node节点使用iptables,将发向clusterIP对应端口的数据,转发到kube-proxy中。然后kube-proxy自己内部实现负载均衡的方法,可以查询到这个service下对应pod的地址和端口,进而把数据转发给对应的pod的地址和端口。
为了实现图上的功能,主要需要以下几个组件的协同工作:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deploy
namespace: default
spec:
replicas: 3
selector:
matchLabels:
app: myapp
release: stabel
template:
metadata:
labels:
app: myapp
release: stabel
env: test
spec:
containers:
- name: myapp
image: hub.qnhyn.com/library/myapp
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
apiVersion: v1
kind: Service
metadata:
name: myapp
namespace: default
spec:
type: ClusterIP
selector:
app: myapp
release: stabel
ports:
- name: http
port: 80
targetPort: 80
# 部署Deployment
kubectl create -f svc-deployment.yaml
# 直接访问deployment中的某个pod
kubectl get pod -o wide
curl 10.244.1.40
# 部署svc 服务可靠维稳访问
kubectl create -f svc.yaml
kubectl get svc
curl 10.110.67.225
ipvsadm -Ln
apiVersion: v1
kind: Service
metadata:
name: myapp-headless
namespace: default
spec:
selector:
app: myapp
clusterIP: "None"
ports:
- port: 80
targetPort: 80
kubectl create -f svc-none.yaml
# 查看发现Cluster Ip为空
kubectl get svc
# 安装包 使用dig命令
yum -y install bind-utils
# 查看coredns的ip
kubectl get pod -n kube-system -o wide
# 对于 Service 一旦创建成功会写入到 CoreDNS 中去 通过命令查看
# 意味着在无头服务中,虽然它没有ip了,但可以通过访问域名的方案依然可以访问服务下的pod
dig -t A myapp-headless.default.svc.cluster.local. @10.244.2.40
apiVersion: v1
kind: Service
metadata:
name: myapp
namespace: default
spec:
type: NodePort
selector:
app: myapp
release: stabel
ports:
- name: http
port: 80
targetPort: 80
kubectl create -f myapp-service.yaml
# 查看svc
kubectl get svc
# 查看各个Node上端口有没有开启成功
netstat -anpt | grep 31217
# iptables查询流程 iptables -t nat -nvL KUBE-NODEPORTS
# 我们实验中使用的是ipvs负载均衡
ipvsadm -Ln
apiVersion: v1
kind: Service
metadata:
name: my-service
namespace: default
spec:
type: ExternalName
externalName: hub.qnhyn.com
kubectl apply -f externalname.yaml
kubectl get pod -n kube-system -o wide
kubectl get svc
# 解析这个服务
dig -t A my-service-1.default.svc.cluster.local. @10.244.1.39
对于k8s传统的svc来说 它仅支持4层代理,如果遇到7层代理的话,是没有办法去实现的
k8s官方在1.11中推出了ingress api接口,通过ingress达到7层代理的效果。
对于ingress来说,必须要绑定一个域名,因为它是基于7层代理的
Ingress现在已经非常成熟啦
暴露方案执行【此处选择裸机暴露方案,就是以svc暴露】(不用这种方式安装,用下面helm管理安装)
Helm管理安装
验证是否完成(由于版本问题和视频中安装不一样)
如果安装错删除之前安装:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-dm
spec:
selector:
matchLabels:
app: nginx-dm
replicas: 2
template:
metadata:
labels:
app: nginx-dm
spec:
containers:
- name: nginx-dm
image: hub.qnhyn.com/library/myapp
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
type: ClusterIP
selector:
app: nginx-dm
ports:
- port: 80
targetPort: 80
protocol: TCP
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx-test
spec:
rules:
- host:www.qnhyn1.com
http:
paths:
- path: /
backend:
serviceName: nginx-svc
servicePort: 80
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-dm3
spec:
selector:
matchLabels:
app: nginx-dm3
replicas: 2
template:
metadata:
labels:
app: nginx-dm3
spec:
containers:
- name: nginx-dm3
image: hub.qnhyn.com/library/myapp
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-svc3
spec:
type: ClusterIP
selector:
app: nginx-dm3
ports:
- port: 80
targetPort: 80
protocol: TCP
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx-https
spec:
tls:
- hosts:
- www.qnhyn3.com
secretName: tls-secret
rules:
- host: www.qnhyn3.com
http:
paths:
- path: /
backend:
serviceName: nginx-svc3
servicePort: 80
yum -y install httpd
htpasswd -c auth foo # 设置用户名foo的密码
kubectl create secret generic basic-auth --from-file=auth
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-with-auth
annotations:
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/auth-secret: basic-auth
nginx.ingress.kubernetes.io/auth-realm: "Authentication Required - foo"
spec:
rules:
- host: auth.qnhyn.com
http:
paths:
- path: /
backend:
serviceName: svc-1
servicePort: 80
名称 | 描述 | 值 |
---|---|---|
nginx.ingress.kubernetes.io/rewrite-target | 必须重定向流量的目标URI | 串 |
nginx.ingress.kubernetes.io/ssl-redirect | 指示位置部分是否仅可访问SSL (当Ingress包含证书时默认为True) | 布尔 |
nginx.ingress.kubernetes.io/force-ssl-redirect | 即使Ingress末启用TLS,也强制重定向到HTTPS | 布尔 |
nginx.ingress.kubernetes.io/app-root | 定义Controller必须重定向的应用程序根,如果它在/上下文中 | 串 |
nginx.ingress.kubernetes.io/use-regex | 指示Ingress上定义的路径是否使用正则表达式 | 布尔 |
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx-redirect
namespace: default
annotations:
nginx.ingress.kubernetes.io/rewrite-target: https://www.qnhyn3.com:31802
spec:
rules:
- host: re.qnhyn3.com
http:
paths:
- path: /
backend:
serviceName: svc-3
servicePort: 80