跳到主要内容

8 篇博文 含有标签「Istio」

查看所有标签

Istio VirtualService 流量管控

· 阅读需 8 分钟

架构示意图 ![VirtualService流量管理.png](/img/Istio Virtualservice 流量管控/VirtualService流量管理.png)

创建网关

Gateway 为HTTP/TCP 流量配置负载均衡器,最常见的是在网格边缘的操作,以启用应用程序的入口流量

创建 gateway

mkdir chap2
cd chap2
cp ../chap1/pod1.yaml ./

kubectl exec -it pod1 -- sh -c "echo 111 > /usr/share/nginx/html/index.html"
kubectl get pods -o wide
curl -s 10.244.223.200
#curl出111

kubectl expose --name=svc1 pod pod1 --port=80

kubectl get svc -n istio-system

kubectl get gw #查看gateway 并没有,需要创建
# No resource found in ns1 namespace

# 编辑 gateway yaml
vim mygw1.yaml

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: mygw
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 80
name: http-1
protocol: HTTP
hosts:
- "aa.yuan.cc"
# 网关里的hosts必须要满足FQDN

# 可以看到我们的路口网关,与上面的创建的gateway的标签是匹配上的
kubectl get pods -n istio-system -l istio=ingressgateway

# 创建 gateway
kubectl apply -f mygw1.yaml
kubectl get gw

virtualService 的基本使用

创建 vs1

kubectl get vs 
# No resource found in ns1 namespace

# 编写 vs1 yaml
vim vs1.yaml

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: myvs
spec:
hosts:
- "aa.yuan.cc"
gateways:
- mygw
http:
- route:
- destination:
host: svc1

# 创建 vs1
kubectl apply -f vs1.yaml
kubectl get vs

测试流量是否跑通

# 找一个服务器客户端
vim /etc/hosts
#写入口网关规定的ip地址
192.168.15.230 aa.yuan.cc aa
192.168.15.230 bb.yuan.cc bb

curl aa.rhce.cc
# 111
curl -I bb.rhce.cc
# bb 是访问不了的,404 ; 因为在网关中没有定义 bb

# 在gateway 中添加 bb 的配置
vim mygw1.yaml

- port:
number: 80
name: http-2
protocol: HTTP
hosts:
- "bb.yuan.cc"

# 重新启动
kubectl apply -f mygw1.yaml

# 此时再次访问 bb.yuan.cc 可以访问通嘛? 还是不行的,因为 vs 没有定义,要不你需要在原本 vs 中加上 bb 的 hosts,要不你就需要再添加一个 vs 来指明 bb
curl -I bb.rhce.cc

# 编写 vs1 yaml
vim vs1.yaml

spec:
hosts:
- "aa.yuan.cc"
- "bb.yuan.cc"

# 重新启动
kubectl apply -f vs1.yaml
curl -I bb.rhce.cc

-------------------------------------------------------
上述是为了测试,如果遇到这种需求可以使用通配符,在gateway yaml中将hosts改为:”*.yuan.cc“

带有权重的 virtualService

创建 svc2

# 创建 pod2
sed 's/pod1/pod2/' pod1.yaml | kubectl apply -f -
kubectl get pods

# 更改 pod2 web 页面
kubectl exec -it pod2 -- sh -c "echo 222 > /usr/share/nginx/html/index.html"

# 创建 svc2
kubectl expose --name=svc2 pod pod2 --port=80
kubectl get svc
curl <CLUSTER IP> # 222

修改 vs1

# 编写 vs1 yaml,添加 svc2,并设置权重
vim vs1.yaml

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: myvs
spec:
hosts:
- "aa.yuan.cc"
gateways:
- mygw
http:
- route:
- destination:
host: svc1
weight: 65
- route:
- destination:
host: svc2
weight: 35

# 重新启动 vs1
kubectl apply -f vs1.yaml

测试 vs 权重

# 在客户端服务器中访问请求
while true ; do
> curl aa.yuan.cc ; sleep 1
> done

# 去 kiali 上添加上 istio-system 的 namespace ,在 Show Edge Labels 中勾选 请求分布

查看 kiali 权重图

故障注入

fault : delay 测试svc1的延迟

