# 使用默认Secret提供的验证信息

集群内部Pod与API服务器需要关注以下三点：

1. 确定API服务器的位置；
2. 确保与API服务器进行交互，而不是一个冒名者；
3. 获得API服务器的授权，获取操作资源的权限；

## 确定API服务器位置

在Kubernetes集群中，API服务是由名为`kube-apiserver`的Pod提供的，而在集群中有一个名为`kubernetes`的Service对象，其Endpoint列表中就是`kube-apiserver`，因此集群中的Pod可以通过访问该Service对象，与API服务器交互。

其中`kube-apiserver`Pod使用的是`hostNetwork`类型的网络，即与主机共享网络命名空间，因此其IP地址是宿主机的IP地址，即对于集群而言，是集群外部地址，因此`kubernetes`是一个`spec.selector=None`的Service，其Endpoint列表为空，是另外单独指定的，具体原理可参考[**与集群外部服务映射**](https://yangsijie151104.gitbook.io/k8s-note/service/yu-ji-qun-wai-bu-fu-wu-ying-she)，原理图如下：

![kubernetes将kube-apiserver作为后端Pod](https://2906552408-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M6Ub8CloS5kJszh6xSR%2Fsync%2F400cc883d0503ab4014ef3fedd7bece0bb0aff00.png?generation=1588594614642833\&alt=media)

并且之前在介绍内部Pod访问Service中提到，我们可以轻易的[**通过环境变量或直接利用FQDN访问Service**](https://yangsijie151104.gitbook.io/k8s-note/service/6.-fu-wu-service/nei-bu-pod-fa-xian-service)，进而由Service将我们的请求转发至API服务器（Pod）。

综上，我们有两种方法确定API服务器的位置：

1. 在Pod中，通过`KUBERNETES_SERVICE_HOST`和`KUBERNETES_SERVICE_PORT`两个环境变量，确定`kubernetes`Service的IP地址和端口；
2. 可以直接通过访问`https://kubernetes`的FQDN的方式访问该Service（域名写全了是`kubernetes.default.svc.cluster.local`）；

## 确保是真正的API服务器

在确定了API服务器的位置（IP地址和端口）后，我们需要验证是否是真的API服务器。

此时需要使用**CA证书**验证API服务器的证书是否由CA签发，从而验证其是否是真正的API服务器。

在[**默认Secret章节**](https://yangsijie151104.gitbook.io/k8s-note/configmap-he-secret/secret/mo-ren-secret)中，说过每一个Pod都会挂载一个默认的Secret卷，该卷会被挂载至容器中的`/var/run/secrets/kubernetes.io/serviceaccount`目录下，其中有一个名为`ca.crt`的文件，其中就是用于验证API服务器的CA证书。

在使用curl访问API服务器时，需要使用`--cacert`参数指定CA证书：

```bash
curl --cacert ca.crt https://kubernetes
```

{% hint style="warning" %}
由于还没有获得API服务器的授权，因此到这一步，还是没有权限对资源对象进行操作的。
{% endhint %}

## 获得API服务器授权

想获得API服务器的授权，需要使用凭证来申请。

**凭证**在[**默认Secret**](https://yangsijie151104.gitbook.io/k8s-note/configmap-he-secret/secret/mo-ren-secret)挂载目录`/var/run/secrets/kubernetes.io/serviceaccount`下的一个名为`token`的文件中。

在使用curl访问API服务器时，需要使用`-H`在请求数据中，加入头信息：

```bash
TOKEN=$(cat token)
curl --cacert ca.crt -H "Authorization: Bearer $TOKEN" https://kubernetes
```

{% hint style="danger" %}
可能在执行完一下操作后还是提示没有权限访问，可能是因为Kubernetes的基于角色的访问控制机制（RBAC），我们可以通过下面的命令先绕过该机制：

```bash
kubectl create clusterrolebinding permissive-binding --clusterrole=cluster-admin --group=system:serviceaccounts
```

{% endhint %}

## 总结

下面总结一下使用默认Secret与API服务器的交互过程：

1. 使用环境变量或FQDN确定API服务器的位置；
2. 应用使用`/var/run/secrets/kubernetes.io/serviceaccount/ca.crt`CA证书验证API服务器的真实性；
3. 应用使用`/var/run/secrets/kubernetes.io/serviceaccount/token`作为获取API服务器授权的凭证；

![通过默认Secret中的文件与API服务器交互](https://2906552408-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M6Ub8CloS5kJszh6xSR%2Fsync%2F032744dfb9d8a9accbe9bf6fd614dfa10ca5255c.png?generation=1588594614098251\&alt=media)
