使用 Kubernetes 和 Istio 学习微服务
查看k8s集群名称
kubectl config current-context
1、设置k8s集群
1.1、创建命名空间
export NAMESPACE=tutorial
kubectl create namespace $NAMESPACE
1.2、安装istio和附加组件
- 附加组件的yaml文件在samples/addons目录下
- 参考
istio1-安装istio章节安装https://www.cnblogs.com/lixunblogs/p/19004831
1.3、创建Ingress
- 目的是给上一步创建的每一个服务创建ingress资源
cat <<EOF>> ingress-istio-system.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: istio-system
namespace: istio-system
spec:
ingressClassName: istio
rules:
- host: my-istio-dashboard.io
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: grafana
port:
number: 3000
- host: my-istio-tracing.io
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: tracing
port:
number: 9411
- host: my-istio-logs-database.io
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: prometheus
port:
number: 9090
- host: my-kiali.io
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: kiali
port:
number: 20001
EOF
kubectl apply -f ingress-istio-system.yaml
1.4、创建Role
- 创建一个角色为 istio-system 命名空间提供读权限
cat <<EOF>> role-istio-system.yaml
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: istio-system-access
namespace: istio-system
rules:
- apiGroups: ["", "extensions", "apps", "networking.k8s.io"]
resources: ["*"]
verbs: ["get", "list"]
EOF
kubectl apply -f role-istio-system.yaml
1.5、创建ServiceAccount
- 为每个用户创建服务账号
cat <<EOF>> sa-istio-system.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: ${NAMESPACE}-user
namespace: $NAMESPACE
EOF
kubectl apply -f sa-istio-system.yaml
使用证书认证
生成私钥
openssl genrsa -out ops-user.key 2048
生成 CSR(证书签名请求)
openssl req -new \
-key ops-user.key \
-out ops-user.csr \
-subj "/CN=ops-user/O=devops"
解释:
CN = 用户名
O = 组名(RBAC 里可用)
用 Kubernetes CA 签发证书
openssl x509 -req \
-in ops-user.csr \
-CA /etc/kubernetes/pki/ca.crt \
-CAkey /etc/kubernetes/pki/ca.key \
-CAcreateserial \
-out ops-user.crt \
-days 3650
创建 kubeconfig
定义集群信息
要访问的 K8s 集群地址、CA 证书
kubectl config set-cluster tutorial-cluster \
--server=https://192.168.40.11:6443 \
--certificate-authority=/etc/kubernetes/pki/ca.crt \
--kubeconfig=ops-user.conf
定义用户凭证
kubectl config set-credentials ops-user \
--client-certificate=ops-user.crt \
--client-key=ops-user.key \
--kubeconfig=ops-user.conf
Context(上下文):把 “集群” 和 “用户” 绑定起来,相当于 “访问入口”;
kubectl config set-context ops-user@istio-k8s \
--cluster=istio-k8s \
--user=ops-user \
--kubeconfig=ops-user.conf
use-context:应用配置
kubectl config use-context ops-user@istio-k8s \
--kubeconfig=ops-user.conf
1.6、限制每个用户的权限
- 用户只需要在他们自己的命名空间中创建资源以及从 istio-system 命名空间中读取资源
- ingress在这个apigroup里,networking.k8s.io。确保role里有这个apigroup
cat <<EOF>> rolebinding-istio-system.yaml
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: ${NAMESPACE}-access
namespace: $NAMESPACE
rules:
- apiGroups: ["", "extensions", "apps", "networking.k8s.io", "networking.istio.io", "authentication.istio.io",
"rbac.istio.io", "config.istio.io", "security.istio.io"]
resources: ["*"]
verbs: ["*"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: ${NAMESPACE}-access
namespace: $NAMESPACE
subjects:
- kind: ServiceAccount
name: ${NAMESPACE}-user
namespace: $NAMESPACE
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: ${NAMESPACE}-access
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: ${NAMESPACE}-istio-system-access
namespace: istio-system
subjects:
- kind: ServiceAccount
name: ${NAMESPACE}-user
namespace: $NAMESPACE
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: istio-system-access
EOF
kubectl apply -f rolebinding-istio-system.yaml
1.7、为每个用户创建k8s配置文件
- 每个用户需要使用他们自己的 Kubernetes 配置文件。这个配置文件指明了集群的详细信息、服务账号、证书和用户的命名空间。kubectl 命令使用这个配置文件在集群上操作
cat <<EOF>> ./${NAMESPACE}-user-config.yaml
apiVersion: v1
kind: Config
preferences: {}
clusters:
- cluster:
certificate-authority-data:
server: $(kubectl config view -o jsonpath="{.clusters[?(.name==\"$(kubectl config view -o jsonpath="{.contexts[?(.name==\"$(kubectl config current-context)\")].context.cluster}")\")].cluster.server}")
name: ${NAMESPACE}-cluster
users:
- name: ${NAMESPACE}-user
user:
client-key-data:
token:
contexts:
- context:
cluster: ${NAMESPACE}-cluster
namespace: ${NAMESPACE}
user: ${NAMESPACE}-user
name: ${NAMESPACE}
current-context: ${NAMESPACE}
EOF
- 这里生成的文件有空字段
tutorial-user-config.yaml
cat tutorial-user-config.yaml
apiVersion: v1
kind: Config
preferences: {}
clusters:
- cluster:
certificate-authority-data:
server: https://192.168.40.11:6443
name: tutorial-cluster
users:
- name: tutorial-user
user:
token:
contexts:
- context:
cluster: tutorial-cluster
namespace: tutorial
user: tutorial-user
name: tutorial
current-context: tutorial
- 生成 token
kubectl create token tutorial-user -n tutorial --duration=24h

- 生成CA
kubectl config view --raw -o jsonpath='{.clusters[0].cluster.certificate-authority-data}'

- 验证
- 分别填入token和certificate-authority-data后验证,如果不成功会提示输入用户名
kubectl --kubeconfig=tutorial-user-config.yaml get pods
说明:kubeconfig 有三种主流认证方式
- Token 认证
- 这种方式不需要 client-certificate-data不需要 client-key-data。所以client-key-data:应该删除或者留空。
users:
- name: tutorial-user
user:
token: xxxxx
- 客户端证书认证(管理员常用)
- 这里的 client-certificate-data = 客户端证书,client-key-data = 客户端私钥,通常来自 /etc/kubernetes/pki/,但这是 kubeadm 管理员级别用的。
users:
- name: kubernetes-admin
user:
client-certificate-data: <base64证书>
client-key-data: <base64私钥>
- OIDC 认证(企业常见)
- 例如接入:Keycloak、LDAP、企业 SSO
1.8、应用新的config文件
export KUBECONFIG=$PWD/${NAMESPACE}-user-config.yaml
- 可以使用unset KUBECONFIG,取消变量声明
1.9、验证默认命名空间
- 打印当前命名空间以确认配置文件已生效,应该输出tutorial
kubectl config view -o jsonpath="{.contexts[?(@.name==\"$(kubectl config current-context)\")].context.namespace}"
2、配置本地计算机
- 因为我是测试环境的k8s集群,本机计算机和集群在一台机器上
- 需要本地计算机有curl、node.js、docker、kubectl。本机除了node.js其他都有
2.1、安装node.js
- 服务器网络环境问题,先从浏览器下载脚本到服务器,再执行安装
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.4/install.sh | bash
- 这里按照提示操作,重开终端或执行命令,这里我选的是重开终端

- 继续安装,并查看版本

3、本地运行微服务
3.1、下载代码及依赖
- 将服务代码和 其 package 文件 下载到一个单独的目录中
mkdir ratings && cd ratings
curl -s https://raw.githubusercontent.com/istio/istio/release-1.29/samples/bookinfo/src/ratings/ratings.js -o ratings.js
curl -s https://raw.githubusercontent.com/istio/istio/release-1.29/samples/bookinfo/src/ratings/package.json -o package.json
- 将 rating 服务的依赖库安装在存储服务代码和 package 文件的同一目录下
npm install

3.2、启动服务
- 在9080端口上监听服务
npm start 9080

3.3、验证
- 修改产品的评级,并在修改前后查看
curl localhost:9080/ratings/7
curl -X POST localhost:9080/ratings/7 -d '{"Reviewer1":1,"Reviewer2":1}'
curl localhost:9080/ratings/7

4、在docker中运行ratings服务
cd ratings
curl -s https://raw.githubusercontent.com/istio/istio/release-1.29/samples/bookinfo/src/ratings/Dockerfile -o Dockerfile
docker build -t user/ratings .
docker run --name my-ratings --rm -d -p 9081:9080 $USER/rating
curl localhost:9081/ratings/7
docker ps
docker stop my-ratings
5、使用 Kubernetes 运行 Bookinfo
设置环境变量 MYHOST 的值为应用程序的 URL
export MYHOST=$(kubectl config view -o jsonpath={.contexts..namespace}).bookinfo.com

部署应用
- 确保已经应用环境变量echo $KUBECONFIG。没设置的话执行1.8步骤
# 下载bookinfo.yaml
wget https://raw.githubusercontent.com/istio/istio/release-1.29/samples/bookinfo/platform/kube/bookinfo.yaml
# 修改镜像源为国内地址
sed -i 's|docker\.io/istio|swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/istio|g' bookinfo.yaml > /dev/null 2>&1
# 通过标签筛选要安装的应用
kubectl apply -l version!=v2,version!=v3 -f bookinfo.yaml

- 如果在1.7步骤时token为空,这里会提示输入用户和密码
- kubectl 认证流程是:先找token,没有的话尝试 client cert,还没有的话尝试 basic auth提示输入用户名密码,basic auth是K8S很早之前的认证,目前默认不开启,所以API Server 根本不会接受它。

- 四个服务达到 Running 状态后,就可以扩展 deployment。要使每个微服务的每个版本在三个 Pod 中运行,请执行以下命令:
kubectl scale deployments --all --replicas 3

- 在服务达到 Running 状态后,部署一个测试 Pod:curl。 此 Pod 用来向您的微服务发送请求:
# 替换镜像
sed -i 's|docker\.io|swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io|g' curl.yaml > /dev/null 2>&1
# 部署测试Pod
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.29/samples/curl/curl.yaml
- 测试 Pod 中用 curl 命令发送请求给 Bookinfo 应用
kubectl exec $(kubectl get pod -l app=curl -o jsonpath='{.items[0].metadata.name}') -c curl -- curl -sS productpage:9080/productpage | grep -o "<title>.*</title>"

创建 Kubernetes Ingress 资源
cat <<EOF>> bookinfo-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: bookinfo
spec:
ingressClassName: nginx
rules:
- host: $MYHOST
http:
paths:
- path: /productpage
pathType: Prefix
backend:
service:
name: productpage
port:
number: 9080
- path: /login
pathType: Prefix
backend:
service:
name: productpage
port:
number: 9080
- path: /logout
pathType: Prefix
backend:
service:
name: productpage
port:
number: 9080
- path: /static
pathType: Prefix
backend:
service:
name: productpage
port:
number: 9080
EOF
kubectl apply -f bookinfo-ingress.yaml
部署nginx ingress controller
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/baremetal/deploy.yaml -O nginx-ingress-controller.yaml
# 替换镜像,还需要手动删除镜像后的摘要
sed -i 's|registry.k8s.io|swr.cn-north-4.myhuaweicloud.com/ddn-k8s/registry.k8s.io|g' nginx-ingress-controller.yaml > /dev/null 2>&1
# 会创建ingressclass和controller
kubectl apply -f nginx-ingress-controller.yaml
更新 /etc/hosts 配置文件
- 获取名为 bookinfo 的 Kubernetes Ingress 的 IP 地址
kubectl get ingress bookinfo
- 以下命令的输出内容追加到 /etc/hosts 文件
echo $(kubectl get ingress istio-system -n istio-system -o jsonpath='{..ip} {..host}') $(kubectl get ingress bookinfo -o jsonpath='{..host}')
- 输出内容为
192.168.40.13 my-istio-dashboard.io my-istio-tracing.io my-istio-logs-database.io my-kiali.io tutorial.bookinfo.com
- 将 ingress-nginx 命名空间下的 svc,ingress-nginx-controller改成loadbalancer的类型,kubectl get svc 查看EXTERNAL-IP为pending,这是因为没有LB Congtroller,没有人分配IP,可以部署MetalLB给裸机 Kubernetes 提供LoadBalancer 功能的。这里继续使用nodeport类型,所以在访问时加上nodeport的端口
- 测试访问
curl -s $MYHOST:31090/productpage | grep -o "<title>.*</title>"

模拟流量
- 在一个单独的终端窗口中设置无限循环,将流量发送到您的应用程序,以模拟现实世界中恒定的用户流量:
# linux
while :; do curl -s $MYHOST:30190/productpage | grep -o "<title>.*</title>"; sleep 1; done
# windows
for /L %i in (0,0,1) do @curl -s tutorial.bookinfo.com:31090/productpage | findstr "title" & timeout /t 1 >nul
生产测试
测试单个微服务
-
确保当前命名空间为tutorial
-
从测试 pod 中向服务之一发起 HTTP 请求
![image]()
-
在宿主机添加hosts后,在宿主机访问
![image]()
混沌测试
-
在dashboard中将details的pod缩容至0个。模拟故障
![image]()
-
再次查看,页面并没有完全崩溃,只是详情部分显示错误
![image]()
添加一个新版本的 reviews
- 使用第五节的文件进行部署
- 确保命名空间是tutorial
kubectl apply -l app=reviews,version=v2 -f bookinfo.yaml
- 多访问几次 tutorial.bookinfo.com:31090/productpage (确保正确配置了hosts)会发现有的页面有星星(约%25的比例),因为v1的pod有3个,v2的pod有1个

- 增加新版本的副本数
kubectl scale deployment reviews-v2 --replicas=3
在 productpage 启用 Istio
- 需要在tutorial环境变量下创建
export KUBECONFIG=/root/cert/ops-user.conf
# 应用默认destnation-rule
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.29/samples/bookinfo/networking/destination-rule-all.yaml
重新部署 productpage 微服务,启用 Istio
wget https://raw.githubusercontent.com/istio/istio/release-1.29/samples/bookinfo/platform/kube/bookinfo.yaml
sed -i 's|docker\.io/istio|swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/istio|g' bookinfo.yaml > /dev/null 2>&1
# 暂时恢复上下文,不然无法执行,原因是权限不足
unset KUBECONFIG
istioctl kube-inject -f bookinfo.yaml > bookinfo-ingected.yaml
sed -i 's/replicas: 1/replicas: 3/g' bookinfo-ingected.yaml > /dev/null 2>&1
export KUBECONFIG=/root/cert/ops-user.conf
# 需要在tutorial环境变量下创建
kubectl apply -l app=productpage,version=v1 -f bookinfo-ingected.yaml

在所有微服务上启用 Istio
- 在dashboard上将tutorial命名空间下的pod缩容为1
![image]()
- 重新部署注入了istio的pod
kubectl apply -l app!=reviews -f bookinfo-ingected.yaml -n tutorial
kubectl apply -l app=reviews,version=v1 -f bookinfo-ingected.yaml -n tutorial
kubectl apply -l app=reviews,version=v2 -f bookinfo-ingected.yaml -n tutorial
- 可以看到,每个pod中有两个容器
![image]()
grafana中显示










浙公网安备 33010602011771号