从零开始搭建 k8s 集群环境系列笔记:
- 从零开始搭建 k8s 集群环境 (一)—— 搭建镜像存储服和镜像服
- 从零开始搭建 k8s 集群环境 (二)—— 构建 Kubernetes 安装包
- 从零开始搭建 k8s 集群环境 (三)—— 搭建 Master 节点
- 从零开始搭建 k8s 集群环境 (四)—— 添加 Node 节点
- 从零开始搭建 k8s 集群环境 (五)—— 安装 Pod 网络
- 从零开始搭建 k8s 集群环境 (六)—— 部署 Dashboard UI
- 从零开始搭建 k8s 集群环境 (七)—— 部署 Ingress 服务
- 从零开始搭建 k8s 集群环境 (番外)—— 纯手动部署全套
经过几天的部署、熟悉和理解,对 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 文件修改后内容如下:
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
端口。改动完之后我们把他重新部署。
部署完之后在集群内就多了一样东西:
[root@localhost ~]# kubectl get ing -o wide
NAME HOSTS ADDRESS PORTS AGE
http-test-ing * 80 16m
这就是用以将 Server
和 Ingress
关联起来的东西。
三、部署 Ingress 服务
yaml 文件
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/mandatory.yaml
镜像
由于是从谷歌拉取,所以老规矩,阿里云走起:
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
):
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
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 文件
[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
来模拟:
[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
也慢慢变得清晰起来,希望大家如果看了这些文字也能得到收获!