1,如何訪問K8S中的服務:
node
1,Ingress介紹nginx
Kubernetes 暴露服務的方式目前只有三種:LoadBlancer Service、NodePort Service、Ingress;前兩種估計都應該很熟悉,下面詳細的瞭解下這個 Ingressgit
Ingress由兩部分組成:Ingress Controller 和 Ingress 服務。github
Ingress Contronler 經過與 Kubernetes API 交互,動態的去感知集羣中 Ingress 規則變化,而後讀取它,按照自定義的規則,規則就是寫明瞭哪一個域名對應哪一個service,生成一段 Nginx 配置,再寫到 Nginx-ingress-control的 Pod 裏,這個 Ingress Contronler 的pod裏面運行着一個nginx服務,控制器會把生成的nginx配置寫入/etc/nginx.conf文件中,而後 reload 一下 使用配置生效。以此來達到域名分配置及動態更新的問題。web
看個簡單的圖方便理解:docker
ingress控制器有兩種:nginx和haproxy 這裏是以nginx爲講解。ubuntu
2,部署一個Nginx Ingress後端
ingress的部署文件在github Ingress 倉庫找到. 針對官方配置咱們單獨添加了 nodeselector 指定,綁定LB地址 以方便DNS 作解析。api
主要用到的文件:bash
$ 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訪問的, 之後再寫。