Istio分步指南(三):在 Kubernetes 中使用 Istio 部署应用程序

Istio分步指南(三):在 Kubernetes 中使用 Istio 部署应用程序

原文地址 https://medium.com/faun/istio-step-by-step-part-03-deploying-an-application-with-istio-in-kubernetes-d2b1de64fb6b

cover

请参阅我在deploying-istio-bookinfo-application-in-minikub上发表的第 12 条文章,以获取有关Bookinfo应用程序的更多信息。

首先,我要提到的是 Istio 发布了一个新版本 Istio 1.0.3,您可以从以下位置查看有关该版本的更多详细信息他们的网站。同样在本教程中,我正在使用 Istio 1.0.3 部署应用程序。

作为快速浏览,首先,我们将创建一个包含两个服务的小型服务网格。一个是小的 telnet 文件,另一个是简单的 Ballerina Hello-World 服务。然后为这两种服务注入 istio-proxy 并调用它们。调用服务分为两部分,分别是从 service-mesh 内部调用服务和从 service mesh 外部调用服务。

我在这里使用 Ballerina 是因为在使用 docker,kubernetes 和其他东西时非常容易。因此,如果您不熟悉Ballerina,可以访问他们的网站。有许多示例为您服务。其次,您必须正确安装 Istio,并确保所有带有”Istio-system”名称空间的 pod 都在运行。至此,让我们开始工作。

在开始工作之前,您必须通过执行以下命令启用istio-injection

1
kubectl label namespace default istio-injection=enabled --overwrite

好吧,现在让我们开始工作。

首先,创建一个 Docker 容器映像并部署

使用以下代码创建 Docker 容器映像并将文件保存为名称 Dockerfile

1
2
3
FROM alpine:latest
RUN apk update && apk add curl busybox-extras
ENTRYPOINT ["tail","-f","/dev/null"]

通常,当您构建 Dockerfile 时,Docker 会创建映像并将其存储在本地计算机的 Docker 注册表中。但是,在本教程中,我没有使用本地计算机的 Docker 注册表;我正在使用运行inside Minikube 的 VM 实例的 Docker 守护进程的 Docker 注册表。因此,使用以下命令将”docker”命令指向您的 Minikube 的 Docker 守护进程,

1
eval $(sudo minikube docker-env)

确保您位于 Dockerfile 所在的目录中。现在使用您想要的名称和标签构建 docker 映像。在这里,我使用 hellodemo 作为名称,使用 v1 作为标签。 记住使用小写字母作为名称。

1
docker build -t hellodemo:v1 .

希望您的终端中有类似的内容。

如果您要检查映像是否在 Minikube 的 Docker 注册表中,则可以通过以下方式进行操作:

1
sudo minikube ssh docker images

太好了,您已经完成了部署 Docker 容器映像的第一部分。现在将创建一个部署。

1
kubectl run hellodemo --image=hellodemo:v1 --port=9095 --image-pull-policy=IfNotPresent

hellodemo 是部署的名称,您可以检查您的部署,可以运行命令,

1
kubectl get deployments

另外,您可以通过运行以下命令来检查 Pod

1
kubectl get pods

您可以在READY列下看到2/2。这意味着在您的 Pod 中有两个容器。是的,当然必须有两个容器,因为一个是服务容器,另一个是 isito-proxy。为了进一步了解,您可以通过执行以下命令来检查 Pod 描述:

1
kubectl describe pod <pod_name>

太好了,您已经完成了部署 Docker 容器映像的第二部分。现在,作为最后一部分,您必须创建服务。为此,请运行命令,

1
kubectl expose deployment hellodemo --type=NodePort

手动负载平衡器不会与群集进行通信以找出后备 Pod 在哪里运行,我们必须使用”type:NodePort”公开服务,并且它们仅在 30000-32767 的端口上可用。

默认情况下,只能通过 Kubernetes 集群中的内部 IP 地址访问 Pod。但是,要使容器能够从 Kubernetes 虚拟网络外部访问,您必须将 Pod 作为 Kubernetes 服务公开。

您可以通过运行以下命令检查服务,

1
kubectl get svc

太好了,您已经完成了第一个任务。

现在,让我们部署 Ballerina Hello World 服务。

在此任务中,我将 IntelliJ 用作 IDE。如果使用的是 IntelliJ,则必须安装 Ballerina 插件。您可以参考此文档来安装插件。

仅供参考:此 Ballerina 服务不适用于新版本的 Ballerina。请参阅此链接了解相关工件。

首先创建一个 Ballerina 服务。 记住要选择Ballerina 服务在创建 Ballerina 文件时要使用“种类”。接下来,添加生成 Kubernetes 部署工件所需的 Kubernetes 批注。

这是带有所有 Kuberenetes 批注的我的 Ballerina 代码。

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
import ballerina/http;
import ballerina/log;
import ballerinax/kubernetes;

