本文由ilanniweb微信公众号提供友情赞助,首发于烂泥行天下

IT技术分享QQ群:571981257

最近一直在学习有关k8s相关的知识,中间的坑比较多,今天就把有关ingress的安装介绍下。

有关k8s的安装,我这边使用的kubeasz这个项目进行安装的。kubeasz是一个基于二进制方式、利用ansible-playbook实现自动化部署k8s的项目,项目地址为:

https://github.com/gjmzj/kubeasz

clip_image001

如果觉得下载比较慢的话,也可以从可下面这个地址下载:

https://gitee.com/ilanni/kubeasz

在部署过程使用到的二进制文件,由于是在百度网盘中,众所周知的原因,下载速度就不需要多说了。为了提高下载速度,我这边把已经下载镜像文件上传到了阿里云的cdn上,下载地址如下:

https://ilanni.ctfile.com/fs/15323800-325473895

由于其中的镜像会和kubeasz的镜像进行更新,为了保持上述连接的稳定,所以该链接会先跳转到一个页面,下载其中的一个文件,然后该文件中有实际的镜像下载地址。

这其中包含k8s相关的镜像,以及harbor的离线安装包。

一、ingress介绍

K8s集群对外暴露服务的方式目前只有三种:loadblancer、nodeport、ingress。前两种熟悉起来比较快,而且使用起来也比较方便,在此就不进行介绍了。

下面详细讲解下ingress这个服务,ingress由两部分组成:ingress controller和ingress服务。

其中ingress controller目前主要有两种:基于nginx服务的ingress controller和基于traefik的ingress controller。

而其中traefik的ingress controller,目前支持http和https协议。由于对nginx比较熟悉,而且需要使用TCP负载,所以在此我们选择的是基于nginx服务的ingress controller。

但是基于nginx服务的ingress controller根据不同的开发公司,又分为k8s社区的ingres-nginx和nginx公司的nginx-ingress。

在此根据github上的活跃度和关注人数,我们选择的是k8s社区的ingres-nginx。

k8s社区提供的ingress,github地址如下:

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

clip_image002

nginx社区提供的ingress,github地址如下:

https://github.com/nginxinc/kubernetes-ingress

clip_image003

有关nginx社区提供的ingress使用方式,我们会在后续的文章中介绍。

二、ingress的工作原理

ingress具体的工作原理如下:

ingress contronler通过与k8s的api进行交互,动态的去感知k8s集群中ingress服务规则的变化,然后读取它,并按照定义的ingress规则,转发到k8s集群中对应的service。

而这个ingress规则写明了哪个域名对应k8s集群中的哪个service,然后再根据ingress-controller中的nginx配置模板,生成一段对应的nginx配置。

然后再把该配置动态的写到ingress-controller的pod里,该ingress-controller的pod里面运行着一个nginx服务,控制器会把生成的nginx配置写入到nginx的配置文件中,然后reload一下,使其配置生效。以此来达到域名分配置及动态更新的效果。

三、拉取镜像

为了本次试验,我们需要使用到httpd:alpine、tomcat:alpine和nginx-ingress-controller:0.21.0这三个镜像。

拉取镜像,使用如下命令:

docker pull httpd:alpine

docker pull tomcat:alpine

clip_image004

拉取nginx-controller镜像如下:

docker pull quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.21.0

或者

docker pull registry.cn-hangzhou.aliyuncs.com/ilanni/nginx-ingress-controller:0.21.0

clip_image005

镜像拉取完毕后,我们开始进行其他操作。

四、基础试验配置

为了进行本次试验,我们首先要从头配置相关的信息。

4.1 创建namespace

k8s中是通过namespace进行资源隔离的,所以在此我们先要创建一个namespace,命名为ilanni-namespace。使用如下命令:

cat > ilanni_namespace.yml << "EOF"

apiVersion: v1

kind: Namespace

metadata:

name: ilanni-namespace

labels:

name: ilanni-namespace

EOF

clip_image006

执行如下命令:

kubectl apply -f ilanni-namespace.yml --record

clip_image007

查询刚刚创建的namespace,使用如下命令:

