k8s Ingress 介绍
k8s 中文社区:https://www.kubernetes.org.cn/1885.html
个人理解,Ingress 就是在 k8s 集群中的 Service 上做了一个 ningx 代理。将所有匹配到的请求转发到对应的 Service 中。
替代方案有以下几种:
你可以通过很多种方式暴露 Service 而不必直接使用 Ingress:
- 使用 Service.Type=LoadBalancer
- 使用 Service.Type=NodePort
- 使用 Port Proxy
- 部署一个 Service loadbalancer 这允许你在多个service之间共享单个IP,并通过Service Annotations实现更高级的负载平衡。
安装 Ingress-nginx
官方网站 是直接使用 kubectl apply -f url
的方式,这里我把这个步骤拆分执行:
# 下载 mandatory.yaml 。--no-check-certificate:避免“无法建立 SSL 连接”错误
[root@k8s-node01 ~]# wget --no-check-certificate https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/mandatory.yaml
......
已发出 HTTP 请求,正在等待回应... 200 OK
长度:6635 (6.5K) [text/plain]
正在保存至: “mandatory.yaml”
100%[=====================>] 6,635 --.-K/s 用时 0s
2020-03-29 19:57:56 (52.1 MB/s) - 已保存 “mandatory.yaml” [6635/6635])
# 查看需要的镜像
[root@k8s-node01 ~]# cat mandatory.yaml | grep image
image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.30.0
# 在每个集群节点中拉取 docker 镜像。
# 创建 Pod(这里如果出错,请参考“权限解决”)
[root@k8s-node01 ~]# kubectl apply -f mandatory.yaml
# 查看 Pod。注意 命令空间是:ingress-nginx
[root@k8s-master01 ingress]# kubectl get pod -n ingress-nginx
NAME READY STATUS RESTARTS AGE
nginx-ingress-controller-5b56f9fdf8-5sjpp 1/1 Running 0 80s
# 下载 service-nodeport.yaml
[root@k8s-master01 ingress]# wget --no-check-certificate https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/provider/baremetal/service-nodeport.yaml
# 创建 svc
[root@k8s-master01 ingress]# kubectl apply -f service-nodeport.yaml
service/ingress-nginx created
# 查看 svc
[root@k8s-master01 ingress]# kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx NodePort 10.106.6.157 <none> 80:30874/TCP,443:30934/TCP 9s
权限问题解决
如果查看 Pod 发现以下错误,可以修改 mandatory.yaml 文件,将里面的 spec.template.spec.containers.securityContext.runAsUser
的值由 101
改为 33
,然后重新创建 Pod 即可。
参考:https://blog.csdn.net/ht1032279753/article/details/103867138
# 查看 Pod,其状态为:CrashLoopBackOff
[root@k8s-master01 ingress]# kubectl get pod -n ingress-nginx
NAME READY STATUS RESTARTS AGE
nginx-ingress-controller-7f8c79cc8d-9qfq6 0/1 CrashLoopBackOff 5 5m31s
# 查看日志
[root@k8s-master01 ingress]# kubectl log nginx-ingress-controller-7f8c79cc8d-9qfq6 -n ingress-nginx
log is DEPRECATED and will be removed in a future version. Use logs instead.
-------------------------------------------------------------------------------
NGINX Ingress controller
Release: 0.25.0
Build: git-1387f7b7e
Repository: https://github.com/kubernetes/ingress-nginx
-------------------------------------------------------------------------------
W0329 12:12:27.799109 6 flags.go:221] SSL certificate chain completion is disabled (--enable-ssl-chain-completion=false)
nginx version: openresty/1.15.8.1
W0329 12:12:27.804684 6 client_config.go:541] Neither --kubeconfig nor --master was specified. Using the inClusterConfig. This might not work.
I0329 12:12:27.804949 6 main.go:183] Creating API client for https://10.96.0.1:443
I0329 12:12:27.817104 6 main.go:227] Running in Kubernetes cluster version v1.15 (v1.15.1) - git (clean) commit 4485c6f18cee9a5d3c3b4e523bd27972b1b53892 - platform linux/amd64
F0329 12:12:28.424666 6 ssl.go:383] unexpected error storing fake SSL Cert: could not create PEM certificate file /etc/ingress-controller/ssl/default-fake-certificate.pem: open /etc/ingress-controller/ssl/default-fake-certificate.pem: permission denied
示例
更多示例可参考:https://www.kubernetes.org.cn/1885.html
HTTP 代理访问
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
template:
metadata:
labels:
app: nginx-app
spec:
containers:
- name: nginx-container
image: hub.xixihaha.com/library/mynginx:v1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
selector:
app: nginx-app
ports:
- port: 80
targetPort: 80
protocol: TCP
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx-ing
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /
backend:
serviceName: nginx-svc
servicePort: 80
上面的资源清单定义了 deployment、svc、ingress。
执行以下操作:
# 将上面资源清单保存并执行
[root@k8s-master01 ingress]# kubectl apply -f ing-http.yaml
[root@k8s-master01 ingress]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deployment-7796b9c74d-7f8tw 1/1 Running 0 8m19s
nginx-deployment-7796b9c74d-fgnpv 1/1 Running 0 8m19s
nginx-deployment-7796b9c74d-spf2c 1/1 Running 0 8m19s
[root@k8s-master01 ingress]# kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 3/3 3 3 8m23s
[root@k8s-master01 ingress]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 11d
nginx-svc ClusterIP 10.97.213.71 <none> 80/TCP 8m26s
[root@k8s-master01 ingress]# kubectl get ing
NAME HOSTS ADDRESS PORTS AGE
nginx-ing foo.bar.com 80 7m45s
可以看到资源清单中的所有资源都被创建出来了,那么我们现在可以通过 foo.bar.com
这个域名来访问到我们的应用服务。
需要注意的是域名的端口不是 80,而是 ingress-nginx 的暴露出来的端口,即:
[root@k8s-master01 ingress]# kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx NodePort 10.106.6.157 <none> 80:30874/TCP,443:30934/TCP 24m
HTTPS 代理访问
创建证书,以 cert 存储方式
# 生成证书文件
[root@k8s-master01 ingress]# openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginxsvc /O=nginxsvc"
Generating a 2048 bit RSA private key
.......................+++
....................+++
writing new private key to 'tls.key'
-----
[root@k8s-master01 ingress]# ls
tls.crt tls.key
# 创建secret
[root@k8s-master01 ingress]# kubectl create secret tls tls-secret --key tls.key --cert tls.crt
secret/tls-secret created
# 查看 secret
[root@k8s-master01 ingress]# kubectl get secret
NAME TYPE DATA AGE
default-token-5997c kubernetes.io/service-account-token 3 11d
tls-secret kubernetes.io/tls 2 6s
创建 ingress
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx-https-ing
spec:
tls:
- hosts:
- foo.bar.com
secretName: tls-secret
rules:
- host: foo.bar.com
http:
paths:
- path: /
backend:
serviceName: nginx-svc
servicePort: 80
创建 ingress:
kubectl apply -f nginx-https-ing.yaml
完成之后便可以使用 https 方式访问 foo.bar.com。
需要注意的是域名的端口为 ingress-nginx 的 svc https 端口:
[root@k8s-master01 ingress]# kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx NodePort 10.106.6.157 <none> 80:30874/TCP,443:30934/TCP 63m
BasicAuth 认证
也就是访问某个域名的时候需要进行账号密码认证。
创建证书
# 安装 httpd
[root@k8s-master01 ingress]# yum -y install httpd
......
已安装:
httpd.x86_64 0:2.4.6-90.el7.centos
作为依赖被安装:
apr.x86_64 0:1.4.8-5.el7 apr-util.x86_64 0:1.5.2-6.el7 httpd-tools.x86_64 0:2.4.6-90.el7.centos mailcap.noarch 0:2.1.41-2.el7
完毕!
# 创建认证账户
[root@k8s-master01 ingress]# htpasswd -c auth foo
New password:
Re-type new password:
Adding password for user foo
# 创建 Secret
[root@k8s-master01 ingress]# kubectl create secret generic basic-auth --from-file=auth
secret/basic-auth created
# 查看 secret
[root@k8s-master01 ingress]# kubectl get secret
NAME TYPE DATA AGE
basic-auth Opaque 1 5m36s
default-token-5997c kubernetes.io/service-account-token 3 11d
创建 ingress
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: auth-ing
annotations:
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/auth-secret: basic-auth
nginx.ingress.kubernetes.io/auth-realm: 'Authenticasion Required - foo'
spec:
rules:
- host: auth.bar.com
http:
paths:
- path: /
backend:
serviceName: nginx-svc
servicePort: 80
创建 ingress:
[root@k8s-master01 ingress]# kubectl apply -f auth-ing.yaml
ingress.extensions/auth-ing created
[root@k8s-master01 ingress]# kubectl get ing
NAME HOSTS ADDRESS PORTS AGE
auth-ing auth.bar.com 80 4s
现在访问 auth.bar.com
这个域名就需要输入账号密码了。
值得注意的是,访问时使用的是 http 协议,端口为 ingress-nginx 的暴露出来的端口,即:
[root@k8s-master01 ingress]# kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx NodePort 10.106.6.157 <none> 80:30874/TCP,443:30934/TCP 24m
查看 nginx 代理配置
文章开头提到过,我个人理解 Ingress 就是在 k8s 集群中的 Service 上做了一个 ningx 代理。将所有匹配到的请求转发到对应的 Service 中。
在我们创建了 ingress 之后,我们可以进入 ingress-controller 这个 Pod 查看里面的 nginx.conf 配置,其实就是将我们在资源清单中编写的规则写入到了这里面。
# 查看 ingress-controller pod
[root@k8s-master01 ingress]# kubectl get pod -n ingress-nginx
NAME READY STATUS RESTARTS AGE
nginx-ingress-controller-5b56f9fdf8-5sjpp 1/1 Running 0 59m
# 进入到 pod 中
[root@k8s-master01 ingress]# kubectl exec nginx-ingress-controller-5b56f9fdf8-5sjpp -n ingress-nginx -it /bin/bash
# 查看里面的 /etc/nginx/nginx.conf 文件
www-data@nginx-ingress-controller-5b56f9fdf8-5sjpp:/etc/nginx$ cat /etc/nginx/nginx.conf
-- end --