vim vs1.yaml

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: myvs
spec:
hosts:
- "aa.yuan.cc"
gateways:
- mygw
http:
- fault:
delay:
percent: 100
fixedDelay: 1s
route:
- destination:
host: svc1
#此route需要在fault里

# 重启vs1
kubectl apply -f vs1.yaml

# 在客户端进行测试
curl aa.yuan.cc. #有了一定的延迟,延期了 fixedDelay 的 1s 的时间

fault : abort 模拟中断

vim vs1.yaml

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: myvs
spec:
hosts:
- "aa.yuan.cc"
gateways:
- mygw
http:
- fault:
#delay:
# percent: 100
# fixedDelay: 1s
abort:
percentage:
value: 100
httpStatus: 503
route:
- destination:
host: svc1

# 重启 vs1
kubectl apply -f vs1.yaml

# client 测试访问
curl -I aa.yuan.cc # 返回503

超时

创建 pod 和 svc

sed 's/pod1/pod3/' pod1.yaml | kubectl apply -f -
sed 's/pod1/pod4/' pod1.yaml | kubectl apply -f -
kubectl get pods

#把 pod4 nginx界面改为444
kubectl exec -it pod4 -- sh -c "echo 444 > /usr/share/nginx/html/index.html"

# 创建 svc
kubectl expose --name=svc3 pod pod3 --port=80
kubectl expose --name=svc4 pod pod4 --port=80

# 修改 pod3 中 nginx 配置文件
kubectl cp pod3:/etc/nginx/conf.d/default.conf default.conf
vim default.conf

location / {
#root /usr/share/nginx/html;
#index index.html index.htm
proxy_pass http://svc4;
proxy_http_version 1.1;
}

kubectl cp default.conf pod3:/etc/nginx/conf.d/default.conf
kubectl exec -it pod3 -- bash
nginx -t
nginx -s reload

# 测试结果
kubectl get svc
curl `svc3的IP` # 会显示 svc4 -> pod4 的444结果

创建 vs2

kubectl get vs
#先删除之前用的vs1
kubectl delete -f vs1.yaml

# 创建vs2
vim vs2.yaml

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: myvs1
spec:
hosts:
- "aa.yuan.cc"
gateways:
- mygw
http:
- route:
- destination:
host: svc3 #映射到svc3
timeout: 3s

# 启动 vs2
kubectl apply -f vs2.yaml

# client 服务器执行测试
curl aa.yuan.cc. #444,目前还是正常的

创建 vs3

vim vs3.yaml

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: myvs2
spec:
hosts:
- "svc4"
http:
- fault:
delay:
percent: 100
fixedDelay: 2s
route:
- destination:
host: svc4

# 启动 vs3
kubectl apply -f vs3.yaml

# client 服务器执行测试
curl aa.yuan.cc #444,目前还是正常的,只是有 2s 的延迟

#修改 vs3 的延迟时间
vim vs3.yaml

fixedDelay: 5s

# 配置生效
kubectl apply -f vs3.yaml

# client 服务器执行测试
curl -I aa.yuan.cc #失败

重试

# 修改 vs2 yaml
vim vs2.yaml

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: myvs1
spec:
hosts:
- "aa.yuan.cc"
gateways:
- mygw
http:
- route:
- destination:
host: svc3 #映射到svc3
timeout: 3s
retries:
attempts: 3 #重试三次
perTryTimeout: 3s #指在这个时间之内去重试,如果超过这个时间就不会再去重试
retryOn: 5xx #如果vs3返回此状态吗,那么则重试3次

# 修改 vs3 yaml
vim vs3.yaml

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: myvs2
spec:
hosts:
- "svc4"
http:
- fault:
#delay:
# percent: 100
# fixedDelay: 2s
abort:
percentage:
value: 100
httpStatus: 503
route:
- destination:
host: svc4

# 重启 vs2 vs3
kubectl apply -f vs2.yaml
kubectl apply -f vs3.yaml

# 查看日志
kubectl logs -f pod3
# 客户端访问
curl aa.yuan.cc
# 切回 pod3 日志,可以看到503的日志,并且是访问一次,重试了3次

