Closed4

GKEのkube-apiserverにcurlしたり、opensslしたりする

waruikedo_waruikedo_

GKEの設定

VPCネイティブで、マスターノードがグローバルIPを持つGKEクラスタを作成する。

❯ gcloud container clusters list                                                                    
NAME       LOCATION       MASTER_VERSION  MASTER_IP     MACHINE_TYPE  NODE_VERSION        NUM_NODES  STATUS
cluster-1  us-central1-c  1.22.8-gke.201  <master-ip>  g1-small      1.21.11-gke.1100 *  1          RUNNING

Node Versionはちょっと古い。 MASTER_IP が、マスターノードのIPアドレス。このアドレスが、kubectl get などのAPIリクエストを受け付ける。

kubecofig のclusterを確認すると、

❯ kubectl config view --minify -o json | jq '.clusters[].cluster.server'
"https://<master-ip>"

となっていて、kube-apiserverを指定している。

waruikedo_waruikedo_

kube-apiserverにcurlしてみる

https://<master-ip> はどこからでもアクセスできる。 curl してみると、

curl https://<master-ip>/version --insecure
{
  "major": "1",
  "minor": "22",
  "gitVersion": "v1.22.8-gke.201",
  "gitCommit": "2dca91e5224568a093c27d3589aa0a96fd3ddc9a",
  "gitTreeState": "clean",
  "buildDate": "2022-05-11T18:39:02Z",
  "goVersion": "go1.16.14b7",
  "compiler": "gc",
  "platform": "linux/amd64"
}%

試しにPodを作って、curlでその情報を取得してみる。

❯ kubectl run test-nginx --image=nginx  

❯ kubectl get pods                                                       
NAME         READY   STATUS    RESTARTS   AGE
test-nginx   1/1     Running   0          148m

curlでリクエストを送るときに、Authorization ヘッダーにBearer Tokenを付加する。 Tokenは自分が使っている認証情報を使ってみる。GKEの場合、kubectlのauth pluginがバイナリgke-gcloud-auth-plugin で提供されるようになっていて、これを使えば自分の使っているTokenがわかる。
詳しくは、Here's what to know about changes to kubectl authentication coming in GKE v1.25を参照。

curl -H 'Authorization: Bearer <token> ' https://<master-ip>/api/v1/namespaces/default/pods --insecure

{
  "kind": "PodList",
  "apiVersion": "v1",
  "metadata": {
    "resourceVersion": "7243326"
  },
  "items": [
    {
      "metadata": {
        "name": "test-nginx",
        "namespace": "default",
        "uid": "64e54acf-ad01-48e8-b7ea-ede75f4b3783",
        "resourceVersion": "7186331",
        "creationTimestamp": "2022-06-06T10:53:22Z",
        "labels": {
          "run": "test-nginx"
        },
        "managedFields": [
          {
            "manager": "kubectl-run",
            "operation": "Update",
            "apiVersion": "v1",
...

Tokenは例えば、KubernetesリソースのSecretのTokenを使うこともできる。下の例はdefaultで作成されているsecretのToken

❯ kubectl get secrets default-token-rqlnh -o json | jq '.data.token'

このService AccountにはKubernetesリソースをgetしたりlistしたりする権限がないので、 Authorizationヘッダーに付加してもリソースは取得できない。

curl -H 'Authorization: Bearer <token> ' https://<master-ip>/api/v1/namespaces/default/pods --insecure

# 権限がない
waruikedo_waruikedo_

Podからkube-apiserverにcurlする

Kubernetesクラスタには default namespaceに kubernetes というServiceが存在している。

❯ kubectl get service kubernetes           
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.3.0.1     <none>        443/TCP   13d

kubernetes Serviceははkube-apiserverをクラスタ内部のPodなどに公開(?言い方わからない)するモノっぽい。 試しに先ほど作った test-nginx Podからcurlしてversion情報を見てみる。

❯ kubectl exec -it test-nginx -- curl https://kubernetes/version --insecure
{
  "major": "1",
  "minor": "22",
  "gitVersion": "v1.22.8-gke.201",
  "gitCommit": "2dca91e5224568a093c27d3589aa0a96fd3ddc9a",
  "gitTreeState": "clean",
  "buildDate": "2022-05-11T18:39:02Z",
  "goVersion": "go1.16.14b7",
  "compiler": "gc",
  "platform": "linux/amd64"
}
waruikedo_waruikedo_

kube-apiserverの証明書を確認してみる。

curlをするときに、--insecure オプションをつけていたが、これはkube-apiserverがオレオレCAを持っているから(だとおもう)。
opensslで、証明書を取得してみる。

❯ openssl s_client -connect <master-ip>:443 -showcerts

このコマンドでとってきた証明書を適当なファイルに読み出して、中身を見てみる。

❯ cat kube-apiserver.crt
-----BEGIN CERTIFICATE-----
.
.
.

-----END CERTIFICATE-----
❯ openssl x509 -text -noout -in kube-apiserver.crt             
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            68:ea:18:0f:19:6a:b5:cf:52:83:13:e6:17:f7:28:8d
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN=87168ee7-7f11-42ec05d92e
        Validity
            Not Before: May 23 13:46:35 2022 GMT
            Not After : May 22 13:48:35 2027 GMT
        Subject: CN=<master-ip>
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)

...
...
      X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            X509v3 Extended Key Usage: 
                TLS Web Server Authentication
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Authority Key Identifier: 
                keyid:ED:F3:CE:A1:7A:1D:3F:8F:45:09:86:4D:17:D6:B1:6E:B7:D5:34:47

            X509v3 Subject Alternative Name: 
                DNS:kubernetes, DNS:kubernetes.default, DNS:kubernetes.default.svc, DNS:kubernetes.default.svc.cluster.local, IP Address:<master-ip> , IP Address:10.3.0.1
...
...

CNが<master-ip>になっている。SANにdefault namespaceのkubernetes ServiceのDNS名や、そのServiceのIPアドレスが設定されている。

このスクラップは2022/06/06にクローズされました