kubectl get ns

clip_image008

通过上图,我们可以很明显的看到ilanni-namespace,这个namespace已经创建成功。

当然也可以,直接使用kubectl create ns ilanni-namespace命令进行创建。

4.2 创建service

Namespace创建完毕后,我们就可以在这个namespace下创建service。使用如下命令:

cat > ilanni-httpd-service.yml << "EOF"

apiVersion: v1

kind: Service

metadata:

name: ilanni-httpd-svc

namespace: ilanni-namespace

spec:

type: NodePort

ports:

- name: http-port

nodePort: 28080

port: 80

targetPort: 80

selector:

app: ilanni-httpd-dm

EOF

clip_image009

在ilanni-httpd-service.yml这个k8s的yml文件中,我们在ilanni-namespace这个namespace中,定义一个名为ilanni-httpd-svc的Service,并且使用NodePort这个service类型,使用28080端口对外提供访问端口。

同时这个yml文件中,我们也使用selector来选择后端的Deployment,在此我们选择的是ilanni-httpd-dm,这个Deployment。

现在执行kubectl apply命令使该文件生效,如下:

kubectl apply -f ilanni-httpd-service.yml --record

kubectl get svc -n ilanni-namespace -o wide

clip_image010

通过上图,我们可以很明显的看出ilanni-httpd-svc这个service分配的IP地址为10.68.184.223.

注意:上述IP地址k8s集群内部的地址。外部是无法访问的。

以上service创建完毕后,我们就要创建deployment。

4.3 创建deployment

现在我们来创建deployment,命令如下:

cat > ilanni-httpd-deployment.yml << "EOF"

apiVersion: extensions/v1beta1

kind: Deployment

metadata:

name: ilanni-httpd

namespace: ilanni-namespace

spec:

replicas: 2

revisionHistoryLimit: 5

strategy:

type: RollingUpdate

#由于replicas为2,则整个升级,pod个数在1-3个之间

rollingUpdate:

##滚动升级时会先启动1个pod

maxSurge: 1

##滚动升级时允许的最大Unavailable的pod个数

maxUnavailable: 0

template:

metadata:

labels:

app: ilanni-httpd-dm

spec:

##k8s将会给应用发送SIGTERM信号,可以用来正确、优雅地关闭应用,默认为30秒

terminationGracePeriodSeconds: 60

restartPolicy: Always

containers:

- name: ilanni-httpd

image: httpd:alpine

imagePullPolicy: Always

EOF

clip_image011

在ilanni-httpd-deployment.yml这个k8s的yml文件中,我们在ilanni-namespace这个namespace中,定义一个名为ilanni-httpd的Deployment,并且定义了一个ilanni-httpd-dm的labels。

这样ilanni-httpd-svc这个Service就和ilanni-httpd这个Deployment关联起来了。

同时在这个yml文件中,我们也定义了该pod的发布策略,以及副本集个数。

现在执行kubectl apply命令使该文件生效,如下:

kubectl apply -f ilanni-httpd-deployment.yml --record

kubectl get deploy -n ilanni-namespace -o wide

clip_image012

上述截图中,可以很明显的看出我们通过yml文件定义的相关信息。

4.4 查看pod

Deployment部署完毕后,相应的pod也正常启动。现在我们来看下pod的运行情况如下,使用如下命令:

kubectl get pod -n ilanni-namespace -o wide

clip_image013

通过上图,我们可以很明显的看出目前有两个ilanni-httpd pod运行在192.168.123.6和192.168.123.7节点,而且pod里面的IP地址也分别是172.20.3.18和172.20.1.15。

这里面需要注意下每个pod所被分配的IP地址,是根据该pod所在node节点cni0网卡的IP地址段来分配的

我们现在可以查看192.168.123.7这个node节点的cni0网卡的IP地址段,如下:

clip_image014

通过上图,我们很明显的看出在192.168.123.7上的cni0网卡的IP地址段为172.20.1.1/24,那么该node节点上的pod说分配的ip地址也是172.20.1.1/24网段的。

