|  | 1,如何访问K8S中的服务: 
 
  
 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 一下 使用配置生效。以此来达到域名分配置及动态更新的问题。
 
 看个简单的图方便理解:
 
 
  
 ingress控制器有两种:nginx和haproxy 这里是以nginx为讲解。
 
 2,部署一个Nginx Ingress
 
 ingress的部署文件在github Ingress 仓库找到. 针对官方配置我们单独添加了 nodeselector 指定,绑定LB地址 以方便DNS 做解析。
 
 主要用到的文件:
 
 $ ls
 default-backend.yaml  jenkins-ingress.yml  nginx-ingress-controller-rbac.yml  nginx-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称之为规则。
 第一个是要部署RBAC文件:
 
 cat nginx-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:
 # 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
 - 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来使用
 创建:
 
 $ kubectl create -f nginx-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服务:
 
 $ cat default-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
 # Any image is permissable as long as:
 # 1. It serves a 404 page at /
 # 2. It serves 200 on a /healthz endpoint
 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     #为default backend 创建一个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
 创建:
 
 $ kubectl create -f default-backend.yaml
 deployment "default-http-backend" created
 service "default-http-backend" created
 创建之后查看:
 
 root@ubuntu15:/data/ingress# kubectl get rs,pod,svc  -n kube-system
 NAME                                 DESIRED   CURRENT   READY     AGE
 rs/default-http-backend-857b544d94   1         1         1         1m
 
 NAME                                       READY     STATUS    RESTARTS   AGE
 po/default-http-backend-857b544d94-bwgjd   1/1       Running   0          1m
 
 NAME                       TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)         AGE
 svc/default-http-backend   ClusterIP   10.254.208.144   <none>        80/TCP          1m
 创建好default backend后就要创建nginx-ingress-controller了:
 
 $ cat nginx-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:
 # hostNetwork makes it possible to use ipv6 and to preserve the source IP correctly regardless of docker configuration
 # however, it is not a hard dependency of the nginx-ingress-controller itself and it may cause issues if port 10254 already is taken on the host
 # that said, since hostPort is broken on CNI (https://github.com/kubernetes/kubernetes/issues/31307) we have to use hostNetwork where CNI is used
 # like with kubeadm
 # 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要和default backend是同一个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容器,现在创建:
 
 $ kubectl create -f nginx-ingress-controller.yaml
 deployment "nginx-ingress-controller" created
 root@ubuntu15:/data/ingress# kubectl get rs,pod,svc  -n kube-system
 NAME                                     DESIRED   CURRENT   READY     AGE
 rs/default-http-backend-857b544d94       1         1         1         12m
 rs/nginx-ingress-controller-8576d4545d   1         1         0         27s
 
 NAME                                           READY     STATUS              RESTARTS   AGE
 po/default-http-backend-857b544d94-bwgjd       1/1       Running             0          12m
 po/nginx-ingress-controller-8576d4545d-9tjnv   0/1       ContainerCreating   0          27s
 
 NAME                       TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)         AGE
 svc/default-http-backend   ClusterIP   10.254.208.144   <none>        80/TCP          12m
 现在ingress controller 控制器已部署好了,那么如何使用了,那就要写一个ingress规则了,此处就以已存在的jenkins服务为例,配置如何使用域名访问这个service:
 
 $ kubectl get svc,ep
 NAME                  TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
 svc/jenkinsservice    NodePort    10.254.70.47     <none>        8080:30002/TCP   3h
 
 NAME                 ENDPOINTS                                         AGE
 ep/jenkinsservice    172.30.10.15:8080,172.30.11.7:8080                3h
 现在写个jenkins service的Ingress 规则:
 
 $ cat jenkins-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
 创建它:
 
 $ kubectl create -f jenkins-ingress.yml
 ingress "jenkins-ingress" created
 
 $ kubectl get ingress
 NAME              HOSTS                 ADDRESS   PORTS     AGE
 jenkins-ingress   ingress.jenkins.com             80        10s
 
 到这里就已经部署完成了,配置好域名后,就可以用此域名来访问了:
 
 
  
 部署完成了,现在看下nginx-ingress-controller 里nginx配置文件发生了哪些变化:
 
 upstream default-jenkinsservice-8080 {
 least_conn;
 server 172.30.10.15:8080 max_fails=0 fail_timeout=0;
 server 172.30.11.7:8080 max_fails=0 fail_timeout=0;
 }
 upstream upstream-default-backend {
 least_conn;
 server 172.30.11.6:8080 max_fails=0 fail_timeout=0;
 }
 
 server {
 server_name ingress.jenkins.com;
 listen [::]:80;
 
 location / {
 ...
 proxy_pass http://default-jenkinsservice-8080;
 ...
 }
 }
 这些配置都是ingress-controller 自已写入的,动态更新就是它能通过K8S API感知到service的endpoint 发生了变化,然后修改nginx配置并执行reload.
 
 至此,部署完成。
 
 Ingress还有很多部署方式,比如配置https访问的, 以后再写。
 
 
 
 ----------------------------
 原文链接:https://blog.51cto.com/newfly/2060587
 
 程序猿的技术大观园:www.javathinker.net
 
 
 
 [这个贴子最后由 flybird 在 2020-03-13 12:16:48 重新编辑]
 |  |