kubernetes部署Ingress访问代理与负载均衡器

  • 来源:新网
  • 更新日期:2018-03-20

摘要:kubernetes部署Ingress访问代理与负载均衡器 ============================================================================== Kubernetes中的pod都有独立的内部IP(外部不可访问),通过Service可以对多个pod进行负载均衡和故障转移,Service可以具有ClusterIP、NodeIP

kubernetes部署Ingress访问代理与负载均衡器
 
Kubernetes中的pod都有独立的内部IP(外部不可访问),通过Service可以对多个pod进行负载均衡和故障转移,Service可以具有ClusterIP、NodeIP或LoadBanlancer模式。目前,ClusterIP只能内部访问,需通过kubectl proxy代理出来,NodeIP是跟Node绑定的、迁移性差,LoadBanlancer的每个服务都有独立的IP地址,管理、使用不便。有没有一个固定的独立IP、自动节点漂移的解决方案呢?以前这样的功能基本上都用Nginx来实现,现在Kubernetes有一个做好了的服务,也是基于Nginx的,就是Ingress。
 
如何访问K8S中的服务:
 
t01c52e4334685a7dbc.jpg
 
1、Ingress介绍
 
Kubernetes 暴露服务的方式目前只有三种:LoadBlancer Service、NodePort Service、Ingress;前两种估计都应该很熟悉,下面详细的了解下这个 Ingress
 
Ingress由两部分组成:Ingress Controller 和 Ingress 服务。
 
Ingress Contronler 通过与 Kubernetes API 交互,动态的去感知集群中 Ingress 规则变化,然后读取它,按照自定义的规则,规则就是写明了哪个域名对应哪个service,生成一段 Nginx 配置,再写到 Nginx-ingress-control的 Pod 里,这个Ingress Contronler 的pod里面运行着一个nginx服务,控制器会把生成的nginx配置写入/etc/nginx.conf文件中,然后 reload 一下使用配置生效。以此来达到域名分配置及动态更新的问题。
 
看个简单的图方便理解:
 
image.png
 
ingress控制器有两种:nginx和haproxy 这里是以nginx为讲解。
 
2、部署一个Nginx Ingress
 
ingress的部署文件在github Ingress 仓库找到. 针对官方配置我们单独添加了 nodeselector 指定,绑定LB地址 以方便DNS 做解析。
 
$ls
 
default-backend.yamljenkins-ingress.ymlnginx-ingress-controller-rbac.ymlnginx-ingress-controller.yaml
 
---
 
default-backend.yaml:这是官方要求必须要给的默认后端,提供404页面的。它还提供了一个http检测功能,检测nginx-ingress-controll健康状态的,通过每隔一定时间访问nginx-ingress-controll的/healthz页面,如是没有响应就
 
返回404之类的错误码。
 
nginx-ingress-controller-rbac.yml:这ingress的RBAC授权文件
 
nginx-ingress-controller.yaml:这是控制器的部署文件。
 
jenkins-ingress.yml:这是Ingress服务文件,这个可以是任意web程序,里面配置域名与service的对应关系,Ingress称之为规则。
 
catnginx-ingress-controller-rbac.yml
 
#apiVersion:v1
 
#kind:Namespace
 
#metadata:#这里是创建一个namespace,因为此namespace早有了就不用再创建了
 
#name:kube-system
 
---
 
apiVersion:v1
 
kind:ServiceAccount
 
metadata:
 
name:nginx-ingress-serviceaccount#创建一个serveerAcount
 
namespace:kube-system
 
---
 
apiVersion:rbac.authorization.k8s.io/v1beta1
 
kind:ClusterRole
 
metadata:
 
name:nginx-ingress-clusterrole#这个ServiceAcount所绑定的集群角色
 
rules:
 
-apiGroups:
 
-""
 
resources:#此集群角色的权限,它能操作的API资源
 
-configmaps
 
-endpoints
 
-nodes
 
-pods
 
-secrets
 
verbs:
 
-list
 
-watch
 
-apiGroups:
 
-""
 
resources:
 
-nodes
 
verbs:
 
-get
 
-apiGroups:
 
-""
 
resources:
 
-services
 
verbs:
 
-get
 
-list
 
-watch
 
-apiGroups:
 
-"extensions"
 
resources:
 
-ingresses
 
verbs:
 
-get
 
-list
 
-watch
 
-apiGroups:
 
-""
 
resources:
 
-events
 
verbs:
 
-create
 
-patch
 
-apiGroups:
 
-"extensions"
 
resources:
 
-ingresses/status
 
verbs:
 
-update
 
---
 
apiVersion:rbac.authorization.k8s.io/v1beta1
 
kind:Role
 
metadata:
 
name:nginx-ingress-role#这是一个角色,而非集群角色
 
namespace:kube-system
 
rules:#角色的权限
 
-apiGroups:
 
-""
 
resources:
 
-configmaps
 
-pods
 
-secrets
 
-namespaces
 
verbs:
 
-get
 