当然这里面牵涉到有关k8s网络部分,暂时不做详细讲解。因为这块我也是在学习中,后续小伙伴们可以多多交流。

4.5 查看node节点

Pod查看完毕后,我们再切换到node节点上,查看具体的docker容器。使用如下命令:

docker ps

clip_image015

通过上图,我们可以很明显的看出每个pod在node节点上都会启动两个docker容器:一个pod本身的docker容器,一个是pod运行时所使用的网络docker容器。

我们再来查看下,该node上所启动的端口,使用如下命令:

netstat -tunlp

clip_image016

通过上图,我们可以很明显的看出node节点已经监听了我们在ilanni-httpd-service.yml文件中配置的ilanni-httpd-svc的NodePort对外的映射端口28080。

4.6 访问httpd

现在我们要从外部访问ilanni-httpd-svc,使用对外映射的端口28080,如下:

http://192.168.123.6:28080/

clip_image017

通过上图,我们可以很明显的看出,ilanni-httpd-svc这个service已经正常对外提供服务,说明我们以上的操作都是正常的。

4.7 yml文件合成(可选)

上述有关namespace、service、deployment的创建,我们都是各自使用一个文件的,也可以合成到一起,作为一个yml文件。如下:

cat > httpd-deployment.yml << "EOF"

apiVersion: v1

kind: Namespace

metadata:

name: ilanni-namespace

labels:

name: ilanni-namespace

---

apiVersion: v1

kind: Service

metadata:

name: ilanni-httpd-svc

namespace: ilanni-namespace

spec:

type: NodePort

ports:

- name: http-port

nodePort: 28080

port: 80

targetPort: 80

selector:

app: ilanni-httpd-dm

---

apiVersion: extensions/v1beta1

kind: Deployment

metadata:

name: ilanni-httpd

namespace: ilanni-namespace

spec:

replicas: 2

revisionHistoryLimit: 5

strategy:

type: RollingUpdate

#由于replicas为2,则整个升级,pod个数在1-3个之间

rollingUpdate:

##滚动升级时会先启动1个pod

maxSurge: 1

##滚动升级时允许的最大Unavailable的pod个数

maxUnavailable: 0

template:

metadata:

labels:

app: ilanni-httpd-dm

spec:

##k8s将会给应用发送SIGTERM信号,可以用来正确、优雅地关闭应用,默认为30秒

terminationGracePeriodSeconds: 60

restartPolicy: Always

containers:

- name: ilanni-httpd

image: httpd:alpine

imagePullPolicy: Always

EOF

clip_image018

clip_image019

因为在本次试验中,我们还使用到另外一个pod tomcat,所以在此也把tomcat相关的yml文件列出来,如下:

cat > tomcat-deployment.yml << "EOF"

apiVersion: v1

kind: Service

metadata:

name: ilanni-tomcat-svc

namespace: ilanni-namespace

spec:

type: NodePort

ports:

- name: http-port

nodePort: 28181

port: 8080

targetPort: 8080

selector:

app: ilanni-tomcat-dm

---

apiVersion: extensions/v1beta1

kind: Deployment

metadata:

name: ilanni-tomcat

namespace: ilanni-namespace

spec:

replicas: 2

revisionHistoryLimit: 5

strategy:

type: RollingUpdate

#由于replicas为2,则整个升级,pod个数在1-3个之间

rollingUpdate:

#滚动升级时会先启动1个pod

maxSurge: 1

#滚动升级时允许的最大Unavailable的pod个数

maxUnavailable: 0

template:

metadata:

labels:

app: ilanni-tomcat-dm

spec:

#k8s将会给应用发送SIGTERM信号,可以用来正确、优雅地关闭应用,默认为30秒

terminationGracePeriodSeconds: 60

restartPolicy: Always

containers:

- name: ilanni-tomcat

image: tomcat:alpine

imagePullPolicy: Always

EOF

clip_image020

文章写了这么多,还没有引出我们今天的主角ingress是不是有点疑问。

那么,下面我们就来正式引入。

在第4.6章节中,我们介绍了访问httpd服务的方法,我们是通过kubectl get pod -n ilanni-namespace -o wide命令查看httpd的pod运行在192.168.123.6和192.168.123.7这两个node节点上。

