theboyaply
theboyaply
发布于 2020-03-29 / 1226 阅读
0
0

k8s Ingress介绍

k8s Ingress 介绍

k8s 中文社区:https://www.kubernetes.org.cn/1885.html

官方网站:https://kubernetes.github.io/ingress-nginx/

Github:https://github.com/kubernetes/ingress-nginx

个人理解,Ingress 就是在 k8s 集群中的 Service 上做了一个 ningx 代理。将所有匹配到的请求转发到对应的 Service 中。

替代方案有以下几种:

你可以通过很多种方式暴露 Service 而不必直接使用 Ingress:

安装 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 --


评论