0%

引言

自上一篇文章【K8s 集群搭建系列(三)K8s 启动】 到现在已经过去很长时间了,而本篇文章在很早之前就该发布,但是每次写了开头都放弃了。因为我觉得作为普通使用者,其实没必要去折腾,能用就可以了。但是还是想把之前的折腾经历分享出来,算是作个记录吧。Istio 安装很简单,但是本地使用的话,由于没有 EXTERNAL-IP,所以需要通过 NodePort 等方式暴露,我觉得不太好。如果能通过域名的方式访问,那就比较完美了。但是本地安装可不可以做到呢?我们回想一下 K8s 使用 ingress-nginx 不就是这样嘛,如果用 ingress-nginx 将流量引入到 Istio gateway 那么应该就可以了,那至于行不行呢,我们实践一下!

版本

  • K8s 版本:v1.19.0
  • Istio 版本:1.8.1
  • ingress-nginx 版本:3.19.0
  • 域名 my.k8s.com 指向了 K8s Master 节点宿主机 ip,这里需要配置一下 hosts

准备测试服务

在开始之前,我们先安装个 web 服务供测试,为了简单起见,我们就装个 nginx 吧!

创建命名空间

1
kubectl create ns test  

安装 yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
kubectl apply -f -<<EOF 
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
namespace: test
labels:
app: nginx
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: nginx
version: v1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.19.2
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx
namespace: test
labels:
app: nginx
spec:
type: ClusterIP
selector:
app: nginx
ports:
- name: http
port: 80
targetPort: 80

EOF

安装好 nginx 对应的 pod 跟 service 之后,我们接下来需要安装 nginx-ingress 将 nginx 暴露出来。

安装 ingress-nginx

配置文件修改

下载 ingress-nginx 并解压之后,我们需要修改一下它的配置文件,即:value.yaml。主要涉及的内容如下:

  • 主机网络模式开启,这样就能够通过主机 ip 访问它

    1
    hostNetwork: true
  • 我们需要将它安装到主节点,所以需要看下主节点的污点

    1
    kubectl describe node master

    拿到它的污点:

  • 修改 value.yaml 文件中关于 ingress-nginx 的容忍度

    1
    2
    3
    4
    tolerations: 
    - key: "node-role.kubernetes.io/master"
    operator: "Exists"
    effect: "NoSchedule"
  • 即使配置了容忍度也不能保证百分百调度到主节点,只是说有机会调度到主节点。接下来需要配置节点选择器,让它往主节点调度

    1
    2
    3
    nodeSelector: {
    kubernetes.io/hostname: master
    }

    必要的参数已经配好,接下来我们就可以安装了!

    安装 controller

    我这里通过 helm 进行安装,安装到 web 服务对应的命名空间下(只是为了测试我们的 web 服务是否可用)

    1
    helm install -n test ingress-nginx ingress-nginx-3.19.0

配置 ingress-nginx 访问规则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
kubectl apply -f -<<EOF 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
namespace: test
spec:
rules:
- host: "my.k8s.com"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx
port:
number: 80
EOF

查看是否畅通

至此,说明我们的测试项目跑起来了。只不过是通过 ingress-nginx 访问的方式,接下来,我们要通过 Istio 用同样的域名方式访问。好,现在就可以卸载 ingress-nginx 了,只不过稍后会再装回来。

卸载 ingress-nginx

1
helm uninstall ingress-nginx -n test

删除 ingress 资源

1
kubectl delete ing -n test nginx-ingress  

安装 Istio

直接去 【GitHub】 上下载压缩包,然后解压配置 istioctl 命令的环境变量即可。

安装默认的配置就可以了

1
istioctl install --set profile=default -y

安装成功之后,我们看下它的 pod:

1
2
3
4
5
kubectl get po -n istio-system   
---
NAME READY STATUS RESTARTS AGE
istio-ingressgateway-64589668d7-tmvld 1/1 Running 0 99s
istiod-5d744fdd4f-969js 1/1 Running 0 106s

看到了熟悉的 istio-ingressgateway-64589668d7-tmvld ,之所以熟悉是因为它也是个 ingress。那么这样就好办了。

安装 ingress-nginx

我们再一次安装 ingress-nginx,只不过我们把它放到 istio-system 命名空间中。

