在 Kubernetes 上部署 Nginx Ingress Cntroller

上一篇博客介绍了如何在 Kubernetes 上部署一个无状态容器,但最后将 Service 暴露成 NodePort 时, 由于 k8s 的限制,默认情况下端口只能是 30000-32767,基本无法对外提供服务。

所幸的是除了 Service 提供的外部负载均衡外,还可以使用 Ingress 控制器从处理流量。 官方提供了 Nginx Ingress Controller,可以较为方便的部署 Nginx 作为入流量控制器,部署过程可以参考官方文档,但我对官方的配置做了一些修改。

Nginx Ingress Controller

官方文档参考:https://kubernetes.github.io/ingress-nginx/deploy/

首先部署命名空间,默认后端(处理 404等),配置等,与官方一致。

1
2
3
4
5
6
7
8
curl https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/namespace.yaml \
| kubectl apply -f -

curl https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/default-backend.yaml \
| kubectl apply -f -

curl https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/configmap.yaml \
| kubectl apply -f -

接着需要为 RBAC 配置角色和权限:

1
2
curl https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/rbac.yaml \
| kubectl apply -f -

部署 Nginx

官方的配置文件使用 Deployment 的方式部署单副本到任意一台 worker 机器,但我修改了一些配置,改变了以下行为:

  1. Nginx 部署在 master 机器上,使用 master 的入口 ip 提供服务
  2. 官方文档部署完后仍然需要使用 Service 做转发,在没有 ELB 的情况下仍需使用 NodePort 方式暴露在高端口上
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
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: nginx-ingress-controller
namespace: ingress-nginx
spec:
selector:
matchLabels:
app: ingress-nginx
template:
metadata:
labels:
app: ingress-nginx
annotations:
prometheus.io/port: '10254'
prometheus.io/scrape: 'true'
spec:
serviceAccountName: nginx-ingress-serviceaccount
hostNetwork: true
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node-role.kubernetes.io/master
operator: Exists
tolerations:
- key: node-role.kubernetes.io/master
operator: Exists
effect: NoSchedule
containers:
- name: nginx-ingress-controller
image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.14.0
args:
- /nginx-ingress-controller
- --default-backend-service=$(POD_NAMESPACE)/default-http-backend
- --configmap=$(POD_NAMESPACE)/nginx-configuration
- --annotations-prefix=nginx.ingress.kubernetes.io
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

对官方配置的修改主要有以下几处:

  1. 使用 hostNetwork 配置将服务暴露在外网接口:L19
  2. 使用亲和性配置限制服务只能部署在 master 上:L20-26
  3. 使用 tolerations 配置允许在 master 上部署此服务:L27-30
  4. 删除了对 tcp 和 udp 直接转发的配置,目前还用不到

Tolerations

默认情况下 Kubernetes 不在 master 上部署各种服务,使用了 taint 的机制限制某个 node 的能力,可以查看一下 master 上的 taint:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 列出所有节点
kubectl --kubeconfig=./kubeconfig get nodes

NAME STATUS ROLES AGE VERSION
spc1d17xmk-master-1 Ready master 2d v1.10.2
spc1d17xmk-worker-1 Ready <none> 2d v1.10.2
spc1d17xmk-worker-2 Ready <none> 2d v1.10.2

// 查看 master 节点
kubectl --kubeconfig=./kubeconfig describe node spc1d17xmk-master-1

Name: spc1d17xmk-master-1
Roles: master
// Omitted
Taints: node-role.kubernetes.io/master:NoSchedule
// Omitted

可以看到 master 节点上的 key 为 node-role.kubernetes.io/master 指定了 NoSchedule 限制,可以阻止其它 pod 被部署到这个节点上。 因此如果想要让 pod 部署在这里,需要在 pod 上指定 tolerations 配置,表示某个 pod 可以容忍被配置了这个 taint 的节点。 Taints 和 Tolerations 是一组非常精巧的设计,组合使用时可以允许某些 pod 被部署在当前节点,但阻止其它 pod 的部署。

配置 Ingress

官方的 Ingress 文档已经非常清楚的描述了如何配置。

1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: submodule-checker-ingress
spec:
rules:
- host: YOUR.HOST.NAME
http:
paths:
- backend:
serviceName: submodule-checker-service
servicePort: 7777

配置完成后将域名解析到 k8s 集群的主节点上,即可访问服务内的 pod。

参考链接

  1. NodePort: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport
  2. Affinity: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity
  3. Tolerations: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
  4. Ingress: https://kubernetes.io/docs/concepts/services-networking/ingress/