系列目录:
经过几天的部署、熟悉和理解,对 k8s
的概念和结构都有了一定了解。而在实际操作中,我们的服务运行在服务器,通常都会做反向代理和负载均衡,增强灵活性。这篇博客就来实现 k8s
的反向代理和负载均衡。
环境说明:
Master:VBox虚拟机/Centos_7.5-1804/192.168.56.100
Images:VBox虚拟机/Centos_7.5-1804/192.168.56.101
Node01:VBox虚拟机/Centos_7.5-1804/192.168.56.102
软件环境说明:
docker-ce-17.03.2
kubernetes-v1.9.0
harbor-v1.4.0
再部署之前,我们先过一遍 k8s
的结构。在 k8s
中,我们的服务以 Pod
为单位分布在一个或多个物理 Node
之上,这些 Pod
通过每个 Node
上运行的 kube-proxy
中转向外提供服务。如果同一组 Pod 是运行在同一个 Node
之上的时候,我们可以通过 nodePort
直接向外暴露服务(比如上一篇部署的UI控制台就是通过这种方式),但是通常情况为了提高服务可用性,Pod
一般都是分布在多个 Node
上运行,但每个 Node
的对外 IP
不尽相同,客户调用的时候不方便切换和维护,更重要的是客户很难对众多 Node
做负载均衡等操作。
很明显,我们就需要一个类似 Nginx
这样的服务来“包容”这些提供服务的 Node
,把负载均衡、反向代理的事情统统交给他去做。当然我们也可以手动创建一个运行在 k8s
上面的 Nginx
服务,直接实现上面的操作,但又有新的问题,当我们服务变动频繁,岂不是又得跟着手动改动 Nginx
?不!我们是程序员,一切能自动化解决的问题,我们一定要写个程序来实现它!
幸运的是,这个程序已经有人帮我们写好了,他就是——Ingress-Nginx
!
GitHub:kubernetes/ingress-nginx
Home Page:NGINX Ingress Controller
二、部署测试服务
之前在第五篇安装网络的时候我们已经部署了一个用来测试 Pod
直接网络的服务,这里我们仍旧继续使用这个服务作为我们的测试服务,但我们需要改动一下它的 yaml
文件,使其支持 Ingress
自动处理。
http-test.yaml 文件修改后内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 apiVersion: extensions/v1beta1 kind: Deployment metadata: name: http-test-dm spec: replicas: 3 template: metadata: labels: name: http-test-dm spec: containers: - name: http-test-con image: registry.cn-shenzhen.aliyuncs.com/lx0758-per/http-test:latest ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: http-test-ser spec: ports: - port: 80 targetPort: 80 selector: name: http-test-dm --- apiVersion: extensions/v1beta1 kind: Ingress metadata: name: http-test-ing spec: rules: - host: test.6xyun.lan http: paths: - path: / backend: serviceName: http-test-ser servicePort: 80
可以看到,我们只是在原来的基础上追加了一个 kind: Ingress
对象,内容就是使用 test.6xyun.lan
这个域名负载均衡到 http-test-ser
这个服务的 80
端口。改动完之后我们把他重新部署。
部署完之后在集群内就多了一样东西:
1 2 3 [root@localhost ~]# kubectl get ing -o wide NAME HOSTS ADDRESS PORTS AGE http-test-ing * 80 16m
这就是用以将 Server
和 Ingress
关联起来的东西。
三、部署 Ingress 服务
yaml 文件
1 wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/mandatory.yaml
镜像
由于是从谷歌拉取,所以老规矩,阿里云走起:
1 2 3 4 5 6 7 docker pull registry.cn-shenzhen.aliyuncs.com/lx0758/defaultbackend:1.4 docker tag registry.cn-shenzhen.aliyuncs.com/lx0758/defaultbackend:1.4 gcr.io/google_containers/defaultbackend:1.4 docker rmi registry.cn-shenzhen.aliyuncs.com/lx0758/defaultbackend:1.4 docker pull registry.cn-shenzhen.aliyuncs.com/lx0758/nginx-ingress-controller:0.15.0 docker tag registry.cn-shenzhen.aliyuncs.com/lx0758/nginx-ingress-controller:0.15.0 quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.15.0 docker rmi registry.cn-shenzhen.aliyuncs.com/lx0758/nginx-ingress-controller:0.15.0
修改 yaml 文件
实际操作发现,服务器的 yaml
有些地方并不太合理,所以还得手动修改一下。
修改镜像 pull
策略和部署节点(注意是两个 Deployment
):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 apiVersion: extensions/v1beta1 kind: Deployment metadata: name: default-http-backend labels: app: default-http-backend namespace: ingress-nginx spec: replicas: 1 selector: matchLabels: app: default-http-backend template: metadata: labels: app: default-http-backend spec: # 强制部署到某节点 nodeName: localhost.master terminationGracePeriodSeconds: 60 containers: - name: default-http-backend # Any image is permissible 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.4 # 修改镜像 pull 策略 imagePullPolicy: IfNotPresent
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 apiVersion: extensions/v1beta1 kind: Deployment metadata: name: nginx-ingress-controller namespace: ingress-nginx spec: replicas: 1 selector: matchLabels: app: ingress-nginx template: metadata: labels: app: ingress-nginx annotations: prometheus.io/port: '10254' prometheus.io/scrape: 'true' spec: # 映射服务到宿主机 hostNetwork: true # 强制部署到某节点 nodeName: localhost.master serviceAccountName: nginx-ingress-serviceaccount containers: - name: nginx-ingress-controller image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.15.0 # 修改镜像 Pull 策略 imagePullPolicy: IfNotPresent args: - /nginx-ingress-controller - --default-backend-service=$(POD_NAMESPACE)/default-http-backend - --configmap=$(POD_NAMESPACE)/nginx-configuration - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services - --udp-services-configmap=$(POD_NAMESPACE)/udp-services - --publish-service=$(POD_NAMESPACE)/ingress-nginx - --annotations-prefix=nginx.ingress.kubernetes.io # 增加 ApiServer 配置(两行) - --apiserver-host=https://192.168.56.100:6443 - --kubeconfig=/etc/kubernetes/master-kubeconfig.yaml env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace ports: - name: http containerPort: 80 - name: https containerPort: 443 livenessProbe: failureThreshold: 3 httpGet: path: /healthz port: 10254 scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 10254 scheme: HTTP periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 securityContext: runAsNonRoot: false # 映射 k8s 配置 volumeMounts: - mountPath: /etc/kubernetes/master-kubeconfig.yaml name: kubeconfig # 挂载 k8s 配置 volumes: - name: kubeconfig hostPath: path: /root/.kube/config
应用修改后的 yaml 文件
1 2 3 4 5 6 7 8 9 10 11 12 13 [root@localhost ~]# kubectl create -f mandatory-fix.yaml.0 namespace "ingress-nginx" created deployment "default-http-backend" created service "default-http-backend" created configmap "nginx-configuration" created configmap "tcp-services" created configmap "udp-services" created 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 deployment "nginx-ingress-controller" created
部署工作到这里接结束了,正常情况我们的 Ingress
就已经开始工作了。
验证配置
上面的 test.6xyun.lan
实际是不存在的,我们可以通过改动 Hosts
文件来虚拟,然后访问这个 test.6xyun.lan
就可以访问到我们部署的测试服务,我这里使用 curl
自定义请求头 host
来模拟:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 [root@localhost ~]# curl test.6xyun.lan curl: (6) Could not resolve host: test.6xyun.lan; 未知的错误 [root@localhost ~]# curl 192.168.56.100 default backend - 404 [root@localhost ~]# curl -H host:test.6xyun.lan 192.168.56.100 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>
实测,集群中只要还有一个 Pod
可用整个服务就能正常工作。至此,我们的 Ingress
就部署完了。
四、总结
这一个系列是楼主用差不多一周的业余时间来完成 从零开始搭建k8s集群环境
,到这里基本就结束了。但博客设计的内容是 k8s
里面最基础的东西,包括这些组件也还只是基本的使用,一些高难度的 骚操作
还需要在实际应用当中去探索、发现和实践。
然后这几篇文字在我不断的学习和填坑的过程中也修改了多次,但我认为依然有错误和不足的地方,所以如果各位发现了错误或者不足,希望能在留言区能够提出来,大家共同学习进步。
经过这个过程之后,原本一窍不通的 k8s
也慢慢变得清晰起来,希望大家如果看了这些文字也能得到收获!