Kubernetes部署简单应用 Ingress

748 阅读5分钟

K8s 部署应用相关概念

1. Ingress、Ingress Controllers

Ingress

在上一篇中我们知道,利用 Service可以把 Pods 暴露出来(指从 K8s 外部访问)。

但是,Service 是没有条件的直接暴露端口。当我们需要有条件的控制外部访问时,我们可以用 Ingress 对象。

Ingress 可以提供

  • 负载均衡
  • SSL termination
  • name-based virtual hosting

下图是一个利用 Ingress 的简单例子

Ingress yaml 例子

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: minimal-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - http:
      paths:
      - path: /testpath
        pathType: Prefix
        backend:
          service:
            name: my-service
            port:
              number: 80

说明:

在 rules 部分,如果客户访问的请求路径以 testpath 开始,则请求会被转入 Service “my-service”的 80 端口,随后“my-service”会把请求转入与其关联的 Pods。

运行以下命令可以看到,我们在上一篇文章中创建的 K8s 环境里还没有创建 ingress 对象。

kubectl get ingress --all-namespaces

后面我们会在这个环境中加入 ingress。

Ingress Controllers

Ingress 的具体功能由 Ingress Controllers 来实现。Ingress Controllers 需要按情况自行安装(比如,在 AWS 环境中,我们会安装 AWS 提供的 Ingress Controllers)。

Ingress 本身只是定义规则,具体工作由 Ingress Controllers 完成,所以在不同的环境下,相同的 Ingress 背后可能由不同的 Ingress Controllers 来实现其功能。

K8s 项目支持维护 AWS, GCE 和 nginx Ingress Controllers。

除此之外,还有其它第三方 Ingress Controllers

  • AKS Application Gateway Ingress Controller:Azure 开发支持 Azure Application Gateway
  • Citrix ingress controller:支持 Citrix Application Delivery Controller
  • HAProxy Ingress:支持 HAProxy

实战步骤

1. 部署 Nginx Ingress Controllers

在使用 Ingress 之前,我们首先要部署 Ingress Controller,我们这里选择 Nginx Ingress。

运行以下命令部署 Nginx Ingress Controller

注意:这个 Ingress Controller 是专门部署在 kind 环境下的

#确定controller稳定版本
VERSION=$(curl -x http://YOUR_PROXY_SERVER:PORT https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/stable.txt)
#下载yaml部署文件
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/${VERSION}/deploy/static/provider/kind/deploy.yaml
#部署ingress controller
kubectl apply -f deploy.yaml

运行结果

查看部署的 ingress Pod

kubectl get pods --namespace ingress-nginx

如果出现以下报错

则运行下列命令查看具体 Pod 报错信息

kubectl describe pods/ingress-nginx-controller-6cd89dbf45-zjw6t --namespace ingress-nginx

如果出现如下问题,我们需要把 k8s 仓库加到 insecure-registries 中来解决

因为我们是在 K8s 中部署 Ingress,即在 K8s 中下载新 Ingress 的镜像,所以要把 K8s 仓库加到 K8s 的运行环境(containerd)中的 insecure-registries 中而不是 Docker Desktop 中。

运行以下命令,进入 K8s 容器内部

docker exec -it tsk8s-control-plane bash

在“/etc/containerd/config.toml”文件最后增加以下内容,把“k8s.gcr.io”加到insecure-registries

#add by ts
[plugins."io.containerd.grpc.v1.cri".registry]
  [plugins."io.containerd.grpc.v1.cri".registry.mirrors]
    [plugin."io.containerd.grpc.v1.cri".registry.mirrors."k8s.gcr.io"]
      endpoint = ["https://k8s.gcr.io"]
    [plugins."io.containerd.grpc.v1.cri".registry.configs]
      [plugins."io.containerd.grpc.v1.cri".registry.configs."k8s.gcr.io".tls]
        insecure_skip_verify = true

然后重启 containerd 并退出容器

systemctl daemon-reload
systemctl restart containerd
exit

运行结果

运行下列命令删除原来报错的 Pod,并查看新创建的 Pod

kubectl delete pods/ingress-nginx-controller-6cd89dbf45-g7b5w -n ingress-nginx
kubectl get pods -n ingress-nginx

说明:

可以看到新创建的 Pod 不再报错,处于容器创建状态了。

因为这里是用 Deployment 部署 Pod,所以手工删除 Pod 后,Deployment 会创建新的 Pod。

2. 创建 Ingress 测试

建好 Ingress controller 后,我们可以创建 Ingress 来测试了

首先我们先部署两个应用

新建文件“foo_app.yaml”并粘贴以下内容

kind: Pod
apiVersion: v1
metadata:
  name: foo-app
  labels:
    app: foo
spec:
  containers:
  - name: foo-app
    image: hashicorp/http-echo:0.2.3
    args:
    - "-text=foo"
---
kind: Service
apiVersion: v1
metadata:
  name: foo-service
spec:
  selector:
    app: foo
  ports:
  # Default port used by the image
  - port: 5678

说明:这个 yaml 文件创建 foo-app 应用,其中包括一个 Pod 和一个 Service。Pod 中有一个修改过的 httpd 镜像,Serivce 与 Pod 相关联并通过 5678 端口访问

运行下列命令创建 foo-app 应用

kubectl apply -f foo_app.yaml

结果如下

因为没有使用 NodePort,所以创建的 Service 不能从 K8s 外部访问

用同样的方法,我们再创建一个 bar-app 应用。

新建文件“bar_app.yaml”并复制以下内容

kind: Pod
apiVersion: v1
metadata:
  name: bar-app
  labels:
    app: bar
spec:
  containers:
  - name: bar-app
    image: hashicorp/http-echo:0.2.3
    args:
    - "-text=bar"
---
kind: Service
apiVersion: v1
metadata:
  name: bar-service
spec:
  selector:
    app: bar
  ports:
  # Default port used by the image
  - port: 5678

说明:这个应用与 foo-app 类似,只是访问的网页内容稍有不同,便于区分

结果如下

下面我们创建 Ingress

新建文件“testingress.yaml”并复制以下内容

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
spec:
  rules:
  - http:
      paths:
      - pathType: Prefix
        path: "/foo"
        backend:
          service:
            name: foo-service
            port:
              number: 5678
      - pathType: Prefix
        path: "/bar"
        backend:
          service:
            name: bar-service
            port:
              number: 5678

说明:在 rules 中,我们设定了通过路径来路由到指定的 Service。如果进来的请求带有/foo 路径,则请求转发到 foo-service;/bar 则转发到 bar-service

运行下列命令创建 foo-app 应用

kubectl apply -f testingress.yaml

运行结果

查看我们刚建的 ingress

kubectl describe ingress/example-ingress

可以看到已经通过路径和不同的 Service 相关联

现在我们可以用浏览器来测试一下

访问http://localhost/foo时,ingree会把请求转到foo应用的Service

而访问http://localhost/bar时,则会转到bar应用

总结

从这两篇文章大家也应该看出来了,K8s 不论是运行应用还是实现自身功能,主要方式就是通过部署各种 yaml 文件来实现。

我们把要部署的 K8s 对象(namespace,deloyment,servicer 等)写在 yaml 文件中,可以分开写成几个 yaml 文件,也可以合成一个,然后用 kubectl apply 命令创建对象。

Ingress 的实现需要 Ingress Controllers 配合,在云上部署的话 Ingress Controllers 一般由云服务商支持。