# 清理环境
kubectl delete pod pod3
kubectl delete pod pod4
kubectl delete svc svc3
kubectl delete svc svc4
kubectl delete -f vs2.yaml
kubectl delete -f vs3.yaml

http 重写

创建 vs , 还原一下环境

kubectl get vs
#No resources found in ns1 namespace
kubectl get gw
#mygw
kubectl get pod
#pod1
#pod2
kubectl get svc
#svc1
#svc2

cp vs1.yaml vs.yaml
# 修改 vs yaml
vim vs.yaml

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: myvs
spec:
hosts:
- "aa.yuan.cc"
gateways:
- mygw
http:
- route:
- destination:
host: svc1

# 启动 vs
kubectl apply -f vs.yaml

修改 vs


# 在 pod1 nginx 中添加 html文件
kubectl exec -it pod1 -- bash
cd /usr/share/nginx/html
mkdir demo1 demo2
echo aaa > demo1/index.html
echo bbb > demo2/index.html

#客户端测试
curl aa.yuan.cc/demo1/index.html
curl aa.yuan.cc/demo2/index.html

# 创建 vs-rewrite yaml
cp vs.yaml vs-rewrite.yaml

vim vs-rewrite.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: myvs
spec:
hosts:
- "aa.yuan.cc"
gateways:
- mygw
http:
- match:
- uri:
prefix: /demo1/
rewrite:
uri: /demo2/ #从demo1跳转至demo2
route:
- destination:
host: svc1

# 启动 vs-rewrite
kubectl apply -f vs-rewrite.yaml

# 客户端测试,或者去 kiali 查看
curl aa.yuan.cc/demo1/index.html #返回bbb
curl aa.yuan.cc/demo2/index.html #没有返回,代表demo2不会匹配上

#如果说svc1的 route 在 match 之上,那么 match 规则 则不会生效,在route上就已经路由过去了
http:
- route:
- destination:
host: svc1
- match:
- uri:
prefix: /demo1/
rewrite:
uri: /demo2/

基于内容转发

cp vs.yaml vs-content.yaml

#编写 vs-content yaml
vim vs-content.yaml

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: myvs
spec:
hosts:
- "aa.yuan.cc"
gateways:
- mygw
http:
- match:
- headers:
User-Agent:
regex: .*(Chrome/([\d.]+)).* #通过 chrome 访问的则访问 svc1,否则访问 svc2
route:
- destination:
host: svc1
- route:
- destination:
host: svc2

## 客户端测试
#模拟非 chrome
curl --user-agent "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTMLme/31.0.1650.63 Safari/537.36" -I aa.yuan.cc
# 返回 222,反问到了 pod2

#模拟 chrome
curl --user-agent 'Chrome/54.0 (Windows NT 10.0)' aa.yuan.cc
#返回 111,访问到了 pod1

影子测试(流量镜像)

cp vs.yaml vs-mirror.yaml

# 编辑 vs-mirror
vim vs-mirror.yaml

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: myvs
spec:
hosts:
- "aa.yuan.cc"
gateways:
- mygw
http:
- route:
- destination:
host: svc1
mirror:
host: svc2

# 启动 vs-mirror
kubectl apply -f vs-mirror.yaml

# 客户端测试,查看pod2是否有复制一份流量过来
curl --user-agent 'Chrome/54.0 (Windows NT 10.0)' aa.yuan.cc
kubectl logs -f pod2

Istio 基础环境搭建

· 阅读需 4 分钟

K8s 部署环境操作省略

K8s version: 1.21.1

环境的准备:

https://metallb.universe.tf/ #官网

https://metallb.universe.tf/installation/#installation-by-manifest #install

kubectl create ns metallb-system

wget https://raw.githubusercontent.com/metallb/metallb/v0.12.1/manifests/metallb.yaml

创建 metallb

# 查看镜像
grep image metallb.yaml

# 拉取镜像
docker pull quay.io/metallb/speaker:v0.10.2
docker pull quay.io/metallb/controller:v0.10.2

# 修改metallb.yaml 镜像拉取策略
image: quay.io/metallb/speaker:v0.10.2
imagePullPolicy: IfNotPresent #新增

image: quay.io/metallb/controller:v0.10.2
imagePullPolicy: IfNotPresent #新增

# 安装
kubectl apply -f metallb.yaml