同时,我们也使用NodePort方式使ilanni-httpd-svc的service对外映射28080端口。

那么问题来了,如果我们有10个node节点,那么此时httpd的pod会在哪一个node节点上运行呢?如果我们再次使用相关命令查看到该pod运行节点,那么下次、下下次呢?

为了我们无感知的访问后端应用,那么我们就可以使用ingress了。

有关ingress的具体工作过程,可以查看第一、二章节。

注意:service、deployment、ingress是区分namespace的。

五、安装和配置ingress-controller

现在我们开始安装和配置ingress-controller,如下。

5.1 下载mandatory.yml

k8s社区提供的ingress,github地址如下:

https://github.com/kubernetes/ingress-nginx/tree/master/deploy

clip_image021

在此我们需要下载mandatory.yaml文件,使用如下命令:

wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/mandatory.yaml

clip_image022

5.2 启用hostNetwork网络

hostNetwork网络,这是一种直接定义Pod网络的方式。

如果在Pod中使用hostNetwork:true配置网络,那么Pod中运行的应用程序可以直接使用node节点的端口,这样node节点主机所在网络的其他主机,都可以通过该端口访问到此应用程序。

启用hostNetwork网络,我们只需在mandatory.yaml文件添加hostNetwork: true即可。如下:

clip_image023

5.3 查看ingress-controller监听端口

我们可以通过mandatory.yaml文件,查看ingress-controller默认的监听端口,如下:

clip_image024

当然我们也可以很明显的看出,nginx-ingress-controller默认负载的是http协议。

如果是要负载TCP协议的话,我们需要单独另外配置,这个我会在后期的文章中进行介绍。

5.4 指定运行节点

nginx-ingress-controller会随意选择一个node节点运行pod,为此需要我们把nginx-ingress-controller运行到指定的node节点上。

首先需要给需要运行nginx-ingress-controller的node节点打标签,在此我们把nginx-ingress-controller运行在192.168.123.7这个node节点上。

给192.168.123.7这个node节点打标签,使用如下命令:

kubectl label node 192.168.123.7 nginx=nginx

kubectl get nodes --show-labels

clip_image025

5.5 修改mandatory.yaml文件

为了让nginx-ingress-controller运行到指定的node节点上,还需要我们修改mandatory.yaml文件。

mandatory.yaml文件中只需要增加如下内容:

nodeSelector:

nginx: "nginx"

clip_image026

5.6 添加ingress service文件

默认情况ingress nginx是没有添加service资源的,不添加service资源也是可以的,但是在ingress nginx的pod日志里面会报找不到相应的service。如下:

clip_image027

添加ingress service文件,使用如下命令:

cat > mandatory-service.yaml << "EOF"

apiVersion: v1

kind: Service

metadata:

name: ingress-nginx

namespace: ingress-nginx

spec:

type: NodePort

ports:

- name: http

port: 80

targetPort: 80

- name: https

port: 443

targetPort: 443

selector:

app: ingress-nginx

EOF

clip_image028

5.7 应用mandatory.yaml文件

mandatory.yaml文件修改完毕后,我们现在来应用该文件,使用如下命令:

kubectl apply -f mandatory.yaml

kubectl apply -f mandatory-service.yaml

clip_image029

查看nginx-ingress-controller运行的node节点,使用如下命令:

kubectl get pod -n ingress-nginx -o wide

clip_image030

通过上图,我们很明显的看出nginx-ingress-controller确实运行在192.168.123.7这个node节点上。

5.8 查看相关资源

查看创建的namespace,使用如下命令:

kubectl get ns

clip_image031

查看创建的cm, deploy ,pod,如下:

kubectl get cm,deploy,pod -n ingress-nginx -o wide

clip_image032

查看创建的service,如下:

kubectl get svc -n ingress-nginx -o wide

clip_image033

登录到192.168.123.6这个node节点上,进行查看端口如下:

netstat -tunlp

clip_image034

通过上图,我们可以很明显的看出,192.168.123.6这个node节点,已经监听了80和443端口。

