KubernetesNginxIngress安裝與使用

店家小二發表於2018-12-18

目錄 (Table of Contents)

[TOCM]

概述

用過kubernetes的人都知道,kubernetes的service的網路型別有三種:cluertip,nodeport,loadbanlance,各種型別的作用就不在這裡描述了。如果一個service想向外部暴露服務,有nodeport和loadbanlance型別,但是nodeport型別,你的知道service對應的pod所在的node的ip,而loadbanlance通常需要第三方雲服務商提供支援。如果沒有第三方服務商服務的就沒辦法做了。除此之外還有很多其他的替代方式,以下我主要講解的是通過ingress的方式來實現service的對外服務的暴露。

下載搭建環境所需要的映象

  • gcr.io/google_containers/nginx-ingress-controller:0.8.3 (ingress controller 的映象)
  • gcr.io/google_containers/defaultbackend:1.0 (預設路由的servcie的映象)
  • gcr.io/google_containers/echoserver:1.0 (用於測試ingress的service映象,當然這個你可以換成你自己的service都可以)

說明:由於GFW的原因下載不下來的,都可以到時速雲去下載相應的映象(只要把grc.io換成index.tenxcloud.com就可以了),由於我用的是自己私用映象倉庫,所以之後看到的映象都是我自己tag之後上傳到自己私有映象倉庫的。

配置default-http-bankend

首先便捷default-http-backend.yaml:

apiVersion: v1
kind: ReplicationController
metadata:
 name: default-http-backend
spec:
 replicas: 1
 selector:
 app: default-http-backend
 template:
 metadata:
 labels:
 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: hub.yfcloud.io/google_containers/defaultbackend:1.0
 livenessProbe:
 httpGet:
 path: /healthz
 port: 8080
 scheme: HTTP
 initialDelaySeconds: 30
 timeoutSeconds: 5
 ports:
 - containerPort: 8080
 resources:
 limits:
 cpu: 10m
 memory: 20Mi
 requests:
 cpu: 10m
 memory: 20Mi

然後建立建立default-http-backend的rc:

kubectl create -f default-http-backend .yaml

最後建立default-http-backend的service,有兩種方式建立,一種是:便捷default-http-backend-service.yaml,另一種通過如下命令建立:

kubectl expose rc default-http-backend --port=80 --target-port=8080 --name=default-http-backend

最後檢視相應的rc以及service是否成功建立:然後自己測試能否正常訪問,訪問方式如下,直接通過的pod的ip/healthz或者serive的ip/(如果是srevice的ip加port)

配置inrgess-controller

首先編輯ingress-controller.yaml檔案:

apiVersion: v1
kind: ReplicationController
metadata:
 name: nginx-ingress-controller
 labels:
 k8s-app: nginx-ingress-lb
spec:
 replicas: 1
 selector:
 k8s-app: nginx-ingress-lb
 template:
 metadata:
 labels:
 k8s-app: nginx-ingress-lb
 name: nginx-ingress-lb
 spec:
 terminationGracePeriodSeconds: 60
 containers:
 - image: hub.yfcloud.io/google_containers/nginx-ingress-controller:0.8.3
 name: nginx-ingress-lb
 imagePullPolicy: Always
 readinessProbe:
 httpGet:
 path: /healthz
 port: 80
 scheme: HTTP
 livenessProbe:
 httpGet:
 path: /healthz
 port: 80
 scheme: HTTP
 initialDelaySeconds: 10
 timeoutSeconds: 1 # use downward API
 env:
 - name: POD_NAME
 valueFrom:
 fieldRef:
 fieldPath: metadata.name
 - name: POD_NAMESPACE
 valueFrom:
 fieldRef:
 fieldPath: metadata.namespace
 - name: KUBERNETES_MASTER
 value: http://183.131.19.231:8080
 ports:
 - containerPort: 80
 hostPort: 80
 - containerPort: 443
 hostPort: 443
 args:
 - /nginx-ingress-controller
 - --default-backend-service=$(POD_NAMESPACE)/default-http-backend
 imagePullSecrets:
 - name: hub.yfcloud.io.key

建立ingress-controller的rc:

kubectl create -f ingress-controller.yaml

最後驗證ingress-controller是否正常啟動成功,方法 如下:檢視ingress-controller中對應pod的ip,然後通過ip:80/healthz 訪問,成功的話會返回 ok。

配置需要測試的service

首先編輯測試用的test.yaml:

apiVersion: v1 kind: ReplicationController metadata:
 name: echoheaders
spec:
 replicas: 1
 template:
 metadata:
 labels:
 app: echoheaders
 spec:
 containers:
 - name: echoheaders
 image: hub.yfcloud.io/google_containers/echoserver:test
 ports:
 - containerPort: 8080

測試service的yaml這裡建立多個:
sv-alp-default.yaml:

apiVersion: v1 kind: Service metadata:
 name: echoheaders-default
 labels:
 app: echoheaders
spec:
 type: NodePort
 ports:
 - port: 80
 nodePort: 30302
 targetPort: 8080
 protocol: TCP
 name: http
 selector:
 app: echoheaders

sv-alp-x.yaml:

apiVersion: v1 kind: Service metadata:
 name: echoheaders-x
 labels:
 app: echoheaders
spec:
 type: NodePort
 ports:
 - port: 80
 nodePort: 30301
 targetPort: 8080
 protocol: TCP
 name: http
 selector:
 app: echoheaders

sv-alp-y.yaml:

apiVersion: v1 kind: Service metadata:
 name: echoheaders-y
 labels:
 app: echoheaders
spec:
 type: NodePort
 ports:
 - port: 80
 nodePort: 30284
 targetPort: 8080
 protocol: TCP
 name: http
 selector:
 app: echoheaders

接著是

配置ingress

編輯ingress-alp.yaml:

apiVersion: extensions/v1beta1 kind: Ingress metadata:
 name: echomap
spec:
 rules:
 - host: foo.bar.com
 http:
 paths:
 - path: /foo
 backend:
 serviceName: echoheaders-x
 servicePort: 80
 - host: bar.baz.com
 http:
 paths:
 - path: /bar
 backend:
 serviceName: echoheaders-y
 servicePort: 80
 - path: /foo
 backend:
 serviceName: echoheaders-x
 servicePort: 80

