# 使用ambassador容器

使用ambassador容器，即在Pod中的另一个容器中使用`kubectl`客户端生成代理，主容器中访问该代理，由于同一个Pod中的所有容器是共享同一个网络命名空间的，因此它们之间可以直接通过环回口通信，因此主容器可以间接与API服务器交互。

它们之间的通信架构如下图所示：

![将加密、授权、服务器验证工作交给ambassador容器中的代理](https://2906552408-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M6Ub8CloS5kJszh6xSR%2Fsync%2F6fde82f2e5982b35caa9e3fce59c22a41e34ebf8.png?generation=1588594619640236\&alt=media)

{% hint style="info" %}

1. `kubernetes`是集群中后端为API服务器Pod`kube-apiserver`的Service实例；
2. ambassador容器生成代理时所需的配置信息来自于[**默认Secret卷**](https://yangsijie151104.gitbook.io/k8s-note/configmap-he-secret/secret/mo-ren-secret)；
   {% endhint %}

## 创建ambassador容器

由于ambassador容器需要使用**kubectl客户端**生成代理，因此需要下载客户端。

使用客户端时，需要添加验证性的文件才可以正常使用，因此还需要从默认Secret卷中获取相关的验证文件。

下面展示创建ambassador容器的Dockerfile：

```
FROM alpine
RUN apk update && apk add curl && curl -L -O https://dl.k8s.io/v1.8.0/kubernetes-client-linux-amd64.tar.gz && tar zvxf kubernetes-client-linux-amd64.tar.gz kubernetes/client/bin/kubectl && mv kubernetes/client/bin/kubectl / && rm -rf kubernetes && rm -f kubernetes-client-linux-amd64.tar.gz
ADD kubectl-proxy.sh /kubectl-proxy.sh
ENTRYPOINT /kubectl-proxy.sh
```

从上述内容可以看出，在ambassador容器中下载了**kubectl客户端**，并且将`kubectl-proxy.sh`添加至根目录，并且设置为默认启动进程。

其中，`kubectl-proxy.sh`的内容如下：

```bash
#!/bin/sh

API_SERVER="https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT"
CA_CRT="/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
TOKEN="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)"

/kubectl proxy --server="$API_SERVER" --certificate-authority="$CA_CRT" --token="$TOKEN" --accept-paths='^.*'
```

从上述内容中可以看出，首先通过环境变量`KUBECTL_SERVICE_HOST`和`KUBERNETES_SERVICE_PORT`确认了后端Pod为API服务器的名为`kubernetes`的Service的位置；接着从默认的Secret卷中，读取了用于验证API服务器真假的CA证书`/var/run/secrets/kubernetes.io/serviceaccount/ca.crt`，以及用于获取API服务器授权的凭证`/var/run/secrets/kubernetes.io/serviceaccount/token`；最后利用**kubectl客户端**生成代理，此时代理会在Pod的8001端口开始监听请求。

## 创建Pod

下面直接展示创建的Pod的配置文件案例：

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: curl-with-ambassador
spec:
  containers:
  - name: main    # 主容器，在该容器中向代理发送请求，间接的与API服务器交互
    image: tutum/curl
    command: ["sleep", "9999999"]
  - name: ambassador    # ambassador容器
    image: luksa/kubectl-proxy:1.6.2
```

创建完成后，只需要在主容器，即名为`main`的容器中，使用如下命令即可与API服务器间接交互，省去了每次请求都需要自行使用验证数据的麻烦：

```bash
curl localhost:8001
```