# 查看是否创建
kubectl get pods -n metallb-system

创建configmap

https://metallb.universe.tf/configuration/#layer-2-configuration

# 创建地址池
vim pool.yaml

apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: default
protocol: layer2
addresses:
- 192.168.15.230-192.168.15.240

# 创建
kubectl apply -f pool.yaml

# 所有的 work 节点都需拉取镜像
docker pull yauritux/busybox-curl
docker pull nginx

istio 安装

# 下载二进制包
wget https://github.com/istio/istio/releases/download/1.10.3/istio-1.10.3-linux-amd64.tar.gz
#wget https://github.com/istio/istio/releases/download/1.10.3/istioctl-1.10.3-linux-amd64.tar.gz

tar xvf istio-1.10.3-linux-amd64.tar.gz

ls istio-1.10.3/bin/
cp istio-1.10.3/bin/istioctl /bin/

#查看 istio 安装的组件
istioctl profile list

# 查看 istio 组件的内容
istioctl profile dump demo #查看demo组件信息,一般demo用于学习环境

# 安装 demo 环境
istioctl install --set profile=demo
y

# 查看
kubectl get pods -n istio-system #查看 有对应的ns和pod被创建出来
kubectl get svc -n istio-system #创建出了LoadBalancer类型的 istio-ingressgateway,ip地址为192.168.15.230
# 如果没有配置metallb的话,可以把 istio-ingressgateway 的类型改为 NodePort

# 如果需要卸载
istioctl x uninstall --purge
y
# 删除命名空间
kubectl delete ns istio-system

istio 注入

好用的命名空间切换工具 kubens 下载

curl -L https://github.com/ahmetb/kubectx/releases/download/v0.9.1/kubens -o /bin/kubens

chmod +x /bin/kubens

# 使用kubens命令即可列出当前所有的namespace

测试一下看之前创建的pod流程

mkdir chap1
cd chap1
kubectl create ns ns1

# 切换namespace
kubens ns1
#Context "kubernetes-admin@kubernetes" modifued.
#Active namespace is "ns1".

# 创建一个pod的yaml
kubectl run pod1 --image=nginx --image-pull-policy=IfNotPresent --dry-run=client -o yaml > pod1.yaml

# 查询参数值
kubectl explain pods.spec

vim /del.txt
terminationGracePeriodSeconds: 0

# 编辑pod1
vim pod1.yaml

spec:
terminationGracePeriodSeconds: 0
containers:

# 创建pod
kubectl apply -f pod1.yaml
kubectl get pods #此时这个pod里只有一个容器,即没有sidecar

# 删除测试的pod
kubectl delete pod pod1

使用 istio 单独的注入一个pod

# 创建
istioctl kube-inject -f pod1.yaml | kubectl apply -f -

# 查看pod数量
kubectl get pods #此时READY数为2

#这个pod新增的docker,就是 pilot,envoy

## 在创建一个 pod 测试
sed 's/pod1/pod2/' pod1.yaml | kubectl apply -f -
kubectl get pods # 发现这个 pod2 是没有被注入的

设置自动 istio 注入,可以通过 namespace 去做

#给ns1的命名空间添加istio标签,那么在这个标签里,所有创建的 pod 都会被自动注入 istio
kubectl label ns ns1 istio-injection=enabled

# 查看labels
kubectl get ns --show-labels

安装kiali :图形化工具,可以直观的查看流量

kubectl get pods -n istio-system

# 安装
kubectl apply -f istio-1.10.3/samples/addons/kiali.yaml
# 或者可以选择直接全部都安装上
kubectl apply -f istio-1.10.3/samples/addons/

kubectl get svc -n istio-system
# kiali 的PORT:20001,TYPE为 ClusterIP

# 修改 kiali 的 svc
kubectl edit svc kiali -n istio-system

sessionAffinity: None
type: LoadBalancer #把ClusterIP修改为NodePort或者LoadBalancer

# 查看并验证
kubectl get svc -n istio-system
# 查看 kiali 的 ip 和端口,使用浏览器访问
# 进入浏览器后可以测试一下,进入 Graph 页面,选择 istio-system 和 ns1 的 Namespace,可以看到我们现在环境中的拓扑图