最後測試,測試方法有兩種,如下:

方法一:

curl -v http://nodeip:80/foo -H `host: foo.bar.com`

結果如下:

* About to connect() to 183.131.19.232 port 80 (#0)
* Trying 183.131.19.232...
* Connected to 183.131.19.232 (183.131.19.232) port 80 (#0)
> GET /foo HTTP/1.1
> User-Agent: curl/7.29.0
> Accept: */*
> host: foo.bar.com
> 
< HTTP/1.1 200 OK
< Server: nginx/1.11.3
< Date: Wed, 12 Oct 2016 10:04:40 GMT
< Transfer-Encoding: chunked
< Connection: keep-alive
< 
CLIENT VALUES:
client_address=(`10.1.58.3`, 57364) (10.1.58.3)
command=GET
path=/foo
real path=/foo
query=
request_version=HTTP/1.1

SERVER VALUES:
server_version=BaseHTTP/0.6
sys_version=Python/3.5.0
protocol_version=HTTP/1.0

HEADERS RECEIVED:
Accept=*/*
Connection=close
Host=foo.bar.com
User-Agent=curl/7.29.0
X-Forwarded-For=183.131.19.231
X-Forwarded-Host=foo.bar.com
X-Forwarded-Port=80
X-Forwarded-Proto=http
X-Real-IP=183.131.19.231
* Connection #0 to host 183.131.19.232 left intact

其他路由的測試修改對應的url即可。

**注意:**nodeip是你的ingress-controller所對應的pod所在的node的ip。

方法二:
將訪問url的主機的host中加上:

nodeip foo.bar.com nodeip bar.baz.com

在瀏覽器中直接訪問:

foo.bar.com/foo
bar.baz.com/bar
bar.baz.com/foo

都是可以的。

問題集

在建立ingress-controller的時候報錯(ingress的yaml檔案是官網中的yaml檔案配置,我只改了相對應的映象。):

問題一:

這裡寫圖片描述

以上錯誤資訊是ingress-controller建立失敗的原因,通過docker log 檢視rc中的對應的ingress-controller的容器的日誌。

原因:從錯誤資訊來看是因為ingress內部程式預設是通過localhost:8080連線master的apiserver,如果是單機版的k8s環境,就不會報這個錯,如果是叢集環境,並且你的ingress-controller的pod所對應的容器不是在master節點上(因為有的叢集環境master也是node,這樣的話,如果你的pod對應的容器在master節點上也不會報這個錯),就會報這個錯。

解決方法:在ingress-controller.yaml中加上如下引數,

- name: KUBERNETES_MASTER
 value: http://183.131.19.231:8080

之後的yaml檔案就是如前面定義的yaml檔案。

問題二:

這個問題是在建立ingress rc成功之後,馬上檢視rc對應的pod對應的容器時報的錯!

這裡寫圖片描述

從這個問題衍生出個連帶的問題,如下圖:

問題1:
這個問題是在建立ingress rc成功之後,當第一個容器失敗,rc的垃圾機制回收第一次建立停止的容器後,重新啟動的容器。檢視rc對應的pod對應的容器時報的錯!

這裡寫圖片描述

原因:因為ingress中的原始碼的健康檢查的url改成了 /healthz,而官方文件中的yaml中定義的健康檢查的路由是/ingress-controller-healthz,這個url是ingress的自檢url,當超過8次之後如果得到結果還是unhealthy,則會掛掉ingress對應的容器。

解決方法:將yaml中的健康檢查的url改成:/healthz即可。:

readinessProbe:
 httpGet:
 path: /healthz
 port: 80
 scheme: HTTP
 livenessProbe:
 httpGet:
 path: /healthz
 port: 80
 scheme: HTTP
 initialDelaySeconds: 10
 timeoutSeconds: 1

目錄 (Table of Contents)

[TOCM]

概述

用過kubernetes的人都知道,kubernetes的service的網路型別有三種:cluertip,nodeport,loadbanlance,各種型別的作用就不在這裡描述了。如果一個service想向外部暴露服務,有nodeport和loadbanlance型別,但是nodeport型別,你的知道service對應的pod所在的node的ip,而loadbanlance通常需要第三方雲服務商提供支援。如果沒有第三方服務商服務的就沒辦法做了。除此之外還有很多其他的替代方式,以下我主要講解的是通過ingress的方式來實現service的對外服務的暴露。

下載搭建環境所需要的映象

  • gcr.io/google_containers/nginx-ingress-controller:0.8.3 (ingress controller 的映象)
  • gcr.io/google_containers/defaultbackend:1.0 (預設路由的servcie的映象)
  • gcr.io/google_containers/echoserver:1.0 (用於測試ingress的service映象,當然這個你可以換成你自己的service都可以)

說明:由於GFW的原因下載不下來的,都可以到時速雲去下載相應的映象(只要把grc.io換成index.tenxcloud.com就可以了),由於我用的是自己私用映象倉庫,所以之後看到的映象都是我自己tag之後上傳到自己私有映象倉庫的。

配置default-http-bankend

首先便捷default-http-backend.yaml:

apiVersion: v1
kind: ReplicationController
metadata:
 name: default-http-backend
spec:
 replicas: 1
 selector:
 app: default-http-backend
 template:
 metadata:
 labels:
 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: hub.yfcloud.io/google_containers/defaultbackend:1.0
 livenessProbe:
 httpGet:
 path: /healthz
 port: 8080
 scheme: HTTP
 initialDelaySeconds: 30
 timeoutSeconds: 5
 ports:
 - containerPort: 8080
 resources:
 limits:
 cpu: 10m
 memory: 20Mi
 requests:
 cpu: 10m
 memory: 20Mi

然後建立建立default-http-backend的rc:

kubectl create -f default-http-backend .yaml

最後建立default-http-backend的service,有兩種方式建立,一種是:便捷default-http-backend-service.yaml,另一種通過如下命令建立:

kubectl expose rc default-http-backend --port=80 --target-port=8080 --name=default-http-backend

最後檢視相應的rc以及service是否成功建立:然後自己測試能否正常訪問,訪問方式如下,直接通過的pod的ip/healthz或者serive的ip/(如果是srevice的ip加port)

配置inrgess-controller

首先編輯ingress-controller.yaml檔案:

apiVersion: v1
kind: ReplicationController
metadata:
 name: nginx-ingress-controller
 labels:
 k8s-app: nginx-ingress-lb
spec:
 replicas: 1
 selector:
 k8s-app: nginx-ingress-lb
 template:
 metadata:
 labels:
 k8s-app: nginx-ingress-lb
 name: nginx-ingress-lb
 spec:
 terminationGracePeriodSeconds: 60
 containers:
 - image: hub.yfcloud.io/google_containers/nginx-ingress-controller:0.8.3
 name: nginx-ingress-lb
 imagePullPolicy: Always
 readinessProbe:
 httpGet:
 path: /healthz
 port: 80
 scheme: HTTP
 livenessProbe:
 httpGet:
 path: /healthz
 port: 80
 scheme: HTTP
 initialDelaySeconds: 10
 timeoutSeconds: 1 # use downward API
 env:
 - name: POD_NAME
 valueFrom:
 fieldRef:
 fieldPath: metadata.name
 - name: POD_NAMESPACE
 valueFrom:
 fieldRef:
 fieldPath: metadata.namespace
 - name: KUBERNETES_MASTER
 value: http://183.131.19.231:8080
 ports:
 - containerPort: 80
 hostPort: 80
 - containerPort: 443
 hostPort: 443
 args:
 - /nginx-ingress-controller
 - --default-backend-service=$(POD_NAMESPACE)/default-http-backend
 imagePullSecrets:
 - name: hub.yfcloud.io.key

建立ingress-controller的rc:

kubectl create -f ingress-controller.yaml

最後驗證ingress-controller是否正常啟動成功,方法 如下:檢視ingress-controller中對應pod的ip,然後通過ip:80/healthz 訪問,成功的話會返回 ok。

配置需要測試的service

首先編輯測試用的test.yaml:

apiVersion: v1 kind: ReplicationController metadata:
 name: echoheaders
spec:
 replicas: 1
 template:
 metadata:
 labels:
 app: echoheaders
 spec:
 containers:
 - name: echoheaders
 image: hub.yfcloud.io/google_containers/echoserver:test
 ports:
 - containerPort: 8080

測試service的yaml這裡建立多個:
sv-alp-default.yaml:

apiVersion: v1 kind: Service metadata:
 name: echoheaders-default
 labels:
 app: echoheaders
spec:
 type: NodePort
 ports:
 - port: 80
 nodePort: 30302
 targetPort: 8080
 protocol: TCP
 name: http
 selector:
 app: echoheaders

sv-alp-x.yaml:

apiVersion: v1 kind: Service metadata:
 name: echoheaders-x
 labels:
 app: echoheaders
spec:
 type: NodePort
 ports:
 - port: 80
 nodePort: 30301
 targetPort: 8080
 protocol: TCP
 name: http
 selector:
 app: echoheaders

sv-alp-y.yaml:

apiVersion: v1 kind: Service metadata:
 name: echoheaders-y
 labels:
 app: echoheaders
spec:
 type: NodePort
 ports:
 - port: 80
 nodePort: 30284
 targetPort: 8080
 protocol: TCP
 name: http
 selector:
 app: echoheaders

接著是

配置ingress

編輯ingress-alp.yaml:

apiVersion: extensions/v1beta1 kind: Ingress metadata:
 name: echomap
spec:
 rules:
 - host: foo.bar.com
 http:
 paths:
 - path: /foo
 backend:
 serviceName: echoheaders-x
 servicePort: 80
 - host: bar.baz.com
 http:
 paths:
 - path: /bar
 backend:
 serviceName: echoheaders-y
 servicePort: 80
 - path: /foo
 backend:
 serviceName: echoheaders-x
 servicePort: 80

最後測試,測試方法有兩種,如下:

方法一:

curl -v http://nodeip:80/foo -H `host: foo.bar.com`

結果如下:

* About to connect() to 183.131.19.232 port 80 (#0)
* Trying 183.131.19.232...
* Connected to 183.131.19.232 (183.131.19.232) port 80 (#0)
> GET /foo HTTP/1.1
> User-Agent: curl/7.29.0
> Accept: */*
> host: foo.bar.com
> 
< HTTP/1.1 200 OK
< Server: nginx/1.11.3
< Date: Wed, 12 Oct 2016 10:04:40 GMT
< Transfer-Encoding: chunked
< Connection: keep-alive
< 
CLIENT VALUES:
client_address=(`10.1.58.3`, 57364) (10.1.58.3)
command=GET
path=/foo
real path=/foo
query=
request_version=HTTP/1.1

SERVER VALUES:
server_version=BaseHTTP/0.6
sys_version=Python/3.5.0
protocol_version=HTTP/1.0

HEADERS RECEIVED:
Accept=*/*
Connection=close
Host=foo.bar.com
User-Agent=curl/7.29.0
X-Forwarded-For=183.131.19.231
X-Forwarded-Host=foo.bar.com
X-Forwarded-Port=80
X-Forwarded-Proto=http
X-Real-IP=183.131.19.231
* Connection #0 to host 183.131.19.232 left intact

其他路由的測試修改對應的url即可。

**注意:**nodeip是你的ingress-controller所對應的pod所在的node的ip。

方法二:
將訪問url的主機的host中加上:

nodeip foo.bar.com nodeip bar.baz.com

在瀏覽器中直接訪問:

foo.bar.com/foo
bar.baz.com/bar
bar.baz.com/foo

都是可以的。

問題集

在建立ingress-controller的時候報錯(ingress的yaml檔案是官網中的yaml檔案配置,我只改了相對應的映象。):

問題一:

這裡寫圖片描述

以上錯誤資訊是ingress-controller建立失敗的原因,通過docker log 檢視rc中的對應的ingress-controller的容器的日誌。

原因:從錯誤資訊來看是因為ingress內部程式預設是通過localhost:8080連線master的apiserver,如果是單機版的k8s環境,就不會報這個錯,如果是叢集環境,並且你的ingress-controller的pod所對應的容器不是在master節點上(因為有的叢集環境master也是node,這樣的話,如果你的pod對應的容器在master節點上也不會報這個錯),就會報這個錯。

解決方法:在ingress-controller.yaml中加上如下引數,

- name: KUBERNETES_MASTER
 value: http://183.131.19.231:8080

之後的yaml檔案就是如前面定義的yaml檔案。

問題二:

這個問題是在建立ingress rc成功之後,馬上檢視rc對應的pod對應的容器時報的錯!

這裡寫圖片描述

從這個問題衍生出個連帶的問題,如下圖:

問題1:
這個問題是在建立ingress rc成功之後,當第一個容器失敗,rc的垃圾機制回收第一次建立停止的容器後,重新啟動的容器。檢視rc對應的pod對應的容器時報的錯!

這裡寫圖片描述

原因:因為ingress中的原始碼的健康檢查的url改成了 /healthz,而官方文件中的yaml中定義的健康檢查的路由是/ingress-controller-healthz,這個url是ingress的自檢url,當超過8次之後如果得到結果還是unhealthy,則會掛掉ingress對應的容器。

解決方法:將yaml中的健康檢查的url改成:/healthz即可。:

readinessProbe:
 httpGet:
 path: /healthz
 port: 80
 scheme: HTTP
 livenessProbe:
 httpGet:
 path: /healthz
 port: 80
 scheme: HTTP
 initialDelaySeconds: 10
 timeoutSeconds: 1

目錄 (Table of Contents)

[TOCM]

概述

用過kubernetes的人都知道,kubernetes的service的網路型別有三種:cluertip,nodeport,loadbanlance,各種型別的作用就不在這裡描述了。如果一個service想向外部暴露服務,有nodeport和loadbanlance型別,但是nodeport型別,你的知道service對應的pod所在的node的ip,而loadbanlance通常需要第三方雲服務商提供支援。如果沒有第三方服務商服務的就沒辦法做了。除此之外還有很多其他的替代方式,以下我主要講解的是通過ingress的方式來實現service的對外服務的暴露。

下載搭建環境所需要的映象

  • gcr.io/google_containers/nginx-ingress-controller:0.8.3 (ingress controller 的映象)
  • gcr.io/google_containers/defaultbackend:1.0 (預設路由的servcie的映象)
  • gcr.io/google_containers/echoserver:1.0 (用於測試ingress的service映象,當然這個你可以換成你自己的service都可以)

說明:由於GFW的原因下載不下來的,都可以到時速雲去下載相應的映象(只要把grc.io換成index.tenxcloud.com就可以了),由於我用的是自己私用映象倉庫,所以之後看到的映象都是我自己tag之後上傳到自己私有映象倉庫的。

配置default-http-bankend

首先便捷default-http-backend.yaml:

apiVersion: v1
kind: ReplicationController
metadata:
 name: default-http-backend
spec:
 replicas: 1
 selector:
 app: default-http-backend
 template:
 metadata:
 labels:
 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: hub.yfcloud.io/google_containers/defaultbackend:1.0
 livenessProbe:
 httpGet:
 path: /healthz
 port: 8080
 scheme: HTTP
 initialDelaySeconds: 30
 timeoutSeconds: 5
 ports:
 - containerPort: 8080
 resources:
 limits:
 cpu: 10m
 memory: 20Mi
 requests:
 cpu: 10m
 memory: 20Mi

然後建立建立default-http-backend的rc:

kubectl create -f default-http-backend .yaml

最後建立default-http-backend的service,有兩種方式建立,一種是:便捷default-http-backend-service.yaml,另一種通過如下命令建立:

kubectl expose rc default-http-backend --port=80 --target-port=8080 --name=default-http-backend

最後檢視相應的rc以及service是否成功建立:然後自己測試能否正常訪問,訪問方式如下,直接通過的pod的ip/healthz或者serive的ip/(如果是srevice的ip加port)

配置inrgess-controller

首先編輯ingress-controller.yaml檔案:

apiVersion: v1
kind: ReplicationController
metadata:
 name: nginx-ingress-controller
 labels:
 k8s-app: nginx-ingress-lb
spec:
 replicas: 1
 selector:
 k8s-app: nginx-ingress-lb
 template:
 metadata:
 labels:
 k8s-app: nginx-ingress-lb
 name: nginx-ingress-lb
 spec:
 terminationGracePeriodSeconds: 60
 containers:
 - image: hub.yfcloud.io/google_containers/nginx-ingress-controller:0.8.3
 name: nginx-ingress-lb
 imagePullPolicy: Always
 readinessProbe:
 httpGet:
 path: /healthz
 port: 80
 scheme: HTTP
 livenessProbe:
 httpGet:
 path: /healthz
 port: 80
 scheme: HTTP
 initialDelaySeconds: 10
 timeoutSeconds: 1 # use downward API
 env:
 - name: POD_NAME
 valueFrom:
 fieldRef:
 fieldPath: metadata.name
 - name: POD_NAMESPACE
 valueFrom:
 fieldRef:
 fieldPath: metadata.namespace
 - name: KUBERNETES_MASTER
 value: http://183.131.19.231:8080
 ports:
 - containerPort: 80
 hostPort: 80
 - containerPort: 443
 hostPort: 443
 args:
 - /nginx-ingress-controller
 - --default-backend-service=$(POD_NAMESPACE)/default-http-backend
 imagePullSecrets:
 - name: hub.yfcloud.io.key

建立ingress-controller的rc:

kubectl create -f ingress-controller.yaml

最後驗證ingress-controller是否正常啟動成功,方法 如下:檢視ingress-controller中對應pod的ip,然後通過ip:80/healthz 訪問,成功的話會返回 ok。

配置需要測試的service

首先編輯測試用的test.yaml:

apiVersion: v1 kind: ReplicationController metadata:
 name: echoheaders
spec:
 replicas: 1
 template:
 metadata:
 labels:
 app: echoheaders
 spec:
 containers:
 - name: echoheaders
 image: hub.yfcloud.io/google_containers/echoserver:test
 ports:
 - containerPort: 8080

測試service的yaml這裡建立多個:
sv-alp-default.yaml:

apiVersion: v1 kind: Service metadata:
 name: echoheaders-default
 labels:
 app: echoheaders
spec:
 type: NodePort
 ports:
 - port: 80
 nodePort: 30302
 targetPort: 8080
 protocol: TCP
 name: http
 selector:
 app: echoheaders

sv-alp-x.yaml:

apiVersion: v1 kind: Service metadata:
 name: echoheaders-x
 labels:
 app: echoheaders
spec:
 type: NodePort
 ports:
 - port: 80
 nodePort: 30301
 targetPort: 8080
 protocol: TCP
 name: http
 selector:
 app: echoheaders

sv-alp-y.yaml:

apiVersion: v1 kind: Service metadata:
 name: echoheaders-y
 labels:
 app: echoheaders
spec:
 type: NodePort
 ports:
 - port: 80
 nodePort: 30284
 targetPort: 8080
 protocol: TCP
 name: http
 selector:
 app: echoheaders

接著是

配置ingress

編輯ingress-alp.yaml:

apiVersion: extensions/v1beta1 kind: Ingress metadata:
 name: echomap
spec:
 rules:
 - host: foo.bar.com
 http:
 paths:
 - path: /foo
 backend:
 serviceName: echoheaders-x
 servicePort: 80
 - host: bar.baz.com
 http:
 paths:
 - path: /bar
 backend:
 serviceName: echoheaders-y
 servicePort: 80
 - path: /foo
 backend:
 serviceName: echoheaders-x
 servicePort: 80

最後測試,測試方法有兩種,如下:

方法一:

curl -v http://nodeip:80/foo -H `host: foo.bar.com`

結果如下:

* About to connect() to 183.131.19.232 port 80 (#0)
* Trying 183.131.19.232...
* Connected to 183.131.19.232 (183.131.19.232) port 80 (#0)
> GET /foo HTTP/1.1
> User-Agent: curl/7.29.0
> Accept: */*
> host: foo.bar.com
> 
< HTTP/1.1 200 OK
< Server: nginx/1.11.3
< Date: Wed, 12 Oct 2016 10:04:40 GMT
< Transfer-Encoding: chunked
< Connection: keep-alive
< 
CLIENT VALUES:
client_address=(`10.1.58.3`, 57364) (10.1.58.3)
command=GET
path=/foo
real path=/foo
query=
request_version=HTTP/1.1

SERVER VALUES:
server_version=BaseHTTP/0.6
sys_version=Python/3.5.0
protocol_version=HTTP/1.0

HEADERS RECEIVED:
Accept=*/*
Connection=close
Host=foo.bar.com
User-Agent=curl/7.29.0
X-Forwarded-For=183.131.19.231
X-Forwarded-Host=foo.bar.com
X-Forwarded-Port=80
X-Forwarded-Proto=http
X-Real-IP=183.131.19.231
* Connection #0 to host 183.131.19.232 left intact

其他路由的測試修改對應的url即可。

**注意:**nodeip是你的ingress-controller所對應的pod所在的node的ip。

方法二:
將訪問url的主機的host中加上:

nodeip foo.bar.com nodeip bar.baz.com

在瀏覽器中直接訪問:

foo.bar.com/foo
bar.baz.com/bar
bar.baz.com/foo

都是可以的。

問題集

在建立ingress-controller的時候報錯(ingress的yaml檔案是官網中的yaml檔案配置,我只改了相對應的映象。):

問題一:

這裡寫圖片描述

以上錯誤資訊是ingress-controller建立失敗的原因,通過docker log 檢視rc中的對應的ingress-controller的容器的日誌。

原因:從錯誤資訊來看是因為ingress內部程式預設是通過localhost:8080連線master的apiserver,如果是單機版的k8s環境,就不會報這個錯,如果是叢集環境,並且你的ingress-controller的pod所對應的容器不是在master節點上(因為有的叢集環境master也是node,這樣的話,如果你的pod對應的容器在master節點上也不會報這個錯),就會報這個錯。

解決方法:在ingress-controller.yaml中加上如下引數,

- name: KUBERNETES_MASTER
 value: http://183.131.19.231:8080

之後的yaml檔案就是如前面定義的yaml檔案。

問題二:

這個問題是在建立ingress rc成功之後,馬上檢視rc對應的pod對應的容器時報的錯!

這裡寫圖片描述

從這個問題衍生出個連帶的問題,如下圖:

問題1:
這個問題是在建立ingress rc成功之後,當第一個容器失敗,rc的垃圾機制回收第一次建立停止的容器後,重新啟動的容器。檢視rc對應的pod對應的容器時報的錯!

這裡寫圖片描述

原因:因為ingress中的原始碼的健康檢查的url改成了 /healthz,而官方文件中的yaml中定義的健康檢查的路由是/ingress-controller-healthz,這個url是ingress的自檢url,當超過8次之後如果得到結果還是unhealthy,則會掛掉ingress對應的容器。

解決方法:將yaml中的健康檢查的url改成:/healthz即可。:

readinessProbe:
 httpGet:
 path: /healthz
 port: 80
 scheme: HTTP
 livenessProbe:
 httpGet:
 path: /healthz
 port: 80
 scheme: HTTP
 initialDelaySeconds: 10
 timeoutSeconds: 1

目錄 (Table of Contents)

[TOCM]

概述

用過kubernetes的人都知道,kubernetes的service的網路型別有三種:cluertip,nodeport,loadbanlance,各種型別的作用就不在這裡描述了。如果一個service想向外部暴露服務,有nodeport和loadbanlance型別,但是nodeport型別,你的知道service對應的pod所在的node的ip,而loadbanlance通常需要第三方雲服務商提供支援。如果沒有第三方服務商服務的就沒辦法做了。除此之外還有很多其他的替代方式,以下我主要講解的是通過ingress的方式來實現service的對外服務的暴露。

下載搭建環境所需要的映象

  • gcr.io/google_containers/nginx-ingress-controller:0.8.3 (ingress controller 的映象)
  • gcr.io/google_containers/defaultbackend:1.0 (預設路由的servcie的映象)
  • gcr.io/google_containers/echoserver:1.0 (用於測試ingress的service映象,當然這個你可以換成你自己的service都可以)

說明:由於GFW的原因下載不下來的,都可以到時速雲去下載相應的映象(只要把grc.io換成index.tenxcloud.com就可以了),由於我用的是自己私用映象倉庫,所以之後看到的映象都是我自己tag之後上傳到自己私有映象倉庫的。

配置default-http-bankend

首先便捷default-http-backend.yaml:

apiVersion: v1
kind: ReplicationController
metadata:
 name: default-http-backend
spec:
 replicas: 1
 selector:
 app: default-http-backend
 template:
 metadata:
 labels:
 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: hub.yfcloud.io/google_containers/defaultbackend:1.0
 livenessProbe:
 httpGet:
 path: /healthz
 port: 8080
 scheme: HTTP
 initialDelaySeconds: 30
 timeoutSeconds: 5
 ports:
 - containerPort: 8080
 resources:
 limits:
 cpu: 10m
 memory: 20Mi
 requests:
 cpu: 10m
 memory: 20Mi

然後建立建立default-http-backend的rc:

kubectl create -f default-http-backend .yaml

最後建立default-http-backend的service,有兩種方式建立,一種是:便捷default-http-backend-service.yaml,另一種通過如下命令建立:

kubectl expose rc default-http-backend --port=80 --target-port=8080 --name=default-http-backend

最後檢視相應的rc以及service是否成功建立:然後自己測試能否正常訪問,訪問方式如下,直接通過的pod的ip/healthz或者serive的ip/(如果是srevice的ip加port)

配置inrgess-controller

首先編輯ingress-controller.yaml檔案:

apiVersion: v1
kind: ReplicationController
metadata:
 name: nginx-ingress-controller
 labels:
 k8s-app: nginx-ingress-lb
spec:
 replicas: 1
 selector:
 k8s-app: nginx-ingress-lb
 template:
 metadata:
 labels:
 k8s-app: nginx-ingress-lb
 name: nginx-ingress-lb
 spec:
 terminationGracePeriodSeconds: 60
 containers:
 - image: hub.yfcloud.io/google_containers/nginx-ingress-controller:0.8.3
 name: nginx-ingress-lb
 imagePullPolicy: Always
 readinessProbe:
 httpGet:
 path: /healthz
 port: 80
 scheme: HTTP
 livenessProbe:
 httpGet:
 path: /healthz
 port: 80
 scheme: HTTP
 initialDelaySeconds: 10
 timeoutSeconds: 1 # use downward API
 env:
 - name: POD_NAME
 valueFrom:
 fieldRef:
 fieldPath: metadata.name
 - name: POD_NAMESPACE
 valueFrom:
 fieldRef:
 fieldPath: metadata.namespace
 - name: KUBERNETES_MASTER
 value: http://183.131.19.231:8080
 ports:
 - containerPort: 80
 hostPort: 80
 - containerPort: 443
 hostPort: 443
 args:
 - /nginx-ingress-controller
 - --default-backend-service=$(POD_NAMESPACE)/default-http-backend
 imagePullSecrets:
 - name: hub.yfcloud.io.key

建立ingress-controller的rc:

kubectl create -f ingress-controller.yaml

最後驗證ingress-controller是否正常啟動成功,方法 如下:檢視ingress-controller中對應pod的ip,然後通過ip:80/healthz 訪問,成功的話會返回 ok。

配置需要測試的service

首先編輯測試用的test.yaml:

apiVersion: v1 kind: ReplicationController metadata:
 name: echoheaders
spec:
 replicas: 1
 template:
 metadata:
 labels:
 app: echoheaders
 spec:
 containers:
 - name: echoheaders
 image: hub.yfcloud.io/google_containers/echoserver:test
 ports:
 - containerPort: 8080

測試service的yaml這裡建立多個:
sv-alp-default.yaml:

apiVersion: v1 kind: Service metadata:
 name: echoheaders-default
 labels:
 app: echoheaders
spec:
 type: NodePort
 ports:
 - port: 80
 nodePort: 30302
 targetPort: 8080
 protocol: TCP
 name: http
 selector:
 app: echoheaders

sv-alp-x.yaml:

apiVersion: v1 kind: Service metadata:
 name: echoheaders-x
 labels:
 app: echoheaders
spec:
 type: NodePort
 ports:
 - port: 80
 nodePort: 30301
 targetPort: 8080
 protocol: TCP
 name: http
 selector:
 app: echoheaders

sv-alp-y.yaml:

apiVersion: v1 kind: Service metadata:
 name: echoheaders-y
 labels:
 app: echoheaders
spec:
 type: NodePort
 ports:
 - port: 80
 nodePort: 30284
 targetPort: 8080
 protocol: TCP
 name: http
 selector:
 app: echoheaders

接著是

配置ingress

編輯ingress-alp.yaml:

apiVersion: extensions/v1beta1 kind: Ingress metadata:
 name: echomap
spec:
 rules:
 - host: foo.bar.com
 http:
 paths:
 - path: /foo
 backend:
 serviceName: echoheaders-x
 servicePort: 80
 - host: bar.baz.com
 http:
 paths:
 - path: /bar
 backend:
 serviceName: echoheaders-y
 servicePort: 80
 - path: /foo
 backend:
 serviceName: echoheaders-x
 servicePort: 80

最後測試,測試方法有兩種,如下:

方法一:

curl -v http://nodeip:80/foo -H `host: foo.bar.com`

結果如下:

* About to connect() to 183.131.19.232 port 80 (#0)
* Trying 183.131.19.232...
* Connected to 183.131.19.232 (183.131.19.232) port 80 (#0)
> GET /foo HTTP/1.1
> User-Agent: curl/7.29.0
> Accept: */*
> host: foo.bar.com
> 
< HTTP/1.1 200 OK
< Server: nginx/1.11.3
< Date: Wed, 12 Oct 2016 10:04:40 GMT
< Transfer-Encoding: chunked
< Connection: keep-alive
< 
CLIENT VALUES:
client_address=(`10.1.58.3`, 57364) (10.1.58.3)
command=GET
path=/foo
real path=/foo
query=
request_version=HTTP/1.1

SERVER VALUES:
server_version=BaseHTTP/0.6
sys_version=Python/3.5.0
protocol_version=HTTP/1.0

HEADERS RECEIVED:
Accept=*/*
Connection=close
Host=foo.bar.com
User-Agent=curl/7.29.0
X-Forwarded-For=183.131.19.231
X-Forwarded-Host=foo.bar.com
X-Forwarded-Port=80
X-Forwarded-Proto=http
X-Real-IP=183.131.19.231
* Connection #0 to host 183.131.19.232 left intact

其他路由的測試修改對應的url即可。

**注意:**nodeip是你的ingress-controller所對應的pod所在的node的ip。

方法二:
將訪問url的主機的host中加上:

nodeip foo.bar.com nodeip bar.baz.com

在瀏覽器中直接訪問:

foo.bar.com/foo
bar.baz.com/bar
bar.baz.com/foo

都是可以的。

問題集

在建立ingress-controller的時候報錯(ingress的yaml檔案是官網中的yaml檔案配置,我只改了相對應的映象。):

問題一:

這裡寫圖片描述

以上錯誤資訊是ingress-controller建立失敗的原因,通過docker log 檢視rc中的對應的ingress-controller的容器的日誌。

原因:從錯誤資訊來看是因為ingress內部程式預設是通過localhost:8080連線master的apiserver,如果是單機版的k8s環境,就不會報這個錯,如果是叢集環境,並且你的ingress-controller的pod所對應的容器不是在master節點上(因為有的叢集環境master也是node,這樣的話,如果你的pod對應的容器在master節點上也不會報這個錯),就會報這個錯。

解決方法:在ingress-controller.yaml中加上如下引數,

- name: KUBERNETES_MASTER
 value: http://183.131.19.231:8080

之後的yaml檔案就是如前面定義的yaml檔案。

問題二:

這個問題是在建立ingress rc成功之後,馬上檢視rc對應的pod對應的容器時報的錯!

這裡寫圖片描述

從這個問題衍生出個連帶的問題,如下圖:

問題1:
這個問題是在建立ingress rc成功之後,當第一個容器失敗,rc的垃圾機制回收第一次建立停止的容器後,重新啟動的容器。檢視rc對應的pod對應的容器時報的錯!

這裡寫圖片描述

原因:因為ingress中的原始碼的健康檢查的url改成了 /healthz,而官方文件中的yaml中定義的健康檢查的路由是/ingress-controller-healthz,這個url是ingress的自檢url,當超過8次之後如果得到結果還是unhealthy,則會掛掉ingress對應的容器。

解決方法:將yaml中的健康檢查的url改成:/healthz即可。:

readinessProbe:
 httpGet:
 path: /healthz
 port: 80
 scheme: HTTP
 livenessProbe:
 httpGet:
 path: /healthz
 port: 80
 scheme: HTTP
 initialDelaySeconds: 10
 timeoutSeconds: 1

目錄 (Table of Contents)

[TOCM]

概述

用過kubernetes的人都知道,kubernetes的service的網路型別有三種:cluertip,nodeport,loadbanlance,各種型別的作用就不在這裡描述了。如果一個service想向外部暴露服務,有nodeport和loadbanlance型別,但是nodeport型別,你的知道service對應的pod所在的node的ip,而loadbanlance通常需要第三方雲服務商提供支援。如果沒有第三方服務商服務的就沒辦法做了。除此之外還有很多其他的替代方式,以下我主要講解的是通過ingress的方式來實現service的對外服務的暴露。

下載搭建環境所需要的映象

  • gcr.io/google_containers/nginx-ingress-controller:0.8.3 (ingress controller 的映象)
  • gcr.io/google_containers/defaultbackend:1.0 (預設路由的servcie的映象)
  • gcr.io/google_containers/echoserver:1.0 (用於測試ingress的service映象,當然這個你可以換成你自己的service都可以)

說明:由於GFW的原因下載不下來的,都可以到時速雲去下載相應的映象(只要把grc.io換成index.tenxcloud.com就可以了),由於我用的是自己私用映象倉庫,所以之後看到的映象都是我自己tag之後上傳到自己私有映象倉庫的。

配置default-http-bankend

首先便捷default-http-backend.yaml:

apiVersion: v1
kind: ReplicationController
metadata:
 name: default-http-backend
spec:
 replicas: 1
 selector:
 app: default-http-backend
 template:
 metadata:
 labels:
 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: hub.yfcloud.io/google_containers/defaultbackend:1.0
 livenessProbe:
 httpGet:
 path: /healthz
 port: 8080
 scheme: HTTP
 initialDelaySeconds: 30
 timeoutSeconds: 5
 ports:
 - containerPort: 8080
 resources:
 limits:
 cpu: 10m
 memory: 20Mi
 requests:
 cpu: 10m
 memory: 20Mi

然後建立建立default-http-backend的rc:

kubectl create -f default-http-backend .yaml

最後建立default-http-backend的service,有兩種方式建立,一種是:便捷default-http-backend-service.yaml,另一種通過如下命令建立:

kubectl expose rc default-http-backend --port=80 --target-port=8080 --name=default-http-backend

最後檢視相應的rc以及service是否成功建立:然後自己測試能否正常訪問,訪問方式如下,直接通過的pod的ip/healthz或者serive的ip/(如果是srevice的ip加port)

配置inrgess-controller

首先編輯ingress-controller.yaml檔案:

apiVersion: v1
kind: ReplicationController
metadata:
 name: nginx-ingress-controller
 labels:
 k8s-app: nginx-ingress-lb
spec:
 replicas: 1
 selector:
 k8s-app: nginx-ingress-lb
 template:
 metadata:
 labels:
 k8s-app: nginx-ingress-lb
 name: nginx-ingress-lb
 spec:
 terminationGracePeriodSeconds: 60
 containers:
 - image: hub.yfcloud.io/google_containers/nginx-ingress-controller:0.8.3
 name: nginx-ingress-lb
 imagePullPolicy: Always
 readinessProbe:
 httpGet:
 path: /healthz
 port: 80
 scheme: HTTP
 livenessProbe:
 httpGet:
 path: /healthz
 port: 80
 scheme: HTTP
 initialDelaySeconds: 10
 timeoutSeconds: 1 # use downward API
 env:
 - name: POD_NAME
 valueFrom:
 fieldRef:
 fieldPath: metadata.name
 - name: POD_NAMESPACE
 valueFrom:
 fieldRef:
 fieldPath: metadata.namespace
 - name: KUBERNETES_MASTER
 value: http://183.131.19.231:8080
 ports:
 - containerPort: 80
 hostPort: 80
 - containerPort: 443
 hostPort: 443
 args:
 - /nginx-ingress-controller
 - --default-backend-service=$(POD_NAMESPACE)/default-http-backend
 imagePullSecrets:
 - name: hub.yfcloud.io.key

建立ingress-controller的rc:

kubectl create -f ingress-controller.yaml

最後驗證ingress-controller是否正常啟動成功,方法 如下:檢視ingress-controller中對應pod的ip,然後通過ip:80/healthz 訪問,成功的話會返回 ok。

配置需要測試的service

首先編輯測試用的test.yaml:

apiVersion: v1 kind: ReplicationController metadata:
 name: echoheaders
spec:
 replicas: 1
 template:
 metadata:
 labels:
 app: echoheaders
 spec:
 containers:
 - name: echoheaders
 image: hub.yfcloud.io/google_containers/echoserver:test
 ports:
 - containerPort: 8080

測試service的yaml這裡建立多個:
sv-alp-default.yaml:

apiVersion: v1 kind: Service metadata:
 name: echoheaders-default
 labels:
 app: echoheaders
spec:
 type: NodePort
 ports:
 - port: 80
 nodePort: 30302
 targetPort: 8080
 protocol: TCP
 name: http
 selector:
 app: echoheaders

sv-alp-x.yaml:

apiVersion: v1 kind: Service metadata:
 name: echoheaders-x
 labels:
 app: echoheaders
spec:
 type: NodePort
 ports:
 - port: 80
 nodePort: 30301
 targetPort: 8080
 protocol: TCP
 name: http
 selector:
 app: echoheaders

sv-alp-y.yaml:

apiVersion: v1 kind: Service metadata:
 name: echoheaders-y
 labels:
 app: echoheaders
spec:
 type: NodePort
 ports:
 - port: 80
 nodePort: 30284
 targetPort: 8080
 protocol: TCP
 name: http
 selector:
 app: echoheaders

接著是

配置ingress

編輯ingress-alp.yaml:

apiVersion: extensions/v1beta1 kind: Ingress metadata:
 name: echomap
spec:
 rules:
 - host: foo.bar.com
 http:
 paths:
 - path: /foo
 backend:
 serviceName: echoheaders-x
 servicePort: 80
 - host: bar.baz.com
 http:
 paths:
 - path: /bar
 backend:
 serviceName: echoheaders-y
 servicePort: 80
 - path: /foo
 backend:
 serviceName: echoheaders-x
 servicePort: 80

最後測試,測試方法有兩種,如下:

方法一:

curl -v http://nodeip:80/foo -H `host: foo.bar.com`

結果如下:

* About to connect() to 183.131.19.232 port 80 (#0)
* Trying 183.131.19.232...
* Connected to 183.131.19.232 (183.131.19.232) port 80 (#0)
> GET /foo HTTP/1.1
> User-Agent: curl/7.29.0
> Accept: */*
> host: foo.bar.com
> 
< HTTP/1.1 200 OK
< Server: nginx/1.11.3
< Date: Wed, 12 Oct 2016 10:04:40 GMT
< Transfer-Encoding: chunked
< Connection: keep-alive
< 
CLIENT VALUES:
client_address=(`10.1.58.3`, 57364) (10.1.58.3)
command=GET
path=/foo
real path=/foo
query=
request_version=HTTP/1.1

SERVER VALUES:
server_version=BaseHTTP/0.6
sys_version=Python/3.5.0
protocol_version=HTTP/1.0

HEADERS RECEIVED:
Accept=*/*
Connection=close
Host=foo.bar.com
User-Agent=curl/7.29.0
X-Forwarded-For=183.131.19.231
X-Forwarded-Host=foo.bar.com
X-Forwarded-Port=80
X-Forwarded-Proto=http
X-Real-IP=183.131.19.231
* Connection #0 to host 183.131.19.232 left intact

其他路由的測試修改對應的url即可。

**注意:**nodeip是你的ingress-controller所對應的pod所在的node的ip。

方法二:
將訪問url的主機的host中加上:

nodeip foo.bar.com nodeip bar.baz.com

在瀏覽器中直接訪問:

foo.bar.com/foo
bar.baz.com/bar
bar.baz.com/foo

都是可以的。

問題集

在建立ingress-controller的時候報錯(ingress的yaml檔案是官網中的yaml檔案配置,我只改了相對應的映象。):

問題一:

這裡寫圖片描述

以上錯誤資訊是ingress-controller建立失敗的原因,通過docker log 檢視rc中的對應的ingress-controller的容器的日誌。

原因:從錯誤資訊來看是因為ingress內部程式預設是通過localhost:8080連線master的apiserver,如果是單機版的k8s環境,就不會報這個錯,如果是叢集環境,並且你的ingress-controller的pod所對應的容器不是在master節點上(因為有的叢集環境master也是node,這樣的話,如果你的pod對應的容器在master節點上也不會報這個錯),就會報這個錯。

解決方法:在ingress-controller.yaml中加上如下引數,

- name: KUBERNETES_MASTER
 value: http://183.131.19.231:8080

之後的yaml檔案就是如前面定義的yaml檔案。

問題二:

這個問題是在建立ingress rc成功之後,馬上檢視rc對應的pod對應的容器時報的錯!

這裡寫圖片描述

從這個問題衍生出個連帶的問題,如下圖:

問題1:
這個問題是在建立ingress rc成功之後,當第一個容器失敗,rc的垃圾機制回收第一次建立停止的容器後,重新啟動的容器。檢視rc對應的pod對應的容器時報的錯!

這裡寫圖片描述

原因:因為ingress中的原始碼的健康檢查的url改成了 /healthz,而官方文件中的yaml中定義的健康檢查的路由是/ingress-controller-healthz,這個url是ingress的自檢url,當超過8次之後如果得到結果還是unhealthy,則會掛掉ingress對應的容器。

解決方法:將yaml中的健康檢查的url改成:/healthz即可。:

readinessProbe:
 httpGet:
 path: /healthz
 port: 80
 scheme: HTTP
 livenessProbe:
 httpGet:
 path: /healthz
 port: 80
 scheme: HTTP
 initialDelaySeconds: 10
 timeoutSeconds: 1

本文轉自開源中國-Kubernetes Nginx Ingress 安裝與使用