@kubernetes:Service {
    serviceType:"NodePort",
    name:"helloworldservice"
}

endpoint http:Listener listener {
    port:9095
};

@kubernetes:Deployment {
    image: "helloworldservice",
    name: "helloworldservice",
    dockerHost:"tcp://<minikube ip>:2376", // IP can be obtained via `sudo minikube ip` command
    dockerCertPath:"<Home Dir>/.minikube/certs",
    singleYAML:true
}
@http:ServiceConfig {basePath:"/helloworld"}
service<http:Service> hello bind listener {
    @http:ResourceConfig{
        path: "/",
        methods: ["GET"]
    }
    sayHello(endpoint caller, http:Request req) {
        http:Response res = new;

        res.setPayload("Hello, World!\n");

        caller->respond(res) but { error e => log:printError(
           "Error sending response", err = e) };
    }
}

请注意,如果使用的是 minikube,则需要指定dockerHostdockerCertPath

这就是创建文档的全部内容,现在将构建代码。为此,请运行命令,

1
ballerina build <.bal file name>

现在,如果您检查项目结构,您将找到一个生成的 YAML 文件。

它包含服务和部署的所有配置。

然后在终端中运行命令以部署 Kubernetes 工件,并检查服务,部署和 Pod 是否正确部署。

太好了,我们已经完成了本教程的两个任务。现在,我们有两个分别包含两个容器和两个服务的 Pod,以及两个部署。

从网格内部调用 hello-world 服务

好的,让我们尝试从 hellodemo 容器调用 hello-world 服务。为此,我们必须进入 hellodemo 容器并运行 curl 命令。

1
kubectl exec -it hellodemo-6889b97ff-g4cf7 -c hellodemo -- curl http://helloworldservice:9095/helloworld/

您可以在终端上看到打印为 “Hello,World”。这意味着服务被调用。

从网格外部调用服务

这是本教程的最后阶段。要完成此任务,我们需要 GatewayVirtual service。您知道 Kubernetes 使用 Ingress 控制器来处理从外部进入群集的流量。但是 Istio 已将其替换为名为 GatewayVirtualservice 的两个组件。

Gateway 用于配置 Envoy 的端口,而 VirtualService 用于启用智能路由首先是我们要使用 Istio 的原因。这两个协同工作以配置 Envoy。

在我们的例子中,我们需要一个 Gateway 和一个 VirtualService 来支持我们的 hello-world 服务。这是我们的服务的 Gateway 和 VirtualService。

Gateway.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: helloworld-gateway
spec:
  selector:
    istio: ingressgateway # use istio default controller
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*"

此网关配置设置了一个代理,以充当负载平衡器,为 HTTP 入口公开端口 80。

另一个重点是

1
2
3
spec:
  selector:
    istio: ingressgateway

在这里,完成的是,由于 istio-ingresgateway Pods 标记有标签 “istio = ingressgateway”,因此该 Pod 将成为接收此网关配置并最终公开端口的 Pod,因为它与 Istio Gateway 标签选择器匹配。

Virtualservice.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: "helloworldservice"
spec:
  hosts:
  - "*"
  gateways:
  - helloworld-gateway
  http:
  - match:
    - uri:
        exact: /helloworld
    route:
    - destination:
        host: "helloworldservice"
        port:
          number: 9095

然后可以将 VirtualService 绑定到网关,以控制到达特定主机或网关端口的流量的转发。就像上面在“规范”下的 Virtualservice 中一样,网关被分配给 helloworld-gateway,并且它将从 URI exact “/helloworld” 到达的流量转发到端口 9095 上的内部 helloworldservice。

这是项目结构。

太好了,现在将它们应用于服务组件,并尝试从外部调用它们。

要将这些应用于服务,请运行命令

1
2
kubectl apply -f Gateway.yaml
kubectl apply -f Virtualservice.yaml

因此,要调用服务,我们必须确定入口 IP 和端口。当我们使用 NodePort 时,请使用以下命令来设置 Ingress 端口。

1
2
export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')
export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}')

同样,当我们使用 minikube 时,请使用以下命令来设置 Ingress IP。

1
export INGRESS_HOST=$(sudo minikube ip)

全部设置好,让我们从外部调用服务。为此,请运行命令,

1
curl http://$INGRESS_HOST:$INGRESS_PORT/{basepath}

根据我的程序

1
curl http://$INGRESS_HOST:$INGRESS_PORT/helloworld

这是我的输出。

因此,您可以看到该服务也可以从服务网格外部调用。

您需要知道:

  • 为什么从其他服务调用服务时使用端口 9095?原因是,您知道根据我们的配置,服务网格服务内部的网关正在侦听端口 9095。

这是本教程的全部内容,希望您能理解发生的基本情况。如果您需要此课程的视频教程,请在下面评论。下篇教程很快见。保持联系以了解更多信息。谢谢。

Rating: