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