-apiGroups:
 
-""
 
resources:
 
-configmaps
 
resourceNames:
 
#Defaultsto"-"
 
#Here:"-"
 
#Thishastobeadaptedifyouchangeeitherparameter
 
#whenlaunchingthenginx-ingress-controller.
 
-"ingress-controller-leader-nginx"
 
verbs:
 
-get
 
-update
 
-apiGroups:
 
-""
 
resources:
 
-configmaps
 
verbs:
 
-create
 
-apiGroups:
 
-""
 
resources:
 
-endpoints
 
verbs:
 
-get
 
-create
 
-update
 
---
 
apiVersion:rbac.authorization.k8s.io/v1beta1
 
kind:RoleBinding#角色绑定
 
metadata:
 
name:nginx-ingress-role-nisa-binding
 
namespace:kube-system
 
roleRef:
 
apiGroup:rbac.authorization.k8s.io
 
kind:Role
 
name:nginx-ingress-role
 
subjects:
 
-kind:ServiceAccount
 
name:nginx-ingress-serviceaccount#绑定在这个用户
 
namespace:kube-system
 
---
 
apiVersion:rbac.authorization.k8s.io/v1beta1
 
kind:ClusterRoleBinding#集群绑定
 
metadata:
 
name:nginx-ingress-clusterrole-nisa-binding
 
roleRef:
 
apiGroup:rbac.authorization.k8s.io
 
kind:ClusterRole
 
name:nginx-ingress-clusterrole
 
subjects:
 
-kind:ServiceAccount
 
name:nginx-ingress-serviceaccount#集群绑定到这个serviceacount
 
namespace:kube-system#集群角色是可以跨namespace,但是这里只指明给这个namespce来使用
 
$kubectlcreate-fnginx-ingress-controller-rbac.yml
 
serviceaccount"nginx-ingress-serviceaccount"created
 
clusterrole"nginx-ingress-clusterrole"created
 
role"nginx-ingress-role"created
 
rolebinding"nginx-ingress-role-nisa-binding"created
 
clusterrolebinding"nginx-ingress-clusterrole-nisa-binding"created
 
RBAC创建完后,就创建default backend服务:
 
$catdefault-backend.yaml
 
apiVersion:extensions/v1beta1
 
kind:Deployment
 
metadata:
 
name:default-http-backend
 
labels:
 
k8s-app:default-http-backend
 
namespace:kube-system
 
spec:
 
replicas:1
 
template:
 
metadata:
 
labels:
 
k8s-app:default-http-backend
 
spec:
 
terminationGracePeriodSeconds:60
 
containers:
 
-name:default-http-backend
 
#Anyimageispermissableaslongas:
 
#1.Itservesa404pageat/
 
#2.Itserves200ona/healthzendpoint
 
image:gcr.io/google_containers/defaultbackend:1.0
 
livenessProbe:
 
httpGet:
 
path:/healthz#这个URI是nginx-ingress-controller中nginx里配置好的localtion
 
port:8080
 
scheme:HTTP
 
initialDelaySeconds:30#30s检测一次/healthz
 
timeoutSeconds:5
 
ports:
 
-containerPort:8080
 
resources:
 
limits:
 
cpu:10m
 
memory:20Mi
 
requests:
 
cpu:10m
 
memory:20Mi
 
nodeSelector:#指定调度到些Node,以便后面DNS解析
 
kubernetes.io/hostname:10.3.1.17
 
---
 
apiVersion:v1
 
kind:Service#为defaultbackend创建一个service
 
metadata:
 
name:default-http-backend
 
namespace:kube-system
 
labels:
 
k8s-app:default-http-backend
 
spec:
 
ports:
 
-port:80
 
targetPort:8080
 
selector:
 
k8s-app:default-http-backend
 
创建:
 
1
 
2
 
3
 
$kubectlcreate-fdefault-backend.yaml
 
deployment"default-http-backend"created
 
service"default-http-backend"created
 
root@ubuntu15:/data/ingress#kubectlgetrs,pod,svc-nkube-system
 
NAMEDESIREDCURRENTREADYAGE
 
rs/default-http-backend-857b544d941111m
 
NAMEREADYSTATUSRESTARTSAGE
 
po/default-http-backend-857b544d94-bwgjd1/1Running01m
 
NAMETYPECLUSTER-IPEXTERNAL-IPPORT(S)AGE
 
svc/default-http-backendClusterIP10.254.208.14480/TCP1m
 
创建好default backend后就要创建nginx-ingress-controller了:
 
