学习目标:掌握svc原理及其构建方式
一、service概念
A、kubernetes定义了这样一种抽象:一个pod的逻辑分组,一种可以访问他们的策略---通常称为微服务。这一组pod能够被service访问到,通常是通过Label Selector
B、service提供负载均衡的能力,但是使用上有以下限制:
1. 只提供4层负载均衡能力,而没有7层,但是有时我们需要更多的匹配规则来转发请求,这点上4层负载均衡是不支持的。
C、类型
1. ClusterIp:默认类型,自动分配一个仅Cluster内部可以访问的虚拟IP
2. NodePort:在ClusterIP基础上为Service在每台机器上绑定一个端口,这样可以通过 NodeIP:NodePort来访问该服务。
3. LoadBalancer: 在NodePort基础上,借助cloud provider创建一个外部负载均衡器,并将请求转发到NodeIp:NodePort
4. ExternalName: 把集群外部的服务引入到集群内部来,在集群内部直接使用。没有任何类型代理被创建,这只有kubernetes 1.7或更高版本才支持
D、架构图
二、VIP和Service代理
A、在Kubernetes集群中,每个Node运行一个kube-proxy进程。kube-proxy负责为service实现一种vip形式,而不是externalName的形式。在kubernetes v1.0版本中,代理完全在userspace。在kubernetes v1.1版本中,新增了iptables代理,但并不是默认的运行模式。从kubernetes v1.2版本起,默认就是iptables代理。在kubernetes v1.8.0-beta.0中,添加了ipvs代理。在kubernetes v1.14版本开始默认使用ipvs代理。在kubernetes v1.0版本,service是“4层”(TCP/UDP)概念。在kubernetes v1.1版本,新增了ingress API(beta版),用来表示“7层”(HTTP)服务。
三、ClusterIP
A、clusterIP主要在每个node节点使用iptables,将发向clusterIP对应端口的数据,转发到kube-proxy中。然后kube-proxy自己内部实现有负载均衡的方法,并且可以查询到这个service下对应pod的地址和端口,进而把数据转发给对应pod的地址和窗口
B、工作流程
1. apiserver:用户通过kubectl命令向apiserver发送创建service的命令,apiserver接收到请求后将数据存储在etcd中
2. kube-proxy:kubernetes的每个节点中都有一个叫做kube-proxy的进程,这个进程负责感知service和pod的变化,将变化的信息写入本地的iptables
3. iptables:使用NAT等技术将virtualIP的流量转至endpoint中
C、例子
1. 创建deployment
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: myapp-deploy
namespace: default
spec:
replicas: 3
selector:
matchLabels:
app: myapp
release: stable
template:
metadata:
labels:
app: myapp
release: stable
env: test
spec:
containers:
- name: myapp
image: hub.atguigu.com/library/myapp:v1
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
2. 创建service
apiVersion: v1
kind: Service
metadata:
name: myapp
namespace: default
spec:
type: ClusterIP
selector:
app: myapp
release: stable
ports:
- name: http
port: 80
targetPort: 80
四、Headless Server
A、有时不需要或者不想要负载均衡,以及单独的service IP。遇到这种情况,可以通过指定Cluster IP(spec.clusterIP)的值为“None”来创建Headless Service。这类service并不会分配cluster IP,kube-proxy不会处理它们,而且平台也不会为它们进行负载均衡和路由。
B、例子
apiVersion: v1
kind: Service
metadata:
name: myapp-headless
namespace: default
spec:
selector:
app: myapp
clusterIP: "None"
ports:
- port: 80
targetPort: 80
五、NodePort
A、NodePort的原理在于在node上开了一个端口,将向该端口的流量导入到kube-proxy,然后由kube-proxy进一步给到对应的pod
B、 例子
apiVersion: v1
kind: Service
metadata:
name: myapp
namespace: default
spec:
type: NodePort
selector:
app: myapp
release: stable
ports:
- name: http
port: 80
targetPort: 80
六、LoadBalancer
A、LoadBalancer和nodePort其实是同一种方式,区别在于loadBalancer比nodePort多了一步,就是可以调用cloud provider去创建LB来向节点导流
七、ExternalName
A、这种类型的Service通过返回CANME和它的值,可以将服务映射到externalName字段的内容。ExternalName Service是service的特例,它没有selector,也没有任何的端口和Endpoin。相反的,对于运行在集群外部的服务,它通过返回该外部服务的别名这种方式来提供服务。
B、例子
apiVersion: v1
kind: Service
metadata:
name: my-service-1
namespace: default
spec:
type: ExternalName
externalName: hub.atguigu.com
八、Ingress实现七层代理
A、
B、例子
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx-dm
spec:
replicas: 2
template:
metadata:
labels:
name: nginx
spec:
containers:
- name: nginx
image: hub.atguigu.com/library/myapp:v1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
selector:
name: nginx
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx-test
spec:
rules:
- host: www1.atguigu.com
http:
paths:
- path: /
backend:
serviceName: nginx-svc
servicePort: 80
C、Ingress HTTPS代理访问
1. 创建证书,以及cert存储方式
a. openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginxsvc/O=nginxsvc"
b. kubectl create secret tls tls-secret --key tls.key --cert tls.crt
2. 例子
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: deployment3
spec:
replicas: 2
template:
metadata:
labels:
name: nginx3
spec:
containers:
- name: nginx3
image: wangyanglinux/myapp:v3
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: svc3
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
selector:
name: nginx3
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: https-ingress
spec:
tls:
- hosts:
- www3.atguigu.com
secretName: tls-secret
rules:
- host: www3.atguigu.com
http:
paths:
- path: /
backend:
serviceName: svc3
servicePort: 80
D、nginx 进行BasicAuth
1. yum -y install httpd
2. htpasswd -c auth foo
3. kubectl create secret generic basic-auth --from-file=auth
4.
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.atguigu.com
http:
paths:
- path: /
backend:
serviceName: svc1
servicePort: 80
E、Nginx进行重写
1. 一些annotations
a. nginx.ingress.kubernetes.io/rewrite-target(必须重定向流量的目标)
b. nginx.ingress.kubernetes.io/ssl-redirect(指示位置部分是否仅可访问SSL(当Ingress包含证书时默认为true))
c. nginx.ingress.kubernetes.io/force-ssl-redirect(及时ingress未启用TLS,也强制重定向到HTTPS)
d. nignx.ingress.kubernetes.io/app-root(定义controller必须重定的应用程序根,如果它在'/'上下文中)
e. nginx.ingress.kubernetes.io/use-regex(指示ingress上定义的路径是否使用正则表达式)
2. 例子
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx-test
annotations:
nginx.ingress.kubernetes.io/rewrite-target: https://www3.atguigu.com:32333
spec:
rules:
- host: re.atguigu.com
http:
paths:
- path: /
backend:
serviceName: svc1
servicePort: 80