其他node节点也是如此进行操作查看即可。

5.9 查看nginx-ingress-controller

现在我们进入nginx-ingress-controller的pod里面,查看下nginx的具体配置,使用如下命令:

kubectl exec -it -n ingress-nginx nginx-ingress-controller-fb47ff79d-bqh5p bash

clip_image035

clip_image036

clip_image037

当然我们也可以不进入pod进行查看,命令如下:

kubectl exec -it -n ingress-nginx nginx-ingress-controller-65755c776f-drztq -- cat nginx.conf

clip_image038

通过上图,我们可以很明显的看出nginx-ingress-controller,实质是nginx与lua脚本的集成,这点和openresty比较类似。

六、创建ingress规则

nginx-ingress-controller创建完毕后,我们再来创建针对具体service的ingress。

现在我们针对ilanni-namespace下的ilanni-httpd-svc和ilanni-tomcat-svc这两个service进行负载。

具体的ingrees文件如下:

cat > ingress_example.yml << "EOF"

apiVersion: v1

kind: List

items:

- apiVersion: extensions/v1beta1

kind: Ingress

metadata:

name: ilanni-ingress

namespace: ilanni-namespace

annotations:

nginx.ingress.kubernetes.io/rewrite-target: /

spec:

rules:

- host: ingress.ilanni.com

http:

paths:

- path: /

backend:

serviceName: ilanni-httpd-svc

servicePort: 80

- path: /tomcat

backend:

serviceName: ilanni-tomcat-svc

servicePort: 8080

EOF

clip_image039

上图中,我们定义了ingress.ilanni.com这个域名,根目录/访问的是ilanni-httpd-svc这个service的80端口,注意该端口也是ilanni-httpd-svc后端pod的容器端口。

子目录tomcat访问的是ilanni-tomcat-svc这个service的8080端口,注意该端口也是ilanni-tomcat-svc后端pod的容器端口。

应用该文件,使用如下命令:

kubectl apply -f ingress_example.yml

kubectl get ing -n ilanni-namespace

clip_image040

查看ingress的相关信息,如下:

kubectl get ing -n ilanni-namespace

kubectl describe ing -n ilanni-namespace ilanni-ingress

clip_image041

通过上图,我们已经很明显的看出我们定义的ingress规则。

七、访问ingress

现在我们来访问ingress定义的域名,如下:

clip_image042

clip_image043

通过以上两张图,我们可以很明显的看出,我们自定义的ingress规则已经生效。

访问ingress.ilanni.com根目录会访问把请求分发到ilanni-httpd-svc这个service。

访问ingress.ilanni.com子目录tomcat会访问把请求分发到ilanni-tomcat-svc这个service。

注意:上述域名我们把它解析到192.168.123.7这个node节点上的。

为什么这样操作?就是因为在5.4章节中,我们把nginx-ingress-controller运行到了该节点上。

如果我们后续要做ingress的高可用的话,要可以通过这种方式。把nginx-ingress-controller运行到指定的几个node节点上,然后再把这几个node节点加入到lb中,然后对应的域名解析到该lb即可实现ingress的高可用。

八、查看nginx-ingress-controller

现在我们来查看nginx-ingress-controller的nginx配置文件,如下:

kubectl exec -it -n ingress-nginx nginx-ingress-controller-65755c776f-drztq -- cat nginx.conf

clip_image044

clip_image045

通过上图,我们可以很明显的看出ingress果真是修改nginx的配置文件。

现在来查看nginx-ingress-controller的pod的日志,使用如下命令:

kubectl logs -f -n ingress-nginx nginx-ingress-controller-788fd6764d-6fjwq

clip_image046

通过上图,我们可以很明显的,刚刚我们的访问被分发到后端对应的service上。

现在我们再来查看对应service的后端pod日志,如下:

kubectl logs -f -n ilanni-namespace ilanni-httpd-84c7fdd8b-db882

clip_image047

到此有关ingress的http负载已经完毕了。在此所有使用的yml文件可以点我下载


--Posted from Rpc

转载于:https://my.oschina.net/lanni654321/blog/3048477

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