.. _nginx_ingress:
=================================
部署Nginx Ingress Controller
=================================
安装和配置Cert-Manager
========================
使用Helm安装 ``cert-manager`` 实现TLS证书(从 `Let's Encrypt `_ 获取) 以及其他证书授权和管理证书生命期。证书需要配置申明 Ingress Resource 的 ``certmanager.k8s.io/issuer`` ,在Ingress spec中添加一个 ``tls`` 段落,并且配置一个或多个指定证书授权声明。
.. note::
以下安装在 ``kube-system`` namespace 安装 ``cert-manager``
- 安装 ``cert-manager`` CRDs,这个步骤必须在Helm chart安装cert-manager之前完成::
kubectl apply -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.8/deploy/manifests/00-crds.yaml
- 将标签添加到 ``kube-system`` namespace ::
kubectl label namespace kube-system certmanager.k8s.io/disable-validation="true"
.. note::
这里标记安装 ``cert-manager`` 的namespace关闭资源验证。对于一个已经存在的namespace,必须添加上述标签,否则安装 ``cert-manager`` 会失败,报错见下文。
- 添加 `Jetstack Helm repository `_ 到Helm,这个仓库包含了 cert-manager Helm chart ::
helm repo add jetstack https://charts.jetstack.io
- 更新 repo (如果已经存在) ::
helm repo update
- 最后安装 chart 到 ``kube-system`` namespace ::
helm install \
--name cert-manager \
--namespace kube-system \
--version v0.8.1 \
jetstack/cert-manager
.. note::
要验证 ``cert-manager`` 是否安装成功,可以参考 `Cert Manager Quick Start `_ 官方文档
安装 cert-manager 异常排查
-----------------------------
socat命令不存在
~~~~~~~~~~~~~~~~~
在执行安装 ``cert-manager`` 命令报错::
helm install --name cert-manager --namespace kube-system stable/cert-manager
出现报错::
E0619 16:43:00.960750 29826 portforward.go:400] an error occurred forwarding 50374 -> 44134: error forwarding port 44134 to pod f4e5e03b5b5f994784598ca6f91c362aba04ceac3e1ac32560b22413f32a385f, uid : unable to do port forwarding: socat not found.
...
E0619 16:43:39.474973 29826 portforward.go:340] error creating error stream for port 50374 -> 44134: Timeout occured
E0619 16:44:04.599089 29826 portforward.go:362] error creating forwarding stream for port 50374 -> 44134: Timeout occured
这里的报错 ``uid : unable to do port forwarding: socat not found.`` 表示在服务器上没有找到工具命令 ``socat`` (参考 `helm commands error with "socat not found" `_ ) ::
sudo apt install socat
no matches for kind "Certificate"报错
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- 如果忘记先安装 ``cert-manager`` CRDs,则直接安装 ``cert-manager`` 会报错::
Error: validation failed: [unable to recognize "": no matches for kind "Certificate" in version "certmanager.k8s.io/v1alpha1", unable to recognize "": no matches for kind "Issuer" in version "certmanager.k8s.io/v1alpha1"]
这个报错参考 `helm install stable/cert-manager does not work anymore? `_ 介绍,引用 `Step 4 — Installing and Configuring Cert-Manager `_ ,需要在安装 cert-manager 之前,创建 cert-manager CRDs 。
在 `Cert Manager Quick Start `_ 文档 ``Step 5 - Deploy Cert Manager`` 说明,按照以下步骤分布执行:
- 安装 ``cert-manager`` CRDs,这个步骤必须在Helm chart安装cert-manager之前完成::
kubectl apply -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.8/deploy/manifests/00-crds.yaml
镜像下载异常
~~~~~~~~~~~~~
- 安装 ``cert-manager`` 后检查pod发现状态异常::
kubectl get pods -n kube-system -o wide
输出显示::
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
cert-manager-cainjector-5dfd7c584d-sndhr 0/1 ImagePullBackOff 0 14m 172.17.0.11 minikube
cert-manager-dcbb6f5b9-7tzs9 0/1 ImagePullBackOff 0 14m 172.17.0.12 minikube
cert-manager-webhook-f6f965745-svjhc 0/1 ContainerCreating 0 14m minikube
.. note::
当Pod状态是 ``ImagePullBackOff`` 表示和镜像下载有关错误,可以通过 ``kubectl describe pod `` 来查看原因。(参考 `How to debug “ImagePullBackOff”? `_ )
- 检查::
kubectl describe pod cert-manager-dcbb6f5b9-7tzs9 -n kube-system
可以看到输出排查::
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 26m default-scheduler Successfully assigned kube-system/cert-manager-dcbb6f5b9-7tzs9 to minikube
Warning Failed 24m kubelet, minikube Failed to pull image "quay.io/jetstack/cert-manager-controller:v0.8.1": rpc error: code = Unknown desc = Error response from daemon: Get https://quay.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
Warning Failed 24m kubelet, minikube Error: ErrImagePull
Normal BackOff 24m kubelet, minikube Back-off pulling image "quay.io/jetstack/cert-manager-controller:v0.8.1"
Warning Failed 24m kubelet, minikube Error: ImagePullBackOff
Normal Pulling 24m (x2 over 26m) kubelet, minikube Pulling image "quay.io/jetstack/cert-manager-controller:v0.8.1"
这个 ``ImagePullBackOff`` 是因为下载镜像 ``quay.io/jetstack/cert-manager-controller:v0.8.1`` 出现错误导致的。不过,Kubernetes是最终一致性,所以会不断重试下载镜像。如果网络恢复正常,可能过一段实践还是会恢复 ``running`` 正常状态的。
volume "certs"挂载异常
~~~~~~~~~~~~~~~~~~~~~~~
- ``cert-manager-webhook`` 启动遇到无法挂载卷 "certs" 错误::
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 49s default-scheduler Successfully assigned kube-system/cert-manager-webhook-f6f965745-svjhc to minikube
Warning FailedMount 17s (x7 over 49s) kubelet, minikube MountVolume.SetUp failed for volume "certs" : secret "cert-manager-webhook-webhook-tls" not found
参考 `[stable/cert-manager] v0.6.0 fails to install w/ missing webhook tls secret `_ :
**如果在一个已经存在的namespace上部署, "必须确保" 这个namespace具备一个附加的label才能部署成功**
果然,我检查了 ``kube-system`` namespace,发现确实没有加上标签 ``certmanager.k8s.io/disable-validation: "true"`` ,所以补上之前漏掉的命令::
kubectl label namespace kube-system certmanager.k8s.io/disable-validation="true"
然后删除掉异常的pod ``cert-manager-webhook-f6f965745-svjhc`` ::
kubectl delete pod cert-manager-webhook-f6f965745-svjhc -n kube-system
删除以后,Kubernetes会自动重建新的 ``cert-manager-webhook`` ,就能够成功。
.. note::
cert-manager 官方文档采用单独建立 ``cerrt-manager`` namespace (请参考 `Cert Manager Quick Start `_ ),不过,我的部署参考 `How to Set Up an Nginx Ingress with Cert-Manager on DigitalOcean Kubernetes `_ 步骤4 ,将 ``cert-manager`` 安装在 ``kube-system`` namespace,所以执行将标签添加到 ``kube-system`` namespace ::
kubectl label namespace kube-system certmanager.k8s.io/disable-validation="true"
参考
=======
- `NGINX Ingress Controller Installation Guide `_
- `How to Set Up an Nginx Ingress with Cert-Manager on DigitalOcean Kubernetes `_