0%

从零开始搭建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

这就是用以将 ServerIngress 关联起来的东西。

三、部署 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 也慢慢变得清晰起来,希望大家如果看了这些文字也能得到收获!