$catnginx-ingress-controller.yaml apiVersion:extensions/v1beta1 kind:Deployment metadata: name:nginx-ingress-controller labels: k8s-app:nginx-ingress-controller namespace:kube-system spec: replicas:1 template: metadata: labels: k8s-app:nginx-ingress-controller spec: #hostNetworkmakesitpossibletouseipv6andtopreservethesourceIPcorrectlyregardlessofdockerconfiguration #however,itisnotaharddependencyofthenginx-ingress-controlleritselfanditmaycauseissuesifport10254alreadyistakenonthehost #thatsaid,sincehostPortisbrokenonCNI(https://github.com/kubernetes/kubernetes/issues/31307)wehavetousehostNetworkwhereCNIisused #likewithkubeadm #hostNetwork:true#注释表示不使用宿主机的80口, terminationGracePeriodSeconds:60 hostNetwork:true#表示容器使用和宿主机一样的网络 serviceAccountName:nginx-ingress-serviceaccount#引用前面创建的serviceacount containers: -image:gcr.io/google_containers/nginx-ingress-controller:0.9.0-beta.1#容器使用的镜像 name:nginx-ingress-controller#容器名 readinessProbe:#启动这个服务时要验证/healthz端口10254会在运行的node上监听。 httpGet: path:/healthz port:10254 scheme:HTTP livenessProbe: httpGet: path:/healthz port:10254 scheme:HTTP initialDelaySeconds:10#每隔10做健康检查 timeoutSeconds:1 ports: -containerPort:80 hostPort:80#80映射到80 -containerPort:443 hostPort:443 env: -name:POD_NAME valueFrom: fieldRef: fieldPath:metadata.name -name:POD_NAMESPACE valueFrom: fieldRef: fieldPath:metadata.namespace args: -/nginx-ingress-controller ---default-backend-service=$(POD_NAMESPACE)/default-http-backend #---default-ssl-certificate=$(POD_NAMESPACE)/ingress-secret#这是启用Https时用的 nodeSelector:#指明运行在哪,此IP要和defaultbackend是同一个IP kubernetes.io/hostname:10.3.1.17#上面映射到了hostport80,确保此IP80,443没有占用.
 
这个控制器就是一个deployment ,里面运行一个容器gcr.io/google_containers/nginx-ingress-controller:0.9.0-beta.1 ,有点像nginx容器,现在创建:
 
1
 
2
 
$kubectlcreate-fnginx-ingress-controller.yaml
 
deployment"nginx-ingress-controller"created
 
root@ubuntu15:/data/ingress#kubectlgetrs,pod,svc-nkube-system
 
NAMEDESIREDCURRENTREADYAGE
 
rs/default-http-backend-857b544d9411112m
 
rs/nginx-ingress-controller-8576d4545d11027s
 
NAMEREADYSTATUSRESTARTSAGE
 
po/default-http-backend-857b544d94-bwgjd1/1Running012m
 
po/nginx-ingress-controller-8576d4545d-9tjnv0/1ContainerCreating027s
 
NAMETYPECLUSTER-IPEXTERNAL-IPPORT(S)AGE
 
svc/default-http-backendClusterIP10.254.208.14480/TCP12m
 
现在ingress controller 控制器已部署好了,那么如何使用了,那就要写一个ingress规则了,此处就以已存在的jenkins服务为例,配置如何使用域名访问这个service:
 
$kubectlgetsvc,ep
 
NAMETYPECLUSTER-IPEXTERNAL-IPPORT(S)AGE
 
svc/jenkinsserviceNodePort10.254.70.478080:30002/TCP3h
 
NAMEENDPOINTSAGE
 
ep/jenkinsservice172.30.10.15:8080,172.30.11.7:80803h
 
现在写个jenkins service的Ingress 规则:
 
$catjenkins-ingress.yml
 
apiVersion:extensions/v1beta1
 
kind:Ingress
 
metadata:
 
name:jenkins-ingress
 
namespace:default#服务在哪个空间内就写哪个空间
 
annotations:
 
kubernetes.io/ingress.class:"nginx"
 
spec:
 
rules:
 
-host:ingress.jenkins.com#此service的访问域名
 
http:
 
paths:
 
-backend:
 
serviceName:jenkinsservice
 
servicePort:8080
 
创建它:
 
$kubectlcreate-fjenkins-ingress.yml ingress"jenkins-ingress"created $kubectlgetingress NAMEHOSTSADDRESSPORTSAGE jenkins-ingressingress.jenkins.com8010s
 
到这里就已经部署完成了,配置好域名后,就可以用此域名来访问了:
 
image.png
 
部署完成了,现在看下nginx-ingress-controller 里nginx配置文件发生了哪些变化:
 
upstreamdefault-jenkinsservice-8080{ least_conn; server172.30.10.15:8080max_fails=0fail_timeout=0; server172.30.11.7:8080max_fails=0fail_timeout=0; } upstreamupstream-default-backend{ least_conn; server172.30.11.6:8080max_fails=0fail_timeout=0; } server{ server_nameingress.jenkins.com; listen[::]:80; location/{ ... proxy_passhttp://default-jenkinsservice-8080; ... } }
 
这些配置都是ingress-controller 自已写入的,动态更新就是它能通过K8S API感知到service的endpoint 发生了变化,然后修改nginx配置并执行reload.
 
至此,部署完成。
 
Ingress还有很多部署方式,比如配置https访问的, 以后再写。