1
helm install -n istio-system ingress-nginx ingress-nginx-3.19.0

配置 ingress 规则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
kubectl apply -f -<<EOF 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
namespace: istio-system
spec:
defaultBackend:
service:
name: istio-ingressgateway
port:
number: 80
EOF

📚 Tips

如上 ingress 配置,我们只添加了一个 defaultBackend,也就是说,所有的流量全部引进来,并把该流量指给网关 istio-ingressgateway。同时还要注意,该 ingress 的命名空间同 gateway。

配置 gateway

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
kubectl apply -f -<<EOF 
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: k8s-gateway
namespace: istio-system
spec:
servers:
- hosts:
- '*'
port:
number: 80
name: http
protocol: HTTP

EOF

📚 Tips

让网关接管所有流量,即:域名 * 的。

配置 virtual service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
kubectl apply -f -<<EOF 
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: nginx
namespace: test
spec:
gateways:
- k8s-gateway.istio-system.svc.cluster.local
- mesh
hosts:
- my.k8s.com
http:
- fault:
abort:
httpStatus: 400
percentage:
value: 50
match:
- uri:
prefix: /nginx
rewrite:
uri: /
route:
- destination:
host: nginx
EOF

📚 Tips

我们通过 http://my.k8s.com/nginx 来访问我们的 nginx web 服务。但是由于 nginx 的访问路径是 “/“ 而不是 “/nginx”,所以我们需要对 url 进行重写。注意,我们这里添加了一个 50% 概率的 400 错误响应,以便验证我们的流量管控是否生效。

配置 destination rule

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
kubectl apply -f -<<EOF 
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: nginx
namespace: test
spec:
host: nginx.test.svc.cluster.local
# Disable the tls for all ports
trafficPolicy:
tls:
mode: DISABLE
subsets:
- labels:
version: v1
name: v1
trafficPolicy:
loadBalancer:
simple: ROUND_ROBIN
# You can config the tls for each rules
tls:
mode: DISABLE
EOF

📚 Tips

这里我们需要关闭 tls 功能。

查看 istio-system 下的 service

1
2
3
4
5
6
7
kubectl get svc -n istio-system  
---
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller LoadBalancer 10.106.58.208 <pending> 80:31241/TCP,443:31603/TCP 10m
ingress-nginx-controller-admission ClusterIP 10.96.93.161 <none> 443/TCP 10m
istio-ingressgateway LoadBalancer 10.98.218.30 <pending> 15021:31234/TCP,80:31748/TCP,443:31819/TCP,15012:31734/TCP,15443:30830/TCP 17m
istiod ClusterIP 10.101.252.30 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP 17m

我们发现 istio-ingressgateway 的 TYPE 是 LoadBalancer 类型,显然这不是我们想要的,删掉:

1
kubectl delete svc -n istio-system istio-ingressgateway

配置 gateway service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
kubectl apply -f -<<EOF 
apiVersion: v1
kind: Service
metadata:
name: istio-ingressgateway
namespace: istio-system
labels:
app: istio-ingressgateway
istio: ingressgateway
release: istio
spec:
type: ClusterIP
selector:
app: istio-ingressgateway
istio: ingressgateway
ports:
- name: status-port
port: 15021
- name: http
port: 80
targetPort: 8080
- name: https
port: 443
targetPort: 8443
- name: tcp
port: 31400
- name: tls
port: 15443
EOF

📚 Tips

这里我们重新配置了一下 gateway 的 service,修改的地方有三点:
一、将 IP 类型该为 ClusterIP
二、将 80 端口映射到 8080
三、关闭无用的端口映射

为命名空间开启自动注入

1
kubectl label namespace test istio-injection=enabled

删除我们先前创建的 pod

1
kubectl delete po -n test nginx-55df9cfb4b-xjvcv   

查看注入是否成功

1
2
3
4
kubectl get po -n test -w
---
NAME READY STATUS RESTARTS AGE
nginx-55df9cfb4b-wwddn 0/2 Init:0/1 0 25s

验证

成功页面

400 页面

至此,完成。后续添加服务,只需要配置好对应的 deployment、service、virtual service、destination rule 即可。我们就可以通过域名的方式访问我们的服务了。

卸载 Istio

1
istioctl manifest generate --set profile=default | kubectl delete --ignore-not-found=true -f -